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:
parent
5de888779e
commit
69a53a7a3a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=293870
@ -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);
|
||||
|
@ -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", ®s[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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user