* [PATCH v16 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled
2025-09-12 9:25 [PATCH v16 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
@ 2025-09-12 9:25 ` Mark Brown
2025-09-12 9:25 ` [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests Mark Brown
` (4 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2025-09-12 9:25 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Shuah Khan
Cc: linux-arm-kernel, linux-doc, kvmarm, linux-kselftest,
linux-kernel, Mark Brown
The initial EL2 setup for GCS did not include disabling of EL1 usage of
GCS instructions, also disable these traps. This is the first disabling
of instruction traps, use x2 to store the value to be written.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/include/asm/el2_setup.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index 46033027510c..d174f405c44a 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -353,6 +353,11 @@
orr x0, x0, #HFGRTR_EL2_nGCS_EL1_MASK
orr x0, x0, #HFGRTR_EL2_nGCS_EL0_MASK
+ /* Disable traps of GCS instructions at EL1 */
+ orr x2, x2, #HFGITR_EL2_nGCSEPP_MASK
+ orr x2, x2, #HFGITR_EL2_nGCSSTR_EL1_MASK
+ orr x2, x2, #HFGITR_EL2_nGCSPUSHM_EL1_MASK
+
.Lskip_gce_fgt_\@:
.Lset_fgt_\@:
--
2.47.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-09-12 9:25 [PATCH v16 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
2025-09-12 9:25 ` [PATCH v16 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled Mark Brown
@ 2025-09-12 9:25 ` Mark Brown
2025-09-12 11:59 ` Marc Zyngier
2025-09-12 9:25 ` [PATCH v16 3/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception Mark Brown
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Mark Brown @ 2025-09-12 9:25 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Shuah Khan
Cc: linux-arm-kernel, linux-doc, kvmarm, linux-kselftest,
linux-kernel, Mark Brown
GCS introduces a number of system registers, 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.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/include/asm/kvm_emulate.h | 3 +++
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 | 31 ++++++++++++++++++++++++++++++
arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 10 ++++++++++
arch/arm64/kvm/sys_regs.c | 30 +++++++++++++++++++++++++++++
6 files changed, 90 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index fa8a08a1ccd5..9ab1e7616854 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -672,6 +672,9 @@ static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu)
if (kvm_has_sctlr2(kvm))
vcpu->arch.hcrx_el2 |= HCRX_EL2_SCTLR2En;
+
+ if (kvm_has_gcs(kvm))
+ vcpu->arch.hcrx_el2 |= HCRX_EL2_GCSEn;
}
}
#endif /* __ARM64_KVM_EMULATE_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 2f2394cce24e..22a3fa9d97aa 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -480,6 +480,10 @@ enum vcpu_sysreg {
POR_EL0, /* Permission Overlay Register 0 (EL0) */
+ /* Guarded Control Stack registers */
+ GCSCRE0_EL1, /* Guarded Control Stack Control (EL0) */
+ GCSPR_EL0, /* Guarded Control Stack Pointer (EL0) */
+
/* FP/SIMD/SVE */
SVCR,
FPMR,
@@ -502,6 +506,8 @@ enum vcpu_sysreg {
PIRE0_EL2, /* Permission Indirection Register 0 (EL2) */
PIR_EL2, /* Permission Indirection Register 1 (EL2) */
POR_EL2, /* Permission Overlay Register 2 (EL2) */
+ GCSCR_EL2, /* Guarded Control Stack Control Register (EL2) */
+ GCSPR_EL2, /* Guarded Control Stack Pointer Register (EL2) */
SPSR_EL2, /* EL2 saved program status register */
ELR_EL2, /* EL2 exception link register */
AFSR0_EL2, /* Auxiliary Fault Status Register 0 (EL2) */
@@ -571,6 +577,10 @@ enum vcpu_sysreg {
VNCR(VDISR_EL2),
VNCR(VSESR_EL2),
+ /* 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),
@@ -1697,6 +1707,10 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
#define kvm_has_sctlr2(k) \
(kvm_has_feat((k), ID_AA64MMFR3_EL1, SCTLRX, IMP))
+#define kvm_has_gcs(k) \
+ (system_supports_gcs() && \
+ kvm_has_feat((k), ID_AA64PFR1_EL1, GCS, IMP))
+
static inline bool kvm_arch_has_irq_bypass(void)
{
return true;
diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm/vncr_mapping.h
index f6ec500ad3fa..e9fac6218d44 100644
--- a/arch/arm64/include/asm/vncr_mapping.h
+++ b/arch/arm64/include/asm/vncr_mapping.h
@@ -95,6 +95,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 a17cbe7582de..053d7b3c5104 100644
--- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
+++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
@@ -17,6 +17,7 @@
#include <asm/kvm_mmu.h>
static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt);
+static inline bool ctxt_has_gcs(struct kvm_cpu_context *ctxt);
static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_cpu_context *ctxt)
{
@@ -67,6 +68,11 @@ 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);
+
+ 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)
@@ -131,6 +137,17 @@ static inline bool ctxt_has_sctlr2(struct kvm_cpu_context *ctxt)
return kvm_has_sctlr2(kern_hyp_va(vcpu->kvm));
}
+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_el1_state(struct kvm_cpu_context *ctxt)
{
ctxt_sys_reg(ctxt, SCTLR_EL1) = read_sysreg_el1(SYS_SCTLR);
@@ -144,6 +161,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);
+ }
}
if (ctxt_has_s1poe(ctxt))
@@ -206,6 +227,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,
@@ -239,6 +265,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);
+ }
}
if (ctxt_has_s1poe(ctxt))
diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
index f28c6cf4fe1b..e63b473d66d1 100644
--- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
@@ -61,6 +61,11 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu)
if (ctxt_has_s1poe(&vcpu->arch.ctxt))
__vcpu_assign_sys_reg(vcpu, POR_EL2, read_sysreg_el1(SYS_POR));
+
+ if (ctxt_has_gcs(&vcpu->arch.ctxt)) {
+ __vcpu_assign_sys_reg(vcpu, GCSCR_EL2, read_sysreg_el1(SYS_GCSCR));
+ __vcpu_assign_sys_reg(vcpu, GCSPR_EL2, read_sysreg_el1(SYS_GCSPR));
+ }
}
/*
@@ -133,6 +138,11 @@ static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu)
if (ctxt_has_s1poe(&vcpu->arch.ctxt))
write_sysreg_el1(__vcpu_sys_reg(vcpu, POR_EL2), SYS_POR);
+
+ if (ctxt_has_gcs(&vcpu->arch.ctxt)) {
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, GCSCR_EL2), SYS_GCSCR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, GCSPR_EL2), SYS_GCSPR);
+ }
}
write_sysreg_el1(__vcpu_sys_reg(vcpu, ESR_EL2), SYS_ESR);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 82ffb3b3b3cf..03fb2dce0b80 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -138,6 +138,8 @@ static bool get_el2_to_el1_mapping(unsigned int reg,
MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1, NULL );
MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1, NULL );
MAPPED_EL2_SYSREG(POR_EL2, POR_EL1, NULL );
+ MAPPED_EL2_SYSREG(GCSCR_EL2, GCSCR_EL1, NULL );
+ MAPPED_EL2_SYSREG(GCSPR_EL2, GCSPR_EL1, NULL );
MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1, NULL );
MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1, NULL );
MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1, NULL );
@@ -2654,6 +2656,21 @@ static unsigned int s1pie_el2_visibility(const struct kvm_vcpu *vcpu,
return __el2_visibility(vcpu, rd, s1pie_visibility);
}
+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;
+}
+
+static unsigned int gcs_el2_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
+{
+ return __el2_visibility(vcpu, rd, gcs_visibility);
+}
+
static bool access_mdcr(struct kvm_vcpu *vcpu,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
@@ -3048,6 +3065,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},
@@ -3162,6 +3186,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
CTR_EL0_DminLine_MASK |
CTR_EL0_L1Ip_MASK |
CTR_EL0_IminLine_MASK),
+ { SYS_DESC(SYS_GCSPR_EL0), NULL, reset_unknown, GCSPR_EL0,
+ .visibility = gcs_visibility },
{ SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility = sme_visibility },
{ SYS_DESC(SYS_FPMR), undef_access, reset_val, FPMR, 0, .visibility = fp8_visibility },
@@ -3401,6 +3427,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
EL2_REG_FILTERED(VNCR_EL2, bad_vncr_trap, reset_val, 0,
vncr_el2_visibility),
+ EL2_REG_FILTERED(GCSCR_EL2, access_rw, reset_val, 0,
+ gcs_el2_visibility),
+ EL2_REG_FILTERED(GCSPR_EL2, access_rw, reset_val, 0,
+ gcs_el2_visibility),
{ SYS_DESC(SYS_DACR32_EL2), undef_access, reset_unknown, DACR32_EL2 },
EL2_REG_VNCR_FILT(HDFGRTR2_EL2, fgt2_visibility),
EL2_REG_VNCR_FILT(HDFGWTR2_EL2, fgt2_visibility),
--
2.47.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-09-12 9:25 ` [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests Mark Brown
@ 2025-09-12 11:59 ` Marc Zyngier
2025-09-12 16:33 ` Mark Brown
0 siblings, 1 reply; 14+ messages in thread
From: Marc Zyngier @ 2025-09-12 11:59 UTC (permalink / raw)
To: Mark Brown
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel
On Fri, 12 Sep 2025 10:25:28 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 82ffb3b3b3cf..03fb2dce0b80 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -138,6 +138,8 @@ static bool get_el2_to_el1_mapping(unsigned int reg,
> MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1, NULL );
> MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1, NULL );
> MAPPED_EL2_SYSREG(POR_EL2, POR_EL1, NULL );
> + MAPPED_EL2_SYSREG(GCSCR_EL2, GCSCR_EL1, NULL );
> + MAPPED_EL2_SYSREG(GCSPR_EL2, GCSPR_EL1, NULL );
> MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1, NULL );
> MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1, NULL );
> MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1, NULL );
Just like the previous version, you're missing the accessors that
would be this table useful. Meaning that the vcpu_read_sys_reg() and
vcpu_write_sys_reg() accessors will fail for all 4 GSC registers.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-09-12 11:59 ` Marc Zyngier
@ 2025-09-12 16:33 ` Mark Brown
2025-09-12 17:14 ` Mark Brown
2025-09-12 21:30 ` Marc Zyngier
0 siblings, 2 replies; 14+ messages in thread
From: Mark Brown @ 2025-09-12 16:33 UTC (permalink / raw)
To: Marc Zyngier
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1048 bytes --]
On Fri, Sep 12, 2025 at 12:59:23PM +0100, Marc Zyngier wrote:
> On Fri, 12 Sep 2025 10:25:28 +0100,
> Mark Brown <broonie@kernel.org> wrote:
> > MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1, NULL );
> > MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1, NULL );
> > MAPPED_EL2_SYSREG(POR_EL2, POR_EL1, NULL );
> > + MAPPED_EL2_SYSREG(GCSCR_EL2, GCSCR_EL1, NULL );
> > + MAPPED_EL2_SYSREG(GCSPR_EL2, GCSPR_EL1, NULL );
> > MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1, NULL );
> > MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1, NULL );
> > MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1, NULL );
> Just like the previous version, you're missing the accessors that
> would be this table useful. Meaning that the vcpu_read_sys_reg() and
> vcpu_write_sys_reg() accessors will fail for all 4 GSC registers.
Just to confirm, this is __vcpu_{read,write}_sysreg()?
Sorry, I missed your comment about this on the prior version due to UI
confusion with my mail cllent. My mistake.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-09-12 16:33 ` Mark Brown
@ 2025-09-12 17:14 ` Mark Brown
2025-09-12 21:30 ` Marc Zyngier
1 sibling, 0 replies; 14+ messages in thread
From: Mark Brown @ 2025-09-12 17:14 UTC (permalink / raw)
To: Marc Zyngier
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 477 bytes --]
On Fri, Sep 12, 2025 at 05:33:39PM +0100, Mark Brown wrote:
> On Fri, Sep 12, 2025 at 12:59:23PM +0100, Marc Zyngier wrote:
> > Just like the previous version, you're missing the accessors that
> > would be this table useful. Meaning that the vcpu_read_sys_reg() and
> > vcpu_write_sys_reg() accessors will fail for all 4 GSC registers.
> Just to confirm, this is __vcpu_{read,write}_sysreg()?
Sorry, that should have been __vcpu_{read,write}_sys_reg_{to,from}_cpu()
*sigh*
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-09-12 16:33 ` Mark Brown
2025-09-12 17:14 ` Mark Brown
@ 2025-09-12 21:30 ` Marc Zyngier
1 sibling, 0 replies; 14+ messages in thread
From: Marc Zyngier @ 2025-09-12 21:30 UTC (permalink / raw)
To: Mark Brown
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel
On Fri, 12 Sep 2025 17:33:36 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> On Fri, Sep 12, 2025 at 12:59:23PM +0100, Marc Zyngier wrote:
> > On Fri, 12 Sep 2025 10:25:28 +0100,
> > Mark Brown <broonie@kernel.org> wrote:
>
> > > MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1, NULL );
> > > MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1, NULL );
> > > MAPPED_EL2_SYSREG(POR_EL2, POR_EL1, NULL );
> > > + MAPPED_EL2_SYSREG(GCSCR_EL2, GCSCR_EL1, NULL );
> > > + MAPPED_EL2_SYSREG(GCSPR_EL2, GCSPR_EL1, NULL );
> > > MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1, NULL );
> > > MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1, NULL );
> > > MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1, NULL );
>
> > Just like the previous version, you're missing the accessors that
> > would be this table useful. Meaning that the vcpu_read_sys_reg() and
> > vcpu_write_sys_reg() accessors will fail for all 4 GSC registers.
>
> Just to confirm, this is __vcpu_{read,write}_sysreg()?
No.
vcpu_{read,write}_sys_reg() and co are the broken high-level
accessors. __vcpu_{read,write}_sysreg() call into those depending on
the context, and __vcpu_{read,write}_sys_reg_{to,from}_cpu() have now
been removed and replaced by similar (but private) accessors.
See -rc4 for the details.
In any case, a bunch of register accesses in this series are broken,
as they don't respect the register life cycle of the guest.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v16 3/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception
2025-09-12 9:25 [PATCH v16 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
2025-09-12 9:25 ` [PATCH v16 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled Mark Brown
2025-09-12 9:25 ` [PATCH v16 2/6] KVM: arm64: Manage GCS access and registers for guests Mark Brown
@ 2025-09-12 9:25 ` Mark Brown
2025-09-12 9:25 ` [PATCH v16 4/6] KVM: arm64: Validate GCS exception lock when emulating ERET Mark Brown
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2025-09-12 9:25 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Shuah Khan
Cc: linux-arm-kernel, linux-doc, kvmarm, linux-kselftest,
linux-kernel, Mark Brown
As per DDI 0487 R_WTXBY we need to manage PSTATE.EXLOCK when entering an
exception, when the exception is entered from a lower EL the bit is cleared
while if entering from the same EL it is set to GCSCR_ELx.EXLOCKEN.
Implement this behaviour in enter_exception64().
Signed-off-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/include/uapi/asm/ptrace.h | 1 +
arch/arm64/kvm/hyp/exception.c | 37 ++++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
index 0f39ba4f3efd..f2fb029fb61a 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -56,6 +56,7 @@
#define PSR_C_BIT 0x20000000
#define PSR_Z_BIT 0x40000000
#define PSR_N_BIT 0x80000000
+#define PSR_EXLOCK_BIT 0x400000000
#define PSR_BTYPE_SHIFT 10
diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c
index 95d186e0bf54..888cea250dc2 100644
--- a/arch/arm64/kvm/hyp/exception.c
+++ b/arch/arm64/kvm/hyp/exception.c
@@ -73,6 +73,38 @@ static void __vcpu_write_spsr_und(struct kvm_vcpu *vcpu, u64 val)
vcpu->arch.ctxt.spsr_und = val;
}
+static unsigned long compute_exlock(struct kvm_vcpu *vcpu,
+ unsigned long mode,
+ unsigned long target_mode)
+{
+ u64 gcscr;
+
+ if (!kvm_has_gcs(kern_hyp_va(vcpu->kvm)))
+ return 0;
+
+ /* GCS can't be enabled for 32 bit */
+ if (mode & PSR_MODE32_BIT)
+ return 0;
+
+ /* When taking an exception to a higher EL EXLOCK is cleared. */
+ if ((mode | PSR_MODE_THREAD_BIT) != target_mode)
+ return 0;
+
+ /*
+ * When taking an exception to the same EL EXLOCK is set to
+ * the effective value of GCSR_ELx.EXLOCKEN.
+ */
+ if (vcpu_is_el2(vcpu))
+ gcscr = __vcpu_read_sys_reg(vcpu, GCSCR_EL2);
+ else
+ gcscr = __vcpu_read_sys_reg(vcpu, GCSCR_EL1);
+
+ if (gcscr & GCSCR_ELx_EXLOCKEN)
+ return PSR_EXLOCK_BIT;
+
+ return 0;
+}
+
/*
* This performs the exception entry at a given EL (@target_mode), stashing PC
* and PSTATE into ELR and SPSR respectively, and compute the new PC/PSTATE.
@@ -162,6 +194,11 @@ static void enter_exception64(struct kvm_vcpu *vcpu, unsigned long target_mode,
// PSTATE.BTYPE is set to zero upon any exception to AArch64
// See ARM DDI 0487E.a, pages D1-2293 to D1-2294.
+ // PSTATE.EXLOCK is set to 0 upon any exception to a higher
+ // EL, or to GCSCR_ELx.EXLOCKEN for an exception to the same
+ // exception level. See ARM DDI 0487 R_WTXBY.
+ new |= compute_exlock(vcpu, mode, target_mode);
+
new |= PSR_D_BIT;
new |= PSR_A_BIT;
new |= PSR_I_BIT;
--
2.47.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v16 4/6] KVM: arm64: Validate GCS exception lock when emulating ERET
2025-09-12 9:25 [PATCH v16 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (2 preceding siblings ...)
2025-09-12 9:25 ` [PATCH v16 3/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception Mark Brown
@ 2025-09-12 9:25 ` Mark Brown
2025-09-12 12:06 ` Marc Zyngier
2025-09-12 9:25 ` [PATCH v16 5/6] KVM: arm64: Allow GCS to be enabled for guests Mark Brown
2025-09-12 9:25 ` [PATCH v16 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list Mark Brown
5 siblings, 1 reply; 14+ messages in thread
From: Mark Brown @ 2025-09-12 9:25 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Shuah Khan
Cc: linux-arm-kernel, linux-doc, kvmarm, linux-kselftest,
linux-kernel, Mark Brown
As per DDI0487 R_TYTWB GCS adds an additional case where an illegal
exception return can be generated. If all of:
- PSTATE.EXLOCK is 0.
- The EL is not being changed by the ERET.
- GCSCR_ELx.EXLOCKEN is 1.
are true then the return is illegal. Emulate this behaviour when
emulating ERET for nested guests.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/kvm/emulate-nested.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 90cb4b7ae0ff..9b02b85eda64 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2632,6 +2632,41 @@ bool forward_debug_exception(struct kvm_vcpu *vcpu)
return forward_mdcr_traps(vcpu, MDCR_EL2_TDE);
}
+/*
+ * A subset of the pseudocode ELFromSPSR(), validity checks are
+ * assumed to have been done in code that is not GCS specific.
+ */
+static inline int exlock_el_from_spsr(u64 spsr)
+{
+ return FIELD_GET(GENMASK(3, 2), spsr);
+}
+
+/* See IllegalExceptionReturn() pseudocode */
+static bool kvm_check_illegal_exlock_return(struct kvm_vcpu *vcpu, u64 spsr)
+{
+ u64 cur_el, target_el;
+ u64 gcscr;
+
+ if (!kvm_has_gcs(vcpu->kvm))
+ return false;
+
+ if (spsr & PSR_EXLOCK_BIT)
+ return false;
+
+ cur_el = exlock_el_from_spsr(vcpu->arch.ctxt.regs.pstate);
+ target_el = exlock_el_from_spsr(spsr);
+
+ if (cur_el != target_el)
+ return false;
+
+ if (vcpu_is_el2(vcpu))
+ gcscr = __vcpu_sys_reg(vcpu, GCSCR_EL2);
+ else
+ gcscr = __vcpu_sys_reg(vcpu, GCSCR_EL1);
+
+ return gcscr & GCSCR_ELx_EXLOCKEN;
+}
+
static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)
{
u64 mode = spsr & PSR_MODE_MASK;
@@ -2642,12 +2677,15 @@ static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)
* - trying to return to an illegal M value
* - trying to return to a 32bit EL
* - trying to return to EL1 with HCR_EL2.TGE set
+ * - GCSCR_ELx.EXLOCKEN is 1 and PSTATE.EXLOCK is 0 when attempting
+ * to return from ELx the same EL.
*/
if (mode == PSR_MODE_EL3t || mode == PSR_MODE_EL3h ||
mode == 0b00001 || (mode & BIT(1)) ||
(spsr & PSR_MODE32_BIT) ||
(vcpu_el2_tge_is_set(vcpu) && (mode == PSR_MODE_EL1t ||
- mode == PSR_MODE_EL1h))) {
+ mode == PSR_MODE_EL1h)) ||
+ kvm_check_illegal_exlock_return(vcpu, spsr)) {
/*
* The guest is playing with our nerves. Preserve EL, SP,
* masks, flags from the existing PSTATE, and set IL.
--
2.47.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v16 4/6] KVM: arm64: Validate GCS exception lock when emulating ERET
2025-09-12 9:25 ` [PATCH v16 4/6] KVM: arm64: Validate GCS exception lock when emulating ERET Mark Brown
@ 2025-09-12 12:06 ` Marc Zyngier
0 siblings, 0 replies; 14+ messages in thread
From: Marc Zyngier @ 2025-09-12 12:06 UTC (permalink / raw)
To: Mark Brown
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel
On Fri, 12 Sep 2025 10:25:30 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> As per DDI0487 R_TYTWB GCS adds an additional case where an illegal
> exception return can be generated. If all of:
>
> - PSTATE.EXLOCK is 0.
> - The EL is not being changed by the ERET.
> - GCSCR_ELx.EXLOCKEN is 1.
>
> are true then the return is illegal. Emulate this behaviour when
> emulating ERET for nested guests.
>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> arch/arm64/kvm/emulate-nested.c | 40 +++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 39 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
> index 90cb4b7ae0ff..9b02b85eda64 100644
> --- a/arch/arm64/kvm/emulate-nested.c
> +++ b/arch/arm64/kvm/emulate-nested.c
> @@ -2632,6 +2632,41 @@ bool forward_debug_exception(struct kvm_vcpu *vcpu)
> return forward_mdcr_traps(vcpu, MDCR_EL2_TDE);
> }
>
> +/*
> + * A subset of the pseudocode ELFromSPSR(), validity checks are
> + * assumed to have been done in code that is not GCS specific.
> + */
> +static inline int exlock_el_from_spsr(u64 spsr)
> +{
> + return FIELD_GET(GENMASK(3, 2), spsr);
> +}
> +
> +/* See IllegalExceptionReturn() pseudocode */
> +static bool kvm_check_illegal_exlock_return(struct kvm_vcpu *vcpu, u64 spsr)
> +{
> + u64 cur_el, target_el;
> + u64 gcscr;
> +
> + if (!kvm_has_gcs(vcpu->kvm))
> + return false;
> +
> + if (spsr & PSR_EXLOCK_BIT)
> + return false;
> +
> + cur_el = exlock_el_from_spsr(vcpu->arch.ctxt.regs.pstate);
> + target_el = exlock_el_from_spsr(spsr);
> +
> + if (cur_el != target_el)
> + return false;
> +
> + if (vcpu_is_el2(vcpu))
> + gcscr = __vcpu_sys_reg(vcpu, GCSCR_EL2);
> + else
> + gcscr = __vcpu_sys_reg(vcpu, GCSCR_EL1);
At the point where we check for an illegal exception return, the state
is live on the CPU. How does this work? Also, we only handle ERET
traps for EL2, not EL1.
> +
> + return gcscr & GCSCR_ELx_EXLOCKEN;
> +}
> +
> static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)
> {
> u64 mode = spsr & PSR_MODE_MASK;
> @@ -2642,12 +2677,15 @@ static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)
> * - trying to return to an illegal M value
> * - trying to return to a 32bit EL
> * - trying to return to EL1 with HCR_EL2.TGE set
> + * - GCSCR_ELx.EXLOCKEN is 1 and PSTATE.EXLOCK is 0 when attempting
> + * to return from ELx the same EL.
> */
> if (mode == PSR_MODE_EL3t || mode == PSR_MODE_EL3h ||
> mode == 0b00001 || (mode & BIT(1)) ||
> (spsr & PSR_MODE32_BIT) ||
> (vcpu_el2_tge_is_set(vcpu) && (mode == PSR_MODE_EL1t ||
> - mode == PSR_MODE_EL1h))) {
> + mode == PSR_MODE_EL1h)) ||
> + kvm_check_illegal_exlock_return(vcpu, spsr)) {
This code is simply never reached. Hint: kvm_hyp_handle_eret().
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v16 5/6] KVM: arm64: Allow GCS to be enabled for guests
2025-09-12 9:25 [PATCH v16 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (3 preceding siblings ...)
2025-09-12 9:25 ` [PATCH v16 4/6] KVM: arm64: Validate GCS exception lock when emulating ERET Mark Brown
@ 2025-09-12 9:25 ` Mark Brown
2025-09-12 21:44 ` Marc Zyngier
2025-09-12 9:25 ` [PATCH v16 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list Mark Brown
5 siblings, 1 reply; 14+ messages in thread
From: Mark Brown @ 2025-09-12 9:25 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Shuah Khan
Cc: linux-arm-kernel, linux-doc, kvmarm, linux-kselftest,
linux-kernel, Mark Brown
Now that required functionality for GCS is in place expose
ID_AA64PFR1_EL1.GCS, allowing guests to be given the feature.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/kvm/nested.c | 7 ++++---
arch/arm64/kvm/sys_regs.c | 2 --
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 153b3e11b115..d2d55e18c610 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1459,9 +1459,10 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
case SYS_ID_AA64PFR1_EL1:
/* Only support BTI, SSBS, CSV2_frac */
- val &= (ID_AA64PFR1_EL1_BT |
- ID_AA64PFR1_EL1_SSBS |
- ID_AA64PFR1_EL1_CSV2_frac);
+ val &= (ID_AA64PFR1_EL1_BT |
+ ID_AA64PFR1_EL1_SSBS |
+ ID_AA64PFR1_EL1_CSV2_frac |
+ ID_AA64PFR1_EL1_GCS);
break;
case SYS_ID_AA64MMFR0_EL1:
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 03fb2dce0b80..60e234422064 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1616,7 +1616,6 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI);
- val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR);
@@ -2953,7 +2952,6 @@ static const struct sys_reg_desc sys_reg_descs[] = {
~(ID_AA64PFR1_EL1_PFAR |
ID_AA64PFR1_EL1_MTEX |
ID_AA64PFR1_EL1_THE |
- ID_AA64PFR1_EL1_GCS |
ID_AA64PFR1_EL1_MTE_frac |
ID_AA64PFR1_EL1_NMI |
ID_AA64PFR1_EL1_RNDR_trap |
--
2.47.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v16 5/6] KVM: arm64: Allow GCS to be enabled for guests
2025-09-12 9:25 ` [PATCH v16 5/6] KVM: arm64: Allow GCS to be enabled for guests Mark Brown
@ 2025-09-12 21:44 ` Marc Zyngier
0 siblings, 0 replies; 14+ messages in thread
From: Marc Zyngier @ 2025-09-12 21:44 UTC (permalink / raw)
To: Mark Brown
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel
On Fri, 12 Sep 2025 10:25:31 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> Now that required functionality for GCS is in place expose
> ID_AA64PFR1_EL1.GCS, allowing guests to be given the feature.
>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> arch/arm64/kvm/nested.c | 7 ++++---
> arch/arm64/kvm/sys_regs.c | 2 --
> 2 files changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 153b3e11b115..d2d55e18c610 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -1459,9 +1459,10 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
>
> case SYS_ID_AA64PFR1_EL1:
> /* Only support BTI, SSBS, CSV2_frac */
> - val &= (ID_AA64PFR1_EL1_BT |
> - ID_AA64PFR1_EL1_SSBS |
> - ID_AA64PFR1_EL1_CSV2_frac);
> + val &= (ID_AA64PFR1_EL1_BT |
> + ID_AA64PFR1_EL1_SSBS |
> + ID_AA64PFR1_EL1_CSV2_frac |
> + ID_AA64PFR1_EL1_GCS);
How about updating the comment?
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v16 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list
2025-09-12 9:25 [PATCH v16 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (4 preceding siblings ...)
2025-09-12 9:25 ` [PATCH v16 5/6] KVM: arm64: Allow GCS to be enabled for guests Mark Brown
@ 2025-09-12 9:25 ` Mark Brown
2025-09-12 21:46 ` Marc Zyngier
5 siblings, 1 reply; 14+ messages in thread
From: Mark Brown @ 2025-09-12 9:25 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Shuah Khan
Cc: linux-arm-kernel, linux-doc, kvmarm, linux-kselftest,
linux-kernel, Mark Brown, Thiago Jung Bauermann
GCS adds new registers GCSCR_EL1, GCSCRE0_EL1, GCSPR_EL1 and GCSPR_EL0. Add
these to those validated by get-reg-list.
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
tools/testing/selftests/kvm/arm64/get-reg-list.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/tools/testing/selftests/kvm/arm64/get-reg-list.c b/tools/testing/selftests/kvm/arm64/get-reg-list.c
index 011fad95dd02..9bf33064377b 100644
--- a/tools/testing/selftests/kvm/arm64/get-reg-list.c
+++ b/tools/testing/selftests/kvm/arm64/get-reg-list.c
@@ -42,6 +42,12 @@ struct feature_id_reg {
static struct feature_id_reg feat_id_regs[] = {
REG_FEAT(TCR2_EL1, ID_AA64MMFR3_EL1, TCRX, IMP),
REG_FEAT(TCR2_EL2, ID_AA64MMFR3_EL1, TCRX, IMP),
+ REG_FEAT(GCSPR_EL0, ID_AA64PFR1_EL1, GCS, IMP),
+ REG_FEAT(GCSPR_EL1, ID_AA64PFR1_EL1, GCS, IMP),
+ REG_FEAT(GCSPR_EL2, ID_AA64PFR1_EL1, GCS, IMP),
+ REG_FEAT(GCSCRE0_EL1, ID_AA64PFR1_EL1, GCS, IMP),
+ REG_FEAT(GCSCR_EL1, ID_AA64PFR1_EL1, GCS, IMP),
+ REG_FEAT(GCSCR_EL2, ID_AA64PFR1_EL1, GCS, IMP),
REG_FEAT(PIRE0_EL1, ID_AA64MMFR3_EL1, S1PIE, IMP),
REG_FEAT(PIRE0_EL2, ID_AA64MMFR3_EL1, S1PIE, IMP),
REG_FEAT(PIR_EL1, ID_AA64MMFR3_EL1, S1PIE, IMP),
@@ -486,6 +492,9 @@ static __u64 base_regs[] = {
ARM64_SYS_REG(3, 0, 2, 0, 1), /* TTBR1_EL1 */
ARM64_SYS_REG(3, 0, 2, 0, 2), /* TCR_EL1 */
ARM64_SYS_REG(3, 0, 2, 0, 3), /* TCR2_EL1 */
+ ARM64_SYS_REG(3, 0, 2, 5, 0), /* GCSCR_EL1 */
+ ARM64_SYS_REG(3, 0, 2, 5, 1), /* GCSPR_EL1 */
+ ARM64_SYS_REG(3, 0, 2, 5, 2), /* GCSCRE0_EL1 */
ARM64_SYS_REG(3, 0, 5, 1, 0), /* AFSR0_EL1 */
ARM64_SYS_REG(3, 0, 5, 1, 1), /* AFSR1_EL1 */
ARM64_SYS_REG(3, 0, 5, 2, 0), /* ESR_EL1 */
@@ -502,6 +511,7 @@ static __u64 base_regs[] = {
ARM64_SYS_REG(3, 0, 13, 0, 4), /* TPIDR_EL1 */
ARM64_SYS_REG(3, 0, 14, 1, 0), /* CNTKCTL_EL1 */
ARM64_SYS_REG(3, 2, 0, 0, 0), /* CSSELR_EL1 */
+ ARM64_SYS_REG(3, 3, 2, 5, 1), /* GCSPR_EL0 */
ARM64_SYS_REG(3, 3, 10, 2, 4), /* POR_EL0 */
ARM64_SYS_REG(3, 3, 13, 0, 2), /* TPIDR_EL0 */
ARM64_SYS_REG(3, 3, 13, 0, 3), /* TPIDRRO_EL0 */
@@ -740,6 +750,8 @@ static __u64 el2_regs[] = {
SYS_REG(PIRE0_EL2),
SYS_REG(PIR_EL2),
SYS_REG(POR_EL2),
+ SYS_REG(GCSPR_EL2),
+ SYS_REG(GCSCR_EL2),
SYS_REG(AMAIR_EL2),
SYS_REG(VBAR_EL2),
SYS_REG(CONTEXTIDR_EL2),
--
2.47.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v16 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list
2025-09-12 9:25 ` [PATCH v16 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list Mark Brown
@ 2025-09-12 21:46 ` Marc Zyngier
0 siblings, 0 replies; 14+ messages in thread
From: Marc Zyngier @ 2025-09-12 21:46 UTC (permalink / raw)
To: Mark Brown
Cc: Catalin Marinas, Will Deacon, Oliver Upton, Joey Gouly,
Suzuki K Poulose, Shuah Khan, linux-arm-kernel, linux-doc, kvmarm,
linux-kselftest, linux-kernel, Thiago Jung Bauermann
On Fri, 12 Sep 2025 10:25:32 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> GCS adds new registers GCSCR_EL1, GCSCRE0_EL1, GCSPR_EL1 and GCSPR_EL0. Add
> these to those validated by get-reg-list.
>
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> tools/testing/selftests/kvm/arm64/get-reg-list.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/tools/testing/selftests/kvm/arm64/get-reg-list.c b/tools/testing/selftests/kvm/arm64/get-reg-list.c
> index 011fad95dd02..9bf33064377b 100644
> --- a/tools/testing/selftests/kvm/arm64/get-reg-list.c
> +++ b/tools/testing/selftests/kvm/arm64/get-reg-list.c
> @@ -42,6 +42,12 @@ struct feature_id_reg {
> static struct feature_id_reg feat_id_regs[] = {
> REG_FEAT(TCR2_EL1, ID_AA64MMFR3_EL1, TCRX, IMP),
> REG_FEAT(TCR2_EL2, ID_AA64MMFR3_EL1, TCRX, IMP),
> + REG_FEAT(GCSPR_EL0, ID_AA64PFR1_EL1, GCS, IMP),
> + REG_FEAT(GCSPR_EL1, ID_AA64PFR1_EL1, GCS, IMP),
> + REG_FEAT(GCSPR_EL2, ID_AA64PFR1_EL1, GCS, IMP),
> + REG_FEAT(GCSCRE0_EL1, ID_AA64PFR1_EL1, GCS, IMP),
> + REG_FEAT(GCSCR_EL1, ID_AA64PFR1_EL1, GCS, IMP),
> + REG_FEAT(GCSCR_EL2, ID_AA64PFR1_EL1, GCS, IMP),
> REG_FEAT(PIRE0_EL1, ID_AA64MMFR3_EL1, S1PIE, IMP),
> REG_FEAT(PIRE0_EL2, ID_AA64MMFR3_EL1, S1PIE, IMP),
> REG_FEAT(PIR_EL1, ID_AA64MMFR3_EL1, S1PIE, IMP),
> @@ -486,6 +492,9 @@ static __u64 base_regs[] = {
> ARM64_SYS_REG(3, 0, 2, 0, 1), /* TTBR1_EL1 */
> ARM64_SYS_REG(3, 0, 2, 0, 2), /* TCR_EL1 */
> ARM64_SYS_REG(3, 0, 2, 0, 3), /* TCR2_EL1 */
> + ARM64_SYS_REG(3, 0, 2, 5, 0), /* GCSCR_EL1 */
> + ARM64_SYS_REG(3, 0, 2, 5, 1), /* GCSPR_EL1 */
> + ARM64_SYS_REG(3, 0, 2, 5, 2), /* GCSCRE0_EL1 */
> ARM64_SYS_REG(3, 0, 5, 1, 0), /* AFSR0_EL1 */
> ARM64_SYS_REG(3, 0, 5, 1, 1), /* AFSR1_EL1 */
> ARM64_SYS_REG(3, 0, 5, 2, 0), /* ESR_EL1 */
> @@ -502,6 +511,7 @@ static __u64 base_regs[] = {
> ARM64_SYS_REG(3, 0, 13, 0, 4), /* TPIDR_EL1 */
> ARM64_SYS_REG(3, 0, 14, 1, 0), /* CNTKCTL_EL1 */
> ARM64_SYS_REG(3, 2, 0, 0, 0), /* CSSELR_EL1 */
> + ARM64_SYS_REG(3, 3, 2, 5, 1), /* GCSPR_EL0 */
> ARM64_SYS_REG(3, 3, 10, 2, 4), /* POR_EL0 */
> ARM64_SYS_REG(3, 3, 13, 0, 2), /* TPIDR_EL0 */
> ARM64_SYS_REG(3, 3, 13, 0, 3), /* TPIDRRO_EL0 */
> @@ -740,6 +750,8 @@ static __u64 el2_regs[] = {
> SYS_REG(PIRE0_EL2),
> SYS_REG(PIR_EL2),
> SYS_REG(POR_EL2),
> + SYS_REG(GCSPR_EL2),
> + SYS_REG(GCSCR_EL2),
> SYS_REG(AMAIR_EL2),
> SYS_REG(VBAR_EL2),
> SYS_REG(CONTEXTIDR_EL2),
>
More importantly, I'd expect a test that exercises the exception
paths, as the current code is pretty broken.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 14+ messages in thread