Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Dec 2014 23:22:12 +0000 (UTC)
From:      Bryan Venteicher <bryanv@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r276040 - in projects/paravirt/sys: conf x86/include x86/x86
Message-ID:  <201412212322.sBLNMCvC035449@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bryanv
Date: Sun Dec 21 23:22:11 2014
New Revision: 276040
URL: https://svnweb.freebsd.org/changeset/base/276040

Log:
  Add a simple and rough hypervisor interface
  
  Pull out the existing CPUID based hypervisor detection into a formal
  interface so that we can later use it to detect multiple hypervisors.
  
  Similar duplicate code exists in XEN and HYPERV, and should eventually
  be consolidated.
  
  This commit breaks the existing VMware detection which will be fixed
  in a subsequent commit.

Added:
  projects/paravirt/sys/x86/include/hypervisor.h   (contents, props changed)
  projects/paravirt/sys/x86/x86/hypervisor.c   (contents, props changed)
Modified:
  projects/paravirt/sys/conf/files.amd64
  projects/paravirt/sys/conf/files.i386
  projects/paravirt/sys/x86/x86/identcpu.c

Modified: projects/paravirt/sys/conf/files.amd64
==============================================================================
--- projects/paravirt/sys/conf/files.amd64	Sun Dec 21 23:20:02 2014	(r276039)
+++ projects/paravirt/sys/conf/files.amd64	Sun Dec 21 23:22:11 2014	(r276040)
@@ -559,6 +559,7 @@ x86/x86/busdma_bounce.c		standard
 x86/x86/busdma_machdep.c	standard
 x86/x86/dump_machdep.c		standard
 x86/x86/fdt_machdep.c		optional	fdt
+x86/x86/hypervisor.c		standard
 x86/x86/identcpu.c		standard
 x86/x86/intr_machdep.c		standard
 x86/x86/io_apic.c		standard

Modified: projects/paravirt/sys/conf/files.i386
==============================================================================
--- projects/paravirt/sys/conf/files.i386	Sun Dec 21 23:20:02 2014	(r276039)
+++ projects/paravirt/sys/conf/files.i386	Sun Dec 21 23:22:11 2014	(r276040)
@@ -577,6 +577,7 @@ x86/x86/busdma_bounce.c		standard
 x86/x86/busdma_machdep.c	standard
 x86/x86/dump_machdep.c		standard
 x86/x86/fdt_machdep.c		optional fdt
+x86/x86/hypervisor.c		standard
 x86/x86/identcpu.c		standard
 x86/x86/intr_machdep.c		standard
 x86/x86/io_apic.c		optional apic

Added: projects/paravirt/sys/x86/include/hypervisor.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/paravirt/sys/x86/include/hypervisor.h	Sun Dec 21 23:22:11 2014	(r276040)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2014 Bryan Venteicher <bryanv@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _X86_HYPERVISOR_H_
+#define _X86_HYPERVISOR_H_
+
+typedef int hypervisor_info_identify_t(void);
+
+struct hypervisor_info {
+	const char			*hvi_name;
+	enum VM_GUEST			 hvi_type;
+	hypervisor_info_identify_t	*hvi_identify;
+};
+
+void	hypervisor_cpuid_identify(void);
+int	hypervisor_cpuid_base(const char *signature, int leaves,
+	    uint32_t *base, uint32_t *high);
+void	hypervisor_print_info(void);
+
+#endif /* !_X86_HYPERVISOR_H_ */
+

Added: projects/paravirt/sys/x86/x86/hypervisor.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/paravirt/sys/x86/x86/hypervisor.c	Sun Dec 21 23:22:11 2014	(r276040)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014 Bryan Venteicher <bryanv@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/limits.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <machine/cpufunc.h>
+#include <machine/cpu.h>
+
+#include <x86/hypervisor.h>
+#include <x86/kvm.h>
+#include <x86/vmware.h>
+
+char hv_vendor[16];
+SYSCTL_STRING(_hw, OID_AUTO, hv_vendor, CTLFLAG_RD, hv_vendor, 0,
+    "Hypervisor vendor");
+
+static const struct hypervisor_info *hypervisor_infos[] = {
+};
+
+static const struct hypervisor_info *hv_info;
+
+/*
+ * [RFC] CPUID usage for interaction between Hypervisors and Linux.
+ * http://lkml.org/lkml/2008/10/1/246
+ */
+int
+hypervisor_cpuid_base(const char *signature, int leaves, uint32_t *base,
+    uint32_t *high)
+{
+	uint32_t leaf, regs[4];
+
+	for (leaf = 0x40000000; leaf < 0x40010000; leaf += 0x100) {
+		do_cpuid(leaf, regs);
+		if (!memcmp(signature, &regs[1], 12) &&
+		    (leaves == 0 || (regs[0] - leaf >= leaves))) {
+			*base = leaf;
+			*high = regs[0];
+			return (0);
+		}
+	}
+
+	return (1);
+}
+
+void
+hypervisor_cpuid_identify(void)
+{
+	const struct hypervisor_info *hvi;
+	int i;
+
+	for (i = 0; i < nitems(hypervisor_infos); i++) {
+		hvi = hypervisor_infos[i];
+
+		if (hvi->hvi_identify() != 0) {
+			hv_info = hvi;
+			vm_guest = hvi->hvi_type;
+			strncpy(hv_vendor, hvi->hvi_name, sizeof(hv_vendor));
+			return;
+		}
+	}
+
+	vm_guest = VM_GUEST_VM;
+}
+
+void
+hypervisor_print_info(void)
+{
+
+	if (*hv_vendor)
+		printf("Hypervisor: Origin = \"%s\"\n", hv_vendor);
+}

Modified: projects/paravirt/sys/x86/x86/identcpu.c
==============================================================================
--- projects/paravirt/sys/x86/x86/identcpu.c	Sun Dec 21 23:20:02 2014	(r276039)
+++ projects/paravirt/sys/x86/x86/identcpu.c	Sun Dec 21 23:22:11 2014	(r276040)
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
 
 #include <amd64/vmm/intel/vmx_controls.h>
 #include <x86/isa/icu.h>
+#include <x86/hypervisor.h>
 #include <x86/vmware.h>
 
 #ifdef __i386__
@@ -78,7 +79,6 @@ static u_int find_cpu_vendor_id(void);
 static void print_AMD_info(void);
 static void print_INTEL_info(void);
 static void print_INTEL_TLB(u_int data);
-static void print_hypervisor_info(void);
 static void print_svm_info(void);
 static void print_via_padlock_info(void);
 static void print_vmx_info(void);
@@ -123,11 +123,6 @@ static int hw_clockrate;
 SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD,
     &hw_clockrate, 0, "CPU instruction clock rate");
 
-u_int hv_high;
-char hv_vendor[16];
-SYSCTL_STRING(_hw, OID_AUTO, hv_vendor, CTLFLAG_RD, hv_vendor, 0,
-    "Hypervisor vendor");
-
 static eventhandler_tag tsc_post_tag;
 
 static char cpu_brand[48];
@@ -985,7 +980,7 @@ printcpuinfo(void)
 #endif
 	}
 
-	print_hypervisor_info();
+	hypervisor_print_info();
 }
 
 void
@@ -1218,25 +1213,11 @@ identify_hypervisor(void)
 	int i;
 
 	/*
-	 * [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
+	 * Modern hypervisors set the HV present feature bit, and are then
+	 * identifiable through a special CPUID leaf.
 	 */
 	if (cpu_feature2 & CPUID2_HV) {
-		vm_guest = VM_GUEST_VM;
-		do_cpuid(0x40000000, regs);
-		if (regs[0] >= 0x40000000) {
-			hv_high = regs[0];
-			((u_int *)&hv_vendor)[0] = regs[1];
-			((u_int *)&hv_vendor)[1] = regs[2];
-			((u_int *)&hv_vendor)[2] = regs[3];
-			hv_vendor[12] = '\0';
-			if (strcmp(hv_vendor, "VMwareVMware") == 0)
-				vm_guest = VM_GUEST_VMWARE;
-		}
+		hypervisor_cpuid_identify();
 		return;
 	}
 
@@ -2150,11 +2131,3 @@ print_vmx_info(void)
 		);
 	}
 }
-
-static void
-print_hypervisor_info(void)
-{
-
-	if (*hv_vendor)
-		printf("Hypervisor: Origin = \"%s\"\n", hv_vendor);
-}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412212322.sBLNMCvC035449>