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