1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/kernel.h> 4 #include <sys/syscall.h> 5 #include <asm/kvm.h> 6 #include <asm/kvm_para.h> 7 8 #include <arm64/gic_v5.h> 9 10 #include "test_util.h" 11 #include "kvm_util.h" 12 #include "processor.h" 13 #include "vgic.h" 14 15 #define NR_VCPUS 1 16 17 struct vm_gic { 18 struct kvm_vm *vm; 19 int gic_fd; 20 u32 gic_dev_type; 21 }; 22 23 #define GUEST_CMD_IRQ_CDIA 10 24 #define GUEST_CMD_IRQ_DIEOI 11 25 #define GUEST_CMD_IS_AWAKE 12 26 #define GUEST_CMD_IS_READY 13 27 28 static void guest_irq_handler(struct ex_regs *regs) 29 { 30 bool valid; 31 u32 hwirq; 32 u64 ia; 33 static int count; 34 35 /* 36 * We have pending interrupts. Should never actually enter WFI 37 * here! 38 */ 39 wfi(); 40 GUEST_SYNC(GUEST_CMD_IS_AWAKE); 41 42 ia = gicr_insn(CDIA); 43 valid = GICV5_GICR_CDIA_VALID(ia); 44 45 GUEST_SYNC(GUEST_CMD_IRQ_CDIA); 46 47 if (!valid) 48 return; 49 50 gsb_ack(); 51 isb(); 52 53 hwirq = FIELD_GET(GICV5_GICR_CDIA_INTID, ia); 54 55 gic_insn(hwirq, CDDI); 56 gic_insn(0, CDEOI); 57 58 GUEST_SYNC(GUEST_CMD_IRQ_DIEOI); 59 60 if (++count >= 2) 61 GUEST_DONE(); 62 63 /* Ask for the next interrupt to be injected */ 64 GUEST_SYNC(GUEST_CMD_IS_READY); 65 } 66 67 static void guest_code(void) 68 { 69 local_irq_disable(); 70 71 gicv5_cpu_enable_interrupts(); 72 local_irq_enable(); 73 74 /* Enable the SW_PPI (3) */ 75 write_sysreg_s(BIT_ULL(3), SYS_ICC_PPI_ENABLER0_EL1); 76 77 /* Ask for the first interrupt to be injected */ 78 GUEST_SYNC(GUEST_CMD_IS_READY); 79 80 /* Loop forever waiting for interrupts */ 81 while (1); 82 } 83 84 85 /* we don't want to assert on run execution, hence that helper */ 86 static int run_vcpu(struct kvm_vcpu *vcpu) 87 { 88 return __vcpu_run(vcpu) ? -errno : 0; 89 } 90 91 static void vm_gic_destroy(struct vm_gic *v) 92 { 93 close(v->gic_fd); 94 kvm_vm_free(v->vm); 95 } 96 97 static void test_vgic_v5_ppis(u32 gic_dev_type) 98 { 99 struct kvm_vcpu *vcpus[NR_VCPUS]; 100 struct ucall uc; 101 u64 user_ppis[2]; 102 struct vm_gic v; 103 int ret, i; 104 105 v.gic_dev_type = gic_dev_type; 106 v.vm = __vm_create(VM_SHAPE_DEFAULT, NR_VCPUS, 0); 107 108 v.gic_fd = kvm_create_device(v.vm, gic_dev_type); 109 110 for (i = 0; i < NR_VCPUS; i++) 111 vcpus[i] = vm_vcpu_add(v.vm, i, guest_code); 112 113 vm_init_descriptor_tables(v.vm); 114 vm_install_exception_handler(v.vm, VECTOR_IRQ_CURRENT, guest_irq_handler); 115 116 for (i = 0; i < NR_VCPUS; i++) 117 vcpu_init_descriptor_tables(vcpus[i]); 118 119 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, 120 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL); 121 122 /* Read out the PPIs that user space is allowed to drive. */ 123 kvm_device_attr_get(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, 124 KVM_DEV_ARM_VGIC_USERSPACE_PPIS, &user_ppis); 125 126 /* We should always be able to drive the SW_PPI. */ 127 TEST_ASSERT(user_ppis[0] & BIT(GICV5_ARCH_PPI_SW_PPI), 128 "SW_PPI is not drivable by userspace"); 129 130 while (1) { 131 ret = run_vcpu(vcpus[0]); 132 if (ret) 133 break; 134 135 switch (get_ucall(vcpus[0], &uc)) { 136 case UCALL_SYNC: 137 /* 138 * The guest is ready for the next level change. Set 139 * high if ready, and lower if it has been consumed. 140 */ 141 if (uc.args[1] == GUEST_CMD_IS_READY || 142 uc.args[1] == GUEST_CMD_IRQ_DIEOI) { 143 u64 irq; 144 bool level = uc.args[1] == GUEST_CMD_IRQ_DIEOI ? 0 : 1; 145 146 irq = FIELD_PREP(KVM_ARM_IRQ_NUM_MASK, 3); 147 irq |= KVM_ARM_IRQ_TYPE_PPI << KVM_ARM_IRQ_TYPE_SHIFT; 148 149 kvm_irq_line(v.vm, irq, level); 150 } else if (uc.args[1] == GUEST_CMD_IS_AWAKE) { 151 pr_info("Guest skipping WFI due to pending IRQ\n"); 152 } else if (uc.args[1] == GUEST_CMD_IRQ_CDIA) { 153 pr_info("Guest acknowledged IRQ\n"); 154 } 155 156 continue; 157 case UCALL_ABORT: 158 REPORT_GUEST_ASSERT(uc); 159 break; 160 case UCALL_DONE: 161 goto done; 162 default: 163 TEST_FAIL("Unknown ucall %lu", uc.cmd); 164 } 165 } 166 167 done: 168 TEST_ASSERT(ret == 0, "Failed to test GICv5 PPIs"); 169 170 vm_gic_destroy(&v); 171 } 172 173 /* 174 * Returns 0 if it's possible to create GIC device of a given type (V5). 175 */ 176 int test_kvm_device(u32 gic_dev_type) 177 { 178 struct kvm_vcpu *vcpus[NR_VCPUS]; 179 struct vm_gic v; 180 int ret; 181 182 v.vm = vm_create_with_vcpus(NR_VCPUS, guest_code, vcpus); 183 184 /* try to create a non existing KVM device */ 185 ret = __kvm_test_create_device(v.vm, 0); 186 TEST_ASSERT(ret && errno == ENODEV, "unsupported device"); 187 188 /* trial mode */ 189 ret = __kvm_test_create_device(v.vm, gic_dev_type); 190 if (ret) 191 return ret; 192 v.gic_fd = kvm_create_device(v.vm, gic_dev_type); 193 194 ret = __kvm_create_device(v.vm, gic_dev_type); 195 TEST_ASSERT(ret < 0 && errno == EEXIST, "create GIC device twice"); 196 197 vm_gic_destroy(&v); 198 199 return 0; 200 } 201 202 void run_tests(u32 gic_dev_type) 203 { 204 pr_info("Test VGICv5 PPIs\n"); 205 test_vgic_v5_ppis(gic_dev_type); 206 } 207 208 int main(int ac, char **av) 209 { 210 int ret; 211 212 test_disable_default_vgic(); 213 214 ret = test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V5); 215 if (ret) { 216 pr_info("No GICv5 support; Not running GIC_v5 tests.\n"); 217 exit(KSFT_SKIP); 218 } 219 220 pr_info("Running VGIC_V5 tests.\n"); 221 run_tests(KVM_DEV_TYPE_ARM_VGIC_V5); 222 223 return 0; 224 } 225