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.


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