This is a repost of "libxc: add ARM support to xc_dom (PV domain building)" and some surrounding infrastructure. I''ve addressed Stefano''s comments and made some cleanups of my own. Stefano has started posting patches which build on these, but I don''t think this baseline is suitable for unstable yet (one patch is a HACK, others touch non-ARM specific bits of the tools and are therefore inappropriate for 4.2), which makes it hard to apply Stefano''s patches anywhere. Therefore I propose to create a specific branch where I put these sorts things, so that we have a consistent baseline set of patches which people can build on. Ideally I wouldn''t include anything which I wouldn''t put in mainline in this branch if it weren''t for the freeze, but for now I think I''ll include "HACK: arm: initial XENMAPSPACE_gmfn_foreign" to allow people to actually make progress while we decide on the right interface there. For that reason the branch would be, at least in principal, potentially rebasing (since I might swap out the HACK for another one or a proper patch) but I''ll announce that if/when it happens. Once 4.3 reopens I''ll repost the content of the branch for review and if necessary prod anyone with a patch in that branch to help rebase. Are people happy for me to make this a git tree based off Anthony''s conversion (chosen because I expect it to become the "Official" conversion at some point)? I could just as easily maintain an hg branch but I think most of the folks working on ARM are using some git conversion or other. Ian.
Ian Campbell
2012-Jul-23 15:31 UTC
[PATCH V2 1/3] HACK: arm: initial XENMAPSPACE_gmfn_foreign
Should use same interface as hybrid x86. --- xen/arch/arm/mm.c | 32 ++++++++++++++++++++++++++------ xen/arch/x86/mm.c | 2 ++ xen/include/public/arch-arm.h | 1 + xen/include/public/memory.h | 12 +++++++----- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 40ac176..d369ee3 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -470,12 +470,32 @@ static int xenmem_add_to_physmap_once( switch ( xatp->space ) { - case XENMAPSPACE_shared_info: - if ( xatp->idx == 0 ) - mfn = virt_to_mfn(d->shared_info); - break; - default: - return -ENOSYS; + case XENMAPSPACE_shared_info: + if ( xatp->idx == 0 ) + mfn = virt_to_mfn(d->shared_info); + break; + case XENMAPSPACE_gmfn_foreign: + { + paddr_t maddr; + struct domain *od; + + rc = rcu_lock_target_domain_by_id(xatp->foreign_domid, &od); + if ( rc < 0 ) + return rc; + maddr = p2m_lookup(od, xatp->idx << PAGE_SHIFT); + if ( maddr == INVALID_PADDR ) + { + printk("bad p2m lookup\n"); + dump_p2m_lookup(od, xatp->idx << PAGE_SHIFT); + rcu_unlock_domain(od); + return -EINVAL; + } + mfn = maddr >> PAGE_SHIFT; + rcu_unlock_domain(od); + break; + } + default: + return -ENOSYS; } domain_lock(d); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 9338575..9f63974 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4561,6 +4561,8 @@ static int xenmem_add_to_physmap_once( mfn = idx; page = mfn_to_page(mfn); break; + case XENMAPSPACE_gmfn_foreign: + return -ENOSYS; } default: break; diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index eb1add9..7ebe966 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -121,6 +121,7 @@ typedef uint64_t xen_pfn_t; #define XEN_LEGACY_MAX_VCPUS 1 typedef uint32_t xen_ulong_t; +#define PRI_xen_ulong PRIx32 struct vcpu_guest_context { struct cpu_user_regs user_regs; /* User-level CPU registers */ diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 86d02c8..b2adfbe 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -212,11 +212,13 @@ struct xen_add_to_physmap { uint16_t size; /* Source mapping space. */ -#define XENMAPSPACE_shared_info 0 /* shared info page */ -#define XENMAPSPACE_grant_table 1 /* grant table page */ -#define XENMAPSPACE_gmfn 2 /* GMFN */ -#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ - unsigned int space; +#define XENMAPSPACE_shared_info 0 /* shared info page */ +#define XENMAPSPACE_grant_table 1 /* grant table page */ +#define XENMAPSPACE_gmfn 2 /* GMFN */ +#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ +#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */ + uint16_t space; + domid_t foreign_domid; /* IFF gmfn_foreign */ #define XENMAPIDX_grant_table_status 0x80000000 -- 1.7.10.4
Ian Campbell
2012-Jul-23 15:31 UTC
[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@citrix.com> --- 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
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- tools/libxc/xc_dom_arm.c | 2 ++ xen/arch/arm/domain.c | 5 ++++- xen/include/public/arch-arm.h | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c index 3eef0d0..65dafe8 100644 --- a/tools/libxc/xc_dom_arm.c +++ b/tools/libxc/xc_dom_arm.c @@ -101,6 +101,8 @@ static int vcpu_arm(struct xc_dom_image *dom, void *ptr) ctxt->user_regs.cpsr = PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC; + ctxt->flags = VGCF_online; + DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx32, ctxt->user_regs.cpsr, ctxt->user_regs.pc); diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index ac6a30d..f61568b 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -416,7 +416,10 @@ int arch_set_info_guest( v->arch.ttbr1 = ctxt->ttbr1; v->arch.ttbcr = ctxt->ttbcr; - clear_bit(_VPF_down, &v->pause_flags); + if ( ctxt->flags & VGCF_online ) + clear_bit(_VPF_down, &v->pause_flags); + else + set_bit(_VPF_down, &v->pause_flags); return 0; } diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 7ebe966..6e0fe47 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -124,6 +124,10 @@ typedef uint32_t xen_ulong_t; #define PRI_xen_ulong PRIx32 struct vcpu_guest_context { +#define _VGCF_online 0 +#define VGCF_online (1<<_VGCF_online) + uint32_t flags; /* VGCF_* */ + struct cpu_user_regs user_regs; /* User-level CPU registers */ uint32_t sctlr; -- 1.7.10.4
Ian Campbell
2012-Jul-23 15:53 UTC
Re: [PATCH V2 1/3] HACK: arm: initial XENMAPSPACE_gmfn_foreign
On Mon, 2012-07-23 at 16:31 +0100, Ian Campbell wrote:> Should use same interface as hybrid x86.Mukesh, Did you settle on an interface on the x86 side for hybrid? Could post just that bit of the hypervisor and kernel patches so we can confirm that the interface works for ARM too and potentially take them in advance of the full hybrid stuff on x86? Ian.> --- > xen/arch/arm/mm.c | 32 ++++++++++++++++++++++++++------ > xen/arch/x86/mm.c | 2 ++ > xen/include/public/arch-arm.h | 1 + > xen/include/public/memory.h | 12 +++++++----- > 4 files changed, 36 insertions(+), 11 deletions(-) > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index 40ac176..d369ee3 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -470,12 +470,32 @@ static int xenmem_add_to_physmap_once( > > switch ( xatp->space ) > { > - case XENMAPSPACE_shared_info: > - if ( xatp->idx == 0 ) > - mfn = virt_to_mfn(d->shared_info); > - break; > - default: > - return -ENOSYS; > + case XENMAPSPACE_shared_info: > + if ( xatp->idx == 0 ) > + mfn = virt_to_mfn(d->shared_info); > + break; > + case XENMAPSPACE_gmfn_foreign: > + { > + paddr_t maddr; > + struct domain *od; > + > + rc = rcu_lock_target_domain_by_id(xatp->foreign_domid, &od); > + if ( rc < 0 ) > + return rc; > + maddr = p2m_lookup(od, xatp->idx << PAGE_SHIFT); > + if ( maddr == INVALID_PADDR ) > + { > + printk("bad p2m lookup\n"); > + dump_p2m_lookup(od, xatp->idx << PAGE_SHIFT); > + rcu_unlock_domain(od); > + return -EINVAL; > + } > + mfn = maddr >> PAGE_SHIFT; > + rcu_unlock_domain(od); > + break; > + } > + default: > + return -ENOSYS; > } > > domain_lock(d); > diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c > index 9338575..9f63974 100644 > --- a/xen/arch/x86/mm.c > +++ b/xen/arch/x86/mm.c > @@ -4561,6 +4561,8 @@ static int xenmem_add_to_physmap_once( > mfn = idx; > page = mfn_to_page(mfn); > break; > + case XENMAPSPACE_gmfn_foreign: > + return -ENOSYS; > } > default: > break; > diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h > index eb1add9..7ebe966 100644 > --- a/xen/include/public/arch-arm.h > +++ b/xen/include/public/arch-arm.h > @@ -121,6 +121,7 @@ typedef uint64_t xen_pfn_t; > #define XEN_LEGACY_MAX_VCPUS 1 > > typedef uint32_t xen_ulong_t; > +#define PRI_xen_ulong PRIx32 > > struct vcpu_guest_context { > struct cpu_user_regs user_regs; /* User-level CPU registers */ > diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h > index 86d02c8..b2adfbe 100644 > --- a/xen/include/public/memory.h > +++ b/xen/include/public/memory.h > @@ -212,11 +212,13 @@ struct xen_add_to_physmap { > uint16_t size; > > /* Source mapping space. */ > -#define XENMAPSPACE_shared_info 0 /* shared info page */ > -#define XENMAPSPACE_grant_table 1 /* grant table page */ > -#define XENMAPSPACE_gmfn 2 /* GMFN */ > -#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ > - unsigned int space; > +#define XENMAPSPACE_shared_info 0 /* shared info page */ > +#define XENMAPSPACE_grant_table 1 /* grant table page */ > +#define XENMAPSPACE_gmfn 2 /* GMFN */ > +#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ > +#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */ > + uint16_t space; > + domid_t foreign_domid; /* IFF gmfn_foreign */ > > #define XENMAPIDX_grant_table_status 0x80000000 >
Stefano Stabellini
2012-Jul-26 16:30 UTC
Re: [PATCH V2 2/3] libxc: add ARM support to xc_dom (PV domain building)
On Mon, 23 Jul 2012, Ian Campbell wrote:> Includes ARM zImage support. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > --- > 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.It looks better now. I think we should take it as is, and then replace ntohl with be32_to_cpu when we have it.> 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;I have just noticed that this parameter should not be called shadow_enabled but rather something like paging_mode_translate_enabled because it is supposed to cover both shadow and HAP. But it is something for another patch.> + 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 >
Ian Campbell
2012-Aug-01 10:28 UTC
Re: [PATCH V2 2/3] libxc: add ARM support to xc_dom (PV domain building)
On Thu, 2012-07-26 at 17:30 +0100, Stefano Stabellini wrote:> On Mon, 23 Jul 2012, Ian Campbell wrote: > > Includes ARM zImage support. > > > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > > --- > > 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. > > It looks better now. > I think we should take it as is, and then replace ntohl with > be32_to_cpu when we have it.OK. I''ve applied this whole series to my "arm-for-4.3" branch which I''ll announce shortly.
Ian Campbell
2012-Oct-09 10:55 UTC
Re: [PATCH V2 2/3] libxc: add ARM support to xc_dom (PV domain building)
On Thu, 2012-07-26 at 17:30 +0100, Stefano Stabellini wrote:> On Mon, 23 Jul 2012, Ian Campbell wrote: > > Includes ARM zImage support. > > > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > > --- > > 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. > > It looks better now. > I think we should take it as is, and then replace ntohl with > be32_to_cpu when we have it.Can I take that as an Ack of the reposted version in <1349433507-21148-2-git-send-email-ian.campbell@citrix.com> ?
Stefano Stabellini
2012-Oct-09 11:28 UTC
Re: [PATCH V2 2/3] libxc: add ARM support to xc_dom (PV domain building)
On Tue, 9 Oct 2012, Ian Campbell wrote:> On Thu, 2012-07-26 at 17:30 +0100, Stefano Stabellini wrote: > > On Mon, 23 Jul 2012, Ian Campbell wrote: > > > Includes ARM zImage support. > > > > > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > > > --- > > > 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. > > > > It looks better now. > > I think we should take it as is, and then replace ntohl with > > be32_to_cpu when we have it. > > Can I take that as an Ack of the reposted version in > <1349433507-21148-2-git-send-email-ian.campbell@citrix.com> > ?yes