From patchwork Mon Apr 10 10:39:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97075 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291230obc; Mon, 10 Apr 2017 03:39:59 -0700 (PDT) X-Received: by 10.98.67.193 with SMTP id l62mr52745887pfi.148.1491820799907; Mon, 10 Apr 2017 03:39:59 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id a128si13256010pfb.111.2017.04.10.03.39.59 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:39:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWji-0005QP-Ik; Mon, 10 Apr 2017 11:39:54 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 1/7] arm: Don't implement BXJ on M-profile CPUs Date: Mon, 10 Apr 2017 11:39:47 +0100 Message-Id: <1491820793-5348-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> For M-profile CPUs, the BXJ instruction does not exist at all, and the encoding should always UNDEF. We were accidentally implementing it to behave like A-profile BXJ; correct the error. Signed-off-by: Peter Maydell --- target/arm/translate.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) -- 2.7.4 Reviewed-by: Philippe Mathieu-Daudé diff --git a/target/arm/translate.c b/target/arm/translate.c index e32e38c..fe3f442 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -10485,7 +10485,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } break; case 4: /* bxj */ - /* Trivial implementation equivalent to bx. */ + /* Trivial implementation equivalent to bx. + * This instruction doesn't exist at all for M-profile. + */ + if (arm_dc_feature(s, ARM_FEATURE_M)) { + goto illegal_op; + } tmp = load_reg(s, rn); gen_bx(s, tmp); break; From patchwork Mon Apr 10 10:39:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97069 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291217obc; Mon, 10 Apr 2017 03:39:56 -0700 (PDT) X-Received: by 10.28.9.76 with SMTP id 73mr3933487wmj.93.1491820796845; Mon, 10 Apr 2017 03:39:56 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id p144si7454243wme.157.2017.04.10.03.39.56 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:39:56 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWjj-0005Qa-2g; Mon, 10 Apr 2017 11:39:55 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 2/7] arm: Thumb shift operations should not permit interworking branches Date: Mon, 10 Apr 2017 11:39:48 +0100 Message-Id: <1491820793-5348-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> In Thumb mode, the only instructions which can cause an interworking branch by writing the PC are BLX, BX, BXJ, LDR, POP and LDM. Unlike ARM mode, data processing instructions which target the PC do not cause interworking branches. When we added support for doing interworking branches on writes to PC from data processing instructions in commit 21aeb3430ce7ba, we accidentally changed a Thumb instruction to have interworking branch behaviour for writes to PC. (MOV, MOVS register-shifted register, encoding T2; this is the standard encoding for LSL/LSR/ASR/ROR (register).) For this encoding, behaviour with Rd == R15 is specified as UNPREDICTABLE, so allowing an interworking branch is within spec, but it's confusing and differs from our handling of this class of UNPREDICTABLE for other Thumb ALU operations. Make it perform a simple (non-interworking) branch like the others. Signed-off-by: Peter Maydell --- target/arm/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.7.4 diff --git a/target/arm/translate.c b/target/arm/translate.c index fe3f442..ddc62b6 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9959,7 +9959,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw gen_arm_shift_reg(tmp, op, tmp2, logic_cc); if (logic_cc) gen_logic_CC(tmp); - store_reg_bx(s, rd, tmp); + store_reg(s, rd, tmp); break; case 1: /* Sign/zero extend. */ op = (insn >> 20) & 7; From patchwork Mon Apr 10 10:39:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97072 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291223obc; Mon, 10 Apr 2017 03:39:58 -0700 (PDT) X-Received: by 10.84.164.199 with SMTP id l7mr66643229plg.151.1491820798275; Mon, 10 Apr 2017 03:39:58 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id 31si7666547plk.265.2017.04.10.03.39.57 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:39:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWjj-0005Ql-If; Mon, 10 Apr 2017 11:39:55 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 3/7] arm: Factor out "generate right kind of step exception" Date: Mon, 10 Apr 2017 11:39:49 +0100 Message-Id: <1491820793-5348-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> We currently have two places that do: if (dc->ss_active) { gen_step_complete_exception(dc); } else { gen_exception_internal(EXCP_DEBUG); } Factor this out into its own function, as we're about to add a third place that needs the same logic. Signed-off-by: Peter Maydell --- target/arm/translate.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) -- 2.7.4 Reviewed-by: Philippe Mathieu-Daudé diff --git a/target/arm/translate.c b/target/arm/translate.c index ddc62b6..870e320 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -296,6 +296,19 @@ static void gen_step_complete_exception(DisasContext *s) s->is_jmp = DISAS_EXC; } +static void gen_singlestep_exception(DisasContext *s) +{ + /* Generate the right kind of exception for singlestep, which is + * either the architectural singlestep or EXCP_DEBUG for QEMU's + * gdb singlestepping. + */ + if (s->ss_active) { + gen_step_complete_exception(s); + } else { + gen_exception_internal(EXCP_DEBUG); + } +} + static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b) { TCGv_i32 tmp1 = tcg_temp_new_i32(); @@ -11998,24 +12011,15 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) gen_set_pc_im(dc, dc->pc); /* fall through */ default: - if (dc->ss_active) { - gen_step_complete_exception(dc); - } else { - /* FIXME: Single stepping a WFI insn will not halt - the CPU. */ - gen_exception_internal(EXCP_DEBUG); - } + /* FIXME: Single stepping a WFI insn will not halt the CPU. */ + gen_singlestep_exception(dc); } if (dc->condjmp) { /* "Condition failed" instruction codepath. */ gen_set_label(dc->condlabel); gen_set_condexec(dc); gen_set_pc_im(dc, dc->pc); - if (dc->ss_active) { - gen_step_complete_exception(dc); - } else { - gen_exception_internal(EXCP_DEBUG); - } + gen_singlestep_exception(dc); } } else { /* While branches must always occur at the end of an IT block, From patchwork Mon Apr 10 10:39:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97074 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291229obc; Mon, 10 Apr 2017 03:39:59 -0700 (PDT) X-Received: by 10.84.196.129 with SMTP id l1mr17384639pld.21.1491820799508; Mon, 10 Apr 2017 03:39:59 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id f21si3028949pfk.108.2017.04.10.03.39.58 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:39:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWjk-0005R7-1S; Mon, 10 Apr 2017 11:39:56 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 4/7] arm: Move gen_set_condexec() and gen_set_pc_im() up in the file Date: Mon, 10 Apr 2017 11:39:50 +0100 Message-Id: <1491820793-5348-5-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> Move the utility routines gen_set_condexec() and gen_set_pc_im() up in the file, as we will want to use them from a function placed earlier in the file than their current location. Signed-off-by: Peter Maydell --- target/arm/translate.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) -- 2.7.4 Reviewed-by: Philippe Mathieu-Daudé diff --git a/target/arm/translate.c b/target/arm/translate.c index 870e320..a1a0e73 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -893,6 +893,21 @@ static const uint8_t table_logic_cc[16] = { 1, /* mvn */ }; +static inline void gen_set_condexec(DisasContext *s) +{ + if (s->condexec_mask) { + uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp, val); + store_cpu_field(tmp, condexec_bits); + } +} + +static inline void gen_set_pc_im(DisasContext *s, target_ulong val) +{ + tcg_gen_movi_i32(cpu_R[15], val); +} + /* Set PC and Thumb state from an immediate address. */ static inline void gen_bx_im(DisasContext *s, uint32_t addr) { @@ -1069,11 +1084,6 @@ DO_GEN_ST(8, MO_UB) DO_GEN_ST(16, MO_UW) DO_GEN_ST(32, MO_UL) -static inline void gen_set_pc_im(DisasContext *s, target_ulong val) -{ - tcg_gen_movi_i32(cpu_R[15], val); -} - static inline void gen_hvc(DisasContext *s, int imm16) { /* The pre HVC helper handles cases when HVC gets trapped @@ -1107,17 +1117,6 @@ static inline void gen_smc(DisasContext *s) s->is_jmp = DISAS_SMC; } -static inline void -gen_set_condexec (DisasContext *s) -{ - if (s->condexec_mask) { - uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp, val); - store_cpu_field(tmp, condexec_bits); - } -} - static void gen_exception_internal_insn(DisasContext *s, int offset, int excp) { gen_set_condexec(s); From patchwork Mon Apr 10 10:39:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97076 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291234obc; Mon, 10 Apr 2017 03:40:00 -0700 (PDT) X-Received: by 10.99.2.5 with SMTP id 5mr26741435pgc.205.1491820800584; Mon, 10 Apr 2017 03:40:00 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id c17si13270555pgh.23.2017.04.10.03.39.59 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:40:00 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWjk-0005RL-GP; Mon, 10 Apr 2017 11:39:56 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 5/7] arm: Move condition-failed codepath generation out of if() Date: Mon, 10 Apr 2017 11:39:51 +0100 Message-Id: <1491820793-5348-6-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> Move the code to generate the "condition failed" instruction codepath out of the if (singlestepping) {} else {}. This will allow adding support for handling a new is_jmp type which can't be neatly split into "singlestepping case" versus "not singlestepping case". Signed-off-by: Peter Maydell --- target/arm/translate.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) -- 2.7.4 Reviewed-by: Philippe Mathieu-Daudé diff --git a/target/arm/translate.c b/target/arm/translate.c index a1a0e73..87fd702 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -11988,9 +11988,9 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) /* At this stage dc->condjmp will only be set when the skipped instruction was a conditional branch or trap, and the PC has already been written. */ + gen_set_condexec(dc); if (unlikely(cs->singlestep_enabled || dc->ss_active)) { /* Unconditional and "condition passed" instruction codepath. */ - gen_set_condexec(dc); switch (dc->is_jmp) { case DISAS_SWI: gen_ss_advance(dc); @@ -12013,13 +12013,6 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) /* FIXME: Single stepping a WFI insn will not halt the CPU. */ gen_singlestep_exception(dc); } - if (dc->condjmp) { - /* "Condition failed" instruction codepath. */ - gen_set_label(dc->condlabel); - gen_set_condexec(dc); - gen_set_pc_im(dc, dc->pc); - gen_singlestep_exception(dc); - } } else { /* While branches must always occur at the end of an IT block, there are a few other things that can cause us to terminate @@ -12029,7 +12022,6 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) - Hardware watchpoints. Hardware breakpoints have already been handled and skip this code. */ - gen_set_condexec(dc); switch(dc->is_jmp) { case DISAS_NEXT: gen_goto_tb(dc, 1, dc->pc); @@ -12069,11 +12061,17 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) gen_exception(EXCP_SMC, syn_aa32_smc(), 3); break; } - if (dc->condjmp) { - gen_set_label(dc->condlabel); - gen_set_condexec(dc); + } + + if (dc->condjmp) { + /* "Condition failed" instruction codepath for the branch/trap insn */ + gen_set_label(dc->condlabel); + gen_set_condexec(dc); + if (unlikely(cs->singlestep_enabled || dc->ss_active)) { + gen_set_pc_im(dc, dc->pc); + gen_singlestep_exception(dc); + } else { gen_goto_tb(dc, 1, dc->pc); - dc->condjmp = 0; } } From patchwork Mon Apr 10 10:39:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97071 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291220obc; Mon, 10 Apr 2017 03:39:57 -0700 (PDT) X-Received: by 10.28.18.21 with SMTP id 21mr8701209wms.77.1491820797595; Mon, 10 Apr 2017 03:39:57 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id g41si15033570wrg.312.2017.04.10.03.39.57 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:39:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWjl-0005Ra-0J; Mon, 10 Apr 2017 11:39:57 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 6/7] arm: Implement M profile exception return properly Date: Mon, 10 Apr 2017 11:39:52 +0100 Message-Id: <1491820793-5348-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> On M profile, return from exceptions happen when privileged code executes one of the following function call return instructions: * POP or LDM which loads the PC * LDR to PC * BX register and the new PC value is 0xFFxxxxxx. QEMU tries to implement this by not treating the instruction specially but then catching the attempt to execute from the magic address value. This is not ideal, because: * there are guest visible differences from the architecturally specified behaviour (for instance jumping to 0xFFxxxxxx via a different instruction should not cause an exception return but it will in the QEMU implementation) * we have to account for it in various places (like refusing to take an interrupt if the PC is at a magic value, and making sure that the MPU doesn't deny execution at the magic value addresses) Drop these hacks, and instead implement exception return the way the architecture specifies -- by having the relevant instructions check for the magic value and raise the 'do an exception return' QEMU internal exception immediately. The effect on the generated code is minor: bx lr, old code (and new code for unprivileged mode): TCG: mov_i32 tmp5,r14 movi_i32 tmp6,$0xfffffffffffffffe and_i32 pc,tmp5,tmp6 movi_i32 tmp6,$0x1 and_i32 tmp5,tmp5,tmp6 st_i32 tmp5,env,$0x218 exit_tb $0x0 set_label $L0 exit_tb $0x7f2aabd61993 x86_64 generated code: 0x7f2aabe87019: mov %ebx,%ebp 0x7f2aabe8701b: and $0xfffffffffffffffe,%ebp 0x7f2aabe8701e: mov %ebp,0x3c(%r14) 0x7f2aabe87022: and $0x1,%ebx 0x7f2aabe87025: mov %ebx,0x218(%r14) 0x7f2aabe8702c: xor %eax,%eax 0x7f2aabe8702e: jmpq 0x7f2aabe7c016 bx lr, new code when privileged: TCG: mov_i32 tmp5,r14 movi_i32 tmp6,$0xfffffffffffffffe and_i32 pc,tmp5,tmp6 movi_i32 tmp6,$0x1 and_i32 tmp5,tmp5,tmp6 st_i32 tmp5,env,$0x218 movi_i32 tmp5,$0xffffffffff000000 brcond_i32 pc,tmp5,geu,$L1 exit_tb $0x0 set_label $L1 movi_i32 tmp5,$0x8 call exception_internal,$0x0,$0,env,tmp5 x86_64 generated code: 0x7fe8fa1264e3: mov %ebp,%ebx 0x7fe8fa1264e5: and $0xfffffffffffffffe,%ebx 0x7fe8fa1264e8: mov %ebx,0x3c(%r14) 0x7fe8fa1264ec: and $0x1,%ebp 0x7fe8fa1264ef: mov %ebp,0x218(%r14) 0x7fe8fa1264f6: cmp $0xff000000,%ebx 0x7fe8fa1264fc: jae 0x7fe8fa126509 0x7fe8fa126502: xor %eax,%eax 0x7fe8fa126504: jmpq 0x7fe8fa122016 0x7fe8fa126509: mov %r14,%rdi 0x7fe8fa12650c: mov $0x8,%esi 0x7fe8fa126511: mov $0x56095dbeccf5,%r10 0x7fe8fa12651b: callq *%r10 which is a difference of one cmp/branch-not-taken. This will be lost in the noise of having to exit generated code and look up the next TB anyway. Signed-off-by: Peter Maydell --- target/arm/translate.h | 4 ++++ target/arm/translate.c | 65 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 6 deletions(-) -- 2.7.4 Reviewed-by: Philippe Mathieu-Daudé diff --git a/target/arm/translate.h b/target/arm/translate.h index abb0760..c2a5451 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -134,6 +134,10 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) #define DISAS_HVC 8 #define DISAS_SMC 9 #define DISAS_YIELD 10 +/* M profile branch which might be an exception return (and so needs + * custom end-of-TB code) + */ +#define DISAS_BX_EXCRET 11 #ifdef TARGET_AARCH64 void a64_translate_init(void); diff --git a/target/arm/translate.c b/target/arm/translate.c index 87fd702..156ab46 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -932,6 +932,51 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var) store_cpu_field(var, thumb); } +/* Set PC and Thumb state from var. var is marked as dead. + * For M-profile CPUs, include logic to detect exception-return + * branches and handle them. + * This is needed for Thumb POP/LDM to PC, LDR to PC, and BX reg, and no others. + */ +static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var) +{ + /* Generate the same code here as for a simple bx, but flag via + * s->is_jmp that we need to do the rest of the work later. + */ + gen_bx(s, var); + if (!IS_USER(s) && arm_dc_feature(s, ARM_FEATURE_M)) { + s->is_jmp = DISAS_BX_EXCRET; + } +} + +static inline void gen_bx_excret_final_code(DisasContext *s) +{ + /* Generate the code to finish possible exception return and end the TB */ + TCGLabel *excret_label = gen_new_label(); + + /* Is the new PC value in the magic range indicating exception return? */ + tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], 0xff000000, excret_label); + /* No: end the TB as we would for a DISAS_JMP */ + if (s->singlestep_enabled || s->ss_active) { + gen_singlestep_exception(s); + } else { + tcg_gen_exit_tb(0); + } + gen_set_label(excret_label); + /* Yes: this is an exception return. + * At this point in runtime env->regs[15] and env->thumb will hold + * the exception-return magic number, which do_v7m_exception_exit() + * will read. Nothing else will be able to see those values because + * the cpu-exec main loop guarantees that we will always go straight + * from raising the exception to the exception-handling code. + * + * gen_ss_advance(s) does nothing on M profile currently but + * calling it is conceptually the right thing as we have executed + * this instruction (compare SWI, HVC, SMC handling). + */ + gen_ss_advance(s); + gen_exception_internal(EXCP_EXCEPTION_EXIT); +} + /* Variant of store_reg which uses branch&exchange logic when storing to r15 in ARM architecture v7 and above. The source must be a temporary and will be marked as dead. */ @@ -951,7 +996,7 @@ static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var) static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var) { if (reg == 15 && ENABLE_ARCH_5) { - gen_bx(s, var); + gen_bx_excret(s, var); } else { store_reg(s, reg, var); } @@ -9870,7 +9915,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw tmp = tcg_temp_new_i32(); gen_aa32_ld32u(s, tmp, addr, get_mem_index(s)); if (i == 15) { - gen_bx(s, tmp); + gen_bx_excret(s, tmp); } else if (i == rn) { loaded_var = tmp; loaded_base = 1; @@ -10902,7 +10947,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw goto illegal_op; } if (rs == 15) { - gen_bx(s, tmp); + gen_bx_excret(s, tmp); } else { store_reg(s, rs, tmp); } @@ -11092,9 +11137,10 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) tmp2 = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp2, val); store_reg(s, 14, tmp2); + gen_bx(s, tmp); + } else { + gen_bx_excret(s, tmp); } - /* already thumb, no need to check */ - gen_bx(s, tmp); break; } break; @@ -11989,7 +12035,14 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) instruction was a conditional branch or trap, and the PC has already been written. */ gen_set_condexec(dc); - if (unlikely(cs->singlestep_enabled || dc->ss_active)) { + if (dc->is_jmp == DISAS_BX_EXCRET) { + /* Exception return branches need some special case code at the + * end of the TB, which is complex enough that it has to + * handle the single-step vs not and the condition-failed + * insn codepath itself. + */ + gen_bx_excret_final_code(dc); + } else if (unlikely(cs->singlestep_enabled || dc->ss_active)) { /* Unconditional and "condition passed" instruction codepath. */ switch (dc->is_jmp) { case DISAS_SWI: From patchwork Mon Apr 10 10:39:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 97073 Delivered-To: patches@linaro.org Received: by 10.182.246.10 with SMTP id xs10csp1291224obc; Mon, 10 Apr 2017 03:39:58 -0700 (PDT) X-Received: by 10.25.161.81 with SMTP id k78mr18503557lfe.111.1491820798369; Mon, 10 Apr 2017 03:39:58 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id h67si7417482lji.207.2017.04.10.03.39.58 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 03:39:58 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cxWjl-0005Ro-Fj; Mon, 10 Apr 2017 11:39:57 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 7/7] arm: Remove workarounds for old M-profile exception return implementation Date: Mon, 10 Apr 2017 11:39:53 +0100 Message-Id: <1491820793-5348-8-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> References: <1491820793-5348-1-git-send-email-peter.maydell@linaro.org> Now that we've rewritten M-profile exception return so that the magic PC values are not visible to other parts of QEMU, we can delete the special casing of them elsewhere. Signed-off-by: Peter Maydell --- target/arm/cpu.c | 43 ++----------------------------------------- target/arm/translate.c | 8 -------- 2 files changed, 2 insertions(+), 49 deletions(-) -- 2.7.4 Reviewed-by: Philippe Mathieu-Daudé diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 04b062c..b357aee 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -304,33 +304,6 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) } #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) -static void arm_v7m_unassigned_access(CPUState *cpu, hwaddr addr, - bool is_write, bool is_exec, int opaque, - unsigned size) -{ - ARMCPU *arm = ARM_CPU(cpu); - CPUARMState *env = &arm->env; - - /* ARMv7-M interrupt return works by loading a magic value into the PC. - * On real hardware the load causes the return to occur. The qemu - * implementation performs the jump normally, then does the exception - * return by throwing a special exception when when the CPU tries to - * execute code at the magic address. - */ - if (env->v7m.exception != 0 && addr >= 0xfffffff0 && is_exec) { - cpu->exception_index = EXCP_EXCEPTION_EXIT; - cpu_loop_exit(cpu); - } - - /* In real hardware an attempt to access parts of the address space - * with nothing there will usually cause an external abort. - * However our QEMU board models are often missing device models where - * the guest can boot anyway with the default read-as-zero/writes-ignored - * behaviour that you get without a QEMU unassigned_access hook. - * So just return here to retain that default behaviour. - */ -} - static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { CPUClass *cc = CPU_GET_CLASS(cs); @@ -338,17 +311,7 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) CPUARMState *env = &cpu->env; bool ret = false; - /* ARMv7-M interrupt return works by loading a magic value - * into the PC. On real hardware the load causes the - * return to occur. The qemu implementation performs the - * jump normally, then does the exception return when the - * CPU tries to execute code at the magic address. - * This will cause the magic PC value to be pushed to - * the stack if an interrupt occurred at the wrong time. - * We avoid this by disabling interrupts when - * pc contains a magic address. - * - * ARMv7-M interrupt masking works differently than -A or -R. + /* ARMv7-M interrupt masking works differently than -A or -R. * There is no FIQ/IRQ distinction. Instead of I and F bits * masking FIQ and IRQ interrupts, an exception is taken only * if it is higher priority than the current execution priority @@ -356,8 +319,7 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) * currently active exception). */ if (interrupt_request & CPU_INTERRUPT_HARD - && (armv7m_nvic_can_take_pending_exception(env->nvic)) - && (env->regs[15] < 0xfffffff0)) { + && (armv7m_nvic_can_take_pending_exception(env->nvic))) { cs->exception_index = EXCP_IRQ; cc->do_interrupt(cs); ret = true; @@ -1091,7 +1053,6 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data) cc->do_interrupt = arm_v7m_cpu_do_interrupt; #endif - cc->do_unassigned_access = arm_v7m_unassigned_access; cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt; } diff --git a/target/arm/translate.c b/target/arm/translate.c index 156ab46..c85bc6c 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -11914,14 +11914,6 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) dc->is_jmp = DISAS_EXC; break; } -#else - if (arm_dc_feature(dc, ARM_FEATURE_M)) { - /* Branches to the magic exception-return addresses should - * already have been caught via the arm_v7m_unassigned_access hook, - * and never get here. - */ - assert(dc->pc < 0xfffffff0); - } #endif if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {