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