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 translation 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
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, addr_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, addr_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, addr_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(addr_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(addr_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(addr_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
523
524
525
526
527
528
529 pt_access_status_t can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
530   pde32_t * entry = &pde[PDE32_INDEX(addr)];
531
532   if (entry->present == 0) {
533     return PT_ACCESS_NOT_PRESENT;
534   } else if ((entry->writable == 0) && (access_type.write == 1)) {
535     return PT_ACCESS_WRITE_ERROR;
536   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
537     // Check CR0.WP?
538     return PT_ACCESS_USER_ERROR;
539   }
540
541   return PT_ACCESS_OK;
542 }
543
544
545 pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
546   pte32_t * entry = &pte[PTE32_INDEX(addr)];
547
548   if (entry->present == 0) {
549     return PT_ACCESS_NOT_PRESENT;
550   } else if ((entry->writable == 0) && (access_type.write == 1)) {
551     return PT_ACCESS_WRITE_ERROR;
552   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
553     // Check CR0.WP?
554     return PT_ACCESS_USER_ERROR;
555   }
556
557   return PT_ACCESS_OK;
558 }
559
560
561
562
563 /* We generate a page table to correspond to a given memory layout
564  * pulling pages from the mem_list when necessary
565  * If there are any gaps in the layout, we add them as unmapped pages
566  */
567 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
568   addr_t current_page_addr = 0;
569   int i, j;
570   struct shadow_map * map = &(guest_info->mem_map);
571
572   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
573
574   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
575     int pte_present = 0;
576     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
577     
578
579     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
580       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
581
582       if (!region || 
583           (region->host_type == HOST_REGION_HOOK) || 
584           (region->host_type == HOST_REGION_UNALLOCATED) || 
585           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
586           (region->host_type == HOST_REGION_REMOTE) ||
587           (region->host_type == HOST_REGION_SWAPPED)) {
588         pte[j].present = 0;
589         pte[j].writable = 0;
590         pte[j].user_page = 0;
591         pte[j].write_through = 0;
592         pte[j].cache_disable = 0;
593         pte[j].accessed = 0;
594         pte[j].dirty = 0;
595         pte[j].pte_attr = 0;
596         pte[j].global_page = 0;
597         pte[j].vmm_info = 0;
598         pte[j].page_base_addr = 0;
599       } else {
600         addr_t host_addr;
601         pte[j].present = 1;
602         pte[j].writable = 1;
603         pte[j].user_page = 1;
604         pte[j].write_through = 0;
605         pte[j].cache_disable = 0;
606         pte[j].accessed = 0;
607         pte[j].dirty = 0;
608         pte[j].pte_attr = 0;
609         pte[j].global_page = 0;
610         pte[j].vmm_info = 0;
611
612         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
613           // BIG ERROR
614           // PANIC
615           return NULL;
616         }
617         
618         pte[j].page_base_addr = host_addr >> 12;
619         
620         pte_present = 1;
621       }
622
623       current_page_addr += PAGE_SIZE;
624     }
625
626     if (pte_present == 0) { 
627       V3_FreePage(V3_PAddr(pte));
628
629       pde[i].present = 0;
630       pde[i].writable = 0;
631       pde[i].user_page = 0;
632       pde[i].write_through = 0;
633       pde[i].cache_disable = 0;
634       pde[i].accessed = 0;
635       pde[i].reserved = 0;
636       pde[i].large_page = 0;
637       pde[i].global_page = 0;
638       pde[i].vmm_info = 0;
639       pde[i].pt_base_addr = 0;
640     } else {
641       pde[i].present = 1;
642       pde[i].writable = 1;
643       pde[i].user_page = 1;
644       pde[i].write_through = 0;
645       pde[i].cache_disable = 0;
646       pde[i].accessed = 0;
647       pde[i].reserved = 0;
648       pde[i].large_page = 0;
649       pde[i].global_page = 0;
650       pde[i].vmm_info = 0;
651       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
652     }
653
654   }
655
656   return pde;
657 }
658
659
660 /* We generate a page table to correspond to a given memory layout
661  * pulling pages from the mem_list when necessary
662  * If there are any gaps in the layout, we add them as unmapped pages
663  */
664 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
665   addr_t current_page_addr = 0;
666   int i, j, k;
667   struct shadow_map * map = &(guest_info->mem_map);
668
669   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
670   memset(pdpe, 0, PAGE_SIZE);
671
672   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
673     int pde_present = 0;
674     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
675
676     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
677
678
679       int pte_present = 0;
680       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
681       
682       
683       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
684         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
685         
686         if (!region || 
687             (region->host_type == HOST_REGION_HOOK) || 
688             (region->host_type == HOST_REGION_UNALLOCATED) || 
689             (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
690             (region->host_type == HOST_REGION_REMOTE) ||
691             (region->host_type == HOST_REGION_SWAPPED)) {
692           pte[k].present = 0;
693           pte[k].writable = 0;
694           pte[k].user_page = 0;
695           pte[k].write_through = 0;
696           pte[k].cache_disable = 0;
697           pte[k].accessed = 0;
698           pte[k].dirty = 0;
699           pte[k].pte_attr = 0;
700           pte[k].global_page = 0;
701           pte[k].vmm_info = 0;
702           pte[k].page_base_addr = 0;
703           pte[k].rsvd = 0;
704         } else {
705           addr_t host_addr;
706           pte[k].present = 1;
707           pte[k].writable = 1;
708           pte[k].user_page = 1;
709           pte[k].write_through = 0;
710           pte[k].cache_disable = 0;
711           pte[k].accessed = 0;
712           pte[k].dirty = 0;
713           pte[k].pte_attr = 0;
714           pte[k].global_page = 0;
715           pte[k].vmm_info = 0;
716           
717           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
718             // BIG ERROR
719             // PANIC
720             return NULL;
721           }
722           
723           pte[k].page_base_addr = host_addr >> 12;
724           pte[k].rsvd = 0;
725
726           pte_present = 1;
727         }
728         
729         current_page_addr += PAGE_SIZE;
730       }
731       
732       if (pte_present == 0) { 
733         V3_FreePage(V3_PAddr(pte));
734         
735         pde[j].present = 0;
736         pde[j].writable = 0;
737         pde[j].user_page = 0;
738         pde[j].write_through = 0;
739         pde[j].cache_disable = 0;
740         pde[j].accessed = 0;
741         pde[j].avail = 0;
742         pde[j].large_page = 0;
743         pde[j].global_page = 0;
744         pde[j].vmm_info = 0;
745         pde[j].pt_base_addr = 0;
746         pde[j].rsvd = 0;
747       } else {
748         pde[j].present = 1;
749         pde[j].writable = 1;
750         pde[j].user_page = 1;
751         pde[j].write_through = 0;
752         pde[j].cache_disable = 0;
753         pde[j].accessed = 0;
754         pde[j].avail = 0;
755         pde[j].large_page = 0;
756         pde[j].global_page = 0;
757         pde[j].vmm_info = 0;
758         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
759         pde[j].rsvd = 0;
760
761         pde_present = 1;
762       }
763       
764     }
765     
766     if (pde_present == 0) { 
767       V3_FreePage(V3_PAddr(pde));
768       
769       pdpe[i].present = 0;
770       pdpe[i].rsvd = 0;
771       pdpe[i].write_through = 0;
772       pdpe[i].cache_disable = 0;
773       pdpe[i].accessed = 0;
774       pdpe[i].avail = 0;
775       pdpe[i].rsvd2 = 0;
776       pdpe[i].vmm_info = 0;
777       pdpe[i].pd_base_addr = 0;
778       pdpe[i].rsvd3 = 0;
779     } else {
780       pdpe[i].present = 1;
781       pdpe[i].rsvd = 0;
782       pdpe[i].write_through = 0;
783       pdpe[i].cache_disable = 0;
784       pdpe[i].accessed = 0;
785       pdpe[i].avail = 0;
786       pdpe[i].rsvd2 = 0;
787       pdpe[i].vmm_info = 0;
788       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
789       pdpe[i].rsvd3 = 0;
790     }
791     
792   }
793
794
795   return pdpe;
796 }
797
798
799
800
801
802
803 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
804   addr_t current_page_addr = 0;
805   int i, j, k, m;
806   struct shadow_map * map = &(info->mem_map);
807   
808   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
809
810   for (i = 0; i < 1; i++) {
811     int pdpe_present = 0;
812     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
813
814     for (j = 0; j < 20; j++) {
815       int pde_present = 0;
816       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
817
818       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
819         int pte_present = 0;
820         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
821
822
823         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
824           struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
825           
826
827           
828           if (!region || 
829               (region->host_type == HOST_REGION_HOOK) || 
830               (region->host_type == HOST_REGION_UNALLOCATED) || 
831               (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
832               (region->host_type == HOST_REGION_REMOTE) ||
833               (region->host_type == HOST_REGION_SWAPPED)) {
834             pte[m].present = 0;
835             pte[m].writable = 0;
836             pte[m].user_page = 0;
837             pte[m].write_through = 0;
838             pte[m].cache_disable = 0;
839             pte[m].accessed = 0;
840             pte[m].dirty = 0;
841             pte[m].pte_attr = 0;
842             pte[m].global_page = 0;
843             pte[m].vmm_info = 0;
844             pte[m].page_base_addr = 0;
845           } else {
846             addr_t host_addr;
847             pte[m].present = 1;
848             pte[m].writable = 1;
849             pte[m].user_page = 1;
850             pte[m].write_through = 0;
851             pte[m].cache_disable = 0;
852             pte[m].accessed = 0;
853             pte[m].dirty = 0;
854             pte[m].pte_attr = 0;
855             pte[m].global_page = 0;
856             pte[m].vmm_info = 0;
857             
858             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
859               // BIG ERROR
860               // PANIC
861               return NULL;
862             }
863
864             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
865
866             //PrintPTE64(current_page_addr, &(pte[m]));
867
868             pte_present = 1;      
869           }
870
871
872
873
874           current_page_addr += PAGE_SIZE;
875         }
876         
877         if (pte_present == 0) {
878           V3_FreePage(V3_PAddr(pte));
879
880           pde[k].present = 0;
881           pde[k].writable = 0;
882           pde[k].user_page = 0;
883           pde[k].write_through = 0;
884           pde[k].cache_disable = 0;
885           pde[k].accessed = 0;
886           pde[k].avail = 0;
887           pde[k].large_page = 0;
888           //pde[k].global_page = 0;
889           pde[k].vmm_info = 0;
890           pde[k].pt_base_addr = 0;
891         } else {
892           pde[k].present = 1;
893           pde[k].writable = 1;
894           pde[k].user_page = 1;
895           pde[k].write_through = 0;
896           pde[k].cache_disable = 0;
897           pde[k].accessed = 0;
898           pde[k].avail = 0;
899           pde[k].large_page = 0;
900           //pde[k].global_page = 0;
901           pde[k].vmm_info = 0;
902           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
903
904           pde_present = 1;
905         }
906       }
907
908       if (pde_present == 0) {
909         V3_FreePage(V3_PAddr(pde));
910         
911         pdpe[j].present = 0;
912         pdpe[j].writable = 0;
913         pdpe[j].user_page = 0;
914         pdpe[j].write_through = 0;
915         pdpe[j].cache_disable = 0;
916         pdpe[j].accessed = 0;
917         pdpe[j].avail = 0;
918         pdpe[j].large_page = 0;
919         //pdpe[j].global_page = 0;
920         pdpe[j].vmm_info = 0;
921         pdpe[j].pd_base_addr = 0;
922       } else {
923         pdpe[j].present = 1;
924         pdpe[j].writable = 1;
925         pdpe[j].user_page = 1;
926         pdpe[j].write_through = 0;
927         pdpe[j].cache_disable = 0;
928         pdpe[j].accessed = 0;
929         pdpe[j].avail = 0;
930         pdpe[j].large_page = 0;
931         //pdpe[j].global_page = 0;
932         pdpe[j].vmm_info = 0;
933         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
934
935
936         pdpe_present = 1;
937       }
938
939     }
940
941     PrintDebug("PML index=%d\n", i);
942
943     if (pdpe_present == 0) {
944       V3_FreePage(V3_PAddr(pdpe));
945       
946       pml[i].present = 0;
947       pml[i].writable = 0;
948       pml[i].user_page = 0;
949       pml[i].write_through = 0;
950       pml[i].cache_disable = 0;
951       pml[i].accessed = 0;
952       pml[i].reserved = 0;
953       //pml[i].large_page = 0;
954       //pml[i].global_page = 0;
955       pml[i].vmm_info = 0;
956       pml[i].pdp_base_addr = 0;
957     } else {
958       pml[i].present = 1;
959       pml[i].writable = 1;
960       pml[i].user_page = 1;
961       pml[i].write_through = 0;
962       pml[i].cache_disable = 0;
963       pml[i].accessed = 0;
964       pml[i].reserved = 0;
965       //pml[i].large_page = 0;
966       //pml[i].global_page = 0;
967       pml[i].vmm_info = 0;
968       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
969     }
970   }
971
972   return pml;
973 }
974
975
976
977