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 library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation;
12 * version 2.1 of the License.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
21 *
22 * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
23 *
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <inttypes.h>
31 #include <zlib.h>
32 #include <assert.h>
33
34 #include "xg_private.h"
35 #include "xc_dom.h"
36 #include "_paths.h"
37
38 /* ------------------------------------------------------------------------ */
39 /* debugging */
40
41
42
43 static const char *default_logfile = XEN_LOG_DIR "/domain-builder-ng.log";
44
xc_dom_loginit(xc_interface * xch)45 int xc_dom_loginit(xc_interface *xch) {
46 if (xch->dombuild_logger) return 0;
47
48 if (!xch->dombuild_logger_file) {
49 xch->dombuild_logger_file = fopen(default_logfile, "a");
50 if (!xch->dombuild_logger_file) {
51 PERROR("Could not open logfile `%s'", default_logfile);
52 return -1;
53 }
54 }
55
56 xch->dombuild_logger = xch->dombuild_logger_tofree =
57 (xentoollog_logger*)
58 xtl_createlogger_stdiostream(xch->dombuild_logger_file, XTL_DETAIL,
59 XTL_STDIOSTREAM_SHOW_DATE|XTL_STDIOSTREAM_SHOW_PID);
60 if (!xch->dombuild_logger)
61 return -1;
62
63 xc_dom_printf(xch, "### ----- xc domain builder logfile opened -----");
64
65 return 0;
66 }
67
xc_dom_printf(xc_interface * xch,const char * fmt,...)68 void xc_dom_printf(xc_interface *xch, const char *fmt, ...)
69 {
70 va_list args;
71 if (!xch->dombuild_logger) return;
72 va_start(args, fmt);
73 xtl_logv(xch->dombuild_logger, XTL_DETAIL, -1, "domainbuilder", fmt, args);
74 va_end(args);
75 }
76
xc_dom_panic_func(xc_interface * xch,const char * file,int line,xc_error_code err,const char * fmt,...)77 void xc_dom_panic_func(xc_interface *xch,
78 const char *file, int line, xc_error_code err,
79 const char *fmt, ...)
80 {
81 va_list args;
82 char msg[XC_MAX_ERROR_MSG_LEN];
83
84 va_start(args, fmt);
85 vsnprintf(msg, sizeof(msg), fmt, args);
86 va_end(args);
87 msg[sizeof(msg)-1] = 0;
88
89 xc_report(xch,
90 xch->dombuild_logger ? xch->dombuild_logger : xch->error_handler,
91 XTL_ERROR, err, "panic: %s:%d: %s",
92 file, line, msg);
93 }
94
print_mem(struct xc_dom_image * dom,const char * name,size_t mem)95 static void print_mem(struct xc_dom_image *dom, const char *name, size_t mem)
96 {
97 if ( mem > (32 * 1024 * 1024) )
98 DOMPRINTF("%-24s : %zd MB", name, mem / (1024 * 1024));
99 else if ( mem > (32 * 1024) )
100 DOMPRINTF("%-24s : %zd kB", name, mem / 1024);
101 else
102 DOMPRINTF("%-24s : %zd bytes", name, mem);
103 }
104
xc_dom_log_memory_footprint(struct xc_dom_image * dom)105 void xc_dom_log_memory_footprint(struct xc_dom_image *dom)
106 {
107 DOMPRINTF("domain builder memory footprint");
108 DOMPRINTF(" allocated");
109 print_mem(dom, " malloc", dom->alloc_malloc);
110 print_mem(dom, " anon mmap", dom->alloc_mem_map);
111 DOMPRINTF(" mapped");
112 print_mem(dom, " file mmap", dom->alloc_file_map);
113 print_mem(dom, " domU mmap", dom->alloc_domU_map);
114 }
115
116 /* ------------------------------------------------------------------------ */
117 /* simple memory pool */
118
xc_dom_malloc(struct xc_dom_image * dom,size_t size)119 void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
120 {
121 struct xc_dom_mem *block;
122
123 if ( size > SIZE_MAX - sizeof(*block) )
124 {
125 DOMPRINTF("%s: unreasonable allocation size", __FUNCTION__);
126 return NULL;
127 }
128 block = malloc(sizeof(*block) + size);
129 if ( block == NULL )
130 {
131 DOMPRINTF("%s: allocation failed", __FUNCTION__);
132 return NULL;
133 }
134 memset(block, 0, sizeof(*block) + size);
135 block->type = XC_DOM_MEM_TYPE_MALLOC_INTERNAL;
136 block->next = dom->memblocks;
137 dom->memblocks = block;
138 dom->alloc_malloc += sizeof(*block) + size;
139 if ( size > (100 * 1024) )
140 print_mem(dom, __FUNCTION__, size);
141 return block->memory;
142 }
143
xc_dom_malloc_page_aligned(struct xc_dom_image * dom,size_t size)144 void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
145 {
146 struct xc_dom_mem *block;
147
148 block = malloc(sizeof(*block));
149 if ( block == NULL )
150 {
151 DOMPRINTF("%s: allocation failed", __FUNCTION__);
152 return NULL;
153 }
154 memset(block, 0, sizeof(*block));
155 block->len = size;
156 block->ptr = mmap(NULL, block->len,
157 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
158 -1, 0);
159 if ( block->ptr == MAP_FAILED )
160 {
161 DOMPRINTF("%s: mmap failed", __FUNCTION__);
162 free(block);
163 return NULL;
164 }
165 block->type = XC_DOM_MEM_TYPE_MMAP;
166 block->next = dom->memblocks;
167 dom->memblocks = block;
168 dom->alloc_malloc += sizeof(*block);
169 dom->alloc_mem_map += block->len;
170 if ( size > (100 * 1024) )
171 print_mem(dom, __FUNCTION__, size);
172 return block->ptr;
173 }
174
xc_dom_register_external(struct xc_dom_image * dom,void * ptr,size_t size)175 int xc_dom_register_external(struct xc_dom_image *dom, void *ptr, size_t size)
176 {
177 struct xc_dom_mem *block;
178
179 block = malloc(sizeof(*block));
180 if ( block == NULL )
181 {
182 DOMPRINTF("%s: allocation failed", __FUNCTION__);
183 return -1;
184 }
185 memset(block, 0, sizeof(*block));
186 block->ptr = ptr;
187 block->len = size;
188 block->type = XC_DOM_MEM_TYPE_MALLOC_EXTERNAL;
189 block->next = dom->memblocks;
190 dom->memblocks = block;
191 dom->alloc_malloc += sizeof(*block);
192 dom->alloc_mem_map += block->len;
193 return 0;
194 }
195
xc_dom_malloc_filemap(struct xc_dom_image * dom,const char * filename,size_t * size,const size_t max_size)196 void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
197 const char *filename, size_t * size,
198 const size_t max_size)
199 {
200 struct xc_dom_mem *block = NULL;
201 int fd = -1;
202 off_t offset;
203
204 fd = open(filename, O_RDONLY);
205 if ( fd == -1 ) {
206 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
207 "failed to open file '%s': %s",
208 filename, strerror(errno));
209 goto err;
210 }
211
212 if ( (lseek(fd, 0, SEEK_SET) == -1) ||
213 ((offset = lseek(fd, 0, SEEK_END)) == -1) ) {
214 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
215 "failed to seek on file '%s': %s",
216 filename, strerror(errno));
217 goto err;
218 }
219
220 *size = offset;
221
222 if ( max_size && *size > max_size )
223 {
224 xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
225 "tried to map file which is too large");
226 goto err;
227 }
228
229 block = malloc(sizeof(*block));
230 if ( block == NULL ) {
231 xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
232 "failed to allocate block (%zu bytes)",
233 sizeof(*block));
234 goto err;
235 }
236
237 memset(block, 0, sizeof(*block));
238 block->len = *size;
239 block->ptr = mmap(NULL, block->len, PROT_READ,
240 MAP_SHARED, fd, 0);
241 if ( block->ptr == MAP_FAILED ) {
242 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
243 "failed to mmap file '%s': %s",
244 filename, strerror(errno));
245 goto err;
246 }
247
248 block->type = XC_DOM_MEM_TYPE_MMAP;
249 block->next = dom->memblocks;
250 dom->memblocks = block;
251 dom->alloc_malloc += sizeof(*block);
252 dom->alloc_file_map += block->len;
253 close(fd);
254 if ( *size > (100 * 1024) )
255 print_mem(dom, __FUNCTION__, *size);
256 return block->ptr;
257
258 err:
259 if ( fd != -1 )
260 close(fd);
261 free(block);
262 DOMPRINTF("%s: failed (on file `%s')", __FUNCTION__, filename);
263 return NULL;
264 }
265
xc_dom_free_all(struct xc_dom_image * dom)266 static void xc_dom_free_all(struct xc_dom_image *dom)
267 {
268 struct xc_dom_mem *block;
269
270 while ( (block = dom->memblocks) != NULL )
271 {
272 dom->memblocks = block->next;
273 switch ( block->type )
274 {
275 case XC_DOM_MEM_TYPE_MALLOC_INTERNAL:
276 break;
277 case XC_DOM_MEM_TYPE_MALLOC_EXTERNAL:
278 free(block->ptr);
279 break;
280 case XC_DOM_MEM_TYPE_MMAP:
281 munmap(block->ptr, block->len);
282 break;
283 }
284 free(block);
285 }
286 }
287
xc_dom_strdup(struct xc_dom_image * dom,const char * str)288 char *xc_dom_strdup(struct xc_dom_image *dom, const char *str)
289 {
290 size_t len = strlen(str) + 1;
291 char *nstr = xc_dom_malloc(dom, len);
292
293 if ( nstr == NULL )
294 return NULL;
295 memcpy(nstr, str, len);
296 return nstr;
297 }
298
299 /* ------------------------------------------------------------------------ */
300 /* decompression buffer sizing */
xc_dom_kernel_check_size(struct xc_dom_image * dom,size_t sz)301 int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz)
302 {
303 /* No limit */
304 if ( !dom->max_kernel_size )
305 return 0;
306
307 if ( sz > dom->max_kernel_size )
308 {
309 xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
310 "kernel image too large");
311 return 1;
312 }
313
314 return 0;
315 }
316
xc_dom_module_check_size(struct xc_dom_image * dom,size_t sz)317 int xc_dom_module_check_size(struct xc_dom_image *dom, size_t sz)
318 {
319 /* No limit */
320 if ( !dom->max_module_size )
321 return 0;
322
323 if ( sz > dom->max_module_size )
324 {
325 xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
326 "module image too large");
327 return 1;
328 }
329
330 return 0;
331 }
332
333 /* ------------------------------------------------------------------------ */
334 /* read files, copy memory blocks, with transparent gunzip */
335
xc_dom_check_gzip(xc_interface * xch,void * blob,size_t ziplen)336 size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
337 {
338 unsigned char *gzlen;
339 size_t unziplen;
340
341 if ( ziplen < 6 )
342 /* Too small. We need (i.e. the subsequent code relies on)
343 * 2 bytes for the magic number plus 4 bytes length. */
344 return 0;
345
346 if ( strncmp(blob, "\037\213", 2) )
347 /* not gzipped */
348 return 0;
349
350 gzlen = blob + ziplen - 4;
351 unziplen = (size_t)gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
352 if ( unziplen > XC_DOM_DECOMPRESS_MAX )
353 {
354 xc_dom_printf
355 (xch,
356 "%s: size (zip %zd, unzip %zd) looks insane, skip gunzip",
357 __FUNCTION__, ziplen, unziplen);
358 return 0;
359 }
360
361 return unziplen + 16;
362 }
363
xc_dom_do_gunzip(xc_interface * xch,void * src,size_t srclen,void * dst,size_t dstlen)364 int xc_dom_do_gunzip(xc_interface *xch,
365 void *src, size_t srclen, void *dst, size_t dstlen)
366 {
367 z_stream zStream;
368 int rc;
369
370 memset(&zStream, 0, sizeof(zStream));
371 zStream.next_in = src;
372 zStream.avail_in = srclen;
373 zStream.next_out = dst;
374 zStream.avail_out = dstlen;
375 rc = inflateInit2(&zStream, (MAX_WBITS + 32)); /* +32 means "handle gzip" */
376 if ( rc != Z_OK )
377 {
378 xc_dom_panic(xch, XC_INTERNAL_ERROR,
379 "%s: inflateInit2 failed (rc=%d)", __FUNCTION__, rc);
380 return -1;
381 }
382 rc = inflate(&zStream, Z_FINISH);
383 inflateEnd(&zStream);
384 if ( rc != Z_STREAM_END )
385 {
386 xc_dom_panic(xch, XC_INTERNAL_ERROR,
387 "%s: inflate failed (rc=%d)", __FUNCTION__, rc);
388 return -1;
389 }
390
391 xc_dom_printf(xch, "%s: unzip ok, 0x%zx -> 0x%zx",
392 __FUNCTION__, srclen, dstlen);
393 return 0;
394 }
395
xc_dom_try_gunzip(struct xc_dom_image * dom,void ** blob,size_t * size)396 int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
397 {
398 void *unzip;
399 size_t unziplen;
400
401 unziplen = xc_dom_check_gzip(dom->xch, *blob, *size);
402 if ( unziplen == 0 )
403 return 0;
404
405 if ( xc_dom_kernel_check_size(dom, unziplen) )
406 return 0;
407
408 unzip = xc_dom_malloc(dom, unziplen);
409 if ( unzip == NULL )
410 return -1;
411
412 if ( xc_dom_do_gunzip(dom->xch, *blob, *size, unzip, unziplen) == -1 )
413 return -1;
414
415 *blob = unzip;
416 *size = unziplen;
417 return 0;
418 }
419
420 /* ------------------------------------------------------------------------ */
421 /* domain memory */
422
xc_dom_pfn_to_ptr(struct xc_dom_image * dom,xen_pfn_t pfn,xen_pfn_t count)423 void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
424 xen_pfn_t count)
425 {
426 xen_pfn_t count_out_dummy;
427 return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
428 }
429
xc_dom_pfn_to_ptr_retcount(struct xc_dom_image * dom,xen_pfn_t pfn,xen_pfn_t count,xen_pfn_t * count_out)430 void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
431 xen_pfn_t count, xen_pfn_t *count_out)
432 {
433 struct xc_dom_phys *phys;
434 xen_pfn_t offset;
435 unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
436 char *mode = "unset";
437
438 *count_out = 0;
439
440 offset = pfn - dom->rambase_pfn;
441 if ( offset > dom->total_pages || /* multiple checks to avoid overflows */
442 count > dom->total_pages ||
443 offset > dom->total_pages - count )
444 {
445 DOMPRINTF("%s: pfn %"PRI_xen_pfn" out of range (0x%" PRIpfn " > 0x%" PRIpfn ")",
446 __FUNCTION__, pfn, offset, dom->total_pages);
447 return NULL;
448 }
449
450 /* already allocated? */
451 for ( phys = dom->phys_pages; phys != NULL; phys = phys->next )
452 {
453 if ( pfn >= (phys->first + phys->count) )
454 continue;
455 if ( count )
456 {
457 /* size given: must be completely within the already allocated block */
458 if ( (pfn + count) <= phys->first )
459 continue;
460 if ( (pfn < phys->first) ||
461 ((pfn + count) > (phys->first + phys->count)) )
462 {
463 DOMPRINTF("%s: request overlaps allocated block"
464 " (req 0x%" PRIpfn "+0x%" PRIpfn ","
465 " blk 0x%" PRIpfn "+0x%" PRIpfn ")",
466 __FUNCTION__, pfn, count, phys->first,
467 phys->count);
468 return NULL;
469 }
470 *count_out = count;
471 }
472 else
473 {
474 /* no size given: block must be allocated already,
475 just hand out a pointer to it */
476 if ( pfn < phys->first )
477 continue;
478 if ( pfn >= phys->first + phys->count )
479 continue;
480 *count_out = phys->count - (pfn - phys->first);
481 }
482 return phys->ptr + ((pfn - phys->first) << page_shift);
483 }
484
485 /* allocating is allowed with size specified only */
486 if ( count == 0 )
487 {
488 DOMPRINTF("%s: no block found, no size given,"
489 " can't malloc (pfn 0x%" PRIpfn ")",
490 __FUNCTION__, pfn);
491 return NULL;
492 }
493
494 /* not found, no overlap => allocate */
495 phys = xc_dom_malloc(dom, sizeof(*phys));
496 if ( phys == NULL )
497 return NULL;
498 memset(phys, 0, sizeof(*phys));
499 phys->first = pfn;
500 phys->count = count;
501
502 if ( dom->guest_domid )
503 {
504 mode = "domU mapping";
505 phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count);
506 if ( phys->ptr == NULL )
507 return NULL;
508 dom->alloc_domU_map += phys->count << page_shift;
509 }
510 else
511 {
512 int err;
513
514 mode = "anonymous memory";
515 phys->ptr = mmap(NULL, phys->count << page_shift,
516 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
517 -1, 0);
518 if ( phys->ptr == MAP_FAILED )
519 {
520 err = errno;
521 xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
522 "%s: oom: can't allocate 0x%" PRIpfn " pages"
523 " [mmap, errno=%i (%s)]",
524 __FUNCTION__, count, err, strerror(err));
525 return NULL;
526 }
527 dom->alloc_mem_map += phys->count << page_shift;
528 }
529
530 #if 1
531 DOMPRINTF("%s: %s: pfn 0x%" PRIpfn "+0x%" PRIpfn " at %p",
532 __FUNCTION__, mode, phys->first, phys->count, phys->ptr);
533 #endif
534 phys->next = dom->phys_pages;
535 dom->phys_pages = phys;
536 return phys->ptr;
537 }
538
xc_dom_chk_alloc_pages(struct xc_dom_image * dom,char * name,xen_pfn_t pages)539 static int xc_dom_chk_alloc_pages(struct xc_dom_image *dom, char *name,
540 xen_pfn_t pages)
541 {
542 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
543
544 if ( pages > dom->total_pages || /* multiple test avoids overflow probs */
545 dom->pfn_alloc_end - dom->rambase_pfn > dom->total_pages ||
546 pages > dom->total_pages - dom->pfn_alloc_end + dom->rambase_pfn )
547 {
548 xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
549 "%s: segment %s too large (0x%"PRIpfn" > "
550 "0x%"PRIpfn" - 0x%"PRIpfn" pages)", __FUNCTION__, name,
551 pages, dom->total_pages,
552 dom->pfn_alloc_end - dom->rambase_pfn);
553 return -1;
554 }
555
556 dom->pfn_alloc_end += pages;
557 dom->virt_alloc_end += pages * page_size;
558
559 if ( dom->allocate )
560 dom->allocate(dom);
561
562 return 0;
563 }
564
xc_dom_alloc_pad(struct xc_dom_image * dom,xen_vaddr_t boundary)565 static int xc_dom_alloc_pad(struct xc_dom_image *dom, xen_vaddr_t boundary)
566 {
567 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
568 xen_pfn_t pages;
569
570 if ( boundary & (page_size - 1) )
571 {
572 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
573 "%s: segment boundary isn't page aligned (0x%" PRIx64 ")",
574 __FUNCTION__, boundary);
575 return -1;
576 }
577 if ( boundary < dom->virt_alloc_end )
578 {
579 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
580 "%s: segment boundary too low (0x%" PRIx64 " < 0x%" PRIx64
581 ")", __FUNCTION__, boundary, dom->virt_alloc_end);
582 return -1;
583 }
584 pages = (boundary - dom->virt_alloc_end) / page_size;
585
586 return xc_dom_chk_alloc_pages(dom, "padding", pages);
587 }
588
xc_dom_alloc_segment(struct xc_dom_image * dom,struct xc_dom_seg * seg,char * name,xen_vaddr_t start,xen_vaddr_t size)589 int xc_dom_alloc_segment(struct xc_dom_image *dom,
590 struct xc_dom_seg *seg, char *name,
591 xen_vaddr_t start, xen_vaddr_t size)
592 {
593 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
594 xen_pfn_t pages;
595 void *ptr;
596
597 if ( start && xc_dom_alloc_pad(dom, start) )
598 return -1;
599
600 pages = (size + page_size - 1) / page_size;
601 start = dom->virt_alloc_end;
602
603 seg->pfn = dom->pfn_alloc_end;
604 seg->pages = pages;
605
606 if ( xc_dom_chk_alloc_pages(dom, name, pages) )
607 return -1;
608
609 /* map and clear pages */
610 ptr = xc_dom_seg_to_ptr(dom, seg);
611 if ( ptr == NULL )
612 return -1;
613 memset(ptr, 0, pages * page_size);
614
615 seg->vstart = start;
616 seg->vend = dom->virt_alloc_end;
617
618 DOMPRINTF("%-20s: %-12s : 0x%" PRIx64 " -> 0x%" PRIx64
619 " (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)",
620 __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages);
621
622 return 0;
623 }
624
xc_dom_alloc_page(struct xc_dom_image * dom,char * name)625 xen_pfn_t xc_dom_alloc_page(struct xc_dom_image *dom, char *name)
626 {
627 xen_vaddr_t start;
628 xen_pfn_t pfn;
629
630 start = dom->virt_alloc_end;
631 pfn = dom->pfn_alloc_end - dom->rambase_pfn;
632
633 if ( xc_dom_chk_alloc_pages(dom, name, 1) )
634 return INVALID_PFN;
635
636 DOMPRINTF("%-20s: %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")",
637 __FUNCTION__, name, start, pfn);
638 return pfn;
639 }
640
xc_dom_unmap_one(struct xc_dom_image * dom,xen_pfn_t pfn)641 void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn)
642 {
643 unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
644 struct xc_dom_phys *phys, *prev = NULL;
645
646 for ( phys = dom->phys_pages; phys != NULL; phys = phys->next )
647 {
648 if ( (pfn >= phys->first) && (pfn < (phys->first + phys->count)) )
649 break;
650 prev = phys;
651 }
652 if ( !phys )
653 {
654 DOMPRINTF("%s: Huh? no mapping with pfn 0x%" PRIpfn "",
655 __FUNCTION__, pfn);
656 return;
657 }
658
659 munmap(phys->ptr, phys->count << page_shift);
660 if ( prev )
661 prev->next = phys->next;
662 else
663 dom->phys_pages = phys->next;
664
665 xc_domain_cacheflush(dom->xch, dom->guest_domid, phys->first, phys->count);
666 }
667
xc_dom_unmap_all(struct xc_dom_image * dom)668 void xc_dom_unmap_all(struct xc_dom_image *dom)
669 {
670 while ( dom->phys_pages )
671 xc_dom_unmap_one(dom, dom->phys_pages->first);
672 }
673
674 /* ------------------------------------------------------------------------ */
675 /* pluggable kernel loaders */
676
677 static struct xc_dom_loader *first_loader = NULL;
678 static struct xc_dom_arch *first_hook = NULL;
679
xc_dom_register_loader(struct xc_dom_loader * loader)680 void xc_dom_register_loader(struct xc_dom_loader *loader)
681 {
682 loader->next = first_loader;
683 first_loader = loader;
684 }
685
xc_dom_find_loader(struct xc_dom_image * dom)686 static struct xc_dom_loader *xc_dom_find_loader(struct xc_dom_image *dom)
687 {
688 struct xc_dom_loader *loader = first_loader;
689
690 while ( loader != NULL )
691 {
692 DOMPRINTF("%s: trying %s loader ... ", __FUNCTION__, loader->name);
693 if ( loader->probe(dom) == 0 )
694 {
695 DOMPRINTF("loader probe OK");
696 return loader;
697 }
698 DOMPRINTF("loader probe failed");
699 loader = loader->next;
700 }
701 xc_dom_panic(dom->xch,
702 XC_INVALID_KERNEL, "%s: no loader found", __FUNCTION__);
703 return NULL;
704 }
705
xc_dom_register_arch_hooks(struct xc_dom_arch * hooks)706 void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks)
707 {
708 hooks->next = first_hook;
709 first_hook = hooks;
710 }
711
xc_dom_set_arch_hooks(struct xc_dom_image * dom)712 int xc_dom_set_arch_hooks(struct xc_dom_image *dom)
713 {
714 struct xc_dom_arch *hooks = first_hook;
715
716 while ( hooks != NULL )
717 {
718 if ( !strcmp(hooks->guest_type, dom->guest_type) )
719 {
720 if ( hooks->arch_private_size )
721 {
722 dom->arch_private = malloc(hooks->arch_private_size);
723 if ( dom->arch_private == NULL )
724 return -1;
725 memset(dom->arch_private, 0, hooks->arch_private_size);
726 dom->alloc_malloc += hooks->arch_private_size;
727 }
728 dom->arch_hooks = hooks;
729 return 0;
730 }
731 hooks = hooks->next;
732 }
733 xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
734 "%s: not found (type %s)", __FUNCTION__, dom->guest_type);
735 return -1;
736 }
737
738 /* ------------------------------------------------------------------------ */
739 /* public interface */
740
xc_dom_release(struct xc_dom_image * dom)741 void xc_dom_release(struct xc_dom_image *dom)
742 {
743 DOMPRINTF_CALLED(dom->xch);
744 if ( dom->phys_pages )
745 xc_dom_unmap_all(dom);
746 xc_dom_free_all(dom);
747 free(dom->arch_private);
748 free(dom);
749 }
750
xc_dom_allocate(xc_interface * xch,const char * cmdline,const char * features)751 struct xc_dom_image *xc_dom_allocate(xc_interface *xch,
752 const char *cmdline, const char *features)
753 {
754 struct xc_dom_image *dom;
755
756 xc_dom_printf(xch, "%s: cmdline=\"%s\", features=\"%s\"",
757 __FUNCTION__, cmdline ? cmdline : "",
758 features ? features : "");
759 dom = malloc(sizeof(*dom));
760 if ( !dom )
761 goto err;
762
763 memset(dom, 0, sizeof(*dom));
764 dom->xch = xch;
765
766 dom->max_kernel_size = XC_DOM_DECOMPRESS_MAX;
767 dom->max_module_size = XC_DOM_DECOMPRESS_MAX;
768 dom->max_devicetree_size = XC_DOM_DECOMPRESS_MAX;
769
770 if ( cmdline )
771 dom->cmdline = xc_dom_strdup(dom, cmdline);
772 if ( features )
773 elf_xen_parse_features(features, dom->f_requested, NULL);
774
775 dom->parms.virt_base = UNSET_ADDR;
776 dom->parms.virt_entry = UNSET_ADDR;
777 dom->parms.virt_hypercall = UNSET_ADDR;
778 dom->parms.virt_hv_start_low = UNSET_ADDR;
779 dom->parms.elf_paddr_offset = UNSET_ADDR;
780 dom->parms.p2m_base = UNSET_ADDR;
781
782 dom->flags = SIF_VIRT_P2M_4TOOLS;
783
784 dom->alloc_malloc += sizeof(*dom);
785 return dom;
786
787 err:
788 if ( dom )
789 xc_dom_release(dom);
790 return NULL;
791 }
792
xc_dom_kernel_max_size(struct xc_dom_image * dom,size_t sz)793 int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz)
794 {
795 DOMPRINTF("%s: kernel_max_size=%zx", __FUNCTION__, sz);
796 dom->max_kernel_size = sz;
797 return 0;
798 }
799
xc_dom_module_max_size(struct xc_dom_image * dom,size_t sz)800 int xc_dom_module_max_size(struct xc_dom_image *dom, size_t sz)
801 {
802 DOMPRINTF("%s: module_max_size=%zx", __FUNCTION__, sz);
803 dom->max_module_size = sz;
804 return 0;
805 }
806
xc_dom_devicetree_max_size(struct xc_dom_image * dom,size_t sz)807 int xc_dom_devicetree_max_size(struct xc_dom_image *dom, size_t sz)
808 {
809 DOMPRINTF("%s: devicetree_max_size=%zx", __FUNCTION__, sz);
810 dom->max_devicetree_size = sz;
811 return 0;
812 }
813
xc_dom_kernel_file(struct xc_dom_image * dom,const char * filename)814 int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
815 {
816 DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
817 dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size,
818 dom->max_kernel_size);
819 if ( dom->kernel_blob == NULL )
820 return -1;
821 return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
822 }
823
xc_dom_module_file(struct xc_dom_image * dom,const char * filename,const char * cmdline)824 int xc_dom_module_file(struct xc_dom_image *dom, const char *filename, const char *cmdline)
825 {
826 unsigned int mod = dom->num_modules++;
827
828 DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
829 dom->modules[mod].blob =
830 xc_dom_malloc_filemap(dom, filename, &dom->modules[mod].size,
831 dom->max_module_size);
832
833 if ( dom->modules[mod].blob == NULL )
834 return -1;
835
836 if ( cmdline )
837 {
838 dom->modules[mod].cmdline = xc_dom_strdup(dom, cmdline);
839
840 if ( dom->modules[mod].cmdline == NULL )
841 return -1;
842 }
843 else
844 {
845 dom->modules[mod].cmdline = NULL;
846 }
847
848 return 0;
849 }
850
xc_dom_devicetree_file(struct xc_dom_image * dom,const char * filename)851 int xc_dom_devicetree_file(struct xc_dom_image *dom, const char *filename)
852 {
853 #if defined (__arm__) || defined(__aarch64__)
854 DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
855 dom->devicetree_blob =
856 xc_dom_malloc_filemap(dom, filename, &dom->devicetree_size,
857 dom->max_devicetree_size);
858
859 if ( dom->devicetree_blob == NULL )
860 return -1;
861 return 0;
862 #else
863 errno = -EINVAL;
864 return -1;
865 #endif
866 }
867
xc_dom_kernel_mem(struct xc_dom_image * dom,const void * mem,size_t memsize)868 int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize)
869 {
870 DOMPRINTF_CALLED(dom->xch);
871 dom->kernel_blob = (void *)mem;
872 dom->kernel_size = memsize;
873 return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
874 }
875
xc_dom_module_mem(struct xc_dom_image * dom,const void * mem,size_t memsize,const char * cmdline)876 int xc_dom_module_mem(struct xc_dom_image *dom, const void *mem,
877 size_t memsize, const char *cmdline)
878 {
879 unsigned int mod = dom->num_modules++;
880
881 DOMPRINTF_CALLED(dom->xch);
882
883 dom->modules[mod].blob = (void *)mem;
884 dom->modules[mod].size = memsize;
885
886 if ( cmdline )
887 {
888 dom->modules[mod].cmdline = xc_dom_strdup(dom, cmdline);
889
890 if ( dom->modules[mod].cmdline == NULL )
891 return -1;
892 }
893 else
894 {
895 dom->modules[mod].cmdline = NULL;
896 }
897
898 return 0;
899 }
900
xc_dom_devicetree_mem(struct xc_dom_image * dom,const void * mem,size_t memsize)901 int xc_dom_devicetree_mem(struct xc_dom_image *dom, const void *mem,
902 size_t memsize)
903 {
904 DOMPRINTF_CALLED(dom->xch);
905 dom->devicetree_blob = (void *)mem;
906 dom->devicetree_size = memsize;
907 return 0;
908 }
909
xc_dom_parse_image(struct xc_dom_image * dom)910 int xc_dom_parse_image(struct xc_dom_image *dom)
911 {
912 int i;
913
914 DOMPRINTF_CALLED(dom->xch);
915
916 /* parse kernel image */
917 dom->kernel_loader = xc_dom_find_loader(dom);
918 if ( dom->kernel_loader == NULL )
919 goto err;
920 if ( dom->kernel_loader->parser(dom) != 0 )
921 goto err;
922 if ( dom->guest_type == NULL )
923 {
924 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
925 "%s: guest_type not set", __FUNCTION__);
926 goto err;
927 }
928
929 /* check features */
930 for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
931 {
932 dom->f_active[i] |= dom->f_requested[i]; /* cmd line */
933 dom->f_active[i] |= dom->parms.f_required[i]; /* kernel */
934 if ( (dom->f_active[i] & dom->parms.f_supported[i]) !=
935 dom->f_active[i] )
936 {
937 xc_dom_panic(dom->xch, XC_INVALID_PARAM,
938 "%s: unsupported feature requested", __FUNCTION__);
939 goto err;
940 }
941 }
942 return 0;
943
944 err:
945 return -1;
946 }
947
xc_dom_rambase_init(struct xc_dom_image * dom,uint64_t rambase)948 int xc_dom_rambase_init(struct xc_dom_image *dom, uint64_t rambase)
949 {
950 dom->rambase_pfn = rambase >> XC_PAGE_SHIFT;
951 dom->pfn_alloc_end = dom->rambase_pfn;
952 DOMPRINTF("%s: RAM starts at %"PRI_xen_pfn,
953 __FUNCTION__, dom->rambase_pfn);
954 return 0;
955 }
956
xc_dom_mem_init(struct xc_dom_image * dom,unsigned int mem_mb)957 int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb)
958 {
959 unsigned int page_shift;
960 xen_pfn_t nr_pages;
961
962 if ( xc_dom_set_arch_hooks(dom) )
963 {
964 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: arch hooks not set",
965 __FUNCTION__);
966 return -1;
967 }
968
969 page_shift = XC_DOM_PAGE_SHIFT(dom);
970 nr_pages = mem_mb << (20 - page_shift);
971
972 DOMPRINTF("%s: mem %d MB, pages 0x%" PRIpfn " pages, %dk each",
973 __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10));
974 dom->total_pages = nr_pages;
975
976 DOMPRINTF("%s: 0x%" PRIpfn " pages",
977 __FUNCTION__, dom->total_pages);
978
979 return 0;
980 }
981
xc_dom_update_guest_p2m(struct xc_dom_image * dom)982 int xc_dom_update_guest_p2m(struct xc_dom_image *dom)
983 {
984 uint32_t *p2m_32;
985 uint64_t *p2m_64;
986 xen_pfn_t i;
987
988 if ( !dom->p2m_guest )
989 return 0;
990
991 switch ( dom->arch_hooks->sizeof_pfn )
992 {
993 case 4:
994 DOMPRINTF("%s: dst 32bit, pages 0x%" PRIpfn "",
995 __FUNCTION__, dom->p2m_size);
996 p2m_32 = dom->p2m_guest;
997 for ( i = 0; i < dom->p2m_size; i++ )
998 if ( dom->p2m_host[i] != INVALID_PFN )
999 p2m_32[i] = dom->p2m_host[i];
1000 else
1001 p2m_32[i] = (uint32_t) - 1;
1002 break;
1003 case 8:
1004 DOMPRINTF("%s: dst 64bit, pages 0x%" PRIpfn "",
1005 __FUNCTION__, dom->p2m_size);
1006 p2m_64 = dom->p2m_guest;
1007 for ( i = 0; i < dom->p2m_size; i++ )
1008 if ( dom->p2m_host[i] != INVALID_PFN )
1009 p2m_64[i] = dom->p2m_host[i];
1010 else
1011 p2m_64[i] = (uint64_t) - 1;
1012 break;
1013 default:
1014 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
1015 "sizeof_pfn is invalid (is %d, can be 4 or 8)",
1016 dom->arch_hooks->sizeof_pfn);
1017 return -1;
1018 }
1019 return 0;
1020 }
1021
xc_dom_build_module(struct xc_dom_image * dom,unsigned int mod)1022 static int xc_dom_build_module(struct xc_dom_image *dom, unsigned int mod)
1023 {
1024 size_t unziplen, modulelen;
1025 void *modulemap;
1026 char name[10];
1027
1028 if ( !dom->modules[mod].seg.vstart )
1029 {
1030 unziplen = xc_dom_check_gzip(dom->xch,
1031 dom->modules[mod].blob, dom->modules[mod].size);
1032 if ( xc_dom_module_check_size(dom, unziplen) != 0 )
1033 unziplen = 0;
1034 }
1035 else
1036 unziplen = 0;
1037
1038 modulelen = unziplen ? unziplen : dom->modules[mod].size;
1039 snprintf(name, sizeof(name), "module%u", mod);
1040 if ( xc_dom_alloc_segment(dom, &dom->modules[mod].seg, name,
1041 dom->modules[mod].seg.vstart, modulelen) != 0 )
1042 goto err;
1043 modulemap = xc_dom_seg_to_ptr(dom, &dom->modules[mod].seg);
1044 if ( modulemap == NULL )
1045 {
1046 DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->modules[%u].seg) => NULL",
1047 __FUNCTION__, mod);
1048 goto err;
1049 }
1050 if ( unziplen )
1051 {
1052 if ( xc_dom_do_gunzip(dom->xch, dom->modules[mod].blob, dom->modules[mod].size,
1053 modulemap, modulelen) == -1 )
1054 goto err;
1055 }
1056 else
1057 memcpy(modulemap, dom->modules[mod].blob, dom->modules[mod].size);
1058
1059 return 0;
1060
1061 err:
1062 return -1;
1063 }
1064
populate_acpi_pages(struct xc_dom_image * dom,xen_pfn_t * extents,unsigned int num_pages)1065 static int populate_acpi_pages(struct xc_dom_image *dom,
1066 xen_pfn_t *extents,
1067 unsigned int num_pages)
1068 {
1069 int rc;
1070 xc_interface *xch = dom->xch;
1071 uint32_t domid = dom->guest_domid;
1072 unsigned long idx;
1073 unsigned long first_high_idx = 4UL << (30 - PAGE_SHIFT); /* 4GB */
1074
1075 for ( ; num_pages; num_pages--, extents++ )
1076 {
1077
1078 if ( xc_domain_populate_physmap(xch, domid, 1, 0, 0, extents) == 1 )
1079 continue;
1080
1081 if ( dom->highmem_end )
1082 {
1083 idx = --dom->highmem_end;
1084 if ( idx == first_high_idx )
1085 dom->highmem_end = 0;
1086 }
1087 else
1088 {
1089 idx = --dom->lowmem_end;
1090 }
1091
1092 rc = xc_domain_add_to_physmap(xch, domid,
1093 XENMAPSPACE_gmfn,
1094 idx, *extents);
1095 if ( rc )
1096 return rc;
1097 }
1098
1099 return 0;
1100 }
1101
xc_dom_load_acpi(struct xc_dom_image * dom)1102 static int xc_dom_load_acpi(struct xc_dom_image *dom)
1103 {
1104 int j, i = 0;
1105 unsigned num_pages;
1106 xen_pfn_t *extents, base;
1107 void *ptr;
1108
1109 while ( (i < MAX_ACPI_MODULES) && dom->acpi_modules[i].length )
1110 {
1111 DOMPRINTF("%s: %d bytes at address %" PRIx64, __FUNCTION__,
1112 dom->acpi_modules[i].length,
1113 dom->acpi_modules[i].guest_addr_out);
1114
1115 num_pages = (dom->acpi_modules[i].length +
1116 (dom->acpi_modules[i].guest_addr_out & ~XC_PAGE_MASK) +
1117 (XC_PAGE_SIZE - 1)) >> XC_PAGE_SHIFT;
1118 extents = malloc(num_pages * sizeof(*extents));
1119 if ( !extents )
1120 {
1121 DOMPRINTF("%s: Out of memory", __FUNCTION__);
1122 goto err;
1123 }
1124
1125 base = dom->acpi_modules[i].guest_addr_out >> XC_PAGE_SHIFT;
1126 for ( j = 0; j < num_pages; j++ )
1127 extents[j] = base + j;
1128 if ( populate_acpi_pages(dom, extents, num_pages) )
1129 {
1130 DOMPRINTF("%s: Can populate ACPI pages", __FUNCTION__);
1131 goto err;
1132 }
1133
1134 ptr = xc_map_foreign_range(dom->xch, dom->guest_domid,
1135 XC_PAGE_SIZE * num_pages,
1136 PROT_READ | PROT_WRITE, base);
1137 if ( !ptr )
1138 {
1139 DOMPRINTF("%s: Can't map %d pages at 0x%"PRI_xen_pfn,
1140 __FUNCTION__, num_pages, base);
1141 goto err;
1142 }
1143
1144 memcpy((uint8_t *)ptr +
1145 (dom->acpi_modules[i].guest_addr_out & ~XC_PAGE_MASK),
1146 dom->acpi_modules[i].data, dom->acpi_modules[i].length);
1147 munmap(ptr, XC_PAGE_SIZE * num_pages);
1148
1149 free(extents);
1150 i++;
1151 }
1152
1153 return 0;
1154
1155 err:
1156 free(extents);
1157 return -1;
1158 }
1159
xc_dom_build_image(struct xc_dom_image * dom)1160 int xc_dom_build_image(struct xc_dom_image *dom)
1161 {
1162 unsigned int page_size;
1163 bool unmapped_initrd;
1164 unsigned int mod;
1165
1166 DOMPRINTF_CALLED(dom->xch);
1167
1168 /* check for arch hooks */
1169 if ( dom->arch_hooks == NULL )
1170 {
1171 xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: arch hooks not set",
1172 __FUNCTION__);
1173 goto err;
1174 }
1175 page_size = XC_DOM_PAGE_SIZE(dom);
1176 if ( dom->parms.virt_base != UNSET_ADDR )
1177 dom->virt_alloc_end = dom->parms.virt_base;
1178
1179 /* load kernel */
1180 if ( xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel",
1181 dom->kernel_seg.vstart,
1182 dom->kernel_seg.vend -
1183 dom->kernel_seg.vstart) != 0 )
1184 goto err;
1185 if ( dom->kernel_loader->loader(dom) != 0 )
1186 goto err;
1187
1188 /* Don't load ramdisk / other modules now if no initial mapping required. */
1189 for ( mod = 0; mod < dom->num_modules; mod++ )
1190 {
1191 unmapped_initrd = (dom->parms.unmapped_initrd &&
1192 !dom->modules[mod].seg.vstart);
1193
1194 if ( dom->modules[mod].blob && !unmapped_initrd )
1195 {
1196 if ( xc_dom_build_module(dom, mod) != 0 )
1197 goto err;
1198
1199 if ( mod == 0 )
1200 {
1201 dom->initrd_start = dom->modules[mod].seg.vstart;
1202 dom->initrd_len =
1203 dom->modules[mod].seg.vend - dom->modules[mod].seg.vstart;
1204 }
1205 }
1206 }
1207
1208 /* load devicetree */
1209 if ( dom->devicetree_blob )
1210 {
1211 void *devicetreemap;
1212
1213 if ( xc_dom_alloc_segment(dom, &dom->devicetree_seg, "devicetree",
1214 dom->devicetree_seg.vstart,
1215 dom->devicetree_size) != 0 )
1216 goto err;
1217 devicetreemap = xc_dom_seg_to_ptr(dom, &dom->devicetree_seg);
1218 if ( devicetreemap == NULL )
1219 {
1220 DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->devicetree_seg) => NULL",
1221 __FUNCTION__);
1222 goto err;
1223 }
1224 memcpy(devicetreemap, dom->devicetree_blob, dom->devicetree_size);
1225 }
1226
1227 /* load ACPI tables */
1228 if ( xc_dom_load_acpi(dom) != 0 )
1229 goto err;
1230
1231 /* allocate other pages */
1232 if ( !dom->arch_hooks->p2m_base_supported ||
1233 dom->parms.p2m_base >= dom->parms.virt_base ||
1234 (dom->parms.p2m_base & (XC_DOM_PAGE_SIZE(dom) - 1)) )
1235 dom->parms.p2m_base = UNSET_ADDR;
1236 if ( dom->arch_hooks->alloc_p2m_list && dom->parms.p2m_base == UNSET_ADDR &&
1237 dom->arch_hooks->alloc_p2m_list(dom) != 0 )
1238 goto err;
1239 if ( dom->arch_hooks->alloc_magic_pages(dom) != 0 )
1240 goto err;
1241 if ( dom->arch_hooks->alloc_pgtables(dom) != 0 )
1242 goto err;
1243 if ( dom->alloc_bootstack )
1244 {
1245 dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack");
1246 if ( dom->bootstack_pfn == INVALID_PFN )
1247 goto err;
1248 }
1249
1250 DOMPRINTF("%-20s: virt_alloc_end : 0x%" PRIx64 "",
1251 __FUNCTION__, dom->virt_alloc_end);
1252 DOMPRINTF("%-20s: virt_pgtab_end : 0x%" PRIx64 "",
1253 __FUNCTION__, dom->virt_pgtab_end);
1254
1255 /* Make sure all memory mapped by initial page tables is available */
1256 if ( dom->virt_pgtab_end && xc_dom_alloc_pad(dom, dom->virt_pgtab_end) )
1257 return -1;
1258
1259 for ( mod = 0; mod < dom->num_modules; mod++ )
1260 {
1261 unmapped_initrd = (dom->parms.unmapped_initrd &&
1262 !dom->modules[mod].seg.vstart);
1263
1264 /* Load ramdisk / other modules if no initial mapping required. */
1265 if ( dom->modules[mod].blob && unmapped_initrd )
1266 {
1267 if ( xc_dom_build_module(dom, mod) != 0 )
1268 goto err;
1269
1270 if ( mod == 0 )
1271 {
1272 dom->flags |= SIF_MOD_START_PFN;
1273 dom->initrd_start = dom->modules[mod].seg.pfn;
1274 dom->initrd_len = page_size * dom->modules[mod].seg.pages;
1275 }
1276 }
1277 }
1278
1279 /* Allocate p2m list if outside of initial kernel mapping. */
1280 if ( dom->arch_hooks->alloc_p2m_list && dom->parms.p2m_base != UNSET_ADDR )
1281 {
1282 if ( dom->arch_hooks->alloc_p2m_list(dom) != 0 )
1283 goto err;
1284 dom->p2m_seg.vstart = dom->parms.p2m_base;
1285 }
1286
1287 return 0;
1288
1289 err:
1290 return -1;
1291 }
1292
1293 /*
1294 * Local variables:
1295 * mode: C
1296 * c-file-style: "BSD"
1297 * c-basic-offset: 4
1298 * tab-width: 4
1299 * indent-tabs-mode: nil
1300 * End:
1301 */
1302