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.


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