svn commit: r326236 - head/sys/powerpc/booke

Justin Hibbits jhibbits at FreeBSD.org
Sun Nov 26 20:30:03 UTC 2017


Author: jhibbits
Date: Sun Nov 26 20:30:02 2017
New Revision: 326236
URL: https://svnweb.freebsd.org/changeset/base/326236

Log:
  Synchronize TLB1 mappings when created
  
  This allows modules creating mappings to be loaded post-boot, after SMP has
  started.  Without this, the TLB1 mappings can become unsynchronized and lead
  to kernel page faults when accessed on the alternate CPUs.
  
  MFC after:	3 weeks

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

Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c	Sun Nov 26 19:17:55 2017	(r326235)
+++ head/sys/powerpc/booke/pmap.c	Sun Nov 26 20:30:02 2017	(r326236)
@@ -3872,31 +3872,27 @@ tlb1_read_entry(tlb_entry_t *entry, unsigned int slot)
 	    tsize2size((entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT);
 }
 
-/*
- * Write given entry to TLB1 hardware.
- */
+struct tlbwrite_args {
+	tlb_entry_t *e;
+	unsigned int idx;
+};
+
 static void
-tlb1_write_entry(tlb_entry_t *e, unsigned int idx)
+tlb1_write_entry_int(void *arg)
 {
-	register_t msr;
+	struct tlbwrite_args *args = arg;
 	uint32_t mas0;
 
-	//debugf("tlb1_write_entry: s\n");
-
 	/* Select entry */
-	mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(idx);
-	//debugf("tlb1_write_entry: mas0 = 0x%08x\n", mas0);
+	mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(args->idx);
 
-	msr = mfmsr();
-	__asm __volatile("wrteei 0");
-
 	mtspr(SPR_MAS0, mas0);
 	__asm __volatile("isync");
-	mtspr(SPR_MAS1, e->mas1);
+	mtspr(SPR_MAS1, args->e->mas1);
 	__asm __volatile("isync");
-	mtspr(SPR_MAS2, e->mas2);
+	mtspr(SPR_MAS2, args->e->mas2);
 	__asm __volatile("isync");
-	mtspr(SPR_MAS3, e->mas3);
+	mtspr(SPR_MAS3, args->e->mas3);
 	__asm __volatile("isync");
 	switch ((mfpvr() >> 16) & 0xFFFF) {
 	case FSL_E500mc:
@@ -3906,7 +3902,7 @@ tlb1_write_entry(tlb_entry_t *e, unsigned int idx)
 		__asm __volatile("isync");
 		/* FALLTHROUGH */
 	case FSL_E500v2:
-		mtspr(SPR_MAS7, e->mas7);
+		mtspr(SPR_MAS7, args->e->mas7);
 		__asm __volatile("isync");
 		break;
 	default:
@@ -3914,9 +3910,42 @@ tlb1_write_entry(tlb_entry_t *e, unsigned int idx)
 	}
 
 	__asm __volatile("tlbwe; isync; msync");
-	mtmsr(msr);
 
-	//debugf("tlb1_write_entry: e\n");
+}
+
+static void
+tlb1_write_entry_sync(void *arg)
+{
+	/* Empty synchronization point for smp_rendezvous(). */
+}
+
+/*
+ * Write given entry to TLB1 hardware.
+ */
+static void
+tlb1_write_entry(tlb_entry_t *e, unsigned int idx)
+{
+	struct tlbwrite_args args;
+
+	args.e = e;
+	args.idx = idx;
+
+#ifdef SMP
+	if ((e->mas2 & _TLB_ENTRY_SHARED) && smp_started) {
+		mb();
+		smp_rendezvous(tlb1_write_entry_sync,
+		    tlb1_write_entry_int,
+		    tlb1_write_entry_sync, &args);
+	} else
+#endif
+	{
+		register_t msr;
+
+		msr = mfmsr();
+		__asm __volatile("wrteei 0");
+		tlb1_write_entry_int(&args);
+		mtmsr(msr);
+	}
 }
 
 /*


More information about the svn-src-head mailing list