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.


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