From nobody Tue Feb 10 09:59:50 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1629897620105424.97175884923456; Wed, 25 Aug 2021 06:20:20 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.172241.314206 (Exim 4.92) (envelope-from ) id 1mIsoz-0003PX-Av; Wed, 25 Aug 2021 13:20:01 +0000 Received: by outflank-mailman (output) from mailman id 172241.314206; Wed, 25 Aug 2021 13:20:01 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1mIsoz-0003PI-6t; Wed, 25 Aug 2021 13:20:01 +0000 Received: by outflank-mailman (input) for mailman id 172241; Wed, 25 Aug 2021 13:19:59 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1mIsox-0001JY-5H for xen-devel@lists.xenproject.org; Wed, 25 Aug 2021 13:19:59 +0000 Received: from foss.arm.com (unknown [217.140.110.172]) by us1-rack-iad1.inumbo.com (Halon) with ESMTP id d5f3d2c7-5089-4218-9b83-3aed8e65be03; Wed, 25 Aug 2021 13:19:50 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id CE6A2106F; Wed, 25 Aug 2021 06:19:49 -0700 (PDT) Received: from e109506.cambridge.arm.com (e109506.cambridge.arm.com [10.1.199.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EE8A23F5A1; Wed, 25 Aug 2021 06:19:48 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: d5f3d2c7-5089-4218-9b83-3aed8e65be03 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Volodymyr Babchuk Subject: [PATCH v3 7/7] xen/arm: Sanitize CTR_EL0 and emulate it if needed Date: Wed, 25 Aug 2021 14:18:31 +0100 Message-Id: X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-ZM-MESSAGEID: 1629897621976100001 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Sanitize CTR_EL0 value between cores. In most cases different values will taint Xen but if different i-cache policies are found, we choose the one which will be compatible between all cores in terms of invalidation/data cache flushing strategy. In this case we need to activate the TID2 bit in HCR to emulate the TCR_EL0 register for guests. This patch is not activating TID2 bit all the time to limit the overhead when possible. When TID2 is activate we also need to emulate the CCSIDR, CSSELR and CLIDR registers which is done here for both 32 and 64bit versions of the registers. Add CTR register field definitions using Linux value and define names and use the opportunity to rename CTR_L1Ip to use an upper case name instead. The patch is also defining ICACHE_POLICY_xxx instead of only having CTR_L1IP_xxx. Code using those defines is also updated by this patch (arm32 setup). On most big/LITTLE platforms this patch will activate TID2 and emulate VIPT type of i-cache for all cores (as most LITTLE cores are VIPT where big ones are PIPT). This is the case for example on Juno boards. On platforms with only the same type of cores, this patch should not modify the behaviour. Signed-off-by: Bertrand Marquis --- Changes in v3: none Change in v2: Patch introduced in v2 --- xen/arch/arm/arm64/cpufeature.c | 19 +++++++++++--- xen/arch/arm/arm64/vsysreg.c | 40 ++++++++++++++++++++++++++++ xen/arch/arm/cpufeature.c | 2 ++ xen/arch/arm/domain.c | 8 ++++++ xen/arch/arm/setup.c | 2 +- xen/arch/arm/vcpreg.c | 45 ++++++++++++++++++++++++++++++++ xen/include/asm-arm/arm64/hsr.h | 6 +++++ xen/include/asm-arm/cpufeature.h | 11 ++++++++ xen/include/asm-arm/processor.h | 18 ++++++++++--- 9 files changed, 143 insertions(+), 8 deletions(-) diff --git a/xen/arch/arm/arm64/cpufeature.c b/xen/arch/arm/arm64/cpufeatur= e.c index b1936ef1d6..334d590ba0 100644 --- a/xen/arch/arm/arm64/cpufeature.c +++ b/xen/arch/arm/arm64/cpufeature.c @@ -275,9 +275,6 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = =3D { ARM64_FTR_END, }; =20 -#if 0 -/* TODO: use this to sanitize the cache line size among cores */ - static const struct arm64_ftr_bits ftr_ctr[] =3D { ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DIC_SHIFT, 1,= 1), @@ -294,7 +291,6 @@ static const struct arm64_ftr_bits ftr_ctr[] =3D { ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IMINLINE_SHIF= T, 4, 0), ARM64_FTR_END, }; -#endif =20 static const struct arm64_ftr_bits ftr_id_mmfr0[] =3D { S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_INNERSH= R_SHIFT, 4, 0xf), @@ -510,6 +506,12 @@ static s64 arm64_ftr_safe_value(const struct arm64_ftr= _bits *ftrp, s64 new, * End of imported linux structures and code */ =20 +/* + * This is set to true if we have different type of i-caches on cores + * and used to activate TID2 bit to emulate CTR_EL0 register for guests + */ +bool mismatch_cache_type =3D false; + static void sanitize_reg(u64 *cur_reg, u64 new_reg, const char *reg_name, const struct arm64_ftr_bits *ftrp) { @@ -600,6 +602,15 @@ void update_system_features(const struct cpuinfo_arm *= new) */ SANITIZE_REG(dczid, 0, dczid); =20 + SANITIZE_REG(ctr, 0, ctr); + + /* + * If CTR is different among cores, set mismatch_cache_type to activate + * TID2 bit in HCR and emulate CTR register access for guests. + */ + if ( system_cpuinfo.ctr.bits[0] !=3D new->ctr.bits[0] ) + mismatch_cache_type =3D true; + if ( cpu_feature64_has_el0_32(&system_cpuinfo) ) { SANITIZE_ID_REG(pfr32, 0, pfr0); diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c index 887266dd46..17212bd7ae 100644 --- a/xen/arch/arm/arm64/vsysreg.c +++ b/xen/arch/arm/arm64/vsysreg.c @@ -341,6 +341,46 @@ void do_sysreg(struct cpu_user_regs *regs, case HSR_SYSREG(3,0,c0,c7,7): return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 1); =20 + /* + * HCR_EL2.TID2 + * + * registers related to cache detection + */ + case HSR_SYSREG_CTR_EL0: + return handle_ro_read_val(regs, regidx, hsr.sysreg.read, hsr, 1, + system_cpuinfo.ctr.bits[0]); + + case HSR_SYSREG_CLIDR_EL1: + return handle_ro_read_val(regs, regidx, hsr.sysreg.read, hsr, 1, + READ_SYSREG(CLIDR_EL1)); + + case HSR_SYSREG_CSSELR_EL1: + if ( psr_mode_is_user(regs) ) + return inject_undef_exception(regs, hsr); + if ( hsr.sysreg.read ) + set_user_reg(regs, regidx, v->arch.csselr); + else + v->arch.csselr =3D get_user_reg(regs, regidx); + break; + + case HSR_SYSREG_CCSIDR_EL1: + if ( psr_mode_is_user(regs) ) + return inject_undef_exception(regs, hsr); + if ( hsr.sysreg.read ) + { + /* we need to set CSSELR and do the read of CCSIDR atomically = */ + WRITE_SYSREG(v->arch.csselr, CSSELR_EL1); + set_user_reg(regs, regidx, READ_SYSREG(CCSIDR_EL1)); + } + break; + + case HSR_SYSREG_CCSIDR2_EL1: + /* + * This would need to return a properly defined value if CCIDX is + * implemented in the processor + */ + return inject_undef_exception(regs, hsr); + /* * HCR_EL2.TIDCP * diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c index 113f20f601..6e51f530a8 100644 --- a/xen/arch/arm/cpufeature.c +++ b/xen/arch/arm/cpufeature.c @@ -127,6 +127,8 @@ void identify_cpu(struct cpuinfo_arm *c) =20 c->dczid.bits[0] =3D READ_SYSREG(DCZID_EL0); =20 + c->ctr.bits[0] =3D READ_SYSREG(CTR_EL0); + aarch32_el0 =3D cpu_feature64_has_el0_32(c); #endif =20 diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 19c756ac3d..7a97fde3e7 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -585,6 +585,14 @@ int arch_vcpu_create(struct vcpu *v) v->arch.vmpidr =3D MPIDR_SMP | vcpuid_to_vaffinity(v->vcpu_id); =20 v->arch.hcr_el2 =3D get_default_hcr_flags(); +#ifdef CONFIG_ARM64 + /* + * Only activated TID2 to catch access to CTR_EL0 if the platform has = some + * mismatching i-cache types among cores + */ + if ( mismatch_cache_type ) + v->arch.hcr_el2 |=3D HCR_TID2; +#endif =20 if ( (rc =3D vcpu_vgic_init(v)) !=3D 0 ) goto fail; diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 3798c5ade0..33b7bfb59c 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -627,7 +627,7 @@ static void __init setup_mm(void) panic("No memory bank\n"); =20 /* We only supports instruction caches implementing the IVIPT extensio= n. */ - if ( ((ctr >> CTR_L1Ip_SHIFT) & CTR_L1Ip_MASK) =3D=3D CTR_L1Ip_AIVIVT ) + if ( ((ctr >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK) =3D=3D ICACHE_POLICY_AI= VIVT ) panic("AIVIVT instruction cache not supported\n"); =20 init_pdx(); diff --git a/xen/arch/arm/vcpreg.c b/xen/arch/arm/vcpreg.c index 33259c4194..5ffed96ded 100644 --- a/xen/arch/arm/vcpreg.c +++ b/xen/arch/arm/vcpreg.c @@ -361,6 +361,51 @@ void do_cp15_32(struct cpu_user_regs *regs, const unio= n hsr hsr) HSR_CPREG32_TID3_CASES(c7): return handle_ro_raz(regs, regidx, cp32.read, hsr, 1); =20 +#ifdef CONFIG_ARM64 + /* + * HCR_EL2.TID2 + * + * registers related to cache detection + * Only supported on arm64 as we do not sanitize cpuinfo on arm32 so we + * do not need to emulate those. + */ + case HSR_CPREG32(CTR): + return handle_ro_read_val(regs, regidx, cp32.read, hsr, 1, + system_cpuinfo.ctr.bits[0]); + + case HSR_CPREG32(CLIDR): + return handle_ro_read_val(regs, regidx, cp32.read, hsr, 1, + READ_SYSREG(CLIDR_EL1)); + + case HSR_CPREG32(CSSELR): + if ( psr_mode_is_user(regs) ) + return inject_undef_exception(regs, hsr); + if ( cp32.read ) + set_user_reg(regs, regidx, v->arch.csselr); + else + v->arch.csselr =3D get_user_reg(regs, regidx); + break; + + case HSR_CPREG32(CCSIDR): + if ( psr_mode_is_user(regs) ) + return inject_undef_exception(regs, hsr); + if ( cp32.read ) + { + /* we need to set CSSELR and do the read of CCSIDR atomically = */ + WRITE_SYSREG(v->arch.csselr, CSSELR_EL1); + set_user_reg(regs, regidx, READ_SYSREG(CCSIDR_EL1)); + } + break; + + case HSR_CPREG32(CCSIDR2): + /* + * This would need to return a properly defined value if CCIDX is + * implemented in the processor + */ + return inject_undef_exception(regs, hsr); + +#endif + /* * HCR_EL2.TIDCP * diff --git a/xen/include/asm-arm/arm64/hsr.h b/xen/include/asm-arm/arm64/hs= r.h index e691d41c17..c33980e4e5 100644 --- a/xen/include/asm-arm/arm64/hsr.h +++ b/xen/include/asm-arm/arm64/hsr.h @@ -147,6 +147,12 @@ #define HSR_SYSREG_ID_AA64AFR1_EL1 HSR_SYSREG(3,0,c0,c5,5) #define HSR_SYSREG_ID_AA64ZFR0_EL1 HSR_SYSREG(3,0,c0,c4,4) =20 +#define HSR_SYSREG_CTR_EL0 HSR_SYSREG(3,3,c0,c0,1) +#define HSR_SYSREG_CLIDR_EL1 HSR_SYSREG(3,1,c0,c0,1) +#define HSR_SYSREG_CSSELR_EL1 HSR_SYSREG(3,2,c0,c0,0) +#define HSR_SYSREG_CCSIDR_EL1 HSR_SYSREG(3,1,c0,c0,0) +#define HSR_SYSREG_CCSIDR2_EL1 HSR_SYSREG(3,1,c0,c0,2) + #endif /* __ASM_ARM_ARM64_HSR_H */ =20 /* diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeat= ure.h index 5219fd3bab..ca6e827fcb 100644 --- a/xen/include/asm-arm/cpufeature.h +++ b/xen/include/asm-arm/cpufeature.h @@ -267,6 +267,14 @@ struct cpuinfo_arm { register_t bits[1]; } dczid; =20 + /* + * CTR is only used to check for different cache types or policies and + * taint Xen in this case + */ + struct { + register_t bits[1]; + } ctr; + #endif =20 /* @@ -339,6 +347,9 @@ extern struct cpuinfo_arm system_cpuinfo; extern void identify_cpu(struct cpuinfo_arm *); =20 #ifdef CONFIG_ARM_64 + +extern bool mismatched_cache_type; + extern void update_system_features(const struct cpuinfo_arm *); #else static inline void update_system_features(const struct cpuinfo_arm *cpuinf= o) diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processo= r.h index 2577e9a244..8c9843e12b 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -7,9 +7,21 @@ #include =20 /* CTR Cache Type Register */ -#define CTR_L1Ip_MASK 0x3 -#define CTR_L1Ip_SHIFT 14 -#define CTR_L1Ip_AIVIVT 0x1 +#define CTR_L1IP_MASK 0x3 +#define CTR_L1IP_SHIFT 14 +#define CTR_DMINLINE_SHIFT 16 +#define CTR_IMINLINE_SHIFT 0 +#define CTR_IMINLINE_MASK 0xf +#define CTR_ERG_SHIFT 20 +#define CTR_CWG_SHIFT 24 +#define CTR_CWG_MASK 15 +#define CTR_IDC_SHIFT 28 +#define CTR_DIC_SHIFT 29 + +#define ICACHE_POLICY_VPIPT 0 +#define ICACHE_POLICY_AIVIVT 1 +#define ICACHE_POLICY_VIPT 2 +#define ICACHE_POLICY_PIPT 3 =20 /* MIDR Main ID Register */ #define MIDR_REVISION_MASK 0xf --=20 2.17.1