提交 2be0071f 编写于 作者: B bellard

simplified PowerPC exception handling (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1492 c046a42c-6fe2-441c-8c8c-71466251a162
上级 f68c781c
...@@ -68,9 +68,9 @@ typedef uint64_t target_phys_addr_t; ...@@ -68,9 +68,9 @@ typedef uint64_t target_phys_addr_t;
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8) #define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
#define EXCP_INTERRUPT 256 /* async interruption */ #define EXCP_INTERRUPT 0x10000 /* async interruption */
#define EXCP_HLT 257 /* hlt instruction reached */ #define EXCP_HLT 0x10001 /* hlt instruction reached */
#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
#define MAX_BREAKPOINTS 32 #define MAX_BREAKPOINTS 32
......
...@@ -706,28 +706,22 @@ void cpu_loop(CPUPPCState *env) ...@@ -706,28 +706,22 @@ void cpu_loop(CPUPPCState *env)
fprintf(logfile, "Invalid data memory access: 0x%08x\n", fprintf(logfile, "Invalid data memory access: 0x%08x\n",
env->spr[SPR_DAR]); env->spr[SPR_DAR]);
} }
switch (env->error_code & 0xF) { switch (env->error_code & 0xFF000000) {
case EXCP_DSI_TRANSLATE: case 0x40000000:
info.si_signo = TARGET_SIGSEGV; info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
break; break;
case EXCP_DSI_NOTSUP: case 0x04000000:
case EXCP_DSI_EXTERNAL:
info.si_signo = TARGET_SIGILL; info.si_signo = TARGET_SIGILL;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLADR; info.si_code = TARGET_ILL_ILLADR;
break; break;
case EXCP_DSI_PROT: case 0x08000000:
info.si_signo = TARGET_SIGSEGV; info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR; info.si_code = TARGET_SEGV_ACCERR;
break; break;
case EXCP_DSI_DABR:
info.si_signo = TARGET_SIGTRAP;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
break;
default: default:
/* Let's send a regular segfault... */ /* Let's send a regular segfault... */
fprintf(stderr, "Invalid segfault errno (%02x)\n", fprintf(stderr, "Invalid segfault errno (%02x)\n",
...@@ -748,19 +742,14 @@ void cpu_loop(CPUPPCState *env) ...@@ -748,19 +742,14 @@ void cpu_loop(CPUPPCState *env)
fprintf(stderr, "Invalid instruction fetch\n"); fprintf(stderr, "Invalid instruction fetch\n");
if (loglevel) if (loglevel)
fprintf(logfile, "Invalid instruction fetch\n"); fprintf(logfile, "Invalid instruction fetch\n");
switch (env->error_code) { switch (env->error_code & 0xFF000000) {
case EXCP_ISI_TRANSLATE: case 0x40000000:
info.si_signo = TARGET_SIGSEGV; info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
break; break;
case EXCP_ISI_GUARD: case 0x10000000:
info.si_signo = TARGET_SIGILL; case 0x08000000:
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLADR;
break;
case EXCP_ISI_NOEXEC:
case EXCP_ISI_PROT:
info.si_signo = TARGET_SIGSEGV; info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR; info.si_code = TARGET_SEGV_ACCERR;
...@@ -930,18 +919,6 @@ void cpu_loop(CPUPPCState *env) ...@@ -930,18 +919,6 @@ void cpu_loop(CPUPPCState *env)
if (loglevel) if (loglevel)
fprintf(logfile, "Decrementer exception\n"); fprintf(logfile, "Decrementer exception\n");
abort(); abort();
case EXCP_RESA: /* Implementation specific */
/* Should not happen ! */
fprintf(stderr, "RESA exception should never happen !\n");
if (loglevel)
fprintf(logfile, "RESA exception should never happen !\n");
abort();
case EXCP_RESB: /* Implementation specific */
/* Should not happen ! */
fprintf(stderr, "RESB exception should never happen !\n");
if (loglevel)
fprintf(logfile, "RESB exception should never happen !\n");
abort();
case EXCP_TRACE: case EXCP_TRACE:
/* Do nothing: we use this to trace execution */ /* Do nothing: we use this to trace execution */
break; break;
...@@ -963,12 +940,6 @@ void cpu_loop(CPUPPCState *env) ...@@ -963,12 +940,6 @@ void cpu_loop(CPUPPCState *env)
case EXCP_BRANCH: case EXCP_BRANCH:
/* We stopped because of a jump... */ /* We stopped because of a jump... */
break; break;
case EXCP_RFI:
/* Should not occur: we always are in user mode */
fprintf(stderr, "Return from interrupt ?\n");
if (loglevel)
fprintf(logfile, "Return from interrupt ?\n");
abort();
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */ /* Don't know why this should ever happen... */
break; break;
......
...@@ -924,62 +924,72 @@ enum { ...@@ -924,62 +924,72 @@ enum {
/*****************************************************************************/ /*****************************************************************************/
/* Exceptions */ /* Exceptions */
enum { #define EXCP_NONE -1
EXCP_NONE = -1, /* PowerPC hardware exceptions : exception vectors defined in PowerPC book 3 */
/* PowerPC hardware exceptions : exception vector / 0x100 */ #define EXCP_RESET 0x0100 /* System reset */
EXCP_RESET = 0x01, /* System reset */ #define EXCP_MACHINE_CHECK 0x0200 /* Machine check exception */
EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */ #define EXCP_DSI 0x0300 /* Data storage exception */
EXCP_DSI = 0x03, /* Impossible memory access */ #define EXCP_DSEG 0x0380 /* Data segment exception */
EXCP_ISI = 0x04, /* Impossible instruction fetch */ #define EXCP_ISI 0x0400 /* Instruction storage exception */
EXCP_EXTERNAL = 0x05, /* External interruption */ #define EXCP_ISEG 0x0480 /* Instruction segment exception */
EXCP_ALIGN = 0x06, /* Alignment exception */ #define EXCP_EXTERNAL 0x0500 /* External interruption */
EXCP_PROGRAM = 0x07, /* Program exception */ #define EXCP_ALIGN 0x0600 /* Alignment exception */
EXCP_NO_FP = 0x08, /* No floating point */ #define EXCP_PROGRAM 0x0700 /* Program exception */
EXCP_DECR = 0x09, /* Decrementer exception */ #define EXCP_NO_FP 0x0800 /* Floating point unavailable exception */
EXCP_RESA = 0x0A, /* Implementation specific */ #define EXCP_DECR 0x0900 /* Decrementer exception */
EXCP_RESB = 0x0B, /* Implementation specific */ #define EXCP_HDECR 0x0980 /* Hypervisor decrementer exception */
EXCP_SYSCALL = 0x0C, /* System call */ #define EXCP_SYSCALL 0x0C00 /* System call */
EXCP_TRACE = 0x0D, /* Trace exception (optional) */ #define EXCP_TRACE 0x0D00 /* Trace exception */
EXCP_FP_ASSIST = 0x0E, /* Floating-point assist (optional) */ #define EXCP_PERF 0x0F00 /* Performance monitor exception */
/* MPC740/745/750 & IBM 750 */ /* Exceptions defined in PowerPC 32 bits programming environment manual */
EXCP_PERF = 0x0F, /* Performance monitor */ #define EXCP_FP_ASSIST 0x0E00 /* Floating-point assist */
EXCP_IABR = 0x13, /* Instruction address breakpoint */ /* Implementation specific exceptions */
EXCP_SMI = 0x14, /* System management interrupt */ /* 40x exceptions */
EXCP_THRM = 0x15, /* Thermal management interrupt */ #define EXCP_40x_PIT 0x1000 /* Programmable interval timer interrupt */
/* MPC755 */ #define EXCP_40x_FIT 0x1010 /* Fixed interval timer interrupt */
EXCP_TLBMISS = 0x10, /* Instruction TLB miss */ #define EXCP_40x_WATCHDOG 0x1020 /* Watchdog timer exception */
EXCP_TLBMISS_DL = 0x11, /* Data TLB miss for load */ #define EXCP_40x_DTLBMISS 0x1100 /* Data TLB miss exception */
EXCP_TLBMISS_DS = 0x12, /* Data TLB miss for store */ #define EXCP_40x_ITLBMISS 0x1200 /* Instruction TLB miss exception */
EXCP_PPC_MAX = 0x16, #define EXCP_40x_DEBUG 0x2000 /* Debug exception */
/* Qemu exception */ /* 405 specific exceptions */
EXCP_OFCALL = 0x20, /* Call open-firmware emulator */ #define EXCP_405_APU 0x0F20 /* APU unavailable exception */
EXCP_RTASCALL = 0x21, /* Call RTAS emulator */ /* TLB assist exceptions (602/603) */
/* Special cases where we want to stop translation */ #define EXCP_I_TLBMISS 0x1000 /* Instruction TLB miss */
EXCP_MTMSR = 0x104, /* mtmsr instruction: */ #define EXCP_DL_TLBMISS 0x1100 /* Data load TLB miss */
#define EXCP_DS_TLBMISS 0x1200 /* Data store TLB miss */
/* Breakpoint exceptions (602/603/604/620/740/745/750/755...) */
#define EXCP_IABR 0x1300 /* Instruction address breakpoint */
#define EXCP_SMI 0x1400 /* System management interrupt */
/* Altivec related exceptions */
#define EXCP_VPU 0x0F20 /* VPU unavailable exception */
/* 601 specific exceptions */
#define EXCP_601_IO 0x0600 /* IO error exception */
#define EXCP_601_RUNM 0x2000 /* Run mode exception */
/* 602 specific exceptions */
#define EXCP_602_WATCHDOG 0x1500 /* Watchdog exception */
#define EXCP_602_EMUL 0x1600 /* Emulation trap exception */
/* G2 specific exceptions */
#define EXCP_G2_CRIT 0x0A00 /* Critical interrupt */
/* MPC740/745/750 & IBM 750 specific exceptions */
#define EXCP_THRM 0x1700 /* Thermal management interrupt */
/* 74xx specific exceptions */
#define EXCP_74xx_VPUA 0x1600 /* VPU assist exception */
/* 970FX specific exceptions */
#define EXCP_970_SOFTP 0x1500 /* Soft patch exception */
#define EXCP_970_MAINT 0x1600 /* Maintenance exception */
#define EXCP_970_THRM 0x1800 /* Thermal exception */
#define EXCP_970_VPUA 0x1700 /* VPU assist exception */
/* End of exception vectors area */
#define EXCP_PPC_MAX 0x4000
/* Qemu exceptions: special cases we want to stop translation */
#define EXCP_MTMSR 0x11000 /* mtmsr instruction: */
/* may change privilege level */ /* may change privilege level */
EXCP_BRANCH = 0x108, /* branch instruction */ #define EXCP_BRANCH 0x11001 /* branch instruction */
EXCP_RFI = 0x10C, /* return from interrupt */ #define EXCP_SYSCALL_USER 0x12000 /* System call in user mode only */
EXCP_SYSCALL_USER = 0x110, /* System call in user mode only */ #define EXCP_INTERRUPT_CRITICAL 0x13000 /* critical IRQ */
};
/* Error codes */ /* Error codes */
enum { enum {
/* Exception subtypes for EXCP_DSI */
EXCP_DSI_TRANSLATE = 0x01, /* Data address can't be translated */
EXCP_DSI_NOTSUP = 0x02, /* Access type not supported */
EXCP_DSI_PROT = 0x03, /* Memory protection violation */
EXCP_DSI_EXTERNAL = 0x04, /* External access disabled */
EXCP_DSI_DABR = 0x05, /* Data address breakpoint */
/* flags for EXCP_DSI */
EXCP_DSI_DIRECT = 0x10,
EXCP_DSI_STORE = 0x20,
EXCP_DSI_ECXW = 0x40,
/* Exception subtypes for EXCP_ISI */
EXCP_ISI_TRANSLATE = 0x01, /* Code address can't be translated */
EXCP_ISI_NOEXEC = 0x02, /* Try to fetch from a data segment */
EXCP_ISI_GUARD = 0x03, /* Fetch from guarded memory */
EXCP_ISI_PROT = 0x04, /* Memory protection violation */
EXCP_ISI_DIRECT = 0x05, /* Trying to fetch from *
* a direct store segment */
/* Exception subtypes for EXCP_ALIGN */ /* Exception subtypes for EXCP_ALIGN */
EXCP_ALIGN_FP = 0x01, /* FP alignment exception */ EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */ EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
......
此差异已折叠。
...@@ -204,16 +204,6 @@ PPC_OP(update_nip) ...@@ -204,16 +204,6 @@ PPC_OP(update_nip)
env->nip = PARAM(1); env->nip = PARAM(1);
} }
PPC_OP(debug)
{
env->nip = PARAM(1);
#if defined (DEBUG_OP)
dump_state();
#endif
do_raise_exception(EXCP_DEBUG);
RETURN();
}
/* Segment registers load and store with immediate index */ /* Segment registers load and store with immediate index */
PPC_OP(load_srin) PPC_OP(load_srin)
{ {
...@@ -1384,14 +1374,10 @@ PPC_OP(check_reservation) ...@@ -1384,14 +1374,10 @@ PPC_OP(check_reservation)
/* Return from interrupt */ /* Return from interrupt */
PPC_OP(rfi) PPC_OP(rfi)
{ {
regs->nip = regs->spr[SPR_SRR0] & ~0x00000003; env->nip = env->spr[SPR_SRR0] & ~0x00000003;
#if 1 // TRY T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
T0 = regs->spr[SPR_SRR1] & ~0xFFF00000;
#else
T0 = regs->spr[SPR_SRR1] & ~0xFFFF0000;
#endif
do_store_msr(env, T0); do_store_msr(env, T0);
do_raise_exception(EXCP_RFI); env->interrupt_request |= CPU_INTERRUPT_EXITTB;
RETURN(); RETURN();
} }
......
...@@ -42,12 +42,6 @@ void do_raise_exception_err (uint32_t exception, int error_code) ...@@ -42,12 +42,6 @@ void do_raise_exception_err (uint32_t exception, int error_code)
printf("Raise exception %3x code : %d\n", exception, error_code); printf("Raise exception %3x code : %d\n", exception, error_code);
#endif #endif
switch (exception) { switch (exception) {
case EXCP_EXTERNAL:
case EXCP_DECR:
printf("DECREMENTER & EXTERNAL exceptions should be hard interrupts !\n");
if (msr_ee == 0)
return;
break;
case EXCP_PROGRAM: case EXCP_PROGRAM:
if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0) if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
return; return;
......
...@@ -179,6 +179,12 @@ static inline void RET_STOP (DisasContext *ctx) ...@@ -179,6 +179,12 @@ static inline void RET_STOP (DisasContext *ctx)
RET_EXCP(ctx, EXCP_MTMSR, 0); RET_EXCP(ctx, EXCP_MTMSR, 0);
} }
static inline void RET_CHG_FLOW (DisasContext *ctx)
{
gen_op_raise_exception_err(EXCP_MTMSR, 0);
ctx->exception = EXCP_MTMSR;
}
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
static void gen_##name (DisasContext *ctx); \ static void gen_##name (DisasContext *ctx); \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \ GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
...@@ -1895,7 +1901,7 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) ...@@ -1895,7 +1901,7 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
return; return;
} }
gen_op_rfi(); gen_op_rfi();
RET_EXCP(ctx, EXCP_RFI, 0); RET_CHG_FLOW(ctx);
#endif #endif
} }
...@@ -2555,7 +2561,8 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ...@@ -2555,7 +2561,8 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
(msr_se && (ctx.nip < 0x100 || (msr_se && (ctx.nip < 0x100 ||
ctx.nip > 0xF00 || ctx.nip > 0xF00 ||
(ctx.nip & 0xFC) != 0x04) && (ctx.nip & 0xFC) != 0x04) &&
ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI && ctx.exception != EXCP_SYSCALL &&
ctx.exception != EXCP_SYSCALL_USER &&
ctx.exception != EXCP_TRAP)) { ctx.exception != EXCP_TRAP)) {
RET_EXCP(ctxp, EXCP_TRACE, 0); RET_EXCP(ctxp, EXCP_TRACE, 0);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册