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.


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