From 5bb0a20b74ad17dee5dae38e3b8b70b383ee7c2d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Sun, 1 Dec 2019 12:20:17 +0000 Subject: target/arm: Handle AArch32 CP15 trapping via HSTR_EL2 HSTR_EL2 offers a way to trap ranges of CP15 system register accesses to EL2, and it looks like this register is completely ignored by QEMU. To avoid adding extra .accessfn filters all over the place (which would have a direct performance impact), let's add a new TB flag that gets set whenever HSTR_EL2 is non-zero and that QEMU translates a context where this trap has a chance to apply, and only generate the extra access check if the hypervisor is actively using this feature. Tested with a hand-crafted KVM guest accessing CBAR. Signed-off-by: Marc Zyngier Reviewed-by: Richard Henderson Message-id: 20191201122018.25808-5-maz@kernel.org [PMM: use is_a64(); fix comment syntax] Signed-off-by: Peter Maydell --- target/arm/op_helper.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'target/arm/op_helper.c') diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index b529d6c1bf..e5a346cb87 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -603,6 +603,27 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env)); } + /* + * Check for an EL2 trap due to HSTR_EL2. We expect EL0 accesses + * to sysregs non accessible at EL0 to have UNDEF-ed already. + */ + if (!is_a64(env) && arm_current_el(env) < 2 && ri->cp == 15 && + (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) { + uint32_t mask = 1 << ri->crn; + + if (ri->type & ARM_CP_64BIT) { + mask = 1 << ri->crm; + } + + /* T4 and T14 are RES0 */ + mask &= ~((1 << 4) | (1 << 14)); + + if (env->cp15.hstr_el2 & mask) { + target_el = 2; + goto exept; + } + } + if (!ri->accessfn) { return; } @@ -652,6 +673,7 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, g_assert_not_reached(); } +exept: raise_exception(env, EXCP_UDEF, syndrome, target_el); } -- cgit v1.2.3