diff mbox series

[07/35] target/arm: Always honour HCR_EL2.TSC when HCR_EL2.NV is set

Message ID 20231218113305.2511480-8-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 HCR_EL2.TSC trap for trapping EL1 execution of SMC instructions
has a behaviour change for FEAT_NV when EL3 is not implemented:

 * in older architecture versions TSC was required to have no
   effect (i.e. the SMC insn UNDEFs)
 * with FEAT_NV, when HCR_EL2.NV == 1 the trap must apply
   (i.e. SMC traps to EL2, as it already does in all cases when
   EL3 is implemented)
 * in newer architecture versions, the behaviour either without
   FEAT_NV or with FEAT_NV and HCR_EL2.NV == 0 is relaxed to
   an IMPDEF choice between UNDEF and trap-to-EL2 (i.e. it is
   permitted to always honour HCR_EL2.TSC) for AArch64 only

Add the condition to honour the trap bit when HCR_EL2.NV == 1.  We
leave the HCR_EL2.NV == 0 case with the existing (UNDEF) behaviour,
as our IMPDEF choice (both because it avoids a behaviour change
for older CPU models and because we'd have to distinguish AArch32
from AArch64 if we opted to trap to EL2).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/tcg/op_helper.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

Comments

Richard Henderson Dec. 27, 2023, 10:18 p.m. UTC | #1
On 12/18/23 22:32, Peter Maydell wrote:
> The HCR_EL2.TSC trap for trapping EL1 execution of SMC instructions
> has a behaviour change for FEAT_NV when EL3 is not implemented:
> 
>   * in older architecture versions TSC was required to have no
>     effect (i.e. the SMC insn UNDEFs)
>   * with FEAT_NV, when HCR_EL2.NV == 1 the trap must apply
>     (i.e. SMC traps to EL2, as it already does in all cases when
>     EL3 is implemented)
>   * in newer architecture versions, the behaviour either without
>     FEAT_NV or with FEAT_NV and HCR_EL2.NV == 0 is relaxed to
>     an IMPDEF choice between UNDEF and trap-to-EL2 (i.e. it is
>     permitted to always honour HCR_EL2.TSC) for AArch64 only
> 
> Add the condition to honour the trap bit when HCR_EL2.NV == 1.  We
> leave the HCR_EL2.NV == 0 case with the existing (UNDEF) behaviour,
> as our IMPDEF choice (both because it avoids a behaviour change
> for older CPU models and because we'd have to distinguish AArch32
> from AArch64 if we opted to trap to EL2).
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   target/arm/tcg/op_helper.c | 16 +++++++++++++---
>   1 file changed, 13 insertions(+), 3 deletions(-)

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

r~
diff mbox series

Patch

diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index ea08936a852..ae158200c00 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -930,7 +930,14 @@  void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
      *
      *  Conduit SMC, valid call  Trap to EL2         PSCI Call
      *  Conduit SMC, inval call  Trap to EL2         Undef insn
-     *  Conduit not SMC          Undef insn          Undef insn
+     *  Conduit not SMC          Undef or trap[1]    Undef insn
+     *
+     * [1] In this case:
+     *  - if HCR_EL2.NV == 1 we must trap to EL2
+     *  - if HCR_EL2.NV == 0 then newer architecture revisions permit
+     *    AArch64 (but not AArch32) to trap to EL2 as an IMPDEF choice
+     *  - otherwise we must UNDEF
+     * We take the IMPDEF choice to always UNDEF if HCR_EL2.NV == 0.
      */
 
     /* On ARMv8 with EL3 AArch64, SMD applies to both S and NS state.
@@ -944,9 +951,12 @@  void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
                                                      : smd_flag && !secure;
 
     if (!arm_feature(env, ARM_FEATURE_EL3) &&
+        !(arm_hcr_el2_eff(env) & HCR_NV) &&
         cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
-        /* If we have no EL3 then SMC always UNDEFs and can't be
-         * trapped to EL2. PSCI-via-SMC is a sort of ersatz EL3
+        /*
+         * If we have no EL3 then traditionally SMC always UNDEFs and can't be
+         * trapped to EL2. For nested virtualization, SMC can be trapped to
+         * the outer hypervisor. PSCI-via-SMC is a sort of ersatz EL3
          * firmware within QEMU, and we want an EL2 guest to be able
          * to forbid its EL1 from making PSCI calls into QEMU's
          * "firmware" via HCR.TSC, so for these purposes treat