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;
 
 
        /* 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();
 
        /* 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);
 
                .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);
 
         * 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();
 
         * 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