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.


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