/* $NetBSD: vmtvar.h,v 1.1 2017/05/23 08:48:34 nonaka Exp $ */ /* NetBSD: vmt.c,v 1.15 2016/11/10 03:32:04 ozaki-r Exp */ /* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */ /* * Copyright (c) 2007 David Crawshaw * Copyright (c) 2008 David Gwynne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* A register. */ union vm_reg { struct { uint16_t low; uint16_t high; } part; uint32_t word; #ifdef __amd64__ struct { uint32_t low; uint32_t high; } words; uint64_t quad; #endif } __packed; /* A register frame. */ /* XXX 'volatile' as a workaround because BACKDOOR_OP is likely broken */ struct vm_backdoor { volatile union vm_reg eax; volatile union vm_reg ebx; volatile union vm_reg ecx; volatile union vm_reg edx; volatile union vm_reg esi; volatile union vm_reg edi; volatile union vm_reg ebp; } __packed; /* RPC context. */ struct vm_rpc { uint16_t channel; uint32_t cookie1; uint32_t cookie2; }; #define BACKDOOR_OP_I386(op, frame) \ __asm__ __volatile__ ( \ "pushal;" \ "pushl %%eax;" \ "movl 0x18(%%eax), %%ebp;" \ "movl 0x14(%%eax), %%edi;" \ "movl 0x10(%%eax), %%esi;" \ "movl 0x0c(%%eax), %%edx;" \ "movl 0x08(%%eax), %%ecx;" \ "movl 0x04(%%eax), %%ebx;" \ "movl 0x00(%%eax), %%eax;" \ op \ "xchgl %%eax, 0x00(%%esp);" \ "movl %%ebp, 0x18(%%eax);" \ "movl %%edi, 0x14(%%eax);" \ "movl %%esi, 0x10(%%eax);" \ "movl %%edx, 0x0c(%%eax);" \ "movl %%ecx, 0x08(%%eax);" \ "movl %%ebx, 0x04(%%eax);" \ "popl 0x00(%%eax);" \ "popal;" \ : \ :"a"(frame) \ ) #define BACKDOOR_OP_AMD64(op, frame) \ __asm__ __volatile__ ( \ "pushq %%rbp; \n\t" \ "pushq %%rax; \n\t" \ "movq 0x30(%%rax), %%rbp; \n\t" \ "movq 0x28(%%rax), %%rdi; \n\t" \ "movq 0x20(%%rax), %%rsi; \n\t" \ "movq 0x18(%%rax), %%rdx; \n\t" \ "movq 0x10(%%rax), %%rcx; \n\t" \ "movq 0x08(%%rax), %%rbx; \n\t" \ "movq 0x00(%%rax), %%rax; \n\t" \ op "\n\t" \ "xchgq %%rax, 0x00(%%rsp); \n\t" \ "movq %%rbp, 0x30(%%rax); \n\t" \ "movq %%rdi, 0x28(%%rax); \n\t" \ "movq %%rsi, 0x20(%%rax); \n\t" \ "movq %%rdx, 0x18(%%rax); \n\t" \ "movq %%rcx, 0x10(%%rax); \n\t" \ "movq %%rbx, 0x08(%%rax); \n\t" \ "popq 0x00(%%rax); \n\t" \ "popq %%rbp; \n\t" \ : /* No outputs. */ \ : "a" (frame) \ /* No pushal on amd64 so warn gcc about the clobbered registers. */\ : "rbx", "rcx", "rdx", "rdi", "rsi", "cc", "memory" \ ) #ifdef __i386__ #define BACKDOOR_OP(op, frame) BACKDOOR_OP_I386(op, frame) #else #define BACKDOOR_OP(op, frame) BACKDOOR_OP_AMD64(op, frame) #endif static __inline void vmt_hvcall(uint8_t cmd, u_int regs[6]) { struct vm_backdoor frame; memset(&frame, 0, sizeof(frame)); frame.eax.word = VM_MAGIC; frame.ebx.word = UINT_MAX; frame.ecx.part.low = cmd; frame.edx.part.low = VM_PORT_CMD; BACKDOOR_OP("inl %%dx, %%eax;", &frame); regs[0] = frame.eax.word; regs[1] = frame.ebx.word; regs[2] = frame.ecx.word; regs[3] = frame.edx.word; regs[4] = frame.esi.word; regs[5] = frame.edi.word; }