diff mbox series

[10/35] target/arm: *_EL12 registers should UNDEF when HCR_EL2.E2H is 0

Message ID 20231218113305.2511480-11-peter.maydell@linaro.org
State Superseded
Headers show
Series target/arm: Implement emulation of nested virtualization | expand

Commit Message

Peter Maydell Dec. 18, 2023, 11:32 a.m. UTC
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>
---
 target/arm/cpregs.h |  3 ++-
 target/arm/helper.c | 16 ++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

Comments

Richard Henderson Dec. 27, 2023, 10:25 p.m. UTC | #1
On 12/18/23 22:32, Peter Maydell wrote:
> 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>
> ---
>   target/arm/cpregs.h |  3 ++-
>   target/arm/helper.c | 16 ++++++++++++++++
>   2 files changed, 18 insertions(+), 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~
diff mbox series

Patch

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);