* [PATCH v15 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
@ 2025-08-20 14:14 ` Mark Brown
2025-08-20 22:24 ` Marc Zyngier
2025-08-20 14:14 ` [PATCH v15 2/6] KVM: arm64: Manage GCS access and registers for guests Mark Brown
` (5 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2025-08-20 14:14 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 | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index 46033027510c..0ac14ea4dbc8 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -355,6 +355,10 @@
.Lskip_gce_fgt_\@:
+ orr x2, x2, #HFGITR_EL2_nGCSEPP_MASK
+ orr x2, x2, #HFGITR_EL2_nGCSSTR_EL1_MASK
+ orr x2, x2, #HFGITR_EL2_nGCSPUSHM_EL1_MASK
+
.Lset_fgt_\@:
msr_s SYS_HFGRTR_EL2, x0
msr_s SYS_HFGWTR_EL2, x0
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v15 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled
2025-08-20 14:14 ` [PATCH v15 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled Mark Brown
@ 2025-08-20 22:24 ` Marc Zyngier
2025-08-20 22:28 ` Marc Zyngier
0 siblings, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 22:24 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 Wed, 20 Aug 2025 15:14:41 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> 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.
Written where?
>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> arch/arm64/include/asm/el2_setup.h | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
> index 46033027510c..0ac14ea4dbc8 100644
> --- a/arch/arm64/include/asm/el2_setup.h
> +++ b/arch/arm64/include/asm/el2_setup.h
> @@ -355,6 +355,10 @@
>
> .Lskip_gce_fgt_\@:
>
> + orr x2, x2, #HFGITR_EL2_nGCSEPP_MASK
What is x2 set to before this?
> + orr x2, x2, #HFGITR_EL2_nGCSSTR_EL1_MASK
> + orr x2, x2, #HFGITR_EL2_nGCSPUSHM_EL1_MASK
> +
> .Lset_fgt_\@:
> msr_s SYS_HFGRTR_EL2, x0
> msr_s SYS_HFGWTR_EL2, x0
Followed by:
msr_s SYS_HFGITR_EL2, xzr
Puzzled.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v15 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled
2025-08-20 22:24 ` Marc Zyngier
@ 2025-08-20 22:28 ` Marc Zyngier
0 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 22:28 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 Wed, 20 Aug 2025 23:24:24 +0100,
Marc Zyngier <maz@kernel.org> wrote:
>
> On Wed, 20 Aug 2025 15:14:41 +0100,
> Mark Brown <broonie@kernel.org> wrote:
> >
> > 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.
>
> Written where?
Gah, I was looking at 6.16, not 6.17-rc1.
Apologies for the noise.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v15 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
2025-08-20 14:14 ` [PATCH v15 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled Mark Brown
@ 2025-08-20 14:14 ` Mark Brown
2025-08-20 21:06 ` Marc Zyngier
2025-08-20 14:14 ` [PATCH v15 3/6] KVM: arm64: Forward GCS exceptions to nested guests Mark Brown
` (4 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2025-08-20 14:14 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 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.
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 | 31 +++++++++++++++++++++++++++++-
6 files changed, 90 insertions(+), 1 deletion(-)
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..592cb5d6497a 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)
@@ -2936,7 +2953,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 |
@@ -3048,6 +3064,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 +3185,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 +3426,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.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v15 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-08-20 14:14 ` [PATCH v15 2/6] KVM: arm64: Manage GCS access and registers for guests Mark Brown
@ 2025-08-20 21:06 ` Marc Zyngier
2025-08-20 22:13 ` Mark Brown
0 siblings, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 21: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 Wed, 20 Aug 2025 15:14:42 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> GCS introduces a number of system registers for EL1 and EL0, on systems
and EL2.
> 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.
I don't see any FGT configuration in this patch. As far as I can tell,
the FGU generation already takes care of that particular case.
>
> 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.
I'm not sure what you mean by that. Making the feature field writable
is only allowable if we have some level of support (and otherwise we
should prevent both the feature being exposed, and the field being
writable).
So future fields being writable will only happen when the features are
fully supported, and only then.
Please clarify, or drop this altogether.
>
> 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 | 31 +++++++++++++++++++++++++++++-
> 6 files changed, 90 insertions(+), 1 deletion(-)
>
[...]
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 82ffb3b3b3cf..592cb5d6497a 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 );
How is the state accessed when loaded on the CPU? You seem to be
missing accessors for these two registers, affecting both EL1 and EL2
in the guest.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v15 2/6] KVM: arm64: Manage GCS access and registers for guests
2025-08-20 21:06 ` Marc Zyngier
@ 2025-08-20 22:13 ` Mark Brown
0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2025-08-20 22:13 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: 905 bytes --]
On Wed, Aug 20, 2025 at 10:06:49PM +0100, Marc Zyngier wrote:
> Mark Brown <broonie@kernel.org> wrote:
> > 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.
> I'm not sure what you mean by that. Making the feature field writable
> is only allowable if we have some level of support (and otherwise we
> should prevent both the feature being exposed, and the field being
> writable).
> So future fields being writable will only happen when the features are
> fully supported, and only then.
> Please clarify, or drop this altogether.
That's bitrot from earlier versions where we needed to enable
ID_AA64PFR1_EL1, the other versions were similar. I'll remove these
stale references.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v15 3/6] KVM: arm64: Forward GCS exceptions to nested guests
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
2025-08-20 14:14 ` [PATCH v15 1/6] arm64/gcs: Ensure FGTs for EL1 GCS instructions are disabled Mark Brown
2025-08-20 14:14 ` [PATCH v15 2/6] KVM: arm64: Manage GCS access and registers for guests Mark Brown
@ 2025-08-20 14:14 ` Mark Brown
2025-08-20 22:15 ` Marc Zyngier
2025-08-20 14:14 ` [PATCH v15 4/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception Mark Brown
` (3 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2025-08-20 14:14 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 can generate exceptions with an EC of 0x2D (GCS Data Check
Exception) when data validation checks fail. When running a nested
guest which has access to GCS such exceptions can be directed from EL0
to EL2 and therefore need to be forwarded to the guest hypervisor, add
handling for this.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/kvm/handle_exit.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index a598072f36d2..2f5aef84b294 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -301,10 +301,18 @@ static int handle_svc(struct kvm_vcpu *vcpu)
static int kvm_handle_gcs(struct kvm_vcpu *vcpu)
{
- /* We don't expect GCS, so treat it with contempt */
- if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, GCS, IMP))
- WARN_ON_ONCE(1);
+ if (!kvm_has_gcs(vcpu->kvm)) {
+ kvm_inject_undefined(vcpu);
+ return 1;
+ }
+ if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
+ kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
+ return 1;
+ }
+
+ /* We shouldn't have generated a trap in this case */
+ WARN_ON_ONCE(1);
kvm_inject_undefined(vcpu);
return 1;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v15 3/6] KVM: arm64: Forward GCS exceptions to nested guests
2025-08-20 14:14 ` [PATCH v15 3/6] KVM: arm64: Forward GCS exceptions to nested guests Mark Brown
@ 2025-08-20 22:15 ` Marc Zyngier
2025-08-21 21:25 ` Mark Brown
0 siblings, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 22:15 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 Wed, 20 Aug 2025 15:14:43 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> GCS can generate exceptions with an EC of 0x2D (GCS Data Check
> Exception) when data validation checks fail. When running a nested
> guest which has access to GCS such exceptions can be directed from EL0
> to EL2 and therefore need to be forwarded to the guest hypervisor, add
> handling for this.
Why is it so? A GCS exception from EL0 should be routed to EL1, no
matter what (either this is an L1 guest with EL1 pretending to be EL2,
or this is an L2 guest that has its own EL1).
Can you describe the case where we need to reinject the exception?
>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> arch/arm64/kvm/handle_exit.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index a598072f36d2..2f5aef84b294 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -301,10 +301,18 @@ static int handle_svc(struct kvm_vcpu *vcpu)
>
> static int kvm_handle_gcs(struct kvm_vcpu *vcpu)
> {
> - /* We don't expect GCS, so treat it with contempt */
> - if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, GCS, IMP))
> - WARN_ON_ONCE(1);
> + if (!kvm_has_gcs(vcpu->kvm)) {
> + kvm_inject_undefined(vcpu);
> + return 1;
> + }
>
> + if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
We now have is_nested_ctxt(), which is more obvious.
> + kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
> + return 1;
> + }
> +
> + /* We shouldn't have generated a trap in this case */
> + WARN_ON_ONCE(1);
> kvm_inject_undefined(vcpu);
> return 1;
> }
>
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v15 3/6] KVM: arm64: Forward GCS exceptions to nested guests
2025-08-20 22:15 ` Marc Zyngier
@ 2025-08-21 21:25 ` Mark Brown
0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2025-08-21 21:25 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: 945 bytes --]
On Wed, Aug 20, 2025 at 11:15:25PM +0100, Marc Zyngier wrote:
> Mark Brown <broonie@kernel.org> wrote:
> > GCS can generate exceptions with an EC of 0x2D (GCS Data Check
> > Exception) when data validation checks fail. When running a nested
> > guest which has access to GCS such exceptions can be directed from EL0
> > to EL2 and therefore need to be forwarded to the guest hypervisor, add
> > handling for this.
> Why is it so? A GCS exception from EL0 should be routed to EL1, no
> matter what (either this is an L1 guest with EL1 pretending to be EL2,
> or this is an L2 guest that has its own EL1).
> Can you describe the case where we need to reinject the exception?
I think I'd got myself confused while looking at the HCR_EL2.TGE case
thinking we enabled that in some case. I can't now see what I was
looking at there, pretty sure I'm just mistaken - thanks for spotting
that, unless I work out what I was thinking I'll drop this.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v15 4/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (2 preceding siblings ...)
2025-08-20 14:14 ` [PATCH v15 3/6] KVM: arm64: Forward GCS exceptions to nested guests Mark Brown
@ 2025-08-20 14:14 ` Mark Brown
2025-08-20 22:02 ` Marc Zyngier
2025-08-20 14:14 ` [PATCH v15 5/6] KVM: arm64: Allow GCS to be enabled for guests Mark Brown
` (2 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2025-08-20 14:14 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 RWTXBY 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..46e1d0c3038c 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 enter_exception64_gcs(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 RWTXBY, D.1.3.2 in K.a.
+ new |= enter_exception64_gcs(vcpu, mode, target_mode);
+
new |= PSR_D_BIT;
new |= PSR_A_BIT;
new |= PSR_I_BIT;
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v15 4/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception
2025-08-20 14:14 ` [PATCH v15 4/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception Mark Brown
@ 2025-08-20 22:02 ` Marc Zyngier
2025-08-21 20:44 ` Mark Brown
0 siblings, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 22:02 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 Wed, 20 Aug 2025 15:14:44 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> As per DDI 0487 RWTXBY we need to manage PSTATE.EXLOCK when entering an
Nit: please use an underscore between the type of a statement and its
"name", as it makes it a bit more readable (R_WTXBY).
> 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..46e1d0c3038c 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 enter_exception64_gcs(struct kvm_vcpu *vcpu,
> + unsigned long mode,
> + unsigned long target_mode)
A more appropriate name would be compute_exlock().
> +{
> + 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 RWTXBY, D.1.3.2 in K.a.
> + new |= enter_exception64_gcs(vcpu, mode, target_mode);
> +
> new |= PSR_D_BIT;
> new |= PSR_A_BIT;
> new |= PSR_I_BIT;
>
But that's not the only case where we have to deal with EXLOCK, is it?
What of ERET and its PAuth variants? R_TYTWB says:
<quote>
If in AArch64 state, any of the following situations can cause an
illegal exception return:
[...]
- If the Effective value of GCSCR_ELx.EXLOCKEN is 1 and PSTATE.EXLOCK
is 0, the execution of an exception return instruction to return to
the current Exception level ELx.
</quote>
My reading of the spec is that this needs handling.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v15 4/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception
2025-08-20 22:02 ` Marc Zyngier
@ 2025-08-21 20:44 ` Mark Brown
0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2025-08-21 20:44 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: 1370 bytes --]
On Wed, Aug 20, 2025 at 11:02:11PM +0100, Marc Zyngier wrote:
> Mark Brown <broonie@kernel.org> wrote:
> > As per DDI 0487 RWTXBY we need to manage PSTATE.EXLOCK when entering an
> Nit: please use an underscore between the type of a statement and its
> "name", as it makes it a bit more readable (R_WTXBY).
Updated as you request. I have seen both usages - the non _ version
plays nicer with searching the PDF to find the rules since you can just
copy it directly into a PDF viewer.
> > + // EL, or to GCSCR_ELx.EXLOCKEN for an exception to the same
> > + // exception level. See ARM DDI 0487 RWTXBY, D.1.3.2 in K.a.
> > + new |= enter_exception64_gcs(vcpu, mode, target_mode);
> > +
> > new |= PSR_D_BIT;
> > new |= PSR_A_BIT;
> > new |= PSR_I_BIT;
> But that's not the only case where we have to deal with EXLOCK, is it?
> What of ERET and its PAuth variants? R_TYTWB says:
> <quote>
> If in AArch64 state, any of the following situations can cause an
> illegal exception return:
>
> [...]
>
> - If the Effective value of GCSCR_ELx.EXLOCKEN is 1 and PSTATE.EXLOCK
> is 0, the execution of an exception return instruction to return to
> the current Exception level ELx.
> </quote>
> My reading of the spec is that this needs handling.
Am I right in thinking that this handling is needed for the NV case
only?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v15 5/6] KVM: arm64: Allow GCS to be enabled for guests
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (3 preceding siblings ...)
2025-08-20 14:14 ` [PATCH v15 4/6] KVM: arm64: Set PSTATE.EXLOCK when entering an exception Mark Brown
@ 2025-08-20 14:14 ` Mark Brown
2025-08-20 22:18 ` Marc Zyngier
2025-08-20 14:14 ` [PATCH v15 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list Mark Brown
2025-08-20 22:30 ` [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Marc Zyngier
6 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2025-08-20 14:14 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/sys_regs.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 592cb5d6497a..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);
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v15 5/6] KVM: arm64: Allow GCS to be enabled for guests
2025-08-20 14:14 ` [PATCH v15 5/6] KVM: arm64: Allow GCS to be enabled for guests Mark Brown
@ 2025-08-20 22:18 ` Marc Zyngier
0 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 22:18 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 Wed, 20 Aug 2025 15:14:45 +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/sys_regs.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 592cb5d6497a..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);
>
Still disabled for NV in limit_nv_id_reg().
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v15 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (4 preceding siblings ...)
2025-08-20 14:14 ` [PATCH v15 5/6] KVM: arm64: Allow GCS to be enabled for guests Mark Brown
@ 2025-08-20 14:14 ` Mark Brown
2025-08-20 22:30 ` [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Marc Zyngier
6 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2025-08-20 14:14 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.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS
2025-08-20 14:14 [PATCH v15 0/6] KVM: arm64: Provide guest support for GCS Mark Brown
` (5 preceding siblings ...)
2025-08-20 14:14 ` [PATCH v15 6/6] KVM: selftests: arm64: Add GCS registers to get-reg-list Mark Brown
@ 2025-08-20 22:30 ` Marc Zyngier
6 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2025-08-20 22: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, Thiago Jung Bauermann
On Wed, 20 Aug 2025 15:14:40 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> The arm64 Guarded Control Stack (GCS) feature provides support for
> hardware protected stacks of return addresses, intended to provide
> hardening against return oriented programming (ROP) attacks and to make
> it easier to gather call stacks for applications such as profiling.
>
> When GCS is active a secondary stack called the Guarded Control Stack is
> maintained, protected with a memory attribute which means that it can
> only be written with specific GCS operations. The current GCS pointer
> can not be directly written to by userspace. When a BL is executed the
> value stored in LR is also pushed onto the GCS, and when a RET is
> executed the top of the GCS is popped and compared to LR with a fault
> being raised if the values do not match. GCS operations may only be
> performed on GCS pages, a data abort is generated if they are not.
>
> The combination of hardware enforcement and lack of extra instructions
> in the function entry and exit paths should result in something which
> has less overhead and is more difficult to attack than a purely software
> implementation like clang's shadow stacks.
>
> This series implements support for managing GCS for KVM guests, it also
> includes a fix for S1PIE which has also been sent separately as this
> feature is a dependency for GCS. It is based on:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/gcs
>
Is this cover letter accurate? I don't see any PIE-related patch, and
you indicate this being rebased on 6.17-rc1...
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 17+ messages in thread