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.


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