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.


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