hyperv: use x86 generic code to do the hypervisor detection

This is first step to move the generic part of HV code into kernel instead
of module, so that it is possible to use hypercall to implement some other
paravirtualization code in the kernel.

Submitted by:		Howard Su <howard0su@gmail.com>
Reviewed by:		royger, delphij, adrian
Approved by:		adrian (mentor)
Sponsored by:		Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D3072
This commit is contained in:
Sepherosa Ziehau 2016-01-14 02:50:13 +00:00
parent 5de888779e
commit 69a53a7a3a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=293870
4 changed files with 22 additions and 65 deletions

View File

@ -251,7 +251,7 @@ hv_vmbus_connect(void) {
hv_vmbus_protocal_version = version;
if (bootverbose)
printf("VMBUS: Portocal Version: %d.%d\n",
printf("VMBUS: Protocol Version: %d.%d\n",
version >> 16, version & 0xFFFF);
sema_destroy(&msg_info->wait_sema);

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pcpu.h>
#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/md_var.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
@ -55,12 +56,6 @@ __FBSDID("$FreeBSD$");
static u_int hv_get_timecount(struct timecounter *tc);
static inline void do_cpuid_inline(unsigned int op, unsigned int *eax,
unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
__asm__ __volatile__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx),
"=d" (*edx) : "0" (op), "c" (ecx));
}
/**
* Globals
*/
@ -86,27 +81,10 @@ hv_get_timecount(struct timecounter *tc)
int
hv_vmbus_query_hypervisor_presence(void)
{
u_int regs[4];
int hyper_v_detected = 0;
/*
* When Xen is detected and native Xen PV support is enabled,
* ignore Xen's HyperV emulation.
*/
if (vm_guest == VM_GUEST_XEN)
if (vm_guest != VM_GUEST_HV)
return (0);
do_cpuid(1, regs);
if (regs[2] & 0x80000000) { /* if(a hypervisor is detected) */
/* make sure this really is Hyper-V */
/* we look at the CPUID info */
do_cpuid(HV_X64_MSR_GUEST_OS_ID, regs);
hyper_v_detected =
regs[0] >= HV_X64_CPUID_MIN &&
regs[0] <= HV_X64_CPUID_MAX &&
!memcmp("Microsoft Hv", &regs[1], 12);
}
return (hyper_v_detected);
return (hv_high >= HV_X64_CPUID_MIN && hv_high <= HV_X64_CPUID_MAX);
}
/**
@ -115,10 +93,7 @@ hv_vmbus_query_hypervisor_presence(void)
static int
hv_vmbus_get_hypervisor_version(void)
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
u_int regs[4];
unsigned int maxLeaf;
unsigned int op;
@ -127,28 +102,16 @@ hv_vmbus_get_hypervisor_version(void)
* Viridian is present
* Query id and revision.
*/
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
do_cpuid(op, regs);
maxLeaf = eax;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
maxLeaf = regs[0];
op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
do_cpuid(op, regs);
if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_VERSION) {
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
do_cpuid(op, regs);
}
return (maxLeaf);
}

View File

@ -60,13 +60,15 @@ __FBSDID("$FreeBSD$");
#include "hv_vmbus_priv.h"
#define VMBUS_IRQ 0x5
#include <contrib/dev/acpica/include/acpi.h>
#include "acpi_if.h"
static device_t vmbus_devp;
static int vmbus_inited;
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
static char *vmbus_ids[] = { "VMBUS", NULL };
/**
* @brief Software interrupt thread routine to handle channel messages from
* the hypervisor.
@ -350,25 +352,15 @@ hv_vmbus_child_device_unregister(struct hv_device *child_dev)
return(ret);
}
static void
vmbus_identify(driver_t *driver, device_t parent)
{
if (!hv_vmbus_query_hypervisor_presence())
return;
vm_guest = VM_GUEST_HV;
BUS_ADD_CHILD(parent, 0, "vmbus", 0);
}
static int
vmbus_probe(device_t dev) {
if(bootverbose)
device_printf(dev, "VMBUS: probe\n");
if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL ||
device_get_unit(dev) != 0)
return (ENXIO);
device_set_desc(dev, "Vmbus Devices");
return (BUS_PROBE_NOWILDCARD);
return (BUS_PROBE_DEFAULT);
}
#ifdef HYPERV
@ -723,7 +715,6 @@ vmbus_modevent(module_t mod, int what, void *arg)
static device_method_t vmbus_methods[] = {
/** Device interface */
DEVMETHOD(device_identify, vmbus_identify),
DEVMETHOD(device_probe, vmbus_probe),
DEVMETHOD(device_attach, vmbus_attach),
DEVMETHOD(device_detach, vmbus_detach),
@ -745,8 +736,9 @@ static driver_t vmbus_driver = { driver_name, vmbus_methods,0, };
devclass_t vmbus_devclass;
DRIVER_MODULE(vmbus, nexus, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
MODULE_VERSION(vmbus,1);
DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
MODULE_VERSION(vmbus, 1);
/* We want to be started after SMP is initialized */
SYSINIT(vmb_init, SI_SUB_SMP + 1, SI_ORDER_FIRST, vmbus_init, NULL);

View File

@ -1294,6 +1294,8 @@ identify_hypervisor(void)
hv_vendor[12] = '\0';
if (strcmp(hv_vendor, "VMwareVMware") == 0)
vm_guest = VM_GUEST_VMWARE;
else if (strcmp(hv_vendor, "Microsoft Hv") == 0)
vm_guest = VM_GUEST_HV;
}
return;
}