ia64/xen-unstable

view tools/libxc/ia64/xc_ia64_hvm_build.c @ 15342:1623f5f5094f

[IA64] Don't try to save nvram on PV domains

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
author Alex Williamson <alex.williamson@hp.com>
date Thu Jun 14 15:32:22 2007 -0600 (2007-06-14)
parents 96617c4f19aa
children 33cc64dcaead
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, 0666);
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 * GFW use 4k page. when doing foreign map, we should 16k align
627 * the address and map one more page to guarantee all 64k nvram data
628 * can be got.
629 */
630 static int
631 copy_from_GFW_to_nvram(int xc_handle, uint32_t dom, int nvram_fd)
632 {
633 xen_pfn_t *pfn_list = NULL;
634 char *tmp_ptr = NULL;
635 unsigned int nr_pages = 0;
636 uint64_t addr_from_GFW_4k_align = 0;
637 uint32_t offset = 0;
638 uint64_t nvram_base_addr = 0;
639 char buf[NVRAM_SIZE] = {0};
640 int i;
642 // map one more page
643 nr_pages = (NVRAM_SIZE + PAGE_SIZE) >> PAGE_SHIFT;
644 pfn_list = (xen_pfn_t *)malloc(sizeof(xen_pfn_t) * nr_pages);
645 if ( NULL == pfn_list )
646 {
647 PERROR("Cannot allocate memory for nvram save!\n");
648 close(nvram_fd);
649 return -1;
650 }
652 /*
653 * GFW allocate memory dynamicly to save nvram data
654 * and save address of the dynamic memory at NVRAM_START.
655 * To save nvram data to file, we must get the dynamic
656 * memory address first.
657 */
658 pfn_list[0] = NVRAM_START >> PAGE_SHIFT;
659 tmp_ptr = (char *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
660 PROT_READ | PROT_WRITE, pfn_list[0]);
662 if ( NULL == tmp_ptr )
663 {
664 PERROR("Cannot get nvram data from GFW!\n");
665 free(pfn_list);
666 close(nvram_fd);
667 return -1;
668 }
670 addr_from_GFW_4k_align = *((uint64_t *)tmp_ptr);
671 munmap(tmp_ptr, PAGE_SIZE);
673 // align address to 16k
674 offset = addr_from_GFW_4k_align % ( 16 * MEM_K );
675 addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset;
676 for ( i=0; i<nr_pages; i++ )
677 pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i;
679 tmp_ptr = (char *)xc_map_foreign_batch(xc_handle, dom,
680 PROT_READ | PROT_WRITE, pfn_list, nr_pages);
681 if ( NULL == tmp_ptr )
682 {
683 PERROR("Cannot get nvram data from GFW!\n");
684 free(pfn_list);
685 close(nvram_fd);
686 return -1;
687 }
689 // calculate nvram data base addrees
690 nvram_base_addr = (uint64_t)(tmp_ptr + offset);
692 memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE);
693 free(pfn_list);
694 munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE);
696 lseek(nvram_fd, 0, SEEK_SET);
697 if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE )
698 {
699 PERROR("Save to nvram fail!\n");
700 return -1;
701 }
703 close(nvram_fd);
705 DPRINTF("Nvram save successful!\n");
707 return 0;
708 }
710 int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom)
711 {
712 xc_dominfo_t info;
713 uint64_t nvram_fd = 0;
715 if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 )
716 {
717 PERROR("Could not get info for domain");
718 return -1;
719 }
721 if ( !info.hvm )
722 return 0;
724 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd);
726 if ( !IS_VALID_NVRAM_FD(nvram_fd) )
727 PERROR("Nvram not initialized. Nvram save failed!\n");
728 else
729 copy_from_GFW_to_nvram(xc_handle, dom, (int)nvram_fd);
731 // although save to nvram maybe fail, we don't return any error number
732 // to Xend. This is quite logical because damage of NVRAM on native would
733 // not block OS's executive path. Return error number will cause an
734 // exception of Xend and block XenU when it destroy.
735 return 0;
736 }
738 #define NVRAM_FILE_PATH "/usr/lib/xen/boot/nvram_"
739 int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom)
740 {
741 int file_path_len = strlen(NVRAM_FILE_PATH);
742 uint64_t nvram_fd = 0;
743 char nvram_path[100] = {0};
745 strncpy(nvram_path, NVRAM_FILE_PATH, file_path_len);
746 if ( file_path_len + strlen(dom_name) + 1 > sizeof(nvram_path) )
747 {
748 PERROR("Nvram file path is too long!\n");
749 return -1;
750 }
751 strcpy(nvram_path + file_path_len, dom_name);
753 nvram_fd = nvram_init(nvram_path);
754 if ( nvram_fd == (uint64_t)(-1) )
755 {
756 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, 0);
757 return -1;
758 }
760 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, nvram_fd);
761 return 0;
762 }
764 #define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT)
765 #define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT)
766 #define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT)
768 static void
769 xc_ia64_setup_md(efi_memory_desc_t *md,
770 unsigned long start, unsigned long end)
771 {
772 md->type = EFI_CONVENTIONAL_MEMORY;
773 md->pad = 0;
774 md->phys_addr = start;
775 md->virt_addr = 0;
776 md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
777 md->attribute = EFI_MEMORY_WB;
778 }
780 static inline unsigned long
781 min(unsigned long lhs, unsigned long rhs)
782 {
783 return (lhs < rhs)? lhs: rhs;
784 }
786 static int
787 xc_ia64_setup_memmap_info(int xc_handle, uint32_t dom,
788 unsigned long dom_memsize, /* in bytes */
789 unsigned long *pfns_special_pages,
790 unsigned long nr_special_pages,
791 unsigned long memmap_info_pfn,
792 unsigned long memmap_info_num_pages)
793 {
794 xen_ia64_memmap_info_t* memmap_info;
795 efi_memory_desc_t *md;
796 uint64_t nr_mds;
798 memmap_info = xc_map_foreign_range(xc_handle, dom,
799 PAGE_SIZE * memmap_info_num_pages,
800 PROT_READ | PROT_WRITE,
801 memmap_info_pfn);
802 if (memmap_info == NULL) {
803 PERROR("Could not map memmmap_info page.\n");
804 return -1;
805 }
806 memset(memmap_info, 0, PAGE_SIZE * memmap_info_num_pages);
808 /*
809 * [0, VGA_IO_START = 0xA0000)
810 * [VGA_IO_START + VGA_IO_SIZE = 0xC0000, MMIO_START = 3GB)
811 * [IO_PAGE_START (> 3GB), IO_PAGE_START + IO_PAGE_SIZE)
812 * [STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE)
813 * [BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
814 * [BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE)
815 * [memmap_info_pfn << PAGE_SHIFT,
816 * (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE)
817 * [GFW_START=4GB - GFW_SIZE, GFW_START + GFW_SIZE = 4GB)
818 * [4GB, ...)
819 */
820 md = (efi_memory_desc_t*)&memmap_info->memdesc;
821 xc_ia64_setup_md(md, 0, min(VGA_IO_START, dom_memsize));
822 md++;
823 if (dom_memsize > (VGA_IO_START + VGA_IO_SIZE)) {
824 xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE,
825 min(MMIO_START, dom_memsize));
826 md++;
827 }
828 xc_ia64_setup_md(md, IO_PAGE_START, IO_PAGE_START + IO_PAGE_SIZE);
829 md++;
830 xc_ia64_setup_md(md, STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE);
831 md++;
832 xc_ia64_setup_md(md, BUFFER_IO_PAGE_START,
833 BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE);
834 md++;
835 xc_ia64_setup_md(md, BUFFER_PIO_PAGE_START,
836 BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE);
837 md++;
838 xc_ia64_setup_md(md, memmap_info_pfn << PAGE_SHIFT,
839 (memmap_info_pfn << PAGE_SHIFT) +
840 PAGE_SIZE * memmap_info_num_pages);
841 md++;
842 xc_ia64_setup_md(md, GFW_START, GFW_START + GFW_SIZE);
843 md++;
844 if (dom_memsize > MMIO_START) {
845 xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + (1 * MEM_G));
846 md++;
847 }
848 nr_mds = md - (efi_memory_desc_t*)&memmap_info->memdesc;
850 assert(nr_mds <=
851 (PAGE_SIZE * memmap_info_num_pages -
852 offsetof(typeof(*memmap_info), memdesc))/sizeof(*md));
853 memmap_info->efi_memmap_size = nr_mds * sizeof(*md);
854 memmap_info->efi_memdesc_size = sizeof(*md);
855 memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
857 munmap(memmap_info, PAGE_SIZE * memmap_info_num_pages);
858 return 0;
859 }
861 /* setup shared_info page */
862 static int
863 xc_ia64_setup_shared_info(int xc_handle, uint32_t dom,
864 unsigned long shared_info_pfn,
865 unsigned long memmap_info_pfn,
866 unsigned long memmap_info_num_pages)
867 {
868 shared_info_t *shared_info;
870 shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
871 PROT_READ | PROT_WRITE,
872 shared_info_pfn);
873 if (shared_info == NULL) {
874 PERROR("Could not map shared_info");
875 return -1;
876 }
877 memset(shared_info, 0, sizeof(*shared_info));
878 shared_info->arch.memmap_info_num_pages = memmap_info_num_pages;
879 shared_info->arch.memmap_info_pfn = memmap_info_pfn;
880 munmap(shared_info, PAGE_SIZE);
881 return 0;
882 }
884 /*
885 * In this function, we will allocate memory and build P2M/M2P table for VTI
886 * guest. Frist, a pfn list will be initialized discontiguous, normal memory
887 * begins with 0, GFW memory and other five pages at their place defined in
888 * xen/include/public/arch-ia64.h xc_domain_memory_populate_physmap() called
889 * five times, to set parameter 'extent_order' to different value, this is
890 * convenient to allocate discontiguous memory with different size.
891 */
892 static int
893 setup_guest(int xc_handle, uint32_t dom, unsigned long memsize,
894 char *image, unsigned long image_size, vcpu_guest_context_t *ctxt)
895 {
896 xen_pfn_t *pfn_list;
897 shared_iopage_t *sp;
898 void *ioreq_buffer_page;
899 void *pio_buffer_page;
900 unsigned long dom_memsize = memsize << 20;
901 unsigned long nr_pages = memsize << (20 - PAGE_SHIFT);
902 unsigned long vcpus;
903 unsigned long nr_special_pages;
904 unsigned long memmap_info_pfn;
905 unsigned long memmap_info_num_pages;
906 unsigned long nvram_start = NVRAM_START, nvram_fd = 0;
907 int rc;
908 long i;
909 DECLARE_DOMCTL;
912 if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
913 PERROR("Guest firmware size is incorrect [%ld]?", image_size);
914 return -1;
915 }
917 pfn_list = malloc(nr_pages * sizeof(xen_pfn_t));
918 if (pfn_list == NULL) {
919 PERROR("Could not allocate memory.\n");
920 return -1;
921 }
923 // Allocate pfn for normal memory
924 for (i = 0; i < dom_memsize >> PAGE_SHIFT; i++)
925 pfn_list[i] = i;
927 // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others.
928 for (i = (MMIO_START >> PAGE_SHIFT); i < (dom_memsize >> PAGE_SHIFT); i++)
929 pfn_list[i] += ((1 * MEM_G) >> PAGE_SHIFT);
931 // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000.
932 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
933 (nr_pages > VGA_START_PAGE) ?
934 VGA_START_PAGE : nr_pages,
935 0, 0, &pfn_list[0]);
937 // We're not likely to attempt to create a domain with less than
938 // 640k of memory, but test for completeness
939 if (rc == 0 && nr_pages > VGA_END_PAGE)
940 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
941 nr_pages - VGA_END_PAGE,
942 0, 0, &pfn_list[VGA_END_PAGE]);
943 if (rc != 0) {
944 PERROR("Could not allocate normal memory for Vti guest.\n");
945 goto error_out;
946 }
948 // We allocate additional pfn for GFW and other five pages, so
949 // the pfn_list is not contiguous. Due to this we must support
950 // old interface xc_ia64_get_pfn_list().
951 for (i = 0; i < GFW_PAGES; i++)
952 pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i;
954 rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES,
955 0, 0, &pfn_list[0]);
956 if (rc != 0) {
957 PERROR("Could not allocate GFW memory for Vti guest.\n");
958 goto error_out;
959 }
961 nr_special_pages = 0;
962 pfn_list[nr_special_pages] = IO_PAGE_START >> PAGE_SHIFT;
963 nr_special_pages++;
964 pfn_list[nr_special_pages] = STORE_PAGE_START >> PAGE_SHIFT;
965 nr_special_pages++;
966 pfn_list[nr_special_pages] = BUFFER_IO_PAGE_START >> PAGE_SHIFT;
967 nr_special_pages++;
968 pfn_list[nr_special_pages] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT;
970 memmap_info_pfn = pfn_list[nr_special_pages] + 1;
971 memmap_info_num_pages = 1;
972 nr_special_pages++;
973 pfn_list[nr_special_pages] = memmap_info_pfn;
974 nr_special_pages++;
976 rc = xc_domain_memory_populate_physmap(xc_handle, dom, nr_special_pages,
977 0, 0, &pfn_list[0]);
978 if (rc != 0) {
979 PERROR("Could not allocate IO page or store page or buffer io page.\n");
980 goto error_out;
981 }
983 domctl.u.arch_setup.flags = XEN_DOMAINSETUP_hvm_guest;
984 domctl.u.arch_setup.bp = 0;
985 domctl.u.arch_setup.maxmem = 0;
986 domctl.cmd = XEN_DOMCTL_arch_setup;
987 domctl.domain = (domid_t)dom;
988 if (xc_domctl(xc_handle, &domctl))
989 goto error_out;
991 // Load guest firmware
992 if (xc_ia64_copy_to_domain_pages(xc_handle, dom, image,
993 (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT,
994 image_size >> PAGE_SHIFT)) {
995 PERROR("Could not load guest firmware into domain");
996 goto error_out;
997 }
999 domctl.cmd = XEN_DOMCTL_getdomaininfo;
1000 domctl.domain = (domid_t)dom;
1001 if (xc_domctl(xc_handle, &domctl) < 0) {
1002 PERROR("Could not get info on domain");
1003 goto error_out;
1006 if (xc_ia64_setup_memmap_info(xc_handle, dom, dom_memsize,
1007 pfn_list, nr_special_pages,
1008 memmap_info_pfn, memmap_info_num_pages)) {
1009 PERROR("Could not build memmap info\n");
1010 goto error_out;
1012 if (xc_ia64_setup_shared_info(xc_handle, dom,
1013 domctl.u.getdomaininfo.shared_info_frame,
1014 memmap_info_pfn, memmap_info_num_pages)) {
1015 PERROR("Could not setup shared_info\n");
1016 goto error_out;
1019 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd);
1020 if ( !IS_VALID_NVRAM_FD(nvram_fd) )
1021 nvram_start = 0;
1022 else if ( copy_from_nvram_to_GFW(xc_handle, dom, (int)nvram_fd ) == -1 ) {
1023 nvram_start = 0;
1024 close(nvram_fd);
1027 vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1;
1029 // Hand-off state passed to guest firmware
1030 if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus, nvram_start) < 0) {
1031 PERROR("Could not build hob\n");
1032 goto error_out;
1035 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, pfn_list[1]);
1037 // Retrieve special pages like io, xenstore, etc.
1038 sp = (shared_iopage_t *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1039 PROT_READ | PROT_WRITE,
1040 pfn_list[0]);
1041 if (sp == 0)
1042 goto error_out;
1044 memset(sp, 0, PAGE_SIZE);
1045 munmap(sp, PAGE_SIZE);
1046 ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1047 PROT_READ | PROT_WRITE,
1048 pfn_list[2]);
1049 memset(ioreq_buffer_page,0,PAGE_SIZE);
1050 munmap(ioreq_buffer_page, PAGE_SIZE);
1052 pio_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
1053 PROT_READ | PROT_WRITE,
1054 pfn_list[3]);
1055 memset(pio_buffer_page,0,PAGE_SIZE);
1056 munmap(pio_buffer_page, PAGE_SIZE);
1057 free(pfn_list);
1058 return 0;
1060 error_out:
1061 return -1;
1064 int
1065 xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name)
1067 struct xen_domctl launch_domctl;
1068 int rc;
1069 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
1070 char *image = NULL;
1071 unsigned long image_size;
1072 unsigned long nr_pages;
1074 nr_pages = xc_get_max_pages(xc_handle, domid);
1075 if (nr_pages < 0) {
1076 PERROR("Could not find total pages for domain");
1077 goto error_out;
1080 image = xc_read_image(image_name, &image_size);
1081 if (image == NULL) {
1082 PERROR("Could not read guest firmware image %s", image_name);
1083 goto error_out;
1086 image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
1088 if (lock_pages(&st_ctxt, sizeof(st_ctxt))) {
1089 PERROR("Unable to lock_pages ctxt");
1090 return 1;
1093 memset(ctxt, 0, sizeof(*ctxt));
1095 if (setup_guest(xc_handle, domid, (unsigned long)memsize, image,
1096 image_size, ctxt) < 0) {
1097 ERROR("Error constructing guest OS");
1098 goto error_out;
1101 free(image);
1103 ctxt->regs.ip = 0x80000000ffffffb0UL;
1104 ctxt->regs.ar.fpsr = xc_ia64_fpsr_default();
1105 ctxt->regs.cr.isr = 1UL << 63;
1106 ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN;
1107 ctxt->regs.cr.dcr = 0;
1108 ctxt->regs.cr.pta = 15 << 2;
1110 memset(&launch_domctl, 0, sizeof(launch_domctl));
1112 launch_domctl.domain = (domid_t)domid;
1113 launch_domctl.u.vcpucontext.vcpu = 0;
1114 set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
1116 launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
1117 rc = do_domctl(xc_handle, &launch_domctl);
1118 unlock_pages(&st_ctxt, sizeof(st_ctxt));
1119 return rc;
1121 error_out:
1122 free(image);
1123 unlock_pages(&st_ctxt, sizeof(st_ctxt));
1124 return -1;
1127 /*
1128 * Local variables:
1129 * mode: C
1130 * c-set-style: "BSD"
1131 * c-basic-offset: 4
1132 * tab-width: 4
1133 * indent-tabs-mode: nil
1134 * End:
1135 */