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,78 +119,56 @@ 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,
"Exception raised on system without exceptions!\n");
return; 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? */
set_esr = true;
env->esr &= ~D_FLAG;
if (env->iflags & D_FLAG) { if (env->iflags & D_FLAG) {
env->esr |= 1 << 12 ; env->esr |= D_FLAG;
env->btr = env->btarget; env->btr = env->btarget;
} }
/* Disable the MMU. */
t = (msr & (MSR_VM | MSR_UM)) << 1;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
msr |= t;
/* Exception in progress. */ /* Exception in progress. */
msr |= MSR_EIP; msr |= MSR_EIP;
mb_cpu_write_msr(env, msr); env->regs[17] = env->pc + 4;
qemu_log_mask(CPU_LOG_INT,
"hw exception at pc=%x ear=%" PRIx64 " "
"esr=%x iflags=%x\n",
env->pc, env->ear,
env->esr, env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x20; env->pc = cpu->cfg.base_vectors + 0x20;
break; break;
case EXCP_MMU: case EXCP_MMU:
env->regs[17] = env->pc;
qemu_log_mask(CPU_LOG_INT, qemu_log_mask(CPU_LOG_INT,
"MMU exception at pc=%x iflags=%x ear=%" PRIx64 "\n", "INT: MMU at pc=%08x msr=%08x "
env->pc, env->iflags, env->ear); "ear=%" PRIx64 " iflags=%x\n",
env->pc, msr, env->ear, env->iflags);
env->esr &= ~(1 << 12);
/* Exception breaks branch + dslot sequence? */ /* Exception breaks branch + dslot sequence? */
set_esr = true;
env->esr &= ~D_FLAG;
if (env->iflags & D_FLAG) { if (env->iflags & D_FLAG) {
env->esr |= 1 << 12 ; env->esr |= D_FLAG;
env->btr = env->btarget; env->btr = env->btarget;
/* Reexecute the branch. */ /* Reexecute the branch. */
env->regs[17] -= 4; env->regs[17] = env->pc - (env->iflags & BIMM_FLAG ? 8 : 4);
/* was the branch immprefixed?. */
if (env->iflags & BIMM_FLAG) {
env->regs[17] -= 4;
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
}
} else if (env->iflags & IMM_FLAG) { } else if (env->iflags & IMM_FLAG) {
env->regs[17] -= 4; /* Reexecute the imm. */
env->regs[17] = env->pc - 4;
} else {
env->regs[17] = env->pc;
} }
/* Disable the MMU. */
t = (msr & (MSR_VM | MSR_UM)) << 1;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
msr |= t;
/* Exception in progress. */ /* Exception in progress. */
msr |= MSR_EIP; msr |= MSR_EIP;
mb_cpu_write_msr(env, msr);
qemu_log_mask(CPU_LOG_INT,
"exception at pc=%x ear=%" PRIx64 " iflags=%x\n",
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; env->pc = cpu->cfg.base_vectors + 0x20;
break; break;
@ -198,62 +177,56 @@ void mb_cpu_do_interrupt(CPUState *cs)
assert(msr & MSR_IE); assert(msr & MSR_IE);
assert(!(env->iflags & (D_FLAG | IMM_FLAG))); assert(!(env->iflags & (D_FLAG | IMM_FLAG)));
t = (msr & (MSR_VM | MSR_UM)) << 1;
#if 0
#include "disas/disas.h"
/* Useful instrumentation when debugging interrupt issues in either
the models or in sw. */
{
const char *sym;
sym = lookup_symbol(env->pc);
if (sym
&& (!strcmp("netif_rx", sym)
|| !strcmp("process_backlog", sym))) {
qemu_log("interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n",
env->pc, msr, t, env->iflags, sym);
log_cpu_state(cs, 0);
}
}
#endif
qemu_log_mask(CPU_LOG_INT, qemu_log_mask(CPU_LOG_INT,
"interrupt at pc=%x msr=%x %x iflags=%x\n", "INT: DEV at pc=%08x msr=%08x iflags=%x\n",
env->pc, msr, t, env->iflags); env->pc, msr, env->iflags);
set_esr = false;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM | MSR_IE);
msr |= t;
mb_cpu_write_msr(env, msr);
/* Disable interrupts. */
msr &= ~MSR_IE;
env->regs[14] = env->pc; env->regs[14] = env->pc;
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x10; env->pc = cpu->cfg.base_vectors + 0x10;
//log_cpu_state_mask(CPU_LOG_INT, cs, 0);
break; break;
case EXCP_HW_BREAK: case EXCP_HW_BREAK:
assert(!(env->iflags & (D_FLAG | IMM_FLAG))); assert(!(env->iflags & (D_FLAG | IMM_FLAG)));
t = (msr & (MSR_VM | MSR_UM)) << 1;
qemu_log_mask(CPU_LOG_INT, qemu_log_mask(CPU_LOG_INT,
"break at pc=%x msr=%x %x iflags=%x\n", "INT: BRK at pc=%08x msr=%08x iflags=%x\n",
env->pc, msr, t, env->iflags); env->pc, msr, env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0); set_esr = false;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
msr |= t; /* Break in progress. */
msr |= MSR_BIP; msr |= MSR_BIP;
env->regs[16] = env->pc; env->regs[16] = env->pc;
env->iflags = 0;
env->pc = cpu->cfg.base_vectors + 0x18; env->pc = cpu->cfg.base_vectors + 0x18;
mb_cpu_write_msr(env, msr);
break; break;
default: default:
cpu_abort(cs, "unhandled exception type=%d\n", cpu_abort(cs, "unhandled exception type=%d\n", cs->exception_index);
cs->exception_index); /* not reached */
break; }
/* Save previous mode, disable mmu, disable user-mode. */
t = (msr & (MSR_VM | MSR_UM)) << 1;
msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
msr |= t;
mb_cpu_write_msr(env, msr);
env->res_addr = RES_ADDR_NONE;
env->iflags = 0;
if (!set_esr) {
qemu_log_mask(CPU_LOG_INT,
" to pc=%08x msr=%08x\n", env->pc, msr);
} else if (env->esr & D_FLAG) {
qemu_log_mask(CPU_LOG_INT,
" to pc=%08x msr=%08x esr=%04x btr=%08x\n",
env->pc, msr, env->esr, env->btr);
} else {
qemu_log_mask(CPU_LOG_INT,
" to pc=%08x msr=%08x esr=%04x\n",
env->pc, msr, env->esr);
} }
} }