182b77854SSepherosa Ziehau /*- 282b77854SSepherosa Ziehau * Copyright (c) 2009-2012,2016 Microsoft Corp. 382b77854SSepherosa Ziehau * Copyright (c) 2012 NetApp Inc. 482b77854SSepherosa Ziehau * Copyright (c) 2012 Citrix Inc. 582b77854SSepherosa Ziehau * All rights reserved. 682b77854SSepherosa Ziehau * 782b77854SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 882b77854SSepherosa Ziehau * modification, are permitted provided that the following conditions 982b77854SSepherosa Ziehau * are met: 1082b77854SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 1182b77854SSepherosa Ziehau * notice unmodified, this list of conditions, and the following 1282b77854SSepherosa Ziehau * disclaimer. 1382b77854SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 1482b77854SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 1582b77854SSepherosa Ziehau * documentation and/or other materials provided with the distribution. 1682b77854SSepherosa Ziehau * 1782b77854SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1882b77854SSepherosa Ziehau * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1982b77854SSepherosa Ziehau * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2082b77854SSepherosa Ziehau * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2182b77854SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2282b77854SSepherosa Ziehau * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2382b77854SSepherosa Ziehau * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2482b77854SSepherosa Ziehau * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2582b77854SSepherosa Ziehau * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2682b77854SSepherosa Ziehau * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2782b77854SSepherosa Ziehau */ 2882b77854SSepherosa Ziehau 2982b77854SSepherosa Ziehau #include <sys/param.h> 3082b77854SSepherosa Ziehau #include <sys/kernel.h> 3182b77854SSepherosa Ziehau #include <sys/systimer.h> 3282b77854SSepherosa Ziehau #include <sys/systm.h> 3382b77854SSepherosa Ziehau 3482b77854SSepherosa Ziehau #include <machine/cpufunc.h> 3582b77854SSepherosa Ziehau 3682b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_busdma.h> 3782b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_machdep.h> 3882b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_reg.h> 3982b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_var.h> 4082b77854SSepherosa Ziehau 4182b77854SSepherosa Ziehau #define HYPERV_DRAGONFLY_BUILD 0ULL 4282b77854SSepherosa Ziehau #define HYPERV_DRAGONFLY_VERSION ((uint64_t)__DragonFly_version) 4382b77854SSepherosa Ziehau #define HYPERV_DRAGONFLY_OSID 0ULL 4482b77854SSepherosa Ziehau 4582b77854SSepherosa Ziehau #define MSR_HV_GUESTID_BUILD_DRAGONFLY \ 4682b77854SSepherosa Ziehau (HYPERV_DRAGONFLY_BUILD & MSR_HV_GUESTID_BUILD_MASK) 4782b77854SSepherosa Ziehau #define MSR_HV_GUESTID_VERSION_DRAGONFLY \ 4882b77854SSepherosa Ziehau ((HYPERV_DRAGONFLY_VERSION << MSR_HV_GUESTID_VERSION_SHIFT) & \ 4982b77854SSepherosa Ziehau MSR_HV_GUESTID_VERSION_MASK) 5082b77854SSepherosa Ziehau #define MSR_HV_GUESTID_OSID_DRAGONFLY \ 5182b77854SSepherosa Ziehau ((HYPERV_DRAGONFLY_OSID << MSR_HV_GUESTID_OSID_SHIFT) & \ 5282b77854SSepherosa Ziehau MSR_HV_GUESTID_OSID_MASK) 5382b77854SSepherosa Ziehau 5482b77854SSepherosa Ziehau #define MSR_HV_GUESTID_DRAGONFLY \ 5582b77854SSepherosa Ziehau (MSR_HV_GUESTID_BUILD_DRAGONFLY | \ 5682b77854SSepherosa Ziehau MSR_HV_GUESTID_VERSION_DRAGONFLY | \ 5782b77854SSepherosa Ziehau MSR_HV_GUESTID_OSID_DRAGONFLY | \ 5882b77854SSepherosa Ziehau MSR_HV_GUESTID_OSTYPE_FREEBSD) 5982b77854SSepherosa Ziehau 6082b77854SSepherosa Ziehau struct hypercall_ctx { 6182b77854SSepherosa Ziehau void *hc_addr; 6282b77854SSepherosa Ziehau struct hyperv_dma hc_dma; 6382b77854SSepherosa Ziehau }; 6482b77854SSepherosa Ziehau 6582b77854SSepherosa Ziehau static void hyperv_cputimer_construct(struct cputimer *, 6682b77854SSepherosa Ziehau sysclock_t); 6782b77854SSepherosa Ziehau static sysclock_t hyperv_cputimer_count(void); 6882b77854SSepherosa Ziehau static boolean_t hyperv_identify(void); 6982b77854SSepherosa Ziehau static int hypercall_create(void); 7082b77854SSepherosa Ziehau static void hypercall_destroy(void); 7182b77854SSepherosa Ziehau static void hypercall_memfree(void); 7282b77854SSepherosa Ziehau static uint64_t hyperv_tc64_rdmsr(void); 7382b77854SSepherosa Ziehau 7482b77854SSepherosa Ziehau u_int hyperv_features; 7582b77854SSepherosa Ziehau static u_int hyperv_recommends; 7682b77854SSepherosa Ziehau 7782b77854SSepherosa Ziehau static u_int hyperv_pm_features; 7882b77854SSepherosa Ziehau static u_int hyperv_features3; 7982b77854SSepherosa Ziehau 8082b77854SSepherosa Ziehau hyperv_tc64_t hyperv_tc64; 8182b77854SSepherosa Ziehau 8282b77854SSepherosa Ziehau static struct cputimer hyperv_cputimer = { 8382b77854SSepherosa Ziehau .next = SLIST_ENTRY_INITIALIZER, 8482b77854SSepherosa Ziehau .name = "Hyper-V", 8582b77854SSepherosa Ziehau .pri = CPUTIMER_PRI_VMM, 8682b77854SSepherosa Ziehau .type = CPUTIMER_VMM, 8782b77854SSepherosa Ziehau .count = hyperv_cputimer_count, 8882b77854SSepherosa Ziehau .fromhz = cputimer_default_fromhz, 8982b77854SSepherosa Ziehau .fromus = cputimer_default_fromus, 9082b77854SSepherosa Ziehau .construct = hyperv_cputimer_construct, 9182b77854SSepherosa Ziehau .destruct = cputimer_default_destruct, 9282b77854SSepherosa Ziehau .freq = HYPERV_TIMER_FREQ 9382b77854SSepherosa Ziehau }; 9482b77854SSepherosa Ziehau 95*31517ca9SSepherosa Ziehau static struct cpucounter hyperv_cpucounter = { 96*31517ca9SSepherosa Ziehau .freq = HYPERV_TIMER_FREQ, 97*31517ca9SSepherosa Ziehau .count = hyperv_tc64_rdmsr, 98*31517ca9SSepherosa Ziehau .flags = CPUCOUNTER_FLAG_MPSYNC, 99*31517ca9SSepherosa Ziehau .prio = CPUCOUNTER_PRIO_VMM, 100*31517ca9SSepherosa Ziehau .type = CPUCOUNTER_VMM 101*31517ca9SSepherosa Ziehau }; 102*31517ca9SSepherosa Ziehau 10382b77854SSepherosa Ziehau static struct hypercall_ctx hypercall_context; 10482b77854SSepherosa Ziehau 10582b77854SSepherosa Ziehau uint64_t 10682b77854SSepherosa Ziehau hypercall_post_message(bus_addr_t msg_paddr) 10782b77854SSepherosa Ziehau { 10882b77854SSepherosa Ziehau return hypercall_md(hypercall_context.hc_addr, 10982b77854SSepherosa Ziehau HYPERCALL_POST_MESSAGE, msg_paddr, 0); 11082b77854SSepherosa Ziehau } 11182b77854SSepherosa Ziehau 11282b77854SSepherosa Ziehau static void 11382b77854SSepherosa Ziehau hyperv_cputimer_construct(struct cputimer *timer, sysclock_t oldclock) 11482b77854SSepherosa Ziehau { 11582b77854SSepherosa Ziehau timer->base = 0; 11682b77854SSepherosa Ziehau timer->base = oldclock - timer->count(); 11782b77854SSepherosa Ziehau } 11882b77854SSepherosa Ziehau 11982b77854SSepherosa Ziehau static sysclock_t 12082b77854SSepherosa Ziehau hyperv_cputimer_count(void) 12182b77854SSepherosa Ziehau { 12282b77854SSepherosa Ziehau uint64_t val; 12382b77854SSepherosa Ziehau 12482b77854SSepherosa Ziehau val = rdmsr(MSR_HV_TIME_REF_COUNT); 12582b77854SSepherosa Ziehau return (val + hyperv_cputimer.base); 12682b77854SSepherosa Ziehau } 12782b77854SSepherosa Ziehau 12882b77854SSepherosa Ziehau static void 12982b77854SSepherosa Ziehau hypercall_memfree(void) 13082b77854SSepherosa Ziehau { 13182b77854SSepherosa Ziehau hyperv_dmamem_free(&hypercall_context.hc_dma, 13282b77854SSepherosa Ziehau hypercall_context.hc_addr); 13382b77854SSepherosa Ziehau hypercall_context.hc_addr = NULL; 13482b77854SSepherosa Ziehau } 13582b77854SSepherosa Ziehau 13682b77854SSepherosa Ziehau static int 13782b77854SSepherosa Ziehau hypercall_create(void) 13882b77854SSepherosa Ziehau { 13982b77854SSepherosa Ziehau uint64_t hc, hc_orig; 14082b77854SSepherosa Ziehau 14182b77854SSepherosa Ziehau hypercall_context.hc_addr = hyperv_dmamem_alloc(NULL, PAGE_SIZE, 0, 14282b77854SSepherosa Ziehau PAGE_SIZE, &hypercall_context.hc_dma, BUS_DMA_WAITOK); 14382b77854SSepherosa Ziehau if (hypercall_context.hc_addr == NULL) { 14482b77854SSepherosa Ziehau kprintf("hyperv: Hypercall page allocation failed\n"); 14582b77854SSepherosa Ziehau return ENOMEM; 14682b77854SSepherosa Ziehau } 14782b77854SSepherosa Ziehau 14882b77854SSepherosa Ziehau /* Get the 'reserved' bits, which requires preservation. */ 14982b77854SSepherosa Ziehau hc_orig = rdmsr(MSR_HV_HYPERCALL); 15082b77854SSepherosa Ziehau 15182b77854SSepherosa Ziehau /* 15282b77854SSepherosa Ziehau * Setup the Hypercall page. 15382b77854SSepherosa Ziehau * 15482b77854SSepherosa Ziehau * NOTE: 'reserved' bits MUST be preserved. 15582b77854SSepherosa Ziehau */ 15682b77854SSepherosa Ziehau hc = ((hypercall_context.hc_dma.hv_paddr >> PAGE_SHIFT) << 15782b77854SSepherosa Ziehau MSR_HV_HYPERCALL_PGSHIFT) | 15882b77854SSepherosa Ziehau (hc_orig & MSR_HV_HYPERCALL_RSVD_MASK) | 15982b77854SSepherosa Ziehau MSR_HV_HYPERCALL_ENABLE; 16082b77854SSepherosa Ziehau wrmsr(MSR_HV_HYPERCALL, hc); 16182b77854SSepherosa Ziehau 16282b77854SSepherosa Ziehau /* 16382b77854SSepherosa Ziehau * Confirm that Hypercall page did get setup. 16482b77854SSepherosa Ziehau */ 16582b77854SSepherosa Ziehau hc = rdmsr(MSR_HV_HYPERCALL); 16682b77854SSepherosa Ziehau if ((hc & MSR_HV_HYPERCALL_ENABLE) == 0) { 16782b77854SSepherosa Ziehau kprintf("hyperv: Hypercall setup failed\n"); 16882b77854SSepherosa Ziehau hypercall_memfree(); 16982b77854SSepherosa Ziehau return EIO; 17082b77854SSepherosa Ziehau } 17182b77854SSepherosa Ziehau if (bootverbose) 17282b77854SSepherosa Ziehau kprintf("hyperv: Hypercall created\n"); 17382b77854SSepherosa Ziehau 17482b77854SSepherosa Ziehau return 0; 17582b77854SSepherosa Ziehau } 17682b77854SSepherosa Ziehau 17782b77854SSepherosa Ziehau static void 17882b77854SSepherosa Ziehau hypercall_destroy(void) 17982b77854SSepherosa Ziehau { 18082b77854SSepherosa Ziehau uint64_t hc; 18182b77854SSepherosa Ziehau 18282b77854SSepherosa Ziehau if (hypercall_context.hc_addr == NULL) 18382b77854SSepherosa Ziehau return; 18482b77854SSepherosa Ziehau 18582b77854SSepherosa Ziehau /* Disable Hypercall */ 18682b77854SSepherosa Ziehau hc = rdmsr(MSR_HV_HYPERCALL); 18782b77854SSepherosa Ziehau wrmsr(MSR_HV_HYPERCALL, (hc & MSR_HV_HYPERCALL_RSVD_MASK)); 18882b77854SSepherosa Ziehau hypercall_memfree(); 18982b77854SSepherosa Ziehau 19082b77854SSepherosa Ziehau if (bootverbose) 19182b77854SSepherosa Ziehau kprintf("hyperv: Hypercall destroyed\n"); 19282b77854SSepherosa Ziehau } 19382b77854SSepherosa Ziehau 19482b77854SSepherosa Ziehau static uint64_t 19582b77854SSepherosa Ziehau hyperv_tc64_rdmsr(void) 19682b77854SSepherosa Ziehau { 19782b77854SSepherosa Ziehau 19882b77854SSepherosa Ziehau return (rdmsr(MSR_HV_TIME_REF_COUNT)); 19982b77854SSepherosa Ziehau } 20082b77854SSepherosa Ziehau 20182b77854SSepherosa Ziehau static boolean_t 20282b77854SSepherosa Ziehau hyperv_identify(void) 20382b77854SSepherosa Ziehau { 20482b77854SSepherosa Ziehau u_int regs[4]; 20582b77854SSepherosa Ziehau unsigned int maxleaf; 20682b77854SSepherosa Ziehau 20782b77854SSepherosa Ziehau if (vmm_guest != VMM_GUEST_HYPERV) 20882b77854SSepherosa Ziehau return (FALSE); 20982b77854SSepherosa Ziehau 21082b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_MAXLEAF, regs); 21182b77854SSepherosa Ziehau maxleaf = regs[0]; 21282b77854SSepherosa Ziehau if (maxleaf < CPUID_LEAF_HV_LIMITS) 21382b77854SSepherosa Ziehau return (FALSE); 21482b77854SSepherosa Ziehau 21582b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_INTERFACE, regs); 21682b77854SSepherosa Ziehau if (regs[0] != CPUID_HV_IFACE_HYPERV) 21782b77854SSepherosa Ziehau return (FALSE); 21882b77854SSepherosa Ziehau 21982b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_FEATURES, regs); 22082b77854SSepherosa Ziehau if ((regs[0] & CPUID_HV_MSR_HYPERCALL) == 0) { 22182b77854SSepherosa Ziehau /* 22282b77854SSepherosa Ziehau * Hyper-V w/o Hypercall is impossible; someone 22382b77854SSepherosa Ziehau * is faking Hyper-V. 22482b77854SSepherosa Ziehau */ 22582b77854SSepherosa Ziehau return (FALSE); 22682b77854SSepherosa Ziehau } 22782b77854SSepherosa Ziehau hyperv_features = regs[0]; 22882b77854SSepherosa Ziehau hyperv_pm_features = regs[2]; 22982b77854SSepherosa Ziehau hyperv_features3 = regs[3]; 23082b77854SSepherosa Ziehau 23182b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_IDENTITY, regs); 23282b77854SSepherosa Ziehau kprintf("Hyper-V Version: %d.%d.%d [SP%d]\n", 23382b77854SSepherosa Ziehau regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]); 23482b77854SSepherosa Ziehau 23582b77854SSepherosa Ziehau kprintf(" Features=0x%b\n", hyperv_features, 23682b77854SSepherosa Ziehau "\020" 23782b77854SSepherosa Ziehau "\001VPRUNTIME" /* MSR_HV_VP_RUNTIME */ 23882b77854SSepherosa Ziehau "\002TMREFCNT" /* MSR_HV_TIME_REF_COUNT */ 23982b77854SSepherosa Ziehau "\003SYNIC" /* MSRs for SynIC */ 24082b77854SSepherosa Ziehau "\004SYNTM" /* MSRs for SynTimer */ 24182b77854SSepherosa Ziehau "\005APIC" /* MSR_HV_{EOI,ICR,TPR} */ 24282b77854SSepherosa Ziehau "\006HYPERCALL" /* MSR_HV_{GUEST_OS_ID,HYPERCALL} */ 24382b77854SSepherosa Ziehau "\007VPINDEX" /* MSR_HV_VP_INDEX */ 24482b77854SSepherosa Ziehau "\010RESET" /* MSR_HV_RESET */ 24582b77854SSepherosa Ziehau "\011STATS" /* MSR_HV_STATS_ */ 24682b77854SSepherosa Ziehau "\012REFTSC" /* MSR_HV_REFERENCE_TSC */ 24782b77854SSepherosa Ziehau "\013IDLE" /* MSR_HV_GUEST_IDLE */ 24882b77854SSepherosa Ziehau "\014TMFREQ" /* MSR_HV_{TSC,APIC}_FREQUENCY */ 24982b77854SSepherosa Ziehau "\015DEBUG"); /* MSR_HV_SYNTH_DEBUG_ */ 25082b77854SSepherosa Ziehau kprintf(" PM Features=0x%b [C%u]\n", 25182b77854SSepherosa Ziehau (hyperv_pm_features & ~CPUPM_HV_CSTATE_MASK), 25282b77854SSepherosa Ziehau "\020" 25382b77854SSepherosa Ziehau "\005C3HPET", /* HPET is required for C3 state */ 25482b77854SSepherosa Ziehau CPUPM_HV_CSTATE(hyperv_pm_features)); 25582b77854SSepherosa Ziehau kprintf(" Features3=0x%b\n", hyperv_features3, 25682b77854SSepherosa Ziehau "\020" 25782b77854SSepherosa Ziehau "\001MWAIT" /* MWAIT */ 25882b77854SSepherosa Ziehau "\002DEBUG" /* guest debug support */ 25982b77854SSepherosa Ziehau "\003PERFMON" /* performance monitor */ 26082b77854SSepherosa Ziehau "\004PCPUDPE" /* physical CPU dynamic partition event */ 26182b77854SSepherosa Ziehau "\005XMMHC" /* hypercall input through XMM regs */ 26282b77854SSepherosa Ziehau "\006IDLE" /* guest idle support */ 26382b77854SSepherosa Ziehau "\007SLEEP" /* hypervisor sleep support */ 26482b77854SSepherosa Ziehau "\010NUMA" /* NUMA distance query support */ 26582b77854SSepherosa Ziehau "\011TMFREQ" /* timer frequency query (TSC, LAPIC) */ 26682b77854SSepherosa Ziehau "\012SYNCMC" /* inject synthetic machine checks */ 26782b77854SSepherosa Ziehau "\013CRASH" /* MSRs for guest crash */ 26882b77854SSepherosa Ziehau "\014DEBUGMSR" /* MSRs for guest debug */ 26982b77854SSepherosa Ziehau "\015NPIEP" /* NPIEP */ 27082b77854SSepherosa Ziehau "\016HVDIS"); /* disabling hypervisor */ 27182b77854SSepherosa Ziehau 27282b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_RECOMMENDS, regs); 27382b77854SSepherosa Ziehau hyperv_recommends = regs[0]; 27482b77854SSepherosa Ziehau if (bootverbose) 27582b77854SSepherosa Ziehau kprintf(" Recommends: %08x %08x\n", regs[0], regs[1]); 27682b77854SSepherosa Ziehau 27782b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_LIMITS, regs); 27882b77854SSepherosa Ziehau if (bootverbose) { 27982b77854SSepherosa Ziehau kprintf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n", 28082b77854SSepherosa Ziehau regs[0], regs[1], regs[2]); 28182b77854SSepherosa Ziehau } 28282b77854SSepherosa Ziehau 28382b77854SSepherosa Ziehau if (maxleaf >= CPUID_LEAF_HV_HWFEATURES) { 28482b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_HWFEATURES, regs); 28582b77854SSepherosa Ziehau if (bootverbose) { 28682b77854SSepherosa Ziehau kprintf(" HW Features: %08x, AMD: %08x\n", 28782b77854SSepherosa Ziehau regs[0], regs[3]); 28882b77854SSepherosa Ziehau } 28982b77854SSepherosa Ziehau } 29082b77854SSepherosa Ziehau 29182b77854SSepherosa Ziehau return (TRUE); 29282b77854SSepherosa Ziehau } 29382b77854SSepherosa Ziehau 29482b77854SSepherosa Ziehau static void 29582b77854SSepherosa Ziehau hyperv_init(void *dummy __unused) 29682b77854SSepherosa Ziehau { 29782b77854SSepherosa Ziehau int error; 29882b77854SSepherosa Ziehau 29982b77854SSepherosa Ziehau if (!hyperv_identify()) { 30082b77854SSepherosa Ziehau /* Not Hyper-V; reset guest id to the generic one. */ 30182b77854SSepherosa Ziehau if (vmm_guest == VMM_GUEST_HYPERV) 30282b77854SSepherosa Ziehau vmm_guest = VMM_GUEST_UNKNOWN; 30382b77854SSepherosa Ziehau return; 30482b77854SSepherosa Ziehau } 30582b77854SSepherosa Ziehau 30682b77854SSepherosa Ziehau /* Set guest id */ 30782b77854SSepherosa Ziehau wrmsr(MSR_HV_GUEST_OS_ID, MSR_HV_GUESTID_DRAGONFLY); 30882b77854SSepherosa Ziehau 30982b77854SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) { 310*31517ca9SSepherosa Ziehau /* Register Hyper-V cputimers */ 31182b77854SSepherosa Ziehau cputimer_register(&hyperv_cputimer); 31282b77854SSepherosa Ziehau cputimer_select(&hyperv_cputimer, 0); 313*31517ca9SSepherosa Ziehau cpucounter_register(&hyperv_cpucounter); 31482b77854SSepherosa Ziehau hyperv_tc64 = hyperv_tc64_rdmsr; 31582b77854SSepherosa Ziehau } 31682b77854SSepherosa Ziehau 31782b77854SSepherosa Ziehau error = hypercall_create(); 31882b77854SSepherosa Ziehau if (error) { 31982b77854SSepherosa Ziehau /* Can't perform any Hyper-V specific actions */ 32082b77854SSepherosa Ziehau vmm_guest = VMM_GUEST_UNKNOWN; 32182b77854SSepherosa Ziehau } 32282b77854SSepherosa Ziehau 32382b77854SSepherosa Ziehau /* Machine dependent initialization. */ 32482b77854SSepherosa Ziehau hyperv_md_init(); 32582b77854SSepherosa Ziehau } 32682b77854SSepherosa Ziehau SYSINIT(hyperv_initialize, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, 32782b77854SSepherosa Ziehau hyperv_init, NULL); 32882b77854SSepherosa Ziehau 32982b77854SSepherosa Ziehau static void 33082b77854SSepherosa Ziehau hyperv_uninit(void *dummy __unused) 33182b77854SSepherosa Ziehau { 33282b77854SSepherosa Ziehau /* Machine dependent uninitialization. */ 33382b77854SSepherosa Ziehau hyperv_md_uninit(); 33482b77854SSepherosa Ziehau 33582b77854SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) { 33682b77854SSepherosa Ziehau /* Deregister Hyper-V systimer */ 33782b77854SSepherosa Ziehau cputimer_deregister(&hyperv_cputimer); 33882b77854SSepherosa Ziehau } 33982b77854SSepherosa Ziehau hypercall_destroy(); 34082b77854SSepherosa Ziehau } 34182b77854SSepherosa Ziehau SYSUNINIT(hyperv_uninitialize, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, 34282b77854SSepherosa Ziehau hyperv_uninit, NULL); 343