From nobody Thu Dec 18 19:31:18 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; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518174546298413.47475618550334; Fri, 9 Feb 2018 03:09:06 -0800 (PST) Received: from localhost ([::1]:34871 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ek6YD-0005Kk-BQ for importer@patchew.org; Fri, 09 Feb 2018 06:09:05 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39747) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ek6Sn-0000z8-SN for qemu-devel@nongnu.org; Fri, 09 Feb 2018 06:03:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ek6Sm-0001w8-86 for qemu-devel@nongnu.org; Fri, 09 Feb 2018 06:03:29 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:46250) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ek6Sm-0001oy-0P for qemu-devel@nongnu.org; Fri, 09 Feb 2018 06:03:28 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1ek6Sc-0002YX-Vd for qemu-devel@nongnu.org; Fri, 09 Feb 2018 11:03:18 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Fri, 9 Feb 2018 11:02:49 +0000 Message-Id: <20180209110314.11766-6-peter.maydell@linaro.org> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180209110314.11766-1-peter.maydell@linaro.org> References: <20180209110314.11766-1-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 05/30] target/arm: Make v7m_push_callee_stack() honour MPU 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 Make v7m_push_callee_stack() honour the MPU by using the new v7m_stack_write() function. We return a flag to indicate whether the pushes failed, which we can then use in v7m_exception_taken() to cause us to handle the derived exception correctly. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-id: 1517324542-6607-6-git-send-email-peter.maydell@linaro.org --- target/arm/helper.c | 64 ++++++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index f31472a044..614162dd1e 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6473,7 +6473,7 @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int = exc, bool targets_secure) return addr; } =20 -static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailcha= in, +static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailcha= in, bool ignore_faults) { /* For v8M, push the callee-saves register part of the stack frame. @@ -6481,31 +6481,55 @@ static void v7m_push_callee_stack(ARMCPU *cpu, uint= 32_t lr, bool dotailchain, * In the tailchaining case this may not be the current stack. */ CPUARMState *env =3D &cpu->env; - CPUState *cs =3D CPU(cpu); uint32_t *frame_sp_p; uint32_t frameptr; + ARMMMUIdx mmu_idx; + bool stacked_ok; =20 if (dotailchain) { - frame_sp_p =3D get_v7m_sp_ptr(env, true, - lr & R_V7M_EXCRET_MODE_MASK, + bool mode =3D lr & R_V7M_EXCRET_MODE_MASK; + bool priv =3D !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_NPRIV_MA= SK) || + !mode; + + mmu_idx =3D arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, pr= iv); + frame_sp_p =3D get_v7m_sp_ptr(env, M_REG_S, mode, lr & R_V7M_EXCRET_SPSEL_MASK); } else { + mmu_idx =3D core_to_arm_mmu_idx(env, cpu_mmu_index(env, false)); frame_sp_p =3D &env->regs[13]; } =20 frameptr =3D *frame_sp_p - 0x28; =20 - stl_phys(cs->as, frameptr, 0xfefa125b); - stl_phys(cs->as, frameptr + 0x8, env->regs[4]); - stl_phys(cs->as, frameptr + 0xc, env->regs[5]); - stl_phys(cs->as, frameptr + 0x10, env->regs[6]); - stl_phys(cs->as, frameptr + 0x14, env->regs[7]); - stl_phys(cs->as, frameptr + 0x18, env->regs[8]); - stl_phys(cs->as, frameptr + 0x1c, env->regs[9]); - stl_phys(cs->as, frameptr + 0x20, env->regs[10]); - stl_phys(cs->as, frameptr + 0x24, env->regs[11]); + /* Write as much of the stack frame as we can. A write failure may + * cause us to pend a derived exception. + */ + stacked_ok =3D + v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults)= && + v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx, + ignore_faults) && + v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx, + ignore_faults); =20 + /* Update SP regardless of whether any of the stack accesses failed. + * When we implement v8M stack limit checking then this attempt to + * update SP might also fail and result in a derived exception. + */ *frame_sp_p =3D frameptr; + + return !stacked_ok; } =20 static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, @@ -6519,6 +6543,7 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t= lr, bool dotailchain, uint32_t addr; bool targets_secure; int exc; + bool push_failed =3D false; =20 armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure); =20 @@ -6546,8 +6571,8 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t= lr, bool dotailchain, */ if (lr & R_V7M_EXCRET_DCRS_MASK && !(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) { - v7m_push_callee_stack(cpu, lr, dotailchain, - ignore_stackfaults); + push_failed =3D v7m_push_callee_stack(cpu, lr, dotailc= hain, + ignore_stackfaults= ); } lr |=3D R_V7M_EXCRET_DCRS_MASK; } @@ -6589,6 +6614,15 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_= t lr, bool dotailchain, } } =20 + if (push_failed && !ignore_stackfaults) { + /* Derived exception on callee-saves register stacking: + * we might now want to take a different exception which + * targets a different security state, so try again from the top. + */ + v7m_exception_taken(cpu, lr, true, true); + return; + } + addr =3D arm_v7m_load_vector(cpu, exc, targets_secure); =20 /* Now we've done everything that might cause a derived exception --=20 2.16.1