[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH V2 2/3] libxc: add ARM support to xc_dom (PV domain building)
Includes ARM zImage support. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- v2: - add comments for rambase_pfn and p2m_host to clarify usage - remove opencoded guest base address of 0x80000000 (still hardcoded, but now with a comment!). - comments around Linux boot protocol setup. --- tools/libxc/Makefile | 1 + tools/libxc/xc_dom.h | 20 +++- tools/libxc/xc_dom_arm.c | 140 ++++++++++++++++++++++++++- tools/libxc/xc_dom_armzimageloader.c | 174 ++++++++++++++++++++++++++++++++++ tools/libxc/xc_dom_core.c | 10 +- tools/libxc/xg_private.h | 4 + 6 files changed, 339 insertions(+), 10 deletions(-) create mode 100644 tools/libxc/xc_dom_armzimageloader.c diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index ca38cbd..a01d457 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -59,6 +59,7 @@ GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c GUEST_SRCS-y += xc_dom_elfloader.c GUEST_SRCS-$(CONFIG_X86) += xc_dom_bzimageloader.c +GUEST_SRCS-$(CONFIG_ARM) += xc_dom_armzimageloader.c GUEST_SRCS-y += xc_dom_binloader.c GUEST_SRCS-y += xc_dom_compat_linux.c diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h index 2aef64a..3cd6dae 100644 --- a/tools/libxc/xc_dom.h +++ b/tools/libxc/xc_dom.h @@ -89,10 +89,24 @@ struct xc_dom_image { /* other state info */ uint32_t f_active[XENFEAT_NR_SUBMAPS]; + /* + * p2m_host maps guest physical addresses an offset from + * rambase_pfn (see below) into gfns. + * + * For a pure PV guest this means that it maps GPFNs into MFNs for + * a hybrid guest this means that it maps GPFNs to GPFNS. + * + * Note that the input is offset by rambase. + */ xen_pfn_t *p2m_host; void *p2m_guest; - /* physical memory */ + /* physical memory + * + * A PV guest has a single contiguous block of physical RAM, + * consisting of total_pages starting at rambase_pfn. + */ + xen_pfn_t rambase_pfn; xen_pfn_t total_pages; struct xc_dom_phys *phys_pages; int realmodearea_log; @@ -286,7 +300,7 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn) { if (dom->shadow_enabled) return pfn; - return dom->p2m_host[pfn]; + return dom->p2m_host[pfn - dom->rambase_pfn]; } static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom, @@ -294,7 +308,7 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom, { if (xc_dom_feature_translated(dom)) return pfn; - return dom->p2m_host[pfn]; + return dom->p2m_host[pfn - dom->rambase_pfn]; } /* --- arch bits --------------------------------------------------- */ diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c index 122d0e8..3eef0d0 100644 --- a/tools/libxc/xc_dom_arm.c +++ b/tools/libxc/xc_dom_arm.c @@ -18,14 +18,143 @@ * Copyright (c) 2011, Citrix Systems */ #include <inttypes.h> + #include <xen/xen.h> +#include <xen/io/protocols.h> + #include "xg_private.h" #include "xc_dom.h" +/* ------------------------------------------------------------------------ */ +/* + * arm guests are hybrid and start off with paging disabled, therefore no + * pagetables and nothing to do here. + */ +static int count_pgtables_arm(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + return 0; +} + +static int setup_pgtables_arm(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int alloc_magic_pages(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + /* XXX + * dom->p2m_guest + * dom->start_info_pfn + * dom->xenstore_pfn + * dom->console_pfn + */ + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int start_info_arm(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + return 0; +} + +static int shared_info_arm(struct xc_dom_image *dom, void *ptr) +{ + DOMPRINTF_CALLED(dom->xch); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int vcpu_arm(struct xc_dom_image *dom, void *ptr) +{ + vcpu_guest_context_t *ctxt = ptr; + + DOMPRINTF_CALLED(dom->xch); + + /* clear everything */ + memset(ctxt, 0, sizeof(*ctxt)); + + ctxt->user_regs.pc = dom->parms.virt_entry; + + /* Linux boot protocol. See linux.Documentation/arm/Booting. */ + ctxt->user_regs.r0 = 0; /* SBZ */ + /* Machine ID: We use DTB therefore no machine id */ + ctxt->user_regs.r1 = 0xffffffff; + /* ATAGS/DTB: We currently require that the guest kernel to be + * using CONFIG_ARM_APPENDED_DTB. Ensure that r2 does not look + * like a valid pointer to a set of ATAGS or a DTB. + */ + ctxt->user_regs.r2 = 0xffffffff; + + ctxt->sctlr = /* #define SCTLR_BASE */0x00c50078; + + ctxt->ttbr0 = 0; + ctxt->ttbr1 = 0; + ctxt->ttbcr = 0; /* Defined Reset Value */ + + ctxt->user_regs.cpsr = PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC; + + DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx32, + ctxt->user_regs.cpsr, ctxt->user_regs.pc); + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static struct xc_dom_arch xc_dom_32 = { + .guest_type = "xen-3.0-armv7l", + .native_protocol = XEN_IO_PROTO_ABI_ARM, + .page_shift = PAGE_SHIFT_ARM, + .sizeof_pfn = 8, + .alloc_magic_pages = alloc_magic_pages, + .count_pgtables = count_pgtables_arm, + .setup_pgtables = setup_pgtables_arm, + .start_info = start_info_arm, + .shared_info = shared_info_arm, + .vcpu = vcpu_arm, +}; + +static void __init register_arch_hooks(void) +{ + xc_dom_register_arch_hooks(&xc_dom_32); +} + int arch_setup_meminit(struct xc_dom_image *dom) { - errno = ENOSYS; - return -1; + int rc; + xen_pfn_t pfn, allocsz, i; + + dom->shadow_enabled = 1; + + dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages); + + /* setup initial p2m */ + for ( pfn = 0; pfn < dom->total_pages; pfn++ ) + dom->p2m_host[pfn] = pfn + dom->rambase_pfn; + + /* allocate guest memory */ + for ( i = rc = allocsz = 0; + (i < dom->total_pages) && !rc; + i += allocsz ) + { + allocsz = dom->total_pages - i; + if ( allocsz > 1024*1024 ) + allocsz = 1024*1024; + + rc = xc_domain_populate_physmap_exact( + dom->xch, dom->guest_domid, allocsz, + 0, 0, &dom->p2m_host[i]); + } + + return 0; } int arch_setup_bootearly(struct xc_dom_image *dom) @@ -36,9 +165,14 @@ int arch_setup_bootearly(struct xc_dom_image *dom) int arch_setup_bootlate(struct xc_dom_image *dom) { - DOMPRINTF("%s: doing nothing", __FUNCTION__); + /* XXX + * map shared info + * map grant tables + * setup shared info + */ return 0; } + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_dom_armzimageloader.c b/tools/libxc/xc_dom_armzimageloader.c new file mode 100644 index 0000000..f316e87 --- /dev/null +++ b/tools/libxc/xc_dom_armzimageloader.c @@ -0,0 +1,174 @@ +/* + * Xen domain builder -- ARM zImage bits + * + * Parse and load ARM zImage kernel images. + * + * Copyright (C) 2012, Citrix Systems. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> + +#include "xg_private.h" +#include "xc_dom.h" + +#include <arpa/inet.h> /* XXX ntohl is not the right function... */ + +/* + * Guest virtual RAM starts here. This must be consistent with the DTB + * appended to the guest kernel. + */ +#define GUEST_RAM_BASE 0x80000000 + +#define ZIMAGE_MAGIC_OFFSET 0x24 +#define ZIMAGE_START_OFFSET 0x28 +#define ZIMAGE_END_OFFSET 0x2c + +#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 int xc_dom_probe_zimage_kernel(struct xc_dom_image *dom) +{ + uint32_t *zimage; + uint32_t end; + + if ( dom->kernel_blob == NULL ) + { + xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, + "%s: no kernel image loaded", __FUNCTION__); + return -EINVAL; + } + + if ( dom->kernel_size < 0x30 /*sizeof(struct setup_header)*/ ) + { + xc_dom_printf(dom->xch, "%s: kernel image too small", __FUNCTION__); + return -EINVAL; + } + + zimage = (uint32_t *)dom->kernel_blob; + if ( zimage[ZIMAGE_MAGIC_OFFSET/4] != ZIMAGE_MAGIC ) + { + xc_dom_printf(dom->xch, "%s: kernel is not a bzImage", __FUNCTION__); + return -EINVAL; + } + + end = zimage[ZIMAGE_END_OFFSET/4]; + + /* + * Check for an appended DTB. + */ + if ( end + sizeof(struct minimal_dtb_header) < dom->kernel_size ) { + struct minimal_dtb_header *dtb_hdr; + dtb_hdr = (struct minimal_dtb_header *)(dom->kernel_blob + end); + if (ntohl/*be32_to_cpu*/(dtb_hdr->magic) == DTB_MAGIC) { + xc_dom_printf(dom->xch, "%s: found an appended DTB", __FUNCTION__); + end += ntohl/*be32_to_cpu*/(dtb_hdr->total_size); + } + } + + dom->kernel_size = end; + + return 0; +} + +static int xc_dom_parse_zimage_kernel(struct xc_dom_image *dom) +{ + uint32_t *zimage; + uint32_t start, entry_addr; + uint64_t v_start, v_end; + uint64_t rambase = GUEST_RAM_BASE; + + DOMPRINTF_CALLED(dom->xch); + + zimage = (uint32_t *)dom->kernel_blob; + + dom->rambase_pfn = rambase >> XC_PAGE_SHIFT; + + /* Do not load kernel at the very first RAM address */ + v_start = rambase + 0x8000; + v_end = v_start + dom->kernel_size; + + start = zimage[ZIMAGE_START_OFFSET/4]; + + if (start == 0) + entry_addr = v_start; + else + entry_addr = start; + + /* find kernel segment */ + dom->kernel_seg.vstart = v_start; + dom->kernel_seg.vend = v_end; + + dom->parms.virt_entry = entry_addr; + + dom->guest_type = "xen-3.0-armv7l"; + DOMPRINTF("%s: %s: RAM starts at %"PRI_xen_pfn, + __FUNCTION__, dom->guest_type, dom->rambase_pfn); + DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "", + __FUNCTION__, dom->guest_type, + dom->kernel_seg.vstart, dom->kernel_seg.vend); + return 0; +} + +static int xc_dom_load_zimage_kernel(struct xc_dom_image *dom) +{ + void *dst; + + DOMPRINTF_CALLED(dom->xch); + + dst = xc_dom_seg_to_ptr(dom, &dom->kernel_seg); + + DOMPRINTF("%s: kernel sed %#"PRIx64"-%#"PRIx64, + __func__, dom->kernel_seg.vstart, dom->kernel_seg.vend); + DOMPRINTF("%s: copy %zd bytes from blob %p to dst %p", + __func__, dom->kernel_size, dom->kernel_blob, dst); + + memcpy(dst, dom->kernel_blob, dom->kernel_size); + + return 0; +} + +static struct xc_dom_loader zimage_loader = { + .name = "Linux zImage (ARM)", + .probe = xc_dom_probe_zimage_kernel, + .parser = xc_dom_parse_zimage_kernel, + .loader = xc_dom_load_zimage_kernel, +}; + +static void __init register_loader(void) +{ + xc_dom_register_loader(&zimage_loader); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c index fea9de5..5244b04 100644 --- a/tools/libxc/xc_dom_core.c +++ b/tools/libxc/xc_dom_core.c @@ -307,15 +307,17 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn, xen_pfn_t count) { struct xc_dom_phys *phys; + xen_pfn_t offset; unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom); char *mode = "unset"; - if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */ + offset = pfn - dom->rambase_pfn; + if ( offset > dom->total_pages || /* multiple checks to avoid overflows */ count > dom->total_pages || - pfn > dom->total_pages - count ) + offset > dom->total_pages - count ) { - DOMPRINTF("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")", - __FUNCTION__, pfn, dom->total_pages); + DOMPRINTF("%s: pfn %"PRI_xen_pfn" out of range (0x%" PRIpfn " > 0x%" PRIpfn ")", + __FUNCTION__, pfn, offset, dom->total_pages); return NULL; } diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index a29fa26..a271942 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -148,6 +148,10 @@ typedef l4_pgentry_64_t l4_pgentry_t; #define l4_table_offset(_a) l4_table_offset_x86_64(_a) #endif +#define PAGE_SHIFT_ARM 12 +#define PAGE_SIZE_ARM (1UL << PAGE_SHIFT_ARM) +#define PAGE_MASK_ARM (~(PAGE_SIZE_ARM-1)) + #define PAGE_SHIFT_X86 12 #define PAGE_SIZE_X86 (1UL << PAGE_SHIFT_X86) #define PAGE_MASK_X86 (~(PAGE_SIZE_X86-1)) -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |