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.


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