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
This commit is contained in:
parent
9d176904ae
commit
81962477fc
@ -515,6 +515,32 @@ memcpy(pcpu->pc_aim.slb, PCPU_GET(aim.slb), sizeof(pcpu->pc_aim.slb));
|
||||
#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)
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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 */
|
||||
|
@ -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,17 +508,16 @@ cpu_printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
|
||||
uint16_t ver;
|
||||
|
||||
switch (vector) {
|
||||
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);
|
||||
case EXC_DSE:
|
||||
case EXC_DSI:
|
||||
case EXC_DTMISS:
|
||||
printf(" dsisr = 0x%lx\n",
|
||||
(u_long)frame->cpu.aim.dsisr);
|
||||
break;
|
||||
}
|
||||
#elif defined(BOOKE)
|
||||
@ -556,6 +550,7 @@ printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
|
||||
case EXC_DSI:
|
||||
case EXC_DTMISS:
|
||||
case EXC_ALI:
|
||||
case EXC_MCHK:
|
||||
printf(" virtual address = 0x%" PRIxPTR "\n", frame->dar);
|
||||
break;
|
||||
case EXC_ISE:
|
||||
@ -563,8 +558,6 @@ printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
|
||||
case EXC_ITMISS:
|
||||
printf(" virtual address = 0x%" PRIxPTR "\n", frame->srr0);
|
||||
break;
|
||||
case EXC_MCHK:
|
||||
break;
|
||||
}
|
||||
cpu_printtrap(vector, frame, isfatal, user);
|
||||
printf(" srr0 = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n",
|
||||
|
Loading…
Reference in New Issue
Block a user