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 <[email protected]>
+ * Copyright (c) 2008 David Gwynne <[email protected]>
+ *
+ * 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 <[email protected]>
+ * Copyright (c) 2008 David Gwynne <[email protected]>
+ *
+ * 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;
+}