From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org
Subject: [Qemu-devel] [PATCH v3 10/31] target/arm: Move helper_exception_return to helper-a64.c
Date: Wed, 9 Jan 2019 08:31:08 +1000 [thread overview]
Message-ID: <20190108223129.5570-11-richard.henderson@linaro.org> (raw)
In-Reply-To: <20190108223129.5570-1-richard.henderson@linaro.org>
This function is only used by AArch64. Code movement only.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper-a64.h | 2 +
target/arm/helper.h | 1 -
target/arm/helper-a64.c | 155 ++++++++++++++++++++++++++++++++++++++++
target/arm/op_helper.c | 155 ----------------------------------------
4 files changed, 157 insertions(+), 156 deletions(-)
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index 28aa0af69d..55299896c4 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -86,6 +86,8 @@ DEF_HELPER_2(advsimd_f16tosinth, i32, f16, ptr)
DEF_HELPER_2(advsimd_f16touinth, i32, f16, ptr)
DEF_HELPER_2(sqrt_f16, f16, f16, ptr)
+DEF_HELPER_1(exception_return, void, env)
+
DEF_HELPER_FLAGS_3(pacia, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pacib, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pacda, TCG_CALL_NO_WG, i64, env, i64, i64)
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 8c9590091b..53a38188c6 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -79,7 +79,6 @@ DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
DEF_HELPER_1(clear_pstate_ss, void, env)
-DEF_HELPER_1(exception_return, void, env)
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 61799d20e1..66ff70dcdb 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -887,6 +887,161 @@ uint32_t HELPER(advsimd_f16touinth)(uint32_t a, void *fpstp)
return float16_to_uint16(a, fpst);
}
+static int el_from_spsr(uint32_t spsr)
+{
+ /* Return the exception level that this SPSR is requesting a return to,
+ * or -1 if it is invalid (an illegal return)
+ */
+ if (spsr & PSTATE_nRW) {
+ switch (spsr & CPSR_M) {
+ case ARM_CPU_MODE_USR:
+ return 0;
+ case ARM_CPU_MODE_HYP:
+ return 2;
+ case ARM_CPU_MODE_FIQ:
+ case ARM_CPU_MODE_IRQ:
+ case ARM_CPU_MODE_SVC:
+ case ARM_CPU_MODE_ABT:
+ case ARM_CPU_MODE_UND:
+ case ARM_CPU_MODE_SYS:
+ return 1;
+ case ARM_CPU_MODE_MON:
+ /* Returning to Mon from AArch64 is never possible,
+ * so this is an illegal return.
+ */
+ default:
+ return -1;
+ }
+ } else {
+ if (extract32(spsr, 1, 1)) {
+ /* Return with reserved M[1] bit set */
+ return -1;
+ }
+ if (extract32(spsr, 0, 4) == 1) {
+ /* return to EL0 with M[0] bit set */
+ return -1;
+ }
+ return extract32(spsr, 2, 2);
+ }
+}
+
+void HELPER(exception_return)(CPUARMState *env)
+{
+ int cur_el = arm_current_el(env);
+ unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
+ uint32_t spsr = env->banked_spsr[spsr_idx];
+ int new_el;
+ bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
+
+ aarch64_save_sp(env, cur_el);
+
+ arm_clear_exclusive(env);
+
+ /* We must squash the PSTATE.SS bit to zero unless both of the
+ * following hold:
+ * 1. debug exceptions are currently disabled
+ * 2. singlestep will be active in the EL we return to
+ * We check 1 here and 2 after we've done the pstate/cpsr write() to
+ * transition to the EL we're going to.
+ */
+ if (arm_generate_debug_exceptions(env)) {
+ spsr &= ~PSTATE_SS;
+ }
+
+ new_el = el_from_spsr(spsr);
+ if (new_el == -1) {
+ goto illegal_return;
+ }
+ if (new_el > cur_el
+ || (new_el == 2 && !arm_feature(env, ARM_FEATURE_EL2))) {
+ /* Disallow return to an EL which is unimplemented or higher
+ * than the current one.
+ */
+ goto illegal_return;
+ }
+
+ if (new_el != 0 && arm_el_is_aa64(env, new_el) != return_to_aa64) {
+ /* Return to an EL which is configured for a different register width */
+ goto illegal_return;
+ }
+
+ if (new_el == 2 && arm_is_secure_below_el3(env)) {
+ /* Return to the non-existent secure-EL2 */
+ goto illegal_return;
+ }
+
+ if (new_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
+ goto illegal_return;
+ }
+
+ qemu_mutex_lock_iothread();
+ arm_call_pre_el_change_hook(arm_env_get_cpu(env));
+ qemu_mutex_unlock_iothread();
+
+ if (!return_to_aa64) {
+ env->aarch64 = 0;
+ /* We do a raw CPSR write because aarch64_sync_64_to_32()
+ * will sort the register banks out for us, and we've already
+ * caught all the bad-mode cases in el_from_spsr().
+ */
+ cpsr_write(env, spsr, ~0, CPSRWriteRaw);
+ if (!arm_singlestep_active(env)) {
+ env->uncached_cpsr &= ~PSTATE_SS;
+ }
+ aarch64_sync_64_to_32(env);
+
+ if (spsr & CPSR_T) {
+ env->regs[15] = env->elr_el[cur_el] & ~0x1;
+ } else {
+ env->regs[15] = env->elr_el[cur_el] & ~0x3;
+ }
+ qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
+ "AArch32 EL%d PC 0x%" PRIx32 "\n",
+ cur_el, new_el, env->regs[15]);
+ } else {
+ env->aarch64 = 1;
+ pstate_write(env, spsr);
+ if (!arm_singlestep_active(env)) {
+ env->pstate &= ~PSTATE_SS;
+ }
+ aarch64_restore_sp(env, new_el);
+ env->pc = env->elr_el[cur_el];
+ qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
+ "AArch64 EL%d PC 0x%" PRIx64 "\n",
+ cur_el, new_el, env->pc);
+ }
+ /*
+ * Note that cur_el can never be 0. If new_el is 0, then
+ * el0_a64 is return_to_aa64, else el0_a64 is ignored.
+ */
+ aarch64_sve_change_el(env, cur_el, new_el, return_to_aa64);
+
+ qemu_mutex_lock_iothread();
+ arm_call_el_change_hook(arm_env_get_cpu(env));
+ qemu_mutex_unlock_iothread();
+
+ return;
+
+illegal_return:
+ /* Illegal return events of various kinds have architecturally
+ * mandated behaviour:
+ * restore NZCV and DAIF from SPSR_ELx
+ * set PSTATE.IL
+ * restore PC from ELR_ELx
+ * no change to exception level, execution state or stack pointer
+ */
+ env->pstate |= PSTATE_IL;
+ env->pc = env->elr_el[cur_el];
+ spsr &= PSTATE_NZCV | PSTATE_DAIF;
+ spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
+ pstate_write(env, spsr);
+ if (!arm_singlestep_active(env)) {
+ env->pstate &= ~PSTATE_SS;
+ }
+ qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
+ "resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
+}
+
/*
* Square Root and Reciprocal square root
*/
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 8b31c6a13b..c998eadfaa 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -1029,161 +1029,6 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
}
}
-static int el_from_spsr(uint32_t spsr)
-{
- /* Return the exception level that this SPSR is requesting a return to,
- * or -1 if it is invalid (an illegal return)
- */
- if (spsr & PSTATE_nRW) {
- switch (spsr & CPSR_M) {
- case ARM_CPU_MODE_USR:
- return 0;
- case ARM_CPU_MODE_HYP:
- return 2;
- case ARM_CPU_MODE_FIQ:
- case ARM_CPU_MODE_IRQ:
- case ARM_CPU_MODE_SVC:
- case ARM_CPU_MODE_ABT:
- case ARM_CPU_MODE_UND:
- case ARM_CPU_MODE_SYS:
- return 1;
- case ARM_CPU_MODE_MON:
- /* Returning to Mon from AArch64 is never possible,
- * so this is an illegal return.
- */
- default:
- return -1;
- }
- } else {
- if (extract32(spsr, 1, 1)) {
- /* Return with reserved M[1] bit set */
- return -1;
- }
- if (extract32(spsr, 0, 4) == 1) {
- /* return to EL0 with M[0] bit set */
- return -1;
- }
- return extract32(spsr, 2, 2);
- }
-}
-
-void HELPER(exception_return)(CPUARMState *env)
-{
- int cur_el = arm_current_el(env);
- unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
- uint32_t spsr = env->banked_spsr[spsr_idx];
- int new_el;
- bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
-
- aarch64_save_sp(env, cur_el);
-
- arm_clear_exclusive(env);
-
- /* We must squash the PSTATE.SS bit to zero unless both of the
- * following hold:
- * 1. debug exceptions are currently disabled
- * 2. singlestep will be active in the EL we return to
- * We check 1 here and 2 after we've done the pstate/cpsr write() to
- * transition to the EL we're going to.
- */
- if (arm_generate_debug_exceptions(env)) {
- spsr &= ~PSTATE_SS;
- }
-
- new_el = el_from_spsr(spsr);
- if (new_el == -1) {
- goto illegal_return;
- }
- if (new_el > cur_el
- || (new_el == 2 && !arm_feature(env, ARM_FEATURE_EL2))) {
- /* Disallow return to an EL which is unimplemented or higher
- * than the current one.
- */
- goto illegal_return;
- }
-
- if (new_el != 0 && arm_el_is_aa64(env, new_el) != return_to_aa64) {
- /* Return to an EL which is configured for a different register width */
- goto illegal_return;
- }
-
- if (new_el == 2 && arm_is_secure_below_el3(env)) {
- /* Return to the non-existent secure-EL2 */
- goto illegal_return;
- }
-
- if (new_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
- goto illegal_return;
- }
-
- qemu_mutex_lock_iothread();
- arm_call_pre_el_change_hook(arm_env_get_cpu(env));
- qemu_mutex_unlock_iothread();
-
- if (!return_to_aa64) {
- env->aarch64 = 0;
- /* We do a raw CPSR write because aarch64_sync_64_to_32()
- * will sort the register banks out for us, and we've already
- * caught all the bad-mode cases in el_from_spsr().
- */
- cpsr_write(env, spsr, ~0, CPSRWriteRaw);
- if (!arm_singlestep_active(env)) {
- env->uncached_cpsr &= ~PSTATE_SS;
- }
- aarch64_sync_64_to_32(env);
-
- if (spsr & CPSR_T) {
- env->regs[15] = env->elr_el[cur_el] & ~0x1;
- } else {
- env->regs[15] = env->elr_el[cur_el] & ~0x3;
- }
- qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
- "AArch32 EL%d PC 0x%" PRIx32 "\n",
- cur_el, new_el, env->regs[15]);
- } else {
- env->aarch64 = 1;
- pstate_write(env, spsr);
- if (!arm_singlestep_active(env)) {
- env->pstate &= ~PSTATE_SS;
- }
- aarch64_restore_sp(env, new_el);
- env->pc = env->elr_el[cur_el];
- qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
- "AArch64 EL%d PC 0x%" PRIx64 "\n",
- cur_el, new_el, env->pc);
- }
- /*
- * Note that cur_el can never be 0. If new_el is 0, then
- * el0_a64 is return_to_aa64, else el0_a64 is ignored.
- */
- aarch64_sve_change_el(env, cur_el, new_el, return_to_aa64);
-
- qemu_mutex_lock_iothread();
- arm_call_el_change_hook(arm_env_get_cpu(env));
- qemu_mutex_unlock_iothread();
-
- return;
-
-illegal_return:
- /* Illegal return events of various kinds have architecturally
- * mandated behaviour:
- * restore NZCV and DAIF from SPSR_ELx
- * set PSTATE.IL
- * restore PC from ELR_ELx
- * no change to exception level, execution state or stack pointer
- */
- env->pstate |= PSTATE_IL;
- env->pc = env->elr_el[cur_el];
- spsr &= PSTATE_NZCV | PSTATE_DAIF;
- spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
- pstate_write(env, spsr);
- if (!arm_singlestep_active(env)) {
- env->pstate &= ~PSTATE_SS;
- }
- qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
- "resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
-}
-
/* Return true if the linked breakpoint entry lbn passes its checks */
static bool linked_bp_matches(ARMCPU *cpu, int lbn)
{
--
2.17.2
next prev parent reply other threads:[~2019-01-08 22:32 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-08 22:30 [Qemu-devel] [PATCH v3 00/31] target/arm: Implement ARMv8.3-PAuth Richard Henderson
2019-01-08 22:30 ` [Qemu-devel] [PATCH v3 01/31] target/arm: Add state for the ARMv8.3-PAuth extension Richard Henderson
2019-01-18 13:34 ` Peter Maydell
2019-01-21 10:10 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 02/31] target/arm: Add SCTLR bits through ARMv8.5 Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 03/31] target/arm: Add PAuth active bit to tbflags Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 04/31] target/arm: Introduce raise_exception_ra Richard Henderson
2019-01-08 23:26 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 05/31] target/arm: Add PAuth helpers Richard Henderson
2019-01-08 23:28 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 06/31] target/arm: Decode PAuth within system hint space Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 07/31] target/arm: Rearrange decode in disas_data_proc_1src Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 08/31] target/arm: Decode PAuth within disas_data_proc_1src Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 09/31] target/arm: Decode PAuth within disas_data_proc_2src Richard Henderson
2019-01-08 22:31 ` Richard Henderson [this message]
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 11/31] target/arm: Add new_pc argument to helper_exception_return Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 12/31] target/arm: Rearrange decode in disas_uncond_b_reg Richard Henderson
2019-01-18 11:40 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 13/31] target/arm: Decode PAuth within disas_uncond_b_reg Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 14/31] target/arm: Decode Load/store register (pac) Richard Henderson
2019-01-08 23:34 ` Peter Maydell
2019-01-09 11:01 ` Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 15/31] target/arm: Move cpu_mmu_index out of line Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 16/31] target/arm: Introduce arm_mmu_idx Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 17/31] target/arm: Introduce arm_stage1_mmu_idx Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 18/31] target/arm: Create ARMVAParameters and helpers Richard Henderson
2019-01-18 11:42 ` Peter Maydell
2019-01-24 11:54 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 19/31] target/arm: Merge TBFLAG_AA_TB{0, 1} to TBII Richard Henderson
2019-01-18 11:44 ` Peter Maydell
2019-01-18 11:45 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 20/31] target/arm: Export aa64_va_parameters to internals.h Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 21/31] target/arm: Add aa64_va_parameters_both Richard Henderson
2019-01-18 12:00 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 22/31] target/arm: Decode TBID from TCR Richard Henderson
2019-01-18 12:05 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 23/31] target/arm: Reuse aa64_va_parameters for setting tbflags Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 24/31] target/arm: Implement pauth_strip Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 25/31] target/arm: Implement pauth_auth Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 26/31] target/arm: Implement pauth_addpac Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 27/31] target/arm: Implement pauth_computepac Richard Henderson
2019-01-18 12:09 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 28/31] target/arm: Add PAuth system registers Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 29/31] target/arm: Enable PAuth for -cpu max Richard Henderson
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 30/31] target/arm: Enable PAuth for user-only Richard Henderson
2019-01-18 12:11 ` Peter Maydell
2019-01-08 22:31 ` [Qemu-devel] [PATCH v3 31/31] target/arm: Tidy TBI handling in gen_a64_set_pc Richard Henderson
2019-01-09 4:59 ` [Qemu-devel] [PATCH v3 00/31] target/arm: Implement ARMv8.3-PAuth no-reply
2019-01-18 13:38 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190108223129.5570-11-richard.henderson@linaro.org \
--to=richard.henderson@linaro.org \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).