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.mayd...@linaro.org> --- target/arm/cpregs.h | 3 ++- target/arm/helper.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h index f1293d16c07..e748d184cb6 100644 --- a/target/arm/cpregs.h +++ b/target/arm/cpregs.h @@ -937,7 +937,7 @@ struct ARMCPRegInfo { CPResetFn *resetfn; /* - * "Original" writefn and readfn. + * "Original" readfn, writefn, accessfn. * For ARMv8.1-VHE register aliases, we overwrite the read/write * accessor functions of various EL1/EL0 to perform the runtime * check for which sysreg should actually be modified, and then @@ -948,6 +948,7 @@ struct ARMCPRegInfo { */ CPReadFn *orig_readfn; CPWriteFn *orig_writefn; + CPAccessFn *orig_accessfn; }; /* diff --git a/target/arm/helper.c b/target/arm/helper.c index c6f069b74cd..e90eb5e16f3 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6519,6 +6519,20 @@ static void el2_e2h_e12_write(CPUARMState *env, const ARMCPRegInfo *ri, 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) { struct E2HAlias { @@ -6632,6 +6646,7 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu) new_reg->opaque = src_reg; new_reg->orig_readfn = src_reg->readfn ?: raw_read; new_reg->orig_writefn = src_reg->writefn ?: raw_write; + new_reg->orig_accessfn = src_reg->accessfn; if (!new_reg->raw_readfn) { new_reg->raw_readfn = raw_read; } @@ -6640,6 +6655,7 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu) } new_reg->readfn = el2_e2h_e12_read; new_reg->writefn = el2_e2h_e12_write; + new_reg->accessfn = el2_e2h_e12_access; ok = g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)a->new_key, new_reg); -- 2.34.1