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.


Basic HRT startup for HVM, plus assorted cleanup
[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     if (v3_init_vm(vm) == -1) {
359         PrintError(VM_NONE, VCORE_NONE, "Failed to initialize VM\n");
360         return -1;
361     }
362
363 #ifdef V3_CONFIG_HVM
364     if (v3_init_hvm_vm(vm,vm_cfg)) { 
365         PrintError(vm,VCORE_NONE,"Cannot initialize HVM for VM\n");
366         return -1;
367     }
368 #endif
369
370    if (schedule_hz_str) {
371         sched_hz = atoi(schedule_hz_str);
372     }
373
374     PrintDebug(VM_NONE, VCORE_NONE, "CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), 
375                (void *)(addr_t)sched_hz);
376
377     vm->yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;
378     
379     return 0;
380 }
381
382
383 static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
384     extern v3_cpu_arch_t v3_mach_type;
385
386     v3_cfg_tree_t * vm_tree = info->vm_info->cfg_data->cfg;
387     v3_cfg_tree_t * pg_tree = v3_cfg_subtree(vm_tree, "paging");
388     char * pg_mode          = v3_cfg_val(pg_tree, "mode");
389     
390     PrintDebug(info->vm_info, info, "Paging mode specified as %s\n", pg_mode);
391
392     if (pg_mode) {
393         if ((strcasecmp(pg_mode, "nested") == 0)) {
394             // we assume symmetric cores, so if core 0 has nested paging they all do
395             if ((v3_mach_type == V3_SVM_REV3_CPU) || 
396                 (v3_mach_type == V3_VMX_EPT_CPU) ||
397                 (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
398                 
399                 V3_Print(info->vm_info, info, "Setting paging mode to NESTED\n");
400                 info->shdw_pg_mode = NESTED_PAGING;
401             } else {
402                 PrintError(info->vm_info, info, "Nested paging not supported on this hardware. Defaulting to shadow paging\n");
403                 info->shdw_pg_mode = SHADOW_PAGING;
404             }
405         } else if ((strcasecmp(pg_mode, "shadow") == 0)) {
406             V3_Print(info->vm_info, info, "Setting paging mode to SHADOW\n");
407             info->shdw_pg_mode = SHADOW_PAGING;
408         } else {
409             PrintError(info->vm_info, info, "Invalid paging mode (%s) specified in configuration. Defaulting to shadow paging\n", pg_mode);
410             info->shdw_pg_mode = SHADOW_PAGING;
411         }
412     } else {
413         V3_Print(info->vm_info, info, "No paging type specified in configuration. Defaulting to shadow paging\n");
414         info->shdw_pg_mode = SHADOW_PAGING;
415     }
416
417
418     if (v3_cfg_val(pg_tree, "large_pages") != NULL) {
419         if (strcasecmp(v3_cfg_val(pg_tree, "large_pages"), "true") == 0) {
420             info->use_large_pages = 1;
421             PrintDebug(info->vm_info, info, "Use of large pages in memory virtualization enabled.\n");
422         }
423     }
424     return 0;
425 }
426
427 static int pre_config_core(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
428     if (determine_paging_mode(info, core_cfg) != 0) {
429         return -1;
430     }
431
432     if (v3_init_core(info) == -1) {
433         PrintError(info->vm_info, info, "Error Initializing Core\n");
434         return -1;
435     }
436
437 #ifdef V3_CONFIG_HVM
438     if (v3_init_hvm_core(info)) { 
439         PrintError(info->vm_info, info, "Error Initializing HVM Core\n");
440         return -1;
441     }
442 #endif
443
444     if (info->vm_info->vm_class == V3_PC_VM) {
445         if (pre_config_pc_core(info, core_cfg) == -1) {
446             PrintError(info->vm_info, info, "PC Post configuration failure\n");
447             return -1;
448         }
449     } else {
450         PrintError(info->vm_info, info, "Invalid VM Class\n");
451         return -1;
452     }
453
454     return 0;
455 }
456
457
458
459 static int post_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
460     
461
462
463     // Configure the memory map for the guest
464     if (setup_memory_map(vm, cfg) == -1) {
465         PrintError(vm, VCORE_NONE,"Setting up guest memory map failed...\n");
466         return -1;
467     }
468
469
470     if (vm->vm_class == V3_PC_VM) {
471         if (post_config_pc(vm, cfg) == -1) {
472             PrintError(vm, VCORE_NONE,"PC Post configuration failure\n");
473             return -1;
474         }
475     } else {
476         PrintError(vm, VCORE_NONE,"Invalid VM Class\n");
477         return -1;
478     }
479
480
481
482     // Initialize fw_cfg state for VMM<->VM SEABIOS communication
483     if (v3_fw_cfg_init(vm) == -1) {
484         PrintError(vm, VCORE_NONE, "Error initializing Firmware Config (fw_cfg) state\n");
485         return -1;
486     }
487
488     /* 
489      * Initialize configured devices
490      */
491     if (setup_devices(vm, cfg) == -1) {
492         PrintError(vm, VCORE_NONE,"Failed to setup devices\n");
493         return -1;
494     }
495
496
497     //    v3_print_io_map(info);
498     v3_print_msr_map(vm);
499
500
501
502
503     /* 
504      * Initialize configured extensions 
505      */
506     if (setup_extensions(vm, cfg) == -1) {
507         PrintError(vm, VCORE_NONE,"Failed to setup extensions\n");
508         return -1;
509     }
510
511     if (v3_setup_performance_tuning(vm, cfg) == -1) { 
512         PrintError(vm, VCORE_NONE,"Failed to configure performance tuning parameters\n");
513         return -1;
514     }
515
516
517     vm->run_state = VM_STOPPED;
518
519     return 0;
520 }
521
522
523
524 static int post_config_core(struct guest_info * info, v3_cfg_tree_t * cfg) {
525
526  
527     if (v3_init_core_extensions(info) == -1) {
528         PrintError(info->vm_info, info, "Error intializing extension core states\n");
529         return -1;
530     }
531
532     if (info->vm_info->vm_class == V3_PC_VM) {
533         if (post_config_pc_core(info, cfg) == -1) {
534             PrintError(info->vm_info, info, "PC Post configuration failure\n");
535             return -1;
536         }
537     } else {
538         PrintError(info->vm_info, info, "Invalid VM Class\n");
539         return -1;
540     }
541
542
543     return 0;
544 }
545
546
547
548 static struct v3_vm_info * allocate_guest(int num_cores) {
549     int guest_state_size = sizeof(struct v3_vm_info) + (sizeof(struct guest_info) * num_cores);
550     struct v3_vm_info * vm = V3_Malloc(guest_state_size);
551
552     if (!vm) {
553         PrintError(VM_NONE, VCORE_NONE, "Unable to allocate space for guest data structures\n");
554         return NULL;
555     }
556
557     int i = 0;
558
559     memset(vm, 0, guest_state_size);
560
561     vm->num_cores = num_cores;
562
563     for (i = 0; i < num_cores; i++) {
564         vm->cores[i].core_run_state = CORE_INVALID;
565     }
566
567     vm->run_state = VM_INVALID;
568
569     return vm;
570 }
571
572
573
574 struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
575     extern v3_cpu_arch_t v3_mach_type;
576     struct v3_config * cfg_data = NULL;
577     struct v3_vm_info * vm = NULL;
578     int num_cores = 0;
579     int i = 0;
580     v3_cfg_tree_t * cores_cfg = NULL;
581     v3_cfg_tree_t * per_core_cfg = NULL;
582
583     if (v3_mach_type == V3_INVALID_CPU) {
584         PrintError(VM_NONE, VCORE_NONE, "Configuring guest on invalid CPU\n");
585         return NULL;
586     }
587
588     cfg_data = parse_config(cfg_blob);
589
590     if (!cfg_data) {
591         PrintError(VM_NONE, VCORE_NONE, "Could not parse configuration\n");
592         return NULL;
593     }
594
595     cores_cfg = v3_cfg_subtree(cfg_data->cfg, "cores");
596
597     if (!cores_cfg) {
598         PrintError(VM_NONE, VCORE_NONE, "Could not find core configuration (new config format required)\n");
599         return NULL;
600     }
601
602     num_cores = atoi(v3_cfg_val(cores_cfg, "count"));
603     if (num_cores == 0) {
604         PrintError(VM_NONE, VCORE_NONE, "No cores specified in configuration\n");
605         return NULL;
606     }
607
608     V3_Print(VM_NONE, VCORE_NONE, "Configuring %d cores\n", num_cores);
609
610     vm = allocate_guest(num_cores);    
611
612     if (!vm) {
613         PrintError(VM_NONE, VCORE_NONE, "Could not allocate %d core guest\n", vm->num_cores);
614         return NULL;
615     }
616
617     vm->host_priv_data = priv_data;
618
619     vm->cfg_data = cfg_data;
620
621     V3_Print(vm, VCORE_NONE, "Preconfiguration\n");
622
623     if (pre_config_vm(vm, vm->cfg_data->cfg) == -1) {
624         PrintError(vm, VCORE_NONE, "Error in preconfiguration, attempting to free\n");
625         vm->run_state=VM_ERROR;
626         v3_free_vm(vm);
627         return NULL;
628     }
629
630     V3_Print(vm, VCORE_NONE, "Per core configuration\n");
631     per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
632
633     // per core configuration
634     for (i = 0; i < vm->num_cores; i++) {
635         struct guest_info * info = &(vm->cores[i]);
636
637         info->vcpu_id = i;
638         info->vm_info = vm;
639         info->core_cfg_data = per_core_cfg;
640
641         if (pre_config_core(info, per_core_cfg) == -1) {
642             PrintError(vm, VCORE_NONE, "Error in core %d preconfiguration, attempting to free guest\n", i);
643             vm->run_state=VM_ERROR;
644             v3_free_vm(vm);
645             return NULL;
646         }
647
648
649         per_core_cfg = v3_cfg_next_branch(per_core_cfg);
650     }
651
652
653     V3_Print(vm, VCORE_NONE, "Post Configuration\n");
654
655     if (post_config_vm(vm, vm->cfg_data->cfg) == -1) {
656         PrintError(vm, VCORE_NONE, "Error in postconfiguration, attempting to free guest\n");
657         vm->run_state=VM_ERROR;
658         v3_free_vm(vm);
659         return NULL;
660     }
661
662
663     per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
664
665     // per core configuration
666     for (i = 0; i < vm->num_cores; i++) {
667         struct guest_info * info = &(vm->cores[i]);
668
669         post_config_core(info, per_core_cfg);
670
671         per_core_cfg = v3_cfg_next_branch(per_core_cfg);
672     }
673
674     V3_Print(vm, VCORE_NONE, "Configuration successfull\n");
675
676     return vm;
677 }
678
679
680
681 int v3_free_config(struct v3_vm_info * vm) {
682    
683     v3_free_htable(vm->cfg_data->file_table, 1, 0);
684
685     v3_xml_free(vm->cfg_data->cfg);
686
687     V3_Free(vm->cfg_data);
688     return 0;
689 }
690
691
692
693
694 static int setup_memory_map(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
695     v3_cfg_tree_t * mem_region = v3_cfg_subtree(v3_cfg_subtree(cfg, "memmap"), "region");
696
697     while (mem_region) {
698         addr_t start_addr = atox(v3_cfg_val(mem_region, "start"));
699         addr_t end_addr = atox(v3_cfg_val(mem_region, "end"));
700         addr_t host_addr = atox(v3_cfg_val(mem_region, "host_addr"));
701
702     
703         if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY, start_addr, end_addr, host_addr) == -1) {
704             PrintError(vm, VCORE_NONE,"Could not map memory region: %p-%p => %p\n", 
705                        (void *)start_addr, (void *)end_addr, (void *)host_addr);
706             return -1;
707         }
708
709         mem_region = v3_cfg_next_branch(mem_region);
710     }
711
712     return 0;
713 }
714
715
716 static int setup_extensions(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
717     v3_cfg_tree_t * extension = v3_cfg_subtree(v3_cfg_subtree(cfg, "extensions"), "extension");
718
719     while (extension) {
720         char * ext_name = v3_cfg_val(extension, "name");
721
722         if (!ext_name) {
723             PrintError(vm, VCORE_NONE, "Extension has no name\n");
724             return -1;
725         }
726
727         V3_Print(vm, VCORE_NONE, "Configuring extension %s\n", ext_name);
728
729         if (v3_add_extension(vm, ext_name, extension) == -1) {
730             PrintError(vm, VCORE_NONE, "Error adding extension %s\n", ext_name);
731             return -1;
732         }
733
734         extension = v3_cfg_next_branch(extension);
735     }
736
737     return 0;
738 }
739
740
741 static int setup_devices(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
742     v3_cfg_tree_t * device = v3_cfg_subtree(v3_cfg_subtree(cfg, "devices"), "device");
743
744     
745     while (device) {
746         char * dev_class = v3_cfg_val(device, "class");
747
748         V3_Print(vm, VCORE_NONE, "configuring device %s\n", dev_class);
749
750         if (v3_create_device(vm, dev_class, device) == -1) {
751             PrintError(vm, VCORE_NONE, "Error creating device %s\n", dev_class);
752             return -1;
753         }
754         
755         device = v3_cfg_next_branch(device);
756     }
757
758     v3_print_dev_mgr(vm);
759
760     return 0;
761 }
762
763
764