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