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