From: Oleksandr Dmytryshyn <oleksandr.dmytrys...@globallogic.com> This setting is used to adjust starting memory address allocated for kernel Dom0. To use 'rambase_pfn' setting just add for example 'dom0_rambase_pfn=0x80000' to the hypervisor command line. Note that 'dom0_rambase_pfn' should be aligned with the smallest memory chunk which use xen memory allocator.
Signed-off-by: Oleksandr Dmytryshyn <oleksandr.dmytrys...@globallogic.com> --- xen/arch/arm/domain_build.c | 24 +++++++++++++--- xen/common/page_alloc.c | 68 +++++++++++++++++++++++++++++++++++---------- xen/include/xen/mm.h | 2 ++ 3 files changed, 75 insertions(+), 19 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 2937ff7..b48718d 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -27,6 +27,9 @@ static unsigned int __initdata opt_dom0_max_vcpus; integer_param("dom0_max_vcpus", opt_dom0_max_vcpus); +static u64 __initdata opt_dom0_rambase_pfn = 0; +integer_param("dom0_rambase_pfn", opt_dom0_rambase_pfn); + int dom0_11_mapping = 1; #define DOM0_MEM_DEFAULT 0x8000000 /* 128 MiB */ @@ -248,6 +251,8 @@ static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo) const unsigned int min_order = get_order_from_bytes(MB(4)); struct page_info *pg; unsigned int order = get_11_allocation_size(kinfo->unassigned_mem); + u64 rambase_pfn = opt_dom0_rambase_pfn; + paddr_t mem_size = kinfo->unassigned_mem; int i; bool_t lowmem = is_32bit_domain(d); @@ -267,7 +272,7 @@ static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo) { for ( bits = order ; bits <= (lowmem ? 32 : PADDR_BITS); bits++ ) { - pg = alloc_domheap_pages(d, order, MEMF_bits(bits)); + pg = alloc_domheap_pages_pfn(d, order, MEMF_bits(bits), rambase_pfn); if ( pg != NULL ) goto got_bank0; } @@ -284,16 +289,21 @@ static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo) /* Now allocate more memory and fill in additional banks */ order = get_11_allocation_size(kinfo->unassigned_mem); + if ( opt_dom0_rambase_pfn ) + rambase_pfn += (mem_size - kinfo->unassigned_mem) >> PAGE_SHIFT; + while ( kinfo->unassigned_mem && kinfo->mem.nr_banks < NR_MEM_BANKS ) { - pg = alloc_domheap_pages(d, order, lowmem ? MEMF_bits(32) : 0); + pg = alloc_domheap_pages_pfn(d, order, lowmem ? MEMF_bits(32) : 0, + rambase_pfn); if ( !pg ) { order --; if ( lowmem && order < min_low_order) { - D11PRINT("Failed at min_low_order, allow high allocations\n"); + if ( !opt_dom0_rambase_pfn ) + D11PRINT("Failed at min_low_order, allow high allocations\n"); order = get_11_allocation_size(kinfo->unassigned_mem); lowmem = false; continue; @@ -313,7 +323,8 @@ static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo) if ( lowmem ) { - D11PRINT("Allocation below bank 0, allow high allocations\n"); + if ( !opt_dom0_rambase_pfn ) + D11PRINT("Allocation below bank 0, allow high allocations\n"); order = get_11_allocation_size(kinfo->unassigned_mem); lowmem = false; continue; @@ -330,6 +341,11 @@ static void allocate_memory_11(struct domain *d, struct kernel_info *kinfo) * allocation possible. */ order = get_11_allocation_size(kinfo->unassigned_mem); + if ( opt_dom0_rambase_pfn ) + { + rambase_pfn += (mem_size - kinfo->unassigned_mem) >> PAGE_SHIFT; + mem_size = kinfo->unassigned_mem; + } } if ( kinfo->unassigned_mem ) diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 74fc1de..d0c0fbb 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -583,16 +583,17 @@ static void check_low_mem_virq(void) } } -/* Allocate 2^@order contiguous pages. */ -static struct page_info *alloc_heap_pages( +/* Allocate 2^@order contiguous pages at given pfn. */ +static struct page_info *alloc_heap_pages_pfn( unsigned int zone_lo, unsigned int zone_hi, unsigned int order, unsigned int memflags, - struct domain *d) + struct domain *d, xen_pfn_t pfn) { unsigned int i, j, zone = 0, nodemask_retry = 0; nodeid_t first_node, node = MEMF_get_node(memflags), req_node = node; unsigned long request = 1UL << order; - struct page_info *pg; + struct page_info *pg, *tmp_pg; + struct page_list_head *pg_list; nodemask_t nodemask = (d != NULL ) ? d->node_affinity : node_online_map; bool_t need_tlbflush = 0; uint32_t tlbflush_timestamp = 0; @@ -657,9 +658,25 @@ static struct page_info *alloc_heap_pages( continue; /* Find smallest order which can satisfy the request. */ - for ( j = order; j <= MAX_ORDER; j++ ) - if ( (pg = page_list_remove_head(&heap(node, zone, j))) ) - goto found; + for ( j = order; j <= MAX_ORDER; j++ ) { + pg_list = &heap(node, zone, j); + if ( pfn ) + { + page_list_for_each_safe( pg, tmp_pg, pg_list ) + { + if ( pfn == page_to_mfn(pg) ) + { + page_list_del(pg, pg_list); + goto found; + } + } + } + else + { + if ( (pg = page_list_remove_head(pg_list)) ) + goto found; + } + } } while ( zone-- > zone_lo ); /* careful: unsigned zone may wrap */ if ( (memflags & MEMF_exact_node) && req_node != NUMA_NO_NODE ) @@ -706,9 +723,15 @@ static struct page_info *alloc_heap_pages( /* We may have to halve the chunk a number of times. */ while ( j != order ) { - PFN_ORDER(pg) = --j; - page_list_add_tail(pg, &heap(node, zone, j)); - pg += 1 << j; + tmp_pg = pg; + if ( pfn ) + tmp_pg += 1 << (j - 1); + + PFN_ORDER(tmp_pg) = --j; + page_list_add_tail(tmp_pg, &heap(node, zone, j)); + + if ( !pfn ) + pg += 1 << j; } ASSERT(avail[node][zone] >= request); @@ -762,6 +785,15 @@ static struct page_info *alloc_heap_pages( return pg; } +/* Allocate 2^@order contiguous pages. */ +static struct page_info *alloc_heap_pages( + unsigned int zone_lo, unsigned int zone_hi, + unsigned int order, unsigned int memflags, + struct domain *d) +{ + return alloc_heap_pages_pfn(zone_lo, zone_hi, order, memflags, d, 0); +} + /* Remove any offlined page in the buddy pointed to by head. */ static int reserve_offlined_page(struct page_info *head) { @@ -1687,8 +1719,8 @@ int assign_pages( } -struct page_info *alloc_domheap_pages( - struct domain *d, unsigned int order, unsigned int memflags) +struct page_info *alloc_domheap_pages_pfn( + struct domain *d, unsigned int order, unsigned int memflags, xen_pfn_t pfn) { struct page_info *pg = NULL; unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1; @@ -1705,12 +1737,12 @@ struct page_info *alloc_domheap_pages( memflags |= MEMF_no_refcount; if ( dma_bitsize && ((dma_zone = bits_to_zone(dma_bitsize)) < zone_hi) ) - pg = alloc_heap_pages(dma_zone + 1, zone_hi, order, memflags, d); + pg = alloc_heap_pages_pfn(dma_zone + 1, zone_hi, order, memflags, d, pfn); if ( (pg == NULL) && ((memflags & MEMF_no_dma) || - ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi, order, - memflags, d)) == NULL)) ) + ((pg = alloc_heap_pages_pfn(MEMZONE_XEN + 1, zone_hi, order, + memflags, d, pfn)) == NULL)) ) return NULL; if ( d && !(memflags & MEMF_no_owner) && @@ -1723,6 +1755,12 @@ struct page_info *alloc_domheap_pages( return pg; } +struct page_info *alloc_domheap_pages( + struct domain *d, unsigned int order, unsigned int memflags) +{ + return alloc_domheap_pages_pfn(d, order, memflags, 0); +} + void free_domheap_pages(struct page_info *pg, unsigned int order) { struct domain *d = page_get_owner(pg); diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index a795dd6..83e4913 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -117,6 +117,8 @@ void get_outstanding_claims(uint64_t *free_pages, uint64_t *outstanding_pages); /* Domain suballocator. These functions are *not* interrupt-safe.*/ void init_domheap_pages(paddr_t ps, paddr_t pe); +struct page_info *alloc_domheap_pages_pfn( + struct domain *d, unsigned int order, unsigned int memflags, xen_pfn_t pfn); struct page_info *alloc_domheap_pages( struct domain *d, unsigned int order, unsigned int memflags); void free_domheap_pages(struct page_info *pg, unsigned int order); -- 2.8.2 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel