From nobody Wed Dec 17 22:45:05 2025 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 434AAC61D9B for ; Wed, 22 Nov 2023 09:45:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235145AbjKVJpZ (ORCPT ); Wed, 22 Nov 2023 04:45:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41464 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343729AbjKVJpC (ORCPT ); Wed, 22 Nov 2023 04:45:02 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D54110CF for ; Wed, 22 Nov 2023 01:44:38 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AB45FC43142; Wed, 22 Nov 2023 09:44:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1700646277; bh=701JTF9Jvt7MHb4vzhbZhtT7BBJBuznNuW3VQeP4Dqk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lBBiPkfs1bDvDwjHk4OkCK/FLfl/DjbD4UXXRmnc6yFzF5zap9dV3IJ72+bcXHLdR tUb7tOWPLx3jyiV+kFx1gYyjX76ecQ9jUUhXAFPxP3MT9oDHjvRaYtVWbg7PEzj2xv 35tvDg3WO/auArFeFCucrYnv98XyP7Q9zZVWus1BTU9i5jNDTO6JUUSp7efT6qfpp4 kNbXvyIW8LgU9/jn09Puy6NA0jHcD+6ZD9V3T6NpokLSw8zrlewKqnApU8DlaGUI11 e86Pgu50Yp02rHLvXaKF0MTkm15a2boO2lGqfFFeQz6uJtO+40YZewfERRgzR+47r4 AeAJJBAkAlg+A== From: Mark Brown Date: Wed, 22 Nov 2023 09:42:24 +0000 Subject: [PATCH v7 14/39] KVM: arm64: Manage GCS registers for guests MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20231122-arm64-gcs-v7-14-201c483bd775@kernel.org> References: <20231122-arm64-gcs-v7-0-201c483bd775@kernel.org> In-Reply-To: <20231122-arm64-gcs-v7-0-201c483bd775@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 , Kees Cook , Shuah Khan , "Rick P. Edgecombe" , Deepak Gupta , Ard Biesheuvel , Szabolcs Nagy Cc: "H.J. Lu" , Paul Walmsley , Palmer Dabbelt , Albert Ou , Florian Weimer , Christian Brauner , Thiago Jung Bauermann , 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.13-dev-0438c X-Developer-Signature: v=1; a=openpgp-sha256; l=5364; i=broonie@kernel.org; h=from:subject:message-id; bh=701JTF9Jvt7MHb4vzhbZhtT7BBJBuznNuW3VQeP4Dqk=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBlXc0BfEgkkRq/SykifBOr7DH7c9OzUQTfc3qa1 neFhSoEgA+JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZV3NAQAKCRAk1otyXVSH 0MFTB/9Zui5cCedvHBD+Vs/u3hLqGSWuJf2lHM51ej/6t6eS1XaHSrFKXdLgTCQYE9smlvcGNQo r4+cJ9fLfz1oQl0jGvRlS6Bnx2jTNrWGGdnFhMgZDfO5xrvSpRjjmXpk3+SRnO4OjVVSGfdAnRS yHzmj/yQQSFe0bfTWBWitkGKeJJcQe/vtDdswlJP2slDDHoCFndFuD21dGsTA+oBvEwSrtNAK0b chDLJDM+svT3/5T0sbV2cWltxUQ5VLZFcpuat5k1Z3WG1YZbg5zH+e+q2CPy36NMutNgtGWpmOV 9/jMEPsWOhkDS2qH1SdZl7RFJHJybmOLGPChu233YdOu3sod X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Traps are already disabled. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 12 ++++++++++++ arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 17 +++++++++++++++++ arch/arm64/kvm/sys_regs.c | 22 ++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 824f29f04916..2b09805da26a 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -401,6 +401,12 @@ enum vcpu_sysreg { PIR_EL1, /* Permission Indirection Register 1 (EL1) */ PIRE0_EL1, /* Permission Indirection Register 0 (EL1) */ =20 + /* Guarded Control Stack registers */ + GCSCRE0_EL1, /* Guarded Control Stack Control (EL0) */ + GCSCR_EL1, /* Guarded Control Stack Control (EL1) */ + GCSPR_EL0, /* Guarded Control Stack Pointer (EL0) */ + GCSPR_EL1, /* Guarded Control Stack Pointer (EL1) */ + /* 32bit specific registers. */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ @@ -1177,6 +1183,12 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu= ); #define kvm_vm_has_ran_once(kvm) \ (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &(kvm)->arch.flags)) =20 +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/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hy= p/include/hyp/sysreg-sr.h index bb6b571ec627..ec34d4a90717 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -25,6 +25,8 @@ static inline void __sysreg_save_user_state(struct kvm_cp= u_context *ctxt) { ctxt_sys_reg(ctxt, TPIDR_EL0) =3D read_sysreg(tpidr_el0); ctxt_sys_reg(ctxt, TPIDRRO_EL0) =3D read_sysreg(tpidrro_el0); + if (has_gcs()) + ctxt_sys_reg(ctxt, GCSPR_EL0) =3D read_sysreg_s(SYS_GCSPR_EL0); } =20 static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) @@ -62,6 +64,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cp= u_context *ctxt) ctxt_sys_reg(ctxt, PAR_EL1) =3D read_sysreg_par(); ctxt_sys_reg(ctxt, TPIDR_EL1) =3D read_sysreg(tpidr_el1); =20 + if (has_gcs()) { + ctxt_sys_reg(ctxt, GCSPR_EL1) =3D read_sysreg_el1(SYS_GCSPR); + ctxt_sys_reg(ctxt, GCSCR_EL1) =3D read_sysreg_el1(SYS_GCSCR); + ctxt_sys_reg(ctxt, GCSCRE0_EL1) =3D read_sysreg_s(SYS_GCSCRE0_EL1); + } + if (ctxt_has_mte(ctxt)) { ctxt_sys_reg(ctxt, TFSR_EL1) =3D read_sysreg_el1(SYS_TFSR); ctxt_sys_reg(ctxt, TFSRE0_EL1) =3D read_sysreg_s(SYS_TFSRE0_EL1); @@ -95,6 +103,8 @@ static inline void __sysreg_restore_user_state(struct kv= m_cpu_context *ctxt) { write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL0), tpidr_el0); write_sysreg(ctxt_sys_reg(ctxt, TPIDRRO_EL0), tpidrro_el0); + if (has_gcs()) + write_sysreg_s(ctxt_sys_reg(ctxt, GCSPR_EL0), SYS_GCSPR_EL0); } =20 static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) @@ -138,6 +148,13 @@ static inline void __sysreg_restore_el1_state(struct k= vm_cpu_context *ctxt) write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1), par_el1); write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1), tpidr_el1); =20 + if (has_gcs()) { + 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 4735e1b37fb3..300719f82dd1 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1876,6 +1876,23 @@ static unsigned int mte_visibility(const struct kvm_= vcpu *vcpu, .visibility =3D mte_visibility, \ } =20 +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 =3D undef_access, \ + .reset =3D reset_unknown, \ + .reg =3D name, \ + .visibility =3D gcs_visibility, \ +} + static unsigned int el2_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { @@ -2223,6 +2240,10 @@ static const struct sys_reg_desc sys_reg_descs[] =3D= { PTRAUTH_KEY(APDB), PTRAUTH_KEY(APGA), =20 + 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}, =20 @@ -2309,6 +2330,7 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { { 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 }, =20 { PMU_SYS_REG(PMCR_EL0), .access =3D access_pmcr, .reset =3D reset_pmcr, --=20 2.39.2