qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 08/19] target-arm: Don't handle c15_cpar changes via tb_flush()
Date: Mon, 29 Sep 2014 19:26:42 +0100	[thread overview]
Message-ID: <1412015213-22268-9-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1412015213-22268-1-git-send-email-peter.maydell@linaro.org>

At the moment we try to handle c15_cpar with the strategy of:
 * emit generated code which makes assumptions about its value
 * when the register value changes call tb_flush() to throw
   away the now-invalid generated code
This works because XScale CPUs are always uniprocessor, but
it's confusing because it suggests that the same approach can
be taken for other registers. It also means we do a tb_flush()
on CPU reset, which makes multithreaded linux-user binaries
even more likely to fail than would otherwise be the case.

Replace it with a combination of TB flags for the access
checks done on cp0/cp1 for the XScale and iwMMXt instructions,
plus a runtime check for cp2..cp13 coprocessor accesses.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1411056959-23070-1-git-send-email-peter.maydell@linaro.org
---
 target-arm/cpu.c       |  5 -----
 target-arm/cpu.h       |  9 +++++++++
 target-arm/helper.c    |  7 +------
 target-arm/op_helper.c | 11 +++++++++++
 target-arm/translate.c | 40 +++++++++++++++++++++-------------------
 target-arm/translate.h |  2 ++
 6 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 6ab0e03..248778d 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -173,11 +173,6 @@ static void arm_cpu_reset(CPUState *s)
     set_float_detect_tininess(float_tininess_before_rounding,
                               &env->vfp.standard_fp_status);
     tlb_flush(s, 1);
-    /* Reset is a state change for some CPUARMState fields which we
-     * bake assumptions about into translated code, so we need to
-     * tb_flush().
-     */
-    tb_flush(env);
 
 #ifndef CONFIG_USER_ONLY
     if (kvm_enabled()) {
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index fa6ae0a..7bd3af9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1224,6 +1224,11 @@ static inline bool arm_singlestep_active(CPUARMState *env)
 #define ARM_TBFLAG_SS_ACTIVE_MASK (1 << ARM_TBFLAG_SS_ACTIVE_SHIFT)
 #define ARM_TBFLAG_PSTATE_SS_SHIFT 19
 #define ARM_TBFLAG_PSTATE_SS_MASK (1 << ARM_TBFLAG_PSTATE_SS_SHIFT)
+/* We store the bottom two bits of the CPAR as TB flags and handle
+ * checks on the other bits at runtime
+ */
+#define ARM_TBFLAG_XSCALE_CPAR_SHIFT 20
+#define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 
 /* Bit usage when in AArch64 state */
 #define ARM_TBFLAG_AA64_EL_SHIFT    0
@@ -1258,6 +1263,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
     (((F) & ARM_TBFLAG_SS_ACTIVE_MASK) >> ARM_TBFLAG_SS_ACTIVE_SHIFT)
 #define ARM_TBFLAG_PSTATE_SS(F) \
     (((F) & ARM_TBFLAG_PSTATE_SS_MASK) >> ARM_TBFLAG_PSTATE_SS_SHIFT)
+#define ARM_TBFLAG_XSCALE_CPAR(F) \
+    (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 #define ARM_TBFLAG_AA64_EL(F) \
     (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
 #define ARM_TBFLAG_AA64_FPEN(F) \
@@ -1335,6 +1342,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                 *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
             }
         }
+        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
+                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
     }
 
     *cs_base = 0;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d246d36..dd9fca5 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1714,12 +1714,7 @@ static const ARMCPRegInfo omap_cp_reginfo[] = {
 static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
                               uint64_t value)
 {
-    value &= 0x3fff;
-    if (env->cp15.c15_cpar != value) {
-        /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
-        tb_flush(env);
-        env->cp15.c15_cpar = value;
-    }
+    env->cp15.c15_cpar = value & 0x3fff;
 }
 
 static const ARMCPRegInfo xscale_cp_reginfo[] = {
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index d0bcd97..25243bd 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -301,6 +301,17 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val)
 void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome)
 {
     const ARMCPRegInfo *ri = rip;
+
+    if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
+        && extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
+        env->exception.syndrome = syndrome;
+        raise_exception(env, EXCP_UDEF);
+    }
+
+    if (!ri->accessfn) {
+        return;
+    }
+
     switch (ri->accessfn(env, ri)) {
     case CP_ACCESS_OK:
         return;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2c0b1de..8a2994f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7001,22 +7001,18 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
     const ARMCPRegInfo *ri;
 
     cpnum = (insn >> 8) & 0xf;
-    if (arm_feature(env, ARM_FEATURE_XSCALE)
-	    && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
-	return 1;
-
-    /* First check for coprocessor space used for actual instructions */
-    switch (cpnum) {
-      case 0:
-      case 1:
-	if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-	    return disas_iwmmxt_insn(env, s, insn);
-	} else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-	    return disas_dsp_insn(env, s, insn);
-	}
-	return 1;
-    default:
-        break;
+
+    /* First check for coprocessor space used for XScale/iwMMXt insns */
+    if (arm_feature(env, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
+        if (extract32(s->c15_cpar, cpnum, 1) == 0) {
+            return 1;
+        }
+        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+            return disas_iwmmxt_insn(env, s, insn);
+        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+            return disas_dsp_insn(env, s, insn);
+        }
+        return 1;
     }
 
     /* Otherwise treat as a generic register access */
@@ -7049,9 +7045,12 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
             return 1;
         }
 
-        if (ri->accessfn) {
+        if (ri->accessfn ||
+            (arm_feature(env, ARM_FEATURE_XSCALE) && cpnum < 14)) {
             /* Emit code to perform further access permissions checks at
              * runtime; this may result in an exception.
+             * Note that on XScale all cp0..c13 registers do an access check
+             * call in order to handle c15_cpar.
              */
             TCGv_ptr tmpptr;
             TCGv_i32 tcg_syn;
@@ -7675,9 +7674,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
         } else if ((insn & 0x0e000f00) == 0x0c000100) {
             if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
                 /* iWMMXt register transfer.  */
-                if (env->cp15.c15_cpar & (1 << 1))
-                    if (!disas_iwmmxt_insn(env, s, insn))
+                if (extract32(s->c15_cpar, 1, 1)) {
+                    if (!disas_iwmmxt_insn(env, s, insn)) {
                         return;
+                    }
+                }
             }
         } else if ((insn & 0x0fe00000) == 0x0c400000) {
             /* Coprocessor double register transfer.  */
@@ -10942,6 +10943,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
     dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
     dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
     dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
+    dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
     dc->cp_regs = cpu->cp_regs;
     dc->current_pl = arm_current_pl(env);
     dc->features = env->features;
diff --git a/target-arm/translate.h b/target-arm/translate.h
index b90d275..85c6f9d 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -52,6 +52,8 @@ typedef struct DisasContext {
     bool is_ldex;
     /* True if a single-step exception will be taken to the current EL */
     bool ss_same_el;
+    /* Bottom two bits of XScale c15_cpar coprocessor access control reg */
+    int c15_cpar;
 #define TMP_A64_MAX 16
     int tmp_a64_count;
     TCGv_i64 tmp_a64[TMP_A64_MAX];
-- 
1.9.1

  parent reply	other threads:[~2014-09-29 18:27 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 02/19] target-arm: Implement handling of breakpoint firing Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 03/19] configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 04/19] hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 05/19] hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio() Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 06/19] hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 07/19] hw/input/tsc210x.c: Delete unused array tsc2101_rates Peter Maydell
2014-09-29 18:26 ` Peter Maydell [this message]
2014-09-29 18:26 ` [Qemu-devel] [PULL 09/19] target-arm: Add HCR_EL2 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 10/19] target-arm: Add SCR_EL3 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 11/19] target-arm: A64: Refactor aarch64_cpu_do_interrupt Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 12/19] target-arm: Break out exception masking to a separate func Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 13/19] target-arm: Don't take interrupts targeting lower ELs Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 14/19] target-arm: A64: Correct updates to FAR and ESR on exceptions Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 15/19] target-arm: A64: Emulate the HVC insn Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 16/19] target-arm: Add a Hypervisor Trap exception type Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 17/19] target-arm: A64: Emulate the SMC insn Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 18/19] target-arm: Add IRQ and FIQ routing to EL2 and 3 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 19/19] target-arm: Add support for VIRQ and VFIQ Peter Maydell
2014-09-30 10:52 ` [Qemu-devel] [PULL 00/19] target-arm queue 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=1412015213-22268-9-git-send-email-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.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).