From patchwork Thu Sep 18 16:15:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 37593 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-we0-f198.google.com (mail-we0-f198.google.com [74.125.82.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 685152054E for ; Thu, 18 Sep 2014 16:17:08 +0000 (UTC) Received: by mail-we0-f198.google.com with SMTP id p10sf745093wes.1 for ; Thu, 18 Sep 2014 09:17:07 -0700 (PDT) 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:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=xY/+kEUJZ1uV0mVzvVSrF9G1L1ZtV7IJFjLeOXfHLKA=; b=GNasPmgNf5VIKO2pgTMLkdMXGKTd9IK84TvZWCKhlvBGjUN3RLGZvyPxISaoBsiett nOiqaH05Td1Olyc37XxvlzpS5YpmYTdxwh8rlA7NjcbczZsL9B5e61NoEJ5woeunxdTT tldmFol+Zxre9F+Lo26vlN0GX0L6ak3pk1ubnBnbN3v33HNgB7kkzpjiSd9IiUDYDuiM xnPXmdO83d0XenIU+oTCVhusHEErZH6zE2wOJfOIPHbIPUaMbSrlToHJcbov2fMZjFcQ g6Sx0F4vsU94Ztv0unJFtRAvvdmG9qrWY8uF4TXd22T0KRBjvg0HJpq1RyfafHi/klMz nl1Q== X-Gm-Message-State: ALoCoQlR29E06I0FrJYwO4n747Rhs29vdexpBZWuBzg4NGuOldYNxiKq58RDKdr9WTfGCCJGaEsz X-Received: by 10.112.92.14 with SMTP id ci14mr63018lbb.23.1411057027464; Thu, 18 Sep 2014 09:17:07 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.7.7 with SMTP id f7ls241535laa.64.gmail; Thu, 18 Sep 2014 09:17:07 -0700 (PDT) X-Received: by 10.112.183.233 with SMTP id ep9mr811868lbc.56.1411057027175; Thu, 18 Sep 2014 09:17:07 -0700 (PDT) Received: from mail-lb0-f173.google.com (mail-lb0-f173.google.com [209.85.217.173]) by mx.google.com with ESMTPS id iy10si4093447lbc.101.2014.09.18.09.17.07 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 18 Sep 2014 09:17:07 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.173 as permitted sender) client-ip=209.85.217.173; Received: by mail-lb0-f173.google.com with SMTP id w7so1489713lbi.18 for ; Thu, 18 Sep 2014 09:17:07 -0700 (PDT) X-Received: by 10.152.246.6 with SMTP id xs6mr847166lac.56.1411057026995; Thu, 18 Sep 2014 09:17:06 -0700 (PDT) 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.112.130.169 with SMTP id of9csp789904lbb; Thu, 18 Sep 2014 09:17:06 -0700 (PDT) X-Received: by 10.195.17.170 with SMTP id gf10mr5547638wjd.111.1411057026370; Thu, 18 Sep 2014 09:17:06 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id cj7si32502851wjc.167.2014.09.18.09.17.06 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 18 Sep 2014 09:17:06 -0700 (PDT) Received-SPF: none (google.com: pm215@archaic.org.uk does not designate permitted sender hosts) client-ip=81.2.115.146; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1XUeND-00060Z-UT; Thu, 18 Sep 2014 17:15:59 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Richard Henderson Subject: [PATCH] target-arm: Don't handle c15_cpar changes via tb_flush() Date: Thu, 18 Sep 2014 17:15:59 +0100 Message-Id: <1411056959-23070-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.173 as permitted sender) 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: , 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 --- Ccing Alex because I know he'll be happy to see that tb_flush disappear from the reset function :-) 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 7ea12bd..39b8d4a 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 d1e1ccb..01e9434 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1223,6 +1223,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 @@ -1257,6 +1262,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) \ @@ -1334,6 +1341,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 ece9673..b998775 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 b956216..1f42b24 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];