blob: c228e6053f656196baec8eda8e52c90b35758899 [file] [log] [blame]
Hank Janssen3e7ee492009-07-13 16:02:34 -07001/*
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
Greg Kroah-Hartmana0086dc2009-08-17 17:22:08 -070024#include <linux/kernel.h>
25#include <linux/mm.h>
Bill Pembertonb7c947f2009-07-29 17:00:13 -040026#include <linux/vmalloc.h>
Greg Kroah-Hartman09d50ff2009-07-13 17:09:34 -070027#include "include/logging.h"
Hank Janssen3e7ee492009-07-13 16:02:34 -070028#include "VmbusPrivate.h"
29
Bill Pemberton454f18a2009-07-27 16:47:24 -040030/* Globals */
Hank Janssen3e7ee492009-07-13 16:02:34 -070031
Bill Pemberton454f18a2009-07-27 16:47:24 -040032/* The one and only */
Hank Janssen3e7ee492009-07-13 16:02:34 -070033HV_CONTEXT gHvContext={
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -070034 .SynICInitialized = false,
Hank Janssen3e7ee492009-07-13 16:02:34 -070035 .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;
Greg Kroah-Hartmanf931a702009-07-29 15:37:12 -070066 cpuid(op, &eax, &ebx, &ecx, &edx);
Hank Janssen3e7ee492009-07-13 16:02:34 -070067
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
Bill Pemberton454f18a2009-07-27 16:47:24 -040093 /*
94 * Its assumed that this is called after confirming that Viridian
95 * is present. Query id and revision.
96 */
97
Hank Janssen3e7ee492009-07-13 16:02:34 -070098
99 eax = 0;
100 ebx = 0;
101 ecx = 0;
102 edx = 0;
103 op = HvCpuIdFunctionHvVendorAndMaxFunction;
Greg Kroah-Hartmanf931a702009-07-29 15:37:12 -0700104 cpuid(op, &eax, &ebx, &ecx, &edx);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700105
106 DPRINT_INFO(VMBUS, "Vendor ID: %c%c%c%c%c%c%c%c%c%c%c%c",
Bill Pemberton454f18a2009-07-27 16:47:24 -0400107 (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));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700119
120 maxLeaf = eax;
121 eax = 0;
122 ebx = 0;
123 ecx = 0;
124 edx = 0;
125 op = HvCpuIdFunctionHvInterface;
Greg Kroah-Hartmanf931a702009-07-29 15:37:12 -0700126 cpuid(op, &eax, &ebx, &ecx, &edx);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700127
128 DPRINT_INFO(VMBUS, "Interface ID: %c%c%c%c",
Bill Pemberton454f18a2009-07-27 16:47:24 -0400129 (eax & 0xFF),
130 ((eax >> 8) & 0xFF),
131 ((eax >> 16) & 0xFF),
132 ((eax >> 24) & 0xFF));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700133
134 if (maxLeaf >= HvCpuIdFunctionMsHvVersion) {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400135 eax = 0;
136 ebx = 0;
137 ecx = 0;
138 edx = 0;
139 op = HvCpuIdFunctionMsHvVersion;
Greg Kroah-Hartmanf931a702009-07-29 15:37:12 -0700140 cpuid(op, &eax, &ebx, &ecx, &edx);
Bill Pemberton454f18a2009-07-27 16:47:24 -0400141 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);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700148 }
149 return maxLeaf;
150}
151
152
153/*++
154
155Name:
156 HvDoHypercall()
157
158Description:
159 Invoke the specified hypercall
160
161--*/
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700162static u64
Hank Janssen3e7ee492009-07-13 16:02:34 -0700163HvDoHypercall (
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700164 u64 Control,
Hank Janssen3e7ee492009-07-13 16:02:34 -0700165 void* Input,
166 void* Output
167 )
168{
Greg Kroah-Hartman530cf202009-07-16 22:31:15 -0700169#ifdef CONFIG_X86_64
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700170 u64 hvStatus=0;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700171 u64 inputAddress = (Input)? virt_to_phys(Input) : 0;
172 u64 outputAddress = (Output)? virt_to_phys(Output) : 0;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700173 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
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700192 u32 controlHi = Control >> 32;
193 u32 controlLo = Control & 0xFFFFFFFF;
194 u32 hvStatusHi = 1;
195 u32 hvStatusLo = 1;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700196 u64 inputAddress = (Input) ? virt_to_phys(Input) : 0;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700197 u32 inputAddressHi = inputAddress >> 32;
198 u32 inputAddressLo = inputAddress & 0xFFFFFFFF;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700199 u64 outputAddress = (Output) ? virt_to_phys(Output) : 0;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700200 u32 outputAddressHi = outputAddress >> 32;
201 u32 outputAddressLo = outputAddress & 0xFFFFFFFF;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700202 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
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700212 DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatusLo | ((u64)hvStatusHi << 32));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700213
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700214 return (hvStatusLo | ((u64)hvStatusHi << 32));
Bill Pemberton454f18a2009-07-27 16:47:24 -0400215#endif /* x86_64 */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700216}
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--*/
Greg Kroah-Hartman98d9fac2009-08-17 17:20:55 -0700228int HvInit (void)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700229{
230 int ret=0;
231 int maxLeaf;
232 HV_X64_MSR_HYPERCALL_CONTENTS hypercallMsr;
Greg Kroah-Hartman949cada2009-07-29 09:06:51 -0700233 void *virtAddr = NULL;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700234
235 DPRINT_ENTER(VMBUS);
236
Bill Pemberton44f357f2009-07-28 13:46:26 -0400237 memset(gHvContext.synICEventPage, 0, sizeof(void *) * MAX_NUM_CPUS);
238 memset(gHvContext.synICMessagePage, 0, sizeof(void *) * MAX_NUM_CPUS);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700239
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();
Bill Pemberton454f18a2009-07-27 16:47:24 -0400249 /* HvQueryHypervisorFeatures(maxLeaf); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700250
Bill Pemberton454f18a2009-07-27 16:47:24 -0400251 /* Determine if we are running on xenlinux (ie x2v shim) or native linux */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700252 rdmsrl(HV_X64_MSR_GUEST_OS_ID, gHvContext.GuestId);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700253 if (gHvContext.GuestId == 0)
254 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400255 /* Write our OS info */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700256 wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700257
258 gHvContext.GuestId = HV_LINUX_GUEST_ID;
259 }
260
Bill Pemberton454f18a2009-07-27 16:47:24 -0400261 /* See if the hypercall page is already set */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700262 rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700263 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
264 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400265 /* Allocate the hypercall page memory */
Greg Kroah-Hartmanbfc30aae2009-07-29 15:40:18 -0700266 /* virtAddr = osd_PageAlloc(1); */
267 virtAddr = osd_VirtualAllocExec(PAGE_SIZE);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700268
269 if (!virtAddr)
270 {
271 DPRINT_ERR(VMBUS, "unable to allocate hypercall page!!");
272 goto Cleanup;
273 }
274
275 hypercallMsr.Enable = 1;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700276 /* hypercallMsr.GuestPhysicalAddress = virt_to_phys(virtAddr) >> PAGE_SHIFT; */
277 hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr);
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700278 wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700279
Bill Pemberton454f18a2009-07-27 16:47:24 -0400280 /* Confirm that hypercall page did get setup. */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700281 hypercallMsr.AsUINT64 = 0;
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700282 rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700283 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
Greg Kroah-Hartman2701f682009-07-16 12:36:37 -0700297 DPRINT_INFO(VMBUS, "Hypercall page VA=%p, PA=0x%0llx",
298 gHvContext.HypercallPage,
299 (u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700300
Bill Pemberton454f18a2009-07-27 16:47:24 -0400301 /* Setup the global signal event param for the signal event hypercall */
Greg Kroah-Hartmane40d37c2009-07-15 12:47:22 -0700302 gHvContext.SignalEventBuffer = kmalloc(sizeof(HV_INPUT_SIGNAL_EVENT_BUFFER), GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700303 if (!gHvContext.SignalEventBuffer)
304 {
305 goto Cleanup;
306 }
307
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700308 gHvContext.SignalEventParam = (PHV_INPUT_SIGNAL_EVENT)(ALIGN_UP((unsigned long)gHvContext.SignalEventBuffer, HV_HYPERCALL_PARAM_ALIGN));
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700309 gHvContext.SignalEventParam->ConnectionId.Asu32 = 0;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700310 gHvContext.SignalEventParam->ConnectionId.u.Id = VMBUS_EVENT_CONNECTION_ID;
311 gHvContext.SignalEventParam->FlagNumber = 0;
312 gHvContext.SignalEventParam->RsvdZ = 0;
313
Bill Pemberton454f18a2009-07-27 16:47:24 -0400314 /* DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId()); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700315
316 DPRINT_EXIT(VMBUS);
317
318 return ret;
319
320Cleanup:
321 if (virtAddr)
322 {
323 if (hypercallMsr.Enable)
324 {
325 hypercallMsr.AsUINT64 = 0;
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700326 wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700327 }
328
Bill Pembertonb7c947f2009-07-29 17:00:13 -0400329 vfree(virtAddr);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700330 }
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--*/
Greg Kroah-Hartman98d9fac2009-08-17 17:20:55 -0700347void HvCleanup (void)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700348{
349 HV_X64_MSR_HYPERCALL_CONTENTS hypercallMsr;
350
351 DPRINT_ENTER(VMBUS);
352
353 if (gHvContext.SignalEventBuffer)
354 {
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700355 kfree(gHvContext.SignalEventBuffer);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700356 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;
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700365 wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
Bill Pembertonb7c947f2009-07-29 17:00:13 -0400366 vfree(gHvContext.HypercallPage);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700367 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--*/
Greg Kroah-Hartman98d9fac2009-08-17 17:20:55 -0700386HV_STATUS HvPostMessage(
Hank Janssen3e7ee492009-07-13 16:02:34 -0700387 HV_CONNECTION_ID connectionId,
388 HV_MESSAGE_TYPE messageType,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700389 void * payload,
Greg Kroah-Hartman45635d92009-07-14 15:14:20 -0700390 size_t payloadSize
Hank Janssen3e7ee492009-07-13 16:02:34 -0700391 )
392{
393 struct alignedInput {
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700394 u64 alignment8;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700395 HV_INPUT_POST_MESSAGE msg;
396 };
397
398 PHV_INPUT_POST_MESSAGE alignedMsg;
399 HV_STATUS status;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700400 unsigned long addr;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700401
402 if (payloadSize > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
403 {
404 return -1;
405 }
406
Greg Kroah-Hartman0a72f3c2009-07-15 12:48:01 -0700407 addr = (unsigned long)kmalloc(sizeof(struct alignedInput), GFP_ATOMIC);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700408
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
Greg Kroah-Hartman949cada2009-07-29 09:06:51 -0700421 status = HvDoHypercall(HvCallPostMessage, alignedMsg, NULL) & 0xFFFF;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700422
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700423 kfree((void*)addr);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700424
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--*/
Greg Kroah-Hartman98d9fac2009-08-17 17:20:55 -0700439HV_STATUS HvSignalEvent(void)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700440{
441 HV_STATUS status;
442
Greg Kroah-Hartman949cada2009-07-29 09:06:51 -0700443 status = HvDoHypercall(HvCallSignalEvent, gHvContext.SignalEventParam, NULL) & 0xFFFF;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700444
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--*/
Greg Kroah-Hartman98d9fac2009-08-17 17:20:55 -0700460int HvSynicInit (u32 irqVector)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700461{
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700462 u64 version;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700463 HV_SYNIC_SIMP simp;
464 HV_SYNIC_SIEFP siefp;
465 HV_SYNIC_SINT sharedSint;
466 HV_SYNIC_SCONTROL sctrl;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700467 u64 guestID;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700468 int ret=0;
469
470 DPRINT_ENTER(VMBUS);
471
472 if (!gHvContext.HypercallPage)
473 {
474 DPRINT_EXIT(VMBUS);
475 return ret;
476 }
477
Bill Pemberton454f18a2009-07-27 16:47:24 -0400478 /* Check the version */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700479 rdmsrl(HV_X64_MSR_SVERSION, version);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700480
481 DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
482
Bill Pemberton454f18a2009-07-27 16:47:24 -0400483 /* TODO: Handle SMP */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700484 if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID)
485 {
486 DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since it is already set.");
487
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700488 rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
489 rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700490
491 DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx", simp.AsUINT64, siefp.AsUINT64);
492
Bill Pemberton454f18a2009-07-27 16:47:24 -0400493 /* Determine if we are running on xenlinux (ie x2v shim) or native linux */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700494 rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700495 if (guestID == HV_LINUX_GUEST_ID)
496 {
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700497 gHvContext.synICMessagePage[0] = phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
498 gHvContext.synICEventPage[0] = phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700499 }
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 {
Greg Kroah-Hartmanbfc30aae2009-07-29 15:40:18 -0700509 gHvContext.synICMessagePage[0] = osd_PageAlloc(1);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700510 if (gHvContext.synICMessagePage[0] == NULL)
511 {
512 DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!");
513 goto Cleanup;
514 }
515
Greg Kroah-Hartmanbfc30aae2009-07-29 15:40:18 -0700516 gHvContext.synICEventPage[0] = osd_PageAlloc(1);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700517 if (gHvContext.synICEventPage[0] == NULL)
518 {
519 DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!");
520 goto Cleanup;
521 }
522
Bill Pemberton454f18a2009-07-27 16:47:24 -0400523 /* Setup the Synic's message page */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700524 rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700525 simp.SimpEnabled = 1;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700526 simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) >> PAGE_SHIFT;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700527
528 DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64);
529
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700530 wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700531
Bill Pemberton454f18a2009-07-27 16:47:24 -0400532 /* Setup the Synic's event page */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700533 rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700534 siefp.SiefpEnabled = 1;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700535 siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) >> PAGE_SHIFT;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700536
537 DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64);
538
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700539 wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700540 }
Bill Pemberton454f18a2009-07-27 16:47:24 -0400541 /* Setup the interception SINT. */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700542 /* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
Bill Pemberton454f18a2009-07-27 16:47:24 -0400543 /* interceptionSint.AsUINT64); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700544
Bill Pemberton454f18a2009-07-27 16:47:24 -0400545 /* Setup the shared SINT. */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700546 rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700547
548 sharedSint.AsUINT64 = 0;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400549 sharedSint.Vector = irqVector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
550 sharedSint.Masked = false;
551 sharedSint.AutoEoi = true;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700552
553 DPRINT_DBG(VMBUS, "HV_X64_MSR_SINT1 msr set to: %llx", sharedSint.AsUINT64);
554
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700555 wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700556
Bill Pemberton454f18a2009-07-27 16:47:24 -0400557 /* Enable the global synic bit */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700558 rdmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700559 sctrl.Enable = 1;
560
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700561 wrmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700562
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700563 gHvContext.SynICInitialized = true;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700564
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 {
Greg Kroah-Hartmanbfc30aae2009-07-29 15:40:18 -0700576 osd_PageFree(gHvContext.synICEventPage[0],1);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700577 }
578
579 if (gHvContext.synICMessagePage[0])
580 {
Greg Kroah-Hartmanbfc30aae2009-07-29 15:40:18 -0700581 osd_PageFree(gHvContext.synICMessagePage[0], 1);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700582 }
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--*/
Greg Kroah-Hartman98d9fac2009-08-17 17:20:55 -0700600void HvSynicCleanup(void)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700601{
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
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700614 rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700615
616 sharedSint.Masked = 1;
617
Bill Pemberton454f18a2009-07-27 16:47:24 -0400618 /* Disable the interrupt */
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700619 wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700620
Bill Pemberton454f18a2009-07-27 16:47:24 -0400621 /*
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 */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700626 if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
627 {
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700628 rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700629 simp.SimpEnabled = 0;
630 simp.BaseSimpGpa = 0;
631
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700632 wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700633
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700634 rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700635 siefp.SiefpEnabled = 0;
636 siefp.BaseSiefpGpa = 0;
637
Greg Kroah-Hartmana51ed7d2009-08-17 17:20:02 -0700638 wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700639
Greg Kroah-Hartmanbfc30aae2009-07-29 15:40:18 -0700640 osd_PageFree(gHvContext.synICMessagePage[0], 1);
641 osd_PageFree(gHvContext.synICEventPage[0], 1);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700642 }
643
644 DPRINT_EXIT(VMBUS);
645}
646
647
Bill Pemberton454f18a2009-07-27 16:47:24 -0400648/* eof */