aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2016-12-08 15:00:46 -0500
committerHelge Deller <deller@gmx.de>2016-12-08 15:27:18 -0500
commit24d0492b7d5d321a9c5846c8c974eba9823ffaa0 (patch)
treebfd151e53141d04d87b55aaffc205ed80454b440
parentfebe42964fe182281859b3d43d844bb25ca49367 (diff)
parisc: Fix TLB related boot crash on SMP machines
At bootup we run measurements to calculate the best threshold for when we should be using full TLB flushes instead of just flushing a specific amount of TLB entries. This performance test is run over the kernel text segment. But running this TLB performance test on the kernel text segment turned out to crash some SMP machines when the kernel text pages were mapped as huge pages. To avoid those crashes this patch simply skips this test on some SMP machines and calculates an optimal threshold based on the maximum number of available TLB entries and number of online CPUs. On a technical side, this seems to happen: The TLB measurement code uses flush_tlb_kernel_range() to flush specific TLB entries with a page size of 4k (pdtlb 0(sr1,addr)). On UP systems this purge instruction seems to work without problems even if the pages were mapped as huge pages. But on SMP systems the TLB purge instruction is broadcasted to other CPUs. Those CPUs then crash the machine because the page size is not as expected. C8000 machines with PA8800/PA8900 CPUs were not affected by this problem, because the required cache coherency prohibits to use huge pages at all. Sadly I didn't found any documentation about this behaviour, so this finding is purely based on testing with phyiscal SMP machines (A500-44 and J5000, both were 2-way boxes). Cc: <stable@vger.kernel.org> # v3.18+ Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--arch/parisc/kernel/cache.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index c263301648f3..977f0a4f5ecf 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -393,6 +393,15 @@ void __init parisc_setup_cache_timing(void)
393 393
394 /* calculate TLB flush threshold */ 394 /* calculate TLB flush threshold */
395 395
396 /* On SMP machines, skip the TLB measure of kernel text which
397 * has been mapped as huge pages. */
398 if (num_online_cpus() > 1 && !parisc_requires_coherency()) {
399 threshold = max(cache_info.it_size, cache_info.dt_size);
400 threshold *= PAGE_SIZE;
401 threshold /= num_online_cpus();
402 goto set_tlb_threshold;
403 }
404
396 alltime = mfctl(16); 405 alltime = mfctl(16);
397 flush_tlb_all(); 406 flush_tlb_all();
398 alltime = mfctl(16) - alltime; 407 alltime = mfctl(16) - alltime;
@@ -411,6 +420,8 @@ void __init parisc_setup_cache_timing(void)
411 alltime, size, rangetime); 420 alltime, size, rangetime);
412 421
413 threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime); 422 threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
423
424set_tlb_threshold:
414 if (threshold) 425 if (threshold)
415 parisc_tlb_flush_threshold = threshold; 426 parisc_tlb_flush_threshold = threshold;
416 printk(KERN_INFO "TLB flush threshold set to %lu KiB\n", 427 printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",