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.


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