Commit c0c76d99 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

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: default avatarSean Christopherson <seanjc@google.com>
Message-Id: <20230204024151.1373296-3-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 4009e0bb
...@@ -1063,6 +1063,8 @@ uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr); ...@@ -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 kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3); 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); void __vm_xsave_require_permission(int bit, const char *name);
......
...@@ -1161,6 +1161,16 @@ uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, ...@@ -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)); 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) const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void)
{ {
static struct kvm_cpuid2 *cpuid; static struct kvm_cpuid2 *cpuid;
......
...@@ -225,15 +225,8 @@ static void guest_code(void) ...@@ -225,15 +225,8 @@ static void guest_code(void)
/* Our turn. Deliver event channel (to ourselves) with /* Our turn. Deliver event channel (to ourselves) with
* EVTCHNOP_send hypercall. */ * EVTCHNOP_send hypercall. */
unsigned long rax;
struct evtchn_send s = { .port = 127 }; struct evtchn_send s = { .port = 127 };
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
"=a" (rax) :
"a" (__HYPERVISOR_event_channel_op),
"D" (EVTCHNOP_send),
"S" (&s));
GUEST_ASSERT(rax == 0);
guest_wait_for_irq(); guest_wait_for_irq();
...@@ -242,24 +235,15 @@ static void guest_code(void) ...@@ -242,24 +235,15 @@ static void guest_code(void)
/* Deliver "outbound" event channel to an eventfd which /* Deliver "outbound" event channel to an eventfd which
* happens to be one of our own irqfds. */ * happens to be one of our own irqfds. */
s.port = 197; s.port = 197;
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
"=a" (rax) :
"a" (__HYPERVISOR_event_channel_op),
"D" (EVTCHNOP_send),
"S" (&s));
GUEST_ASSERT(rax == 0);
guest_wait_for_irq(); guest_wait_for_irq();
GUEST_SYNC(13); GUEST_SYNC(13);
/* Set a timer 100ms in the future. */ /* Set a timer 100ms in the future. */
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_set_timer_op,
"=a" (rax) : rs->state_entry_time + 100000000, NULL);
"a" (__HYPERVISOR_set_timer_op),
"D" (rs->state_entry_time + 100000000));
GUEST_ASSERT(rax == 0);
GUEST_SYNC(14); GUEST_SYNC(14);
...@@ -281,37 +265,19 @@ static void guest_code(void) ...@@ -281,37 +265,19 @@ static void guest_code(void)
.timeout = 0, .timeout = 0,
}; };
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
"=a" (rax) :
"a" (__HYPERVISOR_sched_op),
"D" (SCHEDOP_poll),
"S" (&p));
GUEST_ASSERT(rax == 0);
GUEST_SYNC(17); GUEST_SYNC(17);
/* Poll for an unset port and wait for the timeout. */ /* Poll for an unset port and wait for the timeout. */
p.timeout = 100000000; p.timeout = 100000000;
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
"=a" (rax) :
"a" (__HYPERVISOR_sched_op),
"D" (SCHEDOP_poll),
"S" (&p));
GUEST_ASSERT(rax == 0);
GUEST_SYNC(18); GUEST_SYNC(18);
/* A timer will wake the masked port we're waiting on, while we poll */ /* A timer will wake the masked port we're waiting on, while we poll */
p.timeout = 0; p.timeout = 0;
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
"=a" (rax) :
"a" (__HYPERVISOR_sched_op),
"D" (SCHEDOP_poll),
"S" (&p));
GUEST_ASSERT(rax == 0);
GUEST_SYNC(19); GUEST_SYNC(19);
...@@ -319,13 +285,7 @@ static void guest_code(void) ...@@ -319,13 +285,7 @@ static void guest_code(void)
* actual interrupt, while we're polling on a different port. */ * actual interrupt, while we're polling on a different port. */
ports[0]++; ports[0]++;
p.timeout = 0; p.timeout = 0;
__asm__ __volatile__ ("vmcall" : xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
"=a" (rax) :
"a" (__HYPERVISOR_sched_op),
"D" (SCHEDOP_poll),
"S" (&p));
GUEST_ASSERT(rax == 0);
guest_wait_for_irq(); guest_wait_for_irq();
...@@ -360,12 +320,7 @@ static void guest_code(void) ...@@ -360,12 +320,7 @@ static void guest_code(void)
* timer IRQ is dropped due to an invalid event channel. * timer IRQ is dropped due to an invalid event channel.
*/ */
for (i = 0; i < 100 && !guest_saw_irq; i++) for (i = 0; i < 100 && !guest_saw_irq; i++)
asm volatile("vmcall" __xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
: "=a" (rax)
: "a" (__HYPERVISOR_sched_op),
"D" (SCHEDOP_poll),
"S" (&p)
: "memory");
/* /*
* Re-send the timer IRQ if it was (likely) dropped due to the timer * Re-send the timer IRQ if it was (likely) dropped due to the timer
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment