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 seastar memory mapping
[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
29
30 #include <devices/serial.h>
31 #include <devices/keyboard.h>
32 #include <devices/8259a.h>
33 #include <devices/8254.h>
34 #include <devices/nvram.h>
35 #include <devices/generic.h>
36 #include <devices/ramdisk.h>
37 #include <devices/cdrom.h>
38 #include <devices/bochs_debug.h>
39 #include <devices/os_debug.h>
40 #include <devices/apic.h>
41 #include <devices/io_apic.h>
42 #include <devices/para_net.h>
43
44
45
46 #include <palacios/vmm_host_events.h>
47
48 #define USE_GENERIC 1
49
50
51
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 struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr);
57
58
59
60
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
71
72
73 int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
74     extern v3_cpu_arch_t v3_cpu_type;
75
76     // Initialize the subsystem data strutures
77     v3_init_time(info);
78     v3_init_io_map(info);
79     v3_init_msr_map(info);
80     v3_init_interrupt_state(info);
81     v3_init_dev_mgr(info);
82     v3_init_host_events(info);
83     
84     v3_init_decoder(info);
85     
86     v3_init_shadow_map(info);
87     
88     v3_init_hypercall_map(info);
89     
90   
91     if (v3_cpu_type == V3_SVM_REV3_CPU) {
92         info->shdw_pg_mode = NESTED_PAGING;
93     } else {
94         v3_init_shadow_page_state(info);
95         info->shdw_pg_mode = SHADOW_PAGING;
96     }
97     
98     // Initial CPU operating mode
99     info->cpu_mode = REAL;
100     info->mem_mode = PHYSICAL_MEM;
101     
102     // Amount of ram the Guest will have, rounded to a 4K page boundary
103     info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
104     
105     // Configure the memory map for the guest
106     if (setup_memory_map(info, config_ptr) == -1) {
107         PrintError("Setting up guest memory map failed...\n");
108         return -1;
109     }
110     
111     // Configure the devices for the guest
112     setup_devices(info, config_ptr);
113     
114
115
116     if (config_ptr->enable_profiling) {
117         info->enable_profiler = 1;
118         v3_init_profiler(info);
119     } else {
120         info->enable_profiler = 0;
121     }
122
123     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
124     
125     // Setup initial cpu register state
126     info->rip = 0xfff0;
127     info->vm_regs.rsp = 0x0;
128   
129     
130     return 0;
131 }
132
133
134 /* TODO:
135  * The amount of guest memory is stored in info->mem_size
136  * We need to make sure the memory map extends to cover it
137  */
138 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
139     addr_t mem_pages = info->mem_size >> 12;
140     
141     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
142     
143     // Fill up to the 640K hole
144     if (mem_pages >= 160) {
145         if (v3_add_shadow_mem(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160)) == -1) {
146             PrintError("Could not map full conventional memory\n");
147             return -1;
148         }
149     } else {
150         // Less than 640k of memory
151         if (v3_add_shadow_mem(info, 0x0, (mem_pages * PAGE_SIZE), (addr_t)V3_AllocPages(mem_pages)) == -1) {
152             PrintError("Could not map subset of conventional memory\n");
153             return -1;
154         };
155     }
156
157
158 #define VGABIOS_START 0x000c0000
159 #define ROMBIOS_START 0x000f0000
160     
161     // VGA frame buffer
162     if (1) {
163         if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
164             PrintError("Could not map VGA framebuffer\n");
165             return -1;
166         }
167     } else {
168         v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
169     }  
170     
171     
172     /* layout vgabios */
173     {
174         uint_t num_pages = (config_ptr->vgabios_size + PAGE_SIZE - 1) / PAGE_SIZE;
175         void * guest_mem =  V3_AllocPages(num_pages);
176         addr_t vgabios_end = VGABIOS_START + (num_pages * PAGE_SIZE);
177         
178         PrintDebug("Layout Region %d bytes\n", config_ptr->vgabios_size);
179         memcpy(V3_VAddr(guest_mem), config_ptr->vgabios, config_ptr->vgabios_size);
180         
181         if (v3_add_shadow_mem(info, VGABIOS_START, vgabios_end, (addr_t)guest_mem) == -1) {
182             PrintError("Could not map VGABIOS\n");
183             return -1;
184         }
185         
186         PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
187                    (void *)VGABIOS_START, 
188                    (void *)vgabios_end, 
189                    (void *)guest_mem);
190         
191
192         // Fill in the space between the VGABIOS and the ROMBIOS
193         // We'll just back this to shadow memory for now....
194         if (v3_add_shadow_mem(info, vgabios_end, ROMBIOS_START, 
195                               (addr_t)V3_AllocPages((ROMBIOS_START - vgabios_end) / PAGE_SIZE)) == -1) {
196             PrintError("Could not map VGABIOS->ROMBIOS gap\n");
197             return -1;
198         }
199     }
200     
201     /* layout rombios */
202     {
203         uint_t num_pages = (config_ptr->rombios_size + PAGE_SIZE - 1) / PAGE_SIZE;
204         void * guest_mem =  V3_AllocPages(num_pages);
205         addr_t rombios_end = ROMBIOS_START + (num_pages * PAGE_SIZE);
206         
207         PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size);
208         memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size);
209         
210         if (v3_add_shadow_mem(info, ROMBIOS_START, rombios_end, (addr_t)guest_mem) == -1) {
211             PrintError("Could not map ROMBIOS\n");
212             return -1;
213         }
214         
215         PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
216                    (void *)ROMBIOS_START, 
217                    (void *)rombios_end, 
218                    (void *)guest_mem);
219         
220         if (rombios_end != 0x100000) {
221             PrintError("ROMBIOS must reach the 1MB barrier....\n");
222             return -1;
223         }
224     }
225
226 #ifdef CRAY_XT
227     {
228 #define SEASTAR_START 0xffe00000 
229 #define SEASTAR_END 0xffffffff 
230         
231         // Fill in generic memory below the seastar
232         addr_t top_of_mem = (SEASTAR_START < info->mem_size) ? SEASTAR_START : info->mem_size;
233         int num_low_pages = (top_of_mem - 0x100000) / PAGE_SIZE;
234         
235         if (v3_add_shadow_mem(info, 0x100000, top_of_mem, (addr_t)V3_AllocPages(num_low_pages)) == -1) {
236             PrintError("Could not extended memory below 4G\n");
237             return -1;
238         }
239         
240         // Map the Seastar straight through
241         if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
242             PrintError("Could not map through the seastar\n");
243             return -1;
244         }
245         
246         
247         // Add memory above the seastar
248         if (info->mem_size > SEASTAR_END) {
249             int num_high_pages = mem_pages - (SEASTAR_END / PAGE_SIZE);    
250
251             if (v3_add_shadow_mem(info, SEASTAR_END, info->mem_size, (addr_t)V3_AllocPages(num_high_pages)) == -1) {
252                 PrintError("Could not map extended memory above 4G\n");
253                 return -1;
254             }
255         }
256     }
257 #else 
258     // Fill in the extended memory map....
259     {
260         int num_ext_pages = mem_pages - (0x100000 / PAGE_SIZE);
261         
262         if (num_ext_pages > 0) {
263             if (v3_add_shadow_mem(info, 0x100000, info->mem_size, (addr_t)V3_AllocPages(num_ext_pages)) == -1) {
264                 PrintError("Could not allocate extended shadow memory\n");
265                 return -1;
266             }
267         }
268     }
269 #endif    
270
271     print_shadow_map(info);
272
273     return 0;
274 }
275
276
277
278 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
279     struct vm_device * ramdisk = NULL;
280     struct vm_device * cdrom = NULL;
281     struct vm_device * nvram = v3_create_nvram();
282     //struct vm_device * timer = v3_create_timer();
283     struct vm_device * pic = v3_create_pic();
284     struct vm_device * keyboard = v3_create_keyboard();
285     struct vm_device * pit = v3_create_pit(); 
286     struct vm_device * bochs_debug = v3_create_bochs_debug();
287     struct vm_device * os_debug = v3_create_os_debug();
288     struct vm_device * apic = v3_create_apic();
289     struct vm_device * ioapic = v3_create_io_apic(apic);
290     struct vm_device * para_net = v3_create_para_net();
291
292     //struct vm_device * serial = v3_create_serial();
293     struct vm_device * generic = NULL;
294
295     int use_ramdisk = config_ptr->use_ramdisk;
296     int use_generic = USE_GENERIC;
297
298
299     if (use_ramdisk) {
300         PrintDebug("Creating Ramdisk\n");
301         ramdisk = v3_create_ramdisk();
302         cdrom = v3_create_cdrom(ramdisk, config_ptr->ramdisk, config_ptr->ramdisk_size);
303     }
304     
305     
306     if (use_generic) {
307         generic = configure_generic(info, config_ptr);
308     }
309
310
311     v3_attach_device(info, nvram);
312     //v3_attach_device(info, timer);
313     v3_attach_device(info, pic);
314     v3_attach_device(info, pit);
315     v3_attach_device(info, keyboard);
316     // v3_attach_device(info, serial);
317     v3_attach_device(info, bochs_debug);
318     v3_attach_device(info, os_debug);
319
320     v3_attach_device(info, apic);
321     v3_attach_device(info, ioapic);
322
323     v3_attach_device(info, para_net);
324
325     if (use_ramdisk) {
326         v3_attach_device(info, ramdisk);
327         v3_attach_device(info, cdrom);
328     }
329
330     if (use_generic) {
331         // Important that this be attached last!
332         v3_attach_device(info, generic);
333     }
334     
335     PrintDebugDevMgr(info);
336
337
338     // give keyboard interrupts to vm
339     // no longer needed since we have a keyboard device
340     //hook_irq(&vm_info, 1);
341     
342 #if 0
343     // give floppy controller to vm
344     v3_hook_passthrough_irq(info, 6);
345 #endif
346     
347     
348     if (!use_ramdisk) {
349         PrintDebug("Hooking IDE IRQs\n");
350         
351         //primary ide
352         v3_hook_passthrough_irq(info, 14);
353         
354         // secondary ide
355         v3_hook_passthrough_irq(info, 15);    
356     }  
357     
358
359     return 0;
360 }
361
362
363
364 static struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
365     PrintDebug("Creating Generic Device\n");
366     struct vm_device * generic = v3_create_generic();
367     
368     // Make the DMA controller invisible
369     v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
370     v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
371     v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
372     v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
373     v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
374     v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
375     v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
376     v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
377     v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
378     v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
379     v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
380     v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
381     
382     
383     
384     
385     // Make the Serial ports invisible 
386     
387     v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
388     v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
389     
390
391       
392
393     v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
394     v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
395
396       
397       
398
399     // Make the PCI bus invisible (at least it's configuration)
400     
401     v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
402     v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
403     
404     
405     
406 #if 0
407     if (!use_ramdisk) {
408         // Monitor the IDE controllers (very slow)
409         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
410         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
411     }
412       
413
414     v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
415     v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
416 #endif
417       
418       
419 #if 0
420     
421     // Make the floppy controllers invisible
422     
423     v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
424     v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
425     v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
426     v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
427     v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
428     v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
429     
430 #endif
431
432 #if 1
433
434     // Make the parallel port invisible
435       
436     v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
437
438 #endif
439
440 #if 1
441
442     // Monitor graphics card operations
443     
444     v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
445     v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
446       
447 #endif
448
449
450 #if 1
451     // Make the ISA PNP features invisible
452     
453     v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
454     v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
455     v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
456 #endif
457
458
459 #if 1
460     // Monitor any network card (realtek ne2000) operations 
461     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
462 #endif
463
464
465 #if 1
466     // Make any Bus master ide controller invisible
467     
468     v3_generic_add_port_range(generic, 0xc000, 0xc00f, GENERIC_PRINT_AND_IGNORE);
469 #endif
470     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
471     
472
473     return generic;
474 }