[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: |
Peter Maydell |
Subject: |
Re: [PATCH v2 5/8] target/arm: Take an exception if PC is misaligned |
Date: |
Thu, 26 Aug 2021 14:45:10 +0100 |
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.
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...)
-- PMM
- [PATCH v2 0/8] target/arm: Fix insn exception priorities, Richard Henderson, 2021/08/21
- [PATCH v2 1/8] target/arm: Take an exception if PSTATE.IL is set, Richard Henderson, 2021/08/21
- [PATCH v2 2/8] target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn, Richard Henderson, 2021/08/21
- [PATCH v2 3/8] linux-user/aarch64: Handle EC_PCALIGNMENT, Richard Henderson, 2021/08/21
- [PATCH v2 5/8] target/arm: Take an exception if PC is misaligned, Richard Henderson, 2021/08/21
- Re: [PATCH v2 5/8] target/arm: Take an exception if PC is misaligned,
Peter Maydell <=
- [PATCH v2 6/8] target/arm: Assert thumb pc is aligned, Richard Henderson, 2021/08/21
- [PATCH v2 4/8] linux-user/arm: Report SIGBUS and SIGSEGV correctly, Richard Henderson, 2021/08/21
- [PATCH v2 8/8] tests/tcg: Add arm and aarch64 pc alignment tests, Richard Henderson, 2021/08/21
- [PATCH v2 7/8] target/arm: Suppress bp for exceptions with more priority, Richard Henderson, 2021/08/21