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.


9c5545cb0d80b489cb5c1094e982189a42427545
[palacios.git] / palacios / src / palacios / mmu / vmm_shdw_pg_tlb.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  * Author: Chunxiao Diao <chunxiaodiao2012@u.northwestern.edu> 
16  *
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22 #include <palacios/vmm_shadow_paging.h>
23 #include <palacios/vmm_ctrl_regs.h>
24
25 #include <palacios/vm_guest.h>
26 #include <palacios/vm_guest_mem.h>
27
28
29 #ifndef V3_CONFIG_DEBUG_SHDW_PG_VTLB
30 #undef PrintDebug
31 #define PrintDebug(fmt, ...)
32 #endif
33
34
35 struct shadow_page_data {
36     v3_reg_t cr3;
37     addr_t page_pa;
38   
39     struct list_head page_list_node;
40 };
41
42
43 struct vtlb_local_state {
44  
45     struct list_head page_list;
46
47 };
48
49
50 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
51
52
53 #include "vmm_shdw_pg_tlb_32.h"
54 #include "vmm_shdw_pg_tlb_32pae.h"
55 #include "vmm_shdw_pg_tlb_64.h"
56
57 static inline int get_constraints(struct guest_info *core) 
58 {
59   // the current version of VTLB does not require any constraints
60   // on where page tables are allocated since it will use
61   // 32PAE page tables on a 64 bit machine even in 32 bit mode and below
62   return 0;  
63 }
64
65
66 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
67     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
68     struct vtlb_local_state * impl_state = (struct vtlb_local_state *)(state->local_impl_data);
69     v3_reg_t cur_cr3 = core->ctrl_regs.cr3;
70     struct shadow_page_data * page_tail = NULL;
71     addr_t shdw_page = 0;
72
73     if (!list_empty(&(impl_state->page_list))) {
74         page_tail = list_tail_entry(&(impl_state->page_list), struct shadow_page_data, page_list_node);
75
76
77         if (page_tail->cr3 != cur_cr3) {
78             PrintDebug(core->vm_info, core, "Reusing old shadow Page: %p (cur_CR3=%p)(page_cr3=%p) \n",
79                        (void *)(addr_t)page_tail->page_pa, 
80                        (void *)(addr_t)cur_cr3, 
81                        (void *)(addr_t)(page_tail->cr3));
82
83             list_move(&(page_tail->page_list_node), &(impl_state->page_list));
84
85             memset(V3_VAddr((void *)(page_tail->page_pa)), 0, PAGE_SIZE_4KB);
86
87
88             return page_tail;
89         }
90     }
91
92     // else  
93
94     page_tail = (struct shadow_page_data *)V3_Malloc(sizeof(struct shadow_page_data));
95
96     if (!page_tail) {
97         PrintError(core->vm_info, core, "Cannot allocate\n");
98         return NULL;
99     }
100
101     page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,get_constraints(core));
102
103     if (!page_tail->page_pa) {
104         PrintError(core->vm_info, core, "Cannot allocate page\n");
105         return NULL;
106     }
107
108     PrintDebug(core->vm_info, core, "Allocating new shadow Page: %p (cur_cr3=%p)\n", 
109                (void *)(addr_t)page_tail->page_pa, 
110                (void *)(addr_t)cur_cr3);
111
112     page_tail->cr3 = cur_cr3;
113     list_add(&(page_tail->page_list_node), &(impl_state->page_list));
114
115     shdw_page = (addr_t)V3_VAddr((void *)(page_tail->page_pa));
116     memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
117
118     return page_tail;
119 }
120
121
122
123 static int vtlb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
124
125     V3_Print(vm, VCORE_NONE, "VTLB initialization\n");
126     return 0;
127 }
128
129 static int vtlb_deinit(struct v3_vm_info * vm) {
130     return 0;
131 }
132
133 static int vtlb_local_init(struct guest_info * core) {
134     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
135     struct vtlb_local_state * vtlb_state = NULL;
136
137     V3_Print(core->vm_info, core, "VTLB local initialization\n");
138
139     vtlb_state = (struct vtlb_local_state *)V3_Malloc(sizeof(struct vtlb_local_state));
140
141     if (!vtlb_state) {
142         PrintError(core->vm_info, core, "Cannot allocate\n");
143         return -1;
144     }
145
146     INIT_LIST_HEAD(&(vtlb_state->page_list));
147
148     state->local_impl_data = vtlb_state;
149
150     return 0;
151 }
152
153
154 static int vtlb_local_deinit(struct guest_info * core) {
155     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
156     struct vtlb_local_state * vtlb_state = state->local_impl_data;
157
158     struct shadow_page_data * shdw_pg = NULL;
159     struct shadow_page_data * tmp = NULL;
160
161     // free page list...
162     list_for_each_entry_safe(shdw_pg, tmp, &(vtlb_state->page_list), page_list_node) {
163         list_del(&(shdw_pg->page_list_node));
164         V3_FreePages((void *)shdw_pg->page_pa, 1);
165         V3_Free(shdw_pg);
166     }
167
168
169     V3_Free(vtlb_state);
170
171     return 0;
172 }
173
174
175 static int vtlb_activate_shdw_pt(struct guest_info * core) {
176     switch (v3_get_vm_cpu_mode(core)) {
177
178         case PROTECTED:
179             return activate_shadow_pt_32(core);
180             break;
181         case PROTECTED_PAE:
182             return activate_shadow_pt_32pae(core);
183             break;
184         case LONG:
185         case LONG_32_COMPAT:
186         case LONG_16_COMPAT:
187             return activate_shadow_pt_64(core);
188             break;
189         default:
190             PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
191             return -1;
192             break;
193     }
194
195     return 0;
196 }
197
198 static int vtlb_invalidate_shdw_pt(struct guest_info * core) {
199     return vtlb_activate_shdw_pt(core);
200 }
201
202
203 static int vtlb_handle_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
204   
205         switch (v3_get_vm_cpu_mode(core)) {
206             case PROTECTED:
207                 return handle_shadow_pagefault_32(core, fault_addr, error_code);
208                 break;
209             case PROTECTED_PAE:
210                 return handle_shadow_pagefault_32pae(core, fault_addr, error_code);
211             case LONG:
212             case LONG_32_COMPAT:
213             case LONG_16_COMPAT:
214                 return handle_shadow_pagefault_64(core, fault_addr, error_code);
215                 break;
216             default:
217                 PrintError(core->vm_info, core, "Unhandled CPU Mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
218                 return -1;
219         }
220 }
221
222
223 static int vtlb_handle_invlpg(struct guest_info * core, addr_t vaddr) {
224
225     switch (v3_get_vm_cpu_mode(core)) {
226         case PROTECTED:
227             return handle_shadow_invlpg_32(core, vaddr);
228             break;
229         case PROTECTED_PAE:
230             return handle_shadow_invlpg_32pae(core, vaddr);
231             break;
232         case LONG:
233         case LONG_32_COMPAT:
234         case LONG_16_COMPAT:
235             return handle_shadow_invlpg_64(core, vaddr);
236             break;
237         default:
238             PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
239             return -1;
240             break;
241     }
242 }
243
244 static struct v3_shdw_pg_impl vtlb_impl =  {
245     .name = "VTLB",
246     .init = vtlb_init,
247     .deinit = vtlb_deinit,
248     .local_init = vtlb_local_init,
249     .local_deinit = vtlb_local_deinit,
250     .handle_pagefault = vtlb_handle_pf,
251     .handle_invlpg = vtlb_handle_invlpg,
252     .activate_shdw_pt = vtlb_activate_shdw_pt,
253     .invalidate_shdw_pt = vtlb_invalidate_shdw_pt
254 };
255
256
257
258
259
260 register_shdw_pg_impl(&vtlb_impl);