ia64/xen-unstable

view tools/libxc/ia64/xc_ia64_hvm_build.c @ 12796:d901f2fe8c25

[IA64] Fix Vti

Use new foreign page mapping interface

Signed-off-by: Xu Anthony <Anthony.xu@intel.com>
Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
Signed-off-by: Zhang Xin <xing.z.zhang@intel.com>
author awilliam@xenbuild2.aw
date Wed Dec 06 02:34:46 2006 -0700 (2006-12-06)
parents ba7fca36fbd0
children 2fc3392d0889
line source
1 #include "xg_private.h"
2 #include "xenguest.h"
3 #include "xc_private.h"
4 #include "xc_elf.h"
5 #include <stdlib.h>
6 #include <zlib.h>
7 #include "xen/arch-ia64.h"
8 #include <xen/hvm/ioreq.h>
9 #include <xen/hvm/params.h>
11 static int
12 xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid, void* src_page,
13 unsigned long dst_pfn, int nr_pages)
14 {
15 // N.B. gva should be page aligned
16 int i;
18 for (i = 0; i < nr_pages; i++) {
19 if (xc_copy_to_domain_page(xc_handle, domid, dst_pfn + i,
20 src_page + (i << PAGE_SHIFT)))
21 return -1;
22 }
24 return 0;
25 }
27 int
28 xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value)
29 {
30 DECLARE_HYPERCALL;
31 xen_hvm_param_t arg;
32 int rc;
34 hypercall.op = __HYPERVISOR_hvm_op;
35 hypercall.arg[0] = HVMOP_set_param;
36 hypercall.arg[1] = (unsigned long)&arg;
38 arg.domid = dom;
39 arg.index = param;
40 arg.value = value;
42 if (mlock(&arg, sizeof(arg)) != 0)
43 return -1;
45 rc = do_xen_hypercall(handle, &hypercall);
46 safe_munlock(&arg, sizeof(arg));
48 return rc;
49 }
51 int
52 xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value)
53 {
54 DECLARE_HYPERCALL;
55 xen_hvm_param_t arg;
56 int rc;
58 hypercall.op = __HYPERVISOR_hvm_op;
59 hypercall.arg[0] = HVMOP_get_param;
60 hypercall.arg[1] = (unsigned long)&arg;
62 arg.domid = dom;
63 arg.index = param;
65 if (mlock(&arg, sizeof(arg)) != 0)
66 return -1;
68 rc = do_xen_hypercall(handle, &hypercall);
69 safe_munlock(&arg, sizeof(arg));
71 *value = arg.value;
72 return rc;
73 }
75 #define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64"
76 #define GFW_HOB_START ((4UL<<30)-(14UL<<20)) // 4G - 14M
77 #define GFW_HOB_SIZE (1UL<<20) // 1M
79 typedef struct {
80 unsigned long signature;
81 unsigned int type;
82 unsigned int length;
83 } HOB_GENERIC_HEADER;
85 /*
86 * INFO HOB is the first data data in one HOB list
87 * it contains the control information of the HOB list
88 */
89 typedef struct {
90 HOB_GENERIC_HEADER header;
91 unsigned long length; // current length of hob
92 unsigned long cur_pos; // current poisiton of hob
93 unsigned long buf_size; // size of hob buffer
94 } HOB_INFO;
96 typedef struct{
97 unsigned long start;
98 unsigned long size;
99 } hob_mem_t;
101 typedef enum {
102 HOB_TYPE_INFO=0,
103 HOB_TYPE_TERMINAL,
104 HOB_TYPE_MEM,
105 HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
106 HOB_TYPE_PAL_CACHE_SUMMARY,
107 HOB_TYPE_PAL_MEM_ATTRIB,
108 HOB_TYPE_PAL_CACHE_INFO,
109 HOB_TYPE_PAL_CACHE_PROT_INFO,
110 HOB_TYPE_PAL_DEBUG_INFO,
111 HOB_TYPE_PAL_FIXED_ADDR,
112 HOB_TYPE_PAL_FREQ_BASE,
113 HOB_TYPE_PAL_FREQ_RATIOS,
114 HOB_TYPE_PAL_HALT_INFO,
115 HOB_TYPE_PAL_PERF_MON_INFO,
116 HOB_TYPE_PAL_PROC_GET_FEATURES,
117 HOB_TYPE_PAL_PTCE_INFO,
118 HOB_TYPE_PAL_REGISTER_INFO,
119 HOB_TYPE_PAL_RSE_INFO,
120 HOB_TYPE_PAL_TEST_INFO,
121 HOB_TYPE_PAL_VM_SUMMARY,
122 HOB_TYPE_PAL_VM_INFO,
123 HOB_TYPE_PAL_VM_PAGE_SIZE,
124 HOB_TYPE_NR_VCPU,
125 HOB_TYPE_MAX
126 } hob_type_t;
128 static int hob_init(void *buffer ,unsigned long buf_size);
129 static int add_pal_hob(void* hob_buf);
130 static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
131 static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu);
132 static int build_hob(void* hob_buf, unsigned long hob_buf_size,
133 unsigned long dom_mem_size, unsigned long vcpus);
134 static int load_hob(int xc_handle,uint32_t dom, void *hob_buf,
135 unsigned long dom_mem_size);
137 static int
138 xc_ia64_build_hob(int xc_handle, uint32_t dom,
139 unsigned long memsize, unsigned long vcpus)
140 {
141 char *hob_buf;
143 hob_buf = malloc(GFW_HOB_SIZE);
144 if (hob_buf == NULL) {
145 PERROR("Could not allocate hob");
146 return -1;
147 }
149 if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus) < 0) {
150 free(hob_buf);
151 PERROR("Could not build hob");
152 return -1;
153 }
155 if (load_hob(xc_handle, dom, hob_buf, memsize) < 0) {
156 free(hob_buf);
157 PERROR("Could not load hob");
158 return -1;
159 }
160 free(hob_buf);
161 return 0;
163 }
165 static int
166 hob_init(void *buffer, unsigned long buf_size)
167 {
168 HOB_INFO *phit;
169 HOB_GENERIC_HEADER *terminal;
171 if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
172 // buffer too small
173 return -1;
174 }
176 phit = (HOB_INFO*)buffer;
177 phit->header.signature = HOB_SIGNATURE;
178 phit->header.type = HOB_TYPE_INFO;
179 phit->header.length = sizeof(HOB_INFO);
180 phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
181 phit->cur_pos = 0;
182 phit->buf_size = buf_size;
184 terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO));
185 terminal->signature = HOB_SIGNATURE;
186 terminal->type = HOB_TYPE_TERMINAL;
187 terminal->length = sizeof(HOB_GENERIC_HEADER);
189 return 0;
190 }
192 /*
193 * Add a new HOB to the HOB List.
194 *
195 * hob_start - start address of hob buffer
196 * type - type of the hob to be added
197 * data - data of the hob to be added
198 * data_size - size of the data
199 */
200 static int
201 hob_add(void* hob_start, int type, void* data, int data_size)
202 {
203 HOB_INFO *phit;
204 HOB_GENERIC_HEADER *newhob, *tail;
206 phit = (HOB_INFO*)hob_start;
208 if (phit->length + data_size > phit->buf_size) {
209 // no space for new hob
210 return -1;
211 }
213 //append new HOB
214 newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
215 sizeof(HOB_GENERIC_HEADER));
216 newhob->signature = HOB_SIGNATURE;
217 newhob->type = type;
218 newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
219 memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
221 // append terminal HOB
222 tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size);
223 tail->signature = HOB_SIGNATURE;
224 tail->type = HOB_TYPE_TERMINAL;
225 tail->length = sizeof(HOB_GENERIC_HEADER);
227 // adjust HOB list length
228 phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
230 return 0;
231 }
233 static int
234 get_hob_size(void* hob_buf)
235 {
236 HOB_INFO *phit = (HOB_INFO*)hob_buf;
238 if (phit->header.signature != HOB_SIGNATURE) {
239 PERROR("xc_get_hob_size:Incorrect signature");
240 return -1;
241 }
242 return phit->length;
243 }
245 static int
246 build_hob(void* hob_buf, unsigned long hob_buf_size,
247 unsigned long dom_mem_size, unsigned long vcpus)
248 {
249 //Init HOB List
250 if (hob_init(hob_buf, hob_buf_size) < 0) {
251 PERROR("buffer too small");
252 goto err_out;
253 }
255 if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
256 PERROR("Add memory hob failed, buffer too small");
257 goto err_out;
258 }
260 if (add_vcpus_hob(hob_buf, vcpus) < 0) {
261 PERROR("Add NR_VCPU hob failed, buffer too small");
262 goto err_out;
263 }
265 if (add_pal_hob( hob_buf ) < 0) {
266 PERROR("Add PAL hob failed, buffer too small");
267 goto err_out;
268 }
270 return 0;
272 err_out:
273 return -1;
274 }
276 static int
277 load_hob(int xc_handle, uint32_t dom, void *hob_buf,
278 unsigned long dom_mem_size)
279 {
280 // hob_buf should be page aligned
281 int hob_size;
282 int nr_pages;
284 hob_size = get_hob_size(hob_buf);
285 if (hob_size < 0) {
286 PERROR("Invalid hob data");
287 return -1;
288 }
290 if (hob_size > GFW_HOB_SIZE) {
291 PERROR("No enough memory for hob data");
292 return -1;
293 }
295 nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT;
297 return xc_ia64_copy_to_domain_pages(xc_handle, dom, hob_buf,
298 GFW_HOB_START >> PAGE_SHIFT, nr_pages);
299 }
301 #define MIN(x, y) ((x) < (y)) ? (x) : (y)
302 static int
303 add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
304 {
305 hob_mem_t memhob;
307 // less than 3G
308 memhob.start = 0;
309 memhob.size = MIN(dom_mem_size, 0xC0000000);
311 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
312 return -1;
314 if (dom_mem_size > 0xC0000000) {
315 // 4G ~ 4G+remain
316 memhob.start = 0x100000000; //4G
317 memhob.size = dom_mem_size - 0xC0000000;
318 if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
319 return -1;
320 }
321 return 0;
322 }
324 static int
325 add_vcpus_hob(void* hob_buf, unsigned long vcpus)
326 {
327 return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
328 }
330 static const unsigned char config_pal_bus_get_features_data[24] = {
331 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
333 };
335 static const unsigned char config_pal_cache_summary[16] = {
336 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0
337 };
339 static const unsigned char config_pal_mem_attrib[8] = {
340 241, 0, 0, 0, 0, 0, 0, 0
341 };
343 static const unsigned char config_pal_cache_info[152] = {
344 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
345 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
346 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
347 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
348 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
349 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
350 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
351 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
352 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
353 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
354 };
356 static const unsigned char config_pal_cache_prot_info[200] = {
357 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
358 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
359 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
361 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
362 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
363 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
364 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
365 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
366 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
367 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
368 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
369 0, 0, 0
370 };
372 static const unsigned char config_pal_debug_info[16] = {
373 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
374 };
376 static const unsigned char config_pal_fixed_addr[8] = {
377 0, 0, 0, 0, 0, 0, 0, 0
378 };
380 static const unsigned char config_pal_freq_base[8] = {
381 109, 219, 182, 13, 0, 0, 0, 0
382 };
384 static const unsigned char config_pal_freq_ratios[24] = {
385 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
386 0, 0, 0, 7, 0, 0, 0
387 };
389 static const unsigned char config_pal_halt_info[64] = {
390 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
394 };
396 static const unsigned char config_pal_perf_mon_info[136] = {
397 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
398 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
399 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
400 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0
406 };
408 static const unsigned char config_pal_proc_get_features[104] = {
409 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
412 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
414 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0
416 };
418 static const unsigned char config_pal_ptce_info[24] = {
419 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
420 0, 0, 0, 0, 0, 0, 0, 0
421 };
423 static const unsigned char config_pal_register_info[64] = {
424 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
425 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
426 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
427 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
428 };
430 static const unsigned char config_pal_rse_info[16] = {
431 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
432 };
434 static const unsigned char config_pal_test_info[48] = {
435 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
436 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
438 };
440 static const unsigned char config_pal_vm_summary[16] = {
441 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
442 };
444 static const unsigned char config_pal_vm_info[104] = {
445 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
446 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
447 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
448 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
449 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
450 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
451 };
453 static const unsigned char config_pal_vm_page_size[16] = {
454 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
455 };
457 typedef struct{
458 hob_type_t type;
459 void* data;
460 unsigned long size;
461 } hob_batch_t;
463 static const hob_batch_t hob_batch[]={
464 { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
465 &config_pal_bus_get_features_data,
466 sizeof(config_pal_bus_get_features_data)
467 },
468 { HOB_TYPE_PAL_CACHE_SUMMARY,
469 &config_pal_cache_summary,
470 sizeof(config_pal_cache_summary)
471 },
472 { HOB_TYPE_PAL_MEM_ATTRIB,
473 &config_pal_mem_attrib,
474 sizeof(config_pal_mem_attrib)
475 },
476 { HOB_TYPE_PAL_CACHE_INFO,
477 &config_pal_cache_info,
478 sizeof(config_pal_cache_info)
479 },
480 { HOB_TYPE_PAL_CACHE_PROT_INFO,
481 &config_pal_cache_prot_info,
482 sizeof(config_pal_cache_prot_info)
483 },
484 { HOB_TYPE_PAL_DEBUG_INFO,
485 &config_pal_debug_info,
486 sizeof(config_pal_debug_info)
487 },
488 { HOB_TYPE_PAL_FIXED_ADDR,
489 &config_pal_fixed_addr,
490 sizeof(config_pal_fixed_addr)
491 },
492 { HOB_TYPE_PAL_FREQ_BASE,
493 &config_pal_freq_base,
494 sizeof(config_pal_freq_base)
495 },
496 { HOB_TYPE_PAL_FREQ_RATIOS,
497 &config_pal_freq_ratios,
498 sizeof(config_pal_freq_ratios)
499 },
500 { HOB_TYPE_PAL_HALT_INFO,
501 &config_pal_halt_info,
502 sizeof(config_pal_halt_info)
503 },
504 { HOB_TYPE_PAL_PERF_MON_INFO,
505 &config_pal_perf_mon_info,
506 sizeof(config_pal_perf_mon_info)
507 },
508 { HOB_TYPE_PAL_PROC_GET_FEATURES,
509 &config_pal_proc_get_features,
510 sizeof(config_pal_proc_get_features)
511 },
512 { HOB_TYPE_PAL_PTCE_INFO,
513 &config_pal_ptce_info,
514 sizeof(config_pal_ptce_info)
515 },
516 { HOB_TYPE_PAL_REGISTER_INFO,
517 &config_pal_register_info,
518 sizeof(config_pal_register_info)
519 },
520 { HOB_TYPE_PAL_RSE_INFO,
521 &config_pal_rse_info,
522 sizeof(config_pal_rse_info)
523 },
524 { HOB_TYPE_PAL_TEST_INFO,
525 &config_pal_test_info,
526 sizeof(config_pal_test_info)
527 },
528 { HOB_TYPE_PAL_VM_SUMMARY,
529 &config_pal_vm_summary,
530 sizeof(config_pal_vm_summary)
531 },
532 { HOB_TYPE_PAL_VM_INFO,
533 &config_pal_vm_info,
534 sizeof(config_pal_vm_info)
535 },
536 { HOB_TYPE_PAL_VM_PAGE_SIZE,
537 &config_pal_vm_page_size,
538 sizeof(config_pal_vm_page_size)
539 },
540 };
542 static int
543 add_pal_hob(void* hob_buf)
544 {
545 int i;
546 for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) {
547 if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data,
548 hob_batch[i].size) < 0)
549 return -1;
550 }
551 return 0;
552 }
554 #define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT)
555 #define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT)
556 #define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT)
557 /*
558 * In this function, we will allocate memory and build P2M/M2P table for VTI
559 * guest. Frist, a pfn list will be initialized discontiguous, normal memory
560 * begins with 0, GFW memory and other three pages at their place defined in
561 * xen/include/public/arch-ia64.h xc_domain_memory_populate_physmap() called
562 * three times, to set parameter 'extent_order' to different value, this is
563 * convenient to allocate discontiguous memory with different size.
564 */
565 static int
566 setup_guest(int xc_handle, uint32_t dom, unsigned long memsize,
567 char *image, unsigned long image_size, vcpu_guest_context_t *ctxt)
568 {
569 xen_pfn_t *pfn_list;
570 shared_iopage_t *sp;
571 void *ioreq_buffer_page;
572 // memsize equal to normal memory size(in configure file) + 16M
573 // dom_memsize will pass to xc_ia64_build_hob(), so must be subbed 16M
574 unsigned long dom_memsize = ((memsize - 16) << 20);
575 unsigned long nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
576 unsigned long normal_pages = nr_pages - GFW_PAGES;
577 unsigned long vcpus;
578 int rc;
579 long i, j;
580 DECLARE_DOMCTL;
582 // ROM size for guest firmware, ioreq page and xenstore page
583 nr_pages += 3;
585 if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
586 PERROR("Guest firmware size is incorrect [%ld]?", image_size);
587 return -1;
588 }
590 pfn_list = malloc(nr_pages * sizeof(xen_pfn_t));
591 if (pfn_list == NULL) {
592 PERROR("Could not allocate memory.\n");
593 return -1;
594 }
596 // Allocate pfn for normal memory
597 for (i = 0; i < dom_memsize >> PAGE_SHIFT; i++)
598 pfn_list[i] = i;
600 // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others.
601 for (j = (MMIO_START >> PAGE_SHIFT); j < (dom_memsize >> PAGE_SHIFT); j++)
602 pfn_list[j] += ((1 * MEM_G) >> PAGE_SHIFT);
604 // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000.
605 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
606 (normal_pages > VGA_START_PAGE) ?
607 VGA_START_PAGE : normal_pages,
608 0, 0, &pfn_list[0]);
610 // We're not likely to attempt to create a domain with less than
611 // 640k of memory, but test for completeness
612 if (rc == 0 && nr_pages > VGA_END_PAGE)
613 rc = xc_domain_memory_populate_physmap(xc_handle, dom,
614 normal_pages - VGA_END_PAGE,
615 0, 0, &pfn_list[VGA_END_PAGE]);
616 if (rc != 0) {
617 PERROR("Could not allocate normal memory for Vti guest.\n");
618 goto error_out;
619 }
621 // We allocate additional pfn for GFW and other three pages, so
622 // the pfn_list is not contiguous. Due to this we must support
623 // old interface xc_ia64_get_pfn_list().
624 // Here i = (dom_memsize >> PAGE_SHIFT)
625 for (j = 0; i < nr_pages - 3; i++, j++)
626 pfn_list[i] = (GFW_START >> PAGE_SHIFT) + j;
628 rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES,
629 0, 0, &pfn_list[normal_pages]);
630 if (rc != 0) {
631 PERROR("Could not allocate GFW memory for Vti guest.\n");
632 goto error_out;
633 }
635 // Here i = (dom_memsize >> PAGE_SHIFT) + GFW_PAGES
636 pfn_list[i] = IO_PAGE_START >> PAGE_SHIFT;
637 pfn_list[i+1] = STORE_PAGE_START >> PAGE_SHIFT;
638 pfn_list[i+2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT;
640 rc = xc_domain_memory_populate_physmap(xc_handle, dom, 3,
641 0, 0, &pfn_list[nr_pages - 3]);
642 if (rc != 0) {
643 PERROR("Could not allocate IO page or store page or buffer io page.\n");
644 goto error_out;
645 }
647 domctl.u.arch_setup.flags = XEN_DOMAINSETUP_hvm_guest;
648 domctl.u.arch_setup.bp = 0;
649 domctl.u.arch_setup.maxmem = 0;
650 domctl.cmd = XEN_DOMCTL_arch_setup;
651 domctl.domain = (domid_t)dom;
652 if (xc_domctl(xc_handle, &domctl))
653 goto error_out;
655 // Load guest firmware
656 if (xc_ia64_copy_to_domain_pages(xc_handle, dom, image,
657 (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT,
658 image_size >> PAGE_SHIFT)) {
659 PERROR("Could not load guest firmware into domain");
660 goto error_out;
661 }
663 // Get number of vcpus, stored by pyxc_hvm_build()
664 xc_get_hvm_param(xc_handle, dom, HVM_PARAM_VCPUS, &vcpus);
666 // Hand-off state passed to guest firmware
667 if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus) < 0) {
668 PERROR("Could not build hob\n");
669 goto error_out;
670 }
672 xc_set_hvm_param(xc_handle, dom,
673 HVM_PARAM_STORE_PFN, pfn_list[nr_pages - 2]);
675 // Retrieve special pages like io, xenstore, etc.
676 sp = (shared_iopage_t *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
677 PROT_READ | PROT_WRITE,
678 pfn_list[nr_pages - 3]);
679 if (sp == 0)
680 goto error_out;
682 memset(sp, 0, PAGE_SIZE);
683 munmap(sp, PAGE_SIZE);
684 ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
685 PROT_READ | PROT_WRITE,
686 pfn_list[nr_pages - 1]);
687 memset(ioreq_buffer_page,0,PAGE_SIZE);
688 munmap(ioreq_buffer_page, PAGE_SIZE);
689 free(pfn_list);
690 return 0;
692 error_out:
693 return -1;
694 }
696 int
697 xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name)
698 {
699 struct xen_domctl launch_domctl;
700 int rc;
701 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
702 char *image = NULL;
703 unsigned long image_size;
704 unsigned long nr_pages;
706 nr_pages = xc_get_max_pages(xc_handle, domid);
707 if (nr_pages < 0) {
708 PERROR("Could not find total pages for domain");
709 goto error_out;
710 }
712 image = xc_read_image(image_name, &image_size);
713 if (image == NULL) {
714 PERROR("Could not read guest firmware image %s", image_name);
715 goto error_out;
716 }
718 image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
720 if (mlock(&st_ctxt, sizeof(st_ctxt))) {
721 PERROR("Unable to mlock ctxt");
722 return 1;
723 }
725 memset(ctxt, 0, sizeof(*ctxt));
727 if (setup_guest(xc_handle, domid, (unsigned long)memsize, image,
728 image_size, ctxt) < 0) {
729 ERROR("Error constructing guest OS");
730 goto error_out;
731 }
733 free(image);
735 ctxt->user_regs.cr_iip = 0x80000000ffffffb0UL;
737 memset(&launch_domctl, 0, sizeof(launch_domctl));
739 launch_domctl.domain = (domid_t)domid;
740 launch_domctl.u.vcpucontext.vcpu = 0;
741 set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
743 launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
744 rc = do_domctl(xc_handle, &launch_domctl);
745 return rc;
747 error_out:
748 free(image);
749 return -1;
750 }
752 /*
753 * Local variables:
754 * mode: C
755 * c-set-style: "BSD"
756 * c-basic-offset: 4
757 * tab-width: 4
758 * indent-tabs-mode: nil
759 * End:
760 */