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

[Xen-devel] [PATCH 8/8] arm: setup MM using information from the device tree



From: David Vrabel <david.vrabel@xxxxxxxxxx>

Setup memory management, heaps etc. using the location and size of the
first memory bank given in the device tree.

The DTB is also copied so it can be used afterwards.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
---
 xen/arch/arm/kernel.c         |   22 +++++----
 xen/arch/arm/mm.c             |    3 +
 xen/arch/arm/setup.c          |   98 +++++++++++++++++++++++++++++++----------
 xen/common/device_tree.c      |    7 +++-
 xen/include/asm-arm/mm.h      |   11 +++--
 xen/include/asm-arm/setup.h   |    2 +
 xen/include/xen/device_tree.h |    3 +-
 7 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index d4ffa4f..f2339fa 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -11,6 +11,7 @@
 #include <xen/domain_page.h>
 #include <xen/sched.h>
 #include <asm/byteorder.h>
+#include <asm/setup.h>
 
 #include "kernel.h"
 
@@ -32,25 +33,28 @@ struct minimal_dtb_header {
 
 #define DTB_MAGIC 0xd00dfeed
 
-static void copy_from_flash(void *dst, paddr_t flash, unsigned long len)
+/**
+ * copy_from_paddr - copy data from a physical address
+ * @dst: destination virtual address
+ * @paddr: source physical address
+ * @len: length to copy
+ */
+void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len)
 {
     void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
 
-    printk("Copying %#lx bytes from flash %"PRIpaddr" to %p",
-           len, flash, dst);
-
     while (len) {
         paddr_t p;
         unsigned long l, s;
 
-        p = flash >> PAGE_SHIFT;
-        s = flash & (PAGE_SIZE-1);
+        p = paddr >> PAGE_SHIFT;
+        s = paddr & (PAGE_SIZE-1);
         l = min(PAGE_SIZE - s, len);
 
         set_fixmap(FIXMAP_MISC, p, DEV_SHARED);
         memcpy(dst, src + s, l);
 
-        flash += l;
+        paddr += l;
         dst += l;
         len -= l;
     }
@@ -108,7 +112,7 @@ static int kernel_try_zimage_prepare(struct kernel_info 
*info)
     /*
      * Check for an appended DTB.
      */
-    copy_from_flash(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, 
sizeof(dtb_hdr));
+    copy_from_paddr(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, 
sizeof(dtb_hdr));
     if (be32_to_cpu(dtb_hdr.magic) == DTB_MAGIC) {
         end += be32_to_cpu(dtb_hdr.total_size);
     }
@@ -150,7 +154,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
     if ( info->kernel_img == NULL )
         panic("Cannot allocate temporary buffer for kernel.\n");
 
-    copy_from_flash(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE);
+    copy_from_paddr(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE);
 
     if ( (rc = elf_init(&info->elf.elf, info->kernel_img, KERNEL_FLASH_SIZE )) 
!= 0 )
         return rc;
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 24f977c..0d6c0ca 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -39,6 +39,7 @@ static lpae_t xen_xenmap[LPAE_ENTRIES] 
__attribute__((__aligned__(4096)));
 unsigned long xenheap_mfn_start, xenheap_mfn_end;
 unsigned long xenheap_virt_end;
 
+unsigned long frametable_base_mfn;
 unsigned long frametable_virt_end;
 
 /* Map a 4k page in a fixmap entry */
@@ -301,6 +302,8 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t 
pe)
     unsigned long frametable_size = nr_pages * sizeof(struct page_info);
     unsigned long base_mfn;
 
+    frametable_base_mfn = ps >> PAGE_SHIFT;
+
     /* Round up to 32M boundary */
     frametable_size = (frametable_size + 0x1ffffff) & ~0x1ffffff;
     base_mfn = alloc_boot_pages(frametable_size >> PAGE_SHIFT, 5);
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index e212a2e..eff7098 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -64,16 +64,89 @@ static void __init init_idle_domain(void)
         /* TODO: setup_idle_pagetable(); */
 }
 
+static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
+{
+    paddr_t ram_start;
+    paddr_t ram_end;
+    paddr_t ram_size;
+    unsigned long ram_pages;
+    unsigned long heap_pages, xenheap_pages, domheap_pages;
+    unsigned long dtb_pages;
+    unsigned long boot_mfn_start, boot_mfn_end;
+
+    /*
+     * TODO: only using the first RAM bank for now.  The heaps and the
+     * frame table assume RAM is physically contiguous.
+     */
+    ram_start = early_info.mem.bank[0].start;
+    ram_size  = early_info.mem.bank[0].size;
+    ram_end = ram_start + ram_size;
+    ram_pages = ram_size >> PAGE_SHIFT;
+
+    /*
+     * Calculate the sizes for the heaps using these constraints:
+     *
+     *  - heaps must be 32 MiB aligned
+     *  - must not include Xen itself
+     *  - xen heap must be at most 1 GiB
+     *
+     * XXX: needs a platform with at least 1GiB of RAM or the dom
+     * heap will be empty and no domains can be created.
+     */
+    heap_pages = (ram_size >> PAGE_SHIFT) - (32 << (20 - PAGE_SHIFT));
+    xenheap_pages = min(1ul << (30 - PAGE_SHIFT), heap_pages);
+    domheap_pages = heap_pages - xenheap_pages;
+
+    printk("Xen heap: %lu pages  Dom heap: %lu pages\n", xenheap_pages, 
domheap_pages);
+
+    setup_xenheap_mappings(ram_start >> PAGE_SHIFT, xenheap_pages);
+
+    /*
+     * Need a single mapped page for populating bootmem_region_list
+     * and enough mapped pages for copying the DTB.
+     *
+     * TODO: The DTB (and other payloads) are assumed to be towards
+     * the start of RAM.
+     */
+    dtb_pages = (dtb_size + PAGE_SIZE-1) >> PAGE_SHIFT;
+    boot_mfn_start = xenheap_mfn_end - dtb_pages - 1;
+    boot_mfn_end = xenheap_mfn_end;
+
+    init_boot_pages(pfn_to_paddr(boot_mfn_start), pfn_to_paddr(boot_mfn_end));
+
+    /*
+     * Copy the DTB.
+     *
+     * TODO: handle other payloads too.
+     */
+    device_tree_flattened = mfn_to_virt(alloc_boot_pages(dtb_pages, 1));
+    copy_from_paddr(device_tree_flattened, dtb_paddr, dtb_size);
+
+    /* Add non-xenheap memory */
+    init_boot_pages(pfn_to_paddr(xenheap_mfn_start + xenheap_pages),
+                    pfn_to_paddr(xenheap_mfn_start + xenheap_pages + 
domheap_pages));
+
+    setup_frametable_mappings(ram_start, ram_end);
+
+    /* Add xenheap memory that was not already added to the boot
+       allocator. */
+    init_xenheap_pages(pfn_to_paddr(xenheap_mfn_start),
+                       pfn_to_paddr(boot_mfn_start));
+
+    end_boot_allocator();
+}
+
 void __init start_xen(unsigned long boot_phys_offset,
                       unsigned long arm_type,
                       unsigned long atag_paddr)
 
 {
     void *fdt;
+    size_t fdt_size;
     int i;
 
     fdt = (void *)BOOT_MISC_VIRT_START + (atag_paddr & ((1 << SECOND_SHIFT) - 
1));
-    device_tree_early_init(fdt);
+    fdt_size = device_tree_early_init(fdt);
 
     setup_pagetables(boot_phys_offset);
 
@@ -97,28 +170,7 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     init_xen_time();
 
-    /* TODO: This needs some thought, as well as device-tree mapping.
-     * For testing, assume that the whole xenheap is contiguous in RAM */
-    setup_xenheap_mappings(0x8000000, 0x40000); /* 1 GB @ 512GB */
-    /* Must pass a single mapped page for populating bootmem_region_list. */
-    init_boot_pages(pfn_to_paddr(xenheap_mfn_start),
-                    pfn_to_paddr(xenheap_mfn_start+1));
-
-    /* Add non-xenheap memory */
-    init_boot_pages(0x8040000000, 0x80c0000000); /* 2 GB @513GB */
-
-    /* TODO Make sure Xen's own pages aren't added
-     *     -- the memory above doesn't include our relocation target.  */
-    /* TODO Handle payloads too */
-
-    /* TODO Need to find actual memory, for now use 4GB at 512GB */
-    setup_frametable_mappings(0x8000000000ULL, 0x8100000000UL);
-
-    /* Add xenheap memory */
-    init_xenheap_pages(pfn_to_paddr(xenheap_mfn_start+1),
-                       pfn_to_paddr(xenheap_mfn_end));
-
-    end_boot_allocator();
+    setup_mm(atag_paddr, fdt_size);
 
     /* Setup Hyp vector base */
     WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR);
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index a60ff6d..788b2d3 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -22,6 +22,7 @@
 #include <libfdt.h>
 
 struct dt_early_info __initdata early_info;
+void *device_tree_flattened;
 
 static void __init get_val(const u32 **cell, u32 cells, u64 *val)
 {
@@ -126,8 +127,10 @@ static void __init early_print_info(void)
 /**
  * device_tree_early_init - initialize early info from a DTB
  * @fdt: flattened device tree binary
+ *
+ * Returns the size of the DTB.
  */
-void __init device_tree_early_init(const void *fdt)
+size_t __init device_tree_early_init(const void *fdt)
 {
     int ret;
 
@@ -137,6 +140,8 @@ void __init device_tree_early_init(const void *fdt)
 
     early_scan(fdt);
     early_print_info();
+
+    return fdt_totalsize(fdt);
 }
 
 /**
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 8efa63b..bfc0f76 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -128,6 +128,8 @@ extern void share_xen_page_with_privileged_guests(
     struct page_info *page, int readonly);
 
 #define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
+/* MFN of the first page in the frame table. */
+extern unsigned long frametable_base_mfn;
 
 extern unsigned long max_page;
 extern unsigned long total_pages;
@@ -151,15 +153,14 @@ extern void clear_fixmap(unsigned map);
 })
 
 #define max_pdx                 max_page
-/* XXX Assume everything in the 40-bit physical alias 0x8000000000 for now */
-#define pfn_to_pdx(pfn)         ((pfn) - 0x8000000UL)
-#define pdx_to_pfn(pdx)         ((pdx) + 0x8000000UL)
+#define pfn_to_pdx(pfn)         (pfn)
+#define pdx_to_pfn(pdx)         (pdx)
 #define virt_to_pdx(va)         virt_to_mfn(va)
 #define pdx_to_virt(pdx)        mfn_to_virt(pdx)
 
 /* Convert between machine frame numbers and page-info structures. */
-#define mfn_to_page(mfn)  (frame_table + pfn_to_pdx(mfn))
-#define page_to_mfn(pg)   pdx_to_pfn((unsigned long)((pg) - frame_table))
+#define mfn_to_page(mfn)  (frame_table + (pfn_to_pdx(mfn) - 
frametable_base_mfn))
+#define page_to_mfn(pg)   pdx_to_pfn((unsigned long)((pg) - frame_table) + 
frametable_base_mfn)
 #define __page_to_mfn(pg)  page_to_mfn(pg)
 #define __mfn_to_page(mfn) mfn_to_page(mfn)
 
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 2041f06..05ff89e 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -3,6 +3,8 @@
 
 #include <public/version.h>
 
+void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
+
 void arch_get_xen_caps(xen_capabilities_info_t *info);
 
 int construct_dom0(struct domain *d);
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index eb7f219..3cafdc7 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -29,8 +29,9 @@ struct dt_early_info {
 };
 
 extern struct dt_early_info early_info;
+extern void *device_tree_flattened;
 
-void device_tree_early_init(const void *fdt);
+size_t device_tree_early_init(const void *fdt);
 paddr_t device_tree_get_xen_paddr(void);
 
 #endif
-- 
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®.