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
9531517ca9SSepherosa Ziehau static struct cpucounter hyperv_cpucounter = {
9631517ca9SSepherosa Ziehau .freq = HYPERV_TIMER_FREQ,
9731517ca9SSepherosa Ziehau .count = hyperv_tc64_rdmsr,
9831517ca9SSepherosa Ziehau .flags = CPUCOUNTER_FLAG_MPSYNC,
9931517ca9SSepherosa Ziehau .prio = CPUCOUNTER_PRIO_VMM,
10031517ca9SSepherosa Ziehau .type = CPUCOUNTER_VMM
10131517ca9SSepherosa Ziehau };
10231517ca9SSepherosa Ziehau
10382b77854SSepherosa Ziehau static struct hypercall_ctx hypercall_context;
10482b77854SSepherosa Ziehau
10582b77854SSepherosa Ziehau uint64_t
hypercall_post_message(bus_addr_t msg_paddr)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
hyperv_cputimer_construct(struct cputimer * timer,sysclock_t oldclock)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
hyperv_cputimer_count(void)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
hypercall_memfree(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
hypercall_create(void)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
hypercall_destroy(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
hyperv_tc64_rdmsr(void)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
hyperv_identify(void)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
235*2f8af9dbSzrj kprintf(" Features=0x%pb%i\n",
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 */
249*2f8af9dbSzrj "\015DEBUG", /* MSR_HV_SYNTH_DEBUG_ */
250*2f8af9dbSzrj hyperv_features);
251*2f8af9dbSzrj kprintf(" PM Features=0x%pb%i [C%u]\n",
25282b77854SSepherosa Ziehau "\020"
25382b77854SSepherosa Ziehau "\005C3HPET", /* HPET is required for C3 state */
254*2f8af9dbSzrj (hyperv_pm_features & ~CPUPM_HV_CSTATE_MASK),
25582b77854SSepherosa Ziehau CPUPM_HV_CSTATE(hyperv_pm_features));
256*2f8af9dbSzrj kprintf(" Features3=0x%pb%i\n",
25782b77854SSepherosa Ziehau "\020"
25882b77854SSepherosa Ziehau "\001MWAIT" /* MWAIT */
25982b77854SSepherosa Ziehau "\002DEBUG" /* guest debug support */
26082b77854SSepherosa Ziehau "\003PERFMON" /* performance monitor */
26182b77854SSepherosa Ziehau "\004PCPUDPE" /* physical CPU dynamic partition event */
26282b77854SSepherosa Ziehau "\005XMMHC" /* hypercall input through XMM regs */
26382b77854SSepherosa Ziehau "\006IDLE" /* guest idle support */
26482b77854SSepherosa Ziehau "\007SLEEP" /* hypervisor sleep support */
26582b77854SSepherosa Ziehau "\010NUMA" /* NUMA distance query support */
26682b77854SSepherosa Ziehau "\011TMFREQ" /* timer frequency query (TSC, LAPIC) */
26782b77854SSepherosa Ziehau "\012SYNCMC" /* inject synthetic machine checks */
26882b77854SSepherosa Ziehau "\013CRASH" /* MSRs for guest crash */
26982b77854SSepherosa Ziehau "\014DEBUGMSR" /* MSRs for guest debug */
27082b77854SSepherosa Ziehau "\015NPIEP" /* NPIEP */
271*2f8af9dbSzrj "\016HVDIS", /* disabling hypervisor */
272*2f8af9dbSzrj hyperv_features3);
27382b77854SSepherosa Ziehau
27482b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_RECOMMENDS, regs);
27582b77854SSepherosa Ziehau hyperv_recommends = regs[0];
27682b77854SSepherosa Ziehau if (bootverbose)
27782b77854SSepherosa Ziehau kprintf(" Recommends: %08x %08x\n", regs[0], regs[1]);
27882b77854SSepherosa Ziehau
27982b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_LIMITS, regs);
28082b77854SSepherosa Ziehau if (bootverbose) {
28182b77854SSepherosa Ziehau kprintf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n",
28282b77854SSepherosa Ziehau regs[0], regs[1], regs[2]);
28382b77854SSepherosa Ziehau }
28482b77854SSepherosa Ziehau
28582b77854SSepherosa Ziehau if (maxleaf >= CPUID_LEAF_HV_HWFEATURES) {
28682b77854SSepherosa Ziehau do_cpuid(CPUID_LEAF_HV_HWFEATURES, regs);
28782b77854SSepherosa Ziehau if (bootverbose) {
28882b77854SSepherosa Ziehau kprintf(" HW Features: %08x, AMD: %08x\n",
28982b77854SSepherosa Ziehau regs[0], regs[3]);
29082b77854SSepherosa Ziehau }
29182b77854SSepherosa Ziehau }
29282b77854SSepherosa Ziehau
29382b77854SSepherosa Ziehau return (TRUE);
29482b77854SSepherosa Ziehau }
29582b77854SSepherosa Ziehau
29682b77854SSepherosa Ziehau static void
hyperv_init(void * dummy __unused)29782b77854SSepherosa Ziehau hyperv_init(void *dummy __unused)
29882b77854SSepherosa Ziehau {
29982b77854SSepherosa Ziehau int error;
30082b77854SSepherosa Ziehau
30182b77854SSepherosa Ziehau if (!hyperv_identify()) {
30282b77854SSepherosa Ziehau /* Not Hyper-V; reset guest id to the generic one. */
30382b77854SSepherosa Ziehau if (vmm_guest == VMM_GUEST_HYPERV)
30482b77854SSepherosa Ziehau vmm_guest = VMM_GUEST_UNKNOWN;
30582b77854SSepherosa Ziehau return;
30682b77854SSepherosa Ziehau }
30782b77854SSepherosa Ziehau
30882b77854SSepherosa Ziehau /* Set guest id */
30982b77854SSepherosa Ziehau wrmsr(MSR_HV_GUEST_OS_ID, MSR_HV_GUESTID_DRAGONFLY);
31082b77854SSepherosa Ziehau
31182b77854SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) {
31231517ca9SSepherosa Ziehau /* Register Hyper-V cputimers */
31382b77854SSepherosa Ziehau cputimer_register(&hyperv_cputimer);
31482b77854SSepherosa Ziehau cputimer_select(&hyperv_cputimer, 0);
31531517ca9SSepherosa Ziehau cpucounter_register(&hyperv_cpucounter);
31682b77854SSepherosa Ziehau hyperv_tc64 = hyperv_tc64_rdmsr;
31782b77854SSepherosa Ziehau }
31882b77854SSepherosa Ziehau
31982b77854SSepherosa Ziehau error = hypercall_create();
32082b77854SSepherosa Ziehau if (error) {
32182b77854SSepherosa Ziehau /* Can't perform any Hyper-V specific actions */
32282b77854SSepherosa Ziehau vmm_guest = VMM_GUEST_UNKNOWN;
32382b77854SSepherosa Ziehau }
32482b77854SSepherosa Ziehau
32582b77854SSepherosa Ziehau /* Machine dependent initialization. */
32682b77854SSepherosa Ziehau hyperv_md_init();
32782b77854SSepherosa Ziehau }
32882b77854SSepherosa Ziehau SYSINIT(hyperv_initialize, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST,
32982b77854SSepherosa Ziehau hyperv_init, NULL);
33082b77854SSepherosa Ziehau
33182b77854SSepherosa Ziehau static void
hyperv_uninit(void * dummy __unused)33282b77854SSepherosa Ziehau hyperv_uninit(void *dummy __unused)
33382b77854SSepherosa Ziehau {
33482b77854SSepherosa Ziehau /* Machine dependent uninitialization. */
33582b77854SSepherosa Ziehau hyperv_md_uninit();
33682b77854SSepherosa Ziehau
33782b77854SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) {
33882b77854SSepherosa Ziehau /* Deregister Hyper-V systimer */
33982b77854SSepherosa Ziehau cputimer_deregister(&hyperv_cputimer);
34082b77854SSepherosa Ziehau }
34182b77854SSepherosa Ziehau hypercall_destroy();
34282b77854SSepherosa Ziehau }
34382b77854SSepherosa Ziehau SYSUNINIT(hyperv_uninitialize, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST,
34482b77854SSepherosa Ziehau hyperv_uninit, NULL);
345