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);
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);
......
......@@ -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;
......
......@@ -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 @@ static void guest_code(void)
* 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
......
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