From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id C81DAC71150 for ; Wed, 28 Aug 2024 23:30:26 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5B5AD6B00AC; Wed, 28 Aug 2024 19:30:26 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 565B16B00AE; Wed, 28 Aug 2024 19:30:26 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 405F06B00AF; Wed, 28 Aug 2024 19:30:26 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 244C86B00AC for ; Wed, 28 Aug 2024 19:30:26 -0400 (EDT) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id CF1008021C for ; Wed, 28 Aug 2024 23:30:25 +0000 (UTC) X-FDA: 82503250410.06.D9AE2A9 Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf10.hostedemail.com (Postfix) with ESMTP id 1B5C0C0015 for ; Wed, 28 Aug 2024 23:30:23 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=EGbpbyv4; spf=pass (imf10.hostedemail.com: domain of broonie@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=broonie@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1724887736; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=wmxP7pCO2uFjstxxAElXkS7ECXHhMWQyyYjcz8ZtiHg=; b=JJiai+i2zZHVdnG9Y8mksxEEPL+ndAkAQAefVwa/Ip7ii/tj9BvEYGDEq6WmDSEpJmijvs 9XdBzwtHTFJZBnl5LQKvNqp0T6ECwjoY+3I3wM7tc2PUFAEqnLKOwxKtwCEB8T2DACAkWF iFl2LGG9ug7n8oXhFV9Rfp2zKBT+1Eo= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1724887736; a=rsa-sha256; cv=none; b=lJnTLNJH7W/+UlQtIFjJesL+rIdNk9U9FDvcJ0ng4eenPxzDYcW6nVqfYX1I6b6tB+IDmq IE5A8zdeySlO1Vz7DU3mRMqx9dCQfQph3GrAgc8rxuG4EaT5srgV/5dcfPlIbjGxrfX53t x6qhNQQvzPn48VC25wTLmp0MrC/qEwY= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=EGbpbyv4; spf=pass (imf10.hostedemail.com: domain of broonie@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=broonie@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 84FC1A43769; Wed, 28 Aug 2024 23:30:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A2B3C4CEC7; Wed, 28 Aug 2024 23:30:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724887823; bh=2VNGjU/LjnznPsbE00KIsk9FNHX2/dkkEbGz3eAYf9Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EGbpbyv4WmaXgKZCqumKPyIsLwisa4p7mEKO13j2syZLlNrAH9g6YgeI+XYsfeWAx iv73RpNfkPubQ79VXABGb9LN9yrFgMuT9p/XQSowHPDNEsA5AvlYBIM0PhrkWD2/va FN2KRGUNxUaOe4H8FP9/3PV0zNq4WC9M0jHBAM4P9axp2/2nO2UuuTBMSTghIwPlCi k59xoqhAhh8XvJEozC6oUdoaVCGwfUBrirPcPmoGaFtwelWPK81Nbvj7mWtePIO4z8 BbUyJnTt3kvGCZfFknZv0IP5a7doGkATT3Y1aq4xe01Yo2MVyuxxBbCAlPzpNgkfCV MCrac4X8KVvhg== From: Mark Brown Date: Thu, 29 Aug 2024 00:27:31 +0100 Subject: [PATCH v12 15/39] KVM: arm64: Manage GCS access and registers for guests MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240829-arm64-gcs-v12-15-42fec947436a@kernel.org> References: <20240829-arm64-gcs-v12-0-42fec947436a@kernel.org> In-Reply-To: <20240829-arm64-gcs-v12-0-42fec947436a@kernel.org> To: Catalin Marinas , Will Deacon , Jonathan Corbet , Andrew Morton , Marc Zyngier , Oliver Upton , James Morse , Suzuki K Poulose , Arnd Bergmann , Oleg Nesterov , Eric Biederman , Shuah Khan , "Rick P. Edgecombe" , Deepak Gupta , Ard Biesheuvel , Szabolcs Nagy , Kees Cook Cc: "H.J. Lu" , Paul Walmsley , Palmer Dabbelt , Albert Ou , Florian Weimer , Christian Brauner , Thiago Jung Bauermann , Ross Burton , Yury Khrustalev , Wilco Dijkstra , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, kvmarm@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, Mark Brown X-Mailer: b4 0.15-dev-37811 X-Developer-Signature: v=1; a=openpgp-sha256; l=8779; i=broonie@kernel.org; h=from:subject:message-id; bh=2VNGjU/LjnznPsbE00KIsk9FNHX2/dkkEbGz3eAYf9Y=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBmz7KELbM5DAIosOIiKrxUUZhb86v8KG+Ocbpo6yy3 SiwlwIqJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZs+yhAAKCRAk1otyXVSH0GhIB/ 4vV5nEnjExm4kBwq5k0nLMZj4mTVKRVNd+P5CXXaVZbtEoG4eI9Oss4k5Rf75FfAe36pv9XYwS7kvX EXmdSWvNTN6d6pykuRUgVcaNiVJTuKRSOIpC7fLN1becbNWV3bH5/g4i0n7oIbTTOowOBigwBSIYUK FcvUWQhBCITedD1zu6U8/8T0cliqG7DevqppZehzT98bR9BcpHMFddGxM6cGBMhNdWd5WnllFKryfn WR+73KYracqslCyUfSwZB2mG0Xbanv9yUHiughUBN01SA50l1xXEj6UsgHOm/yopIz8GWAzfKKRImh LkJrbUm+qMi/ND9p1sRATeidkZ2E3a X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-Rspamd-Queue-Id: 1B5C0C0015 X-Stat-Signature: ryhfa46mqxr6c14taesow8qz9bw651gn X-Rspamd-Server: rspam09 X-Rspam-User: X-HE-Tag: 1724887823-845985 X-HE-Meta: U2FsdGVkX1/QwgFAG3TqQzcLw5X1k1oCbHIthZ4CAg5lVKIrKZtQQIQrgPKXYcIWWRQkUbaJpDtj7zQs+g+XvH9n5g85hTomYxvN+xI5m6NKrlPrxjt/RhjNSPYK0dg53B1wFDb4vv0/e0l6XWaKZAAr1KxtRM+39wUDBOOkwQkoEeUcaYhmgPP9guMxG3xXpiimHuv/DTqCZgXKaelrXPtV5Z7TMHPp7AT7IHS4o2Uu3jFDEULqrpJ90Bb2LfhSKDLbMwnFWT1me/yY2eD3Y9NeToTXKsFRXn45XAhmj36qUw9kCAMeN/V1NXJzL0pGMRe4xILcCLoFJg9fhW25VrUh5mis5IMP7qvH6IcRpMAE9m6/DrsBmeGTjxuh9w6pCXtJZaVLmaN+2bZ8S8Tv4gV9uHxsXMjaPUk8dCQuqHzTYMC4vGGaemi5n4sk/Dd9irIy/D7y52zef5pk2Zao+vSLyuqFtSGch7TyvFdzMP2ezGrFrjYE0Z0cTtaW315iza6PQItGuj0Z9+MYuEQpONqHxegLpR7G1nH39ESdpqMsg90UWIw4Rd64K5ypc+Kiyw1jhOKKkY35v0WyPA0urxpuYxFK6mxX/7Wp1q2NCEdNZ85tK7FV5FNeK+fPfCeX3li7zoMDQZ8oYsLckNQfC0thS9DZQUGleMlu7rZD6tz9R+B5LnjozOOa6DrnPrvmmFY07y21htrulOCN/2nG03OtzNqganJIz+/l1G/uHCjfFLw/CKdNvrVHd21/pMbU5PqmC/bonGvecEFHasAt4IeRI9Gg50SV8Xfp5VZsfz+LnHZhjAwSZeD3dWaX/MiF6Yrcf182ayuwSfmUCzkw5oC6ptgPHQ6HG0ai2y2ABMpGZBsJ0tdyM60OyxHWj0+OkllmhyzggYi3Hzgx4sGL9zzWbmXF47hLVLc3bedlszJ7265gT+23lqYb3HiNMrJurj53PSqGEuZDIFaM90z smlo5uId fBWl2e3ajo5PPKbl264bibU01qjP3hPDTl3bCYm0Lr6kTVTFpsKRcitqzkCgcrsJ+QnRL/ipetI/nDvnlXfaXTdqCRB2CJ0uQKMs6Kd0lzN4iGeZaOEWRZPfbHAeOu0kqxrYYNkmbT/rwDwkQyh/rmV4lpnRQ4fLjVtoqDGsx+JEzRKw3Bd33EdNbML2MRtCdT7iYVWr2X1tF39ZdUuAq9lo/haITxG6JzeavMvMob4w95BWTW+pBIUEI3wjo0d57jvGBXyj69b5i3RT5UuIFLJeB6tUW2zmHee4/K+63UBfhn7INjxxMGd+V0zzV0MoNS8oNY0+RcsSB4/dE8bjLWis1S3u/bHTUhH/PP7wo/FRULXxXnvK2p8x1+tx5SGCAVmtbkaxcDOn2MMEbo4fq7xfc2cUHjP6wC6lC X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: GCS introduces a number of system registers for EL1 and EL0, on systems with GCS we need to context switch them and expose them to VMMs to allow guests to use GCS. In order to allow guests to use GCS we also need to configure HCRX_EL2.GCSEn, if this is not set GCS instructions will be noops and CHKFEAT will report GCS as disabled. Also enable fine grained traps for access to the GCS registers by guests which do not have the feature enabled. In order to allow userspace to control availability of the feature to guests we enable writability for only ID_AA64PFR1_EL1.GCS, this is a deliberately conservative choice to avoid errors due to oversights. Further fields should be made writable in future. Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 12 ++++++++ arch/arm64/include/asm/vncr_mapping.h | 2 ++ arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 49 ++++++++++++++++++++++++------ arch/arm64/kvm/sys_regs.c | 27 +++++++++++++++- 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index a33f5996ca9f..88d6a85a2844 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -446,6 +446,10 @@ enum vcpu_sysreg { GCR_EL1, /* Tag Control Register */ TFSRE0_EL1, /* Tag Fault Status Register (EL0) */ + /* Guarded Control Stack registers */ + GCSCRE0_EL1, /* Guarded Control Stack Control (EL0) */ + GCSPR_EL0, /* Guarded Control Stack Pointer (EL0) */ + /* 32bit specific registers. */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ @@ -517,6 +521,10 @@ enum vcpu_sysreg { VNCR(PIR_EL1), /* Permission Indirection Register 1 (EL1) */ VNCR(PIRE0_EL1), /* Permission Indirection Register 0 (EL1) */ + /* Guarded Control Stack registers */ + VNCR(GCSPR_EL1), /* Guarded Control Stack Pointer (EL1) */ + VNCR(GCSCR_EL1), /* Guarded Control Stack Control (EL1) */ + VNCR(HFGRTR_EL2), VNCR(HFGWTR_EL2), VNCR(HFGITR_EL2), @@ -1473,4 +1481,8 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val); (pa + pi + pa3) == 1; \ }) +#define kvm_has_gcs(k) \ + (system_supports_gcs() && \ + kvm_has_feat((k), ID_AA64PFR1_EL1, GCS, IMP)) + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm/vncr_mapping.h index df2c47c55972..5e83e6f579fd 100644 --- a/arch/arm64/include/asm/vncr_mapping.h +++ b/arch/arm64/include/asm/vncr_mapping.h @@ -88,6 +88,8 @@ #define VNCR_PMSIRR_EL1 0x840 #define VNCR_PMSLATFR_EL1 0x848 #define VNCR_TRFCR_EL1 0x880 +#define VNCR_GCSPR_EL1 0x8C0 +#define VNCR_GCSCR_EL1 0x8D0 #define VNCR_MPAM1_EL1 0x900 #define VNCR_MPAMHCR_EL2 0x930 #define VNCR_MPAMVPMV_EL2 0x938 diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index 4c0fdabaf8ae..ac29352e225a 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -16,6 +16,27 @@ #include #include +static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_cpu_context *ctxt) +{ + struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu; + + if (!vcpu) + vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt); + + return vcpu; +} + +static inline bool ctxt_has_gcs(struct kvm_cpu_context *ctxt) +{ + struct kvm_vcpu *vcpu; + + if (!cpus_have_final_cap(ARM64_HAS_GCS)) + return false; + + vcpu = ctxt_to_vcpu(ctxt); + return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64PFR1_EL1, GCS, IMP); +} + static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, MDSCR_EL1) = read_sysreg(mdscr_el1); @@ -25,16 +46,10 @@ static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, TPIDR_EL0) = read_sysreg(tpidr_el0); ctxt_sys_reg(ctxt, TPIDRRO_EL0) = read_sysreg(tpidrro_el0); -} - -static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_cpu_context *ctxt) -{ - struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu; - - if (!vcpu) - vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt); - - return vcpu; + if (ctxt_has_gcs(ctxt)) { + ctxt_sys_reg(ctxt, GCSPR_EL0) = read_sysreg_s(SYS_GCSPR_EL0); + ctxt_sys_reg(ctxt, GCSCRE0_EL1) = read_sysreg_s(SYS_GCSCRE0_EL1); + } } static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) @@ -79,6 +94,10 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) if (ctxt_has_s1pie(ctxt)) { ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); + if (ctxt_has_gcs(ctxt)) { + ctxt_sys_reg(ctxt, GCSPR_EL1) = read_sysreg_el1(SYS_GCSPR); + ctxt_sys_reg(ctxt, GCSCR_EL1) = read_sysreg_el1(SYS_GCSCR); + } } } ctxt_sys_reg(ctxt, ESR_EL1) = read_sysreg_el1(SYS_ESR); @@ -126,6 +145,11 @@ static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) { write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL0), tpidr_el0); write_sysreg(ctxt_sys_reg(ctxt, TPIDRRO_EL0), tpidrro_el0); + if (ctxt_has_gcs(ctxt)) { + write_sysreg_s(ctxt_sys_reg(ctxt, GCSPR_EL0), SYS_GCSPR_EL0); + write_sysreg_s(ctxt_sys_reg(ctxt, GCSCRE0_EL1), + SYS_GCSCRE0_EL1); + } } static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) @@ -157,6 +181,11 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) if (ctxt_has_s1pie(ctxt)) { write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR); write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0); + + if (ctxt_has_gcs(ctxt)) { + write_sysreg_el1(ctxt_sys_reg(ctxt, GCSPR_EL1), SYS_GCSPR); + write_sysreg_el1(ctxt_sys_reg(ctxt, GCSCR_EL1), SYS_GCSCR); + } } } write_sysreg_el1(ctxt_sys_reg(ctxt, ESR_EL1), SYS_ESR); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index c90324060436..4e820dd50414 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1645,6 +1645,15 @@ static unsigned int raz_visibility(const struct kvm_vcpu *vcpu, return REG_RAZ; } +static unsigned int gcs_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *r) +{ + if (kvm_has_gcs(vcpu->kvm)) + return 0; + + return REG_HIDDEN; +} + /* cpufeature ID register access trap handlers */ static bool access_id_reg(struct kvm_vcpu *vcpu, @@ -2362,7 +2371,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_AA64PFR0_EL1_GIC | ID_AA64PFR0_EL1_AdvSIMD | ID_AA64PFR0_EL1_FP), }, - ID_SANITISED(ID_AA64PFR1_EL1), + ID_WRITABLE(ID_AA64PFR1_EL1, ID_AA64PFR1_EL1_GCS), ID_UNALLOCATED(4,2), ID_UNALLOCATED(4,3), ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0), @@ -2446,6 +2455,13 @@ static const struct sys_reg_desc sys_reg_descs[] = { PTRAUTH_KEY(APDB), PTRAUTH_KEY(APGA), + { SYS_DESC(SYS_GCSCR_EL1), NULL, reset_val, GCSCR_EL1, 0, + .visibility = gcs_visibility }, + { SYS_DESC(SYS_GCSPR_EL1), NULL, reset_unknown, GCSPR_EL1, + .visibility = gcs_visibility }, + { SYS_DESC(SYS_GCSCRE0_EL1), NULL, reset_val, GCSCRE0_EL1, 0, + .visibility = gcs_visibility }, + { SYS_DESC(SYS_SPSR_EL1), access_spsr}, { SYS_DESC(SYS_ELR_EL1), access_elr}, @@ -2535,6 +2551,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { CTR_EL0_IDC_MASK | CTR_EL0_DminLine_MASK | CTR_EL0_IminLine_MASK), + { SYS_DESC(SYS_GCSPR_EL0), NULL, reset_unknown, GCSPR_EL0, + .visibility = gcs_visibility }, { SYS_DESC(SYS_SVCR), undef_access }, { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr, @@ -4560,6 +4578,9 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En; + + if (kvm_has_gcs(kvm)) + vcpu->arch.hcrx_el2 |= HCRX_EL2_GCSEn; } if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags)) @@ -4604,6 +4625,10 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 | HFGxTR_EL2_nPIR_EL1); + if (!kvm_has_gcs(kvm)) + kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nGCS_EL0 | + HFGxTR_EL2_nGCS_EL1); + if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, IMP)) kvm->arch.fgu[HAFGRTR_GROUP] |= ~(HAFGRTR_EL2_RES0 | HAFGRTR_EL2_RES1); -- 2.39.2