Module Name: src Committed By: nonaka Date: Tue May 23 08:48:35 UTC 2017
Modified Files: src/sys/arch/amd64/amd64: autoconf.c src/sys/arch/i386/i386: autoconf.c src/sys/arch/x86/include: cpu.h src/sys/arch/x86/x86: identcpu.c vmt.c src/sys/arch/xen/conf: files.xen src/sys/arch/xen/x86: autoconf.c Added Files: src/sys/arch/x86/x86: vmtreg.h vmtvar.h Log Message: x86: hypervisor detection from FreeBSD for x2APIC support. To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.26 src/sys/arch/amd64/amd64/autoconf.c cvs rdiff -u -r1.102 -r1.103 src/sys/arch/i386/i386/autoconf.c cvs rdiff -u -r1.70 -r1.71 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.54 -r1.55 src/sys/arch/x86/x86/identcpu.c cvs rdiff -u -r1.15 -r1.16 src/sys/arch/x86/x86/vmt.c cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/x86/vmtreg.h \ src/sys/arch/x86/x86/vmtvar.h cvs rdiff -u -r1.146 -r1.147 src/sys/arch/xen/conf/files.xen cvs rdiff -u -r1.17 -r1.18 src/sys/arch/xen/x86/autoconf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/autoconf.c diff -u src/sys/arch/amd64/amd64/autoconf.c:1.25 src/sys/arch/amd64/amd64/autoconf.c:1.26 --- src/sys/arch/amd64/amd64/autoconf.c:1.25 Sun Nov 22 13:41:24 2015 +++ src/sys/arch/amd64/amd64/autoconf.c Tue May 23 08:48:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.25 2015/11/22 13:41:24 maxv Exp $ */ +/* $NetBSD: autoconf.c,v 1.26 2017/05/23 08:48:34 nonaka Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -46,7 +46,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.25 2015/11/22 13:41:24 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.26 2017/05/23 08:48:34 nonaka Exp $"); #include "opt_multiprocessor.h" #include "opt_intrdebug.h" @@ -91,6 +91,8 @@ cpu_configure(void) #if NBIOS32 > 0 bios32_init(); platform_init(); + /* identify hypervisor type from SMBIOS */ + identify_hypervisor(); #endif x86_64_proc0_tss_ldt_init(); Index: src/sys/arch/i386/i386/autoconf.c diff -u src/sys/arch/i386/i386/autoconf.c:1.102 src/sys/arch/i386/i386/autoconf.c:1.103 --- src/sys/arch/i386/i386/autoconf.c:1.102 Sat Apr 22 04:29:31 2017 +++ src/sys/arch/i386/i386/autoconf.c Tue May 23 08:48:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.102 2017/04/22 04:29:31 nonaka Exp $ */ +/* $NetBSD: autoconf.c,v 1.103 2017/05/23 08:48:34 nonaka Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -46,7 +46,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.102 2017/04/22 04:29:31 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.103 2017/05/23 08:48:34 nonaka Exp $"); #include "opt_compat_oldboot.h" #include "opt_intrdebug.h" @@ -105,6 +105,8 @@ cpu_configure(void) #if NBIOS32 > 0 bios32_init(); platform_init(); + /* identify hypervisor type from SMBIOS */ + identify_hypervisor(); #endif #ifdef PCIBIOS pcibios_init(); Index: src/sys/arch/x86/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.70 src/sys/arch/x86/include/cpu.h:1.71 --- src/sys/arch/x86/include/cpu.h:1.70 Mon May 15 04:02:52 2017 +++ src/sys/arch/x86/include/cpu.h Tue May 23 08:48:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.70 2017/05/15 04:02:52 msaitoh Exp $ */ +/* $NetBSD: cpu.h,v 1.71 2017/05/23 08:48:34 nonaka Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -422,6 +422,18 @@ void tmx86_init_longrun(void); /* identcpu.c */ void cpu_probe(struct cpu_info *); void cpu_identify(struct cpu_info *); +void identify_hypervisor(void); + +typedef enum vm_guest { + VM_GUEST_NO = 0, + VM_GUEST_VM, + VM_GUEST_XEN, + VM_GUEST_HV, + VM_GUEST_VMWARE, + VM_GUEST_KVM, + VM_LAST +} vm_guest_t; +extern vm_guest_t vm_guest; /* cpu_topology.c */ void x86_cpu_topology(struct cpu_info *); Index: src/sys/arch/x86/x86/identcpu.c diff -u src/sys/arch/x86/x86/identcpu.c:1.54 src/sys/arch/x86/x86/identcpu.c:1.55 --- src/sys/arch/x86/x86/identcpu.c:1.54 Wed May 10 08:02:37 2017 +++ src/sys/arch/x86/x86/identcpu.c Tue May 23 08:48:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: identcpu.c,v 1.54 2017/05/10 08:02:37 msaitoh Exp $ */ +/* $NetBSD: identcpu.c,v 1.55 2017/05/23 08:48:34 nonaka Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.54 2017/05/10 08:02:37 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.55 2017/05/23 08:48:34 nonaka Exp $"); #include "opt_xen.h" @@ -50,6 +50,9 @@ __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v #include <x86/cpuvar.h> #include <x86/cpu_msr.h> +#include <x86/x86/vmtreg.h> /* for vmt_hvcall() */ +#include <x86/x86/vmtvar.h> /* for vmt_hvcall() */ + static const struct x86_cache_info intel_cpuid_cache_info[] = INTEL_CACHE_INFO; static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = @@ -912,6 +915,7 @@ cpu_probe(struct cpu_info *ci) for (i = 0; i < __arraycount(cpu_feature); i++) { cpu_feature[i] = ci->ci_feat_val[i]; } + identify_hypervisor(); #ifndef XEN /* Early patch of text segment. */ x86_patch(true); @@ -995,3 +999,96 @@ cpu_identify(struct cpu_info *ci) #endif /* i386 */ } + +/* + * Hypervisor + */ +vm_guest_t vm_guest = VM_GUEST_NO; + +static const char * const vm_bios_vendors[] = { + "QEMU", /* QEMU */ + "Plex86", /* Plex86 */ + "Bochs", /* Bochs */ + "Xen", /* Xen */ + "BHYVE", /* bhyve */ + "Seabios", /* KVM */ +}; + +static const char * const vm_system_products[] = { + "VMware Virtual Platform", /* VMWare VM */ + "Virtual Machine", /* Microsoft VirtualPC */ + "VirtualBox", /* Sun xVM VirtualBox */ + "Parallels Virtual Platform", /* Parallels VM */ + "KVM", /* KVM */ +}; + +void +identify_hypervisor(void) +{ + u_int regs[6]; + char hv_vendor[12]; + const char *p; + int i; + + if (vm_guest != VM_GUEST_NO) + return; + + /* + * [RFC] CPUID usage for interaction between Hypervisors and Linux. + * http://lkml.org/lkml/2008/10/1/246 + * + * KB1009458: Mechanisms to determine if software is running in + * a VMware virtual machine + * http://kb.vmware.com/kb/1009458 + */ + if (ISSET(cpu_feature[1], CPUID2_RAZ)) { + vm_guest = VM_GUEST_VM; + x86_cpuid(0x40000000, regs); + if (regs[0] >= 0x40000000) { + memcpy(&hv_vendor[0], ®s[1], sizeof(*regs)); + memcpy(&hv_vendor[4], ®s[2], sizeof(*regs)); + memcpy(&hv_vendor[8], ®s[3], sizeof(*regs)); + if (memcmp(hv_vendor, "VMwareVMware", 12) == 0) + vm_guest = VM_GUEST_VMWARE; + else if (memcmp(hv_vendor, "Microsoft Hv", 12) == 0) + vm_guest = VM_GUEST_HV; + else if (memcmp(hv_vendor, "KVMKVMKVM\0\0\0", 12) == 0) + vm_guest = VM_GUEST_KVM; + /* FreeBSD bhyve: "bhyve bhyve " */ + /* OpenBSD vmm: "OpenBSDVMM58" */ + } + return; + } + + /* + * Examine SMBIOS strings for older hypervisors. + */ + p = pmf_get_platform("system-serial"); + if (p != NULL) { + if (strncmp(p, "VMware-", 7) == 0 || strncmp(p, "VMW", 3) == 0) { + vmt_hvcall(VM_CMD_GET_VERSION, regs); + if (regs[1] == VM_MAGIC) { + vm_guest = VM_GUEST_VMWARE; + return; + } + } + } + p = pmf_get_platform("bios-vendor"); + if (p != NULL) { + for (i = 0; i < __arraycount(vm_bios_vendors); i++) { + if (strcmp(p, vm_bios_vendors[i]) == 0) { + vm_guest = VM_GUEST_VM; + return; + } + } + } + p = pmf_get_platform("system-product"); + if (p != NULL) { + for (i = 0; i < __arraycount(vm_system_products); i++) { + if (strcmp(p, vm_system_products[i]) == 0) { + vm_guest = VM_GUEST_VM; + return; + } + } + } +} Index: src/sys/arch/x86/x86/vmt.c diff -u src/sys/arch/x86/x86/vmt.c:1.15 src/sys/arch/x86/x86/vmt.c:1.16 --- src/sys/arch/x86/x86/vmt.c:1.15 Thu Nov 10 03:32:04 2016 +++ src/sys/arch/x86/x86/vmt.c Tue May 23 08:48:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vmt.c,v 1.15 2016/11/10 03:32:04 ozaki-r Exp $ */ +/* $NetBSD: vmt.c,v 1.16 2017/05/23 08:48:34 nonaka Exp $ */ /* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */ /* @@ -46,130 +46,10 @@ #include <dev/sysmon/sysmonvar.h> #include <dev/sysmon/sysmon_taskq.h> -/* #define VMT_DEBUG */ - -/* OS name to report to host */ -#ifdef __i386__ -#define VM_OS_NAME "other" -#else -#define VM_OS_NAME "other-64" -#endif - -/* "The" magic number, always occupies the EAX register. */ -#define VM_MAGIC 0x564D5868 - -/* Port numbers, passed on EDX.LOW . */ -#define VM_PORT_CMD 0x5658 -#define VM_PORT_RPC 0x5659 - -/* Commands, passed on ECX.LOW. */ -#define VM_CMD_GET_SPEED 0x01 -#define VM_CMD_APM 0x02 -#define VM_CMD_GET_MOUSEPOS 0x04 -#define VM_CMD_SET_MOUSEPOS 0x05 -#define VM_CMD_GET_CLIPBOARD_LEN 0x06 -#define VM_CMD_GET_CLIPBOARD 0x07 -#define VM_CMD_SET_CLIPBOARD_LEN 0x08 -#define VM_CMD_SET_CLIPBOARD 0x09 -#define VM_CMD_GET_VERSION 0x0a -#define VM_VERSION_UNMANAGED 0x7fffffff -#define VM_CMD_GET_DEVINFO 0x0b -#define VM_CMD_DEV_ADDREMOVE 0x0c -#define VM_CMD_GET_GUI_OPTIONS 0x0d -#define VM_CMD_SET_GUI_OPTIONS 0x0e -#define VM_CMD_GET_SCREEN_SIZE 0x0f -#define VM_CMD_GET_HWVER 0x11 -#define VM_CMD_POPUP_OSNOTFOUND 0x12 -#define VM_CMD_GET_BIOS_UUID 0x13 -#define VM_CMD_GET_MEM_SIZE 0x14 -/*#define VM_CMD_GET_TIME 0x17 */ /* deprecated */ -#define VM_CMD_RPC 0x1e -#define VM_CMD_GET_TIME_FULL 0x2e - -/* RPC sub-commands, passed on ECX.HIGH. */ -#define VM_RPC_OPEN 0x00 -#define VM_RPC_SET_LENGTH 0x01 -#define VM_RPC_SET_DATA 0x02 -#define VM_RPC_GET_LENGTH 0x03 -#define VM_RPC_GET_DATA 0x04 -#define VM_RPC_GET_END 0x05 -#define VM_RPC_CLOSE 0x06 - -/* RPC magic numbers, passed on EBX. */ -#define VM_RPC_OPEN_RPCI 0x49435052UL /* with VM_RPC_OPEN. */ -#define VM_RPC_OPEN_TCLO 0x4F4C4354UL /* with VP_RPC_OPEN. */ -#define VM_RPC_ENH_DATA 0x00010000UL /* with enhanced RPC data calls. */ - -#define VM_RPC_FLAG_COOKIE 0x80000000UL - -/* RPC reply flags */ -#define VM_RPC_REPLY_SUCCESS 0x0001 -#define VM_RPC_REPLY_DORECV 0x0002 /* incoming message available */ -#define VM_RPC_REPLY_CLOSED 0x0004 /* RPC channel is closed */ -#define VM_RPC_REPLY_UNSENT 0x0008 /* incoming message was removed? */ -#define VM_RPC_REPLY_CHECKPOINT 0x0010 /* checkpoint occurred -> retry */ -#define VM_RPC_REPLY_POWEROFF 0x0020 /* underlying device is powering off */ -#define VM_RPC_REPLY_TIMEOUT 0x0040 -#define VM_RPC_REPLY_HB 0x0080 /* high-bandwidth tx/rx available */ - -/* VM state change IDs */ -#define VM_STATE_CHANGE_HALT 1 -#define VM_STATE_CHANGE_REBOOT 2 -#define VM_STATE_CHANGE_POWERON 3 -#define VM_STATE_CHANGE_RESUME 4 -#define VM_STATE_CHANGE_SUSPEND 5 - -/* VM guest info keys */ -#define VM_GUEST_INFO_DNS_NAME 1 -#define VM_GUEST_INFO_IP_ADDRESS 2 -#define VM_GUEST_INFO_DISK_FREE_SPACE 3 -#define VM_GUEST_INFO_BUILD_NUMBER 4 -#define VM_GUEST_INFO_OS_NAME_FULL 5 -#define VM_GUEST_INFO_OS_NAME 6 -#define VM_GUEST_INFO_UPTIME 7 -#define VM_GUEST_INFO_MEMORY 8 -#define VM_GUEST_INFO_IP_ADDRESS_V2 9 - -/* RPC responses */ -#define VM_RPC_REPLY_OK "OK " -#define VM_RPC_RESET_REPLY "OK ATR toolbox" -#define VM_RPC_REPLY_ERROR "ERROR Unknown command" -#define VM_RPC_REPLY_ERROR_IP_ADDR "ERROR Unable to find guest IP address" - -/* 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; +#include <x86/x86/vmtreg.h> +#include <x86/x86/vmtvar.h> -/* 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 VMT_DEBUG */ static int vmt_match(device_t, cfdata_t, void *); static void vmt_attach(device_t, device_t, void *); @@ -861,64 +741,6 @@ out: callout_schedule(&sc->sc_tclo_tick, sc->sc_tclo_ping ? hz : 1); } -#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 void vm_cmd(struct vm_backdoor *frame) { Index: src/sys/arch/xen/conf/files.xen diff -u src/sys/arch/xen/conf/files.xen:1.146 src/sys/arch/xen/conf/files.xen:1.147 --- src/sys/arch/xen/conf/files.xen:1.146 Fri Mar 24 17:09:37 2017 +++ src/sys/arch/xen/conf/files.xen Tue May 23 08:48:35 2017 @@ -1,4 +1,4 @@ -# $NetBSD: files.xen,v 1.146 2017/03/24 17:09:37 maxv Exp $ +# $NetBSD: files.xen,v 1.147 2017/05/23 08:48:35 nonaka Exp $ # NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp # NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp @@ -146,6 +146,7 @@ file arch/x86/x86/tsc.c machdep file arch/x86/x86/vm_machdep.c machdep file arch/x86/x86/x86_machdep.c machdep file arch/x86/x86/cpu_topology.c machdep +file arch/x86/x86/platform.c machdep include "arch/xen/conf/files.compat" Index: src/sys/arch/xen/x86/autoconf.c diff -u src/sys/arch/xen/x86/autoconf.c:1.17 src/sys/arch/xen/x86/autoconf.c:1.18 --- src/sys/arch/xen/x86/autoconf.c:1.17 Thu Apr 3 15:53:05 2014 +++ src/sys/arch/xen/x86/autoconf.c Tue May 23 08:48:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.17 2014/04/03 15:53:05 christos Exp $ */ +/* $NetBSD: autoconf.c,v 1.18 2017/05/23 08:48:35 nonaka Exp $ */ /* NetBSD: autoconf.c,v 1.75 2003/12/30 12:33:22 pk Exp */ /*- @@ -45,7 +45,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.17 2014/04/03 15:53:05 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.18 2017/05/23 08:48:35 nonaka Exp $"); #include "opt_xen.h" #include "opt_compat_oldboot.h" @@ -94,6 +94,8 @@ int x86_ndisks; #include "bios32.h" #if NBIOS32 > 0 #include <machine/bios32.h> +/* XXX */ +extern void platform_init(void); #endif #include "opt_pcibios.h" @@ -113,10 +115,17 @@ cpu_configure(void) startrtclock(); -#if NBIOS32 > 0 && defined(DOM0OPS) - if (xendomain_is_dom0()) +#if defined(DOM0OPS) + if (xendomain_is_dom0()) { +#if NBIOS32 > 0 bios32_init(); -#endif /* NBIOS32 > 0 && DOM0OPS */ + platform_init(); + /* identify hypervisor type from SMBIOS */ + identify_hypervisor(); +#endif /* NBIOS32 > 0 */ + } else +#endif /* DOM0OPS */ + vm_guest = VM_GUEST_XEN; #ifdef PCIBIOS pcibios_init(); #endif Added files: Index: src/sys/arch/x86/x86/vmtreg.h diff -u /dev/null src/sys/arch/x86/x86/vmtreg.h:1.1 --- /dev/null Tue May 23 08:48:35 2017 +++ src/sys/arch/x86/x86/vmtreg.h Tue May 23 08:48:34 2017 @@ -0,0 +1,117 @@ +/* $NetBSD: vmtreg.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 <da...@zentus.com> + * Copyright (c) 2008 David Gwynne <d...@openbsd.org> + * + * 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. + */ + +/* + * Protocol reverse engineered by Ken Kato: + * http://chitchat.at.infoseek.co.jp/vmware/backdoor.html + */ + +/* OS name to report to host */ +#ifdef __i386__ +#define VM_OS_NAME "other" +#else +#define VM_OS_NAME "other-64" +#endif + +/* "The" magic number, always occupies the EAX register. */ +#define VM_MAGIC 0x564D5868 + +/* Port numbers, passed on EDX.LOW . */ +#define VM_PORT_CMD 0x5658 +#define VM_PORT_RPC 0x5659 + +/* Commands, passed on ECX.LOW. */ +#define VM_CMD_GET_SPEED 0x01 +#define VM_CMD_APM 0x02 +#define VM_CMD_GET_MOUSEPOS 0x04 +#define VM_CMD_SET_MOUSEPOS 0x05 +#define VM_CMD_GET_CLIPBOARD_LEN 0x06 +#define VM_CMD_GET_CLIPBOARD 0x07 +#define VM_CMD_SET_CLIPBOARD_LEN 0x08 +#define VM_CMD_SET_CLIPBOARD 0x09 +#define VM_CMD_GET_VERSION 0x0a +#define VM_VERSION_UNMANAGED 0x7fffffff +#define VM_CMD_GET_DEVINFO 0x0b +#define VM_CMD_DEV_ADDREMOVE 0x0c +#define VM_CMD_GET_GUI_OPTIONS 0x0d +#define VM_CMD_SET_GUI_OPTIONS 0x0e +#define VM_CMD_GET_SCREEN_SIZE 0x0f +#define VM_CMD_GET_HWVER 0x11 +#define VM_CMD_POPUP_OSNOTFOUND 0x12 +#define VM_CMD_GET_BIOS_UUID 0x13 +#define VM_CMD_GET_MEM_SIZE 0x14 +/*#define VM_CMD_GET_TIME 0x17 */ /* deprecated */ +#define VM_CMD_RPC 0x1e +#define VM_CMD_GET_HZ 0x2d +#define VM_CMD_GET_TIME_FULL 0x2e +#define VM_CMD_GET_VCPU_INFO 0x44 +#define VCPUINFO_LEGACY_X2APIC __BIT(3) +#define VCPUINFO_VCPU_RESERVED __BIT(31) + +/* RPC sub-commands, passed on ECX.HIGH. */ +#define VM_RPC_OPEN 0x00 +#define VM_RPC_SET_LENGTH 0x01 +#define VM_RPC_SET_DATA 0x02 +#define VM_RPC_GET_LENGTH 0x03 +#define VM_RPC_GET_DATA 0x04 +#define VM_RPC_GET_END 0x05 +#define VM_RPC_CLOSE 0x06 + +/* RPC magic numbers, passed on EBX. */ +#define VM_RPC_OPEN_RPCI 0x49435052UL /* with VM_RPC_OPEN. */ +#define VM_RPC_OPEN_TCLO 0x4F4C4354UL /* with VP_RPC_OPEN. */ +#define VM_RPC_ENH_DATA 0x00010000UL /* with enhanced RPC data calls. */ + +#define VM_RPC_FLAG_COOKIE 0x80000000UL + +/* RPC reply flags */ +#define VM_RPC_REPLY_SUCCESS 0x0001 +#define VM_RPC_REPLY_DORECV 0x0002 /* incoming message available */ +#define VM_RPC_REPLY_CLOSED 0x0004 /* RPC channel is closed */ +#define VM_RPC_REPLY_UNSENT 0x0008 /* incoming message was removed? */ +#define VM_RPC_REPLY_CHECKPOINT 0x0010 /* checkpoint occurred -> retry */ +#define VM_RPC_REPLY_POWEROFF 0x0020 /* underlying device is powering off */ +#define VM_RPC_REPLY_TIMEOUT 0x0040 +#define VM_RPC_REPLY_HB 0x0080 /* high-bandwidth tx/rx available */ + +/* VM state change IDs */ +#define VM_STATE_CHANGE_HALT 1 +#define VM_STATE_CHANGE_REBOOT 2 +#define VM_STATE_CHANGE_POWERON 3 +#define VM_STATE_CHANGE_RESUME 4 +#define VM_STATE_CHANGE_SUSPEND 5 + +/* VM guest info keys */ +#define VM_GUEST_INFO_DNS_NAME 1 +#define VM_GUEST_INFO_IP_ADDRESS 2 +#define VM_GUEST_INFO_DISK_FREE_SPACE 3 +#define VM_GUEST_INFO_BUILD_NUMBER 4 +#define VM_GUEST_INFO_OS_NAME_FULL 5 +#define VM_GUEST_INFO_OS_NAME 6 +#define VM_GUEST_INFO_UPTIME 7 +#define VM_GUEST_INFO_MEMORY 8 +#define VM_GUEST_INFO_IP_ADDRESS_V2 9 + +/* RPC responses */ +#define VM_RPC_REPLY_OK "OK " +#define VM_RPC_RESET_REPLY "OK ATR toolbox" +#define VM_RPC_REPLY_ERROR "ERROR Unknown command" +#define VM_RPC_REPLY_ERROR_IP_ADDR "ERROR Unable to find guest IP address" Index: src/sys/arch/x86/x86/vmtvar.h diff -u /dev/null src/sys/arch/x86/x86/vmtvar.h:1.1 --- /dev/null Tue May 23 08:48:35 2017 +++ src/sys/arch/x86/x86/vmtvar.h Tue May 23 08:48:34 2017 @@ -0,0 +1,134 @@ +/* $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 <da...@zentus.com> + * Copyright (c) 2008 David Gwynne <d...@openbsd.org> + * + * 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; +}