From owner-svn-src-projects@FreeBSD.ORG Sun Dec 21 23:22:14 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 46511BC7; Sun, 21 Dec 2014 23:22:14 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 31A442E0F; Sun, 21 Dec 2014 23:22:14 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sBLNMEUF035469; Sun, 21 Dec 2014 23:22:14 GMT (envelope-from bryanv@FreeBSD.org) Received: (from bryanv@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sBLNMCvC035449; Sun, 21 Dec 2014 23:22:12 GMT (envelope-from bryanv@FreeBSD.org) Message-Id: <201412212322.sBLNMCvC035449@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: bryanv set sender to bryanv@FreeBSD.org using -f From: Bryan Venteicher Date: Sun, 21 Dec 2014 23:22:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r276040 - in projects/paravirt/sys: conf x86/include x86/x86 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Dec 2014 23:22:14 -0000 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 + * 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 + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +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, ®s[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 #include +#include #include #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); -}