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.


changed shadow memory map to use Red Black Tree
[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
673   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
674
675   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
676     int pte_present = 0;
677     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
678     
679
680     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
681       struct v3_shadow_region * region =  v3_get_shadow_region(guest_info, current_page_addr);
682
683       if (!region || 
684           (region->host_type == SHDW_REGION_FULL_HOOK)) {
685         pte[j].present = 0;
686         pte[j].writable = 0;
687         pte[j].user_page = 0;
688         pte[j].write_through = 0;
689         pte[j].cache_disable = 0;
690         pte[j].accessed = 0;
691         pte[j].dirty = 0;
692         pte[j].pte_attr = 0;
693         pte[j].global_page = 0;
694         pte[j].vmm_info = 0;
695         pte[j].page_base_addr = 0;
696       } else {
697         addr_t host_addr;
698         pte[j].present = 1;
699
700         if (region->host_type == SHDW_REGION_WRITE_HOOK) {
701           pte[j].writable = 0;
702           PrintDebug("Marking Write hook host_addr %p as RO\n", (void *)current_page_addr);
703         } else {
704           pte[j].writable = 1;
705         }
706           
707         pte[j].user_page = 1;
708         pte[j].write_through = 0;
709         pte[j].cache_disable = 0;
710         pte[j].accessed = 0;
711         pte[j].dirty = 0;
712         pte[j].pte_attr = 0;
713         pte[j].global_page = 0;
714         pte[j].vmm_info = 0;
715
716         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
717           // BIG ERROR
718           // PANIC
719           return NULL;
720         }
721         
722         pte[j].page_base_addr = host_addr >> 12;
723         
724         pte_present = 1;
725       }
726
727       current_page_addr += PAGE_SIZE;
728     }
729
730     if (pte_present == 0) { 
731       V3_FreePage(V3_PAddr(pte));
732
733       pde[i].present = 0;
734       pde[i].writable = 0;
735       pde[i].user_page = 0;
736       pde[i].write_through = 0;
737       pde[i].cache_disable = 0;
738       pde[i].accessed = 0;
739       pde[i].reserved = 0;
740       pde[i].large_page = 0;
741       pde[i].global_page = 0;
742       pde[i].vmm_info = 0;
743       pde[i].pt_base_addr = 0;
744     } else {
745       pde[i].present = 1;
746       pde[i].writable = 1;
747       pde[i].user_page = 1;
748       pde[i].write_through = 0;
749       pde[i].cache_disable = 0;
750       pde[i].accessed = 0;
751       pde[i].reserved = 0;
752       pde[i].large_page = 0;
753       pde[i].global_page = 0;
754       pde[i].vmm_info = 0;
755       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
756     }
757
758   }
759
760   return pde;
761 }
762
763
764 /* We generate a page table to correspond to a given memory layout
765  * pulling pages from the mem_list when necessary
766  * If there are any gaps in the layout, we add them as unmapped pages
767  */
768 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
769   addr_t current_page_addr = 0;
770   int i, j, k;
771
772   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
773   memset(pdpe, 0, PAGE_SIZE);
774
775   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
776     int pde_present = 0;
777     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
778
779     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
780
781
782       int pte_present = 0;
783       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
784       
785       
786       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
787         struct v3_shadow_region * region = v3_get_shadow_region(guest_info, current_page_addr);
788         
789         if (!region || 
790             (region->host_type == SHDW_REGION_FULL_HOOK)) {
791           pte[k].present = 0;
792           pte[k].writable = 0;
793           pte[k].user_page = 0;
794           pte[k].write_through = 0;
795           pte[k].cache_disable = 0;
796           pte[k].accessed = 0;
797           pte[k].dirty = 0;
798           pte[k].pte_attr = 0;
799           pte[k].global_page = 0;
800           pte[k].vmm_info = 0;
801           pte[k].page_base_addr = 0;
802           pte[k].rsvd = 0;
803         } else {
804           addr_t host_addr;
805           pte[k].present = 1;
806         
807           if (region->host_type == SHDW_REGION_WRITE_HOOK) {
808             pte[k].writable = 0;
809           } else {
810             pte[k].writable = 1;
811           }
812
813           pte[k].user_page = 1;
814           pte[k].write_through = 0;
815           pte[k].cache_disable = 0;
816           pte[k].accessed = 0;
817           pte[k].dirty = 0;
818           pte[k].pte_attr = 0;
819           pte[k].global_page = 0;
820           pte[k].vmm_info = 0;
821           
822           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
823             // BIG ERROR
824             // PANIC
825             return NULL;
826           }
827           
828           pte[k].page_base_addr = host_addr >> 12;
829           pte[k].rsvd = 0;
830
831           pte_present = 1;
832         }
833         
834         current_page_addr += PAGE_SIZE;
835       }
836       
837       if (pte_present == 0) { 
838         V3_FreePage(V3_PAddr(pte));
839         
840         pde[j].present = 0;
841         pde[j].writable = 0;
842         pde[j].user_page = 0;
843         pde[j].write_through = 0;
844         pde[j].cache_disable = 0;
845         pde[j].accessed = 0;
846         pde[j].avail = 0;
847         pde[j].large_page = 0;
848         pde[j].global_page = 0;
849         pde[j].vmm_info = 0;
850         pde[j].pt_base_addr = 0;
851         pde[j].rsvd = 0;
852       } else {
853         pde[j].present = 1;
854         pde[j].writable = 1;
855         pde[j].user_page = 1;
856         pde[j].write_through = 0;
857         pde[j].cache_disable = 0;
858         pde[j].accessed = 0;
859         pde[j].avail = 0;
860         pde[j].large_page = 0;
861         pde[j].global_page = 0;
862         pde[j].vmm_info = 0;
863         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
864         pde[j].rsvd = 0;
865
866         pde_present = 1;
867       }
868       
869     }
870     
871     if (pde_present == 0) { 
872       V3_FreePage(V3_PAddr(pde));
873       
874       pdpe[i].present = 0;
875       pdpe[i].rsvd = 0;
876       pdpe[i].write_through = 0;
877       pdpe[i].cache_disable = 0;
878       pdpe[i].accessed = 0;
879       pdpe[i].avail = 0;
880       pdpe[i].rsvd2 = 0;
881       pdpe[i].vmm_info = 0;
882       pdpe[i].pd_base_addr = 0;
883       pdpe[i].rsvd3 = 0;
884     } else {
885       pdpe[i].present = 1;
886       pdpe[i].rsvd = 0;
887       pdpe[i].write_through = 0;
888       pdpe[i].cache_disable = 0;
889       pdpe[i].accessed = 0;
890       pdpe[i].avail = 0;
891       pdpe[i].rsvd2 = 0;
892       pdpe[i].vmm_info = 0;
893       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
894       pdpe[i].rsvd3 = 0;
895     }
896     
897   }
898
899
900   return pdpe;
901 }
902
903
904
905
906
907
908 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
909   addr_t current_page_addr = 0;
910   int i, j, k, m;
911   
912   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
913
914   for (i = 0; i < 1; i++) {
915     int pdpe_present = 0;
916     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
917
918     for (j = 0; j < 20; j++) {
919       int pde_present = 0;
920       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
921
922       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
923         int pte_present = 0;
924         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
925
926
927         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
928           struct v3_shadow_region * region = v3_get_shadow_region(info, current_page_addr);
929           
930
931           
932           if (!region || 
933               (region->host_type == SHDW_REGION_FULL_HOOK)) {
934             pte[m].present = 0;
935             pte[m].writable = 0;
936             pte[m].user_page = 0;
937             pte[m].write_through = 0;
938             pte[m].cache_disable = 0;
939             pte[m].accessed = 0;
940             pte[m].dirty = 0;
941             pte[m].pte_attr = 0;
942             pte[m].global_page = 0;
943             pte[m].vmm_info = 0;
944             pte[m].page_base_addr = 0;
945           } else {
946             addr_t host_addr;
947             pte[m].present = 1;
948
949             if (region->host_type == SHDW_REGION_WRITE_HOOK) {
950               pte[m].writable = 0;
951             } else {
952               pte[m].writable = 1;
953             }
954         
955             pte[m].user_page = 1;
956             pte[m].write_through = 0;
957             pte[m].cache_disable = 0;
958             pte[m].accessed = 0;
959             pte[m].dirty = 0;
960             pte[m].pte_attr = 0;
961             pte[m].global_page = 0;
962             pte[m].vmm_info = 0;
963             
964             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
965               // BIG ERROR
966               // PANIC
967               return NULL;
968             }
969
970             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
971
972             //PrintPTE64(current_page_addr, &(pte[m]));
973
974             pte_present = 1;      
975           }
976
977
978
979
980           current_page_addr += PAGE_SIZE;
981         }
982         
983         if (pte_present == 0) {
984           V3_FreePage(V3_PAddr(pte));
985
986           pde[k].present = 0;
987           pde[k].writable = 0;
988           pde[k].user_page = 0;
989           pde[k].write_through = 0;
990           pde[k].cache_disable = 0;
991           pde[k].accessed = 0;
992           pde[k].avail = 0;
993           pde[k].large_page = 0;
994           //pde[k].global_page = 0;
995           pde[k].vmm_info = 0;
996           pde[k].pt_base_addr = 0;
997         } else {
998           pde[k].present = 1;
999           pde[k].writable = 1;
1000           pde[k].user_page = 1;
1001           pde[k].write_through = 0;
1002           pde[k].cache_disable = 0;
1003           pde[k].accessed = 0;
1004           pde[k].avail = 0;
1005           pde[k].large_page = 0;
1006           //pde[k].global_page = 0;
1007           pde[k].vmm_info = 0;
1008           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
1009
1010           pde_present = 1;
1011         }
1012       }
1013
1014       if (pde_present == 0) {
1015         V3_FreePage(V3_PAddr(pde));
1016         
1017         pdpe[j].present = 0;
1018         pdpe[j].writable = 0;
1019         pdpe[j].user_page = 0;
1020         pdpe[j].write_through = 0;
1021         pdpe[j].cache_disable = 0;
1022         pdpe[j].accessed = 0;
1023         pdpe[j].avail = 0;
1024         pdpe[j].large_page = 0;
1025         //pdpe[j].global_page = 0;
1026         pdpe[j].vmm_info = 0;
1027         pdpe[j].pd_base_addr = 0;
1028       } else {
1029         pdpe[j].present = 1;
1030         pdpe[j].writable = 1;
1031         pdpe[j].user_page = 1;
1032         pdpe[j].write_through = 0;
1033         pdpe[j].cache_disable = 0;
1034         pdpe[j].accessed = 0;
1035         pdpe[j].avail = 0;
1036         pdpe[j].large_page = 0;
1037         //pdpe[j].global_page = 0;
1038         pdpe[j].vmm_info = 0;
1039         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
1040
1041
1042         pdpe_present = 1;
1043       }
1044
1045     }
1046
1047     PrintDebug("PML index=%d\n", i);
1048
1049     if (pdpe_present == 0) {
1050       V3_FreePage(V3_PAddr(pdpe));
1051       
1052       pml[i].present = 0;
1053       pml[i].writable = 0;
1054       pml[i].user_page = 0;
1055       pml[i].write_through = 0;
1056       pml[i].cache_disable = 0;
1057       pml[i].accessed = 0;
1058       pml[i].reserved = 0;
1059       //pml[i].large_page = 0;
1060       //pml[i].global_page = 0;
1061       pml[i].vmm_info = 0;
1062       pml[i].pdp_base_addr = 0;
1063     } else {
1064       pml[i].present = 1;
1065       pml[i].writable = 1;
1066       pml[i].user_page = 1;
1067       pml[i].write_through = 0;
1068       pml[i].cache_disable = 0;
1069       pml[i].accessed = 0;
1070       pml[i].reserved = 0;
1071       //pml[i].large_page = 0;
1072       //pml[i].global_page = 0;
1073       pml[i].vmm_info = 0;
1074       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
1075     }
1076   }
1077
1078   return pml;
1079 }
1080
1081
1082 int v3_drill_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, 
1083                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1084                         void * private_data) {
1085   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1086   addr_t host_pde_pa = CR3_TO_PDE32_PA(host_cr3);
1087   addr_t host_pte_pa = 0;
1088   addr_t page_pa = 0;
1089   int ret;
1090
1091   if ((ret = callback(PAGE_PD32, vaddr, (addr_t)host_pde, host_pde_pa, private_data)) != 0) {
1092     return (ret == -1) ? -1 : PAGE_PD32;
1093   }
1094
1095   switch (pde32_lookup(host_pde, vaddr, &host_pte_pa)) {
1096   case PT_ENTRY_NOT_PRESENT:
1097     return -1;
1098   case PT_ENTRY_LARGE_PAGE:
1099     if ((ret == callback(PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1100       return (ret == -1) ? -1 : PAGE_4MB;
1101     }
1102     return 0;
1103   case PT_ENTRY_PAGE:
1104     if ((ret = callback(PAGE_PT32, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1105       return (ret == -1) ? -1 : PAGE_PT32;
1106     }
1107     
1108     if (pte32_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1109       return -1;
1110     } else {
1111       if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1112         return (ret == -1) ? -1 : PAGE_4KB;
1113       }
1114       return 0;
1115     }
1116   }
1117   return -1;
1118 }
1119
1120
1121
1122 int v3_drill_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr,
1123                            int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1124                            void * private_data) {
1125   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1126   addr_t host_pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1127   addr_t host_pde_pa = 0;
1128   addr_t host_pte_pa = 0;
1129   addr_t page_pa = 0;
1130   int ret;
1131
1132   if ((ret = callback(PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, host_pdpe_pa, private_data)) != 0) {
1133     return (ret == -1) ? -1 : PAGE_PDP32PAE;
1134   }
1135
1136   switch (pdpe32pae_lookup(host_pdpe, vaddr, &host_pde_pa)) {
1137   case PT_ENTRY_NOT_PRESENT:
1138     return -1;
1139   case PT_ENTRY_PAGE:
1140
1141     if ((ret = callback(PAGE_PD32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) {
1142       return (ret == -1) ? -1 : PAGE_PD32PAE;
1143     }
1144       
1145     switch (pde32pae_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
1146     case PT_ENTRY_NOT_PRESENT:
1147       return -1;
1148     case PT_ENTRY_LARGE_PAGE:
1149       if ((ret == callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1150         return (ret == -1) ? -1 : PAGE_2MB;
1151       }
1152       return 0;
1153     case PT_ENTRY_PAGE:
1154       if ((ret = callback(PAGE_PT32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1155         return (ret == -1) ? -1 : PAGE_PT32PAE;
1156       }
1157
1158       if (pte32pae_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1159         return -1;
1160       } else {
1161         if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1162           return (ret == -1) ? -1 : PAGE_4KB;
1163         }
1164         return 0;
1165       } 
1166     }
1167   default:
1168     return -1;
1169   }
1170
1171   // should never get here
1172   return -1;
1173 }
1174
1175
1176 int v3_drill_host_pt_64(v3_reg_t host_cr3, addr_t vaddr,
1177                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1178                         void * private_data) {
1179   pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1180   addr_t host_pmle_pa = CR3_TO_PML4E64_PA(host_cr3);
1181   addr_t host_pdpe_pa = 0;
1182   addr_t host_pde_pa = 0;
1183   addr_t host_pte_pa = 0;
1184   addr_t page_pa = 0;
1185   int ret;
1186
1187   if ((ret = callback(PAGE_PML464, vaddr, (addr_t)host_pmle, host_pmle_pa, private_data)) != 0) {
1188     return (ret == -1) ? -1 : PAGE_PML464;
1189   }
1190
1191   switch(pml4e64_lookup(host_pmle, vaddr, &host_pdpe_pa)) {
1192   case PT_ENTRY_NOT_PRESENT:
1193     return -1;
1194   case PT_ENTRY_PAGE:
1195
1196     if ((ret = callback(PAGE_PDP64, vaddr, (addr_t)V3_VAddr((void *)host_pdpe_pa), host_pdpe_pa, private_data)) != 0) {
1197       return (ret == -1) ? -1 : PAGE_PDP64;
1198     }
1199
1200     switch(pdpe64_lookup(V3_VAddr((void *)host_pdpe_pa), vaddr, &host_pde_pa)) {
1201     case PT_ENTRY_NOT_PRESENT:
1202       return -1;
1203     case PT_ENTRY_LARGE_PAGE:
1204       if ((ret == callback(PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) {
1205         return (ret == -1) ? -1 : PAGE_1GB;
1206       }
1207       PrintError("1 Gigabyte Pages not supported\n");
1208       return 0;
1209     case PT_ENTRY_PAGE:
1210
1211       if ((ret = callback(PAGE_PD64, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) {
1212         return (ret == -1) ? -1 : PAGE_PD64;
1213       }
1214
1215       switch (pde64_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
1216       case PT_ENTRY_NOT_PRESENT:
1217         return -1;
1218       case PT_ENTRY_LARGE_PAGE:
1219         if ((ret == callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1220           return (ret == -1) ? -1 : PAGE_2MB;
1221         }
1222         return 0;
1223       case PT_ENTRY_PAGE:
1224
1225         if ((ret = callback(PAGE_PT64, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1226           return (ret == -1) ? -1 : PAGE_PT64;
1227         }
1228
1229         if (pte64_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1230           return -1;
1231         } else {
1232           if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1233             return (ret == -1) ? -1 : PAGE_4KB;
1234           }
1235           return 0;
1236         }
1237       }
1238     }
1239   default:
1240     return -1;
1241   }
1242   // should never get here
1243   return -1;
1244 }
1245
1246
1247
1248
1249
1250
1251
1252 int v3_drill_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1253                          int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1254                          void * private_data) {
1255   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1256   pde32_t * guest_pde = NULL;
1257   addr_t guest_pte_pa = 0;
1258   int ret; 
1259   
1260
1261   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) {
1262     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1263                (void *)guest_pde_pa);
1264     return -1;
1265   }
1266   
1267   if ((ret = callback(PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1268     return (ret == -1) ? -1 : PAGE_PD32;
1269   }
1270   
1271   switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1272   case PT_ENTRY_NOT_PRESENT:
1273     return -1;
1274   case PT_ENTRY_LARGE_PAGE:
1275     {
1276       addr_t large_page_pa = (addr_t)guest_pte_pa;
1277       addr_t large_page_va = 0;
1278       
1279       if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1280         PrintError("Could not get virtual address of Guest Page 4MB (PA=%p)\n", 
1281                    (void *)large_page_va);
1282         return -1;
1283       }
1284
1285
1286       if ((ret == callback(PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1287         return (ret == -1) ? -1 : PAGE_4MB;
1288       }
1289       return 0;
1290     }
1291   case PT_ENTRY_PAGE:
1292     {
1293       pte32_t * guest_pte = NULL;
1294       addr_t page_pa;
1295
1296       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
1297         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1298                    (void *)guest_pte_pa);
1299         return -1;
1300       }
1301
1302       if ((ret = callback(PAGE_PT32, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1303         return (ret == -1) ? -1 : PAGE_PT32;
1304       }
1305
1306       if (pte32_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1307         return -1;
1308       } else {
1309         addr_t page_va;
1310
1311         if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1312           PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1313                      (void *)page_pa);
1314           return -1;
1315         }
1316
1317         if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1318           return (ret == -1) ? -1 : PAGE_4KB;
1319         }
1320         return 0;
1321       }
1322     }
1323   }
1324
1325   // should never get here
1326   PrintError("End of drill function (guest 32)... Should never have gotten here...\n");
1327   return -1;
1328 }
1329
1330
1331
1332 int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr,
1333                                 int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1334                                 void * private_data) {                  
1335   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1336   pdpe32pae_t * guest_pdpe = 0;
1337   addr_t guest_pde_pa = 0;
1338   int ret = 0;
1339
1340   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
1341     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
1342                (void *)guest_pdpe_pa);
1343     return -1;
1344   }
1345
1346   if ((ret = callback(PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1347     return (ret == -1) ? -1 : PAGE_PDP32PAE;
1348   }
1349
1350   switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
1351     {
1352     case PT_ENTRY_NOT_PRESENT:
1353       return -1;
1354     case PT_ENTRY_PAGE:
1355       {
1356         pde32pae_t * guest_pde = NULL;
1357         addr_t guest_pte_pa = 0;
1358         
1359         if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1360           PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
1361                      (void *)guest_pde_pa);
1362           return -1;
1363         }
1364
1365         if ((ret = callback(PAGE_PD32PAE, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1366           return (ret == -1) ? -1 : PAGE_PD32PAE;
1367         }
1368         
1369         switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
1370           {
1371           case PT_ENTRY_NOT_PRESENT:
1372             return -1;
1373           case PT_ENTRY_LARGE_PAGE:
1374             {
1375               addr_t large_page_pa = (addr_t)guest_pte_pa;
1376               addr_t large_page_va = 0;
1377               
1378               if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1379                 PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", 
1380                            (void *)large_page_va);
1381
1382               }
1383               
1384               if ((ret == callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1385                 return (ret == -1) ? -1 : PAGE_2MB;
1386               }
1387               return 0;
1388             }
1389           case PT_ENTRY_PAGE:
1390             {
1391               pte32pae_t * guest_pte = NULL;
1392               addr_t page_pa;
1393
1394               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1395                 PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
1396                            (void *)guest_pte_pa);
1397                 return -1;
1398               }
1399
1400               if ((ret = callback(PAGE_PT32PAE, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1401                 return (ret == -1) ? -1 : PAGE_PT32PAE;
1402               }
1403
1404               if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1405                 return -1;
1406               } else {
1407                 addr_t page_va;
1408                 
1409                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1410                   PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1411                              (void *)page_pa);
1412                   return -1;
1413                 }
1414                 
1415                 if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1416                   return (ret == -1) ? -1 : PAGE_4KB;
1417                 }
1418                 return 0;
1419               }
1420             }
1421           }
1422       }
1423     default:
1424       PrintError("Invalid page type for PD32PAE\n");
1425       return -1;
1426     }
1427
1428   // should never get here
1429   PrintError("End of drill function (guest 32pae)... Should never have gotten here...\n");
1430   return -1;
1431 }
1432
1433 int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1434                                 int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1435                                 void * private_data) {  
1436   addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
1437   pml4e64_t * guest_pmle = 0;
1438   addr_t guest_pdpe_pa = 0;
1439   int ret = 0;
1440
1441   if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
1442     PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
1443                (void *)guest_pml4_pa);
1444     return -1;
1445   }
1446   
1447   if ((ret = callback(PAGE_PML464, vaddr, (addr_t)guest_pmle, guest_pml4_pa, private_data)) != 0) {
1448     return (ret == -1) ? -1 : PAGE_PML464;
1449   }
1450
1451   switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
1452   case PT_ENTRY_NOT_PRESENT:
1453     return -1;
1454   case PT_ENTRY_PAGE:
1455     {
1456       pdpe64_t * guest_pdp = NULL;
1457       addr_t guest_pde_pa = 0;
1458
1459       if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
1460         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1461                    (void *)guest_pdpe_pa);
1462         return -1;
1463       }
1464
1465       if ((ret = callback(PAGE_PDP64, vaddr, (addr_t)guest_pdp, guest_pdpe_pa, private_data)) != 0) {
1466         return (ret == -1) ? -1 : PAGE_PDP64;
1467       }
1468
1469       switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
1470       case PT_ENTRY_NOT_PRESENT:
1471         return -1;
1472       case PT_ENTRY_LARGE_PAGE:
1473         {
1474           addr_t large_page_pa = (addr_t)guest_pde_pa;
1475           addr_t large_page_va = 0;
1476           
1477           if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1478             PrintDebug("Could not get virtual address of Guest Page 1GB (PA=%p)\n", 
1479                        (void *)large_page_va);
1480             
1481           }
1482           
1483           if ((ret == callback(PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1484             return (ret == -1) ? -1 : PAGE_1GB;
1485           }
1486           PrintError("1 Gigabyte Pages not supported\n");
1487           return 0;
1488         }
1489       case PT_ENTRY_PAGE:
1490         {
1491           pde64_t * guest_pde = NULL;
1492           addr_t guest_pte_pa = 0;
1493
1494           if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1495             PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
1496                        (void *)guest_pde_pa);
1497             return -1;
1498           }
1499         
1500           if ((ret = callback(PAGE_PD64, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1501             return (ret == -1) ? -1 : PAGE_PD64;
1502           }
1503
1504           switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1505           case PT_ENTRY_NOT_PRESENT:
1506             return -1;
1507           case PT_ENTRY_LARGE_PAGE:
1508             {
1509               addr_t large_page_pa = (addr_t)guest_pte_pa;
1510               addr_t large_page_va = 0;
1511               
1512               if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1513                 PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", 
1514                            (void *)large_page_va);
1515
1516               }
1517               
1518               if ((ret == callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1519                 return (ret == -1) ? -1 : PAGE_2MB;
1520               }
1521               return 0;
1522             }
1523           case PT_ENTRY_PAGE:
1524             {
1525               pte64_t * guest_pte = NULL;
1526               addr_t page_pa;
1527               
1528               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1529                 PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
1530                            (void *)guest_pte_pa);
1531                 return -1;
1532               }
1533
1534               if ((ret = callback(PAGE_PT64, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1535                 return (ret == -1) ? -1 : PAGE_PT64;
1536               }
1537                 
1538               if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1539                 return -1;
1540               } else {
1541                 addr_t page_va;
1542                 
1543                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1544                   PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1545                              (void *)page_pa);
1546                   return -1;
1547                 }
1548                 
1549                 if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1550                   return (ret == -1) ? -1 : PAGE_4KB;
1551                 }
1552
1553                 return 0;
1554               }
1555             }
1556           }
1557         }
1558       }
1559     }
1560   default:
1561     return -1;
1562   }
1563
1564   // should never get here
1565   PrintError("End of drill function (guest 64)... Should never have gotten here...\n");
1566   return -1;
1567 }
1568
1569
1570
1571
1572 int v3_walk_guest_pt_32(struct guest_info * info,  v3_reg_t guest_cr3,
1573                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1574                         void * private_data) {
1575   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1576   pde32_t * guest_pde = NULL;
1577   int i, j;
1578   addr_t vaddr = 0;
1579
1580   if (!callback) {
1581     PrintError("Call back was not specified\n");
1582     return -1;
1583   }
1584
1585   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1586     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1587                (void *)guest_pde_pa);
1588     return -1;
1589   }
1590
1591   callback(PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data);
1592
1593   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1594     if (guest_pde[i].present) {
1595       if (guest_pde[i].large_page) {
1596         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(guest_pde[i]);
1597         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1598         addr_t large_page_va = 0;
1599
1600         if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1601           PrintDebug("Could not get virtual address of Guest 4MB Page (PA=%p)\n", 
1602                      (void *)large_page_pa);
1603           // We'll let it through for data pages because they may be unmapped or hooked
1604           large_page_va = 0;
1605         }
1606
1607         callback(PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data);
1608
1609         vaddr += PAGE_SIZE_4MB;
1610       } else {
1611         addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1612         pte32_t * tmp_pte = NULL;
1613
1614         if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1615           PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1616                      (void *)pte_pa);
1617           return -1;
1618         }
1619
1620         callback(PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1621
1622         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1623           if (tmp_pte[j].present) {
1624             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1625             addr_t page_va = 0;
1626
1627             if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1628               PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1629                  (void *)page_pa);
1630               // We'll let it through for data pages because they may be unmapped or hooked
1631               page_va = 0;
1632             }
1633             
1634             callback(PAGE_4KB, vaddr, page_va, page_pa, private_data);
1635           }
1636
1637           vaddr += PAGE_SIZE_4KB;
1638         }
1639       }
1640     } else {
1641       vaddr += PAGE_SIZE_4MB;
1642     }
1643   }
1644   return 0;
1645 }
1646
1647
1648 int v3_walk_guest_pt_32pae(struct guest_info * info,  v3_reg_t guest_cr3,
1649                            int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1650                            void * private_data) {
1651   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1652   pdpe32pae_t * guest_pdpe = NULL;
1653   int i, j, k;
1654   addr_t vaddr = 0;
1655
1656   if (!callback) {
1657     PrintError("Call back was not specified\n");
1658     return -1;
1659   }
1660
1661   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdpe) == -1) {
1662     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", 
1663                (void *)guest_pdpe_pa);
1664     return -1;
1665   }
1666
1667   
1668
1669   callback(PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data);
1670
1671   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1672     if (guest_pdpe[i].present) {
1673       addr_t pde_pa = BASE_TO_PAGE_ADDR(guest_pdpe[i].pd_base_addr);
1674       pde32pae_t * tmp_pde = NULL;
1675
1676       if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1677         PrintError("Could not get virtual address of Guest PDE32PAE (PA=%p)\n", 
1678                    (void *)pde_pa);
1679         return -1;
1680       }
1681
1682       callback(PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
1683       
1684       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1685         if (tmp_pde[j].present) {
1686           if (tmp_pde[j].large_page) {
1687             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1688             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1689             addr_t large_page_va = 0;
1690             
1691             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1692               PrintDebug("Could not get virtual address of Guest 2MB Page (PA=%p)\n", 
1693                          (void *)large_page_pa);
1694               // We'll let it through for data pages because they may be unmapped or hooked
1695               large_page_va = 0;
1696             }
1697             
1698             callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data);
1699
1700             vaddr += PAGE_SIZE_2MB;
1701           } else {
1702             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1703             pte32pae_t * tmp_pte = NULL;
1704             
1705             if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1706               PrintError("Could not get virtual address of Guest PTE32PAE (PA=%p)\n", 
1707                          (void *)pte_pa);
1708               return -1;
1709             }
1710             
1711             callback(PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1712             
1713             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1714               if (tmp_pte[k].present) {
1715                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1716                 addr_t page_va = 0;
1717                 
1718                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1719                   PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1720                              (void *)page_pa);
1721                   // We'll let it through for data pages because they may be unmapped or hooked
1722                   page_va = 0;
1723                 }
1724                 
1725                 callback(PAGE_4KB, vaddr, page_va, page_pa, private_data);
1726               }
1727               
1728               vaddr += PAGE_SIZE_4KB;
1729             }
1730           }
1731         } else {
1732           vaddr += PAGE_SIZE_2MB;
1733         }
1734       }
1735     } else {
1736       vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1737     }
1738   }
1739   return 0;
1740 }
1741
1742
1743
1744
1745 int v3_walk_guest_pt_64(struct guest_info * info,  v3_reg_t guest_cr3,
1746                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1747                         void * private_data) {
1748   addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3);
1749   pml4e64_t * guest_pml = NULL;
1750   int i, j, k, m;
1751   addr_t vaddr = 0;
1752
1753   if (!callback) {
1754     PrintError("Call back was not specified\n");
1755     return -1;
1756   }
1757
1758   if (guest_pa_to_host_va(info, guest_pml_pa, (addr_t *)&guest_pml) == -1) {
1759     PrintError("Could not get virtual address of Guest PML464 (PA=%p)\n", 
1760                (void *)guest_pml);
1761     return -1;
1762   }
1763
1764
1765   callback(PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data);
1766
1767   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1768     if (guest_pml[i].present) {
1769       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(guest_pml[i].pdp_base_addr);
1770       pdpe64_t * tmp_pdpe = NULL;
1771       
1772       
1773       if (guest_pa_to_host_va(info, pdpe_pa, (addr_t *)&tmp_pdpe) == -1) {
1774         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1775                    (void *)pdpe_pa);
1776         return -1;
1777       }
1778       
1779       callback(PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data);
1780       
1781       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1782         if (tmp_pdpe[j].present) {
1783           if (tmp_pdpe[j].large_page) {
1784             pdpe64_1GB_t * large_pdpe = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1785             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdpe->page_base_addr);
1786             addr_t large_page_va = 0;
1787
1788             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1789               PrintDebug("Could not get virtual address of Guest 1GB page (PA=%p)\n", 
1790                          (void *)large_page_pa);
1791               // We'll let it through for data pages because they may be unmapped or hooked
1792               large_page_va = 0;
1793             }
1794
1795             callback(PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data);
1796
1797             vaddr += PAGE_SIZE_1GB;
1798           } else {
1799             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1800             pde64_t * tmp_pde = NULL;
1801             
1802             if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1803               PrintError("Could not get virtual address of Guest PDE64 (PA=%p)\n", 
1804                          (void *)pde_pa);
1805               return -1;
1806             }
1807             
1808             callback(PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
1809             
1810             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1811               if (tmp_pde[k].present) {
1812                 if (tmp_pde[k].large_page) {
1813                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1814                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1815                   addr_t large_page_va = 0;
1816                   
1817                   if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1818                     PrintDebug("Could not get virtual address of Guest 2MB page (PA=%p)\n", 
1819                                (void *)large_page_pa);
1820                     // We'll let it through for data pages because they may be unmapped or hooked
1821                     large_page_va = 0;
1822                   }
1823                   
1824                   callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data);
1825
1826                   vaddr += PAGE_SIZE_2MB;
1827                 } else {
1828                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1829                   pte64_t * tmp_pte = NULL;
1830                   
1831                   if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1832                     PrintError("Could not get virtual address of Guest PTE64 (PA=%p)\n", 
1833                                (void *)pte_pa);
1834                     return -1;
1835                   }
1836                   
1837                   callback(PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1838                   
1839                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1840                     if (tmp_pte[m].present) {
1841                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1842                       addr_t page_va = 0;
1843                       
1844                       if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1845                         PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1846                                    (void *)page_pa);
1847                         // We'll let it through for data pages because they may be unmapped or hooked
1848                         page_va = 0;
1849                       }
1850                       
1851                       callback(PAGE_4KB, vaddr, page_va, page_pa, private_data);
1852                     }
1853
1854                     vaddr += PAGE_SIZE_4KB;
1855                   }
1856                 }
1857               } else {
1858                 vaddr += PAGE_SIZE_2MB;
1859               }
1860             }
1861           }
1862         } else {
1863           vaddr += PAGE_SIZE_1GB;
1864         }
1865       }
1866     } else {
1867       vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES);
1868     }
1869   }
1870   return 0;
1871 }
1872
1873 int v3_walk_host_pt_32(v3_reg_t host_cr3,
1874                        int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1875                        void * private_data) {
1876   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1877   addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3);
1878   int i, j;
1879   addr_t vaddr = 0;
1880
1881   if (!callback) {
1882     PrintError("Call back was not specified\n");
1883     return -1;
1884   }
1885
1886   callback(PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data);
1887
1888   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1889     if (host_pde[i].present) {
1890       if (host_pde[i].large_page) {
1891         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]);
1892         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1893
1894         callback(PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1895
1896         vaddr += PAGE_SIZE_4MB;
1897       } else {
1898         addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr);
1899         pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa);
1900
1901         callback(PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1902
1903         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1904           if (tmp_pte[j].present) {
1905             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1906             callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1907           }
1908
1909           vaddr += PAGE_SIZE_4KB;
1910         }
1911       }
1912     } else {
1913       vaddr += PAGE_SIZE_4MB;
1914     }
1915   }
1916   return 0;
1917 }
1918
1919
1920
1921
1922
1923 int v3_walk_host_pt_32pae(v3_reg_t host_cr3,
1924                           int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1925                           void * private_data) {
1926   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1927   addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1928   int i, j, k;
1929   addr_t vaddr = 0;
1930
1931   if (!callback) {
1932     PrintError("Callback was not specified\n");
1933     return -1;
1934   }
1935   
1936   callback(PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data);
1937   
1938   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1939     if (host_pdpe[i].present) { 
1940       addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr);
1941       pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa);
1942       
1943       callback(PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
1944       
1945       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1946         if (tmp_pde[j].present) {
1947           
1948           if (tmp_pde[j].large_page) {
1949             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1950             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1951
1952             callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1953
1954             vaddr += PAGE_SIZE_2MB;
1955           } else {
1956             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1957             pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa);
1958             
1959             callback(PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1960             
1961             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1962               if (tmp_pte[k].present) {
1963                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1964                 callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1965               }
1966
1967               vaddr += PAGE_SIZE_4KB;
1968             }
1969           }
1970         } else {
1971           vaddr += PAGE_SIZE_2MB;
1972         }
1973       }
1974     } else {
1975       vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1976     }
1977   }
1978   return 0;
1979 }
1980                         
1981
1982 int v3_walk_host_pt_64(v3_reg_t host_cr3,
1983                        int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1984                        void * private_data) {
1985   pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1986   addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3);
1987   int i, j, k, m;
1988   addr_t vaddr = 0;
1989
1990   if (!callback) {
1991     PrintError("Callback was not specified\n");
1992     return -1;
1993   }
1994
1995   callback(PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data);
1996
1997   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1998     if (host_pml[i].present) {
1999       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr);
2000       pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa);
2001
2002       callback(PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data);
2003
2004       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
2005         if (tmp_pdpe[j].present) {
2006           if (tmp_pdpe[j].large_page) {
2007             pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
2008             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
2009
2010             callback(PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
2011
2012             vaddr += PAGE_SIZE_1GB;
2013           } else {
2014             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
2015             pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa);
2016
2017             callback(PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
2018
2019             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
2020               if (tmp_pde[k].present) {
2021                 if (tmp_pde[k].large_page) {
2022                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
2023                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
2024                   
2025                   callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
2026                   
2027                   vaddr += PAGE_SIZE_2MB;
2028                 } else {
2029                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
2030                   pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa);
2031
2032                   callback(PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
2033
2034                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
2035                     if (tmp_pte[m].present) {
2036                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
2037                       callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
2038                     }
2039                     vaddr += PAGE_SIZE_4KB;
2040                   }
2041                 }
2042               } else {
2043                 vaddr += PAGE_SIZE_2MB;
2044               }
2045             }
2046           }
2047         } else {
2048           vaddr += PAGE_SIZE_1GB;
2049         }
2050       }
2051     } else {
2052       vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES;
2053     }
2054   }
2055   return 0;
2056 }
2057
2058
2059
2060 static const uchar_t PAGE_4KB_STR[] = "4KB_PAGE";
2061 static const uchar_t PAGE_2MB_STR[] = "2MB_PAGE";
2062 static const uchar_t PAGE_4MB_STR[] = "4MB_PAGE";
2063 static const uchar_t PAGE_1GB_STR[] = "1GB_PAGE";
2064 static const uchar_t PAGE_PT32_STR[] = "32 Bit PT";
2065 static const uchar_t PAGE_PD32_STR[] = "32 Bit PD";
2066 static const uchar_t PAGE_PDP32PAE_STR[] = "32 Bit PAE PDP";
2067 static const uchar_t PAGE_PD32PAE_STR[] = "32 Bit PAE PD";
2068 static const uchar_t PAGE_PT32PAE_STR[] = "32 Bit PAE PT";
2069 static const uchar_t PAGE_PML464_STR[] = "64 Bit PML4";
2070 static const uchar_t PAGE_PDP64_STR[] = "64 Bit PDP";
2071 static const uchar_t PAGE_PD64_STR[] = "64 Bit PD";
2072 static const uchar_t PAGE_PT64_STR[] = "64 Bit PT";
2073
2074
2075 const uchar_t * v3_page_type_to_str(page_type_t type) {
2076   switch (type) {
2077   case PAGE_4KB:
2078     return PAGE_4KB_STR;
2079   case PAGE_2MB:
2080     return PAGE_2MB_STR;
2081   case PAGE_4MB:
2082     return PAGE_4MB_STR;
2083   case PAGE_1GB:
2084     return PAGE_1GB_STR;
2085   case PAGE_PT32:
2086     return PAGE_PT32_STR;
2087   case PAGE_PD32:
2088     return PAGE_PD32_STR;
2089   case PAGE_PDP32PAE:
2090     return PAGE_PDP32PAE_STR;
2091   case PAGE_PD32PAE:
2092     return PAGE_PD32PAE_STR;
2093   case PAGE_PT32PAE:
2094     return PAGE_PT32PAE_STR;
2095   case PAGE_PML464:
2096     return PAGE_PML464_STR;
2097   case PAGE_PDP64:
2098     return PAGE_PDP64_STR;
2099   case PAGE_PD64:
2100     return PAGE_PD64_STR;
2101   case PAGE_PT64:
2102     return PAGE_PT64_STR;
2103   default:
2104     return NULL;
2105   }
2106 }