Author: jhibbits
Date: Sun May 10 19:00:57 2020
New Revision: 360881
URL: https://svnweb.freebsd.org/changeset/base/360881

Log:
  powerpc: Add a CPU-custom machine check handler
  
  Summary:
  Some machine checks are process-recoverable, others are not.  Let a
  CPU-specific handler decide what to do.
  
  This works around a machine check error hit while building www/firefox
  and mail/thunderbird, which would otherwise cause the build to fail.
  
  More work is needed to handle all possible machine check conditions, but
  this is sufficient to unblock some ports building.
  
  Differential Revision: https://reviews.freebsd.org/D23731

Modified:
  head/sys/powerpc/aim/aim_machdep.c
  head/sys/powerpc/aim/trap_subr64.S
  head/sys/powerpc/booke/machdep_e500.c
  head/sys/powerpc/include/cpu.h
  head/sys/powerpc/include/spr.h
  head/sys/powerpc/powerpc/trap.c

Modified: head/sys/powerpc/aim/aim_machdep.c
==============================================================================
--- head/sys/powerpc/aim/aim_machdep.c  Sun May 10 18:17:25 2020        
(r360880)
+++ head/sys/powerpc/aim/aim_machdep.c  Sun May 10 19:00:57 2020        
(r360881)
@@ -515,6 +515,32 @@ memcpy(pcpu->pc_aim.slb, PCPU_GET(aim.slb), sizeof(pcp
 #endif
 }
 
+/* Return 0 on handled success, otherwise signal number. */
+int
+cpu_machine_check(struct thread *td, struct trapframe *frame, int *ucode)
+{
+#ifdef __powerpc64__
+       /*
+        * This block is 64-bit CPU specific currently.  Punt running in 32-bit
+        * mode on 64-bit CPUs.
+        */
+       /* Check if the important information is in DSISR */
+       if ((frame->srr1 & SRR1_MCHK_DATA) != 0) {
+               printf("Machine check, DSISR: %016lx\n", frame->cpu.aim.dsisr);
+               /* SLB multi-hit is recoverable. */
+               if ((frame->cpu.aim.dsisr & DSISR_MC_SLB_MULTIHIT) != 0)
+                       return (0);
+               /* TODO: Add other machine check recovery procedures. */
+       } else {
+               if ((frame->srr1 & SRR1_MCHK_IFETCH_M) == 
SRR1_MCHK_IFETCH_SLBMH)
+                       return (0);
+       }
+#endif
+       *ucode = BUS_OBJERR;
+       return (SIGBUS);
+}
+
+
 #ifndef __powerpc64__
 uint64_t
 va_to_vsid(pmap_t pm, vm_offset_t va)

Modified: head/sys/powerpc/aim/trap_subr64.S
==============================================================================
--- head/sys/powerpc/aim/trap_subr64.S  Sun May 10 18:17:25 2020        
(r360880)
+++ head/sys/powerpc/aim/trap_subr64.S  Sun May 10 19:00:57 2020        
(r360881)
@@ -797,6 +797,8 @@ generictrap:
        std     %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
        mfdar   %r30
        std     %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
+       mfdsisr %r30
+       std     %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
        mfsprg1 %r1                     /* restore SP, in case of branch */
        mfsprg2 %r28                    /* save LR */
        mfcr    %r29                    /* save CR */

Modified: head/sys/powerpc/booke/machdep_e500.c
==============================================================================
--- head/sys/powerpc/booke/machdep_e500.c       Sun May 10 18:17:25 2020        
(r360880)
+++ head/sys/powerpc/booke/machdep_e500.c       Sun May 10 19:00:57 2020        
(r360881)
@@ -119,3 +119,15 @@ void
 booke_disable_l2_cache(void)
 {
 }
+
+/* Return 0 on handled success, otherwise signal number. */
+int
+cpu_machine_check(struct thread *td, struct trapframe *frame, int *ucode)
+{
+       register_t mcsr;
+
+       mcsr = mfspr(SPR_MCSR);
+
+       *ucode = BUS_OBJERR;
+       return (SIGBUS);
+}

Modified: head/sys/powerpc/include/cpu.h
==============================================================================
--- head/sys/powerpc/include/cpu.h      Sun May 10 18:17:25 2020        
(r360880)
+++ head/sys/powerpc/include/cpu.h      Sun May 10 19:00:57 2020        
(r360881)
@@ -134,6 +134,8 @@ get_cyclecount(void)
 extern char btext[];
 extern char etext[];
 
+struct thread;
+
 #ifdef __powerpc64__
 extern void enter_idle_powerx(void);
 extern uint64_t can_wakeup;
@@ -146,5 +148,6 @@ void        cpu_sleep(void);
 void   flush_disable_caches(void);
 void   fork_trampoline(void);
 void   swi_vm(void *);
+int    cpu_machine_check(struct thread *, struct trapframe *, int *);
 
 #endif /* _MACHINE_CPU_H_ */

Modified: head/sys/powerpc/include/spr.h
==============================================================================
--- head/sys/powerpc/include/spr.h      Sun May 10 18:17:25 2020        
(r360880)
+++ head/sys/powerpc/include/spr.h      Sun May 10 19:00:57 2020        
(r360881)
@@ -108,6 +108,15 @@
 #define          DSISR_DABR              0x00400000 /* DABR match */
 #define          DSISR_SEGMENT           0x00200000 /* XXX; not in 6xx PEM */
 #define          DSISR_EAR               0x00100000 /* eciwx/ecowx && EAR[E] 
== 0 */
+#define          DSISR_MC_UE_DEFERRED    0x00008000 /* UE deferred error */
+#define          DSISR_MC_UE_TABLEWALK   0x00004000 /* UE deferred error 
during tablewalk */
+#define          DSISR_MC_DERAT_MULTIHIT         0x00000800 /* D-ERAT 
multi-hit */
+#define          DSISR_MC_TLB_MULTIHIT   0x00000400 /* TLB multi-hit */
+#define          DSISR_MC_TLBIE_ERR      0x00000200 /* TLBIE or TLBIEL 
programming error */
+#define          DSISR_MC_SLB_PARITY     0x00000100 /* SLB parity error */
+#define          DSISR_MC_SLB_MULTIHIT   0x00000080 /* SLB Multi-hit detected 
(D-side) */
+#define          DSISR_MC_BAD_REAL_LD    0x00000040 /* Bad real address for 
load. */
+#define          DSISR_MC_BAD_ADDR       0x00000020 /* Bad address for load or 
store tablewalk */
 #define        SPR_DAR                 0x013   /* .68 Data Address Register */
 #define        SPR_RTCU_W              0x014   /* .6. 601 RTC Upper - Write */
 #define        SPR_RTCL_W              0x015   /* .6. 601 RTC Lower - Write */
@@ -115,9 +124,12 @@
 #define        SPR_SDR1                0x019   /* .68 Page table base address 
register */
 #define        SPR_SRR0                0x01a   /* 468 Save/Restore Register 0 
*/
 #define        SPR_SRR1                0x01b   /* 468 Save/Restore Register 1 
*/
-#define          SRR1_ISI_PFAULT       0x40000000 /* ISI page not found */
-#define          SRR1_ISI_NOEXECUTE    0x10000000 /* Memory marked no-execute 
*/
-#define          SRR1_ISI_PP           0x08000000 /* PP bits forbid access */
+#define          SRR1_ISI_PFAULT         0x40000000 /* ISI page not found */
+#define          SRR1_ISI_NOEXECUTE      0x10000000 /* Memory marked 
no-execute */
+#define          SRR1_ISI_PP             0x08000000 /* PP bits forbid access */
+#define          SRR1_MCHK_DATA          0x00200000 /* Machine check data in 
DSISR */
+#define          SRR1_MCHK_IFETCH_M      0x081c0000 /* Machine check instr 
fetch mask */
+#define          SRR1_MCHK_IFETCH_SLBMH  0x000c0000 /* SLB multihit */
 #define        SPR_DECAR               0x036   /* ..8 Decrementer auto reload 
*/
 #define        SPR_EIE                 0x050   /* ..8 Exception Interrupt ??? 
*/
 #define        SPR_EID                 0x051   /* ..8 Exception Interrupt ??? 
*/
@@ -725,6 +737,16 @@
 
 #define        SPR_MCARU               0x239   /* ..8 Machine Check Address 
register upper bits */
 #define        SPR_MCSR                0x23c   /* ..8 Machine Check Syndrome 
register */
+#define          MCSR_MCP                0x80000000 /* Machine check input 
signal to core */
+#define          MCSR_L2MMU_MHIT         0x08000000 /* L2 MMU simultaneous hit 
*/
+#define          MCSR_NMI                0x00100000 /* Non-maskable interrupt 
*/
+#define          MCSR_MAV                0x00080000 /* MCAR address valid */
+#define          MCSR_MEA                0x00040000 /* MCAR effective address 
*/
+#define          MCSR_IF                 0x00010000 /* Instruction fetch error 
report */
+#define          MCSR_LD                 0x00008000 /* Load instruction error 
report */
+#define          MCSR_ST                 0x00004000 /* Store instruction error 
report */
+#define          MCSR_LDG                0x00002000 /* Guarded load 
instruction error report */
+#define          MCSR_TLBSYNC            0x00000002 /* Simultaneous TLBSYNC 
detected */
 #define        SPR_MCAR                0x23d   /* ..8 Machine Check Address 
register */
 
 #define        SPR_ESR                 0x003e  /* ..8 Exception Syndrome 
Register */

Modified: head/sys/powerpc/powerpc/trap.c
==============================================================================
--- head/sys/powerpc/powerpc/trap.c     Sun May 10 18:17:25 2020        
(r360880)
+++ head/sys/powerpc/powerpc/trap.c     Sun May 10 19:00:57 2020        
(r360881)
@@ -402,13 +402,8 @@ trap(struct trapframe *frame)
                        break;
 
                case EXC_MCHK:
-                       /*
-                        * Note that this may not be recoverable for the user
-                        * process, depending on the type of machine check,
-                        * but it at least prevents the kernel from dying.
-                        */
-                       sig = SIGBUS;
-                       ucode = BUS_OBJERR;
+                       sig = cpu_machine_check(td, frame, &ucode);
+                       printtrap(frame->exc, frame, 0, (frame->srr1 & PSL_PR));
                        break;
 
 #if defined(__powerpc64__) && defined(AIM)
@@ -513,18 +508,17 @@ cpu_printtrap(u_int vector, struct trapframe *frame, i
        uint16_t ver;
 
        switch (vector) {
+       case EXC_MCHK:
+               ver = mfpvr() >> 16;
+               if (MPC745X_P(ver))
+                       printf("    msssr0         = 0x%b\n",
+                           (int)mfspr(SPR_MSSSR0), MSSSR_BITMASK);
        case EXC_DSE:
        case EXC_DSI:
        case EXC_DTMISS:
                printf("   dsisr           = 0x%lx\n",
                    (u_long)frame->cpu.aim.dsisr);
                break;
-       case EXC_MCHK:
-               ver = mfpvr() >> 16;
-               if (MPC745X_P(ver))
-                       printf("    msssr0         = 0x%b\n",
-                           (int)mfspr(SPR_MSSSR0), MSSSR_BITMASK);
-               break;
        }
 #elif defined(BOOKE)
        vm_paddr_t pa;
@@ -556,14 +550,13 @@ printtrap(u_int vector, struct trapframe *frame, int i
        case EXC_DSI:
        case EXC_DTMISS:
        case EXC_ALI:
+       case EXC_MCHK:
                printf("   virtual address = 0x%" PRIxPTR "\n", frame->dar);
                break;
        case EXC_ISE:
        case EXC_ISI:
        case EXC_ITMISS:
                printf("   virtual address = 0x%" PRIxPTR "\n", frame->srr0);
-               break;
-       case EXC_MCHK:
                break;
        }
        cpu_printtrap(vector, frame, isfatal, user);
_______________________________________________
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