diff options
author | Sean Christopherson <seanjc@google.com> | 2023-02-04 02:41:49 +0000 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2023-03-14 10:20:08 -0400 |
commit | c0c76d99939cb4ac28cbc5ce542cff2b9e1e1b02 (patch) | |
tree | b2621f428d853da0561fc7f315424afc9b0f25b1 /tools/testing | |
parent | 4009e0bb7b83d967a14e108d271f003b378f9af9 (diff) | |
download | lwn-c0c76d99939cb4ac28cbc5ce542cff2b9e1e1b02.tar.gz lwn-c0c76d99939cb4ac28cbc5ce542cff2b9e1e1b02.zip |
KVM: selftests: Add helpers to make Xen-style VMCALL/VMMCALL hypercalls
Add wrappers to do hypercalls using VMCALL/VMMCALL and Xen's register ABI
(as opposed to full Xen-style hypercalls through a hypervisor provided
page). Using the common helpers dedups a pile of code, and uses the
native hypercall instruction when running on AMD.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20230204024151.1373296-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'tools/testing')
-rw-r--r-- | tools/testing/selftests/kvm/include/x86_64/processor.h | 2 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/lib/x86_64/processor.c | 10 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c | 63 |
3 files changed, 21 insertions, 54 deletions
diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 53ffa43c90db..90387ddcb2a9 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -1063,6 +1063,8 @@ uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr); uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3); +uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1); +void xen_hypercall(uint64_t nr, uint64_t a0, void *a1); void __vm_xsave_require_permission(int bit, const char *name); diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index ff901cb47ffc..c39a4353ba19 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1161,6 +1161,16 @@ uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, return X86_HYPERCALL("a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); } +uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1) +{ + return X86_HYPERCALL("a"(nr), "D"(a0), "S"(a1)); +} + +void xen_hypercall(uint64_t nr, uint64_t a0, void *a1) +{ + GUEST_ASSERT(!__xen_hypercall(nr, a0, a1)); +} + const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void) { static struct kvm_cpuid2 *cpuid; diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c index 5a3bf8f61417..827b8e126f2f 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -225,15 +225,8 @@ static void guest_code(void) /* Our turn. Deliver event channel (to ourselves) with * EVTCHNOP_send hypercall. */ - unsigned long rax; struct evtchn_send s = { .port = 127 }; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_event_channel_op), - "D" (EVTCHNOP_send), - "S" (&s)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s); guest_wait_for_irq(); @@ -242,24 +235,15 @@ static void guest_code(void) /* Deliver "outbound" event channel to an eventfd which * happens to be one of our own irqfds. */ s.port = 197; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_event_channel_op), - "D" (EVTCHNOP_send), - "S" (&s)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s); guest_wait_for_irq(); GUEST_SYNC(13); /* Set a timer 100ms in the future. */ - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_set_timer_op), - "D" (rs->state_entry_time + 100000000)); - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_set_timer_op, + rs->state_entry_time + 100000000, NULL); GUEST_SYNC(14); @@ -281,37 +265,19 @@ static void guest_code(void) .timeout = 0, }; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); GUEST_SYNC(17); /* Poll for an unset port and wait for the timeout. */ p.timeout = 100000000; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); GUEST_SYNC(18); /* A timer will wake the masked port we're waiting on, while we poll */ p.timeout = 0; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); GUEST_SYNC(19); @@ -319,13 +285,7 @@ static void guest_code(void) * actual interrupt, while we're polling on a different port. */ ports[0]++; p.timeout = 0; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); guest_wait_for_irq(); @@ -360,12 +320,7 @@ wait_for_timer: * timer IRQ is dropped due to an invalid event channel. */ for (i = 0; i < 100 && !guest_saw_irq; i++) - asm volatile("vmcall" - : "=a" (rax) - : "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p) - : "memory"); + __xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); /* * Re-send the timer IRQ if it was (likely) dropped due to the timer |