1*82b77854SSepherosa Ziehau /*- 2*82b77854SSepherosa Ziehau * Copyright (c) 2009-2012,2016 Microsoft Corp. 3*82b77854SSepherosa Ziehau * Copyright (c) 2012 NetApp Inc. 4*82b77854SSepherosa Ziehau * Copyright (c) 2012 Citrix Inc. 5*82b77854SSepherosa Ziehau * All rights reserved. 6*82b77854SSepherosa Ziehau * 7*82b77854SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 8*82b77854SSepherosa Ziehau * modification, are permitted provided that the following conditions 9*82b77854SSepherosa Ziehau * are met: 10*82b77854SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 11*82b77854SSepherosa Ziehau * notice unmodified, this list of conditions, and the following 12*82b77854SSepherosa Ziehau * disclaimer. 13*82b77854SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 14*82b77854SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 15*82b77854SSepherosa Ziehau * documentation and/or other materials provided with the distribution. 16*82b77854SSepherosa Ziehau * 17*82b77854SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18*82b77854SSepherosa Ziehau * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19*82b77854SSepherosa Ziehau * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*82b77854SSepherosa Ziehau * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21*82b77854SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22*82b77854SSepherosa Ziehau * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23*82b77854SSepherosa Ziehau * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24*82b77854SSepherosa Ziehau * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25*82b77854SSepherosa Ziehau * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26*82b77854SSepherosa Ziehau * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*82b77854SSepherosa Ziehau */ 28*82b77854SSepherosa Ziehau 29*82b77854SSepherosa Ziehau #include <sys/param.h> 30*82b77854SSepherosa Ziehau #include <sys/kernel.h> 31*82b77854SSepherosa Ziehau #include <sys/systimer.h> 32*82b77854SSepherosa Ziehau #include <sys/systm.h> 33*82b77854SSepherosa Ziehau 34*82b77854SSepherosa Ziehau #include <machine/cpufunc.h> 35*82b77854SSepherosa Ziehau 36*82b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_busdma.h> 37*82b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_machdep.h> 38*82b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_reg.h> 39*82b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_var.h> 40*82b77854SSepherosa Ziehau 41*82b77854SSepherosa Ziehau #define HYPERV_DRAGONFLY_BUILD 0ULL 42*82b77854SSepherosa Ziehau #define HYPERV_DRAGONFLY_VERSION ((uint64_t)__DragonFly_version) 43*82b77854SSepherosa Ziehau #define HYPERV_DRAGONFLY_OSID 0ULL 44*82b77854SSepherosa Ziehau 45*82b77854SSepherosa Ziehau #define MSR_HV_GUESTID_BUILD_DRAGONFLY \ 46*82b77854SSepherosa Ziehau (HYPERV_DRAGONFLY_BUILD & MSR_HV_GUESTID_BUILD_MASK) 47*82b77854SSepherosa Ziehau #define MSR_HV_GUESTID_VERSION_DRAGONFLY \ 48*82b77854SSepherosa Ziehau ((HYPERV_DRAGONFLY_VERSION << MSR_HV_GUESTID_VERSION_SHIFT) & \ 49*82b77854SSepherosa Ziehau MSR_HV_GUESTID_VERSION_MASK) 50*82b77854SSepherosa Ziehau #define MSR_HV_GUESTID_OSID_DRAGONFLY \ 51*82b77854SSepherosa Ziehau ((HYPERV_DRAGONFLY_OSID << MSR_HV_GUESTID_OSID_SHIFT) & \ 52*82b77854SSepherosa Ziehau MSR_HV_GUESTID_OSID_MASK) 53*82b77854SSepherosa Ziehau 54*82b77854SSepherosa Ziehau #define MSR_HV_GUESTID_DRAGONFLY \ 55*82b77854SSepherosa Ziehau (MSR_HV_GUESTID_BUILD_DRAGONFLY | \ 56*82b77854SSepherosa Ziehau MSR_HV_GUESTID_VERSION_DRAGONFLY | \ 57*82b77854SSepherosa Ziehau MSR_HV_GUESTID_OSID_DRAGONFLY | \ 58*82b77854SSepherosa Ziehau MSR_HV_GUESTID_OSTYPE_FREEBSD) 59*82b77854SSepherosa Ziehau 60*82b77854SSepherosa Ziehau struct hypercall_ctx { 61*82b77854SSepherosa Ziehau void *hc_addr; 62*82b77854SSepherosa Ziehau struct hyperv_dma hc_dma; 63*82b77854SSepherosa Ziehau }; 64*82b77854SSepherosa Ziehau 65*82b77854SSepherosa Ziehau static void hyperv_cputimer_construct(struct cputimer *, 66*82b77854SSepherosa Ziehau sysclock_t); 67*82b77854SSepherosa Ziehau static sysclock_t hyperv_cputimer_count(void); 68*82b77854SSepherosa Ziehau static boolean_t hyperv_identify(void); 69*82b77854SSepherosa Ziehau static int hypercall_create(void); 70*82b77854SSepherosa Ziehau static void hypercall_destroy(void); 71*82b77854SSepherosa Ziehau static void hypercall_memfree(void); 72*82b77854SSepherosa Ziehau static uint64_t hyperv_tc64_rdmsr(void); 73*82b77854SSepherosa Ziehau 74*82b77854SSepherosa Ziehau u_int hyperv_features; 75*82b77854SSepherosa Ziehau static u_int hyperv_recommends; 76*82b77854SSepherosa Ziehau 77*82b77854SSepherosa Ziehau static u_int hyperv_pm_features; 78*82b77854SSepherosa Ziehau static u_int hyperv_features3; 79*82b77854SSepherosa Ziehau 80*82b77854SSepherosa Ziehau hyperv_tc64_t hyperv_tc64; 81*82b77854SSepherosa Ziehau 82*82b77854SSepherosa Ziehau static struct cputimer hyperv_cputimer = { 83*82b77854SSepherosa Ziehau .next = SLIST_ENTRY_INITIALIZER, 84*82b77854SSepherosa Ziehau .name = "Hyper-V", 85*82b77854SSepherosa Ziehau .pri = CPUTIMER_PRI_VMM, 86*82b77854SSepherosa Ziehau .type = CPUTIMER_VMM, 87*82b77854SSepherosa Ziehau .count = hyperv_cputimer_count, 88*82b77854SSepherosa Ziehau .fromhz = cputimer_default_fromhz, 89*82b77854SSepherosa Ziehau .fromus = cputimer_default_fromus, 90*82b77854SSepherosa Ziehau .construct = hyperv_cputimer_construct, 91*82b77854SSepherosa Ziehau .destruct = cputimer_default_destruct, 92*82b77854SSepherosa Ziehau .freq = HYPERV_TIMER_FREQ 93*82b77854SSepherosa Ziehau }; 94*82b77854SSepherosa Ziehau 95*82b77854SSepherosa Ziehau static struct hypercall_ctx hypercall_context; 96*82b77854SSepherosa Ziehau 97*82b77854SSepherosa Ziehau uint64_t 98*82b77854SSepherosa Ziehau hypercall_post_message(bus_addr_t msg_paddr) 99*82b77854SSepherosa Ziehau { 100*82b77854SSepherosa Ziehau return hypercall_md(hypercall_context.hc_addr, 101*82b77854SSepherosa Ziehau HYPERCALL_POST_MESSAGE, msg_paddr, 0); 102*82b77854SSepherosa Ziehau } 103*82b77854SSepherosa Ziehau 104*82b77854SSepherosa Ziehau static void 105*82b77854SSepherosa Ziehau hyperv_cputimer_construct(struct cputimer *timer, sysclock_t oldclock) 106*82b77854SSepherosa Ziehau { 107*82b77854SSepherosa Ziehau timer->base = 0; 108*82b77854SSepherosa Ziehau timer->base = oldclock - timer->count(); 109*82b77854SSepherosa Ziehau } 110*82b77854SSepherosa Ziehau 111*82b77854SSepherosa Ziehau static sysclock_t 112*82b77854SSepherosa Ziehau hyperv_cputimer_count(void) 113*82b77854SSepherosa Ziehau { 114*82b77854SSepherosa Ziehau uint64_t val; 115*82b77854SSepherosa Ziehau 116*82b77854SSepherosa Ziehau val = rdmsr(MSR_HV_TIME_REF_COUNT); 117*82b77854SSepherosa Ziehau return (val + hyperv_cputimer.base); 118*82b77854SSepherosa Ziehau } 119*82b77854SSepherosa Ziehau 120*82b77854SSepherosa Ziehau static void 121*82b77854SSepherosa Ziehau hypercall_memfree(void) 122*82b77854SSepherosa Ziehau { 123*82b77854SSepherosa Ziehau hyperv_dmamem_free(&hypercall_context.hc_dma, 124*82b77854SSepherosa Ziehau hypercall_context.hc_addr); 125*82b77854SSepherosa Ziehau hypercall_context.hc_addr = NULL; 126*82b77854SSepherosa Ziehau } 127*82b77854SSepherosa Ziehau 128*82b77854SSepherosa Ziehau static int 129*82b77854SSepherosa Ziehau hypercall_create(void) 130*82b77854SSepherosa Ziehau { 131*82b77854SSepherosa Ziehau uint64_t hc, hc_orig; 132*82b77854SSepherosa Ziehau 133*82b77854SSepherosa Ziehau hypercall_context.hc_addr = hyperv_dmamem_alloc(NULL, PAGE_SIZE, 0, 134*82b77854SSepherosa Ziehau PAGE_SIZE, &hypercall_context.hc_dma, BUS_DMA_WAITOK); 135*82b77854SSepherosa Ziehau if (hypercall_context.hc_addr == NULL) { 136*82b77854SSepherosa Ziehau kprintf("hyperv: Hypercall page allocation failed\n"); 137*82b77854SSepherosa Ziehau return ENOMEM; 138*82b77854SSepherosa Ziehau } 139*82b77854SSepherosa Ziehau 140*82b77854SSepherosa Ziehau /* Get the 'reserved' bits, which requires preservation. */ 141*82b77854SSepherosa Ziehau hc_orig = rdmsr(MSR_HV_HYPERCALL); 142*82b77854SSepherosa Ziehau 143*82b77854SSepherosa Ziehau /* 144*82b77854SSepherosa Ziehau * Setup the Hypercall page. 145*82b77854SSepherosa Ziehau * 146*82b77854SSepherosa Ziehau * NOTE: 'reserved' bits MUST be preserved. 147*82b77854SSepherosa Ziehau */ 148*82b77854SSepherosa Ziehau hc = ((hypercall_context.hc_dma.hv_paddr >> PAGE_SHIFT) << 149*82b77854SSepherosa Ziehau MSR_HV_HYPERCALL_PGSHIFT) | 150*82b77854SSepherosa Ziehau (hc_orig & MSR_HV_HYPERCALL_RSVD_MASK) | 151*82b77854SSepherosa Ziehau MSR_HV_HYPERCALL_ENABLE; 152*82b77854SSepherosa Ziehau wrmsr(MSR_HV_HYPERCALL, hc); 153*82b77854SSepherosa Ziehau 154*82b77854SSepherosa Ziehau /* 155*82b77854SSepherosa Ziehau * Confirm that Hypercall page did get setup. 156*82b77854SSepherosa Ziehau */ 157*82b77854SSepherosa Ziehau hc = rdmsr(MSR_HV_HYPERCALL); 158*82b77854SSepherosa Ziehau if ((hc & MSR_HV_HYPERCALL_ENABLE) == 0) { 159*82b77854SSepherosa Ziehau kprintf("hyperv: Hypercall setup failed\n"); 160*82b77854SSepherosa Ziehau hypercall_memfree(); 161*82b77854SSepherosa Ziehau return EIO; 162*82b77854SSepherosa Ziehau } 163*82b77854SSepherosa Ziehau if (bootverbose) 164*82b77854SSepherosa Ziehau kprintf("hyperv: Hypercall created\n"); 165*82b77854SSepherosa Ziehau 166*82b77854SSepherosa Ziehau return 0; 167*82b77854SSepherosa Ziehau } 168*82b77854SSepherosa Ziehau 169*82b77854SSepherosa Ziehau static void 170*82b77854SSepherosa Ziehau hypercall_destroy(void) 171*82b77854SSepherosa Ziehau { 172*82b77854SSepherosa Ziehau uint64_t hc; 173*82b77854SSepherosa Ziehau 174*82b77854SSepherosa Ziehau if (hypercall_context.hc_addr == NULL) 175*82b77854SSepherosa Ziehau return; 176*82b77854SSepherosa Ziehau 177*82b77854SSepherosa Ziehau /* Disable Hypercall */ 178*82b77854SSepherosa Ziehau hc = rdmsr(MSR_HV_HYPERCALL); 179*82b77854SSepherosa Ziehau wrmsr(MSR_HV_HYPERCALL, (hc & MSR_HV_HYPERCALL_RSVD_MASK)); 180*82b77854SSepherosa Ziehau hypercall_memfree(); 181*82b77854SSepherosa Ziehau 182*82b77854SSepherosa Ziehau if (bootverbose) 183*82b77854SSepherosa Ziehau kprintf("hyperv: Hypercall destroyed\n"); 184*82b77854SSepherosa Ziehau } 185*82b77854SSepherosa Ziehau 186*82b77854SSepherosa Ziehau static uint64_t 187*82b77854SSepherosa Ziehau hyperv_tc64_rdmsr(void) 188*82b77854SSepherosa Ziehau { 189*82b77854SSepherosa Ziehau 190*82b77854SSepherosa Ziehau return (rdmsr(MSR_HV_TIME_REF_COUNT)); 191*82b77854SSepherosa Ziehau } 192*82b77854SSepherosa Ziehau 193*82b77854SSepherosa Ziehau static boolean_t 194*82b77854SSepherosa Ziehau hyperv_identify(void) 195*82b77854SSepherosa Ziehau { 196*82b77854SSepherosa Ziehau u_int regs[4]; 197*82b77854SSepherosa Ziehau unsigned int maxleaf; 198*82b77854SSepherosa Ziehau 199*82b77854SSepherosa Ziehau if (vmm_guest != VMM_GUEST_HYPERV) 200*82b77854SSepherosa Ziehau return (FALSE); 201*82b77854SSepherosa Ziehau 202*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_MAXLEAF, regs); 203*82b77854SSepherosa Ziehau maxleaf = regs[0]; 204*82b77854SSepherosa Ziehau if (maxleaf < CPUID_LEAF_HV_LIMITS) 205*82b77854SSepherosa Ziehau return (FALSE); 206*82b77854SSepherosa Ziehau 207*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_INTERFACE, regs); 208*82b77854SSepherosa Ziehau if (regs[0] != CPUID_HV_IFACE_HYPERV) 209*82b77854SSepherosa Ziehau return (FALSE); 210*82b77854SSepherosa Ziehau 211*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_FEATURES, regs); 212*82b77854SSepherosa Ziehau if ((regs[0] & CPUID_HV_MSR_HYPERCALL) == 0) { 213*82b77854SSepherosa Ziehau /* 214*82b77854SSepherosa Ziehau * Hyper-V w/o Hypercall is impossible; someone 215*82b77854SSepherosa Ziehau * is faking Hyper-V. 216*82b77854SSepherosa Ziehau */ 217*82b77854SSepherosa Ziehau return (FALSE); 218*82b77854SSepherosa Ziehau } 219*82b77854SSepherosa Ziehau hyperv_features = regs[0]; 220*82b77854SSepherosa Ziehau hyperv_pm_features = regs[2]; 221*82b77854SSepherosa Ziehau hyperv_features3 = regs[3]; 222*82b77854SSepherosa Ziehau 223*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_IDENTITY, regs); 224*82b77854SSepherosa Ziehau kprintf("Hyper-V Version: %d.%d.%d [SP%d]\n", 225*82b77854SSepherosa Ziehau regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]); 226*82b77854SSepherosa Ziehau 227*82b77854SSepherosa Ziehau kprintf(" Features=0x%b\n", hyperv_features, 228*82b77854SSepherosa Ziehau "\020" 229*82b77854SSepherosa Ziehau "\001VPRUNTIME" /* MSR_HV_VP_RUNTIME */ 230*82b77854SSepherosa Ziehau "\002TMREFCNT" /* MSR_HV_TIME_REF_COUNT */ 231*82b77854SSepherosa Ziehau "\003SYNIC" /* MSRs for SynIC */ 232*82b77854SSepherosa Ziehau "\004SYNTM" /* MSRs for SynTimer */ 233*82b77854SSepherosa Ziehau "\005APIC" /* MSR_HV_{EOI,ICR,TPR} */ 234*82b77854SSepherosa Ziehau "\006HYPERCALL" /* MSR_HV_{GUEST_OS_ID,HYPERCALL} */ 235*82b77854SSepherosa Ziehau "\007VPINDEX" /* MSR_HV_VP_INDEX */ 236*82b77854SSepherosa Ziehau "\010RESET" /* MSR_HV_RESET */ 237*82b77854SSepherosa Ziehau "\011STATS" /* MSR_HV_STATS_ */ 238*82b77854SSepherosa Ziehau "\012REFTSC" /* MSR_HV_REFERENCE_TSC */ 239*82b77854SSepherosa Ziehau "\013IDLE" /* MSR_HV_GUEST_IDLE */ 240*82b77854SSepherosa Ziehau "\014TMFREQ" /* MSR_HV_{TSC,APIC}_FREQUENCY */ 241*82b77854SSepherosa Ziehau "\015DEBUG"); /* MSR_HV_SYNTH_DEBUG_ */ 242*82b77854SSepherosa Ziehau kprintf(" PM Features=0x%b [C%u]\n", 243*82b77854SSepherosa Ziehau (hyperv_pm_features & ~CPUPM_HV_CSTATE_MASK), 244*82b77854SSepherosa Ziehau "\020" 245*82b77854SSepherosa Ziehau "\005C3HPET", /* HPET is required for C3 state */ 246*82b77854SSepherosa Ziehau CPUPM_HV_CSTATE(hyperv_pm_features)); 247*82b77854SSepherosa Ziehau kprintf(" Features3=0x%b\n", hyperv_features3, 248*82b77854SSepherosa Ziehau "\020" 249*82b77854SSepherosa Ziehau "\001MWAIT" /* MWAIT */ 250*82b77854SSepherosa Ziehau "\002DEBUG" /* guest debug support */ 251*82b77854SSepherosa Ziehau "\003PERFMON" /* performance monitor */ 252*82b77854SSepherosa Ziehau "\004PCPUDPE" /* physical CPU dynamic partition event */ 253*82b77854SSepherosa Ziehau "\005XMMHC" /* hypercall input through XMM regs */ 254*82b77854SSepherosa Ziehau "\006IDLE" /* guest idle support */ 255*82b77854SSepherosa Ziehau "\007SLEEP" /* hypervisor sleep support */ 256*82b77854SSepherosa Ziehau "\010NUMA" /* NUMA distance query support */ 257*82b77854SSepherosa Ziehau "\011TMFREQ" /* timer frequency query (TSC, LAPIC) */ 258*82b77854SSepherosa Ziehau "\012SYNCMC" /* inject synthetic machine checks */ 259*82b77854SSepherosa Ziehau "\013CRASH" /* MSRs for guest crash */ 260*82b77854SSepherosa Ziehau "\014DEBUGMSR" /* MSRs for guest debug */ 261*82b77854SSepherosa Ziehau "\015NPIEP" /* NPIEP */ 262*82b77854SSepherosa Ziehau "\016HVDIS"); /* disabling hypervisor */ 263*82b77854SSepherosa Ziehau 264*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_RECOMMENDS, regs); 265*82b77854SSepherosa Ziehau hyperv_recommends = regs[0]; 266*82b77854SSepherosa Ziehau if (bootverbose) 267*82b77854SSepherosa Ziehau kprintf(" Recommends: %08x %08x\n", regs[0], regs[1]); 268*82b77854SSepherosa Ziehau 269*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_LIMITS, regs); 270*82b77854SSepherosa Ziehau if (bootverbose) { 271*82b77854SSepherosa Ziehau kprintf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n", 272*82b77854SSepherosa Ziehau regs[0], regs[1], regs[2]); 273*82b77854SSepherosa Ziehau } 274*82b77854SSepherosa Ziehau 275*82b77854SSepherosa Ziehau if (maxleaf >= CPUID_LEAF_HV_HWFEATURES) { 276*82b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_HWFEATURES, regs); 277*82b77854SSepherosa Ziehau if (bootverbose) { 278*82b77854SSepherosa Ziehau kprintf(" HW Features: %08x, AMD: %08x\n", 279*82b77854SSepherosa Ziehau regs[0], regs[3]); 280*82b77854SSepherosa Ziehau } 281*82b77854SSepherosa Ziehau } 282*82b77854SSepherosa Ziehau 283*82b77854SSepherosa Ziehau return (TRUE); 284*82b77854SSepherosa Ziehau } 285*82b77854SSepherosa Ziehau 286*82b77854SSepherosa Ziehau static void 287*82b77854SSepherosa Ziehau hyperv_init(void *dummy __unused) 288*82b77854SSepherosa Ziehau { 289*82b77854SSepherosa Ziehau int error; 290*82b77854SSepherosa Ziehau 291*82b77854SSepherosa Ziehau if (!hyperv_identify()) { 292*82b77854SSepherosa Ziehau /* Not Hyper-V; reset guest id to the generic one. */ 293*82b77854SSepherosa Ziehau if (vmm_guest == VMM_GUEST_HYPERV) 294*82b77854SSepherosa Ziehau vmm_guest = VMM_GUEST_UNKNOWN; 295*82b77854SSepherosa Ziehau return; 296*82b77854SSepherosa Ziehau } 297*82b77854SSepherosa Ziehau 298*82b77854SSepherosa Ziehau /* Set guest id */ 299*82b77854SSepherosa Ziehau wrmsr(MSR_HV_GUEST_OS_ID, MSR_HV_GUESTID_DRAGONFLY); 300*82b77854SSepherosa Ziehau 301*82b77854SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) { 302*82b77854SSepherosa Ziehau /* Register Hyper-V systimer */ 303*82b77854SSepherosa Ziehau cputimer_register(&hyperv_cputimer); 304*82b77854SSepherosa Ziehau cputimer_select(&hyperv_cputimer, 0); 305*82b77854SSepherosa Ziehau hyperv_tc64 = hyperv_tc64_rdmsr; 306*82b77854SSepherosa Ziehau } 307*82b77854SSepherosa Ziehau 308*82b77854SSepherosa Ziehau error = hypercall_create(); 309*82b77854SSepherosa Ziehau if (error) { 310*82b77854SSepherosa Ziehau /* Can't perform any Hyper-V specific actions */ 311*82b77854SSepherosa Ziehau vmm_guest = VMM_GUEST_UNKNOWN; 312*82b77854SSepherosa Ziehau } 313*82b77854SSepherosa Ziehau 314*82b77854SSepherosa Ziehau /* Machine dependent initialization. */ 315*82b77854SSepherosa Ziehau hyperv_md_init(); 316*82b77854SSepherosa Ziehau } 317*82b77854SSepherosa Ziehau SYSINIT(hyperv_initialize, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, 318*82b77854SSepherosa Ziehau hyperv_init, NULL); 319*82b77854SSepherosa Ziehau 320*82b77854SSepherosa Ziehau static void 321*82b77854SSepherosa Ziehau hyperv_uninit(void *dummy __unused) 322*82b77854SSepherosa Ziehau { 323*82b77854SSepherosa Ziehau /* Machine dependent uninitialization. */ 324*82b77854SSepherosa Ziehau hyperv_md_uninit(); 325*82b77854SSepherosa Ziehau 326*82b77854SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) { 327*82b77854SSepherosa Ziehau /* Deregister Hyper-V systimer */ 328*82b77854SSepherosa Ziehau cputimer_deregister(&hyperv_cputimer); 329*82b77854SSepherosa Ziehau } 330*82b77854SSepherosa Ziehau hypercall_destroy(); 331*82b77854SSepherosa Ziehau } 332*82b77854SSepherosa Ziehau SYSUNINIT(hyperv_uninitialize, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, 333*82b77854SSepherosa Ziehau hyperv_uninit, NULL); 334