Commit e7062a98 authored by David Woodhouse's avatar David Woodhouse Committed by Paolo Bonzini
Browse files

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: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Message-Id: <20230204024151.1373296-4-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent c0c76d99
Loading
Loading
Loading
Loading
+82 −51
Original line number Diff line number Diff line
@@ -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 @@ static void guest_code(void)
	 * 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;