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

[Xen-devel] [PATCH RFC 16/18] xen: Add dom0_mem_high option & over 4GB memory allocation for Dom0



From: Iurii Mykhalskyi <iurii.mykhalskyi@xxxxxxxxxxxxxxx>

Add support of custom allocation of over 4GB memory for Dom0. Requested
memory size might be specified by passing dom0_mem_high option in Xen
cmdline

Signed-off-by: Iurii Mykhalskyi <iurii.mykhalskyi@xxxxxxxxxxxxxxx>
---
 xen/Rules.mk                |   1 +
 xen/arch/arm/domain_build.c | 189 +++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/kernel.h       |   9 +++
 3 files changed, 198 insertions(+), 1 deletion(-)

diff --git a/xen/Rules.mk b/xen/Rules.mk
index fbd34a5..51f7124 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -65,6 +65,7 @@ CFLAGS-$(HAS_IOPORTS)   += -DHAS_IOPORTS
 CFLAGS-$(HAS_PDX)       += -DHAS_PDX
 CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER
 CFLAGS-$(ARM32_RELOCATE_OVER_4GB) += -DARM32_RELOCATE_OVER_4GB
+CFLAGS-$(ARM32_SEPAR_MEM_SPLIT) += -DARM32_SEPAR_MEM_SPLIT
 
 ifneq ($(max_phys_cpus),)
 CFLAGS-y                += -DMAX_PHYS_CPUS=$(max_phys_cpus)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f06792e..a63958b 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -35,6 +35,11 @@ int dom0_11_mapping = 1;
 #define DOM0_MEM_DEFAULT 0x8000000 /* 128 MiB */
 static u64 __initdata dom0_mem = DOM0_MEM_DEFAULT;
 
+#ifdef ARM32_SEPAR_MEM_SPLIT
+#define DOM0_MEM_HIGH_DEFAULT 0x0 /* 0 MiB */
+static u64 __initdata dom0_mem_high = DOM0_MEM_HIGH_DEFAULT;
+#endif
+
 static void __init parse_dom0_mem(const char *s)
 {
     dom0_mem = parse_size_and_unit(s, &s);
@@ -43,6 +48,14 @@ static void __init parse_dom0_mem(const char *s)
 }
 custom_param("dom0_mem", parse_dom0_mem);
 
+#ifdef ARM32_SEPAR_MEM_SPLIT
+static void __init parse_dom0_mem_high(const char *s)
+{
+    dom0_mem_high = parse_size_and_unit(s, &s);
+}
+custom_param("dom0_mem_high", parse_dom0_mem_high);
+#endif
+
 //#define DEBUG_DT
 
 #ifdef DEBUG_DT
@@ -130,7 +143,11 @@ static bool_t insert_11_bank(struct domain *d,
     if ( res )
         panic("Failed map pages to DOM0: %d", res);
 
+#ifndef ARM32_SEPAR_MEM_SPLIT
     kinfo->unassigned_mem -= size;
+#else
+    kinfo->unassigned_mem.low -= size;
+#endif
 
     if ( kinfo->mem.nr_banks == 0 )
     {
@@ -192,6 +209,82 @@ fail:
     return false;
 }
 
+#ifdef ARM32_SEPAR_MEM_SPLIT
+static void allocate_dom0_high_memory(struct domain *d, struct kernel_info 
*kinfo)
+{
+    int i, res, st_banks = kinfo->mem.nr_banks;
+    struct page_info *pg = NULL;
+    int bits;
+    unsigned int order = get_11_allocation_size(dom0_mem_high);
+    const unsigned int min_order = get_order_from_bytes(MB(4));
+    paddr_t spfn;
+    paddr_t start, size;
+    struct membank *bank = NULL;
+
+    if (dom0_mem_high == 0)
+        return;
+
+    printk("Allocating %ldMB of high memory region for dom0\n",
+            (unsigned long)(dom0_mem_high >> 20));
+
+    while ( kinfo->unassigned_mem.high && kinfo->mem.nr_banks < NR_MEM_BANKS )
+    {
+        for (bits = PADDR_BITS ; bits >= min_order; bits-- )
+        {
+            pg = alloc_domheap_pages(d, order, MEMF_bits(bits));
+            if ( pg != NULL )
+                break;
+        }
+
+        if ( !pg )
+        {
+            order --;
+            if ( order >= min_order )
+                continue;
+
+            /* No more we can do */
+            break;
+        }
+
+        spfn = page_to_mfn(pg);
+        start = pfn_to_paddr(spfn);
+        size = pfn_to_paddr((1 << order));
+
+        res = guest_physmap_add_page(d, spfn, spfn, order);
+        if ( res )
+            panic("Failed map pages to DOM0: %d", res);
+
+        kinfo->unassigned_mem.high -= size;
+
+        bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
+
+        bank->start = start;
+        bank->size = size;
+        kinfo->mem.nr_banks++;
+
+        /*
+         * Success, next time around try again to get the largest order
+         * allocation possible.
+         */
+
+        order = get_11_allocation_size(kinfo->unassigned_mem.high);
+     }
+
+    if(kinfo->unassigned_mem.high)
+        panic("Unable to allocate high memory bank");
+
+    for( i = st_banks; i < kinfo->mem.nr_banks; i++ )
+    {
+        printk("BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
+               i,
+               kinfo->mem.bank[i].start,
+               kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
+               /* Don't want format this as PRIpaddr (16 digit hex) */
+               (unsigned long)(kinfo->mem.bank[i].size >> 20));
+    }
+}
+#endif
+
 /*
  * This is all pretty horrible.
  *
@@ -250,9 +343,13 @@ static void allocate_memory_11(struct domain *d, struct 
kernel_info *kinfo)
         get_11_allocation_size(min_t(paddr_t, dom0_mem, MB(128)));
     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;
+#ifndef ARM32_SEPAR_MEM_SPLIT
+    unsigned int order = get_11_allocation_size(kinfo->unassigned_mem);
     paddr_t mem_size = kinfo->unassigned_mem;
+#else
+    unsigned int order = get_11_allocation_size(kinfo->unassigned_mem.low);
+#endif
     int i;
 
     bool_t lowmem = is_32bit_domain(d);
@@ -260,7 +357,11 @@ static void allocate_memory_11(struct domain *d, struct 
kernel_info *kinfo)
 
     printk("Allocating 1:1 mappings totalling %ldMB for dom0:\n",
            /* Don't want format this as PRIpaddr (16 digit hex) */
+#ifndef ARM32_SEPAR_MEM_SPLIT
            (unsigned long)(kinfo->unassigned_mem >> 20));
+#else
+           (unsigned long)(kinfo->unassigned_mem.low >> 20));
+#endif
 
     kinfo->mem.nr_banks = 0;
 
@@ -288,6 +389,7 @@ static void allocate_memory_11(struct domain *d, struct 
kernel_info *kinfo)
 
     /* Now allocate more memory and fill in additional banks */
 
+#ifndef ARM32_SEPAR_MEM_SPLIT
     order = get_11_allocation_size(kinfo->unassigned_mem);
     if ( opt_dom0_rambase_pfn )
         rambase_pfn += (mem_size - kinfo->unassigned_mem) >> PAGE_SHIFT;
@@ -353,7 +455,62 @@ static void allocate_memory_11(struct domain *d, struct 
kernel_info *kinfo)
                /* Don't want format this as PRIpaddr (16 digit hex) */
                " %ldMB unallocated\n",
                (unsigned long)kinfo->unassigned_mem >> 20);
+#else
+    order = get_11_allocation_size(kinfo->unassigned_mem.low);
+    while ( kinfo->unassigned_mem.low && kinfo->mem.nr_banks < NR_MEM_BANKS )
+    {
+        pg = alloc_domheap_pages(d, order, lowmem ? MEMF_bits(32) : 0);
+        if ( !pg )
+        {
+            order --;
+
+            if ( lowmem && order < min_low_order)
+            {
+                D11PRINT("Failed at min_low_order, allow high allocations\n");
+                order = get_11_allocation_size(kinfo->unassigned_mem.low);
+                lowmem = false;
+                continue;
+            }
+            if ( order >= min_order )
+                continue;
+
+            /* No more we can do */
+            break;
+        }
+
+        if ( !insert_11_bank(d, kinfo, pg, order) )
+        {
+            if ( kinfo->mem.nr_banks == NR_MEM_BANKS )
+                /* Nothing more we can do. */
+                break;
+
+            if ( lowmem )
+            {
+                D11PRINT("Allocation below bank 0, allow high allocations\n");
+                order = get_11_allocation_size(kinfo->unassigned_mem.low);
+                lowmem = false;
+                continue;
+            }
+            else
+            {
+                D11PRINT("Allocation below bank 0\n");
+                break;
+            }
+        }
+
+        /*
+         * Success, next time around try again to get the largest order
+         * allocation possible.
+         */
+        order = get_11_allocation_size(kinfo->unassigned_mem.low);
+    }
 
+    if ( kinfo->unassigned_mem.low )
+        printk("WARNING: Failed to allocate requested dom0 memory."
+               /* Don't want format this as PRIpaddr (16 digit hex) */
+               " %ldMB unallocated\n",
+               (unsigned long)kinfo->unassigned_mem.low >> 20);
+#endif
     for( i = 0; i < kinfo->mem.nr_banks; i++ )
     {
         printk("BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
@@ -374,7 +531,19 @@ static void allocate_memory(struct domain *d, struct 
kernel_info *kinfo)
     unsigned int bank = 0;
 
     if ( dom0_11_mapping )
+#ifndef ARM32_SEPAR_MEM_SPLIT
         return allocate_memory_11(d, kinfo);
+#else
+    {
+        allocate_memory_11(d, kinfo);
+        return allocate_dom0_high_memory(d, kinfo);
+    }
+#endif
+
+#ifdef ARM32_SEPAR_MEM_SPLIT
+    if (dom0_mem_high != 0)
+        printk("***WARNING*** We don't implement dom0_mem_high option for non 
1:1 mapped domains!\n");
+#endif
 
     while ( (memory = dt_find_node_by_type(memory, "memory")) )
     {
@@ -389,7 +558,11 @@ static void allocate_memory(struct domain *d, struct 
kernel_info *kinfo)
             panic("Memory node has no reg property");
 
         for ( l = 0;
+#ifndef ARM32_SEPAR_MEM_SPLIT
               kinfo->unassigned_mem > 0 && l + reg_size <= reg_len
+#else
+              kinfo->unassigned_mem.low > 0 && l + reg_size <= reg_len
+#endif
                   && kinfo->mem.nr_banks < NR_MEM_BANKS;
               l += reg_size )
         {
@@ -399,8 +572,13 @@ static void allocate_memory(struct domain *d, struct 
kernel_info *kinfo)
                 panic("Unable to retrieve the bank %u for %s",
                       bank, dt_node_full_name(memory));
 
+#ifndef ARM32_SEPAR_MEM_SPLIT
             if ( size > kinfo->unassigned_mem )
                 size = kinfo->unassigned_mem;
+#else
+            if ( size > kinfo->unassigned_mem.low )
+                size = kinfo->unassigned_mem.low;
+#endif
 
             printk("Populate P2M %#"PRIx64"->%#"PRIx64"\n",
                    start, start + size);
@@ -410,7 +588,11 @@ static void allocate_memory(struct domain *d, struct 
kernel_info *kinfo)
             kinfo->mem.bank[kinfo->mem.nr_banks].size = size;
             kinfo->mem.nr_banks++;
 
+#ifndef ARM32_SEPAR_MEM_SPLIT
             kinfo->unassigned_mem -= size;
+#else
+            kinfo->unassigned_mem.low -= size;
+#endif
         }
     }
 }
@@ -1521,7 +1703,12 @@ int construct_dom0(struct domain *d)
 
     d->max_pages = ~0U;
 
+#ifndef ARM32_SEPAR_MEM_SPLIT
     kinfo.unassigned_mem = dom0_mem;
+#else
+    kinfo.unassigned_mem.low = dom0_mem;
+    kinfo.unassigned_mem.high = dom0_mem_high;
+#endif
 
     rc = kernel_probe(&kinfo);
     if ( rc < 0 )
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index c1b07d4..83fa0ed 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -16,7 +16,16 @@ struct kernel_info {
 #endif
 
     void *fdt; /* flat device tree */
+
+#ifndef ARM32_SEPAR_MEM_SPLIT
     paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
+#else
+    struct {
+        paddr_t low; /* Low RAM not (yet) assigned to a bank */
+        paddr_t high; /* High RAM not (yet) assigned to a bank */
+    } unassigned_mem;
+#endif
+
     struct meminfo mem;
 
     /* kernel entry point */
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

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