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