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.


added pae+64 bit page table access checks
[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
28 #define USE_VMM_PAGING_DEBUG
29 // All of the debug functions defined in vmm_paging.h are implemented in this file
30 #include "vmm_paging_debug.h"
31 #undef USE_VMM_PAGING_DEBUG
32
33
34 void delete_page_tables_32(pde32_t * pde) {
35   int i;
36
37   if (pde == NULL) { 
38     return;
39   }
40
41   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
42     if (pde[i].present) {
43       // We double cast, first to an addr_t to handle 64 bit issues, then to the pointer
44       PrintDebug("PTE base addr %x \n", pde[i].pt_base_addr);
45       pte32_t * pte = (pte32_t *)((addr_t)(uint_t)(pde[i].pt_base_addr << PAGE_POWER));
46
47       PrintDebug("Deleting PTE %d (%p)\n", i, pte);
48       V3_FreePage(pte);
49     }
50   }
51
52   PrintDebug("Deleting PDE (%p)\n", pde);
53   V3_FreePage(V3_PAddr(pde));
54 }
55
56 void delete_page_tables_32PAE(pdpe32pae_t * pdpe) { 
57   PrintError("Unimplemented function\n");
58 }
59
60 void delete_page_tables_64(pml4e64_t * pml4) {
61   PrintError("Unimplemented function\n");
62 }
63
64
65 int v3_translate_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
66   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
67   pde32_t * guest_pde = 0;
68   addr_t guest_pte_pa = 0;
69
70   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) {
71     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
72                (void *)guest_pde_pa);
73     return -1;
74   }
75   
76   switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
77   case PT_ENTRY_NOT_PRESENT:
78     *paddr = 0;  
79     return -1;
80   case PT_ENTRY_LARGE_PAGE:
81     *paddr = guest_pte_pa;
82     return 0;
83   case PT_ENTRY_PAGE:
84     {
85       pte32_t * guest_pte = NULL;
86
87       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
88         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
89                    (void *)guest_pte_pa);
90         return -1;
91       }
92
93       if (pte32_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
94         return -1;
95       }
96
97       return 0;
98     }
99   }
100
101   return 0;
102 }
103
104
105 int v3_translate_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
106   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
107   pdpe32pae_t * guest_pdpe = 0;
108   addr_t guest_pde_pa = 0;
109
110   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
111     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
112                (void *)guest_pdpe_pa);
113     return -1;
114   }
115
116   switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
117     {
118     case PT_ENTRY_NOT_PRESENT:
119       *paddr = 0;
120       return -1;
121     case PT_ENTRY_PAGE:
122       {
123         pde32pae_t * guest_pde = NULL;
124         addr_t guest_pte_pa = 0;
125         
126         if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
127           PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
128                      (void *)guest_pde_pa);
129           return -1;
130         }
131         
132         switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
133           {
134           case PT_ENTRY_NOT_PRESENT:
135             *paddr = 0;
136             return -1;
137           case PT_ENTRY_LARGE_PAGE:
138             *paddr = guest_pte_pa;
139             return 0;
140           case PT_ENTRY_PAGE:
141             {
142               pte32pae_t * guest_pte = NULL;
143               
144               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
145                 PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
146                            (void *)guest_pte_pa);
147                 return -1;
148               }
149
150               if (pte32pae_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
151                 return -1;
152               }
153
154               return 0;
155             }
156           }
157       }
158     default:
159       return -1;
160     }
161
162   return 0;
163 }
164
165 int v3_translate_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
166   addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
167   pml4e64_t * guest_pmle = 0;
168   addr_t guest_pdpe_pa = 0;
169
170   if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
171     PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
172                (void *)guest_pml4_pa);
173     return -1;
174   }
175   
176   switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
177   case PT_ENTRY_NOT_PRESENT:
178     *paddr = 0;
179     return -1;
180   case PT_ENTRY_PAGE:
181     {
182       pdpe64_t * guest_pdp = NULL;
183       addr_t guest_pde_pa = 0;
184
185       if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
186         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
187                    (void *)guest_pdpe_pa);
188         return -1;
189       }
190
191       switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
192       case PT_ENTRY_NOT_PRESENT:
193         *paddr = 0;
194         return -1;
195       case PT_ENTRY_LARGE_PAGE:
196         *paddr = 0;
197         PrintError("1 Gigabyte Pages not supported\n");
198         return -1;
199       case PT_ENTRY_PAGE:
200         {
201           pde64_t * guest_pde = NULL;
202           addr_t guest_pte_pa = 0;
203
204           if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
205             PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
206                        (void *)guest_pde_pa);
207             return -1;
208           }
209
210           switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
211           case PT_ENTRY_NOT_PRESENT:
212             *paddr = 0;
213             return -1;
214           case PT_ENTRY_LARGE_PAGE:
215             *paddr = guest_pte_pa;
216             return 0;
217           case PT_ENTRY_PAGE:
218             {
219               pte64_t * guest_pte = NULL;
220               
221               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
222                 PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
223                            (void *)guest_pte_pa);
224                 return -1;
225               }
226                 
227               if (pte64_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
228                 return -1;
229               }
230
231               return 0;
232             }
233           }
234         }
235       }
236     }
237   default:
238     return -1;
239   }
240   return 0;
241 }
242
243
244
245 int v3_translate_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
246   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
247   pte32_t * host_pte = 0;
248     
249   switch (pde32_lookup(host_pde, vaddr, (addr_t *)&host_pte)) {
250   case PT_ENTRY_NOT_PRESENT:
251     *paddr = 0;
252     return -1;
253   case PT_ENTRY_LARGE_PAGE:
254     *paddr = (addr_t)host_pte;
255     return 0;
256   case PT_ENTRY_PAGE:
257     if (pte32_lookup(host_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
258       return -1;
259     }
260     return 0;
261   }
262   
263   // should never get here
264   return -1;
265 }
266
267
268 int v3_translate_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
269   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
270   pde32pae_t * host_pde = NULL;
271   pte32pae_t * host_pte = NULL;
272
273   switch (pdpe32pae_lookup(host_pdpe, vaddr, (addr_t *)&host_pde)) {
274   case PT_ENTRY_NOT_PRESENT:
275     *paddr = 0;
276     return -1;
277   case PT_ENTRY_PAGE:
278     switch (pde32pae_lookup(host_pde, vaddr, (addr_t *)&host_pte)) {
279     case PT_ENTRY_NOT_PRESENT:
280       *paddr = 0;
281       return -1;
282     case PT_ENTRY_LARGE_PAGE:
283       *paddr = (addr_t)host_pte;
284       return 0;
285     case PT_ENTRY_PAGE:
286       if (pte32pae_lookup(host_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
287         return -1;
288       }
289       return 0;
290     }
291   default:
292     return -1;
293   }
294
295   // should never get here
296   return -1;
297 }
298
299
300 int v3_translate_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
301   pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
302   pdpe64_t * host_pdpe = NULL;
303   pde64_t * host_pde = NULL;
304   pte64_t * host_pte = NULL;
305
306   switch(pml4e64_lookup(host_pmle, vaddr, (addr_t *)&host_pdpe)) {
307   case PT_ENTRY_NOT_PRESENT:
308     *paddr = 0;
309     return -1;
310   case PT_ENTRY_PAGE:
311     switch(pdpe64_lookup(host_pdpe, vaddr, (addr_t *)&host_pde)) {
312     case PT_ENTRY_NOT_PRESENT:
313       *paddr = 0;
314       return -1;
315     case PT_ENTRY_LARGE_PAGE:
316       *paddr = 0;
317       PrintError("1 Gigabyte Pages not supported\n");
318       return -1;
319     case PT_ENTRY_PAGE:
320       switch (pde64_lookup(host_pde, vaddr, (addr_t *)&host_pte)) {
321       case PT_ENTRY_NOT_PRESENT:
322         *paddr = 0;
323         return -1;
324       case PT_ENTRY_LARGE_PAGE:
325       case PT_ENTRY_PAGE:
326         if (pte64_lookup(host_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
327           return -1;
328         }
329         return 0;
330       }
331     }
332   default:
333     return -1;
334   }
335
336   // should never get here
337   return -1;
338 }
339
340
341
342
343
344 /*
345  * PAGE TABLE LOOKUP FUNCTIONS
346  *
347  *
348  * The value of entry is a return type:
349  * Page not present: *entry = 0
350  * Large Page: *entry = translated physical address (byte granularity)
351  * PTE entry: *entry is the address of the PTE Page
352  */
353
354 /**
355  * 
356  *  32 bit Page Table lookup functions
357  *
358  **/
359
360 pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
361   pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
362
363   if (!pde_entry->present) {
364     *entry = 0;
365     return PT_ENTRY_NOT_PRESENT;
366   } else if (pde_entry->large_page) {
367     pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry;
368
369     *entry = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
370     *entry += PAGE_OFFSET_4MB(addr);
371
372     return PT_ENTRY_LARGE_PAGE;
373   } else {
374     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
375     return PT_ENTRY_PAGE;
376   }
377 }
378
379
380
381 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
382  */
383 pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
384   pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
385
386   if (!pte_entry->present) {
387     *entry = 0;
388     //    PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
389     return PT_ENTRY_NOT_PRESENT;
390   } else {
391     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
392     return PT_ENTRY_PAGE;
393   }
394
395 }
396
397
398
399 /**
400  * 
401  *  32 bit PAE Page Table lookup functions
402  *
403  **/
404 pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) {
405   pdpe32pae_t * pdpe_entry = &(pdp[PDPE32PAE_INDEX(addr)]);
406   
407   if (!pdpe_entry->present) {
408     *entry = 0;
409     return PT_ENTRY_NOT_PRESENT;
410   } else {
411     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
412     return PT_ENTRY_PAGE;
413   }
414 }
415
416 pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) {
417   pde32pae_t * pde_entry = &(pd[PDE32PAE_INDEX(addr)]);
418
419   if (!pde_entry->present) {
420     *entry = 0;
421     return PT_ENTRY_NOT_PRESENT;
422   } else if (pde_entry->large_page) {
423     pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)pde_entry;
424
425     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
426     *entry += PAGE_OFFSET_2MB(addr);
427
428     return PT_ENTRY_LARGE_PAGE;
429   } else {
430     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
431     return PT_ENTRY_PAGE;
432   }
433 }
434
435 pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) {
436   pte32pae_t * pte_entry = &(pt[PTE32PAE_INDEX(addr)]);
437
438   if (!pte_entry->present) {
439     *entry = 0;
440     return PT_ENTRY_NOT_PRESENT;
441   } else {
442     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
443     return PT_ENTRY_PAGE;
444   }
445 }
446
447
448
449 /**
450  * 
451  *  64 bit Page Table lookup functions
452  *
453  **/
454 pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) {
455   pml4e64_t * pml_entry = &(pml[PML4E64_INDEX(addr)]);
456
457   if (!pml_entry->present) {
458     *entry = 0;
459     return PT_ENTRY_NOT_PRESENT;
460   } else {
461     *entry = BASE_TO_PAGE_ADDR(pml_entry->pdp_base_addr);
462     return PT_ENTRY_PAGE;
463   }
464 }
465
466 pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) {
467   pdpe64_t * pdpe_entry = &(pdp[PDPE64_INDEX(addr)]);
468   
469   if (!pdpe_entry->present) {
470     *entry = 0;
471     return PT_ENTRY_NOT_PRESENT;
472   } else if (pdpe_entry->large_page) {
473     PrintError("1 Gigabyte pages not supported\n");
474     V3_ASSERT(0);
475     return -1;
476   } else {
477     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
478     return PT_ENTRY_PAGE;
479   }
480 }
481
482 pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) {
483   pde64_t * pde_entry = &(pd[PDE64_INDEX(addr)]);
484
485   if (!pde_entry->present) {
486     *entry = 0;
487     return PT_ENTRY_NOT_PRESENT;
488   } else if (pde_entry->large_page) {
489     pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry;
490
491     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
492     *entry += PAGE_OFFSET_2MB(addr);
493
494     return PT_ENTRY_LARGE_PAGE;
495   } else {
496     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
497     return PT_ENTRY_PAGE;
498   }
499 }
500
501 pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) {
502   pte64_t * pte_entry = &(pt[PTE64_INDEX(addr)]);
503
504   if (!pte_entry->present) {
505     *entry = 0;
506     return PT_ENTRY_NOT_PRESENT;
507   } else {
508     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
509     return PT_ENTRY_PAGE;
510   }
511 }
512
513
514
515
516
517
518
519
520
521
522 static pt_access_status_t can_access_pt(gen_pt_t * pt, pf_error_t access_type) {
523   if (pt->present == 0) {
524     return PT_ACCESS_NOT_PRESENT;
525   } else if ((pt->writable == 0) && (access_type.write == 1)) {
526     return PT_ACCESS_WRITE_ERROR;
527   } else if ((pt->user_page == 0) && (access_type.user == 1)) {
528     // Check CR0.WP?
529     return PT_ACCESS_USER_ERROR;
530   }
531
532   return PT_ACCESS_OK;
533 }
534
535
536
537 /*
538  *   32 bit access checks
539  */
540 pt_access_status_t inline v3_can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
541   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)];
542   return can_access_pt(entry, access_type);
543 }
544
545 pt_access_status_t inline v3_can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
546   gen_pt_t * entry = (gen_pt_t *)&pte[PTE32_INDEX(addr)];
547   return can_access_pt(entry, access_type);
548 }
549
550
551 /*
552  *  32 bit PAE access checks
553  */
554 pt_access_status_t inline v3_can_access_pdpe32pae(pdpe32pae_t * pdpe, addr_t addr, pf_error_t access_type) {
555   gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE32PAE_INDEX(addr)];
556   return can_access_pt(entry, access_type);
557 }
558
559 pt_access_status_t inline v3_can_access_pde32pae(pde32pae_t * pde, addr_t addr, pf_error_t access_type) {
560   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32PAE_INDEX(addr)];
561   return can_access_pt(entry, access_type);
562 }
563
564 pt_access_status_t inline v3_can_access_pte32pae(pte32pae_t * pte, addr_t addr, pf_error_t access_type) {
565   gen_pt_t * entry = (gen_pt_t *)&pte[PTE32PAE_INDEX(addr)];
566   return can_access_pt(entry, access_type);
567 }
568
569 /*
570  *   64 Bit access checks
571  */
572 pt_access_status_t inline v3_can_access_pml4e64(pml4e64_t * pmle, addr_t addr, pf_error_t access_type) {
573   gen_pt_t * entry = (gen_pt_t *)&pmle[PML4E64_INDEX(addr)];
574   return can_access_pt(entry, access_type);
575 }
576
577 pt_access_status_t inline v3_can_access_pdpe64(pdpe64_t * pdpe, addr_t addr, pf_error_t access_type) {
578   gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE64_INDEX(addr)];
579   return can_access_pt(entry, access_type);
580 }
581
582 pt_access_status_t inline v3_can_access_pde64(pde64_t * pde, addr_t addr, pf_error_t access_type) {
583   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)];
584   return can_access_pt(entry, access_type);
585 }
586
587 pt_access_status_t inline v3_can_access_pte64(pte64_t * pte, addr_t addr, pf_error_t access_type) {
588   gen_pt_t * entry = (gen_pt_t *)&pte[PTE64_INDEX(addr)];
589   return can_access_pt(entry, access_type);
590 }
591
592
593
594
595
596
597 /* We generate a page table to correspond to a given memory layout
598  * pulling pages from the mem_list when necessary
599  * If there are any gaps in the layout, we add them as unmapped pages
600  */
601 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
602   addr_t current_page_addr = 0;
603   int i, j;
604   struct shadow_map * map = &(guest_info->mem_map);
605
606   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
607
608   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
609     int pte_present = 0;
610     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
611     
612
613     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
614       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
615
616       if (!region || 
617           (region->host_type == HOST_REGION_HOOK) || 
618           (region->host_type == HOST_REGION_UNALLOCATED) || 
619           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
620           (region->host_type == HOST_REGION_REMOTE) ||
621           (region->host_type == HOST_REGION_SWAPPED)) {
622         pte[j].present = 0;
623         pte[j].writable = 0;
624         pte[j].user_page = 0;
625         pte[j].write_through = 0;
626         pte[j].cache_disable = 0;
627         pte[j].accessed = 0;
628         pte[j].dirty = 0;
629         pte[j].pte_attr = 0;
630         pte[j].global_page = 0;
631         pte[j].vmm_info = 0;
632         pte[j].page_base_addr = 0;
633       } else {
634         addr_t host_addr;
635         pte[j].present = 1;
636         pte[j].writable = 1;
637         pte[j].user_page = 1;
638         pte[j].write_through = 0;
639         pte[j].cache_disable = 0;
640         pte[j].accessed = 0;
641         pte[j].dirty = 0;
642         pte[j].pte_attr = 0;
643         pte[j].global_page = 0;
644         pte[j].vmm_info = 0;
645
646         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
647           // BIG ERROR
648           // PANIC
649           return NULL;
650         }
651         
652         pte[j].page_base_addr = host_addr >> 12;
653         
654         pte_present = 1;
655       }
656
657       current_page_addr += PAGE_SIZE;
658     }
659
660     if (pte_present == 0) { 
661       V3_FreePage(V3_PAddr(pte));
662
663       pde[i].present = 0;
664       pde[i].writable = 0;
665       pde[i].user_page = 0;
666       pde[i].write_through = 0;
667       pde[i].cache_disable = 0;
668       pde[i].accessed = 0;
669       pde[i].reserved = 0;
670       pde[i].large_page = 0;
671       pde[i].global_page = 0;
672       pde[i].vmm_info = 0;
673       pde[i].pt_base_addr = 0;
674     } else {
675       pde[i].present = 1;
676       pde[i].writable = 1;
677       pde[i].user_page = 1;
678       pde[i].write_through = 0;
679       pde[i].cache_disable = 0;
680       pde[i].accessed = 0;
681       pde[i].reserved = 0;
682       pde[i].large_page = 0;
683       pde[i].global_page = 0;
684       pde[i].vmm_info = 0;
685       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
686     }
687
688   }
689
690   return pde;
691 }
692
693
694 /* We generate a page table to correspond to a given memory layout
695  * pulling pages from the mem_list when necessary
696  * If there are any gaps in the layout, we add them as unmapped pages
697  */
698 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
699   addr_t current_page_addr = 0;
700   int i, j, k;
701   struct shadow_map * map = &(guest_info->mem_map);
702
703   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
704   memset(pdpe, 0, PAGE_SIZE);
705
706   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
707     int pde_present = 0;
708     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
709
710     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
711
712
713       int pte_present = 0;
714       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
715       
716       
717       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
718         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
719         
720         if (!region || 
721             (region->host_type == HOST_REGION_HOOK) || 
722             (region->host_type == HOST_REGION_UNALLOCATED) || 
723             (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
724             (region->host_type == HOST_REGION_REMOTE) ||
725             (region->host_type == HOST_REGION_SWAPPED)) {
726           pte[k].present = 0;
727           pte[k].writable = 0;
728           pte[k].user_page = 0;
729           pte[k].write_through = 0;
730           pte[k].cache_disable = 0;
731           pte[k].accessed = 0;
732           pte[k].dirty = 0;
733           pte[k].pte_attr = 0;
734           pte[k].global_page = 0;
735           pte[k].vmm_info = 0;
736           pte[k].page_base_addr = 0;
737           pte[k].rsvd = 0;
738         } else {
739           addr_t host_addr;
740           pte[k].present = 1;
741           pte[k].writable = 1;
742           pte[k].user_page = 1;
743           pte[k].write_through = 0;
744           pte[k].cache_disable = 0;
745           pte[k].accessed = 0;
746           pte[k].dirty = 0;
747           pte[k].pte_attr = 0;
748           pte[k].global_page = 0;
749           pte[k].vmm_info = 0;
750           
751           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
752             // BIG ERROR
753             // PANIC
754             return NULL;
755           }
756           
757           pte[k].page_base_addr = host_addr >> 12;
758           pte[k].rsvd = 0;
759
760           pte_present = 1;
761         }
762         
763         current_page_addr += PAGE_SIZE;
764       }
765       
766       if (pte_present == 0) { 
767         V3_FreePage(V3_PAddr(pte));
768         
769         pde[j].present = 0;
770         pde[j].writable = 0;
771         pde[j].user_page = 0;
772         pde[j].write_through = 0;
773         pde[j].cache_disable = 0;
774         pde[j].accessed = 0;
775         pde[j].avail = 0;
776         pde[j].large_page = 0;
777         pde[j].global_page = 0;
778         pde[j].vmm_info = 0;
779         pde[j].pt_base_addr = 0;
780         pde[j].rsvd = 0;
781       } else {
782         pde[j].present = 1;
783         pde[j].writable = 1;
784         pde[j].user_page = 1;
785         pde[j].write_through = 0;
786         pde[j].cache_disable = 0;
787         pde[j].accessed = 0;
788         pde[j].avail = 0;
789         pde[j].large_page = 0;
790         pde[j].global_page = 0;
791         pde[j].vmm_info = 0;
792         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
793         pde[j].rsvd = 0;
794
795         pde_present = 1;
796       }
797       
798     }
799     
800     if (pde_present == 0) { 
801       V3_FreePage(V3_PAddr(pde));
802       
803       pdpe[i].present = 0;
804       pdpe[i].rsvd = 0;
805       pdpe[i].write_through = 0;
806       pdpe[i].cache_disable = 0;
807       pdpe[i].accessed = 0;
808       pdpe[i].avail = 0;
809       pdpe[i].rsvd2 = 0;
810       pdpe[i].vmm_info = 0;
811       pdpe[i].pd_base_addr = 0;
812       pdpe[i].rsvd3 = 0;
813     } else {
814       pdpe[i].present = 1;
815       pdpe[i].rsvd = 0;
816       pdpe[i].write_through = 0;
817       pdpe[i].cache_disable = 0;
818       pdpe[i].accessed = 0;
819       pdpe[i].avail = 0;
820       pdpe[i].rsvd2 = 0;
821       pdpe[i].vmm_info = 0;
822       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
823       pdpe[i].rsvd3 = 0;
824     }
825     
826   }
827
828
829   return pdpe;
830 }
831
832
833
834
835
836
837 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
838   addr_t current_page_addr = 0;
839   int i, j, k, m;
840   struct shadow_map * map = &(info->mem_map);
841   
842   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
843
844   for (i = 0; i < 1; i++) {
845     int pdpe_present = 0;
846     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
847
848     for (j = 0; j < 20; j++) {
849       int pde_present = 0;
850       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
851
852       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
853         int pte_present = 0;
854         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
855
856
857         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
858           struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
859           
860
861           
862           if (!region || 
863               (region->host_type == HOST_REGION_HOOK) || 
864               (region->host_type == HOST_REGION_UNALLOCATED) || 
865               (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
866               (region->host_type == HOST_REGION_REMOTE) ||
867               (region->host_type == HOST_REGION_SWAPPED)) {
868             pte[m].present = 0;
869             pte[m].writable = 0;
870             pte[m].user_page = 0;
871             pte[m].write_through = 0;
872             pte[m].cache_disable = 0;
873             pte[m].accessed = 0;
874             pte[m].dirty = 0;
875             pte[m].pte_attr = 0;
876             pte[m].global_page = 0;
877             pte[m].vmm_info = 0;
878             pte[m].page_base_addr = 0;
879           } else {
880             addr_t host_addr;
881             pte[m].present = 1;
882             pte[m].writable = 1;
883             pte[m].user_page = 1;
884             pte[m].write_through = 0;
885             pte[m].cache_disable = 0;
886             pte[m].accessed = 0;
887             pte[m].dirty = 0;
888             pte[m].pte_attr = 0;
889             pte[m].global_page = 0;
890             pte[m].vmm_info = 0;
891             
892             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
893               // BIG ERROR
894               // PANIC
895               return NULL;
896             }
897
898             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
899
900             //PrintPTE64(current_page_addr, &(pte[m]));
901
902             pte_present = 1;      
903           }
904
905
906
907
908           current_page_addr += PAGE_SIZE;
909         }
910         
911         if (pte_present == 0) {
912           V3_FreePage(V3_PAddr(pte));
913
914           pde[k].present = 0;
915           pde[k].writable = 0;
916           pde[k].user_page = 0;
917           pde[k].write_through = 0;
918           pde[k].cache_disable = 0;
919           pde[k].accessed = 0;
920           pde[k].avail = 0;
921           pde[k].large_page = 0;
922           //pde[k].global_page = 0;
923           pde[k].vmm_info = 0;
924           pde[k].pt_base_addr = 0;
925         } else {
926           pde[k].present = 1;
927           pde[k].writable = 1;
928           pde[k].user_page = 1;
929           pde[k].write_through = 0;
930           pde[k].cache_disable = 0;
931           pde[k].accessed = 0;
932           pde[k].avail = 0;
933           pde[k].large_page = 0;
934           //pde[k].global_page = 0;
935           pde[k].vmm_info = 0;
936           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
937
938           pde_present = 1;
939         }
940       }
941
942       if (pde_present == 0) {
943         V3_FreePage(V3_PAddr(pde));
944         
945         pdpe[j].present = 0;
946         pdpe[j].writable = 0;
947         pdpe[j].user_page = 0;
948         pdpe[j].write_through = 0;
949         pdpe[j].cache_disable = 0;
950         pdpe[j].accessed = 0;
951         pdpe[j].avail = 0;
952         pdpe[j].large_page = 0;
953         //pdpe[j].global_page = 0;
954         pdpe[j].vmm_info = 0;
955         pdpe[j].pd_base_addr = 0;
956       } else {
957         pdpe[j].present = 1;
958         pdpe[j].writable = 1;
959         pdpe[j].user_page = 1;
960         pdpe[j].write_through = 0;
961         pdpe[j].cache_disable = 0;
962         pdpe[j].accessed = 0;
963         pdpe[j].avail = 0;
964         pdpe[j].large_page = 0;
965         //pdpe[j].global_page = 0;
966         pdpe[j].vmm_info = 0;
967         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
968
969
970         pdpe_present = 1;
971       }
972
973     }
974
975     PrintDebug("PML index=%d\n", i);
976
977     if (pdpe_present == 0) {
978       V3_FreePage(V3_PAddr(pdpe));
979       
980       pml[i].present = 0;
981       pml[i].writable = 0;
982       pml[i].user_page = 0;
983       pml[i].write_through = 0;
984       pml[i].cache_disable = 0;
985       pml[i].accessed = 0;
986       pml[i].reserved = 0;
987       //pml[i].large_page = 0;
988       //pml[i].global_page = 0;
989       pml[i].vmm_info = 0;
990       pml[i].pdp_base_addr = 0;
991     } else {
992       pml[i].present = 1;
993       pml[i].writable = 1;
994       pml[i].user_page = 1;
995       pml[i].write_through = 0;
996       pml[i].cache_disable = 0;
997       pml[i].accessed = 0;
998       pml[i].reserved = 0;
999       //pml[i].large_page = 0;
1000       //pml[i].global_page = 0;
1001       pml[i].vmm_info = 0;
1002       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
1003     }
1004   }
1005
1006   return pml;
1007 }
1008
1009
1010
1011