[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] Re: [PATCH 5/5] xen: release all pages within 1-1 p2m mappings



On Fri, Aug 19, 2011 at 03:57:20PM +0100, David Vrabel wrote:
> In xen_memory_setup() all reserved regions and gaps are set to an
> identity (1-1) p2m mapping.  If an available page has a PFN within one
> of these 1-1 mappings it will become accessible (as it MFN is lost) so
> release them before setting up the mapping.
> 
> This can make an additional 256 MiB or more of RAM available
> (depending on the size of the reserved regions in the memory map).

.. if the xen_start_info->nr_pages overlaps the reserved region.

> 
> Signed-off-by: David Vrabel <david.vrabel@xxxxxxx>
> ---
>  arch/x86/xen/setup.c |   88 
> ++++++++++++--------------------------------------
>  1 files changed, 21 insertions(+), 67 deletions(-)
> 
> diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
> index 93e4542..0f1cd69 100644
> --- a/arch/x86/xen/setup.c
> +++ b/arch/x86/xen/setup.c
> @@ -123,73 +123,33 @@ static unsigned long __init 
> xen_release_chunk(phys_addr_t start_addr,
>       return len;
>  }
>  
> -static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
> -                                                  const struct e820entry 
> *map,
> -                                                  int nr_map)
> +static unsigned long __init xen_set_identity_and_release(const struct 
> e820entry *list,
> +                                                      ssize_t map_size,
> +                                                      unsigned long nr_pages)
>  {
> -     phys_addr_t max_addr = PFN_PHYS(max_pfn);
> -     phys_addr_t last_end = ISA_END_ADDRESS;
> +     phys_addr_t avail_end = PFN_PHYS(nr_pages);
> +     phys_addr_t last_end = 0;
>       unsigned long released = 0;
> -     int i;
> -
> -     /* Free any unused memory above the low 1Mbyte. */
> -     for (i = 0; i < nr_map && last_end < max_addr; i++) {
> -             phys_addr_t end = map[i].addr;
> -             end = min(max_addr, end);
> -
> -             if (last_end < end)
> -                     released += xen_release_chunk(last_end, end);
> -             last_end = max(last_end, map[i].addr + map[i].size);
> -     }
> -
> -     if (last_end < max_addr)
> -             released += xen_release_chunk(last_end, max_addr);
> -
> -     printk(KERN_INFO "released %lu pages of unused memory\n", released);
> -     return released;
> -}
> -
> -static unsigned long __init xen_set_identity(const struct e820entry *list,
> -                                          ssize_t map_size)
> -{
> -     phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS;
> -     phys_addr_t start_pci = last;
>       const struct e820entry *entry;
> -     unsigned long identity = 0;
>       int i;
>  
>       for (i = 0, entry = list; i < map_size; i++, entry++) {
> -             phys_addr_t start = entry->addr;
> -             phys_addr_t end = start + entry->size;
> -
> -             if (start < last)
> -                     start = last;
> +             phys_addr_t begin = last_end;

The "begin" is a bit confusing. You are using the previous E820 entry's end - 
not
the beginning of this E820 entry. Doing a s/begin/last_end/ makes
the code a bit easier to understand.

> +             phys_addr_t end = entry->addr + entry->size;
>  
> -             if (end <= start)
> -                     continue;
> +             last_end = end;

Please include the comment:
/* This entry end. */

>  
> -             /* Skip over the 1MB region. */
> -             if (last > end)
> -                     continue;
> +             if (entry->type == E820_RAM || entry->type == E820_UNUSABLE)
> +                     end = entry->addr;

And:
/* Should encapsulate the gap between prev_end and this E820
entry's starting address. */
>  
> -             if ((entry->type == E820_RAM) || (entry->type == 
> E820_UNUSABLE)) {
> -                     if (start > start_pci)
> -                             identity += set_phys_range_identity(
> -                                             PFN_UP(start_pci), 
> PFN_DOWN(start));
> +             if (begin < end) {
> +                     if (begin < avail_end)
> +                             released += xen_release_chunk(begin, min(end, 
> avail_end));
>  
> -                     /* Without saving 'last' we would gooble RAM too
> -                      * at the end of the loop. */
> -                     last = end;
> -                     start_pci = end;
> -                     continue;
> +                     set_phys_range_identity(PFN_UP(begin), PFN_DOWN(end));

identity += set_phys_range ..
>               }
> -             start_pci = min(start, start_pci);
> -             last = end;
>       }
> -     if (last > start_pci)
> -             identity += set_phys_range_identity(
> -                                     PFN_UP(start_pci), PFN_DOWN(last));
> -     return identity;

OK, but you have ripped out the nice printk's that existed before. So add them
back in:


        printk(KERN_INFO "released %lu pages of unused memory\n", released);
        printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity);

as they are quite useful in the field.

> +     return released;
>  }
>  
>  static unsigned long __init xen_get_max_pages(void)
> @@ -217,7 +177,6 @@ char * __init xen_memory_setup(void)
>       struct xen_memory_map memmap;
>       unsigned long max_pages;
>       unsigned long extra_pages = 0;
> -     unsigned long identity_pages = 0;
>       int i;
>       int op;
>  
> @@ -250,7 +209,12 @@ char * __init xen_memory_setup(void)
>       if (max_pages > max_pfn)
>               extra_pages += max_pages - max_pfn;
>  
> -     extra_pages += xen_return_unused_memory(max_pfn, map, 
> memmap.nr_entries);
> +     /*
> +      * Set P2M for all non-RAM pages and E820 gaps to be identity
> +      * type PFNs.  Any RAM pages that would be made inaccesible by
> +      * this are first released.
> +      */
> +     extra_pages += xen_set_identity_and_release(map, memmap.nr_entries, 
> max_pfn);
>  
>       /*
>        * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
> @@ -294,10 +258,6 @@ char * __init xen_memory_setup(void)
>        * In domU, the ISA region is normal, usable memory, but we
>        * reserve ISA memory anyway because too many things poke
>        * about in there.
> -      *
> -      * In Dom0, the host E820 information can leave gaps in the
> -      * ISA range, which would cause us to release those pages.  To
> -      * avoid this, we unconditionally reserve them here.
>        */
>       e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
>                       E820_RESERVED);
> @@ -314,12 +274,6 @@ char * __init xen_memory_setup(void)
>  
>       sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
>  
> -     /*
> -      * Set P2M for all non-RAM pages and E820 gaps to be identity
> -      * type PFNs.
> -      */
> -     identity_pages = xen_set_identity(e820.map, e820.nr_map);
> -     printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages);
>       return "Xen";
>  }
>  
> -- 
> 1.7.2.5

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.