]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/hv/Hv.c
Staging: hv: rndis.h: typedef removal, part 2
[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"
09d50ff8 28#include "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;
233 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
HJ
349{
350 HV_X64_MSR_HYPERCALL_CONTENTS hypercallMsr;
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--*/
98d9fac4 387HV_STATUS HvPostMessage(
3e7ee490
HJ
388 HV_CONNECTION_ID connectionId,
389 HV_MESSAGE_TYPE messageType,
8282c400 390 void * payload,
45635d97 391 size_t payloadSize
3e7ee490
HJ
392 )
393{
394 struct alignedInput {
59471438 395 u64 alignment8;
cba4decd 396 struct hv_input_post_message msg;
3e7ee490
HJ
397 };
398
cba4decd 399 struct hv_input_post_message *alignedMsg;
3e7ee490 400 HV_STATUS status;
c4b0bc94 401 unsigned long addr;
3e7ee490
HJ
402
403 if (payloadSize > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
404 {
405 return -1;
406 }
407
0a72f3cf 408 addr = (unsigned long)kmalloc(sizeof(struct alignedInput), GFP_ATOMIC);
3e7ee490
HJ
409
410 if (!addr)
411 {
412 return -1;
413 }
414
cba4decd 415 alignedMsg = (struct hv_input_post_message *)(ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN));
3e7ee490
HJ
416
417 alignedMsg->ConnectionId = connectionId;
418 alignedMsg->MessageType = messageType;
419 alignedMsg->PayloadSize = payloadSize;
420 memcpy((void*)alignedMsg->Payload, payload, payloadSize);
421
949cadaa 422 status = HvDoHypercall(HvCallPostMessage, alignedMsg, NULL) & 0xFFFF;
3e7ee490 423
8c69f52a 424 kfree((void*)addr);
3e7ee490
HJ
425
426 return status;
427}
428
429
430/*++
431
432Name:
433 HvSignalEvent()
434
435Description:
436 Signal an event on the specified connection using the hypervisor event IPC. This
437 involves a hypercall.
438
439--*/
98d9fac4 440HV_STATUS HvSignalEvent(void)
3e7ee490
HJ
441{
442 HV_STATUS status;
443
949cadaa 444 status = HvDoHypercall(HvCallSignalEvent, gHvContext.SignalEventParam, NULL) & 0xFFFF;
3e7ee490
HJ
445
446 return status;
447}
448
449
450/*++
451
452Name:
453 HvSynicInit()
454
455Description:
456 Initialize the Synthethic Interrupt Controller. If it is already initialized by
457 another entity (ie x2v shim), we need to retrieve the initialized message and event pages.
458 Otherwise, we create and initialize the message and event pages.
459
460--*/
98d9fac4 461int HvSynicInit (u32 irqVector)
3e7ee490 462{
59471438 463 u64 version;
3e7ee490
HJ
464 HV_SYNIC_SIMP simp;
465 HV_SYNIC_SIEFP siefp;
466 HV_SYNIC_SINT sharedSint;
467 HV_SYNIC_SCONTROL sctrl;
59471438 468 u64 guestID;
3e7ee490
HJ
469 int ret=0;
470
471 DPRINT_ENTER(VMBUS);
472
473 if (!gHvContext.HypercallPage)
474 {
475 DPRINT_EXIT(VMBUS);
476 return ret;
477 }
478
454f18a9 479 /* Check the version */
a51ed7d6 480 rdmsrl(HV_X64_MSR_SVERSION, version);
3e7ee490
HJ
481
482 DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
483
454f18a9 484 /* TODO: Handle SMP */
3e7ee490
HJ
485 if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID)
486 {
487 DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since it is already set.");
488
a51ed7d6
GKH
489 rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
490 rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
3e7ee490
HJ
491
492 DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx", simp.AsUINT64, siefp.AsUINT64);
493
454f18a9 494 /* Determine if we are running on xenlinux (ie x2v shim) or native linux */
a51ed7d6 495 rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
3e7ee490
HJ
496 if (guestID == HV_LINUX_GUEST_ID)
497 {
fa56d361
GKH
498 gHvContext.synICMessagePage[0] = phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
499 gHvContext.synICEventPage[0] = phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
3e7ee490
HJ
500 }
501 else
502 {
503 DPRINT_ERR(VMBUS, "unknown guest id!!");
504 goto Cleanup;
505 }
506 DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", gHvContext.synICMessagePage[0], gHvContext.synICEventPage[0]);
507 }
508 else
509 {
bfc30aae 510 gHvContext.synICMessagePage[0] = osd_PageAlloc(1);
3e7ee490
HJ
511 if (gHvContext.synICMessagePage[0] == NULL)
512 {
513 DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!");
514 goto Cleanup;
515 }
516
bfc30aae 517 gHvContext.synICEventPage[0] = osd_PageAlloc(1);
3e7ee490
HJ
518 if (gHvContext.synICEventPage[0] == NULL)
519 {
520 DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!");
521 goto Cleanup;
522 }
523
454f18a9 524 /* Setup the Synic's message page */
a51ed7d6 525 rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
3e7ee490 526 simp.SimpEnabled = 1;
fa56d361 527 simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) >> PAGE_SHIFT;
3e7ee490
HJ
528
529 DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64);
530
a51ed7d6 531 wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
3e7ee490 532
454f18a9 533 /* Setup the Synic's event page */
a51ed7d6 534 rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
3e7ee490 535 siefp.SiefpEnabled = 1;
fa56d361 536 siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) >> PAGE_SHIFT;
3e7ee490
HJ
537
538 DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64);
539
a51ed7d6 540 wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
3e7ee490 541 }
454f18a9 542 /* Setup the interception SINT. */
a51ed7d6 543 /* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
454f18a9
BP
544 /* interceptionSint.AsUINT64); */
545
546 /* Setup the shared SINT. */
a51ed7d6 547 rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
3e7ee490
HJ
548
549 sharedSint.AsUINT64 = 0;
454f18a9
BP
550 sharedSint.Vector = irqVector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
551 sharedSint.Masked = false;
552 sharedSint.AutoEoi = true;
3e7ee490
HJ
553
554 DPRINT_DBG(VMBUS, "HV_X64_MSR_SINT1 msr set to: %llx", sharedSint.AsUINT64);
555
a51ed7d6 556 wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
3e7ee490 557
454f18a9 558 /* Enable the global synic bit */
a51ed7d6 559 rdmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
3e7ee490
HJ
560 sctrl.Enable = 1;
561
a51ed7d6 562 wrmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
3e7ee490 563
0e727613 564 gHvContext.SynICInitialized = true;
3e7ee490
HJ
565
566 DPRINT_EXIT(VMBUS);
567
568 return ret;
569
570Cleanup:
571 ret = -1;
572
573 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
574 {
575 if (gHvContext.synICEventPage[0])
576 {
bfc30aae 577 osd_PageFree(gHvContext.synICEventPage[0],1);
3e7ee490
HJ
578 }
579
580 if (gHvContext.synICMessagePage[0])
581 {
bfc30aae 582 osd_PageFree(gHvContext.synICMessagePage[0], 1);
3e7ee490
HJ
583 }
584 }
585
586 DPRINT_EXIT(VMBUS);
587
588 return ret;
589
590}
591
592/*++
593
594Name:
595 HvSynicCleanup()
596
597Description:
598 Cleanup routine for HvSynicInit().
599
600--*/
98d9fac4 601void HvSynicCleanup(void)
3e7ee490
HJ
602{
603 HV_SYNIC_SINT sharedSint;
604 HV_SYNIC_SIMP simp;
605 HV_SYNIC_SIEFP siefp;
606
607 DPRINT_ENTER(VMBUS);
608
609 if (!gHvContext.SynICInitialized)
610 {
611 DPRINT_EXIT(VMBUS);
612 return;
613 }
614
a51ed7d6 615 rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
3e7ee490
HJ
616
617 sharedSint.Masked = 1;
618
454f18a9 619 /* Disable the interrupt */
a51ed7d6 620 wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
3e7ee490 621
454f18a9
BP
622 /*
623 * Disable and free the resources only if we are running as
624 * native linux since in xenlinux, we are sharing the
625 * resources with the x2v shim
626 */
3e7ee490
HJ
627 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
628 {
a51ed7d6 629 rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
3e7ee490
HJ
630 simp.SimpEnabled = 0;
631 simp.BaseSimpGpa = 0;
632
a51ed7d6 633 wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
3e7ee490 634
a51ed7d6 635 rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
3e7ee490
HJ
636 siefp.SiefpEnabled = 0;
637 siefp.BaseSiefpGpa = 0;
638
a51ed7d6 639 wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
3e7ee490 640
bfc30aae
GKH
641 osd_PageFree(gHvContext.synICMessagePage[0], 1);
642 osd_PageFree(gHvContext.synICEventPage[0], 1);
3e7ee490
HJ
643 }
644
645 DPRINT_EXIT(VMBUS);
646}
647
648
454f18a9 649/* eof */