target/microblaze: Cleanup mb_cpu_do_interrupt

Reindent; remove dead/commented code.
Use D_FLAG to set ESS[DS].
Sink MSR adjustment for kernel entry, iflags and res_addr clear.
Improve CPU_LOG_INT formatting; report pc and msr before and after.

Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2020-09-02 23:11:00 -07:00
parent 64603d1eff
commit a9f614587b

View File

@ -111,6 +111,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env; CPUMBState *env = &cpu->env;
uint32_t t, msr = mb_cpu_read_msr(env); uint32_t t, msr = mb_cpu_read_msr(env);
bool set_esr;
/* IMM flag cannot propagate across a branch and into the dslot. */ /* IMM flag cannot propagate across a branch and into the dslot. */
assert((env->iflags & (D_FLAG | IMM_FLAG)) != (D_FLAG | IMM_FLAG)); assert((env->iflags & (D_FLAG | IMM_FLAG)) != (D_FLAG | IMM_FLAG));
@ -118,142 +119,114 @@ void mb_cpu_do_interrupt(CPUState *cs)
assert((env->iflags & (D_FLAG | BIMM_FLAG)) != BIMM_FLAG); assert((env->iflags & (D_FLAG | BIMM_FLAG)) != BIMM_FLAG);
/* RTI flags are private to translate. */ /* RTI flags are private to translate. */
assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
env->res_addr = RES_ADDR_NONE;
switch (cs->exception_index) { switch (cs->exception_index) {
case EXCP_HW_EXCP: case EXCP_HW_EXCP:
if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) {
qemu_log_mask(LOG_GUEST_ERROR, "Exception raised on system without exceptions!\n"); qemu_log_mask(LOG_GUEST_ERROR,
return; "Exception raised on system without exceptions!\n");
} return;
}
env->regs[17] = env->pc + 4; qemu_log_mask(CPU_LOG_INT,
env->esr &= ~(1 << 12); "INT: HWE at pc=%08x msr=%08x iflags=%x\n",
env->pc, msr, env->iflags);
/* Exception breaks branch + dslot sequence? */ /* Exception breaks branch + dslot sequence? */
if (env->iflags & D_FLAG) { set_esr = true;
env->esr |= 1 << 12 ; env->esr &= ~D_FLAG;
env->btr = env->btarget; if (env->iflags & D_FLAG) {
} env->esr |= D_FLAG;
env->btr = env->btarget;
}
/* Disable the MMU. */ /* Exception in progress. */
t = (msr & (MSR_VM | MSR_UM)) << 1; msr |= MSR_EIP;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); env->regs[17] = env->pc + 4;
msr |= t; env->pc = cpu->cfg.base_vectors + 0x20;
/* Exception in progress. */ break;
msr |= MSR_EIP;
mb_cpu_write_msr(env, msr);
qemu_log_mask(CPU_LOG_INT, case EXCP_MMU:
"hw exception at pc=%x ear=%" PRIx64 " " qemu_log_mask(CPU_LOG_INT,
"esr=%x iflags=%x\n", "INT: MMU at pc=%08x msr=%08x "
env->pc, env->ear, "ear=%" PRIx64 " iflags=%x\n",
env->esr, env->iflags); env->pc, msr, env->ear, env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x20;
break;
case EXCP_MMU: /* Exception breaks branch + dslot sequence? */
set_esr = true;
env->esr &= ~D_FLAG;
if (env->iflags & D_FLAG) {
env->esr |= D_FLAG;
env->btr = env->btarget;
/* Reexecute the branch. */
env->regs[17] = env->pc - (env->iflags & BIMM_FLAG ? 8 : 4);
} else if (env->iflags & IMM_FLAG) {
/* Reexecute the imm. */
env->regs[17] = env->pc - 4;
} else {
env->regs[17] = env->pc; env->regs[17] = env->pc;
}
qemu_log_mask(CPU_LOG_INT, /* Exception in progress. */
"MMU exception at pc=%x iflags=%x ear=%" PRIx64 "\n", msr |= MSR_EIP;
env->pc, env->iflags, env->ear); env->pc = cpu->cfg.base_vectors + 0x20;
break;
env->esr &= ~(1 << 12); case EXCP_IRQ:
/* Exception breaks branch + dslot sequence? */ assert(!(msr & (MSR_EIP | MSR_BIP)));
if (env->iflags & D_FLAG) { assert(msr & MSR_IE);
env->esr |= 1 << 12 ; assert(!(env->iflags & (D_FLAG | IMM_FLAG)));
env->btr = env->btarget;
/* Reexecute the branch. */ qemu_log_mask(CPU_LOG_INT,
env->regs[17] -= 4; "INT: DEV at pc=%08x msr=%08x iflags=%x\n",
/* was the branch immprefixed?. */ env->pc, msr, env->iflags);
if (env->iflags & BIMM_FLAG) { set_esr = false;
env->regs[17] -= 4;
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
}
} else if (env->iflags & IMM_FLAG) {
env->regs[17] -= 4;
}
/* Disable the MMU. */ /* Disable interrupts. */
t = (msr & (MSR_VM | MSR_UM)) << 1; msr &= ~MSR_IE;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); env->regs[14] = env->pc;
msr |= t; env->pc = cpu->cfg.base_vectors + 0x10;
/* Exception in progress. */ break;
msr |= MSR_EIP;
mb_cpu_write_msr(env, msr);
qemu_log_mask(CPU_LOG_INT, case EXCP_HW_BREAK:
"exception at pc=%x ear=%" PRIx64 " iflags=%x\n", assert(!(env->iflags & (D_FLAG | IMM_FLAG)));
env->pc, env->ear, env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x20;
break;
case EXCP_IRQ: qemu_log_mask(CPU_LOG_INT,
assert(!(msr & (MSR_EIP | MSR_BIP))); "INT: BRK at pc=%08x msr=%08x iflags=%x\n",
assert(msr & MSR_IE); env->pc, msr, env->iflags);
assert(!(env->iflags & (D_FLAG | IMM_FLAG))); set_esr = false;
t = (msr & (MSR_VM | MSR_UM)) << 1; /* Break in progress. */
msr |= MSR_BIP;
env->regs[16] = env->pc;
env->pc = cpu->cfg.base_vectors + 0x18;
break;
#if 0 default:
#include "disas/disas.h" cpu_abort(cs, "unhandled exception type=%d\n", cs->exception_index);
/* not reached */
}
/* Useful instrumentation when debugging interrupt issues in either /* Save previous mode, disable mmu, disable user-mode. */
the models or in sw. */ t = (msr & (MSR_VM | MSR_UM)) << 1;
{ msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
const char *sym; msr |= t;
mb_cpu_write_msr(env, msr);
sym = lookup_symbol(env->pc); env->res_addr = RES_ADDR_NONE;
if (sym env->iflags = 0;
&& (!strcmp("netif_rx", sym)
|| !strcmp("process_backlog", sym))) {
qemu_log("interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n", if (!set_esr) {
env->pc, msr, t, env->iflags, sym); qemu_log_mask(CPU_LOG_INT,
" to pc=%08x msr=%08x\n", env->pc, msr);
log_cpu_state(cs, 0); } else if (env->esr & D_FLAG) {
} qemu_log_mask(CPU_LOG_INT,
} " to pc=%08x msr=%08x esr=%04x btr=%08x\n",
#endif env->pc, msr, env->esr, env->btr);
qemu_log_mask(CPU_LOG_INT, } else {
"interrupt at pc=%x msr=%x %x iflags=%x\n", qemu_log_mask(CPU_LOG_INT,
env->pc, msr, t, env->iflags); " to pc=%08x msr=%08x esr=%04x\n",
env->pc, msr, env->esr);
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM | MSR_IE);
msr |= t;
mb_cpu_write_msr(env, msr);
env->regs[14] = env->pc;
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x10;
//log_cpu_state_mask(CPU_LOG_INT, cs, 0);
break;
case EXCP_HW_BREAK:
assert(!(env->iflags & (D_FLAG | IMM_FLAG)));
t = (msr & (MSR_VM | MSR_UM)) << 1;
qemu_log_mask(CPU_LOG_INT,
"break at pc=%x msr=%x %x iflags=%x\n",
env->pc, msr, t, env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
msr |= t;
msr |= MSR_BIP;
env->regs[16] = env->pc;
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x18;
mb_cpu_write_msr(env, msr);
break;
default:
cpu_abort(cs, "unhandled exception type=%d\n",
cs->exception_index);
break;
} }
} }