From 7666a81d159e2ab76e8a1962e37615e8894552f5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: target/arm: Mark exception helpers as noreturn Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-2-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/helper.h b/target/arm/helper.h index b1334e0..5161cdf 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -44,9 +44,9 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) -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_internal, noreturn, env, i32) +DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32) +DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) -- cgit v1.1 From fa33eead8674c08fee3ac770c20fd64970fa0142 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: target/arm: Add coproc parameter to syn_fp_access_trap With ARMv8, this field is always RES0. With ARMv7, targeting EL2 and TA=0, it is always 0xA. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/syndrome.h | 7 ++++--- target/arm/translate-a64.c | 3 ++- target/arm/translate-vfp.c | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h index 0cb26dd..c105f9e 100644 --- a/target/arm/syndrome.h +++ b/target/arm/syndrome.h @@ -185,12 +185,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm, | (rt2 << 10) | (rt << 5) | (crm << 1) | isread; } -static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit) +static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit, + int coproc) { - /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */ + /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 */ return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT) | (is_16bit ? 0 : ARM_EL_IL) - | (cv << 24) | (cond << 20) | 0xa; + | (cv << 24) | (cond << 20) | coproc; } static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index d438fb8..e752589 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1162,7 +1162,8 @@ static bool fp_access_check(DisasContext *s) s->fp_access_checked = true; gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false), s->fp_excp_el); + syn_fp_access_trap(1, 0xe, false, 0), + s->fp_excp_el); return false; } s->fp_access_checked = true; diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c index 40a513b..0f797c5 100644 --- a/target/arm/translate-vfp.c +++ b/target/arm/translate-vfp.c @@ -219,8 +219,18 @@ static void gen_update_fp_context(DisasContext *s) static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled) { if (s->fp_excp_el) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false), s->fp_excp_el); + /* + * The full syndrome is only used for HSR when HCPTR traps: + * For v8, when TA==0, coproc is RES0. + * For v7, any use of a Floating-point instruction or access + * to a Floating-point Extension register that is trapped to + * Hyp mode because of a trap configured in the HCPTR sets + * this field to 0xA. + */ + int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa; + uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc); + + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el); return false; } -- cgit v1.1 From 57287a6e953f6e6f614c87296f8c44ea9c4907b6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: target/arm: Move exception_target_el out of line Move the function to op_helper.c, near raise_exception. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/internals.h | 16 +--------------- target/arm/op_helper.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index a1bae45..af9de2d 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1098,21 +1098,6 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx); -static inline int exception_target_el(CPUARMState *env) -{ - int target_el = MAX(1, arm_current_el(env)); - - /* - * No such thing as secure EL1 if EL3 is aarch32, - * so update the target EL to EL3 in this case. - */ - if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) { - target_el = 3; - } - - return target_el; -} - /* Determine if allocation tags are available. */ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el, uint64_t sctlr) @@ -1339,6 +1324,7 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu); bool el_is_in_host(CPUARMState *env, int el); void aa32_max_features(ARMCPU *cpu); +int exception_target_el(CPUARMState *env); /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index c4bd668..97c8c9e 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -28,6 +28,21 @@ #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) +int exception_target_el(CPUARMState *env) +{ + int target_el = MAX(1, arm_current_el(env)); + + /* + * No such thing as secure EL1 if EL3 is aarch32, + * so update the target EL to EL3 in this case. + */ + if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) { + target_el = 3; + } + + return target_el; +} + void raise_exception(CPUARMState *env, uint32_t excp, uint32_t syndrome, uint32_t target_el) { -- cgit v1.1 From 55ba15b73734e09fc8a14c88c34cad4c0e61abb2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: target/arm: Move arm_singlestep_active out of line Move the function to debug_helper.c, and the declaration to internals.h. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-5-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 10 ---------- target/arm/debug_helper.c | 12 ++++++++++++ target/arm/internals.h | 1 + 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 78dbcb5..bb1dc32 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3106,16 +3106,6 @@ static inline bool arm_generate_debug_exceptions(CPUARMState *env) } } -/* Is single-stepping active? (Note that the "is EL_D AArch64?" check - * implicitly means this always returns false in pre-v8 CPUs.) - */ -static inline bool arm_singlestep_active(CPUARMState *env) -{ - return extract32(env->cp15.mdscr_el1, 0, 1) - && arm_el_is_aa64(env, arm_debug_target_el(env)) - && arm_generate_debug_exceptions(env); -} - static inline bool arm_sctlr_b(CPUARMState *env) { return diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 4689369..1abf41c 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -11,6 +11,18 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" + +/* + * Is single-stepping active? (Note that the "is EL_D AArch64?" check + * implicitly means this always returns false in pre-v8 CPUs.) + */ +bool arm_singlestep_active(CPUARMState *env) +{ + return extract32(env->cp15.mdscr_el1, 0, 1) + && arm_el_is_aa64(env, arm_debug_target_el(env)) + && arm_generate_debug_exceptions(env); +} + /* Return true if the linked breakpoint entry lbn passes its checks */ static bool linked_bp_matches(ARMCPU *cpu, int lbn) { diff --git a/target/arm/internals.h b/target/arm/internals.h index af9de2d..64e2c1d 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1325,6 +1325,7 @@ bool el_is_in_host(CPUARMState *env, int el); void aa32_max_features(ARMCPU *cpu); int exception_target_el(CPUARMState *env); +bool arm_singlestep_active(CPUARMState *env); /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ -- cgit v1.1 From 31c8df53ee2c1bed06ea80644399d6998b887ad1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: target/arm: Move arm_generate_debug_exceptions out of line Move arm_generate_debug_exceptions and its two subroutines, {aa32,aa64}_generate_debug_exceptions into debug_helper.c, and the one interface declaration to internals.h. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-6-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 91 --------------------------------------------- target/arm/debug_helper.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++ target/arm/internals.h | 1 + 3 files changed, 95 insertions(+), 91 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index bb1dc32..50b5a9c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3015,97 +3015,6 @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu) return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0; } -/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ -static inline bool aa64_generate_debug_exceptions(CPUARMState *env) -{ - int cur_el = arm_current_el(env); - int debug_el; - - if (cur_el == 3) { - return false; - } - - /* MDCR_EL3.SDD disables debug events from Secure state */ - if (arm_is_secure_below_el3(env) - && extract32(env->cp15.mdcr_el3, 16, 1)) { - return false; - } - - /* - * Same EL to same EL debug exceptions need MDSCR_KDE enabled - * while not masking the (D)ebug bit in DAIF. - */ - debug_el = arm_debug_target_el(env); - - if (cur_el == debug_el) { - return extract32(env->cp15.mdscr_el1, 13, 1) - && !(env->daif & PSTATE_D); - } - - /* Otherwise the debug target needs to be a higher EL */ - return debug_el > cur_el; -} - -static inline bool aa32_generate_debug_exceptions(CPUARMState *env) -{ - int el = arm_current_el(env); - - if (el == 0 && arm_el_is_aa64(env, 1)) { - return aa64_generate_debug_exceptions(env); - } - - if (arm_is_secure(env)) { - int spd; - - if (el == 0 && (env->cp15.sder & 1)) { - /* SDER.SUIDEN means debug exceptions from Secure EL0 - * are always enabled. Otherwise they are controlled by - * SDCR.SPD like those from other Secure ELs. - */ - return true; - } - - spd = extract32(env->cp15.mdcr_el3, 14, 2); - switch (spd) { - case 1: - /* SPD == 0b01 is reserved, but behaves as 0b00. */ - case 0: - /* For 0b00 we return true if external secure invasive debug - * is enabled. On real hardware this is controlled by external - * signals to the core. QEMU always permits debug, and behaves - * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high. - */ - return true; - case 2: - return false; - case 3: - return true; - } - } - - return el != 2; -} - -/* Return true if debugging exceptions are currently enabled. - * This corresponds to what in ARM ARM pseudocode would be - * if UsingAArch32() then - * return AArch32.GenerateDebugExceptions() - * else - * return AArch64.GenerateDebugExceptions() - * We choose to push the if() down into this function for clarity, - * since the pseudocode has it at all callsites except for the one in - * CheckSoftwareStep(), where it is elided because both branches would - * always return the same value. - */ -static inline bool arm_generate_debug_exceptions(CPUARMState *env) -{ - if (env->aarch64) { - return aa64_generate_debug_exceptions(env); - } else { - return aa32_generate_debug_exceptions(env); - } -} - static inline bool arm_sctlr_b(CPUARMState *env) { return diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 1abf41c..20a0e42 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,6 +12,100 @@ #include "exec/helper-proto.h" +/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ +static bool aa64_generate_debug_exceptions(CPUARMState *env) +{ + int cur_el = arm_current_el(env); + int debug_el; + + if (cur_el == 3) { + return false; + } + + /* MDCR_EL3.SDD disables debug events from Secure state */ + if (arm_is_secure_below_el3(env) + && extract32(env->cp15.mdcr_el3, 16, 1)) { + return false; + } + + /* + * Same EL to same EL debug exceptions need MDSCR_KDE enabled + * while not masking the (D)ebug bit in DAIF. + */ + debug_el = arm_debug_target_el(env); + + if (cur_el == debug_el) { + return extract32(env->cp15.mdscr_el1, 13, 1) + && !(env->daif & PSTATE_D); + } + + /* Otherwise the debug target needs to be a higher EL */ + return debug_el > cur_el; +} + +static bool aa32_generate_debug_exceptions(CPUARMState *env) +{ + int el = arm_current_el(env); + + if (el == 0 && arm_el_is_aa64(env, 1)) { + return aa64_generate_debug_exceptions(env); + } + + if (arm_is_secure(env)) { + int spd; + + if (el == 0 && (env->cp15.sder & 1)) { + /* + * SDER.SUIDEN means debug exceptions from Secure EL0 + * are always enabled. Otherwise they are controlled by + * SDCR.SPD like those from other Secure ELs. + */ + return true; + } + + spd = extract32(env->cp15.mdcr_el3, 14, 2); + switch (spd) { + case 1: + /* SPD == 0b01 is reserved, but behaves as 0b00. */ + case 0: + /* + * For 0b00 we return true if external secure invasive debug + * is enabled. On real hardware this is controlled by external + * signals to the core. QEMU always permits debug, and behaves + * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high. + */ + return true; + case 2: + return false; + case 3: + return true; + } + } + + return el != 2; +} + +/* + * Return true if debugging exceptions are currently enabled. + * This corresponds to what in ARM ARM pseudocode would be + * if UsingAArch32() then + * return AArch32.GenerateDebugExceptions() + * else + * return AArch64.GenerateDebugExceptions() + * We choose to push the if() down into this function for clarity, + * since the pseudocode has it at all callsites except for the one in + * CheckSoftwareStep(), where it is elided because both branches would + * always return the same value. + */ +bool arm_generate_debug_exceptions(CPUARMState *env) +{ + if (env->aarch64) { + return aa64_generate_debug_exceptions(env); + } else { + return aa32_generate_debug_exceptions(env); + } +} + /* * Is single-stepping active? (Note that the "is EL_D AArch64?" check * implicitly means this always returns false in pre-v8 CPUs.) diff --git a/target/arm/internals.h b/target/arm/internals.h index 64e2c1d..02fa70f 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1326,6 +1326,7 @@ bool el_is_in_host(CPUARMState *env, int el); void aa32_max_features(ARMCPU *cpu); int exception_target_el(CPUARMState *env); bool arm_singlestep_active(CPUARMState *env); +bool arm_generate_debug_exceptions(CPUARMState *env); /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ -- cgit v1.1 From 831c1b1087c3aace40a8de36c3780ead81ebbb73 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: target/arm: Use is_a64 in arm_generate_debug_exceptions Use the accessor rather than the raw structure member. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-7-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 20a0e42..a18a09a 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -99,7 +99,7 @@ static bool aa32_generate_debug_exceptions(CPUARMState *env) */ bool arm_generate_debug_exceptions(CPUARMState *env) { - if (env->aarch64) { + if (is_a64(env)) { return aa64_generate_debug_exceptions(env); } else { return aa32_generate_debug_exceptions(env); -- cgit v1.1 From 16f9d5f6937d26f73a9694ba6bac0e113e3015e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: target/arm: Move exception_bkpt_insn to debug_helper.c Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 31 +++++++++++++++++++++++++++++++ target/arm/op_helper.c | 29 ----------------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index a18a09a..80dff07 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -430,6 +430,37 @@ void arm_debug_excp_handler(CPUState *cs) } } +/* + * Raise an EXCP_BKPT with the specified syndrome register value, + * targeting the correct exception level for debug exceptions. + */ +void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) +{ + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + + /* FSR will only be used if the debug target EL is AArch32. */ + env->exception.fsr = arm_debug_exception_fsr(env); + /* + * FAR is UNKNOWN: clear vaddress to avoid potentially exposing + * values to the guest that it shouldn't be able to see at its + * exception/security level. + */ + env->exception.vaddress = 0; + /* + * Other kinds of architectural debug exception are ignored if + * they target an exception level below the current one (in QEMU + * this is checked by arm_generate_debug_exceptions()). Breakpoint + * instructions are special because they always generate an exception + * to somewhere: if they can't go to the configured debug exception + * level they are taken to the current exception level. + */ + if (debug_el < cur_el) { + debug_el = cur_el; + } + raise_exception(env, EXCP_BKPT, syndrome, debug_el); +} + #if !defined(CONFIG_USER_ONLY) vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 97c8c9e..2a8bdc2 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -399,35 +399,6 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, raise_exception(env, excp, syndrome, target_el); } -/* Raise an EXCP_BKPT with the specified syndrome register value, - * targeting the correct exception level for debug exceptions. - */ -void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) -{ - int debug_el = arm_debug_target_el(env); - int cur_el = arm_current_el(env); - - /* FSR will only be used if the debug target EL is AArch32. */ - env->exception.fsr = arm_debug_exception_fsr(env); - /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing - * values to the guest that it shouldn't be able to see at its - * exception/security level. - */ - env->exception.vaddress = 0; - /* - * Other kinds of architectural debug exception are ignored if - * they target an exception level below the current one (in QEMU - * this is checked by arm_generate_debug_exceptions()). Breakpoint - * instructions are special because they always generate an exception - * to somewhere: if they can't go to the configured debug exception - * level they are taken to the current exception level. - */ - if (debug_el < cur_el) { - debug_el = cur_el; - } - raise_exception(env, EXCP_BKPT, syndrome, debug_el); -} - uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~CPSR_EXEC; -- cgit v1.1 From a853e3ae559ddd6020012ee0e6475dfab65d1eb1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: target/arm: Move arm_debug_exception_fsr to debug_helper.c This function now now only used in debug_helper.c, so there is no reason to have a declaration in a header. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 26 ++++++++++++++++++++++++++ target/arm/internals.h | 25 ------------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 80dff07..a743061 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -379,6 +379,32 @@ bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) return check_watchpoints(cpu); } +/* + * Return the FSR value for a debug exception (watchpoint, hardware + * breakpoint or BKPT insn) targeting the specified exception level. + */ +static uint32_t arm_debug_exception_fsr(CPUARMState *env) +{ + ARMMMUFaultInfo fi = { .type = ARMFault_Debug }; + int target_el = arm_debug_target_el(env); + bool using_lpae = false; + + if (target_el == 2 || arm_el_is_aa64(env, target_el)) { + using_lpae = true; + } else { + if (arm_feature(env, ARM_FEATURE_LPAE) && + (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) { + using_lpae = true; + } + } + + if (using_lpae) { + return arm_fi_to_lfsc(&fi); + } else { + return arm_fi_to_sfsc(&fi); + } +} + void arm_debug_excp_handler(CPUState *cs) { /* diff --git a/target/arm/internals.h b/target/arm/internals.h index 02fa70f..6f94f30 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -793,31 +793,6 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; } -/* Return the FSR value for a debug exception (watchpoint, hardware - * breakpoint or BKPT insn) targeting the specified exception level. - */ -static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) -{ - ARMMMUFaultInfo fi = { .type = ARMFault_Debug }; - int target_el = arm_debug_target_el(env); - bool using_lpae = false; - - if (target_el == 2 || arm_el_is_aa64(env, target_el)) { - using_lpae = true; - } else { - if (arm_feature(env, ARM_FEATURE_LPAE) && - (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) { - using_lpae = true; - } - } - - if (using_lpae) { - return arm_fi_to_lfsc(&fi); - } else { - return arm_fi_to_sfsc(&fi); - } -} - /** * arm_num_brps: Return number of implemented breakpoints. * Note that the ID register BRPS field is "number of bps - 1", -- cgit v1.1 From d3c5d50a5c498e3c32c59db210d501a980091ad6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: target/arm: Rename helper_exception_with_syndrome Rename to helper_exception_with_syndrome_el, to emphasize that the target el is a parameter. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-10-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.h | 2 +- target/arm/op_helper.c | 6 +++--- target/arm/translate.c | 6 +++--- target/arm/translate.h | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/target/arm/helper.h b/target/arm/helper.h index 5161cdf..5a6802e 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -45,7 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception_internal, noreturn, env, i32) -DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32) +DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 2a8bdc2..8a6a3b8 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -381,7 +381,7 @@ void HELPER(yield)(CPUARMState *env) * those EXCP values which are special cases for QEMU to interrupt * execution and not to be used for exceptions which are passed to * the guest (those must all have syndrome information and thus should - * use exception_with_syndrome). + * use exception_with_syndrome*). */ void HELPER(exception_internal)(CPUARMState *env, uint32_t excp) { @@ -393,8 +393,8 @@ void HELPER(exception_internal)(CPUARMState *env, uint32_t excp) } /* Raise an exception with the specified syndrome register value */ -void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, - uint32_t syndrome, uint32_t target_el) +void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp, + uint32_t syndrome, uint32_t target_el) { raise_exception(env, excp, syndrome, target_el); } diff --git a/target/arm/translate.c b/target/arm/translate.c index 87a899d..dc03360 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1119,9 +1119,9 @@ static void gen_exception_el(DisasContext *s, int excp, uint32_t syn, { gen_set_condexec(s); gen_set_pc_im(s, s->pc_curr); - gen_helper_exception_with_syndrome(cpu_env, - tcg_constant_i32(excp), - tcg_constant_i32(syn), tcg_el); + gen_helper_exception_with_syndrome_el(cpu_env, + tcg_constant_i32(excp), + tcg_constant_i32(syn), tcg_el); s->base.is_jmp = DISAS_NORETURN; } diff --git a/target/arm/translate.h b/target/arm/translate.h index f473a21..c578301 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -332,9 +332,9 @@ static inline void gen_ss_advance(DisasContext *s) static inline void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) { - gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syndrome), - tcg_constant_i32(target_el)); + gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome), + tcg_constant_i32(target_el)); } /* Generate an architectural singlestep exception */ -- cgit v1.1 From 9c9d03f0c556fb72be840773f0e8024a9a72d5e4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: target/arm: Introduce gen_exception_insn_el_v Create a function below gen_exception_insn that takes the target_el as a TCGv_i32, replacing gen_exception_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index dc03360..9cb3166 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,8 +1086,8 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } -void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, - uint32_t syn, uint32_t target_el) +static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, TCGv_i32 tcg_el) { if (s->aarch64) { gen_a64_set_pc_im(pc); @@ -1095,10 +1095,17 @@ void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, gen_set_condexec(s); gen_set_pc_im(s, pc); } - gen_exception(excp, syn, target_el); + gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syn), tcg_el); s->base.is_jmp = DISAS_NORETURN; } +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, uint32_t target_el) +{ + gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el)); +} + static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) { gen_set_condexec(s); @@ -1114,17 +1121,6 @@ void unallocated_encoding(DisasContext *s) default_exception_el(s)); } -static void gen_exception_el(DisasContext *s, int excp, uint32_t syn, - TCGv_i32 tcg_el) -{ - gen_set_condexec(s); - gen_set_pc_im(s, s->pc_curr); - gen_helper_exception_with_syndrome_el(cpu_env, - tcg_constant_i32(excp), - tcg_constant_i32(syn), tcg_el); - s->base.is_jmp = DISAS_NORETURN; -} - /* Force a TB lookup after an instruction that changes the CPU state. */ void gen_lookup_tb(DisasContext *s) { @@ -2847,7 +2843,8 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, tcg_el = tcg_constant_i32(3); } - gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el); + gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF, + syn_uncategorized(), tcg_el); tcg_temp_free_i32(tcg_el); return false; } -- cgit v1.1 From 8c5d24dc7dace7aeb9d3d1f9eebd679c3b22e3ff Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: target/arm: Rename gen_exception_insn to gen_exception_insn_el Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 36 ++++++++++++++++++------------------ target/arm/translate-m-nocp.c | 16 ++++++++-------- target/arm/translate-mve.c | 4 ++-- target/arm/translate-vfp.c | 6 +++--- target/arm/translate.c | 39 ++++++++++++++++++++------------------- target/arm/translate.h | 4 ++-- 6 files changed, 53 insertions(+), 52 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index e752589..14bc80d 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1161,9 +1161,9 @@ static bool fp_access_check(DisasContext *s) assert(!s->fp_access_checked); s->fp_access_checked = true; - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false, 0), - s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, false, 0), + s->fp_excp_el); return false; } s->fp_access_checked = true; @@ -1179,8 +1179,8 @@ bool sve_access_check(DisasContext *s) assert(!s->sve_access_checked); s->sve_access_checked = true; - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_sve_access_trap(), s->sve_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_sve_access_trap(), s->sve_excp_el); return false; } s->sve_access_checked = true; @@ -1816,8 +1816,8 @@ static void gen_sysreg_undef(DisasContext *s, bool isread, } else { syndrome = syn_uncategorized(); } - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome, - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome, + default_exception_el(s)); } /* MRS - move from system register @@ -2069,8 +2069,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) switch (op2_ll) { case 1: /* SVC */ gen_ss_advance(s); - gen_exception_insn(s, s->base.pc_next, EXCP_SWI, - syn_aa64_svc(imm16), default_exception_el(s)); + gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI, + syn_aa64_svc(imm16), default_exception_el(s)); break; case 2: /* HVC */ if (s->current_el == 0) { @@ -2083,8 +2083,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) gen_a64_set_pc_im(s->pc_curr); gen_helper_pre_hvc(cpu_env); gen_ss_advance(s); - gen_exception_insn(s, s->base.pc_next, EXCP_HVC, - syn_aa64_hvc(imm16), 2); + gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC, + syn_aa64_hvc(imm16), 2); break; case 3: /* SMC */ if (s->current_el == 0) { @@ -2094,8 +2094,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) gen_a64_set_pc_im(s->pc_curr); gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16))); gen_ss_advance(s); - gen_exception_insn(s, s->base.pc_next, EXCP_SMC, - syn_aa64_smc(imm16), 3); + gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC, + syn_aa64_smc(imm16), 3); break; default: unallocated_encoding(s); @@ -14725,8 +14725,8 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_illegalstate(), default_exception_el(s)); return; } @@ -14757,9 +14757,9 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) if (s->btype != 0 && s->guarded_page && !btype_destination_ok(insn, s->bt, s->btype)) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_btitrap(s->btype), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_btitrap(s->btype), + default_exception_el(s)); return; } } else { diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c index 27363a7..636bfb1 100644 --- a/target/arm/translate-m-nocp.c +++ b/target/arm/translate-m-nocp.c @@ -143,8 +143,8 @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel); if (s->fp_excp_el != 0) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return true; } @@ -376,7 +376,7 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, if (!vfp_access_check_m(s, true)) { /* * This was only a conditional exception, so override - * gen_exception_insn()'s default to DISAS_NORETURN + * gen_exception_insn_el()'s default to DISAS_NORETURN */ s->base.is_jmp = DISAS_NEXT; break; @@ -532,7 +532,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, if (!vfp_access_check_m(s, true)) { /* * This was only a conditional exception, so override - * gen_exception_insn()'s default to DISAS_NORETURN + * gen_exception_insn_el()'s default to DISAS_NORETURN */ s->base.is_jmp = DISAS_NEXT; break; @@ -765,14 +765,14 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a) } if (a->cp != 10) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), default_exception_el(s)); return true; } if (s->fp_excp_el != 0) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return true; } diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index 4267d43..5aec2a1 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -100,8 +100,8 @@ bool mve_eci_check(DisasContext *s) return true; default: /* Reserved value: INVSTATE UsageFault */ - gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); return false; } } diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c index 0f797c5..82fdbca 100644 --- a/target/arm/translate-vfp.c +++ b/target/arm/translate-vfp.c @@ -230,7 +230,7 @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled) int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa; uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc); - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el); return false; } @@ -260,8 +260,8 @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update) * the encoding space handled by the patterns in m-nocp.decode, * and for them we may need to raise NOCP here. */ - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return false; } diff --git a/target/arm/translate.c b/target/arm/translate.c index 9cb3166..44f462a 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1100,8 +1100,8 @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, s->base.is_jmp = DISAS_NORETURN; } -void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, - uint32_t syn, uint32_t target_el) +void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, uint32_t target_el) { gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el)); } @@ -1117,8 +1117,8 @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) void unallocated_encoding(DisasContext *s) { /* Unallocated and reserved encodings are uncategorized */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), + default_exception_el(s)); } /* Force a TB lookup after an instruction that changes the CPU state. */ @@ -2869,8 +2869,8 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, undef: /* If we get here then some access check did not pass */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_uncategorized(), exc_target); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_uncategorized(), exc_target); return false; } @@ -5094,7 +5094,8 @@ static void gen_srs(DisasContext *s, * For the UNPREDICTABLE cases we choose to UNDEF. */ if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_uncategorized(), 3); return; } @@ -8479,8 +8480,8 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a) * Do the check-and-raise-exception by hand. */ if (s->fp_excp_el) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return true; } } @@ -8582,8 +8583,8 @@ static bool trans_LE(DisasContext *s, arg_LE *a) tmp = load_cpu_field(v7m.ltpsize); tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc); tcg_temp_free_i32(tmp); - gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); gen_set_label(skipexc); } @@ -9053,8 +9054,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * UsageFault exception. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { - gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); return; } @@ -9063,8 +9064,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_illegalstate(), default_exception_el(s)); return; } @@ -9633,8 +9634,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(dc)); + gen_exception_insn_el(dc, dc->pc_curr, EXCP_UDEF, + syn_illegalstate(), default_exception_el(dc)); return; } @@ -9707,8 +9708,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) */ tcg_remove_ops_after(dc->insn_eci_rewind); dc->condjmp = 0; - gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(dc)); + gen_exception_insn_el(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(dc)); } arm_post_translate_insn(dc); diff --git a/target/arm/translate.h b/target/arm/translate.h index c578301..9ae7653 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -279,8 +279,8 @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label); void arm_gen_test_cc(int cc, TCGLabel *label); MemOp pow2_align(unsigned i); void unallocated_encoding(DisasContext *s); -void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, - uint32_t syn, uint32_t target_el); +void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, uint32_t target_el); /* Return state of Alternate Half-precision flag, caller frees result */ static inline TCGv_i32 get_ahp_flag(void) -- cgit v1.1 From 486d6c9699a5fc1f11c48dbe73b46e183020fa49 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: target/arm: Introduce gen_exception_insn Create a new wrapper function that passes the default exception target to gen_exception_insn_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 15 ++++++--------- target/arm/translate-m-nocp.c | 3 +-- target/arm/translate-mve.c | 3 +-- target/arm/translate.c | 29 +++++++++++++---------------- target/arm/translate.h | 1 + 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 14bc80d..0581118 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1816,8 +1816,7 @@ static void gen_sysreg_undef(DisasContext *s, bool isread, } else { syndrome = syn_uncategorized(); } - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome, - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome); } /* MRS - move from system register @@ -2069,8 +2068,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) switch (op2_ll) { case 1: /* SVC */ gen_ss_advance(s); - gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI, - syn_aa64_svc(imm16), default_exception_el(s)); + gen_exception_insn(s, s->base.pc_next, EXCP_SWI, + syn_aa64_svc(imm16)); break; case 2: /* HVC */ if (s->current_el == 0) { @@ -14725,8 +14724,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate()); return; } @@ -14757,9 +14755,8 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) if (s->btype != 0 && s->guarded_page && !btype_destination_ok(insn, s->bt, s->btype)) { - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_btitrap(s->btype), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, + syn_btitrap(s->btype)); return; } } else { diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c index 636bfb1..4029d7f 100644 --- a/target/arm/translate-m-nocp.c +++ b/target/arm/translate-m-nocp.c @@ -765,8 +765,7 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a) } if (a->cp != 10) { - gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized()); return true; } diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index 5aec2a1..0cf1b5e 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -100,8 +100,7 @@ bool mve_eci_check(DisasContext *s) return true; default: /* Reserved value: INVSTATE UsageFault */ - gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized()); return false; } } diff --git a/target/arm/translate.c b/target/arm/translate.c index 44f462a..c7d422b 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1106,6 +1106,11 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el)); } +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn) +{ + gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s)); +} + static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) { gen_set_condexec(s); @@ -1117,8 +1122,7 @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) void unallocated_encoding(DisasContext *s) { /* Unallocated and reserved encodings are uncategorized */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized()); } /* Force a TB lookup after an instruction that changes the CPU state. */ @@ -2731,8 +2735,6 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, * an exception and return false. Otherwise it will return true, * and set *tgtmode and *regno appropriately. */ - int exc_target = default_exception_el(s); - /* These instructions are present only in ARMv8, or in ARMv7 with the * Virtualization Extensions. */ @@ -2869,8 +2871,7 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, undef: /* If we get here then some access check did not pass */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_uncategorized(), exc_target); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized()); return false; } @@ -8583,8 +8584,7 @@ static bool trans_LE(DisasContext *s, arg_LE *a) tmp = load_cpu_field(v7m.ltpsize); tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc); tcg_temp_free_i32(tmp); - gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized()); gen_set_label(skipexc); } @@ -9054,8 +9054,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * UsageFault exception. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { - gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized()); return; } @@ -9064,8 +9063,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate()); return; } @@ -9634,8 +9632,7 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn_el(dc, dc->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(dc)); + gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, syn_illegalstate()); return; } @@ -9708,8 +9705,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) */ tcg_remove_ops_after(dc->insn_eci_rewind); dc->condjmp = 0; - gen_exception_insn_el(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(dc)); + gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, + syn_uncategorized()); } arm_post_translate_insn(dc); diff --git a/target/arm/translate.h b/target/arm/translate.h index 9ae7653..4575af6 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -281,6 +281,7 @@ MemOp pow2_align(unsigned i); void unallocated_encoding(DisasContext *s); void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, uint32_t syn, uint32_t target_el); +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn); /* Return state of Alternate Half-precision flag, caller frees result */ static inline TCGv_i32 get_ahp_flag(void) -- cgit v1.1 From f0d7c2054aee5d17ed0a84a11cc8c89b38902d3c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: target/arm: Create helper_exception_swstep Move the computation from gen_swstep_exception into a helper. This fixes a bug when: - MDSCR_EL1.KDE == 1 to enable debug exceptions within EL_D itself - we singlestep an ERET from EL_D to some lower EL Previously we were computing 'same el' based on the EL which executed the ERET instruction, whereas it ought to be computed based on the EL to which ERET returned. This happens naturally with the new helper, which runs after EL has been changed. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-14-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 16 ++++++++++++++++ target/arm/helper.h | 1 + target/arm/translate.h | 12 +++--------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index a743061..a3a1b98 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -487,6 +487,22 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) raise_exception(env, EXCP_BKPT, syndrome, debug_el); } +void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) +{ + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + + /* + * If singlestep is targeting a lower EL than the current one, then + * DisasContext.ss_active must be false and we can never get here. + */ + assert(debug_el >= cur_el); + if (debug_el == cur_el) { + syndrome |= 1 << ARM_EL_EC_SHIFT; + } + raise_exception(env, EXCP_UDEF, syndrome, debug_el); +} + #if !defined(CONFIG_USER_ONLY) vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) diff --git a/target/arm/helper.h b/target/arm/helper.h index 5a6802e..db7447d 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, noreturn, env, i32) DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) +DEF_HELPER_2(exception_swstep, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) diff --git a/target/arm/translate.h b/target/arm/translate.h index 4575af6..890e731 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -341,15 +341,9 @@ static inline void gen_exception(int excp, uint32_t syndrome, /* Generate an architectural singlestep exception */ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) { - bool same_el = (s->debug_target_el == s->current_el); - - /* - * If singlestep is targeting a lower EL than the current one, - * then s->ss_active must be false and we can never get here. - */ - assert(s->debug_target_el >= s->current_el); - - gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el); + /* Fill in the same_el field of the syndrome in the helper. */ + uint32_t syn = syn_swstep(false, isv, ex); + gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn)); } /* -- cgit v1.1 From 8480e933edf112d3ee775929106a2bdbaf002fbe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL We no longer need this value during translation, as it is now handled within the helpers. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-15-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 6 ++---- target/arm/helper.c | 12 ++---------- target/arm/translate-a64.c | 1 - target/arm/translate.c | 1 - target/arm/translate.h | 2 -- 5 files changed, 4 insertions(+), 18 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 50b5a9c..719613a 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3104,11 +3104,9 @@ FIELD(TBFLAG_ANY, BE_DATA, 3, 1) FIELD(TBFLAG_ANY, MMUIDX, 4, 4) /* Target EL if we take a floating-point-disabled exception */ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2) -/* For A-profile only, target EL for debug exceptions. */ -FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2) /* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */ -FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1) -FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1) +FIELD(TBFLAG_ANY, ALIGN_MEM, 10, 1) +FIELD(TBFLAG_ANY, PSTATE__IL, 11, 1) /* * Bit usage when in AArch32 state, both A- and M-profile. diff --git a/target/arm/helper.c b/target/arm/helper.c index ac9942d..2b2c199 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -11102,18 +11102,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } -static CPUARMTBFlags rebuild_hflags_aprofile(CPUARMState *env) -{ - CPUARMTBFlags flags = {}; - - DP_TBFLAG_ANY(flags, DEBUG_TARGET_EL, arm_debug_target_el(env)); - return flags; -} - static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, ARMMMUIdx mmu_idx) { - CPUARMTBFlags flags = rebuild_hflags_aprofile(env); + CPUARMTBFlags flags = {}; int el = arm_current_el(env); if (arm_sctlr(env, el) & SCTLR_A) { @@ -11139,7 +11131,7 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { - CPUARMTBFlags flags = rebuild_hflags_aprofile(env); + CPUARMTBFlags flags = {}; ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; uint64_t sctlr; diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 0581118..4f6181a 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -14645,7 +14645,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE); dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS); dc->is_ldex = false; - dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL); /* Bound the number of insns to execute to those left on the page. */ bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; diff --git a/target/arm/translate.c b/target/arm/translate.c index c7d422b..b8a8972 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9350,7 +9350,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT); dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED); } else { - dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL); dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B); dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE); dc->ns = EX_TBFLAG_A32(tb_flags, NS); diff --git a/target/arm/translate.h b/target/arm/translate.h index 890e731..8685f55 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -59,8 +59,6 @@ typedef struct DisasContext { */ uint32_t svc_imm; int current_el; - /* Debug target exception level for single-step exceptions */ - int debug_target_el; GHashTable *cp_regs; uint64_t features; /* CPU features bits */ bool aarch64; -- cgit v1.1 From cc5e672b85da3dd972cc04cd8020aeb5a60519a8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: target/arm: Move gen_exception to translate.c This function is not required by any other translation file. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 7 +++++++ target/arm/translate.h | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index b8a8972..fc5eafa 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,6 +1086,13 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } +static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) +{ + gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome), + tcg_constant_i32(target_el)); +} + static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, uint32_t syn, TCGv_i32 tcg_el) { diff --git a/target/arm/translate.h b/target/arm/translate.h index 8685f55..850bcdc 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -328,14 +328,6 @@ static inline void gen_ss_advance(DisasContext *s) } } -static inline void gen_exception(int excp, uint32_t syndrome, - uint32_t target_el) -{ - gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syndrome), - tcg_constant_i32(target_el)); -} - /* Generate an architectural singlestep exception */ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) { -- cgit v1.1 From bca6f24f0189c0e1a2ff091250d2d46c89a76401 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: target/arm: Rename gen_exception to gen_exception_el Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index fc5eafa..edb7d3f 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,7 +1086,7 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } -static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) +static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) { gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), tcg_constant_i32(syndrome), @@ -9758,16 +9758,16 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) switch (dc->base.is_jmp) { case DISAS_SWI: gen_ss_advance(dc); - gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), + default_exception_el(dc)); break; case DISAS_HVC: gen_ss_advance(dc); - gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); + gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); break; case DISAS_SMC: gen_ss_advance(dc); - gen_exception(EXCP_SMC, syn_aa32_smc(), 3); + gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3); break; case DISAS_NEXT: case DISAS_TOO_MANY: @@ -9828,14 +9828,14 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_helper_yield(cpu_env); break; case DISAS_SWI: - gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), + default_exception_el(dc)); break; case DISAS_HVC: - gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); + gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); break; case DISAS_SMC: - gen_exception(EXCP_SMC, syn_aa32_smc(), 3); + gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3); break; } } -- cgit v1.1 From 1a13b9a86334d85546afc4e8b568bee970d7a828 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: target/arm: Introduce gen_exception Create a new wrapper function that passes the default exception target to gen_exception_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index edb7d3f..5a48937 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1093,6 +1093,11 @@ static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) tcg_constant_i32(target_el)); } +static void gen_exception(DisasContext *s, int excp, uint32_t syndrome) +{ + gen_exception_el(excp, syndrome, default_exception_el(s)); +} + static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, uint32_t syn, TCGv_i32 tcg_el) { @@ -9758,8 +9763,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) switch (dc->base.is_jmp) { case DISAS_SWI: gen_ss_advance(dc); - gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_ss_advance(dc); @@ -9828,8 +9832,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_helper_yield(cpu_env); break; case DISAS_SWI: - gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); -- cgit v1.1 From d6d7f818a9eafeff01d19b70a796bf42248c3690 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: target/arm: Introduce gen_exception_el_v Split out a common helper function for gen_exception_el and gen_exception_insn_el_v. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-19-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index 5a48937..fcb6ee6 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,11 +1086,15 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } -static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) +static void gen_exception_el_v(int excp, uint32_t syndrome, TCGv_i32 tcg_el) { gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syndrome), - tcg_constant_i32(target_el)); + tcg_constant_i32(syndrome), tcg_el); +} + +static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) +{ + gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el)); } static void gen_exception(DisasContext *s, int excp, uint32_t syndrome) @@ -1107,8 +1111,7 @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, gen_set_condexec(s); gen_set_pc_im(s, pc); } - gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syn), tcg_el); + gen_exception_el_v(excp, syn, tcg_el); s->base.is_jmp = DISAS_NORETURN; } -- cgit v1.1 From eeaf596022233818476bf2d1c7a41011fbba7faa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: target/arm: Introduce helper_exception_with_syndrome With the helper we can use exception_target_el at runtime, instead of default_exception_el at translate time. While we're at it, remove the DisasContext parameter from gen_exception, as it is no longer used. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-20-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.h | 1 + target/arm/op_helper.c | 10 ++++++++++ target/arm/translate.c | 18 +++++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/target/arm/helper.h b/target/arm/helper.h index db7447d..07d45fa 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -45,6 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception_internal, noreturn, env, i32) +DEF_HELPER_3(exception_with_syndrome, noreturn, env, i32, i32) DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_swstep, noreturn, env, i32) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 8a6a3b8..c5bde1c 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -399,6 +399,16 @@ void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp, raise_exception(env, excp, syndrome, target_el); } +/* + * Raise an exception with the specified syndrome register value + * to the default target el. + */ +void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, + uint32_t syndrome) +{ + raise_exception(env, excp, syndrome, exception_target_el(env)); +} + uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~CPSR_EXEC; diff --git a/target/arm/translate.c b/target/arm/translate.c index fcb6ee6..81c27e7 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1097,9 +1097,10 @@ static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el)); } -static void gen_exception(DisasContext *s, int excp, uint32_t syndrome) +static void gen_exception(int excp, uint32_t syndrome) { - gen_exception_el(excp, syndrome, default_exception_el(s)); + gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome)); } static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, @@ -1123,7 +1124,14 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn) { - gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s)); + if (s->aarch64) { + gen_a64_set_pc_im(pc); + } else { + gen_set_condexec(s); + gen_set_pc_im(s, pc); + } + gen_exception(excp, syn); + s->base.is_jmp = DISAS_NORETURN; } static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) @@ -9766,7 +9774,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) switch (dc->base.is_jmp) { case DISAS_SWI: gen_ss_advance(dc); - gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); + gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_ss_advance(dc); @@ -9835,7 +9843,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_helper_yield(cpu_env); break; case DISAS_SWI: - gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); + gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); -- cgit v1.1 From 82303761c6fccfd7b166949149fedae9cee15efd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: target/arm: Remove default_exception_el This function is no longer used. At the same time, remove DisasContext.secure_routed_to_el3, as it in turn becomes unused. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 5 ----- target/arm/translate.c | 5 ----- target/arm/translate.h | 16 ---------------- 3 files changed, 26 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 4f6181a..4c64546 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -14585,11 +14585,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->condjmp = 0; dc->aarch64 = true; - /* If we are coming from secure EL0 in a system with a 32-bit EL3, then - * there is no secure EL1, so we route exceptions to EL3. - */ - dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3); dc->thumb = false; dc->sctlr_b = 0; dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE; diff --git a/target/arm/translate.c b/target/arm/translate.c index 81c27e7..6617de7 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9319,11 +9319,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->condjmp = 0; dc->aarch64 = false; - /* If we are coming from secure EL0 in a system with a 32-bit EL3, then - * there is no secure EL1, so we route exceptions to EL3. - */ - dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3); dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB); dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE; condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC); diff --git a/target/arm/translate.h b/target/arm/translate.h index 850bcdc..88dc18a 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -43,8 +43,6 @@ typedef struct DisasContext { int fp_excp_el; /* FP exception EL or 0 if enabled */ int sve_excp_el; /* SVE exception EL or 0 if enabled */ int vl; /* current vector length in bytes */ - /* Flag indicating that exceptions from secure mode are routed to EL3. */ - bool secure_routed_to_el3; bool vfp_enabled; /* FP enabled via FPSCR.EN */ int vec_len; int vec_stride; @@ -199,20 +197,6 @@ static inline int get_mem_index(DisasContext *s) return arm_to_core_mmu_idx(s->mmu_idx); } -/* Function used to determine the target exception EL when otherwise not known - * or default. - */ -static inline int default_exception_el(DisasContext *s) -{ - /* If we are coming from secure EL0 in a system with a 32-bit EL3, then - * there is no secure EL1, so we route exceptions to EL3. Otherwise, - * exceptions can only be routed to ELs above 1, so we target the higher of - * 1 or the current EL. - */ - return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3) - ? 3 : MAX(1, s->current_el); -} - static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) { /* We don't need to save all of the syndrome so we mask and shift -- cgit v1.1 From 04eacf6e79e7489579d188acbfe3046874d7ec3e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: target/arm: Create raise_exception_debug Handle the debug vs current el exception test in one place. Leave EXCP_BKPT alone, since that treats debug < current differently. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-22-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index a3a1b98..26004df 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,6 +12,26 @@ #include "exec/helper-proto.h" +/* + * Raise an exception to the debug target el. + * Modify syndrome to indicate when origin and target EL are the same. + */ +G_NORETURN static void +raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome) +{ + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + + /* + * If singlestep is targeting a lower EL than the current one, then + * DisasContext.ss_active must be false and we can never get here. + * Similarly for watchpoint and breakpoint matches. + */ + assert(debug_el >= cur_el); + syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT; + raise_exception(env, excp, syndrome, debug_el); +} + /* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ static bool aa64_generate_debug_exceptions(CPUARMState *env) { @@ -418,19 +438,16 @@ void arm_debug_excp_handler(CPUState *cs) if (wp_hit) { if (wp_hit->flags & BP_CPU) { bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0; - bool same_el = arm_debug_target_el(env) == arm_current_el(env); cs->watchpoint_hit = NULL; env->exception.fsr = arm_debug_exception_fsr(env); env->exception.vaddress = wp_hit->hitaddr; - raise_exception(env, EXCP_DATA_ABORT, - syn_watchpoint(same_el, 0, wnr), - arm_debug_target_el(env)); + raise_exception_debug(env, EXCP_DATA_ABORT, + syn_watchpoint(0, 0, wnr)); } } else { uint64_t pc = is_a64(env) ? env->pc : env->regs[15]; - bool same_el = (arm_debug_target_el(env) == arm_current_el(env)); /* * (1) GDB breakpoints should be handled first. @@ -450,9 +467,7 @@ void arm_debug_excp_handler(CPUState *cs) * exception/security level. */ env->exception.vaddress = 0; - raise_exception(env, EXCP_PREFETCH_ABORT, - syn_breakpoint(same_el), - arm_debug_target_el(env)); + raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0)); } } @@ -489,18 +504,7 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) { - int debug_el = arm_debug_target_el(env); - int cur_el = arm_current_el(env); - - /* - * If singlestep is targeting a lower EL than the current one, then - * DisasContext.ss_active must be false and we can never get here. - */ - assert(debug_el >= cur_el); - if (debug_el == cur_el) { - syndrome |= 1 << ARM_EL_EC_SHIFT; - } - raise_exception(env, EXCP_UDEF, syndrome, debug_el); + raise_exception_debug(env, EXCP_UDEF, syndrome); } #if !defined(CONFIG_USER_ONLY) -- cgit v1.1 From 38e8a13c116b114c100f488dc6a32c9c9df3ccd0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: target/arm: Move arm_debug_target_el to debug_helper.c This function is no longer used outside debug_helper.c. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-23-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 21 --------------------- target/arm/debug_helper.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 719613a..161ac9f 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -2986,27 +2986,6 @@ typedef enum ARMASIdx { ARMASIdx_TagS = 3, } ARMASIdx; -/* Return the Exception Level targeted by debug exceptions. */ -static inline int arm_debug_target_el(CPUARMState *env) -{ - bool secure = arm_is_secure(env); - bool route_to_el2 = false; - - if (arm_is_el2_enabled(env)) { - route_to_el2 = env->cp15.hcr_el2 & HCR_TGE || - env->cp15.mdcr_el2 & MDCR_TDE; - } - - if (route_to_el2) { - return 2; - } else if (arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3) && secure) { - return 3; - } else { - return 1; - } -} - static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu) { /* If all the CLIDR.Ctypem bits are 0 there are no caches, and diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 26004df..b18a6bd 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,6 +12,27 @@ #include "exec/helper-proto.h" +/* Return the Exception Level targeted by debug exceptions. */ +static int arm_debug_target_el(CPUARMState *env) +{ + bool secure = arm_is_secure(env); + bool route_to_el2 = false; + + if (arm_is_el2_enabled(env)) { + route_to_el2 = env->cp15.hcr_el2 & HCR_TGE || + env->cp15.mdcr_el2 & MDCR_TDE; + } + + if (route_to_el2) { + return 2; + } else if (arm_feature(env, ARM_FEATURE_EL3) && + !arm_el_is_aa64(env, 3) && secure) { + return 3; + } else { + return 1; + } +} + /* * Raise an exception to the debug target el. * Modify syndrome to indicate when origin and target EL are the same. -- cgit v1.1 From 02e1de14bcf7cc686bf4f542b36033521f22d1ee Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: target/arm: Fix Secure PL1 tests in fp_exception_el We were using arm_is_secure and is_a64, which are tests against the current EL, as opposed to arm_el_is_aa64 and arm_is_secure_below_el3, which can be applied to a different EL than current. Consolidate the two tests. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-24-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 2b2c199..b95aa53 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10879,27 +10879,22 @@ int fp_exception_el(CPUARMState *env, int cur_el) int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN); switch (fpen) { + case 1: + if (cur_el != 0) { + break; + } + /* fall through */ case 0: case 2: - if (cur_el == 0 || cur_el == 1) { - /* Trap to PL1, which might be EL1 or EL3 */ - if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) { - return 3; - } - return 1; - } - if (cur_el == 3 && !is_a64(env)) { - /* Secure PL1 running at EL3 */ + /* Trap from Secure PL0 or PL1 to Secure PL1. */ + if (!arm_el_is_aa64(env, 3) + && (cur_el == 3 || arm_is_secure_below_el3(env))) { return 3; } - break; - case 1: - if (cur_el == 0) { + if (cur_el <= 1) { return 1; } break; - case 3: - break; } } -- cgit v1.1 From 284ad5e70c41e02553aeb2c1eaf4e828499cb315 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: tests/qtest: Reduce npcm7xx_sdhci test image size Creating 1GB image for a simple qtest is unnecessary and could lead to failures. We reduce the image size to 1MB to reduce the test overhead. Signed-off-by: Hao Wu Message-id: 20220609214125.4192212-1-wuhaotsh@google.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- tests/qtest/npcm7xx_sdhci-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c index aa35a77..5d68540 100644 --- a/tests/qtest/npcm7xx_sdhci-test.c +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -24,7 +24,7 @@ #define NPCM7XX_REG_SIZE 0x100 #define NPCM7XX_MMC_BA 0xF0842000 #define NPCM7XX_BLK_SIZE 512 -#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 20) char *sd_path; -- cgit v1.1 From bfe43e3d14687f2149451f278671c2c552d96b0a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: target/arm: Adjust format test in scr_write Because reset always initializes the AA64 version, SCR_EL3, test the mode of EL3 instead of the type of the cpreg. Signed-off-by: Richard Henderson Message-id: 20220609214657.1217913-2-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/helper.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index b95aa53..ff9f9fe 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1738,12 +1738,14 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) uint32_t valid_mask = 0x3fff; ARMCPU *cpu = env_archcpu(env); - if (ri->state == ARM_CP_STATE_AA64) { - if (arm_feature(env, ARM_FEATURE_AARCH64) && - !cpu_isar_feature(aa64_aa32_el1, cpu)) { - value |= SCR_FW | SCR_AW; /* these two bits are RES1. */ - } - valid_mask &= ~SCR_NET; + /* + * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always + * passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64. + * Instead, choose the format based on the mode of EL3. + */ + if (arm_el_is_aa64(env, 3)) { + value |= SCR_FW | SCR_AW; /* RES1 */ + valid_mask &= ~SCR_NET; /* RES0 */ if (cpu_isar_feature(aa64_ras, cpu)) { valid_mask |= SCR_TERR; -- cgit v1.1 From 6bcbb07af6a601b2521b07a639861218fbf0c87e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: target/arm: SCR_EL3.RW is RAO/WI without AArch32 EL[12] Since DDI0487F.a, the RW bit is RAO/WI. When specifically targeting such a cpu, e.g. cortex-a76, it is legitimate to ignore the bit within the secure monitor. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1062 Signed-off-by: Richard Henderson Message-id: 20220609214657.1217913-3-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/cpu.h | 5 +++++ target/arm/helper.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 161ac9f..df677b2 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3854,6 +3854,11 @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; } +static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; +} + static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; diff --git a/target/arm/helper.c b/target/arm/helper.c index ff9f9fe..6457e63 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1747,6 +1747,10 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) value |= SCR_FW | SCR_AW; /* RES1 */ valid_mask &= ~SCR_NET; /* RES0 */ + if (!cpu_isar_feature(aa64_aa32_el1, cpu) && + !cpu_isar_feature(aa64_aa32_el2, cpu)) { + value |= SCR_RW; /* RAO/WI */ + } if (cpu_isar_feature(aa64_ras, cpu)) { valid_mask |= SCR_TERR; } -- cgit v1.1 From ebf1b4cbb8ec357f5280dc8895548519b65a2d71 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 10 Jun 2022 14:32:36 +0100 Subject: gdbstub: Don't use GDB syscalls if no GDB is attached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In two places in gdbstub.c we look at gdbserver_state.init to decide whether we're going to do a semihosting syscall via the gdb remote protocol: * when setting up, if the user didn't explicitly select either native semihosting or gdb semihosting, we autoselect, with the intended behaviour "use gdb if gdb is connected" * when the semihosting layer attempts to do a syscall via gdb, we silently ignore it if the gdbstub wasn't actually set up However, if the user's commandline sets up the gdbstub but tells QEMU to start rather than waiting for a GDB to connect (eg using '-s' but not '-S'), then we will have gdbserver_state.init true but no actual connection; an attempt to use gdb syscalls will then crash because we try to use gdbserver_state.c_cpu when it hasn't been set up: #0 0x00007ffff6803ba8 in qemu_cpu_kick (cpu=0x0) at ../../softmmu/cpus.c:457 #1 0x00007ffff6c03913 in gdb_do_syscallv (cb=0x7ffff6c19944 , fmt=0x7ffff7573b7e "", va=0x7ffff56294c0) at ../../gdbstub.c:2946 #2 0x00007ffff6c19c3a in common_semi_gdb_syscall (cs=0x7ffff83fe060, cb=0x7ffff6c19944 , fmt=0x7ffff7573b75 "isatty,%x") at ../../semihosting/arm-compat-semi.c:494 #3 0x00007ffff6c1a064 in gdb_isattyfn (cs=0x7ffff83fe060, gf=0x7ffff86a3690) at ../../semihosting/arm-compat-semi.c:636 #4 0x00007ffff6c1b20f in do_common_semihosting (cs=0x7ffff83fe060) at ../../semihosting/arm-compat-semi.c:967 #5 0x00007ffff693a037 in handle_semihosting (cs=0x7ffff83fe060) at ../../target/arm/helper.c:10316 You can probably also get into this state via some odd corner cases involving connecting a GDB and then telling it to detach from all the vCPUs. Abstract out the test into a new gdb_attached() function which returns true only if there's actually a GDB connected to the debug stub and attached to at least one vCPU. Reported-by: Liviu Ionescu Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Luc Michel Message-id: 20220526190053.521505-2-peter.maydell@linaro.org --- gdbstub.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index a3ff870..88a34c8 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -443,6 +443,15 @@ static int get_char(void) } #endif +/* + * Return true if there is a GDB currently connected to the stub + * and attached to a CPU + */ +static bool gdb_attached(void) +{ + return gdbserver_state.init && gdbserver_state.c_cpu; +} + static enum { GDB_SYS_UNKNOWN, GDB_SYS_ENABLED, @@ -464,8 +473,7 @@ int use_gdb_syscalls(void) /* -semihosting-config target=auto */ /* On the first call check if gdb is connected and remember. */ if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { - gdb_syscall_mode = gdbserver_state.init ? - GDB_SYS_ENABLED : GDB_SYS_DISABLED; + gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED; } return gdb_syscall_mode == GDB_SYS_ENABLED; } @@ -2886,7 +2894,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va) target_ulong addr; uint64_t i64; - if (!gdbserver_state.init) { + if (!gdb_attached()) { return; } -- cgit v1.1 From 90c072e063737e9e8f431489bbd334452f89056e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 10 Jun 2022 14:32:36 +0100 Subject: semihosting/config: Merge --semihosting-config option groups Currently we mishandle the --semihosting-config option if the user specifies it on the command line more than once. For example with: --semihosting-config target=gdb --semihosting-config arg=foo,arg=bar the function qemu_semihosting_config_options() is called twice, once for each argument. But that function expects to be called only once, and it always unconditionally sets the semihosting.enabled, semihost_chardev and semihosting.target variables. This means that if any of those options were set anywhere except the last --semihosting-config option on the command line, those settings are ignored. In the example above, 'target=gdb' in the first option is overridden by an implied default 'target=auto' in the second. The QemuOptsList machinery has a flag for handling this kind of "option group is setting global state": by setting .merge_lists = true; we make the machinery merge all the --semihosting-config arguments the user passes into a single set of options and call our qemu_semihosting_config_options() just once. Signed-off-by: Peter Maydell Reviewed-by: Luc Michel Message-id: 20220526190053.521505-3-peter.maydell@linaro.org --- semihosting/config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/semihosting/config.c b/semihosting/config.c index 50d8210..3afacf5 100644 --- a/semihosting/config.c +++ b/semihosting/config.c @@ -27,6 +27,7 @@ QemuOptsList qemu_semihosting_config_opts = { .name = "semihosting-config", + .merge_lists = true, .implied_opt_name = "enable", .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), .desc = { -- cgit v1.1