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.


Ported palacios to Kbuild
[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     if (config_ptr->schedule_freq == 0) {
108         // set the schedule frequency to 100 HZ
109         config_ptr->schedule_freq = 100;
110     }
111
112     PrintDebug("CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), (void *)config_ptr->schedule_freq);
113
114     info->yield_cycle_period = (V3_CPU_KHZ() * 1000) / config_ptr->schedule_freq;
115     
116     // Initial CPU operating mode
117     info->cpu_mode = REAL;
118     info->mem_mode = PHYSICAL_MEM;
119
120     return 0;
121 }
122
123
124 int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
125
126     // Configure the memory map for the guest
127     if (setup_memory_map(info, config_ptr) == -1) {
128         PrintError("Setting up guest memory map failed...\n");
129         return -1;
130     }
131     
132     //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
133   
134     if (setup_devices(info, config_ptr) == -1) {
135         PrintError("Failed to setup devices\n");
136         return -1;
137     }
138
139     info->run_state = VM_STOPPED;
140
141     info->vm_regs.rdi = 0;
142     info->vm_regs.rsi = 0;
143     info->vm_regs.rbp = 0;
144     info->vm_regs.rsp = 0;
145     info->vm_regs.rbx = 0;
146     info->vm_regs.rdx = 0;
147     info->vm_regs.rcx = 0;
148     info->vm_regs.rax = 0;
149
150     return 0;
151 }
152
153
154
155
156
157 /* TODO:
158  * The amount of guest memory is stored in info->mem_size
159  * We need to make sure the memory map extends to cover it
160  */
161 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
162     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
163     
164     // VGA frame buffer
165     if (1) {
166         if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
167             PrintError("Could not map VGA framebuffer\n");
168             return -1;
169         }
170     } else {
171         v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
172     }
173
174 #define VGABIOS_START 0x000c0000
175 #define ROMBIOS_START 0x000f0000
176
177     /* layout vgabios */
178     {
179         extern uint8_t v3_vgabios_start[];
180         extern uint8_t v3_vgabios_end[];
181
182         addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START);
183         memcpy(V3_VAddr((void *)vgabios_dst), v3_vgabios_start, v3_vgabios_end - v3_vgabios_start);     
184     }
185     
186     /* layout rombios */
187     {
188         extern uint8_t v3_rombios_start[];
189         extern uint8_t v3_rombios_end[];
190
191         addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START);
192         memcpy(V3_VAddr((void *)rombios_dst), v3_rombios_start, v3_rombios_end - v3_rombios_start);
193     }
194
195 #ifdef CRAY_XT
196     {
197 #define SEASTAR_START 0xffe00000 
198 #define SEASTAR_END 0xffffffff 
199         // Map the Seastar straight through
200         if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
201             PrintError("Could not map through the seastar\n");
202             return -1;
203         }
204     }
205 #endif
206
207     print_shadow_map(info);
208
209     return 0;
210 }
211
212
213
214 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
215
216     v3_create_device(info, "8259A", NULL);
217     v3_create_device(info, "KEYBOARD", NULL);
218     v3_create_device(info, "8254_PIT", NULL); 
219     v3_create_device(info, "BOCHS_DEBUG", NULL);
220     v3_create_device(info, "OS_DEBUG", NULL);
221     v3_create_device(info, "LAPIC", NULL);
222     v3_create_device(info, "IOAPIC", "LAPIC");
223     v3_create_device(info, "VMNET", NULL);
224     
225     int use_generic = USE_GENERIC;
226
227     if (config_ptr->enable_pci == 1) {
228         struct ide_cfg ide_config = {"PCI", "PIIX3"};
229         
230         v3_create_device(info, "PCI", NULL);
231         v3_create_device(info, "i440FX", "PCI");
232         v3_create_device(info, "PIIX3", "PCI");
233         
234
235         v3_create_device(info, "LNX_VIRTIO_SYM", "PCI");
236         v3_create_device(info, "LNX_VIRTIO_BLK", "PCI");
237         v3_create_device(info, "LNX_VIRTIO_BALLOON", "PCI");
238         v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK");
239
240
241         v3_create_device(info, "IDE", &ide_config);
242     } else {
243         v3_create_device(info, "IDE", NULL);
244     }
245
246
247     if (config_ptr->pri_disk_type != NONE) {
248         if (config_ptr->pri_disk_type == CDROM) {
249             if (config_ptr->pri_disk_con == RAM) {
250                 struct ram_cd_cfg cfg = {"IDE", 0, 0, 
251                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
252                                          config_ptr->pri_disk_info.ram.size};
253
254                 PrintDebug("Creating RAM CD\n");
255
256                 v3_create_device(info, "RAM-CD", &cfg);
257             } else if (config_ptr->pri_disk_con == NETWORK) {
258                 struct net_cd_cfg cfg = {"IDE", 0, 0, 
259                                          config_ptr->pri_disk_info.net.ip_str,
260                                          config_ptr->pri_disk_info.net.port, 
261                                          config_ptr->pri_disk_info.net.disk_name};
262                 PrintDebug("Creating NET CD\n");
263
264                 v3_create_device(info, "NET-CD", &cfg);
265             }
266         } else if (config_ptr->pri_disk_type == HARDDRIVE) {
267             if (config_ptr->pri_disk_con == RAM) {
268                 struct ram_hd_cfg cfg = {"IDE", 0, 0, 
269                                          (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
270                                          config_ptr->pri_disk_info.ram.size};
271
272                 PrintDebug("Creating RAM HD\n");
273
274                 v3_create_device(info, "RAM-HD", &cfg);
275             } else if (config_ptr->pri_disk_con == NETWORK) {
276                 struct net_hd_cfg cfg  = {"IDE", 0, 0, 
277                                           config_ptr->pri_disk_info.net.ip_str,
278                                           config_ptr->pri_disk_info.net.port, 
279                                           config_ptr->pri_disk_info.net.disk_name};
280                 PrintDebug("Creating NET HD\n");
281                 v3_create_device(info, "NET-HD", &cfg);
282             }
283         }
284     }
285
286
287
288     if (config_ptr->sec_disk_type != NONE) {
289         if (config_ptr->sec_disk_type == CDROM) {
290             if (config_ptr->sec_disk_con == RAM) {
291                 struct ram_cd_cfg cfg = {"IDE", 0, 1, 
292                                          (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
293                                          config_ptr->sec_disk_info.ram.size};
294
295                 PrintDebug("Creating RAM CD\n");
296                 v3_create_device(info, "RAM-CD", &cfg);
297             } else if (config_ptr->sec_disk_con == NETWORK) {
298                 struct net_cd_cfg cfg = {"IDE", 0, 1, 
299                                          config_ptr->sec_disk_info.net.ip_str,
300                                          config_ptr->sec_disk_info.net.port, 
301                                          config_ptr->sec_disk_info.net.disk_name};
302
303                 PrintDebug("Creating NET CD\n");
304                 v3_create_device(info, "NET-CD", &cfg);    
305             }
306         } else if (config_ptr->sec_disk_type == HARDDRIVE) {
307             if (config_ptr->sec_disk_con == RAM) {
308                 struct ram_hd_cfg cfg = {"IDE", 0, 1, 
309                                          (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
310                                          config_ptr->sec_disk_info.ram.size};
311                 PrintDebug("Creating RAM HD\n");
312                 v3_create_device(info, "RAM-HD", &cfg);
313             } else if (config_ptr->sec_disk_con == NETWORK) {
314                 struct net_hd_cfg cfg = {"IDE", 0, 1, 
315                                          config_ptr->sec_disk_info.net.ip_str,
316                                          config_ptr->sec_disk_info.net.port, 
317                                          config_ptr->sec_disk_info.net.disk_name};
318                 PrintDebug("Creating NET HD\n");
319                 v3_create_device(info, "NET-HD", &cfg);
320             }
321         }
322     }
323
324
325
326     if (use_generic) {
327         configure_generic(info, config_ptr);
328     }
329
330     // This should go last because it requires information about the Harddrives
331     v3_create_device(info, "NVRAM", "IDE");
332     
333     PrintDebugDevMgr(info);
334
335     return 0;
336 }
337
338
339
340
341 static int configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
342     PrintDebug("Creating Generic Device\n");
343     v3_create_device(info, "GENERIC", NULL);
344     
345
346     struct vm_device * generic = v3_find_dev(info, "GENERIC");
347
348     if (!generic) {
349         PrintError("Could not find generic device\n");
350         return -1;
351     }
352
353     // port 0x92: A20 enable/disable (bit 2) (This causes an MMU flush)
354
355
356     // Make the DMA controller invisible
357     v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
358     v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
359     v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
360     v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
361     v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
362     v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
363     v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
364     v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
365     v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
366     v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
367     v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
368     v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
369     
370     
371     
372     
373     // Make the Serial ports invisible 
374     
375     v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
376     v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
377     
378
379       
380
381     v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
382     v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
383
384       
385       
386
387     // Make the PCI bus invisible (at least it's configuration)
388     
389     //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
390     //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
391     
392     
393     
394 #if 0
395     if (!use_ramdisk) {
396         // Monitor the IDE controllers (very slow)
397         v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
398         v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
399     }
400       
401
402     v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
403     v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
404 #endif
405       
406       
407 #if 0
408     
409     // Make the floppy controllers invisible
410     
411     v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
412     v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
413     v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
414     v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
415     v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
416     v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
417     
418 #endif
419
420 #if 1
421
422     // Make the parallel port invisible
423       
424     v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
425
426 #endif
427
428 #if 1
429
430     // Monitor graphics card operations
431     
432     v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
433     v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
434       
435 #endif
436
437
438 #if 1
439     // Make the ISA PNP features invisible
440     
441     v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
442     v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
443     v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
444 #endif
445
446
447 #if 1
448     // Monitor any network card (realtek ne2000) operations 
449     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
450 #endif
451
452     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
453     
454     return 0;
455 }