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