|
37 | 37 | * mapping.
|
38 | 38 | */
|
39 | 39 |
|
40 |
| -#include "../include/hax.h" |
41 | 40 | #include "include/ept.h"
|
42 | 41 | #include "include/cpu.h"
|
43 |
| -#include "include/paging.h" |
44 |
| -#include "include/vtlb.h" |
45 | 42 |
|
46 | 43 | static uint64_t ept_capabilities;
|
47 | 44 |
|
@@ -77,251 +74,6 @@ static bool ept_has_cap(uint64_t cap)
|
77 | 74 | return (ept_capabilities & cap) != 0;
|
78 | 75 | }
|
79 | 76 |
|
80 |
| -// Get the PDE entry for the specified gpa in EPT |
81 |
| -static epte_t * ept_get_pde(struct hax_ept *ept, hax_paddr_t gpa) |
82 |
| -{ |
83 |
| - epte_t *e; |
84 |
| - uint which_g = gpa >> 30; |
85 |
| - // PML4 and PDPTE level needs 2 pages |
86 |
| - uint64_t offset = (2 + which_g) * PAGE_SIZE_4K; |
87 |
| - // Need Xiantao's check |
88 |
| - unsigned char *ept_addr = hax_page_va(ept->ept_root_page); |
89 |
| - |
90 |
| - hax_assert(which_g < EPT_MAX_MEM_G); |
91 |
| - |
92 |
| - e = (epte_t *)(ept_addr + offset) + ept_get_pde_idx(gpa); |
93 |
| - return e; |
94 |
| -} |
95 |
| - |
96 |
| -// ept_set_pte: caller can use it to setup p2m mapping for the guest. |
97 |
| -bool ept_set_pte(hax_vm_t *hax_vm, hax_paddr_t gpa, hax_paddr_t hpa, uint emt, |
98 |
| - uint mem_type, bool *is_modified) |
99 |
| -{ |
100 |
| - bool ret = true; |
101 |
| - struct hax_page *page; |
102 |
| - hax_paddr_t pte_ha; |
103 |
| - epte_t *pte; |
104 |
| - void *pte_base, *addr; |
105 |
| - struct hax_ept *ept = hax_vm->ept; |
106 |
| - uint which_g = gpa >> 30; |
107 |
| - uint perm; |
108 |
| - epte_t *pde = ept_get_pde(ept, gpa); |
109 |
| - |
110 |
| - // hax_log(HAX_LOGD, "hpa %llx gpa %llx\n", hpa, gpa); |
111 |
| - if (which_g >= EPT_MAX_MEM_G) { |
112 |
| - hax_log(HAX_LOGE, "Error: Guest's memory size is beyond %dG!\n", |
113 |
| - EPT_MAX_MEM_G); |
114 |
| - return false; |
115 |
| - } |
116 |
| - hax_mutex_lock(hax_vm->vm_lock); |
117 |
| - if (!epte_is_present(pde)) { |
118 |
| - if (mem_type == EPT_TYPE_NONE) { // unmap |
119 |
| - // Don't bother allocating the PT |
120 |
| - goto out_unlock; |
121 |
| - } |
122 |
| - |
123 |
| - page = hax_alloc_page(0, 1); |
124 |
| - if (!page) { |
125 |
| - ret = false; |
126 |
| - goto out_unlock; |
127 |
| - } |
128 |
| - |
129 |
| - hax_list_add(&page->list, &ept->ept_page_list); |
130 |
| - addr = hax_page_va(page); |
131 |
| - memset(addr, 0, PAGE_SIZE_4K); |
132 |
| - pte_ha = hax_page_pa(page); |
133 |
| - // Always own full access rights |
134 |
| - epte_set_entry(pde, pte_ha, 7, EMT_NONE); |
135 |
| - } |
136 |
| - |
137 |
| - // Grab the PTE entry |
138 |
| - pte_base = hax_vmap_pfn(pde->addr); |
139 |
| - if (!pte_base) { |
140 |
| - ret = false; |
141 |
| - goto out_unlock; |
142 |
| - } |
143 |
| - pte = (epte_t *)pte_base + ept_get_pte_idx(gpa); |
144 |
| - // TODO: Just for debugging, need check QEMU for more information |
145 |
| - /* if (epte_is_present(pte)) { |
146 |
| - * hax_log(HAX_LOGD, "Can't change the pte entry!\n"); |
147 |
| - * hax_mutex_unlock(hax_vm->vm_lock); |
148 |
| - * hax_log(HAX_LOGD, "\npte %llx\n", pte->val); |
149 |
| - * hax_vunmap_pfn(pte_base); |
150 |
| - * return 0; |
151 |
| - * } |
152 |
| - */ |
153 |
| - switch (mem_type) { |
154 |
| - case EPT_TYPE_NONE: { |
155 |
| - perm = 0; // unmap |
156 |
| - break; |
157 |
| - } |
158 |
| - case EPT_TYPE_MEM: { |
159 |
| - perm = 7; |
160 |
| - break; |
161 |
| - } |
162 |
| - case EPT_TYPE_ROM: { |
163 |
| - perm = 5; |
164 |
| - break; |
165 |
| - } |
166 |
| - default: { |
167 |
| - hax_log(HAX_LOGE, "Unsupported mapping type 0x%x\n", mem_type); |
168 |
| - ret = false; |
169 |
| - goto out_unmap; |
170 |
| - } |
171 |
| - } |
172 |
| - *is_modified = epte_is_present(pte) && (epte_get_address(pte) != hpa || |
173 |
| - epte_get_perm(pte) != perm || epte_get_emt(pte) != emt); |
174 |
| - epte_set_entry(pte, hpa, perm, emt); |
175 |
| - |
176 |
| -out_unmap: |
177 |
| - hax_vunmap_pfn(pte_base); |
178 |
| -out_unlock: |
179 |
| - hax_mutex_unlock(hax_vm->vm_lock); |
180 |
| - return ret; |
181 |
| -} |
182 |
| - |
183 |
| -static bool ept_lookup(struct vcpu_t *vcpu, hax_paddr_t gpa, hax_paddr_t *hpa) |
184 |
| -{ |
185 |
| - epte_t *pde, *pte; |
186 |
| - void *pte_base; |
187 |
| - struct hax_ept *ept = vcpu->vm->ept; |
188 |
| - uint which_g = gpa >> 30; |
189 |
| - |
190 |
| - hax_assert(ept->ept_root_page); |
191 |
| - if (which_g >= EPT_MAX_MEM_G) { |
192 |
| - hax_log(HAX_LOGD, "ept_lookup error!\n"); |
193 |
| - return 0; |
194 |
| - } |
195 |
| - |
196 |
| - pde = ept_get_pde(ept, gpa); |
197 |
| - |
198 |
| - if (!epte_is_present(pde)) |
199 |
| - return 0; |
200 |
| - |
201 |
| - pte_base = hax_vmap_pfn(pde->addr); |
202 |
| - if (!pte_base) |
203 |
| - return 0; |
204 |
| - |
205 |
| - pte = (epte_t *)pte_base + ept_get_pte_idx(gpa); |
206 |
| - |
207 |
| - if (!epte_is_present(pte)) { |
208 |
| - hax_vunmap_pfn(pte_base); |
209 |
| - return 0; |
210 |
| - } |
211 |
| - |
212 |
| - *hpa = (pte->addr << 12) | (gpa & 0xfff); |
213 |
| - hax_vunmap_pfn(pte_base); |
214 |
| - return 1; |
215 |
| -} |
216 |
| - |
217 |
| -/* |
218 |
| - * Deprecated API of EPT |
219 |
| - * Translate a GPA to an HPA |
220 |
| - * @param vcpu: current vcpu structure pointer |
221 |
| - * @param gpa: guest physical address |
222 |
| - * @param order: order for gpa |
223 |
| - * @param hpa host physical address pointer |
224 |
| - */ |
225 |
| - |
226 |
| -// TODO: Do we need to consider cross-page case ?? |
227 |
| -bool ept_translate(struct vcpu_t *vcpu, hax_paddr_t gpa, uint order, hax_paddr_t *hpa) |
228 |
| -{ |
229 |
| - hax_assert(order == PG_ORDER_4K); |
230 |
| - return ept_lookup(vcpu, gpa, hpa); |
231 |
| -} |
232 |
| - |
233 |
| -static eptp_t ept_construct_eptp(hax_paddr_t addr) |
234 |
| -{ |
235 |
| - eptp_t eptp; |
236 |
| - eptp.val = 0; |
237 |
| - eptp.emt = EMT_WB; |
238 |
| - eptp.gaw = EPT_DEFAULT_GAW; |
239 |
| - eptp.asr = addr >> PG_ORDER_4K; |
240 |
| - return eptp; |
241 |
| -} |
242 |
| - |
243 |
| -bool ept_init(hax_vm_t *hax_vm) |
244 |
| -{ |
245 |
| - uint i; |
246 |
| - hax_paddr_t hpa; |
247 |
| - // Need Xiantao's check |
248 |
| - unsigned char *ept_addr; |
249 |
| - epte_t *e; |
250 |
| - struct hax_page *page; |
251 |
| - struct hax_ept *ept; |
252 |
| - |
253 |
| - if (hax_vm->ept) { |
254 |
| - hax_log(HAX_LOGD, "EPT: EPT has been created already!\n"); |
255 |
| - return 0; |
256 |
| - } |
257 |
| - |
258 |
| - ept = hax_vmalloc(sizeof(struct hax_ept), 0); |
259 |
| - if (!ept) { |
260 |
| - hax_log(HAX_LOGD, |
261 |
| - "EPT: No enough memory for creating EPT structure!\n"); |
262 |
| - return 0; |
263 |
| - } |
264 |
| - memset(ept, 0, sizeof(struct hax_ept)); |
265 |
| - hax_vm->ept = ept; |
266 |
| - |
267 |
| - page = hax_alloc_pages(EPT_PRE_ALLOC_PG_ORDER, 0, 1); |
268 |
| - if (!page) { |
269 |
| - hax_log(HAX_LOGD, "EPT: No enough memory for creating ept table!\n"); |
270 |
| - hax_vfree(hax_vm->ept, sizeof(struct hax_ept)); |
271 |
| - return 0; |
272 |
| - } |
273 |
| - ept->ept_root_page = page; |
274 |
| - ept_addr = hax_page_va(page); |
275 |
| - memset(ept_addr, 0, EPT_PRE_ALLOC_PAGES * PAGE_SIZE_4K); |
276 |
| - |
277 |
| - // One page for building PML4 level |
278 |
| - ept->eptp = ept_construct_eptp(hax_pa(ept_addr)); |
279 |
| - e = (epte_t *)ept_addr; |
280 |
| - |
281 |
| - // One page for building PDPTE level |
282 |
| - ept_addr += PAGE_SIZE_4K; |
283 |
| - hpa = hax_pa(ept_addr); |
284 |
| - epte_set_entry(e, hpa, 7, EMT_NONE); |
285 |
| - e = (epte_t *)ept_addr; |
286 |
| - |
287 |
| - // The rest pages are used to build PDE level |
288 |
| - for (i = 0; i < EPT_MAX_MEM_G; i++) { |
289 |
| - ept_addr += PAGE_SIZE_4K; |
290 |
| - hpa = hax_pa(ept_addr); |
291 |
| - epte_set_entry(e + i, hpa, 7, EMT_NONE); |
292 |
| - } |
293 |
| - |
294 |
| - hax_init_list_head(&ept->ept_page_list); |
295 |
| - |
296 |
| - hax_log(HAX_LOGI, "ept_init: Calling INVEPT\n"); |
297 |
| - invept(hax_vm, EPT_INVEPT_SINGLE_CONTEXT); |
298 |
| - return 1; |
299 |
| -} |
300 |
| - |
301 |
| -// Free the whole ept structure |
302 |
| -void ept_free (hax_vm_t *hax_vm) |
303 |
| -{ |
304 |
| - struct hax_page *page, *n; |
305 |
| - struct hax_ept *ept = hax_vm->ept; |
306 |
| - |
307 |
| - hax_assert(ept); |
308 |
| - |
309 |
| - if (!ept->ept_root_page) |
310 |
| - return; |
311 |
| - |
312 |
| - hax_log(HAX_LOGI, "ept_free: Calling INVEPT\n"); |
313 |
| - invept(hax_vm, EPT_INVEPT_SINGLE_CONTEXT); |
314 |
| - hax_list_entry_for_each_safe(page, n, &ept->ept_page_list, struct hax_page, |
315 |
| - list) { |
316 |
| - hax_list_del(&page->list); |
317 |
| - hax_free_page(page); |
318 |
| - } |
319 |
| - |
320 |
| - hax_free_pages(ept->ept_root_page); |
321 |
| - hax_vfree(hax_vm->ept, sizeof(struct hax_ept)); |
322 |
| - hax_vm->ept = 0; |
323 |
| -} |
324 |
| - |
325 | 77 | struct invept_bundle {
|
326 | 78 | uint type;
|
327 | 79 | struct invept_desc *desc;
|
@@ -416,12 +168,3 @@ void invept(hax_vm_t *hax_vm, uint type)
|
416 | 168 | }
|
417 | 169 | }
|
418 | 170 | }
|
419 |
| - |
420 |
| -uint64_t vcpu_get_eptp(struct vcpu_t *vcpu) |
421 |
| -{ |
422 |
| - struct hax_ept *ept = vcpu->vm->ept; |
423 |
| - |
424 |
| - if (vcpu->mmu->mmu_mode != MMU_MODE_EPT) |
425 |
| - return INVALID_EPTP; |
426 |
| - return ept->eptp.val; |
427 |
| -} |
0 commit comments