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.


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