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

[Xen-changelog] [xen-unstable] arm: support zImage format kernels for dom0



# HG changeset patch
# User David Vrabel <david.vrabel@xxxxxxxxxx>
# Date 1328801570 0
# Node ID da77e2bfcd14b75eb3c341b98b75dfed20ec0bdc
# Parent  48294c0c475d0b5c0f8476c5e6e71cb76c7d9fa8
arm: support zImage format kernels for dom0

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@xxxxxxxxxx>
Committed-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---


diff -r 48294c0c475d -r da77e2bfcd14 xen/arch/arm/Makefile
--- a/xen/arch/arm/Makefile     Thu Feb 09 15:32:50 2012 +0000
+++ b/xen/arch/arm/Makefile     Thu Feb 09 15:32:50 2012 +0000
@@ -7,6 +7,7 @@
 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 -r 48294c0c475d -r da77e2bfcd14 xen/arch/arm/domain_build.c
--- a/xen/arch/arm/domain_build.c       Thu Feb 09 15:32:50 2012 +0000
+++ b/xen/arch/arm/domain_build.c       Thu Feb 09 15:32:50 2012 +0000
@@ -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 @@
 
 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 @@
     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 @@
 
     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 @@
     /* 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);
+    kernel_load(&kinfo);
 
-    printk("Free temporary kernel buffer\n");
-    free_xenheap_pages(kernel_img, kernel_order);
-
-    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 @@
 
     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 -r 48294c0c475d -r da77e2bfcd14 xen/arch/arm/kernel.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/arm/kernel.c     Thu Feb 09 15:32:50 2012 +0000
@@ -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 -r 48294c0c475d -r da77e2bfcd14 xen/arch/arm/kernel.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/arm/kernel.h     Thu Feb 09 15:32:50 2012 +0000
@@ -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__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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