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.


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