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.


restructured the ctrl register handlers
[palacios.git] / palacios / src / palacios / vmm_shadow_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
21 #include <palacios/vmm_shadow_paging.h>
22
23
24 #include <palacios/vmm.h>
25 #include <palacios/vm_guest_mem.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vmm_ctrl_regs.h>
28
29 #ifndef DEBUG_SHADOW_PAGING
30 #undef PrintDebug
31 #define PrintDebug(fmt, args...)
32 #endif
33
34
35 /*** 
36  ***  There be dragons
37  ***/
38
39
40
41
42
43 DEFINE_HASHTABLE_INSERT(add_cr3_to_cache, addr_t, struct hashtable *);
44 DEFINE_HASHTABLE_SEARCH(find_cr3_in_cache, addr_t, struct hashtable *);
45 DEFINE_HASHTABLE_REMOVE(del_cr3_from_cache, addr_t, struct hashtable *, 0);
46
47
48 DEFINE_HASHTABLE_INSERT(add_pte_map, addr_t, addr_t);
49 DEFINE_HASHTABLE_SEARCH(find_pte_map, addr_t, addr_t);
50 DEFINE_HASHTABLE_REMOVE(del_pte_map, addr_t, addr_t, 0);
51
52
53
54 static uint_t pte_hash_fn(addr_t key) {
55   return hash_long(key, 32);
56 }
57
58 static int pte_equals(addr_t key1, addr_t key2) {
59   return (key1 == key2);
60 }
61
62 static uint_t cr3_hash_fn(addr_t key) {
63   return hash_long(key, 32);
64 }
65
66 static int cr3_equals(addr_t key1, addr_t key2) {
67   return (key1 == key2);
68 }
69
70
71
72 static int activate_shadow_pt_32(struct guest_info * info);
73 static int activate_shadow_pt_32pae(struct guest_info * info);
74 static int activate_shadow_pt_64(struct guest_info * info);
75
76
77 static int handle_shadow_pte32_fault(struct guest_info* info, 
78                                      addr_t fault_addr, 
79                                      pf_error_t error_code,
80                                      pte32_t * shadow_pte, 
81                                      pte32_t * guest_pte);
82
83 static int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code);
84
85 int v3_init_shadow_page_state(struct guest_info * info) {
86   struct shadow_page_state * state = &(info->shdw_pg_state);
87   
88   state->guest_cr3 = 0;
89   state->guest_cr0 = 0;
90
91   state->cr3_cache = create_hashtable(0, &cr3_hash_fn, &cr3_equals);
92
93   state->cached_cr3 = 0;
94   state->cached_ptes = NULL;
95
96   return 0;
97 }
98
99
100
101
102 /*
103  For now we'll do something a little more lightweight
104 int cache_page_tables32(struct guest_info * info, addr_t pde) {
105   struct shadow_page_state * state = &(info->shdw_pg_state);
106   addr_t pde_host_addr;
107   pde32_t * tmp_pde;
108   struct hashtable * pte_cache = NULL;
109   int i = 0;
110
111
112   pte_cache = (struct hashtable *)find_cr3_in_cache(state->cr3_cache, pde);
113   if (pte_cache != NULL) {
114     PrintError("CR3 already present in cache\n");
115     state->current_ptes = pte_cache;
116     return 1;
117   } else {
118     PrintError("Creating new CR3 cache entry\n");
119     pte_cache = create_hashtable(0, &pte_hash_fn, &pte_equals);
120     state->current_ptes = pte_cache;
121     add_cr3_to_cache(state->cr3_cache, pde, pte_cache);
122   }
123
124   if (guest_pa_to_host_va(info, pde, &pde_host_addr) == -1) {
125     PrintError("Could not lookup host address of guest PDE\n");
126     return -1;
127   }
128
129   tmp_pde = (pde32_t *)pde_host_addr;
130
131   add_pte_map(pte_cache, pde, pde_host_addr);
132
133
134   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
135     if ((tmp_pde[i].present) && (tmp_pde[i].large_page == 0)) {
136       addr_t pte_host_addr;
137
138       if (guest_pa_to_host_va(info, (addr_t)(PDE32_T_ADDR(tmp_pde[i])), &pte_host_addr) == -1) {
139         PrintError("Could not lookup host address of guest PDE\n");
140         return -1;
141       }
142
143       add_pte_map(pte_cache, (addr_t)(PDE32_T_ADDR(tmp_pde[i])), pte_host_addr); 
144     }
145   }
146
147
148   return 0;
149 }
150 */
151
152
153 int v3_cache_page_tables(struct guest_info * info, addr_t cr3) {
154   switch(v3_get_cpu_mode(info)) {
155   case PROTECTED:
156     return v3_cache_page_tables32(info, (addr_t)V3_PAddr((void *)CR3_TO_PDE32(cr3)));
157   default:
158     return -1;
159   }
160 }
161
162 int v3_cache_page_tables32(struct guest_info * info, addr_t pde) {
163   struct shadow_page_state * state = &(info->shdw_pg_state);
164   addr_t pde_host_addr;
165   pde32_t * tmp_pde;
166   struct hashtable * pte_cache = NULL;
167   int i = 0;
168
169   if (pde == state->cached_cr3) {
170     return 1;
171   }
172
173   if (state->cached_ptes != NULL) {
174     hashtable_destroy(state->cached_ptes, 0, 0);
175     state->cached_ptes = NULL;
176   }
177
178   state->cached_cr3 = pde;
179
180   pte_cache = create_hashtable(0, &pte_hash_fn, &pte_equals);
181   state->cached_ptes = pte_cache;
182
183   if (guest_pa_to_host_va(info, pde, &pde_host_addr) == -1) {
184     PrintError("Could not lookup host address of guest PDE\n");
185     return -1;
186   }
187
188   tmp_pde = (pde32_t *)pde_host_addr;
189
190   add_pte_map(pte_cache, pde, pde_host_addr);
191
192
193   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
194     if ((tmp_pde[i].present) && (tmp_pde[i].large_page == 0)) {
195       addr_t pte_host_addr;
196
197       if (guest_pa_to_host_va(info, (addr_t)(PDE32_T_ADDR(tmp_pde[i])), &pte_host_addr) == -1) {
198         PrintError("Could not lookup host address of guest PDE\n");
199         return -1;
200       }
201
202       add_pte_map(pte_cache, (addr_t)(PDE32_T_ADDR(tmp_pde[i])), pte_host_addr); 
203     }
204   }
205
206   return 0;
207
208 }
209
210
211
212 int v3_replace_shdw_page32(struct guest_info * info, addr_t location, pte32_t * new_page, pte32_t * old_page) {
213   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->ctrl_regs.cr3);
214   pde32_t * shadow_pde =  (pde32_t *)&(shadow_pd[PDE32_INDEX(location)]);
215
216   if (shadow_pde->large_page == 0) {
217     pte32_t * shadow_pt = (pte32_t *)(addr_t)PDE32_T_ADDR((*shadow_pde));
218     pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(location)]);
219
220     //if (shadow_pte->present == 1) {
221     *(uint_t *)old_page = *(uint_t *)shadow_pte;
222     //}
223
224     *(uint_t *)shadow_pte = *(uint_t *)new_page;
225
226   } else {
227     // currently unhandled
228     return -1;
229   }
230   
231   return 0;
232 }
233
234
235
236
237
238 static int activate_shadow_pt_32(struct guest_info * info) {
239     struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
240     struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
241     int cached = 0;
242
243     // Check if shadow page tables are in the cache
244     cached = v3_cache_page_tables32(info, (addr_t)V3_PAddr((void *)(addr_t)CR3_TO_PDE32((void *)*(addr_t *)guest_cr3)));
245     
246     if (cached == -1) {
247       PrintError("CR3 Cache failed\n");
248       return -1;
249     } else if (cached == 0) {
250       addr_t shadow_pt;
251       
252       PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
253       delete_page_tables_32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
254       
255       shadow_pt = v3_create_new_shadow_pt();
256       
257       shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PD32_BASE_ADDR(shadow_pt));
258       PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr );
259       //PrintDebugPageTables( (pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3) );
260     } else {
261       PrintDebug("Reusing cached shadow Page table\n");
262     }
263    
264     shadow_cr3->pwt = guest_cr3->pwt;
265     shadow_cr3->pcd = guest_cr3->pcd;
266
267     return 0;
268 }
269
270 static int activate_shadow_pt_32pae(struct guest_info * info) {
271   PrintError("Activating 32 bit PAE page tables not implemented\n");
272   return -1;
273 }
274
275 static int activate_shadow_pt_64(struct guest_info * info) {
276   PrintError("Activating 64 bit page tables not implemented\n");
277   return -1;
278 }
279
280
281 // Reads the guest CR3 register
282 // creates new shadow page tables
283 // updates the shadow CR3 register to point to the new pts
284 int v3_activate_shadow_pt(struct guest_info * info) {
285   switch (info->cpu_mode) {
286
287   case PROTECTED:
288     return activate_shadow_pt_32(info);
289   case PROTECTED_PAE:
290     return activate_shadow_pt_32pae(info);
291   case LONG:
292   case LONG_32_COMPAT:
293   case LONG_16_COMPAT:
294     return activate_shadow_pt_64(info);
295   default:
296     PrintError("Invalid CPU mode: %d\n", info->cpu_mode);
297     return -1;
298   }
299
300   return 0;
301 }
302
303
304 int v3_handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
305   
306   if (info->mem_mode == PHYSICAL_MEM) {
307     // If paging is not turned on we need to handle the special cases
308
309 #ifdef DEBUG_SHADOW_PAGING
310     PrintPageTree(info->cpu_mode, fault_addr, info->ctrl_regs.cr3);
311 #endif
312
313     return handle_special_page_fault(info, fault_addr, fault_addr, error_code);
314   } else if (info->mem_mode == VIRTUAL_MEM) {
315
316     switch (info->cpu_mode) {
317     case PROTECTED:
318       return handle_shadow_pagefault32(info, fault_addr, error_code);
319       break;
320     case PROTECTED_PAE:
321     case LONG:
322     default:
323       PrintError("Unhandled CPU Mode\n");
324       return -1;
325     }
326   } else {
327     PrintError("Invalid Memory mode\n");
328     return -1;
329   }
330 }
331
332 addr_t v3_create_new_shadow_pt() {
333   void * host_pde = 0;
334
335   host_pde = V3_VAddr(V3_AllocPages(1));
336   memset(host_pde, 0, PAGE_SIZE);
337
338   return (addr_t)host_pde;
339 }
340
341
342 static void inject_guest_pf(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
343   info->ctrl_regs.cr2 = fault_addr;
344   v3_raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
345 }
346
347
348 static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
349   /* basically the reasoning is that there can be multiple reasons for a page fault:
350      If there is a permissions failure for a page present in the guest _BUT_ 
351      the reason for the fault was that the page is not present in the shadow, 
352      _THEN_ we have to map the shadow page in and reexecute, this will generate 
353      a permissions fault which is _THEN_ valid to send to the guest
354      _UNLESS_ both the guest and shadow have marked the page as not present
355
356      whew...
357   */
358   if (guest_access != PT_ACCESS_OK) {
359     // Guest Access Error
360     
361     if ((shadow_access != PT_ENTRY_NOT_PRESENT) &&
362         (guest_access != PT_ENTRY_NOT_PRESENT)) {
363       // aka (guest permission error)
364       return 1;
365     }
366
367     if ((shadow_access == PT_ENTRY_NOT_PRESENT) &&
368         (guest_access == PT_ENTRY_NOT_PRESENT)) {      
369       // Page tables completely blank, handle guest first
370       return 1;
371     }
372
373     // Otherwise we'll handle the guest fault later...?
374   }
375
376   return 0;
377 }
378
379
380
381
382 /* The guest status checks have already been done,
383  * only special case shadow checks remain
384  */
385 static int handle_large_pagefault32(struct guest_info * info, 
386                                     addr_t fault_addr, pf_error_t error_code, 
387                                     pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde) 
388 {
389   pt_access_status_t shadow_pte_access = can_access_pte32(shadow_pt, fault_addr, error_code);
390   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
391   
392   if (shadow_pte_access == PT_ACCESS_OK) {
393     // Inconsistent state...
394     // Guest Re-Entry will flush tables and everything should now workd
395     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
396     return 0;
397   }
398
399   
400   if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
401     // Get the guest physical address of the fault
402     addr_t guest_fault_pa = PDE32_4MB_T_ADDR(*large_guest_pde) + PD32_4MB_PAGE_OFFSET(fault_addr);
403     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
404  
405
406     if (host_page_type == HOST_REGION_INVALID) {
407       // Inject a machine check in the guest
408       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
409       v3_raise_exception(info, MC_EXCEPTION);
410       return 0;
411     }
412
413     if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
414       struct shadow_page_state * state = &(info->shdw_pg_state);
415       addr_t shadow_pa = get_shadow_addr(info, guest_fault_pa);
416
417       shadow_pte->page_base_addr = PT32_BASE_ADDR(shadow_pa);
418
419       shadow_pte->present = 1;
420
421       /* We are assuming that the PDE entry has precedence
422        * so the Shadow PDE will mirror the guest PDE settings, 
423        * and we don't have to worry about them here
424        * Allow everything
425        */
426       shadow_pte->user_page = 1;
427
428       if (find_pte_map(state->cached_ptes, PT32_PAGE_ADDR(guest_fault_pa)) != NULL) {
429         // Check if the entry is a page table...
430         PrintDebug("Marking page as Guest Page Table (large page)\n");
431         shadow_pte->vmm_info = PT32_GUEST_PT;
432         shadow_pte->writable = 0;
433       } else {
434         shadow_pte->writable = 1;
435       }
436
437
438       //set according to VMM policy
439       shadow_pte->write_through = 0;
440       shadow_pte->cache_disable = 0;
441       shadow_pte->global_page = 0;
442       //
443       
444     } else {
445       // Handle hooked pages as well as other special pages
446       if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
447         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
448         return -1;
449       }
450     }
451   } else if ((shadow_pte_access == PT_WRITE_ERROR) && 
452              (shadow_pte->vmm_info == PT32_GUEST_PT)) {
453
454     struct shadow_page_state * state = &(info->shdw_pg_state);
455     PrintDebug("Write operation on Guest PAge Table Page (large page)\n");
456     state->cached_cr3 = 0;
457     shadow_pte->writable = 1;
458
459   } else {
460     PrintError("Error in large page fault handler...\n");
461     PrintError("This case should have been handled at the top level handler\n");
462     return -1;
463   }
464
465   PrintDebug("Returning from large page fault handler\n");
466   return 0;
467 }
468
469
470 static int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
471   pde32_t * guest_pd = NULL;
472   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->ctrl_regs.cr3);
473   addr_t guest_cr3 = (addr_t) V3_PAddr(CR3_TO_PDE32(info->shdw_pg_state.guest_cr3) );
474   pt_access_status_t guest_pde_access;
475   pt_access_status_t shadow_pde_access;
476   pde32_t * guest_pde = NULL;
477   pde32_t * shadow_pde = (pde32_t *)&(shadow_pd[PDE32_INDEX(fault_addr)]);
478
479   PrintDebug("Shadow page fault handler: %p\n", (void*) fault_addr );
480
481   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
482     PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
483     return -1;
484   } 
485
486   guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(fault_addr)]);
487
488
489   // Check the guest page permissions
490   guest_pde_access = can_access_pde32(guest_pd, fault_addr, error_code);
491
492   // Check the shadow page permissions
493   shadow_pde_access = can_access_pde32(shadow_pd, fault_addr, error_code);
494   
495   /* Was the page fault caused by the Guest's page tables? */
496   if (is_guest_pf(guest_pde_access, shadow_pde_access) == 1) {
497     PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
498                *(uint_t *)&guest_pde_access, *(uint_t *)&error_code);
499     inject_guest_pf(info, fault_addr, error_code);
500     return 0;
501   }
502
503   
504   if (shadow_pde_access == PT_ENTRY_NOT_PRESENT) 
505     {
506       pte32_t * shadow_pt =  (pte32_t *)v3_create_new_shadow_pt();
507
508       shadow_pde->present = 1;
509       shadow_pde->user_page = guest_pde->user_page;
510       //    shadow_pde->large_page = guest_pde->large_page;
511       shadow_pde->large_page = 0;
512       
513
514       // VMM Specific options
515       shadow_pde->write_through = 0;
516       shadow_pde->cache_disable = 0;
517       shadow_pde->global_page = 0;
518       //
519       
520       guest_pde->accessed = 1;
521       
522       shadow_pde->pt_base_addr = PD32_BASE_ADDR((addr_t)V3_PAddr(shadow_pt));
523       
524       if (guest_pde->large_page == 0) {
525         shadow_pde->writable = guest_pde->writable;
526       } else {
527         // ??  What if guest pde is dirty a this point?
528         ((pde32_4MB_t *)guest_pde)->dirty = 0;
529         shadow_pde->writable = 0;
530       }
531     }
532   else if (shadow_pde_access == PT_ACCESS_OK) 
533     {
534       //
535       // PTE fault
536       //
537       pte32_t * shadow_pt = (pte32_t *)V3_VAddr( (void*)(addr_t) PDE32_T_ADDR(*shadow_pde) );
538
539       if (guest_pde->large_page == 0) {
540         pte32_t * guest_pt = NULL;
541         if (guest_pa_to_host_va(info, PDE32_T_ADDR((*guest_pde)), (addr_t*)&guest_pt) == -1) {
542           // Machine check the guest
543           PrintDebug("Invalid Guest PTE Address: 0x%x\n", PDE32_T_ADDR((*guest_pde)));
544           v3_raise_exception(info, MC_EXCEPTION);
545           return 0;
546         }
547         
548         if (handle_shadow_pte32_fault(info, fault_addr, error_code, shadow_pt, guest_pt)  == -1) {
549           PrintError("Error handling Page fault caused by PTE\n");
550           return -1;
551         }
552       } else if (guest_pde->large_page == 1) {
553         if (handle_large_pagefault32(info, fault_addr, error_code, shadow_pt, (pde32_4MB_t *)guest_pde) == -1) {
554           PrintError("Error handling large pagefault\n");
555           return -1;
556         }
557       }
558     }
559   else if ((shadow_pde_access == PT_WRITE_ERROR) && 
560            (guest_pde->large_page == 1) && 
561            (((pde32_4MB_t *)guest_pde)->dirty == 0)) 
562     {
563       //
564       // Page Directory Entry marked read-only
565       // Its a large page and we need to update the dirty bit in the guest
566       //
567
568       PrintDebug("Large page write error... Setting dirty bit and returning\n");
569       ((pde32_4MB_t *)guest_pde)->dirty = 1;
570       shadow_pde->writable = guest_pde->writable;
571       return 0;
572       
573     } 
574   else if (shadow_pde_access == PT_USER_ERROR) 
575     {
576       //
577       // Page Directory Entry marked non-user
578       //      
579       PrintDebug("Shadow Paging User access error (shadow_pde_access=0x%x, guest_pde_access=0x%x)\n", 
580                  shadow_pde_access, guest_pde_access);
581       inject_guest_pf(info, fault_addr, error_code);
582       return 0;
583     }
584   else 
585     {
586       // inject page fault in guest
587       inject_guest_pf(info, fault_addr, error_code);
588       PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pde_access);
589       PrintDebug("Manual Says to inject page fault into guest\n");
590 #ifdef DEBUG_SHADOW_PAGING
591       PrintDebug("Guest PDE: (access=%d)\n\t", guest_pde_access);
592       PrintPDE32(fault_addr, guest_pde);
593       PrintDebug("Shadow PDE: (access=%d)\n\t", shadow_pde_access);
594       PrintPDE32(fault_addr, shadow_pde);
595 #endif
596
597       return 0; 
598     }
599
600   PrintDebug("Returning end of PDE function (rip=%p)\n", (void *)(addr_t)(info->rip));
601   return 0;
602 }
603
604
605
606 /* 
607  * We assume the the guest pte pointer has already been translated to a host virtual address
608  */
609 static int handle_shadow_pte32_fault(struct guest_info * info, 
610                                      addr_t fault_addr, 
611                                      pf_error_t error_code,
612                                      pte32_t * shadow_pt, 
613                                      pte32_t * guest_pt) {
614
615   pt_access_status_t guest_pte_access;
616   pt_access_status_t shadow_pte_access;
617   pte32_t * guest_pte = (pte32_t *)&(guest_pt[PTE32_INDEX(fault_addr)]);;
618   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
619
620
621   // Check the guest page permissions
622   guest_pte_access = can_access_pte32(guest_pt, fault_addr, error_code);
623
624   // Check the shadow page permissions
625   shadow_pte_access = can_access_pte32(shadow_pt, fault_addr, error_code);
626   
627 #ifdef DEBUG_SHADOW_PAGING
628   PrintDebug("Guest PTE: (access=%d)\n\t", guest_pte_access);
629   PrintPTE32(fault_addr, guest_pte);
630   PrintDebug("Shadow PTE: (access=%d)\n\t", shadow_pte_access);
631   PrintPTE32(fault_addr, shadow_pte);
632 #endif
633   
634   /* Was the page fault caused by the Guest's page tables? */
635   if (is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
636     PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
637                guest_pte_access, *(uint_t*)&error_code);    
638     inject_guest_pf(info, fault_addr, error_code);
639     return 0; 
640   }
641   
642   
643   if (shadow_pte_access == PT_ACCESS_OK) {
644     // Inconsistent state...
645     // Guest Re-Entry will flush page tables and everything should now work
646     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
647     return 0;
648   }
649
650
651   if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
652
653     addr_t guest_pa = PTE32_T_ADDR((*guest_pte)) +  PT32_PAGE_OFFSET(fault_addr);
654
655     // Page Table Entry Not Present
656
657     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
658
659     if (host_page_type == HOST_REGION_INVALID) {
660       // Inject a machine check in the guest
661       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
662       v3_raise_exception(info, MC_EXCEPTION);
663       return 0;
664     }
665
666     // else...
667
668     if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
669       struct shadow_page_state * state = &(info->shdw_pg_state);
670       addr_t shadow_pa = get_shadow_addr(info, guest_pa);
671       
672       shadow_pte->page_base_addr = PT32_BASE_ADDR(shadow_pa);
673       
674       shadow_pte->present = guest_pte->present;
675       shadow_pte->user_page = guest_pte->user_page;
676       
677       //set according to VMM policy
678       shadow_pte->write_through = 0;
679       shadow_pte->cache_disable = 0;
680       shadow_pte->global_page = 0;
681       //
682       
683       guest_pte->accessed = 1;
684       
685       if (find_pte_map(state->cached_ptes, PT32_PAGE_ADDR(guest_pa)) != NULL) {
686         // Check if the entry is a page table...
687         PrintDebug("Marking page as Guest Page Table %d\n", shadow_pte->writable);
688         shadow_pte->vmm_info = PT32_GUEST_PT;
689       }
690
691       if (guest_pte->dirty == 1) {
692         shadow_pte->writable = guest_pte->writable;
693       } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
694         shadow_pte->writable = guest_pte->writable;
695         guest_pte->dirty = 1;
696         
697         if (shadow_pte->vmm_info == PT32_GUEST_PT) {
698           // Well that was quick...
699           struct shadow_page_state * state = &(info->shdw_pg_state);
700           PrintDebug("Immediate Write operation on Guest PAge Table Page\n");
701           state->cached_cr3 = 0;
702         }
703
704       } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {  // was =
705         shadow_pte->writable = 0;
706       }
707
708
709
710     } else {
711       // Page fault handled by hook functions
712       if (handle_special_page_fault(info, fault_addr, guest_pa, error_code) == -1) {
713         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
714         return -1;
715       }
716     }
717
718   } else if ((shadow_pte_access == PT_WRITE_ERROR) &&
719              (guest_pte->dirty == 0)) {
720
721     PrintDebug("Shadow PTE Write Error\n");
722     guest_pte->dirty = 1;
723     shadow_pte->writable = guest_pte->writable;
724
725     if (shadow_pte->vmm_info == PT32_GUEST_PT) {
726       struct shadow_page_state * state = &(info->shdw_pg_state);
727       PrintDebug("Write operation on Guest PAge Table Page\n");
728       state->cached_cr3 = 0;
729     }
730     
731     return 0;
732
733   } else {
734     // Inject page fault into the guest 
735     inject_guest_pf(info, fault_addr, error_code);
736     PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
737     PrintError("Manual Says to inject page fault into guest\n");
738     return -1;
739   }
740
741   PrintDebug("Returning end of function\n");
742   return 0;
743 }
744
745
746
747
748
749
750 /* Currently Does not work with Segmentation!!! */
751 int v3_handle_shadow_invlpg(struct guest_info * info)
752 {
753   if (info->mem_mode != VIRTUAL_MEM) {
754     // Paging must be turned on...
755     // should handle with some sort of fault I think
756     PrintError("ERROR: INVLPG called in non paged mode\n");
757     return -1;
758   }
759   
760   
761   if (info->cpu_mode != PROTECTED) {
762     return 0;
763   }
764   
765   uchar_t instr[15];
766   int index = 0;
767   
768   int ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
769   if (ret != 15) {
770     PrintError("Could not read instruction 0x%p (ret=%d)\n",  (void *)(addr_t)(info->rip), ret);
771     return -1;
772   }
773   
774   
775   /* Can INVLPG work with Segments?? */
776   while (is_prefix_byte(instr[index])) {
777     index++;
778   }
779     
780     
781   if( (instr[index + 0] != (uchar_t) 0x0f) ||  
782       (instr[index + 1] != (uchar_t) 0x01) ) {
783     PrintError("invalid Instruction Opcode\n");
784     PrintTraceMemDump(instr, 15);
785     return -1;
786   }
787   
788   addr_t first_operand;
789   addr_t second_operand;
790   addr_t guest_cr3 = (addr_t)V3_PAddr( (void*)(addr_t) CR3_TO_PDE32(info->shdw_pg_state.guest_cr3) );
791   
792   pde32_t * guest_pd = NULL;
793   
794   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
795     PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
796     return -1;
797   }
798   
799   index += 2;
800
801   v3_operand_type_t addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
802   
803   if (addr_type != MEM_OPERAND) {
804     PrintError("Invalid Operand type\n");
805     return -1;
806   }
807   
808   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->ctrl_regs.cr3);
809   pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)];
810   pde32_t * guest_pde;
811   
812   //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand));
813   //PrintDebug("FirstOperand = %x\n", first_operand);
814   
815   PrintDebug("Invalidating page for %p\n", (void *)first_operand);
816   
817   guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(first_operand)]);
818   
819   if (guest_pde->large_page == 1) {
820     shadow_pde->present = 0;
821     PrintDebug("Invalidating Large Page\n");
822   } else
823     if (shadow_pde->present == 1) {
824       pte32_t * shadow_pt = (pte32_t *)(addr_t)PDE32_T_ADDR((*shadow_pde));
825       pte32_t * shadow_pte = (pte32_t *) V3_VAddr( (void*) &shadow_pt[PTE32_INDEX(first_operand)] );
826       
827 #ifdef DEBUG_SHADOW_PAGING
828       PrintDebug("Setting not present\n");
829       PrintPTE32(first_operand, shadow_pte );
830 #endif
831       
832       shadow_pte->present = 0;
833     }
834   
835   info->rip += index;
836   
837   return 0;
838 }
839
840
841 /*
842
843
844 static int create_pd32_nonaligned_4MB_page(struct guest_info * info, pte32_t * pt, addr_t guest_addr, pde32_4MB_t * large_shadow_pde) {
845   uint_t i = 0;
846   pte32_t * pte_cursor;
847   addr_t guest_pa = 0;
848
849   for (i = 0; i < 1024; i++) {
850     guest_pa = guest_addr + (PAGE_SIZE * i);
851     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
852     
853     pte_cursor = &(pt[i]);
854
855     if (host_page_type == HOST_REGION_INVALID) {
856       // Currently we don't support this, but in theory we could
857       PrintError("Invalid Host Memory Type\n");
858       return -1;
859     } else if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
860       addr_t shadow_pa = get_shadow_addr(info, guest_pa);
861
862
863       pte_cursor->page_base_addr = PT32_BASE_ADDR(shadow_pa);
864       pte_cursor->present = 1;
865       pte_cursor->writable = large_shadow_pde->writable;
866       pte_cursor->user_page = large_shadow_pde->user_page;
867       pte_cursor->write_through = 0;  
868       pte_cursor->cache_disable = 0;
869       pte_cursor->global_page = 0;
870
871     } else {
872       PrintError("Unsupported Host Memory Type\n");
873       return -1;
874     }
875   }
876   return 0;
877 }
878
879
880 static int handle_large_pagefault32(struct guest_info * info, 
881                                     pde32_t * guest_pde, pde32_t * shadow_pde, 
882                                     addr_t fault_addr, pf_error_t error_code ) {
883   struct shadow_region * mem_reg;
884   pde32_4MB_t * large_guest_pde = (pde32_4MB_t *)guest_pde;
885   pde32_4MB_t * large_shadow_pde = (pde32_4MB_t *)shadow_pde;
886   host_region_type_t host_page_type;
887   addr_t guest_start_addr = PDE32_4MB_T_ADDR(*large_guest_pde);
888   //    addr_t guest_end_addr = guest_start_addr + PAGE_SIZE_4MB; // start address + 4MB
889   
890   
891   // Check that the Guest PDE entry points to valid memory
892   // else Machine Check the guest
893   PrintDebug("Large Page: Page Base Addr=%x\n", guest_start_addr);
894   
895   host_page_type = get_shadow_addr_type(info, guest_start_addr);
896   
897   if (host_page_type == HOST_REGION_INVALID) {
898     PrintError("Invalid guest address in large page (0x%x)\n", guest_start_addr);
899     v3_raise_exception(info, MC_EXCEPTION);
900     return -1;
901   }
902   
903   // else...
904
905   if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
906
907     addr_t host_start_addr = 0;
908     addr_t region_end_addr = 0;
909     
910     // Check for a large enough region in host memory
911     mem_reg = get_shadow_region_by_addr(&(info->mem_map), guest_start_addr);
912     PrintDebug("Host region: host_addr=%x (guest_start=%x, end=%x)\n", 
913                mem_reg->host_addr, mem_reg->guest_start, mem_reg->guest_end);
914     host_start_addr = mem_reg->host_addr + (guest_start_addr - mem_reg->guest_start);
915     region_end_addr = mem_reg->host_addr + (mem_reg->guest_end - mem_reg->guest_start);
916     
917     PrintDebug("Host Start Addr=%x; Region End Addr=%x\n", host_start_addr, region_end_addr);
918     
919     
920     //4f
921     if (large_guest_pde->dirty == 1) { // dirty
922       large_shadow_pde->writable = guest_pde->writable;
923     } else if (error_code.write == 1) { // not dirty, access is write
924       large_shadow_pde->writable = guest_pde->writable;
925       large_guest_pde->dirty = 1;
926     } else { // not dirty, access is read
927       large_shadow_pde->writable = 0;
928     }
929     
930     
931     // Check if the region is at least an additional 4MB
932     
933     
934     //4b.
935     if ((PD32_4MB_PAGE_OFFSET(host_start_addr) == 0) && 
936         (region_end_addr >= host_start_addr + PAGE_SIZE_4MB)) {         // if 4MB boundary
937       large_shadow_pde->page_base_addr = PD32_4MB_BASE_ADDR(host_start_addr);
938     } else {      // else generate 4k pages
939       pte32_t * shadow_pt = NULL;
940       PrintDebug("Handling non aligned large page\n");
941       
942       shadow_pde->large_page = 0;
943       
944       shadow_pt = create_new_shadow_pt32();
945
946       if (create_pd32_nonaligned_4MB_page(info, shadow_pt, guest_start_addr, large_shadow_pde) == -1) {
947         PrintError("Non Aligned Large Page Error\n");
948         V3_Free(shadow_pt);
949         return -1;
950       }
951       
952       
953 #ifdef DEBUG_SHADOW_PAGING
954       PrintDebug("non-aligned Shadow PT\n");
955       PrintPT32(PT32_PAGE_ADDR(fault_addr), shadow_pt);   
956 #endif
957       shadow_pde->pt_base_addr = PD32_BASE_ADDR(shadow_pt);
958     }
959     
960   } else {
961     // Handle hooked pages as well as other special pages
962     if (handle_special_page_fault(info, fault_addr, guest_start_addr, error_code) == -1) {
963       PrintError("Special Page Fault handler returned error for address: %x\n", fault_addr);
964       return -1;
965     }
966   }
967
968   return 0;
969 }
970 */