Skip to content

Commit 797b845

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: selftests: Add test for AArch32 ID registers
Add a test to assert that KVM handles the AArch64 views of the AArch32 ID registers as RAZ/WI (writable only from userspace). For registers that were already hidden or unallocated, expect RAZ + invariant behavior. Signed-off-by: Oliver Upton <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d5efec7 commit 797b845

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

tools/testing/selftests/kvm/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# SPDX-License-Identifier: GPL-2.0-only
2+
/aarch64/aarch32_id_regs
23
/aarch64/arch_timer
34
/aarch64/debug-exceptions
45
/aarch64/get-reg-list

tools/testing/selftests/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ TEST_GEN_PROGS_x86_64 += system_counter_offset_test
144144
# Compiled outputs used by test targets
145145
TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test
146146

147+
TEST_GEN_PROGS_aarch64 += aarch64/aarch32_id_regs
147148
TEST_GEN_PROGS_aarch64 += aarch64/arch_timer
148149
TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
149150
TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* aarch32_id_regs - Test for ID register behavior on AArch64-only systems
4+
*
5+
* Copyright (c) 2022 Google LLC.
6+
*
7+
* Test that KVM handles the AArch64 views of the AArch32 ID registers as RAZ
8+
* and WI from userspace.
9+
*/
10+
11+
#include <stdint.h>
12+
13+
#include "kvm_util.h"
14+
#include "processor.h"
15+
#include "test_util.h"
16+
17+
#define BAD_ID_REG_VAL 0x1badc0deul
18+
19+
#define GUEST_ASSERT_REG_RAZ(reg) GUEST_ASSERT_EQ(read_sysreg_s(reg), 0)
20+
21+
static void guest_main(void)
22+
{
23+
GUEST_ASSERT_REG_RAZ(SYS_ID_PFR0_EL1);
24+
GUEST_ASSERT_REG_RAZ(SYS_ID_PFR1_EL1);
25+
GUEST_ASSERT_REG_RAZ(SYS_ID_DFR0_EL1);
26+
GUEST_ASSERT_REG_RAZ(SYS_ID_AFR0_EL1);
27+
GUEST_ASSERT_REG_RAZ(SYS_ID_MMFR0_EL1);
28+
GUEST_ASSERT_REG_RAZ(SYS_ID_MMFR1_EL1);
29+
GUEST_ASSERT_REG_RAZ(SYS_ID_MMFR2_EL1);
30+
GUEST_ASSERT_REG_RAZ(SYS_ID_MMFR3_EL1);
31+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR0_EL1);
32+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR1_EL1);
33+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR2_EL1);
34+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR3_EL1);
35+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR4_EL1);
36+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR5_EL1);
37+
GUEST_ASSERT_REG_RAZ(SYS_ID_MMFR4_EL1);
38+
GUEST_ASSERT_REG_RAZ(SYS_ID_ISAR6_EL1);
39+
GUEST_ASSERT_REG_RAZ(SYS_MVFR0_EL1);
40+
GUEST_ASSERT_REG_RAZ(SYS_MVFR1_EL1);
41+
GUEST_ASSERT_REG_RAZ(SYS_MVFR2_EL1);
42+
GUEST_ASSERT_REG_RAZ(sys_reg(3, 0, 0, 3, 3));
43+
GUEST_ASSERT_REG_RAZ(SYS_ID_PFR2_EL1);
44+
GUEST_ASSERT_REG_RAZ(SYS_ID_DFR1_EL1);
45+
GUEST_ASSERT_REG_RAZ(SYS_ID_MMFR5_EL1);
46+
GUEST_ASSERT_REG_RAZ(sys_reg(3, 0, 0, 3, 7));
47+
48+
GUEST_DONE();
49+
}
50+
51+
static void test_guest_raz(struct kvm_vcpu *vcpu)
52+
{
53+
struct ucall uc;
54+
55+
vcpu_run(vcpu);
56+
57+
switch (get_ucall(vcpu, &uc)) {
58+
case UCALL_ABORT:
59+
REPORT_GUEST_ASSERT(uc);
60+
break;
61+
case UCALL_DONE:
62+
break;
63+
default:
64+
TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
65+
}
66+
}
67+
68+
static uint64_t raz_wi_reg_ids[] = {
69+
KVM_ARM64_SYS_REG(SYS_ID_PFR0_EL1),
70+
KVM_ARM64_SYS_REG(SYS_ID_PFR1_EL1),
71+
KVM_ARM64_SYS_REG(SYS_ID_DFR0_EL1),
72+
KVM_ARM64_SYS_REG(SYS_ID_MMFR0_EL1),
73+
KVM_ARM64_SYS_REG(SYS_ID_MMFR1_EL1),
74+
KVM_ARM64_SYS_REG(SYS_ID_MMFR2_EL1),
75+
KVM_ARM64_SYS_REG(SYS_ID_MMFR3_EL1),
76+
KVM_ARM64_SYS_REG(SYS_ID_ISAR0_EL1),
77+
KVM_ARM64_SYS_REG(SYS_ID_ISAR1_EL1),
78+
KVM_ARM64_SYS_REG(SYS_ID_ISAR2_EL1),
79+
KVM_ARM64_SYS_REG(SYS_ID_ISAR3_EL1),
80+
KVM_ARM64_SYS_REG(SYS_ID_ISAR4_EL1),
81+
KVM_ARM64_SYS_REG(SYS_ID_ISAR5_EL1),
82+
KVM_ARM64_SYS_REG(SYS_ID_MMFR4_EL1),
83+
KVM_ARM64_SYS_REG(SYS_ID_ISAR6_EL1),
84+
KVM_ARM64_SYS_REG(SYS_MVFR0_EL1),
85+
KVM_ARM64_SYS_REG(SYS_MVFR1_EL1),
86+
KVM_ARM64_SYS_REG(SYS_MVFR2_EL1),
87+
KVM_ARM64_SYS_REG(SYS_ID_PFR2_EL1),
88+
KVM_ARM64_SYS_REG(SYS_ID_MMFR5_EL1),
89+
};
90+
91+
static void test_user_raz_wi(struct kvm_vcpu *vcpu)
92+
{
93+
int i;
94+
95+
for (i = 0; i < ARRAY_SIZE(raz_wi_reg_ids); i++) {
96+
uint64_t reg_id = raz_wi_reg_ids[i];
97+
uint64_t val;
98+
99+
vcpu_get_reg(vcpu, reg_id, &val);
100+
ASSERT_EQ(val, 0);
101+
102+
/*
103+
* Expect the ioctl to succeed with no effect on the register
104+
* value.
105+
*/
106+
vcpu_set_reg(vcpu, reg_id, BAD_ID_REG_VAL);
107+
108+
vcpu_get_reg(vcpu, reg_id, &val);
109+
ASSERT_EQ(val, 0);
110+
}
111+
}
112+
113+
static uint64_t raz_invariant_reg_ids[] = {
114+
KVM_ARM64_SYS_REG(SYS_ID_AFR0_EL1),
115+
KVM_ARM64_SYS_REG(sys_reg(3, 0, 0, 3, 3)),
116+
KVM_ARM64_SYS_REG(SYS_ID_DFR1_EL1),
117+
KVM_ARM64_SYS_REG(sys_reg(3, 0, 0, 3, 7)),
118+
};
119+
120+
static void test_user_raz_invariant(struct kvm_vcpu *vcpu)
121+
{
122+
int i, r;
123+
124+
for (i = 0; i < ARRAY_SIZE(raz_invariant_reg_ids); i++) {
125+
uint64_t reg_id = raz_invariant_reg_ids[i];
126+
uint64_t val;
127+
128+
vcpu_get_reg(vcpu, reg_id, &val);
129+
ASSERT_EQ(val, 0);
130+
131+
r = __vcpu_set_reg(vcpu, reg_id, BAD_ID_REG_VAL);
132+
TEST_ASSERT(r < 0 && errno == EINVAL,
133+
"unexpected KVM_SET_ONE_REG error: r=%d, errno=%d", r, errno);
134+
135+
vcpu_get_reg(vcpu, reg_id, &val);
136+
ASSERT_EQ(val, 0);
137+
}
138+
}
139+
140+
141+
142+
static bool vcpu_aarch64_only(struct kvm_vcpu *vcpu)
143+
{
144+
uint64_t val, el0;
145+
146+
vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR0_EL1), &val);
147+
148+
el0 = (val & ARM64_FEATURE_MASK(ID_AA64PFR0_EL0)) >> ID_AA64PFR0_EL0_SHIFT;
149+
return el0 == ID_AA64PFR0_ELx_64BIT_ONLY;
150+
}
151+
152+
int main(void)
153+
{
154+
struct kvm_vcpu *vcpu;
155+
struct kvm_vm *vm;
156+
157+
vm = vm_create_with_one_vcpu(&vcpu, guest_main);
158+
159+
TEST_REQUIRE(vcpu_aarch64_only(vcpu));
160+
161+
ucall_init(vm, NULL);
162+
163+
test_user_raz_wi(vcpu);
164+
test_user_raz_invariant(vcpu);
165+
test_guest_raz(vcpu);
166+
167+
ucall_uninit(vm);
168+
kvm_vm_free(vm);
169+
}

0 commit comments

Comments
 (0)