# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1171535139 0
# Node ID 0d488e53446a1d0dd74481b52f49e704c362254c
# Parent 82f66bc01da2cb14062c0651a63dbf7286cfd1e7
Remove old elf-parsing code from tools and from Xen.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
tools/libxc/xc_linux_build.c | 1319 -------------------------------------------
tools/libxc/xc_load_bin.c | 306 ---------
tools/libxc/xc_load_elf.c | 684 ----------------------
xen/common/elf.c | 520 ----------------
tools/libxc/Makefile | 4
tools/libxc/xc_private.c | 20
tools/libxc/xg_private.h | 77 --
7 files changed, 2930 deletions(-)
diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/Makefile
--- a/tools/libxc/Makefile Wed Feb 14 12:18:32 2007 -0800
+++ b/tools/libxc/Makefile Thu Feb 15 10:25:39 2007 +0000
@@ -22,11 +22,7 @@ CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptra
CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c
GUEST_SRCS-y :=
-GUEST_SRCS-y += xc_load_bin.c
-GUEST_SRCS-y += xc_load_elf.c
GUEST_SRCS-y += xg_private.c
-#GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c
-#GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c
GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c Wed Feb 14 12:18:32 2007 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1319 +0,0 @@
-/******************************************************************************
- * xc_linux_build.c
- */
-
-#include <stddef.h>
-#include "xg_private.h"
-#include "xc_private.h"
-#include <xenctrl.h>
-
-#include "xc_elf.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <zlib.h>
-
-/* Handy for printing out '0' prepended values at native pointer size */
-#define _p(a) ((void *) ((ulong)a))
-
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#if defined(__i386__)
-#define L3_PROT (_PAGE_PRESENT)
-#elif defined(__x86_64__)
-#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#endif
-
-#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-#define round_pgdown(_p) ((_p)&PAGE_MASK)
-
-struct initrd_info {
- enum { INITRD_none, INITRD_file, INITRD_mem } type;
- /*
- * .len must be filled in by the user for type==INITRD_mem. It is
- * filled in by load_initrd() for INITRD_file and unused for
- * INITRD_none.
- */
- unsigned long len;
- union {
- gzFile file_handle;
- char *mem_addr;
- } u;
-};
-
-static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
- [XENFEAT_writable_page_tables] = "writable_page_tables",
- [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
- [XENFEAT_auto_translated_physmap] = "auto_translated_physmap",
- [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel",
- [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb"
-};
-
-static inline void set_feature_bit (int nr, uint32_t *addr)
-{
- addr[nr>>5] |= (1<<(nr&31));
-}
-
-static inline int test_feature_bit(int nr, uint32_t *addr)
-{
- return !!(addr[nr>>5] & (1<<(nr&31)));
-}
-
-static int parse_features(
- const char *feats,
- uint32_t supported[XENFEAT_NR_SUBMAPS],
- uint32_t required[XENFEAT_NR_SUBMAPS])
-{
- const char *end, *p;
- int i, req;
-
- if ( (end = strchr(feats, ',')) == NULL )
- end = feats + strlen(feats);
-
- while ( feats < end )
- {
- p = strchr(feats, '|');
- if ( (p == NULL) || (p > end) )
- p = end;
-
- req = (*feats == '!');
- if ( req )
- feats++;
-
- for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ )
- {
- if ( feature_names[i] == NULL )
- continue;
-
- if ( strncmp(feature_names[i], feats, p-feats) == 0 )
- {
- set_feature_bit(i, supported);
- if ( required && req )
- set_feature_bit(i, required);
- break;
- }
- }
-
- if ( i == XENFEAT_NR_SUBMAPS*32 )
- {
- ERROR("Unknown feature \"%.*s\".", (int)(p-feats), feats);
- if ( req )
- {
- ERROR("Kernel requires an unknown hypervisor feature.");
- return -EINVAL;
- }
- }
-
- feats = p;
- if ( *feats == '|' )
- feats++;
- }
-
- return -EINVAL;
-}
-
-static int probeimageformat(const char *image,
- unsigned long image_size,
- struct load_funcs *load_funcs)
-{
- if ( probe_elf(image, image_size, load_funcs) &&
- probe_bin(image, image_size, load_funcs) )
- {
- xc_set_error(XC_INVALID_KERNEL, "Not a valid ELF or raw kernel image");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int load_initrd(int xc_handle, domid_t dom,
- struct initrd_info *initrd,
- unsigned long physbase,
- xen_pfn_t *phys_to_mach)
-{
- char page[PAGE_SIZE];
- unsigned long pfn_start, pfn;
-
- if ( initrd->type == INITRD_none )
- return 0;
-
- pfn_start = physbase >> PAGE_SHIFT;
-
- if ( initrd->type == INITRD_mem )
- {
- unsigned long nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ )
- {
- xc_copy_to_domain_page(
- xc_handle, dom, phys_to_mach[pfn],
- &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]);
- }
- }
- else
- {
- int readlen;
-
- pfn = pfn_start;
- initrd->len = 0;
-
- /* gzread returns 0 on EOF */
- while ( (readlen = gzread(initrd->u.file_handle, page, PAGE_SIZE)) )
- {
- if ( readlen < 0 )
- {
- PERROR("Error reading initrd image, could not");
- return -EINVAL;
- }
-
- initrd->len += readlen;
- xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn++], page);
- }
- }
-
- return 0;
-}
-
-#define alloc_pt(ltab, vltab) \
-do { \
- ltab = ppt_alloc++; \
- ltab = (uint64_t)page_array[ltab] << PAGE_SHIFT; \
- if ( vltab != NULL ) \
- munmap(vltab, PAGE_SIZE); \
- if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
- PROT_READ|PROT_WRITE, \
- ltab >> PAGE_SHIFT)) == NULL ) \
- goto error_out; \
- memset(vltab, 0x0, PAGE_SIZE); \
-} while ( 0 )
-
-#if defined(__i386__)
-
-static int setup_pg_tables(int xc_handle, uint32_t dom,
- vcpu_guest_context_t *ctxt,
- unsigned long dsi_v_start,
- unsigned long v_end,
- xen_pfn_t *page_array,
- unsigned long vpt_start,
- unsigned long vpt_end,
- unsigned shadow_mode_enabled)
-{
- l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
- l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
- unsigned long l1tab = 0;
- unsigned long l2tab = 0;
- unsigned long ppt_alloc;
- unsigned long count;
-
- ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
- alloc_pt(l2tab, vl2tab);
- vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
- ctxt->ctrlreg[3] = xen_pfn_to_cr3(l2tab >> PAGE_SHIFT);
-
- for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ )
- {
- if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
- {
- alloc_pt(l1tab, vl1tab);
- vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
- *vl2e++ = l1tab | L2_PROT;
- }
-
- *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-
- if ( !shadow_mode_enabled )
- if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
- (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
- *vl1e &= ~_PAGE_RW;
-
- vl1e++;
- }
- munmap(vl1tab, PAGE_SIZE);
- munmap(vl2tab, PAGE_SIZE);
- return 0;
-
- error_out:
- if (vl1tab)
- munmap(vl1tab, PAGE_SIZE);
- if (vl2tab)
- munmap(vl2tab, PAGE_SIZE);
- return -1;
-}
-
-static int setup_pg_tables_pae(int xc_handle, uint32_t dom,
- vcpu_guest_context_t *ctxt,
- unsigned long dsi_v_start,
- unsigned long v_end,
- xen_pfn_t *page_array,
- unsigned long vpt_start,
- unsigned long vpt_end,
- unsigned shadow_mode_enabled,
- unsigned pae_mode)
-{
- l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL;
- l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL;
- l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL;
- uint64_t l1tab, l2tab, l3tab;
- unsigned long ppt_alloc, count, nmfn;
-
- /* First allocate page for page dir. */
- ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
-
- if ( pae_mode == PAEKERN_extended_cr3 )
- {
- ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3);
- }
- else if ( page_array[ppt_alloc] > 0xfffff )
- {
- nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]);
- if ( nmfn == 0 )
- {
- DPRINTF("Couldn't get a page below 4GB :-(\n");
- goto error_out;
- }
- page_array[ppt_alloc] = nmfn;
- }
-
- alloc_pt(l3tab, vl3tab);
- vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
- ctxt->ctrlreg[3] = xen_pfn_to_cr3(l3tab >> PAGE_SHIFT);
-
- for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++)
- {
- if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
- {
- if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
- {
- alloc_pt(l2tab, vl2tab);
- vl2e = &vl2tab[l2_table_offset_pae(
- dsi_v_start + (count << PAGE_SHIFT))];
- *vl3e++ = l2tab | L3_PROT;
- }
-
- alloc_pt(l1tab, vl1tab);
- vl1e = &vl1tab[l1_table_offset_pae(
- dsi_v_start + (count << PAGE_SHIFT))];
- *vl2e++ = l1tab | L2_PROT;
-
- }
-
- *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
-
- if ( !shadow_mode_enabled )
- if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
- (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
- *vl1e &= ~_PAGE_RW;
-
- vl1e++;
- }
-
- /* Xen requires a mid-level pgdir mapping 0xC0000000 region. */
- if ( (vl3tab[3] & _PAGE_PRESENT) == 0 )
- {
- alloc_pt(l2tab, vl2tab);
- vl3tab[3] = l2tab | L3_PROT;
- }
-
- munmap(vl1tab, PAGE_SIZE);
- munmap(vl2tab, PAGE_SIZE);
- munmap(vl3tab, PAGE_SIZE);
- return 0;
-
- error_out:
- if (vl1tab)
- munmap(vl1tab, PAGE_SIZE);
- if (vl2tab)
- munmap(vl2tab, PAGE_SIZE);
- if (vl3tab)
- munmap(vl3tab, PAGE_SIZE);
- return -1;
-}
-
-#endif
-
-#if defined(__x86_64__)
-
-static int setup_pg_tables_64(int xc_handle, uint32_t dom,
- vcpu_guest_context_t *ctxt,
- unsigned long dsi_v_start,
- unsigned long v_end,
- xen_pfn_t *page_array,
- unsigned long vpt_start,
- unsigned long vpt_end,
- int shadow_mode_enabled)
-{
- l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
- l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
- l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
- l4_pgentry_t *vl4tab=NULL, *vl4e=NULL;
- unsigned long l2tab = 0;
- unsigned long l1tab = 0;
- unsigned long l3tab = 0;
- unsigned long l4tab = 0;
- unsigned long ppt_alloc;
- unsigned long count;
-
- /* First allocate page for page dir. */
- ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
- alloc_pt(l4tab, vl4tab);
- vl4e = &vl4tab[l4_table_offset(dsi_v_start)];
- ctxt->ctrlreg[3] = xen_pfn_to_cr3(l4tab >> PAGE_SHIFT);
-
- for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
- {
- if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
- {
- alloc_pt(l1tab, vl1tab);
-
- if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
- {
- alloc_pt(l2tab, vl2tab);
- if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
- {
- alloc_pt(l3tab, vl3tab);
- vl3e = &vl3tab[l3_table_offset(dsi_v_start +
(count<<PAGE_SHIFT))];
- *vl4e++ = l3tab | L4_PROT;
- }
- vl2e = &vl2tab[l2_table_offset(dsi_v_start +
(count<<PAGE_SHIFT))];
- *vl3e++ = l2tab | L3_PROT;
- }
- vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
- *vl2e++ = l1tab | L2_PROT;
- }
-
- *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-
- if ( !shadow_mode_enabled )
- if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
- (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
- *vl1e &= ~_PAGE_RW;
-
- vl1e++;
- }
-
- munmap(vl1tab, PAGE_SIZE);
- munmap(vl2tab, PAGE_SIZE);
- munmap(vl3tab, PAGE_SIZE);
- munmap(vl4tab, PAGE_SIZE);
- return 0;
-
- error_out:
- if (vl1tab)
- munmap(vl1tab, PAGE_SIZE);
- if (vl2tab)
- munmap(vl2tab, PAGE_SIZE);
- if (vl3tab)
- munmap(vl3tab, PAGE_SIZE);
- if (vl4tab)
- munmap(vl4tab, PAGE_SIZE);
- return -1;
-}
-#endif
-
-#ifdef __ia64__
-static int setup_guest(int xc_handle,
- uint32_t dom,
- const char *image, unsigned long image_size,
- struct initrd_info *initrd,
- unsigned long nr_pages,
- unsigned long *pvsi, unsigned long *pvke,
- unsigned long *pvss, vcpu_guest_context_t *ctxt,
- const char *cmdline,
- unsigned long shared_info_frame,
- unsigned long flags,
- unsigned int store_evtchn, unsigned long *store_mfn,
- unsigned int console_evtchn, unsigned long *console_mfn,
- uint32_t required_features[XENFEAT_NR_SUBMAPS])
-{
- xen_pfn_t *page_array = NULL;
- struct load_funcs load_funcs;
- struct domain_setup_info dsi;
- unsigned long vinitrd_start;
- unsigned long vinitrd_end;
- unsigned long v_end;
- unsigned long start_page, pgnr;
- start_info_t *start_info;
- unsigned long start_info_mpa;
- struct xen_ia64_boot_param *bp;
- shared_info_t *shared_info;
- int i;
- DECLARE_DOMCTL;
- int rc;
-
- rc = probeimageformat(image, image_size, &load_funcs);
- if ( rc != 0 )
- goto error_out;
-
- memset(&dsi, 0, sizeof(struct domain_setup_info));
-
- rc = (load_funcs.parseimage)(image, image_size, &dsi);
- if ( rc != 0 )
- goto error_out;
-
- if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL )
- {
- PERROR("Could not allocate memory");
- goto error_out;
- }
- for ( i = 0; i < nr_pages; i++ )
- page_array[i] = i;
- if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages,
- 0, 0, page_array) )
- {
- PERROR("Could not allocate memory for PV guest.\n");
- goto error_out;
- }
-
- dsi.v_start = round_pgdown(dsi.v_start);
- vinitrd_start = round_pgup(dsi.v_end);
- start_info_mpa = (nr_pages - 3) << PAGE_SHIFT;
- *pvke = dsi.v_kernentry;
-
- /* Build firmware. */
- memset(&domctl.u.arch_setup, 0, sizeof(domctl.u.arch_setup));
- domctl.u.arch_setup.flags = 0;
- domctl.u.arch_setup.bp = start_info_mpa + sizeof (start_info_t);
- domctl.u.arch_setup.maxmem = (nr_pages - 3) << PAGE_SHIFT;
- domctl.cmd = XEN_DOMCTL_arch_setup;
- domctl.domain = (domid_t)dom;
- if ( xc_domctl(xc_handle, &domctl) )
- goto error_out;
-
- start_page = dsi.v_start >> PAGE_SHIFT;
- /* in order to get initrd->len, we need to load initrd image at first */
- if ( load_initrd(xc_handle, dom, initrd,
- vinitrd_start - dsi.v_start, page_array + start_page) )
- goto error_out;
-
- vinitrd_end = vinitrd_start + initrd->len;
- v_end = round_pgup(vinitrd_end);
- pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT;
- if ( pgnr > nr_pages )
- {
- PERROR("too small memory is specified. "
- "At least %ld kb is necessary.\n",
- pgnr << (PAGE_SHIFT - 10));
- }
-
- IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
- " Loaded kernel: %p->%p\n"
- " Init. ramdisk: %p->%p\n"
- " TOTAL: %p->%p\n",
- _p(dsi.v_kernstart), _p(dsi.v_kernend),
- _p(vinitrd_start), _p(vinitrd_end),
- _p(dsi.v_start), _p(v_end));
- IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
-
- (load_funcs.loadimage)(image, image_size, xc_handle, dom,
- page_array + start_page, &dsi);
-
- *store_mfn = page_array[nr_pages - 2]; //XXX
- *console_mfn = page_array[nr_pages - 1]; //XXX
- IPRINTF("start_info: 0x%lx at 0x%lx, "
- "store_mfn: 0x%lx at 0x%lx, "
- "console_mfn: 0x%lx at 0x%lx\n",
- page_array[nr_pages - 3], nr_pages - 3,
- *store_mfn, nr_pages - 2,
- *console_mfn, nr_pages - 1);
-
- start_info = xc_map_foreign_range(
- xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
- page_array[nr_pages - 3]);
- if ( start_info == NULL )
- goto error_out;
-
- memset(start_info, 0, sizeof(*start_info));
- rc = xc_version(xc_handle, XENVER_version, NULL);
- sprintf(start_info->magic, "xen-%i.%i-ia64", rc >> 16, rc & (0xFFFF));
- start_info->flags = flags;
- start_info->store_mfn = nr_pages - 2;
- start_info->store_evtchn = store_evtchn;
- start_info->console.domU.mfn = nr_pages - 1;
- start_info->console.domU.evtchn = console_evtchn;
- start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ????
-
- bp = (struct xen_ia64_boot_param *)(start_info + 1);
- bp->command_line = start_info_mpa + offsetof(start_info_t, cmd_line);
- if ( cmdline != NULL )
- {
- strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
- start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = 0;
- }
- if ( initrd->len != 0 )
- {
- bp->initrd_start = vinitrd_start;
- bp->initrd_size = initrd->len;
- }
- ctxt->user_regs.r28 = start_info_mpa + sizeof (start_info_t);
- munmap(start_info, PAGE_SIZE);
-
- /*
- * shared_info is assiged into guest pseudo physical address space
- * by XEN_DOMCTL_arch_setup. shared_info_frame is stale value until that.
- * So passed shared_info_frame is stale. obtain the right value here.
- */
- domctl.cmd = XEN_DOMCTL_getdomaininfo;
- domctl.domain = (domid_t)dom;
- if ( (xc_domctl(xc_handle, &domctl) < 0) ||
- ((uint16_t)domctl.domain != dom) )
- {
- PERROR("Could not get info on domain");
- goto error_out;
- }
- shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
-
- /* shared_info page starts its life empty. */
- shared_info = xc_map_foreign_range(
- xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
- printf("shared_info = %p frame=%lx\n",
- shared_info, shared_info_frame);
- //memset(shared_info, 0, PAGE_SIZE);
- /* Mask all upcalls... */
- for ( i = 0; i < MAX_VIRT_CPUS; i++ )
- shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
- shared_info->arch.start_info_pfn = nr_pages - 3;
-
- munmap(shared_info, PAGE_SIZE);
- free(page_array);
- return 0;
-
- error_out:
- free(page_array);
- return -1;
-}
-#else /* x86 */
-
-/* Check if the platform supports the guest kernel format */
-static int compat_check(int xc_handle, struct domain_setup_info *dsi)
-{
- xen_capabilities_info_t xen_caps = "";
-
- if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) {
- xc_set_error(XC_INVALID_KERNEL,
- "Cannot determine host capabilities.");
- return 0;
- }
-
-#ifndef __x86_64__//temp
- if (strstr(xen_caps, "xen-3.0-x86_32p")) {
- if (dsi->pae_kernel == PAEKERN_bimodal) {
- dsi->pae_kernel = PAEKERN_extended_cr3;
- } else if (dsi->pae_kernel == PAEKERN_no) {
- xc_set_error(XC_INVALID_KERNEL,
- "Non PAE-kernel on PAE host.");
- return 0;
- }
- } else {
- if (dsi->pae_kernel == PAEKERN_bimodal) {
- dsi->pae_kernel = PAEKERN_no;
- } else if (dsi->pae_kernel != PAEKERN_no) {
- xc_set_error(XC_INVALID_KERNEL,
- "PAE-kernel on non-PAE host.");
- return 0;
- }
- }
-#endif
-
- return 1;
-}
-
-static inline int increment_ulong(unsigned long *pval, unsigned long inc)
-{
- if ( inc >= -*pval )
- {
- ERROR("Value wrapped to zero: image too large?");
- return 0;
- }
- *pval += inc;
- return 1;
-}
-
-static int setup_guest(int xc_handle,
- uint32_t dom,
- const char *image, unsigned long image_size,
- struct initrd_info *initrd,
- unsigned long nr_pages,
- unsigned long *pvsi, unsigned long *pvke,
- unsigned long *pvss, vcpu_guest_context_t *ctxt,
- const char *cmdline,
- unsigned long shared_info_frame,
- unsigned long flags,
- unsigned int store_evtchn, unsigned long *store_mfn,
- unsigned int console_evtchn, unsigned long *console_mfn,
- uint32_t required_features[XENFEAT_NR_SUBMAPS])
-{
- xen_pfn_t *page_array = NULL;
- unsigned long count, i;
- unsigned long long hypercall_page;
- int hypercall_page_defined;
- start_info_t *start_info;
- shared_info_t *shared_info;
- const char *p;
- DECLARE_DOMCTL;
- int rc;
-
- unsigned long nr_pt_pages;
- unsigned long physmap_pfn;
- xen_pfn_t *physmap, *physmap_e;
-
- struct load_funcs load_funcs;
- struct domain_setup_info dsi;
- unsigned long vinitrd_start;
- unsigned long vphysmap_start;
- unsigned long vstartinfo_start;
- unsigned long vstoreinfo_start;
- unsigned long vconsole_start;
- unsigned long vsharedinfo_start = 0; /* XXX gcc */
- unsigned long vstack_start;
- unsigned long vstack_end;
- unsigned long vpt_start;
- unsigned long vpt_end;
- unsigned long v_end;
- unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
- unsigned long shadow_mode_enabled;
- uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, };
-
- rc = probeimageformat(image, image_size, &load_funcs);
- if ( rc != 0 )
- goto error_out;
-
- memset(&dsi, 0, sizeof(struct domain_setup_info));
-
- rc = (load_funcs.parseimage)(image, image_size, &dsi);
- if ( rc != 0 )
- goto error_out;
-
- if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
- {
- PERROR("Guest OS must load to a page boundary.");
- goto error_out;
- }
-
- if ( !compat_check(xc_handle, &dsi) )
- goto error_out;
-
- /* Parse and validate kernel features. */
- if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
- {
- if ( !parse_features(p, supported_features, required_features) )
- {
- ERROR("Failed to parse guest kernel features.");
- goto error_out;
- }
-
- IPRINTF("Supported features = { %08x }.\n", supported_features[0]);
- IPRINTF("Required features = { %08x }.\n", required_features[0]);
- }
-
- for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
- {
- if ( (supported_features[i] & required_features[i]) !=
- required_features[i] )
- {
- ERROR("Guest kernel does not support a required feature.");
- goto error_out;
- }
- }
-
- shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap,
- required_features);
-
- if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
- {
- PERROR("Could not allocate memory");
- goto error_out;
- }
-
- for ( i = 0; i < nr_pages; i++ )
- page_array[i] = i;
-
- if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages,
- 0, 0, page_array) )
- {
- PERROR("Could not allocate memory for PV guest.\n");
- goto error_out;
- }
-
-
- if ( shadow_mode_enabled )
- {
- /*
- * Enable shadow translate mode. This must happen after
- * populate physmap because the p2m reservation is based on
- * the domain's current memory allocation.
- */
- if ( xc_shadow_control(xc_handle, dom,
- XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE,
- NULL, 0, NULL, 0, NULL) < 0 )
- {
- PERROR("Could not enable translation mode");
- goto error_out;
- }
-
- /* Reinitialise the gpfn->gmfn array. */
- for ( i = 0; i < nr_pages; i++ )
- page_array[i] = i;
- }
-
- rc = (load_funcs.loadimage)(image, image_size,
- xc_handle, dom, page_array,
- &dsi);
- if ( rc != 0 )
- goto error_out;
-
- /*
- * Why do we need this? The number of page-table frames depends on the
- * size of the bootstrap address space. But the size of the address space
- * depends on the number of page-table frames (since each one is mapped
- * read-only). We have a pair of simultaneous equations in two unknowns,
- * which we solve by exhaustive search.
- */
- v_end = round_pgup(dsi.v_end);
- if ( v_end == 0 )
- {
- ERROR("End of mapped kernel image too close to end of memory");
- goto error_out;
- }
-
- vinitrd_start = v_end;
- if ( load_initrd(xc_handle, dom, initrd,
- vinitrd_start - dsi.v_start, page_array) )
- goto error_out;
- if ( !increment_ulong(&v_end, round_pgup(initrd->len)) )
- goto error_out;
-
- vphysmap_start = v_end;
- if ( !increment_ulong(&v_end, round_pgup(nr_pages * sizeof(long))) )
- goto error_out;
- vstartinfo_start = v_end;
- if ( !increment_ulong(&v_end, PAGE_SIZE) )
- goto error_out;
- vstoreinfo_start = v_end;
- if ( !increment_ulong(&v_end, PAGE_SIZE) )
- goto error_out;
- vconsole_start = v_end;
- if ( !increment_ulong(&v_end, PAGE_SIZE) )
- goto error_out;
- if ( shadow_mode_enabled ) {
- vsharedinfo_start = v_end;
- if ( !increment_ulong(&v_end, PAGE_SIZE) )
- goto error_out;
- }
- vpt_start = v_end;
-
- for ( nr_pt_pages = 2; ; nr_pt_pages++ )
- {
- /* vpt_end = vpt_staret + (nr_pt_pages * PAGE_SIZE); */
- vpt_end = vpt_start;
- if ( !increment_ulong(&vpt_end, nr_pt_pages * PAGE_SIZE) )
- goto error_out;
-
- vstack_start = vpt_end;
- /* vstack_end = vstack_start + PAGE_SIZE; */
- vstack_end = vstack_start;
- if ( !increment_ulong(&vstack_end, PAGE_SIZE) )
- goto error_out;
-
- /* v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1); */
- v_end = vstack_end;
- if ( !increment_ulong(&v_end, (1UL<<22)-1) )
- goto error_out;
- v_end &= ~((1UL<<22)-1);
-
- if ( (v_end - vstack_end) < (512UL << 10) )
- {
- /* Add extra 4MB to get >= 512kB padding. */
- if ( !increment_ulong(&v_end, 1UL << 22) )
- goto error_out;
- }
-
-#define NR(_l,_h,_s) \
- (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
- ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s))
-#if defined(__i386__)
- if ( dsi.pae_kernel != PAEKERN_no )
- {
- if ( (1 + /* # L3 */
- NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT_PAE) + /* # L2 */
- NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT_PAE) + /* # L1 */
- /* Include a fourth mid-level page directory for Xen. */
- (v_end <= (3 << L3_PAGETABLE_SHIFT_PAE)))
- <= nr_pt_pages )
- break;
- }
- else
- {
- if ( (1 + /* # L2 */
- NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
- <= nr_pt_pages )
- break;
- }
-#elif defined(__x86_64__)
- if ( (1 + /* # L4 */
- NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
- NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
- NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
- <= nr_pt_pages )
- break;
-#endif
- }
-
- IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n");
- IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart),
- _p(dsi.v_kernend));
- if ( initrd->len )
- IPRINTF(" Initial ramdisk: %p->%p\n", _p(vinitrd_start),
- _p(vinitrd_start + initrd->len));
- IPRINTF(" Phys-Mach map: %p\n", _p(vphysmap_start));
- IPRINTF(" Start info: %p\n", _p(vstartinfo_start));
- IPRINTF(" Store page: %p\n", _p(vstoreinfo_start));
- IPRINTF(" Console page: %p\n", _p(vconsole_start));
- if ( shadow_mode_enabled )
- IPRINTF(" Shared Info page: %p\n", _p(vsharedinfo_start));
- IPRINTF(" Page tables: %p\n", _p(vpt_start));
- IPRINTF(" Boot stack: %p\n", _p(vstack_start));
- IPRINTF(" TOTAL: %p->%p\n", _p(dsi.v_start), _p(v_end));
- IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
-
- if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages )
- {
- PERROR("Initial guest OS requires too much space\n"
- "(%pMB is greater than %luMB limit)\n",
- _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT));
- goto error_out;
- }
-
-#if defined(__i386__)
- if ( dsi.pae_kernel != PAEKERN_no )
- rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
- dsi.v_start, v_end,
- page_array, vpt_start, vpt_end,
- shadow_mode_enabled, dsi.pae_kernel);
- else
- rc = setup_pg_tables(xc_handle, dom, ctxt,
- dsi.v_start, v_end,
- page_array, vpt_start, vpt_end,
- shadow_mode_enabled);
-#endif
-#if defined(__x86_64__)
- rc = setup_pg_tables_64(xc_handle, dom, ctxt,
- dsi.v_start, v_end,
- page_array, vpt_start, vpt_end,
- shadow_mode_enabled);
-#endif
- if ( rc != 0 )
- goto error_out;
-
- /*
- * Pin down l2tab addr as page dir page - causes hypervisor to provide
- * correct protection for the page
- */
- if ( !shadow_mode_enabled )
- {
-#if defined(__i386__)
- if ( dsi.pae_kernel != PAEKERN_no )
- {
- if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
- xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
- goto error_out;
- }
- else
- {
- if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
- xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
- goto error_out;
- }
-#elif defined(__x86_64__)
- /*
- * Pin down l4tab addr as page dir page - causes hypervisor to provide
- * correct protection for the page
- */
- if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
- xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
- goto error_out;
-#endif
- }
-
- /* Write the phys->machine table entries (machine->phys already done). */
- physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
- physmap = physmap_e = xc_map_foreign_range(
- xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
- page_array[physmap_pfn++]);
- for ( count = 0; count < nr_pages; count++ )
- {
- *physmap_e++ = page_array[count];
- if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
- {
- munmap(physmap, PAGE_SIZE);
- physmap = physmap_e = xc_map_foreign_range(
- xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
- page_array[physmap_pfn++]);
- }
- }
- munmap(physmap, PAGE_SIZE);
-
- if ( shadow_mode_enabled )
- {
- struct xen_add_to_physmap xatp;
-
- guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT;
-
- /* Map shared info frame into guest physmap. */
- xatp.domid = dom;
- xatp.space = XENMAPSPACE_shared_info;
- xatp.idx = 0;
- xatp.gpfn = guest_shared_info_mfn;
- rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
- if ( rc != 0 )
- {
- PERROR("Cannot map shared info pfn");
- goto error_out;
- }
-
- /* Map grant table frames into guest physmap. */
- for ( i = 0; ; i++ )
- {
- xatp.domid = dom;
- xatp.space = XENMAPSPACE_grant_table;
- xatp.idx = i;
- xatp.gpfn = nr_pages + i;
- rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
- if ( rc != 0 )
- {
- if ( errno == EINVAL )
- break; /* done all grant tables */
- PERROR("Cannot map grant table pfn");
- goto error_out;
- }
- }
- }
- else
- {
- guest_shared_info_mfn = shared_info_frame;
- }
-
- *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
- *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
- if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) ||
- xc_clear_domain_page(xc_handle, dom, *console_mfn) )
- goto error_out;
- if ( shadow_mode_enabled )
- {
- guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT;
- guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT;
- }
- else
- {
- guest_store_mfn = *store_mfn;
- guest_console_mfn = *console_mfn;
- }
-
- start_info = xc_map_foreign_range(
- xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
- page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
- /*shared_info, start_info */
- memset(start_info, 0, sizeof(*start_info));
- rc = xc_version(xc_handle, XENVER_version, NULL);
- sprintf(start_info->magic, "xen-%i.%i-x86_%d%s",
- rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8,
- (dsi.pae_kernel != PAEKERN_no) ? "p" : "");
- start_info->nr_pages = nr_pages;
- start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT;
- start_info->flags = flags;
- start_info->pt_base = vpt_start;
- start_info->nr_pt_frames = nr_pt_pages;
- start_info->mfn_list = vphysmap_start;
- start_info->store_mfn = guest_store_mfn;
- start_info->store_evtchn = store_evtchn;
- start_info->console.domU.mfn = guest_console_mfn;
- start_info->console.domU.evtchn = console_evtchn;
- if ( initrd->len != 0 )
- {
- start_info->mod_start = vinitrd_start;
- start_info->mod_len = initrd->len;
- }
- if ( cmdline != NULL )
- {
- strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
- start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
- }
- munmap(start_info, PAGE_SIZE);
-
- /* shared_info page starts its life empty. */
- shared_info = xc_map_foreign_range(
- xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
- memset(shared_info, 0, PAGE_SIZE);
- /* Mask all upcalls... */
- for ( i = 0; i < MAX_VIRT_CPUS; i++ )
- shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
-
- munmap(shared_info, PAGE_SIZE);
-
- hypercall_page = xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE,
- &hypercall_page_defined);
- if ( hypercall_page_defined )
- {
- unsigned long long pfn = (hypercall_page - dsi.v_start) >> PAGE_SHIFT;
- if ( pfn >= nr_pages )
- goto error_out;
- domctl.domain = (domid_t)dom;
- domctl.u.hypercall_init.gmfn = page_array[pfn];
- domctl.cmd = XEN_DOMCTL_hypercall_init;
- if ( xc_domctl(xc_handle, &domctl) )
- goto error_out;
- }
-
- free(page_array);
-
- *pvsi = vstartinfo_start;
- *pvss = vstack_start;
- *pvke = dsi.v_kernentry;
-
- return 0;
-
- error_out:
- free(page_array);
- return -1;
-}
-#endif
-
-static int xc_linux_build_internal(int xc_handle,
- uint32_t domid,
- unsigned int mem_mb,
- const char *image,
- unsigned long image_size,
- struct initrd_info *initrd,
- const char *cmdline,
- const char *features,
- unsigned long flags,
- unsigned int store_evtchn,
- unsigned long *store_mfn,
- unsigned int console_evtchn,
- unsigned long *console_mfn)
-{
- struct xen_domctl launch_domctl;
- DECLARE_DOMCTL;
- int rc;
- struct vcpu_guest_context st_ctxt, *ctxt = &st_ctxt;
- unsigned long vstartinfo_start, vkern_entry, vstack_start;
- uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, };
-
- if ( features != NULL )
- {
- if ( !parse_features(features, features_bitmap, NULL) )
- {
- PERROR("Failed to parse configured features\n");
- goto error_out;
- }
- }
-
- memset(ctxt, 0, sizeof(*ctxt));
-
- if ( lock_pages(ctxt, sizeof(*ctxt) ) )
- {
- PERROR("%s: ctxt lock failed", __func__);
- return 1;
- }
-
- domctl.cmd = XEN_DOMCTL_getdomaininfo;
- domctl.domain = (domid_t)domid;
- if ( (xc_domctl(xc_handle, &domctl) < 0) ||
- ((uint16_t)domctl.domain != domid) )
- {
- PERROR("Could not get info on domain");
- goto error_out;
- }
-
- if ( setup_guest(xc_handle, domid, image, image_size,
- initrd,
- mem_mb << (20 - PAGE_SHIFT),
- &vstartinfo_start, &vkern_entry,
- &vstack_start, ctxt, cmdline,
- domctl.u.getdomaininfo.shared_info_frame,
- flags, store_evtchn, store_mfn,
- console_evtchn, console_mfn,
- features_bitmap) < 0 )
- {
- goto error_out;
- }
-
-#ifdef __ia64__
- /* based on new_thread in xen/arch/ia64/domain.c */
- ctxt->user_regs.cr_iip = vkern_entry;
- ctxt->user_regs.cr_ifs = 1UL << 63;
- ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default();
-#else /* x86 */
- /*
- * Initial register values:
- * DS,ES,FS,GS = FLAT_KERNEL_DS
- * CS:EIP = FLAT_KERNEL_CS:start_pc
- * SS:ESP = FLAT_KERNEL_DS:start_stack
- * ESI = start_info
- * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
- * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
- */
- ctxt->user_regs.ds = FLAT_KERNEL_DS;
- ctxt->user_regs.es = FLAT_KERNEL_DS;
- ctxt->user_regs.fs = FLAT_KERNEL_DS;
- ctxt->user_regs.gs = FLAT_KERNEL_DS;
- ctxt->user_regs.ss = FLAT_KERNEL_SS;
- ctxt->user_regs.cs = FLAT_KERNEL_CS;
- ctxt->user_regs.eip = vkern_entry;
- ctxt->user_regs.esp = vstack_start + PAGE_SIZE;
- ctxt->user_regs.esi = vstartinfo_start;
- ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
-
- ctxt->flags = VGCF_IN_KERNEL;
-
- ctxt->kernel_ss = ctxt->user_regs.ss;
- ctxt->kernel_sp = ctxt->user_regs.esp;
-#endif /* x86 */
-
- memset(&launch_domctl, 0, sizeof(launch_domctl));
-
- launch_domctl.domain = (domid_t)domid;
- launch_domctl.u.vcpucontext.vcpu = 0;
- set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
-
- launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
- rc = xc_domctl(xc_handle, &launch_domctl);
-
- return rc;
-
- error_out:
- return -1;
-}
-
-int xc_linux_build_mem(int xc_handle,
- uint32_t domid,
- unsigned int mem_mb,
- const char *image_buffer,
- unsigned long image_size,
- const char *initrd,
- unsigned long initrd_len,
- const char *cmdline,
- const char *features,
- unsigned long flags,
- unsigned int store_evtchn,
- unsigned long *store_mfn,
- unsigned int console_evtchn,
- unsigned long *console_mfn)
-{
- int sts;
- char *img_buf;
- unsigned long img_len;
- struct initrd_info initrd_info = { .type = INITRD_none };
-
- /* A kernel buffer is required */
- if ( (image_buffer == NULL) || (image_size == 0) )
- {
- ERROR("kernel image buffer not present");
- return -1;
- }
-
- /* If it's gzipped, inflate it; otherwise, use as is */
- /* xc_inflate_buffer may return the same buffer pointer if */
- /* the buffer is already inflated */
- img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len);
- if ( img_buf == NULL )
- {
- ERROR("unable to inflate kernel image buffer");
- return -1;
- }
-
- /* RAM disks are optional; if we get one, inflate it */
- if ( initrd != NULL )
- {
- initrd_info.type = INITRD_mem;
- initrd_info.u.mem_addr = xc_inflate_buffer(
- initrd, initrd_len, &initrd_info.len);
- if ( initrd_info.u.mem_addr == NULL )
- {
- ERROR("unable to inflate ram disk buffer");
- sts = -1;
- goto out;
- }
- }
-
- sts = xc_linux_build_internal(xc_handle, domid, mem_mb, img_buf, img_len,
- &initrd_info, cmdline, features, flags,
- store_evtchn, store_mfn,
- console_evtchn, console_mfn);
-
- out:
- /* The inflation routines may pass back the same buffer so be */
- /* sure that we have a buffer and that it's not the one passed in. */
- /* Don't unnecessarily annoy/surprise/confound the caller */
- if ( (img_buf != NULL) && (img_buf != image_buffer) )
- free(img_buf);
- if ( (initrd_info.u.mem_addr != NULL) &&
- (initrd_info.u.mem_addr != initrd) )
- free(initrd_info.u.mem_addr);
-
- return sts;
-}
-
-int xc_linux_build(int xc_handle,
- uint32_t domid,
- unsigned int mem_mb,
- const char *image_name,
- const char *initrd_name,
- const char *cmdline,
- const char *features,
- unsigned long flags,
- unsigned int store_evtchn,
- unsigned long *store_mfn,
- unsigned int console_evtchn,
- unsigned long *console_mfn)
-{
- char *image = NULL;
- unsigned long image_size;
- struct initrd_info initrd_info = { .type = INITRD_none };
- int fd = -1, sts = -1;
-
- if ( (image_name == NULL) ||
- ((image = xc_read_image(image_name, &image_size)) == NULL ))
- return -1;
-
- if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) )
- {
- initrd_info.type = INITRD_file;
-
- if ( (fd = open(initrd_name, O_RDONLY)) < 0 )
- {
- PERROR("Could not open the initial ramdisk image");
- goto error_out;
- }
-
- if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL )
- {
- PERROR("Could not allocate decompression state for initrd");
- goto error_out;
- }
- }
-
- sts = xc_linux_build_internal(xc_handle, domid, mem_mb, image, image_size,
- &initrd_info, cmdline, features, flags,
- store_evtchn, store_mfn,
- console_evtchn, console_mfn);
-
- error_out:
- free(image);
- if ( initrd_info.type == INITRD_file && initrd_info.u.file_handle )
- gzclose(initrd_info.u.file_handle);
- else if ( fd >= 0 )
- close(fd);
-
- return sts;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_load_bin.c
--- a/tools/libxc/xc_load_bin.c Wed Feb 14 12:18:32 2007 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/******************************************************************************
- * xc_bin_load.c
- *
- * Based on xc_elf_load.c
- *
- * Loads simple binary images. It's like a .COM file in MS-DOS. No headers are
- * present. The only requirement is that it must have a xen_bin_image table
- * somewhere in the first 8192 bytes, starting on a 32-bit aligned address.
- * Those familiar with the multiboot specification should recognize this, it's
- * (almost) the same as the multiboot header.
- * The layout of the xen_bin_image table is:
- *
- * Offset Type Name Note
- * 0 uint32_t magic required
- * 4 uint32_t flags required
- * 8 uint32_t checksum required
- * 12 uint32_t header_addr required
- * 16 uint32_t load_addr required
- * 20 uint32_t load_end_addr required
- * 24 uint32_t bss_end_addr required
- * 28 uint32_t entry_addr required
- *
- * - magic
- * Magic number identifying the table. For images to be loaded by Xen 3, the
- * magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set).
- * - flags
- * bit 0: indicates whether the image needs to be loaded on a page boundary
- * bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate
- * that memory info should be passed to the image)
- * bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate
- * that the bootloader should pass video mode info to the image)
- * bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate
- * that the values in the fields header_addr - entry_addr are
- * valid)
- * All other bits should be set to 0.
- * - checksum
- * When added to "magic" and "flags", the resulting value should be 0.
- * - header_addr
- * Contains the virtual address corresponding to the beginning of the
- * table - the memory location at which the magic value is supposed to be
- * loaded. This field serves to synchronize the mapping between OS image
- * offsets and virtual memory addresses.
- * - load_addr
- * Contains the virtual address of the beginning of the text segment. The
- * offset in the OS image file at which to start loading is defined by the
- * offset at which the table was found, minus (header addr - load addr).
- * load addr must be less than or equal to header addr.
- * - load_end_addr
- * Contains the virtual address of the end of the data segment.
- * (load_end_addr - load_addr) specifies how much data to load. This implies
- * that the text and data segments must be consecutive in the OS image. If
- * this field is zero, the domain builder assumes that the text and data
- * segments occupy the whole OS image file.
- * - bss_end_addr
- * Contains the virtual address of the end of the bss segment. The domain
- * builder initializes this area to zero, and reserves the memory it occupies
- * to avoid placing boot modules and other data relevant to the loaded image
- * in that area. If this field is zero, the domain builder assumes that no
bss
- * segment is present.
- * - entry_addr
- * The virtual address at which to start execution of the loaded image.
- *
- * Some of the field descriptions were copied from "The Multiboot
- * Specification", Copyright 1995, 96 Bryan Ford <baford@xxxxxxxxxxx>,
- * Erich Stefan Boleyn <erich@xxxxxxxx> Copyright 1999, 2000, 2001, 2002
- * Free Software Foundation, Inc.
- */
-
-#include "xg_private.h"
-#include <stdlib.h>
-
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-
-#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-#define round_pgdown(_p) ((_p)&PAGE_MASK)
-
-struct xen_bin_image_table
-{
- unsigned long magic;
- unsigned long flags;
- unsigned long checksum;
- unsigned long header_addr;
- unsigned long load_addr;
- unsigned long load_end_addr;
- unsigned long bss_end_addr;
- unsigned long entry_addr;
-};
-
-#define XEN_REACTOS_MAGIC3 0x336ec578
-
-#define XEN_REACTOS_FLAG_ALIGN4K 0x00000001
-#define XEN_REACTOS_FLAG_NEEDMEMINFO 0x00000002
-#define XEN_REACTOS_FLAG_NEEDVIDINFO 0x00000004
-#define XEN_REACTOS_FLAG_ADDRSVALID 0x00010000
-
-/* Flags we test for */
-#define FLAGS_MASK ((~ 0) & (~ XEN_REACTOS_FLAG_ALIGN4K))
-#define FLAGS_REQUIRED XEN_REACTOS_FLAG_ADDRSVALID
-
-static const struct xen_bin_image_table *
-findtable(const char *image, unsigned long image_size);
-static int
-parsebinimage(
- const char *image, unsigned long image_size,
- struct domain_setup_info *dsi);
-static int
-loadbinimage(
- const char *image, unsigned long image_size, int xch, uint32_t dom,
- xen_pfn_t *parray, struct domain_setup_info *dsi);
-
-int probe_bin(const char *image,
- unsigned long image_size,
- struct load_funcs *load_funcs)
-{
- if ( findtable(image, image_size) == NULL )
- return -EINVAL;
-
- load_funcs->parseimage = parsebinimage;
- load_funcs->loadimage = loadbinimage;
-
- return 0;
-}
-
-static const struct xen_bin_image_table *
-findtable(const char *image, unsigned long image_size)
-{
- const struct xen_bin_image_table *table;
- const unsigned long *probe_ptr;
- unsigned probe_index;
- unsigned probe_count;
-
- /* Don't go outside the image */
- if ( image_size < sizeof(struct xen_bin_image_table) )
- return NULL;
-
- probe_count = image_size;
- /* Restrict to first 8k */
- if ( probe_count > 8192 )
- probe_count = 8192;
- probe_count = (probe_count - sizeof(struct xen_bin_image_table)) /
- sizeof(unsigned long);
-
- /* Search for the magic header */
- probe_ptr = (const unsigned long *) image;
- table = NULL;
- for ( probe_index = 0; probe_index < probe_count; probe_index++ )
- {
- if ( XEN_REACTOS_MAGIC3 == *probe_ptr )
- {
- table = (const struct xen_bin_image_table *) probe_ptr;
- /* Checksum correct? */
- if ( 0 == table->magic + table->flags + table->checksum )
- {
- return table;
- }
- }
- probe_ptr++;
- }
-
- return NULL;
-}
-
-static int parsebinimage(const char *image,
- unsigned long image_size,
- struct domain_setup_info *dsi)
-{
- const struct xen_bin_image_table *image_info;
- unsigned long start_addr;
- unsigned long end_addr;
-
- image_info = findtable(image, image_size);
- if ( NULL == image_info )
- {
- ERROR("Image does not have a valid xen_bin_image_table table.");
- return -EINVAL;
- }
-
- /* Check the flags */
- if ( FLAGS_REQUIRED != (image_info->flags & FLAGS_MASK) )
- {
- ERROR("xen_bin_image_table flags required 0x%08x found 0x%08lx",
- FLAGS_REQUIRED, image_info->flags & FLAGS_MASK);
- return -EINVAL;
- }
-
- /* Sanity check on the addresses */
- if ( image_info->header_addr < image_info->load_addr ||
- ((const char *) image_info - image) <
- (image_info->header_addr - image_info->load_addr) )
- {
- ERROR("Invalid header_addr.");
- return -EINVAL;
- }
- start_addr = image_info->header_addr - ((const char *) image_info - image);
- if ( 0 != image_info->load_end_addr &&
- ( image_info->load_end_addr < image_info->load_end_addr ||
- start_addr + image_size < image_info->load_end_addr ) )
- {
- ERROR("Invalid load_end_addr");
- return -EINVAL;
- }
- end_addr = (0 == image_info->load_end_addr ? start_addr + image_size :
- image_info->load_end_addr);
- if ( 0 != image_info->bss_end_addr &&
- image_info->bss_end_addr < end_addr )
- {
- ERROR("Invalid bss_end_addr");
- return -EINVAL;
- }
-
- dsi->v_start = image_info->load_addr;
- if ( 0 != image_info->bss_end_addr )
- {
- dsi->v_end = image_info->bss_end_addr;
- }
- else if ( 0 != image_info->load_end_addr )
- {
- dsi->v_end = image_info->load_end_addr;
- }
- else
- {
- dsi->v_end = image_info->load_addr + image_size -
- (((const char *) image_info - image) -
- (image_info->header_addr - image_info->load_addr));
- }
- dsi->v_kernstart = dsi->v_start;
- dsi->v_kernend = dsi->v_end;
- dsi->v_kernentry = image_info->entry_addr;
- dsi->__xen_guest_string = NULL;
-
- return 0;
-}
-
-static int
-loadbinimage(
- const char *image, unsigned long image_size, int xch, uint32_t dom,
- xen_pfn_t *parray, struct domain_setup_info *dsi)
-{
- unsigned long size;
- char *va;
- unsigned long done, chunksz;
- const struct xen_bin_image_table *image_info;
-
- image_info = findtable(image, image_size);
- if ( NULL == image_info )
- {
- ERROR("Image does not have a valid xen_bin_image_table table.");
- return -EINVAL;
- }
-
- /* Determine image size */
- if ( 0 == image_info->load_end_addr )
- {
- size = image_size - (((const char *)image_info - image) -
- (image_info->header_addr -
- image_info->load_addr));
- }
- else
- {
- size = image_info->load_end_addr - image_info->load_addr;
- }
-
- /* It's possible that we need to skip the first part of the image */
- image += ((const char *)image_info - image) -
- (image_info->header_addr - image_info->load_addr);
-
- for ( done = 0; done < size; done += chunksz )
- {
- va = xc_map_foreign_range(
- xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]);
- chunksz = size - done;
- if ( chunksz > PAGE_SIZE )
- chunksz = PAGE_SIZE;
- memcpy(va, image + done, chunksz);
- munmap(va, PAGE_SIZE);
- }
-
- if ( 0 != image_info->bss_end_addr &&
- image_info->load_addr + size < image_info->bss_end_addr )
- {
- size = image_info->bss_end_addr - image_info->load_addr;
- }
- for ( ; done < size; done += chunksz )
- {
- va = xc_map_foreign_range(
- xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]);
- chunksz = size - done;
- if ( chunksz > (PAGE_SIZE - (done & (PAGE_SIZE-1))) )
- chunksz = PAGE_SIZE - (done & (PAGE_SIZE-1));
- memset(va + (done & (PAGE_SIZE-1)), 0, chunksz);
- munmap(va, PAGE_SIZE);
- }
-
- return 0;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_load_elf.c
--- a/tools/libxc/xc_load_elf.c Wed Feb 14 12:18:32 2007 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,684 +0,0 @@
-/******************************************************************************
- * xc_elf_load.c
- */
-
-#include "xg_private.h"
-#include "xc_elf.h"
-#include <stdlib.h>
-#include <inttypes.h>
-
-#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-#define round_pgdown(_p) ((_p)&PAGE_MASK)
-
-static int
-parseelfimage(
- const char *image, unsigned long image_size,
- struct domain_setup_info *dsi);
-static int
-loadelfimage(
- const char *image, unsigned long image_size, int xch, uint32_t dom,
- xen_pfn_t *parray, struct domain_setup_info *dsi);
-static int
-loadelfsymtab(
- const char *image, int xch, uint32_t dom, xen_pfn_t *parray,
- struct domain_setup_info *dsi);
-
-/*
- * Elf header attributes we require for each supported host platform.
- * These are checked in parseelfimage().
- */
-#if defined(__ia64__)
-#define ELFCLASS ELFCLASS64
-#define ELFCLASS_DESC "64-bit"
-
-#define ELFDATA ELFDATA2LSB
-#define ELFDATA_DESC "Little-Endian"
-
-#define ELFMACHINE EM_IA_64
-#define ELFMACHINE_DESC "ia64"
-
-
-#elif defined(__i386__)
-#define ELFCLASS ELFCLASS32
-#define ELFCLASS_DESC "32-bit"
-
-#define ELFDATA ELFDATA2LSB
-#define ELFDATA_DESC "Little-Endian"
-
-#define ELFMACHINE EM_386
-#define ELFMACHINE_DESC "i386"
-
-
-#elif defined(__x86_64__)
-#define ELFCLASS ELFCLASS64
-#define ELFCLASS_DESC "64-bit"
-
-#define ELFDATA ELFDATA2LSB
-#define ELFDATA_DESC "Little-Endian"
-
-#define ELFMACHINE EM_X86_64
-#define ELFMACHINE_DESC "x86_64"
-
-
-#elif defined(__powerpc__)
-#define ELFCLASS ELFCLASS64
-#define ELFCLASS_DESC "64-bit"
-
-#define ELFDATA ELFDATA2MSB
-#define ELFDATA_DESC "Big-Endian"
-
-#define ELFMACHINE EM_PPC64
-#define ELFMACHINE_DESC "ppc64"
-#endif
-
-int probe_elf(const char *image,
- unsigned long image_size,
- struct load_funcs *load_funcs)
-{
- const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image;
-
- if ( !IS_ELF(*ehdr) )
- return -EINVAL;
-
- load_funcs->parseimage = parseelfimage;
- load_funcs->loadimage = loadelfimage;
-
- return 0;
-}
-
-static inline int is_loadable_phdr(const Elf_Phdr *phdr)
-{
- return ((phdr->p_type == PT_LOAD) &&
- ((phdr->p_flags & (PF_W|PF_X)) != 0));
-}
-
-/*
- * Fallback for kernels containing only the legacy __xen_guest string
- * and no ELF notes.
- */
-static int is_xen_guest_section(const Elf_Shdr *shdr, const char *shstrtab)
-{
- return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0;
-}
-
-static const char *xen_guest_lookup(
- const struct domain_setup_info *dsi, int type)
-{
- const char *xenguest_fallbacks[] = {
- [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=",
- [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=",
- [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=",
- [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=",
- [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=",
- [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=",
- [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=",
- [XEN_ELFNOTE_LOADER] = "LOADER=",
- [XEN_ELFNOTE_PAE_MODE] = "PAE=",
- [XEN_ELFNOTE_FEATURES] = "FEATURES=",
- [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=",
- };
- const char *fallback;
- const char *p;
-
- if ( !dsi->__xen_guest_string )
- return NULL;
-
- if ( type > sizeof(xenguest_fallbacks) )
- return NULL;
-
- if ( (fallback = xenguest_fallbacks[type]) == NULL )
- return NULL;
-
- if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL )
- return NULL;
-
- return p + strlen(fallback);
-}
-
-static const char *xen_guest_string(
- const struct domain_setup_info *dsi, int type)
-{
- const char *p = xen_guest_lookup(dsi, type);
-
- /*
- * We special case this since the __xen_guest_section treats the
- * mere precense of the BSD_SYMTAB string as true or false.
- */
- if ( type == XEN_ELFNOTE_BSD_SYMTAB )
- return p ? "yes" : "no";
-
- return p;
-}
-
-static unsigned long long xen_guest_numeric(
- const struct domain_setup_info *dsi, int type, int *defined)
-{
- const char *p = xen_guest_lookup(dsi, type);
- unsigned long long value;
-
- if ( p == NULL )
- return 0;
-
- errno = 0;
- value = strtoull(p, NULL, 0);
- if ( errno < 0 )
- return 0;
-
- /* We special case this since __xen_guest_section contains a PFN
- * for this field not a virtual address.
- */
- if (type == XEN_ELFNOTE_HYPERCALL_PAGE)
- value = dsi->v_start + (value<<PAGE_SHIFT);
-
- *defined = 1;
- return value;
-}
-
-/*
- * Interface to the Xen ELF notes.
- */
-#define ELFNOTE_NAME(_n_) ((const char*)(_n_) + sizeof(*(_n_)))
-#define ELFNOTE_DESC(_n_) (ELFNOTE_NAME(_n_) + (((_n_)->namesz+3)&~3))
-#define ELFNOTE_NEXT(_n_) (ELFNOTE_DESC(_n_) + (((_n_)->descsz+3)&~3))
-
-static int is_xen_elfnote_section(const char *image, const Elf_Shdr *shdr)
-{
- const Elf_Note *note;
-
- if ( shdr->sh_type != SHT_NOTE )
- return 0;
-
- for ( note = (const Elf_Note *)(image + shdr->sh_offset);
- note < (const Elf_Note *)(image + shdr->sh_offset + shdr->sh_size);
- note = (const Elf_Note *)ELFNOTE_NEXT(note) )
- {
- if ( !strncmp(ELFNOTE_NAME(note), "Xen", 4) )
- return 1;
- }
-
- return 0;
-}
-
-static const Elf_Note *xen_elfnote_lookup(
- const struct domain_setup_info *dsi, int type)
-{
- const Elf_Note *note;
-
- if ( !dsi->__elfnote_section )
- return NULL;
-
- for ( note = (const Elf_Note *)dsi->__elfnote_section;
- note < (const Elf_Note *)dsi->__elfnote_section_end;
- note = (const Elf_Note *)ELFNOTE_NEXT(note) )
- {
- if ( strncmp(ELFNOTE_NAME(note), "Xen", 4) )
- continue;
-
- if ( note->type == type )
- return note;
- }
-
- return NULL;
-}
-
-const char *xen_elfnote_string(const struct domain_setup_info *dsi, int type)
-{
- const Elf_Note *note;
-
- if ( !dsi->__elfnote_section )
- return xen_guest_string(dsi, type);
-
- note = xen_elfnote_lookup(dsi, type);
- if ( note == NULL )
- return NULL;
-
- return (const char *)ELFNOTE_DESC(note);
-}
-
-unsigned long long xen_elfnote_numeric(const struct domain_setup_info *dsi,
- int type, int *defined)
-{
- const Elf_Note *note;
-
- *defined = 0;
-
- if ( !dsi->__elfnote_section )
- return xen_guest_numeric(dsi, type, defined);
-
- note = xen_elfnote_lookup(dsi, type);
- if ( note == NULL )
- {
- return 0;
- }
-
- switch ( note->descsz )
- {
- case 4:
- *defined = 1;
- return *(const uint32_t*)ELFNOTE_DESC(note);
- case 8:
- *defined = 1;
- return *(const uint64_t*)ELFNOTE_DESC(note);
- default:
- xc_set_error(XC_INVALID_KERNEL,
- "elfnotes: unknown data size %#x for numeric type note
%#x\n",
- note->descsz, type);
- return 0;
- }
-}
-
-static int parseelfimage(const char *image,
- unsigned long image_len,
- struct domain_setup_info *dsi)
-{
- const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image;
- const Elf_Phdr *phdr;
- const Elf_Shdr *shdr;
- Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_entry;
- const char *shstrtab, *p;
- int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined;
-
- if ( !IS_ELF(*ehdr) )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Kernel image does not have an ELF header.");
- return -EINVAL;
- }
-
- if (ehdr->e_machine != ELFMACHINE)
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Kernel ELF architecture '%d' does not match Xen
architecture '%d' (%s)",
- ehdr->e_machine, ELFMACHINE, ELFMACHINE_DESC);
- return -EINVAL;
- }
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS)
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Kernel ELF wordsize '%d' does not match Xen wordsize
'%d' (%s)",
- ehdr->e_ident[EI_CLASS], ELFCLASS, ELFCLASS_DESC);
- return -EINVAL;
- }
- if (ehdr->e_ident[EI_DATA] != ELFDATA)
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Kernel ELF endianness '%d' does not match Xen endianness
'%d' (%s)",
- ehdr->e_ident[EI_DATA], ELFDATA, ELFDATA_DESC);
- return -EINVAL;
- }
- if (ehdr->e_type != ET_EXEC)
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Kernel ELF type '%d' does not match Xen type '%d'",
- ehdr->e_type, ET_EXEC);
- return -EINVAL;
- }
-
- if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "ELF program headers extend beyond end of image.");
- return -EINVAL;
- }
-
- if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "ELF section headers extend beyond end of image.");
- return -EINVAL;
- }
-
- dsi->__elfnote_section = NULL;
- dsi->__xen_guest_string = NULL;
-
- /* Look for .notes segment containing at least one Xen note */
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- shdr = (const Elf_Shdr *)(
- image + ehdr->e_shoff + (h*ehdr->e_shentsize));
- if ( !is_xen_elfnote_section(image, shdr) )
- continue;
- dsi->__elfnote_section = (const char *)image + shdr->sh_offset;
- dsi->__elfnote_section_end =
- (const char *)image + shdr->sh_offset + shdr->sh_size;
- break;
- }
-
- /* Fall back to looking for the special '__xen_guest' section. */
- if ( dsi->__elfnote_section == NULL )
- {
- /* Find the section-header strings table. */
- if ( ehdr->e_shstrndx == SHN_UNDEF )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "ELF image has no section-header strings table.");
- return -EINVAL;
- }
- shdr = (const Elf_Shdr *)(image + ehdr->e_shoff +
- (ehdr->e_shstrndx*ehdr->e_shentsize));
- shstrtab = image + shdr->sh_offset;
-
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- shdr = (const Elf_Shdr *)(
- image + ehdr->e_shoff + (h*ehdr->e_shentsize));
- if ( is_xen_guest_section(shdr, shstrtab) )
- {
- dsi->__xen_guest_string =
- (const char *)image + shdr->sh_offset;
- break;
- }
- }
- }
-
- /* Check the contents of the Xen notes or guest string. */
- if ( dsi->__elfnote_section || dsi->__xen_guest_string )
- {
- const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER);
- const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS);
- const char *xen_version =
- xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION);
-
- if ( ( loader == NULL || strncmp(loader, "generic", 7) ) &&
- ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Will only load images built for the generic loader "
- "or Linux images");
- return -EINVAL;
- }
-
- if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Will only load images built for Xen v3.0");
- return -EINVAL;
- }
- }
- else
- {
-#if defined(__x86_64__) || defined(__i386__)
- xc_set_error(XC_INVALID_KERNEL,
- "Not a Xen-ELF image: "
- "No ELF notes or '__xen_guest' section found.");
- return -EINVAL;
-#endif
- }
-
- /*
- * A "bimodal" ELF note indicates the kernel will adjust to the current
- * paging mode, including handling extended cr3 syntax. If we have ELF
- * notes then PAE=yes implies that we must support the extended cr3 syntax.
- * Otherwise we need to find the [extended-cr3] syntax in the __xen_guest
- * string. We use strstr() to look for "bimodal" to allow guests to use
- * "yes,bimodal" or "no,bimodal" for compatibility reasons.
- */
-
- dsi->pae_kernel = PAEKERN_no;
- if ( dsi->__elfnote_section )
- {
- p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
- if ( p != NULL && strstr(p, "bimodal") != NULL )
- dsi->pae_kernel = PAEKERN_bimodal;
- else if ( p != NULL && strncmp(p, "yes", 3) == 0 )
- dsi->pae_kernel = PAEKERN_extended_cr3;
-
- }
- else
- {
- p = xen_guest_lookup(dsi, XEN_ELFNOTE_PAE_MODE);
- if ( p != NULL && strncmp(p, "yes", 3) == 0 )
- {
- dsi->pae_kernel = PAEKERN_yes;
- if ( !strncmp(p+3, "[extended-cr3]", 14) )
- dsi->pae_kernel = PAEKERN_extended_cr3;
- }
- }
-
- /* Initial guess for v_start is 0 if it is not explicitly defined. */
- dsi->v_start =
- xen_elfnote_numeric(dsi, XEN_ELFNOTE_VIRT_BASE, &virt_base_defined);
- if ( !virt_base_defined )
- dsi->v_start = 0;
-
- /*
- * If we are using the legacy __xen_guest section then elf_pa_off
- * defaults to v_start in order to maintain compatibility with
- * older hypervisors which set padd in the ELF header to
- * virt_base.
- *
- * If we are using the modern ELF notes interface then the default
- * is 0.
- */
- dsi->elf_paddr_offset = xen_elfnote_numeric(dsi, XEN_ELFNOTE_PADDR_OFFSET,
- &elf_pa_off_defined);
- if ( !elf_pa_off_defined )
- {
- if ( dsi->__elfnote_section )
- dsi->elf_paddr_offset = 0;
- else
- dsi->elf_paddr_offset = dsi->v_start;
- }
-
- if ( elf_pa_off_defined && !virt_base_defined )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "Neither ELF_PADDR_OFFSET nor VIRT_BASE found in ELF "
- " notes or __xen_guest section.");
- return -EINVAL;
- }
-
- for ( h = 0; h < ehdr->e_phnum; h++ )
- {
- phdr = (const Elf_Phdr *)(
- image + ehdr->e_phoff + (h*ehdr->e_phentsize));
- if ( !is_loadable_phdr(phdr) )
- continue;
- vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start;
- if ( (vaddr + phdr->p_memsz) < vaddr )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "ELF program header %d is too large.", h);
- return -EINVAL;
- }
-
- if ( vaddr < kernstart )
- kernstart = vaddr;
- if ( (vaddr + phdr->p_memsz) > kernend )
- kernend = vaddr + phdr->p_memsz;
- }
-
- dsi->v_kernentry = ehdr->e_entry;
-
- virt_entry =
- xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined);
- if ( virt_entry_defined )
- dsi->v_kernentry = virt_entry;
-
- if ( (kernstart > kernend) ||
- (dsi->v_kernentry < kernstart) ||
- (dsi->v_kernentry > kernend) ||
- (dsi->v_start > kernstart) )
- {
- xc_set_error(XC_INVALID_KERNEL,
- "ELF start or entries are out of bounds.");
- return -EINVAL;
- }
-
- p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB);
- if ( p != NULL && strncmp(p, "yes", 3) == 0 )
- dsi->load_symtab = 1;
-
- dsi->v_kernstart = kernstart;
- dsi->v_kernend = kernend;
- dsi->v_end = dsi->v_kernend;
-
- loadelfsymtab(image, 0, 0, NULL, dsi);
-
- return 0;
-}
-
-static int
-loadelfimage(
- const char *image, unsigned long elfsize, int xch, uint32_t dom,
- xen_pfn_t *parray, struct domain_setup_info *dsi)
-{
- const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image;
- const Elf_Phdr *phdr;
- int h;
-
- char *va;
- unsigned long pa, done, chunksz;
-
- for ( h = 0; h < ehdr->e_phnum; h++ )
- {
- phdr = (const Elf_Phdr *)(
- image + ehdr->e_phoff + (h*ehdr->e_phentsize));
- if ( !is_loadable_phdr(phdr) )
- continue;
-
- for ( done = 0; done < phdr->p_filesz; done += chunksz )
- {
- pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
- va = xc_map_foreign_range(
- xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
- if ( va == NULL )
- return -1;
- chunksz = phdr->p_filesz - done;
- if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
- chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
- memcpy(va + (pa & (PAGE_SIZE-1)),
- image + phdr->p_offset + done, chunksz);
- munmap(va, PAGE_SIZE);
- }
-
- for ( ; done < phdr->p_memsz; done += chunksz )
- {
- pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
- va = xc_map_foreign_range(
- xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
- if ( va == NULL )
- return -1;
- chunksz = phdr->p_memsz - done;
- if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
- chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
- memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
- munmap(va, PAGE_SIZE);
- }
- }
-
- loadelfsymtab(image, xch, dom, parray, dsi);
-
- return 0;
-}
-
-#define ELFROUND (ELFSIZE / 8)
-
-static int
-loadelfsymtab(
- const char *image, int xch, uint32_t dom, xen_pfn_t *parray,
- struct domain_setup_info *dsi)
-{
- const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image;
- Elf_Ehdr *sym_ehdr;
- Elf_Shdr *shdr;
- unsigned long maxva, symva;
- char *p;
- int h, i;
-
- if ( !dsi->load_symtab )
- return 0;
-
- p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
- ehdr->e_shnum * sizeof(Elf_Shdr));
- if (p == NULL)
- return 0;
-
- maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
- symva = maxva;
- maxva += sizeof(int);
- dsi->symtab_addr = maxva;
- dsi->symtab_len = 0;
- maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-
- shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
- memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
-
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- if ( shdr[h].sh_type == SHT_STRTAB )
- {
- /* Look for a strtab @i linked to symtab @h. */
- for ( i = 0; i < ehdr->e_shnum; i++ )
- if ( (shdr[i].sh_type == SHT_SYMTAB) &&
- (shdr[i].sh_link == h) )
- break;
- /* Skip symtab @h if we found no corresponding strtab @i. */
- if ( i == ehdr->e_shnum )
- {
- shdr[h].sh_offset = 0;
- continue;
- }
- }
-
- if ( (shdr[h].sh_type == SHT_STRTAB) ||
- (shdr[h].sh_type == SHT_SYMTAB) )
- {
- if ( parray != NULL )
- xc_map_memcpy(maxva, image + shdr[h].sh_offset,
- shdr[h].sh_size,
- xch, dom, parray, dsi->v_start);
-
- /* Mangled to be based on ELF header location. */
- shdr[h].sh_offset = maxva - dsi->symtab_addr;
-
- dsi->symtab_len += shdr[h].sh_size;
- maxva += shdr[h].sh_size;
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
- }
-
- shdr[h].sh_name = 0; /* Name is NULL. */
- }
-
- if ( dsi->symtab_len == 0 )
- {
- dsi->symtab_addr = 0;
- goto out;
- }
-
- if ( parray != NULL )
- {
- *(int *)p = maxva - dsi->symtab_addr;
- sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
- memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
- sym_ehdr->e_phoff = 0;
- sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
- sym_ehdr->e_phentsize = 0;
- sym_ehdr->e_phnum = 0;
- sym_ehdr->e_shstrndx = SHN_UNDEF;
-
- /* Copy total length, crafted ELF header and section header table */
- xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
- ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
- dsi->v_start);
- }
-
- dsi->symtab_len = maxva - dsi->symtab_addr;
- dsi->v_end = round_pgup(maxva);
-
- out:
- free(p);
-
- return 0;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Wed Feb 14 12:18:32 2007 -0800
+++ b/tools/libxc/xc_private.c Thu Feb 15 10:25:39 2007 +0000
@@ -377,26 +377,6 @@ int xc_clear_domain_page(int xc_handle,
return 0;
}
-void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size,
- int xch, uint32_t dom, xen_pfn_t *parray,
- unsigned long vstart)
-{
- char *va;
- unsigned long chunksz, done, pa;
-
- for ( done = 0; done < size; done += chunksz )
- {
- pa = dst + done - vstart;
- va = xc_map_foreign_range(
- xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
- chunksz = size - done;
- if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
- chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
- memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
- munmap(va, PAGE_SIZE);
- }
-}
-
int xc_domctl(int xc_handle, struct xen_domctl *domctl)
{
return do_domctl(xc_handle, domctl);
diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h Wed Feb 14 12:18:32 2007 -0800
+++ b/tools/libxc/xg_private.h Thu Feb 15 10:25:39 2007 +0000
@@ -139,92 +139,15 @@ typedef l4_pgentry_64_t l4_pgentry_t;
#define PAGE_SIZE_IA64 (1UL << PAGE_SHIFT_IA64)
#define PAGE_MASK_IA64 (~(PAGE_SIZE_IA64-1))
-struct domain_setup_info
-{
- uint64_t v_start;
- uint64_t v_end;
- uint64_t v_kernstart;
- uint64_t v_kernend;
- uint64_t v_kernentry;
-
- uint64_t elf_paddr_offset;
-
#define PAEKERN_no 0
#define PAEKERN_yes 1
#define PAEKERN_extended_cr3 2
#define PAEKERN_bimodal 3
- unsigned int pae_kernel;
-
- unsigned int load_symtab;
- unsigned long symtab_addr;
- unsigned long symtab_len;
-
- /*
- * Only one of __elfnote_* or __xen_guest_string will be
- * non-NULL.
- *
- * You should use the xen_elfnote_* accessors below in order to
- * pickup the correct one and retain backwards compatibility.
- */
- const void *__elfnote_section, *__elfnote_section_end;
- const char *__xen_guest_string;
-};
-
-typedef int (*parseimagefunc)(const char *image, unsigned long image_size,
- struct domain_setup_info *dsi);
-typedef int (*loadimagefunc)(const char *image, unsigned long image_size,
- int xch,
- uint32_t dom, xen_pfn_t *parray,
- struct domain_setup_info *dsi);
-
-/*
- * If an ELF note of the given type is found then the value contained
- * in the note is returned and *defined is set to non-zero. If no such
- * note is found then *defined is set to 0 and 0 is returned.
- */
-extern unsigned long long xen_elfnote_numeric(const struct domain_setup_info
*dsi,
- int type, int *defined);
-
-/*
- * If an ELF note of the given type is found then the string contained
- * in the value is returned, otherwise NULL is returned.
- */
-extern const char * xen_elfnote_string(const struct domain_setup_info *dsi,
- int type);
-
-struct load_funcs
-{
- parseimagefunc parseimage;
- loadimagefunc loadimage;
-};
-
-#define mfn_mapper_queue_size 128
-
-typedef struct mfn_mapper {
- int xc_handle;
- int size;
- int prot;
- int error;
- int max_queue_size;
- void * addr;
- privcmd_mmap_t ioctl;
-
-} mfn_mapper_t;
int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
unsigned long dst_pfn, const char *src_page);
-void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size,
- int xch, uint32_t dom, xen_pfn_t *parray,
- unsigned long vstart);
-
int pin_table(int xc_handle, unsigned int type, unsigned long mfn,
domid_t dom);
-/* image loading */
-int probe_elf(const char *image, unsigned long image_size,
- struct load_funcs *funcs);
-int probe_bin(const char *image, unsigned long image_size,
- struct load_funcs *funcs);
-
#endif /* XG_PRIVATE_H */
diff -r 82f66bc01da2 -r 0d488e53446a xen/common/elf.c
--- a/xen/common/elf.c Wed Feb 14 12:18:32 2007 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,520 +0,0 @@
-/******************************************************************************
- * elf.c
- *
- * Generic Elf-loading routines.
- */
-
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <xen/elf.h>
-#include <xen/sched.h>
-#include <xen/errno.h>
-#include <xen/inttypes.h>
-
-#include <public/elfnote.h>
-
-static void loadelfsymtab(struct domain_setup_info *dsi, int doload);
-static inline int is_loadable_phdr(const Elf_Phdr *phdr)
-{
- return ((phdr->p_type == PT_LOAD) &&
- ((phdr->p_flags & (PF_W|PF_X)) != 0));
-}
-
-/*
- * Fallback for kernels containing only the legacy __xen_guest string
- * and no ELF notes.
- */
-static int is_xen_guest_section(const Elf_Shdr *shdr, const char *shstrtab)
-{
- return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0;
-}
-
-static const char *xen_guest_lookup(struct domain_setup_info *dsi, int type)
-{
- const char *xenguest_fallbacks[] = {
- [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=",
- [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=",
- [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=",
- [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=",
- [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=",
- [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=",
- [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=",
- [XEN_ELFNOTE_LOADER] = "LOADER=",
- [XEN_ELFNOTE_PAE_MODE] = "PAE=",
- [XEN_ELFNOTE_FEATURES] = "FEATURES=",
- [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=",
- };
- const char *fallback;
- const char *p;
-
- if ( !dsi->__xen_guest_string )
- return NULL;
-
- if ( type > sizeof(xenguest_fallbacks) )
- return NULL;
-
- if ( (fallback = xenguest_fallbacks[type]) == NULL )
- return NULL;
-
- if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL )
- return NULL;
-
- return p + strlen(fallback);
-}
-
-static const char *xen_guest_string(struct domain_setup_info *dsi, int type)
-{
- const char *p = xen_guest_lookup(dsi, type);
-
- /*
- * We special case this since the __xen_guest_section treats the
- * mere precense of the BSD_SYMTAB string as true or false.
- */
- if ( type == XEN_ELFNOTE_BSD_SYMTAB )
- return p ? "yes" : "no";
-
- return p;
-}
-
-static unsigned long long xen_guest_numeric(struct domain_setup_info *dsi,
- int type, int *defined)
-{
- const char *p = xen_guest_lookup(dsi, type);
- unsigned long long value;
-
- if ( p == NULL )
- return 0;
-
- value = simple_strtoull(p, NULL, 0);
-
- /* We special case this since __xen_guest_section contains a PFN
- * for this field not a virtual address.
- */
- if (type == XEN_ELFNOTE_HYPERCALL_PAGE)
- value = dsi->v_start + (value<<PAGE_SHIFT);
-
- *defined = 1;
- return value;
-}
-
-
-static int is_xen_elfnote_section(const char *image, const Elf_Shdr *shdr)
-{
- const Elf_Note *note;
-
- if ( shdr->sh_type != SHT_NOTE )
- return 0;
-
- for ( note = (const Elf_Note *)(image + shdr->sh_offset);
- note < (const Elf_Note *)(image + shdr->sh_offset + shdr->sh_size);
- note = ELFNOTE_NEXT(note) )
- {
- if ( !strncmp(ELFNOTE_NAME(note), "Xen", 4) )
- return 1;
- }
-
- return 0;
-}
-
-static const Elf_Note *xen_elfnote_lookup(
- struct domain_setup_info *dsi, int type)
-{
- const Elf_Note *note;
-
- if ( !dsi->__elfnote_section )
- return NULL;
-
- for ( note = (const Elf_Note *)dsi->__elfnote_section;
- note < (const Elf_Note *)dsi->__elfnote_section_end;
- note = ELFNOTE_NEXT(note) )
- {
- if ( strncmp(ELFNOTE_NAME(note), "Xen", 4) )
- continue;
-
- if ( note->type == type )
- return note;
- }
-
- return NULL;
-}
-
-const char *xen_elfnote_string(struct domain_setup_info *dsi, int type)
-{
- const Elf_Note *note;
-
- if ( !dsi->__elfnote_section )
- return xen_guest_string(dsi, type);
-
- note = xen_elfnote_lookup(dsi, type);
- if ( note == NULL )
- return NULL;
-
- return (const char *)ELFNOTE_DESC(note);
-}
-
-unsigned long long xen_elfnote_numeric(struct domain_setup_info *dsi,
- int type, int *defined)
-{
- const Elf_Note *note;
-
- *defined = 0;
-
- if ( !dsi->__elfnote_section )
- return xen_guest_numeric(dsi, type, defined);
-
- note = xen_elfnote_lookup(dsi, type);
- if ( note == NULL )
- {
- return 0;
- }
-
- switch ( note->descsz )
- {
- case 4:
- *defined = 1;
- return *(const uint32_t*)ELFNOTE_DESC(note);
- case 8:
- *defined = 1;
- return *(const uint64_t*)ELFNOTE_DESC(note);
- default:
- printk("ERROR: unknown data size %#x for numeric type note %#x\n",
- note->descsz, type);
- return 0;
- }
-}
-
-int parseelfimage(struct domain_setup_info *dsi)
-{
- const Elf_Ehdr *ehdr = (const Elf_Ehdr *)dsi->image_addr;
- const Elf_Phdr *phdr;
- const Elf_Shdr *shdr;
- Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_entry;
- const char *shstrtab, *p;
- const char *image = (char *)dsi->image_addr;
- const unsigned long image_len = dsi->image_len;
- int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined;
-
- if ( !elf_sanity_check(ehdr) )
- return -ENOSYS;
-
- if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len )
- {
- printk("ELF program headers extend beyond end of image.\n");
- return -EINVAL;
- }
-
- if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len )
- {
- printk("ELF section headers extend beyond end of image.\n");
- return -EINVAL;
- }
-
- dsi->__elfnote_section = NULL;
- dsi->__xen_guest_string = NULL;
-
- /* Look for .notes segment containing at least one Xen note */
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- shdr = (const Elf_Shdr *)(
- image + ehdr->e_shoff + (h*ehdr->e_shentsize));
- if ( !is_xen_elfnote_section(image, shdr) )
- continue;
- dsi->__elfnote_section = (const char *)image + shdr->sh_offset;
- dsi->__elfnote_section_end =
- (const char *)image + shdr->sh_offset + shdr->sh_size;
- break;
- }
-
- /* Fall back to looking for the special '__xen_guest' section. */
- if ( dsi->__elfnote_section == NULL )
- {
- /* Find the section-header strings table. */
- if ( ehdr->e_shstrndx == SHN_UNDEF )
- {
- printk("ELF image has no section-header strings table.\n");
- return -EINVAL;
- }
- shdr = (const Elf_Shdr *)(image + ehdr->e_shoff +
- (ehdr->e_shstrndx*ehdr->e_shentsize));
- shstrtab = image + shdr->sh_offset;
-
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- shdr = (const Elf_Shdr *)(
- image + ehdr->e_shoff + (h*ehdr->e_shentsize));
- if ( is_xen_guest_section(shdr, shstrtab) )
- {
- dsi->__xen_guest_string =
- (const char *)image + shdr->sh_offset;
- break;
- }
- }
- }
-
- /* Check the contents of the Xen notes or guest string. */
- if ( dsi->__elfnote_section || dsi->__xen_guest_string )
- {
- const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER);
- const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS);
- const char *xen_version =
- xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION);
-
- if ( ( loader == NULL || strncmp(loader, "generic", 7) ) &&
- ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) )
- {
- printk("ERROR: Will only load images built for the generic "
- "loader or Linux images");
- return -EINVAL;
- }
-
- if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) )
- {
- printk("ERROR: Xen will only load images built for Xen v3.0\n");
- }
- }
- else
- {
-#if defined(__x86_64__) || defined(__i386__)
- printk("ERROR: Not a Xen-ELF image: "
- "No ELF notes or '__xen_guest' section found.\n");
- return -EINVAL;
-#endif
- }
-
- /*
- * A "bimodal" ELF note indicates the kernel will adjust to the
- * current paging mode, including handling extended cr3 syntax.
- * If we have ELF notes then PAE=yes implies that we must support
- * the extended cr3 syntax. Otherwise we need to find the
- * [extended-cr3] syntax in the __xen_guest string.
- */
- dsi->pae_kernel = PAEKERN_no;
- if ( dsi->__elfnote_section )
- {
- p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
- if ( p != NULL && strstr(p, "bimodal") != NULL )
- dsi->pae_kernel = PAEKERN_bimodal;
- else if ( p != NULL && strncmp(p, "yes", 3) == 0 )
- dsi->pae_kernel = PAEKERN_extended_cr3;
- }
- else
- {
- p = xen_guest_lookup(dsi, XEN_ELFNOTE_PAE_MODE);
- if ( p != NULL && strncmp(p, "yes", 3) == 0 )
- {
- dsi->pae_kernel = PAEKERN_yes;
- if ( !strncmp(p+3, "[extended-cr3]", 14) )
- dsi->pae_kernel = PAEKERN_extended_cr3;
- }
- }
-
- /* Initial guess for v_start is 0 if it is not explicitly defined. */
- dsi->v_start =
- xen_elfnote_numeric(dsi, XEN_ELFNOTE_VIRT_BASE, &virt_base_defined);
- if ( !virt_base_defined )
- dsi->v_start = 0;
-
- /*
- * If we are using the legacy __xen_guest section then elf_pa_off
- * defaults to v_start in order to maintain compatibility with
- * older hypervisors which set padd in the ELF header to
- * virt_base.
- *
- * If we are using the modern ELF notes interface then the default
- * is 0.
- */
- dsi->elf_paddr_offset = xen_elfnote_numeric(dsi, XEN_ELFNOTE_PADDR_OFFSET,
- &elf_pa_off_defined);
- if ( !elf_pa_off_defined )
- {
- if ( dsi->__elfnote_section )
- dsi->elf_paddr_offset = 0;
- else
- dsi->elf_paddr_offset = dsi->v_start;
- }
-
- if ( elf_pa_off_defined && !virt_base_defined )
- {
- printk("ERROR: Neither ELF_PADDR_OFFSET nor VIRT_BASE found in"
- " Xen ELF notes.\n");
- return -EINVAL;
- }
-
- for ( h = 0; h < ehdr->e_phnum; h++ )
- {
- phdr = (const Elf_Phdr *)(
- image + ehdr->e_phoff + (h*ehdr->e_phentsize));
- if ( !is_loadable_phdr(phdr) )
- continue;
- vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start;
- if ( (vaddr + phdr->p_memsz) < vaddr )
- {
- printk("ERROR: ELF program header %d is too large.\n", h);
- return -EINVAL;
- }
-
- if ( vaddr < kernstart )
- kernstart = vaddr;
- if ( (vaddr + phdr->p_memsz) > kernend )
- kernend = vaddr + phdr->p_memsz;
- }
-
- dsi->v_kernentry = ehdr->e_entry;
-
- virt_entry =
- xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined);
- if ( virt_entry_defined )
- dsi->v_kernentry = virt_entry;
-
- if ( (kernstart > kernend) ||
- (dsi->v_kernentry < kernstart) ||
- (dsi->v_kernentry > kernend) ||
- (dsi->v_start > kernstart) )
- {
- printk("ERROR: ELF start or entries are out of bounds.\n");
- return -EINVAL;
- }
-
- p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB);
- if ( p != NULL && strncmp(p, "yes", 3) == 0 )
- dsi->load_symtab = 1;
-
- dsi->v_kernstart = kernstart;
- dsi->v_kernend = kernend;
- dsi->v_end = dsi->v_kernend;
-
- loadelfsymtab(dsi, 0);
-
- return 0;
-}
-
-int loadelfimage(struct domain_setup_info *dsi)
-{
- char *image = (char *)dsi->image_addr;
- Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
- Elf_Phdr *phdr;
- unsigned long vaddr;
- int h;
-
- for ( h = 0; h < ehdr->e_phnum; h++ )
- {
- phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
- if ( !is_loadable_phdr(phdr) )
- continue;
- vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start;
- if ( phdr->p_filesz != 0 )
- memcpy((char *)vaddr, image + phdr->p_offset, phdr->p_filesz);
- if ( phdr->p_memsz > phdr->p_filesz )
- memset((char *)vaddr + phdr->p_filesz, 0,
- phdr->p_memsz - phdr->p_filesz);
- }
-
- loadelfsymtab(dsi, 1);
-
- return 0;
-}
-
-#define ELFROUND (ELFSIZE / 8)
-
-static void loadelfsymtab(struct domain_setup_info *dsi, int doload)
-{
- Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr;
- Elf_Shdr *shdr;
- unsigned long maxva, symva;
- char *p, *image = (char *)dsi->image_addr;
- int h, i;
-
- if ( !dsi->load_symtab )
- return;
-
- maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
- symva = maxva;
- maxva += sizeof(int);
- dsi->symtab_addr = maxva;
- dsi->symtab_len = 0;
- maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
- if ( doload )
- {
- p = (void *)symva;
- shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
- memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr));
- }
- else
- {
- p = NULL;
- shdr = (Elf_Shdr *)(image + ehdr->e_shoff);
- }
-
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- if ( shdr[h].sh_type == SHT_STRTAB )
- {
- /* Look for a strtab @i linked to symtab @h. */
- for ( i = 0; i < ehdr->e_shnum; i++ )
- if ( (shdr[i].sh_type == SHT_SYMTAB) &&
- (shdr[i].sh_link == h) )
- break;
- /* Skip symtab @h if we found no corresponding strtab @i. */
- if ( i == ehdr->e_shnum )
- {
- if (doload) {
- shdr[h].sh_offset = 0;
- }
- continue;
- }
- }
-
- if ( (shdr[h].sh_type == SHT_STRTAB) ||
- (shdr[h].sh_type == SHT_SYMTAB) )
- {
- if (doload) {
- memcpy((void *)maxva, image + shdr[h].sh_offset,
- shdr[h].sh_size);
-
- /* Mangled to be based on ELF header location. */
- shdr[h].sh_offset = maxva - dsi->symtab_addr;
-
- }
- dsi->symtab_len += shdr[h].sh_size;
- maxva += shdr[h].sh_size;
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
- }
-
- if ( doload )
- shdr[h].sh_name = 0; /* Name is NULL. */
- }
-
- if ( dsi->symtab_len == 0 )
- {
- dsi->symtab_addr = 0;
- return;
- }
-
- if ( doload )
- {
- *(int *)p = maxva - dsi->symtab_addr;
- sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
- memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
- sym_ehdr->e_phoff = 0;
- sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
- sym_ehdr->e_phentsize = 0;
- sym_ehdr->e_phnum = 0;
- sym_ehdr->e_shstrndx = SHN_UNDEF;
- }
-
- dsi->symtab_len = maxva - dsi->symtab_addr;
- dsi->v_end = maxva;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|