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 yield functionality
[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_BLK", "PCI");
230         v3_create_device(info, "LNX_VIRTIO_BALLOON", "PCI");
231         v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK");
232
233         v3_create_device(info, "IDE", &ide_config);
234     } else {
235         v3_create_device(info, "IDE", NULL);
236     }
237
238
239     if (config_ptr->pri_disk_type != NONE) {
240         if (config_ptr->pri_disk_type == CDROM) {
241             if (config_ptr->pri_disk_con == RAM) {
242                 struct ram_cd_cfg cfg = {"IDE", 0, 0, 
243                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
244                                          config_ptr->pri_disk_info.ram.size};
245
246                 PrintDebug("Creating RAM CD\n");
247
248                 v3_create_device(info, "RAM-CD", &cfg);
249             } else if (config_ptr->pri_disk_con == NETWORK) {
250                 struct net_cd_cfg cfg = {"IDE", 0, 0, 
251                                          config_ptr->pri_disk_info.net.ip_str,
252                                          config_ptr->pri_disk_info.net.port, 
253                                          config_ptr->pri_disk_info.net.disk_name};
254                 PrintDebug("Creating NET CD\n");
255
256                 v3_create_device(info, "NET-CD", &cfg);
257             }
258         } else if (config_ptr->pri_disk_type == HARDDRIVE) {
259             if (config_ptr->pri_disk_con == RAM) {
260                 struct ram_hd_cfg cfg = {"IDE", 0, 0, 
261                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
262                                          config_ptr->pri_disk_info.ram.size};
263
264                 PrintDebug("Creating RAM HD\n");
265
266                 v3_create_device(info, "RAM-HD", &cfg);
267             } else if (config_ptr->pri_disk_con == NETWORK) {
268                 struct net_hd_cfg cfg  = {"IDE", 0, 0, 
269                                           config_ptr->pri_disk_info.net.ip_str,
270                                           config_ptr->pri_disk_info.net.port, 
271                                           config_ptr->pri_disk_info.net.disk_name};
272                 PrintDebug("Creating NET HD\n");
273                 v3_create_device(info, "NET-HD", &cfg);
274             }
275         }
276     }
277
278
279
280     if (config_ptr->sec_disk_type != NONE) {
281         if (config_ptr->sec_disk_type == CDROM) {
282             if (config_ptr->sec_disk_con == RAM) {
283                 struct ram_cd_cfg cfg = {"IDE", 0, 1, 
284                                          (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
285                                          config_ptr->sec_disk_info.ram.size};
286
287                 PrintDebug("Creating RAM CD\n");
288                 v3_create_device(info, "RAM-CD", &cfg);
289             } else if (config_ptr->sec_disk_con == NETWORK) {
290                 struct net_cd_cfg cfg = {"IDE", 0, 1, 
291                                          config_ptr->sec_disk_info.net.ip_str,
292                                          config_ptr->sec_disk_info.net.port, 
293                                          config_ptr->sec_disk_info.net.disk_name};
294
295                 PrintDebug("Creating NET CD\n");
296                 v3_create_device(info, "NET-CD", &cfg);    
297             }
298         } else if (config_ptr->sec_disk_type == HARDDRIVE) {
299             if (config_ptr->sec_disk_con == RAM) {
300                 struct ram_hd_cfg cfg = {"IDE", 0, 1, 
301                                          (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
302                                          config_ptr->sec_disk_info.ram.size};
303                 PrintDebug("Creating RAM HD\n");
304                 v3_create_device(info, "RAM-HD", &cfg);
305             } else if (config_ptr->sec_disk_con == NETWORK) {
306                 struct net_hd_cfg cfg = {"IDE", 0, 1, 
307                                          config_ptr->sec_disk_info.net.ip_str,
308                                          config_ptr->sec_disk_info.net.port, 
309                                          config_ptr->sec_disk_info.net.disk_name};
310                 PrintDebug("Creating NET HD\n");
311                 v3_create_device(info, "NET-HD", &cfg);
312             }
313         }
314     }
315
316
317
318     if (use_generic) {
319         configure_generic(info, config_ptr);
320     }
321
322     // This should go last because it requires information about the Harddrives
323     v3_create_device(info, "NVRAM", "IDE");
324     
325     PrintDebugDevMgr(info);
326
327     return 0;
328 }
329
330
331
332
333 static int configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
334     PrintDebug("Creating Generic Device\n");
335     v3_create_device(info, "GENERIC", NULL);
336     
337
338     struct vm_device * generic = v3_find_dev(info, "GENERIC");
339
340     if (!generic) {
341         PrintError("Could not find generic device\n");
342         return -1;
343     }
344
345     // port 0x92: A20 enable/disable (bit 2) (This causes an MMU flush)
346
347
348     // Make the DMA controller invisible
349     v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
350     v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
351     v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
352     v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
353     v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
354     v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
355     v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
356     v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
357     v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
358     v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
359     v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
360     v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
361     
362     
363     
364     
365     // Make the Serial ports invisible 
366     
367     v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
368     v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
369     
370
371       
372
373     v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
374     v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
375
376       
377       
378
379     // Make the PCI bus invisible (at least it's configuration)
380     
381     //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
382     //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
383     
384     
385     
386 #if 0
387     if (!use_ramdisk) {
388         // Monitor the IDE controllers (very slow)
389         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
390         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
391     }
392       
393
394     v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
395     v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
396 #endif
397       
398       
399 #if 0
400     
401     // Make the floppy controllers invisible
402     
403     v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
404     v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
405     v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
406     v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
407     v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
408     v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
409     
410 #endif
411
412 #if 1
413
414     // Make the parallel port invisible
415       
416     v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
417
418 #endif
419
420 #if 1
421
422     // Monitor graphics card operations
423     
424     v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
425     v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
426       
427 #endif
428
429
430 #if 1
431     // Make the ISA PNP features invisible
432     
433     v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
434     v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
435     v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
436 #endif
437
438
439 #if 1
440     // Monitor any network card (realtek ne2000) operations 
441     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
442 #endif
443
444     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
445     
446     return 0;
447 }