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 lookup functions for all page table forms,
[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 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((void *)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;
86       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
87         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
88                    (void *)guest_pte_pa);
89         return -1;
90       }
91
92       if (pte32_lookup(guest_pte, vaddr, paddr) == -1) {
93         return -1;
94       }
95     }
96   }
97
98   return 0;
99 }
100
101
102 int translate_host_pt_32(addr_t host_cr3, addr_t vaddr, addr_t * paddr) {
103   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA((void *)host_cr3);
104   pte32_t * host_pte = 0;
105     
106   switch (pde32_lookup(host_pde, vaddr, (addr_t *)&host_pte)) {
107   case PT_ENTRY_NOT_PRESENT:
108     *paddr = 0;
109     return -1;
110   case PT_ENTRY_LARGE_PAGE:
111     *paddr = (addr_t)host_pte;
112     return 0;
113   case PT_ENTRY_PAGE:
114     if (pte32_lookup(host_pte, vaddr, paddr) == -1) {
115       return -1;
116     }
117   }
118
119   return 0;
120 }
121
122
123 int translate_host_pt_32pae(addr_t host_cr3, addr_t vaddr, addr_t * paddr) {
124
125
126   return -1;
127 }
128
129
130 int translate_host_pt_64(addr_t host_cr3, addr_t vaddr, addr_t * paddr) {
131
132
133   return -1;
134 }
135
136
137
138
139
140 /*
141  * PAGE TABLE LOOKUP FUNCTIONS
142  *
143  *
144  * The value of entry is a return type:
145  * Page not present: *entry = 0
146  * Large Page: *entry = translated physical address (byte granularity)
147  * PTE entry: *entry is the address of the PTE Page
148  */
149
150 /**
151  * 
152  *  32 bit Page Table lookup functions
153  *
154  **/
155
156 pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
157   pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
158
159   if (!pde_entry->present) {
160     *entry = 0;
161     return PT_ENTRY_NOT_PRESENT;
162   } else if (pde_entry->large_page) {
163     pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry;
164
165     *entry = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
166     *entry += PAGE_OFFSET_4MB(addr);
167
168     return PT_ENTRY_LARGE_PAGE;
169   } else {
170     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
171     return PT_ENTRY_PAGE;
172   }
173 }
174
175
176
177 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
178  */
179 pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
180   pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
181
182   if (!pte_entry->present) {
183     *entry = 0;
184     //    PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
185     return PT_ENTRY_NOT_PRESENT;
186   } else {
187     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
188     return PT_ENTRY_PAGE;
189   }
190
191 }
192
193
194
195 /**
196  * 
197  *  32 bit PAE Page Table lookup functions
198  *
199  **/
200 pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) {
201   pdpe32pae_t * pdpe_entry = &(pdp[PDPE32PAE_INDEX(addr)]);
202   
203   if (!pdpe_entry->present) {
204     *entry = 0;
205     return PT_ENTRY_NOT_PRESENT;
206   } else {
207     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
208     return PT_ENTRY_PAGE;
209   }
210 }
211
212 pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) {
213   pde32pae_t * pde_entry = &(pd[PDE32PAE_INDEX(addr)]);
214
215   if (!pde_entry->present) {
216     *entry = 0;
217     return PT_ENTRY_NOT_PRESENT;
218   } else if (pde_entry->large_page) {
219     pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)pde_entry;
220
221     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
222     *entry += PAGE_OFFSET_2MB(addr);
223
224     return PT_ENTRY_LARGE_PAGE;
225   } else {
226     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
227     return PT_ENTRY_PAGE;
228   }
229 }
230
231 pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) {
232   pte32pae_t * pte_entry = &(pt[PTE32PAE_INDEX(addr)]);
233
234   if (!pte_entry->present) {
235     *entry = 0;
236     return PT_ENTRY_NOT_PRESENT;
237   } else {
238     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
239     return PT_ENTRY_PAGE;
240   }
241 }
242
243
244
245 /**
246  * 
247  *  64 bit Page Table lookup functions
248  *
249  **/
250 pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) {
251   pml4e64_t * pml_entry = &(pml[PML4E64_INDEX(addr)]);
252
253   if (!pml_entry->present) {
254     *entry = 0;
255     return PT_ENTRY_NOT_PRESENT;
256   } else {
257     *entry = BASE_TO_PAGE_ADDR(pml_entry->pdp_base_addr);
258     return PT_ENTRY_PAGE;
259   }
260 }
261
262 pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) {
263   pdpe64_t * pdpe_entry = &(pdp[PDPE64_INDEX(addr)]);
264   
265   if (!pdpe_entry->present) {
266     *entry = 0;
267     return PT_ENTRY_NOT_PRESENT;
268   } else if (pdpe_entry->large_page) {
269     PrintError("1 Gigabyte pages not supported\n");
270     V3_ASSERT(0);
271     return -1;
272   } else {
273     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
274     return PT_ENTRY_PAGE;
275   }
276 }
277
278 pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) {
279   pde64_t * pde_entry = &(pd[PDE64_INDEX(addr)]);
280
281   if (!pde_entry->present) {
282     *entry = 0;
283     return PT_ENTRY_NOT_PRESENT;
284   } else if (pde_entry->large_page) {
285     pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry;
286
287     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
288     *entry += PAGE_OFFSET_2MB(addr);
289
290     return PT_ENTRY_LARGE_PAGE;
291   } else {
292     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
293     return PT_ENTRY_PAGE;
294   }
295 }
296
297 pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) {
298   pte64_t * pte_entry = &(pt[PTE64_INDEX(addr)]);
299
300   if (!pte_entry->present) {
301     *entry = 0;
302     return PT_ENTRY_NOT_PRESENT;
303   } else {
304     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
305     return PT_ENTRY_PAGE;
306   }
307 }
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325 pt_access_status_t can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
326   pde32_t * entry = &pde[PDE32_INDEX(addr)];
327
328   if (entry->present == 0) {
329     return PT_ACCESS_NOT_PRESENT;
330   } else if ((entry->writable == 0) && (access_type.write == 1)) {
331     return PT_ACCESS_WRITE_ERROR;
332   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
333     // Check CR0.WP?
334     return PT_ACCESS_USER_ERROR;
335   }
336
337   return PT_ACCESS_OK;
338 }
339
340
341 pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
342   pte32_t * entry = &pte[PTE32_INDEX(addr)];
343
344   if (entry->present == 0) {
345     return PT_ACCESS_NOT_PRESENT;
346   } else if ((entry->writable == 0) && (access_type.write == 1)) {
347     return PT_ACCESS_WRITE_ERROR;
348   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
349     // Check CR0.WP?
350     return PT_ACCESS_USER_ERROR;
351   }
352
353   return PT_ACCESS_OK;
354 }
355
356
357
358
359 /* We generate a page table to correspond to a given memory layout
360  * pulling pages from the mem_list when necessary
361  * If there are any gaps in the layout, we add them as unmapped pages
362  */
363 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
364   addr_t current_page_addr = 0;
365   int i, j;
366   struct shadow_map * map = &(guest_info->mem_map);
367
368   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
369
370   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
371     int pte_present = 0;
372     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
373     
374
375     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
376       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
377
378       if (!region || 
379           (region->host_type == HOST_REGION_HOOK) || 
380           (region->host_type == HOST_REGION_UNALLOCATED) || 
381           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
382           (region->host_type == HOST_REGION_REMOTE) ||
383           (region->host_type == HOST_REGION_SWAPPED)) {
384         pte[j].present = 0;
385         pte[j].writable = 0;
386         pte[j].user_page = 0;
387         pte[j].write_through = 0;
388         pte[j].cache_disable = 0;
389         pte[j].accessed = 0;
390         pte[j].dirty = 0;
391         pte[j].pte_attr = 0;
392         pte[j].global_page = 0;
393         pte[j].vmm_info = 0;
394         pte[j].page_base_addr = 0;
395       } else {
396         addr_t host_addr;
397         pte[j].present = 1;
398         pte[j].writable = 1;
399         pte[j].user_page = 1;
400         pte[j].write_through = 0;
401         pte[j].cache_disable = 0;
402         pte[j].accessed = 0;
403         pte[j].dirty = 0;
404         pte[j].pte_attr = 0;
405         pte[j].global_page = 0;
406         pte[j].vmm_info = 0;
407
408         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
409           // BIG ERROR
410           // PANIC
411           return NULL;
412         }
413         
414         pte[j].page_base_addr = host_addr >> 12;
415         
416         pte_present = 1;
417       }
418
419       current_page_addr += PAGE_SIZE;
420     }
421
422     if (pte_present == 0) { 
423       V3_FreePage(V3_PAddr(pte));
424
425       pde[i].present = 0;
426       pde[i].writable = 0;
427       pde[i].user_page = 0;
428       pde[i].write_through = 0;
429       pde[i].cache_disable = 0;
430       pde[i].accessed = 0;
431       pde[i].reserved = 0;
432       pde[i].large_page = 0;
433       pde[i].global_page = 0;
434       pde[i].vmm_info = 0;
435       pde[i].pt_base_addr = 0;
436     } else {
437       pde[i].present = 1;
438       pde[i].writable = 1;
439       pde[i].user_page = 1;
440       pde[i].write_through = 0;
441       pde[i].cache_disable = 0;
442       pde[i].accessed = 0;
443       pde[i].reserved = 0;
444       pde[i].large_page = 0;
445       pde[i].global_page = 0;
446       pde[i].vmm_info = 0;
447       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
448     }
449
450   }
451
452   return pde;
453 }
454
455
456 /* We generate a page table to correspond to a given memory layout
457  * pulling pages from the mem_list when necessary
458  * If there are any gaps in the layout, we add them as unmapped pages
459  */
460 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
461   addr_t current_page_addr = 0;
462   int i, j, k;
463   struct shadow_map * map = &(guest_info->mem_map);
464
465   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
466   memset(pdpe, 0, PAGE_SIZE);
467
468   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
469     int pde_present = 0;
470     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
471
472     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
473
474
475       int pte_present = 0;
476       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
477       
478       
479       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
480         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
481         
482         if (!region || 
483             (region->host_type == HOST_REGION_HOOK) || 
484             (region->host_type == HOST_REGION_UNALLOCATED) || 
485             (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
486             (region->host_type == HOST_REGION_REMOTE) ||
487             (region->host_type == HOST_REGION_SWAPPED)) {
488           pte[k].present = 0;
489           pte[k].writable = 0;
490           pte[k].user_page = 0;
491           pte[k].write_through = 0;
492           pte[k].cache_disable = 0;
493           pte[k].accessed = 0;
494           pte[k].dirty = 0;
495           pte[k].pte_attr = 0;
496           pte[k].global_page = 0;
497           pte[k].vmm_info = 0;
498           pte[k].page_base_addr = 0;
499           pte[k].rsvd = 0;
500         } else {
501           addr_t host_addr;
502           pte[k].present = 1;
503           pte[k].writable = 1;
504           pte[k].user_page = 1;
505           pte[k].write_through = 0;
506           pte[k].cache_disable = 0;
507           pte[k].accessed = 0;
508           pte[k].dirty = 0;
509           pte[k].pte_attr = 0;
510           pte[k].global_page = 0;
511           pte[k].vmm_info = 0;
512           
513           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
514             // BIG ERROR
515             // PANIC
516             return NULL;
517           }
518           
519           pte[k].page_base_addr = host_addr >> 12;
520           pte[k].rsvd = 0;
521
522           pte_present = 1;
523         }
524         
525         current_page_addr += PAGE_SIZE;
526       }
527       
528       if (pte_present == 0) { 
529         V3_FreePage(V3_PAddr(pte));
530         
531         pde[j].present = 0;
532         pde[j].writable = 0;
533         pde[j].user_page = 0;
534         pde[j].write_through = 0;
535         pde[j].cache_disable = 0;
536         pde[j].accessed = 0;
537         pde[j].avail = 0;
538         pde[j].large_page = 0;
539         pde[j].global_page = 0;
540         pde[j].vmm_info = 0;
541         pde[j].pt_base_addr = 0;
542         pde[j].rsvd = 0;
543       } else {
544         pde[j].present = 1;
545         pde[j].writable = 1;
546         pde[j].user_page = 1;
547         pde[j].write_through = 0;
548         pde[j].cache_disable = 0;
549         pde[j].accessed = 0;
550         pde[j].avail = 0;
551         pde[j].large_page = 0;
552         pde[j].global_page = 0;
553         pde[j].vmm_info = 0;
554         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
555         pde[j].rsvd = 0;
556
557         pde_present = 1;
558       }
559       
560     }
561     
562     if (pde_present == 0) { 
563       V3_FreePage(V3_PAddr(pde));
564       
565       pdpe[i].present = 0;
566       pdpe[i].rsvd = 0;
567       pdpe[i].write_through = 0;
568       pdpe[i].cache_disable = 0;
569       pdpe[i].accessed = 0;
570       pdpe[i].avail = 0;
571       pdpe[i].rsvd2 = 0;
572       pdpe[i].vmm_info = 0;
573       pdpe[i].pd_base_addr = 0;
574       pdpe[i].rsvd3 = 0;
575     } else {
576       pdpe[i].present = 1;
577       pdpe[i].rsvd = 0;
578       pdpe[i].write_through = 0;
579       pdpe[i].cache_disable = 0;
580       pdpe[i].accessed = 0;
581       pdpe[i].avail = 0;
582       pdpe[i].rsvd2 = 0;
583       pdpe[i].vmm_info = 0;
584       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
585       pdpe[i].rsvd3 = 0;
586     }
587     
588   }
589
590
591   return pdpe;
592 }
593
594
595
596
597
598
599 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
600   addr_t current_page_addr = 0;
601   int i, j, k, m;
602   struct shadow_map * map = &(info->mem_map);
603   
604   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
605
606   for (i = 0; i < 1; i++) {
607     int pdpe_present = 0;
608     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
609
610     for (j = 0; j < 20; j++) {
611       int pde_present = 0;
612       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
613
614       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
615         int pte_present = 0;
616         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
617
618
619         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
620           struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
621           
622
623           
624           if (!region || 
625               (region->host_type == HOST_REGION_HOOK) || 
626               (region->host_type == HOST_REGION_UNALLOCATED) || 
627               (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
628               (region->host_type == HOST_REGION_REMOTE) ||
629               (region->host_type == HOST_REGION_SWAPPED)) {
630             pte[m].present = 0;
631             pte[m].writable = 0;
632             pte[m].user_page = 0;
633             pte[m].write_through = 0;
634             pte[m].cache_disable = 0;
635             pte[m].accessed = 0;
636             pte[m].dirty = 0;
637             pte[m].pte_attr = 0;
638             pte[m].global_page = 0;
639             pte[m].vmm_info = 0;
640             pte[m].page_base_addr = 0;
641           } else {
642             addr_t host_addr;
643             pte[m].present = 1;
644             pte[m].writable = 1;
645             pte[m].user_page = 1;
646             pte[m].write_through = 0;
647             pte[m].cache_disable = 0;
648             pte[m].accessed = 0;
649             pte[m].dirty = 0;
650             pte[m].pte_attr = 0;
651             pte[m].global_page = 0;
652             pte[m].vmm_info = 0;
653             
654             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
655               // BIG ERROR
656               // PANIC
657               return NULL;
658             }
659
660             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
661
662             //PrintPTE64(current_page_addr, &(pte[m]));
663
664             pte_present = 1;      
665           }
666
667
668
669
670           current_page_addr += PAGE_SIZE;
671         }
672         
673         if (pte_present == 0) {
674           V3_FreePage(V3_PAddr(pte));
675
676           pde[k].present = 0;
677           pde[k].writable = 0;
678           pde[k].user_page = 0;
679           pde[k].write_through = 0;
680           pde[k].cache_disable = 0;
681           pde[k].accessed = 0;
682           pde[k].avail = 0;
683           pde[k].large_page = 0;
684           //pde[k].global_page = 0;
685           pde[k].vmm_info = 0;
686           pde[k].pt_base_addr = 0;
687         } else {
688           pde[k].present = 1;
689           pde[k].writable = 1;
690           pde[k].user_page = 1;
691           pde[k].write_through = 0;
692           pde[k].cache_disable = 0;
693           pde[k].accessed = 0;
694           pde[k].avail = 0;
695           pde[k].large_page = 0;
696           //pde[k].global_page = 0;
697           pde[k].vmm_info = 0;
698           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
699
700           pde_present = 1;
701         }
702       }
703
704       if (pde_present == 0) {
705         V3_FreePage(V3_PAddr(pde));
706         
707         pdpe[j].present = 0;
708         pdpe[j].writable = 0;
709         pdpe[j].user_page = 0;
710         pdpe[j].write_through = 0;
711         pdpe[j].cache_disable = 0;
712         pdpe[j].accessed = 0;
713         pdpe[j].avail = 0;
714         pdpe[j].large_page = 0;
715         //pdpe[j].global_page = 0;
716         pdpe[j].vmm_info = 0;
717         pdpe[j].pd_base_addr = 0;
718       } else {
719         pdpe[j].present = 1;
720         pdpe[j].writable = 1;
721         pdpe[j].user_page = 1;
722         pdpe[j].write_through = 0;
723         pdpe[j].cache_disable = 0;
724         pdpe[j].accessed = 0;
725         pdpe[j].avail = 0;
726         pdpe[j].large_page = 0;
727         //pdpe[j].global_page = 0;
728         pdpe[j].vmm_info = 0;
729         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
730
731
732         pdpe_present = 1;
733       }
734
735     }
736
737     PrintDebug("PML index=%d\n", i);
738
739     if (pdpe_present == 0) {
740       V3_FreePage(V3_PAddr(pdpe));
741       
742       pml[i].present = 0;
743       pml[i].writable = 0;
744       pml[i].user_page = 0;
745       pml[i].write_through = 0;
746       pml[i].cache_disable = 0;
747       pml[i].accessed = 0;
748       pml[i].reserved = 0;
749       //pml[i].large_page = 0;
750       //pml[i].global_page = 0;
751       pml[i].vmm_info = 0;
752       pml[i].pdp_base_addr = 0;
753     } else {
754       pml[i].present = 1;
755       pml[i].writable = 1;
756       pml[i].user_page = 1;
757       pml[i].write_through = 0;
758       pml[i].cache_disable = 0;
759       pml[i].accessed = 0;
760       pml[i].reserved = 0;
761       //pml[i].large_page = 0;
762       //pml[i].global_page = 0;
763       pml[i].vmm_info = 0;
764       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
765     }
766   }
767
768   return pml;
769 }
770
771
772
773