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.


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