1*67730e6cSSean Christopherson // SPDX-License-Identifier: GPL-2.0 2*67730e6cSSean Christopherson /* 3*67730e6cSSean Christopherson * vgic_irq.c - Test userspace injection of IRQs 4*67730e6cSSean Christopherson * 5*67730e6cSSean Christopherson * This test validates the injection of IRQs from userspace using various 6*67730e6cSSean Christopherson * methods (e.g., KVM_IRQ_LINE) and modes (e.g., EOI). The guest "asks" the 7*67730e6cSSean Christopherson * host to inject a specific intid via a GUEST_SYNC call, and then checks that 8*67730e6cSSean Christopherson * it received it. 9*67730e6cSSean Christopherson */ 10*67730e6cSSean Christopherson #include <asm/kvm.h> 11*67730e6cSSean Christopherson #include <asm/kvm_para.h> 12*67730e6cSSean Christopherson #include <sys/eventfd.h> 13*67730e6cSSean Christopherson #include <linux/sizes.h> 14*67730e6cSSean Christopherson 15*67730e6cSSean Christopherson #include "processor.h" 16*67730e6cSSean Christopherson #include "test_util.h" 17*67730e6cSSean Christopherson #include "kvm_util.h" 18*67730e6cSSean Christopherson #include "gic.h" 19*67730e6cSSean Christopherson #include "gic_v3.h" 20*67730e6cSSean Christopherson #include "vgic.h" 21*67730e6cSSean Christopherson 22*67730e6cSSean Christopherson /* 23*67730e6cSSean Christopherson * Stores the user specified args; it's passed to the guest and to every test 24*67730e6cSSean Christopherson * function. 25*67730e6cSSean Christopherson */ 26*67730e6cSSean Christopherson struct test_args { 27*67730e6cSSean Christopherson uint32_t nr_irqs; /* number of KVM supported IRQs. */ 28*67730e6cSSean Christopherson bool eoi_split; /* 1 is eoir+dir, 0 is eoir only */ 29*67730e6cSSean Christopherson bool level_sensitive; /* 1 is level, 0 is edge */ 30*67730e6cSSean Christopherson int kvm_max_routes; /* output of KVM_CAP_IRQ_ROUTING */ 31*67730e6cSSean Christopherson bool kvm_supports_irqfd; /* output of KVM_CAP_IRQFD */ 32*67730e6cSSean Christopherson }; 33*67730e6cSSean Christopherson 34*67730e6cSSean Christopherson /* 35*67730e6cSSean Christopherson * KVM implements 32 priority levels: 36*67730e6cSSean Christopherson * 0x00 (highest priority) - 0xF8 (lowest priority), in steps of 8 37*67730e6cSSean Christopherson * 38*67730e6cSSean Christopherson * Note that these macros will still be correct in the case that KVM implements 39*67730e6cSSean Christopherson * more priority levels. Also note that 32 is the minimum for GICv3 and GICv2. 40*67730e6cSSean Christopherson */ 41*67730e6cSSean Christopherson #define KVM_NUM_PRIOS 32 42*67730e6cSSean Christopherson #define KVM_PRIO_SHIFT 3 /* steps of 8 = 1 << 3 */ 43*67730e6cSSean Christopherson #define KVM_PRIO_STEPS (1 << KVM_PRIO_SHIFT) /* 8 */ 44*67730e6cSSean Christopherson #define LOWEST_PRIO (KVM_NUM_PRIOS - 1) 45*67730e6cSSean Christopherson #define CPU_PRIO_MASK (LOWEST_PRIO << KVM_PRIO_SHIFT) /* 0xf8 */ 46*67730e6cSSean Christopherson #define IRQ_DEFAULT_PRIO (LOWEST_PRIO - 1) 47*67730e6cSSean Christopherson #define IRQ_DEFAULT_PRIO_REG (IRQ_DEFAULT_PRIO << KVM_PRIO_SHIFT) /* 0xf0 */ 48*67730e6cSSean Christopherson 49*67730e6cSSean Christopherson /* 50*67730e6cSSean Christopherson * The kvm_inject_* utilities are used by the guest to ask the host to inject 51*67730e6cSSean Christopherson * interrupts (e.g., using the KVM_IRQ_LINE ioctl). 52*67730e6cSSean Christopherson */ 53*67730e6cSSean Christopherson 54*67730e6cSSean Christopherson typedef enum { 55*67730e6cSSean Christopherson KVM_INJECT_EDGE_IRQ_LINE = 1, 56*67730e6cSSean Christopherson KVM_SET_IRQ_LINE, 57*67730e6cSSean Christopherson KVM_SET_IRQ_LINE_HIGH, 58*67730e6cSSean Christopherson KVM_SET_LEVEL_INFO_HIGH, 59*67730e6cSSean Christopherson KVM_INJECT_IRQFD, 60*67730e6cSSean Christopherson KVM_WRITE_ISPENDR, 61*67730e6cSSean Christopherson KVM_WRITE_ISACTIVER, 62*67730e6cSSean Christopherson } kvm_inject_cmd; 63*67730e6cSSean Christopherson 64*67730e6cSSean Christopherson struct kvm_inject_args { 65*67730e6cSSean Christopherson kvm_inject_cmd cmd; 66*67730e6cSSean Christopherson uint32_t first_intid; 67*67730e6cSSean Christopherson uint32_t num; 68*67730e6cSSean Christopherson int level; 69*67730e6cSSean Christopherson bool expect_failure; 70*67730e6cSSean Christopherson }; 71*67730e6cSSean Christopherson 72*67730e6cSSean Christopherson /* Used on the guest side to perform the hypercall. */ 73*67730e6cSSean Christopherson static void kvm_inject_call(kvm_inject_cmd cmd, uint32_t first_intid, 74*67730e6cSSean Christopherson uint32_t num, int level, bool expect_failure); 75*67730e6cSSean Christopherson 76*67730e6cSSean Christopherson /* Used on the host side to get the hypercall info. */ 77*67730e6cSSean Christopherson static void kvm_inject_get_call(struct kvm_vm *vm, struct ucall *uc, 78*67730e6cSSean Christopherson struct kvm_inject_args *args); 79*67730e6cSSean Christopherson 80*67730e6cSSean Christopherson #define _KVM_INJECT_MULTI(cmd, intid, num, expect_failure) \ 81*67730e6cSSean Christopherson kvm_inject_call(cmd, intid, num, -1 /* not used */, expect_failure) 82*67730e6cSSean Christopherson 83*67730e6cSSean Christopherson #define KVM_INJECT_MULTI(cmd, intid, num) \ 84*67730e6cSSean Christopherson _KVM_INJECT_MULTI(cmd, intid, num, false) 85*67730e6cSSean Christopherson 86*67730e6cSSean Christopherson #define _KVM_INJECT(cmd, intid, expect_failure) \ 87*67730e6cSSean Christopherson _KVM_INJECT_MULTI(cmd, intid, 1, expect_failure) 88*67730e6cSSean Christopherson 89*67730e6cSSean Christopherson #define KVM_INJECT(cmd, intid) \ 90*67730e6cSSean Christopherson _KVM_INJECT_MULTI(cmd, intid, 1, false) 91*67730e6cSSean Christopherson 92*67730e6cSSean Christopherson #define KVM_ACTIVATE(cmd, intid) \ 93*67730e6cSSean Christopherson kvm_inject_call(cmd, intid, 1, 1, false); 94*67730e6cSSean Christopherson 95*67730e6cSSean Christopherson struct kvm_inject_desc { 96*67730e6cSSean Christopherson kvm_inject_cmd cmd; 97*67730e6cSSean Christopherson /* can inject PPIs, PPIs, and/or SPIs. */ 98*67730e6cSSean Christopherson bool sgi, ppi, spi; 99*67730e6cSSean Christopherson }; 100*67730e6cSSean Christopherson 101*67730e6cSSean Christopherson static struct kvm_inject_desc inject_edge_fns[] = { 102*67730e6cSSean Christopherson /* sgi ppi spi */ 103*67730e6cSSean Christopherson { KVM_INJECT_EDGE_IRQ_LINE, false, false, true }, 104*67730e6cSSean Christopherson { KVM_INJECT_IRQFD, false, false, true }, 105*67730e6cSSean Christopherson { KVM_WRITE_ISPENDR, true, false, true }, 106*67730e6cSSean Christopherson { 0, }, 107*67730e6cSSean Christopherson }; 108*67730e6cSSean Christopherson 109*67730e6cSSean Christopherson static struct kvm_inject_desc inject_level_fns[] = { 110*67730e6cSSean Christopherson /* sgi ppi spi */ 111*67730e6cSSean Christopherson { KVM_SET_IRQ_LINE_HIGH, false, true, true }, 112*67730e6cSSean Christopherson { KVM_SET_LEVEL_INFO_HIGH, false, true, true }, 113*67730e6cSSean Christopherson { KVM_INJECT_IRQFD, false, false, true }, 114*67730e6cSSean Christopherson { KVM_WRITE_ISPENDR, false, true, true }, 115*67730e6cSSean Christopherson { 0, }, 116*67730e6cSSean Christopherson }; 117*67730e6cSSean Christopherson 118*67730e6cSSean Christopherson static struct kvm_inject_desc set_active_fns[] = { 119*67730e6cSSean Christopherson /* sgi ppi spi */ 120*67730e6cSSean Christopherson { KVM_WRITE_ISACTIVER, true, true, true }, 121*67730e6cSSean Christopherson { 0, }, 122*67730e6cSSean Christopherson }; 123*67730e6cSSean Christopherson 124*67730e6cSSean Christopherson #define for_each_inject_fn(t, f) \ 125*67730e6cSSean Christopherson for ((f) = (t); (f)->cmd; (f)++) 126*67730e6cSSean Christopherson 127*67730e6cSSean Christopherson #define for_each_supported_inject_fn(args, t, f) \ 128*67730e6cSSean Christopherson for_each_inject_fn(t, f) \ 129*67730e6cSSean Christopherson if ((args)->kvm_supports_irqfd || (f)->cmd != KVM_INJECT_IRQFD) 130*67730e6cSSean Christopherson 131*67730e6cSSean Christopherson #define for_each_supported_activate_fn(args, t, f) \ 132*67730e6cSSean Christopherson for_each_supported_inject_fn((args), (t), (f)) 133*67730e6cSSean Christopherson 134*67730e6cSSean Christopherson /* Shared between the guest main thread and the IRQ handlers. */ 135*67730e6cSSean Christopherson volatile uint64_t irq_handled; 136*67730e6cSSean Christopherson volatile uint32_t irqnr_received[MAX_SPI + 1]; 137*67730e6cSSean Christopherson 138*67730e6cSSean Christopherson static void reset_stats(void) 139*67730e6cSSean Christopherson { 140*67730e6cSSean Christopherson int i; 141*67730e6cSSean Christopherson 142*67730e6cSSean Christopherson irq_handled = 0; 143*67730e6cSSean Christopherson for (i = 0; i <= MAX_SPI; i++) 144*67730e6cSSean Christopherson irqnr_received[i] = 0; 145*67730e6cSSean Christopherson } 146*67730e6cSSean Christopherson 147*67730e6cSSean Christopherson static uint64_t gic_read_ap1r0(void) 148*67730e6cSSean Christopherson { 149*67730e6cSSean Christopherson uint64_t reg = read_sysreg_s(SYS_ICC_AP1R0_EL1); 150*67730e6cSSean Christopherson 151*67730e6cSSean Christopherson dsb(sy); 152*67730e6cSSean Christopherson return reg; 153*67730e6cSSean Christopherson } 154*67730e6cSSean Christopherson 155*67730e6cSSean Christopherson static void gic_write_ap1r0(uint64_t val) 156*67730e6cSSean Christopherson { 157*67730e6cSSean Christopherson write_sysreg_s(val, SYS_ICC_AP1R0_EL1); 158*67730e6cSSean Christopherson isb(); 159*67730e6cSSean Christopherson } 160*67730e6cSSean Christopherson 161*67730e6cSSean Christopherson static void guest_set_irq_line(uint32_t intid, uint32_t level); 162*67730e6cSSean Christopherson 163*67730e6cSSean Christopherson static void guest_irq_generic_handler(bool eoi_split, bool level_sensitive) 164*67730e6cSSean Christopherson { 165*67730e6cSSean Christopherson uint32_t intid = gic_get_and_ack_irq(); 166*67730e6cSSean Christopherson 167*67730e6cSSean Christopherson if (intid == IAR_SPURIOUS) 168*67730e6cSSean Christopherson return; 169*67730e6cSSean Christopherson 170*67730e6cSSean Christopherson GUEST_ASSERT(gic_irq_get_active(intid)); 171*67730e6cSSean Christopherson 172*67730e6cSSean Christopherson if (!level_sensitive) 173*67730e6cSSean Christopherson GUEST_ASSERT(!gic_irq_get_pending(intid)); 174*67730e6cSSean Christopherson 175*67730e6cSSean Christopherson if (level_sensitive) 176*67730e6cSSean Christopherson guest_set_irq_line(intid, 0); 177*67730e6cSSean Christopherson 178*67730e6cSSean Christopherson GUEST_ASSERT(intid < MAX_SPI); 179*67730e6cSSean Christopherson irqnr_received[intid] += 1; 180*67730e6cSSean Christopherson irq_handled += 1; 181*67730e6cSSean Christopherson 182*67730e6cSSean Christopherson gic_set_eoi(intid); 183*67730e6cSSean Christopherson GUEST_ASSERT_EQ(gic_read_ap1r0(), 0); 184*67730e6cSSean Christopherson if (eoi_split) 185*67730e6cSSean Christopherson gic_set_dir(intid); 186*67730e6cSSean Christopherson 187*67730e6cSSean Christopherson GUEST_ASSERT(!gic_irq_get_active(intid)); 188*67730e6cSSean Christopherson GUEST_ASSERT(!gic_irq_get_pending(intid)); 189*67730e6cSSean Christopherson } 190*67730e6cSSean Christopherson 191*67730e6cSSean Christopherson static void kvm_inject_call(kvm_inject_cmd cmd, uint32_t first_intid, 192*67730e6cSSean Christopherson uint32_t num, int level, bool expect_failure) 193*67730e6cSSean Christopherson { 194*67730e6cSSean Christopherson struct kvm_inject_args args = { 195*67730e6cSSean Christopherson .cmd = cmd, 196*67730e6cSSean Christopherson .first_intid = first_intid, 197*67730e6cSSean Christopherson .num = num, 198*67730e6cSSean Christopherson .level = level, 199*67730e6cSSean Christopherson .expect_failure = expect_failure, 200*67730e6cSSean Christopherson }; 201*67730e6cSSean Christopherson GUEST_SYNC(&args); 202*67730e6cSSean Christopherson } 203*67730e6cSSean Christopherson 204*67730e6cSSean Christopherson #define GUEST_ASSERT_IAR_EMPTY() \ 205*67730e6cSSean Christopherson do { \ 206*67730e6cSSean Christopherson uint32_t _intid; \ 207*67730e6cSSean Christopherson _intid = gic_get_and_ack_irq(); \ 208*67730e6cSSean Christopherson GUEST_ASSERT(_intid == 0 || _intid == IAR_SPURIOUS); \ 209*67730e6cSSean Christopherson } while (0) 210*67730e6cSSean Christopherson 211*67730e6cSSean Christopherson #define CAT_HELPER(a, b) a ## b 212*67730e6cSSean Christopherson #define CAT(a, b) CAT_HELPER(a, b) 213*67730e6cSSean Christopherson #define PREFIX guest_irq_handler_ 214*67730e6cSSean Christopherson #define GUEST_IRQ_HANDLER_NAME(split, lev) CAT(PREFIX, CAT(split, lev)) 215*67730e6cSSean Christopherson #define GENERATE_GUEST_IRQ_HANDLER(split, lev) \ 216*67730e6cSSean Christopherson static void CAT(PREFIX, CAT(split, lev))(struct ex_regs *regs) \ 217*67730e6cSSean Christopherson { \ 218*67730e6cSSean Christopherson guest_irq_generic_handler(split, lev); \ 219*67730e6cSSean Christopherson } 220*67730e6cSSean Christopherson 221*67730e6cSSean Christopherson GENERATE_GUEST_IRQ_HANDLER(0, 0); 222*67730e6cSSean Christopherson GENERATE_GUEST_IRQ_HANDLER(0, 1); 223*67730e6cSSean Christopherson GENERATE_GUEST_IRQ_HANDLER(1, 0); 224*67730e6cSSean Christopherson GENERATE_GUEST_IRQ_HANDLER(1, 1); 225*67730e6cSSean Christopherson 226*67730e6cSSean Christopherson static void (*guest_irq_handlers[2][2])(struct ex_regs *) = { 227*67730e6cSSean Christopherson {GUEST_IRQ_HANDLER_NAME(0, 0), GUEST_IRQ_HANDLER_NAME(0, 1),}, 228*67730e6cSSean Christopherson {GUEST_IRQ_HANDLER_NAME(1, 0), GUEST_IRQ_HANDLER_NAME(1, 1),}, 229*67730e6cSSean Christopherson }; 230*67730e6cSSean Christopherson 231*67730e6cSSean Christopherson static void reset_priorities(struct test_args *args) 232*67730e6cSSean Christopherson { 233*67730e6cSSean Christopherson int i; 234*67730e6cSSean Christopherson 235*67730e6cSSean Christopherson for (i = 0; i < args->nr_irqs; i++) 236*67730e6cSSean Christopherson gic_set_priority(i, IRQ_DEFAULT_PRIO_REG); 237*67730e6cSSean Christopherson } 238*67730e6cSSean Christopherson 239*67730e6cSSean Christopherson static void guest_set_irq_line(uint32_t intid, uint32_t level) 240*67730e6cSSean Christopherson { 241*67730e6cSSean Christopherson kvm_inject_call(KVM_SET_IRQ_LINE, intid, 1, level, false); 242*67730e6cSSean Christopherson } 243*67730e6cSSean Christopherson 244*67730e6cSSean Christopherson static void test_inject_fail(struct test_args *args, 245*67730e6cSSean Christopherson uint32_t intid, kvm_inject_cmd cmd) 246*67730e6cSSean Christopherson { 247*67730e6cSSean Christopherson reset_stats(); 248*67730e6cSSean Christopherson 249*67730e6cSSean Christopherson _KVM_INJECT(cmd, intid, true); 250*67730e6cSSean Christopherson /* no IRQ to handle on entry */ 251*67730e6cSSean Christopherson 252*67730e6cSSean Christopherson GUEST_ASSERT_EQ(irq_handled, 0); 253*67730e6cSSean Christopherson GUEST_ASSERT_IAR_EMPTY(); 254*67730e6cSSean Christopherson } 255*67730e6cSSean Christopherson 256*67730e6cSSean Christopherson static void guest_inject(struct test_args *args, 257*67730e6cSSean Christopherson uint32_t first_intid, uint32_t num, 258*67730e6cSSean Christopherson kvm_inject_cmd cmd) 259*67730e6cSSean Christopherson { 260*67730e6cSSean Christopherson uint32_t i; 261*67730e6cSSean Christopherson 262*67730e6cSSean Christopherson reset_stats(); 263*67730e6cSSean Christopherson 264*67730e6cSSean Christopherson /* Cycle over all priorities to make things more interesting. */ 265*67730e6cSSean Christopherson for (i = first_intid; i < num + first_intid; i++) 266*67730e6cSSean Christopherson gic_set_priority(i, (i % (KVM_NUM_PRIOS - 1)) << 3); 267*67730e6cSSean Christopherson 268*67730e6cSSean Christopherson asm volatile("msr daifset, #2" : : : "memory"); 269*67730e6cSSean Christopherson KVM_INJECT_MULTI(cmd, first_intid, num); 270*67730e6cSSean Christopherson 271*67730e6cSSean Christopherson while (irq_handled < num) { 272*67730e6cSSean Christopherson wfi(); 273*67730e6cSSean Christopherson local_irq_enable(); 274*67730e6cSSean Christopherson isb(); /* handle IRQ */ 275*67730e6cSSean Christopherson local_irq_disable(); 276*67730e6cSSean Christopherson } 277*67730e6cSSean Christopherson local_irq_enable(); 278*67730e6cSSean Christopherson 279*67730e6cSSean Christopherson GUEST_ASSERT_EQ(irq_handled, num); 280*67730e6cSSean Christopherson for (i = first_intid; i < num + first_intid; i++) 281*67730e6cSSean Christopherson GUEST_ASSERT_EQ(irqnr_received[i], 1); 282*67730e6cSSean Christopherson GUEST_ASSERT_IAR_EMPTY(); 283*67730e6cSSean Christopherson 284*67730e6cSSean Christopherson reset_priorities(args); 285*67730e6cSSean Christopherson } 286*67730e6cSSean Christopherson 287*67730e6cSSean Christopherson /* 288*67730e6cSSean Christopherson * Restore the active state of multiple concurrent IRQs (given by 289*67730e6cSSean Christopherson * concurrent_irqs). This does what a live-migration would do on the 290*67730e6cSSean Christopherson * destination side assuming there are some active IRQs that were not 291*67730e6cSSean Christopherson * deactivated yet. 292*67730e6cSSean Christopherson */ 293*67730e6cSSean Christopherson static void guest_restore_active(struct test_args *args, 294*67730e6cSSean Christopherson uint32_t first_intid, uint32_t num, 295*67730e6cSSean Christopherson kvm_inject_cmd cmd) 296*67730e6cSSean Christopherson { 297*67730e6cSSean Christopherson uint32_t prio, intid, ap1r; 298*67730e6cSSean Christopherson int i; 299*67730e6cSSean Christopherson 300*67730e6cSSean Christopherson /* 301*67730e6cSSean Christopherson * Set the priorities of the first (KVM_NUM_PRIOS - 1) IRQs 302*67730e6cSSean Christopherson * in descending order, so intid+1 can preempt intid. 303*67730e6cSSean Christopherson */ 304*67730e6cSSean Christopherson for (i = 0, prio = (num - 1) * 8; i < num; i++, prio -= 8) { 305*67730e6cSSean Christopherson GUEST_ASSERT(prio >= 0); 306*67730e6cSSean Christopherson intid = i + first_intid; 307*67730e6cSSean Christopherson gic_set_priority(intid, prio); 308*67730e6cSSean Christopherson } 309*67730e6cSSean Christopherson 310*67730e6cSSean Christopherson /* 311*67730e6cSSean Christopherson * In a real migration, KVM would restore all GIC state before running 312*67730e6cSSean Christopherson * guest code. 313*67730e6cSSean Christopherson */ 314*67730e6cSSean Christopherson for (i = 0; i < num; i++) { 315*67730e6cSSean Christopherson intid = i + first_intid; 316*67730e6cSSean Christopherson KVM_ACTIVATE(cmd, intid); 317*67730e6cSSean Christopherson ap1r = gic_read_ap1r0(); 318*67730e6cSSean Christopherson ap1r |= 1U << i; 319*67730e6cSSean Christopherson gic_write_ap1r0(ap1r); 320*67730e6cSSean Christopherson } 321*67730e6cSSean Christopherson 322*67730e6cSSean Christopherson /* This is where the "migration" would occur. */ 323*67730e6cSSean Christopherson 324*67730e6cSSean Christopherson /* finish handling the IRQs starting with the highest priority one. */ 325*67730e6cSSean Christopherson for (i = 0; i < num; i++) { 326*67730e6cSSean Christopherson intid = num - i - 1 + first_intid; 327*67730e6cSSean Christopherson gic_set_eoi(intid); 328*67730e6cSSean Christopherson if (args->eoi_split) 329*67730e6cSSean Christopherson gic_set_dir(intid); 330*67730e6cSSean Christopherson } 331*67730e6cSSean Christopherson 332*67730e6cSSean Christopherson for (i = 0; i < num; i++) 333*67730e6cSSean Christopherson GUEST_ASSERT(!gic_irq_get_active(i + first_intid)); 334*67730e6cSSean Christopherson GUEST_ASSERT_EQ(gic_read_ap1r0(), 0); 335*67730e6cSSean Christopherson GUEST_ASSERT_IAR_EMPTY(); 336*67730e6cSSean Christopherson } 337*67730e6cSSean Christopherson 338*67730e6cSSean Christopherson /* 339*67730e6cSSean Christopherson * Polls the IAR until it's not a spurious interrupt. 340*67730e6cSSean Christopherson * 341*67730e6cSSean Christopherson * This function should only be used in test_inject_preemption (with IRQs 342*67730e6cSSean Christopherson * masked). 343*67730e6cSSean Christopherson */ 344*67730e6cSSean Christopherson static uint32_t wait_for_and_activate_irq(void) 345*67730e6cSSean Christopherson { 346*67730e6cSSean Christopherson uint32_t intid; 347*67730e6cSSean Christopherson 348*67730e6cSSean Christopherson do { 349*67730e6cSSean Christopherson asm volatile("wfi" : : : "memory"); 350*67730e6cSSean Christopherson intid = gic_get_and_ack_irq(); 351*67730e6cSSean Christopherson } while (intid == IAR_SPURIOUS); 352*67730e6cSSean Christopherson 353*67730e6cSSean Christopherson return intid; 354*67730e6cSSean Christopherson } 355*67730e6cSSean Christopherson 356*67730e6cSSean Christopherson /* 357*67730e6cSSean Christopherson * Inject multiple concurrent IRQs (num IRQs starting at first_intid) and 358*67730e6cSSean Christopherson * handle them without handling the actual exceptions. This is done by masking 359*67730e6cSSean Christopherson * interrupts for the whole test. 360*67730e6cSSean Christopherson */ 361*67730e6cSSean Christopherson static void test_inject_preemption(struct test_args *args, 362*67730e6cSSean Christopherson uint32_t first_intid, int num, 363*67730e6cSSean Christopherson kvm_inject_cmd cmd) 364*67730e6cSSean Christopherson { 365*67730e6cSSean Christopherson uint32_t intid, prio, step = KVM_PRIO_STEPS; 366*67730e6cSSean Christopherson int i; 367*67730e6cSSean Christopherson 368*67730e6cSSean Christopherson /* Set the priorities of the first (KVM_NUM_PRIOS - 1) IRQs 369*67730e6cSSean Christopherson * in descending order, so intid+1 can preempt intid. 370*67730e6cSSean Christopherson */ 371*67730e6cSSean Christopherson for (i = 0, prio = (num - 1) * step; i < num; i++, prio -= step) { 372*67730e6cSSean Christopherson GUEST_ASSERT(prio >= 0); 373*67730e6cSSean Christopherson intid = i + first_intid; 374*67730e6cSSean Christopherson gic_set_priority(intid, prio); 375*67730e6cSSean Christopherson } 376*67730e6cSSean Christopherson 377*67730e6cSSean Christopherson local_irq_disable(); 378*67730e6cSSean Christopherson 379*67730e6cSSean Christopherson for (i = 0; i < num; i++) { 380*67730e6cSSean Christopherson uint32_t tmp; 381*67730e6cSSean Christopherson intid = i + first_intid; 382*67730e6cSSean Christopherson KVM_INJECT(cmd, intid); 383*67730e6cSSean Christopherson /* Each successive IRQ will preempt the previous one. */ 384*67730e6cSSean Christopherson tmp = wait_for_and_activate_irq(); 385*67730e6cSSean Christopherson GUEST_ASSERT_EQ(tmp, intid); 386*67730e6cSSean Christopherson if (args->level_sensitive) 387*67730e6cSSean Christopherson guest_set_irq_line(intid, 0); 388*67730e6cSSean Christopherson } 389*67730e6cSSean Christopherson 390*67730e6cSSean Christopherson /* finish handling the IRQs starting with the highest priority one. */ 391*67730e6cSSean Christopherson for (i = 0; i < num; i++) { 392*67730e6cSSean Christopherson intid = num - i - 1 + first_intid; 393*67730e6cSSean Christopherson gic_set_eoi(intid); 394*67730e6cSSean Christopherson if (args->eoi_split) 395*67730e6cSSean Christopherson gic_set_dir(intid); 396*67730e6cSSean Christopherson } 397*67730e6cSSean Christopherson 398*67730e6cSSean Christopherson local_irq_enable(); 399*67730e6cSSean Christopherson 400*67730e6cSSean Christopherson for (i = 0; i < num; i++) 401*67730e6cSSean Christopherson GUEST_ASSERT(!gic_irq_get_active(i + first_intid)); 402*67730e6cSSean Christopherson GUEST_ASSERT_EQ(gic_read_ap1r0(), 0); 403*67730e6cSSean Christopherson GUEST_ASSERT_IAR_EMPTY(); 404*67730e6cSSean Christopherson 405*67730e6cSSean Christopherson reset_priorities(args); 406*67730e6cSSean Christopherson } 407*67730e6cSSean Christopherson 408*67730e6cSSean Christopherson static void test_injection(struct test_args *args, struct kvm_inject_desc *f) 409*67730e6cSSean Christopherson { 410*67730e6cSSean Christopherson uint32_t nr_irqs = args->nr_irqs; 411*67730e6cSSean Christopherson 412*67730e6cSSean Christopherson if (f->sgi) { 413*67730e6cSSean Christopherson guest_inject(args, MIN_SGI, 1, f->cmd); 414*67730e6cSSean Christopherson guest_inject(args, 0, 16, f->cmd); 415*67730e6cSSean Christopherson } 416*67730e6cSSean Christopherson 417*67730e6cSSean Christopherson if (f->ppi) 418*67730e6cSSean Christopherson guest_inject(args, MIN_PPI, 1, f->cmd); 419*67730e6cSSean Christopherson 420*67730e6cSSean Christopherson if (f->spi) { 421*67730e6cSSean Christopherson guest_inject(args, MIN_SPI, 1, f->cmd); 422*67730e6cSSean Christopherson guest_inject(args, nr_irqs - 1, 1, f->cmd); 423*67730e6cSSean Christopherson guest_inject(args, MIN_SPI, nr_irqs - MIN_SPI, f->cmd); 424*67730e6cSSean Christopherson } 425*67730e6cSSean Christopherson } 426*67730e6cSSean Christopherson 427*67730e6cSSean Christopherson static void test_injection_failure(struct test_args *args, 428*67730e6cSSean Christopherson struct kvm_inject_desc *f) 429*67730e6cSSean Christopherson { 430*67730e6cSSean Christopherson uint32_t bad_intid[] = { args->nr_irqs, 1020, 1024, 1120, 5120, ~0U, }; 431*67730e6cSSean Christopherson int i; 432*67730e6cSSean Christopherson 433*67730e6cSSean Christopherson for (i = 0; i < ARRAY_SIZE(bad_intid); i++) 434*67730e6cSSean Christopherson test_inject_fail(args, bad_intid[i], f->cmd); 435*67730e6cSSean Christopherson } 436*67730e6cSSean Christopherson 437*67730e6cSSean Christopherson static void test_preemption(struct test_args *args, struct kvm_inject_desc *f) 438*67730e6cSSean Christopherson { 439*67730e6cSSean Christopherson /* 440*67730e6cSSean Christopherson * Test up to 4 levels of preemption. The reason is that KVM doesn't 441*67730e6cSSean Christopherson * currently implement the ability to have more than the number-of-LRs 442*67730e6cSSean Christopherson * number of concurrently active IRQs. The number of LRs implemented is 443*67730e6cSSean Christopherson * IMPLEMENTATION DEFINED, however, it seems that most implement 4. 444*67730e6cSSean Christopherson */ 445*67730e6cSSean Christopherson if (f->sgi) 446*67730e6cSSean Christopherson test_inject_preemption(args, MIN_SGI, 4, f->cmd); 447*67730e6cSSean Christopherson 448*67730e6cSSean Christopherson if (f->ppi) 449*67730e6cSSean Christopherson test_inject_preemption(args, MIN_PPI, 4, f->cmd); 450*67730e6cSSean Christopherson 451*67730e6cSSean Christopherson if (f->spi) 452*67730e6cSSean Christopherson test_inject_preemption(args, MIN_SPI, 4, f->cmd); 453*67730e6cSSean Christopherson } 454*67730e6cSSean Christopherson 455*67730e6cSSean Christopherson static void test_restore_active(struct test_args *args, struct kvm_inject_desc *f) 456*67730e6cSSean Christopherson { 457*67730e6cSSean Christopherson /* Test up to 4 active IRQs. Same reason as in test_preemption. */ 458*67730e6cSSean Christopherson if (f->sgi) 459*67730e6cSSean Christopherson guest_restore_active(args, MIN_SGI, 4, f->cmd); 460*67730e6cSSean Christopherson 461*67730e6cSSean Christopherson if (f->ppi) 462*67730e6cSSean Christopherson guest_restore_active(args, MIN_PPI, 4, f->cmd); 463*67730e6cSSean Christopherson 464*67730e6cSSean Christopherson if (f->spi) 465*67730e6cSSean Christopherson guest_restore_active(args, MIN_SPI, 4, f->cmd); 466*67730e6cSSean Christopherson } 467*67730e6cSSean Christopherson 468*67730e6cSSean Christopherson static void guest_code(struct test_args *args) 469*67730e6cSSean Christopherson { 470*67730e6cSSean Christopherson uint32_t i, nr_irqs = args->nr_irqs; 471*67730e6cSSean Christopherson bool level_sensitive = args->level_sensitive; 472*67730e6cSSean Christopherson struct kvm_inject_desc *f, *inject_fns; 473*67730e6cSSean Christopherson 474*67730e6cSSean Christopherson gic_init(GIC_V3, 1); 475*67730e6cSSean Christopherson 476*67730e6cSSean Christopherson for (i = 0; i < nr_irqs; i++) 477*67730e6cSSean Christopherson gic_irq_enable(i); 478*67730e6cSSean Christopherson 479*67730e6cSSean Christopherson for (i = MIN_SPI; i < nr_irqs; i++) 480*67730e6cSSean Christopherson gic_irq_set_config(i, !level_sensitive); 481*67730e6cSSean Christopherson 482*67730e6cSSean Christopherson gic_set_eoi_split(args->eoi_split); 483*67730e6cSSean Christopherson 484*67730e6cSSean Christopherson reset_priorities(args); 485*67730e6cSSean Christopherson gic_set_priority_mask(CPU_PRIO_MASK); 486*67730e6cSSean Christopherson 487*67730e6cSSean Christopherson inject_fns = level_sensitive ? inject_level_fns 488*67730e6cSSean Christopherson : inject_edge_fns; 489*67730e6cSSean Christopherson 490*67730e6cSSean Christopherson local_irq_enable(); 491*67730e6cSSean Christopherson 492*67730e6cSSean Christopherson /* Start the tests. */ 493*67730e6cSSean Christopherson for_each_supported_inject_fn(args, inject_fns, f) { 494*67730e6cSSean Christopherson test_injection(args, f); 495*67730e6cSSean Christopherson test_preemption(args, f); 496*67730e6cSSean Christopherson test_injection_failure(args, f); 497*67730e6cSSean Christopherson } 498*67730e6cSSean Christopherson 499*67730e6cSSean Christopherson /* 500*67730e6cSSean Christopherson * Restore the active state of IRQs. This would happen when live 501*67730e6cSSean Christopherson * migrating IRQs in the middle of being handled. 502*67730e6cSSean Christopherson */ 503*67730e6cSSean Christopherson for_each_supported_activate_fn(args, set_active_fns, f) 504*67730e6cSSean Christopherson test_restore_active(args, f); 505*67730e6cSSean Christopherson 506*67730e6cSSean Christopherson GUEST_DONE(); 507*67730e6cSSean Christopherson } 508*67730e6cSSean Christopherson 509*67730e6cSSean Christopherson static void kvm_irq_line_check(struct kvm_vm *vm, uint32_t intid, int level, 510*67730e6cSSean Christopherson struct test_args *test_args, bool expect_failure) 511*67730e6cSSean Christopherson { 512*67730e6cSSean Christopherson int ret; 513*67730e6cSSean Christopherson 514*67730e6cSSean Christopherson if (!expect_failure) { 515*67730e6cSSean Christopherson kvm_arm_irq_line(vm, intid, level); 516*67730e6cSSean Christopherson } else { 517*67730e6cSSean Christopherson /* The interface doesn't allow larger intid's. */ 518*67730e6cSSean Christopherson if (intid > KVM_ARM_IRQ_NUM_MASK) 519*67730e6cSSean Christopherson return; 520*67730e6cSSean Christopherson 521*67730e6cSSean Christopherson ret = _kvm_arm_irq_line(vm, intid, level); 522*67730e6cSSean Christopherson TEST_ASSERT(ret != 0 && errno == EINVAL, 523*67730e6cSSean Christopherson "Bad intid %i did not cause KVM_IRQ_LINE " 524*67730e6cSSean Christopherson "error: rc: %i errno: %i", intid, ret, errno); 525*67730e6cSSean Christopherson } 526*67730e6cSSean Christopherson } 527*67730e6cSSean Christopherson 528*67730e6cSSean Christopherson void kvm_irq_set_level_info_check(int gic_fd, uint32_t intid, int level, 529*67730e6cSSean Christopherson bool expect_failure) 530*67730e6cSSean Christopherson { 531*67730e6cSSean Christopherson if (!expect_failure) { 532*67730e6cSSean Christopherson kvm_irq_set_level_info(gic_fd, intid, level); 533*67730e6cSSean Christopherson } else { 534*67730e6cSSean Christopherson int ret = _kvm_irq_set_level_info(gic_fd, intid, level); 535*67730e6cSSean Christopherson /* 536*67730e6cSSean Christopherson * The kernel silently fails for invalid SPIs and SGIs (which 537*67730e6cSSean Christopherson * are not level-sensitive). It only checks for intid to not 538*67730e6cSSean Christopherson * spill over 1U << 10 (the max reserved SPI). Also, callers 539*67730e6cSSean Christopherson * are supposed to mask the intid with 0x3ff (1023). 540*67730e6cSSean Christopherson */ 541*67730e6cSSean Christopherson if (intid > VGIC_MAX_RESERVED) 542*67730e6cSSean Christopherson TEST_ASSERT(ret != 0 && errno == EINVAL, 543*67730e6cSSean Christopherson "Bad intid %i did not cause VGIC_GRP_LEVEL_INFO " 544*67730e6cSSean Christopherson "error: rc: %i errno: %i", intid, ret, errno); 545*67730e6cSSean Christopherson else 546*67730e6cSSean Christopherson TEST_ASSERT(!ret, "KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO " 547*67730e6cSSean Christopherson "for intid %i failed, rc: %i errno: %i", 548*67730e6cSSean Christopherson intid, ret, errno); 549*67730e6cSSean Christopherson } 550*67730e6cSSean Christopherson } 551*67730e6cSSean Christopherson 552*67730e6cSSean Christopherson static void kvm_set_gsi_routing_irqchip_check(struct kvm_vm *vm, 553*67730e6cSSean Christopherson uint32_t intid, uint32_t num, uint32_t kvm_max_routes, 554*67730e6cSSean Christopherson bool expect_failure) 555*67730e6cSSean Christopherson { 556*67730e6cSSean Christopherson struct kvm_irq_routing *routing; 557*67730e6cSSean Christopherson int ret; 558*67730e6cSSean Christopherson uint64_t i; 559*67730e6cSSean Christopherson 560*67730e6cSSean Christopherson assert(num <= kvm_max_routes && kvm_max_routes <= KVM_MAX_IRQ_ROUTES); 561*67730e6cSSean Christopherson 562*67730e6cSSean Christopherson routing = kvm_gsi_routing_create(); 563*67730e6cSSean Christopherson for (i = intid; i < (uint64_t)intid + num; i++) 564*67730e6cSSean Christopherson kvm_gsi_routing_irqchip_add(routing, i - MIN_SPI, i - MIN_SPI); 565*67730e6cSSean Christopherson 566*67730e6cSSean Christopherson if (!expect_failure) { 567*67730e6cSSean Christopherson kvm_gsi_routing_write(vm, routing); 568*67730e6cSSean Christopherson } else { 569*67730e6cSSean Christopherson ret = _kvm_gsi_routing_write(vm, routing); 570*67730e6cSSean Christopherson /* The kernel only checks e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS */ 571*67730e6cSSean Christopherson if (((uint64_t)intid + num - 1 - MIN_SPI) >= KVM_IRQCHIP_NUM_PINS) 572*67730e6cSSean Christopherson TEST_ASSERT(ret != 0 && errno == EINVAL, 573*67730e6cSSean Christopherson "Bad intid %u did not cause KVM_SET_GSI_ROUTING " 574*67730e6cSSean Christopherson "error: rc: %i errno: %i", intid, ret, errno); 575*67730e6cSSean Christopherson else 576*67730e6cSSean Christopherson TEST_ASSERT(ret == 0, "KVM_SET_GSI_ROUTING " 577*67730e6cSSean Christopherson "for intid %i failed, rc: %i errno: %i", 578*67730e6cSSean Christopherson intid, ret, errno); 579*67730e6cSSean Christopherson } 580*67730e6cSSean Christopherson } 581*67730e6cSSean Christopherson 582*67730e6cSSean Christopherson static void kvm_irq_write_ispendr_check(int gic_fd, uint32_t intid, 583*67730e6cSSean Christopherson struct kvm_vcpu *vcpu, 584*67730e6cSSean Christopherson bool expect_failure) 585*67730e6cSSean Christopherson { 586*67730e6cSSean Christopherson /* 587*67730e6cSSean Christopherson * Ignore this when expecting failure as invalid intids will lead to 588*67730e6cSSean Christopherson * either trying to inject SGIs when we configured the test to be 589*67730e6cSSean Christopherson * level_sensitive (or the reverse), or inject large intids which 590*67730e6cSSean Christopherson * will lead to writing above the ISPENDR register space (and we 591*67730e6cSSean Christopherson * don't want to do that either). 592*67730e6cSSean Christopherson */ 593*67730e6cSSean Christopherson if (!expect_failure) 594*67730e6cSSean Christopherson kvm_irq_write_ispendr(gic_fd, intid, vcpu); 595*67730e6cSSean Christopherson } 596*67730e6cSSean Christopherson 597*67730e6cSSean Christopherson static void kvm_routing_and_irqfd_check(struct kvm_vm *vm, 598*67730e6cSSean Christopherson uint32_t intid, uint32_t num, uint32_t kvm_max_routes, 599*67730e6cSSean Christopherson bool expect_failure) 600*67730e6cSSean Christopherson { 601*67730e6cSSean Christopherson int fd[MAX_SPI]; 602*67730e6cSSean Christopherson uint64_t val; 603*67730e6cSSean Christopherson int ret, f; 604*67730e6cSSean Christopherson uint64_t i; 605*67730e6cSSean Christopherson 606*67730e6cSSean Christopherson /* 607*67730e6cSSean Christopherson * There is no way to try injecting an SGI or PPI as the interface 608*67730e6cSSean Christopherson * starts counting from the first SPI (above the private ones), so just 609*67730e6cSSean Christopherson * exit. 610*67730e6cSSean Christopherson */ 611*67730e6cSSean Christopherson if (INTID_IS_SGI(intid) || INTID_IS_PPI(intid)) 612*67730e6cSSean Christopherson return; 613*67730e6cSSean Christopherson 614*67730e6cSSean Christopherson kvm_set_gsi_routing_irqchip_check(vm, intid, num, 615*67730e6cSSean Christopherson kvm_max_routes, expect_failure); 616*67730e6cSSean Christopherson 617*67730e6cSSean Christopherson /* 618*67730e6cSSean Christopherson * If expect_failure, then just to inject anyway. These 619*67730e6cSSean Christopherson * will silently fail. And in any case, the guest will check 620*67730e6cSSean Christopherson * that no actual interrupt was injected for those cases. 621*67730e6cSSean Christopherson */ 622*67730e6cSSean Christopherson 623*67730e6cSSean Christopherson for (f = 0, i = intid; i < (uint64_t)intid + num; i++, f++) { 624*67730e6cSSean Christopherson fd[f] = eventfd(0, 0); 625*67730e6cSSean Christopherson TEST_ASSERT(fd[f] != -1, __KVM_SYSCALL_ERROR("eventfd()", fd[f])); 626*67730e6cSSean Christopherson } 627*67730e6cSSean Christopherson 628*67730e6cSSean Christopherson for (f = 0, i = intid; i < (uint64_t)intid + num; i++, f++) { 629*67730e6cSSean Christopherson struct kvm_irqfd irqfd = { 630*67730e6cSSean Christopherson .fd = fd[f], 631*67730e6cSSean Christopherson .gsi = i - MIN_SPI, 632*67730e6cSSean Christopherson }; 633*67730e6cSSean Christopherson assert(i <= (uint64_t)UINT_MAX); 634*67730e6cSSean Christopherson vm_ioctl(vm, KVM_IRQFD, &irqfd); 635*67730e6cSSean Christopherson } 636*67730e6cSSean Christopherson 637*67730e6cSSean Christopherson for (f = 0, i = intid; i < (uint64_t)intid + num; i++, f++) { 638*67730e6cSSean Christopherson val = 1; 639*67730e6cSSean Christopherson ret = write(fd[f], &val, sizeof(uint64_t)); 640*67730e6cSSean Christopherson TEST_ASSERT(ret == sizeof(uint64_t), 641*67730e6cSSean Christopherson __KVM_SYSCALL_ERROR("write()", ret)); 642*67730e6cSSean Christopherson } 643*67730e6cSSean Christopherson 644*67730e6cSSean Christopherson for (f = 0, i = intid; i < (uint64_t)intid + num; i++, f++) 645*67730e6cSSean Christopherson close(fd[f]); 646*67730e6cSSean Christopherson } 647*67730e6cSSean Christopherson 648*67730e6cSSean Christopherson /* handles the valid case: intid=0xffffffff num=1 */ 649*67730e6cSSean Christopherson #define for_each_intid(first, num, tmp, i) \ 650*67730e6cSSean Christopherson for ((tmp) = (i) = (first); \ 651*67730e6cSSean Christopherson (tmp) < (uint64_t)(first) + (uint64_t)(num); \ 652*67730e6cSSean Christopherson (tmp)++, (i)++) 653*67730e6cSSean Christopherson 654*67730e6cSSean Christopherson static void run_guest_cmd(struct kvm_vcpu *vcpu, int gic_fd, 655*67730e6cSSean Christopherson struct kvm_inject_args *inject_args, 656*67730e6cSSean Christopherson struct test_args *test_args) 657*67730e6cSSean Christopherson { 658*67730e6cSSean Christopherson kvm_inject_cmd cmd = inject_args->cmd; 659*67730e6cSSean Christopherson uint32_t intid = inject_args->first_intid; 660*67730e6cSSean Christopherson uint32_t num = inject_args->num; 661*67730e6cSSean Christopherson int level = inject_args->level; 662*67730e6cSSean Christopherson bool expect_failure = inject_args->expect_failure; 663*67730e6cSSean Christopherson struct kvm_vm *vm = vcpu->vm; 664*67730e6cSSean Christopherson uint64_t tmp; 665*67730e6cSSean Christopherson uint32_t i; 666*67730e6cSSean Christopherson 667*67730e6cSSean Christopherson /* handles the valid case: intid=0xffffffff num=1 */ 668*67730e6cSSean Christopherson assert(intid < UINT_MAX - num || num == 1); 669*67730e6cSSean Christopherson 670*67730e6cSSean Christopherson switch (cmd) { 671*67730e6cSSean Christopherson case KVM_INJECT_EDGE_IRQ_LINE: 672*67730e6cSSean Christopherson for_each_intid(intid, num, tmp, i) 673*67730e6cSSean Christopherson kvm_irq_line_check(vm, i, 1, test_args, 674*67730e6cSSean Christopherson expect_failure); 675*67730e6cSSean Christopherson for_each_intid(intid, num, tmp, i) 676*67730e6cSSean Christopherson kvm_irq_line_check(vm, i, 0, test_args, 677*67730e6cSSean Christopherson expect_failure); 678*67730e6cSSean Christopherson break; 679*67730e6cSSean Christopherson case KVM_SET_IRQ_LINE: 680*67730e6cSSean Christopherson for_each_intid(intid, num, tmp, i) 681*67730e6cSSean Christopherson kvm_irq_line_check(vm, i, level, test_args, 682*67730e6cSSean Christopherson expect_failure); 683*67730e6cSSean Christopherson break; 684*67730e6cSSean Christopherson case KVM_SET_IRQ_LINE_HIGH: 685*67730e6cSSean Christopherson for_each_intid(intid, num, tmp, i) 686*67730e6cSSean Christopherson kvm_irq_line_check(vm, i, 1, test_args, 687*67730e6cSSean Christopherson expect_failure); 688*67730e6cSSean Christopherson break; 689*67730e6cSSean Christopherson case KVM_SET_LEVEL_INFO_HIGH: 690*67730e6cSSean Christopherson for_each_intid(intid, num, tmp, i) 691*67730e6cSSean Christopherson kvm_irq_set_level_info_check(gic_fd, i, 1, 692*67730e6cSSean Christopherson expect_failure); 693*67730e6cSSean Christopherson break; 694*67730e6cSSean Christopherson case KVM_INJECT_IRQFD: 695*67730e6cSSean Christopherson kvm_routing_and_irqfd_check(vm, intid, num, 696*67730e6cSSean Christopherson test_args->kvm_max_routes, 697*67730e6cSSean Christopherson expect_failure); 698*67730e6cSSean Christopherson break; 699*67730e6cSSean Christopherson case KVM_WRITE_ISPENDR: 700*67730e6cSSean Christopherson for (i = intid; i < intid + num; i++) 701*67730e6cSSean Christopherson kvm_irq_write_ispendr_check(gic_fd, i, vcpu, 702*67730e6cSSean Christopherson expect_failure); 703*67730e6cSSean Christopherson break; 704*67730e6cSSean Christopherson case KVM_WRITE_ISACTIVER: 705*67730e6cSSean Christopherson for (i = intid; i < intid + num; i++) 706*67730e6cSSean Christopherson kvm_irq_write_isactiver(gic_fd, i, vcpu); 707*67730e6cSSean Christopherson break; 708*67730e6cSSean Christopherson default: 709*67730e6cSSean Christopherson break; 710*67730e6cSSean Christopherson } 711*67730e6cSSean Christopherson } 712*67730e6cSSean Christopherson 713*67730e6cSSean Christopherson static void kvm_inject_get_call(struct kvm_vm *vm, struct ucall *uc, 714*67730e6cSSean Christopherson struct kvm_inject_args *args) 715*67730e6cSSean Christopherson { 716*67730e6cSSean Christopherson struct kvm_inject_args *kvm_args_hva; 717*67730e6cSSean Christopherson vm_vaddr_t kvm_args_gva; 718*67730e6cSSean Christopherson 719*67730e6cSSean Christopherson kvm_args_gva = uc->args[1]; 720*67730e6cSSean Christopherson kvm_args_hva = (struct kvm_inject_args *)addr_gva2hva(vm, kvm_args_gva); 721*67730e6cSSean Christopherson memcpy(args, kvm_args_hva, sizeof(struct kvm_inject_args)); 722*67730e6cSSean Christopherson } 723*67730e6cSSean Christopherson 724*67730e6cSSean Christopherson static void print_args(struct test_args *args) 725*67730e6cSSean Christopherson { 726*67730e6cSSean Christopherson printf("nr-irqs=%d level-sensitive=%d eoi-split=%d\n", 727*67730e6cSSean Christopherson args->nr_irqs, args->level_sensitive, 728*67730e6cSSean Christopherson args->eoi_split); 729*67730e6cSSean Christopherson } 730*67730e6cSSean Christopherson 731*67730e6cSSean Christopherson static void test_vgic(uint32_t nr_irqs, bool level_sensitive, bool eoi_split) 732*67730e6cSSean Christopherson { 733*67730e6cSSean Christopherson struct ucall uc; 734*67730e6cSSean Christopherson int gic_fd; 735*67730e6cSSean Christopherson struct kvm_vcpu *vcpu; 736*67730e6cSSean Christopherson struct kvm_vm *vm; 737*67730e6cSSean Christopherson struct kvm_inject_args inject_args; 738*67730e6cSSean Christopherson vm_vaddr_t args_gva; 739*67730e6cSSean Christopherson 740*67730e6cSSean Christopherson struct test_args args = { 741*67730e6cSSean Christopherson .nr_irqs = nr_irqs, 742*67730e6cSSean Christopherson .level_sensitive = level_sensitive, 743*67730e6cSSean Christopherson .eoi_split = eoi_split, 744*67730e6cSSean Christopherson .kvm_max_routes = kvm_check_cap(KVM_CAP_IRQ_ROUTING), 745*67730e6cSSean Christopherson .kvm_supports_irqfd = kvm_check_cap(KVM_CAP_IRQFD), 746*67730e6cSSean Christopherson }; 747*67730e6cSSean Christopherson 748*67730e6cSSean Christopherson print_args(&args); 749*67730e6cSSean Christopherson 750*67730e6cSSean Christopherson vm = vm_create_with_one_vcpu(&vcpu, guest_code); 751*67730e6cSSean Christopherson 752*67730e6cSSean Christopherson vm_init_descriptor_tables(vm); 753*67730e6cSSean Christopherson vcpu_init_descriptor_tables(vcpu); 754*67730e6cSSean Christopherson 755*67730e6cSSean Christopherson /* Setup the guest args page (so it gets the args). */ 756*67730e6cSSean Christopherson args_gva = vm_vaddr_alloc_page(vm); 757*67730e6cSSean Christopherson memcpy(addr_gva2hva(vm, args_gva), &args, sizeof(args)); 758*67730e6cSSean Christopherson vcpu_args_set(vcpu, 1, args_gva); 759*67730e6cSSean Christopherson 760*67730e6cSSean Christopherson gic_fd = vgic_v3_setup(vm, 1, nr_irqs); 761*67730e6cSSean Christopherson __TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3, skipping"); 762*67730e6cSSean Christopherson 763*67730e6cSSean Christopherson vm_install_exception_handler(vm, VECTOR_IRQ_CURRENT, 764*67730e6cSSean Christopherson guest_irq_handlers[args.eoi_split][args.level_sensitive]); 765*67730e6cSSean Christopherson 766*67730e6cSSean Christopherson while (1) { 767*67730e6cSSean Christopherson vcpu_run(vcpu); 768*67730e6cSSean Christopherson 769*67730e6cSSean Christopherson switch (get_ucall(vcpu, &uc)) { 770*67730e6cSSean Christopherson case UCALL_SYNC: 771*67730e6cSSean Christopherson kvm_inject_get_call(vm, &uc, &inject_args); 772*67730e6cSSean Christopherson run_guest_cmd(vcpu, gic_fd, &inject_args, &args); 773*67730e6cSSean Christopherson break; 774*67730e6cSSean Christopherson case UCALL_ABORT: 775*67730e6cSSean Christopherson REPORT_GUEST_ASSERT(uc); 776*67730e6cSSean Christopherson break; 777*67730e6cSSean Christopherson case UCALL_DONE: 778*67730e6cSSean Christopherson goto done; 779*67730e6cSSean Christopherson default: 780*67730e6cSSean Christopherson TEST_FAIL("Unknown ucall %lu", uc.cmd); 781*67730e6cSSean Christopherson } 782*67730e6cSSean Christopherson } 783*67730e6cSSean Christopherson 784*67730e6cSSean Christopherson done: 785*67730e6cSSean Christopherson close(gic_fd); 786*67730e6cSSean Christopherson kvm_vm_free(vm); 787*67730e6cSSean Christopherson } 788*67730e6cSSean Christopherson 789*67730e6cSSean Christopherson static void help(const char *name) 790*67730e6cSSean Christopherson { 791*67730e6cSSean Christopherson printf( 792*67730e6cSSean Christopherson "\n" 793*67730e6cSSean Christopherson "usage: %s [-n num_irqs] [-e eoi_split] [-l level_sensitive]\n", name); 794*67730e6cSSean Christopherson printf(" -n: specify number of IRQs to setup the vgic with. " 795*67730e6cSSean Christopherson "It has to be a multiple of 32 and between 64 and 1024.\n"); 796*67730e6cSSean Christopherson printf(" -e: if 1 then EOI is split into a write to DIR on top " 797*67730e6cSSean Christopherson "of writing EOI.\n"); 798*67730e6cSSean Christopherson printf(" -l: specify whether the IRQs are level-sensitive (1) or not (0)."); 799*67730e6cSSean Christopherson puts(""); 800*67730e6cSSean Christopherson exit(1); 801*67730e6cSSean Christopherson } 802*67730e6cSSean Christopherson 803*67730e6cSSean Christopherson int main(int argc, char **argv) 804*67730e6cSSean Christopherson { 805*67730e6cSSean Christopherson uint32_t nr_irqs = 64; 806*67730e6cSSean Christopherson bool default_args = true; 807*67730e6cSSean Christopherson bool level_sensitive = false; 808*67730e6cSSean Christopherson int opt; 809*67730e6cSSean Christopherson bool eoi_split = false; 810*67730e6cSSean Christopherson 811*67730e6cSSean Christopherson while ((opt = getopt(argc, argv, "hn:e:l:")) != -1) { 812*67730e6cSSean Christopherson switch (opt) { 813*67730e6cSSean Christopherson case 'n': 814*67730e6cSSean Christopherson nr_irqs = atoi_non_negative("Number of IRQs", optarg); 815*67730e6cSSean Christopherson if (nr_irqs > 1024 || nr_irqs % 32) 816*67730e6cSSean Christopherson help(argv[0]); 817*67730e6cSSean Christopherson break; 818*67730e6cSSean Christopherson case 'e': 819*67730e6cSSean Christopherson eoi_split = (bool)atoi_paranoid(optarg); 820*67730e6cSSean Christopherson default_args = false; 821*67730e6cSSean Christopherson break; 822*67730e6cSSean Christopherson case 'l': 823*67730e6cSSean Christopherson level_sensitive = (bool)atoi_paranoid(optarg); 824*67730e6cSSean Christopherson default_args = false; 825*67730e6cSSean Christopherson break; 826*67730e6cSSean Christopherson case 'h': 827*67730e6cSSean Christopherson default: 828*67730e6cSSean Christopherson help(argv[0]); 829*67730e6cSSean Christopherson break; 830*67730e6cSSean Christopherson } 831*67730e6cSSean Christopherson } 832*67730e6cSSean Christopherson 833*67730e6cSSean Christopherson /* 834*67730e6cSSean Christopherson * If the user just specified nr_irqs and/or gic_version, then run all 835*67730e6cSSean Christopherson * combinations. 836*67730e6cSSean Christopherson */ 837*67730e6cSSean Christopherson if (default_args) { 838*67730e6cSSean Christopherson test_vgic(nr_irqs, false /* level */, false /* eoi_split */); 839*67730e6cSSean Christopherson test_vgic(nr_irqs, false /* level */, true /* eoi_split */); 840*67730e6cSSean Christopherson test_vgic(nr_irqs, true /* level */, false /* eoi_split */); 841*67730e6cSSean Christopherson test_vgic(nr_irqs, true /* level */, true /* eoi_split */); 842*67730e6cSSean Christopherson } else { 843*67730e6cSSean Christopherson test_vgic(nr_irqs, level_sensitive, eoi_split); 844*67730e6cSSean Christopherson } 845*67730e6cSSean Christopherson 846*67730e6cSSean Christopherson return 0; 847*67730e6cSSean Christopherson } 848