aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-03-15 13:25:30 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-03-15 13:25:30 +0000
commitddf12db57949a7becc3e991007ce12e28c2768bc (patch)
tree443084e9a779a40b8bf21a2b27d6801245548f0f
parent4280d3ee4cb16ef462172e1da5dc3a1ff5719782 (diff)
downloadxen-ddf12db57949a7becc3e991007ce12e28c2768bc.tar.gz
xen-ddf12db57949a7becc3e991007ce12e28c2768bc.tar.bz2
xen-ddf12db57949a7becc3e991007ce12e28c2768bc.zip
x86: adjust Dom0 initial memory allocation strategy
Simply trying order-9 allocations until they won't succeed anymore may consume unnecessarily much memory from the DMA zone (since the page allocator will try to fulfill the request by using memory from that zone when only lower order memory blocks are left in all other zones). To avoid using DMA zone memory, make alloc_chunk() try to allocate a second smaller chunk and use that one in favor of the first one if it came from a higher addressed memory. This way, all memory outside the DMA zone will be consumed before eating into that zone. Signed-off-by: Jan Beulich <jbeulich@novell.com>
-rw-r--r--xen/arch/x86/domain_build.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index 498726719f..7307cc919b 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -126,7 +126,8 @@ static struct page_info * __init alloc_chunk(
struct domain *d, unsigned long max_pages)
{
struct page_info *page;
- unsigned int order;
+ unsigned int order, free_order;
+
/*
* Allocate up to 2MB at a time: It prevents allocating very large chunks
* from DMA pools before the >4GB pool is fully depleted.
@@ -139,6 +140,26 @@ static struct page_info * __init alloc_chunk(
while ( (page = alloc_domheap_pages(d, order, 0)) == NULL )
if ( order-- == 0 )
break;
+ /*
+ * Make a reasonable attempt at finding a smaller chunk at a higher
+ * address, to avoid allocating from low memory as much as possible.
+ */
+ for ( free_order = order; page && order--; )
+ {
+ struct page_info *pg2;
+
+ if ( d->tot_pages + (1 << order) > d->max_pages )
+ continue;
+ pg2 = alloc_domheap_pages(d, order, 0);
+ if ( pg2 > page )
+ {
+ free_domheap_pages(page, free_order);
+ page = pg2;
+ free_order = order;
+ }
+ else if ( pg2 )
+ free_domheap_pages(pg2, order);
+ }
return page;
}