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.


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