win-pvdrivers

changeset 591:caf4329df174

Started implementing ballooning. GPLPV will now allocate and free memory from Windows based on the memory/target value, but doesn't yet actually return it to xen.
author James Harper <james.harper@bendigoit.com.au>
date Wed Jun 10 13:46:38 2009 +1000 (2009-06-10)
parents d40c760a4f6b
children d1754b0e1ead
files xenpci/xenpci.h xenpci/xenpci_fdo.c
line diff
     1.1 --- a/xenpci/xenpci.h	Tue Jun 09 13:42:03 2009 +1000
     1.2 +++ b/xenpci/xenpci.h	Wed Jun 10 13:46:38 2009 +1000
     1.3 @@ -172,6 +172,14 @@ typedef struct {
     1.4  
     1.5    struct xenstore_domain_interface *xen_store_interface;
     1.6  
     1.7 +
     1.8 +#define BALLOON_UNITS (1024 * 1024) /* 1MB */
     1.9 +  PKTHREAD balloon_thread;
    1.10 +  KEVENT balloon_event;
    1.11 +  ULONG initial_memory;
    1.12 +  ULONG current_memory;
    1.13 +  ULONG target_memory;
    1.14 +  
    1.15    /* xenbus related */
    1.16    XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
    1.17    FAST_MUTEX xb_watch_mutex;
     2.1 --- a/xenpci/xenpci_fdo.c	Tue Jun 09 13:42:03 2009 +1000
     2.2 +++ b/xenpci/xenpci_fdo.c	Wed Jun 10 13:46:38 2009 +1000
     2.3 @@ -222,6 +222,129 @@ XenPci_PrintPendingInterrupts()
     2.4  }
     2.5  #endif
     2.6  
     2.7 +#define BALLOON_UNIT_PAGES (BALLOON_UNITS >> PAGE_SHIFT)
     2.8 +
     2.9 +static VOID
    2.10 +XenPci_BalloonThreadProc(PVOID StartContext)
    2.11 +{
    2.12 +  PXENPCI_DEVICE_DATA xpdd = StartContext;
    2.13 +  ULONG new_target = xpdd->current_memory;
    2.14 +  LARGE_INTEGER timeout;
    2.15 +  PLARGE_INTEGER ptimeout;
    2.16 +  PMDL head = NULL;
    2.17 +  // use the memory_op(unsigned int op, void *arg) hypercall to adjust memory
    2.18 +  // use XENMEM_increase_reservation and XENMEM_decrease_reservation
    2.19 +
    2.20 +  FUNCTION_ENTER();
    2.21 +
    2.22 +  for(;;)
    2.23 +  {
    2.24 +    if (xpdd->current_memory != new_target)
    2.25 +    {
    2.26 +      timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
    2.27 +      ptimeout = &timeout;
    2.28 +    }
    2.29 +    else
    2.30 +    {
    2.31 +      ptimeout = NULL;
    2.32 +    }
    2.33 +    KeWaitForSingleObject(&xpdd->balloon_event, Executive, KernelMode, FALSE, ptimeout);
    2.34 +//TODO: initiate shutdown here
    2.35 +    KdPrint((__DRIVER_NAME "     Got balloon event, current = %d, target = %d\n", xpdd->current_memory, xpdd->target_memory));
    2.36 +    /* not really worried about races here, but cache target so we only read it once */
    2.37 +    new_target = xpdd->target_memory;
    2.38 +    // perform some sanity checks on target_memory
    2.39 +    // make sure target <= initial
    2.40 +    // make sure target > some % of initial
    2.41 +    
    2.42 +    if (xpdd->current_memory == new_target)
    2.43 +    {
    2.44 +      KdPrint((__DRIVER_NAME "     No change to memory\n"));
    2.45 +      continue;
    2.46 +    }
    2.47 +    else if (xpdd->current_memory < new_target)
    2.48 +    {
    2.49 +      PMDL mdl;      
    2.50 +      KdPrint((__DRIVER_NAME "     Trying to take %d MB from Xen\n", new_target - xpdd->current_memory));
    2.51 +      while ((mdl = head) != NULL && xpdd->current_memory < new_target)
    2.52 +      {
    2.53 +        head = mdl->Next;
    2.54 +        mdl->Next = NULL;
    2.55 +        MmFreePagesFromMdl(mdl);
    2.56 +        ExFreePool(mdl);
    2.57 +        xpdd->current_memory++;
    2.58 +      }
    2.59 +    }
    2.60 +    else
    2.61 +    {
    2.62 +      KdPrint((__DRIVER_NAME "     Trying to give %d MB to Xen\n", xpdd->current_memory - new_target));
    2.63 +      while (xpdd->current_memory > new_target)
    2.64 +      {
    2.65 +        PHYSICAL_ADDRESS alloc_low;
    2.66 +        PHYSICAL_ADDRESS alloc_high;
    2.67 +        PHYSICAL_ADDRESS alloc_skip;
    2.68 +        PMDL mdl;
    2.69 +        alloc_low.QuadPart = 0;
    2.70 +        alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
    2.71 +        alloc_skip.QuadPart = 0;
    2.72 +        mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS);
    2.73 +        if (!mdl)
    2.74 +        {
    2.75 +          KdPrint((__DRIVER_NAME "     Allocation failed - try again in 1 second\n"));
    2.76 +          break;
    2.77 +        }
    2.78 +        else
    2.79 +        {
    2.80 +          if (head)
    2.81 +          {
    2.82 +            mdl->Next = head;
    2.83 +            head = mdl;
    2.84 +          }
    2.85 +          else
    2.86 +          {
    2.87 +            head = mdl;
    2.88 +          }
    2.89 +          xpdd->current_memory--;
    2.90 +        }
    2.91 +      }
    2.92 +    }
    2.93 +  }
    2.94 +  //FUNCTION_EXIT();
    2.95 +}
    2.96 +
    2.97 +static VOID
    2.98 +XenPci_BalloonHandler(char *Path, PVOID Data)
    2.99 +{
   2.100 +  WDFDEVICE device = Data;
   2.101 +  PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
   2.102 +  char *value;
   2.103 +  xenbus_transaction_t xbt;
   2.104 +  int retry;
   2.105 +
   2.106 +  UNREFERENCED_PARAMETER(Path);
   2.107 +
   2.108 +  FUNCTION_ENTER();
   2.109 +
   2.110 +  XenBus_StartTransaction(xpdd, &xbt);
   2.111 +
   2.112 +  XenBus_Read(xpdd, XBT_NIL, BALLOON_PATH, &value);
   2.113 +  
   2.114 +  if (atoi(value) > 0)
   2.115 +    xpdd->target_memory = atoi(value) >> 10; /* convert to MB */
   2.116 +
   2.117 +  KdPrint((__DRIVER_NAME "     target memory value = %d (%s)\n", xpdd->target_memory, value));
   2.118 +
   2.119 +  XenBus_EndTransaction(xpdd, xbt, 0, &retry);
   2.120 +
   2.121 +  XenPci_FreeMem(value);
   2.122 +
   2.123 +  KeSetEvent(&xpdd->balloon_event, IO_NO_INCREMENT, FALSE);
   2.124 +  
   2.125 +  // start a thread to allocate memory up to the required amount
   2.126 +
   2.127 +  FUNCTION_EXIT();
   2.128 +}
   2.129 +
   2.130  static VOID
   2.131  XenPci_Suspend0(PVOID context)
   2.132  {
   2.133 @@ -530,6 +653,9 @@ XenPci_EvtDeviceD0EntryPostInterruptsEna
   2.134    NTSTATUS status = STATUS_SUCCESS;
   2.135    PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
   2.136    PCHAR response;
   2.137 +  char *value;
   2.138 +  domid_t domid = DOMID_SELF;
   2.139 +  ULONG ret;
   2.140  
   2.141    UNREFERENCED_PARAMETER(previous_state);
   2.142  
   2.143 @@ -543,24 +669,30 @@ XenPci_EvtDeviceD0EntryPostInterruptsEna
   2.144  
   2.145    response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
   2.146  
   2.147 -#if 0
   2.148 -  response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
   2.149 -  KdPrint((__DRIVER_NAME "     balloon watch response = '%s'\n", response));
   2.150 -#endif
   2.151 +  ret = HYPERVISOR_memory_op(xpdd, XENMEM_current_reservation, &domid);
   2.152 +  KdPrint((__DRIVER_NAME "     XENMEM_current_reservation = %d\n", ret));
   2.153 +  ret = HYPERVISOR_memory_op(xpdd, XENMEM_maximum_reservation, &domid);
   2.154 +  KdPrint((__DRIVER_NAME "     XENMEM_maximum_reservation = %d\n", ret));
   2.155  
   2.156 -#if 0
   2.157 -  status = IoSetDeviceInterfaceState(&xpdd->legacy_interface_name, TRUE);
   2.158 -  if (!NT_SUCCESS(status))
   2.159 +  if (!xpdd->initial_memory)
   2.160    {
   2.161 -    KdPrint((__DRIVER_NAME "     IoSetDeviceInterfaceState (legacy) failed with status 0x%08x\n", status));
   2.162 +    XenBus_Read(xpdd, XBT_NIL, BALLOON_PATH, &value);
   2.163 +    if (atoi(value) > 0)
   2.164 +    {
   2.165 +      xpdd->initial_memory = atoi(value) >> 10; /* convert to MB */
   2.166 +      xpdd->current_memory = xpdd->initial_memory;
   2.167 +      xpdd->target_memory = xpdd->initial_memory;
   2.168 +    }
   2.169 +    KdPrint((__DRIVER_NAME "     Initial Memory Value = %d (%s)\n", xpdd->initial_memory, value));
   2.170 +    KeInitializeEvent(&xpdd->balloon_event, SynchronizationEvent, FALSE);
   2.171 +    status = PsCreateSystemThread(&xpdd->balloon_thread, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenPci_BalloonThreadProc, xpdd);
   2.172 +    if (!NT_SUCCESS(status))
   2.173 +    {
   2.174 +      KdPrint((__DRIVER_NAME "     Could not start balloon thread\n"));
   2.175 +      //return status;
   2.176 +    }    
   2.177    }
   2.178 -
   2.179 -  status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
   2.180 -  if (!NT_SUCCESS(status))
   2.181 -  {
   2.182 -    KdPrint((__DRIVER_NAME "     IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
   2.183 -  }
   2.184 -#endif
   2.185 +  response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, device);
   2.186  
   2.187    FUNCTION_EXIT();
   2.188    
   2.189 @@ -2162,33 +2294,3 @@ XenPci_SystemControl_Fdo(PDEVICE_OBJECT 
   2.190  }
   2.191  
   2.192  #endif
   2.193 -
   2.194 -#if 0
   2.195 -static VOID
   2.196 -XenPci_BalloonHandler(char *Path, PVOID Data)
   2.197 -{
   2.198 -  WDFDEVICE Device = Data;
   2.199 -  char *value;
   2.200 -  xenbus_transaction_t xbt;
   2.201 -  int retry;
   2.202 -
   2.203 -  UNREFERENCED_PARAMETER(Path);
   2.204 -
   2.205 -  KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
   2.206 -
   2.207 -  XenBus_StartTransaction(Device, &xbt);
   2.208 -
   2.209 -  XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
   2.210 -
   2.211 -  KdPrint((__DRIVER_NAME "     Balloon Value = %s\n", value));
   2.212 -
   2.213 -  // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
   2.214 -  // use XENMEM_increase_reservation and XENMEM_decrease_reservation
   2.215 -
   2.216 -  XenBus_EndTransaction(Device, xbt, 0, &retry);
   2.217 -
   2.218 -  XenPci_FreeMem(value);
   2.219 -
   2.220 -  KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
   2.221 -}
   2.222 -#endif