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.


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