These two patches add support for loading ARM kernels built as a zImage with an appended device tree blob (DTB) (CONFIG_ARM_APPENDED_DTB). You can also use an vmlinux ELF as before. This is required to run the latest kernels that support the Versatile Express with a Cortex A15 tile. Such a kernel can be found in the ''vexpress-dt'' branch of git://xenbits.xen.org/people/dvrabel/linux.git. The DTB for the model is named ''vexpress-v2p-aem-v7a.dtb''. David
David Vrabel
2012-Jan-10 16:40 UTC
[PATCH 1/2] ARM: support zImage format kernels for dom0
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
From: David Vrabel <david.vrabel@citrix.com> When copying a zImage from flash, also copy any appended device tree blob. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- xen/arch/arm/kernel.c | 63 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 44 insertions(+), 19 deletions(-) diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index 5fb2ba0..d4ffa4f 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -10,6 +10,7 @@ #include <xen/mm.h> #include <xen/domain_page.h> #include <xen/sched.h> +#include <asm/byteorder.h> #include "kernel.h" @@ -23,6 +24,40 @@ #define ZIMAGE_MAGIC 0x016f2818 +struct minimal_dtb_header { + uint32_t magic; + uint32_t total_size; + /* There are other fields but we don''t use them yet. */ +}; + +#define DTB_MAGIC 0xd00dfeed + +static void copy_from_flash(void *dst, paddr_t flash, 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); + l = min(PAGE_SIZE - s, len); + + set_fixmap(FIXMAP_MISC, p, DEV_SHARED); + memcpy(dst, src + s, l); + + flash += l; + dst += l; + len -= l; + } + + clear_fixmap(FIXMAP_MISC); +} + static void kernel_zimage_load(struct kernel_info *info) { paddr_t load_addr = info->zimage.load_addr; @@ -58,6 +93,7 @@ static int kernel_try_zimage_prepare(struct kernel_info *info) { uint32_t *zimage = (void *)FIXMAP_ADDR(FIXMAP_MISC); uint32_t start, end; + struct minimal_dtb_header dtb_hdr; set_fixmap(FIXMAP_MISC, KERNEL_FLASH_ADDRESS >> PAGE_SHIFT, DEV_SHARED); @@ -69,6 +105,14 @@ static int kernel_try_zimage_prepare(struct kernel_info *info) clear_fixmap(FIXMAP_MISC); + /* + * Check for an appended DTB. + */ + copy_from_flash(&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); + } + /* FIXME: get RAM location from appended DTB (if there is one)? */ /* @@ -97,25 +141,6 @@ static void kernel_elf_load(struct kernel_info *info) 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; -- 1.7.2.5
Stefano Stabellini
2012-Jan-11 16:51 UTC
Re: [PATCH 0/2] ARM: support zImage kernels for dom0
On Tue, 10 Jan 2012, David Vrabel wrote:> These two patches add support for loading ARM kernels built as a > zImage with an appended device tree blob (DTB) > (CONFIG_ARM_APPENDED_DTB). You can also use an vmlinux ELF as before. > > This is required to run the latest kernels that support the Versatile > Express with a Cortex A15 tile. Such a kernel can be found in the > ''vexpress-dt'' branch of git://xenbits.xen.org/people/dvrabel/linux.git. > > The DTB for the model is named ''vexpress-v2p-aem-v7a.dtb''.both patches are fine, thanks
Ian Campbell
2012-Jan-13 14:45 UTC
Re: [PATCH 1/2] ARM: support zImage format kernels for dom0
On Tue, 2012-01-10 at 16:40 +0000, David Vrabel wrote:> 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>These both look good to me, at first I thought there was some code duplication going on but I see now it is all code motion. Please can someone add the necessary Local variables to the end of both new files. Ian.> --- > 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 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel