From patchwork Sat Feb 15 16:07:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 24693 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f69.google.com (mail-pb0-f69.google.com [209.85.160.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3B3A7203BE for ; Sat, 15 Feb 2014 16:08:01 +0000 (UTC) Received: by mail-pb0-f69.google.com with SMTP id md12sf30378600pbc.4 for ; Sat, 15 Feb 2014 08:08:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=d8I2fAH+XAy3f1cHQ34Fu1amKZubSpoaVyDpYYfzu7A=; b=Ezxf0ZbuqCnjR+rrRny5pSKrEyzLz/JhV3sI5fx7x28kTXA7CH02FL1WFK3Wr+AqPG VucmIW+MU7gh567UahqkG3yJw3Fhiil8NeSlCzZcoJAar78KKK8l3FSaaauxmg9TR1Jy jaPek04n2Nq82rkZLuBZTUlhS78HaxGu7wGPTXquA5x5QPxTUrHCslia0ZqHP5/kHro5 sFGWeGQ6MITdcQfSr3/kWE0SVW2srvbSe+IqWcNJ4ij5ws8pDuTsRkmibM8j7miinYqK 7eqRTPCjqyd7b+P8q3sZFSu/+vMA4g9C3PeFI2vb0CJAmzRf5bwBaVVa327/esMfXHh2 X4tQ== X-Gm-Message-State: ALoCoQl6vyiXRnJOAop5x8gssK9WH5nRa4Hf1kSX/J05WvIZLRarsfR4znm6Y/0SqLckAAY8evvy X-Received: by 10.66.146.65 with SMTP id ta1mr6132283pab.19.1392480480488; Sat, 15 Feb 2014 08:08:00 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.92.240 with SMTP id b103ls392677qge.57.gmail; Sat, 15 Feb 2014 08:08:00 -0800 (PST) X-Received: by 10.220.106.84 with SMTP id w20mr9959753vco.18.1392480480319; Sat, 15 Feb 2014 08:08:00 -0800 (PST) Received: from mail-vc0-f178.google.com (mail-vc0-f178.google.com [209.85.220.178]) by mx.google.com with ESMTPS id sq4si2990042vdc.132.2014.02.15.08.08.00 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 15 Feb 2014 08:08:00 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.178; Received: by mail-vc0-f178.google.com with SMTP id ik5so10100114vcb.23 for ; Sat, 15 Feb 2014 08:08:00 -0800 (PST) X-Received: by 10.52.27.9 with SMTP id p9mr4830450vdg.28.1392480480237; Sat, 15 Feb 2014 08:08:00 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp25585vcz; Sat, 15 Feb 2014 08:07:59 -0800 (PST) X-Received: by 10.14.246.203 with SMTP id q51mr38139eer.86.1392480465684; Sat, 15 Feb 2014 08:07:45 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id h44si19278267eew.101.2014.02.15.08.07.42 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 15 Feb 2014 08:07:45 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1WEhm2-0006gg-6j; Sat, 15 Feb 2014 16:07:26 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Michael Matz , Claudio Fontana , Dirk Mueller , Laurent Desnogues , kvmarm@lists.cs.columbia.edu, Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Christoffer Dall , Will Newton , Peter Crosthwaite , Rob Herring Subject: [PATCH v3 29/31] target-arm: A64: Add assertion that FP access was checked Date: Sat, 15 Feb 2014 16:07:22 +0000 Message-Id: <1392480444-25565-30-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1392480444-25565-1-git-send-email-peter.maydell@linaro.org> References: <1392480444-25565-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Because unallocated encodings generate different exception syndrome information from traps due to FP being disabled, we can't do a single "is fp access disabled" check at a high level in the decode tree. To help in catching bugs where the access check was forgotten in some code path, we set this flag when the access check is done, and assert that it is set at the point where we actually touch the FP regs. This requires us to pass the DisasContext to the vec_reg_offset and fp_reg_offset functions. Signed-off-by: Peter Maydell --- target-arm/translate-a64.c | 74 +++++++++++++++++++++++++++++++--------------- target-arm/translate.h | 8 +++++ 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 987b0b4..7c0abc7 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -347,11 +347,29 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf) return v; } +/* We should have at some point before trying to access an FP register + * done the necessary access check, so assert that (a) we did the check + * and (b) we didn't then just plough ahead anyway if it failed. + *.Print the instruction pattern in the abort message so we can figure + * out what we need to fix if a user encounters this problem in the wild. + */ +static inline void assert_fp_access_checked(DisasContext *s) +{ +#ifdef CONFIG_DEBUG_TCG + if (unlikely(!s->fp_access_checked || !s->cpacr_fpen)) { + fprintf(stderr, "target-arm: FP access check missing for " + "instruction 0x%08x\n", s->insn); + abort(); + } +#endif +} + /* Return the offset into CPUARMState of an element of specified * size, 'element' places in from the least significant end of * the FP/vector register Qn. */ -static inline int vec_reg_offset(int regno, int element, TCGMemOp size) +static inline int vec_reg_offset(DisasContext *s, int regno, + int element, TCGMemOp size) { int offs = offsetof(CPUARMState, vfp.regs[regno * 2]); #ifdef HOST_WORDS_BIGENDIAN @@ -366,6 +384,7 @@ static inline int vec_reg_offset(int regno, int element, TCGMemOp size) #else offs += element * (1 << size); #endif + assert_fp_access_checked(s); return offs; } @@ -374,18 +393,20 @@ static inline int vec_reg_offset(int regno, int element, TCGMemOp size) * Dn, Sn, Hn or Bn). * (Note that this is not the same mapping as for A32; see cpu.h) */ -static inline int fp_reg_offset(int regno, TCGMemOp size) +static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size) { int offs = offsetof(CPUARMState, vfp.regs[regno * 2]); #ifdef HOST_WORDS_BIGENDIAN offs += (8 - (1 << size)); #endif + assert_fp_access_checked(s); return offs; } /* Offset of the high half of the 128 bit vector Qn */ -static inline int fp_reg_hi_offset(int regno) +static inline int fp_reg_hi_offset(DisasContext *s, int regno) { + assert_fp_access_checked(s); return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]); } @@ -399,7 +420,7 @@ static TCGv_i64 read_fp_dreg(DisasContext *s, int reg) { TCGv_i64 v = tcg_temp_new_i64(); - tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64)); + tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64)); return v; } @@ -407,7 +428,7 @@ static TCGv_i32 read_fp_sreg(DisasContext *s, int reg) { TCGv_i32 v = tcg_temp_new_i32(); - tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32)); + tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32)); return v; } @@ -415,8 +436,8 @@ static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v) { TCGv_i64 tcg_zero = tcg_const_i64(0); - tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64)); - tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg)); + tcg_gen_st_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64)); + tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(s, reg)); tcg_temp_free_i64(tcg_zero); } @@ -674,14 +695,14 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size) { /* This writes the bottom N bits of a 128 bit wide vector to memory */ TCGv_i64 tmp = tcg_temp_new_i64(); - tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64)); + tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64)); if (size < 4) { tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size); } else { TCGv_i64 tcg_hiaddr = tcg_temp_new_i64(); tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ); tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s)); - tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx)); + tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx)); tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8); tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ); tcg_temp_free_i64(tcg_hiaddr); @@ -714,8 +735,8 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) tcg_temp_free_i64(tcg_hiaddr); } - tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64)); - tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx)); + tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64)); + tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx)); tcg_temp_free_i64(tmplo); tcg_temp_free_i64(tmphi); @@ -737,7 +758,7 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx, int element, TCGMemOp memop) { - int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE); + int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE); switch (memop) { case MO_8: tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off); @@ -769,7 +790,7 @@ static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx, static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx, int element, TCGMemOp memop) { - int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE); + int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE); switch (memop) { case MO_8: tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off); @@ -796,7 +817,7 @@ static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx, static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx, int element, TCGMemOp memop) { - int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE); + int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE); switch (memop) { case MO_8: tcg_gen_st8_i64(tcg_src, cpu_env, vect_off); @@ -818,7 +839,7 @@ static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx, static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src, int destidx, int element, TCGMemOp memop) { - int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE); + int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE); switch (memop) { case MO_8: tcg_gen_st8_i32(tcg_src, cpu_env, vect_off); @@ -880,6 +901,9 @@ static void do_vec_ld(DisasContext *s, int destidx, int element, */ static inline bool fp_access_check(DisasContext *s) { + assert(!s->fp_access_checked); + s->fp_access_checked = true; + if (s->cpacr_fpen) { return true; } @@ -4738,9 +4762,9 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) /* 32 bit */ TCGv_i64 tmp = tcg_temp_new_i64(); tcg_gen_ext32u_i64(tmp, tcg_rn); - tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64)); + tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(s, rd, MO_64)); tcg_gen_movi_i64(tmp, 0); - tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd)); + tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd)); tcg_temp_free_i64(tmp); break; } @@ -4748,14 +4772,14 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) { /* 64 bit */ TCGv_i64 tmp = tcg_const_i64(0); - tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64)); - tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd)); + tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(s, rd, MO_64)); + tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd)); tcg_temp_free_i64(tmp); break; } case 2: /* 64 bit to top half. */ - tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd)); + tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd)); break; } } else { @@ -4764,15 +4788,15 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) switch (type) { case 0: /* 32 bit */ - tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32)); + tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32)); break; case 1: /* 64 bit */ - tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64)); + tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64)); break; case 2: /* 64 bits from top half */ - tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn)); + tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn)); break; } } @@ -5717,7 +5741,7 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn) tcg_rd = new_tmp_a64(s); for (i = 0; i < 2; i++) { - int foffs = i ? fp_reg_hi_offset(rd) : fp_reg_offset(rd, MO_64); + int foffs = i ? fp_reg_hi_offset(s, rd) : fp_reg_offset(s, rd, MO_64); if (i == 1 && !is_q) { /* non-quad ops clear high half of vector */ @@ -9055,6 +9079,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) s->insn = insn; s->pc += 4; + s->fp_access_checked = false; + switch (extract32(insn, 25, 4)) { case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */ unallocated_encoding(s); diff --git a/target-arm/translate.h b/target-arm/translate.h index 2adf0bc..a42e64d 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -31,6 +31,14 @@ typedef struct DisasContext { int aarch64; int current_pl; GHashTable *cp_regs; + /* Because unallocated encodings generate different exception syndrome + * information from traps due to FP being disabled, we can't do a single + * "is fp access disabled" check at a high level in the decode tree. + * To help in catching bugs where the access check was forgotten in some + * code path, we set this flag when the access check is done, and assert + * that it is set at the point where we actually touch the FP regs. + */ + bool fp_access_checked; #define TMP_A64_MAX 16 int tmp_a64_count; TCGv_i64 tmp_a64[TMP_A64_MAX];