⬢ DragonFlyBSD Kernel Audit
DF-5123 / hypercall_md.c
← back to finding ↓ download raw
#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;
}