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.


627bb8452b5681b77ee391ee23f22a0208f73b5a
[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
32 #include <palacios/svm.h>
33 #include <palacios/vmx.h>
34
35 #ifdef CONFIG_SYMBIOTIC
36 #include <palacios/vmm_sym_iface.h>
37
38 #ifdef CONFIG_SYMBIOTIC_SWAP
39 #include <palacios/vmm_sym_swap.h>
40 #endif
41
42 #endif
43
44
45 #include <palacios/vmm_host_events.h>
46 #include <palacios/vmm_socket.h>
47
48 #include "vmm_config_class.h"
49
50 // This is used to access the configuration file index table
51 struct file_hdr {
52     uint32_t index;
53     uint32_t size;
54     uint64_t offset;
55 };
56
57 struct file_idx_table {
58     uint64_t num_files;
59     struct file_hdr hdrs[0];
60 };
61
62
63
64
65 static int setup_memory_map(struct guest_info * info, struct v3_config * config_ptr);
66 static int setup_devices(struct guest_info * info, struct v3_config * config_ptr);
67
68
69 char * v3_cfg_val(v3_cfg_tree_t * tree, char * tag) {
70     char * attrib = (char *)v3_xml_attr(tree, tag);
71     v3_cfg_tree_t * child_entry = v3_xml_child(tree, tag);
72     char * val = NULL;
73
74     if ((child_entry != NULL) && (attrib != NULL)) {
75         PrintError("Duplicate Configuration parameters present for %s\n", tag);
76         return NULL;
77     }
78
79     val = (attrib == NULL) ? v3_xml_txt(child_entry): attrib;
80
81     return val; 
82 }
83
84 v3_cfg_tree_t * v3_cfg_subtree(v3_cfg_tree_t * tree, char * tag) {
85     return v3_xml_child(tree, tag);
86 }
87
88 v3_cfg_tree_t * v3_cfg_next_branch(v3_cfg_tree_t * tree) {
89     return v3_xml_next(tree);
90 }
91
92
93
94 struct v3_cfg_file * v3_cfg_get_file(struct guest_info * info, char * tag) {
95     struct v3_cfg_file * file = NULL;
96
97     file = (struct v3_cfg_file *)v3_htable_search(info->cfg_data->file_table, (addr_t)tag);
98
99     return file;
100 }
101
102
103 static uint_t file_hash_fn(addr_t key) {
104     char * name = (char *)key;
105     return v3_hash_buffer((uchar_t *)name, strlen(name));
106 }
107
108 static int file_eq_fn(addr_t key1, addr_t key2) {
109     char * name1 = (char *)key1;
110     char * name2 = (char *)key2;
111
112     return (strcmp(name1, name2) == 0);
113 }
114
115 static struct v3_config * parse_config(void * cfg_blob) {
116     struct v3_config * cfg = NULL;
117     int offset = 0;
118     uint_t xml_len = 0; 
119     struct file_idx_table * files = NULL;
120     v3_cfg_tree_t * file_tree = NULL;
121
122     V3_Print("cfg data at %p\n", cfg_blob);
123
124     if (memcmp(cfg_blob, "v3vee\0\0\0", 8) != 0) {
125         PrintError("Invalid Configuration Header\n");
126         return NULL;
127     }
128
129     offset += 8;
130
131     cfg = (struct v3_config *)V3_Malloc(sizeof(struct v3_config));
132     memset(cfg, 0, sizeof(struct v3_config));
133
134     cfg->blob = cfg_blob;
135     INIT_LIST_HEAD(&(cfg->file_list));
136     cfg->file_table = v3_create_htable(0, file_hash_fn, file_eq_fn);
137     
138     xml_len = *(uint32_t *)(cfg_blob + offset);
139     offset += 4;
140
141     cfg->cfg = (v3_cfg_tree_t *)v3_xml_parse((uint8_t *)(cfg_blob + offset));
142     offset += xml_len;
143    
144     offset += 8;
145
146     files = (struct file_idx_table *)(cfg_blob + offset);
147
148     V3_Print("Number of files in cfg: %d\n", (uint32_t)(files->num_files));
149
150     file_tree = v3_cfg_subtree(v3_cfg_subtree(cfg->cfg, "files"), "file");
151
152     while (file_tree) {
153         char * id = v3_cfg_val(file_tree, "id");
154         char * index = v3_cfg_val(file_tree, "index");
155         int idx = atoi(index);
156         struct file_hdr * hdr = &(files->hdrs[idx]);
157         struct v3_cfg_file * file = NULL;
158
159         file = (struct v3_cfg_file *)V3_Malloc(sizeof(struct v3_cfg_file));
160         
161         if (!file) {
162             PrintError("Could not allocate file structure\n");
163             return NULL;
164         }
165
166
167         V3_Print("File index=%d id=%s\n", idx, id);
168
169         strncpy(file->tag, id, 256);
170         file->size = hdr->size;
171         file->data = cfg_blob + hdr->offset;
172
173         V3_Print("Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
174         V3_Print("file data at %p\n", file->data);
175         list_add( &(file->file_node), &(cfg->file_list));
176
177         V3_Print("Keying file to name\n");
178         v3_htable_insert(cfg->file_table, (addr_t)(file->tag), (addr_t)(file));
179
180         V3_Print("Iterating to next file\n");
181
182         file_tree = v3_cfg_next_branch(file_tree);
183     }
184
185     V3_Print("Configuration parsed successfully\n");
186
187     return cfg;
188 }
189
190
191 static int pre_config_guest(struct guest_info * info, struct v3_config * config_ptr) {
192     extern v3_cpu_arch_t v3_cpu_types[];
193     char * memory_str = v3_cfg_val(config_ptr->cfg, "memory");
194     char * paging = v3_cfg_val(config_ptr->cfg, "paging");
195     char * schedule_hz_str = v3_cfg_val(config_ptr->cfg, "schedule_hz");
196     char * vm_class = v3_cfg_val(config_ptr->cfg, "class");
197     uint32_t sched_hz = 100;    // set the schedule frequency to 100 HZ
198     
199     if (!memory_str) {
200         PrintError("Memory is a required configuration parameter\n");
201         return -1;
202     }
203     
204     PrintDebug("Memory=%s\n", memory_str);
205
206     // Amount of ram the Guest will have, always in MB
207     info->mem_size = atoi(memory_str) * 1024 * 1024;
208     
209     if (strcasecmp(vm_class, "PC") == 0) {
210         info->vm_class = V3_PC_VM;
211     } else {
212         PrintError("Invalid VM class\n");
213         return -1;
214     }
215
216
217     /*
218      * Initialize the subsystem data strutures
219      */
220 #ifdef CONFIG_TELEMETRY
221     {
222         char * telemetry = v3_cfg_val(config_ptr->cfg, "telemetry");
223
224         // This should go first, because other subsystems will depend on the guest_info flag    
225         if ((telemetry) && (strcasecmp(telemetry, "enable") == 0)) {
226             info->enable_telemetry = 1;
227             v3_init_telemetry(info);
228         } else {
229             info->enable_telemetry = 0;
230         }
231     }
232 #endif
233
234     v3_init_hypercall_map(info);
235     v3_init_io_map(info);
236     v3_init_msr_map(info);
237     v3_init_cpuid_map(info);
238     v3_init_host_events(info);
239
240     // Initialize the memory map
241     if (v3_init_shadow_map(info) == -1) {
242         PrintError("Could not initialize shadow map\n");
243         return -1;
244     }
245     
246     if ((v3_cpu_types[info->cpu_id] == V3_SVM_REV3_CPU) && 
247         (paging) && (strcasecmp(paging, "nested") == 0)) {
248         PrintDebug("Guest Page Mode: NESTED_PAGING\n");
249         info->shdw_pg_mode = NESTED_PAGING;
250     } else {
251         PrintDebug("Guest Page Mode: SHADOW_PAGING\n");
252         v3_init_shadow_page_state(info);
253         info->shdw_pg_mode = SHADOW_PAGING;
254     }
255
256 #ifdef CONFIG_SYMBIOTIC
257     v3_init_sym_iface(info);
258 #endif
259
260     v3_init_time(info);
261     v3_init_interrupt_state(info);
262     v3_init_exception_state(info);
263     v3_init_dev_mgr(info);
264     v3_init_decoder(info);
265     
266 #ifdef CONFIG_SYMBIOTIC_SWAP
267     PrintDebug("initializing symbiotic swap\n");
268     v3_init_sym_swap(info);
269 #endif
270
271     if (schedule_hz_str) {
272         sched_hz = atoi(schedule_hz_str);
273     }
274
275     PrintDebug("CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), 
276                (void *)(addr_t)sched_hz);
277
278     info->yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;
279     
280
281
282     return 0;
283 }
284
285
286 static int post_config_guest(struct guest_info * info, struct v3_config * config_ptr) {
287
288     // Configure the memory map for the guest
289     if (setup_memory_map(info, config_ptr) == -1) {
290         PrintError("Setting up guest memory map failed...\n");
291         return -1;
292     }
293     
294     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
295   
296     if (setup_devices(info, config_ptr) == -1) {
297         PrintError("Failed to setup devices\n");
298         return -1;
299     }
300
301     //    v3_print_io_map(info);
302     v3_print_msr_map(info);
303
304     info->run_state = VM_STOPPED;
305
306     if (info->vm_class == V3_PC_VM) {
307         if (post_config_pc(info, config_ptr) == -1) {
308             PrintError("PC Post configuration failure\n");
309             return -1;
310         }
311     } else {
312         PrintError("Invalid VM Class\n");
313         return -1;
314     }
315
316
317     return 0;
318 }
319
320
321
322 int v3_config_guest(struct guest_info * info, void * cfg_blob) {
323     v3_cpu_arch_t cpu_type = v3_get_cpu_type(v3_get_cpu_id());
324
325     if (cpu_type == V3_INVALID_CPU) {
326         PrintError("Configuring guest on invalid CPU\n");
327         return -1;
328     }
329
330     info->cfg_data = parse_config(cfg_blob);
331
332     if (!info->cfg_data) {
333         PrintError("Could not parse configuration\n");
334         return -1;
335     }
336
337     V3_Print("Preconfiguration\n");
338
339     if (pre_config_guest(info, info->cfg_data) == -1) {
340         PrintError("Error in preconfiguration\n");
341         return -1;
342     }
343
344     V3_Print("Arch dependent configuration\n");
345
346     // init SVM/VMX
347 #ifdef CONFIG_SVM
348     if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
349         if (v3_init_svm_vmcb(info, info->vm_class) == -1) {
350             PrintError("Error in SVM initialization\n");
351             return -1;
352         }
353     } 
354 #endif
355 #ifdef CONFIG_VMX
356     else if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU)) {
357         if (v3_init_vmx_vmcs(info, info->vm_class) == -1) {
358             PrintError("Error in VMX initialization\n");
359             return -1;
360         }
361     }
362 #endif
363     else {
364         PrintError("Invalid CPU Type\n");
365         return -1;
366     }
367
368     V3_Print("Post Configuration\n");
369
370     if (post_config_guest(info, info->cfg_data) == -1) {
371         PrintError("Error in postconfiguration\n");
372         return -1;
373     }
374
375     V3_Print("Configuration successfull\n");
376
377     return 0;
378 }
379
380
381
382
383
384 static int setup_memory_map(struct guest_info * info, struct v3_config * config_ptr) {
385     v3_cfg_tree_t * mem_region = v3_cfg_subtree(v3_cfg_subtree(config_ptr->cfg, "memmap"), "region");
386
387     while (mem_region) {
388         addr_t start_addr = atox(v3_cfg_val(mem_region, "start"));
389         addr_t end_addr = atox(v3_cfg_val(mem_region, "end"));
390         addr_t host_addr = atox(v3_cfg_val(mem_region, "host_addr"));
391
392     
393         if (v3_add_shadow_mem(info, start_addr, end_addr, host_addr) == -1) {
394             PrintError("Could not map memory region: %p-%p => %p\n", 
395                        (void *)start_addr, (void *)end_addr, (void *)host_addr);
396             return -1;
397         }
398
399         mem_region = v3_cfg_next_branch(mem_region);
400     }
401
402     return 0;
403 }
404
405
406
407
408
409
410
411
412
413 static int setup_devices(struct guest_info * info, struct v3_config * config_ptr) {
414     v3_cfg_tree_t * device = v3_cfg_subtree(v3_cfg_subtree(config_ptr->cfg, "devices"), "device");
415
416     
417     while (device) {
418         char * id = v3_cfg_val(device, "id");
419
420         V3_Print("configuring device %s\n", id);
421
422         if (v3_create_device(info, id, device) == -1) {
423             PrintError("Error creating device %s\n", id);
424             return -1;
425         }
426         
427         device = v3_cfg_next_branch(device);
428     }
429
430
431    v3_print_dev_mgr(info);
432
433     return 0;
434 }
435
436