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.


turned off VGA hooks
[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
440 }