qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Peter Crosthwaite" <peter.crosthwaite@xilinx.com>,
	patches@linaro.org, "Michael Matz" <matz@suse.de>,
	"Alexander Graf" <agraf@suse.de>,
	"Will Newton" <will.newton@linaro.org>,
	"Dirk Mueller" <dmueller@suse.de>,
	"Laurent Desnogues" <laurent.desnogues@gmail.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	kvmarm@lists.cs.columbia.edu,
	"Christoffer Dall" <christoffer.dall@linaro.org>,
	"Richard Henderson" <rth@twiddle.net>
Subject: [Qemu-devel] [PATCH v5 08/37] target-arm: A64: Add assertion that FP access was checked
Date: Fri, 28 Mar 2014 16:09:55 +0000	[thread overview]
Message-ID: <1396023024-2262-9-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1396023024-2262-1-git-send-email-peter.maydell@linaro.org>

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 <peter.maydell@linaro.org>
---
 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 2f67af3..b7cf907 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -353,11 +353,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
@@ -372,6 +390,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;
 }
 
@@ -380,18 +399,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]);
 }
 
@@ -405,7 +426,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;
 }
 
@@ -413,7 +434,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;
 }
 
@@ -421,8 +442,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);
 }
 
@@ -693,14 +714,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);
@@ -733,8 +754,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);
@@ -756,7 +777,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);
@@ -788,7 +809,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);
@@ -815,7 +836,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);
@@ -837,7 +858,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);
@@ -899,6 +920,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;
     }
@@ -4748,9 +4772,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;
         }
@@ -4758,14 +4782,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 {
@@ -4774,15 +4798,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;
         }
     }
@@ -5727,7 +5751,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 */
@@ -10557,6 +10581,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 4536f82..3f7d5ca 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -32,6 +32,14 @@ typedef struct DisasContext {
     int current_pl;
     GHashTable *cp_regs;
     uint64_t features; /* CPU features bits */
+    /* 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];
-- 
1.9.0

  parent reply	other threads:[~2014-03-28 16:27 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-28 16:09 [Qemu-devel] [PATCH v5 00/37] AArch64 system emulation Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 01/37] target-arm: Split out private-to-target functions into internals.h Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 02/37] target-arm: Implement AArch64 DAIF system register Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 03/37] target-arm: Define exception record for AArch64 exceptions Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 04/37] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 05/37] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 06/37] target-arm: Provide syndrome information for MMU faults Peter Maydell
2014-04-01  3:10   ` Peter Crosthwaite
2014-04-04 13:25     ` Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 07/37] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
2014-03-28 16:09 ` Peter Maydell [this message]
2014-04-01  3:24   ` [Qemu-devel] [PATCH v5 08/37] target-arm: A64: Add assertion that FP access was checked Peter Crosthwaite
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 09/37] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
2014-04-01  3:30   ` Peter Crosthwaite
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 10/37] target-arm: Add v8 mmu translation support Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 11/37] target-arm: Don't mention PMU in debug feature register Peter Maydell
2014-04-01 13:19   ` Christopher Covington
2014-04-01 13:43     ` Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 12/37] target-arm: A64: Implement DC ZVA Peter Maydell
2014-03-28 18:42   ` Richard Henderson
2014-04-04 14:12     ` Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 13/37] target-arm: Use dedicated CPU state fields for ARM946 access bit registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 14/37] target-arm: Implement AArch64 views of fault status and data registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 15/37] target-arm: Add AArch64 ELR_EL1 register Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 16/37] target-arm: Implement SP_EL0, SP_EL1 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 17/37] target-arm: Implement AArch64 SPSR_EL1 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 18/37] target-arm: Move arm_log_exception() into internals.h Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 19/37] target-arm: Implement AArch64 EL1 exception handling Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 20/37] target-arm: Implement ARMv8 MVFR registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 21/37] target-arm: Add Cortex-A57 processor Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 22/37] hw/arm/virt: Add support for Cortex-A57 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 23/37] target-arm: Implement AArch64 views of AArch32 ID registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 24/37] target-arm: Implement AArch64 view of CONTEXTIDR Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 25/37] target-arm: Implement AArch64 view of ACTLR Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 26/37] target-arm: Implement ISR_EL1 register Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 27/37] target-arm: Remove THUMB2EE feature from AArch64 'any' CPU Peter Maydell
2014-04-02 12:20   ` Peter Crosthwaite
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 28/37] target-arm: Don't expose wildcard ID register definitions for ARMv8 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 29/37] target-arm: Replace wildcarded cpreg definitions with precise ones " Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 30/37] target-arm: Implement auxiliary fault status registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 31/37] target-arm: Implement AArch64 address translation operations Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 32/37] target-arm: Implement RVBAR register Peter Maydell
2014-04-04  5:17   ` Peter Crosthwaite
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 33/37] target-arm: Implement Cortex-A57 implementation-defined system registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 34/37] target-arm: Implement CBAR for Cortex-A57 Peter Maydell
2014-04-04  5:32   ` Peter Crosthwaite
2014-04-04  8:25     ` Peter Maydell
2014-04-04 12:32       ` Peter Crosthwaite
2014-04-04 13:05         ` Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 35/37] target-arm: Make Cortex-A15 CBAR read-only Peter Maydell
2014-04-04  5:33   ` Peter Crosthwaite
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 36/37] target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 37/37] target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32 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=1396023024-2262-9-git-send-email-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=agraf@suse.de \
    --cc=alex.bennee@linaro.org \
    --cc=christoffer.dall@linaro.org \
    --cc=dmueller@suse.de \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=laurent.desnogues@gmail.com \
    --cc=matz@suse.de \
    --cc=patches@linaro.org \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=will.newton@linaro.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).