win-pvdrivers

view xenpci/xenpci_fdo.c @ 607:c2aea3e060a7

Missed a line in cut&paste in previous checksum fix
author James Harper <james.harper@bendigoit.com.au>
date Sun Jul 05 21:06:26 2009 +1000 (2009-07-05)
parents f118fcbe5ca8
children bddc14051767
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
21 #include <stdlib.h>
22 #include <aux_klib.h>
24 #define SYSRQ_PATH "control/sysrq"
25 #define SHUTDOWN_PATH "control/shutdown"
26 #define BALLOON_PATH "memory/target"
28 static VOID
29 XenPci_MapHalThenPatchKernel(PXENPCI_DEVICE_DATA xpdd)
30 {
31 NTSTATUS status;
32 PAUX_MODULE_EXTENDED_INFO amei;
33 ULONG module_info_buffer_size;
34 ULONG i;
36 FUNCTION_ENTER();
38 status = AuxKlibInitialize();
39 amei = NULL;
40 /* buffer size could change between requesting and allocating - need to loop until we are successful */
41 while ((status = AuxKlibQueryModuleInformation(&module_info_buffer_size, sizeof(AUX_MODULE_EXTENDED_INFO), amei)) == STATUS_BUFFER_TOO_SMALL || amei == NULL)
42 {
43 if (amei != NULL)
44 ExFreePoolWithTag(amei, XENPCI_POOL_TAG);
45 amei = ExAllocatePoolWithTag(NonPagedPool, module_info_buffer_size, XENPCI_POOL_TAG);
46 }
48 KdPrint((__DRIVER_NAME " AuxKlibQueryModuleInformation = %d\n", status));
49 for (i = 0; i < module_info_buffer_size / sizeof(AUX_MODULE_EXTENDED_INFO); i++)
50 {
51 if (strcmp((PCHAR)amei[i].FullPathName + amei[i].FileNameOffset, "hal.dll") == 0)
52 {
53 KdPrint((__DRIVER_NAME " hal.dll found at %p - %p\n",
54 amei[i].BasicInfo.ImageBase,
55 ((PUCHAR)amei[i].BasicInfo.ImageBase) + amei[i].ImageSize));
56 XenPci_PatchKernel(xpdd, amei[i].BasicInfo.ImageBase, amei[i].ImageSize);
57 }
58 }
59 ExFreePoolWithTag(amei, XENPCI_POOL_TAG);
60 FUNCTION_EXIT();
61 }
63 #if 0
64 PMDL
65 XenPCI_AllocMMIO(WDFDEVICE device, ULONG len)
66 {
67 PMDL mdl = ExAllocatePoolWithTag(NonPagedPool, MmSizeOfMdl(0, len), XENPCI_POOL_TAG);
68 PVOID va = MmAllocateMappingAddress(len, XENPCI_POOL_TAG);
70 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, len);
72 }
73 #endif
75 /*
76 * Alloc MMIO from the device's MMIO region. There is no corresponding free() fn
77 */
78 PHYSICAL_ADDRESS
79 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len)
80 {
81 PHYSICAL_ADDRESS addr;
83 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
85 addr = xpdd->platform_mmio_addr;
86 addr.QuadPart += xpdd->platform_mmio_alloc;
87 xpdd->platform_mmio_alloc += len;
89 ASSERT(xpdd->platform_mmio_alloc <= xpdd->platform_mmio_len);
91 return addr;
92 }
94 extern ULONG tpr_patch_requested;
96 NTSTATUS
97 XenPci_EvtDeviceQueryRemove(WDFDEVICE device)
98 {
99 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
100 NTSTATUS status;
102 FUNCTION_ENTER();
103 if (xpdd->removable)
104 status = STATUS_SUCCESS;
105 else
106 status = STATUS_UNSUCCESSFUL;
107 FUNCTION_EXIT();
108 return status;
109 }
111 static NTSTATUS
112 XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
113 {
114 struct xen_add_to_physmap xatp;
115 int ret;
117 FUNCTION_ENTER();
119 hvm_get_stubs(xpdd);
121 if (!xpdd->shared_info_area)
122 {
123 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
124 /* this should be safe as this part will never be called on resume where IRQL == HIGH_LEVEL */
125 xpdd->shared_info_area_unmapped = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
126 xpdd->shared_info_area = MmMapIoSpace(xpdd->shared_info_area_unmapped,
127 PAGE_SIZE, MmNonCached);
128 }
129 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", xpdd->shared_info_area_unmapped.QuadPart));
130 xatp.domid = DOMID_SELF;
131 xatp.idx = 0;
132 xatp.space = XENMAPSPACE_shared_info;
133 xatp.gpfn = (xen_pfn_t)(xpdd->shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
134 KdPrint((__DRIVER_NAME " gpfn = %x\n", xatp.gpfn));
135 ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
136 KdPrint((__DRIVER_NAME " hypervisor memory op (XENMAPSPACE_shared_info) ret = %d\n", ret));
138 FUNCTION_EXIT();
140 return STATUS_SUCCESS;
141 }
143 static NTSTATUS
144 XenPci_Resume(PXENPCI_DEVICE_DATA xpdd)
145 {
146 return XenPci_Init(xpdd);
147 }
149 static VOID
150 XenPci_SysrqHandler(char *path, PVOID context)
151 {
152 PXENPCI_DEVICE_DATA xpdd = context;
153 char *value;
154 char letter;
155 char *res;
157 UNREFERENCED_PARAMETER(path);
159 FUNCTION_ENTER();
161 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
163 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
165 if (value != NULL && strlen(value) != 0)
166 {
167 letter = *value;
168 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
169 if (res)
170 {
171 KdPrint(("Error writing sysrq path\n"));
172 XenPci_FreeMem(res);
173 return;
174 }
175 }
176 else
177 {
178 letter = 0;
179 }
181 if (value != NULL)
182 {
183 XenPci_FreeMem(value);
184 }
186 switch (letter)
187 {
188 case 0:
189 break;
190 case 'B': /* cause a bug check */
191 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
192 break;
193 default:
194 KdPrint((" Unhandled sysrq letter %c\n", letter));
195 break;
196 }
198 FUNCTION_EXIT();
199 }
201 #if 0
202 static VOID
203 XenPci_PrintPendingInterrupts()
204 {
205 PULONG bitmap = (PULONG)0xFFFE0200;
206 int i;
207 int j;
208 ULONG value;
210 for (i = 0; i < 8; i++)
211 {
212 value = bitmap[(7 - i) * 4];
213 if (value)
214 {
215 for (j = 0; j < 32; j++)
216 {
217 if ((value >> j) & 1)
218 KdPrint((" Interrupt pending on pin %d\n", ((7 - i) << 5) | j));
219 }
220 }
221 }
222 }
223 #endif
225 #define BALLOON_UNIT_PAGES (BALLOON_UNITS >> PAGE_SHIFT)
227 static VOID
228 XenPci_BalloonThreadProc(PVOID StartContext)
229 {
230 PXENPCI_DEVICE_DATA xpdd = StartContext;
231 ULONG new_target = xpdd->current_memory;
232 LARGE_INTEGER timeout;
233 PLARGE_INTEGER ptimeout;
234 PMDL head = NULL;
235 // use the memory_op(unsigned int op, void *arg) hypercall to adjust memory
236 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
238 FUNCTION_ENTER();
240 for(;;)
241 {
242 if (xpdd->current_memory != new_target)
243 {
244 timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
245 ptimeout = &timeout;
246 }
247 else
248 {
249 ptimeout = NULL;
250 }
251 KeWaitForSingleObject(&xpdd->balloon_event, Executive, KernelMode, FALSE, ptimeout);
252 //TODO: initiate shutdown here
253 KdPrint((__DRIVER_NAME " Got balloon event, current = %d, target = %d\n", xpdd->current_memory, xpdd->target_memory));
254 /* not really worried about races here, but cache target so we only read it once */
255 new_target = xpdd->target_memory;
256 // perform some sanity checks on target_memory
257 // make sure target <= initial
258 // make sure target > some % of initial
260 if (xpdd->current_memory == new_target)
261 {
262 KdPrint((__DRIVER_NAME " No change to memory\n"));
263 continue;
264 }
265 else if (xpdd->current_memory < new_target)
266 {
267 PMDL mdl;
268 KdPrint((__DRIVER_NAME " Trying to take %d MB from Xen\n", new_target - xpdd->current_memory));
269 while ((mdl = head) != NULL && xpdd->current_memory < new_target)
270 {
271 head = mdl->Next;
272 mdl->Next = NULL;
273 MmFreePagesFromMdl(mdl);
274 ExFreePool(mdl);
275 xpdd->current_memory++;
276 }
277 }
278 else
279 {
280 KdPrint((__DRIVER_NAME " Trying to give %d MB to Xen\n", xpdd->current_memory - new_target));
281 while (xpdd->current_memory > new_target)
282 {
283 PHYSICAL_ADDRESS alloc_low;
284 PHYSICAL_ADDRESS alloc_high;
285 PHYSICAL_ADDRESS alloc_skip;
286 PMDL mdl;
287 alloc_low.QuadPart = 0;
288 alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
289 alloc_skip.QuadPart = 0;
290 mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS);
291 if (!mdl)
292 {
293 KdPrint((__DRIVER_NAME " Allocation failed - try again in 1 second\n"));
294 break;
295 }
296 else
297 {
298 if (head)
299 {
300 mdl->Next = head;
301 head = mdl;
302 }
303 else
304 {
305 head = mdl;
306 }
307 xpdd->current_memory--;
308 }
309 }
310 }
311 }
312 //FUNCTION_EXIT();
313 }
315 static VOID
316 XenPci_BalloonHandler(char *Path, PVOID Data)
317 {
318 WDFDEVICE device = Data;
319 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
320 char *value;
321 xenbus_transaction_t xbt;
322 int retry;
324 UNREFERENCED_PARAMETER(Path);
326 FUNCTION_ENTER();
328 XenBus_StartTransaction(xpdd, &xbt);
330 XenBus_Read(xpdd, XBT_NIL, BALLOON_PATH, &value);
332 if (atoi(value) > 0)
333 xpdd->target_memory = atoi(value) >> 10; /* convert to MB */
335 KdPrint((__DRIVER_NAME " target memory value = %d (%s)\n", xpdd->target_memory, value));
337 XenBus_EndTransaction(xpdd, xbt, 0, &retry);
339 XenPci_FreeMem(value);
341 KeSetEvent(&xpdd->balloon_event, IO_NO_INCREMENT, FALSE);
343 // start a thread to allocate memory up to the required amount
345 FUNCTION_EXIT();
346 }
348 static VOID
349 XenPci_Suspend0(PVOID context)
350 {
351 PXENPCI_DEVICE_DATA xpdd = context;
352 ULONG cancelled;
354 FUNCTION_ENTER();
356 GntTbl_Suspend(xpdd);
358 cancelled = hvm_shutdown(xpdd, SHUTDOWN_suspend);
359 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
361 if (qemu_filtered_by_qemu)
362 {
363 XenPci_HideQemuDevices();
364 ASSERT(qemu_filtered_by_qemu);
365 }
367 XenPci_Resume(xpdd);
368 GntTbl_Resume(xpdd);
369 EvtChn_Resume(xpdd); /* this enables interrupts again too */
371 FUNCTION_EXIT();
372 }
374 static VOID
375 XenPci_SuspendN(PVOID context)
376 {
377 UNREFERENCED_PARAMETER(context);
379 FUNCTION_ENTER();
380 KdPrint((__DRIVER_NAME " doing nothing on cpu N\n"));
381 FUNCTION_EXIT();
382 }
384 /* Called at PASSIVE_LEVEL */
385 static VOID DDKAPI
386 XenPci_SuspendResume(WDFWORKITEM workitem)
387 {
388 NTSTATUS status;
389 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
390 WDFDEVICE device = WdfWorkItemGetParentObject(workitem);
391 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
392 WDFCHILDLIST child_list = WdfFdoGetDefaultChildList(device);
393 WDF_CHILD_LIST_ITERATOR child_iterator;
394 WDFDEVICE child_device;
396 FUNCTION_ENTER();
398 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
399 {
400 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
401 KeMemoryBarrier();
403 WDF_CHILD_LIST_ITERATOR_INIT(&child_iterator, WdfRetrievePresentChildren);
404 WdfChildListBeginIteration(child_list, &child_iterator);
405 while ((status = WdfChildListRetrieveNextDevice(child_list, &child_iterator, &child_device, NULL)) == STATUS_SUCCESS)
406 {
407 KdPrint((__DRIVER_NAME " Suspending child\n"));
408 XenPci_Pdo_Suspend(child_device);
409 }
410 KdPrint((__DRIVER_NAME " WdfChildListRetrieveNextDevice = %08x, STATUS_NO_MORE_ENTRIES = %08x\n", status, STATUS_NO_MORE_ENTRIES));
411 WdfChildListEndIteration(child_list, &child_iterator);
413 XenBus_Suspend(xpdd);
414 EvtChn_Suspend(xpdd);
415 XenPci_HighSync(XenPci_Suspend0, XenPci_SuspendN, xpdd);
417 xpdd->suspend_state = SUSPEND_STATE_RESUMING;
418 XenBus_Resume(xpdd);
420 WdfChildListBeginIteration(child_list, &child_iterator);
421 while ((status = WdfChildListRetrieveNextDevice(child_list, &child_iterator, &child_device, NULL)) == STATUS_SUCCESS)
422 {
423 KdPrint((__DRIVER_NAME " Resuming child\n"));
424 XenPci_Pdo_Resume(child_device);
425 }
426 KdPrint((__DRIVER_NAME " WdfChildListRetrieveNextDevice = %08x, STATUS_NO_MORE_ENTRIES = %08x\n", status, STATUS_NO_MORE_ENTRIES));
427 WdfChildListEndIteration(child_list, &child_iterator);
429 xpdd->suspend_state = SUSPEND_STATE_NONE;
430 }
431 FUNCTION_EXIT();
432 }
434 static void
435 XenPci_ShutdownHandler(char *path, PVOID context)
436 {
437 NTSTATUS status;
438 WDFDEVICE device = context;
439 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
440 char *res;
441 char *value;
442 //KIRQL old_irql;
443 WDF_OBJECT_ATTRIBUTES attributes;
444 WDF_WORKITEM_CONFIG workitem_config;
445 WDFWORKITEM workitem;
447 UNREFERENCED_PARAMETER(path);
449 FUNCTION_ENTER();
451 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
452 if (res)
453 {
454 KdPrint(("Error reading shutdown path - %s\n", res));
455 XenPci_FreeMem(res);
456 FUNCTION_EXIT();
457 return;
458 }
460 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
462 if (strlen(value) && strcmp(value, "suspend") == 0)
463 {
464 {
465 KdPrint((__DRIVER_NAME " Suspend detected\n"));
466 /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
467 WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenPci_SuspendResume);
468 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
469 attributes.ParentObject = device;
470 status = WdfWorkItemCreate(&workitem_config, &attributes, &workitem);
471 // TODO: check status here
472 WdfWorkItemEnqueue(workitem);
473 }
474 }
476 XenPci_FreeMem(value);
478 FUNCTION_EXIT();
479 }
481 static VOID
482 XenPci_DeviceWatchHandler(char *path, PVOID context)
483 {
484 char **bits;
485 int count;
486 char *err;
487 char *value;
488 PXENPCI_DEVICE_DATA xpdd = context;
490 //FUNCTION_ENTER();
492 bits = SplitString(path, '/', 4, &count);
493 if (count == 3)
494 {
495 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
496 if (err)
497 {
498 /* obviously path no longer exists, in which case the removal is being taken care of elsewhere and we shouldn't invalidate now */
499 XenPci_FreeMem(err);
500 }
501 else
502 {
503 XenPci_FreeMem(value);
504 /* we probably have to be a bit smarter here and do nothing if xenpci isn't running yet */
505 KdPrint((__DRIVER_NAME " Rescanning child list\n"));
506 XenPci_EvtChildListScanForChildren(xpdd->child_list);
507 }
508 }
509 FreeSplitString(bits, count);
511 //FUNCTION_EXIT();
512 }
514 NTSTATUS
515 XenPci_EvtDevicePrepareHardware (WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
516 {
517 NTSTATUS status = STATUS_SUCCESS;
518 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
519 PCM_PARTIAL_RESOURCE_DESCRIPTOR raw_descriptor, translated_descriptor;
520 ULONG i;
522 FUNCTION_ENTER();
524 ASSERT(WdfCmResourceListGetCount(resources_raw) == WdfCmResourceListGetCount(resources_translated));
526 for (i = 0; i < WdfCmResourceListGetCount(resources_raw); i++)
527 {
528 raw_descriptor = WdfCmResourceListGetDescriptor(resources_raw, i);
529 translated_descriptor = WdfCmResourceListGetDescriptor(resources_translated, i);
530 switch (raw_descriptor->Type) {
531 case CmResourceTypePort:
532 KdPrint((__DRIVER_NAME " IoPort Address(%x) Length: %d\n", translated_descriptor->u.Port.Start.LowPart, translated_descriptor->u.Port.Length));
533 xpdd->platform_ioport_addr = translated_descriptor->u.Port.Start.LowPart;
534 xpdd->platform_ioport_len = translated_descriptor->u.Port.Length;
535 break;
536 case CmResourceTypeMemory:
537 KdPrint((__DRIVER_NAME " Memory mapped CSR:(%x:%x) Length:(%d)\n", translated_descriptor->u.Memory.Start.LowPart, translated_descriptor->u.Memory.Start.HighPart, translated_descriptor->u.Memory.Length));
538 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", translated_descriptor->Flags));
539 #if 0
540 mmio_freelist_free = 0;
541 for (j = 0; j < translated_descriptor->u.Memory.Length >> PAGE_SHIFT; j++)
542 put_mmio_on_freelist((xpdd->platform_mmio_addr >> PAGE_SHIFT) + j);
543 #endif
544 xpdd->platform_mmio_addr = translated_descriptor->u.Memory.Start;
545 xpdd->platform_mmio_len = translated_descriptor->u.Memory.Length;
546 xpdd->platform_mmio_flags = translated_descriptor->Flags;
547 break;
548 case CmResourceTypeInterrupt:
549 xpdd->irq_level = (KIRQL)translated_descriptor->u.Interrupt.Level;
550 xpdd->irq_vector = translated_descriptor->u.Interrupt.Vector;
551 xpdd->irq_affinity = translated_descriptor->u.Interrupt.Affinity;
552 xpdd->irq_mode = (translated_descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?Latched:LevelSensitive;
553 xpdd->irq_number = raw_descriptor->u.Interrupt.Vector;
554 KdPrint((__DRIVER_NAME " irq_number = %03x\n", raw_descriptor->u.Interrupt.Vector));
555 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", translated_descriptor->u.Interrupt.Vector));
556 KdPrint((__DRIVER_NAME " irq_level = %03x\n", translated_descriptor->u.Interrupt.Level));
557 KdPrint((__DRIVER_NAME " irq_mode = %s\n", (xpdd->irq_mode == Latched)?"Latched":"LevelSensitive"));
558 switch(translated_descriptor->ShareDisposition)
559 {
560 case CmResourceShareDeviceExclusive:
561 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDeviceExclusive\n"));
562 break;
563 case CmResourceShareDriverExclusive:
564 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDriverExclusive\n"));
565 break;
566 case CmResourceShareShared:
567 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareShared\n"));
568 break;
569 default:
570 KdPrint((__DRIVER_NAME " ShareDisposition = %d\n", translated_descriptor->ShareDisposition));
571 break;
572 }
573 break;
574 case CmResourceTypeDevicePrivate:
575 KdPrint((__DRIVER_NAME " Private Data: 0x%02x 0x%02x 0x%02x\n", translated_descriptor->u.DevicePrivate.Data[0], translated_descriptor->u.DevicePrivate.Data[1], translated_descriptor->u.DevicePrivate.Data[2]));
576 break;
577 default:
578 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", translated_descriptor->Type));
579 break;
580 }
581 }
583 FUNCTION_EXIT();
585 return status;
586 }
588 NTSTATUS
589 XenPci_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
590 {
591 NTSTATUS status = STATUS_SUCCESS;
592 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
594 FUNCTION_ENTER();
596 xpdd->hibernated = FALSE;
598 switch (previous_state)
599 {
600 case WdfPowerDeviceD0:
601 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
602 break;
603 case WdfPowerDeviceD1:
604 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
605 break;
606 case WdfPowerDeviceD2:
607 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
608 break;
609 case WdfPowerDeviceD3:
610 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
611 break;
612 case WdfPowerDeviceD3Final:
613 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
614 break;
615 case WdfPowerDevicePrepareForHibernation:
616 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
617 break;
618 default:
619 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
620 break;
621 }
623 if (previous_state == WdfPowerDevicePrepareForHibernation && qemu_filtered_by_qemu)
624 {
625 XenPci_HideQemuDevices();
626 ASSERT(qemu_filtered_by_qemu);
627 }
629 XenPci_Init(xpdd);
630 if (tpr_patch_requested && !xpdd->tpr_patched)
631 {
632 XenPci_MapHalThenPatchKernel(xpdd);
633 xpdd->tpr_patched = TRUE;
634 }
635 if (previous_state == WdfPowerDevicePrepareForHibernation)
636 {
637 GntTbl_Resume(xpdd);
638 }
639 else
640 {
641 GntTbl_Init(xpdd);
642 }
643 EvtChn_Init(xpdd);
645 FUNCTION_EXIT();
647 return status;
648 }
650 NTSTATUS
651 XenPci_EvtDeviceD0EntryPostInterruptsEnabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
652 {
653 NTSTATUS status = STATUS_SUCCESS;
654 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
655 PCHAR response;
656 char *value;
657 domid_t domid = DOMID_SELF;
658 ULONG ret;
659 xen_ulong_t *max_ram_page;
661 UNREFERENCED_PARAMETER(previous_state);
663 FUNCTION_ENTER();
665 XenBus_Init(xpdd);
667 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
669 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, device);
671 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
673 ret = HYPERVISOR_memory_op(xpdd, XENMEM_current_reservation, &domid);
674 KdPrint((__DRIVER_NAME " XENMEM_current_reservation = %d\n", ret));
675 ret = HYPERVISOR_memory_op(xpdd, XENMEM_maximum_reservation, &domid);
676 KdPrint((__DRIVER_NAME " XENMEM_maximum_reservation = %d\n", ret));
677 ret = HYPERVISOR_memory_op(xpdd, XENMEM_maximum_ram_page, &max_ram_page);
678 KdPrint((__DRIVER_NAME " XENMEM_maximum_ram_page = %d\n", ret));
680 if (!xpdd->initial_memory)
681 {
682 XenBus_Read(xpdd, XBT_NIL, BALLOON_PATH, &value);
683 if (atoi(value) > 0)
684 {
685 xpdd->initial_memory = atoi(value) >> 10; /* convert to MB */
686 xpdd->current_memory = xpdd->initial_memory;
687 xpdd->target_memory = xpdd->initial_memory;
688 }
689 KdPrint((__DRIVER_NAME " Initial Memory Value = %d (%s)\n", xpdd->initial_memory, value));
690 KeInitializeEvent(&xpdd->balloon_event, SynchronizationEvent, FALSE);
691 status = PsCreateSystemThread(&xpdd->balloon_thread, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenPci_BalloonThreadProc, xpdd);
692 if (!NT_SUCCESS(status))
693 {
694 KdPrint((__DRIVER_NAME " Could not start balloon thread\n"));
695 //return status;
696 }
697 }
698 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, device);
700 FUNCTION_EXIT();
702 return status;
703 }
705 NTSTATUS
706 XenPci_EvtDeviceD0ExitPreInterruptsDisabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
707 {
708 NTSTATUS status = STATUS_SUCCESS;
710 UNREFERENCED_PARAMETER(device);
712 FUNCTION_ENTER();
714 switch (target_state)
715 {
716 case WdfPowerDeviceD0:
717 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
718 break;
719 case WdfPowerDeviceD1:
720 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
721 break;
722 case WdfPowerDeviceD2:
723 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
724 break;
725 case WdfPowerDeviceD3:
726 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
727 break;
728 case WdfPowerDeviceD3Final:
729 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
730 break;
731 case WdfPowerDevicePrepareForHibernation:
732 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
733 break;
734 default:
735 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
736 break;
737 }
739 FUNCTION_EXIT();
741 return status;
742 }
744 NTSTATUS
745 XenPci_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
746 {
747 NTSTATUS status = STATUS_SUCCESS;
748 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
750 FUNCTION_ENTER();
752 switch (target_state)
753 {
754 case WdfPowerDeviceD0:
755 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
756 break;
757 case WdfPowerDeviceD1:
758 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
759 break;
760 case WdfPowerDeviceD2:
761 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
762 break;
763 case WdfPowerDeviceD3:
764 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
765 break;
766 case WdfPowerDeviceD3Final:
767 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
768 break;
769 case WdfPowerDevicePrepareForHibernation:
770 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
771 xpdd->hibernated = TRUE;
772 break;
773 default:
774 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
775 break;
776 }
778 if (target_state == WdfPowerDevicePrepareForHibernation)
779 {
780 GntTbl_Suspend(xpdd);
781 }
783 FUNCTION_EXIT();
785 return status;
786 }
788 NTSTATUS
789 XenPci_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
790 {
791 NTSTATUS status = STATUS_SUCCESS;
793 UNREFERENCED_PARAMETER(device);
794 UNREFERENCED_PARAMETER(resources_translated);
796 FUNCTION_ENTER();
797 FUNCTION_EXIT();
799 return status;
800 }
802 VOID
803 XenPci_EvtChildListScanForChildren(WDFCHILDLIST child_list)
804 {
805 NTSTATUS status;
806 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
807 char *msg;
808 char **devices;
809 char **instances;
810 ULONG i, j;
811 CHAR path[128];
812 XENPCI_PDO_IDENTIFICATION_DESCRIPTION child_description;
814 FUNCTION_ENTER();
816 WdfChildListBeginScan(child_list);
818 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
819 if (!msg)
820 {
821 for (i = 0; devices[i]; i++)
822 {
823 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
825 for (j = 0; j < WdfCollectionGetCount(xpdd->veto_devices); j++)
826 {
827 WDFOBJECT ws = WdfCollectionGetItem(xpdd->veto_devices, j);
828 UNICODE_STRING val;
829 ANSI_STRING s;
830 WdfStringGetUnicodeString(ws, &val);
831 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
832 if (!strcmp(devices[i], s.Buffer))
833 {
834 RtlFreeAnsiString(&s);
835 break;
836 }
837 RtlFreeAnsiString(&s);
838 }
839 if (j < WdfCollectionGetCount(xpdd->veto_devices))
840 {
841 XenPci_FreeMem(devices[i]);
842 continue;
843 }
845 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
846 if (!msg)
847 {
848 for (j = 0; instances[j]; j++)
849 {
850 /* the device comparison is done as a memory compare so zero-ing the structure is important */
851 RtlZeroMemory(&child_description, sizeof(child_description));
852 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
853 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
854 RtlStringCbCopyA(child_description.path, ARRAY_SIZE(child_description.path), path);
855 RtlStringCbCopyA(child_description.device, ARRAY_SIZE(child_description.device), devices[i]);
856 child_description.index = atoi(instances[j]);
857 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
858 if (!NT_SUCCESS(status))
859 {
860 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status));
861 }
862 XenPci_FreeMem(instances[j]);
863 }
864 XenPci_FreeMem(instances);
865 }
866 else
867 {
868 // wtf do we do here???
869 KdPrint((__DRIVER_NAME " Failed to list %s tree\n", devices[i]));
870 }
871 XenPci_FreeMem(devices[i]);
872 }
873 XenPci_FreeMem(devices);
874 }
875 else
876 {
877 // wtf do we do here???
878 KdPrint((__DRIVER_NAME " Failed to list device tree\n"));
879 }
881 WdfChildListEndScan(child_list);
883 FUNCTION_EXIT();
884 }