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.


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