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.


various changes...
[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 #ifdef CONFIG_SYMBIOTIC
33 #include <palacios/vmm_sym_iface.h>
34
35 #ifdef CONFIG_SYMBIOTIC_SWAP
36 #include <palacios/vmm_sym_swap.h>
37 #endif
38
39 #endif
40
41 #include <devices/generic.h>
42 #include <devices/ide.h>
43 #include <devices/ram_cd.h>
44 #include <devices/net_cd.h>
45 #include <devices/ram_hd.h>
46 #include <devices/net_hd.h>
47
48 #include <devices/telnet_cons.h>
49 #include <devices/pci_passthrough.h>
50
51
52 /*
53 static const char * test_cfg_xml = \
54 "<root>\n \
55 <memory>2048</memory>\n\
56 <devices>\n\
57 <device id=\"PCI\" />\n\
58 <device id=\"IDE\"  />\n\
59 </devices>\n\
60 </root>";
61 */
62
63
64
65 #include <palacios/vmm_host_events.h>
66
67
68
69 #include <palacios/vmm_socket.h>
70
71
72 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr);
73 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr);
74 static int configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr);
75
76
77
78 #ifdef CONFIG_PASSTHROUGH_VIDEO
79 static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
80
81     return length;
82     //  memcpy((void*)guest_addr, src, length);
83     PrintDebug("Write of %d bytes to %p\n", length, (void *)guest_addr);
84     PrintDebug("Write Value = %p\n", (void *)*(addr_t *)src);
85     
86     return length;
87 }
88 #endif
89
90 int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
91    extern v3_cpu_arch_t v3_cpu_types[];
92
93
94    /*
95    {
96        struct v3_xml * cfg = v3_xml_parse((char *)test_cfg_xml);
97        struct v3_xml * devs = NULL;
98        struct v3_xml * tmp = NULL;
99        PrintError("Parsed XML COnfig %s\n", v3_xml_name(cfg));
100        
101        PrintError("memory=%s\n", v3_xml_txt(v3_xml_child(cfg, "memory")));
102        
103        devs = v3_xml_child(cfg, "devices");
104        
105        for (tmp = v3_xml_child(devs, "device"); tmp; tmp = v3_xml_next(tmp)) {
106            PrintError("Device: %s, id=%s\n", 
107                       v3_xml_name(tmp), 
108                       v3_xml_attr(tmp, "id"));
109        }
110        v3_xml_free(cfg);
111        
112        return -1;
113    }
114    */
115
116     // Amount of ram the Guest will have, rounded to a 4K page boundary
117     info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
118
119     info->cpu_id = config_ptr->guest_cpu;
120
121     /*
122      * Initialize the subsystem data strutures
123      */
124 #ifdef CONFIG_TELEMETRY
125     // This should go first, because other subsystems will depend on the guest_info flag
126     if (config_ptr->enable_telemetry) {
127         info->enable_telemetry = 1;
128         v3_init_telemetry(info);
129     } else {
130         info->enable_telemetry = 0;
131     }
132 #endif
133
134     v3_init_hypercall_map(info);
135     v3_init_io_map(info);
136     v3_init_msr_map(info);
137     v3_init_cpuid_map(info);
138     v3_init_host_events(info);
139
140     // Initialize the memory map
141     if (v3_init_shadow_map(info) == -1) {
142         PrintError("Could not initialize shadow map\n");
143         return -1;
144     }
145     
146     if ((v3_cpu_types[info->cpu_id] == V3_SVM_REV3_CPU) && 
147         (config_ptr->enable_nested_paging == 1)) {
148         PrintDebug("Guest Page Mode: NESTED_PAGING\n");
149         info->shdw_pg_mode = NESTED_PAGING;
150     } else {
151         PrintDebug("Guest Page Mode: SHADOW_PAGING\n");
152         v3_init_shadow_page_state(info);
153         info->shdw_pg_mode = SHADOW_PAGING;
154     }
155
156 #ifdef CONFIG_SYMBIOTIC
157     v3_init_sym_iface(info);
158 #endif
159
160     v3_init_time(info);
161     v3_init_interrupt_state(info);
162     v3_init_exception_state(info);
163     v3_init_dev_mgr(info);
164     v3_init_decoder(info);
165     
166 #ifdef CONFIG_SYMBIOTIC_SWAP
167     PrintDebug("initializing symbiotic swap\n");
168     v3_init_sym_swap(info);
169 #endif
170
171
172     if (config_ptr->schedule_freq == 0) {
173         // set the schedule frequency to 100 HZ
174         config_ptr->schedule_freq = 100;
175     }
176
177     PrintDebug("CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), (void *)config_ptr->schedule_freq);
178
179     info->yield_cycle_period = (V3_CPU_KHZ() * 1000) / config_ptr->schedule_freq;
180     
181     // Initial CPU operating mode
182     info->cpu_mode = REAL;
183     info->mem_mode = PHYSICAL_MEM;
184
185     return 0;
186 }
187
188
189 int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
190
191     // Configure the memory map for the guest
192     if (setup_memory_map(info, config_ptr) == -1) {
193         PrintError("Setting up guest memory map failed...\n");
194         return -1;
195     }
196     
197     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
198   
199     if (setup_devices(info, config_ptr) == -1) {
200         PrintError("Failed to setup devices\n");
201         return -1;
202     }
203
204     //    v3_print_io_map(info);
205     v3_print_msr_map(info);
206
207     info->run_state = VM_STOPPED;
208
209     info->vm_regs.rdi = 0;
210     info->vm_regs.rsi = 0;
211     info->vm_regs.rbp = 0;
212     info->vm_regs.rsp = 0;
213     info->vm_regs.rbx = 0;
214     info->vm_regs.rdx = 0;
215     info->vm_regs.rcx = 0;
216     info->vm_regs.rax = 0;
217
218     return 0;
219 }
220
221
222
223
224
225 /* TODO:
226  * The amount of guest memory is stored in info->mem_size
227  * We need to make sure the memory map extends to cover it
228  */
229 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
230
231 #ifdef CONFIG_PASSTHROUGH_VIDEO
232     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
233     
234     // VGA frame buffer
235     if (1) {
236         if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
237             PrintError("Could not map VGA framebuffer\n");
238             return -1;
239         }
240     } else {
241         v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
242     }
243 #endif
244
245 #define VGABIOS_START 0x000c0000
246 #define ROMBIOS_START 0x000f0000
247
248     /* layout vgabios */
249     {
250         extern uint8_t v3_vgabios_start[];
251         extern uint8_t v3_vgabios_end[];
252
253         addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START);
254         memcpy(V3_VAddr((void *)vgabios_dst), v3_vgabios_start, v3_vgabios_end - v3_vgabios_start);     
255     }
256     
257     /* layout rombios */
258     {
259         extern uint8_t v3_rombios_start[];
260         extern uint8_t v3_rombios_end[];
261
262         addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START);
263         memcpy(V3_VAddr((void *)rombios_dst), v3_rombios_start, v3_rombios_end - v3_rombios_start);
264     }
265
266 #ifdef CONFIG_CRAY_XT
267     {
268 #define SEASTAR_START 0xffe00000 
269 #define SEASTAR_END 0xffffffff 
270         // Map the Seastar straight through
271         if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
272             PrintError("Could not map through the seastar\n");
273             return -1;
274         }
275     }
276 #endif
277
278     v3_print_mem_map(info);
279
280     return 0;
281 }
282
283
284
285 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
286
287     v3_create_device(info, "8259A", NULL);
288     v3_create_device(info, "KEYBOARD", NULL);
289     v3_create_device(info, "8254_PIT", NULL); 
290     v3_create_device(info, "BOCHS_DEBUG", NULL);
291     v3_create_device(info, "OS_DEBUG", NULL);
292     v3_create_device(info, "LAPIC", NULL);
293     v3_create_device(info, "IOAPIC", "LAPIC");
294     v3_create_device(info, "VMNET", NULL);
295     
296
297     v3_create_device(info, "CGA_VIDEO", (void *)1);
298     {
299         struct telnet_cons_cfg cons_cfg = {"CGA_VIDEO", 19997};
300         v3_create_device(info, "TELNET_CONSOLE", &cons_cfg);
301     }
302
303     if (config_ptr->enable_pci == 1) {
304         struct ide_cfg ide_config = {"PCI", "PIIX3"};
305         struct pci_passthrough_cfg pci_qemu_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e};
306         struct pci_passthrough_cfg pci_hw_pt_cfg = {"PCI", "E1000", 0x8086, 0x107c};
307         
308         v3_create_device(info, "PCI", NULL);
309         v3_create_device(info, "i440FX", "PCI");
310         v3_create_device(info, "PIIX3", "PCI");
311         
312
313         v3_create_device(info, "LNX_VIRTIO_SYM", "PCI");
314         v3_create_device(info, "LNX_VIRTIO_BLK", "PCI");
315         v3_create_device(info, "LNX_VIRTIO_BALLOON", "PCI");
316         v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK");
317         //      v3_create_device(info, "TMP_BLK", "LNX_VIRTIO_BLK");
318
319         v3_create_device(info, "IDE", &ide_config);
320        
321         v3_create_device(info, "PCI_PASSTHROUGH", &pci_qemu_pt_cfg);
322         v3_create_device(info, "PCI_PASSTHROUGH", &pci_hw_pt_cfg);
323
324
325     } else {
326         v3_create_device(info, "IDE", NULL);
327     }
328
329
330     if (config_ptr->pri_disk_type != NONE) {
331         if (config_ptr->pri_disk_type == CDROM) {
332             if (config_ptr->pri_disk_con == RAM) {
333                 struct ram_cd_cfg cfg = {"IDE", 0, 0, 
334                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
335                                          config_ptr->pri_disk_info.ram.size};
336
337                 PrintDebug("Creating RAM CD\n");
338
339                 v3_create_device(info, "RAM-CD", &cfg);
340             } else if (config_ptr->pri_disk_con == NETWORK) {
341                 struct net_cd_cfg cfg = {"IDE", 0, 0, 
342                                          config_ptr->pri_disk_info.net.ip_str,
343                                          config_ptr->pri_disk_info.net.port, 
344                                          config_ptr->pri_disk_info.net.disk_name};
345                 PrintDebug("Creating NET CD\n");
346
347                 v3_create_device(info, "NET-CD", &cfg);
348             }
349         } else if (config_ptr->pri_disk_type == HARDDRIVE) {
350             if (config_ptr->pri_disk_con == RAM) {
351                 struct ram_hd_cfg cfg = {"IDE", 0, 0, 
352                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
353                                          config_ptr->pri_disk_info.ram.size};
354
355                 PrintDebug("Creating RAM HD\n");
356
357                 v3_create_device(info, "RAM-HD", &cfg);
358             } else if (config_ptr->pri_disk_con == NETWORK) {
359                 struct net_hd_cfg cfg  = {"IDE", 0, 0, 
360                                           config_ptr->pri_disk_info.net.ip_str,
361                                           config_ptr->pri_disk_info.net.port, 
362                                           config_ptr->pri_disk_info.net.disk_name};
363                 PrintDebug("Creating NET HD\n");
364                 v3_create_device(info, "NET-HD", &cfg);
365             }
366
367         } else if (config_ptr->pri_disk_type == VIRTIO) {
368             if (config_ptr->pri_disk_con == RAM) {
369                 struct ram_hd_cfg cfg = {"LNX_VIRTIO_BLK", 0, 0,
370                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
371                                          config_ptr->pri_disk_info.ram.size};
372
373                 PrintDebug("Creating Virtio RAM HD\n");
374
375                 v3_create_device(info, "RAM-HD", &cfg);
376             } 
377
378         }
379     }
380
381
382
383     if (config_ptr->sec_disk_type != NONE) {
384         if (config_ptr->sec_disk_type == CDROM) {
385             if (config_ptr->sec_disk_con == RAM) {
386                 struct ram_cd_cfg cfg = {"IDE", 0, 1, 
387                                          (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
388                                          config_ptr->sec_disk_info.ram.size};
389
390                 PrintDebug("Creating RAM CD\n");
391                 v3_create_device(info, "RAM-CD", &cfg);
392             } else if (config_ptr->sec_disk_con == NETWORK) {
393                 struct net_cd_cfg cfg = {"IDE", 0, 1, 
394                                          config_ptr->sec_disk_info.net.ip_str,
395                                          config_ptr->sec_disk_info.net.port, 
396                                          config_ptr->sec_disk_info.net.disk_name};
397
398                 PrintDebug("Creating NET CD\n");
399                 v3_create_device(info, "NET-CD", &cfg);    
400             }
401         } else if (config_ptr->sec_disk_type == HARDDRIVE) {
402             if (config_ptr->sec_disk_con == RAM) {
403                 struct ram_hd_cfg cfg = {"IDE", 0, 1, 
404                                          (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
405                                          config_ptr->sec_disk_info.ram.size};
406                 PrintDebug("Creating RAM HD\n");
407                 v3_create_device(info, "RAM-HD", &cfg);
408             } else if (config_ptr->sec_disk_con == NETWORK) {
409                 struct net_hd_cfg cfg = {"IDE", 0, 1, 
410                                          config_ptr->sec_disk_info.net.ip_str,
411                                          config_ptr->sec_disk_info.net.port, 
412                                          config_ptr->sec_disk_info.net.disk_name};
413                 PrintDebug("Creating NET HD\n");
414                 v3_create_device(info, "NET-HD", &cfg);
415             }
416         }
417     }
418
419
420
421 #ifdef CONFIG_GENERIC
422         configure_generic(info, config_ptr);
423 #endif
424
425     // This should go last because it requires information about the Harddrives
426     v3_create_device(info, "NVRAM", "IDE");
427     
428     PrintDebugDevMgr(info);
429
430     return 0;
431 }
432
433
434
435 #ifdef CONFIG_GENERIC
436 static int configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
437     PrintDebug("Creating Generic Device\n");
438     v3_create_device(info, "GENERIC", NULL);
439     
440
441     struct vm_device * generic = v3_find_dev(info, "GENERIC");
442
443     if (!generic) {
444         PrintError("Could not find generic device\n");
445         return -1;
446     }
447
448     // port 0x92: A20 enable/disable (bit 2) (This causes an MMU flush)
449
450
451     // Make the DMA controller invisible
452     v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
453     v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
454     v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
455     v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
456     v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
457     v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
458     v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
459     v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
460     v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
461     v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
462     v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
463     v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
464     
465     
466     
467     
468     // Make the Serial ports invisible 
469     
470     v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
471     v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
472     
473
474       
475
476     v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
477     v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
478
479       
480       
481
482     // Make the PCI bus invisible (at least it's configuration)
483     
484     //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
485     //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
486     
487     
488     
489 #if 0
490     if (!use_ramdisk) {
491         // Monitor the IDE controllers (very slow)
492         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
493         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
494     }
495       
496
497     v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
498     v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
499 #endif
500       
501       
502 #if 0
503     
504     // Make the floppy controllers invisible
505     
506     v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
507     v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
508     v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
509     v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
510     v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
511     v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
512     
513 #endif
514
515 #if 1
516
517     // Make the parallel port invisible
518       
519     v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
520
521 #endif
522
523 #ifdef CONFIG_PASTHROUGH_VIDEO
524
525     // Monitor graphics card operations
526     
527     v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
528     v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
529       
530 #endif
531
532
533 #if 1
534     // Make the ISA PNP features invisible
535     
536     v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
537     v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
538     v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
539 #endif
540
541
542 #if 1
543     // Monitor any network card (realtek ne2000) operations 
544     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
545 #endif
546
547     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
548     
549     return 0;
550 }
551 #endif