From patchwork Tue Jun 25 14:57:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 13711439 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 91110C2BBCA for ; Tue, 25 Jun 2024 15:02:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 1D7C26B007B; Tue, 25 Jun 2024 11:02:46 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 187036B0082; Tue, 25 Jun 2024 11:02:46 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 001556B00A7; Tue, 25 Jun 2024 11:02:45 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id D66076B007B for ; Tue, 25 Jun 2024 11:02:45 -0400 (EDT) Received: from smtpin23.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 574E31601AC for ; Tue, 25 Jun 2024 15:02:45 +0000 (UTC) X-FDA: 82269727890.23.4273518 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by imf18.hostedemail.com (Postfix) with ESMTP id CB2E91C00CD for ; Tue, 25 Jun 2024 15:02:16 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=lWB+uD0P; spf=pass (imf18.hostedemail.com: domain of broonie@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=broonie@kernel.org; dmarc=pass (policy=none) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1719327729; 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=EYV+u0n4owJTVnrCnnx5V8EfrF/8bv3xG6MPSWuL/8M=; b=TvGXwt5iu86hz+4lOZrsN2iHxNxlmwH/268DDT4mMUtJgWiXKbyoP7zS1g0WwYWIPQGRoZ LahsT+8QYbSRW8tYOmAzWi+D2rpYm2q1q5a6rubfq/EYVG54/Iw9wJO6z0bNwAHKT1hrf8 Agpu7DxMfDY6+1sFXEKHTFYhOMsxxxE= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=lWB+uD0P; spf=pass (imf18.hostedemail.com: domain of broonie@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=broonie@kernel.org; dmarc=pass (policy=none) header.from=kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1719327729; a=rsa-sha256; cv=none; b=SoIumLkTlvAhG4GByrMANMrYpgISmpExU6U4HyTvXtPXweXc6mxko4ELZDQTPoQiHkApkt 9Jc/FkAAmruVKzWrRyWiiOeyGydkzVFQ5IYZmlEQKyrC+/YfJ4VXmyi35IYdKcBSSsoCR6 bmrKxgBoevWlAnmPTCpuZK9yGCyPX7w= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id D9878CE1AD3; Tue, 25 Jun 2024 15:02:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 46220C4AF0C; Tue, 25 Jun 2024 15:02:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719327732; bh=xFEBkbQzN0IGx0Wur4TK4R13m6HUYLs3KSs1WTNlE3k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lWB+uD0P+CZjn0D3gIAi3l0wU12UJryATRoPFYQtAME5DuHfW1K9pv1JUDN+Lhumu cVyY7Tmc3evtv7bmt7yv1Hy9kKinKs+K0cVYKH7c8T6q1IihAZNe6QC3B4U8rzozVZ 0UO2+IFvCxXWoKhdNUHq+doeb7GJimmPC3Z+RcjSB+xKVxqHtUlcF7X8vfCvqVZC2E KJ/DF2f+Lei3CvZlWp5lyi5slixonkkPt2PZ5BIsQpcHYmMeGkX20gmOMjL4uX52PK e+IcuGz91DS/akfrs2Sj9xekORyI+T4p5xB0nWEEVsIpq2hGccUqOFjR2uEqHZsA1G myPT1Px2w/Cgg== From: Mark Brown Date: Tue, 25 Jun 2024 15:57:41 +0100 Subject: [PATCH v9 13/39] KVM: arm64: Manage GCS registers for guests MIME-Version: 1.0 Message-Id: <20240625-arm64-gcs-v9-13-0f634469b8f0@kernel.org> References: <20240625-arm64-gcs-v9-0-0f634469b8f0@kernel.org> In-Reply-To: <20240625-arm64-gcs-v9-0-0f634469b8f0@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 , 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.14-dev-d4707 X-Developer-Signature: v=1; a=openpgp-sha256; l=7774; i=broonie@kernel.org; h=from:subject:message-id; bh=xFEBkbQzN0IGx0Wur4TK4R13m6HUYLs3KSs1WTNlE3k=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBmett8m5SYHux/E6PwvC/oBmSfOioYLmK8C9wuf+Gt ttHfrYSJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZnrbfAAKCRAk1otyXVSH0LNcB/ sE9kOsJaxY+fNfIdAyx39PauEcgMwlrnb6xtbVyGoccy9lGhVAF/xvD3pVrB6J00a0MW81xOuUR/Lp axWcRu/lwnABdEA8tzhxXxoxlnCjkMYGQKtbtmha8MgBDK6Lf8gpvsjYL1JRZzhiWpj4MWhanRZHyi N2StFGm8sSC6BiCW2P5SLJGc8Jv6gdby1NcFsl9ycBvme+gnJ1AIHghOUJvvDLk8zjYCvri6btuPKN B5DQWdwsHE+YzGYUK6aSI/JqJ6qurYeTypfyG7gzSUJL+rn73PcOM7GFB18XxrdiLjBXjKhYo1zUb+ rKdfxTqYaakV3i/NZpXXEYO/NqmQ1o X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-Rspamd-Server: rspam11 X-Rspamd-Queue-Id: CB2E91C00CD X-Stat-Signature: c5kaqh8575sq8nfs5mqj1n8nojkounxb X-Rspam-User: X-HE-Tag: 1719327736-483090 X-HE-Meta: U2FsdGVkX19OucpZ5KSuisyvBURmsWPnL87PnSAPcm3okt3zmU0V/XE7E8+hCIYvElgpLdf/y5lqBRTCxUEVtM5xWldUCknpZ0YQ8MosjVZzeilyl+50nTMNg7UvRiXg4r+bwt7ysbIcj5o99K11byyYSHn09Yy7y4a5rkuSVroPpbO8BBFOg4q7I5OTq1h5pREfz0X2rohJsM/amL1bITG5v8RNdh67o6zLBe2RtP8lgRB34H/v6+dMq3OWz8ce25T1PTpmz0nf6HNRBlD2VPCPHwa1dbmS6Cg3sZWv9pM16wq4Q8yv/HgRzLntF1hYWx4aZb0P8KWJkc72EhIdeomS0SafgBmLzsTAhuHLNvqdJejxEI0gBjMBQ4axOmWu8LnrLCg4A7ZV6taSc+XtuvcHGrSZzxVOacjWkf2KR5sLa9+HBwfEpCMxRTVNCoFacjZ5isK6Mij+RlRbVIRew1GOt486ph3n4w4VUhYjQmHJMOfKnMImc78VvqYoK62o5taNYPhQ+Kx4ZY8XWAk/j8BTkN9CNBFlFNRl9wFW5IJvPfGxSBxOzKeTdFMwKle71S18/XFJ1+elaa3qpMOvGjbaMocY2Z+AfVLrQqxoLLCavWfQYGb+1uJENdczkAtgFunDLklh7OUCZ+Eq6qkpw/J31ryK99A0xuwROmAHa2SIt1C9bCAbisYLsXmRMg0jN8QfTXbC/m1zfa+Wn2EGkMbsMyntb9gTIQYRuQp9p9RF81jXwpr/dzJImqjk1J+K+VgihFTqLqAueU2v4UTkzZNbMgXsp0/C7OJw8u+5i0nJ0IW1ObiTVZU/QnKrFC2/LCQ8N+Sf8gkgRbyXYJl6PRNR3c4BHJyQs76e5Mam0Wb8qLkGObJThsT2v3S7u+A79Wt34SaXHyLVUPFJUxlg4XKodw3N3SbVTnbKPgJ6PzWCwLAU8QU9mafwsJSUUtzvd8GOJTHUk5Bit+XW+7d /bHKtfb+ vle7xmhjsHkkyCrS5fJN9cA8fJSI3ASpVTv2h209yvLRy8udojaPPnj51cwNd9bPJbSOqen6QT5Hl/nYtO0KM1Qyxb828CFqVYQuiPGDAU1H12bI9oJTgP9nP9eqHhSB8ZXqfsIJMzTLSGNqvqn5usKclkwR25cqA+o87k1ejpH1Wb/nRfmT2K+tbi2hnDXCYNQ6EWx0c/2598v0jaRVliNZeuAPtJ2bana6F1ppt9gd1fKL9uN5Qr7a7nM4mP0H1R9Jzx1qMrwCsui1EtJu7VBh56TtvG6H3WvKIEU2xVMn+fpo+c/GoSM5DAKjHNobkCX5ygB2Qch9mfPIhBZYD85hEI3P5TY48djvvyznW7W7i7kW9BHi91PdJvxE25Ws3oFGZ 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, as well as describe their fine grained traps to nested virtualisation. Traps are already disabled. Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 14 +++++++++ arch/arm64/include/asm/vncr_mapping.h | 2 ++ arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 48 +++++++++++++++++++++++------- arch/arm64/kvm/sys_regs.c | 25 +++++++++++++++- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 36b8e97bf49e..316fb412f355 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -411,6 +411,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 */ @@ -481,6 +485,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), @@ -1343,6 +1351,12 @@ static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature) #define kvm_vcpu_initialized(v) vcpu_get_flag(vcpu, VCPU_INITIALIZED) +static inline bool has_gcs(void) +{ + return IS_ENABLED(CONFIG_ARM64_GCS) && + cpus_have_final_cap(ARM64_HAS_GCS); +} + int kvm_trng_call(struct kvm_vcpu *vcpu); #ifdef CONFIG_KVM extern phys_addr_t hyp_mem_base; 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 4be6a7fa0070..b20212d80e9b 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,8 @@ 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); } static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) @@ -80,6 +93,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) ctxt_sys_reg(ctxt, PAR_EL1) = read_sysreg_par(); ctxt_sys_reg(ctxt, TPIDR_EL1) = read_sysreg(tpidr_el1); + 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, GCSCRE0_EL1) = read_sysreg_s(SYS_GCSCRE0_EL1); + } + if (ctxt_has_mte(ctxt)) { ctxt_sys_reg(ctxt, TFSR_EL1) = read_sysreg_el1(SYS_TFSR); ctxt_sys_reg(ctxt, TFSRE0_EL1) = read_sysreg_s(SYS_TFSRE0_EL1); @@ -113,6 +132,8 @@ 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); } static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) @@ -156,6 +177,13 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1), par_el1); write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1), tpidr_el1); + 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_s(ctxt_sys_reg(ctxt, GCSCRE0_EL1), + SYS_GCSCRE0_EL1); + } + if (ctxt_has_mte(ctxt)) { write_sysreg_el1(ctxt_sys_reg(ctxt, TFSR_EL1), SYS_TFSR); write_sysreg_s(ctxt_sys_reg(ctxt, TFSRE0_EL1), SYS_TFSRE0_EL1); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 22b45a15d068..cf068dcfbd49 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2015,6 +2015,23 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu, .visibility = mte_visibility, \ } +static unsigned int gcs_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + if (has_gcs()) + return 0; + + return REG_HIDDEN; +} + +#define GCS_REG(name) { \ + SYS_DESC(SYS_##name), \ + .access = undef_access, \ + .reset = reset_unknown, \ + .reg = name, \ + .visibility = gcs_visibility, \ +} + static unsigned int el2_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { @@ -2306,7 +2323,8 @@ 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_RES0 | + ID_AA64PFR1_EL1_BT)), ID_UNALLOCATED(4,2), ID_UNALLOCATED(4,3), ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0), @@ -2390,6 +2408,10 @@ static const struct sys_reg_desc sys_reg_descs[] = { PTRAUTH_KEY(APDB), PTRAUTH_KEY(APGA), + GCS_REG(GCSCR_EL1), + GCS_REG(GCSPR_EL1), + GCS_REG(GCSCRE0_EL1), + { SYS_DESC(SYS_SPSR_EL1), access_spsr}, { SYS_DESC(SYS_ELR_EL1), access_elr}, @@ -2476,6 +2498,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_SMIDR_EL1), undef_access }, { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 }, { SYS_DESC(SYS_CTR_EL0), access_ctr }, + GCS_REG(GCSPR_EL0), { SYS_DESC(SYS_SVCR), undef_access }, { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr,