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