Staging: hv: fix sparse function warnings
[deliverable/linux.git] / drivers / staging / hv / Hv.c
CommitLineData
3e7ee490
HJ
1/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
24
09d50ff8 25#include "include/logging.h"
3e7ee490
HJ
26#include "VmbusPrivate.h"
27
454f18a9 28/* Globals */
3e7ee490 29
454f18a9 30/* The one and only */
3e7ee490 31HV_CONTEXT gHvContext={
0e727613 32 .SynICInitialized = false,
3e7ee490
HJ
33 .HypercallPage = NULL,
34 .SignalEventParam = NULL,
35 .SignalEventBuffer = NULL,
36};
37
38
39/*++
40
41Name:
42 HvQueryHypervisorPresence()
43
44Description:
45 Query the cpuid for presense of windows hypervisor
46
47--*/
48static int
49HvQueryHypervisorPresence (
50 void
51 )
52{
53 unsigned int eax;
54 unsigned int ebx;
55 unsigned int ecx;
56 unsigned int edx;
57 unsigned int op;
58
59 eax = 0;
60 ebx = 0;
61 ecx = 0;
62 edx = 0;
63 op = HvCpuIdFunctionVersionAndFeatures;
64 do_cpuid(op, &eax, &ebx, &ecx, &edx);
65
66 return (ecx & HV_PRESENT_BIT);
67}
68
69
70/*++
71
72Name:
73 HvQueryHypervisorInfo()
74
75Description:
76 Get version info of the windows hypervisor
77
78--*/
79static int
80HvQueryHypervisorInfo (
81 void
82 )
83{
84 unsigned int eax;
85 unsigned int ebx;
86 unsigned int ecx;
87 unsigned int edx;
88 unsigned int maxLeaf;
89 unsigned int op;
90
454f18a9
BP
91 /*
92 * Its assumed that this is called after confirming that Viridian
93 * is present. Query id and revision.
94 */
95
3e7ee490
HJ
96
97 eax = 0;
98 ebx = 0;
99 ecx = 0;
100 edx = 0;
101 op = HvCpuIdFunctionHvVendorAndMaxFunction;
102 do_cpuid(op, &eax, &ebx, &ecx, &edx);
103
104 DPRINT_INFO(VMBUS, "Vendor ID: %c%c%c%c%c%c%c%c%c%c%c%c",
454f18a9
BP
105 (ebx & 0xFF),
106 ((ebx >> 8) & 0xFF),
107 ((ebx >> 16) & 0xFF),
108 ((ebx >> 24) & 0xFF),
109 (ecx & 0xFF),
110 ((ecx >> 8) & 0xFF),
111 ((ecx >> 16) & 0xFF),
112 ((ecx >> 24) & 0xFF),
113 (edx & 0xFF),
114 ((edx >> 8) & 0xFF),
115 ((edx >> 16) & 0xFF),
116 ((edx >> 24) & 0xFF));
3e7ee490
HJ
117
118 maxLeaf = eax;
119 eax = 0;
120 ebx = 0;
121 ecx = 0;
122 edx = 0;
123 op = HvCpuIdFunctionHvInterface;
124 do_cpuid(op, &eax, &ebx, &ecx, &edx);
125
126 DPRINT_INFO(VMBUS, "Interface ID: %c%c%c%c",
454f18a9
BP
127 (eax & 0xFF),
128 ((eax >> 8) & 0xFF),
129 ((eax >> 16) & 0xFF),
130 ((eax >> 24) & 0xFF));
3e7ee490
HJ
131
132 if (maxLeaf >= HvCpuIdFunctionMsHvVersion) {
454f18a9
BP
133 eax = 0;
134 ebx = 0;
135 ecx = 0;
136 edx = 0;
137 op = HvCpuIdFunctionMsHvVersion;
138 do_cpuid(op, &eax, &ebx, &ecx, &edx);
139 DPRINT_INFO(VMBUS, "OS Build:%d-%d.%d-%d-%d.%d",
140 eax,
141 ebx >> 16,
142 ebx & 0xFFFF,
143 ecx,
144 edx >> 24,
145 edx & 0xFFFFFF);
3e7ee490
HJ
146 }
147 return maxLeaf;
148}
149
150
151/*++
152
153Name:
154 HvDoHypercall()
155
156Description:
157 Invoke the specified hypercall
158
159--*/
59471438 160static u64
3e7ee490 161HvDoHypercall (
59471438 162 u64 Control,
3e7ee490
HJ
163 void* Input,
164 void* Output
165 )
166{
530cf207 167#ifdef CONFIG_X86_64
59471438
GKH
168 u64 hvStatus=0;
169 u64 inputAddress = (Input)? GetPhysicalAddress(Input) : 0;
170 u64 outputAddress = (Output)? GetPhysicalAddress(Output) : 0;
3e7ee490
HJ
171 volatile void* hypercallPage = gHvContext.HypercallPage;
172
173 DPRINT_DBG(VMBUS, "Hypercall <control %llx input phys %llx virt %p output phys %llx virt %p hypercall %p>",
174 Control,
175 inputAddress,
176 Input,
177 outputAddress,
178 Output,
179 hypercallPage);
180
181 __asm__ __volatile__ ("mov %0, %%r8" : : "r" (outputAddress): "r8");
182 __asm__ __volatile__ ("call *%3" : "=a"(hvStatus): "c" (Control), "d" (inputAddress), "m" (hypercallPage));
183
184 DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatus);
185
186 return hvStatus;
187
188#else
189
4d643114
GKH
190 u32 controlHi = Control >> 32;
191 u32 controlLo = Control & 0xFFFFFFFF;
192 u32 hvStatusHi = 1;
193 u32 hvStatusLo = 1;
59471438 194 u64 inputAddress = (Input) ? GetPhysicalAddress(Input) : 0;
4d643114
GKH
195 u32 inputAddressHi = inputAddress >> 32;
196 u32 inputAddressLo = inputAddress & 0xFFFFFFFF;
59471438 197 u64 outputAddress = (Output) ?GetPhysicalAddress(Output) : 0;
4d643114
GKH
198 u32 outputAddressHi = outputAddress >> 32;
199 u32 outputAddressLo = outputAddress & 0xFFFFFFFF;
3e7ee490
HJ
200 volatile void* hypercallPage = gHvContext.HypercallPage;
201
202 DPRINT_DBG(VMBUS, "Hypercall <control %llx input %p output %p>",
203 Control,
204 Input,
205 Output);
206
207 __asm__ __volatile__ ("call *%8" : "=d"(hvStatusHi), "=a"(hvStatusLo) : "d" (controlHi), "a" (controlLo), "b" (inputAddressHi), "c" (inputAddressLo), "D"(outputAddressHi), "S"(outputAddressLo), "m" (hypercallPage));
208
209
59471438 210 DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatusLo | ((u64)hvStatusHi << 32));
3e7ee490 211
59471438 212 return (hvStatusLo | ((u64)hvStatusHi << 32));
454f18a9 213#endif /* x86_64 */
3e7ee490
HJ
214}
215
216/*++
217
218Name:
219 HvInit()
220
221Description:
222 Main initialization routine. This routine must be called
223 before any other routines in here are called
224
225--*/
226static int
227HvInit (
228 void
229 )
230{
231 int ret=0;
232 int maxLeaf;
233 HV_X64_MSR_HYPERCALL_CONTENTS hypercallMsr;
234 void* virtAddr=0;
3e7ee490
HJ
235
236 DPRINT_ENTER(VMBUS);
237
44f357f8
BP
238 memset(gHvContext.synICEventPage, 0, sizeof(void *) * MAX_NUM_CPUS);
239 memset(gHvContext.synICMessagePage, 0, sizeof(void *) * MAX_NUM_CPUS);
3e7ee490
HJ
240
241 if (!HvQueryHypervisorPresence())
242 {
243 DPRINT_ERR(VMBUS, "No Windows hypervisor detected!!");
244 goto Cleanup;
245 }
246
247 DPRINT_INFO(VMBUS, "Windows hypervisor detected! Retrieving more info...");
248
249 maxLeaf = HvQueryHypervisorInfo();
454f18a9 250 /* HvQueryHypervisorFeatures(maxLeaf); */
3e7ee490 251
454f18a9 252 /* Determine if we are running on xenlinux (ie x2v shim) or native linux */
3e7ee490
HJ
253 gHvContext.GuestId = ReadMsr(HV_X64_MSR_GUEST_OS_ID);
254
255 if (gHvContext.GuestId == 0)
256 {
454f18a9 257 /* Write our OS info */
3e7ee490
HJ
258 WriteMsr(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
259
260 gHvContext.GuestId = HV_LINUX_GUEST_ID;
261 }
262
454f18a9 263 /* See if the hypercall page is already set */
3e7ee490
HJ
264 hypercallMsr.AsUINT64 = ReadMsr(HV_X64_MSR_HYPERCALL);
265
266 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
267 {
454f18a9
BP
268 /* Allocate the hypercall page memory */
269 /* virtAddr = PageAlloc(1); */
3e7ee490
HJ
270 virtAddr = VirtualAllocExec(PAGE_SIZE);
271
272 if (!virtAddr)
273 {
274 DPRINT_ERR(VMBUS, "unable to allocate hypercall page!!");
275 goto Cleanup;
276 }
277
278 hypercallMsr.Enable = 1;
454f18a9 279 /* hypercallMsr.GuestPhysicalAddress = Logical2PhysicalAddr(virtAddr) >> PAGE_SHIFT; */
3e7ee490
HJ
280 hypercallMsr.GuestPhysicalAddress = Virtual2Physical(virtAddr) >> PAGE_SHIFT;
281 WriteMsr(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
282
454f18a9 283 /* Confirm that hypercall page did get setup. */
3e7ee490
HJ
284 hypercallMsr.AsUINT64 = 0;
285 hypercallMsr.AsUINT64 = ReadMsr(HV_X64_MSR_HYPERCALL);
286
287 if (!hypercallMsr.Enable)
288 {
289 DPRINT_ERR(VMBUS, "unable to set hypercall page!!");
290 goto Cleanup;
291 }
292
293 gHvContext.HypercallPage = virtAddr;
294 }
295 else
296 {
297 DPRINT_ERR(VMBUS, "Unknown guest id (0x%llx)!!", gHvContext.GuestId);
298 goto Cleanup;
299 }
300
2701f686
GKH
301 DPRINT_INFO(VMBUS, "Hypercall page VA=%p, PA=0x%0llx",
302 gHvContext.HypercallPage,
303 (u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT);
3e7ee490 304
454f18a9 305 /* Setup the global signal event param for the signal event hypercall */
e40d37cc 306 gHvContext.SignalEventBuffer = kmalloc(sizeof(HV_INPUT_SIGNAL_EVENT_BUFFER), GFP_KERNEL);
3e7ee490
HJ
307 if (!gHvContext.SignalEventBuffer)
308 {
309 goto Cleanup;
310 }
311
c4b0bc94 312 gHvContext.SignalEventParam = (PHV_INPUT_SIGNAL_EVENT)(ALIGN_UP((unsigned long)gHvContext.SignalEventBuffer, HV_HYPERCALL_PARAM_ALIGN));
4d643114 313 gHvContext.SignalEventParam->ConnectionId.Asu32 = 0;
3e7ee490
HJ
314 gHvContext.SignalEventParam->ConnectionId.u.Id = VMBUS_EVENT_CONNECTION_ID;
315 gHvContext.SignalEventParam->FlagNumber = 0;
316 gHvContext.SignalEventParam->RsvdZ = 0;
317
454f18a9 318 /* DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId()); */
3e7ee490
HJ
319
320 DPRINT_EXIT(VMBUS);
321
322 return ret;
323
324Cleanup:
325 if (virtAddr)
326 {
327 if (hypercallMsr.Enable)
328 {
329 hypercallMsr.AsUINT64 = 0;
330 WriteMsr(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
331 }
332
333 VirtualFree(virtAddr);
334 }
335 ret = -1;
336 DPRINT_EXIT(VMBUS);
337
338 return ret;
339}
340
341
342/*++
343
344Name:
345 HvCleanup()
346
347Description:
348 Cleanup routine. This routine is called normally during driver unloading or exiting.
349
350--*/
bd1de709 351static void
3e7ee490
HJ
352HvCleanup (
353 void
354 )
355{
356 HV_X64_MSR_HYPERCALL_CONTENTS hypercallMsr;
357
358 DPRINT_ENTER(VMBUS);
359
360 if (gHvContext.SignalEventBuffer)
361 {
8c69f52a 362 kfree(gHvContext.SignalEventBuffer);
3e7ee490
HJ
363 gHvContext.SignalEventBuffer = NULL;
364 gHvContext.SignalEventParam = NULL;
365 }
366
367 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
368 {
369 if (gHvContext.HypercallPage)
370 {
371 hypercallMsr.AsUINT64 = 0;
372 WriteMsr(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
373 VirtualFree(gHvContext.HypercallPage);
374 gHvContext.HypercallPage = NULL;
375 }
376 }
377
378 DPRINT_EXIT(VMBUS);
379
380}
381
382
383/*++
384
385Name:
386 HvPostMessage()
387
388Description:
389 Post a message using the hypervisor message IPC. This
390 involves a hypercall.
391
392--*/
bd1de709 393static HV_STATUS
3e7ee490
HJ
394HvPostMessage(
395 HV_CONNECTION_ID connectionId,
396 HV_MESSAGE_TYPE messageType,
8282c400 397 void * payload,
45635d97 398 size_t payloadSize
3e7ee490
HJ
399 )
400{
401 struct alignedInput {
59471438 402 u64 alignment8;
3e7ee490
HJ
403 HV_INPUT_POST_MESSAGE msg;
404 };
405
406 PHV_INPUT_POST_MESSAGE alignedMsg;
407 HV_STATUS status;
c4b0bc94 408 unsigned long addr;
3e7ee490
HJ
409
410 if (payloadSize > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
411 {
412 return -1;
413 }
414
0a72f3cf 415 addr = (unsigned long)kmalloc(sizeof(struct alignedInput), GFP_ATOMIC);
3e7ee490
HJ
416
417 if (!addr)
418 {
419 return -1;
420 }
421
422 alignedMsg = (PHV_INPUT_POST_MESSAGE)(ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN));
423
424 alignedMsg->ConnectionId = connectionId;
425 alignedMsg->MessageType = messageType;
426 alignedMsg->PayloadSize = payloadSize;
427 memcpy((void*)alignedMsg->Payload, payload, payloadSize);
428
429 status = HvDoHypercall(HvCallPostMessage, alignedMsg, 0) & 0xFFFF;
430
8c69f52a 431 kfree((void*)addr);
3e7ee490
HJ
432
433 return status;
434}
435
436
437/*++
438
439Name:
440 HvSignalEvent()
441
442Description:
443 Signal an event on the specified connection using the hypervisor event IPC. This
444 involves a hypercall.
445
446--*/
bd1de709 447static HV_STATUS
12772906 448HvSignalEvent(void)
3e7ee490
HJ
449{
450 HV_STATUS status;
451
452 status = HvDoHypercall(HvCallSignalEvent, gHvContext.SignalEventParam, 0) & 0xFFFF;
453
454 return status;
455}
456
457
458/*++
459
460Name:
461 HvSynicInit()
462
463Description:
464 Initialize the Synthethic Interrupt Controller. If it is already initialized by
465 another entity (ie x2v shim), we need to retrieve the initialized message and event pages.
466 Otherwise, we create and initialize the message and event pages.
467
468--*/
bd1de709 469static int
3e7ee490 470HvSynicInit (
4d643114 471 u32 irqVector
3e7ee490
HJ
472 )
473{
59471438 474 u64 version;
3e7ee490
HJ
475 HV_SYNIC_SIMP simp;
476 HV_SYNIC_SIEFP siefp;
477 HV_SYNIC_SINT sharedSint;
478 HV_SYNIC_SCONTROL sctrl;
59471438 479 u64 guestID;
3e7ee490
HJ
480 int ret=0;
481
482 DPRINT_ENTER(VMBUS);
483
484 if (!gHvContext.HypercallPage)
485 {
486 DPRINT_EXIT(VMBUS);
487 return ret;
488 }
489
454f18a9 490 /* Check the version */
3e7ee490
HJ
491 version = ReadMsr(HV_X64_MSR_SVERSION);
492
493 DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
494
454f18a9 495 /* TODO: Handle SMP */
3e7ee490
HJ
496 if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID)
497 {
498 DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since it is already set.");
499
500 simp.AsUINT64 = ReadMsr(HV_X64_MSR_SIMP);
501 siefp.AsUINT64 = ReadMsr(HV_X64_MSR_SIEFP);
502
503 DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx", simp.AsUINT64, siefp.AsUINT64);
504
454f18a9 505 /* Determine if we are running on xenlinux (ie x2v shim) or native linux */
3e7ee490
HJ
506 guestID = ReadMsr(HV_X64_MSR_GUEST_OS_ID);
507
508 if (guestID == HV_LINUX_GUEST_ID)
509 {
510 gHvContext.synICMessagePage[0] = GetVirtualAddress(simp.BaseSimpGpa << PAGE_SHIFT);
511 gHvContext.synICEventPage[0] = GetVirtualAddress(siefp.BaseSiefpGpa << PAGE_SHIFT);
512 }
513 else
514 {
515 DPRINT_ERR(VMBUS, "unknown guest id!!");
516 goto Cleanup;
517 }
518 DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", gHvContext.synICMessagePage[0], gHvContext.synICEventPage[0]);
519 }
520 else
521 {
522 gHvContext.synICMessagePage[0] = PageAlloc(1);
523 if (gHvContext.synICMessagePage[0] == NULL)
524 {
525 DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!");
526 goto Cleanup;
527 }
528
529 gHvContext.synICEventPage[0] = PageAlloc(1);
530 if (gHvContext.synICEventPage[0] == NULL)
531 {
532 DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!");
533 goto Cleanup;
534 }
535
454f18a9 536 /* Setup the Synic's message page */
3e7ee490
HJ
537 simp.AsUINT64 = ReadMsr(HV_X64_MSR_SIMP);
538 simp.SimpEnabled = 1;
539 simp.BaseSimpGpa = GetPhysicalAddress(gHvContext.synICMessagePage[0]) >> PAGE_SHIFT;
540
541 DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64);
542
543 WriteMsr(HV_X64_MSR_SIMP, simp.AsUINT64);
544
454f18a9 545 /* Setup the Synic's event page */
3e7ee490
HJ
546 siefp.AsUINT64 = ReadMsr(HV_X64_MSR_SIEFP);
547 siefp.SiefpEnabled = 1;
548 siefp.BaseSiefpGpa = GetPhysicalAddress(gHvContext.synICEventPage[0]) >> PAGE_SHIFT;
549
550 DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64);
551
552 WriteMsr(HV_X64_MSR_SIEFP, siefp.AsUINT64);
553 }
454f18a9
BP
554 /* Setup the interception SINT. */
555 /* WriteMsr((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
556 /* interceptionSint.AsUINT64); */
557
558 /* Setup the shared SINT. */
3e7ee490
HJ
559 sharedSint.AsUINT64 = ReadMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT);
560
561 sharedSint.AsUINT64 = 0;
454f18a9
BP
562 sharedSint.Vector = irqVector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
563 sharedSint.Masked = false;
564 sharedSint.AutoEoi = true;
3e7ee490
HJ
565
566 DPRINT_DBG(VMBUS, "HV_X64_MSR_SINT1 msr set to: %llx", sharedSint.AsUINT64);
567
568 WriteMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
569
454f18a9 570 /* Enable the global synic bit */
3e7ee490
HJ
571 sctrl.AsUINT64 = ReadMsr(HV_X64_MSR_SCONTROL);
572 sctrl.Enable = 1;
573
454f18a9 574 WriteMsr(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
3e7ee490 575
0e727613 576 gHvContext.SynICInitialized = true;
3e7ee490
HJ
577
578 DPRINT_EXIT(VMBUS);
579
580 return ret;
581
582Cleanup:
583 ret = -1;
584
585 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
586 {
587 if (gHvContext.synICEventPage[0])
588 {
589 PageFree(gHvContext.synICEventPage[0],1);
590 }
591
592 if (gHvContext.synICMessagePage[0])
593 {
594 PageFree(gHvContext.synICMessagePage[0], 1);
595 }
596 }
597
598 DPRINT_EXIT(VMBUS);
599
600 return ret;
601
602}
603
604/*++
605
606Name:
607 HvSynicCleanup()
608
609Description:
610 Cleanup routine for HvSynicInit().
611
612--*/
bd1de709 613static void
3e7ee490 614HvSynicCleanup(
e20f683b 615 void
3e7ee490
HJ
616 )
617{
618 HV_SYNIC_SINT sharedSint;
619 HV_SYNIC_SIMP simp;
620 HV_SYNIC_SIEFP siefp;
621
622 DPRINT_ENTER(VMBUS);
623
624 if (!gHvContext.SynICInitialized)
625 {
626 DPRINT_EXIT(VMBUS);
627 return;
628 }
629
630 sharedSint.AsUINT64 = ReadMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT);
631
632 sharedSint.Masked = 1;
633
454f18a9 634 /* Disable the interrupt */
3e7ee490
HJ
635 WriteMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
636
454f18a9
BP
637 /*
638 * Disable and free the resources only if we are running as
639 * native linux since in xenlinux, we are sharing the
640 * resources with the x2v shim
641 */
3e7ee490
HJ
642 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
643 {
644 simp.AsUINT64 = ReadMsr(HV_X64_MSR_SIMP);
645 simp.SimpEnabled = 0;
646 simp.BaseSimpGpa = 0;
647
648 WriteMsr(HV_X64_MSR_SIMP, simp.AsUINT64);
649
650 siefp.AsUINT64 = ReadMsr(HV_X64_MSR_SIEFP);
651 siefp.SiefpEnabled = 0;
652 siefp.BaseSiefpGpa = 0;
653
654 WriteMsr(HV_X64_MSR_SIEFP, siefp.AsUINT64);
655
656 PageFree(gHvContext.synICMessagePage[0], 1);
657 PageFree(gHvContext.synICEventPage[0], 1);
658 }
659
660 DPRINT_EXIT(VMBUS);
661}
662
663
454f18a9 664/* eof */
This page took 0.101134 seconds and 5 git commands to generate.