Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cleanup and sanity-checking of divide-by-zero and floating point use bugs (Coverity...
[palacios.git] / palacios / src / palacios / vmm_config.c
1  /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_config.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_debug.h>
23 #include <palacios/vmm_msr.h>
24 #include <palacios/vmm_decoder.h>
25 #include <palacios/vmm_telemetry.h>
26 #include <palacios/vmm_mem.h>
27 #include <palacios/vmm_hypercall.h>
28 #include <palacios/vmm_dev_mgr.h>
29 #include <palacios/vmm_cpuid.h>
30 #include <palacios/vmm_xml.h>
31 #include <palacios/vmm_io.h>
32 #include <palacios/vmm_msr.h>
33 #include <palacios/vmm_sprintf.h>
34
35
36 #ifdef V3_CONFIG_SWAPPING
37 #include <palacios/vmm_swapping.h>
38 #endif
39
40 #ifdef V3_CONFIG_MULTIBOOT
41 #include <palacios/vmm_multiboot.h>
42 #endif
43
44 #ifdef V3_CONFIG_HVM
45 #include <palacios/vmm_hvm.h>
46 #endif
47
48 #include <palacios/vmm_host_events.h>
49 #include <palacios/vmm_perftune.h>
50
51 #include "vmm_config_class.h"
52
53
54 /* The Palacios cookie encodes "v3vee" followed by a 
55    3 byte version code.   There are currently two versions:
56
57     \0\0\0 => original (no checksum)
58     \0\0\1 => checksum
59 */
60 #define COOKIE_LEN 8
61 #define COOKIE_V0 "v3vee\0\0\0"
62 #define COOKIE_V1 "v3vee\0\0\1"
63
64 // This is used to access the configuration file index table
65 struct file_hdr_v0 {
66     uint32_t index;
67     uint32_t size;
68     uint64_t offset;
69 };
70
71 struct file_hdr_v1 {
72     uint32_t index;
73     uint32_t size;
74     uint64_t offset;
75     ulong_t  hash;
76 };
77
78
79 struct file_idx_table_v0 {
80     uint64_t num_files;
81     struct file_hdr_v0 hdrs[0];
82 };
83
84 struct file_idx_table_v1 {
85     uint64_t num_files;
86     struct file_hdr_v1 hdrs[0];
87 };
88
89
90
91
92 static int setup_memory_map(struct v3_vm_info * vm, v3_cfg_tree_t * cfg);
93 static int setup_extensions(struct v3_vm_info * vm, v3_cfg_tree_t * cfg);
94 static int setup_devices(struct v3_vm_info * vm, v3_cfg_tree_t * cfg);
95
96
97
98 char * v3_cfg_val(v3_cfg_tree_t * tree, char * tag) {
99     char * attrib = (char *)v3_xml_attr(tree, tag);
100     v3_cfg_tree_t * child_entry = v3_xml_child(tree, tag);
101     char * val = NULL;
102
103     if ((child_entry != NULL) && (attrib != NULL)) {
104         PrintError(VM_NONE, VCORE_NONE, "Duplicate Configuration parameters present for %s\n", tag);
105         return NULL;
106     }
107
108     if (attrib == NULL) {
109         val = v3_xml_txt(child_entry);
110         
111         if ( val[0] == 0 )
112                 val = NULL;
113     } else {
114         val = attrib;
115     }
116     
117     return val;
118 }
119
120 v3_cfg_tree_t * v3_cfg_subtree(v3_cfg_tree_t * tree, char * tag) {
121     return v3_xml_child(tree, tag);
122 }
123
124 v3_cfg_tree_t * v3_cfg_next_branch(v3_cfg_tree_t * tree) {
125     return v3_xml_next(tree);
126 }
127
128
129
130 struct v3_cfg_file * v3_cfg_get_file(struct v3_vm_info * vm, char * tag) {
131     struct v3_cfg_file * file = NULL;
132
133     file = (struct v3_cfg_file *)v3_htable_search(vm->cfg_data->file_table, (addr_t)tag);
134
135     return file;
136 }
137
138
139 static uint_t file_hash_fn(addr_t key) {
140     char * name = (char *)key;
141     return v3_hash_buffer((uchar_t *)name, strlen(name));
142 }
143
144 static int file_eq_fn(addr_t key1, addr_t key2) {
145     char * name1 = (char *)key1;
146     char * name2 = (char *)key2;
147
148     return (strcmp(name1, name2) == 0);
149 }
150
151 static struct v3_config * parse_config(void * cfg_blob) {
152     struct v3_config * cfg = NULL;
153     int offset = 0;
154     uint_t xml_len = 0; 
155     struct file_idx_table_v0 * files_v0 = NULL;
156     struct file_idx_table_v1 * files_v1 = NULL;
157     v3_cfg_tree_t * file_tree = NULL;
158     int version=-1;
159
160     V3_Print(VM_NONE, VCORE_NONE, "cfg data at %p\n", cfg_blob);
161
162     if (memcmp(cfg_blob, COOKIE_V0, COOKIE_LEN) == 0) {
163         version = 0;
164     } else if (memcmp(cfg_blob, COOKIE_V1, COOKIE_LEN) == 0) { 
165         version = 1;
166     } else {
167         PrintError(VM_NONE, VCORE_NONE, "Invalid Configuration Header Or Unknown Version\n");
168         return NULL;
169     } 
170
171     V3_Print(VM_NONE, VCORE_NONE, "Handling Palacios Image Format, Version 0x%x\n",version);
172
173     offset += COOKIE_LEN;
174
175     cfg = (struct v3_config *)V3_Malloc(sizeof(struct v3_config));
176
177     if (!cfg) {
178         PrintError(VM_NONE, VCORE_NONE, "Unable to allocate while parsing\n");
179         return NULL;
180     }
181
182     memset(cfg, 0, sizeof(struct v3_config));
183
184     cfg->blob = cfg_blob;
185     INIT_LIST_HEAD(&(cfg->file_list));
186     cfg->file_table = v3_create_htable(0, file_hash_fn, file_eq_fn);
187
188     if (!(cfg->file_table)) {
189         PrintError(VM_NONE, VCORE_NONE, "Unable to allocate hash table while parsing\n");
190         V3_Free(cfg);
191         return NULL;
192     }
193     
194     xml_len = *(uint32_t *)(cfg_blob + offset);
195     offset += 4;
196
197     cfg->cfg = (v3_cfg_tree_t *)v3_xml_parse((uint8_t *)(cfg_blob + offset));
198     offset += xml_len;
199    
200     offset += 8;
201
202     // This is hideous, but the file formats are still very close
203     if (version==0) { 
204         files_v0 = (struct file_idx_table_v0 *)(cfg_blob + offset);
205         V3_Print(VM_NONE, VCORE_NONE, "Number of files in cfg: %d\n", (uint32_t)(files_v0->num_files));
206     } else {
207         files_v1 = (struct file_idx_table_v1 *)(cfg_blob + offset);
208         V3_Print(VM_NONE, VCORE_NONE, "Number of files in cfg: %d\n", (uint32_t)(files_v1->num_files));
209     }
210
211
212     file_tree = v3_cfg_subtree(v3_cfg_subtree(cfg->cfg, "files"), "file");
213
214     while (file_tree) {
215         char * id = v3_cfg_val(file_tree, "id");
216         char * index = v3_cfg_val(file_tree, "index");
217         int idx = atoi(index);
218         struct v3_cfg_file * file = NULL;
219
220         file = (struct v3_cfg_file *)V3_Malloc(sizeof(struct v3_cfg_file));
221         
222         if (!file) {
223             PrintError(VM_NONE, VCORE_NONE, "Could not allocate file structure\n");
224             v3_free_htable(cfg->file_table,0,0);
225             V3_Free(cfg);
226             return NULL;
227         }
228
229         V3_Print(VM_NONE, VCORE_NONE, "File index=%d id=%s\n", idx, id);
230
231         strncpy(file->tag, id, V3_MAX_TAG_LEN);
232         file->tag[V3_MAX_TAG_LEN-1] = 0 ;
233
234         if (version==0) { 
235             struct file_hdr_v0 * hdr = &(files_v0->hdrs[idx]);
236
237             file->size = hdr->size;
238             file->data = cfg_blob + hdr->offset;
239             file->hash = 0;
240             
241             V3_Print(VM_NONE, VCORE_NONE, "Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
242             V3_Print(VM_NONE, VCORE_NONE, "file data at %p\n", file->data);
243
244         } else if (version==1) { 
245             struct file_hdr_v1 * hdr = &(files_v1->hdrs[idx]);
246             unsigned long hash;
247
248             file->size = hdr->size;
249             file->data = cfg_blob + hdr->offset;
250             file->hash = hdr->hash;
251
252             V3_Print(VM_NONE, VCORE_NONE, "Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
253             V3_Print(VM_NONE, VCORE_NONE, "file data at %p\n", file->data);
254             V3_Print(VM_NONE, VCORE_NONE, "Checking file data integrity...\n");
255             if ((hash = v3_hash_buffer(file->data, file->size)) != file->hash) {
256                 PrintError(VM_NONE, VCORE_NONE, "File data corrupted! (orig hash=0x%lx, new=0x%lx\n",
257                            file->hash, hash);
258                 return NULL;
259             }
260             V3_Print(VM_NONE, VCORE_NONE, "File data OK\n");
261             
262         }
263             
264             
265         list_add( &(file->file_node), &(cfg->file_list));
266
267         V3_Print(VM_NONE, VCORE_NONE, "Keying file to name\n");
268         v3_htable_insert(cfg->file_table, (addr_t)(file->tag), (addr_t)(file));
269
270         V3_Print(VM_NONE, VCORE_NONE, "Iterating to next file\n");
271
272         file_tree = v3_cfg_next_branch(file_tree);
273     }
274
275     V3_Print(VM_NONE, VCORE_NONE, "Configuration parsed successfully\n");
276
277     return cfg;
278 }
279
280
281 static inline uint32_t get_alignment(char * align_str) {
282     // default is 4KB alignment
283     uint32_t alignment = PAGE_SIZE_4KB;
284
285     if (align_str != NULL) {
286         if (strcasecmp(align_str, "2MB") == 0) {
287             alignment = PAGE_SIZE_2MB;
288         } else if (strcasecmp(align_str, "4MB") == 0) {
289             alignment = PAGE_SIZE_4MB;
290         }
291     }
292     
293 #ifndef V3_CONFIG_ALIGNED_PG_ALLOC
294     if (alignment != PAGE_SIZE_4KB) {
295         PrintError(VM_NONE, VCORE_NONE, "Aligned page allocations are not supported in this host (requested alignment=%d)\n", alignment);
296         PrintError(VM_NONE, VCORE_NONE, "Ignoring alignment request\n");
297         alignment = PAGE_SIZE_4KB;
298     }
299 #endif 
300
301     return alignment;
302 }
303
304
305
306 static int pre_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * vm_cfg) {
307     char * memory_str = v3_cfg_val(vm_cfg, "memory");
308     char * schedule_hz_str = v3_cfg_val(vm_cfg, "schedule_hz");
309     char * vm_class = v3_cfg_val(vm_cfg, "class");
310     char * align_str = v3_cfg_val(v3_cfg_subtree(vm_cfg, "memory"), "alignment");
311     uint32_t sched_hz = 100;    // set the schedule frequency to 100 HZ
312    
313
314     if (!memory_str) {
315         PrintError(VM_NONE, VCORE_NONE, "Memory is a required configuration parameter\n");
316         return -1;
317     }
318     
319     PrintDebug(VM_NONE, VCORE_NONE, "Memory=%s\n", memory_str);
320     if (align_str) {
321          PrintDebug(VM_NONE, VCORE_NONE, "Alignment=%s\n", align_str);
322     } else {
323          PrintDebug(VM_NONE, VCORE_NONE, "Alignment defaulted to 4KB.\n");
324     }
325
326     // Amount of ram the Guest will have, always in MB
327     vm->mem_size = (addr_t)atoi(memory_str) * 1024 * 1024;
328     vm->mem_align = get_alignment(align_str);
329
330     // set up defaults for memory management for threads associated 
331     // with this VM
332     vm->resource_control.pg_alignment=vm->mem_align;
333     vm->resource_control.pg_node_id=-1;
334     
335 #ifdef V3_CONFIG_SWAPPING
336     if (v3_init_swapping_vm(vm,vm_cfg)) {
337         PrintError(vm,VCORE_NONE,"Unable to initialize swapping correctly\n");
338         return -1;
339     }
340     if (vm->swap_state.enable_swapping) { 
341         PrintDebug(vm,VCORE_NONE,"Swapping enabled\n");
342     } else {
343         PrintDebug(vm,VCORE_NONE,"Swapping disabled\n");
344     }
345 #endif
346         
347     PrintDebug(VM_NONE, VCORE_NONE, "Alignment for %lu bytes of memory computed as 0x%x\n", vm->mem_size, vm->mem_align);
348
349     if (strcasecmp(vm_class, "PC") == 0) {
350         vm->vm_class = V3_PC_VM;
351     } else {
352         PrintError(VM_NONE, VCORE_NONE, "Invalid VM class\n");
353         return -1;
354     }
355
356 #ifdef V3_CONFIG_TELEMETRY
357     {
358         char * telemetry = v3_cfg_val(vm_cfg, "telemetry");
359
360         // This should go first, because other subsystems will depend on the guest_info flag    
361         if ((telemetry) && (strcasecmp(telemetry, "enable") == 0)) {
362             vm->enable_telemetry = 1;
363         } else {
364             vm->enable_telemetry = 0;
365         }
366     }
367 #endif
368
369     if (v3_init_vm(vm) == -1) {
370         PrintError(VM_NONE, VCORE_NONE, "Failed to initialize VM\n");
371         return -1;
372     }
373
374 #ifdef V3_CONFIG_MULTIBOOT
375     if (v3_init_multiboot_vm(vm,vm_cfg)) { 
376         PrintError(vm,VCORE_NONE,"Cannot initialize Multiboot for VM\n");
377         return -1;
378     }
379 #endif
380 #ifdef V3_CONFIG_HVM
381     if (v3_init_hvm_vm(vm,vm_cfg)) { 
382         PrintError(vm,VCORE_NONE,"Cannot initialize HVM for VM\n");
383         return -1;
384     }
385 #endif
386
387    if (schedule_hz_str) {
388         sched_hz = atoi(schedule_hz_str);
389         if (sched_hz==0) { 
390             PrintError(vm,VCORE_NONE,"Cannot set sched Hz to 0\n");
391             return -1;
392         }
393     }
394
395     PrintDebug(VM_NONE, VCORE_NONE, "CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), 
396                (void *)(addr_t)sched_hz);
397
398     vm->yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;
399     
400     return 0;
401 }
402
403
404 static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
405     extern v3_cpu_arch_t v3_mach_type;
406
407     v3_cfg_tree_t * vm_tree = info->vm_info->cfg_data->cfg;
408     v3_cfg_tree_t * pg_tree = v3_cfg_subtree(vm_tree, "paging");
409     char * pg_mode          = v3_cfg_val(pg_tree, "mode");
410     
411     PrintDebug(info->vm_info, info, "Paging mode specified as %s\n", pg_mode);
412
413     if (pg_mode) {
414         if ((strcasecmp(pg_mode, "nested") == 0)) {
415             // we assume symmetric cores, so if core 0 has nested paging they all do
416             if ((v3_mach_type == V3_SVM_REV3_CPU) || 
417                 (v3_mach_type == V3_VMX_EPT_CPU) ||
418                 (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
419                 
420                 V3_Print(info->vm_info, info, "Setting paging mode to NESTED\n");
421                 info->shdw_pg_mode = NESTED_PAGING;
422             } else {
423                 PrintError(info->vm_info, info, "Nested paging not supported on this hardware. Defaulting to shadow paging\n");
424                 info->shdw_pg_mode = SHADOW_PAGING;
425             }
426         } else if ((strcasecmp(pg_mode, "shadow") == 0)) {
427             V3_Print(info->vm_info, info, "Setting paging mode to SHADOW\n");
428             info->shdw_pg_mode = SHADOW_PAGING;
429         } else {
430             PrintError(info->vm_info, info, "Invalid paging mode (%s) specified in configuration. Defaulting to shadow paging\n", pg_mode);
431             info->shdw_pg_mode = SHADOW_PAGING;
432         }
433     } else {
434         V3_Print(info->vm_info, info, "No paging type specified in configuration. Defaulting to shadow paging\n");
435         info->shdw_pg_mode = SHADOW_PAGING;
436     }
437
438
439     if (v3_cfg_val(pg_tree, "large_pages") != NULL) {
440         if (strcasecmp(v3_cfg_val(pg_tree, "large_pages"), "true") == 0) {
441             info->use_large_pages = 1;
442             PrintDebug(info->vm_info, info, "Use of large pages in memory virtualization enabled.\n");
443         }
444     }
445     return 0;
446 }
447
448 static int pre_config_core(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
449     if (determine_paging_mode(info, core_cfg) != 0) {
450         return -1;
451     }
452
453     if (v3_init_core(info) == -1) {
454         PrintError(info->vm_info, info, "Error Initializing Core\n");
455         return -1;
456     }
457
458 #ifdef V3_CONFIG_MULTIBOOT
459     if (v3_init_multiboot_core(info)) { 
460         PrintError(info->vm_info, info, "Error Initializing Multiboot Core\n");
461         return -1;
462     }
463 #endif
464 #ifdef V3_CONFIG_HVM
465     if (v3_init_hvm_core(info)) { 
466         PrintError(info->vm_info, info, "Error Initializing HVM Core\n");
467         return -1;
468     }
469 #endif
470
471     if (info->vm_info->vm_class == V3_PC_VM) {
472         if (pre_config_pc_core(info, core_cfg) == -1) {
473             PrintError(info->vm_info, info, "PC Post configuration failure\n");
474             return -1;
475         }
476     } else {
477         PrintError(info->vm_info, info, "Invalid VM Class\n");
478         return -1;
479     }
480
481     return 0;
482 }
483
484
485
486 static int post_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
487     
488
489
490     // Configure the memory map for the guest
491     if (setup_memory_map(vm, cfg) == -1) {
492         PrintError(vm, VCORE_NONE,"Setting up guest memory map failed...\n");
493         return -1;
494     }
495
496
497     if (vm->vm_class == V3_PC_VM) {
498         if (post_config_pc(vm, cfg) == -1) {
499             PrintError(vm, VCORE_NONE,"PC Post configuration failure\n");
500             return -1;
501         }
502     } else {
503         PrintError(vm, VCORE_NONE,"Invalid VM Class\n");
504         return -1;
505     }
506
507
508
509     // Initialize fw_cfg state for VMM<->VM SEABIOS communication
510     if (v3_fw_cfg_init(vm) == -1) {
511         PrintError(vm, VCORE_NONE, "Error initializing Firmware Config (fw_cfg) state\n");
512         return -1;
513     }
514
515     /* 
516      * Initialize configured devices
517      */
518     if (setup_devices(vm, cfg) == -1) {
519         PrintError(vm, VCORE_NONE,"Failed to setup devices\n");
520         return -1;
521     }
522
523
524     //    v3_print_io_map(info);
525     v3_print_msr_map(vm);
526
527
528
529
530     /* 
531      * Initialize configured extensions 
532      */
533     if (setup_extensions(vm, cfg) == -1) {
534         PrintError(vm, VCORE_NONE,"Failed to setup extensions\n");
535         return -1;
536     }
537
538     if (v3_setup_performance_tuning(vm, cfg) == -1) { 
539         PrintError(vm, VCORE_NONE,"Failed to configure performance tuning parameters\n");
540         return -1;
541     }
542
543
544     vm->run_state = VM_STOPPED;
545
546     return 0;
547 }
548
549
550
551 static int post_config_core(struct guest_info * info, v3_cfg_tree_t * cfg) {
552
553  
554     if (v3_init_core_extensions(info) == -1) {
555         PrintError(info->vm_info, info, "Error intializing extension core states\n");
556         return -1;
557     }
558
559     if (info->vm_info->vm_class == V3_PC_VM) {
560         if (post_config_pc_core(info, cfg) == -1) {
561             PrintError(info->vm_info, info, "PC Post configuration failure\n");
562             return -1;
563         }
564     } else {
565         PrintError(info->vm_info, info, "Invalid VM Class\n");
566         return -1;
567     }
568
569
570     return 0;
571 }
572
573
574
575 static struct v3_vm_info * allocate_guest(int num_cores) {
576     int guest_state_size = sizeof(struct v3_vm_info) + (sizeof(struct guest_info) * num_cores);
577     struct v3_vm_info * vm = V3_Malloc(guest_state_size);
578
579     if (!vm) {
580         PrintError(VM_NONE, VCORE_NONE, "Unable to allocate space for guest data structures\n");
581         return NULL;
582     }
583
584     int i = 0;
585
586     memset(vm, 0, guest_state_size);
587
588     vm->num_cores = num_cores;
589
590     for (i = 0; i < num_cores; i++) {
591         vm->cores[i].core_run_state = CORE_INVALID;
592     }
593
594     vm->run_state = VM_INVALID;
595
596     return vm;
597 }
598
599 /*
600    
601
602 */
603
604
605 struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
606     extern v3_cpu_arch_t v3_mach_type;
607     struct v3_config * cfg_data = NULL;
608     struct v3_vm_info * vm = NULL;
609     int num_cores = 0;
610     int i = 0;
611     v3_cfg_tree_t * cores_cfg = NULL;
612     v3_cfg_tree_t * per_core_cfg = NULL;
613
614
615     if (v3_mach_type == V3_INVALID_CPU) {
616         PrintError(VM_NONE, VCORE_NONE, "Configuring guest on invalid CPU\n");
617         return NULL;
618     }
619
620     cfg_data = parse_config(cfg_blob);
621
622
623     if (!cfg_data) {
624         PrintError(VM_NONE, VCORE_NONE, "Could not parse configuration\n");
625         return NULL;
626     }
627
628
629     cores_cfg = v3_cfg_subtree(cfg_data->cfg, "cores");
630
631     if (!cores_cfg) {
632         PrintError(VM_NONE, VCORE_NONE, "Could not find core configuration (new config format required)\n");
633         return NULL;
634     }
635
636     num_cores = atoi(v3_cfg_val(cores_cfg, "count"));
637     if (num_cores == 0) {
638         PrintError(VM_NONE, VCORE_NONE, "No cores specified in configuration\n");
639         return NULL;
640     }
641
642     V3_Print(VM_NONE, VCORE_NONE, "Configuring %d cores\n", num_cores);
643
644     vm = allocate_guest(num_cores);    
645
646     if (!vm) {
647         PrintError(VM_NONE, VCORE_NONE, "Could not allocate %d core guest\n", num_cores);
648         return NULL;
649     }
650
651 #ifdef V3_CONFIG_CACHEPART
652     // Need to initialize cache management and resource control
653     // as early as possible so that allocations are done accordingly
654     if (v3_init_cachepart_vm(vm,cfg_data->cfg)) {
655         PrintError(VM_NONE, VCORE_NONE, "Could not initialize cache partioning\n");
656         V3_Free(vm);
657         return NULL;
658     }
659 #endif
660
661     vm->host_priv_data = priv_data;
662
663     vm->cfg_data = cfg_data;
664
665     V3_Print(vm, VCORE_NONE, "Preconfiguration\n");
666
667     if (pre_config_vm(vm, vm->cfg_data->cfg) == -1) {
668         PrintError(vm, VCORE_NONE, "Error in preconfiguration, attempting to free\n");
669         vm->run_state=VM_ERROR;
670         v3_free_vm(vm);
671         return NULL;
672     }
673
674     V3_Print(vm, VCORE_NONE, "Per core configuration\n");
675     per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
676
677     // per core configuration
678     for (i = 0; i < vm->num_cores; i++) {
679         struct guest_info * info = &(vm->cores[i]);
680
681         info->vcpu_id = i;
682         info->vm_info = vm;
683         info->core_cfg_data = per_core_cfg;
684
685         if (pre_config_core(info, per_core_cfg) == -1) {
686             PrintError(vm, VCORE_NONE, "Error in core %d preconfiguration, attempting to free guest\n", i);
687             vm->run_state=VM_ERROR;
688             v3_free_vm(vm);
689             return NULL;
690         }
691
692
693         per_core_cfg = v3_cfg_next_branch(per_core_cfg);
694     }
695
696
697     V3_Print(vm, VCORE_NONE, "Post Configuration\n");
698
699     if (post_config_vm(vm, vm->cfg_data->cfg) == -1) {
700         PrintError(vm, VCORE_NONE, "Error in postconfiguration, attempting to free guest\n");
701         vm->run_state=VM_ERROR;
702         v3_free_vm(vm);
703         return NULL;
704     }
705
706
707     per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
708
709     // per core configuration
710     for (i = 0; i < vm->num_cores; i++) {
711         struct guest_info * info = &(vm->cores[i]);
712
713         post_config_core(info, per_core_cfg);
714
715         per_core_cfg = v3_cfg_next_branch(per_core_cfg);
716     }
717
718     V3_Print(vm, VCORE_NONE, "Configuration successfull\n");
719
720     return vm;
721 }
722
723
724
725 int v3_free_config(struct v3_vm_info * vm) {
726    
727     v3_free_htable(vm->cfg_data->file_table, 1, 0);
728
729     v3_xml_free(vm->cfg_data->cfg);
730
731     V3_Free(vm->cfg_data);
732     return 0;
733 }
734
735
736
737
738 static int setup_memory_map(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
739     v3_cfg_tree_t * mem_region = v3_cfg_subtree(v3_cfg_subtree(cfg, "memmap"), "region");
740
741     while (mem_region) {
742         addr_t start_addr = atox(v3_cfg_val(mem_region, "start"));
743         addr_t end_addr = atox(v3_cfg_val(mem_region, "end"));
744         addr_t host_addr = atox(v3_cfg_val(mem_region, "host_addr"));
745
746     
747         if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY, start_addr, end_addr, host_addr) == -1) {
748             PrintError(vm, VCORE_NONE,"Could not map memory region: %p-%p => %p\n", 
749                        (void *)start_addr, (void *)end_addr, (void *)host_addr);
750             return -1;
751         }
752
753         mem_region = v3_cfg_next_branch(mem_region);
754     }
755
756     return 0;
757 }
758
759
760 static int setup_extensions(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
761     v3_cfg_tree_t * extension = v3_cfg_subtree(v3_cfg_subtree(cfg, "extensions"), "extension");
762
763     while (extension) {
764         char * ext_name = v3_cfg_val(extension, "name");
765
766         if (!ext_name) {
767             PrintError(vm, VCORE_NONE, "Extension has no name\n");
768             return -1;
769         }
770
771         V3_Print(vm, VCORE_NONE, "Configuring extension %s\n", ext_name);
772
773         if (v3_add_extension(vm, ext_name, extension) == -1) {
774             PrintError(vm, VCORE_NONE, "Error adding extension %s\n", ext_name);
775             return -1;
776         }
777
778         extension = v3_cfg_next_branch(extension);
779     }
780
781     return 0;
782 }
783
784
785 static int setup_devices(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
786     v3_cfg_tree_t * device = v3_cfg_subtree(v3_cfg_subtree(cfg, "devices"), "device");
787
788     
789     while (device) {
790         char * dev_class = v3_cfg_val(device, "class");
791
792         V3_Print(vm, VCORE_NONE, "configuring device %s\n", dev_class);
793
794         if (v3_create_device(vm, dev_class, device) == -1) {
795             PrintError(vm, VCORE_NONE, "Error creating device %s\n", dev_class);
796             return -1;
797         }
798         
799         device = v3_cfg_next_branch(device);
800     }
801
802     v3_print_dev_mgr(vm);
803
804     return 0;
805 }
806
807
808