xref: /dflybsd-src/sys/dev/virtual/hyperv/hyperv.c (revision 2f8af9db97ed459e9c8eb19927a185f29b8b0d2e)
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