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.


separated configuration to 2 phases pre/post
[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 int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
76    extern v3_cpu_arch_t v3_cpu_type;
77
78     // Amount of ram the Guest will have, rounded to a 4K page boundary
79     info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
80
81
82     // Initialize the subsystem data strutures
83     v3_init_time(info);
84     v3_init_io_map(info);
85     v3_init_msr_map(info);
86     v3_init_interrupt_state(info);
87     v3_init_exception_state(info);
88     v3_init_dev_mgr(info);
89     v3_init_host_events(info);
90
91
92     v3_init_decoder(info);
93     
94     v3_init_hypercall_map(info);
95
96
97     // Initialize the memory map
98     v3_init_shadow_map(info);
99     
100     if ((v3_cpu_type == V3_SVM_REV3_CPU) && 
101         (config_ptr->enable_nested_paging == 1)) {
102         PrintDebug("Guest Page Mode: NESTED_PAGING\n");
103         info->shdw_pg_mode = NESTED_PAGING;
104     } else {
105         PrintDebug("Guest Page Mode: SHADOW_PAGING\n");
106         v3_init_shadow_page_state(info);
107         info->shdw_pg_mode = SHADOW_PAGING;
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     
118     // Initial CPU operating mode
119     info->cpu_mode = REAL;
120     info->mem_mode = PHYSICAL_MEM;
121
122     return 0;
123 }
124
125
126 int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
127
128     // Configure the memory map for the guest
129     if (setup_memory_map(info, config_ptr) == -1) {
130         PrintError("Setting up guest memory map failed...\n");
131         return -1;
132     }
133     
134     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
135   
136     if (setup_devices(info, config_ptr) == -1) {
137         PrintError("Failed to setup devices\n");
138         return -1;
139     }
140
141     info->run_state = VM_STOPPED;
142
143     info->vm_regs.rdi = 0;
144     info->vm_regs.rsi = 0;
145     info->vm_regs.rbp = 0;
146     info->vm_regs.rsp = 0;
147     info->vm_regs.rbx = 0;
148     info->vm_regs.rdx = 0;
149     info->vm_regs.rcx = 0;
150     info->vm_regs.rax = 0;
151
152     return 0;
153 }
154
155
156
157
158
159 /* TODO:
160  * The amount of guest memory is stored in info->mem_size
161  * We need to make sure the memory map extends to cover it
162  */
163 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
164     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
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 #define VGABIOS_START 0x000c0000
177 #define ROMBIOS_START 0x000f0000
178
179     /* layout vgabios */
180     {
181         addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START);
182         memcpy(V3_VAddr((void *)vgabios_dst), config_ptr->vgabios, config_ptr->vgabios_size);   
183     }
184     
185     /* layout rombios */
186     {
187         addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START);
188         memcpy(V3_VAddr((void *)rombios_dst), config_ptr->rombios, config_ptr->rombios_size);
189     }
190
191 #ifdef CRAY_XT
192     {
193 #define SEASTAR_START 0xffe00000 
194 #define SEASTAR_END 0xffffffff 
195         // Map the Seastar straight through
196         if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
197             PrintError("Could not map through the seastar\n");
198             return -1;
199         }
200     }
201 #endif    
202
203     print_shadow_map(info);
204
205     return 0;
206 }
207
208
209
210 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
211
212     struct vm_device * ide = NULL;
213     struct vm_device * ramdisk = NULL;
214     
215     struct vm_device * pci = NULL;
216     struct vm_device * northbridge = NULL;
217     struct vm_device * southbridge = NULL;
218
219     struct vm_device * nvram = NULL;
220     struct vm_device * pic = v3_create_pic();
221     struct vm_device * keyboard = v3_create_keyboard();
222     struct vm_device * pit = v3_create_pit(); 
223     struct vm_device * bochs_debug = v3_create_bochs_debug();
224     struct vm_device * os_debug = v3_create_os_debug();
225     struct vm_device * apic = v3_create_apic();
226     struct vm_device * ioapic = v3_create_io_apic(apic);
227     struct vm_device * para_net = v3_create_para_net();
228
229
230     //struct vm_device * serial = v3_create_serial();
231     struct vm_device * generic = NULL;
232
233
234     int use_generic = USE_GENERIC;
235
236     if (config_ptr->enable_pci == 1) {
237         pci = v3_create_pci();
238         northbridge = v3_create_i440fx(pci);
239         southbridge = v3_create_piix3(pci);
240         ide = v3_create_ide(pci, southbridge);
241     } else {
242         ide = v3_create_ide(NULL, NULL);
243     }
244
245
246
247     nvram = v3_create_nvram(ide);
248
249     if (config_ptr->use_ram_cd == 1) {
250         PrintDebug("Creating Ram CD\n");
251         ramdisk = v3_create_ram_cd(ide, 0, 0, 
252                                    (addr_t)(config_ptr->ramdisk), 
253                                    config_ptr->ramdisk_size);
254     } else if (config_ptr->use_ram_hd == 1) {
255         PrintDebug("Creating Ram HD\n");
256         ramdisk = v3_create_ram_hd(ide, 0, 0, 
257                                    (addr_t)(config_ptr->ramdisk), 
258                                    config_ptr->ramdisk_size);
259     }
260     
261     
262     if (use_generic) {
263         generic = configure_generic(info, config_ptr);
264     }
265
266
267
268
269
270     v3_attach_device(info, pic);
271     v3_attach_device(info, pit);
272     v3_attach_device(info, keyboard);
273     // v3_attach_device(info, serial);
274     v3_attach_device(info, bochs_debug);
275     v3_attach_device(info, os_debug);
276
277     v3_attach_device(info, apic);
278     v3_attach_device(info, ioapic);
279
280     v3_attach_device(info, para_net);
281
282     if (config_ptr->enable_pci == 1) {
283         PrintDebug("Attaching PCI\n");
284         v3_attach_device(info, pci);
285         PrintDebug("Attaching Northbridge\n");
286         v3_attach_device(info, northbridge);
287         PrintDebug("Attaching Southbridge\n");
288         v3_attach_device(info, southbridge);
289     }
290
291     PrintDebug("Attaching IDE\n");
292     v3_attach_device(info, ide);
293
294     if (ramdisk != NULL) {
295         v3_attach_device(info, ramdisk);
296     }
297
298     if (use_generic) {
299         // Important that this be attached last!
300         v3_attach_device(info, generic);
301     }
302
303     // This should go last because it contains the hardware state
304     v3_attach_device(info, nvram);
305     
306     PrintDebugDevMgr(info);
307
308     return 0;
309 }
310
311
312
313
314
315 static struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
316     PrintDebug("Creating Generic Device\n");
317     struct vm_device * generic = v3_create_generic();
318     
319
320     // port 0x92: A20 enable/disable (bit 2) (This causes an MMU flush)
321
322
323     // Make the DMA controller invisible
324     v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
325     v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
326     v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
327     v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
328     v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
329     v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
330     v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
331     v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
332     v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
333     v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
334     v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
335     v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
336     
337     
338     
339     
340     // Make the Serial ports invisible 
341     
342     v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
343     v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
344     
345
346       
347
348     v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
349     v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
350
351       
352       
353
354     // Make the PCI bus invisible (at least it's configuration)
355     
356     //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
357     //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
358     
359     
360     
361 #if 0
362     if (!use_ramdisk) {
363         // Monitor the IDE controllers (very slow)
364         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
365         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
366     }
367       
368
369     v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
370     v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
371 #endif
372       
373       
374 #if 0
375     
376     // Make the floppy controllers invisible
377     
378     v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
379     v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
380     v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
381     v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
382     v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
383     v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
384     
385 #endif
386
387 #if 1
388
389     // Make the parallel port invisible
390       
391     v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
392
393 #endif
394
395 #if 1
396
397     // Monitor graphics card operations
398     
399     v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
400     v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
401       
402 #endif
403
404
405 #if 1
406     // Make the ISA PNP features invisible
407     
408     v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
409     v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
410     v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
411 #endif
412
413
414 #if 1
415     // Monitor any network card (realtek ne2000) operations 
416     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
417 #endif
418
419
420
421     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
422     
423
424     return generic;
425 }