ia64/xen-unstable

view tools/libxc/ia64/xc_ia64_hvm_build.c @ 15762:6644d8486266

[IA64] Clean up NVRAM failure case

copy_from_GFW_to_nvram() in libxc forgot munmap() if NVRAM data
invalid. Also it forgot free() and close() too.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author Alex Williamson <alex.williamson@hp.com>
date Fri Aug 24 15:09:14 2007 -0600 (2007-08-24)
parents 38d061886873
children f88eea67a469
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 {
688 free(pfn_list);
689 munmap(tmp_ptr, PAGE_SIZE);
690 close(nvram_fd);
691 return -1;
692 }
694 addr_from_GFW_4k_align = ((struct nvram_save_addr *)tmp_ptr)->addr;
695 munmap(tmp_ptr, PAGE_SIZE);
697 // align address to 16k
698 offset = addr_from_GFW_4k_align % ( 16 * MEM_K );
699 addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset;
700 for ( i=0; i<nr_pages; i++ )
701 pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i;
703 tmp_ptr = (char *)xc_map_foreign_batch(xc_handle, dom,
704 PROT_READ | PROT_WRITE, pfn_list, nr_pages);
705 if ( NULL == tmp_ptr )
706 {
707 PERROR("Cannot get nvram data from GFW!\n");
708 free(pfn_list);
709 close(nvram_fd);
710 return -1;
711 }
713 // calculate nvram data base addrees
714 nvram_base_addr = (uint64_t)(tmp_ptr + offset);
716 memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE);
717 free(pfn_list);
718 munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE);
720 lseek(nvram_fd, 0, SEEK_SET);
721 if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE )
722 {
723 PERROR("Save to nvram fail!\n");
724 return -1;
725 }
727 close(nvram_fd);
729 DPRINTF("Nvram save successful!\n");
731 return 0;
732 }
734 int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom)
735 {
736 xc_dominfo_t info;
737 uint64_t nvram_fd = 0;
739 if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 )
740 {
741 PERROR("Could not get info for domain");
742 return -1;
743 }
745 if ( !info.hvm )
746 return 0;
748 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd);
750 if ( !IS_VALID_NVRAM_FD(nvram_fd) )
751 PERROR("Nvram not initialized. Nvram save failed!\n");
752 else
753 copy_from_GFW_to_nvram(xc_handle, dom, (int)nvram_fd);
755 // although save to nvram maybe fail, we don't return any error number
756 // to Xend. This is quite logical because damage of NVRAM on native would
757 // not block OS's executive path. Return error number will cause an
758 // exception of Xend and block XenU when it destroy.
759 return 0;
760 }
762 #define NVRAM_DIR "/usr/lib/xen/boot/"
763 #define NVRAM_FILE_PATH "/usr/lib/xen/boot/nvram_"
765 int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom)
766 {
767 int file_path_len = strlen(NVRAM_FILE_PATH);
768 uint64_t nvram_fd = 0;
769 char nvram_path[100] = {0};
770 struct stat stat_buf;
772 if ( stat(NVRAM_DIR, &stat_buf) == -1 ) {
773 if ( errno != ENOENT )
774 {
775 PERROR("Error stat'ing NVRAM dir %s.", NVRAM_DIR);
776 return -1;
777 }
778 if ( mkdir(NVRAM_DIR, 0755) == -1 )
779 {
780 PERROR("Unable to create NVRAM store directory %s.", NVRAM_DIR);
781 return -1;
782 }
783 }
785 if ( !(stat_buf.st_mode & S_IRUSR) || !(stat_buf.st_mode & S_IWUSR) )
786 {
787 errno = EACCES;
788 PERROR("No R/W permission to NVRAM store directory %s.", NVRAM_DIR);
789 return -1;
790 }
792 strncpy(nvram_path, NVRAM_FILE_PATH, file_path_len);
793 if ( file_path_len + strlen(dom_name) + 1 > sizeof(nvram_path) )
794 {
795 PERROR("Nvram file path is too long!\n");
796 return -1;
797 }
798 strcpy(nvram_path + file_path_len, dom_name);
800 nvram_fd = nvram_init(nvram_path);
801 if ( nvram_fd == (uint64_t)(-1) )
802 {
803 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, 0);
804 return -1;
805 }
807 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, nvram_fd);
808 return 0;
809 }
811 #define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT)
812 #define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT)
813 #define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT)
815 static void
816 xc_ia64_setup_md(efi_memory_desc_t *md,
817 unsigned long start, unsigned long end)
818 {
819 md->type = EFI_CONVENTIONAL_MEMORY;
820 md->pad = 0;
821 md->phys_addr = start;
822 md->virt_addr = 0;
823 md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
824 md->attribute = EFI_MEMORY_WB;
825 }
827 static inline unsigned long
828 min(unsigned long lhs, unsigned long rhs)
829 {
830 return (lhs < rhs)? lhs: rhs;
831 }
833 static int
834 xc_ia64_setup_memmap_info(int xc_handle, uint32_t dom,
835 unsigned long dom_memsize, /* in bytes */
836 unsigned long *pfns_special_pages,
837 unsigned long nr_special_pages,
838 unsigned long memmap_info_pfn,
839 unsigned long memmap_info_num_pages)
840 {
841 xen_ia64_memmap_info_t* memmap_info;
842 efi_memory_desc_t *md;
843 uint64_t nr_mds;
845 memmap_info = xc_map_foreign_range(xc_handle, dom,
846 PAGE_SIZE * memmap_info_num_pages,
847 PROT_READ | PROT_WRITE,
848 memmap_info_pfn);
849 if (memmap_info == NULL) {
850 PERROR("Could not map memmmap_info page.\n");
851 return -1;
852 }
853 memset(memmap_info, 0, PAGE_SIZE * memmap_info_num_pages);
855 /*
856 * [0, VGA_IO_START = 0xA0000)
857 * [VGA_IO_START + VGA_IO_SIZE = 0xC0000, MMIO_START = 3GB)
858 * [IO_PAGE_START (> 3GB), IO_PAGE_START + IO_PAGE_SIZE)
859 * [STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE)
860 * [BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
861 * [BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE)
862 * [memmap_info_pfn << PAGE_SHIFT,
863 * (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE)
864 * [GFW_START=4GB - GFW_SIZE, GFW_START + GFW_SIZE = 4GB)
865 * [4GB, ...)
866 */
867 md = (efi_memory_desc_t*)&memmap_info->memdesc;
868 xc_ia64_setup_md(md, 0, min(VGA_IO_START, dom_memsize));
869 md++;
870 if (dom_memsize > (VGA_IO_START + VGA_IO_SIZE)) {
871 xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE,
872 min(MMIO_START, dom_memsize));
873 md++;
874 }
875 xc_ia64_setup_md(md, IO_PAGE_START, IO_PAGE_START + IO_PAGE_SIZE);
876 md++;
877 xc_ia64_setup_md(md, STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE);
878 md++;
879 xc_ia64_setup_md(md, BUFFER_IO_PAGE_START,
880 BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE);
881 md++;
882 xc_ia64_setup_md(md, BUFFER_PIO_PAGE_START,
883 BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE);
884 md++;
885 xc_ia64_setup_md(md, memmap_info_pfn << PAGE_SHIFT,
886 (memmap_info_pfn << PAGE_SHIFT) +
887 PAGE_SIZE * memmap_info_num_pages);
888 md++;
889 xc_ia64_setup_md(md, GFW_START, GFW_START + GFW_SIZE);
890 md++;
891 if (dom_memsize > MMIO_START) {
892 xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + (1 * MEM_G));
893 md++;
894 }
895 nr_mds = md - (efi_memory_desc_t*)&memmap_info->memdesc;
897 assert(nr_mds <=
898 (PAGE_SIZE * memmap_info_num_pages -
899 offsetof(typeof(*memmap_info), memdesc))/sizeof(*md));
900 memmap_info->efi_memmap_size = nr_mds * sizeof(*md);
901 memmap_info->efi_memdesc_size = sizeof(*md);
902 memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
904 munmap(memmap_info, PAGE_SIZE * memmap_info_num_pages);
905 return 0;
906 }
908 /* setup shared_info page */
909 static int
910 xc_ia64_setup_shared_info(int xc_handle, uint32_t dom,
911 unsigned long shared_info_pfn,
912 unsigned long memmap_info_pfn,
913 unsigned long memmap_info_num_pages)
914 {
915 shared_info_t *shared_info;
917 shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
918 PROT_READ | PROT_WRITE,
919 shared_info_pfn);
920 if (shared_info == NULL) {
921 PERROR("Could not map shared_info");
922 return -1;
923 }
924 memset(shared_info, 0, sizeof(*shared_info));
925 shared_info->arch.memmap_info_num_pages = memmap_info_num_pages;
926 shared_info->arch.memmap_info_pfn = memmap_info_pfn;
927 munmap(shared_info, PAGE_SIZE);
928 return 0;
929 }
931 /*
932 * In this function, we will allocate memory and build P2M/M2P table for VTI
933 * guest. Frist, a pfn list will be initialized discontiguous, normal memory
934 * begins with 0, GFW memory and other five pages at their place defined in
935 * xen/include/public/arch-ia64.h xc_domain_memory_populate_physmap() called
936 * five times, to set parameter 'extent_order' to different value, this is
937 * convenient to allocate discontiguous memory with different size.
938 */
939 static int
940 setup_guest(int xc_handle, uint32_t dom, unsigned long memsize,
941 char *image, unsigned long image_size, vcpu_guest_context_t *ctxt)
942 {
943 xen_pfn_t *pfn_list;
944 shared_iopage_t *sp;
945 void *ioreq_buffer_page;
946 void *pio_buffer_page;
947 unsigned long dom_memsize = memsize << 20;
948 unsigned long nr_pages = memsize << (20 - PAGE_SHIFT);
949 unsigned long vcpus;
950 unsigned long nr_special_pages;
951 unsigned long memmap_info_pfn;
952 unsigned long memmap_info_num_pages;
953 unsigned long nvram_start = NVRAM_START, nvram_fd = 0;
954 int rc;
955 long i;
956 DECLARE_DOMCTL;
959 if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
960 PERROR("Guest firmware size is incorrect [%ld]?", image_size);
961 return -1;
962 }
964 pfn_list = malloc(nr_pages * sizeof(xen_pfn_t));
965 if (pfn_list == NULL) {
966 PERROR("Could not allocate memory.\n");
967 return -1;
968 }
970 // Allocate pfn for normal memory
971 for (i = 0; i < dom_memsize >> PAGE_SHIFT; i++)
972 pfn_list[i] = i;
974 // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others.
975 for (i = (MMIO_START >> PAGE_SHIFT); i < (dom_memsize >> PAGE_SHIFT); i++)
976 pfn_list[i] += ((1 * MEM_G) >> PAGE_SHIFT);
978 // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000.
979 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
980 (nr_pages > VGA_START_PAGE) ?
981 VGA_START_PAGE : nr_pages,
982 0, 0, &pfn_list[0]);
984 // We're not likely to attempt to create a domain with less than
985 // 640k of memory, but test for completeness
986 if (rc == 0 && nr_pages > VGA_END_PAGE)
987 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
988 nr_pages - VGA_END_PAGE,
989 0, 0, &pfn_list[VGA_END_PAGE]);
990 if (rc != 0) {
991 PERROR("Could not allocate normal memory for Vti guest.\n");
992 goto error_out;
993 }
995 // We allocate additional pfn for GFW and other five pages, so
996 // the pfn_list is not contiguous. Due to this we must support
997 // old interface xc_ia64_get_pfn_list().
998 for (i = 0; i < GFW_PAGES; i++)
999 pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i;
1001 rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES,
1002 0, 0, &pfn_list[0]);
1003 if (rc != 0) {
1004 PERROR("Could not allocate GFW memory for Vti guest.\n");
1005 goto error_out;
1008 nr_special_pages = 0;
1009 pfn_list[nr_special_pages] = IO_PAGE_START >> PAGE_SHIFT;
1010 nr_special_pages++;
1011 pfn_list[nr_special_pages] = STORE_PAGE_START >> PAGE_SHIFT;
1012 nr_special_pages++;
1013 pfn_list[nr_special_pages] = BUFFER_IO_PAGE_START >> PAGE_SHIFT;
1014 nr_special_pages++;
1015 pfn_list[nr_special_pages] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT;
1017 memmap_info_pfn = pfn_list[nr_special_pages] + 1;
1018 memmap_info_num_pages = 1;
1019 nr_special_pages++;
1020 pfn_list[nr_special_pages] = memmap_info_pfn;
1021 nr_special_pages++;
1023 rc = xc_domain_memory_populate_physmap(xc_handle, dom, nr_special_pages,
1024 0, 0, &pfn_list[0]);
1025 if (rc != 0) {
1026 PERROR("Could not allocate IO page or store page or buffer io page.\n");
1027 goto error_out;
1030 domctl.u.arch_setup.flags = XEN_DOMAINSETUP_hvm_guest;
1031 domctl.u.arch_setup.bp = 0;
1032 domctl.u.arch_setup.maxmem = 0;
1033 domctl.cmd = XEN_DOMCTL_arch_setup;
1034 domctl.domain = (domid_t)dom;
1035 if (xc_domctl(xc_handle, &domctl))
1036 goto error_out;
1038 // Load guest firmware
1039 if (xc_ia64_copy_to_domain_pages(xc_handle, dom, image,
1040 (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT,
1041 image_size >> PAGE_SHIFT)) {
1042 PERROR("Could not load guest firmware into domain");
1043 goto error_out;
1046 domctl.cmd = XEN_DOMCTL_getdomaininfo;
1047 domctl.domain = (domid_t)dom;
1048 if (xc_domctl(xc_handle, &domctl) < 0) {
1049 PERROR("Could not get info on domain");
1050 goto error_out;
1053 if (xc_ia64_setup_memmap_info(xc_handle, dom, dom_memsize,
1054 pfn_list, nr_special_pages,
1055 memmap_info_pfn, memmap_info_num_pages)) {
1056 PERROR("Could not build memmap info\n");
1057 goto error_out;
1059 if (xc_ia64_setup_shared_info(xc_handle, dom,
1060 domctl.u.getdomaininfo.shared_info_frame,
1061 memmap_info_pfn, memmap_info_num_pages)) {
1062 PERROR("Could not setup shared_info\n");
1063 goto error_out;
1066 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd);
1067 if ( !IS_VALID_NVRAM_FD(nvram_fd) )
1068 nvram_start = 0;
1069 else if ( copy_from_nvram_to_GFW(xc_handle, dom, (int)nvram_fd ) == -1 ) {
1070 nvram_start = 0;
1071 close(nvram_fd);
1074 vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1;
1076 // Hand-off state passed to guest firmware
1077 if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus, nvram_start) < 0) {
1078 PERROR("Could not build hob\n");
1079 goto error_out;
1082 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, pfn_list[1]);
1084 // Retrieve special pages like io, xenstore, etc.
1085 sp = (shared_iopage_t *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1086 PROT_READ | PROT_WRITE,
1087 pfn_list[0]);
1088 if (sp == 0)
1089 goto error_out;
1091 memset(sp, 0, PAGE_SIZE);
1092 munmap(sp, PAGE_SIZE);
1093 ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1094 PROT_READ | PROT_WRITE,
1095 pfn_list[2]);
1096 memset(ioreq_buffer_page,0,PAGE_SIZE);
1097 munmap(ioreq_buffer_page, PAGE_SIZE);
1099 pio_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1100 PROT_READ | PROT_WRITE,
1101 pfn_list[3]);
1102 memset(pio_buffer_page,0,PAGE_SIZE);
1103 munmap(pio_buffer_page, PAGE_SIZE);
1104 free(pfn_list);
1105 return 0;
1107 error_out:
1108 return -1;
1111 int
1112 xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name)
1114 struct xen_domctl launch_domctl;
1115 int rc;
1116 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
1117 char *image = NULL;
1118 unsigned long image_size;
1119 unsigned long nr_pages;
1121 nr_pages = xc_get_max_pages(xc_handle, domid);
1122 if (nr_pages < 0) {
1123 PERROR("Could not find total pages for domain");
1124 goto error_out;
1127 image = xc_read_image(image_name, &image_size);
1128 if (image == NULL) {
1129 PERROR("Could not read guest firmware image %s", image_name);
1130 goto error_out;
1133 image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
1135 if (lock_pages(&st_ctxt, sizeof(st_ctxt))) {
1136 PERROR("Unable to lock_pages ctxt");
1137 return 1;
1140 memset(ctxt, 0, sizeof(*ctxt));
1142 if (setup_guest(xc_handle, domid, (unsigned long)memsize, image,
1143 image_size, ctxt) < 0) {
1144 ERROR("Error constructing guest OS");
1145 goto error_out;
1148 free(image);
1150 ctxt->regs.ip = 0x80000000ffffffb0UL;
1151 ctxt->regs.ar.fpsr = xc_ia64_fpsr_default();
1152 ctxt->regs.cr.isr = 1UL << 63;
1153 ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN;
1154 ctxt->regs.cr.dcr = 0;
1155 ctxt->regs.cr.pta = 15 << 2;
1157 memset(&launch_domctl, 0, sizeof(launch_domctl));
1159 launch_domctl.domain = (domid_t)domid;
1160 launch_domctl.u.vcpucontext.vcpu = 0;
1161 set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
1163 launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
1164 rc = do_domctl(xc_handle, &launch_domctl);
1165 unlock_pages(&st_ctxt, sizeof(st_ctxt));
1166 return rc;
1168 error_out:
1169 free(image);
1170 unlock_pages(&st_ctxt, sizeof(st_ctxt));
1171 return -1;
1174 /*
1175 * Local variables:
1176 * mode: C
1177 * c-set-style: "BSD"
1178 * c-basic-offset: 4
1179 * tab-width: 4
1180 * indent-tabs-mode: nil
1181 * End:
1182 */