diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-08 18:40:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-08 18:40:15 -0500 |
commit | a37102dcd7ec71f6f6a00b1ad770c3bde3af3c18 (patch) | |
tree | dc3f896f1180a70c2c138dcd292066e06a6a8f73 | |
parent | b4aafe77ec65ab2846a5780bb1ba4eff7ccf82d1 (diff) | |
parent | 24d0492b7d5d321a9c5846c8c974eba9823ffaa0 (diff) |
Merge branch 'parisc-4.9-5' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc fixes from Helge Deller:
"Three important fixes for the parisc architecture.
Dave provided two patches: One which purges the TLB before setting a
PTE entry and a second one which drops unnecessary TLB flushes. Both
patches have been tested for one week on the debian buildd servers and
prevent random segmentation faults.
The patch from me fixes a crash at boot inside the TLB measuring code
on SMP machines with PA8000-PA8700 CPUs (specifically A500-44 and
J5000 servers)"
* 'parisc-4.9-5' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Fix TLB related boot crash on SMP machines
parisc: Remove unnecessary TLB purges from flush_dcache_page_asm and flush_icache_page_asm
parisc: Purge TLB before setting PTE
-rw-r--r-- | arch/parisc/include/asm/pgtable.h | 8 | ||||
-rw-r--r-- | arch/parisc/kernel/cache.c | 11 | ||||
-rw-r--r-- | arch/parisc/kernel/pacache.S | 22 |
3 files changed, 16 insertions, 25 deletions
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index c2c43f714684..3a4ed9f91d57 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
@@ -65,9 +65,9 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | |||
65 | unsigned long flags; \ | 65 | unsigned long flags; \ |
66 | spin_lock_irqsave(&pa_tlb_lock, flags); \ | 66 | spin_lock_irqsave(&pa_tlb_lock, flags); \ |
67 | old_pte = *ptep; \ | 67 | old_pte = *ptep; \ |
68 | set_pte(ptep, pteval); \ | ||
69 | if (pte_inserted(old_pte)) \ | 68 | if (pte_inserted(old_pte)) \ |
70 | purge_tlb_entries(mm, addr); \ | 69 | purge_tlb_entries(mm, addr); \ |
70 | set_pte(ptep, pteval); \ | ||
71 | spin_unlock_irqrestore(&pa_tlb_lock, flags); \ | 71 | spin_unlock_irqrestore(&pa_tlb_lock, flags); \ |
72 | } while (0) | 72 | } while (0) |
73 | 73 | ||
@@ -478,8 +478,8 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned | |||
478 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 478 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
479 | return 0; | 479 | return 0; |
480 | } | 480 | } |
481 | set_pte(ptep, pte_mkold(pte)); | ||
482 | purge_tlb_entries(vma->vm_mm, addr); | 481 | purge_tlb_entries(vma->vm_mm, addr); |
482 | set_pte(ptep, pte_mkold(pte)); | ||
483 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 483 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
484 | return 1; | 484 | return 1; |
485 | } | 485 | } |
@@ -492,9 +492,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
492 | 492 | ||
493 | spin_lock_irqsave(&pa_tlb_lock, flags); | 493 | spin_lock_irqsave(&pa_tlb_lock, flags); |
494 | old_pte = *ptep; | 494 | old_pte = *ptep; |
495 | set_pte(ptep, __pte(0)); | ||
496 | if (pte_inserted(old_pte)) | 495 | if (pte_inserted(old_pte)) |
497 | purge_tlb_entries(mm, addr); | 496 | purge_tlb_entries(mm, addr); |
497 | set_pte(ptep, __pte(0)); | ||
498 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 498 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
499 | 499 | ||
500 | return old_pte; | 500 | return old_pte; |
@@ -504,8 +504,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
504 | { | 504 | { |
505 | unsigned long flags; | 505 | unsigned long flags; |
506 | spin_lock_irqsave(&pa_tlb_lock, flags); | 506 | spin_lock_irqsave(&pa_tlb_lock, flags); |
507 | set_pte(ptep, pte_wrprotect(*ptep)); | ||
508 | purge_tlb_entries(mm, addr); | 507 | purge_tlb_entries(mm, addr); |
508 | set_pte(ptep, pte_wrprotect(*ptep)); | ||
509 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 509 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
510 | } | 510 | } |
511 | 511 | ||
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 | |||
424 | set_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", |
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 1b39a2acaadf..adf7187f8951 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S | |||
@@ -892,19 +892,10 @@ ENTRY_CFI(flush_dcache_page_asm) | |||
892 | fdc,m r31(%r28) | 892 | fdc,m r31(%r28) |
893 | fdc,m r31(%r28) | 893 | fdc,m r31(%r28) |
894 | fdc,m r31(%r28) | 894 | fdc,m r31(%r28) |
895 | cmpb,COND(<<) %r28, %r25,1b | 895 | cmpb,COND(<<) %r28, %r25,1b |
896 | fdc,m r31(%r28) | 896 | fdc,m r31(%r28) |
897 | 897 | ||
898 | sync | 898 | sync |
899 | |||
900 | #ifdef CONFIG_PA20 | ||
901 | pdtlb,l %r0(%r25) | ||
902 | #else | ||
903 | tlb_lock %r20,%r21,%r22 | ||
904 | pdtlb %r0(%r25) | ||
905 | tlb_unlock %r20,%r21,%r22 | ||
906 | #endif | ||
907 | |||
908 | bv %r0(%r2) | 899 | bv %r0(%r2) |
909 | nop | 900 | nop |
910 | .exit | 901 | .exit |
@@ -979,17 +970,6 @@ ENTRY_CFI(flush_icache_page_asm) | |||
979 | fic,m %r31(%sr4,%r28) | 970 | fic,m %r31(%sr4,%r28) |
980 | 971 | ||
981 | sync | 972 | sync |
982 | |||
983 | #ifdef CONFIG_PA20 | ||
984 | pdtlb,l %r0(%r28) | ||
985 | pitlb,l %r0(%sr4,%r25) | ||
986 | #else | ||
987 | tlb_lock %r20,%r21,%r22 | ||
988 | pdtlb %r0(%r28) | ||
989 | pitlb %r0(%sr4,%r25) | ||
990 | tlb_unlock %r20,%r21,%r22 | ||
991 | #endif | ||
992 | |||
993 | bv %r0(%r2) | 973 | bv %r0(%r2) |
994 | nop | 974 | nop |
995 | .exit | 975 | .exit |