target/hppa: Create raise_exception_with_ior

Handle pa2.0 logic for filling in ISR+IOR.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-10-27 03:35:57 -07:00
parent f5b5c85760
commit 8a02b9a68e

View File

@ -289,6 +289,53 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return excp == EXCP_DTLB_MISS ? -1 : phys;
}
G_NORETURN static void
raise_exception_with_ior(CPUHPPAState *env, int excp, uintptr_t retaddr,
vaddr addr, bool mmu_disabled)
{
CPUState *cs = env_cpu(env);
cs->exception_index = excp;
if (env->psw & PSW_Q) {
/*
* For pa1.x, the offset and space never overlap, and so we
* simply extract the high and low part of the virtual address.
*
* For pa2.0, the formation of these are described in section
* "Interruption Parameter Registers", page 2-15.
*/
env->cr[CR_IOR] = (uint32_t)addr;
env->cr[CR_ISR] = addr >> 32;
if (hppa_is_pa20(env)) {
if (mmu_disabled) {
/*
* If data translation was disabled, the ISR contains
* the upper portion of the abs address, zero-extended.
*/
env->cr[CR_ISR] &= 0x3fffffff;
} else {
/*
* If data translation was enabled, the upper two bits
* of the IOR (the b field) are equal to the two space
* bits from the base register used to form the gva.
*/
uint64_t b;
cpu_restore_state(cs, retaddr);
b = env->gr[env->unwind_breg];
b >>= (env->psw & PSW_W ? 62 : 30);
env->cr[CR_IOR] |= b << 62;
cpu_loop_exit(cs);
}
}
}
cpu_loop_exit_restore(cs, retaddr);
}
bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
MMUAccessType type, int mmu_idx,
bool probe, uintptr_t retaddr)
@ -318,14 +365,10 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
return false;
}
trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx);
/* Failure. Raise the indicated exception. */
cs->exception_index = excp;
if (cpu->env.psw & PSW_Q) {
/* ??? Needs tweaking for hppa64. */
cpu->env.cr[CR_IOR] = addr;
cpu->env.cr[CR_ISR] = addr >> 32;
}
cpu_loop_exit_restore(cs, retaddr);
raise_exception_with_ior(env, excp, retaddr,
addr, mmu_idx == MMU_PHYS_IDX);
}
trace_hppa_tlb_fill_success(env, addr & TARGET_PAGE_MASK,
@ -553,16 +596,11 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0,
&phys, &prot, NULL);
if (excp >= 0) {
if (env->psw & PSW_Q) {
/* ??? Needs tweaking for hppa64. */
env->cr[CR_IOR] = addr;
env->cr[CR_ISR] = addr >> 32;
}
if (excp == EXCP_DTLB_MISS) {
excp = EXCP_NA_DTLB_MISS;
}
trace_hppa_tlb_lpa_failed(env, addr);
hppa_dynamic_excp(env, excp, GETPC());
raise_exception_with_ior(env, excp, GETPC(), addr, false);
}
trace_hppa_tlb_lpa_success(env, addr, phys);
return phys;