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