* [PATCH 1/5] KVM: arm64: Add routing/handling for GMID_EL1
2025-11-20 13:31 [PATCH 0/5] KVM: arm64: Add support for FEAT_IDST Marc Zyngier
@ 2025-11-20 13:31 ` Marc Zyngier
2025-11-20 13:31 ` [PATCH 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE Marc Zyngier
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2025-11-20 13:31 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu
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.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/emulate-nested.c | 8 ++++++++
arch/arm64/kvm/sys_regs.c | 1 +
2 files changed, 9 insertions(+)
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 834f13fb1fb7d..616eb6ad68701 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -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),
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e67eb39ddc118..84e6f04220589 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -3397,6 +3397,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 },
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE
2025-11-20 13:31 [PATCH 0/5] KVM: arm64: Add support for FEAT_IDST Marc Zyngier
2025-11-20 13:31 ` [PATCH 1/5] KVM: arm64: Add routing/handling for GMID_EL1 Marc Zyngier
@ 2025-11-20 13:31 ` Marc Zyngier
2025-11-20 14:34 ` Joey Gouly
2025-11-20 13:32 ` [PATCH 3/5] KVM: arm64: Add a generic synchronous exception injection primitive Marc Zyngier
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Marc Zyngier @ 2025-11-20 13:31 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu
If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5
to force GMID_EL1 being trapped.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 84e6f04220589..40f32b017f107 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -5558,6 +5558,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
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE
2025-11-20 13:31 ` [PATCH 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE Marc Zyngier
@ 2025-11-20 14:34 ` Joey Gouly
2025-11-20 14:51 ` Marc Zyngier
0 siblings, 1 reply; 10+ messages in thread
From: Joey Gouly @ 2025-11-20 14:34 UTC (permalink / raw)
To: Marc Zyngier
Cc: kvmarm, kvm, linux-arm-kernel, Suzuki K Poulose, Oliver Upton,
Zenghui Yu
On Thu, Nov 20, 2025 at 01:31:59PM +0000, Marc Zyngier wrote:
> If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5
> to force GMID_EL1 being trapped.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> arch/arm64/kvm/sys_regs.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 84e6f04220589..40f32b017f107 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -5558,6 +5558,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;
This is because we want to enable the trapping regardless of CONFIG_ARM64_MTE
(so we can't use system_supports_mte()).
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
>
> /*
> * In the absence of FGT, we cannot independently trap TLBI
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE
2025-11-20 14:34 ` Joey Gouly
@ 2025-11-20 14:51 ` Marc Zyngier
0 siblings, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2025-11-20 14:51 UTC (permalink / raw)
To: Joey Gouly
Cc: kvmarm, kvm, linux-arm-kernel, Suzuki K Poulose, Oliver Upton,
Zenghui Yu
On Thu, 20 Nov 2025 14:34:19 +0000,
Joey Gouly <joey.gouly@arm.com> wrote:
>
> On Thu, Nov 20, 2025 at 01:31:59PM +0000, Marc Zyngier wrote:
> > If our host has MTE, but the guest doesn't, make sure we set HCR_EL2.TID5
> > to force GMID_EL1 being trapped.
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > arch/arm64/kvm/sys_regs.c | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > index 84e6f04220589..40f32b017f107 100644
> > --- a/arch/arm64/kvm/sys_regs.c
> > +++ b/arch/arm64/kvm/sys_regs.c
> > @@ -5558,6 +5558,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;
>
> This is because we want to enable the trapping regardless of CONFIG_ARM64_MTE
> (so we can't use system_supports_mte()).
Indeed. In general, we cannot rely on the kernel's own configuration,
since the guest sees most of the actual HW.
>
> Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Thanks!
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/5] KVM: arm64: Add a generic synchronous exception injection primitive
2025-11-20 13:31 [PATCH 0/5] KVM: arm64: Add support for FEAT_IDST Marc Zyngier
2025-11-20 13:31 ` [PATCH 1/5] KVM: arm64: Add routing/handling for GMID_EL1 Marc Zyngier
2025-11-20 13:31 ` [PATCH 2/5] KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE Marc Zyngier
@ 2025-11-20 13:32 ` Marc Zyngier
2025-11-20 13:32 ` [PATCH 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome Marc Zyngier
2025-11-20 13:32 ` [PATCH 5/5] KVM: arm64: selftests: Add a test for FEAT_IDST Marc Zyngier
4 siblings, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2025-11-20 13:32 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu
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.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/kvm_emulate.h | 1 +
arch/arm64/kvm/inject_fault.c | 10 +++++++---
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index c9eab316398e2..df20d47f0d256 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -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);
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index dfcd66c655179..7102424a3fa5e 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -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
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome
2025-11-20 13:31 [PATCH 0/5] KVM: arm64: Add support for FEAT_IDST Marc Zyngier
` (2 preceding siblings ...)
2025-11-20 13:32 ` [PATCH 3/5] KVM: arm64: Add a generic synchronous exception injection primitive Marc Zyngier
@ 2025-11-20 13:32 ` Marc Zyngier
2025-11-24 10:41 ` Ben Horgan
2025-11-20 13:32 ` [PATCH 5/5] KVM: arm64: selftests: Add a test for FEAT_IDST Marc Zyngier
4 siblings, 1 reply; 10+ messages in thread
From: Marc Zyngier @ 2025-11-20 13:32 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu
With FEAT_IDST, unimplemented system registers must be reported using
EC=0x18 at the closest handling EL, rather than with an UNDEF.
Most 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.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 40f32b017f107..992137822dcf9 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -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 */
@@ -3396,9 +3406,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
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome
2025-11-20 13:32 ` [PATCH 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome Marc Zyngier
@ 2025-11-24 10:41 ` Ben Horgan
2025-11-24 11:48 ` Marc Zyngier
0 siblings, 1 reply; 10+ messages in thread
From: Ben Horgan @ 2025-11-24 10:41 UTC (permalink / raw)
To: Marc Zyngier, kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu
Hi Marc,
On 11/20/25 13:32, Marc Zyngier wrote:
> With FEAT_IDST, unimplemented system registers must be reported using
> EC=0x18 at the closest handling EL, rather than with an UNDEF.
I think this needs 'in the feature ID space' adding. Something like:
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 system registers are always implemented thanks to their dependency
'Most of these system registers...'
> 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).
I agree that these 3 are currently the only optional system registers in
the feature ID space.
>
> 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.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> arch/arm64/kvm/sys_regs.c | 16 +++++++++++++---
> 1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 40f32b017f107..992137822dcf9 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -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 */
> @@ -3396,9 +3406,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,
Thanks,
Ben
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome
2025-11-24 10:41 ` Ben Horgan
@ 2025-11-24 11:48 ` Marc Zyngier
0 siblings, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2025-11-24 11:48 UTC (permalink / raw)
To: Ben Horgan
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Oliver Upton, Zenghui Yu
On Mon, 24 Nov 2025 10:41:56 +0000,
Ben Horgan <ben.horgan@arm.com> wrote:
>
> Hi Marc,
>
> On 11/20/25 13:32, Marc Zyngier wrote:
> > With FEAT_IDST, unimplemented system registers must be reported using
> > EC=0x18 at the closest handling EL, rather than with an UNDEF.
>
> I think this needs 'in the feature ID space' adding. Something like:
>
> 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.
Ah, good point. I got (slightly) carried away!
I'll fold these updates in.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/5] KVM: arm64: selftests: Add a test for FEAT_IDST
2025-11-20 13:31 [PATCH 0/5] KVM: arm64: Add support for FEAT_IDST Marc Zyngier
` (3 preceding siblings ...)
2025-11-20 13:32 ` [PATCH 4/5] KVM: arm64: Report optional ID register traps with a 0x18 syndrome Marc Zyngier
@ 2025-11-20 13:32 ` Marc Zyngier
4 siblings, 0 replies; 10+ messages in thread
From: Marc Zyngier @ 2025-11-20 13:32 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu
Add a very basic test checking that FEAT_IDST actually works for
the {GMID,SMIDR,CSSIDR2}_EL1 registers.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
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
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 148d427ff24be..fa44e6d9afc35 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -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
diff --git a/tools/testing/selftests/kvm/arm64/idreg-idst.c b/tools/testing/selftests/kvm/arm64/idreg-idst.c
new file mode 100644
index 0000000000000..9ca9f125abdb7
--- /dev/null
+++ b/tools/testing/selftests/kvm/arm64/idreg-idst.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Access all FEAT_IDST-handled registers that depend on more than
+ * just FEAT_AA64, and fail if we don't get an a trap with an 0x18 EC.
+ */
+
+#include <test_util.h>
+#include <kvm_util.h>
+#include <processor.h>
+
+static volatile bool sys64, undef;
+
+#define __check_sr_read(r) \
+ ({ \
+ uint64_t val; \
+ \
+ sys64 = false; \
+ undef = false; \
+ dsb(sy); \
+ val = read_sysreg_s(SYS_ ## r); \
+ val; \
+ })
+
+/* Fatal checks */
+#define check_sr_read(r) \
+ do { \
+ __check_sr_read(r); \
+ __GUEST_ASSERT(!undef, #r " unexpected UNDEF"); \
+ __GUEST_ASSERT(sys64, #r " didn't trap"); \
+ } while(0)
+
+
+static void guest_code(void)
+{
+ check_sr_read(CCSIDR2_EL1);
+ check_sr_read(SMIDR_EL1);
+ check_sr_read(GMID_EL1);
+
+ GUEST_DONE();
+}
+
+static void guest_sys64_handler(struct ex_regs *regs)
+{
+ sys64 = true;
+ undef = false;
+ regs->pc += 4;
+}
+
+static void guest_undef_handler(struct ex_regs *regs)
+{
+ sys64 = false;
+ undef = true;
+ regs->pc += 4;
+}
+
+static void test_run_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ do {
+ vcpu_run(vcpu);
+
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_PRINTF:
+ printf("%s", uc.buffer);
+ break;
+ case UCALL_DONE:
+ break;
+ default:
+ TEST_FAIL("Unknown ucall %lu", uc.cmd);
+ }
+ } while (uc.cmd != UCALL_DONE);
+}
+
+static void test_guest_feat_idst(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+
+ /* This VM has no MTE, no SME, no CCIDX */
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+
+ vm_init_descriptor_tables(vm);
+ vcpu_init_descriptor_tables(vcpu);
+
+ vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+ ESR_ELx_EC_SYS64, guest_sys64_handler);
+ vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+ ESR_ELx_EC_UNKNOWN, guest_undef_handler);
+
+ test_run_vcpu(vcpu);
+
+ kvm_vm_free(vm);
+}
+
+int main(int argc, char *argv[])
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ uint64_t mmfr2;
+
+ test_disable_default_vgic();
+
+ vm = vm_create_with_one_vcpu(&vcpu, NULL);
+ mmfr2 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64MMFR2_EL1));
+ __TEST_REQUIRE(FIELD_GET(ID_AA64MMFR2_EL1_IDS, mmfr2) > 0,
+ "FEAT_IDST not supported");
+ kvm_vm_free(vm);
+
+ test_guest_feat_idst();
+
+ return 0;
+}
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread