target/hppa: Define hardware exception types

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2017-10-11 10:03:02 -07:00
parent ba1d0b4482
commit 2986721df7
6 changed files with 110 additions and 32 deletions

View File

@ -3773,21 +3773,41 @@ void cpu_loop(CPUHPPAState *env)
env->iaoq_f = env->gr[31]; env->iaoq_f = env->gr[31];
env->iaoq_b = env->gr[31] + 4; env->iaoq_b = env->gr[31] + 4;
break; break;
case EXCP_SIGSEGV: case EXCP_ITLB_MISS:
case EXCP_DTLB_MISS:
case EXCP_NA_ITLB_MISS:
case EXCP_NA_DTLB_MISS:
case EXCP_IMP:
case EXCP_DMP:
case EXCP_DMB:
case EXCP_PAGE_REF:
case EXCP_DMAR:
case EXCP_DMPI:
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;
info._sifields._sigfault._addr = env->ior; info._sifields._sigfault._addr = env->ior;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_SIGILL: case EXCP_UNALIGN:
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = 0;
info._sifields._sigfault._addr = env->ior;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case EXCP_ILL:
case EXCP_PRIV_OPR:
case EXCP_PRIV_REG:
info.si_signo = TARGET_SIGILL; info.si_signo = TARGET_SIGILL;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN; info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->iaoq_f; info._sifields._sigfault._addr = env->iaoq_f;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_SIGFPE: case EXCP_OVERFLOW:
case EXCP_COND:
case EXCP_ASSIST:
info.si_signo = TARGET_SIGFPE; info.si_signo = TARGET_SIGFPE;
info.si_errno = 0; info.si_errno = 0;
info.si_code = 0; info.si_code = 0;

View File

@ -40,11 +40,40 @@
#define MMU_USER_IDX 0 #define MMU_USER_IDX 0
#define TARGET_INSN_START_EXTRA_WORDS 1 #define TARGET_INSN_START_EXTRA_WORDS 1
#define EXCP_SYSCALL 1 /* Hardware exceptions, interupts, faults, and traps. */
#define EXCP_SYSCALL_LWS 2 #define EXCP_HPMC 1 /* high priority machine check */
#define EXCP_SIGSEGV 3 #define EXCP_POWER_FAIL 2
#define EXCP_SIGILL 4 #define EXCP_RC 3 /* recovery counter */
#define EXCP_SIGFPE 5 #define EXCP_EXT_INTERRUPT 4 /* external interrupt */
#define EXCP_LPMC 5 /* low priority machine check */
#define EXCP_ITLB_MISS 6 /* itlb miss / instruction page fault */
#define EXCP_IMP 7 /* instruction memory protection trap */
#define EXCP_ILL 8 /* illegal instruction trap */
#define EXCP_BREAK 9 /* break instruction */
#define EXCP_PRIV_OPR 10 /* privileged operation trap */
#define EXCP_PRIV_REG 11 /* privileged register trap */
#define EXCP_OVERFLOW 12 /* signed overflow trap */
#define EXCP_COND 13 /* trap-on-condition */
#define EXCP_ASSIST 14 /* assist exception trap */
#define EXCP_DTLB_MISS 15 /* dtlb miss / data page fault */
#define EXCP_NA_ITLB_MISS 16 /* non-access itlb miss */
#define EXCP_NA_DTLB_MISS 17 /* non-access dtlb miss */
#define EXCP_DMP 18 /* data memory protection trap */
#define EXCP_DMB 19 /* data memory break trap */
#define EXCP_TLB_DIRTY 20 /* tlb dirty bit trap */
#define EXCP_PAGE_REF 21 /* page reference trap */
#define EXCP_ASSIST_EMU 22 /* assist emulation trap */
#define EXCP_HPT 23 /* high-privilege transfer trap */
#define EXCP_LPT 24 /* low-privilege transfer trap */
#define EXCP_TB 25 /* taken branch trap */
#define EXCP_DMAR 26 /* data memory access rights trap */
#define EXCP_DMPI 27 /* data memory protection id trap */
#define EXCP_UNALIGN 28 /* unaligned data reference trap */
#define EXCP_PER_INTERRUPT 29 /* performance monitor interrupt */
/* Exceptions for linux-user emulation. */
#define EXCP_SYSCALL 30
#define EXCP_SYSCALL_LWS 31
/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */ /* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
#define PSW_I 0x00000001 #define PSW_I 0x00000001

View File

@ -74,25 +74,52 @@ void hppa_cpu_do_interrupt(CPUState *cs)
int i = cs->exception_index; int i = cs->exception_index;
if (qemu_loglevel_mask(CPU_LOG_INT)) { if (qemu_loglevel_mask(CPU_LOG_INT)) {
static const char * const names[] = {
[EXCP_HPMC] = "high priority machine check",
[EXCP_POWER_FAIL] = "power fail interrupt",
[EXCP_RC] = "recovery counter trap",
[EXCP_EXT_INTERRUPT] = "external interrupt",
[EXCP_LPMC] = "low priority machine check",
[EXCP_ITLB_MISS] = "instruction tlb miss fault",
[EXCP_IMP] = "instruction memory protection trap",
[EXCP_ILL] = "illegal instruction trap",
[EXCP_BREAK] = "break instruction trap",
[EXCP_PRIV_OPR] = "privileged operation trap",
[EXCP_PRIV_REG] = "privileged register trap",
[EXCP_OVERFLOW] = "overflow trap",
[EXCP_COND] = "conditional trap",
[EXCP_ASSIST] = "assist exception trap",
[EXCP_DTLB_MISS] = "data tlb miss fault",
[EXCP_NA_ITLB_MISS] = "non-access instruction tlb miss",
[EXCP_NA_DTLB_MISS] = "non-access data tlb miss",
[EXCP_DMP] = "data memory protection trap",
[EXCP_DMB] = "data memory break trap",
[EXCP_TLB_DIRTY] = "tlb dirty bit trap",
[EXCP_PAGE_REF] = "page reference trap",
[EXCP_ASSIST_EMU] = "assist emulation trap",
[EXCP_HPT] = "high-privilege transfer trap",
[EXCP_LPT] = "low-privilege transfer trap",
[EXCP_TB] = "taken branch trap",
[EXCP_DMAR] = "data memory access rights trap",
[EXCP_DMPI] = "data memory protection id trap",
[EXCP_UNALIGN] = "unaligned data reference trap",
[EXCP_PER_INTERRUPT] = "performance monitor interrupt",
[EXCP_SYSCALL] = "syscall",
[EXCP_SYSCALL_LWS] = "syscall-lws",
};
static int count; static int count;
const char *name = "<unknown>"; const char *name = NULL;
switch (i) { if (i >= 0 && i < ARRAY_SIZE(names)) {
case EXCP_SYSCALL: name = names[i];
name = "syscall"; }
break; if (name) {
case EXCP_SIGSEGV: qemu_log("INT %6d: %s ia_f=" TARGET_FMT_lx "\n",
name = "sigsegv"; ++count, name, env->iaoq_f);
break; } else {
case EXCP_SIGILL: qemu_log("INT %6d: unknown %d ia_f=" TARGET_FMT_lx "\n",
name = "sigill"; ++count, i, env->iaoq_f);
break;
case EXCP_SIGFPE:
name = "sigfpe";
break;
} }
qemu_log("INT %6d: %s ia_f=" TARGET_FMT_lx "\n",
++count, name, env->iaoq_f);
} }
cs->exception_index = -1; cs->exception_index = -1;
} }

View File

@ -29,7 +29,9 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
{ {
HPPACPU *cpu = HPPA_CPU(cs); HPPACPU *cpu = HPPA_CPU(cs);
cs->exception_index = EXCP_SIGSEGV; /* ??? Test between data page fault and data memory protection trap,
which would affect si_code. */
cs->exception_index = EXCP_DMP;
cpu->env.ior = address; cpu->env.ior = address;
return 1; return 1;
} }

View File

@ -44,14 +44,14 @@ static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra)
void HELPER(tsv)(CPUHPPAState *env, target_ulong cond) void HELPER(tsv)(CPUHPPAState *env, target_ulong cond)
{ {
if (unlikely((target_long)cond < 0)) { if (unlikely((target_long)cond < 0)) {
dynexcp(env, EXCP_SIGFPE, GETPC()); dynexcp(env, EXCP_OVERFLOW, GETPC());
} }
} }
void HELPER(tcond)(CPUHPPAState *env, target_ulong cond) void HELPER(tcond)(CPUHPPAState *env, target_ulong cond)
{ {
if (unlikely(cond)) { if (unlikely(cond)) {
dynexcp(env, EXCP_SIGFPE, GETPC()); dynexcp(env, EXCP_COND, GETPC());
} }
} }
@ -235,7 +235,7 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
env->fr[0] = (uint64_t)shadow << 32; env->fr[0] = (uint64_t)shadow << 32;
if (hard_exp & shadow) { if (hard_exp & shadow) {
dynexcp(env, EXCP_SIGFPE, ra); dynexcp(env, EXCP_ASSIST, ra);
} }
} }

View File

@ -462,7 +462,7 @@ static DisasJumpType gen_excp(DisasContext *ctx, int exception)
static DisasJumpType gen_illegal(DisasContext *ctx) static DisasJumpType gen_illegal(DisasContext *ctx)
{ {
nullify_over(ctx); nullify_over(ctx);
return nullify_end(ctx, gen_excp(ctx, EXCP_SIGILL)); return nullify_end(ctx, gen_excp(ctx, EXCP_ILL));
} }
static bool use_goto_tb(DisasContext *ctx, target_ulong dest) static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
@ -1578,7 +1578,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx)
switch (ctx->iaoq_f) { switch (ctx->iaoq_f) {
case 0x00: /* Null pointer call */ case 0x00: /* Null pointer call */
gen_excp_1(EXCP_SIGSEGV); gen_excp_1(EXCP_IMP);
return DISAS_NORETURN; return DISAS_NORETURN;
case 0xb0: /* LWS */ case 0xb0: /* LWS */
@ -1597,7 +1597,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx)
default: default:
do_sigill: do_sigill:
gen_excp_1(EXCP_SIGILL); gen_excp_1(EXCP_ILL);
return DISAS_NORETURN; return DISAS_NORETURN;
} }
} }
@ -1614,7 +1614,7 @@ static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn,
const DisasInsn *di) const DisasInsn *di)
{ {
nullify_over(ctx); nullify_over(ctx);
return nullify_end(ctx, gen_excp(ctx, EXCP_DEBUG)); return nullify_end(ctx, gen_excp(ctx, EXCP_BREAK));
} }
static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn, static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn,