source: trunk/packages/xen-3.1/xen-3.1/tools/libxc/ia64/xc_ia64_hvm_build.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 22.4 KB
Line 
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>
10
11static int
12xc_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;
17
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    }
23
24    return 0;
25}
26
27int 
28xc_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;
33
34    hypercall.op = __HYPERVISOR_hvm_op;
35    hypercall.arg[0] = HVMOP_set_param;
36    hypercall.arg[1] = (unsigned long)&arg;
37
38    arg.domid = dom;
39    arg.index = param;
40    arg.value = value;
41
42    if (mlock(&arg, sizeof(arg)) != 0)
43        return -1;
44
45    rc = do_xen_hypercall(handle, &hypercall);
46    safe_munlock(&arg, sizeof(arg));
47
48    return rc;
49}
50
51int 
52xc_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;
57
58    hypercall.op = __HYPERVISOR_hvm_op;
59    hypercall.arg[0] = HVMOP_get_param;
60    hypercall.arg[1] = (unsigned long)&arg;
61
62    arg.domid = dom;
63    arg.index = param;
64
65    if (mlock(&arg, sizeof(arg)) != 0)
66        return -1;
67
68    rc = do_xen_hypercall(handle, &hypercall);
69    safe_munlock(&arg, sizeof(arg));
70
71    *value = arg.value;
72    return rc;
73}
74
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
78
79typedef struct {
80    unsigned long signature;
81    unsigned int  type;
82    unsigned int  length;
83} HOB_GENERIC_HEADER;
84
85/*
86 * INFO HOB is the first data data in one HOB list
87 * it contains the control information of the HOB list
88 */
89typedef 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;
95
96typedef struct{
97    unsigned long start;
98    unsigned long size;
99} hob_mem_t;
100
101typedef 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;
127
128static int hob_init(void  *buffer ,unsigned long buf_size);
129static int add_pal_hob(void* hob_buf);
130static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
131static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu);
132static int build_hob(void* hob_buf, unsigned long hob_buf_size,
133                     unsigned long dom_mem_size, unsigned long vcpus);
134static int load_hob(int xc_handle,uint32_t dom, void *hob_buf,
135                    unsigned long dom_mem_size);
136
137static int
138xc_ia64_build_hob(int xc_handle, uint32_t dom,
139                  unsigned long memsize, unsigned long vcpus)
140{
141    char   *hob_buf;
142
143    hob_buf = malloc(GFW_HOB_SIZE);
144    if (hob_buf == NULL) {
145        PERROR("Could not allocate hob");
146        return -1;
147    }
148
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    }
154
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;
162
163}
164
165static int
166hob_init(void *buffer, unsigned long buf_size)
167{
168    HOB_INFO *phit;
169    HOB_GENERIC_HEADER *terminal;
170
171    if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
172        // buffer too small
173        return -1;
174    }
175
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;
183
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);
188
189    return 0;
190}
191
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 */
200static int
201hob_add(void* hob_start, int type, void* data, int data_size)
202{
203    HOB_INFO *phit;
204    HOB_GENERIC_HEADER *newhob, *tail;
205
206    phit = (HOB_INFO*)hob_start;
207
208    if (phit->length + data_size > phit->buf_size) {
209        // no space for new hob
210        return -1;
211    }
212
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);
220
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);
226
227    // adjust HOB list length
228    phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
229
230    return 0;
231}
232
233static int
234get_hob_size(void* hob_buf)
235{
236    HOB_INFO *phit = (HOB_INFO*)hob_buf;
237
238    if (phit->header.signature != HOB_SIGNATURE) {
239        PERROR("xc_get_hob_size:Incorrect signature");
240        return -1;
241    }
242    return phit->length;
243}
244
245static int
246build_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    }
254
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    }
259
260    if (add_vcpus_hob(hob_buf, vcpus) < 0) {
261        PERROR("Add NR_VCPU hob failed, buffer too small");
262        goto err_out;
263    }
264
265    if (add_pal_hob( hob_buf ) < 0) {
266        PERROR("Add PAL hob failed, buffer too small");
267        goto err_out;
268    }
269
270    return 0;
271
272err_out:
273    return -1;
274}
275
276static int
277load_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;
283
284    hob_size = get_hob_size(hob_buf);
285    if (hob_size < 0) {
286        PERROR("Invalid hob data");
287        return -1;
288    }
289
290    if (hob_size > GFW_HOB_SIZE) {
291        PERROR("No enough memory for hob data");
292        return -1;
293    }
294
295    nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT;
296
297    return xc_ia64_copy_to_domain_pages(xc_handle, dom, hob_buf,
298                                        GFW_HOB_START >> PAGE_SHIFT, nr_pages);
299}
300
301#define MIN(x, y) ((x) < (y)) ? (x) : (y)
302static int
303add_mem_hob(void* hob_buf, unsigned long dom_mem_size)
304{
305    hob_mem_t memhob;
306
307    // less than 3G
308    memhob.start = 0;
309    memhob.size = MIN(dom_mem_size, 0xC0000000);
310
311    if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
312        return -1;
313
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}
323
324static int 
325add_vcpus_hob(void* hob_buf, unsigned long vcpus)
326{
327    return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
328}
329
330static 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};
334
335static 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};
338
339static const unsigned char config_pal_mem_attrib[8] = {
340    241, 0, 0, 0, 0, 0, 0, 0
341};
342
343static 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};
355
356static 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};
371
372static 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};
375
376static const unsigned char config_pal_fixed_addr[8] = {
377    0, 0, 0, 0, 0, 0, 0, 0
378};
379
380static const unsigned char config_pal_freq_base[8] = {
381    109, 219, 182, 13, 0, 0, 0, 0
382};
383
384static 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};
388
389static 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};
395
396static 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};
407
408static 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};
417
418static 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};
422
423static 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};
429
430static 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};
433
434static 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};
439
440static 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};
443
444static 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};
452
453static 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};
456
457typedef struct{
458    hob_type_t type;
459    void* data;
460    unsigned long size;
461} hob_batch_t;
462
463static 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};
541
542static int
543add_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}
553
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 */
565static int
566setup_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    void *pio_buffer_page;
573    unsigned long dom_memsize = memsize << 20;
574    unsigned long nr_pages = memsize << (20 - PAGE_SHIFT);
575    unsigned long vcpus;
576    int rc;
577    long i;
578    DECLARE_DOMCTL;
579
580
581    if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
582        PERROR("Guest firmware size is incorrect [%ld]?", image_size);
583        return -1;
584    }
585
586    pfn_list = malloc(nr_pages * sizeof(xen_pfn_t));
587    if (pfn_list == NULL) {
588        PERROR("Could not allocate memory.\n");
589        return -1;
590    }
591
592    // Allocate pfn for normal memory
593    for (i = 0; i < dom_memsize >> PAGE_SHIFT; i++)
594        pfn_list[i] = i;
595
596    // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others.
597    for (i = (MMIO_START >> PAGE_SHIFT); i < (dom_memsize >> PAGE_SHIFT); i++)
598        pfn_list[i] += ((1 * MEM_G) >> PAGE_SHIFT);
599
600    // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000.
601    rc = xc_domain_memory_populate_physmap(xc_handle, dom,
602                                           (nr_pages > VGA_START_PAGE) ?
603                                           VGA_START_PAGE : nr_pages,
604                                           0, 0, &pfn_list[0]);
605
606    // We're not likely to attempt to create a domain with less than
607    // 640k of memory, but test for completeness
608    if (rc == 0 && nr_pages > VGA_END_PAGE)
609        rc = xc_domain_memory_populate_physmap(xc_handle, dom,
610                                               nr_pages - VGA_END_PAGE,
611                                               0, 0, &pfn_list[VGA_END_PAGE]);
612    if (rc != 0) {
613        PERROR("Could not allocate normal memory for Vti guest.\n");
614        goto error_out;
615    }
616
617    // We allocate additional pfn for GFW and other three pages, so
618    // the pfn_list is not contiguous.  Due to this we must support
619    // old interface xc_ia64_get_pfn_list().
620    for (i = 0; i < GFW_PAGES; i++) 
621        pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i;
622
623    rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES,
624                                           0, 0, &pfn_list[0]);
625    if (rc != 0) {
626        PERROR("Could not allocate GFW memory for Vti guest.\n");
627        goto error_out;
628    }
629
630    pfn_list[0] = IO_PAGE_START >> PAGE_SHIFT;
631    pfn_list[1] = STORE_PAGE_START >> PAGE_SHIFT;
632    pfn_list[2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT;
633    pfn_list[3] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT;
634
635    rc = xc_domain_memory_populate_physmap(xc_handle, dom, 4,
636                                           0, 0, &pfn_list[0]);
637    if (rc != 0) {
638        PERROR("Could not allocate IO page or store page or buffer io page.\n");
639        goto error_out;
640    }
641
642    domctl.u.arch_setup.flags = XEN_DOMAINSETUP_hvm_guest;
643    domctl.u.arch_setup.bp = 0;
644    domctl.u.arch_setup.maxmem = 0;
645    domctl.cmd = XEN_DOMCTL_arch_setup;
646    domctl.domain = (domid_t)dom;
647    if (xc_domctl(xc_handle, &domctl))
648        goto error_out;
649
650    // Load guest firmware
651    if (xc_ia64_copy_to_domain_pages(xc_handle, dom, image,
652                            (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT,
653                            image_size >> PAGE_SHIFT)) {
654        PERROR("Could not load guest firmware into domain");
655        goto error_out;
656    }
657
658    domctl.cmd = XEN_DOMCTL_getdomaininfo;
659    domctl.domain = (domid_t)dom;
660    if (xc_domctl(xc_handle, &domctl) < 0) {
661        PERROR("Could not get info on domain");
662        goto error_out;
663    }
664
665    vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1;
666
667    // Hand-off state passed to guest firmware
668    if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus) < 0) {
669        PERROR("Could not build hob\n");
670        goto error_out;
671    }
672
673    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, pfn_list[1]);
674
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[0]);
679    if (sp == 0)
680        goto error_out;
681
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[2]); 
687    memset(ioreq_buffer_page,0,PAGE_SIZE);
688    munmap(ioreq_buffer_page, PAGE_SIZE);
689
690    pio_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
691                                           PROT_READ | PROT_WRITE,
692                                           pfn_list[3]);
693    memset(pio_buffer_page,0,PAGE_SIZE);
694    munmap(pio_buffer_page, PAGE_SIZE);
695    free(pfn_list);
696    return 0;
697
698error_out:
699    return -1;
700}
701
702int
703xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name)
704{
705    struct xen_domctl launch_domctl;
706    int rc;
707    vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
708    char *image = NULL;
709    unsigned long image_size;
710    unsigned long nr_pages;
711
712    nr_pages = xc_get_max_pages(xc_handle, domid);
713    if (nr_pages < 0) {
714        PERROR("Could not find total pages for domain");
715        goto error_out;
716    }
717
718    image = xc_read_image(image_name, &image_size);
719    if (image == NULL) {
720        PERROR("Could not read guest firmware image %s", image_name);
721        goto error_out;
722    }
723
724    image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
725
726    if (mlock(&st_ctxt, sizeof(st_ctxt))) {
727        PERROR("Unable to mlock ctxt");
728        return 1;
729    }
730
731    memset(ctxt, 0, sizeof(*ctxt));
732
733    if (setup_guest(xc_handle, domid, (unsigned long)memsize, image,
734                    image_size, ctxt) < 0) {
735        ERROR("Error constructing guest OS");
736        goto error_out;
737    }
738
739    free(image);
740
741    ctxt->user_regs.cr_iip = 0x80000000ffffffb0UL;
742
743    memset(&launch_domctl, 0, sizeof(launch_domctl));
744
745    launch_domctl.domain = (domid_t)domid;
746    launch_domctl.u.vcpucontext.vcpu = 0;
747    set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
748
749    launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
750    rc = do_domctl(xc_handle, &launch_domctl);
751    return rc;
752
753error_out:
754    free(image);
755    return -1;
756}
757
758/*
759 * Local variables:
760 * mode: C
761 * c-set-style: "BSD"
762 * c-basic-offset: 4
763 * tab-width: 4
764 * indent-tabs-mode: nil
765 * End:
766 */
Note: See TracBrowser for help on using the repository browser.