Commit a37102dc authored by Linus Torvalds's avatar Linus Torvalds

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
parents b4aafe77 24d0492b
...@@ -65,9 +65,9 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) ...@@ -65,9 +65,9 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
unsigned long flags; \ unsigned long flags; \
spin_lock_irqsave(&pa_tlb_lock, flags); \ spin_lock_irqsave(&pa_tlb_lock, flags); \
old_pte = *ptep; \ old_pte = *ptep; \
set_pte(ptep, pteval); \
if (pte_inserted(old_pte)) \ if (pte_inserted(old_pte)) \
purge_tlb_entries(mm, addr); \ purge_tlb_entries(mm, addr); \
set_pte(ptep, pteval); \
spin_unlock_irqrestore(&pa_tlb_lock, flags); \ spin_unlock_irqrestore(&pa_tlb_lock, flags); \
} while (0) } while (0)
...@@ -478,8 +478,8 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned ...@@ -478,8 +478,8 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
spin_unlock_irqrestore(&pa_tlb_lock, flags); spin_unlock_irqrestore(&pa_tlb_lock, flags);
return 0; return 0;
} }
set_pte(ptep, pte_mkold(pte));
purge_tlb_entries(vma->vm_mm, addr); purge_tlb_entries(vma->vm_mm, addr);
set_pte(ptep, pte_mkold(pte));
spin_unlock_irqrestore(&pa_tlb_lock, flags); spin_unlock_irqrestore(&pa_tlb_lock, flags);
return 1; return 1;
} }
...@@ -492,9 +492,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, ...@@ -492,9 +492,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
spin_lock_irqsave(&pa_tlb_lock, flags); spin_lock_irqsave(&pa_tlb_lock, flags);
old_pte = *ptep; old_pte = *ptep;
set_pte(ptep, __pte(0));
if (pte_inserted(old_pte)) if (pte_inserted(old_pte))
purge_tlb_entries(mm, addr); purge_tlb_entries(mm, addr);
set_pte(ptep, __pte(0));
spin_unlock_irqrestore(&pa_tlb_lock, flags); spin_unlock_irqrestore(&pa_tlb_lock, flags);
return old_pte; return old_pte;
...@@ -504,8 +504,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, ...@@ -504,8 +504,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&pa_tlb_lock, flags); spin_lock_irqsave(&pa_tlb_lock, flags);
set_pte(ptep, pte_wrprotect(*ptep));
purge_tlb_entries(mm, addr); purge_tlb_entries(mm, addr);
set_pte(ptep, pte_wrprotect(*ptep));
spin_unlock_irqrestore(&pa_tlb_lock, flags); spin_unlock_irqrestore(&pa_tlb_lock, flags);
} }
......
...@@ -393,6 +393,15 @@ void __init parisc_setup_cache_timing(void) ...@@ -393,6 +393,15 @@ void __init parisc_setup_cache_timing(void)
/* calculate TLB flush threshold */ /* calculate TLB flush threshold */
/* On SMP machines, skip the TLB measure of kernel text which
* has been mapped as huge pages. */
if (num_online_cpus() > 1 && !parisc_requires_coherency()) {
threshold = max(cache_info.it_size, cache_info.dt_size);
threshold *= PAGE_SIZE;
threshold /= num_online_cpus();
goto set_tlb_threshold;
}
alltime = mfctl(16); alltime = mfctl(16);
flush_tlb_all(); flush_tlb_all();
alltime = mfctl(16) - alltime; alltime = mfctl(16) - alltime;
...@@ -411,6 +420,8 @@ void __init parisc_setup_cache_timing(void) ...@@ -411,6 +420,8 @@ void __init parisc_setup_cache_timing(void)
alltime, size, rangetime); alltime, size, rangetime);
threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime); threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
set_tlb_threshold:
if (threshold) if (threshold)
parisc_tlb_flush_threshold = threshold; parisc_tlb_flush_threshold = threshold;
printk(KERN_INFO "TLB flush threshold set to %lu KiB\n", printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
......
...@@ -896,15 +896,6 @@ ENTRY_CFI(flush_dcache_page_asm) ...@@ -896,15 +896,6 @@ ENTRY_CFI(flush_dcache_page_asm)
fdc,m r31(%r28) fdc,m r31(%r28)
sync sync
#ifdef CONFIG_PA20
pdtlb,l %r0(%r25)
#else
tlb_lock %r20,%r21,%r22
pdtlb %r0(%r25)
tlb_unlock %r20,%r21,%r22
#endif
bv %r0(%r2) bv %r0(%r2)
nop nop
.exit .exit
...@@ -979,17 +970,6 @@ ENTRY_CFI(flush_icache_page_asm) ...@@ -979,17 +970,6 @@ ENTRY_CFI(flush_icache_page_asm)
fic,m %r31(%sr4,%r28) fic,m %r31(%sr4,%r28)
sync sync
#ifdef CONFIG_PA20
pdtlb,l %r0(%r28)
pitlb,l %r0(%sr4,%r25)
#else
tlb_lock %r20,%r21,%r22
pdtlb %r0(%r28)
pitlb %r0(%sr4,%r25)
tlb_unlock %r20,%r21,%r22
#endif
bv %r0(%r2) bv %r0(%r2)
nop nop
.exit .exit
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment