DF-5123 / hypercall_md.c
#include <stdint.h> /* EXACT copy of sys/dev/virtual/hyperv/x86_64/hyperv_machdep.c:74-84 */ uint64_t hypercall_md(volatile void *hc_addr, uint64_t in_val, uint64_t in_paddr, uint64_t out_paddr) { uint64_t status; __asm__ __volatile__ ("mov %0, %%r8" : : "r" (out_paddr): "r8"); __asm__ __volatile__ ("call *%3" : "=a" (status) : "c" (in_val), "d" (in_paddr), "m" (hc_addr)); return (status); } /* Variant B: same two-asm pattern, forced inline into a caller with live * memory the compiler may move across the (memoryless-clobber) asm. */ static inline __attribute__((always_inline)) uint64_t hc_inline(volatile void *hc_addr, uint64_t in_val, uint64_t in_paddr, uint64_t out_paddr) { uint64_t status; __asm__ __volatile__ ("mov %0, %%r8" : : "r" (out_paddr): "r8"); __asm__ __volatile__ ("call *%3" : "=a" (status) : "c" (in_val), "d" (in_paddr), "m" (hc_addr)); return (status); } volatile uint64_t g_out; extern unsigned char msgpage[4096]; uint64_t caller(uint64_t control, uint64_t in_pa, uint64_t out_pa) { ((volatile uint64_t *)msgpage)[0] = control; /* must be visible to hypercall */ uint64_t r = hc_inline(msgpage, control, in_pa, out_pa); ((volatile uint64_t *)msgpage)[1] = r; /* written after hypercall reads/writes */ return r + g_out; } |