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.


IO APIC implementation
[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
28
29 #include <devices/serial.h>
30 #include <devices/keyboard.h>
31 #include <devices/8259a.h>
32 #include <devices/8254.h>
33 #include <devices/nvram.h>
34 #include <devices/generic.h>
35 #include <devices/ramdisk.h>
36 #include <devices/cdrom.h>
37 #include <devices/bochs_debug.h>
38 #include <devices/os_debug.h>
39 #include <devices/apic.h>
40 #include <devices/io_apic.h>
41
42
43
44 #include <palacios/vmm_host_events.h>
45
46 #define USE_GENERIC 1
47
48
49 #define ROMBIOS_START 0x000f0000
50 #define VGABIOS_START 0x000c0000
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   if (v3_cpu_type == V3_SVM_REV3_CPU) {
89     info->shdw_pg_mode = NESTED_PAGING;
90   } else {
91     v3_init_shadow_page_state(info);
92     info->shdw_pg_mode = SHADOW_PAGING;
93   }
94   
95   // Initial CPU operating mode
96   info->cpu_mode = REAL;
97   info->mem_mode = PHYSICAL_MEM;
98
99   // Amount of ram the Guest will have
100   info->mem_size = config_ptr->mem_size;
101
102   // Configure the memory map for the guest
103   setup_memory_map(info, config_ptr);
104
105   // Configure the devices for the guest
106   setup_devices(info, config_ptr);
107  
108
109
110   if (config_ptr->enable_profiling) {
111     info->enable_profiler = 1;
112     v3_init_profiler(info);
113   } else {
114     info->enable_profiler = 0;
115   }
116
117   //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
118
119   // Setup initial cpu register state
120   info->rip = 0xfff0;
121   info->vm_regs.rsp = 0x0;
122   
123
124   return 0;
125 }
126
127
128 /* TODO:
129  * The amount of guest memory is stored in info->mem_size
130  * We need to make sure the memory map extends to cover it
131  */
132 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
133
134   /* layout rombios */
135   {
136     uint_t num_pages = (config_ptr->rombios_size + PAGE_SIZE - 1) / PAGE_SIZE;
137     void * guest_mem =  V3_AllocPages(num_pages);
138
139     PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size);
140     memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size);
141
142     v3_add_shadow_mem(info, ROMBIOS_START, ROMBIOS_START + (num_pages * PAGE_SIZE) - 1, (addr_t)guest_mem);
143     
144     PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
145                (void *)ROMBIOS_START, 
146                (void *)ROMBIOS_START + (num_pages * PAGE_SIZE), 
147                (void *)guest_mem);
148   }
149
150
151   /* layout vgabios */
152   {
153     uint_t num_pages = (config_ptr->vgabios_size + PAGE_SIZE - 1) / PAGE_SIZE;
154     void * guest_mem =  V3_AllocPages(num_pages);
155
156     PrintDebug("Layout Region %d bytes\n", config_ptr->vgabios_size);
157     memcpy(V3_VAddr(guest_mem), config_ptr->vgabios, config_ptr->vgabios_size);
158
159     v3_add_shadow_mem(info, VGABIOS_START, VGABIOS_START + (num_pages * PAGE_SIZE) - 1, (addr_t)guest_mem);
160     
161     PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
162                (void *)VGABIOS_START, 
163                (void *)VGABIOS_START + (num_pages * PAGE_SIZE), 
164                (void *)guest_mem);
165   }
166
167       //     
168   v3_add_shadow_mem(info, 0x0, 0x9ffff, (addr_t)V3_AllocPages(160));
169   
170   if (1) {
171     v3_add_shadow_mem(info, 0xa0000, 0xbffff, 0xa0000); 
172   } else {
173     v3_hook_write_mem(info, 0xa0000, 0xbffff, 0xa0000,  passthrough_mem_write, NULL);
174   }  
175   
176   // TEMP
177   //add_shadow_region_passthrough(info, 0xc0000, 0xc8000, 0xc0000);
178   
179   if (1) {
180     v3_add_shadow_mem(info, 0xc7000, 0xc8000, (addr_t)V3_AllocPages(1));
181     if (v3_add_shadow_mem(info, 0xc8000, 0xf0000, (addr_t)V3_AllocPages(40)) == -1) {
182       PrintDebug("Error adding shadow region\n");
183     }
184   } else {
185     v3_add_shadow_mem(info, 0xc0000, 0xc8000, 0xc0000);
186     v3_add_shadow_mem(info, 0xc8000, 0xf0000, 0xc8000);
187   }
188   
189   
190   if (1) {
191     v3_add_shadow_mem(info, 0x100000, 0x1000000, (addr_t)V3_AllocPages(4096));
192   } else {
193     /* MEMORY HOOK TEST */
194     v3_add_shadow_mem(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304));
195     v3_hook_write_mem(info, 0xa00000, 0xa01000, (addr_t)V3_AllocPages(1), passthrough_mem_write, NULL); 
196     v3_add_shadow_mem(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791));
197   }
198
199   v3_add_shadow_mem(info, 0x1000000, 0x8000000, (addr_t)V3_AllocPages(32768));
200  
201   // test - give linux accesss to PCI space - PAD
202   //v3_add_shadow_mem(info, 0xc0000000,0xffffffff,0xc0000000);
203   
204   
205   print_shadow_map(info);
206
207   return 0;
208 }
209
210
211
212 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
213     struct vm_device * ramdisk = NULL;
214     struct vm_device * cdrom = NULL;
215     struct vm_device * nvram = v3_create_nvram();
216     //struct vm_device * timer = v3_create_timer();
217     struct vm_device * pic = v3_create_pic();
218     struct vm_device * keyboard = v3_create_keyboard();
219     struct vm_device * pit = v3_create_pit(); 
220     struct vm_device * bochs_debug = v3_create_bochs_debug();
221     struct vm_device * os_debug = v3_create_os_debug();
222     struct vm_device * apic = v3_create_apic();
223     struct vm_device * ioapic = v3_create_io_apic();
224
225     //struct vm_device * serial = v3_create_serial();
226     struct vm_device * generic = NULL;
227
228     int use_ramdisk = config_ptr->use_ramdisk;
229     int use_generic = USE_GENERIC;
230
231
232     if (use_ramdisk) {
233       PrintDebug("Creating Ramdisk\n");
234       ramdisk = v3_create_ramdisk();
235       cdrom = v3_create_cdrom(ramdisk, config_ptr->ramdisk, config_ptr->ramdisk_size); 
236     }
237     
238     
239     if (use_generic) {
240       generic = configure_generic(info, config_ptr);
241     }
242
243
244     v3_attach_device(info, nvram);
245     //v3_attach_device(info, timer);
246     v3_attach_device(info, pic);
247     v3_attach_device(info, pit);
248     v3_attach_device(info, keyboard);
249     // v3_attach_device(info, serial);
250     v3_attach_device(info, bochs_debug);
251     v3_attach_device(info, os_debug);
252
253     v3_attach_device(info, apic);
254     v3_attach_device(info, ioapic);
255
256     if (use_ramdisk) {
257       v3_attach_device(info, ramdisk);
258       v3_attach_device(info, cdrom);
259     }
260
261     if (use_generic) {
262       // Important that this be attached last!
263       v3_attach_device(info, generic);
264     }
265     
266     PrintDebugDevMgr(info);
267
268
269     // give keyboard interrupts to vm
270     // no longer needed since we have a keyboard device
271     //hook_irq(&vm_info, 1);
272     
273 #if 0
274     // give floppy controller to vm
275     v3_hook_passthrough_irq(info, 6);
276 #endif
277     
278     
279     if (!use_ramdisk) {
280       PrintDebug("Hooking IDE IRQs\n");
281       
282       //primary ide
283       v3_hook_passthrough_irq(info, 14);
284       
285       // secondary ide
286       v3_hook_passthrough_irq(info, 15);    
287     }  
288     
289
290   return 0;
291 }
292
293
294
295 static struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
296       PrintDebug("Creating Generic Device\n");
297       struct vm_device * generic = v3_create_generic();
298       
299       // Make the DMA controller invisible
300       v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
301       v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
302       v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
303       v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
304       v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
305       v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
306       v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
307       v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
308       v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
309       v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
310       v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
311       v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
312       
313       
314       
315       
316       // Make the Serial ports invisible 
317       
318       v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
319       v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
320       
321
322       
323
324       v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
325       v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
326
327       
328       
329
330       // Make the PCI bus invisible (at least it's configuration)
331       
332       v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
333       v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
334
335       
336       
337 #if 0
338       if (!use_ramdisk) {
339         // Monitor the IDE controllers (very slow)
340         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
341         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
342       }
343       
344
345       v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
346       v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
347 #endif
348       
349       
350 #if 0
351       
352       // Make the floppy controllers invisible
353       
354       v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
355       v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
356       v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
357       v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
358       v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
359       v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
360       
361 #endif
362
363 #if 1
364
365       // Make the parallel port invisible
366       
367       v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
368
369 #endif
370
371 #if 1
372
373       // Monitor graphics card operations
374
375       v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
376       v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
377       
378 #endif
379
380
381 #if 1
382       // Make the ISA PNP features invisible
383
384       v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
385       v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
386       v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
387 #endif
388
389
390 #if 1
391       // Monitor any network card (realtek ne2000) operations 
392       v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
393 #endif
394
395
396 #if 1
397       // Make any Bus master ide controller invisible
398       
399       v3_generic_add_port_range(generic, 0xc000, 0xc00f, GENERIC_PRINT_AND_IGNORE);
400 #endif
401       //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
402       
403
404       return generic;
405
406 }