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.


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