Skip to content

Commit 3ad0e83

Browse files
committed
Merge branch 'parisc-4.9-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc fixes from Helge Deller: "On parisc we were still seeing occasional random segmentation faults and memory corruption on SMP machines. Dave Anglin then looked again at the TLB related code and found two issues in the PCI DMA and generic TLB flush functions. Then, in our startup code we had some timing of the cache and TLB functions to calculate a threshold when to use a complete TLB/cache flush or just to flush a specific range. This code produced a race with newly started CPUs and thus lead to occasional kernel crashes (due to stale TLB/cache entries). The patch by Dave fixes this issue by flushing the local caches before starting secondary CPUs and by removing the race. The last problem fixed by this series is that we quite often suffered from hung tasks and self-detected stalls on the CPUs. It was somehow clear that this was related to the (in v4.7) newly introduced cr16 clocksource and the own implementation of sched_clock(). I replaced the open-coded sched_clock() function and switched to the generic sched_clock() implementation which seems to have fixed this isse as well. All patches have been sucessfully tested on a variety of machines, including our debian buildd servers. All patches (beside the small pr_cont fix) are tagged for stable releases" * 'parisc-4.9-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: parisc: Also flush data TLB in flush_icache_page_asm parisc: Fix race in pci-dma.c parisc: Switch to generic sched_clock implementation parisc: Fix races in parisc_setup_cache_timing() parisc: Fix printk continuations in system detection
2 parents 86b01b5 + 5035b23 commit 3ad0e83

File tree

7 files changed

+57
-86
lines changed

7 files changed

+57
-86
lines changed

arch/parisc/Kconfig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ config PARISC
3434
select HAVE_ARCH_HASH
3535
select HAVE_ARCH_SECCOMP_FILTER
3636
select HAVE_ARCH_TRACEHOOK
37-
select HAVE_UNSTABLE_SCHED_CLOCK if (SMP || !64BIT)
37+
select GENERIC_SCHED_CLOCK
38+
select HAVE_UNSTABLE_SCHED_CLOCK if SMP
39+
select GENERIC_CLOCKEVENTS
3840
select ARCH_NO_COHERENT_DMA_MMAP
3941
select CPU_NO_EFFICIENT_FFS
4042

arch/parisc/kernel/cache.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ void __init parisc_setup_cache_timing(void)
369369
{
370370
unsigned long rangetime, alltime;
371371
unsigned long size, start;
372+
unsigned long threshold;
372373

373374
alltime = mfctl(16);
374375
flush_data_cache();
@@ -382,17 +383,12 @@ void __init parisc_setup_cache_timing(void)
382383
printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
383384
alltime, size, rangetime);
384385

385-
/* Racy, but if we see an intermediate value, it's ok too... */
386-
parisc_cache_flush_threshold = size * alltime / rangetime;
387-
388-
parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold);
389-
if (!parisc_cache_flush_threshold)
390-
parisc_cache_flush_threshold = FLUSH_THRESHOLD;
391-
392-
if (parisc_cache_flush_threshold > cache_info.dc_size)
393-
parisc_cache_flush_threshold = cache_info.dc_size;
394-
395-
printk(KERN_INFO "Setting cache flush threshold to %lu kB\n",
386+
threshold = L1_CACHE_ALIGN(size * alltime / rangetime);
387+
if (threshold > cache_info.dc_size)
388+
threshold = cache_info.dc_size;
389+
if (threshold)
390+
parisc_cache_flush_threshold = threshold;
391+
printk(KERN_INFO "Cache flush threshold set to %lu KiB\n",
396392
parisc_cache_flush_threshold/1024);
397393

398394
/* calculate TLB flush threshold */
@@ -401,7 +397,7 @@ void __init parisc_setup_cache_timing(void)
401397
flush_tlb_all();
402398
alltime = mfctl(16) - alltime;
403399

404-
size = PAGE_SIZE;
400+
size = 0;
405401
start = (unsigned long) _text;
406402
rangetime = mfctl(16);
407403
while (start < (unsigned long) _end) {
@@ -414,13 +410,10 @@ void __init parisc_setup_cache_timing(void)
414410
printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n",
415411
alltime, size, rangetime);
416412

417-
parisc_tlb_flush_threshold = size * alltime / rangetime;
418-
parisc_tlb_flush_threshold *= num_online_cpus();
419-
parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold);
420-
if (!parisc_tlb_flush_threshold)
421-
parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD;
422-
423-
printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n",
413+
threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
414+
if (threshold)
415+
parisc_tlb_flush_threshold = threshold;
416+
printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
424417
parisc_tlb_flush_threshold/1024);
425418
}
426419

arch/parisc/kernel/inventory.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void __init setup_pdc(void)
5858
status = pdc_system_map_find_mods(&module_result, &module_path, 0);
5959
if (status == PDC_OK) {
6060
pdc_type = PDC_TYPE_SYSTEM_MAP;
61-
printk("System Map.\n");
61+
pr_cont("System Map.\n");
6262
return;
6363
}
6464

@@ -77,7 +77,7 @@ void __init setup_pdc(void)
7777
status = pdc_pat_cell_get_number(&cell_info);
7878
if (status == PDC_OK) {
7979
pdc_type = PDC_TYPE_PAT;
80-
printk("64 bit PAT.\n");
80+
pr_cont("64 bit PAT.\n");
8181
return;
8282
}
8383
#endif
@@ -97,12 +97,12 @@ void __init setup_pdc(void)
9797
case 0xC: /* 715/64, at least */
9898

9999
pdc_type = PDC_TYPE_SNAKE;
100-
printk("Snake.\n");
100+
pr_cont("Snake.\n");
101101
return;
102102

103103
default: /* Everything else */
104104

105-
printk("Unsupported.\n");
105+
pr_cont("Unsupported.\n");
106106
panic("If this is a 64-bit machine, please try a 64-bit kernel.\n");
107107
}
108108
}

arch/parisc/kernel/pacache.S

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fitmanyloop: /* Loop if LOOP >= 2 */
9696

9797
fitmanymiddle: /* Loop if LOOP >= 2 */
9898
addib,COND(>) -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
99-
pitlbe 0(%sr1, %r28)
99+
pitlbe %r0(%sr1, %r28)
100100
pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */
101101
addib,COND(>) -1, %r29, fitmanymiddle /* Middle loop decr */
102102
copy %arg3, %r31 /* Re-init inner loop count */
@@ -139,7 +139,7 @@ fdtmanyloop: /* Loop if LOOP >= 2 */
139139

140140
fdtmanymiddle: /* Loop if LOOP >= 2 */
141141
addib,COND(>) -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
142-
pdtlbe 0(%sr1, %r28)
142+
pdtlbe %r0(%sr1, %r28)
143143
pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */
144144
addib,COND(>) -1, %r29, fdtmanymiddle /* Middle loop decr */
145145
copy %arg3, %r31 /* Re-init inner loop count */
@@ -626,12 +626,12 @@ ENTRY_CFI(copy_user_page_asm)
626626
/* Purge any old translations */
627627

628628
#ifdef CONFIG_PA20
629-
pdtlb,l 0(%r28)
630-
pdtlb,l 0(%r29)
629+
pdtlb,l %r0(%r28)
630+
pdtlb,l %r0(%r29)
631631
#else
632632
tlb_lock %r20,%r21,%r22
633-
pdtlb 0(%r28)
634-
pdtlb 0(%r29)
633+
pdtlb %r0(%r28)
634+
pdtlb %r0(%r29)
635635
tlb_unlock %r20,%r21,%r22
636636
#endif
637637

@@ -774,10 +774,10 @@ ENTRY_CFI(clear_user_page_asm)
774774
/* Purge any old translation */
775775

776776
#ifdef CONFIG_PA20
777-
pdtlb,l 0(%r28)
777+
pdtlb,l %r0(%r28)
778778
#else
779779
tlb_lock %r20,%r21,%r22
780-
pdtlb 0(%r28)
780+
pdtlb %r0(%r28)
781781
tlb_unlock %r20,%r21,%r22
782782
#endif
783783

@@ -858,10 +858,10 @@ ENTRY_CFI(flush_dcache_page_asm)
858858
/* Purge any old translation */
859859

860860
#ifdef CONFIG_PA20
861-
pdtlb,l 0(%r28)
861+
pdtlb,l %r0(%r28)
862862
#else
863863
tlb_lock %r20,%r21,%r22
864-
pdtlb 0(%r28)
864+
pdtlb %r0(%r28)
865865
tlb_unlock %r20,%r21,%r22
866866
#endif
867867

@@ -898,10 +898,10 @@ ENTRY_CFI(flush_dcache_page_asm)
898898
sync
899899

900900
#ifdef CONFIG_PA20
901-
pdtlb,l 0(%r25)
901+
pdtlb,l %r0(%r25)
902902
#else
903903
tlb_lock %r20,%r21,%r22
904-
pdtlb 0(%r25)
904+
pdtlb %r0(%r25)
905905
tlb_unlock %r20,%r21,%r22
906906
#endif
907907

@@ -931,13 +931,18 @@ ENTRY_CFI(flush_icache_page_asm)
931931
depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */
932932
#endif
933933

934-
/* Purge any old translation */
934+
/* Purge any old translation. Note that the FIC instruction
935+
* may use either the instruction or data TLB. Given that we
936+
* have a flat address space, it's not clear which TLB will be
937+
* used. So, we purge both entries. */
935938

936939
#ifdef CONFIG_PA20
940+
pdtlb,l %r0(%r28)
937941
pitlb,l %r0(%sr4,%r28)
938942
#else
939943
tlb_lock %r20,%r21,%r22
940-
pitlb (%sr4,%r28)
944+
pdtlb %r0(%r28)
945+
pitlb %r0(%sr4,%r28)
941946
tlb_unlock %r20,%r21,%r22
942947
#endif
943948

@@ -976,10 +981,12 @@ ENTRY_CFI(flush_icache_page_asm)
976981
sync
977982

978983
#ifdef CONFIG_PA20
984+
pdtlb,l %r0(%r28)
979985
pitlb,l %r0(%sr4,%r25)
980986
#else
981987
tlb_lock %r20,%r21,%r22
982-
pitlb (%sr4,%r25)
988+
pdtlb %r0(%r28)
989+
pitlb %r0(%sr4,%r25)
983990
tlb_unlock %r20,%r21,%r22
984991
#endif
985992

arch/parisc/kernel/pci-dma.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ static inline int map_pte_uncached(pte_t * pte,
9595

9696
if (!pte_none(*pte))
9797
printk(KERN_ERR "map_pte_uncached: page already exists\n");
98-
set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
9998
purge_tlb_start(flags);
99+
set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
100100
pdtlb_kernel(orig_vaddr);
101101
purge_tlb_end(flags);
102102
vaddr += PAGE_SIZE;

arch/parisc/kernel/setup.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@ static int __init parisc_init(void)
334334
/* tell PDC we're Linux. Nevermind failure. */
335335
pdc_stable_write(0x40, &osid, sizeof(osid));
336336

337+
/* start with known state */
338+
flush_cache_all_local();
339+
flush_tlb_all_local(NULL);
340+
337341
processor_init();
338342
#ifdef CONFIG_SMP
339343
pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n",

arch/parisc/kernel/time.c

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/module.h>
1515
#include <linux/rtc.h>
1616
#include <linux/sched.h>
17+
#include <linux/sched_clock.h>
1718
#include <linux/kernel.h>
1819
#include <linux/param.h>
1920
#include <linux/string.h>
@@ -39,18 +40,6 @@
3940

4041
static unsigned long clocktick __read_mostly; /* timer cycles per tick */
4142

42-
#ifndef CONFIG_64BIT
43-
/*
44-
* The processor-internal cycle counter (Control Register 16) is used as time
45-
* source for the sched_clock() function. This register is 64bit wide on a
46-
* 64-bit kernel and 32bit on a 32-bit kernel. Since sched_clock() always
47-
* requires a 64bit counter we emulate on the 32-bit kernel the higher 32bits
48-
* with a per-cpu variable which we increase every time the counter
49-
* wraps-around (which happens every ~4 secounds).
50-
*/
51-
static DEFINE_PER_CPU(unsigned long, cr16_high_32_bits);
52-
#endif
53-
5443
/*
5544
* We keep time on PA-RISC Linux by using the Interval Timer which is
5645
* a pair of registers; one is read-only and one is write-only; both
@@ -121,12 +110,6 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
121110
*/
122111
mtctl(next_tick, 16);
123112

124-
#if !defined(CONFIG_64BIT)
125-
/* check for overflow on a 32bit kernel (every ~4 seconds). */
126-
if (unlikely(next_tick < now))
127-
this_cpu_inc(cr16_high_32_bits);
128-
#endif
129-
130113
/* Skip one clocktick on purpose if we missed next_tick.
131114
* The new CR16 must be "later" than current CR16 otherwise
132115
* itimer would not fire until CR16 wrapped - e.g 4 seconds
@@ -208,7 +191,7 @@ EXPORT_SYMBOL(profile_pc);
208191

209192
/* clock source code */
210193

211-
static cycle_t read_cr16(struct clocksource *cs)
194+
static cycle_t notrace read_cr16(struct clocksource *cs)
212195
{
213196
return get_cycles();
214197
}
@@ -287,26 +270,9 @@ void read_persistent_clock(struct timespec *ts)
287270
}
288271

289272

290-
/*
291-
* sched_clock() framework
292-
*/
293-
294-
static u32 cyc2ns_mul __read_mostly;
295-
static u32 cyc2ns_shift __read_mostly;
296-
297-
u64 sched_clock(void)
273+
static u64 notrace read_cr16_sched_clock(void)
298274
{
299-
u64 now;
300-
301-
/* Get current cycle counter (Control Register 16). */
302-
#ifdef CONFIG_64BIT
303-
now = mfctl(16);
304-
#else
305-
now = mfctl(16) + (((u64) this_cpu_read(cr16_high_32_bits)) << 32);
306-
#endif
307-
308-
/* return the value in ns (cycles_2_ns) */
309-
return mul_u64_u32_shr(now, cyc2ns_mul, cyc2ns_shift);
275+
return get_cycles();
310276
}
311277

312278

@@ -316,17 +282,16 @@ u64 sched_clock(void)
316282

317283
void __init time_init(void)
318284
{
319-
unsigned long current_cr16_khz;
285+
unsigned long cr16_hz;
320286

321-
current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */
322287
clocktick = (100 * PAGE0->mem_10msec) / HZ;
323-
324-
/* calculate mult/shift values for cr16 */
325-
clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz,
326-
NSEC_PER_MSEC, 0);
327-
328288
start_cpu_itimer(); /* get CPU 0 started */
329289

290+
cr16_hz = 100 * PAGE0->mem_10msec; /* Hz */
291+
330292
/* register at clocksource framework */
331-
clocksource_register_khz(&clocksource_cr16, current_cr16_khz);
293+
clocksource_register_hz(&clocksource_cr16, cr16_hz);
294+
295+
/* register as sched_clock source */
296+
sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_hz);
332297
}

0 commit comments

Comments
 (0)