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.


I think I might have fixed the SHUTDOWN bug...
[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 struct vm_device *  configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr);
59
60
61
62
63 static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
64
65     return length;
66     //  memcpy((void*)guest_addr, src, length);
67     PrintDebug("Write of %d bytes to %p\n", length, (void *)guest_addr);
68     PrintDebug("Write Value = %p\n", (void *)*(addr_t *)src);
69     
70     return length;
71 }
72
73
74
75 int v3_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     
101     if ((v3_cpu_type == V3_SVM_REV3_CPU) && 
102         (config_ptr->enable_nested_paging == 1)) {
103         PrintDebug("Guest Page Mode: NESTED_PAGING\n");
104         info->shdw_pg_mode = NESTED_PAGING;
105     } else {
106         PrintDebug("Guest Page Mode: SHADOW_PAGING\n");
107         v3_init_shadow_page_state(info);
108         info->shdw_pg_mode = SHADOW_PAGING;
109     }
110     
111     // Initial CPU operating mode
112     info->cpu_mode = REAL;
113     info->mem_mode = PHYSICAL_MEM;
114     
115     // Configure the memory map for the guest
116     if (setup_memory_map(info, config_ptr) == -1) {
117         PrintError("Setting up guest memory map failed...\n");
118         return -1;
119     }
120     
121
122     if (config_ptr->enable_profiling) {
123         info->enable_profiler = 1;
124         v3_init_profiler(info);
125     } else {
126         info->enable_profiler = 0;
127     }
128
129     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
130     
131     // Setup initial cpu register state
132     info->rip = 0xfff0;
133     info->vm_regs.rsp = 0x0;
134   
135     
136     return 0;
137 }
138
139
140
141
142
143 /* TODO:
144  * The amount of guest memory is stored in info->mem_size
145  * We need to make sure the memory map extends to cover it
146  */
147 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
148     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
149     
150     // VGA frame buffer
151     if (1) {
152         if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
153             PrintError("Could not map VGA framebuffer\n");
154             return -1;
155         }
156     } else {
157         v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
158     }  
159
160 #define VGABIOS_START 0x000c0000
161 #define ROMBIOS_START 0x000f0000
162
163     /* layout vgabios */
164     {
165         addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START);
166         memcpy(V3_VAddr((void *)vgabios_dst), config_ptr->vgabios, config_ptr->vgabios_size);   
167     }
168     
169     /* layout rombios */
170     {
171         addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START);
172         memcpy(V3_VAddr((void *)rombios_dst), config_ptr->rombios, config_ptr->rombios_size);
173     }
174
175 #ifdef CRAY_XT
176     {
177 #define SEASTAR_START 0xffe00000 
178 #define SEASTAR_END 0xffffffff 
179         // Map the Seastar straight through
180         if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
181             PrintError("Could not map through the seastar\n");
182             return -1;
183         }
184     }
185 #endif    
186
187     print_shadow_map(info);
188
189     return 0;
190 }
191
192
193
194 int v3_config_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
195
196     struct vm_device * ide = NULL;
197     struct vm_device * ramdisk = NULL;
198     
199     struct vm_device * pci = NULL;
200     struct vm_device * northbridge = NULL;
201     struct vm_device * southbridge = NULL;
202
203     struct vm_device * nvram = NULL;
204     struct vm_device * pic = v3_create_pic();
205     struct vm_device * keyboard = v3_create_keyboard();
206     struct vm_device * pit = v3_create_pit(); 
207     struct vm_device * bochs_debug = v3_create_bochs_debug();
208     struct vm_device * os_debug = v3_create_os_debug();
209     struct vm_device * apic = v3_create_apic();
210     struct vm_device * ioapic = v3_create_io_apic(apic);
211     struct vm_device * para_net = v3_create_para_net();
212
213
214     //struct vm_device * serial = v3_create_serial();
215     struct vm_device * generic = NULL;
216
217
218     int use_generic = USE_GENERIC;
219
220     if (config_ptr->enable_pci == 1) {
221         pci = v3_create_pci();
222         northbridge = v3_create_i440fx(pci);
223         southbridge = v3_create_piix3(pci);
224         ide = v3_create_ide(pci, southbridge);
225     } else {
226         ide = v3_create_ide(NULL, NULL);
227     }
228
229
230
231     nvram = v3_create_nvram(ide);
232
233     if (config_ptr->use_ram_cd == 1) {
234         PrintDebug("Creating Ram CD\n");
235         ramdisk = v3_create_ram_cd(ide, 0, 0, 
236                                    (addr_t)(config_ptr->ramdisk), 
237                                    config_ptr->ramdisk_size);
238     } else if (config_ptr->use_ram_hd == 1) {
239         PrintDebug("Creating Ram HD\n");
240         ramdisk = v3_create_ram_hd(ide, 0, 0, 
241                                    (addr_t)(config_ptr->ramdisk), 
242                                    config_ptr->ramdisk_size);
243     }
244     
245     
246     if (use_generic) {
247         generic = configure_generic(info, config_ptr);
248     }
249
250
251
252
253
254     v3_attach_device(info, pic);
255     v3_attach_device(info, pit);
256     v3_attach_device(info, keyboard);
257     // v3_attach_device(info, serial);
258     v3_attach_device(info, bochs_debug);
259     v3_attach_device(info, os_debug);
260
261     v3_attach_device(info, apic);
262     v3_attach_device(info, ioapic);
263
264     v3_attach_device(info, para_net);
265
266     if (config_ptr->enable_pci == 1) {
267         PrintDebug("Attaching PCI\n");
268         v3_attach_device(info, pci);
269         PrintDebug("Attaching Northbridge\n");
270         v3_attach_device(info, northbridge);
271         PrintDebug("Attaching Southbridge\n");
272         v3_attach_device(info, southbridge);
273     }
274
275     PrintDebug("Attaching IDE\n");
276     v3_attach_device(info, ide);
277
278     if (ramdisk != NULL) {
279         v3_attach_device(info, ramdisk);
280     }
281
282     if (use_generic) {
283         // Important that this be attached last!
284         v3_attach_device(info, generic);
285     }
286
287     // This should go last because it contains the hardware state
288     v3_attach_device(info, nvram);
289     
290     PrintDebugDevMgr(info);
291
292     return 0;
293 }
294
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
304     // port 0x92: A20 enable/disable (bit 2) (This causes an MMU flush)
305
306
307     // Make the DMA controller invisible
308     v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
309     v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
310     v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
311     v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
312     v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
313     v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
314     v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
315     v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
316     v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
317     v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
318     v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
319     v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
320     
321     
322     
323     
324     // Make the Serial ports invisible 
325     
326     v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
327     v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
328     
329
330       
331
332     v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
333     v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
334
335       
336       
337
338     // Make the PCI bus invisible (at least it's configuration)
339     
340     //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
341     //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
342     
343     
344     
345 #if 0
346     if (!use_ramdisk) {
347         // Monitor the IDE controllers (very slow)
348         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
349         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
350     }
351       
352
353     v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
354     v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
355 #endif
356       
357       
358 #if 0
359     
360     // Make the floppy controllers invisible
361     
362     v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
363     v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
364     v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
365     v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
366     v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
367     v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
368     
369 #endif
370
371 #if 1
372
373     // Make the parallel port invisible
374       
375     v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
376
377 #endif
378
379 #if 1
380
381     // Monitor graphics card operations
382     
383     v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
384     v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
385       
386 #endif
387
388
389 #if 1
390     // Make the ISA PNP features invisible
391     
392     v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
393     v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
394     v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
395 #endif
396
397
398 #if 1
399     // Monitor any network card (realtek ne2000) operations 
400     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
401 #endif
402
403
404
405     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
406     
407
408     return generic;
409 }