Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Dec 2015 02:23:14 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r292900 - head/sys/powerpc/booke
Message-ID:  <201512300223.tBU2NEGk079674@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Wed Dec 30 02:23:14 2015
New Revision: 292900
URL: https://svnweb.freebsd.org/changeset/base/292900

Log:
  Rewrite tid_flush() in C.
  
  There's no need for it to be in asm.  Also, by writing in C, and marking it
  static in pmap.c, it saves a branch to the function itself, as it's only used in
  one location.  The generated asm is virtually identical to the handwritten code.

Modified:
  head/sys/powerpc/booke/locore.S
  head/sys/powerpc/booke/pmap.c

Modified: head/sys/powerpc/booke/locore.S
==============================================================================
--- head/sys/powerpc/booke/locore.S	Wed Dec 30 02:15:12 2015	(r292899)
+++ head/sys/powerpc/booke/locore.S	Wed Dec 30 02:23:14 2015	(r292900)
@@ -658,77 +658,6 @@ __boot_page_padding:
 /************************************************************************/
 
 /*
- * void tid_flush(tlbtid_t tid);
- *
- * Invalidate all TLB0 entries which match the given TID. Note this is
- * dedicated for cases when invalidation(s) should NOT be propagated to other
- * CPUs.
- *
- * void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way);
- *
- * XXX: why isn't this in C?
- */
-ENTRY(tid_flush)
-	cmpwi	%r3, TID_KERNEL
-	beq	tid_flush_end	/* don't evict kernel translations */
-
-	/* Disable interrupts */
-	mfmsr	%r10
-	wrteei	0
-
-	li	%r6, 0		/* ways counter */
-loop_ways:
-	li	%r7, 0		/* entries [per way] counter */
-loop_entries:
-	/* Select TLB0 and ESEL (way) */
-	lis	%r8, MAS0_TLBSEL0@h
-	rlwimi	%r8, %r6, 16, 14, 15
-	mtspr	SPR_MAS0, %r8
-	isync
-
-	/* Select EPN (entry within the way) */
-	rlwinm	%r8, %r7, 12, 13, 19
-	mtspr	SPR_MAS2, %r8
-	isync
-	tlbre
-
-	/* Check if valid entry */
-	mfspr	%r8, SPR_MAS1
-	andis.	%r9, %r8, MAS1_VALID@h
-	beq	next_entry	/* invalid entry */
-
-	/* Check if this is our TID */
-	rlwinm	%r9, %r8, 16, 24, 31
-
-	cmplw	%r9, %r3
-	bne	next_entry	/* not our TID */
-
-	/* Clear VALID bit */
-	rlwinm	%r8, %r8, 0, 1, 31
-	mtspr	SPR_MAS1, %r8
-	isync
-	tlbwe
-	isync
-	msync
-
-next_entry:
-	addi	%r7, %r7, 1
-	cmpw	%r7, %r5
-	bne	loop_entries
-
-	/* Next way */
-	addi	%r6, %r6, 1
-	cmpw	%r6, %r4
-	bne	loop_ways
-
-	/* Restore MSR (possibly re-enable interrupts) */
-	mtmsr	%r10
-	isync
-
-tid_flush_end:
-	blr
-
-/*
  * Cache disable/enable/inval sequences according
  * to section 2.16 of E500CORE RM.
  */

Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c	Wed Dec 30 02:15:12 2015	(r292899)
+++ head/sys/powerpc/booke/pmap.c	Wed Dec 30 02:23:14 2015	(r292900)
@@ -161,7 +161,6 @@ unsigned int kernel_ptbls;	/* Number of 
 #define PMAP_REMOVE_DONE(pmap) \
 	((pmap) != kernel_pmap && (pmap)->pm_stats.resident_count == 0)
 
-extern void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way);
 extern int elf32_nxstack;
 
 /**************************************************************************/
@@ -195,6 +194,7 @@ static unsigned int tlb1_idx;
 static vm_offset_t tlb1_map_base = VM_MAX_KERNEL_ADDRESS;
 
 static tlbtid_t tid_alloc(struct pmap *);
+static void tid_flush(tlbtid_t tid);
 
 static void tlb_print_entry(int, uint32_t, uint32_t, uint32_t, uint32_t);
 
@@ -2915,7 +2915,7 @@ tid_alloc(pmap_t pmap)
 		tidbusy[thiscpu][tid]->pm_tid[thiscpu] = TID_NONE;
 
 		/* Flush all entries from TLB0 matching this TID. */
-		tid_flush(tid, tlb0_ways, tlb0_entries_per_way);
+		tid_flush(tid);
 	}
 
 	tidbusy[thiscpu][tid] = pmap;
@@ -3426,3 +3426,48 @@ tlb1_iomapped(int i, vm_paddr_t pa, vm_s
 	*va = (tlb1[i].mas2 & MAS2_EPN_MASK) + (pa - pa_start);
 	return (0);
 }
+
+/*
+ * Invalidate all TLB0 entries which match the given TID. Note this is
+ * dedicated for cases when invalidations should NOT be propagated to other
+ * CPUs.
+ */
+static void
+tid_flush(tlbtid_t tid)
+{
+	register_t msr;
+	uint32_t mas0, mas1, mas2;
+	int entry, way;
+
+
+	/* Don't evict kernel translations */
+	if (tid == TID_KERNEL)
+		return;
+
+	msr = mfmsr();
+	__asm __volatile("wrteei 0");
+
+	for (way = 0; way < TLB0_WAYS; way++)
+		for (entry = 0; entry < TLB0_ENTRIES_PER_WAY; entry++) {
+
+			mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(way);
+			mtspr(SPR_MAS0, mas0);
+			__asm __volatile("isync");
+
+			mas2 = entry << MAS2_TLB0_ENTRY_IDX_SHIFT;
+			mtspr(SPR_MAS2, mas2);
+
+			__asm __volatile("isync; tlbre");
+
+			mas1 = mfspr(SPR_MAS1);
+
+			if (!(mas1 & MAS1_VALID))
+				continue;
+			if (((mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT) != tid)
+				continue;
+			mas1 &= ~MAS1_VALID;
+			mtspr(SPR_MAS1, mas1);
+			__asm __volatile("isync; tlbwe; isync; msync");
+		}
+	mtmsr(msr);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512300223.tBU2NEGk079674>