debuggers.hg

view tools/libxc/xc_dom_core.c @ 20935:7a10f8513b3f

libxc: Check there's enough memory for segments we're creating

Previously, xc_dom_alloc_segment would go ahead even if the segment
we're trying to create is too big for the domain's RAM (or the
requested addr is out of range). It would pass invalid parameters to
xc_dom_seg_to_ptr giving undefined behaviour.

Fixing xc_dom_seg_to_ptr to fail is not sufficient because we want to
provide a comprehensible explanation to the caller - which may
ultimately be the user.

In particular, with this change attempting "xl create" with a ramdisk
image bigger than the guest's specified RAM will provide a useful
error message mentioning the ramdisk.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 03 09:46:01 2010 +0000 (2010-02-03)
parents 02107eca8fb7
children 779c0ef9682c
line source
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>
20 #include "xg_private.h"
21 #include "xc_dom.h"
23 /* ------------------------------------------------------------------------ */
24 /* debugging */
26 FILE *xc_dom_logfile = NULL;
28 void 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 }
37 int xc_dom_printf(const char *fmt, ...)
38 {
39 va_list args;
40 char buf[1024];
41 int rc;
43 if ( !xc_dom_logfile )
44 return 0;
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);
51 return rc;
52 }
54 int 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];
63 if ( xc_dom_logfile )
64 fp = xc_dom_logfile;
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 }
75 static 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 }
85 void 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 }
96 /* ------------------------------------------------------------------------ */
97 /* simple memory pool */
99 void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
100 {
101 struct xc_dom_mem *block;
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 }
115 void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
116 {
117 struct xc_dom_mem *block;
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_ANON,
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 }
141 void *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;
147 fd = open(filename, O_RDONLY);
148 if ( fd == -1 )
149 goto err;
151 lseek(fd, 0, SEEK_SET);
152 *size = lseek(fd, 0, SEEK_END);
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;
172 err:
173 if ( fd != -1 )
174 close(fd);
175 if ( block != NULL )
176 free(block);
177 return NULL;
178 }
180 static void xc_dom_free_all(struct xc_dom_image *dom)
181 {
182 struct xc_dom_mem *block;
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 }
193 char *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);
198 if ( nstr == NULL )
199 return NULL;
200 memcpy(nstr, str, len);
201 return nstr;
202 }
204 /* ------------------------------------------------------------------------ */
205 /* read files, copy memory blocks, with transparent gunzip */
207 size_t xc_dom_check_gzip(void *blob, size_t ziplen)
208 {
209 unsigned char *gzlen;
210 size_t unziplen;
212 if ( strncmp(blob, "\037\213", 2) )
213 /* not gzipped */
214 return 0;
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 }
226 return unziplen + 16;
227 }
229 int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen)
230 {
231 z_stream zStream;
232 int rc;
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 inflateEnd(&zStream);
248 if ( rc != Z_STREAM_END )
249 {
250 xc_dom_panic(XC_INTERNAL_ERROR,
251 "%s: inflate failed (rc=%d)\n", __FUNCTION__, rc);
252 return -1;
253 }
255 xc_dom_printf("%s: unzip ok, 0x%zx -> 0x%zx\n",
256 __FUNCTION__, srclen, dstlen);
257 return 0;
258 }
260 int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
261 {
262 void *unzip;
263 size_t unziplen;
265 unziplen = xc_dom_check_gzip(*blob, *size);
266 if ( unziplen == 0 )
267 return 0;
269 unzip = xc_dom_malloc(dom, unziplen);
270 if ( unzip == NULL )
271 return -1;
273 if ( xc_dom_do_gunzip(*blob, *size, unzip, unziplen) == -1 )
274 return -1;
276 *blob = unzip;
277 *size = unziplen;
278 return 0;
279 }
281 /* ------------------------------------------------------------------------ */
282 /* domain memory */
284 void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
285 xen_pfn_t count)
286 {
287 struct xc_dom_phys *phys;
288 unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
289 char *mode = "unset";
291 if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */
292 count > dom->total_pages ||
293 pfn > dom->total_pages - count )
294 {
295 xc_dom_printf("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")\n",
296 __FUNCTION__, pfn, dom->total_pages);
297 return NULL;
298 }
300 /* already allocated? */
301 for ( phys = dom->phys_pages; phys != NULL; phys = phys->next )
302 {
303 if ( pfn >= (phys->first + phys->count) )
304 continue;
305 if ( count )
306 {
307 /* size given: must be completely within the already allocated block */
308 if ( (pfn + count) <= phys->first )
309 continue;
310 if ( (pfn < phys->first) ||
311 ((pfn + count) > (phys->first + phys->count)) )
312 {
313 xc_dom_printf("%s: request overlaps allocated block"
314 " (req 0x%" PRIpfn "+0x%" PRIpfn ","
315 " blk 0x%" PRIpfn "+0x%" PRIpfn ")\n",
316 __FUNCTION__, pfn, count, phys->first,
317 phys->count);
318 return NULL;
319 }
320 }
321 else
322 {
323 /* no size given: block must be allocated already,
324 just hand out a pointer to it */
325 if ( pfn < phys->first )
326 continue;
327 }
328 return phys->ptr + ((pfn - phys->first) << page_shift);
329 }
331 /* allocating is allowed with size specified only */
332 if ( count == 0 )
333 {
334 xc_dom_printf("%s: no block found, no size given,"
335 " can't malloc (pfn 0x%" PRIpfn ")\n",
336 __FUNCTION__, pfn);
337 return NULL;
338 }
340 /* not found, no overlap => allocate */
341 phys = xc_dom_malloc(dom, sizeof(*phys));
342 if ( phys == NULL )
343 return NULL;
344 memset(phys, 0, sizeof(*phys));
345 phys->first = pfn;
346 phys->count = count;
348 if ( dom->guest_domid )
349 {
350 mode = "domU mapping";
351 phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count);
352 if ( phys->ptr == NULL )
353 return NULL;
354 dom->alloc_domU_map += phys->count << page_shift;
355 }
356 else
357 {
358 int err;
360 mode = "anonymous memory";
361 phys->ptr = mmap(NULL, phys->count << page_shift,
362 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
363 -1, 0);
364 if ( phys->ptr == MAP_FAILED )
365 {
366 err = errno;
367 xc_dom_panic(XC_OUT_OF_MEMORY,
368 "%s: oom: can't allocate 0x%" PRIpfn " pages"
369 " [mmap, errno=%i (%s)]\n",
370 __FUNCTION__, count, err, strerror(err));
371 return NULL;
372 }
373 dom->alloc_mem_map += phys->count << page_shift;
374 }
376 #if 1
377 xc_dom_printf("%s: %s: pfn 0x%" PRIpfn "+0x%" PRIpfn " at %p\n",
378 __FUNCTION__, mode, phys->first, phys->count, phys->ptr);
379 #endif
380 phys->next = dom->phys_pages;
381 dom->phys_pages = phys;
382 return phys->ptr;
383 }
385 int xc_dom_alloc_segment(struct xc_dom_image *dom,
386 struct xc_dom_seg *seg, char *name,
387 xen_vaddr_t start, xen_vaddr_t size)
388 {
389 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
390 xen_pfn_t pages = (size + page_size - 1) / page_size;
391 void *ptr;
393 if ( start == 0 )
394 start = dom->virt_alloc_end;
396 if ( start & (page_size - 1) )
397 {
398 xc_dom_panic(XC_INTERNAL_ERROR,
399 "%s: segment start isn't page aligned (0x%" PRIx64 ")\n",
400 __FUNCTION__, start);
401 return -1;
402 }
403 if ( start < dom->virt_alloc_end )
404 {
405 xc_dom_panic(XC_INTERNAL_ERROR,
406 "%s: segment start too low (0x%" PRIx64 " < 0x%" PRIx64
407 ")\n", __FUNCTION__, start, dom->virt_alloc_end);
408 return -1;
409 }
411 seg->vstart = start;
412 seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
414 if ( pages > dom->total_pages || /* double test avoids overflow probs */
415 pages > dom->total_pages - seg->pfn)
416 {
417 xc_dom_panic(XC_OUT_OF_MEMORY,
418 "%s: segment %s too large (0x%"PRIpfn" > "
419 "0x%"PRIpfn" - 0x%"PRIpfn" pages)\n",
420 __FUNCTION__, name, pages, dom->total_pages, seg->pfn);
421 return -1;
422 }
424 seg->vend = start + pages * page_size;
425 dom->virt_alloc_end = seg->vend;
426 if (dom->allocate)
427 dom->allocate(dom, dom->virt_alloc_end);
429 xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " -> 0x%" PRIx64
430 " (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n",
431 __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages);
433 /* map and clear pages */
434 ptr = xc_dom_seg_to_ptr(dom, seg);
435 if ( ptr == NULL )
436 return -1;
437 memset(ptr, 0, pages * page_size);
439 return 0;
440 }
442 int xc_dom_alloc_page(struct xc_dom_image *dom, char *name)
443 {
444 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
445 xen_vaddr_t start;
446 xen_pfn_t pfn;
448 start = dom->virt_alloc_end;
449 dom->virt_alloc_end += page_size;
450 if (dom->allocate)
451 dom->allocate(dom, dom->virt_alloc_end);
452 pfn = (start - dom->parms.virt_base) / page_size;
454 xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n",
455 __FUNCTION__, name, start, pfn);
456 return pfn;
457 }
459 void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn)
460 {
461 unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
462 struct xc_dom_phys *phys, *prev = NULL;
464 for ( phys = dom->phys_pages; phys != NULL; phys = phys->next )
465 {
466 if ( (pfn >= phys->first) && (pfn < (phys->first + phys->count)) )
467 break;
468 prev = phys;
469 }
470 if ( !phys )
471 {
472 xc_dom_printf("%s: Huh? no mapping with pfn 0x%" PRIpfn "\n",
473 __FUNCTION__, pfn);
474 return;
475 }
477 munmap(phys->ptr, phys->count << page_shift);
478 if ( prev )
479 prev->next = phys->next;
480 else
481 dom->phys_pages = phys->next;
482 }
484 void xc_dom_unmap_all(struct xc_dom_image *dom)
485 {
486 while ( dom->phys_pages )
487 xc_dom_unmap_one(dom, dom->phys_pages->first);
488 }
490 /* ------------------------------------------------------------------------ */
491 /* pluggable kernel loaders */
493 static struct xc_dom_loader *first_loader = NULL;
494 static struct xc_dom_arch *first_hook = NULL;
496 void xc_dom_register_loader(struct xc_dom_loader *loader)
497 {
498 loader->next = first_loader;
499 first_loader = loader;
500 }
502 static struct xc_dom_loader *xc_dom_find_loader(struct xc_dom_image *dom)
503 {
504 struct xc_dom_loader *loader = first_loader;
506 while ( loader != NULL )
507 {
508 xc_dom_printf("%s: trying %s loader ... ", __FUNCTION__, loader->name);
509 if ( loader->probe(dom) == 0 )
510 {
511 xc_dom_printf("OK\n");
512 return loader;
513 }
514 xc_dom_printf("failed\n");
515 loader = loader->next;
516 }
517 xc_dom_panic(XC_INVALID_KERNEL, "%s: no loader found\n", __FUNCTION__);
518 return NULL;
519 }
521 void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks)
522 {
523 hooks->next = first_hook;
524 first_hook = hooks;
525 }
527 struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
528 {
529 struct xc_dom_arch *hooks = first_hook;
531 while ( hooks != NULL )
532 {
533 if ( !strcmp(hooks->guest_type, guest_type))
534 return hooks;
535 hooks = hooks->next;
536 }
537 xc_dom_panic(XC_INVALID_KERNEL,
538 "%s: not found (type %s)\n", __FUNCTION__, guest_type);
539 return NULL;
540 }
542 /* ------------------------------------------------------------------------ */
543 /* public interface */
545 void xc_dom_release(struct xc_dom_image *dom)
546 {
547 xc_dom_printf("%s: called\n", __FUNCTION__);
548 if ( dom->phys_pages )
549 xc_dom_unmap_all(dom);
550 xc_dom_free_all(dom);
551 free(dom);
552 }
554 struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features)
555 {
556 struct xc_dom_image *dom;
558 xc_dom_printf("%s: cmdline=\"%s\", features=\"%s\"\n",
559 __FUNCTION__, cmdline, features);
560 dom = malloc(sizeof(*dom));
561 if ( !dom )
562 goto err;
564 memset(dom, 0, sizeof(*dom));
565 if ( cmdline )
566 dom->cmdline = xc_dom_strdup(dom, cmdline);
567 if ( features )
568 elf_xen_parse_features(features, dom->f_requested, NULL);
570 dom->parms.virt_base = UNSET_ADDR;
571 dom->parms.virt_entry = UNSET_ADDR;
572 dom->parms.virt_hypercall = UNSET_ADDR;
573 dom->parms.virt_hv_start_low = UNSET_ADDR;
574 dom->parms.elf_paddr_offset = UNSET_ADDR;
576 dom->alloc_malloc += sizeof(*dom);
577 return dom;
579 err:
580 if ( dom )
581 xc_dom_release(dom);
582 return NULL;
583 }
585 int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
586 {
587 xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename);
588 dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size);
589 if ( dom->kernel_blob == NULL )
590 return -1;
591 return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
592 }
594 int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename)
595 {
596 xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename);
597 dom->ramdisk_blob =
598 xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size);
599 if ( dom->ramdisk_blob == NULL )
600 return -1;
601 // return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
602 return 0;
603 }
605 int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize)
606 {
607 xc_dom_printf("%s: called\n", __FUNCTION__);
608 dom->kernel_blob = (void *)mem;
609 dom->kernel_size = memsize;
610 return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
611 }
613 int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
614 size_t memsize)
615 {
616 xc_dom_printf("%s: called\n", __FUNCTION__);
617 dom->ramdisk_blob = (void *)mem;
618 dom->ramdisk_size = memsize;
619 // return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
620 return 0;
621 }
623 int xc_dom_parse_image(struct xc_dom_image *dom)
624 {
625 int i;
627 xc_dom_printf("%s: called\n", __FUNCTION__);
629 /* parse kernel image */
630 dom->kernel_loader = xc_dom_find_loader(dom);
631 if ( dom->kernel_loader == NULL )
632 goto err;
633 if ( dom->kernel_loader->parser(dom) != 0 )
634 goto err;
635 if ( dom->guest_type == NULL )
636 {
637 xc_dom_panic(XC_INTERNAL_ERROR,
638 "%s: guest_type not set\n", __FUNCTION__);
639 goto err;
640 }
642 /* check features */
643 for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
644 {
645 dom->f_active[i] |= dom->f_requested[i]; /* cmd line */
646 dom->f_active[i] |= dom->parms.f_required[i]; /* kernel */
647 if ( (dom->f_active[i] & dom->parms.f_supported[i]) !=
648 dom->f_active[i] )
649 {
650 xc_dom_panic(XC_INVALID_PARAM,
651 "%s: unsupported feature requested\n", __FUNCTION__);
652 goto err;
653 }
654 }
655 return 0;
657 err:
658 return -1;
659 }
661 int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb)
662 {
663 unsigned int page_shift;
664 xen_pfn_t nr_pages;
666 dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type);
667 if ( dom->arch_hooks == NULL )
668 {
669 xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n",
670 __FUNCTION__);
671 return -1;
672 }
674 page_shift = XC_DOM_PAGE_SHIFT(dom);
675 nr_pages = mem_mb << (20 - page_shift);
677 xc_dom_printf("%s: mem %d MB, pages 0x%" PRIpfn " pages, %dk each\n",
678 __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10));
679 dom->total_pages = nr_pages;
681 xc_dom_printf("%s: 0x%" PRIpfn " pages\n",
682 __FUNCTION__, dom->total_pages);
684 return 0;
685 }
687 int xc_dom_update_guest_p2m(struct xc_dom_image *dom)
688 {
689 uint32_t *p2m_32;
690 uint64_t *p2m_64;
691 xen_pfn_t i;
693 if ( !dom->p2m_guest )
694 return 0;
696 switch ( dom->arch_hooks->sizeof_pfn )
697 {
698 case 4:
699 xc_dom_printf("%s: dst 32bit, pages 0x%" PRIpfn " \n",
700 __FUNCTION__, dom->total_pages);
701 p2m_32 = dom->p2m_guest;
702 for ( i = 0; i < dom->total_pages; i++ )
703 if ( dom->p2m_host[i] != INVALID_P2M_ENTRY )
704 p2m_32[i] = dom->p2m_host[i];
705 else
706 p2m_32[i] = (uint32_t) - 1;
707 break;
708 case 8:
709 xc_dom_printf("%s: dst 64bit, pages 0x%" PRIpfn " \n",
710 __FUNCTION__, dom->total_pages);
711 p2m_64 = dom->p2m_guest;
712 for ( i = 0; i < dom->total_pages; i++ )
713 if ( dom->p2m_host[i] != INVALID_P2M_ENTRY )
714 p2m_64[i] = dom->p2m_host[i];
715 else
716 p2m_64[i] = (uint64_t) - 1;
717 break;
718 default:
719 xc_dom_panic(XC_INTERNAL_ERROR,
720 "sizeof_pfn is invalid (is %d, can be 4 or 8)",
721 dom->arch_hooks->sizeof_pfn);
722 return -1;
723 }
724 return 0;
725 }
727 int xc_dom_build_image(struct xc_dom_image *dom)
728 {
729 unsigned int page_size;
731 xc_dom_printf("%s: called\n", __FUNCTION__);
733 /* check for arch hooks */
734 if ( dom->arch_hooks == NULL )
735 {
736 xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n",
737 __FUNCTION__);
738 goto err;
739 }
740 page_size = XC_DOM_PAGE_SIZE(dom);
742 /* load kernel */
743 if ( xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel",
744 dom->kernel_seg.vstart,
745 dom->kernel_seg.vend -
746 dom->kernel_seg.vstart) != 0 )
747 goto err;
748 if ( dom->kernel_loader->loader(dom) != 0 )
749 goto err;
751 /* load ramdisk */
752 if ( dom->ramdisk_blob )
753 {
754 size_t unziplen, ramdisklen;
755 void *ramdiskmap;
757 unziplen = xc_dom_check_gzip(dom->ramdisk_blob, dom->ramdisk_size);
758 ramdisklen = unziplen ? unziplen : dom->ramdisk_size;
759 if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0,
760 ramdisklen) != 0 )
761 goto err;
762 ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
763 if ( unziplen )
764 {
765 if ( xc_dom_do_gunzip(dom->ramdisk_blob, dom->ramdisk_size,
766 ramdiskmap, ramdisklen) == -1 )
767 goto err;
768 }
769 else
770 memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size);
771 }
773 /* allocate other pages */
774 if ( dom->arch_hooks->alloc_magic_pages(dom) != 0 )
775 goto err;
776 if ( dom->arch_hooks->count_pgtables )
777 {
778 dom->arch_hooks->count_pgtables(dom);
779 if ( (dom->pgtables > 0) &&
780 (xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0,
781 dom->pgtables * page_size) != 0) )
782 goto err;
783 }
784 if ( dom->alloc_bootstack )
785 dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack");
786 xc_dom_printf("%-20s: virt_alloc_end : 0x%" PRIx64 "\n",
787 __FUNCTION__, dom->virt_alloc_end);
788 xc_dom_printf("%-20s: virt_pgtab_end : 0x%" PRIx64 "\n",
789 __FUNCTION__, dom->virt_pgtab_end);
790 return 0;
792 err:
793 return -1;
794 }
796 /*
797 * Local variables:
798 * mode: C
799 * c-set-style: "BSD"
800 * c-basic-offset: 4
801 * tab-width: 4
802 * indent-tabs-mode: nil
803 * End:
804 */