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.


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