target/arm: *_EL12 registers should UNDEF when HCR_EL2.E2H is 0

The alias registers like SCTLR_EL12 only exist when HCR_EL2.E2H
is 1; they should UNDEF otherwise. We weren't implementing this.
Add an intercept of the accessfn for these aliases, and implement
the UNDEF check.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Miguel Luis <miguel.luis@oracle.com>
This commit is contained in:
Peter Maydell 2024-01-09 14:43:47 +00:00
parent 6f53b1267b
commit e730287cef
2 changed files with 18 additions and 1 deletions

View File

@ -937,7 +937,7 @@ struct ARMCPRegInfo {
CPResetFn *resetfn; CPResetFn *resetfn;
/* /*
* "Original" writefn and readfn. * "Original" readfn, writefn, accessfn.
* For ARMv8.1-VHE register aliases, we overwrite the read/write * For ARMv8.1-VHE register aliases, we overwrite the read/write
* accessor functions of various EL1/EL0 to perform the runtime * accessor functions of various EL1/EL0 to perform the runtime
* check for which sysreg should actually be modified, and then * check for which sysreg should actually be modified, and then
@ -948,6 +948,7 @@ struct ARMCPRegInfo {
*/ */
CPReadFn *orig_readfn; CPReadFn *orig_readfn;
CPWriteFn *orig_writefn; CPWriteFn *orig_writefn;
CPAccessFn *orig_accessfn;
}; };
/* /*

View File

@ -6535,6 +6535,20 @@ static void el2_e2h_e12_write(CPUARMState *env, const ARMCPRegInfo *ri,
return ri->orig_writefn(env, ri->opaque, value); return ri->orig_writefn(env, ri->opaque, value);
} }
static CPAccessResult el2_e2h_e12_access(CPUARMState *env,
const ARMCPRegInfo *ri,
bool isread)
{
/* FOO_EL12 aliases only exist when E2H is 1; otherwise they UNDEF */
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
return CP_ACCESS_TRAP_UNCATEGORIZED;
}
if (ri->orig_accessfn) {
return ri->orig_accessfn(env, ri->opaque, isread);
}
return CP_ACCESS_OK;
}
static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu) static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
{ {
struct E2HAlias { struct E2HAlias {
@ -6648,6 +6662,7 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
new_reg->opaque = src_reg; new_reg->opaque = src_reg;
new_reg->orig_readfn = src_reg->readfn ?: raw_read; new_reg->orig_readfn = src_reg->readfn ?: raw_read;
new_reg->orig_writefn = src_reg->writefn ?: raw_write; new_reg->orig_writefn = src_reg->writefn ?: raw_write;
new_reg->orig_accessfn = src_reg->accessfn;
if (!new_reg->raw_readfn) { if (!new_reg->raw_readfn) {
new_reg->raw_readfn = raw_read; new_reg->raw_readfn = raw_read;
} }
@ -6656,6 +6671,7 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
} }
new_reg->readfn = el2_e2h_e12_read; new_reg->readfn = el2_e2h_e12_read;
new_reg->writefn = el2_e2h_e12_write; new_reg->writefn = el2_e2h_e12_write;
new_reg->accessfn = el2_e2h_e12_access;
ok = g_hash_table_insert(cpu->cp_regs, ok = g_hash_table_insert(cpu->cp_regs,
(gpointer)(uintptr_t)a->new_key, new_reg); (gpointer)(uintptr_t)a->new_key, new_reg);