Skip to contentSkip to conversation

KVM: arm64: Add support for FEAT_IDST

PATCH Superseded Marc Zyngier 4 participants 17 messages Nov 26, 2025 – Nov 27, 2025

Subsystems (4)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Marc Zyngier

author maintainer
#0 lore raw

v2 cover KVM: arm64: Add support for FEAT_IDST

FEAT_IDST appeared in ARMv8.4, and allows ID registers to be trapped if they are not implemented. This only concerns 3 registers (GMID_EL1, CCSIDR2_EL1 and SMIDR_EL1), which are part of features that may not be exposed to the guest even if present on the host.

For these registers, the HW should report them with EC=0x18, even if the feature isn't implemented.

Add support for this feature by handling these registers in a specific way and implementing GMID_EL1 support in the process. A very basic selftest checks that these registers behave as expected.

* From v1: [1]

- Fixed commit message in patch #4 (Ben)
- Collected RB, with thanks (Joey)

[1] https://lore.kernel.org/r/[email protected]

Marc Zyngier (5):
KVM: arm64: Add routing/handling for GMID_EL1
KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE
KVM: arm64: Add a generic synchronous exception injection primitive
KVM: arm64: Report optional ID register traps with a 0x18 syndrome
KVM: arm64: selftests: Add a test for FEAT_IDST

 arch/arm64/include/asm/kvm_emulate.h          |   1 +
 arch/arm64/kvm/emulate-nested.c               |   8 ++
 arch/arm64/kvm/inject_fault.c                 |  10 +-
 arch/arm64/kvm/sys_regs.c                     |  17 ++-
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../testing/selftests/kvm/arm64/idreg-idst.c  | 117 ++++++++++++++++++
 6 files changed, 149 insertions(+), 5 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/arm64/idreg-idst.c
Signature · 1 line
2.47.3
author maintainer
#1 lore raw

PATCH v2 1/5 KVM: arm64: Add routing/handling for GMID_EL1

HCR_EL2.TID5 is currently ignored by the trap routing infrastructure, and we currently don't handle GMID_EL1 either (the only register trapped by TID5).

Wire both the trap bit and a default UNDEF handler.

---
 arch/arm64/kvm/emulate-nested.c | 8 ++++++++
 arch/arm64/kvm/sys_regs.c       | 1 +
 2 files changed, 9 insertions(+)
arch/arm64/kvm/emulate-nested.c +8 -0
index 834f13fb1fb7d..616eb6ad68701 100644
@@ -70,6 +70,7 @@ enum cgt_group_id {
 	CGT_HCR_ENSCXT,
 	CGT_HCR_TTLBIS,
 	CGT_HCR_TTLBOS,
+	CGT_HCR_TID5,
 
 	CGT_MDCR_TPMCR,
 	CGT_MDCR_TPM,
@@ -308,6 +309,12 @@ static const struct trap_bits coarse_trap_bits[] = {
 		.mask		= HCR_TTLBOS,
 		.behaviour	= BEHAVE_FORWARD_RW,
 	},
+	[CGT_HCR_TID5] = {
+		.index		= HCR_EL2,
+		.value		= HCR_TID5,
+		.mask		= HCR_TID5,
+		.behaviour	= BEHAVE_FORWARD_RW,
+	},
 	[CGT_MDCR_TPMCR] = {
 		.index		= MDCR_EL2,
 		.value		= MDCR_EL2_TPMCR,
@@ -665,6 +672,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
 	SR_TRAP(SYS_CCSIDR2_EL1,	CGT_HCR_TID2_TID4),
 	SR_TRAP(SYS_CLIDR_EL1,		CGT_HCR_TID2_TID4),
 	SR_TRAP(SYS_CSSELR_EL1,		CGT_HCR_TID2_TID4),
+	SR_TRAP(SYS_GMID_EL1,		CGT_HCR_TID5),
 	SR_RANGE_TRAP(SYS_ID_PFR0_EL1,
 		      sys_reg(3, 0, 0, 7, 7), CGT_HCR_TID3),
 	SR_TRAP(SYS_ICC_SGI0R_EL1,	CGT_HCR_IMO_FMO_ICH_HCR_TC),
arch/arm64/kvm/sys_regs.c +1 -0
index 8ae2bca816148..9e4c46fbfd802 100644
@@ -3400,6 +3400,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	{ SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1,
 	  .set_user = set_clidr, .val = ~CLIDR_EL1_RES0 },
 	{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
+	{ SYS_DESC(SYS_GMID_EL1), undef_access },
 	{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
 	IMPLEMENTATION_ID(AIDR_EL1, GENMASK_ULL(63, 0)),
 	{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
Signature · 1 line
2.47.3
author maintainer
#2 lore raw

PATCH v2 2/5 KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE

In reply to Marc Zyngier

If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5 to force GMID_EL1 being trapped.

---
 arch/arm64/kvm/sys_regs.c | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/kvm/sys_regs.c +2 -0
index 9e4c46fbfd802..2ca6862e935b5 100644
@@ -5561,6 +5561,8 @@ static void vcpu_set_hcr(struct kvm_vcpu *vcpu)
 
 	if (kvm_has_mte(vcpu->kvm))
 		vcpu->arch.hcr_el2 |= HCR_ATA;
+	else if (id_aa64pfr1_mte(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))
+		vcpu->arch.hcr_el2 |= HCR_TID5;
 
 	/*
 	 * In the absence of FGT, we cannot independently trap TLBI
Signature · 1 line
2.47.3
Reviewed-by on v2 2/5
#3 lore raw

Re: [PATCH v2 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE

Hi Marc,

Quoted 14 lines · Marc Zyngier

If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5 to force GMID_EL1 being trapped.

---
 arch/arm64/kvm/sys_regs.c | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/kvm/sys_regs.c +0 -0
index 9e4c46fbfd802..2ca6862e935b5 100644

arch/arm64/kvm/sys_regs.c static void vcpu_set_hcr(struct kvm_vcpu *vcpu) · line 5565

Quoted 5 lines
arch/arm64/kvm/sys_regs.c +2 -0
@@ -5561,6 +5561,8 @@ static void vcpu_set_hcr(struct kvm_vcpu *vcpu)
 
 	if (kvm_has_mte(vcpu->kvm))
 		vcpu->arch.hcr_el2 |= HCR_ATA;
+	else if (id_aa64pfr1_mte(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))
+		vcpu->arch.hcr_el2 |= HCR_TID5;
Quoted 6 lines
arch/arm64/kvm/sys_regs.c +0 -1
 	/*
 	 * In the absence of FGT, we cannot independently trap TLBI
--

2.47.3

maintainer
#4 lore raw

Re: [PATCH v2 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE

In reply to Marc Zyngier
Quoted 14 lines · Marc Zyngier

If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5 to force GMID_EL1 being trapped.

---
 arch/arm64/kvm/sys_regs.c | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/kvm/sys_regs.c +0 -0
index 9e4c46fbfd802..2ca6862e935b5 100644

arch/arm64/kvm/sys_regs.c static void vcpu_set_hcr(struct kvm_vcpu *vcpu) · line 5564

Quoted 4 lines
arch/arm64/kvm/sys_regs.c +1 -0
@@ -5561,6 +5561,8 @@ static void vcpu_set_hcr(struct kvm_vcpu *vcpu)
 
 	if (kvm_has_mte(vcpu->kvm))
 		vcpu->arch.hcr_el2 |= HCR_ATA;
+	else if (id_aa64pfr1_mte(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))

This helper is ugly!

arch/arm64/kvm/sys_regs.c static void vcpu_set_hcr(struct kvm_vcpu *vcpu) · line 5565

Quoted 1 line
arch/arm64/kvm/sys_regs.c +1 -0
+		vcpu->arch.hcr_el2 |= HCR_TID5;

How about setting the trap unconditionally when !kvm_has_mte()? Even in the case of asymmetry we'd want GMID_EL1 to trap.

Thanks,
Oliver

author maintainer
#5 lore raw

Re: [PATCH v2 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE

Quoted 17 lines · Oliver Upton
Quoted 15 lines · Marc Zyngier

If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5 to force GMID_EL1 being trapped.

---
 arch/arm64/kvm/sys_regs.c | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/kvm/sys_regs.c +0 -0
index 9e4c46fbfd802..2ca6862e935b5 100644
@@ -5561,6 +5561,8 @@ static void vcpu_set_hcr(struct kvm_vcpu *vcpu)
 
Quoted 5 lines

arch/arm64/kvm/sys_regs.c static void vcpu_set_hcr(struct kvm_vcpu *vcpu) · line 5564

Quoted 3 lines
arch/arm64/kvm/sys_regs.c +1 -0
 	if (kvm_has_mte(vcpu->kvm))
 		vcpu->arch.hcr_el2 |= HCR_ATA;
+	else if (id_aa64pfr1_mte(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))

This helper is ugly!

You think? :D

Quoted 5 lines

arch/arm64/kvm/sys_regs.c static void vcpu_set_hcr(struct kvm_vcpu *vcpu) · line 5565

Quoted 2 lines
arch/arm64/kvm/sys_regs.c +1 -0
+		vcpu->arch.hcr_el2 |= HCR_TID5;

How about setting the trap unconditionally when !kvm_has_mte()? Even in the case of asymmetry we'd want GMID_EL1 to trap.

Yup, that's a good point. I'll fix that.

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
author maintainer
#6 lore raw

PATCH v2 3/5 KVM: arm64: Add a generic synchronous exception injection primitive

In reply to Marc Zyngier

Maybe in a surprising way, we don't currently have a generic way to inject a synchronous exception at the EL the vcpu is currently running at.

Extract such primitive from the UNDEF injection code.

---
 arch/arm64/include/asm/kvm_emulate.h |  1 +
 arch/arm64/kvm/inject_fault.c        | 10 +++++++---
 2 files changed, 8 insertions(+), 3 deletions(-)
arch/arm64/include/asm/kvm_emulate.h +1 -0
index c9eab316398e2..df20d47f0d256 100644
@@ -45,6 +45,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
 void kvm_skip_instr32(struct kvm_vcpu *vcpu);
 
 void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr);
 int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
 int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
 void kvm_inject_size_fault(struct kvm_vcpu *vcpu);
arch/arm64/kvm/inject_fault.c +7 -3
index dfcd66c655179..7102424a3fa5e 100644
@@ -162,12 +162,16 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
 	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
 }
 
+void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr)
+{
+	pend_sync_exception(vcpu);
+	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
+}
+
 static void inject_undef64(struct kvm_vcpu *vcpu)
 {
 	u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
 
-	pend_sync_exception(vcpu);
-
 	/*
 	 * Build an unknown exception, depending on the instruction
 	 * set.
@@ -175,7 +179,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
 	if (kvm_vcpu_trap_il_is32bit(vcpu))
 		esr |= ESR_ELx_IL;
 
-	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
+	kvm_inject_sync(vcpu, esr);
 }
 
 #define DFSR_FSC_EXTABT_LPAE	0x10
Signature · 1 line
2.47.3
Reviewed-by on v2 3/5
#7 lore raw

Re: [PATCH v2 3/5] KVM: arm64: Add a generic synchronous exception injection primitive

Hi Marc,

Quoted 11 lines · Marc Zyngier

Maybe in a surprising way, we don't currently have a generic way to inject a synchronous exception at the EL the vcpu is currently running at.

Extract such primitive from the UNDEF injection code.

---
 arch/arm64/include/asm/kvm_emulate.h |  1 +
 arch/arm64/kvm/inject_fault.c        | 10 +++++++---
 2 files changed, 8 insertions(+), 3 deletions(-)

LGTM.

Thanks,

Ben

Reviewed-by on v2 3/5
#8 lore raw

Re: [PATCH v2 3/5] KVM: arm64: Add a generic synchronous exception injection primitive

In reply to Marc Zyngier
Quoted 3 lines · Marc Zyngier

Maybe in a surprising way, we don't currently have a generic way to inject a synchronous exception at the EL the vcpu is currently running at.

Hi Marc,

Thanks for bring this in generic way.

Quoted 56 lines

Extract such primitive from the UNDEF injection code.

---
 arch/arm64/include/asm/kvm_emulate.h |  1 +
 arch/arm64/kvm/inject_fault.c        | 10 +++++++---
 2 files changed, 8 insertions(+), 3 deletions(-)
arch/arm64/include/asm/kvm_emulate.h +1 -0
index c9eab316398e2..df20d47f0d256 100644
@@ -45,6 +45,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
 void kvm_skip_instr32(struct kvm_vcpu *vcpu);
 
 void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr);
 int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
 int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
 void kvm_inject_size_fault(struct kvm_vcpu *vcpu);
arch/arm64/kvm/inject_fault.c +7 -4
index dfcd66c655179..7102424a3fa5e 100644
@@ -162,12 +162,16 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
 	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
 }
 
+void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr)
+{
+	pend_sync_exception(vcpu);
+	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
+}
+
 static void inject_undef64(struct kvm_vcpu *vcpu)
 {
 	u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
 
-	pend_sync_exception(vcpu);
-
 	/*
 	 * Build an unknown exception, depending on the instruction
 	 * set.
@@ -175,7 +179,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
 	if (kvm_vcpu_trap_il_is32bit(vcpu))
 		esr |= ESR_ELx_IL;
 
-	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
+	kvm_inject_sync(vcpu, esr);
 }
 
 #define DFSR_FSC_EXTABT_LPAE	0x10
--

2.47.3

author maintainer
#9 lore raw

PATCH v2 4/5 KVM: arm64: Report optional ID register traps with a 0x18 syndrome

In reply to Marc Zyngier

With FEAT_IDST, unimplemented system registers in the feature ID space must be reported using EC=0x18 at the closest handling EL, rather than with an UNDEF.

Most of these system registers are always implemented thanks to their dependency on FEAT_AA64, except for a set of (currently) three registers:
GMID_EL1 (depending on MTE2), CCSIDR2_EL1 (depending on FEAT_CCIDX), and SMIDR_EL1 (depending on SME).

For these three registers, report their trap as EC=0x18 if they end-up trapping into KVM and that FEAT_IDST is not implemented in the guest. Otherwise, just make them UNDEF.

---
 arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/arm64/kvm/sys_regs.c +13 -3
index 2ca6862e935b5..7705f703e7c6d 100644
@@ -82,6 +82,16 @@ static bool write_to_read_only(struct kvm_vcpu *vcpu,
 			"sys_reg write to read-only register");
 }
 
+static bool idst_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
+{
+	if (kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, 0x0))
+		return undef_access(vcpu, p, r);
+
+	kvm_inject_sync(vcpu, kvm_vcpu_get_esr(vcpu));
+	return false;
+}
+
 enum sr_loc_attr {
 	SR_LOC_MEMORY	= 0,	  /* Register definitely in memory */
 	SR_LOC_LOADED	= BIT(0), /* Register on CPU, unless it cannot */
@@ -3399,9 +3409,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	{ SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
 	{ SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1,
 	  .set_user = set_clidr, .val = ~CLIDR_EL1_RES0 },
-	{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
-	{ SYS_DESC(SYS_GMID_EL1), undef_access },
-	{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
+	{ SYS_DESC(SYS_CCSIDR2_EL1), idst_access },
+	{ SYS_DESC(SYS_GMID_EL1), idst_access },
+	{ SYS_DESC(SYS_SMIDR_EL1), idst_access },
 	IMPLEMENTATION_ID(AIDR_EL1, GENMASK_ULL(63, 0)),
 	{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
 	ID_FILTERED(CTR_EL0, ctr_el0,
Signature · 1 line
2.47.3
Reviewed-by on v2 4/5
#10 lore raw

Re: [PATCH v2 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome

Hi Marc,

Quoted 4 lines · Marc Zyngier

With FEAT_IDST, unimplemented system registers in the feature ID space must be reported using EC=0x18 at the closest handling EL, rather than with an UNDEF.

Quoted 8 lines

Most of these system registers are always implemented thanks to their dependency on FEAT_AA64, except for a set of (currently) three registers:
GMID_EL1 (depending on MTE2), CCSIDR2_EL1 (depending on FEAT_CCIDX), and SMIDR_EL1 (depending on SME).

For these three registers, report their trap as EC=0x18 if they end-up trapping into KVM and that FEAT_IDST is not implemented in the guest. Otherwise, just make them UNDEF.

Missed it before but there is a stray 'not' in there. You get the EC=0x18 trap if FEAT_IDST is implemented.

Quoted 5 lines
---
 arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

The code looks good.

Reviewed-by Ben Horgan

Thanks,

Ben

Reviewed-by
#11 lore raw

Re: [PATCH v2 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome

Quoted 20 lines · Ben Horgan

Hi Marc,

Quoted 4 lines · Marc Zyngier

With FEAT_IDST, unimplemented system registers in the feature ID space must be reported using EC=0x18 at the closest handling EL, rather than with an UNDEF.

Quoted 8 lines

Most of these system registers are always implemented thanks to their dependency on FEAT_AA64, except for a set of (currently) three registers:
GMID_EL1 (depending on MTE2), CCSIDR2_EL1 (depending on FEAT_CCIDX), and SMIDR_EL1 (depending on SME).

For these three registers, report their trap as EC=0x18 if they end-up trapping into KVM and that FEAT_IDST is not implemented in the guest. Otherwise, just make them UNDEF.

Missed it before but there is a stray 'not' in there. You get the EC=0x18 trap if FEAT_IDST is implemented.

Quoted 1 line
Quoted 8 lines
Quoted 4 lines
---
 arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

The code looks good.

Reviewed-by Ben Horgan

Just to complete that tag.

Quoted 6 lines

Thanks,

Ben

Signature · 3 lines
Thanks,

Ben
Reviewed-by on v2 4/5
#12 lore raw

Re: [PATCH v2 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome

In reply to Marc Zyngier
Quoted 23 lines · Marc Zyngier

With FEAT_IDST, unimplemented system registers in the feature ID space must be reported using EC=0x18 at the closest handling EL, rather than with an UNDEF.

Most of these system registers are always implemented thanks to their dependency on FEAT_AA64, except for a set of (currently) three registers:
GMID_EL1 (depending on MTE2), CCSIDR2_EL1 (depending on FEAT_CCIDX), and SMIDR_EL1 (depending on SME).

For these three registers, report their trap as EC=0x18 if they end-up trapping into KVM and that FEAT_IDST is not implemented in the guest. Otherwise, just make them UNDEF.

---
 arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/arm64/kvm/sys_regs.c +0 -0
index 2ca6862e935b5..7705f703e7c6d 100644

arch/arm64/kvm/sys_regs.c static bool write_to_read_only(struct kvm_vcpu *vcpu, · line 88

Quoted 7 lines
arch/arm64/kvm/sys_regs.c +4 -0
@@ -82,6 +82,16 @@ static bool write_to_read_only(struct kvm_vcpu *vcpu,
 			"sys_reg write to read-only register");
 }
 
+static bool idst_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
+{
+	if (kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, 0x0))

Hi Marc,

Minor: maybe beter readability if use NI instead of 0x0, just like things in feat_nv2() below, but depends on you.

static bool feat_nv2(struct kvm *kvm)

{
	return ((kvm_has_feat(kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY) &&
		 kvm_has_feat_enum(kvm, ID_AA64MMFR2_EL1, NV, NI)) ||
		kvm_has_feat(kvm, ID_AA64MMFR2_EL1, NV, NV2));
}

For others(except the "not" mentioned by Ben):

Quoted 25 lines
arch/arm64/kvm/sys_regs.c +9 -4
+		return undef_access(vcpu, p, r);
+
+	kvm_inject_sync(vcpu, kvm_vcpu_get_esr(vcpu));
+	return false;
+}
+
 enum sr_loc_attr {
 	SR_LOC_MEMORY	= 0,	  /* Register definitely in memory */
 	SR_LOC_LOADED	= BIT(0), /* Register on CPU, unless it cannot */
@@ -3399,9 +3409,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	{ SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
 	{ SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1,
 	  .set_user = set_clidr, .val = ~CLIDR_EL1_RES0 },
-	{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
-	{ SYS_DESC(SYS_GMID_EL1), undef_access },
-	{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
+	{ SYS_DESC(SYS_CCSIDR2_EL1), idst_access },
+	{ SYS_DESC(SYS_GMID_EL1), idst_access },
+	{ SYS_DESC(SYS_SMIDR_EL1), idst_access },
 	IMPLEMENTATION_ID(AIDR_EL1, GENMASK_ULL(63, 0)),
 	{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
 	ID_FILTERED(CTR_EL0, ctr_el0,
--

2.47.3

maintainer
#13 lore raw

Re: [PATCH v2 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome

Quoted 34 lines · Yao Yuan
Quoted 23 lines · Marc Zyngier

With FEAT_IDST, unimplemented system registers in the feature ID space must be reported using EC=0x18 at the closest handling EL, rather than with an UNDEF.

Most of these system registers are always implemented thanks to their dependency on FEAT_AA64, except for a set of (currently) three registers:
GMID_EL1 (depending on MTE2), CCSIDR2_EL1 (depending on FEAT_CCIDX), and SMIDR_EL1 (depending on SME).

For these three registers, report their trap as EC=0x18 if they end-up trapping into KVM and that FEAT_IDST is not implemented in the guest. Otherwise, just make them UNDEF.

---
 arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/arm64/kvm/sys_regs.c +0 -0
index 2ca6862e935b5..7705f703e7c6d 100644

arch/arm64/kvm/sys_regs.c static bool write_to_read_only(struct kvm_vcpu *vcpu, · line 88

Quoted 7 lines
arch/arm64/kvm/sys_regs.c +4 -0
@@ -82,6 +82,16 @@ static bool write_to_read_only(struct kvm_vcpu *vcpu,
 			"sys_reg write to read-only register");
 }
 
+static bool idst_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
+{
+	if (kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, 0x0))

Hi Marc,

Quoted 2 lines

Minor: maybe beter readability if use NI instead of 0x0, just like things in feat_nv2() below, but depends on you.

+1, using the ESR value as an identifier in the sysreg tables is just terrible. This reads like a literal.

Thanks,
Oliver

author maintainer
#14 lore raw

Re: [PATCH v2 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome

Quoted 36 lines · Oliver Upton
Quoted 34 lines · Yao Yuan
Quoted 23 lines · Marc Zyngier

With FEAT_IDST, unimplemented system registers in the feature ID space must be reported using EC=0x18 at the closest handling EL, rather than with an UNDEF.

Most of these system registers are always implemented thanks to their dependency on FEAT_AA64, except for a set of (currently) three registers:
GMID_EL1 (depending on MTE2), CCSIDR2_EL1 (depending on FEAT_CCIDX), and SMIDR_EL1 (depending on SME).

For these three registers, report their trap as EC=0x18 if they end-up trapping into KVM and that FEAT_IDST is not implemented in the guest. Otherwise, just make them UNDEF.

---
 arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/arm64/kvm/sys_regs.c +0 -0
index 2ca6862e935b5..7705f703e7c6d 100644

arch/arm64/kvm/sys_regs.c static bool write_to_read_only(struct kvm_vcpu *vcpu, · line 88

Quoted 7 lines
arch/arm64/kvm/sys_regs.c +4 -0
@@ -82,6 +82,16 @@ static bool write_to_read_only(struct kvm_vcpu *vcpu,
 			"sys_reg write to read-only register");
 }
 
+static bool idst_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
+{
+	if (kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, 0x0))

Hi Marc,

Quoted 5 lines
Quoted 2 lines

Minor: maybe beter readability if use NI instead of 0x0, just like things in feat_nv2() below, but depends on you.

+1, using the ESR value as an identifier in the sysreg tables is just terrible. This reads like a literal.

Yeah, I was a bit shocked when I found how it was encoded in the sysreg file, but kept it as is. Since there is a consensus that this is pretty lame, I'll add a patch repainting it using the usual NI/IMP identifiers.

Thanks,

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
author maintainer
#15 lore raw

PATCH v2 5/5 KVM: arm64: selftests: Add a test for FEAT_IDST

In reply to Marc Zyngier

Add a very basic test checking that FEAT_IDST actually works for the {GMID,SMIDR,CSSIDR2}_EL1 registers.

---
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../testing/selftests/kvm/arm64/idreg-idst.c  | 117 ++++++++++++++++++
 2 files changed, 118 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/arm64/idreg-idst.c
tools/testing/selftests/kvm/Makefile.kvm +1 -0
index 148d427ff24be..fa44e6d9afc35 100644
@@ -171,6 +171,7 @@ TEST_GEN_PROGS_arm64 += arm64/vgic_irq
 TEST_GEN_PROGS_arm64 += arm64/vgic_lpi_stress
 TEST_GEN_PROGS_arm64 += arm64/vpmu_counter_access
 TEST_GEN_PROGS_arm64 += arm64/no-vgic-v3
+TEST_GEN_PROGS_arm64 += arm64/idreg-idst
 TEST_GEN_PROGS_arm64 += arm64/kvm-uuid
 TEST_GEN_PROGS_arm64 += access_tracking_perf_test
 TEST_GEN_PROGS_arm64 += arch_timer
tools/testing/selftests/kvm/arm64/idreg-idst.c new file +117 -0

117 lines not on this page · raw message

Signature · 1 line
2.47.3
author maintainer
#16 lore raw
In reply to Marc Zyngier
Quoted 6 lines · Marc Zyngier

FEAT_IDST appeared in ARMv8.4, and allows ID registers to be trapped if they are not implemented. This only concerns 3 registers (GMID_EL1, CCSIDR2_EL1 and SMIDR_EL1), which are part of features that may not be exposed to the guest even if present on the host.

Quoted 6 lines

For these registers, the HW should report them with EC=0x18, even if the feature isn't implemented.

Add support for this feature by handling these registers in a specific way and implementing GMID_EL1 support in the process. A very basic selftest checks that these registers behave as expected.

Except that said selftest indicates that pKVM doesn't do the right thing and requires similar rework. I now have some patches to address it, and will repost the series sometime next week.

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.