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