ia64/xen-unstable

changeset 13639:fd50500eee7c

libxc domain builder rewrite, core bits.

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
---
tools/libxc/Makefile | 14
tools/libxc/xc_dom.h | 261 +++++++++++++
tools/libxc/xc_dom_binloader.c | 294 +++++++++++++++
tools/libxc/xc_dom_boot.c | 515 +++++++++++++++++++++++++++
tools/libxc/xc_dom_core.c | 773 +++++++++++++++++++++++++++++++++++++++++
tools/libxc/xc_dom_elfloader.c | 283 +++++++++++++++
tools/libxc/xc_dom_ia64.c | 118 ++++++
tools/libxc/xc_dom_powerpc64.c | 100 +++++
tools/libxc/xc_dom_x86.c | 559 +++++++++++++++++++++++++++++
9 files changed, 2917 insertions(+)
author Emmanuel Ackaouy <ack@xensource.com>
date Thu Jan 25 22:16:52 2007 +0000 (2007-01-25)
parents 50d9e2ddc377
children d42878949f63
files tools/libxc/Makefile tools/libxc/xc_dom.h tools/libxc/xc_dom_binloader.c tools/libxc/xc_dom_boot.c tools/libxc/xc_dom_core.c tools/libxc/xc_dom_elfloader.c tools/libxc/xc_dom_ia64.c tools/libxc/xc_dom_powerpc64.c tools/libxc/xc_dom_x86.c
line diff
     1.1 --- a/tools/libxc/Makefile	Thu Jan 25 22:16:52 2007 +0000
     1.2 +++ b/tools/libxc/Makefile	Thu Jan 25 22:16:52 2007 +0000
     1.3 @@ -45,6 +45,20 @@ libelf-relocate.o: libelf-relocate.c lib
     1.4  # add libelf bits to libxc
     1.5  GUEST_SRCS-y += $(LIBELF_SRCS)
     1.6  
     1.7 +# new domain builder
     1.8 +GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
     1.9 +GUEST_SRCS-y += xc_dom_elfloader.c
    1.10 +GUEST_SRCS-y += xc_dom_binloader.c
    1.11 +
    1.12 +ifeq ($(CONFIG_POWERPC),y)
    1.13 +# big endian boxes
    1.14 +GUEST_SRCS-y += xc_dom_powerpc64.c
    1.15 +else
    1.16 +# little endian boxes
    1.17 +GUEST_SRCS-y += xc_dom_x86.c
    1.18 +GUEST_SRCS-y += xc_dom_ia64.c
    1.19 +endif
    1.20 +
    1.21  -include $(XEN_TARGET_ARCH)/Makefile
    1.22  
    1.23  CFLAGS   += -Werror -Wmissing-prototypes
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libxc/xc_dom.h	Thu Jan 25 22:16:52 2007 +0000
     2.3 @@ -0,0 +1,261 @@
     2.4 +#include <xen/libelf.h>
     2.5 +
     2.6 +#define INVALID_P2M_ENTRY   ((xen_pfn_t)-1)
     2.7 +
     2.8 +/* --- typedefs and structs ---------------------------------------- */
     2.9 +
    2.10 +typedef uint64_t xen_vaddr_t;
    2.11 +typedef uint64_t xen_paddr_t;
    2.12 +
    2.13 +/* FIXME: temporary hack ... */
    2.14 +#ifndef PRIpfn
    2.15 +#define PRIpfn "lx"
    2.16 +#endif
    2.17 +
    2.18 +struct xc_dom_seg {
    2.19 +    xen_vaddr_t vstart;
    2.20 +    xen_vaddr_t vend;
    2.21 +    xen_pfn_t pfn;
    2.22 +};
    2.23 +
    2.24 +struct xc_dom_mem {
    2.25 +    struct xc_dom_mem *next;
    2.26 +    void *mmap_ptr;
    2.27 +    size_t mmap_len;
    2.28 +    unsigned char memory[0];
    2.29 +};
    2.30 +
    2.31 +struct xc_dom_phys {
    2.32 +    struct xc_dom_phys *next;
    2.33 +    void *ptr;
    2.34 +    xen_pfn_t first;
    2.35 +    xen_pfn_t count;
    2.36 +};
    2.37 +
    2.38 +struct xc_dom_image {
    2.39 +    /* files */
    2.40 +    void *kernel_blob;
    2.41 +    size_t kernel_size;
    2.42 +    void *ramdisk_blob;
    2.43 +    size_t ramdisk_size;
    2.44 +
    2.45 +    /* arguments and parameters */
    2.46 +    char *cmdline;
    2.47 +    uint32_t f_requested[XENFEAT_NR_SUBMAPS];
    2.48 +
    2.49 +    /* info from (elf) kernel image */
    2.50 +    struct elf_dom_parms parms;
    2.51 +    char *guest_type;
    2.52 +
    2.53 +    /* memory layout */
    2.54 +    struct xc_dom_seg kernel_seg;
    2.55 +    struct xc_dom_seg ramdisk_seg;
    2.56 +    struct xc_dom_seg p2m_seg;
    2.57 +    struct xc_dom_seg pgtables_seg;
    2.58 +    xen_pfn_t start_info_pfn;
    2.59 +    xen_pfn_t console_pfn;
    2.60 +    xen_pfn_t xenstore_pfn;
    2.61 +    xen_pfn_t shared_info_pfn;
    2.62 +    xen_pfn_t bootstack_pfn;
    2.63 +    xen_vaddr_t virt_alloc_end;
    2.64 +    xen_vaddr_t bsd_symtab_start;
    2.65 +
    2.66 +    /* initial page tables */
    2.67 +    unsigned int pgtables;
    2.68 +    unsigned int pg_l4;
    2.69 +    unsigned int pg_l3;
    2.70 +    unsigned int pg_l2;
    2.71 +    unsigned int pg_l1;
    2.72 +    unsigned int alloc_bootstack;
    2.73 +    unsigned int extra_pages;
    2.74 +    xen_vaddr_t virt_pgtab_end;
    2.75 +
    2.76 +    /* other state info */
    2.77 +    uint32_t f_active[XENFEAT_NR_SUBMAPS];
    2.78 +    xen_pfn_t *p2m_host;
    2.79 +    void *p2m_guest;
    2.80 +
    2.81 +    /* physical memory */
    2.82 +    xen_pfn_t total_pages;
    2.83 +    struct xc_dom_phys *phys_pages;
    2.84 +
    2.85 +    /* malloc memory pool */
    2.86 +    struct xc_dom_mem *memblocks;
    2.87 +
    2.88 +    /* memory footprint stats */
    2.89 +    size_t alloc_malloc;
    2.90 +    size_t alloc_mem_map;
    2.91 +    size_t alloc_file_map;
    2.92 +    size_t alloc_domU_map;
    2.93 +
    2.94 +    /* misc xen domain config stuff */
    2.95 +    unsigned long flags;
    2.96 +    unsigned int console_evtchn;
    2.97 +    unsigned int xenstore_evtchn;
    2.98 +    xen_pfn_t shared_info_mfn;
    2.99 +
   2.100 +    int guest_xc;
   2.101 +    domid_t guest_domid;
   2.102 +    int shadow_enabled;
   2.103 +
   2.104 +    int xen_version;
   2.105 +    xen_capabilities_info_t xen_caps;
   2.106 +
   2.107 +    /* kernel loader, arch hooks */
   2.108 +    struct xc_dom_loader *kernel_loader;
   2.109 +    void *private_loader;
   2.110 +
   2.111 +    /* kernel loader */
   2.112 +    struct xc_dom_arch *arch_hooks;
   2.113 +};
   2.114 +
   2.115 +/* --- pluggable kernel loader ------------------------------------- */
   2.116 +
   2.117 +struct xc_dom_loader {
   2.118 +    char *name;
   2.119 +    int (*probe) (struct xc_dom_image * dom);
   2.120 +    int (*parser) (struct xc_dom_image * dom);
   2.121 +    int (*loader) (struct xc_dom_image * dom);
   2.122 +
   2.123 +    struct xc_dom_loader *next;
   2.124 +};
   2.125 +
   2.126 +#define __init __attribute__ ((constructor))
   2.127 +void xc_dom_register_loader(struct xc_dom_loader *loader);
   2.128 +
   2.129 +/* --- arch specific hooks ----------------------------------------- */
   2.130 +
   2.131 +struct xc_dom_arch {
   2.132 +    /* pagetable setup */
   2.133 +    int (*alloc_magic_pages) (struct xc_dom_image * dom);
   2.134 +    int (*count_pgtables) (struct xc_dom_image * dom);
   2.135 +    int (*setup_pgtables) (struct xc_dom_image * dom);
   2.136 +
   2.137 +    /* arch-specific data structs setup */
   2.138 +    int (*start_info) (struct xc_dom_image * dom);
   2.139 +    int (*shared_info) (struct xc_dom_image * dom, void *shared_info);
   2.140 +    int (*vcpu) (struct xc_dom_image * dom, void *vcpu_ctxt);
   2.141 +
   2.142 +    char *guest_type;
   2.143 +    int page_shift;
   2.144 +    int sizeof_pfn;
   2.145 +
   2.146 +    struct xc_dom_arch *next;
   2.147 +};
   2.148 +void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks);
   2.149 +
   2.150 +#define XC_DOM_PAGE_SHIFT(dom)  ((dom)->arch_hooks->page_shift)
   2.151 +#define XC_DOM_PAGE_SIZE(dom)   (1 << (dom)->arch_hooks->page_shift)
   2.152 +
   2.153 +/* --- main functions ---------------------------------------------- */
   2.154 +
   2.155 +struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features);
   2.156 +void xc_dom_release_phys(struct xc_dom_image *dom);
   2.157 +void xc_dom_release(struct xc_dom_image *dom);
   2.158 +int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
   2.159 +
   2.160 +size_t xc_dom_check_gzip(void *blob, size_t ziplen);
   2.161 +int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen);
   2.162 +int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size);
   2.163 +
   2.164 +int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename);
   2.165 +int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename);
   2.166 +int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem,
   2.167 +		      size_t memsize);
   2.168 +int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
   2.169 +		       size_t memsize);
   2.170 +
   2.171 +int xc_dom_parse_image(struct xc_dom_image *dom);
   2.172 +int xc_dom_build_image(struct xc_dom_image *dom);
   2.173 +int xc_dom_update_guest_p2m(struct xc_dom_image *dom);
   2.174 +
   2.175 +int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid);
   2.176 +int xc_dom_boot_mem_init(struct xc_dom_image *dom);
   2.177 +void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
   2.178 +			   xen_pfn_t count);
   2.179 +int xc_dom_boot_image(struct xc_dom_image *dom);
   2.180 +int xc_dom_compat_check(struct xc_dom_image *dom);
   2.181 +
   2.182 +/* --- debugging bits ---------------------------------------------- */
   2.183 +
   2.184 +extern FILE *xc_dom_logfile;
   2.185 +
   2.186 +void xc_dom_loginit(void);
   2.187 +int xc_dom_printf(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
   2.188 +int xc_dom_panic_func(const char *file, int line, xc_error_code err,
   2.189 +		      const char *fmt, ...)
   2.190 +    __attribute__ ((format(printf, 4, 5)));
   2.191 +#define xc_dom_panic(err, fmt, args...) \
   2.192 +	xc_dom_panic_func(__FILE__, __LINE__, err, fmt, ## args)
   2.193 +#define xc_dom_trace(mark) \
   2.194 +	xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark)
   2.195 +
   2.196 +void xc_dom_log_memory_footprint(struct xc_dom_image *dom);
   2.197 +
   2.198 +/* --- simple memory pool ------------------------------------------ */
   2.199 +
   2.200 +void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
   2.201 +void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
   2.202 +void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
   2.203 +			    const char *filename, size_t * size);
   2.204 +char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
   2.205 +
   2.206 +/* --- alloc memory pool ------------------------------------------- */
   2.207 +
   2.208 +int xc_dom_alloc_page(struct xc_dom_image *dom, char *name);
   2.209 +int xc_dom_alloc_segment(struct xc_dom_image *dom,
   2.210 +			 struct xc_dom_seg *seg, char *name,
   2.211 +			 xen_vaddr_t start, xen_vaddr_t size);
   2.212 +
   2.213 +/* --- misc bits --------------------------------------------------- */
   2.214 +
   2.215 +void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
   2.216 +			xen_pfn_t count);
   2.217 +void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
   2.218 +void xc_dom_unmap_all(struct xc_dom_image *dom);
   2.219 +
   2.220 +static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
   2.221 +				      struct xc_dom_seg *seg)
   2.222 +{
   2.223 +    xen_vaddr_t segsize = seg->vend - seg->vstart;
   2.224 +    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
   2.225 +    xen_pfn_t pages = (segsize + page_size - 1) / page_size;
   2.226 +
   2.227 +    return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
   2.228 +}
   2.229 +
   2.230 +static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
   2.231 +					xen_vaddr_t vaddr)
   2.232 +{
   2.233 +    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
   2.234 +    xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
   2.235 +    unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
   2.236 +    void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
   2.237 +
   2.238 +    if (!ptr)
   2.239 +	return NULL;
   2.240 +    return ptr + offset;
   2.241 +}
   2.242 +
   2.243 +static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
   2.244 +{
   2.245 +    return elf_xen_feature_get(XENFEAT_auto_translated_physmap, dom->f_active);
   2.246 +}
   2.247 +
   2.248 +static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
   2.249 +{
   2.250 +    if (dom->shadow_enabled)
   2.251 +	return pfn;
   2.252 +    return dom->p2m_host[pfn];
   2.253 +}
   2.254 +
   2.255 +static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
   2.256 +					 xen_pfn_t pfn)
   2.257 +{
   2.258 +    if (xc_dom_feature_translated(dom))
   2.259 +	return pfn;
   2.260 +    return dom->p2m_host[pfn];
   2.261 +}
   2.262 +
   2.263 +/* --- arch bits --------------------------------------------------- */
   2.264 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/xc_dom_binloader.c	Thu Jan 25 22:16:52 2007 +0000
     3.3 @@ -0,0 +1,294 @@
     3.4 +/******************************************************************************
     3.5 + *
     3.6 + * Loads simple binary images. It's like a .COM file in MS-DOS. No headers are
     3.7 + * present. The only requirement is that it must have a xen_bin_image table
     3.8 + * somewhere in the first 8192 bytes, starting on a 32-bit aligned address.
     3.9 + * Those familiar with the multiboot specification should recognize this, it's
    3.10 + * (almost) the same as the multiboot header.
    3.11 + * The layout of the xen_bin_image table is:
    3.12 + *
    3.13 + * Offset Type Name          Note
    3.14 + * 0      uint32_t  magic         required
    3.15 + * 4      uint32_t  flags         required
    3.16 + * 8      uint32_t  checksum      required
    3.17 + * 12     uint32_t  header_addr   required
    3.18 + * 16     uint32_t  load_addr     required
    3.19 + * 20     uint32_t  load_end_addr required
    3.20 + * 24     uint32_t  bss_end_addr  required
    3.21 + * 28     uint32_t  entry_addr    required
    3.22 + *
    3.23 + * - magic
    3.24 + *   Magic number identifying the table. For images to be loaded by Xen 3, the
    3.25 + *   magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set).
    3.26 + * - flags
    3.27 + *   bit 0: indicates whether the image needs to be loaded on a page boundary
    3.28 + *   bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate
    3.29 + *          that memory info should be passed to the image)
    3.30 + *   bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate
    3.31 + *          that the bootloader should pass video mode info to the image)
    3.32 + *   bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate
    3.33 + *           that the values in the fields header_addr - entry_addr are
    3.34 + *           valid)
    3.35 + *   All other bits should be set to 0.
    3.36 + * - checksum
    3.37 + *   When added to "magic" and "flags", the resulting value should be 0.
    3.38 + * - header_addr
    3.39 + *   Contains the virtual address corresponding to the beginning of the
    3.40 + *   table - the memory location at which the magic value is supposed to be
    3.41 + *   loaded. This field serves to synchronize the mapping between OS image
    3.42 + *   offsets and virtual memory addresses.
    3.43 + * - load_addr
    3.44 + *   Contains the virtual address of the beginning of the text segment. The
    3.45 + *   offset in the OS image file at which to start loading is defined by the
    3.46 + *   offset at which the table was found, minus (header addr - load addr).
    3.47 + *   load addr must be less than or equal to header addr.
    3.48 + * - load_end_addr
    3.49 + *   Contains the virtual address of the end of the data segment.
    3.50 + *   (load_end_addr - load_addr) specifies how much data to load. This implies
    3.51 + *   that the text and data segments must be consecutive in the OS image. If
    3.52 + *   this field is zero, the domain builder assumes that the text and data
    3.53 + *   segments occupy the whole OS image file.
    3.54 + * - bss_end_addr
    3.55 + *   Contains the virtual address of the end of the bss segment. The domain
    3.56 + *   builder initializes this area to zero, and reserves the memory it occupies
    3.57 + *   to avoid placing boot modules and other data relevant to the loaded image
    3.58 + *   in that area. If this field is zero, the domain builder assumes that no bss
    3.59 + *   segment is present.
    3.60 + * - entry_addr
    3.61 + *   The virtual address at which to start execution of the loaded image.
    3.62 + *
    3.63 + * Some of the field descriptions were copied from "The Multiboot
    3.64 + * Specification", Copyright 1995, 96 Bryan Ford <baford@cs.utah.edu>,
    3.65 + * Erich Stefan Boleyn <erich@uruk.org> Copyright 1999, 2000, 2001, 2002
    3.66 + * Free Software Foundation, Inc.
    3.67 + */
    3.68 +
    3.69 +#include <stdlib.h>
    3.70 +#include <inttypes.h>
    3.71 +
    3.72 +#include "xg_private.h"
    3.73 +#include "xc_dom.h"
    3.74 +
    3.75 +#define round_pgup(_p)    (((_p)+(PAGE_SIZE_X86-1))&PAGE_MASK_X86)
    3.76 +#define round_pgdown(_p)  ((_p)&PAGE_MASK_X86)
    3.77 +
    3.78 +struct xen_bin_image_table
    3.79 +{
    3.80 +    uint32_t magic;
    3.81 +    uint32_t flags;
    3.82 +    uint32_t checksum;
    3.83 +    uint32_t header_addr;
    3.84 +    uint32_t load_addr;
    3.85 +    uint32_t load_end_addr;
    3.86 +    uint32_t bss_end_addr;
    3.87 +    uint32_t entry_addr;
    3.88 +};
    3.89 +
    3.90 +#define XEN_MULTIBOOT_MAGIC3 0x336ec578
    3.91 +
    3.92 +#define XEN_MULTIBOOT_FLAG_ALIGN4K     0x00000001
    3.93 +#define XEN_MULTIBOOT_FLAG_NEEDMEMINFO 0x00000002
    3.94 +#define XEN_MULTIBOOT_FLAG_NEEDVIDINFO 0x00000004
    3.95 +#define XEN_MULTIBOOT_FLAG_ADDRSVALID  0x00010000
    3.96 +#define XEN_MULTIBOOT_FLAG_PAE_SHIFT   14
    3.97 +#define XEN_MULTIBOOT_FLAG_PAE_MASK    (3 << XEN_MULTIBOOT_FLAG_PAE_SHIFT)
    3.98 +
    3.99 +/* Flags we test for */
   3.100 +#define FLAGS_MASK     ((~ 0) & (~ XEN_MULTIBOOT_FLAG_ALIGN4K) & \
   3.101 +				(~ XEN_MULTIBOOT_FLAG_PAE_MASK))
   3.102 +#define FLAGS_REQUIRED XEN_MULTIBOOT_FLAG_ADDRSVALID
   3.103 +
   3.104 +/* --------------------------------------------------------------------- */
   3.105 +
   3.106 +static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
   3.107 +{
   3.108 +    struct xen_bin_image_table *table;
   3.109 +    uint32_t *probe_ptr;
   3.110 +    uint32_t *probe_end;
   3.111 +
   3.112 +    probe_ptr = dom->kernel_blob;
   3.113 +    probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
   3.114 +    if ((void*)probe_end > dom->kernel_blob + 8192)
   3.115 +        probe_end = dom->kernel_blob + 8192;
   3.116 +
   3.117 +    for (table = NULL; probe_ptr < probe_end; probe_ptr++)
   3.118 +    {
   3.119 +        if (XEN_MULTIBOOT_MAGIC3 == *probe_ptr)
   3.120 +        {
   3.121 +            table = (struct xen_bin_image_table *) probe_ptr;
   3.122 +            /* Checksum correct? */
   3.123 +            if (0 == table->magic + table->flags + table->checksum)
   3.124 +            {
   3.125 +                return table;
   3.126 +            }
   3.127 +        }
   3.128 +    }
   3.129 +    return NULL;
   3.130 +}
   3.131 +
   3.132 +static int xc_dom_probe_bin_kernel(struct xc_dom_image *dom)
   3.133 +{
   3.134 +    struct xen_bin_image_table *table;
   3.135 +
   3.136 +    table = find_table(dom);
   3.137 +    if (!table)
   3.138 +        return -EINVAL;
   3.139 +    return 0;
   3.140 +}
   3.141 +
   3.142 +static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom)
   3.143 +{
   3.144 +    struct xen_bin_image_table *image_info;
   3.145 +    char *image = dom->kernel_blob;
   3.146 +    size_t image_size = dom->kernel_size;
   3.147 +    uint32_t start_addr;
   3.148 +    uint32_t load_end_addr;
   3.149 +    uint32_t bss_end_addr;
   3.150 +    uint32_t pae_flags;
   3.151 +
   3.152 +    image_info = find_table(dom);
   3.153 +    if (!image_info)
   3.154 +        return -EINVAL;
   3.155 +
   3.156 +    xc_dom_printf("%s: multiboot header fields\n", __FUNCTION__);
   3.157 +    xc_dom_printf("  flags:         0x%" PRIx32 "\n", image_info->flags);
   3.158 +    xc_dom_printf("  header_addr:   0x%" PRIx32 "\n", image_info->header_addr);
   3.159 +    xc_dom_printf("  load_addr:     0x%" PRIx32 "\n", image_info->load_addr);
   3.160 +    xc_dom_printf("  load_end_addr: 0x%" PRIx32 "\n", image_info->load_end_addr);
   3.161 +    xc_dom_printf("  bss_end_addr:  0x%" PRIx32 "\n", image_info->bss_end_addr);
   3.162 +    xc_dom_printf("  entry_addr:    0x%" PRIx32 "\n", image_info->entry_addr);
   3.163 +
   3.164 +    /* Check the flags */
   3.165 +    if ( FLAGS_REQUIRED != (image_info->flags & FLAGS_MASK) )
   3.166 +    {
   3.167 +        xc_dom_panic(XC_INVALID_KERNEL,
   3.168 +                     "%s: xen_bin_image_table flags required "
   3.169 +                     "0x%08" PRIx32 " found 0x%08" PRIx32 "\n",
   3.170 +                     __FUNCTION__, FLAGS_REQUIRED, image_info->flags & FLAGS_MASK);
   3.171 +        return -EINVAL;
   3.172 +    }
   3.173 +
   3.174 +    /* Sanity check on the addresses */
   3.175 +    if ( image_info->header_addr < image_info->load_addr ||
   3.176 +         ((char *) image_info - image) <
   3.177 +         (image_info->header_addr - image_info->load_addr) )
   3.178 +    {
   3.179 +        xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid header_addr.",
   3.180 +                     __FUNCTION__);
   3.181 +        return -EINVAL;
   3.182 +    }
   3.183 +
   3.184 +    start_addr = image_info->header_addr - ((char *)image_info - image);
   3.185 +    load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
   3.186 +    bss_end_addr = image_info->bss_end_addr ?: load_end_addr;
   3.187 +
   3.188 +    xc_dom_printf("%s: calculated addresses\n", __FUNCTION__);
   3.189 +    xc_dom_printf("  start_addr:    0x%" PRIx32 "\n", start_addr);
   3.190 +    xc_dom_printf("  load_end_addr: 0x%" PRIx32 "\n", load_end_addr);
   3.191 +    xc_dom_printf("  bss_end_addr:  0x%" PRIx32 "\n", bss_end_addr);
   3.192 +
   3.193 +    if ( start_addr + image_size < load_end_addr )
   3.194 +    {
   3.195 +        xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid load_end_addr.\n",
   3.196 +                     __FUNCTION__);
   3.197 +        return -EINVAL;
   3.198 +    }
   3.199 +
   3.200 +    if ( bss_end_addr < load_end_addr)
   3.201 +    {
   3.202 +        xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid bss_end_addr.\n",
   3.203 +                     __FUNCTION__);
   3.204 +        return -EINVAL;
   3.205 +    }
   3.206 +
   3.207 +    dom->kernel_seg.vstart = image_info->load_addr;
   3.208 +    dom->kernel_seg.vend   = bss_end_addr;
   3.209 +    dom->parms.virt_base   = start_addr;
   3.210 +    dom->parms.virt_entry  = image_info->entry_addr;
   3.211 +
   3.212 +    pae_flags = image_info->flags & XEN_MULTIBOOT_FLAG_PAE_MASK;
   3.213 +    switch (pae_flags >> XEN_MULTIBOOT_FLAG_PAE_SHIFT) {
   3.214 +    case 0:
   3.215 +	dom->guest_type = "xen-3.0-x86_32";
   3.216 +	break;
   3.217 +    case 1:
   3.218 +	dom->guest_type = "xen-3.0-x86_32p";
   3.219 +	break;
   3.220 +    case 2:
   3.221 +	dom->guest_type = "xen-3.0-x86_64";
   3.222 +	break;
   3.223 +    case 3:
   3.224 +	/* Kernel detects PAE at runtime.  So try to figure whenever
   3.225 +	 * xen supports PAE and advertise a PAE-capable kernel in case
   3.226 +	 * it does. */
   3.227 +	dom->guest_type = "xen-3.0-x86_32";
   3.228 +	if (strstr(dom->xen_caps, "xen-3.0-x86_32p")) {
   3.229 +	    xc_dom_printf("%s: PAE fixup\n", __FUNCTION__);
   3.230 +	    dom->guest_type = "xen-3.0-x86_32p";
   3.231 +	    dom->parms.pae  = 2;
   3.232 +	}
   3.233 +	break;
   3.234 +    }
   3.235 +    return 0;
   3.236 +}
   3.237 +
   3.238 +static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
   3.239 +{
   3.240 +    struct xen_bin_image_table *image_info;
   3.241 +    char *image = dom->kernel_blob;
   3.242 +    char *dest;
   3.243 +    size_t image_size = dom->kernel_size;
   3.244 +    uint32_t start_addr;
   3.245 +    uint32_t load_end_addr;
   3.246 +    uint32_t bss_end_addr;
   3.247 +    uint32_t skip, text_size, bss_size;
   3.248 +    uint32_t pae_flags;
   3.249 +
   3.250 +    image_info = find_table(dom);
   3.251 +    if (!image_info)
   3.252 +        return -EINVAL;
   3.253 +
   3.254 +    start_addr = image_info->header_addr - ((char *)image_info - image);
   3.255 +    load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
   3.256 +    bss_end_addr = image_info->bss_end_addr ?: load_end_addr;
   3.257 +
   3.258 +    /* It's possible that we need to skip the first part of the image */
   3.259 +    skip = image_info->load_addr - start_addr;
   3.260 +    text_size = load_end_addr - image_info->load_addr;
   3.261 +    bss_size = bss_end_addr - load_end_addr;
   3.262 +
   3.263 +    xc_dom_printf("%s: calculated sizes\n", __FUNCTION__);
   3.264 +    xc_dom_printf("  skip:      0x%" PRIx32 "\n", skip);
   3.265 +    xc_dom_printf("  text_size: 0x%" PRIx32 "\n", text_size);
   3.266 +    xc_dom_printf("  bss_size:  0x%" PRIx32 "\n", bss_size);
   3.267 +
   3.268 +    dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
   3.269 +    memcpy(dest, image + skip, text_size);
   3.270 +    memset(dest + text_size, 0, bss_size);
   3.271 +
   3.272 +    pae_flags = image_info->flags & XEN_MULTIBOOT_FLAG_PAE_MASK;
   3.273 +    if (3 == (pae_flags >> XEN_MULTIBOOT_FLAG_PAE_SHIFT) && dom->guest_xc > 0)
   3.274 +    {
   3.275 +    }
   3.276 +    return 0;
   3.277 +}
   3.278 +
   3.279 +/* ------------------------------------------------------------------------ */
   3.280 +
   3.281 +static struct xc_dom_loader bin_loader = {
   3.282 +    .name = "multiboot-binary",
   3.283 +    .probe = xc_dom_probe_bin_kernel,
   3.284 +    .parser = xc_dom_parse_bin_kernel,
   3.285 +    .loader = xc_dom_load_bin_kernel,
   3.286 +};
   3.287 +
   3.288 +static void __init register_loader(void)
   3.289 +{
   3.290 +    xc_dom_register_loader(&bin_loader);
   3.291 +}
   3.292 +
   3.293 +/*
   3.294 + * Local variables:
   3.295 + * c-basic-offset: 4
   3.296 + * End:
   3.297 + */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxc/xc_dom_boot.c	Thu Jan 25 22:16:52 2007 +0000
     4.3 @@ -0,0 +1,515 @@
     4.4 +/*
     4.5 + * Xen domain builder -- xen booter.
     4.6 + *
     4.7 + * This is the code which actually boots a fresh
     4.8 + * prepared domain image as xen guest domain.
     4.9 + *
    4.10 + * ==>  this is the only domain bilder code piece
    4.11 + *          where xen hypercalls are allowed        <==
    4.12 + *
    4.13 + * This code is licenced under the GPL.
    4.14 + * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
    4.15 + *
    4.16 + */
    4.17 +#include <stdio.h>
    4.18 +#include <stdlib.h>
    4.19 +#include <string.h>
    4.20 +#include <inttypes.h>
    4.21 +#include <zlib.h>
    4.22 +
    4.23 +#include "xg_private.h"
    4.24 +#include "xc_dom.h"
    4.25 +#include <xen/hvm/params.h>
    4.26 +
    4.27 +/* ------------------------------------------------------------------------ */
    4.28 +
    4.29 +static int setup_hypercall_page(struct xc_dom_image *dom)
    4.30 +{
    4.31 +    DECLARE_DOMCTL;
    4.32 +    xen_pfn_t pfn;
    4.33 +    int rc;
    4.34 +
    4.35 +    if (-1 == dom->parms.virt_hypercall)
    4.36 +	return 0;
    4.37 +    pfn = (dom->parms.virt_hypercall - dom->parms.virt_base)
    4.38 +	>> XC_DOM_PAGE_SHIFT(dom);
    4.39 +
    4.40 +    xc_dom_printf("%s: vaddr=0x%" PRIx64 " pfn=0x%" PRIpfn "\n", __FUNCTION__,
    4.41 +		  dom->parms.virt_hypercall, pfn);
    4.42 +    domctl.cmd = XEN_DOMCTL_hypercall_init;
    4.43 +    domctl.domain = dom->guest_domid;
    4.44 +    domctl.u.hypercall_init.gmfn = xc_dom_p2m_guest(dom, pfn);
    4.45 +    rc = do_domctl(dom->guest_xc, &domctl);
    4.46 +    if (0 != rc)
    4.47 +	xc_dom_panic(XC_INTERNAL_ERROR, "%s: HYPERCALL_INIT failed (rc=%d)\n",
    4.48 +		     __FUNCTION__, rc);
    4.49 +    return rc;
    4.50 +}
    4.51 +
    4.52 +static int launch_vm(int xc, domid_t domid, void *ctxt)
    4.53 +{
    4.54 +    DECLARE_DOMCTL;
    4.55 +    int rc;
    4.56 +
    4.57 +    xc_dom_printf("%s: called, ctxt=%p\n", __FUNCTION__, ctxt);
    4.58 +    memset(&domctl, 0, sizeof(domctl));
    4.59 +    domctl.cmd = XEN_DOMCTL_setvcpucontext;
    4.60 +    domctl.domain = domid;
    4.61 +    domctl.u.vcpucontext.vcpu = 0;
    4.62 +    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
    4.63 +    rc = do_domctl(xc, &domctl);
    4.64 +    if (0 != rc)
    4.65 +	xc_dom_panic(XC_INTERNAL_ERROR,
    4.66 +		     "%s: SETVCPUCONTEXT failed (rc=%d)\n", __FUNCTION__, rc);
    4.67 +    return rc;
    4.68 +}
    4.69 +
    4.70 +static int clear_page(struct xc_dom_image *dom, xen_pfn_t pfn)
    4.71 +{
    4.72 +    xen_pfn_t dst;
    4.73 +    int rc;
    4.74 +
    4.75 +    if (0 == pfn)
    4.76 +	return 0;
    4.77 +
    4.78 +    dst = xc_dom_p2m_host(dom, pfn);
    4.79 +    xc_dom_printf("%s: pfn 0x%" PRIpfn ", mfn 0x%" PRIpfn "\n",
    4.80 +		  __FUNCTION__, pfn, dst);
    4.81 +    rc = xc_clear_domain_page(dom->guest_xc, dom->guest_domid, dst);
    4.82 +    if (0 != rc)
    4.83 +	xc_dom_panic(XC_INTERNAL_ERROR,
    4.84 +		     "%s: xc_clear_domain_page failed (pfn 0x%" PRIpfn
    4.85 +		     ", rc=%d)\n", __FUNCTION__, pfn, rc);
    4.86 +    return rc;
    4.87 +}
    4.88 +
    4.89 +/* ------------------------------------------------------------------------ */
    4.90 +/* arch stuff: x86 bits                                                     */
    4.91 +
    4.92 +#if defined(__i386__) || defined(__x86_64__)
    4.93 +
    4.94 +
    4.95 +static int x86_compat(int xc, domid_t domid, char *guest_type)
    4.96 +{
    4.97 +#ifdef XEN_DOMCTL_set_compat
    4.98 +    static const struct {
    4.99 +	char           *guest;
   4.100 +	unsigned long  cmd;
   4.101 +    } types[] = {
   4.102 +	{ "xen-3.0-x86_32p", XEN_DOMCTL_set_compat },
   4.103 +	{ "xen-3.0-x86_64",  XEN_DOMCTL_set_native },
   4.104 +    };
   4.105 +    DECLARE_DOMCTL;
   4.106 +    int i,rc;
   4.107 +
   4.108 +    memset(&domctl, 0, sizeof(domctl));
   4.109 +    domctl.domain = domid;
   4.110 +    for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)
   4.111 +	if (0 == strcmp(types[i].guest, guest_type))
   4.112 +	    domctl.cmd = types[i].cmd;
   4.113 +    if (0 == domctl.cmd)
   4.114 +	/* nothing to do */
   4.115 +	return 0;
   4.116 +
   4.117 +    xc_dom_printf("%s: guest %s, cmd %d\n", __FUNCTION__,
   4.118 +		  guest_type, domctl.cmd);
   4.119 +    rc = do_domctl(xc, &domctl);
   4.120 +    if (0 != rc)
   4.121 +	xc_dom_printf("%s: warning: failed (rc=%d)\n",
   4.122 +		      __FUNCTION__, rc);
   4.123 +    return rc;
   4.124 +#else
   4.125 +    xc_dom_printf("%s: compiled without compat/native switching\n", __FUNCTION__);
   4.126 +    return 0;
   4.127 +#endif /* XEN_DOMCTL_set_compat */
   4.128 +}
   4.129 +
   4.130 +
   4.131 +static int x86_shadow(int xc, domid_t domid)
   4.132 +{
   4.133 +    int rc, mode;
   4.134 +
   4.135 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   4.136 +
   4.137 +    mode = XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT |
   4.138 +	XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE;
   4.139 +
   4.140 +    rc = xc_shadow_control(xc, domid,
   4.141 +			   XEN_DOMCTL_SHADOW_OP_ENABLE,
   4.142 +			   NULL, 0, NULL, mode, NULL);
   4.143 +    if (0 != rc)
   4.144 +    {
   4.145 +	xc_dom_panic(XC_INTERNAL_ERROR,
   4.146 +		     "%s: SHADOW_OP_ENABLE (mode=0x%x) failed (rc=%d)\n",
   4.147 +		     __FUNCTION__, mode, rc);
   4.148 +	return rc;
   4.149 +    }
   4.150 +    xc_dom_printf("%s: shadow enabled (mode=0x%x)\n", __FUNCTION__, mode);
   4.151 +    return rc;
   4.152 +}
   4.153 +
   4.154 +static int arch_setup_early(struct xc_dom_image *dom)
   4.155 +{
   4.156 +    int rc = 0;
   4.157 +
   4.158 +    x86_compat(dom->guest_xc, dom->guest_domid, dom->guest_type);
   4.159 +    if (xc_dom_feature_translated(dom))
   4.160 +    {
   4.161 +	dom->shadow_enabled = 1;
   4.162 +	rc = x86_shadow(dom->guest_xc, dom->guest_domid);
   4.163 +    }
   4.164 +    return rc;
   4.165 +}
   4.166 +
   4.167 +static int arch_setup_late(struct xc_dom_image *dom)
   4.168 +{
   4.169 +    static const struct {
   4.170 +	char *guest;
   4.171 +	unsigned long pgd_type;
   4.172 +    } types[] = {
   4.173 +	{ "xen-3.0-x86_32",  MMUEXT_PIN_L2_TABLE},
   4.174 +	{ "xen-3.0-x86_32p", MMUEXT_PIN_L3_TABLE},
   4.175 +	{ "xen-3.0-x86_64",  MMUEXT_PIN_L4_TABLE},
   4.176 +    };
   4.177 +    unsigned long pgd_type = 0;
   4.178 +    shared_info_t *shared_info;
   4.179 +    xen_pfn_t shinfo;
   4.180 +    int i, rc;
   4.181 +
   4.182 +    for (i = 0; i < sizeof(types) / sizeof(types[0]); i++)
   4.183 +	if (0 == strcmp(types[i].guest, dom->guest_type))
   4.184 +	    pgd_type = types[i].pgd_type;
   4.185 +
   4.186 +    if (!xc_dom_feature_translated(dom))
   4.187 +    {
   4.188 +	/* paravirtualized guest */
   4.189 +	xc_dom_unmap_one(dom, dom->pgtables_seg.pfn);
   4.190 +	rc = pin_table(dom->guest_xc, pgd_type,
   4.191 +		       xc_dom_p2m_host(dom, dom->pgtables_seg.pfn),
   4.192 +		       dom->guest_domid);
   4.193 +	if (0 != rc)
   4.194 +	{
   4.195 +	    xc_dom_panic(XC_INTERNAL_ERROR,
   4.196 +			 "%s: pin_table failed (pfn 0x%" PRIpfn ", rc=%d)\n",
   4.197 +			 __FUNCTION__, dom->pgtables_seg.pfn, rc);
   4.198 +	    return rc;
   4.199 +	}
   4.200 +	shinfo = dom->shared_info_mfn;
   4.201 +    }
   4.202 +    else
   4.203 +    {
   4.204 +	/* paravirtualized guest with auto-translation */
   4.205 +	struct xen_add_to_physmap xatp;
   4.206 +	int i;
   4.207 +
   4.208 +	/* Map shared info frame into guest physmap. */
   4.209 +	xatp.domid = dom->guest_domid;
   4.210 +	xatp.space = XENMAPSPACE_shared_info;
   4.211 +	xatp.idx = 0;
   4.212 +	xatp.gpfn = dom->shared_info_pfn;
   4.213 +	rc = xc_memory_op(dom->guest_xc, XENMEM_add_to_physmap, &xatp);
   4.214 +	if (rc != 0)
   4.215 +	{
   4.216 +	    xc_dom_panic(XC_INTERNAL_ERROR, "%s: mapping shared_info failed "
   4.217 +			 "(pfn=0x%" PRIpfn ", rc=%d)\n",
   4.218 +			 __FUNCTION__, xatp.gpfn, rc);
   4.219 +	    return rc;
   4.220 +	}
   4.221 +
   4.222 +	/* Map grant table frames into guest physmap. */
   4.223 +	for (i = 0;; i++)
   4.224 +	{
   4.225 +	    xatp.domid = dom->guest_domid;
   4.226 +	    xatp.space = XENMAPSPACE_grant_table;
   4.227 +	    xatp.idx = i;
   4.228 +	    xatp.gpfn = dom->total_pages + i;
   4.229 +	    rc = xc_memory_op(dom->guest_xc, XENMEM_add_to_physmap, &xatp);
   4.230 +	    if (rc != 0)
   4.231 +	    {
   4.232 +		if (i > 0 && errno == EINVAL)
   4.233 +		{
   4.234 +		    xc_dom_printf("%s: %d grant tables mapped\n", __FUNCTION__,
   4.235 +				  i);
   4.236 +		    break;
   4.237 +		}
   4.238 +		xc_dom_panic(XC_INTERNAL_ERROR,
   4.239 +			     "%s: mapping grant tables failed " "(pfn=0x%"
   4.240 +			     PRIpfn ", rc=%d)\n", __FUNCTION__, xatp.gpfn, rc);
   4.241 +		return rc;
   4.242 +	    }
   4.243 +	}
   4.244 +	shinfo = dom->shared_info_pfn;
   4.245 +    }
   4.246 +
   4.247 +    /* setup shared_info page */
   4.248 +    xc_dom_printf("%s: shared_info: pfn 0x%" PRIpfn ", mfn 0x%" PRIpfn "\n",
   4.249 +		  __FUNCTION__, dom->shared_info_pfn, dom->shared_info_mfn);
   4.250 +    shared_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
   4.251 +				       PAGE_SIZE_X86,
   4.252 +				       PROT_READ | PROT_WRITE,
   4.253 +				       shinfo);
   4.254 +    if (NULL == shared_info)
   4.255 +	return -1;
   4.256 +    dom->arch_hooks->shared_info(dom, shared_info);
   4.257 +    munmap(shared_info, PAGE_SIZE_X86);
   4.258 +
   4.259 +    return 0;
   4.260 +}
   4.261 +
   4.262 +/* ------------------------------------------------------------------------ */
   4.263 +/* arch stuff: ia64                                                         */
   4.264 +
   4.265 +#elif defined(__ia64__)
   4.266 +
   4.267 +static int arch_setup_early(struct xc_dom_image *dom)
   4.268 +{
   4.269 +    DECLARE_DOMCTL;
   4.270 +    int rc;
   4.271 +
   4.272 +    xc_dom_printf("%s: setup firmware\n", __FUNCTION__);
   4.273 +
   4.274 +    memset(&domctl, 0, sizeof(domctl));
   4.275 +    domctl.cmd = XEN_DOMCTL_arch_setup;
   4.276 +    domctl.domain = dom->guest_domid;
   4.277 +    domctl.u.arch_setup.flags = 0;
   4.278 +    domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT)
   4.279 +	+ sizeof(start_info_t);
   4.280 +    domctl.u.arch_setup.maxmem = dom->total_pages << PAGE_SHIFT;
   4.281 +    rc = do_domctl(dom->guest_xc, &domctl);
   4.282 +    return rc;
   4.283 +}
   4.284 +
   4.285 +static int arch_setup_late(struct xc_dom_image *dom)
   4.286 +{
   4.287 +    xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
   4.288 +    return 0;
   4.289 +}
   4.290 +
   4.291 +/* ------------------------------------------------------------------------ */
   4.292 +/* arch stuff: powerpc                                                      */
   4.293 +
   4.294 +#elif defined(__powerpc64__)
   4.295 +
   4.296 +static int arch_setup_early(struct xc_dom_image *dom)
   4.297 +{
   4.298 +    xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
   4.299 +    return 0;
   4.300 +}
   4.301 +
   4.302 +static int arch_setup_late(struct xc_dom_image *dom)
   4.303 +{
   4.304 +    start_info_t *si =
   4.305 +	xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
   4.306 +
   4.307 +    xc_dom_printf("%s: TODO: setup devtree\n", __FUNCTION__);
   4.308 +
   4.309 +#if 0
   4.310 +    load_devtree(dom->guest_xc,
   4.311 +		 dom->guest_domid,
   4.312 +		 dom->p2m_host,
   4.313 +		 devtree,           // FIXME
   4.314 +		 devtree_addr,      // FIXME
   4.315 +		 dom->ramdisk_seg.vstart,
   4.316 +		 dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart,
   4.317 +		 si,
   4.318 +		 dom->start_info_pfn << PAGE_SHIFT);
   4.319 +#endif
   4.320 +    return rc;
   4.321 +}
   4.322 +
   4.323 +/* ------------------------------------------------------------------------ */
   4.324 +/* arch stuff: other                                                        */
   4.325 +
   4.326 +#else
   4.327 +
   4.328 +static int arch_setup_early(struct xc_dom_image *dom)
   4.329 +{
   4.330 +    xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
   4.331 +    return 0;
   4.332 +}
   4.333 +
   4.334 +static int arch_setup_late(struct xc_dom_image *dom)
   4.335 +{
   4.336 +    xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
   4.337 +    return 0;
   4.338 +}
   4.339 +
   4.340 +#endif /* arch stuff */
   4.341 +
   4.342 +/* ------------------------------------------------------------------------ */
   4.343 +
   4.344 +int xc_dom_compat_check(struct xc_dom_image *dom)
   4.345 +{
   4.346 +    xen_capabilities_info_t xen_caps;
   4.347 +    char *item, *ptr;
   4.348 +    int match, found = 0;
   4.349 +
   4.350 +    strcpy(xen_caps, dom->xen_caps);
   4.351 +    for (item = strtok_r(xen_caps, " ", &ptr);
   4.352 +	 NULL != item; item = strtok_r(NULL, " ", &ptr))
   4.353 +    {
   4.354 +	match = (0 == strcmp(dom->guest_type, item));
   4.355 +	xc_dom_printf("%s: supported guest type: %s%s\n", __FUNCTION__,
   4.356 +		      item, match ? " <= matches" : "");
   4.357 +	if (match)
   4.358 +	    found++;
   4.359 +    }
   4.360 +    if (!found)
   4.361 +	xc_dom_panic(XC_INVALID_KERNEL,
   4.362 +		     "%s: guest type %s not supported by xen kernel, sorry\n",
   4.363 +		     __FUNCTION__, dom->guest_type);
   4.364 +
   4.365 +    return found;
   4.366 +}
   4.367 +
   4.368 +int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid)
   4.369 +{
   4.370 +    dom->guest_xc = xc;
   4.371 +    dom->guest_domid = domid;
   4.372 +
   4.373 +    dom->xen_version = xc_version(dom->guest_xc, XENVER_version, NULL);
   4.374 +    if (xc_version(xc, XENVER_capabilities, &dom->xen_caps) < 0) {
   4.375 +	xc_dom_panic(XC_INTERNAL_ERROR, "can't get xen capabilities");
   4.376 +	return -1;
   4.377 +    }
   4.378 +    xc_dom_printf("%s: ver %d.%d, caps %s\n", __FUNCTION__,
   4.379 +		  dom->xen_version >> 16, dom->xen_version & 0xff,
   4.380 +		  dom->xen_caps);
   4.381 +    return 0;
   4.382 +}
   4.383 +
   4.384 +int xc_dom_boot_mem_init(struct xc_dom_image *dom)
   4.385 +{
   4.386 +    long rc;
   4.387 +
   4.388 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   4.389 +
   4.390 +    if (0 != (rc = arch_setup_early(dom)))
   4.391 +	return rc;
   4.392 +
   4.393 +    /* allocate guest memory */
   4.394 +    rc = xc_domain_memory_populate_physmap(dom->guest_xc, dom->guest_domid,
   4.395 +					   dom->total_pages, 0, 0,
   4.396 +					   dom->p2m_host);
   4.397 +    if (0 != rc)
   4.398 +    {
   4.399 +	xc_dom_panic(XC_OUT_OF_MEMORY,
   4.400 +		     "%s: can't allocate low memory for domain\n",
   4.401 +		     __FUNCTION__);
   4.402 +	return rc;
   4.403 +    }
   4.404 +
   4.405 +    return 0;
   4.406 +}
   4.407 +
   4.408 +void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
   4.409 +			   xen_pfn_t count)
   4.410 +{
   4.411 +    int page_shift = XC_DOM_PAGE_SHIFT(dom);
   4.412 +    privcmd_mmap_entry_t *entries;
   4.413 +    void *ptr;
   4.414 +    int i, rc;
   4.415 +
   4.416 +    entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t));
   4.417 +    if (NULL == entries)
   4.418 +    {
   4.419 +	xc_dom_panic(XC_INTERNAL_ERROR,
   4.420 +		     "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
   4.421 +		     " [malloc]\n", __FUNCTION__, pfn, count);
   4.422 +	return NULL;
   4.423 +    }
   4.424 +
   4.425 +    ptr = mmap(NULL, count << page_shift, PROT_READ | PROT_WRITE,
   4.426 +	       MAP_SHARED, dom->guest_xc, 0);
   4.427 +    if (MAP_FAILED == ptr)
   4.428 +    {
   4.429 +	xc_dom_panic(XC_INTERNAL_ERROR,
   4.430 +		     "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
   4.431 +		     " [mmap]\n", __FUNCTION__, pfn, count);
   4.432 +	return NULL;
   4.433 +    }
   4.434 +
   4.435 +    for (i = 0; i < count; i++)
   4.436 +    {
   4.437 +	entries[i].va = (uintptr_t) ptr + (i << page_shift);
   4.438 +	entries[i].mfn = xc_dom_p2m_host(dom, pfn + i);
   4.439 +	entries[i].npages = 1;
   4.440 +    }
   4.441 +
   4.442 +    rc = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid, entries, count);
   4.443 +    if (rc < 0)
   4.444 +    {
   4.445 +	xc_dom_panic(XC_INTERNAL_ERROR,
   4.446 +		     "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
   4.447 +		     " [xenctl, rc=%d]\n", __FUNCTION__, pfn, count, rc);
   4.448 +	return NULL;
   4.449 +    }
   4.450 +    return ptr;
   4.451 +}
   4.452 +
   4.453 +int xc_dom_boot_image(struct xc_dom_image *dom)
   4.454 +{
   4.455 +    DECLARE_DOMCTL;
   4.456 +    void *ctxt;
   4.457 +    int rc;
   4.458 +
   4.459 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   4.460 +
   4.461 +    /* collect some info */
   4.462 +    domctl.cmd = XEN_DOMCTL_getdomaininfo;
   4.463 +    domctl.domain = dom->guest_domid;
   4.464 +    rc = do_domctl(dom->guest_xc, &domctl);
   4.465 +    if (0 != rc)
   4.466 +    {
   4.467 +	xc_dom_panic(XC_INTERNAL_ERROR,
   4.468 +		     "%s: getdomaininfo failed (rc=%d)\n", __FUNCTION__, rc);
   4.469 +	return rc;
   4.470 +    }
   4.471 +    if (domctl.domain != dom->guest_domid)
   4.472 +    {
   4.473 +	xc_dom_panic(XC_INTERNAL_ERROR,
   4.474 +		     "%s: Huh? domid mismatch (%d != %d)\n", __FUNCTION__,
   4.475 +		     domctl.domain, dom->guest_domid);
   4.476 +	return -1;
   4.477 +    }
   4.478 +    dom->shared_info_mfn = domctl.u.getdomaininfo.shared_info_frame;
   4.479 +
   4.480 +    /* sanity checks */
   4.481 +    if (!xc_dom_compat_check(dom))
   4.482 +	return -1;
   4.483 +
   4.484 +    /* initial mm setup */
   4.485 +    if (0 != (rc = xc_dom_update_guest_p2m(dom)))
   4.486 +	return rc;
   4.487 +    if (dom->arch_hooks->setup_pgtables)
   4.488 +	if (0 != (rc = dom->arch_hooks->setup_pgtables(dom)))
   4.489 +	    return rc;
   4.490 +
   4.491 +    if (0 != (rc = clear_page(dom, dom->console_pfn)))
   4.492 +	return rc;
   4.493 +    if (0 != (rc = clear_page(dom, dom->xenstore_pfn)))
   4.494 +	return rc;
   4.495 +
   4.496 +    /* start info page */
   4.497 +    if (dom->arch_hooks->start_info)
   4.498 +	dom->arch_hooks->start_info(dom);
   4.499 +
   4.500 +    /* hypercall page */
   4.501 +    if (0 != (rc = setup_hypercall_page(dom)))
   4.502 +	return rc;
   4.503 +    xc_dom_log_memory_footprint(dom);
   4.504 +
   4.505 +    /* misc x86 stuff */
   4.506 +    if (0 != (rc = arch_setup_late(dom)))
   4.507 +	return rc;
   4.508 +
   4.509 +    /* let the vm run */
   4.510 +    ctxt = xc_dom_malloc(dom, PAGE_SIZE * 2 /* FIXME */ );
   4.511 +    memset(ctxt, 0, PAGE_SIZE * 2);
   4.512 +    if (0 != (rc = dom->arch_hooks->vcpu(dom, ctxt)))
   4.513 +	return rc;
   4.514 +    xc_dom_unmap_all(dom);
   4.515 +    rc = launch_vm(dom->guest_xc, dom->guest_domid, ctxt);
   4.516 +
   4.517 +    return rc;
   4.518 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libxc/xc_dom_core.c	Thu Jan 25 22:16:52 2007 +0000
     5.3 @@ -0,0 +1,773 @@
     5.4 +/*
     5.5 + * Xen domain builder -- core bits.
     5.6 + *
     5.7 + * The core code goes here:
     5.8 + *   - allocate and release domain structs.
     5.9 + *   - memory management functions.
    5.10 + *   - misc helper functions.
    5.11 + *
    5.12 + * This code is licenced under the GPL.
    5.13 + * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
    5.14 + *
    5.15 + */
    5.16 +#include <stdio.h>
    5.17 +#include <stdlib.h>
    5.18 +#include <string.h>
    5.19 +#include <stdarg.h>
    5.20 +#include <inttypes.h>
    5.21 +#include <zlib.h>
    5.22 +
    5.23 +#include "xg_private.h"
    5.24 +#include "xc_dom.h"
    5.25 +
    5.26 +/* ------------------------------------------------------------------------ */
    5.27 +/* debugging                                                                */
    5.28 +
    5.29 +FILE *xc_dom_logfile = NULL;
    5.30 +
    5.31 +void xc_dom_loginit(void)
    5.32 +{
    5.33 +    if (xc_dom_logfile)
    5.34 +	return;
    5.35 +    xc_dom_logfile = fopen("/var/log/xen/domain-builder-ng.log", "a");
    5.36 +    setvbuf(xc_dom_logfile, NULL, _IONBF, 0);
    5.37 +    xc_dom_printf("### ----- xc domain builder logfile opened -----\n");
    5.38 +}
    5.39 +
    5.40 +int xc_dom_printf(const char *fmt, ...)
    5.41 +{
    5.42 +    va_list args;
    5.43 +    char buf[1024];
    5.44 +    int rc;
    5.45 +
    5.46 +    if (!xc_dom_logfile)
    5.47 +	return 0;
    5.48 +
    5.49 +    va_start(args, fmt);
    5.50 +    rc = vsnprintf(buf, sizeof(buf), fmt, args);
    5.51 +    va_end(args);
    5.52 +    rc = fwrite(buf, rc, 1, xc_dom_logfile);
    5.53 +
    5.54 +    return rc;
    5.55 +}
    5.56 +
    5.57 +int xc_dom_panic_func(const char *file, int line, xc_error_code err,
    5.58 +		      const char *fmt, ...)
    5.59 +{
    5.60 +    va_list args;
    5.61 +    FILE *fp = stderr;
    5.62 +    int rc = 0;
    5.63 +    char pos[256];
    5.64 +    char msg[XC_MAX_ERROR_MSG_LEN];
    5.65 +
    5.66 +    if (xc_dom_logfile)
    5.67 +	fp = xc_dom_logfile;
    5.68 +
    5.69 +    snprintf(pos, sizeof(pos), "%s:%d: panic: ", file, line);
    5.70 +    va_start(args, fmt);
    5.71 +    vsnprintf(msg, sizeof(msg), fmt, args);
    5.72 +    va_end(args);
    5.73 +    xc_set_error(err, "%s", msg);
    5.74 +    rc = fprintf(fp, "%s%s", pos, msg);
    5.75 +    return rc;
    5.76 +}
    5.77 +
    5.78 +static void print_mem(const char *name, size_t mem)
    5.79 +{
    5.80 +    if (mem > 32 * 1024 * 1024)
    5.81 +	xc_dom_printf("%-24s : %zd MB\n", name, mem / (1024 * 1024));
    5.82 +    else if (mem > 32 * 1024)
    5.83 +	xc_dom_printf("%-24s : %zd kB\n", name, mem / 1024);
    5.84 +    else
    5.85 +	xc_dom_printf("%-24s : %zd bytes\n", name, mem);
    5.86 +}
    5.87 +
    5.88 +void xc_dom_log_memory_footprint(struct xc_dom_image *dom)
    5.89 +{
    5.90 +    xc_dom_printf("domain builder memory footprint\n");
    5.91 +    xc_dom_printf("   allocated\n");
    5.92 +    print_mem("      malloc", dom->alloc_malloc);
    5.93 +    print_mem("      anon mmap", dom->alloc_mem_map);
    5.94 +    xc_dom_printf("   mapped\n");
    5.95 +    print_mem("      file mmap", dom->alloc_file_map);
    5.96 +    print_mem("      domU mmap", dom->alloc_domU_map);
    5.97 +}
    5.98 +
    5.99 +/* ------------------------------------------------------------------------ */
   5.100 +/* simple memory pool                                                       */
   5.101 +
   5.102 +void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
   5.103 +{
   5.104 +    struct xc_dom_mem *block;
   5.105 +
   5.106 +    block = malloc(sizeof(*block) + size);
   5.107 +    if (NULL == block)
   5.108 +	return NULL;
   5.109 +    memset(block, 0, sizeof(*block) + size);
   5.110 +    block->next = dom->memblocks;
   5.111 +    dom->memblocks = block;
   5.112 +    dom->alloc_malloc += sizeof(*block) + size;
   5.113 +    if (size > 100 * 1024)
   5.114 +	print_mem(__FUNCTION__, size);
   5.115 +    return block->memory;
   5.116 +}
   5.117 +
   5.118 +void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
   5.119 +{
   5.120 +    struct xc_dom_mem *block;
   5.121 +
   5.122 +    block = malloc(sizeof(*block));
   5.123 +    if (NULL == block)
   5.124 +	return NULL;
   5.125 +    memset(block, 0, sizeof(*block));
   5.126 +    block->mmap_len = size;
   5.127 +    block->mmap_ptr = mmap(NULL, block->mmap_len,
   5.128 +			   PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
   5.129 +			   -1, 0);
   5.130 +    if (MAP_FAILED == block->mmap_ptr)
   5.131 +    {
   5.132 +	free(block);
   5.133 +	return NULL;
   5.134 +    }
   5.135 +    block->next = dom->memblocks;
   5.136 +    dom->memblocks = block;
   5.137 +    dom->alloc_malloc += sizeof(*block);
   5.138 +    dom->alloc_mem_map += block->mmap_len;
   5.139 +    if (size > 100 * 1024)
   5.140 +	print_mem(__FUNCTION__, size);
   5.141 +    return block->mmap_ptr;
   5.142 +}
   5.143 +
   5.144 +void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
   5.145 +			    const char *filename, size_t * size)
   5.146 +{
   5.147 +    struct xc_dom_mem *block = NULL;
   5.148 +    int fd = -1;
   5.149 +
   5.150 +    fd = open(filename, O_RDONLY);
   5.151 +    if (-1 == fd)
   5.152 +	goto err;
   5.153 +
   5.154 +    lseek(fd, 0, SEEK_SET);
   5.155 +    *size = lseek(fd, 0, SEEK_END);
   5.156 +
   5.157 +    block = malloc(sizeof(*block));
   5.158 +    if (NULL == block)
   5.159 +	goto err;
   5.160 +    memset(block, 0, sizeof(*block));
   5.161 +    block->mmap_len = *size;
   5.162 +    block->mmap_ptr = mmap(NULL, block->mmap_len, PROT_READ, MAP_SHARED, fd, 0);
   5.163 +    if (MAP_FAILED == block->mmap_ptr)
   5.164 +	goto err;
   5.165 +    block->next = dom->memblocks;
   5.166 +    dom->memblocks = block;
   5.167 +    dom->alloc_malloc += sizeof(*block);
   5.168 +    dom->alloc_file_map += block->mmap_len;
   5.169 +    close(fd);
   5.170 +    if (*size > 100 * 1024)
   5.171 +	print_mem(__FUNCTION__, *size);
   5.172 +    return block->mmap_ptr;
   5.173 +
   5.174 +  err:
   5.175 +    if (-1 != fd)
   5.176 +	close(fd);
   5.177 +    if (block)
   5.178 +	free(block);
   5.179 +    return NULL;
   5.180 +}
   5.181 +
   5.182 +static void xc_dom_free_all(struct xc_dom_image *dom)
   5.183 +{
   5.184 +    struct xc_dom_mem *block;
   5.185 +
   5.186 +    while (NULL != (block = dom->memblocks))
   5.187 +    {
   5.188 +	dom->memblocks = block->next;
   5.189 +	if (block->mmap_ptr)
   5.190 +	    munmap(block->mmap_ptr, block->mmap_len);
   5.191 +	free(block);
   5.192 +    }
   5.193 +}
   5.194 +
   5.195 +char *xc_dom_strdup(struct xc_dom_image *dom, const char *str)
   5.196 +{
   5.197 +    size_t len = strlen(str) + 1;
   5.198 +    char *nstr = xc_dom_malloc(dom, len);
   5.199 +
   5.200 +    if (NULL == nstr)
   5.201 +	return NULL;
   5.202 +    memcpy(nstr, str, len);
   5.203 +    return nstr;
   5.204 +}
   5.205 +
   5.206 +/* ------------------------------------------------------------------------ */
   5.207 +/* read files, copy memory blocks, with transparent gunzip                  */
   5.208 +
   5.209 +size_t xc_dom_check_gzip(void *blob, size_t ziplen)
   5.210 +{
   5.211 +    unsigned char *gzlen;
   5.212 +    size_t unziplen;
   5.213 +
   5.214 +    if (0 != strncmp(blob, "\037\213", 2))
   5.215 +	/* not gzipped */
   5.216 +	return 0;
   5.217 +
   5.218 +    gzlen = blob + ziplen - 4;
   5.219 +    unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
   5.220 +    if (unziplen < ziplen || unziplen > ziplen * 8)
   5.221 +    {
   5.222 +	xc_dom_printf
   5.223 +	    ("%s: size (zip %zd, unzip %zd) looks insane, skip gunzip\n",
   5.224 +	     __FUNCTION__, ziplen, unziplen);
   5.225 +	return 0;
   5.226 +    }
   5.227 +
   5.228 +    return unziplen + 16;
   5.229 +}
   5.230 +
   5.231 +int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen)
   5.232 +{
   5.233 +    z_stream zStream;
   5.234 +    int rc;
   5.235 +
   5.236 +    memset(&zStream, 0, sizeof(zStream));
   5.237 +    zStream.next_in = src;
   5.238 +    zStream.avail_in = srclen;
   5.239 +    zStream.next_out = dst;
   5.240 +    zStream.avail_out = dstlen;
   5.241 +    rc = inflateInit2(&zStream, (MAX_WBITS + 32));	/* +32 means "handle gzip" */
   5.242 +    if (rc != Z_OK)
   5.243 +    {
   5.244 +	xc_dom_panic(XC_INTERNAL_ERROR,
   5.245 +		     "%s: inflateInit2 failed (rc=%d)\n", __FUNCTION__, rc);
   5.246 +	return -1;
   5.247 +    }
   5.248 +    rc = inflate(&zStream, Z_FINISH);
   5.249 +    if (rc != Z_STREAM_END)
   5.250 +    {
   5.251 +	xc_dom_panic(XC_INTERNAL_ERROR,
   5.252 +		     "%s: inflate failed (rc=%d)\n", __FUNCTION__, rc);
   5.253 +	return -1;
   5.254 +    }
   5.255 +
   5.256 +    xc_dom_printf("%s: unzip ok, 0x%zx -> 0x%zx\n",
   5.257 +		  __FUNCTION__, srclen, dstlen);
   5.258 +    return 0;
   5.259 +}
   5.260 +
   5.261 +int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
   5.262 +{
   5.263 +    void *unzip;
   5.264 +    size_t unziplen;
   5.265 +
   5.266 +    unziplen = xc_dom_check_gzip(*blob, *size);
   5.267 +    if (0 == unziplen)
   5.268 +	return 0;
   5.269 +
   5.270 +    unzip = xc_dom_malloc(dom, unziplen);
   5.271 +    if (NULL == unzip)
   5.272 +	return -1;
   5.273 +
   5.274 +    if (-1 == xc_dom_do_gunzip(*blob, *size, unzip, unziplen))
   5.275 +	return -1;
   5.276 +
   5.277 +    *blob = unzip;
   5.278 +    *size = unziplen;
   5.279 +    return 0;
   5.280 +}
   5.281 +
   5.282 +/* ------------------------------------------------------------------------ */
   5.283 +/* domain memory                                                            */
   5.284 +
   5.285 +void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
   5.286 +			xen_pfn_t count)
   5.287 +{
   5.288 +    struct xc_dom_phys *phys;
   5.289 +    unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
   5.290 +    char *mode = "unset";
   5.291 +
   5.292 +    if (pfn > dom->total_pages)
   5.293 +    {
   5.294 +	xc_dom_printf("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")\n",
   5.295 +		      __FUNCTION__, pfn, dom->total_pages);
   5.296 +	return NULL;
   5.297 +    }
   5.298 +
   5.299 +    /* already allocated? */
   5.300 +    for (phys = dom->phys_pages; NULL != phys; phys = phys->next)
   5.301 +    {
   5.302 +	if (pfn >= phys->first + phys->count)
   5.303 +	    continue;
   5.304 +	if (count)
   5.305 +	{
   5.306 +	    /* size given: must be completely within the already allocated block */
   5.307 +	    if (pfn + count <= phys->first)
   5.308 +		continue;
   5.309 +	    if (pfn < phys->first || pfn + count > phys->first + phys->count)
   5.310 +	    {
   5.311 +		xc_dom_printf("%s: request overlaps allocated block"
   5.312 +			      " (req 0x%" PRIpfn "+0x%" PRIpfn ","
   5.313 +			      " blk 0x%" PRIpfn "+0x%" PRIpfn ")\n",
   5.314 +			      __FUNCTION__, pfn, count, phys->first,
   5.315 +			      phys->count);
   5.316 +		return NULL;
   5.317 +	    }
   5.318 +	}
   5.319 +	else
   5.320 +	{
   5.321 +	    /* no size given: block must be allocated already,
   5.322 +	       just hand out a pointer to it */
   5.323 +	    if (pfn < phys->first)
   5.324 +		continue;
   5.325 +	}
   5.326 +	return phys->ptr + ((pfn - phys->first) << page_shift);
   5.327 +    }
   5.328 +
   5.329 +    /* allocating is allowed with size specified only */
   5.330 +    if (0 == count)
   5.331 +    {
   5.332 +	xc_dom_printf("%s: no block found, no size given,"
   5.333 +		      " can't malloc (pfn 0x%" PRIpfn ")\n", __FUNCTION__, pfn);
   5.334 +	return NULL;
   5.335 +    }
   5.336 +
   5.337 +    /* not found, no overlap => allocate */
   5.338 +    phys = xc_dom_malloc(dom, sizeof(*phys));
   5.339 +    if (NULL == phys)
   5.340 +	return NULL;
   5.341 +    memset(phys, 0, sizeof(*phys));
   5.342 +    phys->first = pfn;
   5.343 +    phys->count = count;
   5.344 +
   5.345 +    if (dom->guest_domid)
   5.346 +    {
   5.347 +	mode = "domU mapping";
   5.348 +	phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count);
   5.349 +	if (NULL == phys->ptr)
   5.350 +	    return NULL;
   5.351 +	dom->alloc_domU_map += phys->count << page_shift;
   5.352 +    }
   5.353 +    else
   5.354 +    {
   5.355 +	mode = "anonymous memory";
   5.356 +	phys->ptr = mmap(NULL, phys->count << page_shift,
   5.357 +			 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
   5.358 +			 -1, 0);
   5.359 +	if (MAP_FAILED == phys->ptr)
   5.360 +	{
   5.361 +	    xc_dom_panic(XC_OUT_OF_MEMORY,
   5.362 +			 "%s: oom: can't allocate 0x%" PRIpfn " pages\n",
   5.363 +			 __FUNCTION__, count);
   5.364 +	    return NULL;
   5.365 +	}
   5.366 +	dom->alloc_mem_map += phys->count << page_shift;
   5.367 +    }
   5.368 +
   5.369 +#if 1
   5.370 +    xc_dom_printf("%s: %s: pfn 0x%" PRIpfn "+0x%" PRIpfn " at %p\n",
   5.371 +		  __FUNCTION__, mode, phys->first, phys->count, phys->ptr);
   5.372 +#endif
   5.373 +    phys->next = dom->phys_pages;
   5.374 +    dom->phys_pages = phys;
   5.375 +    return phys->ptr;
   5.376 +}
   5.377 +
   5.378 +int xc_dom_alloc_segment(struct xc_dom_image *dom,
   5.379 +			 struct xc_dom_seg *seg, char *name,
   5.380 +			 xen_vaddr_t start, xen_vaddr_t size)
   5.381 +{
   5.382 +    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
   5.383 +    xen_pfn_t pages = (size + page_size - 1) / page_size;
   5.384 +    void *ptr;
   5.385 +
   5.386 +    if (0 == start)
   5.387 +	start = dom->virt_alloc_end;
   5.388 +
   5.389 +    if (start & (page_size - 1))
   5.390 +    {
   5.391 +	xc_dom_panic(XC_INTERNAL_ERROR,
   5.392 +		     "%s: segment start isn't page aligned (0x%" PRIx64 ")\n",
   5.393 +		     __FUNCTION__, start);
   5.394 +	return -1;
   5.395 +    }
   5.396 +    if (start < dom->virt_alloc_end)
   5.397 +    {
   5.398 +	xc_dom_panic(XC_INTERNAL_ERROR,
   5.399 +		     "%s: segment start too low (0x%" PRIx64 " < 0x%" PRIx64
   5.400 +		     ")\n", __FUNCTION__, start, dom->virt_alloc_end);
   5.401 +	return -1;
   5.402 +    }
   5.403 +
   5.404 +    seg->vstart = start;
   5.405 +    seg->vend = start + pages * page_size;
   5.406 +    seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
   5.407 +    dom->virt_alloc_end = seg->vend;
   5.408 +
   5.409 +    xc_dom_printf("%-20s:   %-12s : 0x%" PRIx64 " -> 0x%" PRIx64
   5.410 +		  "  (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n",
   5.411 +		  __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages);
   5.412 +
   5.413 +    /* map and clear pages */
   5.414 +    ptr = xc_dom_seg_to_ptr(dom, seg);
   5.415 +    if (NULL == ptr)
   5.416 +	return -1;
   5.417 +    memset(ptr, 0, pages * page_size);
   5.418 +
   5.419 +    return 0;
   5.420 +}
   5.421 +
   5.422 +int xc_dom_alloc_page(struct xc_dom_image *dom, char *name)
   5.423 +{
   5.424 +    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
   5.425 +    xen_vaddr_t start;
   5.426 +    xen_pfn_t pfn;
   5.427 +
   5.428 +    start = dom->virt_alloc_end;
   5.429 +    dom->virt_alloc_end += page_size;
   5.430 +    pfn = (start - dom->parms.virt_base) / page_size;
   5.431 +
   5.432 +    xc_dom_printf("%-20s:   %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n",
   5.433 +		  __FUNCTION__, name, start, pfn);
   5.434 +    return pfn;
   5.435 +}
   5.436 +
   5.437 +void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn)
   5.438 +{
   5.439 +    unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
   5.440 +    struct xc_dom_phys *phys, *prev = NULL;
   5.441 +
   5.442 +    for (phys = dom->phys_pages; NULL != phys; phys = phys->next)
   5.443 +    {
   5.444 +	if (pfn >= phys->first && pfn < phys->first + phys->count)
   5.445 +	    break;
   5.446 +	prev = phys;
   5.447 +    }
   5.448 +    if (!phys)
   5.449 +    {
   5.450 +	xc_dom_printf("%s: Huh? no mapping with pfn 0x%" PRIpfn "\n",
   5.451 +		      __FUNCTION__, pfn);
   5.452 +	return;
   5.453 +    }
   5.454 +
   5.455 +    munmap(phys->ptr, phys->count << page_shift);
   5.456 +    if (prev)
   5.457 +	prev->next = phys->next;
   5.458 +    else
   5.459 +	dom->phys_pages = phys->next;
   5.460 +}
   5.461 +
   5.462 +void xc_dom_unmap_all(struct xc_dom_image *dom)
   5.463 +{
   5.464 +    while (dom->phys_pages)
   5.465 +	xc_dom_unmap_one(dom, dom->phys_pages->first);
   5.466 +}
   5.467 +
   5.468 +/* ------------------------------------------------------------------------ */
   5.469 +/* pluggable kernel loaders                                                 */
   5.470 +
   5.471 +static struct xc_dom_loader *first_loader = NULL;
   5.472 +static struct xc_dom_arch *first_hook = NULL;
   5.473 +
   5.474 +void xc_dom_register_loader(struct xc_dom_loader *loader)
   5.475 +{
   5.476 +    loader->next = first_loader;
   5.477 +    first_loader = loader;
   5.478 +}
   5.479 +
   5.480 +static struct xc_dom_loader *xc_dom_find_loader(struct xc_dom_image *dom)
   5.481 +{
   5.482 +    struct xc_dom_loader *loader = first_loader;
   5.483 +
   5.484 +    while (NULL != loader)
   5.485 +    {
   5.486 +	xc_dom_printf("%s: trying %s loader ... ", __FUNCTION__, loader->name);
   5.487 +	if (0 == loader->probe(dom))
   5.488 +	{
   5.489 +	    xc_dom_printf("OK\n");
   5.490 +	    return loader;
   5.491 +	}
   5.492 +	xc_dom_printf("failed\n");
   5.493 +	loader = loader->next;
   5.494 +    }
   5.495 +    xc_dom_panic(XC_INVALID_KERNEL, "%s: no loader found\n", __FUNCTION__);
   5.496 +    return NULL;
   5.497 +}
   5.498 +
   5.499 +void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks)
   5.500 +{
   5.501 +    hooks->next = first_hook;
   5.502 +    first_hook = hooks;
   5.503 +}
   5.504 +
   5.505 +static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
   5.506 +{
   5.507 +    struct xc_dom_arch *hooks = first_hook;
   5.508 +
   5.509 +    while (NULL != hooks)
   5.510 +    {
   5.511 +	if (0 == strcmp(hooks->guest_type, guest_type))
   5.512 +	    return hooks;
   5.513 +	hooks = hooks->next;
   5.514 +    }
   5.515 +    xc_dom_panic(XC_INVALID_KERNEL,
   5.516 +		 "%s: not found (type %s)\n", __FUNCTION__, guest_type);
   5.517 +    return NULL;
   5.518 +}
   5.519 +
   5.520 +/* ------------------------------------------------------------------------ */
   5.521 +/* public interface                                                         */
   5.522 +
   5.523 +void xc_dom_release(struct xc_dom_image *dom)
   5.524 +{
   5.525 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   5.526 +    if (dom->phys_pages)
   5.527 +	xc_dom_unmap_all(dom);
   5.528 +    xc_dom_free_all(dom);
   5.529 +    free(dom);
   5.530 +}
   5.531 +
   5.532 +struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features)
   5.533 +{
   5.534 +    struct xc_dom_image *dom;
   5.535 +
   5.536 +    xc_dom_printf("%s: cmdline=\"%s\", features=\"%s\"\n",
   5.537 +		  __FUNCTION__, cmdline, features);
   5.538 +    dom = malloc(sizeof(*dom));
   5.539 +    if (!dom)
   5.540 +	goto err;
   5.541 +
   5.542 +    memset(dom, 0, sizeof(*dom));
   5.543 +    if (cmdline)
   5.544 +	dom->cmdline = xc_dom_strdup(dom, cmdline);
   5.545 +    if (features)
   5.546 +	elf_xen_parse_features(features, dom->f_requested, NULL);
   5.547 +
   5.548 +    dom->parms.virt_base = UNSET_ADDR;
   5.549 +    dom->parms.virt_entry = UNSET_ADDR;
   5.550 +    dom->parms.virt_hypercall = UNSET_ADDR;
   5.551 +    dom->parms.virt_hv_start_low = UNSET_ADDR;
   5.552 +    dom->parms.elf_paddr_offset = UNSET_ADDR;
   5.553 +
   5.554 +    dom->alloc_malloc += sizeof(*dom);
   5.555 +    return dom;
   5.556 +
   5.557 +  err:
   5.558 +    if (dom)
   5.559 +	xc_dom_release(dom);
   5.560 +    return NULL;
   5.561 +}
   5.562 +
   5.563 +int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
   5.564 +{
   5.565 +    xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename);
   5.566 +    dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size);
   5.567 +    if (NULL == dom->kernel_blob)
   5.568 +	return -1;
   5.569 +    return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
   5.570 +}
   5.571 +
   5.572 +int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename)
   5.573 +{
   5.574 +    xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename);
   5.575 +    dom->ramdisk_blob =
   5.576 +	xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size);
   5.577 +    if (NULL == dom->ramdisk_blob)
   5.578 +	return -1;
   5.579 +//    return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
   5.580 +    return 0;
   5.581 +}
   5.582 +
   5.583 +int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize)
   5.584 +{
   5.585 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   5.586 +    dom->kernel_blob = (void *)mem;
   5.587 +    dom->kernel_size = memsize;
   5.588 +    return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
   5.589 +}
   5.590 +
   5.591 +int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
   5.592 +		       size_t memsize)
   5.593 +{
   5.594 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   5.595 +    dom->ramdisk_blob = (void *)mem;
   5.596 +    dom->ramdisk_size = memsize;
   5.597 +//    return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
   5.598 +    return 0;
   5.599 +}
   5.600 +
   5.601 +int xc_dom_parse_image(struct xc_dom_image *dom)
   5.602 +{
   5.603 +    int i;
   5.604 +
   5.605 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   5.606 +
   5.607 +    /* parse kernel image */
   5.608 +    dom->kernel_loader = xc_dom_find_loader(dom);
   5.609 +    if (NULL == dom->kernel_loader)
   5.610 +	goto err;
   5.611 +    if (0 != dom->kernel_loader->parser(dom))
   5.612 +	goto err;
   5.613 +    if (NULL == dom->guest_type)
   5.614 +    {
   5.615 +	xc_dom_panic(XC_INTERNAL_ERROR,
   5.616 +		     "%s: guest_type not set\n", __FUNCTION__);
   5.617 +	goto err;
   5.618 +    }
   5.619 +
   5.620 +    /* check features */
   5.621 +    for (i = 0; i < XENFEAT_NR_SUBMAPS; i++)
   5.622 +    {
   5.623 +	dom->f_active[i] |= dom->f_requested[i];	/* cmd line */
   5.624 +	dom->f_active[i] |= dom->parms.f_required[i];	/* kernel   */
   5.625 +	if ((dom->f_active[i] & dom->parms.f_supported[i]) != dom->f_active[i])
   5.626 +	{
   5.627 +	    xc_dom_panic(XC_INVALID_PARAM,
   5.628 +			 "%s: unsupported feature requested\n", __FUNCTION__);
   5.629 +	    goto err;
   5.630 +	}
   5.631 +    }
   5.632 +    return 0;
   5.633 +
   5.634 +  err:
   5.635 +    return -1;
   5.636 +}
   5.637 +
   5.638 +int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb)
   5.639 +{
   5.640 +    unsigned int page_shift;
   5.641 +    xen_pfn_t nr_pages, pfn;
   5.642 +
   5.643 +    dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type);
   5.644 +    if (NULL == dom->arch_hooks)
   5.645 +    {
   5.646 +	xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n",
   5.647 +		     __FUNCTION__);
   5.648 +	return -1;
   5.649 +    }
   5.650 +
   5.651 +    page_shift = XC_DOM_PAGE_SHIFT(dom);
   5.652 +    nr_pages = mem_mb << (20 - page_shift);
   5.653 +
   5.654 +    xc_dom_printf("%s: mem %d MB, pages 0x%" PRIpfn " pages, %dk each\n",
   5.655 +		  __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10));
   5.656 +    dom->total_pages = nr_pages;
   5.657 +
   5.658 +    xc_dom_printf("%s: 0x%" PRIpfn " pages\n",
   5.659 +		  __FUNCTION__, dom->total_pages);
   5.660 +
   5.661 +    /* setup initial p2m */
   5.662 +    dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
   5.663 +    for (pfn = 0; pfn < dom->total_pages; pfn++)
   5.664 +	dom->p2m_host[pfn] = pfn;
   5.665 +    return 0;
   5.666 +}
   5.667 +
   5.668 +int xc_dom_update_guest_p2m(struct xc_dom_image *dom)
   5.669 +{
   5.670 +    uint32_t *p2m_32;
   5.671 +    uint64_t *p2m_64;
   5.672 +    xen_pfn_t i;
   5.673 +
   5.674 +    if (!dom->p2m_guest)
   5.675 +	return 0;
   5.676 +
   5.677 +    switch (dom->arch_hooks->sizeof_pfn)
   5.678 +    {
   5.679 +    case 4:
   5.680 +	xc_dom_printf("%s: dst 32bit, pages 0x%" PRIpfn " \n",
   5.681 +		      __FUNCTION__, dom->total_pages);
   5.682 +	p2m_32 = dom->p2m_guest;
   5.683 +	for (i = 0; i < dom->total_pages; i++)
   5.684 +	    if (INVALID_P2M_ENTRY != dom->p2m_host[i])
   5.685 +		p2m_32[i] = dom->p2m_host[i];
   5.686 +	    else
   5.687 +		p2m_32[i] = (uint32_t) - 1;
   5.688 +	break;
   5.689 +    case 8:
   5.690 +	xc_dom_printf("%s: dst 64bit, pages 0x%" PRIpfn " \n",
   5.691 +		      __FUNCTION__, dom->total_pages);
   5.692 +	p2m_64 = dom->p2m_guest;
   5.693 +	for (i = 0; i < dom->total_pages; i++)
   5.694 +	    if (INVALID_P2M_ENTRY != dom->p2m_host[i])
   5.695 +		p2m_64[i] = dom->p2m_host[i];
   5.696 +	    else
   5.697 +		p2m_64[i] = (uint64_t) - 1;
   5.698 +	break;
   5.699 +    default:
   5.700 +	xc_dom_panic(XC_INTERNAL_ERROR,
   5.701 +		     "sizeof_pfn is invalid (is %d, can be 4 or 8)",
   5.702 +		     dom->arch_hooks->sizeof_pfn);
   5.703 +	return -1;
   5.704 +    }
   5.705 +    return 0;
   5.706 +}
   5.707 +
   5.708 +int xc_dom_build_image(struct xc_dom_image *dom)
   5.709 +{
   5.710 +    unsigned int page_size;
   5.711 +
   5.712 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   5.713 +
   5.714 +    /* check for arch hooks */
   5.715 +    if (NULL == dom->arch_hooks)
   5.716 +    {
   5.717 +	xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n",
   5.718 +		     __FUNCTION__);
   5.719 +	goto err;
   5.720 +    }
   5.721 +    page_size = XC_DOM_PAGE_SIZE(dom);
   5.722 +
   5.723 +    /* load kernel */
   5.724 +    if (0 != xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel",
   5.725 +				  dom->kernel_seg.vstart,
   5.726 +				  dom->kernel_seg.vend -
   5.727 +				  dom->kernel_seg.vstart))
   5.728 +	goto err;
   5.729 +    if (0 != dom->kernel_loader->loader(dom))
   5.730 +	goto err;
   5.731 +
   5.732 +    /* load ramdisk */
   5.733 +    if (dom->ramdisk_blob)
   5.734 +    {
   5.735 +	size_t unziplen, ramdisklen;
   5.736 +	void *ramdiskmap;
   5.737 +
   5.738 +	unziplen = xc_dom_check_gzip(dom->ramdisk_blob, dom->ramdisk_size);
   5.739 +	ramdisklen = unziplen ? unziplen : dom->ramdisk_size;
   5.740 +	if (0 != xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0,
   5.741 +				      ramdisklen))
   5.742 +	    goto err;
   5.743 +	ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
   5.744 +	if (unziplen)
   5.745 +	{
   5.746 +	    if (-1 == xc_dom_do_gunzip(dom->ramdisk_blob, dom->ramdisk_size,
   5.747 +				       ramdiskmap, ramdisklen))
   5.748 +		goto err;
   5.749 +	}
   5.750 +	else
   5.751 +	    memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size);
   5.752 +    }
   5.753 +
   5.754 +    /* allocate other pages */
   5.755 +    if (0 != dom->arch_hooks->alloc_magic_pages(dom))
   5.756 +	goto err;
   5.757 +    if (dom->arch_hooks->count_pgtables)
   5.758 +    {
   5.759 +	dom->arch_hooks->count_pgtables(dom);
   5.760 +	if (dom->pgtables > 0)
   5.761 +	    if (0 !=
   5.762 +		xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0,
   5.763 +				     dom->pgtables * page_size))
   5.764 +		goto err;
   5.765 +    }
   5.766 +    if (dom->alloc_bootstack)
   5.767 +	dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack");
   5.768 +    xc_dom_printf("%-20s: virt_alloc_end : 0x%" PRIx64 "\n",
   5.769 +		  __FUNCTION__, dom->virt_alloc_end);
   5.770 +    xc_dom_printf("%-20s: virt_pgtab_end : 0x%" PRIx64 "\n",
   5.771 +		  __FUNCTION__, dom->virt_pgtab_end);
   5.772 +    return 0;
   5.773 +
   5.774 +  err:
   5.775 +    return -1;
   5.776 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libxc/xc_dom_elfloader.c	Thu Jan 25 22:16:52 2007 +0000
     6.3 @@ -0,0 +1,283 @@
     6.4 +/*
     6.5 + * Xen domain builder -- ELF bits.
     6.6 + *
     6.7 + * Parse and load ELF kernel images.
     6.8 + *
     6.9 + * This code is licenced under the GPL.
    6.10 + * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
    6.11 + *
    6.12 + */
    6.13 +#include <stdio.h>
    6.14 +#include <stdlib.h>
    6.15 +#include <inttypes.h>
    6.16 +
    6.17 +#include "xg_private.h"
    6.18 +#include "xc_dom.h"
    6.19 +
    6.20 +#define XEN_VER "xen-3.0"
    6.21 +
    6.22 +/* ------------------------------------------------------------------------ */
    6.23 +
    6.24 +static char *xc_dom_guest_type(struct xc_dom_image *dom,
    6.25 +			       struct elf_binary *elf)
    6.26 +{
    6.27 +    uint64_t machine = elf_uval(elf, elf->ehdr, e_machine);
    6.28 +
    6.29 +    switch (machine) {
    6.30 +    case EM_386:
    6.31 +	switch (dom->parms.pae) {
    6.32 +	case 3 /* PAEKERN_bimodal */:
    6.33 +	    if (strstr(dom->xen_caps, "xen-3.0-x86_32p"))
    6.34 +		return "xen-3.0-x86_32p";
    6.35 +	    return "xen-3.0-x86_32";
    6.36 +	case PAEKERN_extended_cr3:
    6.37 +	case PAEKERN_yes:
    6.38 +	    return "xen-3.0-x86_32p";
    6.39 +	    break;
    6.40 +	case PAEKERN_no:
    6.41 +	default:
    6.42 +	    return "xen-3.0-x86_32";
    6.43 +	}
    6.44 +    case EM_X86_64:
    6.45 +	return "xen-3.0-x86_64";
    6.46 +    case EM_IA_64:
    6.47 +	return elf_msb(elf) ? "xen-3.0-ia64be" : "xen-3.0-ia64";
    6.48 +    case EM_PPC64:
    6.49 +	return "xen-3.0-powerpc64";
    6.50 +    default:
    6.51 +	return "xen-3.0-unknown";
    6.52 +    }
    6.53 +}
    6.54 +
    6.55 +/* ------------------------------------------------------------------------ */
    6.56 +/* parse elf binary                                                         */
    6.57 +
    6.58 +static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
    6.59 +{
    6.60 +    if (NULL == dom->kernel_blob)
    6.61 +    {
    6.62 +	if (verbose)
    6.63 +	    xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n",
    6.64 +			 __FUNCTION__);
    6.65 +	return -EINVAL;
    6.66 +    }
    6.67 +
    6.68 +    if (!elf_is_elfbinary(dom->kernel_blob))
    6.69 +    {
    6.70 +	if (verbose)
    6.71 +	    xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not an ELF image\n",
    6.72 +			 __FUNCTION__);
    6.73 +	return -EINVAL;
    6.74 +    }
    6.75 +    return 0;
    6.76 +}
    6.77 +
    6.78 +static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
    6.79 +{
    6.80 +    return check_elf_kernel(dom, 0);
    6.81 +}
    6.82 +
    6.83 +static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
    6.84 +				  struct elf_binary *elf, int load)
    6.85 +{
    6.86 +    struct elf_binary syms;
    6.87 +    const elf_shdr *shdr, *shdr2;
    6.88 +    xen_vaddr_t symtab, maxaddr;
    6.89 +    char *hdr;
    6.90 +    size_t size;
    6.91 +    int h, count, type, i, tables = 0;
    6.92 +
    6.93 +    if (elf_swap(elf)) {
    6.94 +	xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n",
    6.95 +		      __FUNCTION__);
    6.96 +	return 0;
    6.97 +    }
    6.98 +
    6.99 +    if (load) {
   6.100 +	if (!dom->bsd_symtab_start)
   6.101 +	    return 0;
   6.102 +	size = dom->kernel_seg.vend - dom->bsd_symtab_start;
   6.103 +	hdr  = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
   6.104 +	*(int *)hdr = size - sizeof(int);
   6.105 +    } else {
   6.106 +	size = sizeof(int) + elf_size(elf, elf->ehdr) +
   6.107 +	    elf_shdr_count(elf) * elf_size(elf, shdr);
   6.108 +	hdr = xc_dom_malloc(dom, size);
   6.109 +	if (hdr == NULL)
   6.110 +	    return 0;
   6.111 +	dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
   6.112 +    }
   6.113 +
   6.114 +    memcpy(hdr + sizeof(int),
   6.115 +	   elf->image,
   6.116 +	   elf_size(elf, elf->ehdr));
   6.117 +    memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
   6.118 +	   elf->image + elf_uval(elf, elf->ehdr, e_shoff),
   6.119 +	   elf_shdr_count(elf) * elf_size(elf, shdr));
   6.120 +    if (elf_64bit(elf)) {
   6.121 +	Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
   6.122 +	ehdr->e_phoff = 0;
   6.123 +	ehdr->e_phentsize = 0;
   6.124 +	ehdr->e_phnum = 0;
   6.125 +	ehdr->e_shoff = elf_size(elf, elf->ehdr);
   6.126 +	ehdr->e_shstrndx = SHN_UNDEF;
   6.127 +    } else {
   6.128 +	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
   6.129 +	ehdr->e_phoff = 0;
   6.130 +	ehdr->e_phentsize = 0;
   6.131 +	ehdr->e_phnum = 0;
   6.132 +	ehdr->e_shoff = elf_size(elf, elf->ehdr);
   6.133 +	ehdr->e_shstrndx = SHN_UNDEF;
   6.134 +    }
   6.135 +    if (0 != elf_init(&syms, hdr + sizeof(int), size - sizeof(int)))
   6.136 +	return -1;
   6.137 +    if (xc_dom_logfile)
   6.138 +	elf_set_logfile(&syms, xc_dom_logfile, 1);
   6.139 +
   6.140 +    symtab = dom->bsd_symtab_start + sizeof(int);
   6.141 +    maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
   6.142 +			   elf_shdr_count(&syms) * elf_size(&syms, shdr));
   6.143 +
   6.144 +    xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64
   6.145 +		  " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n",
   6.146 +		  __FUNCTION__, load ? "load" : "parse",
   6.147 +		  dom->bsd_symtab_start, dom->kernel_seg.vend, symtab, maxaddr);
   6.148 +
   6.149 +    count = elf_shdr_count(&syms);
   6.150 +    for (h = 0; h < count; h++)
   6.151 +    {
   6.152 +	shdr = elf_shdr_by_index(&syms, h);
   6.153 +	type = elf_uval(&syms, shdr, sh_type);
   6.154 +	if (type == SHT_STRTAB)
   6.155 +	{
   6.156 +	    /* Look for a strtab @i linked to symtab @h. */
   6.157 +	    for (i = 0; i < count; i++) {
   6.158 +		shdr2 = elf_shdr_by_index(&syms, i);
   6.159 +		if ((elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
   6.160 +		    (elf_uval(&syms, shdr2, sh_link) == h))
   6.161 +		    break;
   6.162 +	    }
   6.163 +	    /* Skip symtab @h if we found no corresponding strtab @i. */
   6.164 +	    if (i == count)
   6.165 +	    {
   6.166 +		if (elf_64bit(&syms))
   6.167 +		    *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
   6.168 +		else
   6.169 +		    *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
   6.170 +		continue;
   6.171 +	    }
   6.172 +	}
   6.173 +
   6.174 +	if ((type == SHT_STRTAB) || (type == SHT_SYMTAB))
   6.175 +	{
   6.176 +	    /* Mangled to be based on ELF header location. */
   6.177 +	    if (elf_64bit(&syms))
   6.178 +		*(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
   6.179 +	    else
   6.180 +		*(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
   6.181 +	    size = elf_uval(&syms, shdr, sh_size);
   6.182 +	    maxaddr = elf_round_up(&syms, maxaddr + size);
   6.183 +	    tables++;
   6.184 +	    xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n",
   6.185 +			  __FUNCTION__, h,
   6.186 +			  type == SHT_SYMTAB ? "symtab" : "strtab",
   6.187 +			  size, maxaddr);
   6.188 +
   6.189 +	    if (load) {
   6.190 +		shdr2 = elf_shdr_by_index(elf, h);
   6.191 +		memcpy((void*)elf_section_start(&syms, shdr),
   6.192 +		       elf_section_start(elf, shdr2),
   6.193 +		       size);
   6.194 +	    }
   6.195 +	}
   6.196 +
   6.197 +	/* Name is NULL. */
   6.198 +	if (elf_64bit(&syms))
   6.199 +	    *(Elf64_Half*)(&shdr->e64.sh_name) = 0;
   6.200 +	else
   6.201 +	    *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
   6.202 +    }
   6.203 +
   6.204 +    if (0 == tables)
   6.205 +    {
   6.206 +	xc_dom_printf("%s: no symbol table present\n", __FUNCTION__);
   6.207 +	dom->bsd_symtab_start = 0;
   6.208 +	return 0;
   6.209 +    }
   6.210 +    if (!load)
   6.211 +	dom->kernel_seg.vend = maxaddr;
   6.212 +    return 0;
   6.213 +}
   6.214 +
   6.215 +static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
   6.216 +{
   6.217 +    struct elf_binary *elf;
   6.218 +    int rc;
   6.219 +
   6.220 +    rc = check_elf_kernel(dom, 1);
   6.221 +    if (0 != rc)
   6.222 +	return rc;
   6.223 +
   6.224 +    elf = xc_dom_malloc(dom, sizeof(*elf));
   6.225 +    dom->private_loader = elf;
   6.226 +    rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
   6.227 +    if (xc_dom_logfile)
   6.228 +	elf_set_logfile(elf, xc_dom_logfile, 1);
   6.229 +    if (0 != rc)
   6.230 +    {
   6.231 +	xc_dom_panic(XC_INVALID_KERNEL, "%s: corrupted ELF image\n",
   6.232 +		     __FUNCTION__);
   6.233 +	return rc;
   6.234 +    }
   6.235 +
   6.236 +    /* Find the section-header strings table. */
   6.237 +    if (NULL == elf->sec_strtab)
   6.238 +    {
   6.239 +	xc_dom_panic(XC_INVALID_KERNEL, "%s: ELF image has no shstrtab\n",
   6.240 +		     __FUNCTION__);
   6.241 +	return -EINVAL;
   6.242 +    }
   6.243 +
   6.244 +    /* parse binary and get xen meta info */
   6.245 +    elf_parse_binary(elf);
   6.246 +    if (0 != (rc = elf_xen_parse(elf, &dom->parms)))
   6.247 +	return rc;
   6.248 +
   6.249 +    /* find kernel segment */
   6.250 +    dom->kernel_seg.vstart = dom->parms.virt_kstart;
   6.251 +    dom->kernel_seg.vend   = dom->parms.virt_kend;
   6.252 +
   6.253 +    if (dom->parms.bsd_symtab)
   6.254 +	xc_dom_load_elf_symtab(dom, elf, 0);
   6.255 +
   6.256 +    dom->guest_type = xc_dom_guest_type(dom, elf);
   6.257 +    xc_dom_printf("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
   6.258 +		  __FUNCTION__, dom->guest_type,
   6.259 +		  dom->kernel_seg.vstart, dom->kernel_seg.vend);
   6.260 +    return 0;
   6.261 +}
   6.262 +
   6.263 +static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
   6.264 +{
   6.265 +    struct elf_binary *elf = dom->private_loader;
   6.266 +
   6.267 +    elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
   6.268 +    elf_load_binary(elf);
   6.269 +    if (dom->parms.bsd_symtab)
   6.270 +	xc_dom_load_elf_symtab(dom, elf, 1);
   6.271 +    return 0;
   6.272 +}
   6.273 +
   6.274 +/* ------------------------------------------------------------------------ */
   6.275 +
   6.276 +static struct xc_dom_loader elf_loader = {
   6.277 +    .name = "ELF-generic",
   6.278 +    .probe = xc_dom_probe_elf_kernel,
   6.279 +    .parser = xc_dom_parse_elf_kernel,
   6.280 +    .loader = xc_dom_load_elf_kernel,
   6.281 +};
   6.282 +
   6.283 +static void __init register_loader(void)
   6.284 +{
   6.285 +    xc_dom_register_loader(&elf_loader);
   6.286 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxc/xc_dom_ia64.c	Thu Jan 25 22:16:52 2007 +0000
     7.3 @@ -0,0 +1,118 @@
     7.4 +/*
     7.5 + * Xen domain builder -- ia64 bits.
     7.6 + *
     7.7 + * Most architecture-specific code for ia64 goes here.
     7.8 + *   - fill architecture-specific structs.
     7.9 + *
    7.10 + * This code is licenced under the GPL.
    7.11 + * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
    7.12 + *
    7.13 + */
    7.14 +#include <stdio.h>
    7.15 +#include <stdlib.h>
    7.16 +#include <string.h>
    7.17 +#include <inttypes.h>
    7.18 +
    7.19 +#include <xen/xen.h>
    7.20 +#include <xen/foreign/ia64.h>
    7.21 +
    7.22 +#include "xg_private.h"
    7.23 +#include "xc_dom.h"
    7.24 +
    7.25 +/* ------------------------------------------------------------------------ */
    7.26 +
    7.27 +static int alloc_magic_pages(struct xc_dom_image *dom)
    7.28 +{
    7.29 +    /* allocate special pages */
    7.30 +    dom->console_pfn = dom->total_pages -1;
    7.31 +    dom->xenstore_pfn = dom->total_pages -2;
    7.32 +    dom->start_info_pfn = dom->total_pages -3;
    7.33 +    return 0;
    7.34 +}
    7.35 +
    7.36 +static int start_info_ia64(struct xc_dom_image *dom)
    7.37 +{
    7.38 +    start_info_ia64_t *start_info =
    7.39 +	xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
    7.40 +    struct xen_ia64_boot_param_ia64 *bp =
    7.41 +	(struct xen_ia64_boot_param_ia64 *)(start_info + 1);
    7.42 +
    7.43 +    xc_dom_printf("%s\n", __FUNCTION__);
    7.44 +
    7.45 +    sprintf(start_info->magic, dom->guest_type);
    7.46 +    start_info->flags = dom->flags;
    7.47 +    start_info->nr_pages = dom->total_pages;
    7.48 +    start_info->store_mfn = dom->xenstore_pfn;
    7.49 +    start_info->store_evtchn = dom->xenstore_evtchn;
    7.50 +    start_info->console.domU.mfn = dom->console_pfn;
    7.51 +    start_info->console.domU.evtchn = dom->console_evtchn;
    7.52 +
    7.53 +    if (dom->ramdisk_blob)
    7.54 +    {
    7.55 +	start_info->mod_start = dom->ramdisk_seg.vstart;
    7.56 +	start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart;
    7.57 +	bp->initrd_start = start_info->mod_start;
    7.58 +	bp->initrd_size = start_info->mod_len;
    7.59 +    }
    7.60 +    if (dom->cmdline)
    7.61 +    {
    7.62 +	strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE);
    7.63 +	start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0';
    7.64 +	bp->command_line = (dom->start_info_pfn << PAGE_SHIFT_IA64)
    7.65 +	    + offsetof(start_info_t, cmd_line);
    7.66 +    }
    7.67 +    return 0;
    7.68 +}
    7.69 +
    7.70 +static int shared_info_ia64(struct xc_dom_image *dom, void *ptr)
    7.71 +{
    7.72 +    shared_info_ia64_t *shared_info = ptr;
    7.73 +    int i;
    7.74 +
    7.75 +    xc_dom_printf("%s: called\n", __FUNCTION__);
    7.76 +
    7.77 +    memset(shared_info, 0, sizeof(*shared_info));
    7.78 +    for (i = 0; i < MAX_VIRT_CPUS; i++)
    7.79 +	shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
    7.80 +    shared_info->arch.start_info_pfn = dom->start_info_pfn;
    7.81 +    return 0;
    7.82 +}
    7.83 +
    7.84 +extern unsigned long xc_ia64_fpsr_default(void);
    7.85 +
    7.86 +static int vcpu_ia64(struct xc_dom_image *dom, void *ptr)
    7.87 +{
    7.88 +    vcpu_guest_context_ia64_t *ctxt = ptr;
    7.89 +
    7.90 +    xc_dom_printf("%s: called\n", __FUNCTION__);
    7.91 +
    7.92 +    /* clear everything */
    7.93 +    memset(ctxt, 0, sizeof(*ctxt));
    7.94 +
    7.95 +    ctxt->flags = 0;
    7.96 +    ctxt->user_regs.cr_ipsr = 0;	/* all necessary bits filled by hypervisor */
    7.97 +    ctxt->user_regs.cr_iip = dom->parms.virt_entry;
    7.98 +    ctxt->user_regs.cr_ifs = (uint64_t) 1 << 63;
    7.99 +#ifdef __ia64__			/* FIXME */
   7.100 +    ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default();
   7.101 +#endif
   7.102 +    ctxt->user_regs.r28 = (dom->start_info_pfn << PAGE_SHIFT_IA64)
   7.103 +	+ sizeof(start_info_ia64_t);
   7.104 +    return 0;
   7.105 +}
   7.106 +
   7.107 +/* ------------------------------------------------------------------------ */
   7.108 +
   7.109 +static struct xc_dom_arch xc_dom_arch = {
   7.110 +    .guest_type = "xen-3.0-ia64",
   7.111 +    .page_shift = PAGE_SHIFT_IA64,
   7.112 +    .alloc_magic_pages = alloc_magic_pages,
   7.113 +    .start_info = start_info_ia64,
   7.114 +    .shared_info = shared_info_ia64,
   7.115 +    .vcpu = vcpu_ia64,
   7.116 +};
   7.117 +
   7.118 +static void __init register_arch_hooks(void)
   7.119 +{
   7.120 +    xc_dom_register_arch_hooks(&xc_dom_arch);
   7.121 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/libxc/xc_dom_powerpc64.c	Thu Jan 25 22:16:52 2007 +0000
     8.3 @@ -0,0 +1,100 @@
     8.4 +/*
     8.5 + * Xen domain builder -- ia64 bits.
     8.6 + *
     8.7 + * Most architecture-specific code for ia64 goes here.
     8.8 + *   - fill architecture-specific structs.
     8.9 + *
    8.10 + * This code is licenced under the GPL.
    8.11 + * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
    8.12 + *
    8.13 + */
    8.14 +#include <stdio.h>
    8.15 +#include <stdlib.h>
    8.16 +#include <string.h>
    8.17 +#include <inttypes.h>
    8.18 +
    8.19 +#include <xen/xen.h>
    8.20 +
    8.21 +#include "xg_private.h"
    8.22 +#include "xc_dom.h"
    8.23 +
    8.24 +/* ------------------------------------------------------------------------ */
    8.25 +
    8.26 +static int alloc_magic_pages(struct xc_dom_image *dom)
    8.27 +{
    8.28 +    /* allocate special pages */
    8.29 +    dom->low_top--; /* shared_info */
    8.30 +    dom->xenstore_pfn = --dom->low_top;
    8.31 +    dom->console_pfn = --dom->low_top;
    8.32 +    dom->start_info_pfn = --dom->low_top;
    8.33 +    return 0;
    8.34 +}
    8.35 +
    8.36 +static int start_info(struct xc_dom_image *dom)
    8.37 +{
    8.38 +    start_info_t *si =
    8.39 +	xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
    8.40 +
    8.41 +    xc_dom_printf("%s\n", __FUNCTION__);
    8.42 +
    8.43 +    snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0);
    8.44 +
    8.45 +    si->nr_pages = dom->total_pages;
    8.46 +    si->shared_info = (dom->total_pages - 1) << PAGE_SHIFT;
    8.47 +    si->store_mfn = dom->xenstore_pfn;
    8.48 +    si->store_evtchn = dom->store_evtchn;
    8.49 +    si->console.domU.mfn = dom->console_pfn;
    8.50 +    si->console.domU.evtchn = dom->console_evtchn;
    8.51 +    return 0;
    8.52 +}
    8.53 +
    8.54 +static int shared_info(struct xc_dom_image *dom, void *ptr)
    8.55 +{
    8.56 +    shared_info_t *shared_info = ptr;
    8.57 +    int i;
    8.58 +
    8.59 +    xc_dom_printf("%s: called\n", __FUNCTION__);
    8.60 +
    8.61 +    memset(shared_info, 0, sizeof(*shared_info));
    8.62 +    return 0;
    8.63 +}
    8.64 +
    8.65 +static int vcpu(struct xc_dom_image *dom, void *ptr)
    8.66 +{
    8.67 +    vcpu_guest_context_t *ctxt = ptr;
    8.68 +
    8.69 +    xc_dom_printf("%s: called\n", __FUNCTION__);
    8.70 +
    8.71 +    /* clear everything */
    8.72 +    memset(ctxt, 0, sizeof(*ctxt));
    8.73 +
    8.74 +    memset(&ctxt->user_regs, 0x55, sizeof(ctxt.user_regs));
    8.75 +    ctxt->user_regs.pc = dsi->v_kernentry;
    8.76 +    ctxt->user_regs.msr = 0;
    8.77 +    ctxt->user_regs.gprs[1] = 0; /* Linux uses its own stack */
    8.78 +    ctxt->user_regs.gprs[3] = devtree_addr;
    8.79 +    ctxt->user_regs.gprs[4] = kern_addr;
    8.80 +    ctxt->user_regs.gprs[5] = 0;
    8.81 +
    8.82 +    /* There is a buggy kernel that does not zero the "local_paca", so
    8.83 +     * we must make sure this register is 0 */
    8.84 +    ctxt->user_regs.gprs[13] = 0;
    8.85 +
    8.86 +    return 0;
    8.87 +}
    8.88 +
    8.89 +/* ------------------------------------------------------------------------ */
    8.90 +
    8.91 +static struct xc_dom_arch xc_dom_arch = {
    8.92 +    .guest_type = "xen-3.0-powerpc64",
    8.93 +    .page_shift = FIXME,
    8.94 +    .alloc_magic_pages = alloc_magic_pages,
    8.95 +    .start_info = start_info,
    8.96 +    .shared_info = shared_info,
    8.97 +    .vcpu = vcpu,
    8.98 +};
    8.99 +
   8.100 +static void __init register_arch_hooks(void)
   8.101 +{
   8.102 +    xc_dom_register_arch_hooks(&xc_dom_arch);
   8.103 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/libxc/xc_dom_x86.c	Thu Jan 25 22:16:52 2007 +0000
     9.3 @@ -0,0 +1,559 @@
     9.4 +/*
     9.5 + * Xen domain builder -- i386 and x86_64 bits.
     9.6 + *
     9.7 + * Most architecture-specific code for x86 goes here.
     9.8 + *   - prepare page tables.
     9.9 + *   - fill architecture-specific structs.
    9.10 + *
    9.11 + * This code is licenced under the GPL.
    9.12 + * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
    9.13 + *
    9.14 + */
    9.15 +#include <stdio.h>
    9.16 +#include <stdlib.h>
    9.17 +#include <string.h>
    9.18 +#include <inttypes.h>
    9.19 +
    9.20 +#include <xen/xen.h>
    9.21 +#include <xen/foreign/x86_32.h>
    9.22 +#include <xen/foreign/x86_64.h>
    9.23 +#include <xen/hvm/hvm_info_table.h>
    9.24 +#include <xen/hvm/e820.h>
    9.25 +
    9.26 +#include "xg_private.h"
    9.27 +#include "xc_dom.h"
    9.28 +
    9.29 +/* ------------------------------------------------------------------------ */
    9.30 +
    9.31 +#define bits_to_mask(bits)       (((xen_vaddr_t)1 << (bits))-1)
    9.32 +#define round_down(addr, mask)   ((addr) & ~(mask))
    9.33 +#define round_up(addr, mask)     ((addr) | (mask))
    9.34 +
    9.35 +static inline unsigned long
    9.36 +nr_page_tables(xen_vaddr_t start, xen_vaddr_t end, unsigned long bits)
    9.37 +{
    9.38 +    xen_vaddr_t mask = bits_to_mask(bits);
    9.39 +    int tables;
    9.40 +
    9.41 +    if (0 == bits)
    9.42 +	return 0;		/* unused */
    9.43 +
    9.44 +    if (8 * sizeof(unsigned long) == bits)
    9.45 +    {
    9.46 +	/* must be pgd, need one */
    9.47 +	start = 0;
    9.48 +	end = -1;
    9.49 +	tables = 1;
    9.50 +    }
    9.51 +    else
    9.52 +    {
    9.53 +	start = round_down(start, mask);
    9.54 +	end = round_up(end, mask);
    9.55 +	tables = ((end - start) >> bits) + 1;
    9.56 +    }
    9.57 +
    9.58 +    xc_dom_printf("%s: 0x%016" PRIx64 "/%ld: 0x%016" PRIx64
    9.59 +		  " -> 0x%016" PRIx64 ", %d table(s)\n",
    9.60 +		  __FUNCTION__, mask, bits, start, end, tables);
    9.61 +    return tables;
    9.62 +}
    9.63 +
    9.64 +static int count_pgtables(struct xc_dom_image *dom, int pae,
    9.65 +			  int l4_bits, int l3_bits, int l2_bits, int l1_bits)
    9.66 +{
    9.67 +    int pages, extra_pages;
    9.68 +    xen_vaddr_t try_virt_end;
    9.69 +
    9.70 +    extra_pages = dom->alloc_bootstack ? 1 : 0;
    9.71 +    extra_pages += dom->extra_pages;
    9.72 +    pages = extra_pages;
    9.73 +    for (;;)
    9.74 +    {
    9.75 +	try_virt_end = round_up(dom->virt_alloc_end + pages * PAGE_SIZE_X86,
    9.76 +				bits_to_mask(l1_bits));
    9.77 +	dom->pg_l4 =
    9.78 +	    nr_page_tables(dom->parms.virt_base, try_virt_end, l4_bits);
    9.79 +	dom->pg_l3 =
    9.80 +	    nr_page_tables(dom->parms.virt_base, try_virt_end, l3_bits);
    9.81 +	dom->pg_l2 =
    9.82 +	    nr_page_tables(dom->parms.virt_base, try_virt_end, l2_bits);
    9.83 +	dom->pg_l1 =
    9.84 +	    nr_page_tables(dom->parms.virt_base, try_virt_end, l1_bits);
    9.85 +	if (pae && try_virt_end < 0xc0000000)
    9.86 +	{
    9.87 +	    xc_dom_printf("%s: PAE: extra l2 page table for l3#3\n", __FUNCTION__);
    9.88 +	    dom->pg_l2++;
    9.89 +	}
    9.90 +	dom->pgtables = dom->pg_l4 + dom->pg_l3 + dom->pg_l2 + dom->pg_l1;
    9.91 +	pages = dom->pgtables + extra_pages;
    9.92 +	if (dom->virt_alloc_end + pages * PAGE_SIZE_X86 <= try_virt_end + 1)
    9.93 +	    break;
    9.94 +    }
    9.95 +    dom->virt_pgtab_end = try_virt_end + 1;
    9.96 +    return 0;
    9.97 +}
    9.98 +
    9.99 +/* ------------------------------------------------------------------------ */
   9.100 +/* i386 pagetables                                                          */
   9.101 +
   9.102 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   9.103 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.104 +#define L3_PROT (_PAGE_PRESENT)
   9.105 +
   9.106 +static int count_pgtables_x86_32(struct xc_dom_image *dom)
   9.107 +{
   9.108 +    return count_pgtables(dom, 0, 0, 0, 32, L2_PAGETABLE_SHIFT_I386);
   9.109 +}
   9.110 +
   9.111 +static int count_pgtables_x86_32_pae(struct xc_dom_image *dom)
   9.112 +{
   9.113 +    return count_pgtables(dom, 1, 0, 32,
   9.114 +			  L3_PAGETABLE_SHIFT_PAE, L2_PAGETABLE_SHIFT_PAE);
   9.115 +}
   9.116 +
   9.117 +#define pfn_to_paddr(pfn) ((xen_paddr_t)(pfn) << PAGE_SHIFT_X86)
   9.118 +
   9.119 +static int setup_pgtables_x86_32(struct xc_dom_image *dom)
   9.120 +{
   9.121 +    xen_pfn_t l2pfn = dom->pgtables_seg.pfn;
   9.122 +    xen_pfn_t l1pfn = dom->pgtables_seg.pfn + dom->pg_l2;
   9.123 +    l2_pgentry_32_t *l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
   9.124 +    l1_pgentry_32_t *l1tab = NULL;
   9.125 +    unsigned long l2off, l1off;
   9.126 +    xen_vaddr_t addr;
   9.127 +    xen_pfn_t pgpfn;
   9.128 +
   9.129 +    for (addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
   9.130 +	 addr += PAGE_SIZE_X86)
   9.131 +    {
   9.132 +	if (NULL == l1tab)
   9.133 +	{
   9.134 +	    /* get L1 tab, make L2 entry */
   9.135 +	    l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
   9.136 +	    l2off = l2_table_offset_i386(addr);
   9.137 +	    l2tab[l2off] =
   9.138 +		pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
   9.139 +	    l1pfn++;
   9.140 +	}
   9.141 +
   9.142 +	/* make L1 entry */
   9.143 +	l1off = l1_table_offset_i386(addr);
   9.144 +	pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86;
   9.145 +	l1tab[l1off] =
   9.146 +	    pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT;
   9.147 +	if (addr >= dom->pgtables_seg.vstart && addr < dom->pgtables_seg.vend)
   9.148 +	    l1tab[l1off] &= ~_PAGE_RW;	/* page tables are r/o */
   9.149 +	if (L1_PAGETABLE_ENTRIES_I386 - 1 == l1off)
   9.150 +	    l1tab = NULL;
   9.151 +    }
   9.152 +    return 0;
   9.153 +}
   9.154 +
   9.155 +static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
   9.156 +{
   9.157 +    xen_pfn_t l3pfn = dom->pgtables_seg.pfn;
   9.158 +    xen_pfn_t l2pfn = dom->pgtables_seg.pfn + dom->pg_l3;
   9.159 +    xen_pfn_t l1pfn = dom->pgtables_seg.pfn + dom->pg_l3 + dom->pg_l2;
   9.160 +    l3_pgentry_64_t *l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
   9.161 +    l2_pgentry_64_t *l2tab = NULL;
   9.162 +    l1_pgentry_64_t *l1tab = NULL;
   9.163 +    unsigned long l3off, l2off, l1off;
   9.164 +    xen_vaddr_t addr;
   9.165 +    xen_pfn_t pgpfn;
   9.166 +
   9.167 +    for (addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
   9.168 +	 addr += PAGE_SIZE_X86)
   9.169 +    {
   9.170 +	if (NULL == l2tab)
   9.171 +	{
   9.172 +	    /* get L2 tab, make L3 entry */
   9.173 +	    l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
   9.174 +	    l3off = l3_table_offset_pae(addr);
   9.175 +	    l3tab[l3off] =
   9.176 +		pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
   9.177 +	    l2pfn++;
   9.178 +	}
   9.179 +
   9.180 +	if (NULL == l1tab)
   9.181 +	{
   9.182 +	    /* get L1 tab, make L2 entry */
   9.183 +	    l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
   9.184 +	    l2off = l2_table_offset_pae(addr);
   9.185 +	    l2tab[l2off] =
   9.186 +		pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
   9.187 +	    if (L2_PAGETABLE_ENTRIES_PAE - 1 == l2off)
   9.188 +		l2tab = NULL;
   9.189 +	    l1pfn++;
   9.190 +	}
   9.191 +
   9.192 +	/* make L1 entry */
   9.193 +	l1off = l1_table_offset_pae(addr);
   9.194 +	pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86;
   9.195 +	l1tab[l1off] =
   9.196 +	    pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT;
   9.197 +	if (addr >= dom->pgtables_seg.vstart && addr < dom->pgtables_seg.vend)
   9.198 +	    l1tab[l1off] &= ~_PAGE_RW;	/* page tables are r/o */
   9.199 +	if (L1_PAGETABLE_ENTRIES_PAE - 1 == l1off)
   9.200 +	    l1tab = NULL;
   9.201 +    }
   9.202 +
   9.203 +    if (dom->virt_pgtab_end <= 0xc0000000)
   9.204 +    {
   9.205 +	xc_dom_printf("%s: PAE: extra l2 page table for l3#3\n", __FUNCTION__);
   9.206 +	l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
   9.207 +    }
   9.208 +    return 0;
   9.209 +}
   9.210 +
   9.211 +#undef L1_PROT
   9.212 +#undef L2_PROT
   9.213 +#undef L3_PROT
   9.214 +
   9.215 +/* ------------------------------------------------------------------------ */
   9.216 +/* x86_64 pagetables                                                        */
   9.217 +
   9.218 +static int count_pgtables_x86_64(struct xc_dom_image *dom)
   9.219 +{
   9.220 +    return count_pgtables(dom, 0,
   9.221 +			  L4_PAGETABLE_SHIFT_X86_64 + 9,
   9.222 +			  L4_PAGETABLE_SHIFT_X86_64,
   9.223 +			  L3_PAGETABLE_SHIFT_X86_64, L2_PAGETABLE_SHIFT_X86_64);
   9.224 +}
   9.225 +
   9.226 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   9.227 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.228 +#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.229 +#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.230 +
   9.231 +static int setup_pgtables_x86_64(struct xc_dom_image *dom)
   9.232 +{
   9.233 +    xen_pfn_t l4pfn = dom->pgtables_seg.pfn;
   9.234 +    xen_pfn_t l3pfn = dom->pgtables_seg.pfn + dom->pg_l4;
   9.235 +    xen_pfn_t l2pfn = dom->pgtables_seg.pfn + dom->pg_l4 + dom->pg_l3;
   9.236 +    xen_pfn_t l1pfn =
   9.237 +	dom->pgtables_seg.pfn + dom->pg_l4 + dom->pg_l3 + dom->pg_l2;
   9.238 +    l4_pgentry_64_t *l4tab = xc_dom_pfn_to_ptr(dom, l4pfn, 1);
   9.239 +    l3_pgentry_64_t *l3tab = NULL;
   9.240 +    l2_pgentry_64_t *l2tab = NULL;
   9.241 +    l1_pgentry_64_t *l1tab = NULL;
   9.242 +    uint64_t l4off, l3off, l2off, l1off;
   9.243 +    uint64_t addr;
   9.244 +    xen_pfn_t pgpfn;
   9.245 +
   9.246 +    for (addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
   9.247 +	 addr += PAGE_SIZE_X86)
   9.248 +    {
   9.249 +	if (NULL == l3tab)
   9.250 +	{
   9.251 +	    /* get L3 tab, make L4 entry */
   9.252 +	    l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
   9.253 +	    l4off = l4_table_offset_x86_64(addr);
   9.254 +	    l4tab[l4off] =
   9.255 +		pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
   9.256 +	    l3pfn++;
   9.257 +	}
   9.258 +
   9.259 +	if (NULL == l2tab)
   9.260 +	{
   9.261 +	    /* get L2 tab, make L3 entry */
   9.262 +	    l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
   9.263 +	    l3off = l3_table_offset_x86_64(addr);
   9.264 +	    l3tab[l3off] =
   9.265 +		pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
   9.266 +	    if (L3_PAGETABLE_ENTRIES_X86_64 - 1 == l3off)
   9.267 +		l3tab = NULL;
   9.268 +	    l2pfn++;
   9.269 +	}
   9.270 +
   9.271 +	if (NULL == l1tab)
   9.272 +	{
   9.273 +	    /* get L1 tab, make L2 entry */
   9.274 +	    l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
   9.275 +	    l2off = l2_table_offset_x86_64(addr);
   9.276 +	    l2tab[l2off] =
   9.277 +		pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
   9.278 +	    if (L2_PAGETABLE_ENTRIES_X86_64 - 1 == l2off)
   9.279 +		l2tab = NULL;
   9.280 +	    l1pfn++;
   9.281 +	}
   9.282 +
   9.283 +	/* make L1 entry */
   9.284 +	l1off = l1_table_offset_x86_64(addr);
   9.285 +	pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86;
   9.286 +	l1tab[l1off] =
   9.287 +	    pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT;
   9.288 +	if (addr >= dom->pgtables_seg.vstart && addr < dom->pgtables_seg.vend)
   9.289 +	    l1tab[l1off] &= ~_PAGE_RW;	/* page tables are r/o */
   9.290 +	if (L1_PAGETABLE_ENTRIES_X86_64 - 1 == l1off)
   9.291 +	    l1tab = NULL;
   9.292 +    }
   9.293 +    return 0;
   9.294 +}
   9.295 +
   9.296 +#undef L1_PROT
   9.297 +#undef L2_PROT
   9.298 +#undef L3_PROT
   9.299 +#undef L4_PROT
   9.300 +
   9.301 +/* ------------------------------------------------------------------------ */
   9.302 +
   9.303 +static int alloc_magic_pages(struct xc_dom_image *dom)
   9.304 +{
   9.305 +    size_t p2m_size = dom->total_pages * dom->arch_hooks->sizeof_pfn;
   9.306 +
   9.307 +    /* allocate phys2mach table */
   9.308 +    if (0 != xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size))
   9.309 +	return -1;
   9.310 +    dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
   9.311 +
   9.312 +    /* allocate special pages */
   9.313 +    dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
   9.314 +    dom->xenstore_pfn = xc_dom_alloc_page(dom, "xenstore");
   9.315 +    dom->console_pfn = xc_dom_alloc_page(dom, "console");
   9.316 +    if (xc_dom_feature_translated(dom))
   9.317 +	dom->shared_info_pfn = xc_dom_alloc_page(dom, "shared info");
   9.318 +    dom->alloc_bootstack = 1;
   9.319 +    return 0;
   9.320 +}
   9.321 +
   9.322 +/* ------------------------------------------------------------------------ */
   9.323 +
   9.324 +static int start_info_x86_32(struct xc_dom_image *dom)
   9.325 +{
   9.326 +    start_info_x86_32_t *start_info =
   9.327 +	xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
   9.328 +    xen_pfn_t shinfo =
   9.329 +	xc_dom_feature_translated(dom) ? dom->shared_info_pfn : dom->
   9.330 +	shared_info_mfn;
   9.331 +
   9.332 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   9.333 +
   9.334 +    sprintf(start_info->magic, dom->guest_type);
   9.335 +    start_info->nr_pages = dom->total_pages;
   9.336 +    start_info->shared_info = shinfo << PAGE_SHIFT_X86;
   9.337 +    start_info->pt_base = dom->pgtables_seg.vstart;
   9.338 +    start_info->nr_pt_frames = dom->pgtables;
   9.339 +    start_info->mfn_list = dom->p2m_seg.vstart;
   9.340 +
   9.341 +    start_info->flags = dom->flags;
   9.342 +    start_info->store_mfn = xc_dom_p2m_guest(dom, dom->xenstore_pfn);
   9.343 +    start_info->store_evtchn = dom->xenstore_evtchn;
   9.344 +    start_info->console.domU.mfn = xc_dom_p2m_guest(dom, dom->console_pfn);
   9.345 +    start_info->console.domU.evtchn = dom->console_evtchn;
   9.346 +
   9.347 +    if (dom->ramdisk_blob)
   9.348 +    {
   9.349 +	start_info->mod_start = dom->ramdisk_seg.vstart;
   9.350 +	start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart;
   9.351 +    }
   9.352 +    if (dom->cmdline)
   9.353 +    {
   9.354 +	strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE);
   9.355 +	start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0';
   9.356 +    }
   9.357 +    return 0;
   9.358 +}
   9.359 +
   9.360 +static int start_info_x86_64(struct xc_dom_image *dom)
   9.361 +{
   9.362 +    start_info_x86_64_t *start_info =
   9.363 +	xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
   9.364 +    xen_pfn_t shinfo =
   9.365 +	xc_dom_feature_translated(dom) ? dom->shared_info_pfn : dom->
   9.366 +	shared_info_mfn;
   9.367 +
   9.368 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   9.369 +
   9.370 +    sprintf(start_info->magic, dom->guest_type);
   9.371 +    start_info->nr_pages = dom->total_pages;
   9.372 +    start_info->shared_info = shinfo << PAGE_SHIFT_X86;
   9.373 +    start_info->pt_base = dom->pgtables_seg.vstart;
   9.374 +    start_info->nr_pt_frames = dom->pgtables;
   9.375 +    start_info->mfn_list = dom->p2m_seg.vstart;
   9.376 +
   9.377 +    start_info->flags = dom->flags;
   9.378 +    start_info->store_mfn = xc_dom_p2m_guest(dom, dom->xenstore_pfn);
   9.379 +    start_info->store_evtchn = dom->xenstore_evtchn;
   9.380 +    start_info->console.domU.mfn = xc_dom_p2m_guest(dom, dom->console_pfn);
   9.381 +    start_info->console.domU.evtchn = dom->console_evtchn;
   9.382 +
   9.383 +    if (dom->ramdisk_blob)
   9.384 +    {
   9.385 +	start_info->mod_start = dom->ramdisk_seg.vstart;
   9.386 +	start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart;
   9.387 +    }
   9.388 +    if (dom->cmdline)
   9.389 +    {
   9.390 +	strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE);
   9.391 +	start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0';
   9.392 +    }
   9.393 +    return 0;
   9.394 +}
   9.395 +
   9.396 +static int shared_info_x86_32(struct xc_dom_image *dom, void *ptr)
   9.397 +{
   9.398 +    shared_info_x86_32_t *shared_info = ptr;
   9.399 +    int i;
   9.400 +
   9.401 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   9.402 +
   9.403 +    memset(shared_info, 0, sizeof(*shared_info));
   9.404 +    for (i = 0; i < MAX_VIRT_CPUS; i++)
   9.405 +	shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
   9.406 +    return 0;
   9.407 +}
   9.408 +
   9.409 +static int shared_info_x86_64(struct xc_dom_image *dom, void *ptr)
   9.410 +{
   9.411 +    shared_info_x86_64_t *shared_info = ptr;
   9.412 +    int i;
   9.413 +
   9.414 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   9.415 +
   9.416 +    memset(shared_info, 0, sizeof(*shared_info));
   9.417 +    for (i = 0; i < MAX_VIRT_CPUS; i++)
   9.418 +	shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
   9.419 +    return 0;
   9.420 +}
   9.421 +
   9.422 +/* ------------------------------------------------------------------------ */
   9.423 +
   9.424 +static int vcpu_x86_32(struct xc_dom_image *dom, void *ptr)
   9.425 +{
   9.426 +    vcpu_guest_context_x86_32_t *ctxt = ptr;
   9.427 +    xen_pfn_t cr3_pfn;
   9.428 +    int i;
   9.429 +
   9.430 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   9.431 +
   9.432 +    /* clear everything */
   9.433 +    memset(ctxt, 0, sizeof(*ctxt));
   9.434 +
   9.435 +    /* Virtual IDT is empty at start-of-day. */
   9.436 +    for (i = 0; i < 256; i++)
   9.437 +    {
   9.438 +	ctxt->trap_ctxt[i].vector = i;
   9.439 +	ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32;
   9.440 +    }
   9.441 +
   9.442 +    /* No callback handlers. */
   9.443 +    ctxt->event_callback_cs = FLAT_KERNEL_CS_X86_32;
   9.444 +    ctxt->failsafe_callback_cs = FLAT_KERNEL_CS_X86_32;
   9.445 +
   9.446 +    ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_32;
   9.447 +    ctxt->user_regs.es = FLAT_KERNEL_DS_X86_32;
   9.448 +    ctxt->user_regs.fs = FLAT_KERNEL_DS_X86_32;
   9.449 +    ctxt->user_regs.gs = FLAT_KERNEL_DS_X86_32;
   9.450 +    ctxt->user_regs.ss = FLAT_KERNEL_SS_X86_32;
   9.451 +    ctxt->user_regs.cs = FLAT_KERNEL_CS_X86_32;
   9.452 +    ctxt->user_regs.eip = dom->parms.virt_entry;
   9.453 +    ctxt->user_regs.esp =
   9.454 +	dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
   9.455 +    ctxt->user_regs.esi =
   9.456 +	dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
   9.457 +    ctxt->user_regs.eflags = 1 << 9;	/* Interrupt Enable */
   9.458 +
   9.459 +    ctxt->kernel_ss = FLAT_KERNEL_SS_X86_32;
   9.460 +    ctxt->kernel_sp =
   9.461 +	dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
   9.462 +
   9.463 +    ctxt->flags = VGCF_in_kernel_X86_32;
   9.464 +    if (dom->parms.pae == 2 /* extended_cr3 */ ||
   9.465 +	dom->parms.pae == 3 /* bimodal */)
   9.466 +	ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3);
   9.467 +
   9.468 +    cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn);
   9.469 +    ctxt->ctrlreg[3] = xen_pfn_to_cr3_x86_32(cr3_pfn);
   9.470 +    xc_dom_printf("%s: cr3: pfn 0x%" PRIpfn " mfn 0x%" PRIpfn "\n",
   9.471 +		  __FUNCTION__, dom->pgtables_seg.pfn, cr3_pfn);
   9.472 +
   9.473 +    return 0;
   9.474 +}
   9.475 +
   9.476 +static int vcpu_x86_64(struct xc_dom_image *dom, void *ptr)
   9.477 +{
   9.478 +    vcpu_guest_context_x86_64_t *ctxt = ptr;
   9.479 +    xen_pfn_t cr3_pfn;
   9.480 +    int i;
   9.481 +
   9.482 +    xc_dom_printf("%s: called\n", __FUNCTION__);
   9.483 +
   9.484 +    /* clear everything */
   9.485 +    memset(ctxt, 0, sizeof(*ctxt));
   9.486 +
   9.487 +    /* Virtual IDT is empty at start-of-day. */
   9.488 +    for (i = 0; i < 256; i++)
   9.489 +    {
   9.490 +	ctxt->trap_ctxt[i].vector = i;
   9.491 +	ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64;
   9.492 +    }
   9.493 +
   9.494 +    ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_64;
   9.495 +    ctxt->user_regs.es = FLAT_KERNEL_DS_X86_64;
   9.496 +    ctxt->user_regs.fs = FLAT_KERNEL_DS_X86_64;
   9.497 +    ctxt->user_regs.gs = FLAT_KERNEL_DS_X86_64;
   9.498 +    ctxt->user_regs.ss = FLAT_KERNEL_SS_X86_64;
   9.499 +    ctxt->user_regs.cs = FLAT_KERNEL_CS_X86_64;
   9.500 +    ctxt->user_regs.rip = dom->parms.virt_entry;
   9.501 +    ctxt->user_regs.rsp =
   9.502 +	dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
   9.503 +    ctxt->user_regs.rsi =
   9.504 +	dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
   9.505 +    ctxt->user_regs.rflags = 1 << 9;	/* Interrupt Enable */
   9.506 +
   9.507 +    ctxt->kernel_ss = FLAT_KERNEL_SS_X86_64;
   9.508 +    ctxt->kernel_sp =
   9.509 +	dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
   9.510 +
   9.511 +    ctxt->flags = VGCF_in_kernel_X86_64;
   9.512 +    cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn);
   9.513 +    ctxt->ctrlreg[3] = xen_pfn_to_cr3_x86_64(cr3_pfn);
   9.514 +    xc_dom_printf("%s: cr3: pfn 0x%" PRIpfn " mfn 0x%" PRIpfn "\n",
   9.515 +		  __FUNCTION__, dom->pgtables_seg.pfn, cr3_pfn);
   9.516 +
   9.517 +    return 0;
   9.518 +}
   9.519 +
   9.520 +/* ------------------------------------------------------------------------ */
   9.521 +
   9.522 +static struct xc_dom_arch xc_dom_32 = {
   9.523 +    .guest_type = "xen-3.0-x86_32",
   9.524 +    .page_shift = PAGE_SHIFT_X86,
   9.525 +    .sizeof_pfn = 4,
   9.526 +    .alloc_magic_pages = alloc_magic_pages,
   9.527 +    .count_pgtables = count_pgtables_x86_32,
   9.528 +    .setup_pgtables = setup_pgtables_x86_32,
   9.529 +    .start_info = start_info_x86_32,
   9.530 +    .shared_info = shared_info_x86_32,
   9.531 +    .vcpu = vcpu_x86_32,
   9.532 +};
   9.533 +static struct xc_dom_arch xc_dom_32_pae = {
   9.534 +    .guest_type = "xen-3.0-x86_32p",
   9.535 +    .page_shift = PAGE_SHIFT_X86,
   9.536 +    .sizeof_pfn = 4,
   9.537 +    .alloc_magic_pages = alloc_magic_pages,
   9.538 +    .count_pgtables = count_pgtables_x86_32_pae,
   9.539 +    .setup_pgtables = setup_pgtables_x86_32_pae,
   9.540 +    .start_info = start_info_x86_32,
   9.541 +    .shared_info = shared_info_x86_32,
   9.542 +    .vcpu = vcpu_x86_32,
   9.543 +};
   9.544 +
   9.545 +static struct xc_dom_arch xc_dom_64 = {
   9.546 +    .guest_type = "xen-3.0-x86_64",
   9.547 +    .page_shift = PAGE_SHIFT_X86,
   9.548 +    .sizeof_pfn = 8,
   9.549 +    .alloc_magic_pages = alloc_magic_pages,
   9.550 +    .count_pgtables = count_pgtables_x86_64,
   9.551 +    .setup_pgtables = setup_pgtables_x86_64,
   9.552 +    .start_info = start_info_x86_64,
   9.553 +    .shared_info = shared_info_x86_64,
   9.554 +    .vcpu = vcpu_x86_64,
   9.555 +};
   9.556 +
   9.557 +static void __init register_arch_hooks(void)
   9.558 +{
   9.559 +    xc_dom_register_arch_hooks(&xc_dom_32);
   9.560 +    xc_dom_register_arch_hooks(&xc_dom_32_pae);
   9.561 +    xc_dom_register_arch_hooks(&xc_dom_64);
   9.562 +}