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.


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