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