ia64/xen-unstable

changeset 13634:a63d1af01b3d

libelf: use for hvm builder.

This patch switches over the hvm domain builder to libelf
(for loading hvmloader).

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
---
tools/libxc/xc_hvm_build.c | 220 +++++++++++++--------------------------------
1 file changed, 65 insertions(+), 155 deletions(-)
author Emmanuel Ackaouy <ack@xensource.com>
date Thu Jan 25 22:16:52 2007 +0000 (2007-01-25)
parents a754192ffce6
children 4aa6044ab967
files tools/libxc/xc_hvm_build.c
line diff
     1.1 --- a/tools/libxc/xc_hvm_build.c	Thu Jan 25 22:16:52 2007 +0000
     1.2 +++ b/tools/libxc/xc_hvm_build.c	Thu Jan 25 22:16:52 2007 +0000
     1.3 @@ -2,29 +2,22 @@
     1.4   * xc_hvm_build.c
     1.5   */
     1.6  
     1.7 -#define ELFSIZE 32
     1.8  #include <stddef.h>
     1.9  #include <inttypes.h>
    1.10 -#include "xg_private.h"
    1.11 -#include "xc_private.h"
    1.12 -#include "xc_elf.h"
    1.13  #include <stdlib.h>
    1.14  #include <unistd.h>
    1.15  #include <zlib.h>
    1.16 +
    1.17 +#include "xg_private.h"
    1.18 +#include "xc_private.h"
    1.19 +
    1.20  #include <xen/hvm/hvm_info_table.h>
    1.21  #include <xen/hvm/params.h>
    1.22  #include <xen/hvm/e820.h>
    1.23  
    1.24 -#define SCRATCH_PFN 0xFFFFF
    1.25 +#include <xen/libelf.h>
    1.26  
    1.27 -#define HVM_LOADER_ENTR_ADDR  0x00100000
    1.28 -static int
    1.29 -parseelfimage(
    1.30 -    char *elfbase, unsigned long elfsize, struct domain_setup_info *dsi);
    1.31 -static int
    1.32 -loadelfimage(
    1.33 -    char *elfbase, int xch, uint32_t dom, unsigned long *parray,
    1.34 -    struct domain_setup_info *dsi);
    1.35 +#define SCRATCH_PFN 0xFFFFF
    1.36  
    1.37  int xc_set_hvm_param(
    1.38      int handle, domid_t dom, int param, unsigned long value)
    1.39 @@ -144,6 +137,48 @@ static void build_e820map(void *e820_pag
    1.40      *(((unsigned char *)e820_page) + E820_MAP_NR_OFFSET) = nr_map;
    1.41  }
    1.42  
    1.43 +static int
    1.44 +loadelfimage(struct elf_binary *elf, int xch, uint32_t dom, unsigned long *parray)
    1.45 +{
    1.46 +    privcmd_mmap_entry_t *entries = NULL;
    1.47 +    int pages = (elf->pend - elf->pstart + PAGE_SIZE - 1) >> PAGE_SHIFT;
    1.48 +    int i, rc = -1;
    1.49 +
    1.50 +    /* map hvmloader address space */
    1.51 +    entries = malloc(pages * sizeof(privcmd_mmap_entry_t));
    1.52 +    if (NULL == entries)
    1.53 +        goto err;
    1.54 +    elf->dest = mmap(NULL, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE,
    1.55 +                     MAP_SHARED, xch, 0);
    1.56 +    if (MAP_FAILED == elf->dest)
    1.57 +        goto err;
    1.58 +
    1.59 +    for (i = 0; i < pages; i++)
    1.60 +    {
    1.61 +        entries[i].va = (uintptr_t)elf->dest + (i << PAGE_SHIFT);
    1.62 +        entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i];
    1.63 +        entries[i].npages = 1;
    1.64 +    }
    1.65 +    rc = xc_map_foreign_ranges(xch, dom, entries, pages);
    1.66 +    if (rc < 0)
    1.67 +        goto err;
    1.68 +
    1.69 +    /* load hvmloader */
    1.70 +    elf_load_binary(elf);
    1.71 +    rc = 0;
    1.72 +
    1.73 + err:
    1.74 +    /* cleanup */
    1.75 +    if (elf->dest) {
    1.76 +        munmap(elf->dest, pages << PAGE_SHIFT);
    1.77 +        elf->dest = NULL;
    1.78 +    }
    1.79 +    if (entries)
    1.80 +        free(entries);
    1.81 +
    1.82 +    return rc;
    1.83 +}
    1.84 +
    1.85  static int setup_guest(int xc_handle,
    1.86                         uint32_t dom, int memsize,
    1.87                         char *image, unsigned long image_size,
    1.88 @@ -155,35 +190,35 @@ static int setup_guest(int xc_handle,
    1.89      struct xen_add_to_physmap xatp;
    1.90      struct shared_info *shared_info;
    1.91      void *e820_page;
    1.92 -    struct domain_setup_info dsi;
    1.93 -    uint64_t v_end;
    1.94 +    struct elf_binary elf;
    1.95 +    uint64_t v_start, v_end;
    1.96      int rc;
    1.97  
    1.98 -    memset(&dsi, 0, sizeof(struct domain_setup_info));
    1.99 +    if (0 != elf_init(&elf, image, image_size))
   1.100 +        goto error_out;
   1.101 +    elf_parse_binary(&elf);
   1.102 +    v_start = 0;
   1.103 +    v_end = (unsigned long long)memsize << 20;
   1.104  
   1.105 -    if ( (parseelfimage(image, image_size, &dsi)) != 0 )
   1.106 -        goto error_out;
   1.107 -
   1.108 -    if ( (dsi.v_kernstart & (PAGE_SIZE - 1)) != 0 )
   1.109 +    if ( (elf.pstart & (PAGE_SIZE - 1)) != 0 )
   1.110      {
   1.111          PERROR("Guest OS must load to a page boundary.\n");
   1.112          goto error_out;
   1.113      }
   1.114  
   1.115 -    v_end = (unsigned long long)memsize << 20;
   1.116 -
   1.117      IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
   1.118 -           "  Loaded HVM loader:    %016"PRIx64"->%016"PRIx64"\n"
   1.119 -           "  TOTAL:                %016"PRIx64"->%016"PRIx64"\n",
   1.120 -           dsi.v_kernstart, dsi.v_kernend,
   1.121 -           dsi.v_start, v_end);
   1.122 -    IPRINTF("  ENTRY ADDRESS:        %016"PRIx64"\n", dsi.v_kernentry);
   1.123 +            "  Loaded HVM loader:    %016"PRIx64"->%016"PRIx64"\n"
   1.124 +            "  TOTAL:                %016"PRIx64"->%016"PRIx64"\n"
   1.125 +            "  ENTRY ADDRESS:        %016"PRIx64"\n",
   1.126 +            elf.pstart, elf.pend,
   1.127 +            v_start, v_end,
   1.128 +            elf_uval(&elf, elf.ehdr, e_entry));
   1.129  
   1.130 -    if ( (v_end - dsi.v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) )
   1.131 +    if ( (v_end - v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) )
   1.132      {
   1.133          PERROR("Initial guest OS requires too much space: "
   1.134                 "(%lluMB is greater than %lluMB limit)\n",
   1.135 -               (unsigned long long)(v_end - dsi.v_start) >> 20,
   1.136 +               (unsigned long long)(v_end - v_start) >> 20,
   1.137                 ((unsigned long long)nr_pages << PAGE_SHIFT) >> 20);
   1.138          goto error_out;
   1.139      }
   1.140 @@ -212,7 +247,7 @@ static int setup_guest(int xc_handle,
   1.141          goto error_out;
   1.142      }
   1.143  
   1.144 -    loadelfimage(image, xc_handle, dom, page_array, &dsi);
   1.145 +    loadelfimage(&elf, xc_handle, dom, page_array);
   1.146  
   1.147      if ( (e820_page = xc_map_foreign_range(
   1.148                xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
   1.149 @@ -255,7 +290,7 @@ static int setup_guest(int xc_handle,
   1.150  
   1.151      free(page_array);
   1.152  
   1.153 -    ctxt->user_regs.eip = dsi.v_kernentry;
   1.154 +    ctxt->user_regs.eip = elf_uval(&elf, elf.ehdr, e_entry);
   1.155  
   1.156      return 0;
   1.157  
   1.158 @@ -314,131 +349,6 @@ static inline int is_loadable_phdr(Elf32
   1.159              ((phdr->p_flags & (PF_W|PF_X)) != 0));
   1.160  }
   1.161  
   1.162 -static int parseelfimage(char *elfbase,
   1.163 -                         unsigned long elfsize,
   1.164 -                         struct domain_setup_info *dsi)
   1.165 -{
   1.166 -    Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfbase;
   1.167 -    Elf32_Phdr *phdr;
   1.168 -    Elf32_Shdr *shdr;
   1.169 -    unsigned long kernstart = ~0UL, kernend=0UL;
   1.170 -    char *shstrtab;
   1.171 -    int h;
   1.172 -
   1.173 -    if ( !IS_ELF(*ehdr) )
   1.174 -    {
   1.175 -        xc_set_error(XC_INVALID_KERNEL,
   1.176 -                     "Kernel image does not have an ELF header.");
   1.177 -        return -EINVAL;
   1.178 -    }
   1.179 -
   1.180 -    if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
   1.181 -    {
   1.182 -        xc_set_error(XC_INVALID_KERNEL,
   1.183 -                     "ELF program headers extend beyond end of image.");
   1.184 -        return -EINVAL;
   1.185 -    }
   1.186 -
   1.187 -    if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
   1.188 -    {
   1.189 -        xc_set_error(XC_INVALID_KERNEL,
   1.190 -                     "ELF section headers extend beyond end of image.");
   1.191 -        return -EINVAL;
   1.192 -    }
   1.193 -
   1.194 -    /* Find the section-header strings table. */
   1.195 -    if ( ehdr->e_shstrndx == SHN_UNDEF )
   1.196 -    {
   1.197 -        xc_set_error(XC_INVALID_KERNEL,
   1.198 -                     "ELF image has no section-header strings table (shstrtab).");
   1.199 -        return -EINVAL;
   1.200 -    }
   1.201 -    shdr = (Elf32_Shdr *)(elfbase + ehdr->e_shoff +
   1.202 -                          (ehdr->e_shstrndx*ehdr->e_shentsize));
   1.203 -    shstrtab = elfbase + shdr->sh_offset;
   1.204 -
   1.205 -    for ( h = 0; h < ehdr->e_phnum; h++ )
   1.206 -    {
   1.207 -        phdr = (Elf32_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
   1.208 -        if ( !is_loadable_phdr(phdr) )
   1.209 -            continue;
   1.210 -        if ( phdr->p_paddr < kernstart )
   1.211 -            kernstart = phdr->p_paddr;
   1.212 -        if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
   1.213 -            kernend = phdr->p_paddr + phdr->p_memsz;
   1.214 -    }
   1.215 -
   1.216 -    if ( (kernstart > kernend) ||
   1.217 -         (ehdr->e_entry < kernstart) ||
   1.218 -         (ehdr->e_entry > kernend) )
   1.219 -    {
   1.220 -        xc_set_error(XC_INVALID_KERNEL,
   1.221 -                     "Malformed ELF image.");
   1.222 -        return -EINVAL;
   1.223 -    }
   1.224 -
   1.225 -    dsi->v_start = 0x00000000;
   1.226 -
   1.227 -    dsi->v_kernstart = kernstart;
   1.228 -    dsi->v_kernend   = kernend;
   1.229 -    dsi->v_kernentry = HVM_LOADER_ENTR_ADDR;
   1.230 -
   1.231 -    dsi->v_end       = dsi->v_kernend;
   1.232 -
   1.233 -    return 0;
   1.234 -}
   1.235 -
   1.236 -static int
   1.237 -loadelfimage(
   1.238 -    char *elfbase, int xch, uint32_t dom, unsigned long *parray,
   1.239 -    struct domain_setup_info *dsi)
   1.240 -{
   1.241 -    Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfbase;
   1.242 -    Elf32_Phdr *phdr;
   1.243 -    int h;
   1.244 -
   1.245 -    char         *va;
   1.246 -    unsigned long pa, done, chunksz;
   1.247 -
   1.248 -    for ( h = 0; h < ehdr->e_phnum; h++ )
   1.249 -    {
   1.250 -        phdr = (Elf32_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
   1.251 -        if ( !is_loadable_phdr(phdr) )
   1.252 -            continue;
   1.253 -
   1.254 -        for ( done = 0; done < phdr->p_filesz; done += chunksz )
   1.255 -        {
   1.256 -            pa = (phdr->p_paddr + done) - dsi->v_start;
   1.257 -            if ((va = xc_map_foreign_range(
   1.258 -                xch, dom, PAGE_SIZE, PROT_WRITE,
   1.259 -                parray[pa >> PAGE_SHIFT])) == 0)
   1.260 -                return -1;
   1.261 -            chunksz = phdr->p_filesz - done;
   1.262 -            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
   1.263 -                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
   1.264 -            memcpy(va + (pa & (PAGE_SIZE-1)),
   1.265 -                   elfbase + phdr->p_offset + done, chunksz);
   1.266 -            munmap(va, PAGE_SIZE);
   1.267 -        }
   1.268 -
   1.269 -        for ( ; done < phdr->p_memsz; done += chunksz )
   1.270 -        {
   1.271 -            pa = (phdr->p_paddr + done) - dsi->v_start;
   1.272 -            if ((va = xc_map_foreign_range(
   1.273 -                xch, dom, PAGE_SIZE, PROT_WRITE,
   1.274 -                parray[pa >> PAGE_SHIFT])) == 0)
   1.275 -                return -1;
   1.276 -            chunksz = phdr->p_memsz - done;
   1.277 -            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
   1.278 -                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
   1.279 -            memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
   1.280 -            munmap(va, PAGE_SIZE);
   1.281 -        }
   1.282 -    }
   1.283 -
   1.284 -    return 0;
   1.285 -}
   1.286 -
   1.287  /* xc_hvm_build
   1.288   *
   1.289   * Create a domain for a virtualized Linux, using files/filenames