From nobody Tue Apr 15 15:39:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1507308092305708.0514991556753; Fri, 6 Oct 2017 09:41:32 -0700 (PDT) Received: from localhost ([::1]:45856 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e0Vgf-0007CH-Bl for importer@patchew.org; Fri, 06 Oct 2017 12:41:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58290) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e0V1r-0004Nq-4s for qemu-devel@nongnu.org; Fri, 06 Oct 2017 11:59:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e0V1k-0007q3-Vu for qemu-devel@nongnu.org; Fri, 06 Oct 2017 11:59:11 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:37718) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1e0V1k-0007nY-Kd for qemu-devel@nongnu.org; Fri, 06 Oct 2017 11:59:04 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1e0V1b-0002tW-5u for qemu-devel@nongnu.org; Fri, 06 Oct 2017 16:58:55 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Fri, 6 Oct 2017 16:59:31 +0100 Message-Id: <1507305585-20608-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1507305585-20608-1-git-send-email-peter.maydell@linaro.org> References: <1507305585-20608-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PULL 06/20] target/arm: Prepare for CONTROL.SPSEL being nonzero in Handler mode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 In the v7M architecture, there is an invariant that if the CPU is in Handler mode then the CONTROL.SPSEL bit cannot be nonzero. This in turn means that the current stack pointer is always indicated by CONTROL.SPSEL, even though Handler mode always uses the Main stack pointer. In v8M, this invariant is removed, and CONTROL.SPSEL may now be nonzero in Handler mode (though Handler mode still always uses the Main stack pointer). In preparation for this change, change how we handle this bit: rename switch_v7m_sp() to the now more accurate write_v7m_control_spsel(), and make it check both the handler mode state and the SPSEL bit. Note that this implicitly changes the point at which we switch active SP on exception exit from before we pop the exception frame to after it. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson Message-id: 1506092407-26985-4-git-send-email-peter.maydell@linaro.org --- target/arm/cpu.h | 8 ++++++- hw/intc/armv7m_nvic.c | 2 +- target/arm/helper.c | 65 ++++++++++++++++++++++++++++++++++-------------= ---- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 8afceca..ad6eff4 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -991,6 +991,11 @@ void pmccntr_sync(CPUARMState *env); #define PSTATE_MODE_EL1t 4 #define PSTATE_MODE_EL0t 0 =20 +/* Write a new value to v7m.exception, thus transitioning into or out + * of Handler mode; this may result in a change of active stack pointer. + */ +void write_v7m_exception(CPUARMState *env, uint32_t new_exc); + /* Map EL and handler into a PSTATE_MODE. */ static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handl= er) { @@ -1071,7 +1076,8 @@ static inline void xpsr_write(CPUARMState *env, uint3= 2_t val, uint32_t mask) env->condexec_bits |=3D (val >> 8) & 0xfc; } if (mask & XPSR_EXCP) { - env->v7m.exception =3D val & XPSR_EXCP; + /* Note that this only happens on exception exit */ + write_v7m_exception(env, val & XPSR_EXCP); } } =20 diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index bc7b66d..a1041c2 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -616,7 +616,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque) vec->active =3D 1; vec->pending =3D 0; =20 - env->v7m.exception =3D s->vectpending; + write_v7m_exception(env, s->vectpending); =20 nvic_irq_update(s); =20 diff --git a/target/arm/helper.c b/target/arm/helper.c index 7548d4c..36173e2 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6059,21 +6059,44 @@ static bool v7m_using_psp(CPUARMState *env) env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK; } =20 -/* Switch to V7M main or process stack pointer. */ -static void switch_v7m_sp(CPUARMState *env, bool new_spsel) +/* Write to v7M CONTROL.SPSEL bit. This may change the current + * stack pointer between Main and Process stack pointers. + */ +static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel) { uint32_t tmp; - uint32_t old_control =3D env->v7m.control[env->v7m.secure]; - bool old_spsel =3D old_control & R_V7M_CONTROL_SPSEL_MASK; + bool new_is_psp, old_is_psp =3D v7m_using_psp(env); + + env->v7m.control[env->v7m.secure] =3D + deposit32(env->v7m.control[env->v7m.secure], + R_V7M_CONTROL_SPSEL_SHIFT, + R_V7M_CONTROL_SPSEL_LENGTH, new_spsel); + + new_is_psp =3D v7m_using_psp(env); =20 - if (old_spsel !=3D new_spsel) { + if (old_is_psp !=3D new_is_psp) { tmp =3D env->v7m.other_sp; env->v7m.other_sp =3D env->regs[13]; env->regs[13] =3D tmp; + } +} + +void write_v7m_exception(CPUARMState *env, uint32_t new_exc) +{ + /* Write a new value to v7m.exception, thus transitioning into or out + * of Handler mode; this may result in a change of active stack pointe= r. + */ + bool new_is_psp, old_is_psp =3D v7m_using_psp(env); + uint32_t tmp; =20 - env->v7m.control[env->v7m.secure] =3D deposit32(old_control, - R_V7M_CONTROL_SPSEL_SHIFT, - R_V7M_CONTROL_SPSEL_LENGTH, new_spsel= ); + env->v7m.exception =3D new_exc; + + new_is_psp =3D v7m_using_psp(env); + + if (old_is_psp !=3D new_is_psp) { + tmp =3D env->v7m.other_sp; + env->v7m.other_sp =3D env->regs[13]; + env->regs[13] =3D tmp; } } =20 @@ -6159,13 +6182,11 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, b= ool secure, bool threadmode, bool want_psp =3D threadmode && spsel; =20 if (secure =3D=3D env->v7m.secure) { - /* Currently switch_v7m_sp switches SP as it updates SPSEL, - * so the SP we want is always in regs[13]. - * When we decouple SPSEL from the actually selected SP - * we need to check want_psp against v7m_using_psp() - * to see whether we need regs[13] or v7m.other_sp. - */ - return &env->regs[13]; + if (want_psp =3D=3D v7m_using_psp(env)) { + return &env->regs[13]; + } else { + return &env->v7m.other_sp; + } } else { if (want_psp) { return &env->v7m.other_ss_psp; @@ -6208,7 +6229,7 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t= lr) uint32_t addr; =20 armv7m_nvic_acknowledge_irq(env->nvic); - switch_v7m_sp(env, 0); + write_v7m_control_spsel(env, 0); arm_clear_exclusive(env); /* Clear IT bits */ env->condexec_bits =3D 0; @@ -6354,11 +6375,11 @@ static void do_v7m_exception_exit(ARMCPU *cpu) return; } =20 - /* Set CONTROL.SPSEL from excret.SPSEL. For QEMU this currently - * causes us to switch the active SP, but we will change this - * later to not do that so we can support v8M. + /* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in + * Handler mode (and will be until we write the new XPSR.Interrupt + * field) this does not switch around the current stack pointer. */ - switch_v7m_sp(env, return_to_sp_process); + write_v7m_control_spsel(env, return_to_sp_process); =20 { /* The stack pointer we should be reading the exception frame from @@ -9173,11 +9194,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t mas= kreg, uint32_t val) case 20: /* CONTROL */ /* Writing to the SPSEL bit only has an effect if we are in * thread mode; other bits can be updated by any privileged code. - * switch_v7m_sp() deals with updating the SPSEL bit in + * write_v7m_control_spsel() deals with updating the SPSEL bit in * env->v7m.control, so we only need update the others. */ if (!arm_v7m_is_handler_mode(env)) { - switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) !=3D 0); + write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) = !=3D 0); } env->v7m.control[env->v7m.secure] &=3D ~R_V7M_CONTROL_NPRIV_MASK; env->v7m.control[env->v7m.secure] |=3D val & R_V7M_CONTROL_NPRIV_M= ASK; --=20 2.7.4