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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vm_guest_mem.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_paging.h>
24 extern struct v3_os_hooks * os_hooks;
27 /**********************************/
29 /**********************************/
31 int v3_hva_to_hpa(addr_t hva, addr_t * hpa) {
32 if ((os_hooks) && (os_hooks)->vaddr_to_paddr) {
34 *hpa = (addr_t)(os_hooks)->vaddr_to_paddr((void *)hva);
37 PrintError("In HVA->HPA: Invalid HVA(%p)->HPA lookup\n",
42 PrintError("In HVA->HPA: os_hooks not defined\n");
49 int v3_hpa_to_hva(addr_t hpa, addr_t * hva) {
50 if ((os_hooks) && (os_hooks)->paddr_to_vaddr) {
52 *hva = (addr_t)(os_hooks)->paddr_to_vaddr((void *)hpa);
55 PrintError("In HPA->HVA: Invalid HPA(%p)->HVA lookup\n",
60 PrintError("In HPA->HVA: os_hooks not defined\n");
66 int v3_gpa_to_hpa(struct guest_info * info, addr_t gpa, addr_t * hpa) {
67 struct v3_mem_region * reg = v3_get_mem_region(info->vm_info, info->cpu_id, gpa);
70 PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (NULL REGION)\n",
75 if (reg->flags.alloced == 0) {
76 //PrintError("In GPA->HPA: Tried to translate physical address of non allocated page (addr=%p)\n",
78 //v3_print_mem_map(info->vm_info);
82 *hpa = (gpa - reg->guest_start) + reg->host_addr;
88 /* !! Currently not implemented !! */
89 // This is a scan of the shadow map
90 // For now we ignore it
92 int v3_hpa_to_gpa(struct guest_info * guest_info, addr_t hpa, addr_t * gpa) {
94 PrintError("ERROR!!! HPA->GPA currently not implemented!!!\n");
101 /**********************************/
103 /**********************************/
106 /* !! Currently not implemented !! */
107 // This will return negative until we implement hpa_to_guest_pa()
108 int v3_hva_to_gpa(struct guest_info * guest_info, addr_t hva, addr_t * gpa) {
112 if (v3_hva_to_hpa(hva, &hpa) != 0) {
113 PrintError("In HVA->GPA: Invalid HVA(%p)->HPA lookup\n",
118 if (v3_hpa_to_gpa(guest_info, hpa, gpa) != 0) {
119 PrintError("In HVA->GPA: Invalid HPA(%p)->GPA lookup\n",
130 int v3_gpa_to_hva(struct guest_info * guest_info, addr_t gpa, addr_t * hva) {
135 if (v3_gpa_to_hpa(guest_info, gpa, &hpa) != 0) {
136 // PrintError("In GPA->HVA: Invalid GPA(%p)->HPA lookup\n",
141 if (v3_hpa_to_hva(hpa, hva) != 0) {
142 PrintError("In GPA->HVA: Invalid HPA(%p)->HVA lookup\n",
151 int v3_gva_to_gpa(struct guest_info * guest_info, addr_t gva, addr_t * gpa) {
152 v3_reg_t guest_cr3 = 0;
154 if (guest_info->mem_mode == PHYSICAL_MEM) {
155 // guest virtual address is the same as the physical
160 if (guest_info->shdw_pg_mode == SHADOW_PAGING) {
161 guest_cr3 = guest_info->shdw_pg_state.guest_cr3;
163 guest_cr3 = guest_info->ctrl_regs.cr3;
167 // Guest Is in Paged mode
168 switch (guest_info->cpu_mode) {
170 if (v3_translate_guest_pt_32(guest_info, guest_cr3, gva, gpa) == -1) {
171 /*PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n",
172 (void *)gva, (void *)(addr_t)guest_cr3);*/
177 if (v3_translate_guest_pt_32pae(guest_info, guest_cr3, gva, gpa) == -1) {
178 /*PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n",
179 (void *)gva, (void *)(addr_t)guest_cr3);*/
186 if (v3_translate_guest_pt_64(guest_info, guest_cr3, gva, gpa) == -1) {
187 /*PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n",
188 (void *)gva, (void *)(addr_t)guest_cr3);*/
201 /* !! Currently not implemented !! */
202 /* This will be a real pain.... its your standard page table walker in guest memory
204 * For now we ignore it...
206 int v3_gpa_to_gva(struct guest_info * guest_info, addr_t gpa, addr_t * gva) {
208 PrintError("ERROR!!: GPA->GVA Not Implemented!!\n");
213 /**********************************/
215 /**********************************/
218 int v3_gva_to_hpa(struct guest_info * guest_info, addr_t gva, addr_t * hpa) {
223 if (v3_gva_to_gpa(guest_info, gva, &gpa) != 0) {
224 PrintError("In GVA->HPA: Invalid GVA(%p)->GPA lookup\n",
229 if (v3_gpa_to_hpa(guest_info, gpa, hpa) != 0) {
230 PrintError("In GVA->HPA: Invalid GPA(%p)->HPA lookup\n",
238 /* !! Currently not implemented !! */
239 int v3_hpa_to_gva(struct guest_info * guest_info, addr_t hpa, addr_t * gva) {
244 if (v3_hpa_to_gpa(guest_info, hpa, &gpa) != 0) {
245 PrintError("In HPA->GVA: Invalid HPA(%p)->GPA lookup\n",
250 if (v3_gpa_to_gva(guest_info, gpa, gva) != 0) {
251 PrintError("In HPA->GVA: Invalid GPA(%p)->GVA lookup\n",
262 int v3_gva_to_hva(struct guest_info * guest_info, addr_t gva, addr_t * hva) {
268 if (v3_gva_to_gpa(guest_info, gva, &gpa) != 0) {
269 /*PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n",
274 if (v3_gpa_to_hpa(guest_info, gpa, &hpa) != 0) {
275 PrintError("In GVA->HVA: Invalid GPA(%p)->HPA lookup\n",
280 if (v3_hpa_to_hva(hpa, hva) != 0) {
281 PrintError("In GVA->HVA: Invalid HPA(%p)->HVA lookup\n",
290 /* !! Currently not implemented !! */
291 int v3_hva_to_gva(struct guest_info * guest_info, addr_t hva, addr_t * gva) {
297 if (v3_hva_to_hpa(hva, &hpa) != 0) {
298 PrintError("In HVA->GVA: Invalid HVA(%p)->HPA lookup\n",
303 if (v3_hpa_to_gpa(guest_info, hpa, &gpa) != 0) {
304 PrintError("In HVA->GVA: Invalid HPA(%p)->GPA lookup\n",
309 if (v3_gpa_to_gva(guest_info, gpa, gva) != 0) {
310 PrintError("In HVA->GVA: Invalid GPA(%p)->GVA lookup\n",
320 /* KCH: currently only checks if we can perform a user-mode write
321 return 1 on success */
322 int v3_gva_can_access(struct guest_info * core, addr_t gva) {
324 v3_reg_t guest_cr3 = 0;
325 pf_error_t access_type;
326 pt_access_status_t access_status;
328 access_type.write = 1;
329 access_type.user = 1;
331 if (core->mem_mode == PHYSICAL_MEM) {
335 if (core->shdw_pg_mode == SHADOW_PAGING) {
336 guest_cr3 = core->shdw_pg_state.guest_cr3;
338 guest_cr3 = core->ctrl_regs.cr3;
341 // guest is in paged mode
342 switch (core->cpu_mode) {
344 if (v3_check_guest_pt_32(core, guest_cr3, gva, access_type, &access_status) == -1) {
349 if (v3_check_guest_pt_32pae(core, guest_cr3, gva, access_type, &access_status) == -1) {
356 if (v3_check_guest_pt_64(core, guest_cr3, gva, access_type, &access_status) == -1) {
364 if (access_status != PT_ACCESS_OK) {
373 /* This is a straight address conversion + copy,
374 * except for the tiny little issue of crossing page boundries.....
376 int v3_read_gva_memory(struct guest_info * guest_info, addr_t gva, int count, uchar_t * dest) {
383 int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
384 int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
385 addr_t host_addr = 0;
388 if (v3_gva_to_hva(guest_info, cursor, &host_addr) != 0) {
389 PrintDebug("Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
395 memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
397 bytes_read += bytes_to_copy;
398 count -= bytes_to_copy;
399 cursor += bytes_to_copy;
410 /* This is a straight address conversion + copy,
411 * except for the tiny little issue of crossing page boundries.....
413 int v3_read_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t * dest) {
418 int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
419 int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
420 addr_t host_addr = 0;
422 if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
427 PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
428 PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
429 PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
430 PrintDebug("guest_pa=0x%x\n", guest_pa);
433 memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
435 bytes_read += bytes_to_copy;
436 count -= bytes_to_copy;
437 cursor += bytes_to_copy;
446 /* This is a straight address conversion + copy,
447 * except for the tiny little issue of crossing page boundries.....
449 int v3_write_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t * src) {
451 int bytes_written = 0;
454 int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
455 int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
458 if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
459 return bytes_written;
463 memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
465 bytes_written += bytes_to_copy;
466 count -= bytes_to_copy;
467 cursor += bytes_to_copy;
470 return bytes_written;