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);
+       }
 }
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to