Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a37102dc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -65,9 +65,9 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
		unsigned long flags;				\
		spin_lock_irqsave(&pa_tlb_lock, flags);		\
		old_pte = *ptep;				\
		set_pte(ptep, pteval);				\
		if (pte_inserted(old_pte))			\
			purge_tlb_entries(mm, addr);		\
		set_pte(ptep, pteval);				\
		spin_unlock_irqrestore(&pa_tlb_lock, flags);	\
	} while (0)

@@ -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);
		return 0;
	}
	set_pte(ptep, pte_mkold(pte));
	purge_tlb_entries(vma->vm_mm, addr);
	set_pte(ptep, pte_mkold(pte));
	spin_unlock_irqrestore(&pa_tlb_lock, flags);
	return 1;
}
@@ -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);
	old_pte = *ptep;
	set_pte(ptep, __pte(0));
	if (pte_inserted(old_pte))
		purge_tlb_entries(mm, addr);
	set_pte(ptep, __pte(0));
	spin_unlock_irqrestore(&pa_tlb_lock, flags);

	return old_pte;
@@ -504,8 +504,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
{
	unsigned long flags;
	spin_lock_irqsave(&pa_tlb_lock, flags);
	set_pte(ptep, pte_wrprotect(*ptep));
	purge_tlb_entries(mm, addr);
	set_pte(ptep, pte_wrprotect(*ptep));
	spin_unlock_irqrestore(&pa_tlb_lock, flags);
}

+11 −0
Original line number Diff line number Diff line
@@ -393,6 +393,15 @@ void __init parisc_setup_cache_timing(void)

	/* 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);
	flush_tlb_all();
	alltime = mfctl(16) - alltime;
@@ -411,6 +420,8 @@ void __init parisc_setup_cache_timing(void)
		alltime, size, rangetime);

	threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);

set_tlb_threshold:
	if (threshold)
		parisc_tlb_flush_threshold = threshold;
	printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
+1 −21
Original line number Diff line number Diff line
@@ -896,15 +896,6 @@ ENTRY_CFI(flush_dcache_page_asm)
	fdc,m		r31(%r28)

	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)
	nop
	.exit
@@ -979,17 +970,6 @@ ENTRY_CFI(flush_icache_page_asm)
	fic,m		%r31(%sr4,%r28)

	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)
	nop
	.exit