]> xenbits.xensource.com Git - people/vhanquez/xen.git/commitdiff
arm: setup MM using information from the device tree
authorDavid Vrabel <david.vrabel@citrix.com>
Mon, 13 Feb 2012 14:33:10 +0000 (14:33 +0000)
committerDavid Vrabel <david.vrabel@citrix.com>
Mon, 13 Feb 2012 14:33:10 +0000 (14:33 +0000)
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@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
xen/arch/arm/kernel.c
xen/arch/arm/mm.c
xen/arch/arm/setup.c
xen/common/device_tree.c
xen/include/asm-arm/mm.h
xen/include/asm-arm/setup.h
xen/include/xen/device_tree.h

index d4ffa4f624ee4a44e75d10e0dae974050994da8b..f2339fad15186c80e8ac117b553705b3506a2088 100644 (file)
@@ -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;
index 24f977c30a35a9372f1a979e5e5da98f5a95c6ee..0d6c0cada8fdd4ca519609435f114a5aafd9236b 100644 (file)
@@ -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);
index 01d26683e070c954451ba6bbfca9ce02141bb1ab..de7d5f2dec211f5c240b56d58a738ff300cc6e57 100644 (file)
@@ -64,17 +64,90 @@ 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);
 
@@ -98,28 +171,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);
index 7d7514dc01d53a96058c78fc82ef1c81ba741880..d50cb9cc6b48cb90f27b88f205be7b35830a9b48 100644 (file)
@@ -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);
 }
 
 /**
index 8efa63bc244995d88dd4c487077af3886e60665a..bfc0f7696336a656ff36ae66c4b4256e5d7f163f 100644 (file)
@@ -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)
 
index 2041f068db58ca5547da31bf9afb30e3b344e597..05ff89ec287431dca96145735a7340aac16ce9ce 100644 (file)
@@ -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);
index ae3e3444954ac5179d32993004c755db4cae1ae1..28a3deef59c8a943ca9930848bcf4b6ba3a3d10a 100644 (file)
@@ -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