win-pvdrivers

view xenpci/xenpci.c @ 497:312a41f82b8f

Updated to support the proposed patches to qemu from Steven Smith on ~20081216
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 19 22:08:17 2008 +1100 (2008-12-19)
parents a6e3f76419c3
children cb0b2da68686
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 #define INITGUID
21 #include "xenpci.h"
22 #include <stdlib.h>
24 #define SYSRQ_PATH "control/sysrq"
25 #define SHUTDOWN_PATH "control/shutdown"
26 #define BALLOON_PATH "memory/target"
28 #ifdef ALLOC_PRAGMA
29 DRIVER_INITIALIZE DriverEntry;
30 #pragma alloc_text (INIT, DriverEntry)
31 #endif
33 #pragma warning(disable : 4200) // zero-sized array
35 static DDKAPI NTSTATUS
36 XenPci_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
37 {
38 NTSTATUS status;
39 PXENPCI_COMMON common = device_object->DeviceExtension;
41 if (common->lower_do)
42 status = XenPci_Pnp_Fdo(device_object, irp);
43 else
44 status = XenPci_Pnp_Pdo(device_object, irp);
46 return status;
47 }
49 static DDKAPI NTSTATUS
50 XenPci_Power(PDEVICE_OBJECT device_object, PIRP irp)
51 {
52 NTSTATUS status;
53 PXENPCI_COMMON common = device_object->DeviceExtension;
55 if (common->lower_do)
56 status = XenPci_Power_Fdo(device_object, irp);
57 else
58 status = XenPci_Power_Pdo(device_object, irp);
60 return status;
61 }
63 static DDKAPI NTSTATUS
64 XenPci_Irp_Create(PDEVICE_OBJECT device_object, PIRP irp)
65 {
66 NTSTATUS status;
67 PXENPCI_COMMON common = device_object->DeviceExtension;
69 if (common->lower_do)
70 status = XenPci_Irp_Create_Fdo(device_object, irp);
71 else
72 status = XenPci_Irp_Create_Pdo(device_object, irp);
74 return status;
75 }
77 static DDKAPI NTSTATUS
78 XenPci_Irp_Close(PDEVICE_OBJECT device_object, PIRP irp)
79 {
80 NTSTATUS status;
81 PXENPCI_COMMON common = device_object->DeviceExtension;
83 if (common->lower_do)
84 status = XenPci_Irp_Close_Fdo(device_object, irp);
85 else
86 status = XenPci_Irp_Close_Pdo(device_object, irp);
88 return status;
89 }
91 static DDKAPI NTSTATUS
92 XenPci_Irp_Read(PDEVICE_OBJECT device_object, PIRP irp)
93 {
94 NTSTATUS status;
95 PXENPCI_COMMON common = device_object->DeviceExtension;
97 if (common->lower_do)
98 status = XenPci_Irp_Read_Fdo(device_object, irp);
99 else
100 status = XenPci_Irp_Read_Pdo(device_object, irp);
102 return status;
103 }
105 static DDKAPI NTSTATUS
106 XenPci_Irp_Cleanup(PDEVICE_OBJECT device_object, PIRP irp)
107 {
108 NTSTATUS status;
109 PXENPCI_COMMON common = device_object->DeviceExtension;
111 if (common->lower_do)
112 status = XenPci_Irp_Cleanup_Fdo(device_object, irp);
113 else
114 status = XenPci_Irp_Cleanup_Pdo(device_object, irp);
116 return status;
117 }
119 static DDKAPI NTSTATUS
120 XenPci_SystemControl(PDEVICE_OBJECT device_object, PIRP irp)
121 {
122 NTSTATUS status;
123 PXENPCI_COMMON common = device_object->DeviceExtension;
125 if (common->lower_do)
126 status = XenPci_SystemControl_Fdo(device_object, irp);
127 else
128 status = XenPci_SystemControl_Pdo(device_object, irp);
130 return status;
131 }
133 static DDKAPI NTSTATUS
134 XenPci_Dummy(PDEVICE_OBJECT device_object, PIRP irp)
135 {
136 NTSTATUS status;
137 PIO_STACK_LOCATION stack;
138 PXENPCI_COMMON common = device_object->DeviceExtension;
140 FUNCTION_ENTER();
142 UNREFERENCED_PARAMETER(device_object);
144 stack = IoGetCurrentIrpStackLocation(irp);
145 KdPrint((__DRIVER_NAME " Major = %d, Minor = %d\n", stack->MajorFunction, stack->MinorFunction));
146 IoSkipCurrentIrpStackLocation(irp);
147 status = IoCallDriver(common->lower_do, irp);
149 FUNCTION_EXIT();
151 return status;
152 }
154 static DDKAPI NTSTATUS
155 XenPci_AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject)
156 {
157 NTSTATUS status;
158 PDEVICE_OBJECT fdo = NULL;
159 // PNP_BUS_INFORMATION busInfo;
160 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
161 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
162 // WDFDEVICE Device;
163 PXENPCI_DEVICE_DATA xpdd;
164 //PWSTR InterfaceList;
166 FUNCTION_ENTER();
168 status = IoCreateDevice(DriverObject,
169 sizeof(XENPCI_DEVICE_DATA),
170 NULL,
171 FILE_DEVICE_BUS_EXTENDER,
172 FILE_DEVICE_SECURE_OPEN,
173 FALSE,
174 &fdo);
176 if (!NT_SUCCESS(status))
177 {
178 KdPrint((__DRIVER_NAME " IoCreateDevice failed 0x%08x\n", status));
179 return status;
180 }
182 fdo->Flags |= DO_BUFFERED_IO;
184 xpdd = (PXENPCI_DEVICE_DATA)fdo->DeviceExtension;
186 RtlZeroMemory(xpdd, sizeof(XENPCI_DEVICE_DATA));
188 xpdd->shutdown_prod = 0;
189 xpdd->shutdown_cons = 0;
190 KeInitializeSpinLock(&xpdd->shutdown_ring_lock);
192 xpdd->common.fdo = fdo;
193 xpdd->common.pdo = PhysicalDeviceObject;
194 xpdd->common.lower_do = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
195 if(xpdd->common.lower_do == NULL) {
196 IoDeleteDevice(fdo);
197 return STATUS_NO_SUCH_DEVICE;
198 }
199 INIT_PNP_STATE(&xpdd->common);
200 xpdd->common.device_usage_paging = 0;
201 xpdd->common.device_usage_dump = 0;
202 xpdd->common.device_usage_hibernation = 0;
204 InitializeListHead(&xpdd->child_list);
206 status = IoRegisterDeviceInterface(
207 PhysicalDeviceObject,
208 &GUID_XEN_IFACE,
209 NULL,
210 &xpdd->interface_name);
212 if (!NT_SUCCESS(status))
213 {
214 KdPrint((__DRIVER_NAME " IoRegisterDeviceInterface failed with status 0x%08x\n", status));
215 }
216 else
217 {
218 KdPrint((__DRIVER_NAME " IoRegisterDeviceInterface succeeded - %wZ\n", &xpdd->interface_name));
219 }
221 fdo->Flags &= ~DO_DEVICE_INITIALIZING;
223 FUNCTION_EXIT();
224 return status;
225 }
227 ULONG qemu_filtered;
228 ULONG qemu_protocol_version;
229 extern PULONG InitSafeBootMode;
231 NTSTATUS DDKAPI
232 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
233 {
234 NTSTATUS status = STATUS_SUCCESS;
235 PCONFIGURATION_INFORMATION conf_info;
236 WCHAR *SystemStartOptions;
237 UNICODE_STRING RegKeyName;
238 UNICODE_STRING RegValueName;
239 HANDLE RegHandle;
240 OBJECT_ATTRIBUTES RegObjectAttributes;
241 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
242 ULONG BufLen = 300;
243 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
245 UNREFERENCED_PARAMETER(RegistryPath);
247 FUNCTION_ENTER();
249 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
250 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
251 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
252 if(!NT_SUCCESS(status))
253 {
254 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
255 }
257 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
258 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
259 if(!NT_SUCCESS(status))
260 {
261 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
262 }
263 else
264 ZwClose(RegHandle);
265 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
266 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
268 KdPrint((__DRIVER_NAME " SystemStartOptions = %s\n", SystemStartOptions));
269 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
270 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
271 conf_info = IoGetConfigurationInformation();
272 if ((conf_info == NULL || conf_info->DiskCount == 0)
273 && !wcsstr(SystemStartOptions, L"NOGPLPV")
274 && !*InitSafeBootMode)
275 {
276 /* see if the qemu method of disabling the PCI devices exists */
277 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
278 {
279 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
280 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
281 switch(qemu_protocol_version)
282 {
283 case 1:
284 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
285 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
286 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
287 {
288 KdPrint((__DRIVER_NAME " Blacklisted\n"));
289 break;
290 }
291 /* fall through */
292 case 0:
293 qemu_filtered = TRUE;
294 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
295 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));
296 break;
297 default:
298 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
299 break;
300 }
301 }
302 else
303 {
304 KdPrint((__DRIVER_NAME " Missing XEN signature\n"));
305 }
306 /* if not, tell the filter to deny the pci devices their resources */
307 if (!qemu_filtered)
308 {
309 OBJECT_ATTRIBUTES oa;
310 UNICODE_STRING dir_name;
311 NTSTATUS status;
312 HANDLE handle;
314 KdPrint((__DRIVER_NAME " Adding DirectoryObject\n"));
315 RtlInitUnicodeString(&dir_name, L"\\NEED_GPLPV_FILTER");
316 InitializeObjectAttributes(&oa, &dir_name, OBJ_KERNEL_HANDLE, NULL, NULL);
317 status = ZwCreateDirectoryObject(&handle, DIRECTORY_CREATE_OBJECT, &oa);
318 KdPrint((__DRIVER_NAME " ZwCreateDirectoryObject = %08x\n", status));
319 if (!NT_SUCCESS(status))
320 {
321 return status;
322 }
323 qemu_filtered = TRUE;
324 }
325 }
327 DriverObject->DriverExtension->AddDevice = XenPci_AddDevice;
328 DriverObject->MajorFunction[IRP_MJ_PNP] = XenPci_Pnp;
329 DriverObject->MajorFunction[IRP_MJ_POWER] = XenPci_Power;
330 DriverObject->MajorFunction[IRP_MJ_CREATE] = XenPci_Irp_Create;
331 DriverObject->MajorFunction[IRP_MJ_CLOSE] = XenPci_Irp_Close;
332 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = XenPci_Irp_Cleanup;
333 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = XenPci_Dummy;
334 DriverObject->MajorFunction[IRP_MJ_READ] = XenPci_Irp_Read;
335 DriverObject->MajorFunction[IRP_MJ_WRITE] = XenPci_Dummy;
336 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = XenPci_SystemControl;
338 FUNCTION_EXIT();
340 return status;
341 }