Skip to content

Commit c0c76d9

Browse files
sean-jcbonzini
authored andcommitted
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 <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 4009e0b commit c0c76d9

File tree

3 files changed

+21
-54
lines changed

3 files changed

+21
-54
lines changed

tools/testing/selftests/kvm/include/x86_64/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,8 @@ uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr);
10631063

10641064
uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
10651065
uint64_t a3);
1066+
uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1);
1067+
void xen_hypercall(uint64_t nr, uint64_t a0, void *a1);
10661068

10671069
void __vm_xsave_require_permission(int bit, const char *name);
10681070

tools/testing/selftests/kvm/lib/x86_64/processor.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,16 @@ uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
11611161
return X86_HYPERCALL("a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3));
11621162
}
11631163

1164+
uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1)
1165+
{
1166+
return X86_HYPERCALL("a"(nr), "D"(a0), "S"(a1));
1167+
}
1168+
1169+
void xen_hypercall(uint64_t nr, uint64_t a0, void *a1)
1170+
{
1171+
GUEST_ASSERT(!__xen_hypercall(nr, a0, a1));
1172+
}
1173+
11641174
const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void)
11651175
{
11661176
static struct kvm_cpuid2 *cpuid;

tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,8 @@ static void guest_code(void)
225225

226226
/* Our turn. Deliver event channel (to ourselves) with
227227
* EVTCHNOP_send hypercall. */
228-
unsigned long rax;
229228
struct evtchn_send s = { .port = 127 };
230-
__asm__ __volatile__ ("vmcall" :
231-
"=a" (rax) :
232-
"a" (__HYPERVISOR_event_channel_op),
233-
"D" (EVTCHNOP_send),
234-
"S" (&s));
235-
236-
GUEST_ASSERT(rax == 0);
229+
xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
237230

238231
guest_wait_for_irq();
239232

@@ -242,24 +235,15 @@ static void guest_code(void)
242235
/* Deliver "outbound" event channel to an eventfd which
243236
* happens to be one of our own irqfds. */
244237
s.port = 197;
245-
__asm__ __volatile__ ("vmcall" :
246-
"=a" (rax) :
247-
"a" (__HYPERVISOR_event_channel_op),
248-
"D" (EVTCHNOP_send),
249-
"S" (&s));
250-
251-
GUEST_ASSERT(rax == 0);
238+
xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
252239

253240
guest_wait_for_irq();
254241

255242
GUEST_SYNC(13);
256243

257244
/* Set a timer 100ms in the future. */
258-
__asm__ __volatile__ ("vmcall" :
259-
"=a" (rax) :
260-
"a" (__HYPERVISOR_set_timer_op),
261-
"D" (rs->state_entry_time + 100000000));
262-
GUEST_ASSERT(rax == 0);
245+
xen_hypercall(__HYPERVISOR_set_timer_op,
246+
rs->state_entry_time + 100000000, NULL);
263247

264248
GUEST_SYNC(14);
265249

@@ -281,51 +265,27 @@ static void guest_code(void)
281265
.timeout = 0,
282266
};
283267

284-
__asm__ __volatile__ ("vmcall" :
285-
"=a" (rax) :
286-
"a" (__HYPERVISOR_sched_op),
287-
"D" (SCHEDOP_poll),
288-
"S" (&p));
289-
290-
GUEST_ASSERT(rax == 0);
268+
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
291269

292270
GUEST_SYNC(17);
293271

294272
/* Poll for an unset port and wait for the timeout. */
295273
p.timeout = 100000000;
296-
__asm__ __volatile__ ("vmcall" :
297-
"=a" (rax) :
298-
"a" (__HYPERVISOR_sched_op),
299-
"D" (SCHEDOP_poll),
300-
"S" (&p));
301-
302-
GUEST_ASSERT(rax == 0);
274+
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
303275

304276
GUEST_SYNC(18);
305277

306278
/* A timer will wake the masked port we're waiting on, while we poll */
307279
p.timeout = 0;
308-
__asm__ __volatile__ ("vmcall" :
309-
"=a" (rax) :
310-
"a" (__HYPERVISOR_sched_op),
311-
"D" (SCHEDOP_poll),
312-
"S" (&p));
313-
314-
GUEST_ASSERT(rax == 0);
280+
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
315281

316282
GUEST_SYNC(19);
317283

318284
/* A timer wake an *unmasked* port which should wake us with an
319285
* actual interrupt, while we're polling on a different port. */
320286
ports[0]++;
321287
p.timeout = 0;
322-
__asm__ __volatile__ ("vmcall" :
323-
"=a" (rax) :
324-
"a" (__HYPERVISOR_sched_op),
325-
"D" (SCHEDOP_poll),
326-
"S" (&p));
327-
328-
GUEST_ASSERT(rax == 0);
288+
xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
329289

330290
guest_wait_for_irq();
331291

@@ -360,12 +320,7 @@ static void guest_code(void)
360320
* timer IRQ is dropped due to an invalid event channel.
361321
*/
362322
for (i = 0; i < 100 && !guest_saw_irq; i++)
363-
asm volatile("vmcall"
364-
: "=a" (rax)
365-
: "a" (__HYPERVISOR_sched_op),
366-
"D" (SCHEDOP_poll),
367-
"S" (&p)
368-
: "memory");
323+
__xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
369324

370325
/*
371326
* Re-send the timer IRQ if it was (likely) dropped due to the timer

0 commit comments

Comments
 (0)