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.


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