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.


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