mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 23:00:21 +00:00
KVM: selftests: Use enum for test numbers in xen_shinfo_test
The xen_shinfo_test started off with very few iterations, and the numbers we used in GUEST_SYNC() were precisely mapped to the RUNSTATE_xxx values anyway to start with. It has since grown quite a few more tests, and it's kind of awful to be handling them all as bare numbers. Especially when I want to add a new test in the middle. Define an enum for the test stages, and use it both in the guest code and the host switch statement. No functional change, if I can count to 24. Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20230204024151.1373296-4-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
c0c76d9993
commit
e7062a98d0
@ -41,6 +41,36 @@
|
||||
#define EVTCHN_TEST2 66
|
||||
#define EVTCHN_TIMER 13
|
||||
|
||||
enum {
|
||||
TEST_INJECT_VECTOR = 0,
|
||||
TEST_RUNSTATE_runnable,
|
||||
TEST_RUNSTATE_blocked,
|
||||
TEST_RUNSTATE_offline,
|
||||
TEST_RUNSTATE_ADJUST,
|
||||
TEST_RUNSTATE_DATA,
|
||||
TEST_STEAL_TIME,
|
||||
TEST_EVTCHN_MASKED,
|
||||
TEST_EVTCHN_UNMASKED,
|
||||
TEST_EVTCHN_SLOWPATH,
|
||||
TEST_EVTCHN_SEND_IOCTL,
|
||||
TEST_EVTCHN_HCALL,
|
||||
TEST_EVTCHN_HCALL_EVENTFD,
|
||||
TEST_TIMER_SETUP,
|
||||
TEST_TIMER_WAIT,
|
||||
TEST_TIMER_RESTORE,
|
||||
TEST_POLL_READY,
|
||||
TEST_POLL_TIMEOUT,
|
||||
TEST_POLL_MASKED,
|
||||
TEST_POLL_WAKE,
|
||||
TEST_TIMER_PAST,
|
||||
TEST_LOCKING_SEND_RACE,
|
||||
TEST_LOCKING_POLL_RACE,
|
||||
TEST_LOCKING_POLL_TIMEOUT,
|
||||
TEST_DONE,
|
||||
|
||||
TEST_GUEST_SAW_IRQ,
|
||||
};
|
||||
|
||||
#define XEN_HYPERCALL_MSR 0x40000000
|
||||
|
||||
#define MIN_STEAL_TIME 50000
|
||||
@ -144,7 +174,7 @@ static void evtchn_handler(struct ex_regs *regs)
|
||||
vi->evtchn_pending_sel = 0;
|
||||
guest_saw_irq = true;
|
||||
|
||||
GUEST_SYNC(0x20);
|
||||
GUEST_SYNC(TEST_GUEST_SAW_IRQ);
|
||||
}
|
||||
|
||||
static void guest_wait_for_irq(void)
|
||||
@ -165,41 +195,41 @@ static void guest_code(void)
|
||||
);
|
||||
|
||||
/* Trigger an interrupt injection */
|
||||
GUEST_SYNC(0);
|
||||
GUEST_SYNC(TEST_INJECT_VECTOR);
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
/* Test having the host set runstates manually */
|
||||
GUEST_SYNC(RUNSTATE_runnable);
|
||||
GUEST_SYNC(TEST_RUNSTATE_runnable);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_runnable] != 0);
|
||||
GUEST_ASSERT(rs->state == 0);
|
||||
|
||||
GUEST_SYNC(RUNSTATE_blocked);
|
||||
GUEST_SYNC(TEST_RUNSTATE_blocked);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_blocked] != 0);
|
||||
GUEST_ASSERT(rs->state == 0);
|
||||
|
||||
GUEST_SYNC(RUNSTATE_offline);
|
||||
GUEST_SYNC(TEST_RUNSTATE_offline);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_offline] != 0);
|
||||
GUEST_ASSERT(rs->state == 0);
|
||||
|
||||
/* Test runstate time adjust */
|
||||
GUEST_SYNC(4);
|
||||
GUEST_SYNC(TEST_RUNSTATE_ADJUST);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x5a);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x6b6b);
|
||||
|
||||
/* Test runstate time set */
|
||||
GUEST_SYNC(5);
|
||||
GUEST_SYNC(TEST_RUNSTATE_DATA);
|
||||
GUEST_ASSERT(rs->state_entry_time >= 0x8000);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_runnable] == 0);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x6b6b);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x5a);
|
||||
|
||||
/* sched_yield() should result in some 'runnable' time */
|
||||
GUEST_SYNC(6);
|
||||
GUEST_SYNC(TEST_STEAL_TIME);
|
||||
GUEST_ASSERT(rs->time[RUNSTATE_runnable] >= MIN_STEAL_TIME);
|
||||
|
||||
/* Attempt to deliver a *masked* interrupt */
|
||||
GUEST_SYNC(7);
|
||||
GUEST_SYNC(TEST_EVTCHN_MASKED);
|
||||
|
||||
/* Wait until we see the bit set */
|
||||
struct shared_info *si = (void *)SHINFO_VADDR;
|
||||
@ -207,21 +237,21 @@ static void guest_code(void)
|
||||
__asm__ __volatile__ ("rep nop" : : : "memory");
|
||||
|
||||
/* Now deliver an *unmasked* interrupt */
|
||||
GUEST_SYNC(8);
|
||||
GUEST_SYNC(TEST_EVTCHN_UNMASKED);
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
/* Change memslots and deliver an interrupt */
|
||||
GUEST_SYNC(9);
|
||||
GUEST_SYNC(TEST_EVTCHN_SLOWPATH);
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
/* Deliver event channel with KVM_XEN_HVM_EVTCHN_SEND */
|
||||
GUEST_SYNC(10);
|
||||
GUEST_SYNC(TEST_EVTCHN_SEND_IOCTL);
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(11);
|
||||
GUEST_SYNC(TEST_EVTCHN_HCALL);
|
||||
|
||||
/* Our turn. Deliver event channel (to ourselves) with
|
||||
* EVTCHNOP_send hypercall. */
|
||||
@ -230,7 +260,7 @@ static void guest_code(void)
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(12);
|
||||
GUEST_SYNC(TEST_EVTCHN_HCALL_EVENTFD);
|
||||
|
||||
/* Deliver "outbound" event channel to an eventfd which
|
||||
* happens to be one of our own irqfds. */
|
||||
@ -239,23 +269,23 @@ static void guest_code(void)
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(13);
|
||||
GUEST_SYNC(TEST_TIMER_SETUP);
|
||||
|
||||
/* Set a timer 100ms in the future. */
|
||||
xen_hypercall(__HYPERVISOR_set_timer_op,
|
||||
rs->state_entry_time + 100000000, NULL);
|
||||
|
||||
GUEST_SYNC(14);
|
||||
GUEST_SYNC(TEST_TIMER_WAIT);
|
||||
|
||||
/* Now wait for the timer */
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(15);
|
||||
GUEST_SYNC(TEST_TIMER_RESTORE);
|
||||
|
||||
/* The host has 'restored' the timer. Just wait for it. */
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(16);
|
||||
GUEST_SYNC(TEST_POLL_READY);
|
||||
|
||||
/* Poll for an event channel port which is already set */
|
||||
u32 ports[1] = { EVTCHN_TIMER };
|
||||
@ -267,19 +297,19 @@ static void guest_code(void)
|
||||
|
||||
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
|
||||
|
||||
GUEST_SYNC(17);
|
||||
GUEST_SYNC(TEST_POLL_TIMEOUT);
|
||||
|
||||
/* Poll for an unset port and wait for the timeout. */
|
||||
p.timeout = 100000000;
|
||||
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
|
||||
|
||||
GUEST_SYNC(18);
|
||||
GUEST_SYNC(TEST_POLL_MASKED);
|
||||
|
||||
/* A timer will wake the masked port we're waiting on, while we poll */
|
||||
p.timeout = 0;
|
||||
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
|
||||
|
||||
GUEST_SYNC(19);
|
||||
GUEST_SYNC(TEST_POLL_WAKE);
|
||||
|
||||
/* A timer wake an *unmasked* port which should wake us with an
|
||||
* actual interrupt, while we're polling on a different port. */
|
||||
@ -289,17 +319,17 @@ static void guest_code(void)
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(20);
|
||||
GUEST_SYNC(TEST_TIMER_PAST);
|
||||
|
||||
/* Timer should have fired already */
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(21);
|
||||
GUEST_SYNC(TEST_LOCKING_SEND_RACE);
|
||||
/* Racing host ioctls */
|
||||
|
||||
guest_wait_for_irq();
|
||||
|
||||
GUEST_SYNC(22);
|
||||
GUEST_SYNC(TEST_LOCKING_POLL_RACE);
|
||||
/* Racing vmcall against host ioctl */
|
||||
|
||||
ports[0] = 0;
|
||||
@ -327,12 +357,12 @@ wait_for_timer:
|
||||
* expiring while the event channel was invalid.
|
||||
*/
|
||||
if (!guest_saw_irq) {
|
||||
GUEST_SYNC(23);
|
||||
GUEST_SYNC(TEST_LOCKING_POLL_TIMEOUT);
|
||||
goto wait_for_timer;
|
||||
}
|
||||
guest_saw_irq = false;
|
||||
|
||||
GUEST_SYNC(24);
|
||||
GUEST_SYNC(TEST_DONE);
|
||||
}
|
||||
|
||||
static int cmp_timespec(struct timespec *a, struct timespec *b)
|
||||
@ -602,25 +632,26 @@ int main(int argc, char *argv[])
|
||||
"runstate times don't add up");
|
||||
|
||||
switch (uc.args[1]) {
|
||||
case 0:
|
||||
case TEST_INJECT_VECTOR:
|
||||
if (verbose)
|
||||
printf("Delivering evtchn upcall\n");
|
||||
evtchn_irq_expected = true;
|
||||
vinfo->evtchn_upcall_pending = 1;
|
||||
break;
|
||||
|
||||
case RUNSTATE_runnable...RUNSTATE_offline:
|
||||
case TEST_RUNSTATE_runnable...TEST_RUNSTATE_offline:
|
||||
TEST_ASSERT(!evtchn_irq_expected, "Event channel IRQ not seen");
|
||||
if (!do_runstate_tests)
|
||||
goto done;
|
||||
if (verbose)
|
||||
printf("Testing runstate %s\n", runstate_names[uc.args[1]]);
|
||||
rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT;
|
||||
rst.u.runstate.state = uc.args[1];
|
||||
rst.u.runstate.state = uc.args[1] + RUNSTATE_runnable -
|
||||
TEST_RUNSTATE_runnable;
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case TEST_RUNSTATE_ADJUST:
|
||||
if (verbose)
|
||||
printf("Testing RUNSTATE_ADJUST\n");
|
||||
rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST;
|
||||
@ -635,7 +666,7 @@ int main(int argc, char *argv[])
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case TEST_RUNSTATE_DATA:
|
||||
if (verbose)
|
||||
printf("Testing RUNSTATE_DATA\n");
|
||||
rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA;
|
||||
@ -647,7 +678,7 @@ int main(int argc, char *argv[])
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case TEST_STEAL_TIME:
|
||||
if (verbose)
|
||||
printf("Testing steal time\n");
|
||||
/* Yield until scheduler delay exceeds target */
|
||||
@ -657,7 +688,7 @@ int main(int argc, char *argv[])
|
||||
} while (get_run_delay() < rundelay);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case TEST_EVTCHN_MASKED:
|
||||
if (!do_eventfd_tests)
|
||||
goto done;
|
||||
if (verbose)
|
||||
@ -667,7 +698,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case TEST_EVTCHN_UNMASKED:
|
||||
if (verbose)
|
||||
printf("Testing unmasked event channel\n");
|
||||
/* Unmask that, but deliver the other one */
|
||||
@ -678,7 +709,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
case TEST_EVTCHN_SLOWPATH:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
shinfo->evtchn_pending[1] = 0;
|
||||
@ -691,7 +722,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
case TEST_EVTCHN_SEND_IOCTL:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
if (!do_evtchn_tests)
|
||||
@ -711,7 +742,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
case TEST_EVTCHN_HCALL:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
shinfo->evtchn_pending[1] = 0;
|
||||
@ -722,7 +753,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
case TEST_EVTCHN_HCALL_EVENTFD:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
shinfo->evtchn_pending[0] = 0;
|
||||
@ -733,7 +764,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
case TEST_TIMER_SETUP:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
shinfo->evtchn_pending[1] = 0;
|
||||
@ -742,7 +773,7 @@ int main(int argc, char *argv[])
|
||||
printf("Testing guest oneshot timer\n");
|
||||
break;
|
||||
|
||||
case 14:
|
||||
case TEST_TIMER_WAIT:
|
||||
memset(&tmr, 0, sizeof(tmr));
|
||||
tmr.type = KVM_XEN_VCPU_ATTR_TYPE_TIMER;
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_GET_ATTR, &tmr);
|
||||
@ -756,7 +787,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case TEST_TIMER_RESTORE:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
shinfo->evtchn_pending[0] = 0;
|
||||
@ -770,7 +801,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
case TEST_POLL_READY:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
|
||||
@ -780,14 +811,14 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 17:
|
||||
case TEST_POLL_TIMEOUT:
|
||||
if (verbose)
|
||||
printf("Testing SCHEDOP_poll timeout\n");
|
||||
shinfo->evtchn_pending[0] = 0;
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 18:
|
||||
case TEST_POLL_MASKED:
|
||||
if (verbose)
|
||||
printf("Testing SCHEDOP_poll wake on masked event\n");
|
||||
|
||||
@ -796,7 +827,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 19:
|
||||
case TEST_POLL_WAKE:
|
||||
shinfo->evtchn_pending[0] = shinfo->evtchn_mask[0] = 0;
|
||||
if (verbose)
|
||||
printf("Testing SCHEDOP_poll wake on unmasked event\n");
|
||||
@ -813,7 +844,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 20:
|
||||
case TEST_TIMER_PAST:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
/* Read timer and check it is no longer pending */
|
||||
@ -830,7 +861,7 @@ int main(int argc, char *argv[])
|
||||
alarm(1);
|
||||
break;
|
||||
|
||||
case 21:
|
||||
case TEST_LOCKING_SEND_RACE:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
alarm(0);
|
||||
@ -852,7 +883,7 @@ int main(int argc, char *argv[])
|
||||
__vm_ioctl(vm, KVM_XEN_HVM_EVTCHN_SEND, &uxe);
|
||||
break;
|
||||
|
||||
case 22:
|
||||
case TEST_LOCKING_POLL_RACE:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
|
||||
@ -867,7 +898,7 @@ int main(int argc, char *argv[])
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &tmr);
|
||||
break;
|
||||
|
||||
case 23:
|
||||
case TEST_LOCKING_POLL_TIMEOUT:
|
||||
/*
|
||||
* Optional and possibly repeated sync point.
|
||||
* Injecting the timer IRQ may fail if the
|
||||
@ -889,7 +920,7 @@ int main(int argc, char *argv[])
|
||||
SHINFO_RACE_TIMEOUT * 1000000000ULL;
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &tmr);
|
||||
break;
|
||||
case 24:
|
||||
case TEST_DONE:
|
||||
TEST_ASSERT(!evtchn_irq_expected,
|
||||
"Expected event channel IRQ but it didn't happen");
|
||||
|
||||
@ -900,7 +931,7 @@ int main(int argc, char *argv[])
|
||||
TEST_ASSERT(ret == 0, "pthread_join() failed: %s", strerror(ret));
|
||||
goto done;
|
||||
|
||||
case 0x20:
|
||||
case TEST_GUEST_SAW_IRQ:
|
||||
TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ");
|
||||
evtchn_irq_expected = false;
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user