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.


started the emulation framework
[palacios.git] / palacios / src / palacios / vmm_shadow_paging.c
1 #include <palacios/vmm_shadow_paging.h>
2
3
4 #include <palacios/vmm.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_decoder.h>
7
8 #ifndef DEBUG_SHADOW_PAGING
9 #undef PrintDebug
10 #define PrintDebug(fmt, args...)
11 #endif
12
13
14 /*** 
15  ***  There be dragons
16  ***/
17
18
19
20
21 static int handle_shadow_pte32_fault(struct guest_info* info, 
22                                      addr_t fault_addr, 
23                                      pf_error_t error_code,
24                                      pte32_t * shadow_pte, 
25                                      pte32_t * guest_pte);
26
27 static int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code);
28
29 int init_shadow_page_state(struct guest_info * info) {
30   struct shadow_page_state * state = &(info->shdw_pg_state);
31   state->guest_mode = PDE32;
32   state->shadow_mode = PDE32;
33   
34   state->guest_cr3 = 0;
35   state->shadow_cr3 = 0;
36
37   return 0;
38 }
39
40 int handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
41   
42   if (info->mem_mode == PHYSICAL_MEM) {
43     // If paging is not turned on we need to handle the special cases
44     return handle_special_page_fault(info, fault_addr, fault_addr, error_code);
45   } else if (info->mem_mode == VIRTUAL_MEM) {
46
47     switch (info->cpu_mode) {
48     case PROTECTED:
49       return handle_shadow_pagefault32(info, fault_addr, error_code);
50       break;
51     case PROTECTED_PAE:
52     case LONG:
53     default:
54       PrintError("Unhandled CPU Mode\n");
55       return -1;
56     }
57   } else {
58     PrintError("Invalid Memory mode\n");
59     return -1;
60   }
61 }
62
63 addr_t create_new_shadow_pt32() {
64   void * host_pde = 0;
65
66   host_pde = V3_AllocPages(1);
67   memset(host_pde, 0, PAGE_SIZE);
68
69   return (addr_t)host_pde;
70 }
71
72
73 static void inject_guest_pf(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
74   info->ctrl_regs.cr2 = fault_addr;
75   v3_raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
76 }
77
78
79 static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
80   /* basically the reasoning is that there can be multiple reasons for a page fault:
81      If there is a permissions failure for a page present in the guest _BUT_ 
82      the reason for the fault was that the page is not present in the shadow, 
83      _THEN_ we have to map the shadow page in and reexecute, this will generate 
84      a permissions fault which is _THEN_ valid to send to the guest
85      _UNLESS_ both the guest and shadow have marked the page as not present
86
87      whew...
88   */
89   if (guest_access != PT_ACCESS_OK) {
90     // Guest Access Error
91     
92     if ((shadow_access != PT_ENTRY_NOT_PRESENT) &&
93         (guest_access != PT_ENTRY_NOT_PRESENT)) {
94       // aka (guest permission error)
95       return 1;
96     }
97
98     if ((shadow_access == PT_ENTRY_NOT_PRESENT) &&
99         (guest_access == PT_ENTRY_NOT_PRESENT)) {      
100       // Page tables completely blank, handle guest first
101       return 1;
102     }
103
104     // Otherwise we'll handle the guest fault later...?
105   }
106
107   return 0;
108 }
109
110
111
112
113 /* The guest status checks have already been done,
114  * only special case shadow checks remain
115  */
116 static int handle_large_pagefault32(struct guest_info * info, 
117                                     addr_t fault_addr, pf_error_t error_code, 
118                                     pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde) 
119 {
120   pt_access_status_t shadow_pte_access = can_access_pte32(shadow_pt, fault_addr, error_code);
121   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
122   
123   if (shadow_pte_access == PT_ACCESS_OK) {
124     // Inconsistent state...
125     // Guest Re-Entry will flush tables and everything should now workd
126     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
127     return 0;
128   }
129
130   
131   if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
132     // Get the guest physical address of the fault
133     addr_t guest_fault_pa = PDE32_4MB_T_ADDR(*large_guest_pde) + PD32_4MB_PAGE_OFFSET(fault_addr);
134     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
135  
136
137     if (host_page_type == HOST_REGION_INVALID) {
138       // Inject a machine check in the guest
139       PrintDebug("Invalid Guest Address in page table (0x%x)\n", guest_fault_pa);
140       v3_raise_exception(info, MC_EXCEPTION);
141       return 0;
142     }
143
144     if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
145       addr_t shadow_pa = get_shadow_addr(info, guest_fault_pa);
146
147       shadow_pte->page_base_addr = PT32_BASE_ADDR(shadow_pa);
148
149       shadow_pte->present = 1;
150
151       /* We are assuming that the PDE entry has precedence
152        * so the Shadow PDE will mirror the guest PDE settings, 
153        * and we don't have to worry about them here
154        * Allow everything
155        */
156       shadow_pte->user_page = 1;
157       shadow_pte->writable = 1;
158
159       //set according to VMM policy
160       shadow_pte->write_through = 0;
161       shadow_pte->cache_disable = 0;
162       shadow_pte->global_page = 0;
163       //
164       
165     } else {
166       // Handle hooked pages as well as other special pages
167       if (handle_special_page_fault(info, fault_addr, PT32_PAGE_ADDR(guest_fault_pa), error_code) == -1) {
168         PrintError("Special Page Fault handler returned error for address: %x\n", fault_addr);
169         return -1;
170       }
171     }
172   } else {
173     PrintError("Error in large page fault handler...\n");
174     PrintError("This case should have been handled at the top level handler\n");
175     return -1;
176   }
177
178   PrintDebug("Returning from large page fault handler\n");
179   return 0;
180 }
181
182
183 static int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
184   pde32_t * guest_pd = NULL;
185   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3);
186   addr_t guest_cr3 = CR3_TO_PDE32(info->shdw_pg_state.guest_cr3);
187   pt_access_status_t guest_pde_access;
188   pt_access_status_t shadow_pde_access;
189   pde32_t * guest_pde = NULL;
190   pde32_t * shadow_pde = (pde32_t *)&(shadow_pd[PDE32_INDEX(fault_addr)]);
191
192   PrintDebug("Shadow page fault handler\n");
193
194   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
195     PrintError("Invalid Guest PDE Address: 0x%x\n", guest_cr3);
196     return -1;
197   } 
198
199   guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(fault_addr)]);
200
201
202   // Check the guest page permissions
203   guest_pde_access = can_access_pde32(guest_pd, fault_addr, error_code);
204
205   // Check the shadow page permissions
206   shadow_pde_access = can_access_pde32(shadow_pd, fault_addr, error_code);
207   
208   /* Was the page fault caused by the Guest's page tables? */
209   if (is_guest_pf(guest_pde_access, shadow_pde_access) == 1) {
210     PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
211                guest_pde_access, error_code);
212     inject_guest_pf(info, fault_addr, error_code);
213     return 0;
214   }
215
216   
217   if (shadow_pde_access == PT_ENTRY_NOT_PRESENT) 
218     {
219       pte32_t * shadow_pt =  (pte32_t *)create_new_shadow_pt32();
220
221       shadow_pde->present = 1;
222       shadow_pde->user_page = guest_pde->user_page;
223       //    shadow_pde->large_page = guest_pde->large_page;
224       shadow_pde->large_page = 0;
225       
226
227       // VMM Specific options
228       shadow_pde->write_through = 0;
229       shadow_pde->cache_disable = 0;
230       shadow_pde->global_page = 0;
231       //
232       
233       guest_pde->accessed = 1;
234       
235       shadow_pde->pt_base_addr = PD32_BASE_ADDR(shadow_pt);
236       
237       if (guest_pde->large_page == 0) {
238         shadow_pde->writable = guest_pde->writable;
239       } else {
240         ((pde32_4MB_t *)guest_pde)->dirty = 0;
241         shadow_pde->writable = 0;
242       }
243     }
244   else if (shadow_pde_access == PT_ACCESS_OK) 
245     {
246       //
247       // PTE fault
248       //
249       pte32_t * shadow_pt = (pte32_t *)PDE32_T_ADDR((*shadow_pde));
250
251       if (guest_pde->large_page == 0) {
252         pte32_t * guest_pt = NULL;
253         if (guest_pa_to_host_va(info, PDE32_T_ADDR((*guest_pde)), (addr_t*)&guest_pt) == -1) {
254           // Machine check the guest
255           PrintDebug("Invalid Guest PTE Address: 0x%x\n", PDE32_T_ADDR((*guest_pde)));
256           v3_raise_exception(info, MC_EXCEPTION);
257           return 0;
258         }
259         
260         if (handle_shadow_pte32_fault(info, fault_addr, error_code, shadow_pt, guest_pt)  == -1) {
261           PrintError("Error handling Page fault caused by PTE\n");
262           return -1;
263         }
264       } else if (guest_pde->large_page == 1) {
265         if (handle_large_pagefault32(info, fault_addr, error_code, shadow_pt, (pde32_4MB_t *)guest_pde) == -1) {
266           PrintError("Error handling large pagefault\n");
267           return -1;
268         }
269       }
270     }
271   else if ((shadow_pde_access == PT_WRITE_ERROR) && 
272            (guest_pde->large_page == 1) && 
273            (((pde32_4MB_t *)guest_pde)->dirty == 0)) 
274     {
275       //
276       // Page Directory Entry marked read-only
277       // Its a large page and we need to update the dirty bit in the guest
278       //
279       PrintDebug("Large page write error... Setting dirty bit and returning\n");
280       ((pde32_4MB_t *)guest_pde)->dirty = 1;
281       shadow_pde->writable = guest_pde->writable;
282       return 0;
283       
284     } 
285   else if (shadow_pde_access == PT_USER_ERROR) 
286     {
287       //
288       // Page Directory Entry marked non-user
289       //      
290       PrintDebug("Shadow Paging User access error (shadow_pde_access=0x%x, guest_pde_access=0x%x)\n", 
291                  shadow_pde_access, guest_pde_access);
292       inject_guest_pf(info, fault_addr, error_code);
293       return 0;
294     }
295   else 
296     {
297       // inject page fault in guest
298       inject_guest_pf(info, fault_addr, error_code);
299       PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pde_access);
300       PrintDebug("Manual Says to inject page fault into guest\n");
301 #ifdef DEBUG_SHADOW_PAGING
302       PrintDebug("Guest PDE: (access=%d)\n\t", guest_pde_access);
303       PrintPDE32(fault_addr, guest_pde);
304       PrintDebug("Shadow PDE: (access=%d)\n\t", shadow_pde_access);
305       PrintPDE32(fault_addr, shadow_pde);
306 #endif
307
308       return 0; 
309     }
310
311   PrintDebug("Returning end of PDE function (rip=%x)\n", info->rip);
312   return 0;
313 }
314
315
316
317 /* 
318  * We assume the the guest pte pointer has already been translated to a host virtual address
319  */
320 static int handle_shadow_pte32_fault(struct guest_info * info, 
321                                      addr_t fault_addr, 
322                                      pf_error_t error_code,
323                                      pte32_t * shadow_pt, 
324                                      pte32_t * guest_pt) {
325
326   pt_access_status_t guest_pte_access;
327   pt_access_status_t shadow_pte_access;
328   pte32_t * guest_pte = (pte32_t *)&(guest_pt[PTE32_INDEX(fault_addr)]);;
329   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
330
331
332   // Check the guest page permissions
333   guest_pte_access = can_access_pte32(guest_pt, fault_addr, error_code);
334
335   // Check the shadow page permissions
336   shadow_pte_access = can_access_pte32(shadow_pt, fault_addr, error_code);
337   
338 #ifdef DEBUG_SHADOW_PAGING
339   PrintDebug("Guest PTE: (access=%d)\n\t", guest_pte_access);
340   PrintPTE32(fault_addr, guest_pte);
341   PrintDebug("Shadow PTE: (access=%d)\n\t", shadow_pte_access);
342   PrintPTE32(fault_addr, shadow_pte);
343 #endif
344   
345   /* Was the page fault caused by the Guest's page tables? */
346   if (is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
347     PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
348                guest_pte_access, *(uint_t*)&error_code);    
349     inject_guest_pf(info, fault_addr, error_code);
350     return 0; 
351   }
352   
353   
354   if (shadow_pte_access == PT_ACCESS_OK) {
355     // Inconsistent state...
356     // Guest Re-Entry will flush page tables and everything should now work
357     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
358     return 0;
359   }
360
361
362   if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
363
364     addr_t guest_pa = PTE32_T_ADDR((*guest_pte));
365
366     // Page Table Entry Not Present
367
368     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
369
370     if (host_page_type == HOST_REGION_INVALID) {
371       // Inject a machine check in the guest
372       PrintDebug("Invalid Guest Address in page table (0x%x)\n", guest_pa);
373       v3_raise_exception(info, MC_EXCEPTION);
374       return 0;
375     }
376
377     // else...
378
379     if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
380       addr_t shadow_pa = get_shadow_addr(info, guest_pa);
381       
382       shadow_pte->page_base_addr = PT32_BASE_ADDR(shadow_pa);
383       
384       shadow_pte->present = guest_pte->present;
385       shadow_pte->user_page = guest_pte->user_page;
386       
387       //set according to VMM policy
388       shadow_pte->write_through = 0;
389       shadow_pte->cache_disable = 0;
390       shadow_pte->global_page = 0;
391       //
392       
393       guest_pte->accessed = 1;
394       
395       if (guest_pte->dirty == 1) {
396         shadow_pte->writable = guest_pte->writable;
397       } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
398         shadow_pte->writable = guest_pte->writable;
399         guest_pte->dirty = 1;
400       } else if ((guest_pte->dirty = 0) && (error_code.write == 0)) {
401         shadow_pte->writable = 0;
402       }
403     } else {
404       // Page fault handled by hook functions
405       if (handle_special_page_fault(info, fault_addr, guest_pa, error_code) == -1) {
406         PrintError("Special Page fault handler returned error for address: %x\n", fault_addr);
407         return -1;
408       }
409     }
410
411   } else if ((shadow_pte_access == PT_WRITE_ERROR) &&
412              (guest_pte->dirty == 0)) {
413
414     PrintDebug("Shadow PTE Write Error\n");
415     guest_pte->dirty = 1;
416     shadow_pte->writable = guest_pte->writable;
417     return 0;
418
419   } else {
420     // Inject page fault into the guest 
421     inject_guest_pf(info, fault_addr, error_code);
422     PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
423     PrintError("Manual Says to inject page fault into guest\n");
424     return -1;
425   }
426
427   PrintDebug("Returning end of function\n");
428   return 0;
429 }
430
431
432
433
434
435
436 /* Currently Does not work with Segmentation!!! */
437 int handle_shadow_invlpg(struct guest_info * info) {
438   if (info->mem_mode != VIRTUAL_MEM) {
439     // Paging must be turned on...
440     // should handle with some sort of fault I think
441     PrintError("ERROR: INVLPG called in non paged mode\n");
442     return -1;
443   }
444
445
446   if (info->cpu_mode == PROTECTED) {
447     char instr[15];
448     int ret;
449     int index = 0;
450
451     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
452     if (ret != 15) {
453       PrintError("Could not read instruction 0x%x (ret=%d)\n", info->rip, ret);
454       return -1;
455     }
456
457    
458     /* Can INVLPG work with Segments?? */
459     while (is_prefix_byte(instr[index])) {
460       index++;
461     }
462     
463     
464     if ((instr[index] == (uchar_t)0x0f) &&
465         (instr[index + 1] == (uchar_t)0x01)) {
466
467       addr_t first_operand;
468       addr_t second_operand;
469       operand_type_t addr_type;
470       addr_t guest_cr3 = CR3_TO_PDE32(info->shdw_pg_state.guest_cr3);
471
472       pde32_t * guest_pd = NULL;
473
474       if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
475         PrintError("Invalid Guest PDE Address: 0x%x\n", guest_cr3);
476         return -1;
477       }
478
479       
480
481
482       index += 2;
483
484       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
485
486       if (addr_type == MEM_OPERAND) {
487         pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3);
488         pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)];
489         pde32_t * guest_pde;
490
491         //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand));
492         //PrintDebug("FirstOperand = %x\n", first_operand);
493
494         PrintDebug("Invalidating page for %x\n", first_operand);
495
496         guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(first_operand)]);
497
498         if (guest_pde->large_page == 1) {
499           shadow_pde->present = 0;
500           PrintDebug("Invalidating Large Page\n");
501         } else {
502          
503           if (shadow_pde->present == 1) {
504             pte32_t * shadow_pt = (pte32_t *)PDE32_T_ADDR((*shadow_pde));
505             pte32_t * shadow_pte = (pte32_t *)&shadow_pt[PTE32_INDEX(first_operand)];
506
507 #ifdef DEBUG_SHADOW_PAGING
508             PrintDebug("Setting not present\n");
509             PrintPTE32(first_operand, shadow_pte);
510 #endif
511
512             shadow_pte->present = 0;
513           }
514         }
515
516         info->rip += index;
517
518       } else {
519         PrintError("Invalid Operand type\n");
520         return -1;
521       }
522     } else {
523       PrintError("invalid Instruction Opcode\n");
524       PrintTraceMemDump(instr, 15);
525       return -1;
526     }
527   }
528
529   return 0;
530 }
531
532
533 /*
534
535
536 static int create_pd32_nonaligned_4MB_page(struct guest_info * info, pte32_t * pt, addr_t guest_addr, pde32_4MB_t * large_shadow_pde) {
537   uint_t i = 0;
538   pte32_t * pte_cursor;
539   addr_t guest_pa = 0;
540
541   for (i = 0; i < 1024; i++) {
542     guest_pa = guest_addr + (PAGE_SIZE * i);
543     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
544     
545     pte_cursor = &(pt[i]);
546
547     if (host_page_type == HOST_REGION_INVALID) {
548       // Currently we don't support this, but in theory we could
549       PrintError("Invalid Host Memory Type\n");
550       return -1;
551     } else if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
552       addr_t shadow_pa = get_shadow_addr(info, guest_pa);
553
554
555       pte_cursor->page_base_addr = PT32_BASE_ADDR(shadow_pa);
556       pte_cursor->present = 1;
557       pte_cursor->writable = large_shadow_pde->writable;
558       pte_cursor->user_page = large_shadow_pde->user_page;
559       pte_cursor->write_through = 0;  
560       pte_cursor->cache_disable = 0;
561       pte_cursor->global_page = 0;
562
563     } else {
564       PrintError("Unsupported Host Memory Type\n");
565       return -1;
566     }
567   }
568   return 0;
569 }
570
571
572 static int handle_large_pagefault32(struct guest_info * info, 
573                                     pde32_t * guest_pde, pde32_t * shadow_pde, 
574                                     addr_t fault_addr, pf_error_t error_code ) {
575   struct shadow_region * mem_reg;
576   pde32_4MB_t * large_guest_pde = (pde32_4MB_t *)guest_pde;
577   pde32_4MB_t * large_shadow_pde = (pde32_4MB_t *)shadow_pde;
578   host_region_type_t host_page_type;
579   addr_t guest_start_addr = PDE32_4MB_T_ADDR(*large_guest_pde);
580   //    addr_t guest_end_addr = guest_start_addr + PAGE_SIZE_4MB; // start address + 4MB
581   
582   
583   // Check that the Guest PDE entry points to valid memory
584   // else Machine Check the guest
585   PrintDebug("Large Page: Page Base Addr=%x\n", guest_start_addr);
586   
587   host_page_type = get_shadow_addr_type(info, guest_start_addr);
588   
589   if (host_page_type == HOST_REGION_INVALID) {
590     PrintError("Invalid guest address in large page (0x%x)\n", guest_start_addr);
591     v3_raise_exception(info, MC_EXCEPTION);
592     return -1;
593   }
594   
595   // else...
596
597   if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
598
599     addr_t host_start_addr = 0;
600     addr_t region_end_addr = 0;
601     
602     // Check for a large enough region in host memory
603     mem_reg = get_shadow_region_by_addr(&(info->mem_map), guest_start_addr);
604     PrintDebug("Host region: host_addr=%x (guest_start=%x, end=%x)\n", 
605                mem_reg->host_addr, mem_reg->guest_start, mem_reg->guest_end);
606     host_start_addr = mem_reg->host_addr + (guest_start_addr - mem_reg->guest_start);
607     region_end_addr = mem_reg->host_addr + (mem_reg->guest_end - mem_reg->guest_start);
608     
609     PrintDebug("Host Start Addr=%x; Region End Addr=%x\n", host_start_addr, region_end_addr);
610     
611     
612     //4f
613     if (large_guest_pde->dirty == 1) { // dirty
614       large_shadow_pde->writable = guest_pde->writable;
615     } else if (error_code.write == 1) { // not dirty, access is write
616       large_shadow_pde->writable = guest_pde->writable;
617       large_guest_pde->dirty = 1;
618     } else { // not dirty, access is read
619       large_shadow_pde->writable = 0;
620     }
621     
622     
623     // Check if the region is at least an additional 4MB
624     
625     
626     //4b.
627     if ((PD32_4MB_PAGE_OFFSET(host_start_addr) == 0) && 
628         (region_end_addr >= host_start_addr + PAGE_SIZE_4MB)) {         // if 4MB boundary
629       large_shadow_pde->page_base_addr = PD32_4MB_BASE_ADDR(host_start_addr);
630     } else {      // else generate 4k pages
631       pte32_t * shadow_pt = NULL;
632       PrintDebug("Handling non aligned large page\n");
633       
634       shadow_pde->large_page = 0;
635       
636       shadow_pt = create_new_shadow_pt32();
637
638       if (create_pd32_nonaligned_4MB_page(info, shadow_pt, guest_start_addr, large_shadow_pde) == -1) {
639         PrintError("Non Aligned Large Page Error\n");
640         V3_Free(shadow_pt);
641         return -1;
642       }
643       
644       
645 #ifdef DEBUG_SHADOW_PAGING
646       PrintDebug("non-aligned Shadow PT\n");
647       PrintPT32(PT32_PAGE_ADDR(fault_addr), shadow_pt);   
648 #endif
649       shadow_pde->pt_base_addr = PD32_BASE_ADDR(shadow_pt);
650     }
651     
652   } else {
653     // Handle hooked pages as well as other special pages
654     if (handle_special_page_fault(info, fault_addr, guest_start_addr, error_code) == -1) {
655       PrintError("Special Page Fault handler returned error for address: %x\n", fault_addr);
656       return -1;
657     }
658   }
659
660   return 0;
661 }
662 */