win-pvdrivers

changeset 924:35ec9d4ebf94 0.11.0.294

Updates to manage ballooning a bit better
author James Harper <james.harper@bendigoit.com.au>
date Sat May 21 19:38:53 2011 +1000 (2011-05-21)
parents 5c84e3cd00b2
children 80b2f4b8263b
files xenpci/xenpci.c xenpci/xenpci.h xenpci/xenpci_fdo.c
line diff
     1.1 --- a/xenpci/xenpci.c	Sat May 21 19:36:29 2011 +1000
     1.2 +++ b/xenpci/xenpci.c	Sat May 21 19:38:53 2011 +1000
     1.3 @@ -578,13 +578,16 @@ XenPci_InitialBalloonDown()
     1.4    ULONG maximum_reservation;
     1.5    ULONG current_reservation;
     1.6    ULONG extra_kb;
     1.7 -  ULONG extra_mb;
     1.8    ULONG ret;
     1.9    struct xen_memory_reservation reservation;
    1.10    xen_pfn_t *pfns;
    1.11    PMDL head = NULL;
    1.12    PMDL mdl;
    1.13    int i, j;
    1.14 +  ULONG curr_pfns_offset;
    1.15 +  PHYSICAL_ADDRESS alloc_low;
    1.16 +  PHYSICAL_ADDRESS alloc_high;
    1.17 +  PHYSICAL_ADDRESS alloc_skip;
    1.18  
    1.19    FUNCTION_ENTER();
    1.20    
    1.21 @@ -602,58 +605,53 @@ XenPci_InitialBalloonDown()
    1.22    current_reservation = ret;
    1.23  
    1.24    extra_kb = (maximum_reservation - current_reservation) << 2;
    1.25 -  extra_mb = ((extra_kb + 1023) >> 10);
    1.26  
    1.27 -  KdPrint((__DRIVER_NAME "     Trying to give %d MB to Xen\n", extra_mb));
    1.28 +  alloc_low.QuadPart = 0;
    1.29 +  alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
    1.30 +  alloc_skip.QuadPart = PAGE_SIZE;
    1.31 +
    1.32 +  KdPrint((__DRIVER_NAME "     Trying to give %d KB (%d MB) to Xen\n", extra_kb, extra_kb >> 10));
    1.33  
    1.34    /* this code is mostly duplicated from the actual balloon thread... too hard to reuse */
    1.35 -  for (j = 0; j < (int)extra_mb; j++)
    1.36 -  {  
    1.37 -    PHYSICAL_ADDRESS alloc_low;
    1.38 -    PHYSICAL_ADDRESS alloc_high;
    1.39 -    PHYSICAL_ADDRESS alloc_skip;
    1.40 -    alloc_low.QuadPart = 0;
    1.41 -    alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
    1.42 -    alloc_skip.QuadPart = 0;
    1.43 +  pfns = ExAllocatePoolWithTag(NonPagedPool, max(BALLOON_UNIT_PAGES, (64 << 8)) * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    1.44 +  curr_pfns_offset = 0;
    1.45 +  /* this makes sure we balloon up to the next multiple of BALLOON_UNITS_KB */
    1.46 +  for (j = 0; j < (int)extra_kb; j += BALLOON_UNITS_KB)
    1.47 +  {
    1.48      #if (NTDDI_VERSION >= NTDDI_WS03SP1)
    1.49      /* our contract says that we must zero pages before returning to xen, so we can't use MM_DONT_ZERO_ALLOCATION */
    1.50 -    mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS, MmCached, 0);
    1.51 +    mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS_KB * 1024, MmCached, 0);
    1.52      #else
    1.53 -    mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS);
    1.54 +    mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS_KB * 1024);
    1.55      #endif
    1.56 -    if (!mdl)
    1.57 +    if (!mdl || MmGetMdlByteCount(mdl) != BALLOON_UNITS_KB * 1024)
    1.58      {
    1.59        /* 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... */
    1.60        KdPrint((__DRIVER_NAME "     Initial Balloon Down failed\n"));
    1.61 -      KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000002, extra_mb, j, 0x00000000);
    1.62 +      KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000002, extra_kb, j, 0x00000000);
    1.63        break;
    1.64      }
    1.65      else
    1.66      {
    1.67 -      int pfn_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
    1.68 -      if (pfn_count != BALLOON_UNIT_PAGES)
    1.69 -      {
    1.70 -        /* we could probably do this better but it will only happen in low memory conditions... */
    1.71 -        KdPrint((__DRIVER_NAME "     wanted %d pages got %d pages\n", BALLOON_UNIT_PAGES, pfn_count));
    1.72 -        MmFreePagesFromMdl(mdl);
    1.73 -        ExFreePool(mdl);
    1.74 -        break;
    1.75 -      }
    1.76 -      pfns = ExAllocatePoolWithTag(NonPagedPool, pfn_count * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    1.77        /* sizeof(xen_pfn_t) may not be the same as PPFN_NUMBER */
    1.78 -      for (i = 0; i < pfn_count; i++)
    1.79 -        pfns[i] = (xen_pfn_t)(MmGetMdlPfnArray(mdl)[i]);
    1.80 -      reservation.address_bits = 0;
    1.81 -      reservation.extent_order = 0;
    1.82 -      reservation.domid = DOMID_SELF;
    1.83 -      reservation.nr_extents = pfn_count;
    1.84 -      #pragma warning(disable: 4127) /* conditional expression is constant */
    1.85 -      set_xen_guest_handle(reservation.extent_start, pfns);
    1.86 -      
    1.87 -      //KdPrint((__DRIVER_NAME "     Calling HYPERVISOR_memory_op(XENMEM_decrease_reservation) - pfn_count = %d\n", pfn_count));
    1.88 -      ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_decrease_reservation, &reservation);
    1.89 -      ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
    1.90 -      //KdPrint((__DRIVER_NAME "     decreased %d pages\n", ret));
    1.91 +      for (i = 0; i < BALLOON_UNIT_PAGES; i++)
    1.92 +      {
    1.93 +        pfns[curr_pfns_offset] = (xen_pfn_t)(MmGetMdlPfnArray(mdl)[i]);
    1.94 +        curr_pfns_offset++;
    1.95 +      }
    1.96 +      if (curr_pfns_offset == (ULONG)max(BALLOON_UNIT_PAGES, (64 << 8)) || j + BALLOON_UNITS_KB > (int)extra_kb)
    1.97 +      {
    1.98 +        reservation.address_bits = 0;
    1.99 +        reservation.extent_order = 0;
   1.100 +        reservation.domid = DOMID_SELF;
   1.101 +        reservation.nr_extents = curr_pfns_offset;
   1.102 +        #pragma warning(disable: 4127) /* conditional expression is constant */
   1.103 +        set_xen_guest_handle(reservation.extent_start, pfns);
   1.104 +        ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_decrease_reservation, &reservation);
   1.105 +        if (ret != curr_pfns_offset)
   1.106 +          FUNCTION_MSG("only decreased %d of %d pages\n", ret, curr_pfns_offset);
   1.107 +        curr_pfns_offset = 0;
   1.108 +      }
   1.109        if (head)
   1.110        {
   1.111          mdl->Next = head;
   1.112 @@ -664,8 +662,9 @@ XenPci_InitialBalloonDown()
   1.113          head = mdl;
   1.114        }
   1.115      }
   1.116 +//KdPrint((__DRIVER_NAME "     C\n"));
   1.117    }
   1.118 -  
   1.119 +  ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
   1.120    hvm_free_hypercall_stubs(hypercall_stubs);
   1.121    
   1.122    FUNCTION_EXIT();
     2.1 --- a/xenpci/xenpci.h	Sat May 21 19:36:29 2011 +1000
     2.2 +++ b/xenpci/xenpci.h	Sat May 21 19:38:53 2011 +1000
     2.3 @@ -77,7 +77,8 @@ DEFINE_GUID( GUID_XENPCI_DEVCLASS, 0xC82
     2.4  #define XEN_PV_PRODUCT_NUMBER   0x0002
     2.5  #define XEN_PV_PRODUCT_BUILD    0x00000001
     2.6  
     2.7 -#define BALLOON_UNIT_PAGES (BALLOON_UNITS >> PAGE_SHIFT)
     2.8 +#define BALLOON_UNITS_KB (1 * 1024) /* 1MB */
     2.9 +#define BALLOON_UNIT_PAGES ((BALLOON_UNITS_KB << 10) >> PAGE_SHIFT)
    2.10  
    2.11  extern ULONG qemu_protocol_version;
    2.12  
    2.13 @@ -187,13 +188,12 @@ typedef struct {
    2.14    
    2.15    struct xenstore_domain_interface *xen_store_interface;
    2.16  
    2.17 -#define BALLOON_UNITS (1024 * 1024) /* 1MB */
    2.18    PKTHREAD balloon_thread;
    2.19    KEVENT balloon_event;
    2.20    BOOLEAN balloon_shutdown;
    2.21 -  ULONG initial_memory;
    2.22 -  ULONG current_memory;
    2.23 -  ULONG target_memory;
    2.24 +  ULONG initial_memory_kb;
    2.25 +  ULONG current_memory_kb;
    2.26 +  ULONG target_memory_kb;
    2.27    
    2.28    /* xenbus related */
    2.29    XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
     3.1 --- a/xenpci/xenpci_fdo.c	Sat May 21 19:36:29 2011 +1000
     3.2 +++ b/xenpci/xenpci_fdo.c	Sat May 21 19:38:53 2011 +1000
     3.3 @@ -230,7 +230,7 @@ static VOID
     3.4  XenPci_BalloonThreadProc(PVOID StartContext)
     3.5  {
     3.6    PXENPCI_DEVICE_DATA xpdd = StartContext;
     3.7 -  ULONG new_target = xpdd->current_memory;
     3.8 +  ULONG new_target_kb = xpdd->current_memory_kb;
     3.9    LARGE_INTEGER timeout;
    3.10    PLARGE_INTEGER ptimeout;
    3.11    PMDL head;
    3.12 @@ -267,7 +267,7 @@ XenPci_BalloonThreadProc(PVOID StartCont
    3.13    for(;;)
    3.14    {
    3.15      /* back off exponentially if we have adjustments to make, or wait for event if we don't */
    3.16 -    if (xpdd->current_memory != new_target)
    3.17 +    if (xpdd->current_memory_kb != new_target_kb)
    3.18      {
    3.19        timeout.QuadPart = WDF_REL_TIMEOUT_IN_MS(timeout_ms);
    3.20        ptimeout = &timeout;
    3.21 @@ -283,22 +283,22 @@ XenPci_BalloonThreadProc(PVOID StartCont
    3.22      KeWaitForSingleObject(&xpdd->balloon_event, Executive, KernelMode, FALSE, ptimeout);
    3.23      if (xpdd->balloon_shutdown)
    3.24        PsTerminateSystemThread(0);
    3.25 -    KdPrint((__DRIVER_NAME "     Got balloon event, current = %d, target = %d\n", xpdd->current_memory, xpdd->target_memory));
    3.26 +    KdPrint((__DRIVER_NAME "     Got balloon event, current = %d, target = %d\n", xpdd->current_memory_kb, xpdd->target_memory_kb));
    3.27      /* not really worried about races here, but cache target so we only read it once */
    3.28 -    new_target = xpdd->target_memory;
    3.29 +    new_target_kb = xpdd->target_memory_kb;
    3.30      // perform some sanity checks on target_memory
    3.31      // make sure target <= initial
    3.32      // make sure target > some % of initial
    3.33      
    3.34 -    if (xpdd->current_memory == new_target)
    3.35 +    if (xpdd->current_memory_kb == new_target_kb)
    3.36      {
    3.37        KdPrint((__DRIVER_NAME "     No change to memory\n"));
    3.38        continue;
    3.39      }
    3.40 -    else if (xpdd->current_memory < new_target)
    3.41 +    else if (xpdd->current_memory_kb < new_target_kb)
    3.42      {
    3.43 -      KdPrint((__DRIVER_NAME "     Trying to take %d MB from Xen\n", new_target - xpdd->current_memory));
    3.44 -      while ((mdl = head) != NULL && xpdd->current_memory < new_target)
    3.45 +      KdPrint((__DRIVER_NAME "     Trying to take %d MB from Xen\n", new_target_kb - xpdd->current_memory_kb));
    3.46 +      while ((mdl = head) != NULL && xpdd->current_memory_kb < new_target_kb)
    3.47        {
    3.48          pfn_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
    3.49          pfns = ExAllocatePoolWithTag(NonPagedPool, pfn_count * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    3.50 @@ -332,13 +332,13 @@ XenPci_BalloonThreadProc(PVOID StartCont
    3.51          mdl->Next = NULL;        
    3.52          MmFreePagesFromMdl(mdl);
    3.53          ExFreePool(mdl);
    3.54 -        xpdd->current_memory++;
    3.55 +        xpdd->current_memory_kb += BALLOON_UNITS_KB;
    3.56        }
    3.57      }
    3.58      else
    3.59      {
    3.60 -      KdPrint((__DRIVER_NAME "     Trying to give %d MB to Xen\n", xpdd->current_memory - new_target));
    3.61 -      while (xpdd->current_memory > new_target)
    3.62 +      KdPrint((__DRIVER_NAME "     Trying to give %d MB to Xen\n", xpdd->current_memory_kb - new_target_kb));
    3.63 +      while (xpdd->current_memory_kb > new_target_kb)
    3.64        {
    3.65          PHYSICAL_ADDRESS alloc_low;
    3.66          PHYSICAL_ADDRESS alloc_high;
    3.67 @@ -358,9 +358,9 @@ XenPci_BalloonThreadProc(PVOID StartCont
    3.68  
    3.69          #if (NTDDI_VERSION >= NTDDI_WS03SP1)
    3.70          /* our contract says that we must zero pages before returning to xen, so we can't use MM_DONT_ZERO_ALLOCATION */
    3.71 -        mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS, MmCached, 0);
    3.72 +        mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS_KB * 1024, MmCached, 0);
    3.73          #else
    3.74 -        mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS);
    3.75 +        mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS_KB * 1024);
    3.76          #endif
    3.77          if (!mdl)
    3.78          {
    3.79 @@ -404,11 +404,11 @@ XenPci_BalloonThreadProc(PVOID StartCont
    3.80            {
    3.81              head = mdl;
    3.82            }
    3.83 -          xpdd->current_memory--;
    3.84 +          xpdd->current_memory_kb -= BALLOON_UNITS_KB;
    3.85          }
    3.86        }
    3.87      }
    3.88 -    KdPrint((__DRIVER_NAME "     Memory = %d, Balloon Target = %d\n", xpdd->current_memory, new_target));
    3.89 +    KdPrint((__DRIVER_NAME "     Memory = %d, Balloon Target = %d\n", xpdd->current_memory_kb, new_target_kb));
    3.90    }
    3.91    //FUNCTION_EXIT();
    3.92  }
    3.93 @@ -439,9 +439,9 @@ XenPci_BalloonHandler(char *Path, PVOID 
    3.94    }
    3.95  
    3.96    if (atoi(value) > 0)
    3.97 -    xpdd->target_memory = atoi(value) >> 10; /* convert to MB */
    3.98 +    xpdd->target_memory_kb = atoi(value);
    3.99  
   3.100 -  KdPrint((__DRIVER_NAME "     target memory value = %d (%s)\n", xpdd->target_memory, value));
   3.101 +  KdPrint((__DRIVER_NAME "     target memory value = %d (%s)\n", xpdd->target_memory_kb, value));
   3.102  
   3.103    XenBus_EndTransaction(xpdd, xbt, 0, &retry);
   3.104  
   3.105 @@ -844,16 +844,16 @@ XenPci_EvtDeviceD0EntryPostInterruptsEna
   3.106  
   3.107      response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
   3.108  
   3.109 -    if (!xpdd->initial_memory)
   3.110 +    if (!xpdd->initial_memory_kb)
   3.111      {
   3.112        XenBus_Read(xpdd, XBT_NIL, BALLOON_PATH, &value);
   3.113        if (atoi(value) > 0)
   3.114        {
   3.115 -        xpdd->initial_memory = atoi(value) >> 10; /* convert to MB */
   3.116 -        xpdd->current_memory = xpdd->initial_memory;
   3.117 -        xpdd->target_memory = xpdd->initial_memory;
   3.118 +        xpdd->initial_memory_kb = atoi(value);
   3.119 +        xpdd->current_memory_kb = xpdd->initial_memory_kb;
   3.120 +        xpdd->target_memory_kb = xpdd->initial_memory_kb;
   3.121        }
   3.122 -      KdPrint((__DRIVER_NAME "     Initial Memory Value = %d (%s)\n", xpdd->initial_memory, value));
   3.123 +      KdPrint((__DRIVER_NAME "     Initial Memory Value = %d (%s)\n", xpdd->initial_memory_kb, value));
   3.124        KeInitializeEvent(&xpdd->balloon_event, SynchronizationEvent, FALSE);
   3.125        xpdd->balloon_shutdown = FALSE;
   3.126        status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenPci_BalloonThreadProc, xpdd);