Author: jhibbits
Date: Thu May 21 03:33:20 2020
New Revision: 361317
URL: https://svnweb.freebsd.org/changeset/base/361317

Log:
  powerpc: Handle machine checks caused by D-ERAT multihit
  
  Instead of crashing the user process when a D-ERAT multihit is detected, try
  to flush the ERAT, and continue.  This machine check indicates a likely PMAP
  invalidation shortcoming that will need to be addressed, but it's
  recoverable, so just recover.  The recovery is pmap-specific to flush the
  ERAT, so add a pmap function to do so, currently only implemented by the
  POWER9 radix pmap.

Modified:
  head/sys/powerpc/aim/aim_machdep.c
  head/sys/powerpc/aim/mmu_radix.c
  head/sys/powerpc/include/pmap.h
  head/sys/powerpc/powerpc/mmu_if.m
  head/sys/powerpc/powerpc/pmap_dispatch.c

Modified: head/sys/powerpc/aim/aim_machdep.c
==============================================================================
--- head/sys/powerpc/aim/aim_machdep.c  Thu May 21 02:10:45 2020        
(r361316)
+++ head/sys/powerpc/aim/aim_machdep.c  Thu May 21 03:33:20 2020        
(r361317)
@@ -539,6 +539,10 @@ cpu_machine_check(struct thread *td, struct trapframe 
                /* SLB multi-hit is recoverable. */
                if ((frame->cpu.aim.dsisr & DSISR_MC_SLB_MULTIHIT) != 0)
                        return (0);
+               if ((frame->cpu.aim.dsisr & DSISR_MC_DERAT_MULTIHIT) != 0) {
+                       pmap_tlbie_all();
+                       return (0);
+               }
                /* TODO: Add other machine check recovery procedures. */
        } else {
                if ((frame->srr1 & SRR1_MCHK_IFETCH_M) == 
SRR1_MCHK_IFETCH_SLBMH)

Modified: head/sys/powerpc/aim/mmu_radix.c
==============================================================================
--- head/sys/powerpc/aim/mmu_radix.c    Thu May 21 02:10:45 2020        
(r361316)
+++ head/sys/powerpc/aim/mmu_radix.c    Thu May 21 03:33:20 2020        
(r361317)
@@ -482,6 +482,7 @@ static void mmu_radix_dumpsys_map(mmu_t mmu, vm_paddr_
     void **va);
 static void mmu_radix_scan_init(mmu_t mmu);
 static void    mmu_radix_cpu_bootstrap(mmu_t, int ap);
+static void    mmu_radix_tlbie_all(mmu_t);
 
 static mmu_method_t mmu_radix_methods[] = {
        MMUMETHOD(mmu_bootstrap,        mmu_radix_bootstrap),
@@ -543,6 +544,8 @@ static mmu_method_t mmu_radix_methods[] = {
        MMUMETHOD(mmu_change_attr,      mmu_radix_change_attr),
        MMUMETHOD(mmu_map_user_ptr,     mmu_radix_map_user_ptr),
        MMUMETHOD(mmu_decode_kernel_ptr, mmu_radix_decode_kernel_ptr),
+
+       MMUMETHOD(mmu_tlbie_all,        mmu_radix_tlbie_all),
        { 0, 0 }
 };
 
@@ -772,6 +775,13 @@ mmu_radix_tlbiel_flush(int scope)
 
        tlbiel_flush_isa3(POWER9_TLB_SETS_RADIX, is);
        __asm __volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
+}
+
+static void
+mmu_radix_tlbie_all(mmu_t __unused mmu)
+{
+       /* TODO: LPID invalidate */
+       mmu_radix_tlbiel_flush(TLB_INVAL_SCOPE_GLOBAL);
 }
 
 static void

Modified: head/sys/powerpc/include/pmap.h
==============================================================================
--- head/sys/powerpc/include/pmap.h     Thu May 21 02:10:45 2020        
(r361316)
+++ head/sys/powerpc/include/pmap.h     Thu May 21 03:33:20 2020        
(r361317)
@@ -341,6 +341,7 @@ vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t
 void pmap_early_io_unmap(vm_offset_t va, vm_size_t size);
 void pmap_track_page(pmap_t pmap, vm_offset_t va);
 void pmap_page_print_mappings(vm_page_t m);
+void pmap_tlbie_all(void);
 
 static inline int
 pmap_vmspace_copy(pmap_t dst_pmap __unused, pmap_t src_pmap __unused)

Modified: head/sys/powerpc/powerpc/mmu_if.m
==============================================================================
--- head/sys/powerpc/powerpc/mmu_if.m   Thu May 21 02:10:45 2020        
(r361316)
+++ head/sys/powerpc/powerpc/mmu_if.m   Thu May 21 03:33:20 2020        
(r361317)
@@ -1100,3 +1100,11 @@ METHOD boolean_t ps_enabled {
        mmu_t           _mmu;
        pmap_t          _pmap;
 } DEFAULT mmu_null_ps_enabled;
+
+
+/**
+ * @brief Flush the TLB (used by machine check handler).
+ */
+METHOD void tlbie_all {
+       mmu_t           _mmu;
+};

Modified: head/sys/powerpc/powerpc/pmap_dispatch.c
==============================================================================
--- head/sys/powerpc/powerpc/pmap_dispatch.c    Thu May 21 02:10:45 2020        
(r361316)
+++ head/sys/powerpc/powerpc/pmap_dispatch.c    Thu May 21 03:33:20 2020        
(r361317)
@@ -631,6 +631,13 @@ pmap_ps_enabled(pmap_t pmap)
        return (MMU_PS_ENABLED(mmu_obj, pmap));
 }
 
+void
+pmap_tlbie_all(void)
+{
+       CTR1(KTR_PMAP, "%s()", __func__);
+       return (MMU_TLBIE_ALL(mmu_obj));
+}
+
 /*
  * MMU install routines. Highest priority wins, equal priority also
  * overrides allowing last-set to win.
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to