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.


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