win-pvdrivers

diff xenpci/xenpci_fdo.c @ 794:aee3767c191d

Complete implementation of ballooning. Not well tested yet.
author James Harper <james.harper@bendigoit.com.au>
date Thu May 20 15:49:59 2010 +1000 (2010-05-20)
parents 467005e7f509
children 340f4430ab07
line diff
     1.1 --- a/xenpci/xenpci_fdo.c	Tue Mar 23 21:26:00 2010 +1100
     1.2 +++ b/xenpci/xenpci_fdo.c	Thu May 20 15:49:59 2010 +1000
     1.3 @@ -229,13 +229,18 @@ XenPci_BalloonThreadProc(PVOID StartCont
     1.4    LARGE_INTEGER timeout;
     1.5    PLARGE_INTEGER ptimeout;
     1.6    PMDL head = NULL;
     1.7 -  // use the memory_op(unsigned int op, void *arg) hypercall to adjust memory
     1.8 -  // use XENMEM_increase_reservation and XENMEM_decrease_reservation
     1.9 -
    1.10 +  PMDL mdl;      
    1.11 +  struct xen_memory_reservation reservation;
    1.12 +  xen_pfn_t *pfns;
    1.13 +  int i;
    1.14 +  ULONG ret;
    1.15 +  int pfn_count;
    1.16 +  
    1.17    FUNCTION_ENTER();
    1.18  
    1.19    for(;;)
    1.20    {
    1.21 +    /* wait for 1 second if we have adjustments to make, or forever if we don't */
    1.22      if (xpdd->current_memory != new_target)
    1.23      {
    1.24        timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
    1.25 @@ -262,12 +267,30 @@ XenPci_BalloonThreadProc(PVOID StartCont
    1.26      }
    1.27      else if (xpdd->current_memory < new_target)
    1.28      {
    1.29 -      PMDL mdl;      
    1.30        KdPrint((__DRIVER_NAME "     Trying to take %d MB from Xen\n", new_target - xpdd->current_memory));
    1.31        while ((mdl = head) != NULL && xpdd->current_memory < new_target)
    1.32        {
    1.33          head = mdl->Next;
    1.34          mdl->Next = NULL;
    1.35 +        
    1.36 +        pfn_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
    1.37 +        pfns = ExAllocatePoolWithTag(NonPagedPool, pfn_count * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    1.38 +        /* sizeof(xen_pfn_t) may not be the same as PPFN_NUMBER */
    1.39 +        for (i = 0; i < pfn_count; i++)
    1.40 +          pfns[i] = (xen_pfn_t)(MmGetMdlPfnArray(mdl)[i]);
    1.41 +        reservation.address_bits = 0;
    1.42 +        reservation.extent_order = 0;
    1.43 +        reservation.domid = DOMID_SELF;
    1.44 +        reservation.nr_extents = pfn_count;
    1.45 +        #pragma warning(disable: 4127) /* conditional expression is constant */
    1.46 +        set_xen_guest_handle(reservation.extent_start, pfns);
    1.47 +        
    1.48 +        KdPrint((__DRIVER_NAME "     Calling HYPERVISOR_memory_op(XENMEM_populate_physmap) - pfn_count = %d\n", pfn_count));
    1.49 +        ret = HYPERVISOR_memory_op(xpdd, XENMEM_populate_physmap, &reservation);
    1.50 +        ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
    1.51 +        KdPrint((__DRIVER_NAME "     populated %d pages\n", ret));
    1.52 +        /* TODO: what do we do if less than the required number of pages were populated??? */
    1.53 +        
    1.54          MmFreePagesFromMdl(mdl);
    1.55          ExFreePool(mdl);
    1.56          xpdd->current_memory++;
    1.57 @@ -281,11 +304,10 @@ XenPci_BalloonThreadProc(PVOID StartCont
    1.58          PHYSICAL_ADDRESS alloc_low;
    1.59          PHYSICAL_ADDRESS alloc_high;
    1.60          PHYSICAL_ADDRESS alloc_skip;
    1.61 -        PMDL mdl;
    1.62          alloc_low.QuadPart = 0;
    1.63          alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
    1.64          alloc_skip.QuadPart = 0;
    1.65 -        mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS);
    1.66 +        mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS, MmCached, MM_DONT_ZERO_ALLOCATION);
    1.67          if (!mdl)
    1.68          {
    1.69            KdPrint((__DRIVER_NAME "     Allocation failed - try again in 1 second\n"));
    1.70 @@ -293,6 +315,32 @@ XenPci_BalloonThreadProc(PVOID StartCont
    1.71          }
    1.72          else
    1.73          {
    1.74 +          int i;
    1.75 +          ULONG ret;
    1.76 +          int pfn_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
    1.77 +          if (pfn_count != BALLOON_UNIT_PAGES)
    1.78 +          {
    1.79 +            /* we could probably do this better but it will only happen in low memory conditions... */
    1.80 +            KdPrint((__DRIVER_NAME "     wanted %d pages got %d pages\n", BALLOON_UNIT_PAGES, pfn_count));
    1.81 +            MmFreePagesFromMdl(mdl);
    1.82 +            ExFreePool(mdl);
    1.83 +            break;
    1.84 +          }
    1.85 +          pfns = ExAllocatePoolWithTag(NonPagedPool, pfn_count * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
    1.86 +          /* sizeof(xen_pfn_t) may not be the same as PPFN_NUMBER */
    1.87 +          for (i = 0; i < pfn_count; i++)
    1.88 +            pfns[i] = (xen_pfn_t)(MmGetMdlPfnArray(mdl)[i]);
    1.89 +          reservation.address_bits = 0;
    1.90 +          reservation.extent_order = 0;
    1.91 +          reservation.domid = DOMID_SELF;
    1.92 +          reservation.nr_extents = pfn_count;
    1.93 +          #pragma warning(disable: 4127) /* conditional expression is constant */
    1.94 +          set_xen_guest_handle(reservation.extent_start, pfns);
    1.95 +          
    1.96 +          KdPrint((__DRIVER_NAME "     Calling HYPERVISOR_memory_op(XENMEM_decrease_reservation) - pfn_count = %d\n", pfn_count));
    1.97 +          ret = HYPERVISOR_memory_op(xpdd, XENMEM_decrease_reservation, &reservation);
    1.98 +          ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
    1.99 +          KdPrint((__DRIVER_NAME "     decreased %d pages\n", ret));
   1.100            if (head)
   1.101            {
   1.102              mdl->Next = head;