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