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.


Addition of basic multiboot functionality plus refactor of HVM
[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
233         if (version==0) { 
234             struct file_hdr_v0 * hdr = &(files_v0->hdrs[idx]);
235
236             file->size = hdr->size;
237             file->data = cfg_blob + hdr->offset;
238             file->hash = 0;
239             
240             V3_Print(VM_NONE, VCORE_NONE, "Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
241             V3_Print(VM_NONE, VCORE_NONE, "file data at %p\n", file->data);
242
243         } else if (version==1) { 
244             struct file_hdr_v1 * hdr = &(files_v1->hdrs[idx]);
245             unsigned long hash;
246
247             file->size = hdr->size;
248             file->data = cfg_blob + hdr->offset;
249             file->hash = hdr->hash;
250
251             V3_Print(VM_NONE, VCORE_NONE, "Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
252             V3_Print(VM_NONE, VCORE_NONE, "file data at %p\n", file->data);
253             V3_Print(VM_NONE, VCORE_NONE, "Checking file data integrity...\n");
254             if ((hash = v3_hash_buffer(file->data, file->size)) != file->hash) {
255                 PrintError(VM_NONE, VCORE_NONE, "File data corrupted! (orig hash=0x%lx, new=0x%lx\n",
256                            file->hash, hash);
257                 return NULL;
258             }
259             V3_Print(VM_NONE, VCORE_NONE, "File data OK\n");
260             
261         }
262             
263             
264         list_add( &(file->file_node), &(cfg->file_list));
265
266         V3_Print(VM_NONE, VCORE_NONE, "Keying file to name\n");
267         v3_htable_insert(cfg->file_table, (addr_t)(file->tag), (addr_t)(file));
268
269         V3_Print(VM_NONE, VCORE_NONE, "Iterating to next file\n");
270
271         file_tree = v3_cfg_next_branch(file_tree);
272     }
273
274     V3_Print(VM_NONE, VCORE_NONE, "Configuration parsed successfully\n");
275
276     return cfg;
277 }
278
279
280 static inline uint32_t get_alignment(char * align_str) {
281     // default is 4KB alignment
282     uint32_t alignment = PAGE_SIZE_4KB;
283
284     if (align_str != NULL) {
285         if (strcasecmp(align_str, "2MB") == 0) {
286             alignment = PAGE_SIZE_2MB;
287         } else if (strcasecmp(align_str, "4MB") == 0) {
288             alignment = PAGE_SIZE_4MB;
289         }
290     }
291     
292 #ifndef V3_CONFIG_ALIGNED_PG_ALLOC
293     if (alignment != PAGE_SIZE_4KB) {
294         PrintError(VM_NONE, VCORE_NONE, "Aligned page allocations are not supported in this host (requested alignment=%d)\n", alignment);
295         PrintError(VM_NONE, VCORE_NONE, "Ignoring alignment request\n");
296     }
297 #endif 
298
299     return alignment;
300 }
301
302
303
304 static int pre_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * vm_cfg) {
305     char * memory_str = v3_cfg_val(vm_cfg, "memory");
306     char * schedule_hz_str = v3_cfg_val(vm_cfg, "schedule_hz");
307     char * vm_class = v3_cfg_val(vm_cfg, "class");
308     char * align_str = v3_cfg_val(v3_cfg_subtree(vm_cfg, "memory"), "alignment");
309     uint32_t sched_hz = 100;    // set the schedule frequency to 100 HZ
310    
311
312     if (!memory_str) {
313         PrintError(VM_NONE, VCORE_NONE, "Memory is a required configuration parameter\n");
314         return -1;
315     }
316     
317     PrintDebug(VM_NONE, VCORE_NONE, "Memory=%s\n", memory_str);
318     if (align_str) {
319          PrintDebug(VM_NONE, VCORE_NONE, "Alignment=%s\n", align_str);
320     } else {
321          PrintDebug(VM_NONE, VCORE_NONE, "Alignment defaulted to 4KB.\n");
322     }
323
324     // Amount of ram the Guest will have, always in MB
325     vm->mem_size = (addr_t)atoi(memory_str) * 1024 * 1024;
326     vm->mem_align = get_alignment(align_str);
327     
328 #ifdef V3_CONFIG_SWAPPING
329     if (v3_init_swapping_vm(vm,vm_cfg)) {
330         PrintError(vm,VCORE_NONE,"Unable to initialize swapping correctly\n");
331         return -1;
332     }
333     if (vm->swap_state.enable_swapping) { 
334         PrintDebug(vm,VCORE_NONE,"Swapping enabled\n");
335     } else {
336         PrintDebug(vm,VCORE_NONE,"Swapping disabled\n");
337     }
338 #endif
339         
340     PrintDebug(VM_NONE, VCORE_NONE, "Alignment for %lu bytes of memory computed as 0x%x\n", vm->mem_size, vm->mem_align);
341
342     if (strcasecmp(vm_class, "PC") == 0) {
343         vm->vm_class = V3_PC_VM;
344     } else {
345         PrintError(VM_NONE, VCORE_NONE, "Invalid VM class\n");
346         return -1;
347     }
348
349 #ifdef V3_CONFIG_TELEMETRY
350     {
351         char * telemetry = v3_cfg_val(vm_cfg, "telemetry");
352
353         // This should go first, because other subsystems will depend on the guest_info flag    
354         if ((telemetry) && (strcasecmp(telemetry, "enable") == 0)) {
355             vm->enable_telemetry = 1;
356         } else {
357             vm->enable_telemetry = 0;
358         }
359     }
360 #endif
361
362     if (v3_init_vm(vm) == -1) {
363         PrintError(VM_NONE, VCORE_NONE, "Failed to initialize VM\n");
364         return -1;
365     }
366
367 #ifdef V3_CONFIG_MULTIBOOT
368     if (v3_init_multiboot_vm(vm,vm_cfg)) { 
369         PrintError(vm,VCORE_NONE,"Cannot initialize Multiboot for VM\n");
370         return -1;
371     }
372 #endif
373 #ifdef V3_CONFIG_HVM
374     if (v3_init_hvm_vm(vm,vm_cfg)) { 
375         PrintError(vm,VCORE_NONE,"Cannot initialize HVM for VM\n");
376         return -1;
377     }
378 #endif
379
380    if (schedule_hz_str) {
381         sched_hz = atoi(schedule_hz_str);
382     }
383
384     PrintDebug(VM_NONE, VCORE_NONE, "CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), 
385                (void *)(addr_t)sched_hz);
386
387     vm->yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;
388     
389     return 0;
390 }
391
392
393 static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
394     extern v3_cpu_arch_t v3_mach_type;
395
396     v3_cfg_tree_t * vm_tree = info->vm_info->cfg_data->cfg;
397     v3_cfg_tree_t * pg_tree = v3_cfg_subtree(vm_tree, "paging");
398     char * pg_mode          = v3_cfg_val(pg_tree, "mode");
399     
400     PrintDebug(info->vm_info, info, "Paging mode specified as %s\n", pg_mode);
401
402     if (pg_mode) {
403         if ((strcasecmp(pg_mode, "nested") == 0)) {
404             // we assume symmetric cores, so if core 0 has nested paging they all do
405             if ((v3_mach_type == V3_SVM_REV3_CPU) || 
406                 (v3_mach_type == V3_VMX_EPT_CPU) ||
407                 (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
408                 
409                 V3_Print(info->vm_info, info, "Setting paging mode to NESTED\n");
410                 info->shdw_pg_mode = NESTED_PAGING;
411             } else {
412                 PrintError(info->vm_info, info, "Nested paging not supported on this hardware. Defaulting to shadow paging\n");
413                 info->shdw_pg_mode = SHADOW_PAGING;
414             }
415         } else if ((strcasecmp(pg_mode, "shadow") == 0)) {
416             V3_Print(info->vm_info, info, "Setting paging mode to SHADOW\n");
417             info->shdw_pg_mode = SHADOW_PAGING;
418         } else {
419             PrintError(info->vm_info, info, "Invalid paging mode (%s) specified in configuration. Defaulting to shadow paging\n", pg_mode);
420             info->shdw_pg_mode = SHADOW_PAGING;
421         }
422     } else {
423         V3_Print(info->vm_info, info, "No paging type specified in configuration. Defaulting to shadow paging\n");
424         info->shdw_pg_mode = SHADOW_PAGING;
425     }
426
427
428     if (v3_cfg_val(pg_tree, "large_pages") != NULL) {
429         if (strcasecmp(v3_cfg_val(pg_tree, "large_pages"), "true") == 0) {
430             info->use_large_pages = 1;
431             PrintDebug(info->vm_info, info, "Use of large pages in memory virtualization enabled.\n");
432         }
433     }
434     return 0;
435 }
436
437 static int pre_config_core(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
438     if (determine_paging_mode(info, core_cfg) != 0) {
439         return -1;
440     }
441
442     if (v3_init_core(info) == -1) {
443         PrintError(info->vm_info, info, "Error Initializing Core\n");
444         return -1;
445     }
446
447 #ifdef V3_CONFIG_MULTIBOOT
448     if (v3_init_multiboot_core(info)) { 
449         PrintError(info->vm_info, info, "Error Initializing Multiboot Core\n");
450         return -1;
451     }
452 #endif
453 #ifdef V3_CONFIG_HVM
454     if (v3_init_hvm_core(info)) { 
455         PrintError(info->vm_info, info, "Error Initializing HVM Core\n");
456         return -1;
457     }
458 #endif
459
460     if (info->vm_info->vm_class == V3_PC_VM) {
461         if (pre_config_pc_core(info, core_cfg) == -1) {
462             PrintError(info->vm_info, info, "PC Post configuration failure\n");
463             return -1;
464         }
465     } else {
466         PrintError(info->vm_info, info, "Invalid VM Class\n");
467         return -1;
468     }
469
470     return 0;
471 }
472
473
474
475 static int post_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
476     
477
478
479     // Configure the memory map for the guest
480     if (setup_memory_map(vm, cfg) == -1) {
481         PrintError(vm, VCORE_NONE,"Setting up guest memory map failed...\n");
482         return -1;
483     }
484
485
486     if (vm->vm_class == V3_PC_VM) {
487         if (post_config_pc(vm, cfg) == -1) {
488             PrintError(vm, VCORE_NONE,"PC Post configuration failure\n");
489             return -1;
490         }
491     } else {
492         PrintError(vm, VCORE_NONE,"Invalid VM Class\n");
493         return -1;
494     }
495
496
497
498     // Initialize fw_cfg state for VMM<->VM SEABIOS communication
499     if (v3_fw_cfg_init(vm) == -1) {
500         PrintError(vm, VCORE_NONE, "Error initializing Firmware Config (fw_cfg) state\n");
501         return -1;
502     }
503
504     /* 
505      * Initialize configured devices
506      */
507     if (setup_devices(vm, cfg) == -1) {
508         PrintError(vm, VCORE_NONE,"Failed to setup devices\n");
509         return -1;
510     }
511
512
513     //    v3_print_io_map(info);
514     v3_print_msr_map(vm);
515
516
517
518
519     /* 
520      * Initialize configured extensions 
521      */
522     if (setup_extensions(vm, cfg) == -1) {
523         PrintError(vm, VCORE_NONE,"Failed to setup extensions\n");
524         return -1;
525     }
526
527     if (v3_setup_performance_tuning(vm, cfg) == -1) { 
528         PrintError(vm, VCORE_NONE,"Failed to configure performance tuning parameters\n");
529         return -1;
530     }
531
532
533     vm->run_state = VM_STOPPED;
534
535     return 0;
536 }
537
538
539
540 static int post_config_core(struct guest_info * info, v3_cfg_tree_t * cfg) {
541
542  
543     if (v3_init_core_extensions(info) == -1) {
544         PrintError(info->vm_info, info, "Error intializing extension core states\n");
545         return -1;
546     }
547
548     if (info->vm_info->vm_class == V3_PC_VM) {
549         if (post_config_pc_core(info, cfg) == -1) {
550             PrintError(info->vm_info, info, "PC Post configuration failure\n");
551             return -1;
552         }
553     } else {
554         PrintError(info->vm_info, info, "Invalid VM Class\n");
555         return -1;
556     }
557
558
559     return 0;
560 }
561
562
563
564 static struct v3_vm_info * allocate_guest(int num_cores) {
565     int guest_state_size = sizeof(struct v3_vm_info) + (sizeof(struct guest_info) * num_cores);
566     struct v3_vm_info * vm = V3_Malloc(guest_state_size);
567
568     if (!vm) {
569         PrintError(VM_NONE, VCORE_NONE, "Unable to allocate space for guest data structures\n");
570         return NULL;
571     }
572
573     int i = 0;
574
575     memset(vm, 0, guest_state_size);
576
577     vm->num_cores = num_cores;
578
579     for (i = 0; i < num_cores; i++) {
580         vm->cores[i].core_run_state = CORE_INVALID;
581     }
582
583     vm->run_state = VM_INVALID;
584
585     return vm;
586 }
587
588
589
590 struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
591     extern v3_cpu_arch_t v3_mach_type;
592     struct v3_config * cfg_data = NULL;
593     struct v3_vm_info * vm = NULL;
594     int num_cores = 0;
595     int i = 0;
596     v3_cfg_tree_t * cores_cfg = NULL;
597     v3_cfg_tree_t * per_core_cfg = NULL;
598
599     if (v3_mach_type == V3_INVALID_CPU) {
600         PrintError(VM_NONE, VCORE_NONE, "Configuring guest on invalid CPU\n");
601         return NULL;
602     }
603
604     cfg_data = parse_config(cfg_blob);
605
606     if (!cfg_data) {
607         PrintError(VM_NONE, VCORE_NONE, "Could not parse configuration\n");
608         return NULL;
609     }
610
611     cores_cfg = v3_cfg_subtree(cfg_data->cfg, "cores");
612
613     if (!cores_cfg) {
614         PrintError(VM_NONE, VCORE_NONE, "Could not find core configuration (new config format required)\n");
615         return NULL;
616     }
617
618     num_cores = atoi(v3_cfg_val(cores_cfg, "count"));
619     if (num_cores == 0) {
620         PrintError(VM_NONE, VCORE_NONE, "No cores specified in configuration\n");
621         return NULL;
622     }
623
624     V3_Print(VM_NONE, VCORE_NONE, "Configuring %d cores\n", num_cores);
625
626     vm = allocate_guest(num_cores);    
627
628     if (!vm) {
629         PrintError(VM_NONE, VCORE_NONE, "Could not allocate %d core guest\n", vm->num_cores);
630         return NULL;
631     }
632
633     vm->host_priv_data = priv_data;
634
635     vm->cfg_data = cfg_data;
636
637     V3_Print(vm, VCORE_NONE, "Preconfiguration\n");
638
639     if (pre_config_vm(vm, vm->cfg_data->cfg) == -1) {
640         PrintError(vm, VCORE_NONE, "Error in preconfiguration, attempting to free\n");
641         vm->run_state=VM_ERROR;
642         v3_free_vm(vm);
643         return NULL;
644     }
645
646     V3_Print(vm, VCORE_NONE, "Per core configuration\n");
647     per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
648
649     // per core configuration
650     for (i = 0; i < vm->num_cores; i++) {
651         struct guest_info * info = &(vm->cores[i]);
652
653         info->vcpu_id = i;
654         info->vm_info = vm;
655         info->core_cfg_data = per_core_cfg;
656
657         if (pre_config_core(info, per_core_cfg) == -1) {
658             PrintError(vm, VCORE_NONE, "Error in core %d preconfiguration, attempting to free guest\n", i);
659             vm->run_state=VM_ERROR;
660             v3_free_vm(vm);
661             return NULL;
662         }
663
664
665         per_core_cfg = v3_cfg_next_branch(per_core_cfg);
666     }
667
668
669     V3_Print(vm, VCORE_NONE, "Post Configuration\n");
670
671     if (post_config_vm(vm, vm->cfg_data->cfg) == -1) {
672         PrintError(vm, VCORE_NONE, "Error in postconfiguration, attempting to free guest\n");
673         vm->run_state=VM_ERROR;
674         v3_free_vm(vm);
675         return NULL;
676     }
677
678
679     per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
680
681     // per core configuration
682     for (i = 0; i < vm->num_cores; i++) {
683         struct guest_info * info = &(vm->cores[i]);
684
685         post_config_core(info, per_core_cfg);
686
687         per_core_cfg = v3_cfg_next_branch(per_core_cfg);
688     }
689
690     V3_Print(vm, VCORE_NONE, "Configuration successfull\n");
691
692     return vm;
693 }
694
695
696
697 int v3_free_config(struct v3_vm_info * vm) {
698    
699     v3_free_htable(vm->cfg_data->file_table, 1, 0);
700
701     v3_xml_free(vm->cfg_data->cfg);
702
703     V3_Free(vm->cfg_data);
704     return 0;
705 }
706
707
708
709
710 static int setup_memory_map(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
711     v3_cfg_tree_t * mem_region = v3_cfg_subtree(v3_cfg_subtree(cfg, "memmap"), "region");
712
713     while (mem_region) {
714         addr_t start_addr = atox(v3_cfg_val(mem_region, "start"));
715         addr_t end_addr = atox(v3_cfg_val(mem_region, "end"));
716         addr_t host_addr = atox(v3_cfg_val(mem_region, "host_addr"));
717
718     
719         if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY, start_addr, end_addr, host_addr) == -1) {
720             PrintError(vm, VCORE_NONE,"Could not map memory region: %p-%p => %p\n", 
721                        (void *)start_addr, (void *)end_addr, (void *)host_addr);
722             return -1;
723         }
724
725         mem_region = v3_cfg_next_branch(mem_region);
726     }
727
728     return 0;
729 }
730
731
732 static int setup_extensions(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
733     v3_cfg_tree_t * extension = v3_cfg_subtree(v3_cfg_subtree(cfg, "extensions"), "extension");
734
735     while (extension) {
736         char * ext_name = v3_cfg_val(extension, "name");
737
738         if (!ext_name) {
739             PrintError(vm, VCORE_NONE, "Extension has no name\n");
740             return -1;
741         }
742
743         V3_Print(vm, VCORE_NONE, "Configuring extension %s\n", ext_name);
744
745         if (v3_add_extension(vm, ext_name, extension) == -1) {
746             PrintError(vm, VCORE_NONE, "Error adding extension %s\n", ext_name);
747             return -1;
748         }
749
750         extension = v3_cfg_next_branch(extension);
751     }
752
753     return 0;
754 }
755
756
757 static int setup_devices(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
758     v3_cfg_tree_t * device = v3_cfg_subtree(v3_cfg_subtree(cfg, "devices"), "device");
759
760     
761     while (device) {
762         char * dev_class = v3_cfg_val(device, "class");
763
764         V3_Print(vm, VCORE_NONE, "configuring device %s\n", dev_class);
765
766         if (v3_create_device(vm, dev_class, device) == -1) {
767             PrintError(vm, VCORE_NONE, "Error creating device %s\n", dev_class);
768             return -1;
769         }
770         
771         device = v3_cfg_next_branch(device);
772     }
773
774     v3_print_dev_mgr(vm);
775
776     return 0;
777 }
778
779
780