Skip to content

Commit b638a9d

Browse files
author
Marc Zyngier
committed
KVM: arm64: selftests: Add a test for FEAT_IDST
Add a very basic test checking that FEAT_IDST actually works for the {GMID,SMIDR,CSSIDR2}_EL1 registers. Link: https://patch.msgid.link/20260108173233.2911955-10-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent 592dc2c commit b638a9d

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

tools/testing/selftests/kvm/Makefile.kvm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ TEST_GEN_PROGS_arm64 += arm64/vgic_irq
175175
TEST_GEN_PROGS_arm64 += arm64/vgic_lpi_stress
176176
TEST_GEN_PROGS_arm64 += arm64/vpmu_counter_access
177177
TEST_GEN_PROGS_arm64 += arm64/no-vgic-v3
178+
TEST_GEN_PROGS_arm64 += arm64/idreg-idst
178179
TEST_GEN_PROGS_arm64 += arm64/kvm-uuid
179180
TEST_GEN_PROGS_arm64 += access_tracking_perf_test
180181
TEST_GEN_PROGS_arm64 += arch_timer
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Access all FEAT_IDST-handled registers that depend on more than
5+
* just FEAT_AA64, and fail if we don't get an a trap with an 0x18 EC.
6+
*/
7+
8+
#include <test_util.h>
9+
#include <kvm_util.h>
10+
#include <processor.h>
11+
12+
static volatile bool sys64, undef;
13+
14+
#define __check_sr_read(r) \
15+
({ \
16+
uint64_t val; \
17+
\
18+
sys64 = false; \
19+
undef = false; \
20+
dsb(sy); \
21+
val = read_sysreg_s(SYS_ ## r); \
22+
val; \
23+
})
24+
25+
/* Fatal checks */
26+
#define check_sr_read(r) \
27+
do { \
28+
__check_sr_read(r); \
29+
__GUEST_ASSERT(!undef, #r " unexpected UNDEF"); \
30+
__GUEST_ASSERT(sys64, #r " didn't trap"); \
31+
} while(0)
32+
33+
34+
static void guest_code(void)
35+
{
36+
check_sr_read(CCSIDR2_EL1);
37+
check_sr_read(SMIDR_EL1);
38+
check_sr_read(GMID_EL1);
39+
40+
GUEST_DONE();
41+
}
42+
43+
static void guest_sys64_handler(struct ex_regs *regs)
44+
{
45+
sys64 = true;
46+
undef = false;
47+
regs->pc += 4;
48+
}
49+
50+
static void guest_undef_handler(struct ex_regs *regs)
51+
{
52+
sys64 = false;
53+
undef = true;
54+
regs->pc += 4;
55+
}
56+
57+
static void test_run_vcpu(struct kvm_vcpu *vcpu)
58+
{
59+
struct ucall uc;
60+
61+
do {
62+
vcpu_run(vcpu);
63+
64+
switch (get_ucall(vcpu, &uc)) {
65+
case UCALL_ABORT:
66+
REPORT_GUEST_ASSERT(uc);
67+
break;
68+
case UCALL_PRINTF:
69+
printf("%s", uc.buffer);
70+
break;
71+
case UCALL_DONE:
72+
break;
73+
default:
74+
TEST_FAIL("Unknown ucall %lu", uc.cmd);
75+
}
76+
} while (uc.cmd != UCALL_DONE);
77+
}
78+
79+
static void test_guest_feat_idst(void)
80+
{
81+
struct kvm_vcpu *vcpu;
82+
struct kvm_vm *vm;
83+
84+
/* This VM has no MTE, no SME, no CCIDX */
85+
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
86+
87+
vm_init_descriptor_tables(vm);
88+
vcpu_init_descriptor_tables(vcpu);
89+
90+
vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
91+
ESR_ELx_EC_SYS64, guest_sys64_handler);
92+
vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
93+
ESR_ELx_EC_UNKNOWN, guest_undef_handler);
94+
95+
test_run_vcpu(vcpu);
96+
97+
kvm_vm_free(vm);
98+
}
99+
100+
int main(int argc, char *argv[])
101+
{
102+
struct kvm_vcpu *vcpu;
103+
struct kvm_vm *vm;
104+
uint64_t mmfr2;
105+
106+
test_disable_default_vgic();
107+
108+
vm = vm_create_with_one_vcpu(&vcpu, NULL);
109+
mmfr2 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64MMFR2_EL1));
110+
__TEST_REQUIRE(FIELD_GET(ID_AA64MMFR2_EL1_IDS, mmfr2) > 0,
111+
"FEAT_IDST not supported");
112+
kvm_vm_free(vm);
113+
114+
test_guest_feat_idst();
115+
116+
return 0;
117+
}

0 commit comments

Comments
 (0)