xref: /linux/tools/testing/selftests/kvm/arm64/idreg-idst.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
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 }
118