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

Re: [Xen-devel] [PATCH 36/38] libxc: add ARM support to xc_dom (PV domain building)



On Fri, 1 Jun 2012, Ian Campbell wrote:
> Includes ARM zImage support.
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
>  tools/libxc/Makefile                 |    1 +
>  tools/libxc/xc_dom.h                 |    5 +-
>  tools/libxc/xc_dom_arm.c             |  135 +++++++++++++++++++++++++++-
>  tools/libxc/xc_dom_armzimageloader.c |  167 
> ++++++++++++++++++++++++++++++++++
>  tools/libxc/xc_dom_core.c            |   12 ++-
>  tools/libxc/xg_private.h             |    4 +
>  6 files changed, 315 insertions(+), 9 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..4db8fad 100644
> --- a/tools/libxc/xc_dom.h
> +++ b/tools/libxc/xc_dom.h
> @@ -93,6 +93,7 @@ struct xc_dom_image {
>      void *p2m_guest;
> 
>      /* physical memory */
> +    xen_pfn_t rambase_pfn;
>      xen_pfn_t total_pages;
>      struct xc_dom_phys *phys_pages;
>      int realmodearea_log;
> @@ -286,7 +287,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 +295,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];
>  }

I take that rambase_pfn is the offset in the guest physical address
space where the ram is located. It would be nice to write it down.


>  /* --- arch bits --------------------------------------------------- */
> diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
> index 122d0e8..9099cad 100644
> --- a/tools/libxc/xc_dom_arm.c
> +++ b/tools/libxc/xc_dom_arm.c
> @@ -18,14 +18,138 @@
>   * 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);
> +    /* XXX */
> +    return 0;
> +}
> +
> +static int shared_info_arm(struct xc_dom_image *dom, void *ptr)
> +{
> +    DOMPRINTF_CALLED(dom->xch);
> +    /* XXX */
> +    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;
> +    ctxt->user_regs.r0 = 0; /* SBZ */
> +    ctxt->user_regs.r1 = 2272; /* Machine NR: Versatile Express */
> +
> +    ctxt->user_regs.r2 = 0xffffffff; //devicetree_seg //dtb_paddr; //atags 
> or dtb /* XXX using APPEND right now */
> +    ctxt->user_regs.r3 = 0xdeadbeef;
> +    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;

uhm.. so maybe rambase_pfn is the offset in the machine address space where
the guest ram has been allocated?


> +    /* 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 +160,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..220176d
> --- /dev/null
> +++ b/tools/libxc/xc_dom_armzimageloader.c
> @@ -0,0 +1,167 @@
> +/*
> + * 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... */

Yes, you are right, we should write a be32_to_cpu (the ones in Xen, QEMU
and Linux are GPLv2 rather than LGLPv2).


> +#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 = 0x80000000; /* XXX */
> +
> +    DOMPRINTF_CALLED(dom->xch);
> +
> +    zimage = (uint32_t *)dom->kernel_blob;
> +
> +    dom->rambase_pfn = rambase >> XC_PAGE_SHIFT;
> +
> +    v_start = rambase + 0x8000; /* XXX */
> +    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..b0d48d5 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;

spaces around the '-' please


> +    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;
>      }
> 
> @@ -599,6 +601,8 @@ struct xc_dom_image *xc_dom_allocate(xc_interface *xch,
>      dom->parms.virt_hv_start_low = UNSET_ADDR;
>      dom->parms.elf_paddr_offset = UNSET_ADDR;
> 
> +    dom->rambase_pfn = 0;
> +
>      dom->alloc_malloc += sizeof(*dom);
>      return dom;

There is no need to explicitly set rambase_pfn to 0, because the whole
dom struct is memset to 0 few lines above.



> 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.9.1
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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