ia64/xen-unstable

view tools/libxc/ia64/xc_ia64_hvm_build.c @ 15415:38d061886873

[IA64] Fix incorrect NVRAM saving if domain is destroyed by config error

Nvram saving is always executed even if a domain is destroyed by a
configuration parameter error. In this case, Nvram saving function
will get a bad address for the NVRAM data and save garbage into the
NVRAM file. Configuring a wrong vif parameter can expose this issue.

This patch fixes the issue by adding an address check function in
NVRAM saving path.

Signed-off-by: Zhang Xin <xing.z.zhang@intel.com>
author Alex Williamson <alex.williamson@hp.com>
date Mon Jul 02 09:05:24 2007 -0600 (2007-07-02)
parents fd0103b55504
children 6644d8486266
line source
1 #include <asm/kregs.h>
2 #include "xg_private.h"
3 #include "xenguest.h"
4 #include "xc_private.h"
5 #include "xc_elf.h"
6 #include "xc_efi.h"
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <zlib.h>
10 #include "xen/arch-ia64.h"
11 #include <xen/hvm/ioreq.h>
12 #include <xen/hvm/params.h>
14 static int
15 xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid, void* src_page,
16 unsigned long dst_pfn, int nr_pages)
17 {
18 // N.B. gva should be page aligned
19 int i;
21 for (i = 0; i < nr_pages; i++) {
22 if (xc_copy_to_domain_page(xc_handle, domid, dst_pfn + i,
23 src_page + (i << PAGE_SHIFT)))
24 return -1;
25 }
27 return 0;
28 }
30 int
31 xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value)
32 {
33 DECLARE_HYPERCALL;
34 xen_hvm_param_t arg;
35 int rc;
37 hypercall.op = __HYPERVISOR_hvm_op;
38 hypercall.arg[0] = HVMOP_set_param;
39 hypercall.arg[1] = (unsigned long)&arg;
41 arg.domid = dom;
42 arg.index = param;
43 arg.value = value;
45 if (lock_pages(&arg, sizeof(arg)) != 0)
46 return -1;
48 rc = do_xen_hypercall(handle, &hypercall);
49 unlock_pages(&arg, sizeof(arg));
51 return rc;
52 }
54 int
55 xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value)
56 {
57 DECLARE_HYPERCALL;
58 xen_hvm_param_t arg;
59 int rc;
61 hypercall.op = __HYPERVISOR_hvm_op;
62 hypercall.arg[0] = HVMOP_get_param;
63 hypercall.arg[1] = (unsigned long)&arg;
65 arg.domid = dom;
66 arg.index = param;
68 if (lock_pages(&arg, sizeof(arg)) != 0)
69 return -1;
71 rc = do_xen_hypercall(handle, &hypercall);
72 unlock_pages(&arg, sizeof(arg));
74 *value = arg.value;
75 return rc;
76 }
78 #define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64"
79 #define GFW_HOB_START ((4UL<<30)-(14UL<<20)) // 4G - 14M
80 #define GFW_HOB_SIZE (1UL<<20) // 1M
82 typedef struct {
83 unsigned long signature;
84 unsigned int type;
85 unsigned int length;
86 } HOB_GENERIC_HEADER;
88 /*
89 * INFO HOB is the first data data in one HOB list
90 * it contains the control information of the HOB list
91 */
92 typedef struct {
93 HOB_GENERIC_HEADER header;
94 unsigned long length; // current length of hob
95 unsigned long cur_pos; // current poisiton of hob
96 unsigned long buf_size; // size of hob buffer
97 } HOB_INFO;
99 typedef struct{
100 unsigned long start;
101 unsigned long size;
102 } hob_mem_t;
104 typedef enum {
105 HOB_TYPE_INFO=0,
106 HOB_TYPE_TERMINAL,
107 HOB_TYPE_MEM,
108 HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
109 HOB_TYPE_PAL_CACHE_SUMMARY,
110 HOB_TYPE_PAL_MEM_ATTRIB,
111 HOB_TYPE_PAL_CACHE_INFO,
112 HOB_TYPE_PAL_CACHE_PROT_INFO,
113 HOB_TYPE_PAL_DEBUG_INFO,
114 HOB_TYPE_PAL_FIXED_ADDR,
115 HOB_TYPE_PAL_FREQ_BASE,
116 HOB_TYPE_PAL_FREQ_RATIOS,
117 HOB_TYPE_PAL_HALT_INFO,
118 HOB_TYPE_PAL_PERF_MON_INFO,
119 HOB_TYPE_PAL_PROC_GET_FEATURES,
120 HOB_TYPE_PAL_PTCE_INFO,
121 HOB_TYPE_PAL_REGISTER_INFO,
122 HOB_TYPE_PAL_RSE_INFO,
123 HOB_TYPE_PAL_TEST_INFO,
124 HOB_TYPE_PAL_VM_SUMMARY,
125 HOB_TYPE_PAL_VM_INFO,
126 HOB_TYPE_PAL_VM_PAGE_SIZE,
127 HOB_TYPE_NR_VCPU,
128 HOB_TYPE_NVRAM,
129 HOB_TYPE_MAX
130 } hob_type_t;
132 static int hob_init(void *buffer ,unsigned long buf_size);
133 static int add_pal_hob(void* hob_buf);
134 static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
135 static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu);
136 static int add_nvram_hob(void* hob_buf, unsigned long nvram_addr);
137 static int build_hob(void* hob_buf, unsigned long hob_buf_size,
138 unsigned long dom_mem_size, unsigned long vcpus,
139 unsigned long nvram_addr);
140 static int load_hob(int xc_handle,uint32_t dom, void *hob_buf,
141 unsigned long dom_mem_size);
143 static int
144 xc_ia64_build_hob(int xc_handle, uint32_t dom,
145 unsigned long memsize, unsigned long vcpus,
146 unsigned long nvram_addr)
147 {
148 char *hob_buf;
150 hob_buf = malloc(GFW_HOB_SIZE);
151 if (hob_buf == NULL) {
152 PERROR("Could not allocate hob");
153 return -1;
154 }
156 if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) {
157 free(hob_buf);
158 PERROR("Could not build hob");
159 return -1;
160 }
162 if (load_hob(xc_handle, dom, hob_buf, memsize) < 0) {
163 free(hob_buf);
164 PERROR("Could not load hob");
165 return -1;
166 }
167 free(hob_buf);
168 return 0;
170 }
172 static int
173 hob_init(void *buffer, unsigned long buf_size)
174 {
175 HOB_INFO *phit;
176 HOB_GENERIC_HEADER *terminal;
178 if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
179 // buffer too small
180 return -1;
181 }
183 phit = (HOB_INFO*)buffer;
184 phit->header.signature = HOB_SIGNATURE;
185 phit->header.type = HOB_TYPE_INFO;
186 phit->header.length = sizeof(HOB_INFO);
187 phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
188 phit->cur_pos = 0;
189 phit->buf_size = buf_size;
191 terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO));
192 terminal->signature = HOB_SIGNATURE;
193 terminal->type = HOB_TYPE_TERMINAL;
194 terminal->length = sizeof(HOB_GENERIC_HEADER);
196 return 0;
197 }
199 /*
200 * Add a new HOB to the HOB List.
201 *
202 * hob_start - start address of hob buffer
203 * type - type of the hob to be added
204 * data - data of the hob to be added
205 * data_size - size of the data
206 */
207 static int
208 hob_add(void* hob_start, int type, void* data, int data_size)
209 {
210 HOB_INFO *phit;
211 HOB_GENERIC_HEADER *newhob, *tail;
213 phit = (HOB_INFO*)hob_start;
215 if (phit->length + data_size > phit->buf_size) {
216 // no space for new hob
217 return -1;
218 }
220 //append new HOB
221 newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
222 sizeof(HOB_GENERIC_HEADER));
223 newhob->signature = HOB_SIGNATURE;
224 newhob->type = type;
225 newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
226 memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
228 // append terminal HOB
229 tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size);
230 tail->signature = HOB_SIGNATURE;
231 tail->type = HOB_TYPE_TERMINAL;
232 tail->length = sizeof(HOB_GENERIC_HEADER);
234 // adjust HOB list length
235 phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
237 return 0;
238 }
240 static int
241 get_hob_size(void* hob_buf)
242 {
243 HOB_INFO *phit = (HOB_INFO*)hob_buf;
245 if (phit->header.signature != HOB_SIGNATURE) {
246 PERROR("xc_get_hob_size:Incorrect signature");
247 return -1;
248 }
249 return phit->length;
250 }
252 static int
253 build_hob(void* hob_buf, unsigned long hob_buf_size,
254 unsigned long dom_mem_size, unsigned long vcpus,
255 unsigned long nvram_addr)
256 {
257 //Init HOB List
258 if (hob_init(hob_buf, hob_buf_size) < 0) {
259 PERROR("buffer too small");
260 goto err_out;
261 }
263 if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
264 PERROR("Add memory hob failed, buffer too small");
265 goto err_out;
266 }
268 if (add_vcpus_hob(hob_buf, vcpus) < 0) {
269 PERROR("Add NR_VCPU hob failed, buffer too small");
270 goto err_out;
271 }
273 if (add_pal_hob( hob_buf ) < 0) {
274 PERROR("Add PAL hob failed, buffer too small");
275 goto err_out;
276 }
278 if (add_nvram_hob( hob_buf, nvram_addr ) < 0) {
279 PERROR("Add nvram hob failed, buffer too small");
280 goto err_out;
281 }
283 return 0;
285 err_out:
286 return -1;
287 }
289 static int
290 load_hob(int xc_handle, uint32_t dom, void *hob_buf,
291 unsigned long dom_mem_size)
292 {
293 // hob_buf should be page aligned
294 int hob_size;
295 int nr_pages;
297 hob_size = get_hob_size(hob_buf);
298 if (hob_size < 0) {
299 PERROR("Invalid hob data");
300 return -1;
301 }
303 if (hob_size > GFW_HOB_SIZE) {
304 PERROR("No enough memory for hob data");
305 return -1;
306 }
308 nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT;
310 return xc_ia64_copy_to_domain_pages(xc_handle, dom, hob_buf,
311 GFW_HOB_START >> PAGE_SHIFT, nr_pages);
312 }
314 #define MIN(x, y) ((x) < (y)) ? (x) : (y)
315 static int
316 add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
317 {
318 hob_mem_t memhob;
320 // less than 3G
321 memhob.start = 0;
322 memhob.size = MIN(dom_mem_size, 0xC0000000);
324 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
325 return -1;
327 if (dom_mem_size > 0xC0000000) {
328 // 4G ~ 4G+remain
329 memhob.start = 0x100000000; //4G
330 memhob.size = dom_mem_size - 0xC0000000;
331 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
332 return -1;
333 }
334 return 0;
335 }
337 static int
338 add_vcpus_hob(void* hob_buf, unsigned long vcpus)
339 {
340 return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
341 }
343 static int
344 add_nvram_hob(void *hob_buf, unsigned long nvram_addr)
345 {
346 return hob_add(hob_buf, HOB_TYPE_NVRAM, &nvram_addr, sizeof(nvram_addr));
347 }
349 static const unsigned char config_pal_bus_get_features_data[24] = {
350 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
352 };
354 static const unsigned char config_pal_cache_summary[16] = {
355 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
356 };
358 static const unsigned char config_pal_mem_attrib[8] = {
359 241, 0, 0, 0, 0, 0, 0, 0
360 };
362 static const unsigned char config_pal_cache_info[152] = {
363 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
364 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
365 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
366 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
367 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
368 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
369 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
370 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
371 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
372 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
373 };
375 static const unsigned char config_pal_cache_prot_info[200] = {
376 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
377 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
379 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
380 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
381 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
383 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
384 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
385 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
387 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
388 0, 0, 0
389 };
391 static const unsigned char config_pal_debug_info[16] = {
392 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
393 };
395 static const unsigned char config_pal_fixed_addr[8] = {
396 0, 0, 0, 0, 0, 0, 0, 0
397 };
399 static const unsigned char config_pal_freq_base[8] = {
400 109, 219, 182, 13, 0, 0, 0, 0
401 };
403 static const unsigned char config_pal_freq_ratios[24] = {
404 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
405 0, 0, 0, 7, 0, 0, 0
406 };
408 static const unsigned char config_pal_halt_info[64] = {
409 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
413 };
415 static const unsigned char config_pal_perf_mon_info[136] = {
416 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
417 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
420 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
422 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
424 0, 0, 0, 0, 0, 0, 0, 0
425 };
427 static const unsigned char config_pal_proc_get_features[104] = {
428 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
429 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
430 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
431 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
432 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
433 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
434 0, 0, 0, 0, 0, 0, 0, 0
435 };
437 static const unsigned char config_pal_ptce_info[24] = {
438 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
439 0, 0, 0, 0, 0, 0, 0, 0
440 };
442 static const unsigned char config_pal_register_info[64] = {
443 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
444 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
445 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
446 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
447 };
449 static const unsigned char config_pal_rse_info[16] = {
450 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
451 };
453 static const unsigned char config_pal_test_info[48] = {
454 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
457 };
459 static const unsigned char config_pal_vm_summary[16] = {
460 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
461 };
463 static const unsigned char config_pal_vm_info[104] = {
464 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
465 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
466 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
467 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
468 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
469 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
470 };
472 static const unsigned char config_pal_vm_page_size[16] = {
473 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
474 };
476 typedef struct{
477 hob_type_t type;
478 void* data;
479 unsigned long size;
480 } hob_batch_t;
482 static const hob_batch_t hob_batch[]={
483 { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
484 &config_pal_bus_get_features_data,
485 sizeof(config_pal_bus_get_features_data)
486 },
487 { HOB_TYPE_PAL_CACHE_SUMMARY,
488 &config_pal_cache_summary,
489 sizeof(config_pal_cache_summary)
490 },
491 { HOB_TYPE_PAL_MEM_ATTRIB,
492 &config_pal_mem_attrib,
493 sizeof(config_pal_mem_attrib)
494 },
495 { HOB_TYPE_PAL_CACHE_INFO,
496 &config_pal_cache_info,
497 sizeof(config_pal_cache_info)
498 },
499 { HOB_TYPE_PAL_CACHE_PROT_INFO,
500 &config_pal_cache_prot_info,
501 sizeof(config_pal_cache_prot_info)
502 },
503 { HOB_TYPE_PAL_DEBUG_INFO,
504 &config_pal_debug_info,
505 sizeof(config_pal_debug_info)
506 },
507 { HOB_TYPE_PAL_FIXED_ADDR,
508 &config_pal_fixed_addr,
509 sizeof(config_pal_fixed_addr)
510 },
511 { HOB_TYPE_PAL_FREQ_BASE,
512 &config_pal_freq_base,
513 sizeof(config_pal_freq_base)
514 },
515 { HOB_TYPE_PAL_FREQ_RATIOS,
516 &config_pal_freq_ratios,
517 sizeof(config_pal_freq_ratios)
518 },
519 { HOB_TYPE_PAL_HALT_INFO,
520 &config_pal_halt_info,
521 sizeof(config_pal_halt_info)
522 },
523 { HOB_TYPE_PAL_PERF_MON_INFO,
524 &config_pal_perf_mon_info,
525 sizeof(config_pal_perf_mon_info)
526 },
527 { HOB_TYPE_PAL_PROC_GET_FEATURES,
528 &config_pal_proc_get_features,
529 sizeof(config_pal_proc_get_features)
530 },
531 { HOB_TYPE_PAL_PTCE_INFO,
532 &config_pal_ptce_info,
533 sizeof(config_pal_ptce_info)
534 },
535 { HOB_TYPE_PAL_REGISTER_INFO,
536 &config_pal_register_info,
537 sizeof(config_pal_register_info)
538 },
539 { HOB_TYPE_PAL_RSE_INFO,
540 &config_pal_rse_info,
541 sizeof(config_pal_rse_info)
542 },
543 { HOB_TYPE_PAL_TEST_INFO,
544 &config_pal_test_info,
545 sizeof(config_pal_test_info)
546 },
547 { HOB_TYPE_PAL_VM_SUMMARY,
548 &config_pal_vm_summary,
549 sizeof(config_pal_vm_summary)
550 },
551 { HOB_TYPE_PAL_VM_INFO,
552 &config_pal_vm_info,
553 sizeof(config_pal_vm_info)
554 },
555 { HOB_TYPE_PAL_VM_PAGE_SIZE,
556 &config_pal_vm_page_size,
557 sizeof(config_pal_vm_page_size)
558 },
559 };
561 static int
562 add_pal_hob(void* hob_buf)
563 {
564 int i;
565 for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) {
566 if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data,
567 hob_batch[i].size) < 0)
568 return -1;
569 }
570 return 0;
571 }
573 // The most significant bit of nvram file descriptor:
574 // 1: valid; 0: invalid
575 #define VALIDATE_NVRAM_FD(x) ((1UL<<(sizeof(x)*8 - 1)) | x)
576 #define IS_VALID_NVRAM_FD(x) ((uint64_t)x >> (sizeof(x)*8 - 1))
577 static uint64_t
578 nvram_init(const char *nvram_path)
579 {
580 uint64_t fd = 0;
581 fd = open(nvram_path, O_CREAT|O_RDWR, 0644);
583 if ( fd < 0 )
584 {
585 PERROR("Nvram open failed at %s. Guest will boot without"
586 " nvram support!\n", nvram_path);
587 return -1;
588 }
590 return VALIDATE_NVRAM_FD(fd);
591 }
593 static int
594 copy_from_nvram_to_GFW(int xc_handle, uint32_t dom, int nvram_fd)
595 {
596 unsigned int nr_pages = NVRAM_SIZE >> PAGE_SHIFT;
597 struct stat file_stat;
598 char buf[NVRAM_SIZE] = {0};
600 if ( fstat(nvram_fd, &file_stat) < 0 )
601 {
602 PERROR("Cannot get Nvram file info! Guest will boot without "
603 "nvram support!\n");
604 return -1;
605 }
607 if ( 0 == file_stat.st_size )
608 {
609 DPRINTF("Nvram file create successful!\n");
610 return 0;
611 }
613 if ( read(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE )
614 {
615 PERROR("Load nvram fail. guest will boot without"
616 " nvram support!\n");
617 return -1;
618 }
620 return xc_ia64_copy_to_domain_pages(xc_handle, dom, buf,
621 NVRAM_START >> PAGE_SHIFT, nr_pages);
622 }
625 /*
626 *Check is the address where NVRAM data located valid
627 */
628 static int is_valid_address(void *addr)
629 {
630 struct nvram_save_addr *p = (struct nvram_save_addr *)addr;
632 if ( p->signature == NVRAM_VALID_SIG )
633 return 1;
634 else {
635 PERROR("Invalid nvram signature. Nvram save failed!\n");
636 return 0;
637 }
638 }
640 /*
641 * GFW use 4k page. when doing foreign map, we should 16k align
642 * the address and map one more page to guarantee all 64k nvram data
643 * can be got.
644 */
645 static int
646 copy_from_GFW_to_nvram(int xc_handle, uint32_t dom, int nvram_fd)
647 {
648 xen_pfn_t *pfn_list = NULL;
649 char *tmp_ptr = NULL;
650 unsigned int nr_pages = 0;
651 uint64_t addr_from_GFW_4k_align = 0;
652 uint32_t offset = 0;
653 uint64_t nvram_base_addr = 0;
654 char buf[NVRAM_SIZE] = {0};
655 int i;
657 // map one more page
658 nr_pages = (NVRAM_SIZE + PAGE_SIZE) >> PAGE_SHIFT;
659 pfn_list = (xen_pfn_t *)malloc(sizeof(xen_pfn_t) * nr_pages);
660 if ( NULL == pfn_list )
661 {
662 PERROR("Cannot allocate memory for nvram save!\n");
663 close(nvram_fd);
664 return -1;
665 }
667 /*
668 * GFW allocate memory dynamicly to save nvram data
669 * and save address of the dynamic memory at NVRAM_START.
670 * To save nvram data to file, we must get the dynamic
671 * memory address first.
672 */
673 pfn_list[0] = NVRAM_START >> PAGE_SHIFT;
674 tmp_ptr = (char *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
675 PROT_READ | PROT_WRITE, pfn_list[0]);
677 if ( NULL == tmp_ptr )
678 {
679 PERROR("Cannot get nvram data from GFW!\n");
680 free(pfn_list);
681 close(nvram_fd);
682 return -1;
683 }
685 /* Check is NVRAM data vaild */
686 if ( !is_valid_address(tmp_ptr) )
687 return -1;
689 addr_from_GFW_4k_align = ((struct nvram_save_addr *)tmp_ptr)->addr;
690 munmap(tmp_ptr, PAGE_SIZE);
692 // align address to 16k
693 offset = addr_from_GFW_4k_align % ( 16 * MEM_K );
694 addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset;
695 for ( i=0; i<nr_pages; i++ )
696 pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i;
698 tmp_ptr = (char *)xc_map_foreign_batch(xc_handle, dom,
699 PROT_READ | PROT_WRITE, pfn_list, nr_pages);
700 if ( NULL == tmp_ptr )
701 {
702 PERROR("Cannot get nvram data from GFW!\n");
703 free(pfn_list);
704 close(nvram_fd);
705 return -1;
706 }
708 // calculate nvram data base addrees
709 nvram_base_addr = (uint64_t)(tmp_ptr + offset);
711 memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE);
712 free(pfn_list);
713 munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE);
715 lseek(nvram_fd, 0, SEEK_SET);
716 if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE )
717 {
718 PERROR("Save to nvram fail!\n");
719 return -1;
720 }
722 close(nvram_fd);
724 DPRINTF("Nvram save successful!\n");
726 return 0;
727 }
729 int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom)
730 {
731 xc_dominfo_t info;
732 uint64_t nvram_fd = 0;
734 if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 )
735 {
736 PERROR("Could not get info for domain");
737 return -1;
738 }
740 if ( !info.hvm )
741 return 0;
743 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd);
745 if ( !IS_VALID_NVRAM_FD(nvram_fd) )
746 PERROR("Nvram not initialized. Nvram save failed!\n");
747 else
748 copy_from_GFW_to_nvram(xc_handle, dom, (int)nvram_fd);
750 // although save to nvram maybe fail, we don't return any error number
751 // to Xend. This is quite logical because damage of NVRAM on native would
752 // not block OS's executive path. Return error number will cause an
753 // exception of Xend and block XenU when it destroy.
754 return 0;
755 }
757 #define NVRAM_DIR "/usr/lib/xen/boot/"
758 #define NVRAM_FILE_PATH "/usr/lib/xen/boot/nvram_"
760 int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom)
761 {
762 int file_path_len = strlen(NVRAM_FILE_PATH);
763 uint64_t nvram_fd = 0;
764 char nvram_path[100] = {0};
765 struct stat stat_buf;
767 if ( stat(NVRAM_DIR, &stat_buf) == -1 ) {
768 if ( errno != ENOENT )
769 {
770 PERROR("Error stat'ing NVRAM dir %s.", NVRAM_DIR);
771 return -1;
772 }
773 if ( mkdir(NVRAM_DIR, 0755) == -1 )
774 {
775 PERROR("Unable to create NVRAM store directory %s.", NVRAM_DIR);
776 return -1;
777 }
778 }
780 if ( !(stat_buf.st_mode & S_IRUSR) || !(stat_buf.st_mode & S_IWUSR) )
781 {
782 errno = EACCES;
783 PERROR("No R/W permission to NVRAM store directory %s.", NVRAM_DIR);
784 return -1;
785 }
787 strncpy(nvram_path, NVRAM_FILE_PATH, file_path_len);
788 if ( file_path_len + strlen(dom_name) + 1 > sizeof(nvram_path) )
789 {
790 PERROR("Nvram file path is too long!\n");
791 return -1;
792 }
793 strcpy(nvram_path + file_path_len, dom_name);
795 nvram_fd = nvram_init(nvram_path);
796 if ( nvram_fd == (uint64_t)(-1) )
797 {
798 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, 0);
799 return -1;
800 }
802 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, nvram_fd);
803 return 0;
804 }
806 #define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT)
807 #define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT)
808 #define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT)
810 static void
811 xc_ia64_setup_md(efi_memory_desc_t *md,
812 unsigned long start, unsigned long end)
813 {
814 md->type = EFI_CONVENTIONAL_MEMORY;
815 md->pad = 0;
816 md->phys_addr = start;
817 md->virt_addr = 0;
818 md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
819 md->attribute = EFI_MEMORY_WB;
820 }
822 static inline unsigned long
823 min(unsigned long lhs, unsigned long rhs)
824 {
825 return (lhs < rhs)? lhs: rhs;
826 }
828 static int
829 xc_ia64_setup_memmap_info(int xc_handle, uint32_t dom,
830 unsigned long dom_memsize, /* in bytes */
831 unsigned long *pfns_special_pages,
832 unsigned long nr_special_pages,
833 unsigned long memmap_info_pfn,
834 unsigned long memmap_info_num_pages)
835 {
836 xen_ia64_memmap_info_t* memmap_info;
837 efi_memory_desc_t *md;
838 uint64_t nr_mds;
840 memmap_info = xc_map_foreign_range(xc_handle, dom,
841 PAGE_SIZE * memmap_info_num_pages,
842 PROT_READ | PROT_WRITE,
843 memmap_info_pfn);
844 if (memmap_info == NULL) {
845 PERROR("Could not map memmmap_info page.\n");
846 return -1;
847 }
848 memset(memmap_info, 0, PAGE_SIZE * memmap_info_num_pages);
850 /*
851 * [0, VGA_IO_START = 0xA0000)
852 * [VGA_IO_START + VGA_IO_SIZE = 0xC0000, MMIO_START = 3GB)
853 * [IO_PAGE_START (> 3GB), IO_PAGE_START + IO_PAGE_SIZE)
854 * [STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE)
855 * [BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
856 * [BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE)
857 * [memmap_info_pfn << PAGE_SHIFT,
858 * (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE)
859 * [GFW_START=4GB - GFW_SIZE, GFW_START + GFW_SIZE = 4GB)
860 * [4GB, ...)
861 */
862 md = (efi_memory_desc_t*)&memmap_info->memdesc;
863 xc_ia64_setup_md(md, 0, min(VGA_IO_START, dom_memsize));
864 md++;
865 if (dom_memsize > (VGA_IO_START + VGA_IO_SIZE)) {
866 xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE,
867 min(MMIO_START, dom_memsize));
868 md++;
869 }
870 xc_ia64_setup_md(md, IO_PAGE_START, IO_PAGE_START + IO_PAGE_SIZE);
871 md++;
872 xc_ia64_setup_md(md, STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE);
873 md++;
874 xc_ia64_setup_md(md, BUFFER_IO_PAGE_START,
875 BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE);
876 md++;
877 xc_ia64_setup_md(md, BUFFER_PIO_PAGE_START,
878 BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE);
879 md++;
880 xc_ia64_setup_md(md, memmap_info_pfn << PAGE_SHIFT,
881 (memmap_info_pfn << PAGE_SHIFT) +
882 PAGE_SIZE * memmap_info_num_pages);
883 md++;
884 xc_ia64_setup_md(md, GFW_START, GFW_START + GFW_SIZE);
885 md++;
886 if (dom_memsize > MMIO_START) {
887 xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + (1 * MEM_G));
888 md++;
889 }
890 nr_mds = md - (efi_memory_desc_t*)&memmap_info->memdesc;
892 assert(nr_mds <=
893 (PAGE_SIZE * memmap_info_num_pages -
894 offsetof(typeof(*memmap_info), memdesc))/sizeof(*md));
895 memmap_info->efi_memmap_size = nr_mds * sizeof(*md);
896 memmap_info->efi_memdesc_size = sizeof(*md);
897 memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
899 munmap(memmap_info, PAGE_SIZE * memmap_info_num_pages);
900 return 0;
901 }
903 /* setup shared_info page */
904 static int
905 xc_ia64_setup_shared_info(int xc_handle, uint32_t dom,
906 unsigned long shared_info_pfn,
907 unsigned long memmap_info_pfn,
908 unsigned long memmap_info_num_pages)
909 {
910 shared_info_t *shared_info;
912 shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
913 PROT_READ | PROT_WRITE,
914 shared_info_pfn);
915 if (shared_info == NULL) {
916 PERROR("Could not map shared_info");
917 return -1;
918 }
919 memset(shared_info, 0, sizeof(*shared_info));
920 shared_info->arch.memmap_info_num_pages = memmap_info_num_pages;
921 shared_info->arch.memmap_info_pfn = memmap_info_pfn;
922 munmap(shared_info, PAGE_SIZE);
923 return 0;
924 }
926 /*
927 * In this function, we will allocate memory and build P2M/M2P table for VTI
928 * guest. Frist, a pfn list will be initialized discontiguous, normal memory
929 * begins with 0, GFW memory and other five pages at their place defined in
930 * xen/include/public/arch-ia64.h xc_domain_memory_populate_physmap() called
931 * five times, to set parameter 'extent_order' to different value, this is
932 * convenient to allocate discontiguous memory with different size.
933 */
934 static int
935 setup_guest(int xc_handle, uint32_t dom, unsigned long memsize,
936 char *image, unsigned long image_size, vcpu_guest_context_t *ctxt)
937 {
938 xen_pfn_t *pfn_list;
939 shared_iopage_t *sp;
940 void *ioreq_buffer_page;
941 void *pio_buffer_page;
942 unsigned long dom_memsize = memsize << 20;
943 unsigned long nr_pages = memsize << (20 - PAGE_SHIFT);
944 unsigned long vcpus;
945 unsigned long nr_special_pages;
946 unsigned long memmap_info_pfn;
947 unsigned long memmap_info_num_pages;
948 unsigned long nvram_start = NVRAM_START, nvram_fd = 0;
949 int rc;
950 long i;
951 DECLARE_DOMCTL;
954 if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
955 PERROR("Guest firmware size is incorrect [%ld]?", image_size);
956 return -1;
957 }
959 pfn_list = malloc(nr_pages * sizeof(xen_pfn_t));
960 if (pfn_list == NULL) {
961 PERROR("Could not allocate memory.\n");
962 return -1;
963 }
965 // Allocate pfn for normal memory
966 for (i = 0; i < dom_memsize >> PAGE_SHIFT; i++)
967 pfn_list[i] = i;
969 // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others.
970 for (i = (MMIO_START >> PAGE_SHIFT); i < (dom_memsize >> PAGE_SHIFT); i++)
971 pfn_list[i] += ((1 * MEM_G) >> PAGE_SHIFT);
973 // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000.
974 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
975 (nr_pages > VGA_START_PAGE) ?
976 VGA_START_PAGE : nr_pages,
977 0, 0, &pfn_list[0]);
979 // We're not likely to attempt to create a domain with less than
980 // 640k of memory, but test for completeness
981 if (rc == 0 && nr_pages > VGA_END_PAGE)
982 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
983 nr_pages - VGA_END_PAGE,
984 0, 0, &pfn_list[VGA_END_PAGE]);
985 if (rc != 0) {
986 PERROR("Could not allocate normal memory for Vti guest.\n");
987 goto error_out;
988 }
990 // We allocate additional pfn for GFW and other five pages, so
991 // the pfn_list is not contiguous. Due to this we must support
992 // old interface xc_ia64_get_pfn_list().
993 for (i = 0; i < GFW_PAGES; i++)
994 pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i;
996 rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES,
997 0, 0, &pfn_list[0]);
998 if (rc != 0) {
999 PERROR("Could not allocate GFW memory for Vti guest.\n");
1000 goto error_out;
1003 nr_special_pages = 0;
1004 pfn_list[nr_special_pages] = IO_PAGE_START >> PAGE_SHIFT;
1005 nr_special_pages++;
1006 pfn_list[nr_special_pages] = STORE_PAGE_START >> PAGE_SHIFT;
1007 nr_special_pages++;
1008 pfn_list[nr_special_pages] = BUFFER_IO_PAGE_START >> PAGE_SHIFT;
1009 nr_special_pages++;
1010 pfn_list[nr_special_pages] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT;
1012 memmap_info_pfn = pfn_list[nr_special_pages] + 1;
1013 memmap_info_num_pages = 1;
1014 nr_special_pages++;
1015 pfn_list[nr_special_pages] = memmap_info_pfn;
1016 nr_special_pages++;
1018 rc = xc_domain_memory_populate_physmap(xc_handle, dom, nr_special_pages,
1019 0, 0, &pfn_list[0]);
1020 if (rc != 0) {
1021 PERROR("Could not allocate IO page or store page or buffer io page.\n");
1022 goto error_out;
1025 domctl.u.arch_setup.flags = XEN_DOMAINSETUP_hvm_guest;
1026 domctl.u.arch_setup.bp = 0;
1027 domctl.u.arch_setup.maxmem = 0;
1028 domctl.cmd = XEN_DOMCTL_arch_setup;
1029 domctl.domain = (domid_t)dom;
1030 if (xc_domctl(xc_handle, &domctl))
1031 goto error_out;
1033 // Load guest firmware
1034 if (xc_ia64_copy_to_domain_pages(xc_handle, dom, image,
1035 (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT,
1036 image_size >> PAGE_SHIFT)) {
1037 PERROR("Could not load guest firmware into domain");
1038 goto error_out;
1041 domctl.cmd = XEN_DOMCTL_getdomaininfo;
1042 domctl.domain = (domid_t)dom;
1043 if (xc_domctl(xc_handle, &domctl) < 0) {
1044 PERROR("Could not get info on domain");
1045 goto error_out;
1048 if (xc_ia64_setup_memmap_info(xc_handle, dom, dom_memsize,
1049 pfn_list, nr_special_pages,
1050 memmap_info_pfn, memmap_info_num_pages)) {
1051 PERROR("Could not build memmap info\n");
1052 goto error_out;
1054 if (xc_ia64_setup_shared_info(xc_handle, dom,
1055 domctl.u.getdomaininfo.shared_info_frame,
1056 memmap_info_pfn, memmap_info_num_pages)) {
1057 PERROR("Could not setup shared_info\n");
1058 goto error_out;
1061 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd);
1062 if ( !IS_VALID_NVRAM_FD(nvram_fd) )
1063 nvram_start = 0;
1064 else if ( copy_from_nvram_to_GFW(xc_handle, dom, (int)nvram_fd ) == -1 ) {
1065 nvram_start = 0;
1066 close(nvram_fd);
1069 vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1;
1071 // Hand-off state passed to guest firmware
1072 if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus, nvram_start) < 0) {
1073 PERROR("Could not build hob\n");
1074 goto error_out;
1077 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, pfn_list[1]);
1079 // Retrieve special pages like io, xenstore, etc.
1080 sp = (shared_iopage_t *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1081 PROT_READ | PROT_WRITE,
1082 pfn_list[0]);
1083 if (sp == 0)
1084 goto error_out;
1086 memset(sp, 0, PAGE_SIZE);
1087 munmap(sp, PAGE_SIZE);
1088 ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1089 PROT_READ | PROT_WRITE,
1090 pfn_list[2]);
1091 memset(ioreq_buffer_page,0,PAGE_SIZE);
1092 munmap(ioreq_buffer_page, PAGE_SIZE);
1094 pio_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1095 PROT_READ | PROT_WRITE,
1096 pfn_list[3]);
1097 memset(pio_buffer_page,0,PAGE_SIZE);
1098 munmap(pio_buffer_page, PAGE_SIZE);
1099 free(pfn_list);
1100 return 0;
1102 error_out:
1103 return -1;
1106 int
1107 xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name)
1109 struct xen_domctl launch_domctl;
1110 int rc;
1111 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
1112 char *image = NULL;
1113 unsigned long image_size;
1114 unsigned long nr_pages;
1116 nr_pages = xc_get_max_pages(xc_handle, domid);
1117 if (nr_pages < 0) {
1118 PERROR("Could not find total pages for domain");
1119 goto error_out;
1122 image = xc_read_image(image_name, &image_size);
1123 if (image == NULL) {
1124 PERROR("Could not read guest firmware image %s", image_name);
1125 goto error_out;
1128 image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
1130 if (lock_pages(&st_ctxt, sizeof(st_ctxt))) {
1131 PERROR("Unable to lock_pages ctxt");
1132 return 1;
1135 memset(ctxt, 0, sizeof(*ctxt));
1137 if (setup_guest(xc_handle, domid, (unsigned long)memsize, image,
1138 image_size, ctxt) < 0) {
1139 ERROR("Error constructing guest OS");
1140 goto error_out;
1143 free(image);
1145 ctxt->regs.ip = 0x80000000ffffffb0UL;
1146 ctxt->regs.ar.fpsr = xc_ia64_fpsr_default();
1147 ctxt->regs.cr.isr = 1UL << 63;
1148 ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN;
1149 ctxt->regs.cr.dcr = 0;
1150 ctxt->regs.cr.pta = 15 << 2;
1152 memset(&launch_domctl, 0, sizeof(launch_domctl));
1154 launch_domctl.domain = (domid_t)domid;
1155 launch_domctl.u.vcpucontext.vcpu = 0;
1156 set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
1158 launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
1159 rc = do_domctl(xc_handle, &launch_domctl);
1160 unlock_pages(&st_ctxt, sizeof(st_ctxt));
1161 return rc;
1163 error_out:
1164 free(image);
1165 unlock_pages(&st_ctxt, sizeof(st_ctxt));
1166 return -1;
1169 /*
1170 * Local variables:
1171 * mode: C
1172 * c-set-style: "BSD"
1173 * c-basic-offset: 4
1174 * tab-width: 4
1175 * indent-tabs-mode: nil
1176 * End:
1177 */