source: trunk/packages/xen-3.1/xen-3.1/tools/libxc/xc_dom_core.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 22.0 KB
Line 
1/*
2 * Xen domain builder -- core bits.
3 *
4 * The core code goes here:
5 *   - allocate and release domain structs.
6 *   - memory management functions.
7 *   - misc helper functions.
8 *
9 * This code is licenced under the GPL.
10 * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
11 *
12 */
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <stdarg.h>
17#include <inttypes.h>
18#include <zlib.h>
19
20#include "xg_private.h"
21#include "xc_dom.h"
22
23/* ------------------------------------------------------------------------ */
24/* debugging                                                                */
25
26FILE *xc_dom_logfile = NULL;
27
28void xc_dom_loginit(void)
29{
30    if ( xc_dom_logfile )
31        return;
32    xc_dom_logfile = fopen("/var/log/xen/domain-builder-ng.log", "a");
33    setvbuf(xc_dom_logfile, NULL, _IONBF, 0);
34    xc_dom_printf("### ----- xc domain builder logfile opened -----\n");
35}
36
37int xc_dom_printf(const char *fmt, ...)
38{
39    va_list args;
40    char buf[1024];
41    int rc;
42
43    if ( !xc_dom_logfile )
44        return 0;
45
46    va_start(args, fmt);
47    rc = vsnprintf(buf, sizeof(buf), fmt, args);
48    va_end(args);
49    rc = fwrite(buf, rc, 1, xc_dom_logfile);
50
51    return rc;
52}
53
54int xc_dom_panic_func(const char *file, int line, xc_error_code err,
55                      const char *fmt, ...)
56{
57    va_list args;
58    FILE *fp = stderr;
59    int rc = 0;
60    char pos[256];
61    char msg[XC_MAX_ERROR_MSG_LEN];
62
63    if ( xc_dom_logfile )
64        fp = xc_dom_logfile;
65
66    snprintf(pos, sizeof(pos), "%s:%d: panic: ", file, line);
67    va_start(args, fmt);
68    vsnprintf(msg, sizeof(msg), fmt, args);
69    va_end(args);
70    xc_set_error(err, "%s", msg);
71    rc = fprintf(fp, "%s%s", pos, msg);
72    return rc;
73}
74
75static void print_mem(const char *name, size_t mem)
76{
77    if ( mem > (32 * 1024 * 1024) )
78        xc_dom_printf("%-24s : %zd MB\n", name, mem / (1024 * 1024));
79    else if ( mem > (32 * 1024) )
80        xc_dom_printf("%-24s : %zd kB\n", name, mem / 1024);
81    else
82        xc_dom_printf("%-24s : %zd bytes\n", name, mem);
83}
84
85void xc_dom_log_memory_footprint(struct xc_dom_image *dom)
86{
87    xc_dom_printf("domain builder memory footprint\n");
88    xc_dom_printf("   allocated\n");
89    print_mem("      malloc", dom->alloc_malloc);
90    print_mem("      anon mmap", dom->alloc_mem_map);
91    xc_dom_printf("   mapped\n");
92    print_mem("      file mmap", dom->alloc_file_map);
93    print_mem("      domU mmap", dom->alloc_domU_map);
94}
95
96/* ------------------------------------------------------------------------ */
97/* simple memory pool                                                       */
98
99void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
100{
101    struct xc_dom_mem *block;
102
103    block = malloc(sizeof(*block) + size);
104    if ( block == NULL )
105        return NULL;
106    memset(block, 0, sizeof(*block) + size);
107    block->next = dom->memblocks;
108    dom->memblocks = block;
109    dom->alloc_malloc += sizeof(*block) + size;
110    if ( size > (100 * 1024) )
111        print_mem(__FUNCTION__, size);
112    return block->memory;
113}
114
115void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
116{
117    struct xc_dom_mem *block;
118
119    block = malloc(sizeof(*block));
120    if ( block == NULL )
121        return NULL;
122    memset(block, 0, sizeof(*block));
123    block->mmap_len = size;
124    block->mmap_ptr = mmap(NULL, block->mmap_len,
125                           PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
126                           -1, 0);
127    if ( block->mmap_ptr == MAP_FAILED )
128    {
129        free(block);
130        return NULL;
131    }
132    block->next = dom->memblocks;
133    dom->memblocks = block;
134    dom->alloc_malloc += sizeof(*block);
135    dom->alloc_mem_map += block->mmap_len;
136    if ( size > (100 * 1024) )
137        print_mem(__FUNCTION__, size);
138    return block->mmap_ptr;
139}
140
141void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
142                            const char *filename, size_t * size)
143{
144    struct xc_dom_mem *block = NULL;
145    int fd = -1;
146
147    fd = open(filename, O_RDONLY);
148    if ( fd == -1 )
149        goto err;
150
151    lseek(fd, 0, SEEK_SET);
152    *size = lseek(fd, 0, SEEK_END);
153
154    block = malloc(sizeof(*block));
155    if ( block == NULL )
156        goto err;
157    memset(block, 0, sizeof(*block));
158    block->mmap_len = *size;
159    block->mmap_ptr = mmap(NULL, block->mmap_len, PROT_READ,
160                           MAP_SHARED, fd, 0);
161    if ( block->mmap_ptr == MAP_FAILED )
162        goto err;
163    block->next = dom->memblocks;
164    dom->memblocks = block;
165    dom->alloc_malloc += sizeof(*block);
166    dom->alloc_file_map += block->mmap_len;
167    close(fd);
168    if ( *size > (100 * 1024) )
169        print_mem(__FUNCTION__, *size);
170    return block->mmap_ptr;
171
172 err:
173    if ( fd != -1 )
174        close(fd);
175    if ( block != NULL )
176        free(block);
177    return NULL;
178}
179
180static void xc_dom_free_all(struct xc_dom_image *dom)
181{
182    struct xc_dom_mem *block;
183
184    while ( (block = dom->memblocks) != NULL )
185    {
186        dom->memblocks = block->next;
187        if ( block->mmap_ptr )
188            munmap(block->mmap_ptr, block->mmap_len);
189        free(block);
190    }
191}
192
193char *xc_dom_strdup(struct xc_dom_image *dom, const char *str)
194{
195    size_t len = strlen(str) + 1;
196    char *nstr = xc_dom_malloc(dom, len);
197
198    if ( nstr == NULL )
199        return NULL;
200    memcpy(nstr, str, len);
201    return nstr;
202}
203
204/* ------------------------------------------------------------------------ */
205/* read files, copy memory blocks, with transparent gunzip                  */
206
207size_t xc_dom_check_gzip(void *blob, size_t ziplen)
208{
209    unsigned char *gzlen;
210    size_t unziplen;
211
212    if ( strncmp(blob, "\037\213", 2) )
213        /* not gzipped */
214        return 0;
215
216    gzlen = blob + ziplen - 4;
217    unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
218    if ( (unziplen < 0) || (unziplen > (1024*1024*1024)) ) /* 1GB limit */
219    {
220        xc_dom_printf
221            ("%s: size (zip %zd, unzip %zd) looks insane, skip gunzip\n",
222             __FUNCTION__, ziplen, unziplen);
223        return 0;
224    }
225
226    return unziplen + 16;
227}
228
229int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen)
230{
231    z_stream zStream;
232    int rc;
233
234    memset(&zStream, 0, sizeof(zStream));
235    zStream.next_in = src;
236    zStream.avail_in = srclen;
237    zStream.next_out = dst;
238    zStream.avail_out = dstlen;
239    rc = inflateInit2(&zStream, (MAX_WBITS + 32)); /* +32 means "handle gzip" */
240    if ( rc != Z_OK )
241    {
242        xc_dom_panic(XC_INTERNAL_ERROR,
243                     "%s: inflateInit2 failed (rc=%d)\n", __FUNCTION__, rc);
244        return -1;
245    }
246    rc = inflate(&zStream, Z_FINISH);
247    if ( rc != Z_STREAM_END )
248    {
249        xc_dom_panic(XC_INTERNAL_ERROR,
250                     "%s: inflate failed (rc=%d)\n", __FUNCTION__, rc);
251        return -1;
252    }
253
254    xc_dom_printf("%s: unzip ok, 0x%zx -> 0x%zx\n",
255                  __FUNCTION__, srclen, dstlen);
256    return 0;
257}
258
259int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
260{
261    void *unzip;
262    size_t unziplen;
263
264    unziplen = xc_dom_check_gzip(*blob, *size);
265    if ( unziplen == 0 )
266        return 0;
267
268    unzip = xc_dom_malloc(dom, unziplen);
269    if ( unzip == NULL )
270        return -1;
271
272    if ( xc_dom_do_gunzip(*blob, *size, unzip, unziplen) == -1 )
273        return -1;
274
275    *blob = unzip;
276    *size = unziplen;
277    return 0;
278}
279
280/* ------------------------------------------------------------------------ */
281/* domain memory                                                            */
282
283void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
284                        xen_pfn_t count)
285{
286    struct xc_dom_phys *phys;
287    unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
288    char *mode = "unset";
289
290    if ( pfn > dom->total_pages )
291    {
292        xc_dom_printf("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")\n",
293                      __FUNCTION__, pfn, dom->total_pages);
294        return NULL;
295    }
296
297    /* already allocated? */
298    for ( phys = dom->phys_pages; phys != NULL; phys = phys->next )
299    {
300        if ( pfn >= (phys->first + phys->count) )
301            continue;
302        if ( count )
303        {
304            /* size given: must be completely within the already allocated block */
305            if ( (pfn + count) <= phys->first )
306                continue;
307            if ( (pfn < phys->first) ||
308                 ((pfn + count) > (phys->first + phys->count)) )
309            {
310                xc_dom_printf("%s: request overlaps allocated block"
311                              " (req 0x%" PRIpfn "+0x%" PRIpfn ","
312                              " blk 0x%" PRIpfn "+0x%" PRIpfn ")\n",
313                              __FUNCTION__, pfn, count, phys->first,
314                              phys->count);
315                return NULL;
316            }
317        }
318        else
319        {
320            /* no size given: block must be allocated already,
321               just hand out a pointer to it */
322            if ( pfn < phys->first )
323                continue;
324        }
325        return phys->ptr + ((pfn - phys->first) << page_shift);
326    }
327
328    /* allocating is allowed with size specified only */
329    if ( count == 0 )
330    {
331        xc_dom_printf("%s: no block found, no size given,"
332                      " can't malloc (pfn 0x%" PRIpfn ")\n",
333                      __FUNCTION__, pfn);
334        return NULL;
335    }
336
337    /* not found, no overlap => allocate */
338    phys = xc_dom_malloc(dom, sizeof(*phys));
339    if ( phys == NULL )
340        return NULL;
341    memset(phys, 0, sizeof(*phys));
342    phys->first = pfn;
343    phys->count = count;
344
345    if ( dom->guest_domid )
346    {
347        mode = "domU mapping";
348        phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count);
349        if ( phys->ptr == NULL )
350            return NULL;
351        dom->alloc_domU_map += phys->count << page_shift;
352    }
353    else
354    {
355        mode = "anonymous memory";
356        phys->ptr = mmap(NULL, phys->count << page_shift,
357                         PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
358                         -1, 0);
359        if ( phys->ptr == MAP_FAILED )
360        {
361            xc_dom_panic(XC_OUT_OF_MEMORY,
362                         "%s: oom: can't allocate 0x%" PRIpfn " pages\n",
363                         __FUNCTION__, count);
364            return NULL;
365        }
366        dom->alloc_mem_map += phys->count << page_shift;
367    }
368
369#if 1
370    xc_dom_printf("%s: %s: pfn 0x%" PRIpfn "+0x%" PRIpfn " at %p\n",
371                  __FUNCTION__, mode, phys->first, phys->count, phys->ptr);
372#endif
373    phys->next = dom->phys_pages;
374    dom->phys_pages = phys;
375    return phys->ptr;
376}
377
378int xc_dom_alloc_segment(struct xc_dom_image *dom,
379                         struct xc_dom_seg *seg, char *name,
380                         xen_vaddr_t start, xen_vaddr_t size)
381{
382    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
383    xen_pfn_t pages = (size + page_size - 1) / page_size;
384    void *ptr;
385
386    if ( start == 0 )
387        start = dom->virt_alloc_end;
388
389    if ( start & (page_size - 1) )
390    {
391        xc_dom_panic(XC_INTERNAL_ERROR,
392                     "%s: segment start isn't page aligned (0x%" PRIx64 ")\n",
393                     __FUNCTION__, start);
394        return -1;
395    }
396    if ( start < dom->virt_alloc_end )
397    {
398        xc_dom_panic(XC_INTERNAL_ERROR,
399                     "%s: segment start too low (0x%" PRIx64 " < 0x%" PRIx64
400                     ")\n", __FUNCTION__, start, dom->virt_alloc_end);
401        return -1;
402    }
403
404    seg->vstart = start;
405    seg->vend = start + pages * page_size;
406    seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
407    dom->virt_alloc_end = seg->vend;
408
409    xc_dom_printf("%-20s:   %-12s : 0x%" PRIx64 " -> 0x%" PRIx64
410                  "  (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n",
411                  __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages);
412
413    /* map and clear pages */
414    ptr = xc_dom_seg_to_ptr(dom, seg);
415    if ( ptr == NULL )
416        return -1;
417    memset(ptr, 0, pages * page_size);
418
419    return 0;
420}
421
422int xc_dom_alloc_page(struct xc_dom_image *dom, char *name)
423{
424    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
425    xen_vaddr_t start;
426    xen_pfn_t pfn;
427
428    start = dom->virt_alloc_end;
429    dom->virt_alloc_end += page_size;
430    pfn = (start - dom->parms.virt_base) / page_size;
431
432    xc_dom_printf("%-20s:   %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n",
433                  __FUNCTION__, name, start, pfn);
434    return pfn;
435}
436
437void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn)
438{
439    unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
440    struct xc_dom_phys *phys, *prev = NULL;
441
442    for ( phys = dom->phys_pages; phys != NULL; phys = phys->next )
443    {
444        if ( (pfn >= phys->first) && (pfn < (phys->first + phys->count)) )
445            break;
446        prev = phys;
447    }
448    if ( !phys )
449    {
450        xc_dom_printf("%s: Huh? no mapping with pfn 0x%" PRIpfn "\n",
451                      __FUNCTION__, pfn);
452        return;
453    }
454
455    munmap(phys->ptr, phys->count << page_shift);
456    if ( prev )
457        prev->next = phys->next;
458    else
459        dom->phys_pages = phys->next;
460}
461
462void xc_dom_unmap_all(struct xc_dom_image *dom)
463{
464    while ( dom->phys_pages )
465        xc_dom_unmap_one(dom, dom->phys_pages->first);
466}
467
468/* ------------------------------------------------------------------------ */
469/* pluggable kernel loaders                                                 */
470
471static struct xc_dom_loader *first_loader = NULL;
472static struct xc_dom_arch *first_hook = NULL;
473
474void xc_dom_register_loader(struct xc_dom_loader *loader)
475{
476    loader->next = first_loader;
477    first_loader = loader;
478}
479
480static struct xc_dom_loader *xc_dom_find_loader(struct xc_dom_image *dom)
481{
482    struct xc_dom_loader *loader = first_loader;
483
484    while ( loader != NULL )
485    {
486        xc_dom_printf("%s: trying %s loader ... ", __FUNCTION__, loader->name);
487        if ( loader->probe(dom) == 0 )
488        {
489            xc_dom_printf("OK\n");
490            return loader;
491        }
492        xc_dom_printf("failed\n");
493        loader = loader->next;
494    }
495    xc_dom_panic(XC_INVALID_KERNEL, "%s: no loader found\n", __FUNCTION__);
496    return NULL;
497}
498
499void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks)
500{
501    hooks->next = first_hook;
502    first_hook = hooks;
503}
504
505static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
506{
507    struct xc_dom_arch *hooks = first_hook;
508
509    while (  hooks != NULL )
510    {
511        if ( !strcmp(hooks->guest_type, guest_type))
512            return hooks;
513        hooks = hooks->next;
514    }
515    xc_dom_panic(XC_INVALID_KERNEL,
516                 "%s: not found (type %s)\n", __FUNCTION__, guest_type);
517    return NULL;
518}
519
520/* ------------------------------------------------------------------------ */
521/* public interface                                                         */
522
523void xc_dom_release(struct xc_dom_image *dom)
524{
525    xc_dom_printf("%s: called\n", __FUNCTION__);
526    if ( dom->phys_pages )
527        xc_dom_unmap_all(dom);
528    xc_dom_free_all(dom);
529    free(dom);
530}
531
532struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features)
533{
534    struct xc_dom_image *dom;
535
536    xc_dom_printf("%s: cmdline=\"%s\", features=\"%s\"\n",
537                  __FUNCTION__, cmdline, features);
538    dom = malloc(sizeof(*dom));
539    if ( !dom )
540        goto err;
541
542    memset(dom, 0, sizeof(*dom));
543    if ( cmdline )
544        dom->cmdline = xc_dom_strdup(dom, cmdline);
545    if ( features )
546        elf_xen_parse_features(features, dom->f_requested, NULL);
547
548    dom->parms.virt_base = UNSET_ADDR;
549    dom->parms.virt_entry = UNSET_ADDR;
550    dom->parms.virt_hypercall = UNSET_ADDR;
551    dom->parms.virt_hv_start_low = UNSET_ADDR;
552    dom->parms.elf_paddr_offset = UNSET_ADDR;
553
554    dom->alloc_malloc += sizeof(*dom);
555    return dom;
556
557 err:
558    if ( dom )
559        xc_dom_release(dom);
560    return NULL;
561}
562
563int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
564{
565    xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename);
566    dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size);
567    if ( dom->kernel_blob == NULL )
568        return -1;
569    return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
570}
571
572int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename)
573{
574    xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename);
575    dom->ramdisk_blob =
576        xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size);
577    if ( dom->ramdisk_blob == NULL )
578        return -1;
579//    return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
580    return 0;
581}
582
583int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize)
584{
585    xc_dom_printf("%s: called\n", __FUNCTION__);
586    dom->kernel_blob = (void *)mem;
587    dom->kernel_size = memsize;
588    return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
589}
590
591int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
592                       size_t memsize)
593{
594    xc_dom_printf("%s: called\n", __FUNCTION__);
595    dom->ramdisk_blob = (void *)mem;
596    dom->ramdisk_size = memsize;
597//    return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
598    return 0;
599}
600
601int xc_dom_parse_image(struct xc_dom_image *dom)
602{
603    int i;
604
605    xc_dom_printf("%s: called\n", __FUNCTION__);
606
607    /* parse kernel image */
608    dom->kernel_loader = xc_dom_find_loader(dom);
609    if ( dom->kernel_loader == NULL )
610        goto err;
611    if ( dom->kernel_loader->parser(dom) != 0 )
612        goto err;
613    if ( dom->guest_type == NULL )
614    {
615        xc_dom_panic(XC_INTERNAL_ERROR,
616                     "%s: guest_type not set\n", __FUNCTION__);
617        goto err;
618    }
619
620    /* check features */
621    for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
622    {
623        dom->f_active[i] |= dom->f_requested[i]; /* cmd line */
624        dom->f_active[i] |= dom->parms.f_required[i]; /* kernel   */
625        if ( (dom->f_active[i] & dom->parms.f_supported[i]) !=
626             dom->f_active[i] )
627        {
628            xc_dom_panic(XC_INVALID_PARAM,
629                         "%s: unsupported feature requested\n", __FUNCTION__);
630            goto err;
631        }
632    }
633    return 0;
634
635 err:
636    return -1;
637}
638
639int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb)
640{
641    unsigned int page_shift;
642    xen_pfn_t nr_pages;
643
644    dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type);
645    if ( dom->arch_hooks == NULL )
646    {
647        xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n",
648                     __FUNCTION__);
649        return -1;
650    }
651
652    page_shift = XC_DOM_PAGE_SHIFT(dom);
653    nr_pages = mem_mb << (20 - page_shift);
654
655    xc_dom_printf("%s: mem %d MB, pages 0x%" PRIpfn " pages, %dk each\n",
656                  __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10));
657    dom->total_pages = nr_pages;
658
659    xc_dom_printf("%s: 0x%" PRIpfn " pages\n",
660                  __FUNCTION__, dom->total_pages);
661
662    return 0;
663}
664
665int xc_dom_update_guest_p2m(struct xc_dom_image *dom)
666{
667    uint32_t *p2m_32;
668    uint64_t *p2m_64;
669    xen_pfn_t i;
670
671    if ( !dom->p2m_guest )
672        return 0;
673
674    switch ( dom->arch_hooks->sizeof_pfn )
675    {
676    case 4:
677        xc_dom_printf("%s: dst 32bit, pages 0x%" PRIpfn " \n",
678                      __FUNCTION__, dom->total_pages);
679        p2m_32 = dom->p2m_guest;
680        for ( i = 0; i < dom->total_pages; i++ )
681            if ( dom->p2m_host[i] != INVALID_P2M_ENTRY )
682                p2m_32[i] = dom->p2m_host[i];
683            else
684                p2m_32[i] = (uint32_t) - 1;
685        break;
686    case 8:
687        xc_dom_printf("%s: dst 64bit, pages 0x%" PRIpfn " \n",
688                      __FUNCTION__, dom->total_pages);
689        p2m_64 = dom->p2m_guest;
690        for ( i = 0; i < dom->total_pages; i++ )
691            if ( dom->p2m_host[i] != INVALID_P2M_ENTRY )
692                p2m_64[i] = dom->p2m_host[i];
693            else
694                p2m_64[i] = (uint64_t) - 1;
695        break;
696    default:
697        xc_dom_panic(XC_INTERNAL_ERROR,
698                     "sizeof_pfn is invalid (is %d, can be 4 or 8)",
699                     dom->arch_hooks->sizeof_pfn);
700        return -1;
701    }
702    return 0;
703}
704
705int xc_dom_build_image(struct xc_dom_image *dom)
706{
707    unsigned int page_size;
708
709    xc_dom_printf("%s: called\n", __FUNCTION__);
710
711    /* check for arch hooks */
712    if ( dom->arch_hooks == NULL )
713    {
714        xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n",
715                     __FUNCTION__);
716        goto err;
717    }
718    page_size = XC_DOM_PAGE_SIZE(dom);
719
720    /* load kernel */
721    if ( xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel",
722                              dom->kernel_seg.vstart,
723                              dom->kernel_seg.vend -
724                              dom->kernel_seg.vstart) != 0 )
725        goto err;
726    if ( dom->kernel_loader->loader(dom) != 0 )
727        goto err;
728
729    /* load ramdisk */
730    if ( dom->ramdisk_blob )
731    {
732        size_t unziplen, ramdisklen;
733        void *ramdiskmap;
734
735        unziplen = xc_dom_check_gzip(dom->ramdisk_blob, dom->ramdisk_size);
736        ramdisklen = unziplen ? unziplen : dom->ramdisk_size;
737        if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0,
738                                  ramdisklen) != 0 )
739            goto err;
740        ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
741        if ( unziplen )
742        {
743            if ( xc_dom_do_gunzip(dom->ramdisk_blob, dom->ramdisk_size,
744                                  ramdiskmap, ramdisklen) == -1 )
745                goto err;
746        }
747        else
748            memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size);
749    }
750
751    /* allocate other pages */
752    if ( dom->arch_hooks->alloc_magic_pages(dom) != 0 )
753        goto err;
754    if ( dom->arch_hooks->count_pgtables )
755    {
756        dom->arch_hooks->count_pgtables(dom);
757        if ( (dom->pgtables > 0) &&
758             (xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0,
759                                   dom->pgtables * page_size) != 0) )
760                goto err;
761    }
762    if ( dom->alloc_bootstack )
763        dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack");
764    xc_dom_printf("%-20s: virt_alloc_end : 0x%" PRIx64 "\n",
765                  __FUNCTION__, dom->virt_alloc_end);
766    xc_dom_printf("%-20s: virt_pgtab_end : 0x%" PRIx64 "\n",
767                  __FUNCTION__, dom->virt_pgtab_end);
768    return 0;
769
770 err:
771    return -1;
772}
773
774/*
775 * Local variables:
776 * mode: C
777 * c-set-style: "BSD"
778 * c-basic-offset: 4
779 * tab-width: 4
780 * indent-tabs-mode: nil
781 * End:
782 */
Note: See TracBrowser for help on using the repository browser.