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.


huge update for merge
[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/ide.h>
37 #include <devices/ram_cd.h>
38 #include <devices/ram_hd.h>
39 #include <devices/bochs_debug.h>
40 #include <devices/os_debug.h>
41 #include <devices/apic.h>
42 #include <devices/io_apic.h>
43 #include <devices/para_net.h>
44 #include <devices/pci.h>
45
46
47
48 #include <palacios/vmm_host_events.h>
49
50 #define USE_GENERIC 1
51
52
53
54
55
56 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr);
57 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr);
58 static struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr);
59
60
61
62
63 static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
64
65     return length;
66     //  memcpy((void*)guest_addr, src, length);
67     PrintDebug("Write of %d bytes to %p\n", length, (void *)guest_addr);
68     PrintDebug("Write Value = %p\n", (void *)*(addr_t *)src);
69     
70     return length;
71 }
72
73
74
75 int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
76     extern v3_cpu_arch_t v3_cpu_type;
77
78     // Initialize the subsystem data strutures
79     v3_init_time(info);
80     v3_init_io_map(info);
81     v3_init_msr_map(info);
82     v3_init_interrupt_state(info);
83     v3_init_dev_mgr(info);
84     v3_init_host_events(info);
85     
86     v3_init_decoder(info);
87     
88     v3_init_shadow_map(info);
89     
90     v3_init_hypercall_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     // Initial CPU operating mode
103     info->cpu_mode = REAL;
104     info->mem_mode = PHYSICAL_MEM;
105     
106     // Amount of ram the Guest will have, rounded to a 4K page boundary
107     info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
108     
109     // Configure the memory map for the guest
110     if (setup_memory_map(info, config_ptr) == -1) {
111         PrintError("Setting up guest memory map failed...\n");
112         return -1;
113     }
114     
115     // Configure the devices for the guest
116     setup_devices(info, config_ptr);
117     
118
119
120     if (config_ptr->enable_profiling) {
121         info->enable_profiler = 1;
122         v3_init_profiler(info);
123     } else {
124         info->enable_profiler = 0;
125     }
126
127     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
128     
129     // Setup initial cpu register state
130     info->rip = 0xfff0;
131     info->vm_regs.rsp = 0x0;
132   
133     
134     return 0;
135 }
136
137
138 /* TODO:
139  * The amount of guest memory is stored in info->mem_size
140  * We need to make sure the memory map extends to cover it
141  */
142 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
143     addr_t mem_pages = info->mem_size >> 12;
144     
145     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
146     
147     // Fill up to the 640K hole
148     if (mem_pages >= 160) {
149         if (v3_add_shadow_mem(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160)) == -1) {
150             PrintError("Could not map full conventional memory\n");
151             return -1;
152         }
153     } else {
154         // Less than 640k of memory
155         if (v3_add_shadow_mem(info, 0x0, (mem_pages * PAGE_SIZE), (addr_t)V3_AllocPages(mem_pages)) == -1) {
156             PrintError("Could not map subset of conventional memory\n");
157             return -1;
158         };
159     }
160
161
162 #define VGABIOS_START 0x000c0000
163 #define ROMBIOS_START 0x000f0000
164     
165     // VGA frame buffer
166     if (1) {
167         if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
168             PrintError("Could not map VGA framebuffer\n");
169             return -1;
170         }
171     } else {
172         v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
173     }  
174     
175     
176     /* layout vgabios */
177     {
178         uint_t num_pages = (config_ptr->vgabios_size + PAGE_SIZE - 1) / PAGE_SIZE;
179         void * guest_mem =  V3_AllocPages(num_pages);
180         addr_t vgabios_end = VGABIOS_START + (num_pages * PAGE_SIZE);
181         
182         PrintDebug("Layout Region %d bytes\n", config_ptr->vgabios_size);
183         memcpy(V3_VAddr(guest_mem), config_ptr->vgabios, config_ptr->vgabios_size);
184         
185         if (v3_add_shadow_mem(info, VGABIOS_START, vgabios_end, (addr_t)guest_mem) == -1) {
186             PrintError("Could not map VGABIOS\n");
187             return -1;
188         }
189         
190         PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
191                    (void *)VGABIOS_START, 
192                    (void *)vgabios_end, 
193                    (void *)guest_mem);
194         
195
196         // Fill in the space between the VGABIOS and the ROMBIOS
197         // We'll just back this to shadow memory for now....
198         if (v3_add_shadow_mem(info, vgabios_end, ROMBIOS_START, 
199                               (addr_t)V3_AllocPages((ROMBIOS_START - vgabios_end) / PAGE_SIZE)) == -1) {
200             PrintError("Could not map VGABIOS->ROMBIOS gap\n");
201             return -1;
202         }
203     }
204     
205     /* layout rombios */
206     {
207         uint_t num_pages = (config_ptr->rombios_size + PAGE_SIZE - 1) / PAGE_SIZE;
208         void * guest_mem =  V3_AllocPages(num_pages);
209         addr_t rombios_end = ROMBIOS_START + (num_pages * PAGE_SIZE);
210         
211         PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size);
212         memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size);
213         
214         if (v3_add_shadow_mem(info, ROMBIOS_START, rombios_end, (addr_t)guest_mem) == -1) {
215             PrintError("Could not map ROMBIOS\n");
216             return -1;
217         }
218         
219         PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
220                    (void *)ROMBIOS_START, 
221                    (void *)rombios_end, 
222                    (void *)guest_mem);
223         
224         if (rombios_end != 0x100000) {
225             PrintError("ROMBIOS must reach the 1MB barrier....\n");
226             return -1;
227         }
228     }
229
230 #ifdef CRAY_XT
231     {
232 #define SEASTAR_START 0xffe00000 
233 #define SEASTAR_END 0xffffffff 
234         
235         // Fill in generic memory below the seastar
236         addr_t top_of_mem = (SEASTAR_START < info->mem_size) ? SEASTAR_START : info->mem_size;
237         int num_low_pages = (top_of_mem - 0x100000) / PAGE_SIZE;
238         
239         if (v3_add_shadow_mem(info, 0x100000, top_of_mem, (addr_t)V3_AllocPages(num_low_pages)) == -1) {
240             PrintError("Could not extended memory below 4G\n");
241             return -1;
242         }
243         
244         // Map the Seastar straight through
245         if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
246             PrintError("Could not map through the seastar\n");
247             return -1;
248         }
249         
250         
251         // Add memory above the seastar
252         if (info->mem_size > SEASTAR_END) {
253             int num_high_pages = mem_pages - (SEASTAR_END / PAGE_SIZE);    
254
255             if (v3_add_shadow_mem(info, SEASTAR_END, info->mem_size, (addr_t)V3_AllocPages(num_high_pages)) == -1) {
256                 PrintError("Could not map extended memory above 4G\n");
257                 return -1;
258             }
259         }
260     }
261 #else 
262     // Fill in the extended memory map....
263     {
264         int num_ext_pages = mem_pages - (0x100000 / PAGE_SIZE);
265         
266         if (num_ext_pages > 0) {
267             if (v3_add_shadow_mem(info, 0x100000, info->mem_size, (addr_t)V3_AllocPages(num_ext_pages)) == -1) {
268                 PrintError("Could not allocate extended shadow memory\n");
269                 return -1;
270             }
271         }
272     }
273 #endif    
274
275     print_shadow_map(info);
276
277     return 0;
278 }
279
280
281
282 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
283     struct vm_device * ide = NULL;
284     //struct vm_device * ram_cd = NULL;
285     struct vm_device * ram_hd = NULL;
286     struct vm_device * pci = v3_create_pci();
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     ide = v3_create_ide(pci);
305
306     if (use_ramdisk) {
307         PrintDebug("Creating Ramdisk\n");
308         //ram_cd = v3_create_ram_cd(ide, 0, 0, 
309         //                (addr_t)(config_ptr->ramdisk), 
310         //                config_ptr->ramdisk_size);
311         ram_hd = v3_create_ram_hd(ide, 0, 0, 
312                                   (addr_t)(config_ptr->ramdisk), 
313                                   config_ptr->ramdisk_size);
314     }
315     
316     
317     if (use_generic) {
318         generic = configure_generic(info, config_ptr);
319     }
320
321
322     v3_attach_device(info, pci);
323
324     v3_attach_device(info, nvram);
325     //v3_attach_device(info, timer);
326     v3_attach_device(info, pic);
327     v3_attach_device(info, pit);
328     v3_attach_device(info, keyboard);
329     // v3_attach_device(info, serial);
330     v3_attach_device(info, bochs_debug);
331     v3_attach_device(info, os_debug);
332
333     v3_attach_device(info, apic);
334     v3_attach_device(info, ioapic);
335
336     v3_attach_device(info, para_net);
337
338     v3_attach_device(info, ide);
339
340     if (use_ramdisk) {
341         //              v3_attach_device(info, ram_cd);
342         v3_attach_device(info, ram_hd);
343     }
344
345     if (use_generic) {
346         // Important that this be attached last!
347         v3_attach_device(info, generic);
348     }
349     
350     PrintDebugDevMgr(info);
351
352
353     // give keyboard interrupts to vm
354     // no longer needed since we have a keyboard device
355     //hook_irq(&vm_info, 1);
356     
357 #if 0
358     // give floppy controller to vm
359     v3_hook_passthrough_irq(info, 6);
360 #endif
361     
362     
363     if (!use_ramdisk) {
364         PrintDebug("Hooking IDE IRQs\n");
365         
366         //primary ide
367         v3_hook_passthrough_irq(info, 14);
368         
369         // secondary ide
370         v3_hook_passthrough_irq(info, 15);    
371     }  
372     
373
374     return 0;
375 }
376
377
378
379 static struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
380     PrintDebug("Creating Generic Device\n");
381     struct vm_device * generic = v3_create_generic();
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 #if 1
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
480 #if 1
481     // Make any Bus master ide controller invisible
482     
483     v3_generic_add_port_range(generic, 0xc000, 0xc00f, GENERIC_PRINT_AND_IGNORE);
484 #endif
485     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
486     
487
488     return generic;
489 }