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.


Avoid physical/virtual contiguity assumptions using new guest memory access functions
[palacios.git] / palacios / src / palacios / vmm_bios.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) 2015, The V3VEE Project <http://www.v3vee.org> 
11  * All rights reserved.
12  *
13  * Author: Peter Dinda <pdinda@northwestern.edu>
14  *
15  * This is free software.  You are permitted to use,
16  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
17  */
18
19 #include <palacios/vmm_bios.h>
20 #include <palacios/vm_guest_mem.h>
21 #include <palacios/vmm_xml.h>
22
23
24
25 int v3_setup_bioses(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) 
26 {
27
28     v3_cfg_tree_t * bios_tree = NULL;
29     v3_cfg_tree_t * bios_list = NULL;
30     
31     bios_tree = v3_cfg_subtree(cfg, "bioses");
32     
33     
34     if (!v3_cfg_val(bios_tree, "disable_vgabios")) {
35         
36 #if defined(V3_CONFIG_SEABIOS) || defined(V3_CONFIG_BOCHSBIOS)
37
38 #define VGABIOS_START 0x000c0000
39         /* layout vgabios */
40         {
41             extern uint8_t v3_vgabios_start[];
42             extern uint8_t v3_vgabios_end[];
43
44             V3_Print(vm,VCORE_NONE,"Mapping VGA BIOS of %llu bytes at gpa %p\n", (uint64_t)(v3_vgabios_end-v3_vgabios_start), (void*)VGABIOS_START);
45
46             if (v3_write_gpa_memory(&(vm->cores[0]), VGABIOS_START, v3_vgabios_end - v3_vgabios_start, v3_vgabios_start) != (v3_vgabios_end - v3_vgabios_start)) { 
47                 PrintError(vm, VCORE_NONE, "Could not write VGA BIOS\n");
48                 return -1;
49             }
50         }
51
52 #endif
53
54     }
55
56
57     if (!v3_cfg_val(bios_tree, "disable_rombios")) {
58
59         /* layout rombios */
60         {
61             extern uint8_t v3_rombios_start[];
62             extern uint8_t v3_rombios_end[];
63
64             V3_Print(vm,VCORE_NONE,"Mapping BIOS of %llu bytes at gpa %p\n", (uint64_t)(v3_rombios_end-v3_rombios_start), (void*)V3_CONFIG_BIOS_START);
65
66             if (v3_write_gpa_memory(&(vm->cores[0]), V3_CONFIG_BIOS_START, v3_rombios_end - v3_rombios_start, v3_rombios_start) != (v3_rombios_end - v3_rombios_start)) { 
67                 PrintError(vm, VCORE_NONE, "Could not write ROM BIOS\n");
68                 return -1;
69             }
70
71 #ifdef V3_CONFIG_SEABIOS
72             
73 #define SEABIOS_HIGH_START 0xfffe0000ULL
74 #define SEABIOS_HIGH_END   0x100000000ULL
75
76             V3_Print(vm,VCORE_NONE,"Additionally mapping SEABIOS of %llu bytes at gpa %p\n", (uint64_t)(v3_rombios_end-v3_rombios_start), (void*)SEABIOS_HIGH_START);
77
78             if (v3_get_mem_region(vm,V3_MEM_CORE_ANY, SEABIOS_HIGH_START)) {
79                 // it is already mapped, we are done
80                 // note it's mapped to the same place as the low memory copy
81                 // so it's now pointing to the fresh copy
82                 V3_Print(vm,VCORE_NONE,"BIOS is already mapped\n");
83             } else {
84                 extern uint64_t v3_mem_block_size;
85                 void *rombios_dst;
86
87                 if (v3_gpa_to_hva(&(vm->cores[0]), V3_CONFIG_BIOS_START, (addr_t *)&rombios_dst) == -1) { 
88                     PrintError(vm, VCORE_NONE, "Could not find ROMBIOS destination address\n");
89                     return -1;
90                 }
91
92                 if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY, 
93                                       SEABIOS_HIGH_START, SEABIOS_HIGH_END,
94                                       (addr_t)V3_PAddr(rombios_dst)) == -1) {
95                     PrintError(vm, VCORE_NONE, "Error mapping SEABIOS to end of memory\n");
96                     return -1;
97                 }
98
99                 if ((V3_CONFIG_BIOS_START / v3_mem_block_size) != 
100                     ((V3_CONFIG_BIOS_START+(SEABIOS_HIGH_END-SEABIOS_HIGH_START-1)) / v3_mem_block_size)) { 
101                     PrintError(vm,VCORE_NONE, "ALERT: MAPPING OF SEABIOS SPANS MEMORY BLOCKS: %llx %llx %llx\n",
102                                (uint64_t) V3_CONFIG_BIOS_START,(uint64_t)(V3_CONFIG_BIOS_START+(SEABIOS_HIGH_END-SEABIOS_HIGH_START-1)), v3_mem_block_size);
103                 }
104
105                 V3_Print(vm,VCORE_NONE,"BIOS  mapped\n");
106
107             }
108             
109 #endif
110
111         }
112
113         {
114
115 // traditional BIOS data area (and IVT, etc).  Technically only 0x400-0x4ff is the BDA
116 #define BDA_START   0x0
117 #define BDA_END     0xfff
118
119 // Extended BDA and EBDA2.  Technically not standardized.  Usually at the
120 // end of the 640K chunk.  We're just using that last page to play it save
121 #define EBDA_START 0x9f000
122 #define EBDA_END   0x9ffff
123
124             V3_Print(vm,VCORE_NONE,"Clearing BDA %p through %p\n",(void*)BDA_START,(void*)BDA_END);
125
126             if (v3_set_gpa_memory(&vm->cores[0],BDA_START,BDA_END-BDA_START,0)!=BDA_END-BDA_START) {
127                 PrintError(vm, VCORE_NONE, "Could not zero BDA\n");
128                 return -1;
129             }
130
131             V3_Print(vm,VCORE_NONE,"Clearing EBDA %p through %p\n",(void*)EBDA_START,(void*)EBDA_END);
132
133             if (v3_set_gpa_memory(&vm->cores[0],EBDA_START,EBDA_END-EBDA_START,0)!=EBDA_END-EBDA_START) {
134                 PrintError(vm, VCORE_NONE, "Could not zero eBDA\n");
135                 return -1;
136             }
137
138
139         }
140
141     }
142
143     
144
145     bios_list = v3_cfg_subtree(bios_tree, "bios");
146
147     while (bios_list) {
148         char * id = v3_cfg_val(bios_list, "file");
149         char * addr = v3_cfg_val(bios_list, "address");
150         uint64_t file_ptr = 0;
151         struct v3_cfg_file * file = NULL;
152
153         if (!id) {
154             PrintError(vm, VCORE_NONE, "Could not find bios file\n");
155             continue;
156         }
157
158         if (!addr) {
159             PrintError(vm, VCORE_NONE, "Could not find bios address\n");
160             continue;
161         }
162
163         file = v3_cfg_get_file(vm, id);
164         if (!file) {
165             PrintError(vm, VCORE_NONE, "Invalid BIOS file: %s\n", id);
166             continue;
167         }
168
169         file_ptr = atox(addr);
170
171         V3_Print(vm, VCORE_NONE, "Copying BIOS ROM (%s) to %p (size=%lld)\n", 
172                  id,
173                  (void*)file_ptr,
174                  file->size);
175
176         if (v3_write_gpa_memory(&vm->cores[0],(addr_t)file_ptr,file->size,file->data)!=file->size) {
177             PrintError(vm, VCORE_NONE, "Could not copy BIOS (%s)\n",id);
178             return -1;
179         }
180
181         V3_Print(vm, VCORE_NONE, "Moving on to next BIOS file\n");
182         bios_list = v3_cfg_next_branch(bios_list);
183     }
184
185     // NOW BLOW AWAY BDA and EBDA here
186     // possibly also reset CMOS
187
188
189     return 0;
190 }