Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+57 -86
+3 -1
arch/parisc/Kconfig
··· 34 34 select HAVE_ARCH_HASH 35 35 select HAVE_ARCH_SECCOMP_FILTER 36 36 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 38 40 select ARCH_NO_COHERENT_DMA_MMAP 39 41 select CPU_NO_EFFICIENT_FFS 40 42
+12 -19
arch/parisc/kernel/cache.c
··· 369 369 { 370 370 unsigned long rangetime, alltime; 371 371 unsigned long size, start; 372 + unsigned long threshold; 372 373 373 374 alltime = mfctl(16); 374 375 flush_data_cache(); ··· 383 382 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n", 384 383 alltime, size, rangetime); 385 384 386 - /* Racy, but if we see an intermediate value, it's ok too... */ 387 - parisc_cache_flush_threshold = size * alltime / rangetime; 388 - 389 - parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold); 390 - if (!parisc_cache_flush_threshold) 391 - parisc_cache_flush_threshold = FLUSH_THRESHOLD; 392 - 393 - if (parisc_cache_flush_threshold > cache_info.dc_size) 394 - parisc_cache_flush_threshold = cache_info.dc_size; 395 - 396 - printk(KERN_INFO "Setting cache flush threshold to %lu kB\n", 385 + threshold = L1_CACHE_ALIGN(size * alltime / rangetime); 386 + if (threshold > cache_info.dc_size) 387 + threshold = cache_info.dc_size; 388 + if (threshold) 389 + parisc_cache_flush_threshold = threshold; 390 + printk(KERN_INFO "Cache flush threshold set to %lu KiB\n", 397 391 parisc_cache_flush_threshold/1024); 398 392 399 393 /* calculate TLB flush threshold */ ··· 397 401 flush_tlb_all(); 398 402 alltime = mfctl(16) - alltime; 399 403 400 - size = PAGE_SIZE; 404 + size = 0; 401 405 start = (unsigned long) _text; 402 406 rangetime = mfctl(16); 403 407 while (start < (unsigned long) _end) { ··· 410 414 printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n", 411 415 alltime, size, rangetime); 412 416 413 - parisc_tlb_flush_threshold = size * alltime / rangetime; 414 - parisc_tlb_flush_threshold *= num_online_cpus(); 415 - parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold); 416 - if (!parisc_tlb_flush_threshold) 417 - parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; 418 - 419 - printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n", 417 + threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime); 418 + if (threshold) 419 + parisc_tlb_flush_threshold = threshold; 420 + printk(KERN_INFO "TLB flush threshold set to %lu KiB\n", 420 421 parisc_tlb_flush_threshold/1024); 421 422 } 422 423
+4 -4
arch/parisc/kernel/inventory.c
··· 58 58 status = pdc_system_map_find_mods(&module_result, &module_path, 0); 59 59 if (status == PDC_OK) { 60 60 pdc_type = PDC_TYPE_SYSTEM_MAP; 61 - printk("System Map.\n"); 61 + pr_cont("System Map.\n"); 62 62 return; 63 63 } 64 64 ··· 77 77 status = pdc_pat_cell_get_number(&cell_info); 78 78 if (status == PDC_OK) { 79 79 pdc_type = PDC_TYPE_PAT; 80 - printk("64 bit PAT.\n"); 80 + pr_cont("64 bit PAT.\n"); 81 81 return; 82 82 } 83 83 #endif ··· 97 97 case 0xC: /* 715/64, at least */ 98 98 99 99 pdc_type = PDC_TYPE_SNAKE; 100 - printk("Snake.\n"); 100 + pr_cont("Snake.\n"); 101 101 return; 102 102 103 103 default: /* Everything else */ 104 104 105 - printk("Unsupported.\n"); 105 + pr_cont("Unsupported.\n"); 106 106 panic("If this is a 64-bit machine, please try a 64-bit kernel.\n"); 107 107 } 108 108 }
+22 -15
arch/parisc/kernel/pacache.S
··· 96 96 97 97 fitmanymiddle: /* Loop if LOOP >= 2 */ 98 98 addib,COND(>) -1, %r31, fitmanymiddle /* Adjusted inner loop decr */ 99 - pitlbe 0(%sr1, %r28) 99 + pitlbe %r0(%sr1, %r28) 100 100 pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */ 101 101 addib,COND(>) -1, %r29, fitmanymiddle /* Middle loop decr */ 102 102 copy %arg3, %r31 /* Re-init inner loop count */ ··· 139 139 140 140 fdtmanymiddle: /* Loop if LOOP >= 2 */ 141 141 addib,COND(>) -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */ 142 - pdtlbe 0(%sr1, %r28) 142 + pdtlbe %r0(%sr1, %r28) 143 143 pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */ 144 144 addib,COND(>) -1, %r29, fdtmanymiddle /* Middle loop decr */ 145 145 copy %arg3, %r31 /* Re-init inner loop count */ ··· 626 626 /* Purge any old translations */ 627 627 628 628 #ifdef CONFIG_PA20 629 - pdtlb,l 0(%r28) 630 - pdtlb,l 0(%r29) 629 + pdtlb,l %r0(%r28) 630 + pdtlb,l %r0(%r29) 631 631 #else 632 632 tlb_lock %r20,%r21,%r22 633 - pdtlb 0(%r28) 634 - pdtlb 0(%r29) 633 + pdtlb %r0(%r28) 634 + pdtlb %r0(%r29) 635 635 tlb_unlock %r20,%r21,%r22 636 636 #endif 637 637 ··· 774 774 /* Purge any old translation */ 775 775 776 776 #ifdef CONFIG_PA20 777 - pdtlb,l 0(%r28) 777 + pdtlb,l %r0(%r28) 778 778 #else 779 779 tlb_lock %r20,%r21,%r22 780 - pdtlb 0(%r28) 780 + pdtlb %r0(%r28) 781 781 tlb_unlock %r20,%r21,%r22 782 782 #endif 783 783 ··· 858 858 /* Purge any old translation */ 859 859 860 860 #ifdef CONFIG_PA20 861 - pdtlb,l 0(%r28) 861 + pdtlb,l %r0(%r28) 862 862 #else 863 863 tlb_lock %r20,%r21,%r22 864 - pdtlb 0(%r28) 864 + pdtlb %r0(%r28) 865 865 tlb_unlock %r20,%r21,%r22 866 866 #endif 867 867 ··· 898 898 sync 899 899 900 900 #ifdef CONFIG_PA20 901 - pdtlb,l 0(%r25) 901 + pdtlb,l %r0(%r25) 902 902 #else 903 903 tlb_lock %r20,%r21,%r22 904 - pdtlb 0(%r25) 904 + pdtlb %r0(%r25) 905 905 tlb_unlock %r20,%r21,%r22 906 906 #endif 907 907 ··· 931 931 depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ 932 932 #endif 933 933 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. */ 935 938 936 939 #ifdef CONFIG_PA20 940 + pdtlb,l %r0(%r28) 937 941 pitlb,l %r0(%sr4,%r28) 938 942 #else 939 943 tlb_lock %r20,%r21,%r22 940 - pitlb (%sr4,%r28) 944 + pdtlb %r0(%r28) 945 + pitlb %r0(%sr4,%r28) 941 946 tlb_unlock %r20,%r21,%r22 942 947 #endif 943 948 ··· 981 976 sync 982 977 983 978 #ifdef CONFIG_PA20 979 + pdtlb,l %r0(%r28) 984 980 pitlb,l %r0(%sr4,%r25) 985 981 #else 986 982 tlb_lock %r20,%r21,%r22 987 - pitlb (%sr4,%r25) 983 + pdtlb %r0(%r28) 984 + pitlb %r0(%sr4,%r25) 988 985 tlb_unlock %r20,%r21,%r22 989 986 #endif 990 987
+1 -1
arch/parisc/kernel/pci-dma.c
··· 95 95 96 96 if (!pte_none(*pte)) 97 97 printk(KERN_ERR "map_pte_uncached: page already exists\n"); 98 - set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); 99 98 purge_tlb_start(flags); 99 + set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); 100 100 pdtlb_kernel(orig_vaddr); 101 101 purge_tlb_end(flags); 102 102 vaddr += PAGE_SIZE;
+4
arch/parisc/kernel/setup.c
··· 334 334 /* tell PDC we're Linux. Nevermind failure. */ 335 335 pdc_stable_write(0x40, &osid, sizeof(osid)); 336 336 337 + /* start with known state */ 338 + flush_cache_all_local(); 339 + flush_tlb_all_local(NULL); 340 + 337 341 processor_init(); 338 342 #ifdef CONFIG_SMP 339 343 pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n",
+11 -46
arch/parisc/kernel/time.c
··· 14 14 #include <linux/module.h> 15 15 #include <linux/rtc.h> 16 16 #include <linux/sched.h> 17 + #include <linux/sched_clock.h> 17 18 #include <linux/kernel.h> 18 19 #include <linux/param.h> 19 20 #include <linux/string.h> ··· 39 38 #include <linux/timex.h> 40 39 41 40 static unsigned long clocktick __read_mostly; /* timer cycles per tick */ 42 - 43 - #ifndef CONFIG_64BIT 44 - /* 45 - * The processor-internal cycle counter (Control Register 16) is used as time 46 - * source for the sched_clock() function. This register is 64bit wide on a 47 - * 64-bit kernel and 32bit on a 32-bit kernel. Since sched_clock() always 48 - * requires a 64bit counter we emulate on the 32-bit kernel the higher 32bits 49 - * with a per-cpu variable which we increase every time the counter 50 - * wraps-around (which happens every ~4 secounds). 51 - */ 52 - static DEFINE_PER_CPU(unsigned long, cr16_high_32_bits); 53 - #endif 54 41 55 42 /* 56 43 * We keep time on PA-RISC Linux by using the Interval Timer which is ··· 109 120 * Only bottom 32-bits of next_tick are writable in CR16! 110 121 */ 111 122 mtctl(next_tick, 16); 112 - 113 - #if !defined(CONFIG_64BIT) 114 - /* check for overflow on a 32bit kernel (every ~4 seconds). */ 115 - if (unlikely(next_tick < now)) 116 - this_cpu_inc(cr16_high_32_bits); 117 - #endif 118 123 119 124 /* Skip one clocktick on purpose if we missed next_tick. 120 125 * The new CR16 must be "later" than current CR16 otherwise ··· 191 208 192 209 /* clock source code */ 193 210 194 - static cycle_t read_cr16(struct clocksource *cs) 211 + static cycle_t notrace read_cr16(struct clocksource *cs) 195 212 { 196 213 return get_cycles(); 197 214 } ··· 270 287 } 271 288 272 289 273 - /* 274 - * sched_clock() framework 275 - */ 276 - 277 - static u32 cyc2ns_mul __read_mostly; 278 - static u32 cyc2ns_shift __read_mostly; 279 - 280 - u64 sched_clock(void) 290 + static u64 notrace read_cr16_sched_clock(void) 281 291 { 282 - u64 now; 283 - 284 - /* Get current cycle counter (Control Register 16). */ 285 - #ifdef CONFIG_64BIT 286 - now = mfctl(16); 287 - #else 288 - now = mfctl(16) + (((u64) this_cpu_read(cr16_high_32_bits)) << 32); 289 - #endif 290 - 291 - /* return the value in ns (cycles_2_ns) */ 292 - return mul_u64_u32_shr(now, cyc2ns_mul, cyc2ns_shift); 292 + return get_cycles(); 293 293 } 294 294 295 295 ··· 282 316 283 317 void __init time_init(void) 284 318 { 285 - unsigned long current_cr16_khz; 319 + unsigned long cr16_hz; 286 320 287 - current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */ 288 321 clocktick = (100 * PAGE0->mem_10msec) / HZ; 289 - 290 - /* calculate mult/shift values for cr16 */ 291 - clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz, 292 - NSEC_PER_MSEC, 0); 293 - 294 322 start_cpu_itimer(); /* get CPU 0 started */ 295 323 324 + cr16_hz = 100 * PAGE0->mem_10msec; /* Hz */ 325 + 296 326 /* register at clocksource framework */ 297 - clocksource_register_khz(&clocksource_cr16, current_cr16_khz); 327 + clocksource_register_hz(&clocksource_cr16, cr16_hz); 328 + 329 + /* register as sched_clock source */ 330 + sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_hz); 298 331 }