xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
To: xen-devel@lists.xensource.com
Cc: David Vrabel <david.vrabel@citrix.com>,
	Stefano.Stabellini@eu.citrix.com, Ian.Campbell@citrix.com,
	Tim.Deegan@citrix.com
Subject: [PATCH v6 26/27] ARM: support zImage format kernels for dom0
Date: Fri, 20 Jan 2012 16:36:14 +0000	[thread overview]
Message-ID: <1327077375-7623-26-git-send-email-stefano.stabellini@eu.citrix.com> (raw)
In-Reply-To: <alpine.DEB.2.00.1201201605370.3196@kaball-desktop>

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

Allow a zImage format kernel to be used for dom0.  zImages are (by
default) hardcoded with the RAM location so adjust the RAM in the
memory map to match the physical memory map (0x80000000).

Vmlinux ELF images are loaded using a hack to locate the RAM so the
IPA is the same as the kernel's VA so the elf loader does the right
thing.  If an ELF image is loaded the RAM will be located at
0xC0000000 (as before).

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 xen/arch/arm/Makefile       |    1 +
 xen/arch/arm/domain_build.c |   72 ++++--------------
 xen/arch/arm/kernel.c       |  167 +++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/kernel.h       |   37 ++++++++++
 4 files changed, 221 insertions(+), 56 deletions(-)
 create mode 100644 xen/arch/arm/kernel.c
 create mode 100644 xen/arch/arm/kernel.h

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 5a07ae7..9bc2fc8 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -7,6 +7,7 @@ obj-y += domain_build.o
 obj-y += gic.o
 obj-y += io.o
 obj-y += irq.o
+obj-y += kernel.o
 obj-y += mm.o
 obj-y += p2m.o
 obj-y += guestcopy.o
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f73df85..cbbc0b9 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -4,10 +4,10 @@
 #include <xen/mm.h>
 #include <xen/domain_page.h>
 #include <xen/sched.h>
-#include <xen/libelf.h>
 #include <asm/irq.h>
 
 #include "gic.h"
+#include "kernel.h"
 
 static unsigned int __initdata opt_dom0_max_vcpus;
 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
@@ -28,25 +28,6 @@ struct vcpu *__init alloc_dom0_vcpu0(void)
 
 extern void guest_mode_entry(void);
 
-static void copy_from_flash(void *dst, paddr_t flash, unsigned long len)
-{
-    void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
-    unsigned long offs;
-
-    printk("Copying %#lx bytes from flash %"PRIpaddr" to %p-%p: [",
-           len, flash, dst, dst+(1<<23));
-    for ( offs = 0; offs < len ; offs += PAGE_SIZE )
-    {
-        if ( ( offs % (1<<20) ) == 0 )
-            printk(".");
-        set_fixmap(FIXMAP_MISC, (flash+offs) >> PAGE_SHIFT, DEV_SHARED);
-        memcpy(dst+offs, src, PAGE_SIZE);
-    }
-    printk("]\n");
-
-    clear_fixmap(FIXMAP_MISC);
-}
-
 static void setup_linux_atag(paddr_t tags, paddr_t ram_s, paddr_t ram_e)
 {
     paddr_t ma = gvirt_to_maddr(tags);
@@ -84,21 +65,14 @@ static void setup_linux_atag(paddr_t tags, paddr_t ram_s, paddr_t ram_e)
     unmap_domain_page(map);
 }
 
-/* Store kernel in first 8M of flash */
-#define KERNEL_FLASH_ADDRESS 0x00000000UL
-#define KERNEL_FLASH_SIZE    0x00800000UL
-
 int construct_dom0(struct domain *d)
 {
-    int rc, kernel_order;
-    void *kernel_img;
+    struct kernel_info kinfo = {};
+    int rc;
 
     struct vcpu *v = d->vcpu[0];
     struct cpu_user_regs *regs = &v->arch.user_regs;
 
-    struct elf_binary elf;
-    struct elf_dom_parms parms;
-
     /* Sanity! */
     BUG_ON(d->domain_id != 0);
     BUG_ON(d->vcpu[0] == NULL);
@@ -106,31 +80,22 @@ int construct_dom0(struct domain *d)
 
     printk("*** LOADING DOMAIN 0 ***\n");
 
-    kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
-    kernel_img = alloc_xenheap_pages(kernel_order, 0);
-    if ( kernel_img == NULL )
-        panic("Cannot allocate temporary buffer for kernel.\n");
+    /* 128M at 2G physical */
+    /* TODO size and location from DT. */
+    kinfo.ram_start = 0x80000000;
+    kinfo.ram_end   = 0x88000000;
 
-    copy_from_flash(kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE);
+    rc = kernel_prepare(&kinfo);
+    if (rc < 0)
+        return rc;
 
     d->max_pages = ~0U;
 
-    if ( (rc = elf_init(&elf, kernel_img, KERNEL_FLASH_SIZE )) != 0 )
-        return rc;  memset(regs, 0, sizeof(*regs));
-#ifdef VERBOSE
-    elf_set_verbose(&elf);
-#endif
-    elf_parse_binary(&elf);
-    if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
-        return rc;
-
     if ( (rc = p2m_alloc_table(d)) != 0 )
         return rc;
 
-    /* 128M at 3G physical */
-    /* TODO size and location according to platform info */
-    printk("Populate P2M %#llx->%#llx\n", 0xc0000000ULL, 0xc8000000ULL);
-    p2m_populate_ram(d, 0xc0000000ULL, 0xc8000000ULL);
+    printk("Populate P2M %#llx->%#llx\n", kinfo.ram_start, kinfo.ram_end);
+    p2m_populate_ram(d, kinfo.ram_start, kinfo.ram_end);
 
     printk("Map CS2 MMIO regions 1:1 in the P2M %#llx->%#llx\n", 0x18000000ULL, 0x1BFFFFFFULL);
     map_mmio_regions(d, 0x18000000, 0x1BFFFFFF, 0x18000000);
@@ -161,20 +126,15 @@ int construct_dom0(struct domain *d)
     /* The following load uses domain's p2m */
     p2m_load_VTTBR(d);
 
-    printk("Loading ELF image into guest memory\n");
-    elf.dest = (void*)(unsigned long)parms.virt_kstart;
-    elf_load_binary(&elf);
-
-    printk("Free temporary kernel buffer\n");
-    free_xenheap_pages(kernel_img, kernel_order);
+    kernel_load(&kinfo);
 
-    setup_linux_atag(0xc0000100ULL, 0xc0000000ULL, 0xc8000000ULL);
+    setup_linux_atag(kinfo.ram_start + 0x100, kinfo.ram_start, kinfo.ram_end);
 
     clear_bit(_VPF_down, &v->pause_flags);
 
     memset(regs, 0, sizeof(*regs));
 
-    regs->pc = (uint32_t)parms.virt_entry;
+    regs->pc = (uint32_t)kinfo.entry;
 
     regs->cpsr = PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC;
 
@@ -191,7 +151,7 @@ int construct_dom0(struct domain *d)
 
     regs->r0 = 0; /* SBZ */
     regs->r1 = 2272; /* Machine NR: Versatile Express */
-    regs->r2 = 0xc0000100; /* ATAGS */
+    regs->r2 = kinfo.ram_start + 0x100; /* ATAGS */
 
     WRITE_CP32(SCTLR_BASE, SCTLR);
 
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
new file mode 100644
index 0000000..5fb2ba0
--- /dev/null
+++ b/xen/arch/arm/kernel.c
@@ -0,0 +1,167 @@
+/*
+ * Kernel image loading.
+ *
+ * Copyright (C) 2011 Citrix Systems, Inc.
+ */
+#include <xen/config.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/domain_page.h>
+#include <xen/sched.h>
+
+#include "kernel.h"
+
+/* Store kernel in first 8M of flash */
+#define KERNEL_FLASH_ADDRESS 0x00000000UL
+#define KERNEL_FLASH_SIZE    0x00800000UL
+
+#define ZIMAGE_MAGIC_OFFSET 0x24
+#define ZIMAGE_START_OFFSET 0x28
+#define ZIMAGE_END_OFFSET   0x2c
+
+#define ZIMAGE_MAGIC 0x016f2818
+
+static void kernel_zimage_load(struct kernel_info *info)
+{
+    paddr_t load_addr = info->zimage.load_addr;
+    paddr_t len = info->zimage.len;
+    paddr_t flash = KERNEL_FLASH_ADDRESS;
+    void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
+    unsigned long offs;
+
+    printk("Loading %"PRIpaddr" byte zImage from flash %"PRIpaddr" to %"PRIpaddr"-%"PRIpaddr": [",
+           len, flash, load_addr, load_addr + len);
+    for ( offs = 0; offs < len; offs += PAGE_SIZE )
+    {
+        paddr_t ma = gvirt_to_maddr(load_addr + offs);
+        void *dst = map_domain_page(ma>>PAGE_SHIFT);
+
+        if ( ( offs % (1<<20) ) == 0 )
+            printk(".");
+
+        set_fixmap(FIXMAP_MISC, (flash+offs) >> PAGE_SHIFT, DEV_SHARED);
+        memcpy(dst, src, PAGE_SIZE);
+        clear_fixmap(FIXMAP_MISC);
+
+        unmap_domain_page(dst);
+    }
+    printk("]\n");
+}
+
+/**
+ * Check the image is a zImage and return the load address and length
+ * (FIXME: including any appended DTB).
+ */
+static int kernel_try_zimage_prepare(struct kernel_info *info)
+{
+    uint32_t *zimage = (void *)FIXMAP_ADDR(FIXMAP_MISC);
+    uint32_t start, end;
+
+    set_fixmap(FIXMAP_MISC, KERNEL_FLASH_ADDRESS >> PAGE_SHIFT, DEV_SHARED);
+
+    if (zimage[ZIMAGE_MAGIC_OFFSET/4] != ZIMAGE_MAGIC)
+        return -EINVAL;
+
+    start = zimage[ZIMAGE_START_OFFSET/4];
+    end = zimage[ZIMAGE_END_OFFSET/4];
+
+    clear_fixmap(FIXMAP_MISC);
+
+    /* FIXME: get RAM location from appended DTB (if there is one)? */
+
+    /*
+     * If start is zero, the zImage is position independent -- load it
+     * at 32k from start of RAM.
+     */
+    if (start == 0)
+        info->zimage.load_addr = info->ram_start + 0x8000;
+    else
+        info->zimage.load_addr = start;
+    info->zimage.len = end - start;
+
+    info->entry = info->zimage.load_addr;
+    info->load = kernel_zimage_load;
+
+    return 0;
+}
+
+static void kernel_elf_load(struct kernel_info *info)
+{
+    printk("Loading ELF image into guest memory\n");
+    info->elf.elf.dest = (void*)(unsigned long)info->elf.parms.virt_kstart;
+    elf_load_binary(&info->elf.elf);
+
+    printk("Free temporary kernel buffer\n");
+    free_xenheap_pages(info->kernel_img, info->kernel_order);
+}
+
+static void copy_from_flash(void *dst, paddr_t flash, unsigned long len)
+{
+    void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
+    unsigned long offs;
+
+    printk("Copying %#lx bytes from flash %"PRIpaddr" to %p-%p: [",
+           len, flash, dst, dst+(1<<23));
+    for ( offs = 0; offs < len ; offs += PAGE_SIZE )
+    {
+        if ( ( offs % (1<<20) ) == 0 )
+            printk(".");
+        set_fixmap(FIXMAP_MISC, (flash+offs) >> PAGE_SHIFT, DEV_SHARED);
+        memcpy(dst+offs, src, PAGE_SIZE);
+    }
+    printk("]\n");
+
+    clear_fixmap(FIXMAP_MISC);
+}
+
+static int kernel_try_elf_prepare(struct kernel_info *info)
+{
+    int rc;
+
+    info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
+    info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
+    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);
+
+    if ( (rc = elf_init(&info->elf.elf, info->kernel_img, KERNEL_FLASH_SIZE )) != 0 )
+        return rc;
+#ifdef VERBOSE
+    elf_set_verbose(&info->elf.elf);
+#endif
+    elf_parse_binary(&info->elf.elf);
+    if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
+        return rc;
+
+    /*
+     * FIXME: can the ELF header be used to find the physical address
+     * to load the image to?  Instead of making virt == phys by
+     * relocating the guest's RAM.
+     */
+    info->ram_start = 0xc0000000;
+    info->ram_end   = 0xc8000000;
+
+    info->entry = info->elf.parms.virt_entry;
+    info->load = kernel_elf_load;
+
+    return 0;
+}
+
+int kernel_prepare(struct kernel_info *info)
+{
+    int rc;
+
+    rc = kernel_try_zimage_prepare(info);
+    if (rc < 0)
+        rc = kernel_try_elf_prepare(info);
+
+    return rc;
+}
+
+void kernel_load(struct kernel_info *info)
+{
+    info->load(info);
+}
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
new file mode 100644
index 0000000..5caebe5
--- /dev/null
+++ b/xen/arch/arm/kernel.h
@@ -0,0 +1,37 @@
+/*
+ * Kernel image loading.
+ *
+ * Copyright (C) 2011 Citrix Systems, Inc.
+ */
+#ifndef __ARCH_ARM_KERNEL_H__
+#define __ARCH_ARM_KERNEL_H__
+
+#include <xen/libelf.h>
+
+struct kernel_info {
+    paddr_t entry;
+    paddr_t ram_start;
+    paddr_t ram_end;
+
+    void *kernel_img;
+    unsigned kernel_order;
+
+    union {
+        struct {
+            paddr_t load_addr;
+            paddr_t len;
+        } zimage;
+
+        struct {
+            struct elf_binary elf;
+            struct elf_dom_parms parms;
+        } elf;
+    };
+
+    void (*load)(struct kernel_info *info);
+};
+
+int kernel_prepare(struct kernel_info *info);
+void kernel_load(struct kernel_info *info);
+
+#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
-- 
1.7.2.5

  parent reply	other threads:[~2012-01-20 16:36 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-20 16:35 [PATCH v6 00/27] xen: ARMv7 with virtualization extensions Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 01/27] Move cpufreq option parsing to cpufreq.c Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 02/27] Include some header files that are not automatically included on all archs Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 03/27] A collection of fixes to Xen common files Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 04/27] xen: implement an signed 64 bit division helper function Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 05/27] Introduce clear_user and clear_guest Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 06/27] libelf-loader: introduce elf_load_image Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 07/27] xen/common/Makefile: introduce HAS_CPUFREQ, HAS_PCI, HAS_PASSTHROUGH, HAS_NS16550, HAS_KEXEC Stefano Stabellini
2012-01-27 15:15   ` Ian Campbell
2012-02-08  8:35   ` Keir Fraser
2012-01-20 16:35 ` [PATCH v6 08/27] arm: compile tmem Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 09/27] arm: header files Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 10/27] arm: bit manipulation, copy and division libraries Stefano Stabellini
2012-01-20 16:35 ` [PATCH v6 11/27] arm: entry.S and head.S Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 12/27] arm: domain Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 13/27] arm: domain_build Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 14/27] arm: driver for CoreLink GIC-400 Generic Interrupt Controller Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 15/27] arm: mmio handlers Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 16/27] arm: irq Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 17/27] arm: mm and p2m Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 19/27] arm: early setup code Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 20/27] arm: shutdown, smp and smpboot Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 21/27] arm: driver for the generic timer for ARMv7 Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 22/27] arm: trap handlers Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 23/27] arm: vgic emulation Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 24/27] arm: vtimer Stefano Stabellini
2012-01-20 16:36 ` [PATCH v6 25/27] arm: makefiles Stefano Stabellini
2012-02-02 16:46   ` Stefano Stabellini
2012-01-20 16:36 ` Stefano Stabellini [this message]
2012-01-20 16:36 ` [PATCH v6 27/27] ARM: copy DTB appended to zImage Stefano Stabellini
2012-02-09 11:49 ` [PATCH v6 00/27] xen: ARMv7 with virtualization extensions Ian Campbell
2012-02-09 14:45   ` Ian Campbell
2012-02-09 14:53     ` [PATCH] arm: define domain_pirq_to_irq Ian Campbell
2012-02-09 15:18       ` Stefano Stabellini
2012-02-09 15:21         ` Ian Campbell
2012-02-09 15:28           ` Stefano Stabellini
2012-02-09 15:52             ` Ian Campbell
2012-02-09 14:53     ` [PATCH] arm: define stub arch_dump_shared_mem_info Ian Campbell
2012-02-09 15:19       ` Stefano Stabellini
2012-02-09 15:22         ` Ian Campbell
2012-02-09 15:28           ` Stefano Stabellini

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=1327077375-7623-26-git-send-email-stefano.stabellini@eu.citrix.com \
    --to=stefano.stabellini@eu.citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Tim.Deegan@citrix.com \
    --cc=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).