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.


5089c5cb614b96708184af58c62b1ae09cbdef72
[palacios.git] / palacios / src / palacios / vmm_paging.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_paging.h>
21
22 #include <palacios/vmm.h>
23
24 #include <palacios/vm_guest_mem.h>
25
26
27 static pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry);
28 static pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry);
29
30 static pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry);
31 static pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry);
32 static pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry);
33
34 static pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry);
35 static pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry);
36 static pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry);
37 static pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry);
38
39
40
41
42 #define USE_VMM_PAGING_DEBUG
43 // All of the debug functions defined in vmm_paging.h are implemented in this file
44 #include "vmm_paging_debug.h"
45 #undef USE_VMM_PAGING_DEBUG
46
47
48
49 #ifndef DEBUG_SHADOW_PAGING
50 #undef PrintDebug
51 #define PrintDebug(fmt, args...)
52 #endif
53
54
55
56 void delete_page_tables_32(pde32_t * pde) {
57   int i;
58
59   if (pde == NULL) { 
60     return;
61   }
62
63   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
64     if (pde[i].present) {
65       // We double cast, first to an addr_t to handle 64 bit issues, then to the pointer
66       PrintDebug("PTE base addr %x \n", pde[i].pt_base_addr);
67       pte32_t * pte = (pte32_t *)((addr_t)(uint_t)(pde[i].pt_base_addr << PAGE_POWER));
68
69       PrintDebug("Deleting PTE %d (%p)\n", i, pte);
70       V3_FreePage(pte);
71     }
72   }
73
74   PrintDebug("Deleting PDE (%p)\n", pde);
75   V3_FreePage(V3_PAddr(pde));
76 }
77
78 void delete_page_tables_32PAE(pdpe32pae_t * pdpe) { 
79   PrintError("Unimplemented function\n");
80 }
81
82 void delete_page_tables_64(pml4e64_t * pml4) {
83   PrintError("Unimplemented function\n");
84 }
85
86
87
88
89 static int translate_pt_32_cb(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
90   addr_t * paddr = (addr_t *)private_data;
91
92   switch (type) {
93   case PAGE_PD32:
94   case PAGE_PT32:
95     return 0;
96   case PAGE_4MB:
97     *paddr = page_pa + PAGE_OFFSET_4MB(vaddr);
98     return 0;
99   case PAGE_4KB:
100     *paddr = page_pa + PAGE_OFFSET_4KB(vaddr);
101     return 0;
102   default: 
103     PrintError("Inavlid page type (%s) in tranlate pt 32 callback\n", v3_page_type_to_str(type));
104     return -1;
105   }
106 }
107
108 static int translate_pt_32pae_cb(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
109   addr_t * paddr = (addr_t *)private_data;
110   
111   switch (type) {
112   case PAGE_PDP32PAE:
113   case PAGE_PD32PAE:
114   case PAGE_PT32PAE:
115     return 0;
116   case PAGE_2MB:
117     *paddr = page_pa + PAGE_OFFSET_2MB(vaddr);
118     return 0;
119   case PAGE_4KB:
120     *paddr = page_pa + PAGE_OFFSET_4KB(vaddr);
121     return 0;
122   default:
123     PrintError("Inavlid page type (%s) in translate pt 32pae callback\n", v3_page_type_to_str(type));
124     return -1;
125   }
126 }
127
128 static int translate_pt_64_cb(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
129   addr_t * paddr = (addr_t *)private_data;
130
131   switch (type) {
132   case PAGE_PML464:
133   case PAGE_PDP64:
134   case PAGE_PD64:
135   case PAGE_PT64:
136     return 0;
137   case PAGE_1GB:
138     *paddr = page_pa + PAGE_OFFSET_1GB(vaddr);
139     return 0;
140   case PAGE_2MB:
141     *paddr = page_pa + PAGE_OFFSET_2MB(vaddr);
142     return 0;
143   case PAGE_4KB:
144     *paddr = page_pa + PAGE_OFFSET_4KB(vaddr);
145     return 0;
146   default:
147     PrintError("Inavlid page type (%s) in translate pt 64 callback\n", v3_page_type_to_str(type));
148     return -1;
149   }
150 }
151
152
153 int v3_translate_host_pt_32(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
154   return v3_drill_host_pt_32(info, host_cr3, vaddr, translate_pt_32_cb, paddr);
155 }
156 int v3_translate_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
157   return v3_drill_guest_pt_32(info, guest_cr3, vaddr, translate_pt_32_cb, paddr);
158 }
159
160
161 int v3_translate_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
162   return v3_drill_host_pt_32pae(info, host_cr3, vaddr, translate_pt_32pae_cb, paddr);
163 }
164 int v3_translate_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
165   return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, translate_pt_32pae_cb, paddr);
166 }
167
168
169 int v3_translate_host_pt_64(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
170   return v3_drill_host_pt_64(info, host_cr3, vaddr, translate_pt_64_cb, paddr);
171 }
172 int v3_translate_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
173   return v3_drill_guest_pt_64(info, guest_cr3, vaddr, translate_pt_64_cb, paddr);
174 }
175
176
177
178 struct pt_find_data {
179   page_type_t type;
180   addr_t * pt_page_ptr;
181   addr_t * pt_page_pa;
182 };
183
184 static int find_pt_cb(struct guest_info * info, page_type_t type, addr_t vaddr, 
185                       addr_t page_ptr, addr_t page_pa, void * private_data) {
186   struct pt_find_data * pt_data = (struct pt_find_data *)private_data;
187
188   PrintDebug("FIND_PT Type=%s, page_pa = %p\n",              
189              v3_page_type_to_str(type),
190              (void *)page_pa);
191
192   if (type == pt_data->type) {
193     *(pt_data->pt_page_ptr) = page_ptr;
194     *(pt_data->pt_page_pa) = page_pa;
195     return 1;
196   }
197
198   return 0;
199 }
200
201
202 int v3_find_host_pt_32_page(struct guest_info * info, v3_reg_t host_cr3, page_type_t type, addr_t vaddr, 
203                             addr_t * page_ptr, addr_t * page_pa) {
204   struct pt_find_data data;
205
206   data.type = type;
207   data.pt_page_ptr = page_ptr;
208   data.pt_page_pa = page_pa;
209   
210   return v3_drill_host_pt_32(info, host_cr3, vaddr, find_pt_cb, &data);
211 }
212
213 int v3_find_host_pt_32pae_page(struct guest_info * info, v3_reg_t host_cr3, page_type_t type, addr_t vaddr, 
214                                addr_t * page_ptr, addr_t * page_pa) {
215   struct pt_find_data data;
216
217   data.type = type;
218   data.pt_page_ptr = page_ptr;
219   data.pt_page_pa = page_pa;  
220
221   return v3_drill_host_pt_32pae(info, host_cr3, vaddr, find_pt_cb, &data);
222 }
223
224 int v3_find_host_pt_64_page(struct guest_info * info, v3_reg_t host_cr3, page_type_t type, addr_t vaddr, 
225                             addr_t * page_ptr, addr_t * page_pa) {
226   struct pt_find_data data;
227
228   data.type = type;
229   data.pt_page_ptr = page_ptr;
230   data.pt_page_pa = page_pa;
231
232   return v3_drill_host_pt_64(info, host_cr3, vaddr, find_pt_cb, &data);
233 }
234 int v3_find_guest_pt_32_page(struct guest_info * info, v3_reg_t guest_cr3, page_type_t type, addr_t vaddr, 
235                              addr_t * page_ptr, addr_t * page_pa) {
236   struct pt_find_data data;
237
238   data.type = type;
239   data.pt_page_ptr = page_ptr;
240   data.pt_page_pa = page_pa;
241   
242   return v3_drill_guest_pt_32(info, guest_cr3, vaddr, find_pt_cb, &data);
243 }
244
245 int v3_find_guest_pt_32pae_page(struct guest_info * info, v3_reg_t guest_cr3, page_type_t type, addr_t vaddr, 
246                                 addr_t * page_ptr, addr_t * page_pa) {
247   struct pt_find_data data;
248
249   data.type = type;
250   data.pt_page_ptr = page_ptr;
251   data.pt_page_pa = page_pa;
252   
253   return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, find_pt_cb, &data);
254 }
255
256 int v3_find_guest_pt_64_page(struct guest_info * info, v3_reg_t guest_cr3, page_type_t type, addr_t vaddr, 
257                              addr_t * page_ptr, addr_t * page_pa) {
258   struct pt_find_data data;
259
260   data.type = type;
261   data.pt_page_ptr = page_ptr;
262   data.pt_page_pa = page_pa;
263   
264   return v3_drill_guest_pt_64(info, guest_cr3, vaddr, find_pt_cb, &data);
265 }
266
267
268 /* 
269  *
270  * Page Table Access Checks
271  *
272  */
273
274
275 struct pt_check_data {
276   pf_error_t access_type;
277   pt_access_status_t * access_status;
278 };
279
280 static int check_pt_32_cb(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
281   struct pt_check_data * chk_data = (struct pt_check_data *)private_data;
282
283   switch (type) {
284   case PAGE_PD32:
285     *(chk_data->access_status) = v3_can_access_pde32((pde32_t *)page_ptr, vaddr, chk_data->access_type);
286     break;
287   case PAGE_PT32:
288     *(chk_data->access_status) = v3_can_access_pte32((pte32_t *)page_ptr, vaddr, chk_data->access_type);
289     break;
290   case PAGE_4MB:
291   case PAGE_4KB:
292     return 0;
293   default: 
294     PrintError("Inavlid page type (%s) in check pt 32 callback\n", v3_page_type_to_str(type));
295     return -1;
296   }
297
298   if (chk_data->access_status != PT_ACCESS_OK) {
299     return 1;
300   }
301
302   return 0;
303 }
304
305
306 static int check_pt_32pae_cb(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
307   struct pt_check_data * chk_data = (struct pt_check_data *)private_data;
308
309   switch (type) {
310   case PAGE_PDP32PAE:
311     *(chk_data->access_status) = v3_can_access_pdpe32pae((pdpe32pae_t *)page_ptr, vaddr, chk_data->access_type);
312     break;
313   case PAGE_PD32PAE:
314     *(chk_data->access_status) = v3_can_access_pde32pae((pde32pae_t *)page_ptr, vaddr, chk_data->access_type);
315     break;
316   case PAGE_PT32PAE:
317     *(chk_data->access_status) = v3_can_access_pte32pae((pte32pae_t *)page_ptr, vaddr, chk_data->access_type);
318     break;
319   case PAGE_2MB:
320   case PAGE_4KB:
321     return 0;
322   default: 
323     PrintError("Inavlid page type (%s) in check pt 32pae callback\n", v3_page_type_to_str(type));
324     return -1;
325   }
326
327   if (chk_data->access_status != PT_ACCESS_OK) {
328     return 1;
329   }
330
331   return 0;
332 }
333
334
335 static int check_pt_64_cb(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
336   struct pt_check_data * chk_data = (struct pt_check_data *)private_data;
337
338   switch (type) {
339   case PAGE_PML464:
340     *(chk_data->access_status) = v3_can_access_pml4e64((pml4e64_t *)page_ptr, vaddr, chk_data->access_type);
341     break;
342   case PAGE_PDP64:
343     *(chk_data->access_status) = v3_can_access_pdpe64((pdpe64_t *)page_ptr, vaddr, chk_data->access_type);
344     break;
345   case PAGE_PD64:
346     *(chk_data->access_status) = v3_can_access_pde64((pde64_t *)page_ptr, vaddr, chk_data->access_type);
347     break;
348   case PAGE_PT64:
349     *(chk_data->access_status) = v3_can_access_pte64((pte64_t *)page_ptr, vaddr, chk_data->access_type);
350     break;
351   case PAGE_1GB:
352   case PAGE_2MB:
353   case PAGE_4KB:
354     return 0;
355   default: 
356     PrintError("Inavlid page type (%s) in check pt 64 callback\n", v3_page_type_to_str(type));
357     return -1;
358   }
359
360   if (chk_data->access_status != PT_ACCESS_OK) {
361     return 1;
362   }
363
364   return 0;
365 }
366
367
368
369 int v3_check_host_pt_32(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) {
370   struct pt_check_data access_data;
371
372   access_data.access_type = access_type;
373   access_data.access_status = access_status;
374
375   return v3_drill_host_pt_32(info, host_cr3, vaddr, check_pt_32_cb, &access_data);
376 }
377
378 int v3_check_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) {
379   struct pt_check_data access_data;
380
381   access_data.access_type = access_type;
382   access_data.access_status = access_status;
383
384   return v3_drill_host_pt_32pae(info, host_cr3, vaddr, check_pt_32pae_cb, &access_data);
385 }
386
387
388
389 int v3_check_host_pt_64(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) {
390   struct pt_check_data access_data;
391
392   access_data.access_type = access_type;
393   access_data.access_status = access_status;
394
395   return v3_drill_host_pt_64(info, host_cr3, vaddr, check_pt_64_cb, &access_data);
396 }
397
398
399
400 int v3_check_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
401                          pf_error_t access_type, pt_access_status_t * access_status) {
402   struct pt_check_data access_data;
403
404   access_data.access_type = access_type;
405   access_data.access_status = access_status;
406
407   return v3_drill_guest_pt_32(info, guest_cr3, vaddr, check_pt_32_cb, &access_data);
408 }
409
410
411
412
413
414 int v3_check_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
415                             pf_error_t access_type, pt_access_status_t * access_status) {
416   struct pt_check_data access_data;
417
418   access_data.access_type = access_type;
419   access_data.access_status = access_status;
420
421   return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, check_pt_32pae_cb, &access_data);
422 }
423
424
425
426 int v3_check_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
427                          pf_error_t access_type, pt_access_status_t * access_status) {
428   struct pt_check_data access_data;
429
430   access_data.access_type = access_type;
431   access_data.access_status = access_status;
432
433   return v3_drill_guest_pt_64(info, guest_cr3, vaddr, check_pt_64_cb, &access_data);
434 }
435
436
437
438 /*
439  * PAGE TABLE LOOKUP FUNCTIONS
440  *
441  * The value of entry is a return type:
442  * Page not present: *entry = 0
443  */
444
445 /**
446  * 
447  *  32 bit Page Table lookup functions
448  *
449  **/
450
451 static pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
452   pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
453
454   if (!pde_entry->present) {
455     *entry = 0;
456     return PT_ENTRY_NOT_PRESENT;
457   } else if (pde_entry->large_page) {
458     pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry;
459
460     *entry = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
461
462     return PT_ENTRY_LARGE_PAGE;
463   } else {
464     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
465     return PT_ENTRY_PAGE;
466   }
467 }
468
469
470
471 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
472  */
473 static pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
474   pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
475
476   if (!pte_entry->present) {
477     *entry = 0;
478     //    PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
479     return PT_ENTRY_NOT_PRESENT;
480   } else {
481     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
482
483     return PT_ENTRY_PAGE;
484   }
485
486 }
487
488
489
490 /**
491  * 
492  *  32 bit PAE Page Table lookup functions
493  *
494  **/
495 static pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) {
496   pdpe32pae_t * pdpe_entry = &(pdp[PDPE32PAE_INDEX(addr)]);
497   
498   if (!pdpe_entry->present) {
499     *entry = 0;
500     return PT_ENTRY_NOT_PRESENT;
501   } else {
502     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
503     return PT_ENTRY_PAGE;
504   }
505 }
506
507 static pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) {
508   pde32pae_t * pde_entry = &(pd[PDE32PAE_INDEX(addr)]);
509
510   if (!pde_entry->present) {
511     *entry = 0;
512     return PT_ENTRY_NOT_PRESENT;
513   } else if (pde_entry->large_page) {
514     pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)pde_entry;
515
516     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
517
518     return PT_ENTRY_LARGE_PAGE;
519   } else {
520     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
521     return PT_ENTRY_PAGE;
522   }
523 }
524
525 static pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) {
526   pte32pae_t * pte_entry = &(pt[PTE32PAE_INDEX(addr)]);
527
528   if (!pte_entry->present) {
529     *entry = 0;
530     return PT_ENTRY_NOT_PRESENT;
531   } else {
532     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
533     return PT_ENTRY_PAGE;
534   }
535 }
536
537
538
539 /**
540  * 
541  *  64 bit Page Table lookup functions
542  *
543  **/
544 static pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) {
545   pml4e64_t * pml_entry = &(pml[PML4E64_INDEX(addr)]);
546
547   if (!pml_entry->present) {
548     *entry = 0;
549     return PT_ENTRY_NOT_PRESENT;
550   } else {
551     *entry = BASE_TO_PAGE_ADDR(pml_entry->pdp_base_addr);
552     return PT_ENTRY_PAGE;
553   }
554 }
555
556 static pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) {
557   pdpe64_t * pdpe_entry = &(pdp[PDPE64_INDEX(addr)]);
558   
559   if (!pdpe_entry->present) {
560     *entry = 0;
561     return PT_ENTRY_NOT_PRESENT;
562   } else if (pdpe_entry->large_page) {
563     PrintError("1 Gigabyte pages not supported\n");
564     V3_ASSERT(0);
565     return -1;
566   } else {
567     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
568     return PT_ENTRY_PAGE;
569   }
570 }
571
572 static pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) {
573   pde64_t * pde_entry = &(pd[PDE64_INDEX(addr)]);
574
575   if (!pde_entry->present) {
576     *entry = 0;
577     return PT_ENTRY_NOT_PRESENT;
578   } else if (pde_entry->large_page) {
579     pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry;
580
581     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
582
583     return PT_ENTRY_LARGE_PAGE;
584   } else {
585     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
586     return PT_ENTRY_PAGE;
587   }
588 }
589
590 static pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) {
591   pte64_t * pte_entry = &(pt[PTE64_INDEX(addr)]);
592
593   if (!pte_entry->present) {
594     *entry = 0;
595     return PT_ENTRY_NOT_PRESENT;
596   } else {
597     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
598     return PT_ENTRY_PAGE;
599   }
600 }
601
602
603
604
605 static pt_access_status_t can_access_pt_entry(gen_pt_t * pt, pf_error_t access_type) {
606   if (pt->present == 0) {
607     return PT_ACCESS_NOT_PRESENT;
608   } else if ((pt->writable == 0) && (access_type.write == 1)) {
609     return PT_ACCESS_WRITE_ERROR;
610   } else if ((pt->user_page == 0) && (access_type.user == 1)) {
611     // Check CR0.WP?
612     return PT_ACCESS_USER_ERROR;
613   }
614
615   return PT_ACCESS_OK;
616 }
617
618
619
620 /*
621  *   32 bit access checks
622  */
623 pt_access_status_t inline v3_can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
624   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)];
625   return can_access_pt_entry(entry, access_type);
626 }
627
628 pt_access_status_t inline v3_can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
629   gen_pt_t * entry = (gen_pt_t *)&pte[PTE32_INDEX(addr)];
630   return can_access_pt_entry(entry, access_type);
631 }
632
633
634 /*
635  *  32 bit PAE access checks
636  */
637 pt_access_status_t inline v3_can_access_pdpe32pae(pdpe32pae_t * pdpe, addr_t addr, pf_error_t access_type) {
638   gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE32PAE_INDEX(addr)];
639   return can_access_pt_entry(entry, access_type);
640 }
641
642 pt_access_status_t inline v3_can_access_pde32pae(pde32pae_t * pde, addr_t addr, pf_error_t access_type) {
643   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32PAE_INDEX(addr)];
644   return can_access_pt_entry(entry, access_type);
645 }
646
647 pt_access_status_t inline v3_can_access_pte32pae(pte32pae_t * pte, addr_t addr, pf_error_t access_type) {
648   gen_pt_t * entry = (gen_pt_t *)&pte[PTE32PAE_INDEX(addr)];
649   return can_access_pt_entry(entry, access_type);
650 }
651
652 /*
653  *   64 Bit access checks
654  */
655 pt_access_status_t inline v3_can_access_pml4e64(pml4e64_t * pmle, addr_t addr, pf_error_t access_type) {
656   gen_pt_t * entry = (gen_pt_t *)&pmle[PML4E64_INDEX(addr)];
657   return can_access_pt_entry(entry, access_type);
658 }
659
660 pt_access_status_t inline v3_can_access_pdpe64(pdpe64_t * pdpe, addr_t addr, pf_error_t access_type) {
661   gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE64_INDEX(addr)];
662   return can_access_pt_entry(entry, access_type);
663 }
664
665 pt_access_status_t inline v3_can_access_pde64(pde64_t * pde, addr_t addr, pf_error_t access_type) {
666   gen_pt_t * entry = (gen_pt_t *)&pde[PDE64_INDEX(addr)];
667   return can_access_pt_entry(entry, access_type);
668 }
669
670 pt_access_status_t inline v3_can_access_pte64(pte64_t * pte, addr_t addr, pf_error_t access_type) {
671   gen_pt_t * entry = (gen_pt_t *)&pte[PTE64_INDEX(addr)];
672   return can_access_pt_entry(entry, access_type);
673 }
674
675
676
677
678
679
680
681
682
683
684 /* We generate a page table to correspond to a given memory layout
685  * pulling pages from the mem_list when necessary
686  * If there are any gaps in the layout, we add them as unmapped pages
687  */
688 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
689   addr_t current_page_addr = 0;
690   int i, j;
691
692   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
693
694   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
695     int pte_present = 0;
696     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
697     
698
699     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
700       struct v3_shadow_region * region =  v3_get_shadow_region(guest_info, current_page_addr);
701
702       if (!region || 
703           (region->host_type == SHDW_REGION_FULL_HOOK)) {
704         pte[j].present = 0;
705         pte[j].writable = 0;
706         pte[j].user_page = 0;
707         pte[j].write_through = 0;
708         pte[j].cache_disable = 0;
709         pte[j].accessed = 0;
710         pte[j].dirty = 0;
711         pte[j].pte_attr = 0;
712         pte[j].global_page = 0;
713         pte[j].vmm_info = 0;
714         pte[j].page_base_addr = 0;
715       } else {
716         addr_t host_addr;
717         pte[j].present = 1;
718
719         if (region->host_type == SHDW_REGION_WRITE_HOOK) {
720           pte[j].writable = 0;
721           PrintDebug("Marking Write hook host_addr %p as RO\n", (void *)current_page_addr);
722         } else {
723           pte[j].writable = 1;
724         }
725           
726         pte[j].user_page = 1;
727         pte[j].write_through = 0;
728         pte[j].cache_disable = 0;
729         pte[j].accessed = 0;
730         pte[j].dirty = 0;
731         pte[j].pte_attr = 0;
732         pte[j].global_page = 0;
733         pte[j].vmm_info = 0;
734
735         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
736           // BIG ERROR
737           // PANIC
738           return NULL;
739         }
740         
741         pte[j].page_base_addr = host_addr >> 12;
742         
743         pte_present = 1;
744       }
745
746       current_page_addr += PAGE_SIZE;
747     }
748
749     if (pte_present == 0) { 
750       V3_FreePage(V3_PAddr(pte));
751
752       pde[i].present = 0;
753       pde[i].writable = 0;
754       pde[i].user_page = 0;
755       pde[i].write_through = 0;
756       pde[i].cache_disable = 0;
757       pde[i].accessed = 0;
758       pde[i].reserved = 0;
759       pde[i].large_page = 0;
760       pde[i].global_page = 0;
761       pde[i].vmm_info = 0;
762       pde[i].pt_base_addr = 0;
763     } else {
764       pde[i].present = 1;
765       pde[i].writable = 1;
766       pde[i].user_page = 1;
767       pde[i].write_through = 0;
768       pde[i].cache_disable = 0;
769       pde[i].accessed = 0;
770       pde[i].reserved = 0;
771       pde[i].large_page = 0;
772       pde[i].global_page = 0;
773       pde[i].vmm_info = 0;
774       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
775     }
776
777   }
778
779   return pde;
780 }
781
782
783 /* We generate a page table to correspond to a given memory layout
784  * pulling pages from the mem_list when necessary
785  * If there are any gaps in the layout, we add them as unmapped pages
786  */
787 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
788   addr_t current_page_addr = 0;
789   int i, j, k;
790
791   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
792   memset(pdpe, 0, PAGE_SIZE);
793
794   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
795     int pde_present = 0;
796     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
797
798     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
799
800
801       int pte_present = 0;
802       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
803       
804       
805       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
806         struct v3_shadow_region * region = v3_get_shadow_region(guest_info, current_page_addr);
807         
808         if (!region || 
809             (region->host_type == SHDW_REGION_FULL_HOOK)) {
810           pte[k].present = 0;
811           pte[k].writable = 0;
812           pte[k].user_page = 0;
813           pte[k].write_through = 0;
814           pte[k].cache_disable = 0;
815           pte[k].accessed = 0;
816           pte[k].dirty = 0;
817           pte[k].pte_attr = 0;
818           pte[k].global_page = 0;
819           pte[k].vmm_info = 0;
820           pte[k].page_base_addr = 0;
821           pte[k].rsvd = 0;
822         } else {
823           addr_t host_addr;
824           pte[k].present = 1;
825         
826           if (region->host_type == SHDW_REGION_WRITE_HOOK) {
827             pte[k].writable = 0;
828           } else {
829             pte[k].writable = 1;
830           }
831
832           pte[k].user_page = 1;
833           pte[k].write_through = 0;
834           pte[k].cache_disable = 0;
835           pte[k].accessed = 0;
836           pte[k].dirty = 0;
837           pte[k].pte_attr = 0;
838           pte[k].global_page = 0;
839           pte[k].vmm_info = 0;
840           
841           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
842             // BIG ERROR
843             // PANIC
844             return NULL;
845           }
846           
847           pte[k].page_base_addr = host_addr >> 12;
848           pte[k].rsvd = 0;
849
850           pte_present = 1;
851         }
852         
853         current_page_addr += PAGE_SIZE;
854       }
855       
856       if (pte_present == 0) { 
857         V3_FreePage(V3_PAddr(pte));
858         
859         pde[j].present = 0;
860         pde[j].writable = 0;
861         pde[j].user_page = 0;
862         pde[j].write_through = 0;
863         pde[j].cache_disable = 0;
864         pde[j].accessed = 0;
865         pde[j].avail = 0;
866         pde[j].large_page = 0;
867         pde[j].global_page = 0;
868         pde[j].vmm_info = 0;
869         pde[j].pt_base_addr = 0;
870         pde[j].rsvd = 0;
871       } else {
872         pde[j].present = 1;
873         pde[j].writable = 1;
874         pde[j].user_page = 1;
875         pde[j].write_through = 0;
876         pde[j].cache_disable = 0;
877         pde[j].accessed = 0;
878         pde[j].avail = 0;
879         pde[j].large_page = 0;
880         pde[j].global_page = 0;
881         pde[j].vmm_info = 0;
882         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
883         pde[j].rsvd = 0;
884
885         pde_present = 1;
886       }
887       
888     }
889     
890     if (pde_present == 0) { 
891       V3_FreePage(V3_PAddr(pde));
892       
893       pdpe[i].present = 0;
894       pdpe[i].rsvd = 0;
895       pdpe[i].write_through = 0;
896       pdpe[i].cache_disable = 0;
897       pdpe[i].accessed = 0;
898       pdpe[i].avail = 0;
899       pdpe[i].rsvd2 = 0;
900       pdpe[i].vmm_info = 0;
901       pdpe[i].pd_base_addr = 0;
902       pdpe[i].rsvd3 = 0;
903     } else {
904       pdpe[i].present = 1;
905       pdpe[i].rsvd = 0;
906       pdpe[i].write_through = 0;
907       pdpe[i].cache_disable = 0;
908       pdpe[i].accessed = 0;
909       pdpe[i].avail = 0;
910       pdpe[i].rsvd2 = 0;
911       pdpe[i].vmm_info = 0;
912       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
913       pdpe[i].rsvd3 = 0;
914     }
915     
916   }
917
918
919   return pdpe;
920 }
921
922
923
924
925
926
927 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
928   addr_t current_page_addr = 0;
929   int i, j, k, m;
930   
931   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
932
933   for (i = 0; i < 1; i++) {
934     int pdpe_present = 0;
935     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
936
937     for (j = 0; j < 20; j++) {
938       int pde_present = 0;
939       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
940
941       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
942         int pte_present = 0;
943         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
944
945
946         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
947           struct v3_shadow_region * region = v3_get_shadow_region(info, current_page_addr);
948           
949
950           
951           if (!region || 
952               (region->host_type == SHDW_REGION_FULL_HOOK)) {
953             pte[m].present = 0;
954             pte[m].writable = 0;
955             pte[m].user_page = 0;
956             pte[m].write_through = 0;
957             pte[m].cache_disable = 0;
958             pte[m].accessed = 0;
959             pte[m].dirty = 0;
960             pte[m].pte_attr = 0;
961             pte[m].global_page = 0;
962             pte[m].vmm_info = 0;
963             pte[m].page_base_addr = 0;
964           } else {
965             addr_t host_addr;
966             pte[m].present = 1;
967
968             if (region->host_type == SHDW_REGION_WRITE_HOOK) {
969               pte[m].writable = 0;
970             } else {
971               pte[m].writable = 1;
972             }
973         
974             pte[m].user_page = 1;
975             pte[m].write_through = 0;
976             pte[m].cache_disable = 0;
977             pte[m].accessed = 0;
978             pte[m].dirty = 0;
979             pte[m].pte_attr = 0;
980             pte[m].global_page = 0;
981             pte[m].vmm_info = 0;
982             
983             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
984               // BIG ERROR
985               // PANIC
986               return NULL;
987             }
988
989             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
990
991             //PrintPTE64(current_page_addr, &(pte[m]));
992
993             pte_present = 1;      
994           }
995
996
997
998
999           current_page_addr += PAGE_SIZE;
1000         }
1001         
1002         if (pte_present == 0) {
1003           V3_FreePage(V3_PAddr(pte));
1004
1005           pde[k].present = 0;
1006           pde[k].writable = 0;
1007           pde[k].user_page = 0;
1008           pde[k].write_through = 0;
1009           pde[k].cache_disable = 0;
1010           pde[k].accessed = 0;
1011           pde[k].avail = 0;
1012           pde[k].large_page = 0;
1013           //pde[k].global_page = 0;
1014           pde[k].vmm_info = 0;
1015           pde[k].pt_base_addr = 0;
1016         } else {
1017           pde[k].present = 1;
1018           pde[k].writable = 1;
1019           pde[k].user_page = 1;
1020           pde[k].write_through = 0;
1021           pde[k].cache_disable = 0;
1022           pde[k].accessed = 0;
1023           pde[k].avail = 0;
1024           pde[k].large_page = 0;
1025           //pde[k].global_page = 0;
1026           pde[k].vmm_info = 0;
1027           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
1028
1029           pde_present = 1;
1030         }
1031       }
1032
1033       if (pde_present == 0) {
1034         V3_FreePage(V3_PAddr(pde));
1035         
1036         pdpe[j].present = 0;
1037         pdpe[j].writable = 0;
1038         pdpe[j].user_page = 0;
1039         pdpe[j].write_through = 0;
1040         pdpe[j].cache_disable = 0;
1041         pdpe[j].accessed = 0;
1042         pdpe[j].avail = 0;
1043         pdpe[j].large_page = 0;
1044         //pdpe[j].global_page = 0;
1045         pdpe[j].vmm_info = 0;
1046         pdpe[j].pd_base_addr = 0;
1047       } else {
1048         pdpe[j].present = 1;
1049         pdpe[j].writable = 1;
1050         pdpe[j].user_page = 1;
1051         pdpe[j].write_through = 0;
1052         pdpe[j].cache_disable = 0;
1053         pdpe[j].accessed = 0;
1054         pdpe[j].avail = 0;
1055         pdpe[j].large_page = 0;
1056         //pdpe[j].global_page = 0;
1057         pdpe[j].vmm_info = 0;
1058         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
1059
1060
1061         pdpe_present = 1;
1062       }
1063
1064     }
1065
1066     PrintDebug("PML index=%d\n", i);
1067
1068     if (pdpe_present == 0) {
1069       V3_FreePage(V3_PAddr(pdpe));
1070       
1071       pml[i].present = 0;
1072       pml[i].writable = 0;
1073       pml[i].user_page = 0;
1074       pml[i].write_through = 0;
1075       pml[i].cache_disable = 0;
1076       pml[i].accessed = 0;
1077       pml[i].reserved = 0;
1078       //pml[i].large_page = 0;
1079       //pml[i].global_page = 0;
1080       pml[i].vmm_info = 0;
1081       pml[i].pdp_base_addr = 0;
1082     } else {
1083       pml[i].present = 1;
1084       pml[i].writable = 1;
1085       pml[i].user_page = 1;
1086       pml[i].write_through = 0;
1087       pml[i].cache_disable = 0;
1088       pml[i].accessed = 0;
1089       pml[i].reserved = 0;
1090       //pml[i].large_page = 0;
1091       //pml[i].global_page = 0;
1092       pml[i].vmm_info = 0;
1093       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
1094     }
1095   }
1096
1097   return pml;
1098 }
1099
1100
1101 int v3_drill_host_pt_32(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, 
1102                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1103                         void * private_data) {
1104   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1105   addr_t host_pde_pa = CR3_TO_PDE32_PA(host_cr3);
1106   addr_t host_pte_pa = 0;
1107   addr_t page_pa = 0;
1108   int ret;
1109
1110   if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)host_pde, host_pde_pa, private_data)) != 0) {
1111     return (ret == -1) ? -1 : PAGE_PD32;
1112   }
1113
1114   switch (pde32_lookup(host_pde, vaddr, &host_pte_pa)) {
1115   case PT_ENTRY_NOT_PRESENT:
1116     return -1;
1117   case PT_ENTRY_LARGE_PAGE:
1118     if ((ret == callback(info, PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1119       return (ret == -1) ? -1 : PAGE_4MB;
1120     }
1121     return 0;
1122   case PT_ENTRY_PAGE:
1123     if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1124       return (ret == -1) ? -1 : PAGE_PT32;
1125     }
1126     
1127     if (pte32_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1128       return -1;
1129     } else {
1130       if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1131         return (ret == -1) ? -1 : PAGE_4KB;
1132       }
1133       return 0;
1134     }
1135   }
1136   return -1;
1137 }
1138
1139
1140
1141 int v3_drill_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr,
1142                            int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1143                            void * private_data) {
1144   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1145   addr_t host_pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1146   addr_t host_pde_pa = 0;
1147   addr_t host_pte_pa = 0;
1148   addr_t page_pa = 0;
1149   int ret;
1150
1151   if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, host_pdpe_pa, private_data)) != 0) {
1152     return (ret == -1) ? -1 : PAGE_PDP32PAE;
1153   }
1154
1155   switch (pdpe32pae_lookup(host_pdpe, vaddr, &host_pde_pa)) {
1156   case PT_ENTRY_NOT_PRESENT:
1157     return -1;
1158   case PT_ENTRY_PAGE:
1159
1160     if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) {
1161       return (ret == -1) ? -1 : PAGE_PD32PAE;
1162     }
1163       
1164     switch (pde32pae_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
1165     case PT_ENTRY_NOT_PRESENT:
1166       return -1;
1167     case PT_ENTRY_LARGE_PAGE:
1168       if ((ret == callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1169         return (ret == -1) ? -1 : PAGE_2MB;
1170       }
1171       return 0;
1172     case PT_ENTRY_PAGE:
1173       if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1174         return (ret == -1) ? -1 : PAGE_PT32PAE;
1175       }
1176
1177       if (pte32pae_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1178         return -1;
1179       } else {
1180         if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1181           return (ret == -1) ? -1 : PAGE_4KB;
1182         }
1183         return 0;
1184       } 
1185     }
1186   default:
1187     return -1;
1188   }
1189
1190   // should never get here
1191   return -1;
1192 }
1193
1194
1195 int v3_drill_host_pt_64(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr,
1196                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1197                         void * private_data) {
1198   pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1199   addr_t host_pmle_pa = CR3_TO_PML4E64_PA(host_cr3);
1200   addr_t host_pdpe_pa = 0;
1201   addr_t host_pde_pa = 0;
1202   addr_t host_pte_pa = 0;
1203   addr_t page_pa = 0;
1204   int ret;
1205
1206   if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)host_pmle, host_pmle_pa, private_data)) != 0) {
1207     return (ret == -1) ? -1 : PAGE_PML464;
1208   }
1209
1210   switch(pml4e64_lookup(host_pmle, vaddr, &host_pdpe_pa)) {
1211   case PT_ENTRY_NOT_PRESENT:
1212     return -1;
1213   case PT_ENTRY_PAGE:
1214
1215     if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)V3_VAddr((void *)host_pdpe_pa), host_pdpe_pa, private_data)) != 0) {
1216       return (ret == -1) ? -1 : PAGE_PDP64;
1217     }
1218
1219     switch(pdpe64_lookup(V3_VAddr((void *)host_pdpe_pa), vaddr, &host_pde_pa)) {
1220     case PT_ENTRY_NOT_PRESENT:
1221       return -1;
1222     case PT_ENTRY_LARGE_PAGE:
1223       if ((ret == callback(info, PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) {
1224         return (ret == -1) ? -1 : PAGE_1GB;
1225       }
1226       PrintError("1 Gigabyte Pages not supported\n");
1227       return 0;
1228     case PT_ENTRY_PAGE:
1229
1230       if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) {
1231         return (ret == -1) ? -1 : PAGE_PD64;
1232       }
1233
1234       switch (pde64_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
1235       case PT_ENTRY_NOT_PRESENT:
1236         return -1;
1237       case PT_ENTRY_LARGE_PAGE:
1238         if ((ret == callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1239           return (ret == -1) ? -1 : PAGE_2MB;
1240         }
1241         return 0;
1242       case PT_ENTRY_PAGE:
1243
1244         if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1245           return (ret == -1) ? -1 : PAGE_PT64;
1246         }
1247
1248         if (pte64_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1249           return -1;
1250         } else {
1251           if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1252             return (ret == -1) ? -1 : PAGE_4KB;
1253           }
1254           return 0;
1255         }
1256       }
1257     }
1258   default:
1259     return -1;
1260   }
1261   // should never get here
1262   return -1;
1263 }
1264
1265
1266
1267
1268
1269
1270
1271 int v3_drill_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1272                          int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1273                          void * private_data) {
1274   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1275   pde32_t * guest_pde = NULL;
1276   addr_t guest_pte_pa = 0;
1277   int ret; 
1278   
1279
1280   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1281     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1282                (void *)guest_pde_pa);
1283     return -1;
1284   }
1285   
1286   if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1287     return (ret == -1) ? -1 : PAGE_PD32;
1288   }
1289   
1290   switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1291   case PT_ENTRY_NOT_PRESENT:
1292     return -1;
1293   case PT_ENTRY_LARGE_PAGE:
1294     {
1295       addr_t large_page_pa = (addr_t)guest_pte_pa;
1296       addr_t large_page_va = 0;
1297       
1298       if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1299         PrintError("Could not get virtual address of Guest Page 4MB (PA=%p)\n", 
1300                    (void *)large_page_va);
1301         return -1;
1302       }
1303
1304
1305       if ((ret == callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1306         return (ret == -1) ? -1 : PAGE_4MB;
1307       }
1308       return 0;
1309     }
1310   case PT_ENTRY_PAGE:
1311     {
1312       pte32_t * guest_pte = NULL;
1313       addr_t page_pa;
1314
1315       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
1316         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1317                    (void *)guest_pte_pa);
1318         return -1;
1319       }
1320
1321       if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1322         return (ret == -1) ? -1 : PAGE_PT32;
1323       }
1324
1325       if (pte32_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1326         return -1;
1327       } else {
1328         addr_t page_va;
1329
1330         if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1331           PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1332                      (void *)page_pa);
1333           return -1;
1334         }
1335
1336         if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1337           return (ret == -1) ? -1 : PAGE_4KB;
1338         }
1339         return 0;
1340       }
1341     }
1342   }
1343
1344   // should never get here
1345   PrintError("End of drill function (guest 32)... Should never have gotten here...\n");
1346   return -1;
1347 }
1348
1349
1350
1351 int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr,
1352                                 int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1353                                 void * private_data) {                  
1354   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1355   pdpe32pae_t * guest_pdpe = 0;
1356   addr_t guest_pde_pa = 0;
1357   int ret = 0;
1358
1359   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
1360     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
1361                (void *)guest_pdpe_pa);
1362     return -1;
1363   }
1364
1365   if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1366     return (ret == -1) ? -1 : PAGE_PDP32PAE;
1367   }
1368
1369   switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
1370     {
1371     case PT_ENTRY_NOT_PRESENT:
1372       return -1;
1373     case PT_ENTRY_PAGE:
1374       {
1375         pde32pae_t * guest_pde = NULL;
1376         addr_t guest_pte_pa = 0;
1377         
1378         if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1379           PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
1380                      (void *)guest_pde_pa);
1381           return -1;
1382         }
1383
1384         if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1385           return (ret == -1) ? -1 : PAGE_PD32PAE;
1386         }
1387         
1388         switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
1389           {
1390           case PT_ENTRY_NOT_PRESENT:
1391             return -1;
1392           case PT_ENTRY_LARGE_PAGE:
1393             {
1394               addr_t large_page_pa = (addr_t)guest_pte_pa;
1395               addr_t large_page_va = 0;
1396               
1397               if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1398                 PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", 
1399                            (void *)large_page_va);
1400
1401               }
1402               
1403               if ((ret == callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1404                 return (ret == -1) ? -1 : PAGE_2MB;
1405               }
1406               return 0;
1407             }
1408           case PT_ENTRY_PAGE:
1409             {
1410               pte32pae_t * guest_pte = NULL;
1411               addr_t page_pa;
1412
1413               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1414                 PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
1415                            (void *)guest_pte_pa);
1416                 return -1;
1417               }
1418
1419               if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1420                 return (ret == -1) ? -1 : PAGE_PT32PAE;
1421               }
1422
1423               if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1424                 return -1;
1425               } else {
1426                 addr_t page_va;
1427                 
1428                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1429                   PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1430                              (void *)page_pa);
1431                   return -1;
1432                 }
1433                 
1434                 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1435                   return (ret == -1) ? -1 : PAGE_4KB;
1436                 }
1437                 return 0;
1438               }
1439             }
1440           }
1441       }
1442     default:
1443       PrintError("Invalid page type for PD32PAE\n");
1444       return -1;
1445     }
1446
1447   // should never get here
1448   PrintError("End of drill function (guest 32pae)... Should never have gotten here...\n");
1449   return -1;
1450 }
1451
1452 int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1453                                 int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1454                                 void * private_data) {  
1455   addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
1456   pml4e64_t * guest_pmle = 0;
1457   addr_t guest_pdpe_pa = 0;
1458   int ret = 0;
1459
1460   if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
1461     PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
1462                (void *)guest_pml4_pa);
1463     return -1;
1464   }
1465   
1466   if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pmle, guest_pml4_pa, private_data)) != 0) {
1467     return (ret == -1) ? -1 : PAGE_PML464;
1468   }
1469
1470   switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
1471   case PT_ENTRY_NOT_PRESENT:
1472     return -1;
1473   case PT_ENTRY_PAGE:
1474     {
1475       pdpe64_t * guest_pdp = NULL;
1476       addr_t guest_pde_pa = 0;
1477
1478       if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
1479         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1480                    (void *)guest_pdpe_pa);
1481         return -1;
1482       }
1483
1484       if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)guest_pdp, guest_pdpe_pa, private_data)) != 0) {
1485         return (ret == -1) ? -1 : PAGE_PDP64;
1486       }
1487
1488       switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
1489       case PT_ENTRY_NOT_PRESENT:
1490         return -1;
1491       case PT_ENTRY_LARGE_PAGE:
1492         {
1493           addr_t large_page_pa = (addr_t)guest_pde_pa;
1494           addr_t large_page_va = 0;
1495           
1496           if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1497             PrintDebug("Could not get virtual address of Guest Page 1GB (PA=%p)\n", 
1498                        (void *)large_page_va);
1499             
1500           }
1501           
1502           if ((ret == callback(info, PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1503             return (ret == -1) ? -1 : PAGE_1GB;
1504           }
1505           PrintError("1 Gigabyte Pages not supported\n");
1506           return 0;
1507         }
1508       case PT_ENTRY_PAGE:
1509         {
1510           pde64_t * guest_pde = NULL;
1511           addr_t guest_pte_pa = 0;
1512
1513           if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1514             PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
1515                        (void *)guest_pde_pa);
1516             return -1;
1517           }
1518         
1519           if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1520             return (ret == -1) ? -1 : PAGE_PD64;
1521           }
1522
1523           switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1524           case PT_ENTRY_NOT_PRESENT:
1525             return -1;
1526           case PT_ENTRY_LARGE_PAGE:
1527             {
1528               addr_t large_page_pa = (addr_t)guest_pte_pa;
1529               addr_t large_page_va = 0;
1530               
1531               if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1532                 PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", 
1533                            (void *)large_page_va);
1534
1535               }
1536               
1537               if ((ret == callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1538                 return (ret == -1) ? -1 : PAGE_2MB;
1539               }
1540               return 0;
1541             }
1542           case PT_ENTRY_PAGE:
1543             {
1544               pte64_t * guest_pte = NULL;
1545               addr_t page_pa;
1546               
1547               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1548                 PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
1549                            (void *)guest_pte_pa);
1550                 return -1;
1551               }
1552
1553               if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1554                 return (ret == -1) ? -1 : PAGE_PT64;
1555               }
1556                 
1557               if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1558                 return -1;
1559               } else {
1560                 addr_t page_va;
1561                 
1562                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1563                   PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1564                              (void *)page_pa);
1565                   return -1;
1566                 }
1567                 
1568                 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1569                   return (ret == -1) ? -1 : PAGE_4KB;
1570                 }
1571
1572                 return 0;
1573               }
1574             }
1575           }
1576         }
1577       }
1578     }
1579   default:
1580     return -1;
1581   }
1582
1583   // should never get here
1584   PrintError("End of drill function (guest 64)... Should never have gotten here...\n");
1585   return -1;
1586 }
1587
1588
1589
1590
1591 int v3_walk_guest_pt_32(struct guest_info * info,  v3_reg_t guest_cr3,
1592                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1593                         void * private_data) {
1594   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1595   pde32_t * guest_pde = NULL;
1596   int i, j;
1597   addr_t vaddr = 0;
1598   int ret = 0;
1599
1600   if (!callback) {
1601     PrintError("Call back was not specified\n");
1602     return -1;
1603   }
1604
1605   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1606     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1607                (void *)guest_pde_pa);
1608     return -1;
1609   }
1610
1611   if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1612     return ret;
1613   }
1614
1615   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1616     if (guest_pde[i].present) {
1617       if (guest_pde[i].large_page) {
1618         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(guest_pde[i]);
1619         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1620         addr_t large_page_va = 0;
1621
1622         if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1623           PrintDebug("Could not get virtual address of Guest 4MB Page (PA=%p)\n", 
1624                      (void *)large_page_pa);
1625           // We'll let it through for data pages because they may be unmapped or hooked
1626           large_page_va = 0;
1627         }
1628
1629         if ((ret = callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1630           return ret;
1631         }
1632
1633         vaddr += PAGE_SIZE_4MB;
1634       } else {
1635         addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1636         pte32_t * tmp_pte = NULL;
1637
1638         if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1639           PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1640                      (void *)pte_pa);
1641           return -1;
1642         }
1643
1644         if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1645           return ret;
1646         }
1647
1648         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1649           if (tmp_pte[j].present) {
1650             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1651             addr_t page_va = 0;
1652
1653             if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1654               PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1655                  (void *)page_pa);
1656               // We'll let it through for data pages because they may be unmapped or hooked
1657               page_va = 0;
1658             }
1659             
1660             if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1661               return ret;
1662             }
1663           }
1664
1665           vaddr += PAGE_SIZE_4KB;
1666         }
1667       }
1668     } else {
1669       vaddr += PAGE_SIZE_4MB;
1670     }
1671   }
1672   return 0;
1673 }
1674
1675
1676 int v3_walk_guest_pt_32pae(struct guest_info * info,  v3_reg_t guest_cr3,
1677                            int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1678                            void * private_data) {
1679   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1680   pdpe32pae_t * guest_pdpe = NULL;
1681   int i, j, k;
1682   addr_t vaddr = 0;
1683   int ret = 0;
1684
1685   if (!callback) {
1686     PrintError("Call back was not specified\n");
1687     return -1;
1688   }
1689
1690   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdpe) == -1) {
1691     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", 
1692                (void *)guest_pdpe_pa);
1693     return -1;
1694   }
1695
1696   
1697   if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1698     return ret;
1699   }
1700
1701   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1702     if (guest_pdpe[i].present) {
1703       addr_t pde_pa = BASE_TO_PAGE_ADDR(guest_pdpe[i].pd_base_addr);
1704       pde32pae_t * tmp_pde = NULL;
1705
1706       if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1707         PrintError("Could not get virtual address of Guest PDE32PAE (PA=%p)\n", 
1708                    (void *)pde_pa);
1709         return -1;
1710       }
1711
1712       if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1713         return ret;
1714       }
1715       
1716       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1717         if (tmp_pde[j].present) {
1718           if (tmp_pde[j].large_page) {
1719             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1720             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1721             addr_t large_page_va = 0;
1722             
1723             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1724               PrintDebug("Could not get virtual address of Guest 2MB Page (PA=%p)\n", 
1725                          (void *)large_page_pa);
1726               // We'll let it through for data pages because they may be unmapped or hooked
1727               large_page_va = 0;
1728             }
1729             
1730             if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1731               return ret;
1732             }
1733
1734             vaddr += PAGE_SIZE_2MB;
1735           } else {
1736             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1737             pte32pae_t * tmp_pte = NULL;
1738             
1739             if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1740               PrintError("Could not get virtual address of Guest PTE32PAE (PA=%p)\n", 
1741                          (void *)pte_pa);
1742               return -1;
1743             }
1744             
1745             if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1746               return ret;
1747             }
1748             
1749             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1750               if (tmp_pte[k].present) {
1751                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1752                 addr_t page_va = 0;
1753                 
1754                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1755                   PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1756                              (void *)page_pa);
1757                   // We'll let it through for data pages because they may be unmapped or hooked
1758                   page_va = 0;
1759                 }
1760                 
1761                 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1762                   return ret;
1763                 }
1764               }
1765               
1766               vaddr += PAGE_SIZE_4KB;
1767             }
1768           }
1769         } else {
1770           vaddr += PAGE_SIZE_2MB;
1771         }
1772       }
1773     } else {
1774       vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1775     }
1776   }
1777   return 0;
1778 }
1779
1780
1781
1782
1783 int v3_walk_guest_pt_64(struct guest_info * info,  v3_reg_t guest_cr3,
1784                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1785                         void * private_data) {
1786   addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3);
1787   pml4e64_t * guest_pml = NULL;
1788   int i, j, k, m;
1789   addr_t vaddr = 0;
1790   int ret = 0;
1791
1792   if (!callback) {
1793     PrintError("Call back was not specified\n");
1794     return -1;
1795   }
1796
1797   if (guest_pa_to_host_va(info, guest_pml_pa, (addr_t *)&guest_pml) == -1) {
1798     PrintError("Could not get virtual address of Guest PML464 (PA=%p)\n", 
1799                (void *)guest_pml);
1800     return -1;
1801   }
1802
1803
1804   if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data)) != 0) {
1805     return ret;
1806   }
1807
1808   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1809     if (guest_pml[i].present) {
1810       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(guest_pml[i].pdp_base_addr);
1811       pdpe64_t * tmp_pdpe = NULL;
1812       
1813       
1814       if (guest_pa_to_host_va(info, pdpe_pa, (addr_t *)&tmp_pdpe) == -1) {
1815         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1816                    (void *)pdpe_pa);
1817         return -1;
1818       }
1819       
1820       if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
1821         return ret;
1822       }
1823       
1824       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1825         if (tmp_pdpe[j].present) {
1826           if (tmp_pdpe[j].large_page) {
1827             pdpe64_1GB_t * large_pdpe = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1828             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdpe->page_base_addr);
1829             addr_t large_page_va = 0;
1830
1831             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1832               PrintDebug("Could not get virtual address of Guest 1GB page (PA=%p)\n", 
1833                          (void *)large_page_pa);
1834               // We'll let it through for data pages because they may be unmapped or hooked
1835               large_page_va = 0;
1836             }
1837
1838             if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data)) != 0) {
1839               return ret;
1840             }
1841
1842             vaddr += PAGE_SIZE_1GB;
1843           } else {
1844             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1845             pde64_t * tmp_pde = NULL;
1846             
1847             if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1848               PrintError("Could not get virtual address of Guest PDE64 (PA=%p)\n", 
1849                          (void *)pde_pa);
1850               return -1;
1851             }
1852             
1853             if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1854               return ret;
1855             }
1856             
1857             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1858               if (tmp_pde[k].present) {
1859                 if (tmp_pde[k].large_page) {
1860                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1861                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1862                   addr_t large_page_va = 0;
1863                   
1864                   if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1865                     PrintDebug("Could not get virtual address of Guest 2MB page (PA=%p)\n", 
1866                                (void *)large_page_pa);
1867                     // We'll let it through for data pages because they may be unmapped or hooked
1868                     large_page_va = 0;
1869                   }
1870                   
1871                   if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1872                     return ret;
1873                   }
1874
1875                   vaddr += PAGE_SIZE_2MB;
1876                 } else {
1877                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1878                   pte64_t * tmp_pte = NULL;
1879                   
1880                   if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1881                     PrintError("Could not get virtual address of Guest PTE64 (PA=%p)\n", 
1882                                (void *)pte_pa);
1883                     return -1;
1884                   }
1885                   
1886                   if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1887                     return ret;
1888                   }
1889                   
1890                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1891                     if (tmp_pte[m].present) {
1892                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1893                       addr_t page_va = 0;
1894                       
1895                       if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1896                         PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1897                                    (void *)page_pa);
1898                         // We'll let it through for data pages because they may be unmapped or hooked
1899                         page_va = 0;
1900                       }
1901                       
1902                       if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1903                         return ret;
1904                       }
1905                     }
1906
1907                     vaddr += PAGE_SIZE_4KB;
1908                   }
1909                 }
1910               } else {
1911                 vaddr += PAGE_SIZE_2MB;
1912               }
1913             }
1914           }
1915         } else {
1916           vaddr += PAGE_SIZE_1GB;
1917         }
1918       }
1919     } else {
1920       vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES);
1921     }
1922   }
1923   return 0;
1924 }
1925
1926 int v3_walk_host_pt_32(struct guest_info * info, v3_reg_t host_cr3,
1927                        int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1928                        void * private_data) {
1929   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1930   addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3);
1931   int i, j;
1932   addr_t vaddr = 0;
1933   int ret = 0;
1934
1935   if (!callback) {
1936     PrintError("Call back was not specified\n");
1937     return -1;
1938   }
1939
1940   if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data)) != 0) {
1941     return ret;
1942   }
1943
1944   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1945     if (host_pde[i].present) {
1946       if (host_pde[i].large_page) {
1947         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]);
1948         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1949
1950         if ((ret = callback(info, PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1951           return ret;
1952         }
1953
1954         vaddr += PAGE_SIZE_4MB;
1955       } else {
1956         addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr);
1957         pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa);
1958
1959         if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1960           return ret;
1961         }
1962
1963         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1964           if (tmp_pte[j].present) {
1965             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1966             if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1967               return ret;
1968             }
1969           }
1970
1971           vaddr += PAGE_SIZE_4KB;
1972         }
1973       }
1974     } else {
1975       vaddr += PAGE_SIZE_4MB;
1976     }
1977   }
1978   return 0;
1979 }
1980
1981
1982
1983
1984
1985 int v3_walk_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3,
1986                           int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1987                           void * private_data) {
1988   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1989   addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1990   int i, j, k;
1991   addr_t vaddr = 0;
1992   int ret = 0;
1993
1994   if (!callback) {
1995     PrintError("Callback was not specified\n");
1996     return -1;
1997   }
1998   
1999   if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data)) != 0) {
2000     return ret;
2001   }
2002   
2003   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
2004     if (host_pdpe[i].present) { 
2005       addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr);
2006       pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa);
2007       
2008       if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
2009         return ret;
2010       }
2011       
2012       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
2013         if (tmp_pde[j].present) {
2014           
2015           if (tmp_pde[j].large_page) {
2016             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
2017             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
2018
2019             if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
2020               return ret;
2021             }
2022
2023             vaddr += PAGE_SIZE_2MB;
2024           } else {
2025             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
2026             pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa);
2027             
2028             if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
2029               return ret;
2030             }
2031             
2032             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
2033               if (tmp_pte[k].present) {
2034                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
2035                 if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
2036                   return ret;
2037                 }
2038               }
2039
2040               vaddr += PAGE_SIZE_4KB;
2041             }
2042           }
2043         } else {
2044           vaddr += PAGE_SIZE_2MB;
2045         }
2046       }
2047     } else {
2048       vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
2049     }
2050   }
2051   return 0;
2052 }
2053                         
2054
2055 int v3_walk_host_pt_64(struct guest_info * info, v3_reg_t host_cr3,
2056                        int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
2057                        void * private_data) {
2058   pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
2059   addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3);
2060   int i, j, k, m;
2061   addr_t vaddr = 0;
2062   int ret = 0;
2063
2064   if (!callback) {
2065     PrintError("Callback was not specified\n");
2066     return -1;
2067   }
2068
2069   if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data)) != 0) {
2070     return ret;
2071   }
2072
2073   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
2074     if (host_pml[i].present) {
2075       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr);
2076       pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa);
2077
2078       if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
2079         return ret;
2080       }
2081
2082       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
2083         if (tmp_pdpe[j].present) {
2084           if (tmp_pdpe[j].large_page) {
2085             pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
2086             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
2087
2088             if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
2089               return ret;
2090             }
2091
2092             vaddr += PAGE_SIZE_1GB;
2093           } else {
2094             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
2095             pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa);
2096
2097             if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
2098               return ret;
2099             }
2100
2101             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
2102               if (tmp_pde[k].present) {
2103                 if (tmp_pde[k].large_page) {
2104                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
2105                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
2106                   
2107                   if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
2108                     return ret;
2109                   }
2110                   
2111                   vaddr += PAGE_SIZE_2MB;
2112                 } else {
2113                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
2114                   pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa);
2115
2116                   if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
2117                     return ret;
2118                   }
2119
2120                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
2121                     if (tmp_pte[m].present) {
2122                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
2123                       if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
2124                         return ret;
2125                       }
2126                     }
2127                     vaddr += PAGE_SIZE_4KB;
2128                   }
2129                 }
2130               } else {
2131                 vaddr += PAGE_SIZE_2MB;
2132               }
2133             }
2134           }
2135         } else {
2136           vaddr += PAGE_SIZE_1GB;
2137         }
2138       }
2139     } else {
2140       vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES;
2141     }
2142   }
2143   return 0;
2144 }
2145
2146
2147
2148 static const uchar_t PAGE_4KB_STR[] = "4KB_PAGE";
2149 static const uchar_t PAGE_2MB_STR[] = "2MB_PAGE";
2150 static const uchar_t PAGE_4MB_STR[] = "4MB_PAGE";
2151 static const uchar_t PAGE_1GB_STR[] = "1GB_PAGE";
2152 static const uchar_t PAGE_PT32_STR[] = "32 Bit PT";
2153 static const uchar_t PAGE_PD32_STR[] = "32 Bit PD";
2154 static const uchar_t PAGE_PDP32PAE_STR[] = "32 Bit PAE PDP";
2155 static const uchar_t PAGE_PD32PAE_STR[] = "32 Bit PAE PD";
2156 static const uchar_t PAGE_PT32PAE_STR[] = "32 Bit PAE PT";
2157 static const uchar_t PAGE_PML464_STR[] = "64 Bit PML4";
2158 static const uchar_t PAGE_PDP64_STR[] = "64 Bit PDP";
2159 static const uchar_t PAGE_PD64_STR[] = "64 Bit PD";
2160 static const uchar_t PAGE_PT64_STR[] = "64 Bit PT";
2161
2162
2163 const uchar_t * v3_page_type_to_str(page_type_t type) {
2164   switch (type) {
2165   case PAGE_4KB:
2166     return PAGE_4KB_STR;
2167   case PAGE_2MB:
2168     return PAGE_2MB_STR;
2169   case PAGE_4MB:
2170     return PAGE_4MB_STR;
2171   case PAGE_1GB:
2172     return PAGE_1GB_STR;
2173   case PAGE_PT32:
2174     return PAGE_PT32_STR;
2175   case PAGE_PD32:
2176     return PAGE_PD32_STR;
2177   case PAGE_PDP32PAE:
2178     return PAGE_PDP32PAE_STR;
2179   case PAGE_PD32PAE:
2180     return PAGE_PD32PAE_STR;
2181   case PAGE_PT32PAE:
2182     return PAGE_PT32PAE_STR;
2183   case PAGE_PML464:
2184     return PAGE_PML464_STR;
2185   case PAGE_PDP64:
2186     return PAGE_PDP64_STR;
2187   case PAGE_PD64:
2188     return PAGE_PD64_STR;
2189   case PAGE_PT64:
2190     return PAGE_PT64_STR;
2191   default:
2192     return NULL;
2193   }
2194 }