Commit 120cf52f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] PPC32: Add Book E / PPC44x specific exception support

From: Matt Porter <mporter@kernel.crashing.org>

Adds general Book E machine check exception support and PPC44x-specific
machine check exception implementation.
parent 47d83679
......@@ -56,6 +56,19 @@
#define BOOKE_SAVE_COR
#endif
#ifdef CONFIG_BOOKE
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
mtspr SPRG6W,r8
lis r8,mcheck_save@ha
lwz r0,mcheck_r10@l(r8)
stw r0,GPR10(r11)
lwz r0,mcheck_r11@l(r8)
stw r0,GPR11(r11)
mfspr r8,SPRG6R
b transfer_to_handler_full
#endif
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
.globl crit_transfer_to_handler
crit_transfer_to_handler:
......@@ -97,7 +110,7 @@ transfer_to_handler:
beq 2f /* if from user, fix up THREAD.regs */
addi r11,r1,STACK_FRAME_OVERHEAD
stw r11,PT_REGS(r12)
#ifdef CONFIG_4xx
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
lwz r12,PTRACE-THREAD(r12)
andi. r12,r12,PT_PTRACED
beq+ 3f
......@@ -738,8 +751,10 @@ ret_from_crit_exc:
mtspr SPRN_SPRG4,r10
lwz r10,crit_sprg5@l(COR)
mtspr SPRN_SPRG5,r10
#ifdef CONFIG_40x
lwz r10,crit_sprg6@l(COR)
mtspr SPRN_SPRG6,r10
#endif
lwz r10,crit_sprg7@l(COR)
mtspr SPRN_SPRG7,r10
lwz r10,crit_srr0@l(COR)
......@@ -756,6 +771,74 @@ ret_from_crit_exc:
rfci
b . /* prevent prefetch past rfci */
#ifdef CONFIG_BOOKE
/*
* Return from a machine check interrupt, similar to a critical
* interrupt.
*/
.globl ret_from_mcheck_exc
ret_from_mcheck_exc:
REST_NVGPRS(r1)
lwz r3,_MSR(r1)
andi. r3,r3,MSR_PR
LOAD_MSR_KERNEL(r10,MSR_KERNEL)
bne user_exc_return
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
REST_4GPRS(3, r1)
REST_2GPRS(7, r1)
lwz r10,_XER(r1)
lwz r11,_CTR(r1)
mtspr XER,r10
mtctr r11
stwcx. r0,0,r1 /* to clear the reservation */
lwz r11,_LINK(r1)
mtlr r11
lwz r10,_CCR(r1)
mtcrf 0xff,r10
lwz r9,_DEAR(r1)
lwz r10,_ESR(r1)
mtspr SPRN_DEAR,r9
mtspr SPRN_ESR,r10
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
mtspr MCSRR0,r11
mtspr MCSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
mtspr SPRG6W,r8
lis r8,mcheck_save@ha
lwz r10,mcheck_sprg0@l(r8)
mtspr SPRN_SPRG0,r10
lwz r10,mcheck_sprg1@l(r8)
mtspr SPRN_SPRG1,r10
lwz r10,mcheck_sprg4@l(r8)
mtspr SPRN_SPRG4,r10
lwz r10,mcheck_sprg5@l(r8)
mtspr SPRN_SPRG5,r10
lwz r10,mcheck_sprg7@l(r8)
mtspr SPRN_SPRG7,r10
lwz r10,mcheck_srr0@l(r8)
mtspr SRR0,r10
lwz r10,mcheck_srr1@l(r8)
mtspr SRR1,r10
lwz r10,mcheck_csrr0@l(r8)
mtspr CSRR0,r10
lwz r10,mcheck_csrr1@l(r8)
mtspr CSRR1,r10
lwz r10,mcheck_pid@l(r8)
mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
mfspr r8,SPRG6R
RFMCI
#endif /* CONFIG_BOOKE */
/*
* Load the DBCR0 value for a task that is being ptraced,
* having first saved away the global DBCR0.
......
This diff is collapsed.
......@@ -222,14 +222,43 @@ MachineCheckException(struct pt_regs *regs)
if (check_io_access(regs))
return;
#ifdef CONFIG_4xx
#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
if (reason & ESR_IMCP) {
printk("Instruction");
mtspr(SPRN_ESR, reason & ~ESR_IMCP);
} else
printk("Data");
printk(" machine check in kernel mode.\n");
#elif defined(CONFIG_440A)
printk("Machine check in kernel mode.\n");
if (reason & ESR_IMCP){
printk("Instruction Synchronous Machine Check exception\n");
mtspr(SPRN_ESR, reason & ~ESR_IMCP);
}
else {
u32 mcsr = mfspr(SPRN_MCSR);
if (mcsr & MCSR_IB)
printk("Instruction Read PLB Error\n");
if (mcsr & MCSR_DRB)
printk("Data Read PLB Error\n");
if (mcsr & MCSR_DWB)
printk("Data Write PLB Error\n");
if (mcsr & MCSR_TLBP)
printk("TLB Parity Error\n");
if (mcsr & MCSR_ICP){
flush_instruction_cache();
printk("I-Cache Parity Error\n");
}
if (mcsr & MCSR_DCSP)
printk("D-Cache Search Parity Error\n");
if (mcsr & MCSR_DCFP)
printk("D-Cache Flush Parity Error\n");
if (mcsr & MCSR_IMPE)
printk("Machine Check exception is imprecise\n");
/* Clear MCSR */
mtspr(SPRN_MCSR, mcsr);
}
#else /* !CONFIG_4xx */
printk("Machine check in kernel mode.\n");
printk("Caused by (from SRR1=%lx): ", reason);
......
......@@ -161,6 +161,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
#define CLR_TOP32(r)
#endif /* CONFIG_PPC64BRIDGE */
#define RFMCI .long 0x4c00004c /* rfmci instruction */
#ifdef CONFIG_IBM405_ERR77
#define PPC405_ERR77(ra,rb) dcbt ra, rb;
#define PPC405_ERR77_SYNC sync;
......
......@@ -86,6 +86,20 @@ do { \
#define SPRN_IVOR13 0x19D /* Interrupt Vector Offset Register 13 */
#define SPRN_IVOR14 0x19E /* Interrupt Vector Offset Register 14 */
#define SPRN_IVOR15 0x19F /* Interrupt Vector Offset Register 15 */
#define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */
#define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */
#define SPRN_MCSR 0x23C /* Machine Check Status Register */
#ifdef CONFIG_440A
#define MCSR_MCS 0x80000000 /* Machine Check Summary */
#define MCSR_IB 0x40000000 /* Instruction PLB Error */
#define MCSR_DRB 0x20000000 /* Data Read PLB Error */
#define MCSR_DWB 0x10000000 /* Data Write PLB Error */
#define MCSR_TLBP 0x08000000 /* TLB Parity Error */
#define MCSR_ICP 0x04000000 /* I-Cache Parity Error */
#define MCSR_DCSP 0x02000000 /* D-Cache Search Parity Error */
#define MCSR_DCFP 0x01000000 /* D-Cache Flush Parity Error */
#define MCSR_IMPE 0x00800000 /* Imprecise Machine Check Exception */
#endif
#define SPRN_ZPR 0x3B0 /* Zone Protection Register (40x) */
#define SPRN_MMUCR 0x3B2 /* MMU Control Register */
#define SPRN_CCR0 0x3B3 /* Core Configuration Register */
......@@ -251,6 +265,8 @@ do { \
#define CSRR0 SPRN_SRR2 /* Logically and functionally equivalent. */
#define CSRR1 SPRN_SRR3 /* Logically and functionally equivalent. */
#endif
#define MCSRR0 SPRN_MCSRR0 /* Machine Check Save and Restore Register 0 */
#define MCSRR1 SPRN_MCSRR1 /* Machine Check Save and Restore Register 1 */
#define DCMP SPRN_DCMP /* Data TLB Compare Register */
#define SPRG4R SPRN_SPRG4R /* Supervisor Private Registers */
#define SPRG5R SPRN_SPRG5R
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment