qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 5/8] target/arm: Take an exception if PC is misaligned


From: Richard Henderson
Subject: Re: [PATCH v2 5/8] target/arm: Take an exception if PC is misaligned
Date: Sun, 19 Sep 2021 18:29:31 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0

On 8/26/21 6:45 AM, Peter Maydell wrote:
On Sat, 21 Aug 2021 at 21:00, Richard Henderson
<richard.henderson@linaro.org> wrote:

For A64, any input to an indirect branch can cause this.

For A32, many indirect branch paths force the branch to be aligned,
but BXWritePC does not.  This includes the BX instruction but also
other interworking changes to PC.  Prior to v8, this case is UNDEFINED.
With v8, this is CONSTRAINED UNPREDICTABLE and may either raise an
exception or force align the PC.

We choose to raise an exception because we have the infrastructure,
it makes the generated code for gen_bx simpler, and it has the
possibility of catching more guest bugs.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
  target/arm/helper.h        |  1 +
  target/arm/syndrome.h      |  5 +++++
  target/arm/tlb_helper.c    | 24 +++++++++++++++++++++++
  target/arm/translate-a64.c | 21 ++++++++++++++++++--
  target/arm/translate.c     | 39 +++++++++++++++++++++++++++++++-------
  5 files changed, 81 insertions(+), 9 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 248569b0cd..d629ee6859 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
  DEF_HELPER_2(exception_internal, void, env, i32)
  DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
  DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
+DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
  DEF_HELPER_1(setend, void, env)
  DEF_HELPER_2(wfi, void, env, i32)
  DEF_HELPER_1(wfe, void, env)
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index 54d135897b..e9d97fac6e 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -275,4 +275,9 @@ static inline uint32_t syn_illegalstate(void)
      return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
  }

+static inline uint32_t syn_pcalignment(void)
+{
+    return (EC_PCALIGNMENT << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
  #endif /* TARGET_ARM_SYNDROME_H */
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index 3107f9823e..25c422976e 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -9,6 +9,7 @@
  #include "cpu.h"
  #include "internals.h"
  #include "exec/exec-all.h"
+#include "exec/helper-proto.h"

  static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
                                              unsigned int target_el,
@@ -123,6 +124,29 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
      arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
  }

+void helper_exception_pc_alignment(CPUARMState *env, target_ulong pc)
+{
+    int target_el = exception_target_el(env);
+
+    if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
+        /*
+         * To aarch64 and aarch32 el2, pc alignment has a
+         * special exception class.
+         */
+        env->exception.vaddress = pc;
+        env->exception.fsr = 0;
+        raise_exception(env, EXCP_PREFETCH_ABORT, syn_pcalignment(), 
target_el);
+    } else {
+        /*
+         * To aarch32 el1, pc alignment is like data alignment
+         * except with a prefetch abort.
+         */
+        ARMMMUFaultInfo fi = { .type = ARMFault_Alignment };
+        arm_deliver_fault(env_archcpu(env), pc, MMU_INST_FETCH,
+                          cpu_mmu_index(env, true), &fi);

I don't think you should need to special case AArch64 vs AArch32 like this;
you can do
    env->exception.vaddress = pc;
    env->exception.fsr = the_fsr;
    raise_exception(env, EXCP_PREFETCH_ABORT, syn_pcalignment(), target_el);

for both. AArch64/AArch32-Hyp exception entry will ignore exception.fsr,
and AArch32-not-Hyp entry will ignore exception.syndrome.

Not true.  The latter case still requires syndrome with EC_INSNABORT, etc.

I played with this a bit, but IMO the cleanest solution is the original patch.

We could probably do with factoring out the
"if (something) { fsr = arm_fi_to_lfsc(&fi) }  else { fsr =
arm_fi_to_sfsc(&fi); }"
logic which we currently duplicate in arm_deliver_fault() and
do_ats_write() and arm_debug_exception_fsr() and also want here.
(NB I haven't checked these really are doing exactly the same
condition check...)

It is exactly the same two out of three; the debug_exception one is worded slightly different. I think it would come out the same if one refactored arm_s1_regime_using_lpae_format to not use the mmu_idx but instead regime_el(mmu_idx).


r~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]