#ifdef _KERNEL_OPT
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_ppcarch.h"
#endif
#define GET_PCB(rX) \
GET_CPUINFO(rX); \
lwz rX,CI_CURPCB(rX)
#define STANDARD_PROLOG(savearea) \
mtsprg1 %r1; \
GET_CPUINFO(%r1); \
stmw %r28,(savearea+CPUSAVE_R28)(%r1); \
mflr %r28; \
mfcr %r29; \
mfsrr0 %r30; \
mfsrr1 %r31; \
stmw %r30,(savearea+CPUSAVE_SRR0)(%r1); \
mfsprg1 %r1; \
mtcr %r31; \
bf MSR_PR,1f; \
GET_PCB(%r1); \
addi %r1,%r1,USPACE-CALLFRAMELEN; \
1:
#define ACCESS_PROLOG(savearea) \
mtsprg1 %r1; \
GET_CPUINFO(%r1); \
stmw %r28,(savearea+CPUSAVE_R28)(%r1); \
mflr %r28; \
mfcr %r29; \
mfspr %r30,SPR_DEAR; \
mfspr %r31,SPR_ESR; \
stmw %r30,(savearea+CPUSAVE_DEAR)(%r1); \
mfsrr0 %r30; \
mfsrr1 %r31; \
stmw %r30,(savearea+CPUSAVE_SRR0)(%r1); \
mfsprg1 %r1; \
mtcr %r31; \
bf MSR_PR,1f; \
GET_PCB(%r1); \
addi %r1,%r1,USPACE-CALLFRAMELEN; \
1:
#ifdef PPC_IBM440
#define CRITICAL_PROLOG(savearea) \
mtsprg1 %r1; \
GET_CPUINFO(%r1); \
stmw %r28,(savearea+CPUSAVE_R28)(%r1); \
mflr %r28; \
mfcr %r29; \
mfspr %r30,SPR_CSRR0; \
mfspr %r31,SPR_CSRR1; \
stmw %r30,(savearea+CPUSAVE_SRR0)(%r1); \
mfsprg1 %r1; \
mtcr %r31; \
bf MSR_PR,1f; \
GET_PCB(%r1); \
addi %r1,%r1,USPACE-CALLFRAMELEN; \
1:
#define MCHK_PROLOG(savearea) \
mtsprg1 %r1; \
GET_CPUINFO(%r1); \
stmw %r28,(savearea+CPUSAVE_R28)(%r1); \
mflr %r28; \
mfcr %r29; \
mfspr %r30,SPR_MCSRR0; \
mfspr %r31,SPR_MCSRR1; \
stmw %r30,(savearea+CPUSAVE_SRR0)(%r1); \
mfsprg1 %r1; \
mtcr %r31; \
bf MSR_PR,1f; \
GET_PCB(%r1); \
addi %r1,%r1,USPACE-CALLFRAMELEN; \
1:
#else
#define CRITICAL_PROLOG(savearea) \
mtsprg1 %r1; \
GET_CPUINFO(%r1); \
stmw %r28,(savearea+CPUSAVE_R28)(%r1); \
mflr %r28; \
mfcr %r29; \
mfsrr2 %r30; \
mfsrr3 %r31; \
stmw %r30,(savearea+CPUSAVE_SRR0)(%r1); \
mfsprg1 %r1; \
mtcr %r31; \
bf MSR_PR,1f; \
GET_PCB(%r1); \
addi %r1,%r1,USPACE-CALLFRAMELEN; \
1:
#endif
#define STANDARD_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
STANDARD_PROLOG(CI_TEMPSAVE); \
bla s_trap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
#define ACCESS_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
ACCESS_PROLOG(CI_TEMPSAVE); \
bla s_trap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
#ifdef PPC_IBM440
#define CRITICAL_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
CRITICAL_PROLOG(CI_CRITSAVE); \
bla s_ctrap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
#else
#define CRITICAL_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
CRITICAL_PROLOG(CI_TEMPSAVE); \
bla s_trap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
#endif
#define INTR_PROLOG(tempsave) \
mtsprg1 %r1; \
GET_CPUINFO(%r1); \
stmw %r28,(tempsave+CPUSAVE_R28)(%r1); \
mflr %r28; \
mfcr %r29; \
mfxer %r30; \
mfsrr1 %r31; \
mtcr %r31; \
mfsprg1 %r1; \
bf MSR_PR,1f; \
GET_PCB(%r1); \
addi %r1,%r1,USPACE-CALLFRAMELEN; \
1:
#ifdef PPC_IBM440
#define MCHK_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
MCHK_PROLOG(CI_CRITSAVE); \
bla s_mctrap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
#endif
.text
STANDARD_EXC_HANDLER(default)
ACCESS_EXC_HANDLER(access)
CRITICAL_EXC_HANDLER(critical)
#ifdef PPC_IBM440
MCHK_EXC_HANDLER(mchk)
#endif
.globl _C_LABEL(extint),_C_LABEL(extsize)
_C_LABEL(extint):
INTR_PROLOG(CI_TEMPSAVE)
ba extintr
_C_LABEL(extsize) = .-_C_LABEL(extint)
#if defined(DDB) || defined(KGDB)
.globl _C_LABEL(ddblow),_C_LABEL(ddbsize)
_C_LABEL(ddblow):
ACCESS_PROLOG(CI_DDBSAVE)
bla ddbtrap
_C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
#endif
#ifdef DEBUG
#define TRAP_IF_ZERO(r) tweqi r,0
#else
#define TRAP_IF_ZERO(r)
#endif
#define ENABLE_TRANSLATION(pidreg,tmpreg) \
mfspr pidreg,SPR_PID; \
li tmpreg,KERNEL_PID; \
mtspr SPR_PID,tmpreg; \
mfmsr tmpreg; \
ori tmpreg,tmpreg,(PSL_DR|PSL_IR)@l; \
mtmsr tmpreg; \
isync
#define CLEAR_WAIT_STATE(reg) rlwinm reg,reg,0,14,12
#define FRAME_SETUP(savearea) \
\
ENABLE_TRANSLATION(%r30,%r31); \
mfsprg1 %r31; \
stwu %r31,-FRAMELEN(%r1); \
stw %r30,FRAME_PID(%r1); \
stw %r0,FRAME_R0(%r1); \
stw %r31,FRAME_R1(%r1); \
stw %r2,FRAME_R2(%r1); \
GET_CPUINFO(%r2); \
stw %r28,FRAME_LR(%r1); \
stw %r29,FRAME_CR(%r1); \
lmw %r28,(savearea+CPUSAVE_R28)(%r2); \
stmw %r3,FRAME_R3(%r1); \
lmw %r28,(savearea+CPUSAVE_DEAR)(%r2); \
lwz %r13,CI_CURLWP(%r2); \
mfxer %r3; \
mfctr %r4; \
mflr %r5; \
andi. %r5,%r5,0xff00; \
stw %r3,FRAME_XER(%r1); \
stw %r4,FRAME_CTR(%r1); \
stw %r5,FRAME_EXC(%r1); \
stw %r28,FRAME_DEAR(%r1); \
stw %r29,FRAME_ESR(%r1); \
stw %r30,FRAME_SRR0(%r1); \
CLEAR_WAIT_STATE(%r31); \
stw %r31,FRAME_SRR1(%r1)
#define FRAME_SAVE_CALLEE \
stmw %r14,FRAME_R14(%r1)
#define FRAME_RESTORE \
lwz %r6,FRAME_LR(%r1); \
lwz %r7,FRAME_CR(%r1); \
lwz %r8,FRAME_XER(%r1); \
lwz %r9,FRAME_CTR(%r1); \
lwz %r10,FRAME_SRR0(%r1); \
lwz %r11,FRAME_SRR1(%r1); \
mtlr %r6; \
mtcr %r7; \
mtxer %r8; \
mtctr %r9; \
mtsrr0 %r10; \
mtsrr1 %r11; \
lwz %r13,FRAME_R13(%r1); \
lwz %r12,FRAME_R12(%r1); \
lwz %r11,FRAME_R11(%r1); \
lwz %r10,FRAME_R10(%r1); \
lwz %r9,FRAME_R9(%r1); \
lwz %r8,FRAME_R8(%r1); \
lwz %r7,FRAME_R7(%r1); \
lwz %r6,FRAME_R6(%r1); \
lwz %r5,FRAME_R5(%r1); \
lwz %r4,FRAME_R4(%r1); \
lwz %r3,FRAME_R3(%r1); \
lwz %r2,FRAME_R2(%r1); \
lwz %r0,FRAME_R1(%r1); \
mtsprg1 %r0; \
lwz %r0,FRAME_R0(%r1)
s_trap:
FRAME_SETUP(CI_TEMPSAVE)
trapagain:
wrtee %r31
addi %r3,%r1,FRAME_TF
bl _C_LABEL(trap)
.globl _C_LABEL(trapexit)
_C_LABEL(trapexit):
wrteei 0
mtcr %r31
bf MSR_PR,trapleave_to_kernel
lwz %r4,L_MD_ASTPENDING(%r13)
andi. %r4,%r4,1
beq trapleave_to_user
li %r6,EXC_AST
stw %r6,FRAME_EXC(%r1)
b trapagain
trapleave_to_kernel:
lmw %r14, FRAME_R14(%r1)
intrleave_to_kernel:
FRAME_RESTORE
mtsprg2 %r30
mtsprg3 %r31
mfmsr %r30
li %r31,(PSL_DR|PSL_IR)@l
andc %r30,%r30,%r31
lwz %r31,FRAME_PID(%r1)
TRAP_IF_ZERO(%r31)
mfsprg1 %r1
mtmsr %r30
isync
mtspr SPR_PID,%r31
mfsprg3 %r31
mfsprg2 %r30
IBM405_ERRATA77_SYNC
rfi
ba .
trapleave_to_user:
lmw %r14, FRAME_R14(%r1)
intrleave_to_user:
lwz %r3,FRAME_PID(%r1)
lwz %r4,FRAME_SRR1(%r1)
bl _C_LABEL(ctx_setup)
TRAP_IF_ZERO(%r3)
stw %r3,FRAME_PID(%r1)
FRAME_RESTORE
mtsprg2 %r30
mtsprg3 %r31
mfmsr %r30
li %r31,(PSL_DR|PSL_IR)@l
andc %r30,%r30,%r31
lwz %r31,FRAME_PID(%r1)
TRAP_IF_ZERO(%r31)
mfsprg1 %r1
mtmsr %r30
isync
mtspr SPR_PID,%r31
mfsprg3 %r31
mfsprg2 %r30
IBM405_ERRATA77_SYNC
rfi
ba .
#ifdef PPC_IBM440
#define FRAME_RESTORE_TO(srr0spr, srr1spr) \
lwz %r6,FRAME_LR(%r1); \
lwz %r7,FRAME_CR(%r1); \
lwz %r8,FRAME_XER(%r1); \
lwz %r9,FRAME_CTR(%r1); \
lwz %r10,FRAME_SRR0(%r1); \
lwz %r11,FRAME_SRR1(%r1); \
mtlr %r6; \
mtcr %r7; \
mtxer %r8; \
mtctr %r9; \
mtspr srr0spr,%r10; \
mtspr srr1spr,%r11; \
lwz %r13,FRAME_R13(%r1); \
lwz %r12,FRAME_R12(%r1); \
lwz %r11,FRAME_R11(%r1); \
lwz %r10,FRAME_R10(%r1); \
lwz %r9,FRAME_R9(%r1); \
lwz %r8,FRAME_R8(%r1); \
lwz %r7,FRAME_R7(%r1); \
lwz %r6,FRAME_R6(%r1); \
lwz %r5,FRAME_R5(%r1); \
lwz %r4,FRAME_R4(%r1); \
lwz %r3,FRAME_R3(%r1); \
lwz %r2,FRAME_R2(%r1); \
lwz %r0,FRAME_R1(%r1); \
mtsprg1 %r0; \
lwz %r0,FRAME_R0(%r1)
#define CRIT_LEAVE_PROLOGUE \
mtsprg2 %r30; \
mtsprg3 %r31; \
mfmsr %r30; \
li %r31,(PSL_DR|PSL_IR)@l; \
andc %r30,%r30,%r31; \
lwz %r31,FRAME_PID(%r1); \
TRAP_IF_ZERO(%r31); \
mfsprg1 %r1; \
mtmsr %r30; \
isync; \
mtspr SPR_PID,%r31; \
mfsprg3 %r31; \
mfsprg2 %r30
s_ctrap:
FRAME_SETUP(CI_CRITSAVE)
wrtee %r31
addi %r3,%r1,FRAME_TF
bl _C_LABEL(trap)
wrteei 0
lmw %r14,FRAME_R14(%r1)
FRAME_RESTORE_TO(SPR_CSRR0, SPR_CSRR1)
CRIT_LEAVE_PROLOGUE
rfci
ba .
s_mctrap:
FRAME_SETUP(CI_CRITSAVE)
addi %r3,%r1,FRAME_TF
bl _C_LABEL(trap)
lmw %r14,FRAME_R14(%r1)
FRAME_RESTORE_TO(SPR_MCSRR0, SPR_MCSRR1)
CRIT_LEAVE_PROLOGUE
rfmci
ba .
#endif
.globl _C_LABEL(sctrap),_C_LABEL(scsize),_C_LABEL(sctrapexit)
_C_LABEL(sctrap):
STANDARD_PROLOG(CI_TEMPSAVE)
bla s_sctrap
_C_LABEL(scsize) = .-_C_LABEL(sctrap)
s_sctrap:
FRAME_SETUP(CI_TEMPSAVE)
wrteei 1
addi %r3,%r1,FRAME_TF
lwz %r4,L_PROC(%r13)
lwz %r4,P_MD_SYSCALL(%r4)
mtctr %r4
bctrl
_C_LABEL(sctrapexit):
b trapexit
#define INTR_SAVE(tempsave) \
\
stwu %r1,-FRAMELEN(%r1); \
stw %r0,FRAME_R0(%r1); \
mfsprg1 %r0; \
stw %r0,FRAME_R1(%r1); \
stw %r2,FRAME_R2(%r1); \
stw %r3,FRAME_R3(%r1); \
stw %r4,FRAME_R4(%r1); \
stw %r5,FRAME_R5(%r1); \
stw %r6,FRAME_R6(%r1); \
stw %r7,FRAME_R7(%r1); \
stw %r8,FRAME_R8(%r1); \
stw %r9,FRAME_R9(%r1); \
stw %r10,FRAME_R10(%r1); \
stw %r11,FRAME_R11(%r1); \
stw %r12,FRAME_R12(%r1); \
stw %r13,FRAME_R13(%r1); \
mfctr %r31; \
stmw %r28,FRAME_LR(%r1); \
GET_CPUINFO(%r5); \
lmw %r28,(tempsave+CPUSAVE_R28)(%r5); \
lwz %r13,CI_CURLWP(%r5); \
lwz %r5,CI_IDEPTH(%r5); \
mfsrr0 %r4; \
mfsrr1 %r3; \
stw %r5,FRAME_IDEPTH(%r1); \
stw %r4,FRAME_SRR0(%r1); \
CLEAR_WAIT_STATE(%r3); \
stw %r3,FRAME_SRR1(%r1); \
\
ENABLE_TRANSLATION(%r0,%r5); \
stw %r0,FRAME_PID(%r1);
.globl _C_LABEL(extint_call)
extintr:
INTR_SAVE(CI_TEMPSAVE)
_C_LABEL(extint_call):
bl _C_LABEL(extint_call)
intr_exit:
wrteei 0
isync
lwz %r4,FRAME_SRR1(%r1)
mtcr %r4
bf MSR_PR,intrleave_to_kernel
lwz %r4,L_MD_ASTPENDING(%r13)
andi. %r4,%r4,1
beq intrleave_to_user
FRAME_SAVE_CALLEE
li %r6,EXC_AST
stw %r6,FRAME_EXC(%r1)
lwz %r31,FRAME_SRR1(%r1)
b trapagain
.align 5
_C_LABEL(pitint):
INTR_PROLOG(CI_TEMPSAVE)
INTR_SAVE(CI_TEMPSAVE)
addi %r3,%r1,FRAME_CF
bl _C_LABEL(decr_intr)
b intr_exit
.align 5
_C_LABEL(fitint):
INTR_PROLOG(CI_TEMPSAVE)
INTR_SAVE(CI_TEMPSAVE)
addi %r3,%r1,FRAME_CF
bl _C_LABEL(stat_intr)
b intr_exit
#if defined(DDB) || defined(KGDB)
.globl _C_LABEL(ddb_trap)
_C_LABEL(ddb_trap):
mtsprg1 %r1
GET_CPUINFO(%r4)
mfmsr %r3
stw %r3,(CI_DDBSAVE+CPUSAVE_SRR1)(%r4)
wrteei 0
isync
stmw %r28,CI_DDBSAVE(%r4)
mflr %r28
stw %r28,(CI_DDBSAVE+CPUSAVE_SRR0)(%r4)
li %r29,EXC_BPT
mtlr %r29
mfcr %r29
ddbtrap:
FRAME_SETUP(CI_DDBSAVE)
addi %r3,%r1,FRAME_TF
bl _C_LABEL(ddb_trap_glue)
or. %r3,%r3,%r3
beq trapagain
b trapexit
#endif
#ifdef PPC_IBM440
#include <powerpc/powerpc/fpu_subr.S>
#endif