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.


72e63af8dd571bea9f2d7ef61e2e3e890b351771
[palacios.git] / palacios / src / palacios / mmu / vmm_shdw_pg_kvm.c
1 /*
2  * Shadow page cache implementation that has been stolen from Linux's KVM Implementation
3  * This module is licensed under the GPL
4  */
5
6 #include <palacios/vmm_shadow_paging.h>
7 #include <palacios/vmm_ctrl_regs.h>
8
9 #include <palacios/vm_guest.h>
10 #include <palacios/vm_guest_mem.h>
11
12 #include <palacios/vmm_paging.h>
13
14
15 #ifndef V3_CONFIG_DEBUG_SHDW_CACHE
16 #undef PrintDebug
17 #define PrintDebug(fmt, ...)
18 #endif
19
20 #ifdef V3_CONFIG_SHADOW_CACHE
21
22 struct pde_chain {
23     addr_t shadow_pdes[NR_PTE_CHAIN_ENTRIES];
24     struct hlist_node link;
25 };
26
27 struct rmap {
28     addr_t shadow_ptes[RMAP_EXT];
29     struct rmap * more;
30 };
31
32 static inline int activate_shadow_pt_32(struct guest_info * core);
33 static inline unsigned shadow_page_table_hashfn(addr_t guest_fn)
34 {
35     return guest_fn;
36 }
37
38 static void *shadow_cache_alloc(struct shadow_cache *mc, size_t size)
39 {
40     void *p;
41     if (!mc->nobjs) {
42         PrintDebug("at shadow_cache_alloc mc->nobjs non-exist\n");
43     }
44
45     p = mc->objects[--mc->nobjs];
46     memset(p, 0, size);
47     return p;
48
49 }
50
51 static void shadow_cache_free(struct shadow_cache *mc, void *obj)
52 {
53     if (mc->nobjs < NR_MEM_OBJS) {
54         mc->objects[mc->nobjs++] = obj;
55     }
56     else V3_Free(obj);
57 }
58
59 static struct rmap *shadow_alloc_rmap(struct guest_info *core)
60 {       
61     return shadow_cache_alloc(&core->shadow_rmap_cache,sizeof(struct rmap));
62 }
63
64 static void shadow_free_rmap(struct guest_info *core,struct rmap *rd)
65 {
66     return shadow_cache_free(&core->shadow_rmap_cache,rd);
67 }
68
69 int shadow_topup_cache(struct shadow_cache * cache, size_t objsize, int min) {
70
71     void  *obj;
72
73     if (cache->nobjs >= min) return 0;
74     while (cache->nobjs < ARRAY_SIZE(cache->objects)) {
75         obj = V3_Malloc(objsize);
76         if (!obj) {
77             PrintDebug("at shadow_topup_cache obj alloc fail\n");
78             return -1;
79         }
80         cache->objects[cache->nobjs++] = obj;
81     }
82     return 0;
83                 
84 }
85
86 static int shadow_topup_caches(struct guest_info * core) {
87     int r;
88         
89     r = shadow_topup_cache(&core->shadow_pde_chain_cache, 
90                 sizeof(struct pde_chain), 4);
91
92     if (r) goto out;
93
94     r = shadow_topup_cache(&core->shadow_rmap_cache, 
95                 sizeof(struct rmap), 1);
96
97 out:
98         return r;
99 }
100
101 static struct pde_chain *shadow_alloc_pde_chain(struct guest_info *core)
102 {
103     return shadow_cache_alloc(&core->shadow_pde_chain_cache,
104                 sizeof(struct pde_chain));
105 }
106
107 static void shadow_free_pde_chain(struct guest_info *core, struct pde_chain *pc)
108 {
109     PrintDebug("shdw_free_pdechain: start\n");
110     shadow_cache_free(&core->shadow_pde_chain_cache, pc);
111     PrintDebug("shdw_free_pdechain: return\n");
112 }
113
114
115 static void shadow_free_page (struct guest_info * core, struct shadow_page_cache_data * page) 
116 {
117     list_del(&page->link);
118
119     V3_FreePages((void *)page->page_pa, 1);
120     page->page_pa=(addr_t)V3_AllocPages(1);
121
122     if (!page->page_pa) { 
123         PrintError("Freeing shadow page failed on allocation\n");
124         return;
125     }
126         
127     list_add(&page->link,&core->free_pages);
128     ++core->n_free_shadow_pages;        
129         
130 }
131
132 static struct shadow_page_cache_data * shadow_alloc_page(struct guest_info * core, addr_t shadow_pde) {
133
134     struct shadow_page_cache_data * page;
135
136     if (list_empty(&core->free_pages)) return NULL;
137
138     page = list_entry(core->free_pages.next, struct shadow_page_cache_data, link);
139     list_del(&page->link);
140
141     list_add(&page->link, &core->active_shadow_pages);
142     page->multimapped = 0;
143     page->shadow_pde = shadow_pde;
144     --core->n_free_shadow_pages;
145         
146     PrintDebug("alloc_page: n_free_shdw_pg %d page_pa %p page_va %p\n",
147                 core->n_free_shadow_pages,(void *)(page->page_pa),V3_VAddr((void *)(page->page_pa)));
148
149     addr_t shdw_page = (addr_t)V3_VAddr((void *)(page->page_pa));
150     memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
151         
152     return page;
153         
154 }
155
156 static void shadow_zap_page(struct guest_info * core, struct shadow_page_cache_data * page);
157
158 static void free_shadow_pages(struct guest_info * core)
159 {
160     struct shadow_page_cache_data *page;
161
162     while (!list_empty(&core->active_shadow_pages)) {
163         page = container_of(core->active_shadow_pages.next,
164                                     struct shadow_page_cache_data, link);
165         shadow_zap_page(core, page);
166     }
167         
168     while (!list_empty(&core->free_pages)) {
169         page = list_entry(core->free_pages.next, struct shadow_page_cache_data, link);
170         list_del(&page->link);
171         V3_FreePages((void *)page->page_pa, 1);
172         page->page_pa = ~(addr_t)0; //invalid address
173     }
174 }
175
176 static int alloc_shadow_pages(struct guest_info * core)
177 {
178     int i;
179     struct shadow_page_cache_data * page_header = NULL;
180
181     for (i = 0; i < NUM_SHADOW_PAGES; i++) {
182         page_header = &core->page_header_buf[i];
183
184         INIT_LIST_HEAD(&page_header->link);
185         if (!(page_header->page_pa = (addr_t)V3_AllocPages(1))) {
186             PrintError("Allocation failed in allocating shadow page\n");
187             goto error_1;
188         }
189         addr_t shdw_page = (addr_t)V3_VAddr((void *)(page_header->page_pa));
190         memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
191
192         list_add(&page_header->link, &core->free_pages);
193         ++core->n_free_shadow_pages;
194         PrintDebug("alloc_shdw_pg: n_free_shdw_pg %d page_pa %p\n",
195                 core->n_free_shadow_pages,(void*)page_header->page_pa);
196     }
197     return 0;
198
199 error_1:
200     free_shadow_pages(core);
201     return -1; //out of memory
202
203 }
204
205 static void shadow_page_add_shadow_pde(struct guest_info * core, 
206         struct shadow_page_cache_data * page, addr_t shadow_pde) 
207 {
208     struct pde_chain *pde_chain;
209     struct hlist_node *node;
210     int i;
211     addr_t old;
212
213     if(!shadow_pde) {
214         return; 
215     }
216
217     if (!page->multimapped) {
218         old = page->shadow_pde;
219
220         if(!old) {
221             page->shadow_pde = shadow_pde;
222             return;
223         }
224
225         page->multimapped = 1;
226         pde_chain = shadow_alloc_pde_chain(core);
227         INIT_HLIST_HEAD(&page->shadow_pdes);
228         hlist_add_head(&pde_chain->link,&page->shadow_pdes);
229         pde_chain->shadow_pdes[0] = old;                
230     }
231         
232     hlist_for_each_entry(pde_chain, node, &page->shadow_pdes, link) {
233         if (pde_chain->shadow_pdes[NR_PTE_CHAIN_ENTRIES-1]) continue;
234         for(i=0; i < NR_PTE_CHAIN_ENTRIES; ++i)
235             if (!pde_chain->shadow_pdes[i]) {
236                 pde_chain->shadow_pdes[i] = shadow_pde;
237                 return;
238             }
239         }
240
241         pde_chain = shadow_alloc_pde_chain(core);
242         //error msg
243         hlist_add_head(&pde_chain->link,&page->shadow_pdes);
244         pde_chain->shadow_pdes[0] = shadow_pde;
245         
246 }
247
248 static void shadow_page_remove_shadow_pde(struct guest_info * core, 
249         struct shadow_page_cache_data * page, addr_t shadow_pde) 
250 {
251
252     struct pde_chain * pde_chain;
253     struct hlist_node * node;
254     int i;
255
256     PrintDebug("rm_shdw_pde: multimap %d\n", page->multimapped);
257     if(!page->multimapped) {
258         PrintDebug("rm_shdw_pde: no multimap\n");
259         if(page->shadow_pde !=  shadow_pde) 
260             PrintDebug("rm_shdw_pde: error page->shadow_pde is not equal to shadow_pde\n");
261         page->shadow_pde = 0;
262         PrintDebug("rm_shdw_pde: return\n");
263         return;
264     }
265         
266     PrintDebug("rm_shdw_pde: multimap\n");
267
268     hlist_for_each_entry (pde_chain, node, &page->shadow_pdes, link)
269     for (i=0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
270         if(!pde_chain->shadow_pdes[i]) break;
271         if(pde_chain->shadow_pdes[i] != shadow_pde) continue;
272
273         PrintDebug("rm_shdw_pde: found shadow_pde at i %d\n",i);
274         while (i+1 < NR_PTE_CHAIN_ENTRIES && pde_chain->shadow_pdes[i+1]) {
275             pde_chain->shadow_pdes[i] = pde_chain->shadow_pdes[i+1];
276             ++i;
277         }
278         pde_chain->shadow_pdes[i] = 0;
279
280         if(i==0) {
281             PrintDebug("rm_shdw_pde: only one!\n");
282             hlist_del(&pde_chain->link);                                
283             shadow_free_pde_chain(core, pde_chain);
284             if(hlist_empty(&page->shadow_pdes)) {
285                 page->multimapped = 0;
286                 page->shadow_pde = 0;
287             }
288         }
289
290         PrintDebug("rm_shdw_pde: return\n");
291         return;
292     }
293     PrintDebug("rm_shdw_pde: return\n");
294 }
295
296 static void shadow_page_search_shadow_pde (struct guest_info* core, addr_t shadow_pde, 
297         addr_t guest_pde, unsigned hlevel) {
298
299     struct shadow_page_cache_data* shdw_page;
300     unsigned index;
301     struct hlist_head* bucket;
302     struct hlist_node* node;
303     int hugepage_access = 0;
304     union shadow_page_role role;
305     addr_t pt_base_addr = 0;
306     int metaphysical = 0;
307
308     PrintDebug("shadow_page_search_shadow_pde\n");
309     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
310
311     if (mode == PROTECTED) {
312
313         PrintDebug("shadow_page_search_shadow_pde: PROTECTED\n");
314         pt_base_addr = ((pde32_t*)guest_pde)->pt_base_addr;
315         
316         if(((pde32_t*)guest_pde)->large_page == 1) {
317             PrintDebug("shadow_page_search_shadow_pde: large page\n");
318             hugepage_access = (((pde32_4MB_t *) guest_pde)->writable) | (((pde32_4MB_t*)guest_pde)->user_page << 1);
319             metaphysical = 1;
320             pt_base_addr = (addr_t) PAGE_BASE_ADDR(BASE_TO_PAGE_ADDR_4MB(((pde32_4MB_t*)guest_pde)->page_base_addr));
321         }
322                         
323         role.word = 0; 
324         role.glevels = PT32_ROOT_LEVEL; //max level
325         role.hlevels = PT_PAGE_TABLE_LEVEL;
326         role.metaphysical = metaphysical;
327         role.hugepage_access = hugepage_access;
328                 
329     } else if (mode == LONG_32_COMPAT || mode == LONG) {
330
331         PrintDebug("shadow_page_search_shadow_pde: LONG_32_COMPAT/LONG\n");
332         pt_base_addr = ((pde64_t*)guest_pde)->pt_base_addr;
333
334                 
335         if(hlevel == PT_DIRECTORY_LEVEL) { 
336             if(((pde64_t*)guest_pde)->large_page == 1) {
337                 hugepage_access = (((pde64_2MB_t *) guest_pde)->writable) | (((pde64_2MB_t*)guest_pde)->user_page << 1);
338                 metaphysical = 1;
339                 pt_base_addr = (addr_t) PAGE_BASE_ADDR(BASE_TO_PAGE_ADDR_2MB(((pde64_2MB_t*)guest_pde)->page_base_addr));
340             }   
341             role.hlevels = PT_PAGE_TABLE_LEVEL;
342                 
343         } else if(hlevel == PT32E_ROOT_LEVEL) {
344             if(((pdpe64_t*)guest_pde)->large_page == 1) {
345                 hugepage_access = (((pdpe64_1GB_t *) guest_pde)->writable) | (((pdpe64_1GB_t*)guest_pde)->user_page << 1);
346                 metaphysical = 1;
347                 pt_base_addr = (addr_t) PAGE_BASE_ADDR(BASE_TO_PAGE_ADDR_1GB(((pdpe64_1GB_t*)guest_pde)->page_base_addr));
348             }
349             role.hlevels = PT_DIRECTORY_LEVEL;
350                 
351         } else if(hlevel == PT64_ROOT_LEVEL) {          
352             if(((pdpe64_t*)guest_pde)->large_page == 1) {
353                 hugepage_access = (((pdpe64_1GB_t *) guest_pde)->writable) | (((pdpe64_1GB_t*)guest_pde)->user_page << 1);
354                 metaphysical = 1;
355                 pt_base_addr = (addr_t) PAGE_BASE_ADDR(BASE_TO_PAGE_ADDR_1GB(((pdpe64_1GB_t*)guest_pde)->page_base_addr));
356             }
357             role.hlevels = PT32E_ROOT_LEVEL;
358
359         }
360                         
361         role.word = 0; 
362         role.glevels = PT64_ROOT_LEVEL; //store numeric
363         role.metaphysical = metaphysical;
364         role.hugepage_access = hugepage_access; 
365
366     }
367
368     index = shadow_page_table_hashfn(pt_base_addr) % NUM_SHADOW_PAGES;
369     bucket = &core->shadow_page_hash[index];
370
371     hlist_for_each_entry(shdw_page, node, bucket, hash_link) 
372     if (shdw_page->guest_fn == pt_base_addr  && shdw_page->role.word == role.word ) {
373         PrintDebug("shadow_page_search_shadow_pde: found\n");
374         shadow_page_remove_shadow_pde(core, shdw_page, (addr_t)shadow_pde);
375         
376     } 
377     return;
378
379 }
380
381 static struct shadow_page_cache_data * shadow_page_lookup_page(struct guest_info *core, addr_t guest_fn, int opt) //purpose of this is write protection 
382 {
383     unsigned index;
384     struct hlist_head * bucket;
385     struct shadow_page_cache_data * page;
386     struct hlist_node * node;
387         
388     PrintDebug("lookup: guest_fn addr %p\n",(void *)BASE_TO_PAGE_ADDR(guest_fn));
389         
390     index = shadow_page_table_hashfn(guest_fn) % NUM_SHADOW_PAGES;
391     bucket = &core->shadow_page_hash[index];
392     PrintDebug("lookup: index %d bucket %p\n",index,(void*)bucket);
393
394     hlist_for_each_entry(page, node, bucket, hash_link)
395         if (opt == 0) {
396             PrintDebug("lookup: page->gfn %p gfn %p metaphysical %d\n",
397                 (void*)BASE_TO_PAGE_ADDR(page->guest_fn),(void*)BASE_TO_PAGE_ADDR(guest_fn),page->role.metaphysical);
398             if (page->guest_fn == guest_fn && !page->role.metaphysical) {
399                 return page;
400             }
401         }
402         else if(page->guest_fn == guest_fn) { 
403             return page; 
404         }
405         
406     return NULL;        
407 }
408
409 static void rmap_remove(struct guest_info * core, addr_t shadow_pte);
410 static void rmap_write_protect(struct guest_info * core, addr_t guest_fn);
411
412 struct shadow_page_cache_data * shadow_page_get_page(struct guest_info *core, 
413                                                                                                                 addr_t guest_fn,
414                                                                                                                 unsigned level, 
415                                                                                                                 int metaphysical,
416                                                                                                                 unsigned hugepage_access,
417                                                                                                                 addr_t shadow_pde,
418                                                                                                                 int force)  //0:default 1:off cache 2:off debug print
419 {
420     struct shadow_page_cache_data *page;
421     union shadow_page_role role;
422     unsigned index;
423     struct hlist_head *bucket;
424     struct hlist_node *node;
425     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
426         
427     role.word = 0; 
428     if (mode == REAL || mode == PROTECTED) role.glevels = PT32_ROOT_LEVEL; 
429         //exceptional, longterm there should be argument 
430     else if (mode == PROTECTED_PAE) role.glevels = PT32E_ROOT_LEVEL;
431     else if (mode == LONG || mode == LONG_32_COMPAT) role.glevels = PT64_ROOT_LEVEL;
432     else return NULL;
433         
434         //store numeric
435     role.hlevels = level;
436     role.metaphysical = metaphysical;
437     role.hugepage_access = hugepage_access;
438         
439     index = shadow_page_table_hashfn(guest_fn) % NUM_SHADOW_PAGES;
440     bucket = &core->shadow_page_hash[index];
441
442     if (force != 2) PrintDebug("get_page: lvl %d idx %d gfn %p role %x\n", level, index, (void *)guest_fn,role.word);
443
444     hlist_for_each_entry(page, node, bucket, hash_link)
445         if (page->guest_fn == guest_fn && page->role.word == role.word) {
446             shadow_page_add_shadow_pde(core, page, shadow_pde); //guest_fn is right there
447             if(force != 2) 
448                 PrintDebug("get_page: found guest_fn %p, index %d, multi %d, next %p\n", 
449                     (void *)page->guest_fn, index, page->multimapped, (void *)page->hash_link.next);
450             if (force == 0 || force == 2) 
451                 return page;
452             else { 
453                 shadow_zap_page(core,page);
454                 goto new_alloc;
455             }
456         } else {
457             if(force != 2) 
458                 PrintDebug("get_page: no found guest_fn %p, index %d, multimapped %d, next %p\n", 
459                     (void *)page->guest_fn, index, page->multimapped, (void *)page->hash_link.next);
460         }
461
462     if (force != 2) 
463         PrintDebug("get_page: no found\n");
464
465 new_alloc:
466
467     page=shadow_alloc_page(core, shadow_pde);
468
469     if (!page) return page; 
470
471     page->guest_fn = guest_fn;
472     page->role=role;
473     page->multimapped = 0;
474     page->shadow_pde = 0;
475         
476     if (force != 2) 
477         PrintDebug("get_page: hadd h->first %p, n %p, n->next %p\n", 
478             (void *)bucket->first, (void *)&page->hash_link, (void *)page->hash_link.next);
479
480     hlist_add_head(&page->hash_link, bucket);
481     shadow_page_add_shadow_pde(core, page, shadow_pde);
482
483     if (force != 2) PrintDebug("get_page: hadd h->first %p, n %p, n->next %p\n", 
484         (void *)bucket->first, (void *)&page->hash_link, (void *)page->hash_link.next); 
485
486     if (!metaphysical) rmap_write_protect(core, guest_fn); //in case rmapped guest_fn being allocated as pt or pd
487     if (force != 2) PrintDebug("get_page: return\n");
488
489     return page;
490
491 }
492
493 static void shadow_page_unlink_children (struct guest_info * core, struct shadow_page_cache_data * page) {
494     unsigned i;
495
496     uint32_t* shdw32_table;
497     uint32_t* shdw32_entry;
498     uint64_t* shdw64_table;
499     uint64_t* shdw64_entry;
500
501     uint32_t* guest32_table;
502     uint32_t* guest32_entry;
503     uint64_t* guest64_table;
504     uint64_t* guest64_entry;
505
506     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
507
508     if(page->role.hlevels == PT_PAGE_TABLE_LEVEL) {             
509
510         if (mode == PROTECTED) {
511
512             shdw32_table = (uint32_t*) V3_VAddr((void *)(addr_t)CR3_TO_PDE32_PA(page->page_pa));                
513             PrintDebug("ulink_chil: pte lvl\n");
514
515             for (i = 0; i < PT32_ENT_PER_PAGE; ++i) {
516                 shdw32_entry = (uint32_t*)&(shdw32_table[i]);
517                 if (*shdw32_entry & PT_PRESENT_MASK) {
518                     rmap_remove(core, (addr_t)shdw32_entry);
519                     PrintDebug("ulink_chil: %d pte: shadow %x\n", i, *shdw32_entry);
520                 }
521                 memset((void *)shdw32_entry, 0, sizeof(uint32_t));
522             }
523             PrintDebug("ulink_chil: return pte\n");
524             return;     
525                         
526         } else if (mode == LONG_32_COMPAT || mode == LONG) {
527
528             shdw64_table = (uint64_t*) V3_VAddr((void *)(addr_t)CR3_TO_PML4E64_PA(page->page_pa));              
529             PrintDebug("ulink_chil: pte lvl\n");
530
531             for (i = 0; i < PT_ENT_PER_PAGE; ++i) {                     
532                 shdw64_entry = (uint64_t*)&(shdw64_table[i]);
533                 if (*shdw64_entry & PT_PRESENT_MASK) {
534                     rmap_remove(core, (addr_t)shdw64_entry);
535                     PrintDebug("ulink_chil: %d pte: shadow %p\n", i, (void*)*((uint64_t*)shdw64_entry));
536                 }
537                 memset((void *)shdw64_entry, 0, sizeof(uint64_t));
538             }
539
540             PrintDebug("ulink_chil: return pte\n");
541             return;                             
542         }
543     }
544
545     PrintDebug("ulink_chil: pde lvl\n");
546     if (mode == PROTECTED) {
547                 
548         shdw32_table = (uint32_t*) V3_VAddr((void*)(addr_t)CR3_TO_PDE32_PA(page->page_pa));
549
550         if (guest_pa_to_host_va(core, BASE_TO_PAGE_ADDR(page->guest_fn), (addr_t*)&guest32_table) == -1) {
551             PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)BASE_TO_PAGE_ADDR(page->guest_fn));
552             return;
553         } 
554                 
555         for (i = 0; i < PT32_ENT_PER_PAGE; ++i) {
556             int present = 0;
557             shdw32_entry = (uint32_t*)&(shdw32_table[i]);
558             guest32_entry = (uint32_t*)&(guest32_table[i]);
559             present = *shdw32_entry & PT_PRESENT_MASK;
560             if(present) PrintDebug("ulink_chil: pde %dth: shadow %x\n", i, *((uint32_t*)shdw32_entry));
561             memset((void *)shdw32_entry, 0, sizeof(uint32_t));
562             if (present != 1) continue;
563
564             shadow_page_search_shadow_pde(core, (addr_t)shdw32_entry, (addr_t)guest32_entry, page->role.hlevels);
565         }
566         PrintDebug("ulink_child: before return at pde lvel\n");
567         return;
568
569     }else if(mode == LONG_32_COMPAT || mode == LONG)  {
570
571         shdw64_table = (uint64_t*) V3_VAddr((void*)(addr_t)CR3_TO_PML4E64_PA(page->page_pa));
572
573         if (guest_pa_to_host_va(core, BASE_TO_PAGE_ADDR(page->guest_fn), (addr_t*)&guest64_table) == -1) {
574             if(page->role.hlevels == PT_DIRECTORY_LEVEL) 
575                 PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)BASE_TO_PAGE_ADDR(page->guest_fn));
576             if(page->role.hlevels == PT32E_ROOT_LEVEL) 
577                 PrintError("Invalid Guest PDPE Address: 0x%p\n",  (void *)BASE_TO_PAGE_ADDR(page->guest_fn));
578             if(page->role.hlevels == PT64_ROOT_LEVEL) 
579                 PrintError("Invalid Guest PML4E Address: 0x%p\n",  (void *)BASE_TO_PAGE_ADDR(page->guest_fn));
580             return;     
581         }
582
583         for (i = 0; i < PT_ENT_PER_PAGE; ++i) {
584             int present = 0;
585             shdw64_entry = (uint64_t*)&(shdw64_table[i]);
586             guest64_entry = (uint64_t*)&(guest64_table[i]);
587             present = *shdw64_entry & PT_PRESENT_MASK;
588             if(present) PrintDebug("ulink_chil: pde: shadow %p\n",(void *)*((uint64_t *)shdw64_entry));
589             memset((void *)shdw64_entry, 0, sizeof(uint64_t));
590             if (present != 1) continue;
591
592             shadow_page_search_shadow_pde(core, (addr_t)shdw64_entry, (addr_t)guest64_entry, page->role.hlevels);
593         }
594         return;         
595
596     }
597     //PrintDebug("ulink_chil: return pde\n");
598
599 }
600
601 static void shadow_page_put_page(struct guest_info *core, struct shadow_page_cache_data * page, addr_t shadow_pde) { 
602
603         PrintDebug("put_page: start\n");        
604         shadow_page_remove_shadow_pde(core, page, shadow_pde);
605
606         PrintDebug("put_page: end\n");
607
608
609
610 static void shadow_zap_page(struct guest_info * core, struct shadow_page_cache_data * page) {
611
612     addr_t shadow_pde;
613     addr_t cr3_base_addr = 0;
614     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
615         
616     PrintDebug("zap: multimapped %d, metaphysical %d\n", page->multimapped, page->role.metaphysical);
617         
618     while (page->multimapped || page->shadow_pde) {
619         if (!page->multimapped) {
620             shadow_pde = page->shadow_pde;              
621         } else {
622             struct pde_chain * chain;
623             chain = container_of(page->shadow_pdes.first, struct pde_chain, link);
624             shadow_pde = chain->shadow_pdes[0];
625         }               
626         shadow_page_put_page(core, page, shadow_pde);
627         PrintDebug("zap_parent: pde: shadow %p\n",(void *)*((addr_t *)shadow_pde));
628         memset((void *)shadow_pde, 0, sizeof(uint32_t));
629     }
630
631     shadow_page_unlink_children(core, page);
632
633     PrintDebug("zap: end of unlink\n");
634         
635     if (mode == PROTECTED) {
636         cr3_base_addr =  ((struct cr3_32 *)&(core->shdw_pg_state.guest_cr3))->pdt_base_addr;
637     } else if (mode == LONG_32_COMPAT || mode == LONG) {
638         cr3_base_addr =  ((struct cr3_64 *)&(core->shdw_pg_state.guest_cr3))->pml4t_base_addr;
639     }
640     else return;        
641
642     PrintDebug("zap: before hlist_del\n");
643     PrintDebug("zap: page->guest_fn %p\n", (void*) page->guest_fn);
644
645     if (page->guest_fn !=  (addr_t)(cr3_base_addr)) {
646         PrintDebug("zap: first hlist_del\n");
647
648         hlist_del(&page->hash_link);
649         shadow_free_page(core, page);
650
651     } else {
652         PrintDebug("zap: second hlist_del\n");
653
654         list_del(&page->link);
655         list_add(&page->link,&core->active_shadow_pages);
656     }           
657
658     PrintDebug("zap: end hlist_del\n");
659     return;
660 }
661
662 int shadow_zap_hierarchy_32(struct guest_info * core, struct shadow_page_cache_data * page) {
663
664     unsigned i;
665     pde32_t *shadow_pde;
666     pde32_t *shadow_pd;
667     pde32_t *guest_pde;
668     pde32_t *guest_pd;
669         
670     if (page->role.hlevels != 2) return -1;
671
672     shadow_pd = CR3_TO_PDE32_VA(page->page_pa);
673     if (guest_pa_to_host_va(core, BASE_TO_PAGE_ADDR(page->guest_fn), (addr_t*)&guest_pd) == -1) {
674         PrintError("Invalid Guest PDE Address: 0x%p\n", (void*)BASE_TO_PAGE_ADDR(page->guest_fn));
675         return -1;
676     }
677         
678     for (i=0; i < PT32_ENT_PER_PAGE; ++i) {
679         int present = 0;
680         shadow_pde = (pde32_t*)&(shadow_pd[i]);
681         guest_pde = (pde32_t*)&(guest_pd[i]);
682         present = shadow_pde->present;
683         if (shadow_pde->present) PrintDebug("ulink_child: pde shadow %x\n", *((uint32_t*)shadow_pde));
684         memset((void*)shadow_pde, 0, sizeof(uint32_t));
685         if (present != 1) continue;
686
687         struct shadow_page_cache_data *shdw_page;
688         unsigned index;
689         struct hlist_head *bucket;
690         struct hlist_node *node;
691         int hugepage_access =0;
692         int metaphysical = 0;
693         union shadow_page_role role;
694         v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
695
696         if (((pde32_t*)guest_pde)->large_page == 1) {
697             hugepage_access = (((pde32_4MB_t*)guest_pde)->writable) | (((pde32_4MB_t*)guest_pde)->user_page << 1);
698             metaphysical = 1;
699         }
700         
701         role.word = 0; 
702         if (mode == REAL || mode == PROTECTED) role.glevels = PT32_ROOT_LEVEL; 
703         //exceptional, longterm there should be argument 
704         else if (mode == PROTECTED_PAE) role.glevels = PT32E_ROOT_LEVEL;
705         else if (mode == LONG || mode == LONG_32_COMPAT) role.glevels = PT64_ROOT_LEVEL;
706         else return -1;
707         
708         role.hlevels = 1;
709         role.metaphysical = metaphysical;
710         role.hugepage_access = hugepage_access;
711
712         index = shadow_page_table_hashfn(guest_pde->pt_base_addr) % NUM_SHADOW_PAGES;
713         bucket = &core->shadow_page_hash[index];
714
715         hlist_for_each_entry(shdw_page, node, bucket, hash_link)
716         if (shdw_page->guest_fn == (guest_pde->pt_base_addr) && (shdw_page->role.word == role.word)) {
717             shadow_zap_page(core, shdw_page);
718         }       
719     }
720
721     shadow_zap_page(core, page);
722     return 0;
723 }
724
725
726 int shadow_unprotect_page(struct guest_info * core, addr_t guest_fn) {
727
728     unsigned index;
729     struct hlist_head * bucket;
730     struct shadow_page_cache_data * page = NULL;
731     struct hlist_node * node;
732     struct hlist_node * n;
733     int r;
734
735     r = 0;
736     index = shadow_page_table_hashfn(guest_fn) % NUM_SHADOW_PAGES;
737     bucket = &core->shadow_page_hash[index];
738     PrintDebug("unprotect: gfn %p\n",(void *) guest_fn);
739         
740     hlist_for_each_entry_safe(page, node, n, bucket, hash_link) {
741     //hlist_for_each_entry(page, node, bucket, hash_link) {
742         if ((page->guest_fn == guest_fn) && !(page->role.metaphysical)) {
743             PrintDebug("unprotect: match page.gfn %p page.role %x gfn %p\n",(void *) page->guest_fn,page->role.word,(void *)guest_fn);
744             shadow_zap_page(core, page);
745             r = 1;
746         }
747     }
748         
749     PrintDebug("at shadow_unprotect_page return %d\n",r);
750     return r;
751 }
752
753 /*
754 reverse mapping data structures:
755 if page_private bit zero is zero, then page->private points to the shadow page table entry that points to page address
756 if page_private bit zero is one, then page->private & ~1 points to a struct rmap containing more mappings
757 */
758
759 void rmap_add(struct guest_info *core, addr_t shadow_pte) {
760     struct rmap *desc;
761     addr_t page_private = 0;
762     gen_pt_t * shadow_pte_gen;
763     addr_t page_base_addr = 0;
764     addr_t * mem_map;
765     int i;
766     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
767
768     shadow_pte_gen = (gen_pt_t *) shadow_pte;
769
770     if (mode == PROTECTED) {
771         page_base_addr = ((pte32_t *)shadow_pte)->page_base_addr;
772         PrintDebug("at rmap_add shadow_pte: %x\n", (uint32_t)*((uint32_t*)shadow_pte));
773
774     } else if (mode == LONG_32_COMPAT || mode == LONG) {
775         page_base_addr = ((pte64_t *)shadow_pte)->page_base_addr;
776         PrintDebug("at rmap_add shadow_pte: %p\n", (void*)*((uint64_t*)shadow_pte));
777
778     }
779     else return;        
780         
781     PrintDebug("debug rmap: at rmap_add shadow_pte->page_base_addr (%p), shadow_pte_present %d, shadow_pte_writable %d\n", 
782         (void *)BASE_TO_PAGE_ADDR(page_base_addr), (shadow_pte_gen->present), (shadow_pte_gen->writable));
783         
784     if (shadow_pte_gen->present == 0 || shadow_pte_gen->writable == 0)
785         return;
786
787     PrintDebug("at rmap_add host_fn %p\n", (void *)BASE_TO_PAGE_ADDR(page_base_addr));
788                 
789     mem_map = core->vm_info.mem_map.base_region.mem_map;
790     page_private = mem_map[page_base_addr];
791
792     PrintDebug("at rmap_add page_private %p\n", (void *)page_private);
793         
794     if (!page_private) {
795         PrintDebug("at rmap_add initial\n");
796         mem_map[page_base_addr] = (addr_t)shadow_pte;
797         PrintDebug("rmap_add: shadow_pte %p\n", (void *)shadow_pte);
798
799     } else if (!(page_private & 1)) {
800         PrintDebug("at rmap_add into multi\n");
801
802         desc = shadow_alloc_rmap(core);
803         desc->shadow_ptes[0] = page_private;
804         desc->shadow_ptes[1] = shadow_pte;
805         mem_map[page_base_addr] = (addr_t)desc | 1;
806         desc->more = NULL;
807         PrintDebug("rmap_add: desc %p desc|1 %p\n",(void *)desc,(void *)((addr_t)desc |1));
808
809     } else {
810         PrintDebug("at rmap_add multimap\n");
811         desc = (struct rmap *)(page_private & ~1ul);
812
813         while (desc->more && desc->shadow_ptes[RMAP_EXT-1]) desc = desc->more;
814                 
815         if (desc->shadow_ptes[RMAP_EXT-1]) {
816             desc->more = shadow_alloc_rmap(core);
817             desc = desc->more;
818         }
819
820         for (i = 0; desc->shadow_ptes[i]; ++i) ;
821         desc->shadow_ptes[i] = shadow_pte;              
822     }
823                 
824 }
825
826 static void rmap_desc_remove_entry(struct guest_info *core,
827                                    addr_t * page_private,
828                                    struct rmap *desc,
829                                    int i,
830                                    struct rmap *prev_desc) 
831 {
832     int j;
833
834     for (j = RMAP_EXT - 1; !desc->shadow_ptes[j]  &&  j > i; --j) ;
835     desc->shadow_ptes[i] = desc->shadow_ptes[j];
836     desc->shadow_ptes[j] = 0;
837
838     if (j != 0) {
839         PrintDebug("rmap_desc_rm: i %d j %d\n",i,j);
840         return;
841     }
842
843     if (!prev_desc && !desc->more) {
844         PrintDebug("rmap_desc_rm: no more no less\n");
845         *page_private = desc->shadow_ptes[0];
846     } else {            //more should be null
847         if (prev_desc) {
848             PrintDebug("rmap_desc_rm: no more\n");
849             prev_desc->more = desc->more; 
850         } else {
851             PrintDebug("rmap_desc_rm: no less\n");
852             *page_private = (addr_t) desc->more | 1;
853         }
854     }
855     shadow_free_rmap(core, desc);
856 }
857
858 static void rmap_remove(struct guest_info * core, addr_t shadow_pte) {
859     struct rmap *desc;
860     struct rmap *prev_desc;
861     addr_t page_private = 0;
862     gen_pt_t * shadow_pte_gen;
863     addr_t page_base_addr = 0;
864     addr_t * mem_map;
865     int i;
866
867     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
868
869     if (mode == PROTECTED) {
870         PrintDebug("rmap_rm: PROTECTED %d\n", mode);
871         page_base_addr = ((pte32_t *)shadow_pte)->page_base_addr;
872
873     } else if (mode == LONG_32_COMPAT || mode == LONG) {
874         PrintDebug("rmap_rm: LONG_32_COMPAT/LONG %d\n", mode);
875         page_base_addr = ((pte64_t *)shadow_pte)->page_base_addr;               
876
877     }   else {
878         PrintDebug("rmap_rm: mode %d\n", mode);
879         return; 
880     }
881     shadow_pte_gen = (gen_pt_t*)shadow_pte;
882
883     if (shadow_pte_gen->present == 0 || shadow_pte_gen->writable == 0) {
884         PrintDebug("rmap_rm: present %d, write %d, pte %p\n",
885                 shadow_pte_gen->present, shadow_pte_gen->writable,
886                 (void*)*((addr_t*)shadow_pte));
887         return;
888     }
889     PrintDebug("rmap_rm: shadow_pte->page_base_addr (%p)\n", (void *)BASE_TO_PAGE_ADDR(page_base_addr));
890
891     mem_map = core->vm_info.mem_map.base_region.mem_map;
892     page_private = mem_map[page_base_addr];
893
894     PrintDebug("rmap_rm: page_private %p page_private&1 %p\n",(void *)page_private,(void*)(page_private&1));
895         
896     if (!page_private) {                
897         PrintDebug("rmap_rm: single page_prive %p\n",(void *)page_private);
898         
899     } else if (!(page_private & 1)) {   
900         PrintDebug("rmap_rm: multi page_prive %p\n",(void *)page_private);
901         mem_map[page_base_addr] = (addr_t)0;
902
903     } else {
904         PrintDebug("rmap_rm: multimap page_prive %p\n",(void *)page_private);
905         desc = (struct rmap *)(page_private & ~1ul);
906         prev_desc = NULL;
907         
908         while (desc) {
909             PrintDebug("rmap_rm: desc loop\n");
910             for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i)
911             if (desc->shadow_ptes[i] == shadow_pte) {
912                 PrintDebug("rmap_rm: rmap_desc_remove_entry i %d\n",i);
913                 rmap_desc_remove_entry(core, &mem_map[page_base_addr], desc, i, prev_desc);
914                 return;
915             }
916             prev_desc = desc;
917             desc = desc->more;
918         }
919     }
920 }
921
922 static inline int activate_shadow_pt_32(struct guest_info * core);
923
924 static void rmap_write_protect(struct guest_info * core, addr_t guest_fn) {
925     struct rmap * desc;
926     //pte32_t * shadow_pte;
927     addr_t shadow_pte;
928     addr_t page_private;
929     addr_t host_pa;
930
931     PrintDebug("rmap_wrprot: gfn %p\n",(void *) guest_fn);
932
933     if (guest_pa_to_host_pa(core, BASE_TO_PAGE_ADDR(guest_fn), &host_pa)!=0) {
934         PrintDebug("rmap_wrprot: error \n");
935     }
936
937     page_private = core->vm_info.mem_map.base_region.mem_map[PAGE_BASE_ADDR(host_pa)];
938
939     PrintDebug("rmap_wrprot: host_fn %p\n",(void *)PAGE_BASE_ADDR(host_pa));
940         
941     while(page_private) {
942         PrintDebug("rmap_wrprot: page_private %p\n", (void*)page_private);
943         if(!(page_private & 1)) {
944             PrintDebug("rmap_wrprot: reverse desc single\n");
945             shadow_pte = page_private;
946                 
947         } else {
948             desc = (struct rmap *) (page_private & ~1ul);
949             PrintDebug("rmap_wrprot: reverse desc multimap\n");
950             shadow_pte = desc->shadow_ptes[0];
951         }
952                 
953         PrintDebug("rmap_wrprot: pg_priv %p, host_fn %p, shdw_pte %p\n",
954                 (void *)page_private, (void *)PAGE_BASE_ADDR(host_pa), (void*)*((uint64_t*)shadow_pte));
955         
956         //CHECKPOINT
957         rmap_remove(core, shadow_pte); 
958
959         //PrintDebug("rmap_wrprot: shadow_pte->page_base_addr (%p)\n", 
960         //      (void *)BASE_TO_PAGE_ADDR(shadow_pte->page_base_addr));
961
962         ((gen_pt_t *)shadow_pte)->writable = 0;
963         PrintDebug("rmap_wrprot: %p\n",(void*)*((uint64_t *)shadow_pte));
964                                 
965         page_private = core->vm_info.mem_map.base_region.mem_map[PAGE_BASE_ADDR(host_pa)];
966
967         PrintDebug("rmap_wrprot: page_private %p\n",(void*)page_private);
968     }   
969
970     PrintDebug("rmap_wrprot: done\n");
971
972 }
973
974 void shadow_page_pre_write(struct guest_info * core, addr_t guest_pa, int bytes, int force) {
975 //guest frame number is not guest physical address
976     addr_t guest_fn = PAGE_BASE_ADDR(guest_pa);
977     struct shadow_page_cache_data * page;
978     struct hlist_node *node, *n;
979     struct hlist_head * bucket;
980     unsigned index;
981
982     uint32_t* shdw32_table = NULL;
983     uint32_t* shdw32_entry = NULL;
984     uint64_t* shdw64_table = NULL;
985     uint64_t* shdw64_entry = NULL;
986         
987     unsigned pte_size;
988     unsigned offset = PAGE_OFFSET(guest_pa);
989     unsigned misaligned = 0;
990     int level;
991     int flooded = 0;
992
993     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
994
995     if (guest_fn == core->last_pt_write_guest_fn) {
996         ++core->last_pt_write_count;
997         if (core->last_pt_write_count >= 3) flooded = 1;
998     } else {
999         core->last_pt_write_guest_fn = guest_fn;
1000         core->last_pt_write_count = 1;
1001     }
1002
1003     PrintDebug("shdw_pre-write: gpa %p byte %d force %d flood %d last_gfn %p last_cnt %d\n",
1004         (void *)guest_pa,bytes,force,flooded,(void*)core->last_pt_write_guest_fn,core->last_pt_write_count);
1005
1006     index = shadow_page_table_hashfn(guest_fn) % NUM_SHADOW_PAGES;
1007     bucket = &core->shadow_page_hash[index];
1008
1009     PrintDebug("shdw_pre-write: check point after bucket\n");
1010         
1011     //hlist_for_each_entry_safe(page, node, bucket, hash_link) {
1012     hlist_for_each_entry_safe(page, node, n, bucket, hash_link) {
1013
1014         if (page->guest_fn != guest_fn || page->role.metaphysical) continue;
1015
1016         pte_size = 4; //because 32bit nonPAE for now
1017         pte_size = page->role.glevels == 2 ? 4 : 8;
1018
1019         if (!force) misaligned = (offset & (offset + bytes -1)) & ~(pte_size -1);
1020
1021         if (misaligned || flooded || force) {
1022             /*
1023             * Misaligned accesses are too much trobule to fix up
1024             * also they usually indicate a page is not used as a page table
1025             */
1026             PrintDebug("shdw_pre-write: misaligned\n");
1027             shadow_zap_page(core, page);
1028             continue;
1029         }       
1030
1031         level = page->role.hlevels;             
1032                 
1033         PrintDebug("shdw_pre-write: found out one page at the level of %d\n", level);
1034         
1035         if (mode == PROTECTED) {
1036             shdw32_table = (uint32_t*)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(PAGE_BASE_ADDR(page->page_pa)));
1037             shdw32_entry = (uint32_t*)&(shdw32_table[offset/sizeof(uint32_t)]);
1038
1039             if (*shdw32_entry & PT_PRESENT_MASK) {
1040                 if (level == PT_PAGE_TABLE_LEVEL) {
1041                     PrintDebug("shdw_pre-write: pte idx %d\n", (unsigned int)(offset/sizeof(uint32_t)));
1042                     rmap_remove(core, (addr_t)shdw32_entry);
1043                     memset((void*)shdw32_entry, 0, sizeof(uint32_t));
1044                 
1045                 } else {
1046                     shadow_page_remove_shadow_pde(core, page, (addr_t)shdw32_entry);
1047                     memset((void*)shdw32_entry, 0, sizeof(uint32_t));                   
1048                 }
1049             }
1050                         
1051         } else if (mode == LONG_32_COMPAT || mode == LONG) {
1052
1053             shdw64_table = (uint64_t*)V3_VAddr((void*)(addr_t)BASE_TO_PAGE_ADDR(PAGE_BASE_ADDR(page->page_pa)));
1054             shdw64_entry = (uint64_t*)&(shdw64_table[offset/sizeof(uint64_t)]);
1055
1056             if (*shdw64_entry & PT_PRESENT_MASK) {
1057                 if (level == PT_PAGE_TABLE_LEVEL) {
1058                     PrintDebug("shdw_pre-write: pte idx %d\n", (unsigned int)(offset/sizeof(uint64_t)));
1059                     rmap_remove(core, (addr_t)shdw64_entry);
1060                     memset((void*)shdw64_entry, 0, sizeof(uint64_t));
1061                 } else {
1062                     shadow_page_remove_shadow_pde(core, page, (addr_t)shdw64_entry);
1063                     memset((void*)shdw64_entry, 0, sizeof(uint64_t));                   
1064                 }
1065             }
1066         }
1067     }
1068 }
1069
1070 //emulation for synchronization
1071 void shadow_page_post_write(struct guest_info * core, addr_t guest_pa)  {
1072
1073 }
1074
1075 int shadow_unprotect_page_virt(struct guest_info * core, addr_t guest_va) {
1076     addr_t guest_pa;
1077
1078     if (guest_va_to_guest_pa(core, guest_va, &guest_pa) != 0) {
1079         PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
1080                 (void *)guest_va);
1081         return -1;
1082     }
1083         
1084     return shadow_unprotect_page(core, PAGE_BASE_ADDR(guest_pa));
1085 }
1086
1087 void shadow_free_some_pages(struct guest_info * core) {
1088     while (core->n_free_shadow_pages < REFILE_PAGES) {
1089         struct shadow_page_cache_data * page;
1090         page = container_of(core->active_shadow_pages.prev,
1091             struct shadow_page_cache_data, link);
1092         shadow_zap_page(core,page);
1093     }           
1094 }
1095
1096 void shadow_free_all_pages(struct guest_info *core) {
1097
1098     struct shadow_page_cache_data * sp, *node;
1099     list_for_each_entry_safe(sp, node, &core->active_shadow_pages, link) {
1100         shadow_zap_page(core , sp);
1101     }
1102 }
1103
1104
1105 static struct shadow_page_cache_data * create_new_shadow_pt(struct guest_info * core);
1106
1107
1108 #include "vmm_shdw_pg_cache_32.h"
1109 #include "vmm_shdw_pg_cache_32pae.h"
1110 #include "vmm_shdw_pg_cache_64.h"
1111
1112 static int vtlb_caching_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1113
1114     V3_Print("VTLB Caching initialization\n");
1115     return 0;
1116 }
1117
1118 static int vtlb_caching_deinit(struct v3_vm_info * vm) {
1119     return -1;
1120 }
1121
1122 static int vtlb_caching_local_init(struct guest_info * core) {
1123
1124     V3_Print("VTLB local initialization\n");
1125
1126     INIT_LIST_HEAD(&core->active_shadow_pages);
1127     INIT_LIST_HEAD(&core->free_pages);
1128
1129     alloc_shadow_pages(core);   
1130
1131     shadow_topup_caches(core);
1132
1133     core->prev_cr3_pdt_base = 0;
1134         
1135     return 0;
1136 }
1137
1138
1139 static int vtlb_caching_activate_shdw_pt(struct guest_info * core) {
1140     switch (v3_get_vm_cpu_mode(core)) {
1141
1142         case PROTECTED:
1143             return activate_shadow_pt_32(core);
1144         case PROTECTED_PAE:
1145             return activate_shadow_pt_32pae(core);
1146         case LONG:
1147         case LONG_32_COMPAT:
1148         case LONG_16_COMPAT:
1149             return activate_shadow_pt_64(core);
1150         default:
1151             PrintError("Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
1152             return -1;
1153     }
1154
1155     return 0;
1156 }
1157
1158 static int vtlb_caching_invalidate_shdw_pt(struct guest_info * core) {
1159     return vtlb_caching_activate_shdw_pt(core);
1160 }
1161
1162
1163 static int vtlb_caching_handle_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
1164
1165         switch (v3_get_vm_cpu_mode(core)) {
1166             case PROTECTED:
1167                 return handle_shadow_pagefault_32(core, fault_addr, error_code);
1168                 break;
1169             case PROTECTED_PAE:
1170                 return handle_shadow_pagefault_32pae(core, fault_addr, error_code);
1171             case LONG:
1172             case LONG_32_COMPAT:
1173             case LONG_16_COMPAT:
1174                 return handle_shadow_pagefault_64(core, fault_addr, error_code);
1175                 break;
1176             default:
1177                 PrintError("Unhandled CPU Mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
1178                 return -1;
1179         }
1180 }
1181
1182
1183 static int vtlb_caching_handle_invlpg(struct guest_info * core, addr_t vaddr) {
1184
1185     switch (v3_get_vm_cpu_mode(core)) {
1186         case PROTECTED:
1187             return handle_shadow_invlpg_32(core, vaddr);
1188         case PROTECTED_PAE:
1189             return handle_shadow_invlpg_32pae(core, vaddr);
1190         case LONG:
1191         case LONG_32_COMPAT:
1192         case LONG_16_COMPAT:
1193             return handle_shadow_invlpg_64(core, vaddr);
1194         default:
1195             PrintError("Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
1196             return -1;
1197     }
1198 }
1199
1200 static struct v3_shdw_pg_impl vtlb_caching_impl =  {
1201     .name = "VTLB_CACHING",
1202     .init = vtlb_caching_init,
1203     .deinit = vtlb_caching_deinit,
1204     .local_init = vtlb_caching_local_init,
1205     .handle_pagefault = vtlb_caching_handle_pf,
1206     .handle_invlpg = vtlb_caching_handle_invlpg,
1207     .activate_shdw_pt = vtlb_caching_activate_shdw_pt,
1208     .invalidate_shdw_pt = vtlb_caching_invalidate_shdw_pt
1209 };
1210
1211
1212
1213
1214
1215 register_shdw_pg_impl(&vtlb_caching_impl);
1216
1217 #endif