Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch x86: hypervisor detection from FreeBSD for x2APIC s...



details:   https://anonhg.NetBSD.org/src/rev/6ff390575b73
branches:  trunk
changeset: 824097:6ff390575b73
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Tue May 23 08:48:34 2017 +0000

description:
x86: hypervisor detection from FreeBSD for x2APIC support.

diffstat:

 sys/arch/amd64/amd64/autoconf.c |    6 +-
 sys/arch/i386/i386/autoconf.c   |    6 +-
 sys/arch/x86/include/cpu.h      |   14 ++-
 sys/arch/x86/x86/identcpu.c     |  101 +++++++++++++++++++++-
 sys/arch/x86/x86/vmt.c          |  186 +---------------------------------------
 sys/arch/x86/x86/vmtreg.h       |  117 +++++++++++++++++++++++++
 sys/arch/x86/x86/vmtvar.h       |  134 ++++++++++++++++++++++++++++
 sys/arch/xen/conf/files.xen     |    3 +-
 sys/arch/xen/x86/autoconf.c     |   19 +++-
 9 files changed, 391 insertions(+), 195 deletions(-)

diffs (truncated from 747 to 300 lines):

diff -r 8e5d5cb0a5cf -r 6ff390575b73 sys/arch/amd64/amd64/autoconf.c
--- a/sys/arch/amd64/amd64/autoconf.c   Tue May 23 07:57:26 2017 +0000
+++ b/sys/arch/amd64/amd64/autoconf.c   Tue May 23 08:48:34 2017 +0000
@@ -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 @@
 #if NBIOS32 > 0
        bios32_init();
        platform_init();
+       /* identify hypervisor type from SMBIOS */
+       identify_hypervisor();
 #endif
 
        x86_64_proc0_tss_ldt_init();
diff -r 8e5d5cb0a5cf -r 6ff390575b73 sys/arch/i386/i386/autoconf.c
--- a/sys/arch/i386/i386/autoconf.c     Tue May 23 07:57:26 2017 +0000
+++ b/sys/arch/i386/i386/autoconf.c     Tue May 23 08:48:34 2017 +0000
@@ -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 @@
 #if NBIOS32 > 0
        bios32_init();
        platform_init();
+       /* identify hypervisor type from SMBIOS */
+       identify_hypervisor();
 #endif
 #ifdef PCIBIOS
        pcibios_init();
diff -r 8e5d5cb0a5cf -r 6ff390575b73 sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h        Tue May 23 07:57:26 2017 +0000
+++ b/sys/arch/x86/include/cpu.h        Tue May 23 08:48:34 2017 +0000
@@ -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 @@
 /* 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 *);
diff -r 8e5d5cb0a5cf -r 6ff390575b73 sys/arch/x86/x86/identcpu.c
--- a/sys/arch/x86/x86/identcpu.c       Tue May 23 07:57:26 2017 +0000
+++ b/sys/arch/x86/x86/identcpu.c       Tue May 23 08:48:34 2017 +0000
@@ -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 @@
 #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 @@
                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 @@
 #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], &regs[1], sizeof(*regs));
+                       memcpy(&hv_vendor[4], &regs[2], sizeof(*regs));
+                       memcpy(&hv_vendor[8], &regs[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;
+                       }
+               }
+       }
+}
diff -r 8e5d5cb0a5cf -r 6ff390575b73 sys/arch/x86/x86/vmt.c
--- a/sys/arch/x86/x86/vmt.c    Tue May 23 07:57:26 2017 +0000
+++ b/sys/arch/x86/x86/vmt.c    Tue May 23 08:48:34 2017 +0000
@@ -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
+#include <x86/x86/vmtreg.h>
+#include <x86/x86/vmtvar.h>
 
-/* 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



Home | Main Index | Thread Index | Old Index