win-pvdrivers

view xenpci/xenpci.h @ 900:938de6b8623d

fix memory leak on suspend/resume
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 31 20:20:36 2011 +1100 (2011-03-31)
parents e315b8490131
children 35ec9d4ebf94
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 #if !defined(_XENPCI_H_)
21 #define _XENPCI_H_
23 #define __attribute__(arg) /* empty */
24 #define EISCONN 127
26 #include <ntddk.h>
28 /* including ntifs.h (only needed for this function) causes PREFast to trip up on lots of bogus errors */
29 PDEVICE_OBJECT IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject);
30 //#include <ntifs.h>
32 //#include <wdm.h>
33 #include <wdf.h>
34 #include <initguid.h>
35 #include <wdmguid.h>
36 #include <errno.h>
37 #define NTSTRSAFE_LIB
38 #include <ntstrsafe.h>
40 #include <liblfds.h>
42 #define __DRIVER_NAME "XenPCI"
44 #include <xen_windows.h>
45 #include <memory.h>
46 #include <grant_table.h>
47 #include <event_channel.h>
48 #include <hvm/params.h>
49 #include <hvm/hvm_op.h>
50 #include <sched.h>
51 #include <io/xenbus.h>
52 #include <io/xs_wire.h>
54 #include <xen_public.h>
56 //{C828ABE9-14CA-4445-BAA6-82C2376C6518}
57 DEFINE_GUID( GUID_XENPCI_DEVCLASS, 0xC828ABE9, 0x14CA, 0x4445, 0xBA, 0xA6, 0x82, 0xC2, 0x37, 0x6C, 0x65, 0x18);
59 #define XENPCI_POOL_TAG (ULONG) 'XenP'
61 #define NR_RESERVED_ENTRIES 8
62 #define NR_GRANT_FRAMES 32
63 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
65 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
67 #define EVT_ACTION_TYPE_EMPTY 0
68 #define EVT_ACTION_TYPE_NORMAL 1
69 #define EVT_ACTION_TYPE_DPC 2
70 #define EVT_ACTION_TYPE_IRQ 3
71 #define EVT_ACTION_TYPE_SUSPEND 4
72 #define EVT_ACTION_TYPE_NEW 5 /* setup of event is in progress */
74 #define EVT_ACTION_FLAGS_DEFAULT 0 /* no special flags */
75 #define EVT_ACTION_FLAGS_NO_SUSPEND 1 /* should not be fired on EVT_ACTION_TYPE_SUSPEND event */
77 #define XEN_PV_PRODUCT_NUMBER 0x0002
78 #define XEN_PV_PRODUCT_BUILD 0x00000001
80 #define BALLOON_UNIT_PAGES (BALLOON_UNITS >> PAGE_SHIFT)
82 extern ULONG qemu_protocol_version;
84 typedef struct _ev_action_t {
85 PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine;
86 PVOID ServiceContext;
87 CHAR description[128];
88 ULONG type; /* EVT_ACTION_TYPE_* */
89 ULONG flags; /* EVT_ACTION_FLAGS_* */
90 KDPC Dpc;
91 ULONG port;
92 ULONG vector;
93 ULONG count;
94 PVOID xpdd;
95 ULONG generation; /* increases each time the event is renewed */
96 } ev_action_t;
98 typedef struct _XENBUS_WATCH_RING
99 {
100 char Path[128];
101 char Token[10];
102 } XENBUS_WATCH_RING;
104 typedef struct xsd_sockmsg xsd_sockmsg_t;
106 typedef struct _XENBUS_WATCH_ENTRY {
107 char Path[128];
108 PXENBUS_WATCH_CALLBACK ServiceRoutine;
109 PVOID ServiceContext;
110 int Count;
111 int Active;
112 } XENBUS_WATCH_ENTRY, *PXENBUS_WATCH_ENTRY;
114 #define NR_EVENTS 1024
115 #define WATCH_RING_SIZE 128
116 #define NR_XB_REQS 32
117 #define MAX_WATCH_ENTRIES 128
119 #define CHILD_STATE_EMPTY 0
120 #define CHILD_STATE_DELETED 1
121 #define CHILD_STATE_ADDED 2
123 #define SUSPEND_STATE_NONE 0 /* no suspend in progress */
124 #define SUSPEND_STATE_SCHEDULED 1 /* suspend scheduled */
125 #define SUSPEND_STATE_HIGH_IRQL 2 /* all processors are at high IRQL and spinning */
126 #define SUSPEND_STATE_RESUMING 3 /* we are the other side of the suspend and things are starting to get back to normal */
128 /* we take some grant refs out and put them aside so that we dont get corrupted by hibernate */
129 #define HIBER_GREF_COUNT 128
131 typedef struct {
132 ULONG generation;
133 ULONG tag;
134 } grant_tag_t;
136 typedef struct {
137 WDFDEVICE wdf_device;
139 BOOLEAN tpr_patched;
141 WDFINTERRUPT interrupt;
142 ULONG irq_number;
143 ULONG irq_vector;
144 KIRQL irq_level;
145 KINTERRUPT_MODE irq_mode;
146 KAFFINITY irq_affinity;
148 PHYSICAL_ADDRESS shared_info_area_unmapped;
149 shared_info_t *shared_info_area;
150 xen_ulong_t evtchn_pending_pvt[MAX_VIRT_CPUS][sizeof(xen_ulong_t) * 8];
151 xen_ulong_t evtchn_pending_suspend[sizeof(xen_ulong_t) * 8];
152 evtchn_port_t pdo_event_channel;
153 KEVENT pdo_suspend_event;
154 BOOLEAN interrupts_masked;
156 PHYSICAL_ADDRESS platform_mmio_addr;
157 ULONG platform_mmio_orig_len;
158 ULONG platform_mmio_len;
159 ULONG platform_mmio_alloc;
160 USHORT platform_mmio_flags;
162 ULONG platform_ioport_addr;
163 ULONG platform_ioport_len;
165 char *hypercall_stubs;
167 evtchn_port_t xen_store_evtchn;
169 /* grant related */
170 struct stack_state *gnttbl_ss;
171 struct stack_state *gnttbl_ss_copy;
172 grant_ref_t hiber_grefs[HIBER_GREF_COUNT];
173 PMDL gnttbl_mdl;
174 grant_entry_t *gnttbl_table;
175 grant_entry_t *gnttbl_table_copy;
176 #if DBG
177 ULONG gnttbl_generation; /* incremented once per save or hibernate */
178 grant_tag_t *gnttbl_tag;
179 grant_tag_t *gnttbl_tag_copy;
180 #endif
181 ULONG grant_frames;
183 ev_action_t ev_actions[NR_EVENTS];
184 // unsigned long bound_ports[NR_EVENTS/(8*sizeof(unsigned long))];
186 BOOLEAN xb_state;
188 struct xenstore_domain_interface *xen_store_interface;
190 #define BALLOON_UNITS (1024 * 1024) /* 1MB */
191 PKTHREAD balloon_thread;
192 KEVENT balloon_event;
193 BOOLEAN balloon_shutdown;
194 ULONG initial_memory;
195 ULONG current_memory;
196 ULONG target_memory;
198 /* xenbus related */
199 XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
200 KSPIN_LOCK xb_ring_spinlock;
201 FAST_MUTEX xb_watch_mutex;
202 FAST_MUTEX xb_request_mutex;
203 KEVENT xb_request_complete_event;
204 struct xsd_sockmsg *xb_reply;
205 struct xsd_sockmsg *xb_msg;
206 ULONG xb_msg_offset;
208 WDFCHILDLIST child_list;
210 KSPIN_LOCK suspend_lock;
211 evtchn_port_t suspend_evtchn;
212 int suspend_state;
214 UNICODE_STRING legacy_interface_name;
215 UNICODE_STRING interface_name;
216 BOOLEAN interface_open;
218 BOOLEAN removable;
220 BOOLEAN hibernated;
222 WDFQUEUE io_queue;
224 //WDFCOLLECTION veto_devices;
225 LIST_ENTRY veto_list;
227 #if 0
228 KSPIN_LOCK mmio_freelist_lock;
229 PPFN_NUMBER mmio_freelist_base;
230 ULONG mmio_freelist_free;
231 #endif
233 } XENPCI_DEVICE_DATA, *PXENPCI_DEVICE_DATA;
235 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_DEVICE_DATA, GetXpdd)
237 typedef struct {
238 UCHAR front_target;
239 UCHAR back_expected;
240 UCHAR wait; /* units = 100ms */
241 } XENPCI_STATE_MAP_ELEMENT, *PXENPCI_STATE_MAP_ELEMENT;
243 typedef struct {
244 WDFDEVICE wdf_device;
245 WDFDEVICE wdf_device_bus_fdo;
246 BOOLEAN reported_missing;
247 char path[128];
248 char device[128];
249 ULONG index;
250 ULONG irq_number;
251 ULONG irq_vector;
252 KIRQL irq_level;
253 char backend_path[128];
254 //PVOID xenbus_request;
255 KEVENT backend_state_event;
256 ULONG backend_state;
257 FAST_MUTEX backend_state_mutex;
258 ULONG frontend_state;
259 PMDL config_page_mdl;
260 PHYSICAL_ADDRESS config_page_phys;
261 ULONG config_page_length;
262 PUCHAR requested_resources_start;
263 PUCHAR requested_resources_ptr;
264 PUCHAR assigned_resources_start;
265 PUCHAR assigned_resources_ptr;
266 XENPCI_DEVICE_STATE device_state;
267 BOOLEAN restart_on_resume;
268 BOOLEAN backend_initiated_remove;
269 BOOLEAN do_not_enumerate;
271 XENPCI_STATE_MAP_ELEMENT xb_pre_connect_map[5];
272 XENPCI_STATE_MAP_ELEMENT xb_post_connect_map[5];
273 XENPCI_STATE_MAP_ELEMENT xb_shutdown_map[5];
275 BOOLEAN hiber_usage_kludge;
276 } XENPCI_PDO_DEVICE_DATA, *PXENPCI_PDO_DEVICE_DATA;
278 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_PDO_DEVICE_DATA, GetXppdd)
280 typedef struct {
281 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER header;
282 CHAR path[128];
283 CHAR device[128];
284 ULONG index;
285 } XENPCI_PDO_IDENTIFICATION_DESCRIPTION, *PXENPCI_PDO_IDENTIFICATION_DESCRIPTION;
287 #define XEN_INTERFACE_VERSION 1
289 //#define DEVICE_INTERFACE_TYPE_LEGACY 0
290 #define DEVICE_INTERFACE_TYPE_XENBUS 1
291 #define DEVICE_INTERFACE_TYPE_EVTCHN 2
292 #define DEVICE_INTERFACE_TYPE_GNTDEV 3
294 typedef struct {
295 ULONG len;
296 WDFQUEUE io_queue;
297 union {
298 struct xsd_sockmsg msg;
299 UCHAR buffer[PAGE_SIZE];
300 } u;
301 LIST_ENTRY read_list_head;
302 LIST_ENTRY watch_list_head;
303 } XENBUS_INTERFACE_DATA, *PXENBUS_INTERFACE_DATA;
305 typedef struct {
306 ULONG dummy; /* fill this in with whatever is required */
307 } EVTCHN_INTERFACE_DATA, *PEVTCHN_INTERFACE_DATA;
309 typedef struct {
310 ULONG dummy; /* fill this in with whatever is required */
311 } GNTDEV_INTERFACE_DATA, *PGNTDEV_INTERFACE_DATA;
313 typedef struct {
314 ULONG type;
315 KSPIN_LOCK lock;
316 WDFQUEUE io_queue;
317 EVT_WDF_FILE_CLEANUP *EvtFileCleanup;
318 EVT_WDF_FILE_CLOSE *EvtFileClose;
319 union {
320 XENBUS_INTERFACE_DATA xenbus;
321 EVTCHN_INTERFACE_DATA evtchn;
322 GNTDEV_INTERFACE_DATA gntdev;
323 };
324 } XENPCI_DEVICE_INTERFACE_DATA, *PXENPCI_DEVICE_INTERFACE_DATA;
326 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_DEVICE_INTERFACE_DATA, GetXpdid)
328 NTSTATUS
329 XenBus_DeviceFileInit(WDFDEVICE device, PWDF_IO_QUEUE_CONFIG queue_config, WDFFILEOBJECT file_object);
331 EVT_WDF_DEVICE_FILE_CREATE XenPci_EvtDeviceFileCreate;
332 EVT_WDF_FILE_CLOSE XenPci_EvtFileClose;
333 EVT_WDF_FILE_CLEANUP XenPci_EvtFileCleanup;
334 EVT_WDF_IO_QUEUE_IO_DEFAULT XenPci_EvtIoDefault;
336 #define HYPERVISOR_memory_op(xpdd, cmd, arg) _HYPERVISOR_memory_op(xpdd->hypercall_stubs, cmd, arg)
337 #define HYPERVISOR_xen_version(xpdd, cmd, arg) _HYPERVISOR_xen_version(xpdd->hypercall_stubs, cmd, arg)
338 #define HYPERVISOR_grant_table_op(xpdd, cmd, uop, count) _HYPERVISOR_grant_table_op(xpdd->hypercall_stubs, cmd, uop, count)
339 #define HYPERVISOR_hvm_op(xpdd, op, arg) _HYPERVISOR_hvm_op(xpdd->hypercall_stubs, op, arg)
340 #define HYPERVISOR_event_channel_op(xpdd, cmd, op) _HYPERVISOR_event_channel_op(xpdd->hypercall_stubs, cmd, op)
341 #define HYPERVISOR_sched_op(xpdd, cmd, arg) _HYPERVISOR_sched_op(xpdd->hypercall_stubs, cmd, arg)
342 #define HYPERVISOR_shutdown(xpdd, reason) _HYPERVISOR_shutdown(xpdd->hypercall_stubs, reason)
344 #define hvm_get_parameter(xvdd, hvm_param) _hvm_get_parameter(xvdd->hypercall_stubs, hvm_param);
345 #define hvm_set_parameter(xvdd, hvm_param, value) _hvm_set_parameter(xvdd->hypercall_stubs, hvm_param, value);
346 #define hvm_shutdown(xvdd, reason) _hvm_shutdown(xvdd->hypercall_stubs, reason);
347 #define HYPERVISOR_yield(xvdd) _HYPERVISOR_yield(xvdd->hypercall_stubs);
349 #include "hypercall.h"
351 #define XBT_NIL ((xenbus_transaction_t)0)
353 PVOID
354 hvm_get_hypercall_stubs();
355 VOID
356 hvm_free_hypercall_stubs(PVOID hypercall_stubs);
358 EVT_WDF_DEVICE_PREPARE_HARDWARE XenPci_EvtDevicePrepareHardware;
359 EVT_WDF_DEVICE_RELEASE_HARDWARE XenPci_EvtDeviceReleaseHardware;
360 EVT_WDF_DEVICE_D0_ENTRY XenPci_EvtDeviceD0Entry;
361 EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
362 EVT_WDF_DEVICE_D0_EXIT XenPci_EvtDeviceD0Exit;
363 EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
364 EVT_WDF_DEVICE_QUERY_REMOVE XenPci_EvtDeviceQueryRemove;
365 EVT_WDF_CHILD_LIST_CREATE_DEVICE XenPci_EvtChildListCreateDevice;
366 EVT_WDF_CHILD_LIST_SCAN_FOR_CHILDREN XenPci_EvtChildListScanForChildren;
368 VOID
369 XenPci_HideQemuDevices();
370 extern WDFCOLLECTION qemu_hide_devices;
371 extern USHORT qemu_hide_flags_value;
373 NTSTATUS
374 XenPci_Pdo_Suspend(WDFDEVICE device);
375 NTSTATUS
376 XenPci_Pdo_Resume(WDFDEVICE device);
378 VOID
379 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object);
381 typedef VOID
382 (*PXENPCI_HIGHSYNC_FUNCTION)(PVOID context);
384 VOID
385 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context);
387 VOID
388 XenPci_PatchKernel(PXENPCI_DEVICE_DATA xpdd, PVOID base, ULONG length);
390 NTSTATUS
391 XenPci_HookDbgPrint();
392 NTSTATUS
393 XenPci_UnHookDbgPrint();
395 struct xsd_sockmsg *
396 XenBus_Raw(PXENPCI_DEVICE_DATA xpdd, struct xsd_sockmsg *msg);
397 char *
398 XenBus_Read(PVOID Context, xenbus_transaction_t xbt, char *path, char **value);
399 char *
400 XenBus_Write(PVOID Context, xenbus_transaction_t xbt, char *path, char *value);
401 char *
402 XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, char *path, char *fmt, ...);
403 char *
404 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt);
405 char *
406 XenBus_EndTransaction(PVOID Context, xenbus_transaction_t t, int abort, int *retry);
407 char *
408 XenBus_List(PVOID Context, xenbus_transaction_t xbt, char *prefix, char ***contents);
409 char *
410 XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
411 char *
412 XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
413 //VOID
414 //XenBus_ThreadProc(PVOID StartContext);
415 NTSTATUS
416 XenBus_Init(PXENPCI_DEVICE_DATA xpdd);
417 NTSTATUS
418 XenBus_Halt(PXENPCI_DEVICE_DATA xpdd);
419 NTSTATUS
420 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd);
421 NTSTATUS
422 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd);
424 PHYSICAL_ADDRESS
425 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len);
427 EVT_WDF_INTERRUPT_ISR EvtChn_EvtInterruptIsr;
428 EVT_WDF_INTERRUPT_ENABLE EvtChn_EvtInterruptEnable;
429 EVT_WDF_INTERRUPT_DISABLE EvtChn_EvtInterruptDisable;
431 NTSTATUS
432 EvtChn_Init(PXENPCI_DEVICE_DATA xpdd);
433 NTSTATUS
434 EvtChn_Suspend(PXENPCI_DEVICE_DATA xpdd);
435 NTSTATUS
436 EvtChn_Resume(PXENPCI_DEVICE_DATA xpdd);
438 NTSTATUS
439 EvtChn_Mask(PVOID Context, evtchn_port_t Port);
440 NTSTATUS
441 EvtChn_Unmask(PVOID Context, evtchn_port_t Port);
442 NTSTATUS
443 EvtChn_Bind(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext, ULONG flags);
444 NTSTATUS
445 EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext, ULONG flags);
446 NTSTATUS
447 EvtChn_BindIrq(PVOID Context, evtchn_port_t Port, ULONG vector, PCHAR description, ULONG flags);
448 evtchn_port_t
449 EvtChn_AllocIpi(PVOID context, ULONG vcpu);
450 NTSTATUS
451 EvtChn_Unbind(PVOID Context, evtchn_port_t Port);
452 NTSTATUS
453 EvtChn_Notify(PVOID Context, evtchn_port_t Port);
454 VOID
455 EvtChn_Close(PVOID Context, evtchn_port_t Port);
456 evtchn_port_t
457 EvtChn_AllocUnbound(PVOID Context, domid_t Domain);
458 BOOLEAN
459 EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt);
461 VOID
462 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd);
463 VOID
464 GntTbl_Suspend(PXENPCI_DEVICE_DATA xpdd);
465 VOID
466 GntTbl_Resume(PXENPCI_DEVICE_DATA xpdd);
467 grant_ref_t
468 GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t, int readonly, grant_ref_t ref, ULONG tag);
469 BOOLEAN
470 GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref, ULONG tag);
471 VOID
472 GntTbl_PutRef(PVOID Context, grant_ref_t ref, ULONG tag);
473 grant_ref_t
474 GntTbl_GetRef(PVOID Context, ULONG tag);
476 #endif