win-pvdrivers

changeset 860:95159ee58473

Shuffle things around. Intial balloon-down (for PoD) happens as early as possible now to avoid crashes when Windows access unpopulated memory.
Also place a crash dump header in memory for dump-core -> windows dump conversion
author James Harper <james.harper@bendigoit.com.au>
date Sun Feb 27 14:28:41 2011 +1100 (2011-02-27)
parents 658d20a31016
children 16af5a68a3e1
files xenpci/hypercall.h xenpci/hypercall_amd64.h xenpci/hypercall_x86.h xenpci/memory.c xenpci/xenpci.c xenpci/xenpci.h xenpci/xenpci_fdo.c xenpci/xenpci_pdo.c
line diff
     1.1 --- a/xenpci/hypercall.h	Sun Feb 27 11:14:20 2011 +1100
     1.2 +++ b/xenpci/hypercall.h	Sun Feb 27 14:28:41 2011 +1100
     1.3 @@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     1.4  #endif
     1.5  
     1.6  static __inline ULONGLONG
     1.7 -hvm_get_parameter(PXENPCI_DEVICE_DATA xpdd, int hvm_param)
     1.8 +_hvm_get_parameter(PVOID hypercall_stubs, int hvm_param)
     1.9  {
    1.10    struct xen_hvm_param a;
    1.11    int retval;
    1.12 @@ -38,15 +38,14 @@ hvm_get_parameter(PXENPCI_DEVICE_DATA xp
    1.13    FUNCTION_ENTER();
    1.14    a.domid = DOMID_SELF;
    1.15    a.index = hvm_param;
    1.16 -  //a.value = via;
    1.17 -  retval = HYPERVISOR_hvm_op(xpdd, HVMOP_get_param, &a);
    1.18 +  retval = _HYPERVISOR_hvm_op(hypercall_stubs, HVMOP_get_param, &a);
    1.19    KdPrint((__DRIVER_NAME " HYPERVISOR_hvm_op retval = %d\n", retval));
    1.20    FUNCTION_EXIT();
    1.21    return a.value;
    1.22  }
    1.23  
    1.24  static __inline ULONGLONG
    1.25 -hvm_set_parameter(PXENPCI_DEVICE_DATA xpdd, int hvm_param, ULONGLONG value)
    1.26 +_hvm_set_parameter(PVOID hypercall_stubs, int hvm_param, ULONGLONG value)
    1.27  {
    1.28    struct xen_hvm_param a;
    1.29    int retval;
    1.30 @@ -55,27 +54,27 @@ hvm_set_parameter(PXENPCI_DEVICE_DATA xp
    1.31    a.domid = DOMID_SELF;
    1.32    a.index = hvm_param;
    1.33    a.value = value;
    1.34 -  retval = HYPERVISOR_hvm_op(xpdd, HVMOP_set_param, &a);
    1.35 +  retval = _HYPERVISOR_hvm_op(hypercall_stubs, HVMOP_set_param, &a);
    1.36    KdPrint((__DRIVER_NAME " HYPERVISOR_hvm_op retval = %d\n", retval));
    1.37    FUNCTION_EXIT();
    1.38    return retval;
    1.39  }
    1.40  
    1.41  static __inline int
    1.42 -hvm_shutdown(PXENPCI_DEVICE_DATA xpdd, unsigned int reason)
    1.43 +_hvm_shutdown(PVOID hypercall_stubs, unsigned int reason)
    1.44  {
    1.45    struct sched_shutdown ss;
    1.46    int retval;
    1.47  
    1.48    FUNCTION_ENTER();
    1.49    ss.reason = reason;
    1.50 -  retval = HYPERVISOR_sched_op(xpdd, SCHEDOP_shutdown, &ss);
    1.51 +  retval = _HYPERVISOR_sched_op(hypercall_stubs, SCHEDOP_shutdown, &ss);
    1.52    FUNCTION_EXIT();
    1.53    return retval;
    1.54  }
    1.55  
    1.56  static __inline VOID
    1.57 -HYPERVISOR_yield(PXENPCI_DEVICE_DATA xpdd)
    1.58 +_HYPERVISOR_yield(PVOID hypercall_stubs)
    1.59  {
    1.60 -  HYPERVISOR_sched_op(xpdd, SCHEDOP_yield, NULL);
    1.61 +  _HYPERVISOR_sched_op(hypercall_stubs, SCHEDOP_yield, NULL);
    1.62  }
     2.1 --- a/xenpci/hypercall_amd64.h	Sun Feb 27 11:14:20 2011 +1100
     2.2 +++ b/xenpci/hypercall_amd64.h	Sun Feb 27 14:28:41 2011 +1100
     2.3 @@ -21,111 +21,65 @@ extern int _hypercall2(VOID *address, xe
     2.4  extern int _hypercall3(VOID *address, xen_ulong_t a1, xen_ulong_t a2, xen_ulong_t a3);
     2.5  
     2.6  static __inline int
     2.7 -HYPERVISOR_memory_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *arg)
     2.8 +_HYPERVISOR_memory_op(PVOID hypercall_stubs, int cmd, void *arg)
     2.9  {
    2.10 -  PCHAR memory_op_func = xpdd->hypercall_stubs;
    2.11 +  PCHAR memory_op_func = hypercall_stubs;
    2.12    memory_op_func += __HYPERVISOR_memory_op * 32;
    2.13    return _hypercall2(memory_op_func, (xen_ulong_t)cmd, (xen_ulong_t)arg);
    2.14  }
    2.15  
    2.16  static __inline int
    2.17 -HYPERVISOR_xen_version(PXENPCI_DEVICE_DATA xpdd, int cmd, void *arg)
    2.18 +_HYPERVISOR_xen_version(PVOID hypercall_stubs, int cmd, void *arg)
    2.19  {
    2.20 -  PCHAR xen_version_func = xpdd->hypercall_stubs;
    2.21 +  PCHAR xen_version_func = hypercall_stubs;
    2.22    xen_version_func += __HYPERVISOR_xen_version * 32;
    2.23    return _hypercall2(xen_version_func, (xen_ulong_t)cmd, (xen_ulong_t)arg);
    2.24  }
    2.25  
    2.26  static __inline int
    2.27 -HYPERVISOR_grant_table_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *uop, unsigned int count)
    2.28 +_HYPERVISOR_grant_table_op(PVOID hypercall_stubs, int cmd, void *uop, unsigned int count)
    2.29  {
    2.30 -  PCHAR grant_table_op_func = xpdd->hypercall_stubs;
    2.31 +  PCHAR grant_table_op_func = hypercall_stubs;
    2.32    grant_table_op_func += __HYPERVISOR_grant_table_op * 32;
    2.33    return _hypercall3(grant_table_op_func, (xen_ulong_t)cmd, (xen_ulong_t)uop, (xen_ulong_t)count);
    2.34  }
    2.35  
    2.36 -#if 0
    2.37  static __inline int
    2.38 -HYPERVISOR_mmu_update(PXENPCI_DEVICE_DATA xpdd, mmu_update_t *req, int count, int *success_count, domid_t domid)
    2.39 +_HYPERVISOR_hvm_op(PVOID hypercall_stubs, int op, struct xen_hvm_param *arg)
    2.40  {
    2.41 -  ASSERTMSG("mmu_update not yet supported under AMD64", FALSE);
    2.42 -/*
    2.43 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    2.44 -  long __res;
    2.45 -  long _domid = (long)domid;
    2.46 -  __asm {
    2.47 -    mov ebx, req
    2.48 -    mov ecx, count
    2.49 -    mov edx, success_count
    2.50 -    mov edi, _domid
    2.51 -    mov eax, hypercall_stubs
    2.52 -    add eax, (__HYPERVISOR_mmu_update * 32)
    2.53 -    call eax
    2.54 -    mov [__res], eax
    2.55 -  }
    2.56 -  return __res;
    2.57 -*/
    2.58 -  return -1;
    2.59 -}
    2.60 -#endif
    2.61 -
    2.62 -static __inline int
    2.63 -HYPERVISOR_hvm_op(PXENPCI_DEVICE_DATA xpdd, int op, struct xen_hvm_param *arg)
    2.64 -{
    2.65 -  PCHAR hvm_op_func = xpdd->hypercall_stubs;
    2.66 +  PCHAR hvm_op_func = hypercall_stubs;
    2.67    hvm_op_func += __HYPERVISOR_hvm_op * 32;
    2.68    return _hypercall2(hvm_op_func, (xen_ulong_t)op, (xen_ulong_t)arg);
    2.69  }
    2.70  
    2.71  static __inline int
    2.72 -HYPERVISOR_event_channel_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *op)
    2.73 +_HYPERVISOR_event_channel_op(PVOID hypercall_stubs, int cmd, void *op)
    2.74  {
    2.75 -  PCHAR event_channel_op_func = xpdd->hypercall_stubs;
    2.76 +  PCHAR event_channel_op_func = hypercall_stubs;
    2.77    event_channel_op_func += __HYPERVISOR_event_channel_op * 32;
    2.78    return _hypercall2(event_channel_op_func, (xen_ulong_t)cmd, (xen_ulong_t)op);
    2.79  }
    2.80  
    2.81  static __inline int
    2.82 -HYPERVISOR_sched_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *arg)
    2.83 +_HYPERVISOR_sched_op(PVOID hypercall_stubs, int cmd, void *arg)
    2.84  {
    2.85 -  PCHAR sched_op_func = xpdd->hypercall_stubs;
    2.86 +  PCHAR sched_op_func = hypercall_stubs;
    2.87    sched_op_func += __HYPERVISOR_sched_op * 32;
    2.88    return _hypercall2(sched_op_func, (xen_ulong_t)cmd, (xen_ulong_t)arg);
    2.89  }
    2.90  
    2.91  static __inline int
    2.92 -HYPERVISOR_shutdown(PXENPCI_DEVICE_DATA xpdd, unsigned int reason)
    2.93 +_HYPERVISOR_shutdown(PVOID hypercall_stubs, unsigned int reason)
    2.94  {
    2.95    struct sched_shutdown ss;
    2.96    int retval;
    2.97  
    2.98    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.99 -
   2.100 +  
   2.101    ss.reason = reason;
   2.102 -
   2.103 -  KdPrint((__DRIVER_NAME "     A\n"));
   2.104 -
   2.105 -  retval = HYPERVISOR_sched_op(xpdd, SCHEDOP_shutdown, &ss);
   2.106 -
   2.107 +  retval = _HYPERVISOR_sched_op(hypercall_stubs, SCHEDOP_shutdown, &ss);
   2.108 +  
   2.109    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.110  
   2.111    return retval;
   2.112 -}
   2.113 -
   2.114 -#if 0
   2.115 -static __inline ULONGLONG
   2.116 -hvm_get_parameter(PXENPCI_DEVICE_DATA xpdd, int hvm_param)
   2.117 -{
   2.118 -  struct xen_hvm_param a;
   2.119 -  int retval;
   2.120 -
   2.121 -  KdPrint((__DRIVER_NAME " --> hvm_get_parameter\n"));
   2.122 -  a.domid = DOMID_SELF;
   2.123 -  a.index = hvm_param;
   2.124 -  retval = HYPERVISOR_hvm_op(xpdd, HVMOP_get_param, &a);
   2.125 -  KdPrint((__DRIVER_NAME " hvm_get_parameter retval = %d\n", retval));
   2.126 -  KdPrint((__DRIVER_NAME " hvm_get_parameter value = %ld\n", a.value));
   2.127 -  KdPrint((__DRIVER_NAME " <-- hvm_get_parameter\n"));
   2.128 -  return a.value;
   2.129 -}
   2.130 -#endif
   2.131 \ No newline at end of file
   2.132 +}
   2.133 \ No newline at end of file
     3.1 --- a/xenpci/hypercall_x86.h	Sun Feb 27 11:14:20 2011 +1100
     3.2 +++ b/xenpci/hypercall_x86.h	Sun Feb 27 14:28:41 2011 +1100
     3.3 @@ -20,9 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fi
     3.4  */
     3.5  
     3.6  static __inline int
     3.7 -HYPERVISOR_memory_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *arg)
     3.8 +_HYPERVISOR_memory_op(PVOID hypercall_stubs, int cmd, void *arg)
     3.9  {
    3.10 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.11    long __res;
    3.12    __asm {
    3.13      mov ebx, cmd
    3.14 @@ -36,9 +35,8 @@ HYPERVISOR_memory_op(PXENPCI_DEVICE_DATA
    3.15  }
    3.16  
    3.17  static __inline int
    3.18 -HYPERVISOR_sched_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *arg)
    3.19 +_HYPERVISOR_sched_op(PVOID hypercall_stubs, int cmd, void *arg)
    3.20  {
    3.21 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.22    long __res;
    3.23    __asm {
    3.24      mov ebx, cmd
    3.25 @@ -52,9 +50,8 @@ HYPERVISOR_sched_op(PXENPCI_DEVICE_DATA 
    3.26  }
    3.27  
    3.28  static __inline int
    3.29 -HYPERVISOR_xen_version(PXENPCI_DEVICE_DATA xpdd, int cmd, void *arg)
    3.30 +_HYPERVISOR_xen_version(PVOID hypercall_stubs, int cmd, void *arg)
    3.31  {
    3.32 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.33    long __res;
    3.34    __asm {
    3.35      mov ebx, cmd
    3.36 @@ -68,9 +65,8 @@ HYPERVISOR_xen_version(PXENPCI_DEVICE_DA
    3.37  }
    3.38  
    3.39  static __inline int
    3.40 -HYPERVISOR_grant_table_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *uop, unsigned int count)
    3.41 +_HYPERVISOR_grant_table_op(PVOID hypercall_stubs, int cmd, void *uop, unsigned int count)
    3.42  {
    3.43 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.44    long __res;
    3.45    __asm {
    3.46      mov ebx, cmd
    3.47 @@ -85,45 +81,8 @@ HYPERVISOR_grant_table_op(PXENPCI_DEVICE
    3.48  }
    3.49  
    3.50  static __inline int
    3.51 -HYPERVISOR_mmu_update(PXENPCI_DEVICE_DATA xpdd, mmu_update_t *req, int count, int *success_count, domid_t domid)
    3.52 +_HYPERVISOR_hvm_op(PVOID hypercall_stubs, int op, struct xen_hvm_param *arg)
    3.53  {
    3.54 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.55 -  long __res;
    3.56 -  long _domid = (long)domid;
    3.57 -  __asm {
    3.58 -    mov ebx, req
    3.59 -    mov ecx, count
    3.60 -    mov edx, success_count
    3.61 -    mov edi, _domid
    3.62 -    mov eax, hypercall_stubs
    3.63 -    add eax, (__HYPERVISOR_mmu_update * 32)
    3.64 -    call eax
    3.65 -    mov [__res], eax
    3.66 -  }
    3.67 -  return __res;
    3.68 -}
    3.69 -
    3.70 -static __inline int
    3.71 -HYPERVISOR_console_io(PXENPCI_DEVICE_DATA xpdd, int cmd, int count, char *string)
    3.72 -{
    3.73 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.74 -  long __res;
    3.75 -  __asm {
    3.76 -    mov ebx, cmd
    3.77 -    mov ecx, count
    3.78 -    mov edx, string
    3.79 -    mov eax, hypercall_stubs
    3.80 -    add eax, (__HYPERVISOR_console_io * 32)
    3.81 -    call eax
    3.82 -    mov [__res], eax
    3.83 -  }
    3.84 -  return __res;
    3.85 -}
    3.86 -
    3.87 -static __inline int
    3.88 -HYPERVISOR_hvm_op(PXENPCI_DEVICE_DATA xpdd, int op, struct xen_hvm_param *arg)
    3.89 -{
    3.90 -  char *hypercall_stubs = xpdd->hypercall_stubs;
    3.91    long __res;
    3.92    __asm {
    3.93      mov ebx, op
    3.94 @@ -137,9 +96,8 @@ HYPERVISOR_hvm_op(PXENPCI_DEVICE_DATA xp
    3.95  }
    3.96  
    3.97  static __inline int
    3.98 -HYPERVISOR_event_channel_op(PXENPCI_DEVICE_DATA xpdd, int cmd, void *op)
    3.99 +_HYPERVISOR_event_channel_op(PVOID hypercall_stubs, int cmd, void *op)
   3.100  {
   3.101 -  char *hypercall_stubs = xpdd->hypercall_stubs;
   3.102    long __res;
   3.103    __asm {
   3.104      mov ebx, cmd
     4.1 --- a/xenpci/memory.c	Sun Feb 27 11:14:20 2011 +1100
     4.2 +++ b/xenpci/memory.c	Sun Feb 27 14:28:41 2011 +1100
     4.3 @@ -2,14 +2,13 @@
     4.4  
     4.5  /* must be called at <= DISPATCH_LEVEL if hypercall_stubs == NULL */
     4.6  
     4.7 -#if !defined(__ia64__)
     4.8 -
     4.9  #define XEN_SIGNATURE_LOWER 0x40000000
    4.10  #define XEN_SIGNATURE_UPPER 0x4000FFFF
    4.11  
    4.12 -NTSTATUS
    4.13 -hvm_get_stubs(PXENPCI_DEVICE_DATA xpdd)
    4.14 +PVOID
    4.15 +hvm_get_hypercall_stubs()
    4.16  {
    4.17 +  PVOID hypercall_stubs;
    4.18    ULONG base;
    4.19    DWORD32 cpuid_output[4];
    4.20    char xensig[13];
    4.21 @@ -31,53 +30,29 @@ hvm_get_stubs(PXENPCI_DEVICE_DATA xpdd)
    4.22    if (base > XEN_SIGNATURE_UPPER)
    4.23    {
    4.24      KdPrint((__DRIVER_NAME "     Cannot find Xen signature\n"));
    4.25 -    return STATUS_UNSUCCESSFUL;
    4.26 +    return NULL;
    4.27    }
    4.28  
    4.29    __cpuid(cpuid_output, base + 2);
    4.30    pages = cpuid_output[0];
    4.31    msr = cpuid_output[1];
    4.32  
    4.33 -  if (!xpdd->hypercall_stubs)
    4.34 -  {
    4.35 -    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    4.36 -    xpdd->hypercall_stubs = ExAllocatePoolWithTag(NonPagedPool, pages * PAGE_SIZE, XENPCI_POOL_TAG);
    4.37 -  }
    4.38 -  KdPrint((__DRIVER_NAME "     Hypercall area at %p\n", xpdd->hypercall_stubs));
    4.39 +  hypercall_stubs = ExAllocatePoolWithTag(NonPagedPool, pages * PAGE_SIZE, XENPCI_POOL_TAG);
    4.40 +  KdPrint((__DRIVER_NAME "     Hypercall area at %p\n", hypercall_stubs));
    4.41  
    4.42 -  if (!xpdd->hypercall_stubs)
    4.43 -    return 1;
    4.44 +  if (!hypercall_stubs)
    4.45 +    return NULL;
    4.46    for (i = 0; i < pages; i++) {
    4.47      ULONGLONG pfn;
    4.48 -    pfn = (MmGetPhysicalAddress(xpdd->hypercall_stubs + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
    4.49 +    pfn = (MmGetPhysicalAddress((PUCHAR)hypercall_stubs + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
    4.50      //KdPrint((__DRIVER_NAME "     pfn = %16lX\n", pfn));
    4.51      __writemsr(msr, (pfn << PAGE_SHIFT) + i);
    4.52    }
    4.53 -  return STATUS_SUCCESS;
    4.54 -}
    4.55 -
    4.56 -NTSTATUS
    4.57 -hvm_free_stubs(PXENPCI_DEVICE_DATA xpdd)
    4.58 -{
    4.59 -  ExFreePoolWithTag(xpdd->hypercall_stubs, XENPCI_POOL_TAG);
    4.60 -
    4.61 -  return STATUS_SUCCESS;
    4.62 +  return hypercall_stubs;
    4.63  }
    4.64  
    4.65 -#else
    4.66 -
    4.67 -NTSTATUS
    4.68 -hvm_get_stubs(PXENPCI_DEVICE_DATA xpdd)
    4.69 +VOID
    4.70 +hvm_free_hypercall_stubs(PVOID hypercall_stubs)
    4.71  {
    4.72 -  UNREFERENCED_PARAMETER(xpdd);
    4.73 -  return STATUS_SUCCESS;
    4.74 +  ExFreePoolWithTag(hypercall_stubs, XENPCI_POOL_TAG);
    4.75  }
    4.76 -
    4.77 -NTSTATUS
    4.78 -hvm_free_stubs(PXENPCI_DEVICE_DATA xpdd)
    4.79 -{
    4.80 -  UNREFERENCED_PARAMETER(xpdd);
    4.81 -  return STATUS_SUCCESS;
    4.82 -}
    4.83 -
    4.84 -#endif
     5.1 --- a/xenpci/xenpci.c	Sun Feb 27 11:14:20 2011 +1100
     5.2 +++ b/xenpci/xenpci.c	Sun Feb 27 14:28:41 2011 +1100
     5.3 @@ -35,6 +35,18 @@ static EVT_WDF_DRIVER_DEVICE_ADD XenPci_
     5.4  static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPci_EvtDeviceUsageNotification;
     5.5  static EVT_WDF_DEVICE_PREPARE_HARDWARE XenHide_EvtDevicePrepareHardware;
     5.6  
     5.7 +/* this is supposed to be defined in wdm.h, but isn't */
     5.8 +NTSTATUS 
     5.9 +  KeInitializeCrashDumpHeader(
    5.10 +    IN ULONG  Type,
    5.11 +    IN ULONG  Flags,
    5.12 +    OUT PVOID  Buffer,
    5.13 +    IN ULONG  BufferSize,
    5.14 +    OUT PULONG  BufferNeeded OPTIONAL
    5.15 +    );
    5.16 +
    5.17 +#define DUMP_TYPE_FULL 1
    5.18 +
    5.19  static VOID
    5.20  XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
    5.21  {
    5.22 @@ -552,6 +564,109 @@ XenPci_EvtDriverUnload(WDFDRIVER driver)
    5.23    #endif  
    5.24  }
    5.25  
    5.26 +/* we need to balloon down very early on in the case of PoD, so things get a little messy */
    5.27 +static PMDL
    5.28 +XenPci_InitialBalloonDown()
    5.29 +{
    5.30 +  PVOID hypercall_stubs;
    5.31 +  domid_t domid = DOMID_SELF;
    5.32 +  ULONG maximum_reservation;
    5.33 +  ULONG current_reservation;
    5.34 +  ULONG extra_kb;
    5.35 +  ULONG extra_mb;
    5.36 +  ULONG ret;
    5.37 +  struct xen_memory_reservation reservation;
    5.38 +  xen_pfn_t *pfns;
    5.39 +  PMDL head = NULL;
    5.40 +  PMDL mdl;
    5.41 +  int i, j;
    5.42 +
    5.43 +  FUNCTION_ENTER();
    5.44 +  
    5.45 +  hypercall_stubs = hvm_get_hypercall_stubs();
    5.46 +  if (!hypercall_stubs)
    5.47 +  {
    5.48 +    KdPrint((__DRIVER_NAME "     Failed to copy hypercall stubs. Maybe not running under Xen?\n"));
    5.49 +    return NULL;
    5.50 +  }
    5.51 +  ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_maximum_reservation, &domid);
    5.52 +  KdPrint((__DRIVER_NAME "     XENMEM_maximum_reservation = %d\n", ret));
    5.53 +  maximum_reservation = ret;
    5.54 +  ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_current_reservation, &domid);
    5.55 +  KdPrint((__DRIVER_NAME "     XENMEM_current_reservation = %d\n", ret));
    5.56 +  current_reservation = ret;
    5.57 +
    5.58 +  extra_kb = (maximum_reservation - current_reservation) << 2;
    5.59 +  extra_mb = ((extra_kb + 1023) >> 10);
    5.60 +
    5.61 +  KdPrint((__DRIVER_NAME "     Trying to give %d MB to Xen\n", extra_mb));
    5.62 +
    5.63 +  /* this code is mostly duplicated from the actual balloon thread... too hard to reuse */
    5.64 +  for (j = 0; j < (int)extra_mb; j++)
    5.65 +  {  
    5.66 +    PHYSICAL_ADDRESS alloc_low;
    5.67 +    PHYSICAL_ADDRESS alloc_high;
    5.68 +    PHYSICAL_ADDRESS alloc_skip;
    5.69 +    alloc_low.QuadPart = 0;
    5.70 +    alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
    5.71 +    alloc_skip.QuadPart = 0;
    5.72 +    #if (NTDDI_VERSION >= NTDDI_WS03SP1)
    5.73 +    /* our contract says that we must zero pages before returning to xen, so we can't use MM_DONT_ZERO_ALLOCATION */
    5.74 +    mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS, MmCached, 0);
    5.75 +    #else
    5.76 +    mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS);
    5.77 +    #endif
    5.78 +    if (!mdl)
    5.79 +    {
    5.80 +      /* this should actually never happen. If we can't allocate the memory it means windows is using it, and if it was using it we would have crashed already... */
    5.81 +      KdPrint((__DRIVER_NAME "     Initial Balloon Down failed\n"));
    5.82 +      break;
    5.83 +    }
    5.84 +    else
    5.85 +    {
    5.86 +      int pfn_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
    5.87 +      if (pfn_count != BALLOON_UNIT_PAGES)
    5.88 +      {
    5.89 +        /* we could probably do this better but it will only happen in low memory conditions... */
    5.90 +        KdPrint((__DRIVER_NAME "     wanted %d pages got %d pages\n", BALLOON_UNIT_PAGES, pfn_count));
    5.91 +        MmFreePagesFromMdl(mdl);
    5.92 +        ExFreePool(mdl);
    5.93 +        break;
    5.94 +      }
    5.95 +      pfns = ExAllocatePoolWithTag(NonPagedPool, pfn_count * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    5.96 +      /* sizeof(xen_pfn_t) may not be the same as PPFN_NUMBER */
    5.97 +      for (i = 0; i < pfn_count; i++)
    5.98 +        pfns[i] = (xen_pfn_t)(MmGetMdlPfnArray(mdl)[i]);
    5.99 +      reservation.address_bits = 0;
   5.100 +      reservation.extent_order = 0;
   5.101 +      reservation.domid = DOMID_SELF;
   5.102 +      reservation.nr_extents = pfn_count;
   5.103 +      #pragma warning(disable: 4127) /* conditional expression is constant */
   5.104 +      set_xen_guest_handle(reservation.extent_start, pfns);
   5.105 +      
   5.106 +      KdPrint((__DRIVER_NAME "     Calling HYPERVISOR_memory_op(XENMEM_decrease_reservation) - pfn_count = %d\n", pfn_count));
   5.107 +      ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_decrease_reservation, &reservation);
   5.108 +      ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
   5.109 +      KdPrint((__DRIVER_NAME "     decreased %d pages\n", ret));
   5.110 +      if (head)
   5.111 +      {
   5.112 +        mdl->Next = head;
   5.113 +        head = mdl;
   5.114 +      }
   5.115 +      else
   5.116 +      {
   5.117 +        head = mdl;
   5.118 +      }
   5.119 +    }
   5.120 +  }
   5.121 +  
   5.122 +  hvm_free_hypercall_stubs(hypercall_stubs);
   5.123 +  
   5.124 +  FUNCTION_EXIT();
   5.125 +  
   5.126 +  return head;
   5.127 +}
   5.128 +
   5.129  NTSTATUS
   5.130  DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
   5.131  {
   5.132 @@ -571,6 +686,8 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
   5.133    DECLARE_CONST_UNICODE_STRING(txt_always_patch_name, L"txt_patch_tpr_always");
   5.134    WDFSTRING wdf_system_start_options;
   5.135    UNICODE_STRING system_start_options;
   5.136 +  PVOID dump_page;
   5.137 +  ULONG dump_header_size;
   5.138    
   5.139    UNREFERENCED_PARAMETER(RegistryPath);
   5.140  
   5.141 @@ -582,9 +699,16 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
   5.142    XenPci_HookDbgPrint();
   5.143    #endif
   5.144  
   5.145 +  XenPci_InitialBalloonDown();
   5.146 +    
   5.147 +  dump_page = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
   5.148 +  status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, dump_page, PAGE_SIZE, &dump_header_size);
   5.149 +  KdPrint((__DRIVER_NAME "     KeInitializeCrashDumpHeader status = %08x, size = %d\n", status, dump_header_size));
   5.150 +
   5.151    /* again after enabling DbgPrint hooking */
   5.152    KdPrint((__DRIVER_NAME " " VER_FILEVERSION_STR "\n"));
   5.153  
   5.154 +  
   5.155    WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
   5.156    config.EvtDriverUnload = XenPci_EvtDriverUnload;
   5.157    status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
     6.1 --- a/xenpci/xenpci.h	Sun Feb 27 11:14:20 2011 +1100
     6.2 +++ b/xenpci/xenpci.h	Sun Feb 27 14:28:41 2011 +1100
     6.3 @@ -72,10 +72,11 @@ DEFINE_GUID( GUID_XENPCI_DEVCLASS, 0xC82
     6.4  #define EVT_ACTION_FLAGS_DEFAULT    0 /* no special flags */
     6.5  #define EVT_ACTION_FLAGS_NO_SUSPEND 1 /* should not be fired on EVT_ACTION_TYPE_SUSPEND event */
     6.6  
     6.7 -
     6.8  #define XEN_PV_PRODUCT_NUMBER   0x0002
     6.9  #define XEN_PV_PRODUCT_BUILD    0x00000001
    6.10  
    6.11 +#define BALLOON_UNIT_PAGES (BALLOON_UNITS >> PAGE_SHIFT)
    6.12 +
    6.13  extern ULONG qemu_protocol_version;
    6.14  
    6.15  typedef struct _ev_action_t {
    6.16 @@ -330,14 +331,27 @@ EVT_WDF_FILE_CLOSE XenPci_EvtFileClose;
    6.17  EVT_WDF_FILE_CLEANUP XenPci_EvtFileCleanup;
    6.18  EVT_WDF_IO_QUEUE_IO_DEFAULT XenPci_EvtIoDefault;
    6.19  
    6.20 +#define HYPERVISOR_memory_op(xpdd, cmd, arg) _HYPERVISOR_memory_op(xpdd->hypercall_stubs, cmd, arg)
    6.21 +#define HYPERVISOR_xen_version(xpdd, cmd, arg) _HYPERVISOR_xen_version(xpdd->hypercall_stubs, cmd, arg)
    6.22 +#define HYPERVISOR_grant_table_op(xpdd, cmd, uop, count) _HYPERVISOR_grant_table_op(xpdd->hypercall_stubs, cmd, uop, count)
    6.23 +#define HYPERVISOR_hvm_op(xpdd, op, arg) _HYPERVISOR_hvm_op(xpdd->hypercall_stubs, op, arg)
    6.24 +#define HYPERVISOR_event_channel_op(xpdd, cmd, op) _HYPERVISOR_event_channel_op(xpdd->hypercall_stubs, cmd, op)
    6.25 +#define HYPERVISOR_sched_op(xpdd, cmd, arg) _HYPERVISOR_sched_op(xpdd->hypercall_stubs, cmd, arg)
    6.26 +#define HYPERVISOR_shutdown(xpdd, reason) _HYPERVISOR_shutdown(xpdd->hypercall_stubs, reason)
    6.27 +
    6.28 +#define hvm_get_parameter(xvdd, hvm_param) _hvm_get_parameter(xvdd->hypercall_stubs, hvm_param);
    6.29 +#define hvm_set_parameter(xvdd, hvm_param, value) _hvm_set_parameter(xvdd->hypercall_stubs, hvm_param, value);
    6.30 +#define hvm_shutdown(xvdd, reason) _hvm_shutdown(xvdd->hypercall_stubs, reason);
    6.31 +#define HYPERVISOR_yield(xvdd) _HYPERVISOR_yield(xvdd->hypercall_stubs);
    6.32 +
    6.33  #include "hypercall.h"
    6.34  
    6.35  #define XBT_NIL ((xenbus_transaction_t)0)
    6.36  
    6.37 -NTSTATUS
    6.38 -hvm_get_stubs(PXENPCI_DEVICE_DATA xpdd);
    6.39 -NTSTATUS
    6.40 -hvm_free_stubs(PXENPCI_DEVICE_DATA xpdd);
    6.41 +PVOID
    6.42 +hvm_get_hypercall_stubs();
    6.43 +VOID
    6.44 +hvm_free_hypercall_stubs(PVOID hypercall_stubs);
    6.45  
    6.46  EVT_WDF_DEVICE_PREPARE_HARDWARE XenPci_EvtDevicePrepareHardware;
    6.47  EVT_WDF_DEVICE_RELEASE_HARDWARE XenPci_EvtDeviceReleaseHardware;
    6.48 @@ -354,57 +368,6 @@ XenPci_HideQemuDevices();
    6.49  extern WDFCOLLECTION qemu_hide_devices;
    6.50  extern USHORT qemu_hide_flags_value;
    6.51  
    6.52 -#if 0
    6.53 -NTSTATUS
    6.54 -XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.55 -NTSTATUS
    6.56 -XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.57 -NTSTATUS
    6.58 -XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.59 -NTSTATUS
    6.60 -XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.61 -NTSTATUS
    6.62 -XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.63 -NTSTATUS
    6.64 -XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.65 -NTSTATUS
    6.66 -XenPci_Irp_Write_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.67 -NTSTATUS
    6.68 -XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.69 -NTSTATUS
    6.70 -XenPci_SystemControl_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.71 -
    6.72 -NTSTATUS
    6.73 -XenPci_Irp_Create_XenBus(PDEVICE_OBJECT device_object, PIRP irp);
    6.74 -NTSTATUS
    6.75 -XenPci_Irp_Close_XenBus(PDEVICE_OBJECT device_object, PIRP irp);
    6.76 -NTSTATUS
    6.77 -XenPci_Irp_Read_XenBus(PDEVICE_OBJECT device_object, PIRP irp);
    6.78 -NTSTATUS
    6.79 -XenPci_Irp_Write_XenBus(PDEVICE_OBJECT device_object, PIRP irp);
    6.80 -NTSTATUS
    6.81 -XenPci_Irp_Cleanup_XenBus(PDEVICE_OBJECT device_object, PIRP irp);
    6.82 -
    6.83 -NTSTATUS
    6.84 -XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.85 -//NTSTATUS
    6.86 -//XenPci_Dummy_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.87 -NTSTATUS
    6.88 -XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.89 -NTSTATUS
    6.90 -XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.91 -NTSTATUS
    6.92 -XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.93 -NTSTATUS
    6.94 -XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.95 -NTSTATUS
    6.96 -XenPci_Irp_Write_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.97 -NTSTATUS
    6.98 -XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
    6.99 -NTSTATUS
   6.100 -XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
   6.101 -#endif
   6.102 -
   6.103  NTSTATUS
   6.104  XenPci_Pdo_Suspend(WDFDEVICE device);
   6.105  NTSTATUS
     7.1 --- a/xenpci/xenpci_fdo.c	Sun Feb 27 11:14:20 2011 +1100
     7.2 +++ b/xenpci/xenpci_fdo.c	Sun Feb 27 14:28:41 2011 +1100
     7.3 @@ -104,15 +104,18 @@ XenPci_EvtDeviceQueryRemove(WDFDEVICE de
     7.4  static NTSTATUS
     7.5  XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
     7.6  {
     7.7 -  NTSTATUS status;
     7.8    struct xen_add_to_physmap xatp;
     7.9    int ret;
    7.10  
    7.11    FUNCTION_ENTER();
    7.12  
    7.13 -  status = hvm_get_stubs(xpdd);
    7.14 -  if (!NT_SUCCESS(status))
    7.15 -    return status;
    7.16 +  if (!xpdd->hypercall_stubs)
    7.17 +  {
    7.18 +    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    7.19 +    xpdd->hypercall_stubs = hvm_get_hypercall_stubs();
    7.20 +  }
    7.21 +  if (!xpdd->hypercall_stubs)
    7.22 +    return STATUS_UNSUCCESSFUL;
    7.23  
    7.24    if (!xpdd->shared_info_area)
    7.25    {
    7.26 @@ -221,8 +224,6 @@ XenPci_PrintPendingInterrupts()
    7.27  }
    7.28  #endif
    7.29  
    7.30 -#define BALLOON_UNIT_PAGES (BALLOON_UNITS >> PAGE_SHIFT)
    7.31 -
    7.32  static VOID
    7.33  XenPci_BalloonThreadProc(PVOID StartContext)
    7.34  {
    7.35 @@ -237,16 +238,20 @@ XenPci_BalloonThreadProc(PVOID StartCont
    7.36    int i;
    7.37    ULONG ret;
    7.38    int pfn_count;
    7.39 +  int timeout_ms = 1000;
    7.40    
    7.41    FUNCTION_ENTER();
    7.42  
    7.43    for(;;)
    7.44    {
    7.45 -    /* wait for 1 second if we have adjustments to make, or forever if we don't */
    7.46 +    /* back off exponentially if we have adjustments to make, or wait for event if we don't */
    7.47      if (xpdd->current_memory != new_target)
    7.48      {
    7.49 -      timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
    7.50 +      timeout.QuadPart = WDF_REL_TIMEOUT_IN_MS(timeout_ms);
    7.51        ptimeout = &timeout;
    7.52 +      timeout_ms <<= 1;
    7.53 +      if (timeout_ms > 60000)
    7.54 +        timeout_ms = 60000;
    7.55      }
    7.56      else
    7.57      {
    7.58 @@ -272,9 +277,6 @@ XenPci_BalloonThreadProc(PVOID StartCont
    7.59        KdPrint((__DRIVER_NAME "     Trying to take %d MB from Xen\n", new_target - xpdd->current_memory));
    7.60        while ((mdl = head) != NULL && xpdd->current_memory < new_target)
    7.61        {
    7.62 -        head = mdl->Next;
    7.63 -        mdl->Next = NULL;
    7.64 -        
    7.65          pfn_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
    7.66          pfns = ExAllocatePoolWithTag(NonPagedPool, pfn_count * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    7.67          /* sizeof(xen_pfn_t) may not be the same as PPFN_NUMBER */
    7.68 @@ -289,10 +291,22 @@ XenPci_BalloonThreadProc(PVOID StartCont
    7.69          
    7.70          KdPrint((__DRIVER_NAME "     Calling HYPERVISOR_memory_op(XENMEM_populate_physmap) - pfn_count = %d\n", pfn_count));
    7.71          ret = HYPERVISOR_memory_op(xpdd, XENMEM_populate_physmap, &reservation);
    7.72 -        ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
    7.73          KdPrint((__DRIVER_NAME "     populated %d pages\n", ret));
    7.74 -        /* TODO: what do we do if less than the required number of pages were populated??? can this happen??? */
    7.75 -        
    7.76 +        if(ret < (ULONG)pfn_count)
    7.77 +        {
    7.78 +          if(ret > 0)
    7.79 +          {
    7.80 +            /* We hit the Xen hard limit: reprobe. */
    7.81 +            reservation.nr_extents = ret;
    7.82 +            ret = HYPERVISOR_memory_op(xpdd, XENMEM_decrease_reservation, &reservation);
    7.83 +            KdPrint((__DRIVER_NAME "     decreased %d pages (xen is out of pages)\n", ret));
    7.84 +          }
    7.85 +          ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
    7.86 +          break;
    7.87 +        }
    7.88 +        ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
    7.89 +        head = mdl->Next;
    7.90 +        mdl->Next = NULL;        
    7.91          MmFreePagesFromMdl(mdl);
    7.92          ExFreePool(mdl);
    7.93          xpdd->current_memory++;
    7.94 @@ -361,6 +375,7 @@ XenPci_BalloonThreadProc(PVOID StartCont
    7.95          }
    7.96        }
    7.97      }
    7.98 +    timeout_ms = 1000;
    7.99    }
   7.100    //FUNCTION_EXIT();
   7.101  }
   7.102 @@ -778,9 +793,6 @@ XenPci_EvtDeviceD0EntryPostInterruptsEna
   7.103    PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
   7.104    PCHAR response;
   7.105    char *value;
   7.106 -  domid_t domid = DOMID_SELF;
   7.107 -  ULONG ret;
   7.108 -  xen_ulong_t *max_ram_page;
   7.109    HANDLE thread_handle;
   7.110  
   7.111    UNREFERENCED_PARAMETER(previous_state);
   7.112 @@ -799,13 +811,6 @@ XenPci_EvtDeviceD0EntryPostInterruptsEna
   7.113  
   7.114      response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
   7.115  
   7.116 -    ret = HYPERVISOR_memory_op(xpdd, XENMEM_current_reservation, &domid);
   7.117 -    KdPrint((__DRIVER_NAME "     XENMEM_current_reservation = %d\n", ret));
   7.118 -    ret = HYPERVISOR_memory_op(xpdd, XENMEM_maximum_reservation, &domid);
   7.119 -    KdPrint((__DRIVER_NAME "     XENMEM_maximum_reservation = %d\n", ret));
   7.120 -    ret = HYPERVISOR_memory_op(xpdd, XENMEM_maximum_ram_page, &max_ram_page);
   7.121 -    KdPrint((__DRIVER_NAME "     XENMEM_maximum_ram_page = %d\n", ret));
   7.122 -
   7.123      if (!xpdd->initial_memory)
   7.124      {
   7.125        XenBus_Read(xpdd, XBT_NIL, BALLOON_PATH, &value);
     8.1 --- a/xenpci/xenpci_pdo.c	Sun Feb 27 11:14:20 2011 +1100
     8.2 +++ b/xenpci/xenpci_pdo.c	Sun Feb 27 14:28:41 2011 +1100
     8.3 @@ -1494,7 +1494,6 @@ XenPci_Pdo_Suspend(WDFDEVICE device)
     8.4    NTSTATUS status = STATUS_SUCCESS;
     8.5    PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
     8.6    PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
     8.7 -  //LARGE_INTEGER wait_time;
     8.8    char path[128];
     8.9    PUCHAR in_ptr;
    8.10    UCHAR type;
    8.11 @@ -1548,7 +1547,7 @@ XenPci_Pdo_Suspend(WDFDEVICE device)
    8.12      xppdd->restart_on_resume = FALSE;
    8.13    }
    8.14  
    8.15 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    8.16 +  FUNCTION_EXIT();
    8.17    
    8.18    return status;
    8.19  }