xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: David Vrabel <david.vrabel@citrix.com>
To: xen-devel@lists.xensource.com
Cc: David Vrabel <david.vrabel@citrix.com>
Subject: [PATCH 7/8] arm, device tree: parse the DTB for RAM location and size
Date: Mon, 13 Feb 2012 13:18:50 +0000	[thread overview]
Message-ID: <1329139131-27554-8-git-send-email-david.vrabel@citrix.com> (raw)
In-Reply-To: <1329139131-27554-1-git-send-email-david.vrabel@citrix.com>

From: David Vrabel <david.vrabel@citrix.com>

Prior to setting up the page tables, parse the DTB for the location
and size of RAM.

Use this information to get the physical address to relocate Xen to in
setup_pagetables().

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>
---
 xen/arch/arm/mm.c             |    3 +-
 xen/arch/arm/setup.c          |    6 ++
 xen/common/Makefile           |    3 +
 xen/common/device_tree.c      |  179 +++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/mm.h      |    5 +-
 xen/include/xen/device_tree.h |   36 ++++++++
 6 files changed, 228 insertions(+), 4 deletions(-)
 create mode 100644 xen/common/device_tree.c
 create mode 100644 xen/include/xen/device_tree.h

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index f1fe4ba..24f977c 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -20,6 +20,7 @@
 #include <xen/config.h>
 #include <xen/compile.h>
 #include <xen/types.h>
+#include <xen/device_tree.h>
 #include <xen/init.h>
 #include <xen/mm.h>
 #include <xen/preempt.h>
@@ -159,7 +160,7 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
         write_pte(xen_second + second_linear_offset(dest_va), pte);
     }
 
-    xen_paddr = XEN_PADDR;
+    xen_paddr = device_tree_get_xen_paddr();
 
     /* Map the destination in the boot misc area. */
     dest_va = BOOT_MISC_VIRT_START;
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 51afb31..01d2668 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -19,6 +19,7 @@
 
 #include <xen/config.h>
 #include <xen/compile.h>
+#include <xen/device_tree.h>
 #include <xen/domain_page.h>
 #include <xen/types.h>
 #include <xen/string.h>
@@ -68,8 +69,13 @@ void __init start_xen(unsigned long boot_phys_offset,
                       unsigned long atag_paddr)
 
 {
+    void *fdt;
     int i;
 
+    fdt = (void *)BOOT_MISC_VIRT_START
+        + (atag_paddr & ((1 << SECOND_SHIFT) - 1));
+    device_tree_early_init(fdt);
+
     setup_pagetables(boot_phys_offset);
 
 #ifdef EARLY_UART_ADDRESS
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 4b1e6f2..372b259 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -1,6 +1,7 @@
 obj-y += bitmap.o
 obj-y += cpu.o
 obj-y += cpupool.o
+obj-$(HAS_DEVICE_TREE) += device_tree.o
 obj-y += domctl.o
 obj-y += domain.o
 obj-y += event_channel.o
@@ -60,3 +61,5 @@ subdir-$(ia64) += hvm
 
 subdir-y += libelf
 subdir-$(HAS_DEVICE_TREE) += libfdt
+
+CFLAGS += -Ilibfdt
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
new file mode 100644
index 0000000..7d7514d
--- /dev/null
+++ b/xen/common/device_tree.c
@@ -0,0 +1,179 @@
+/*
+ * Device Tree
+ *
+ * Copyright (C) 2012 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/init.h>
+#include <xen/device_tree.h>
+#include <xen/kernel.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/stdarg.h>
+#include <xen/string.h>
+#include <asm/early_printk.h>
+
+#include <libfdt.h>
+
+struct dt_early_info __initdata early_info;
+
+static void __init get_val(const u32 **cell, u32 cells, u64 *val)
+{
+    *val = 0;
+
+    while (cells--) {
+        *val <<= 32;
+        *val |= fdt32_to_cpu(*(*cell)++);
+    }
+}
+
+static void __init get_register(const u32 **cell, u32 address_cells, u32 size_cells,
+                                u64 *start, u64 *size)
+{
+    get_val(cell, address_cells, start);
+    get_val(cell, size_cells, size);
+}
+
+static u32 __init prop_by_name_u32(const void *fdt, int node, const char *prop_name)
+{
+    const struct fdt_property *prop;
+
+    prop = fdt_get_property(fdt, node, prop_name, NULL);
+    if (!prop || prop->len < sizeof(u32))
+        return 0; /* default to 0 */
+
+    return fdt32_to_cpu(*(uint32_t*)prop->data);
+}
+
+static void __init process_memory_node(const void *fdt, int node,
+                                       u32 address_cells, u32 size_cells)
+{
+    const struct fdt_property *prop;
+    size_t reg_cells;
+    int i;
+    int banks;
+    const u32 *cell;
+    paddr_t start, size;
+
+    if (address_cells < 1 || size_cells < 1) {
+        early_printk("fdt: node `%s': invalid #address-cells or #size-cells",
+                     fdt_get_name(fdt, node, NULL));
+        return;
+    }
+
+    prop = fdt_get_property(fdt, node, "reg", NULL);
+    if (!prop) {
+        early_printk("fdt: node `%s': missing `reg' property\n",
+                     fdt_get_name(fdt, node, NULL));
+        return;
+    }
+
+    cell = (const u32 *)prop->data;
+    reg_cells = address_cells + size_cells;
+    banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof(u32));
+
+    for (i = 0; i < banks && early_info.mem.nr_banks < NR_MEM_BANKS; i++) {
+        get_register(&cell, address_cells, size_cells, &start, &size);
+        early_info.mem.bank[early_info.mem.nr_banks].start = start;
+        early_info.mem.bank[early_info.mem.nr_banks].size = size;
+        early_info.mem.nr_banks++;
+    }
+}
+
+#define MAX_DEPTH 16
+
+static void __init early_scan(const void *fdt)
+{
+    int node;
+    int depth;
+    const char *name;
+    u32 address_cells[MAX_DEPTH];
+    u32 size_cells[MAX_DEPTH];
+
+    for (node = 0; depth >= 0; node = fdt_next_node(fdt, node, &depth)) {
+        name = fdt_get_name(fdt, node, NULL);
+
+        if (depth >= MAX_DEPTH) {
+            early_printk("fdt: node '%s': nested too deep\n",
+                         fdt_get_name(fdt, node, NULL));
+            continue;
+        }
+
+        address_cells[depth] = prop_by_name_u32(fdt, node, "#address-cells");
+        size_cells[depth] = prop_by_name_u32(fdt, node, "#size-cells");
+
+        if (strncmp(name, "memory", 6) == 0)
+            process_memory_node(fdt, node, address_cells[depth-1], size_cells[depth-1]);
+    }
+}
+
+static void __init early_print_info(void)
+{
+    struct dt_mem_info *mi = &early_info.mem;
+    int i;
+
+    for (i = 0; i < mi->nr_banks; i++)
+        early_printk("RAM: %016llx - %016llx\n",
+                     mi->bank[i].start, mi->bank[i].start + mi->bank[i].size - 1);
+}
+
+/**
+ * device_tree_early_init - initialize early info from a DTB
+ * @fdt: flattened device tree binary
+ */
+void __init device_tree_early_init(const void *fdt)
+{
+    int ret;
+
+    ret = fdt_check_header(fdt);
+    if (ret < 0)
+        early_panic("No valid device tree\n");
+
+    early_scan(fdt);
+    early_print_info();
+}
+
+/**
+ * device_tree_get_xen_paddr - get physical address to relocate Xen to
+ *
+ * Xen is relocated to the top of RAM and aligned to a XEN_PADDR_ALIGN
+ * boundary.
+ */
+paddr_t __init device_tree_get_xen_paddr(void)
+{
+    struct dt_mem_info *mi = &early_info.mem;
+    paddr_t min_size;
+    paddr_t paddr = 0, t;
+    int i;
+
+    min_size = (_end - _start + (XEN_PADDR_ALIGN-1)) & ~(XEN_PADDR_ALIGN-1);
+
+    /* Find the highest bank with enough space. */
+    for (i = 0; i < mi->nr_banks; i++) {
+        if (mi->bank[i].size >= min_size) {
+            t = mi->bank[i].start + mi->bank[i].size - min_size;
+            if (t > paddr)
+                paddr = t;
+        }
+    }
+
+    if (!paddr)
+        early_panic("Not enough memory to relocate Xen\n");
+
+    return paddr;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index f721c54..8efa63b 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -6,9 +6,8 @@
 #include <asm/page.h>
 #include <public/xen.h>
 
-/* Find a suitable place at the top of memory for Xen to live */
-/* XXX For now, use the top of the VE's 4GB RAM, at a 40-bit alias */
-#define XEN_PADDR 0x80ffe00000ull
+/* Align Xen to a 2 MiB boundary. */
+#define XEN_PADDR_ALIGN (1 << 21)
 
 /*
  * Per-page-frame information.
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
new file mode 100644
index 0000000..ae3e344
--- /dev/null
+++ b/xen/include/xen/device_tree.h
@@ -0,0 +1,36 @@
+/*
+ * Device Tree
+ *
+ * Copyright (C) 2012 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __XEN_DEVICE_TREE_H__
+#define __XEN_DEVICE_TREE_H__
+
+#include <xen/types.h>
+
+#define NR_MEM_BANKS 8
+
+struct membank {
+    paddr_t start;
+    paddr_t size;
+};
+
+struct dt_mem_info {
+    int nr_banks;
+    struct membank bank[NR_MEM_BANKS];
+};
+
+struct dt_early_info {
+    struct dt_mem_info mem;
+};
+
+extern struct dt_early_info early_info;
+
+void device_tree_early_init(const void *fdt);
+paddr_t device_tree_get_xen_paddr(void);
+
+#endif
-- 
1.7.2.5

  parent reply	other threads:[~2012-02-13 13:18 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-13 13:18 [PATCH 0/8] arm: initial device tree support (#3) David Vrabel
2012-02-13 13:18 ` [PATCH 1/8] libfdt: add version 1.3.0 David Vrabel
2012-02-13 13:18 ` [PATCH 2/8] libfdt: fixup libfdt_env.h for xen David Vrabel
2012-02-13 13:18 ` [PATCH 3/8] libfdt: add to build David Vrabel
2012-02-13 13:18 ` [PATCH 4/8] arm: link a device tree blob into the xen image David Vrabel
2012-02-17 17:13   ` Ian Campbell
2012-02-17 17:22     ` David Vrabel
2012-02-20 17:20       ` Ian Campbell
2012-02-22 14:34         ` Ian Campbell
2012-02-13 13:18 ` [PATCH 5/8] arm: map device tree blob in initial page tables David Vrabel
2012-02-13 13:18 ` [PATCH 6/8] arm: add early_printk() David Vrabel
2012-02-13 13:18 ` David Vrabel [this message]
2012-02-13 14:51   ` [PATCH 7/8] arm, device tree: parse the DTB for RAM location and size Ian Campbell
2012-02-13 15:46     ` David Vrabel
2012-02-13 16:53       ` Ian Campbell
2012-02-13 17:41         ` Ian Jackson
2012-03-14 10:53           ` Ian Campbell
2012-02-13 13:18 ` [PATCH 8/8] arm: setup MM using information from the device tree David Vrabel
2012-02-13 15:27 ` [PATCH 0/8] arm: initial device tree support (#3) Ian Campbell
2012-02-13 15:49   ` David Vrabel
  -- strict thread matches above, loose matches on Subject: below --
2012-02-10 13:03 [PATCH 0/8] arm: initial device tree support (#2) David Vrabel
2012-02-10 13:03 ` [PATCH 7/8] arm, device tree: parse the DTB for RAM location and size David Vrabel
2012-02-10 13:25   ` Tim Deegan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1329139131-27554-8-git-send-email-david.vrabel@citrix.com \
    --to=david.vrabel@citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).