debuggers.hg

changeset 20943:217f6aa87716

mem hotplug: Fix an incorrect sanity check in memory add

Current, memory hot-add will fail if the new added memory is bigger
than current max_pages. This is really a stupid checking, considering
user may hot-add the biggest address riser card firstly.

This patch fix this issue. It check if all new added memory is
unpopulated, if yes, then it is ok.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 04 13:09:30 2010 +0000 (2010-02-04)
parents ece60564af6f
children 8c1889297084
files xen/arch/x86/x86_64/mm.c
line diff
     1.1 --- a/xen/arch/x86/x86_64/mm.c	Thu Feb 04 09:09:13 2010 +0000
     1.2 +++ b/xen/arch/x86/x86_64/mm.c	Thu Feb 04 13:09:30 2010 +0000
     1.3 @@ -1332,9 +1332,12 @@ int transfer_pages_to_heap(struct mem_ho
     1.4  
     1.5  int mem_hotadd_check(unsigned long spfn, unsigned long epfn)
     1.6  {
     1.7 -    unsigned long s, e, length;
     1.8 +    unsigned long s, e, length, sidx, eidx;
     1.9  
    1.10 -    if ( (spfn >= epfn) || (spfn < max_page) )
    1.11 +    if ( (spfn >= epfn) )
    1.12 +        return 0;
    1.13 +
    1.14 +    if (pfn_to_pdx(epfn) > (FRAMETABLE_SIZE / sizeof(*frame_table)))
    1.15          return 0;
    1.16  
    1.17      if ( (spfn | epfn) & ((1UL << PAGETABLE_ORDER) - 1) )
    1.18 @@ -1343,6 +1346,20 @@ int mem_hotadd_check(unsigned long spfn,
    1.19      if ( (spfn | epfn) & pfn_hole_mask )
    1.20          return 0;
    1.21  
    1.22 +    /* Make sure the new range is not present now */
    1.23 +    sidx = ((pfn_to_pdx(spfn) + PDX_GROUP_COUNT - 1)  & ~(PDX_GROUP_COUNT - 1))
    1.24 +            / PDX_GROUP_COUNT;
    1.25 +    eidx = (pfn_to_pdx(epfn - 1) & ~(PDX_GROUP_COUNT - 1)) / PDX_GROUP_COUNT;
    1.26 +    if (sidx >= eidx)
    1.27 +        return 0;
    1.28 +
    1.29 +    s = find_next_zero_bit(pdx_group_valid, eidx, sidx);
    1.30 +    if ( s > eidx )
    1.31 +        return 0;
    1.32 +    e = find_next_bit(pdx_group_valid, eidx, s);
    1.33 +    if ( e < eidx )
    1.34 +        return 0;
    1.35 +
    1.36      /* Caculate at most required m2p/compat m2p/frametable pages */
    1.37      s = (spfn & ~((1UL << (L2_PAGETABLE_SHIFT - 3)) - 1));
    1.38      e = (epfn + (1UL << (L2_PAGETABLE_SHIFT - 3)) - 1) &
    1.39 @@ -1433,8 +1450,11 @@ int memory_add(unsigned long spfn, unsig
    1.40          goto destroy_frametable;
    1.41  
    1.42      /* Set max_page as setup_m2p_table will use it*/
    1.43 -    max_page = epfn;
    1.44 -    max_pdx = pfn_to_pdx(max_page - 1) + 1;
    1.45 +    if (max_page < epfn)
    1.46 +    {
    1.47 +        max_page = epfn;
    1.48 +        max_pdx = pfn_to_pdx(max_page - 1) + 1;
    1.49 +    }
    1.50      total_pages += epfn - spfn;
    1.51  
    1.52      set_pdx_range(spfn, epfn);
    1.53 @@ -1443,7 +1463,7 @@ int memory_add(unsigned long spfn, unsig
    1.54      if ( ret )
    1.55          goto destroy_m2p;
    1.56  
    1.57 -    for ( i = old_max; i < epfn; i++ )
    1.58 +    for ( i = spfn; i < epfn; i++ )
    1.59          if ( iommu_map_page(dom0, i, i) )
    1.60              break;
    1.61