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.


more shadow paging changes
[palacios.git] / palacios / src / palacios / vmm_shadow_paging.c
1 #include <palacios/vmm_shadow_paging.h>
2
3
4 #include <palacios/vmm.h>
5 #include <palacios/vm_guest_mem.h>
6
7
8
9
10 int init_shadow_page_state(struct shadow_page_state * state) {
11   state->guest_mode = PDE32;
12   state->shadow_mode = PDE32;
13   
14   state->guest_cr3 = 0;
15   state->shadow_cr3 = 0;
16
17   return 0;
18 }
19
20 int handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
21   if (info->cpu_mode == PROTECTED_PG) {
22     return handle_shadow_pagefault32(info, fault_addr, error_code);
23   } else {
24     return -1;
25   }
26 }
27
28
29 int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
30   pde32_t * guest_pde = NULL;
31   pde32_t * shadow_pde = (pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3);
32   addr_t guest_cr3 = CR3_TO_PDE32(info->shdw_pg_state.guest_cr3);
33   pt_access_status_t guest_pde_access;
34   pt_access_status_t shadow_pde_access;
35   pde32_t * guest_pde_entry = NULL;
36   pde32_t * shadow_pde_entry = (pde32_t *)&(shadow_pde[PDE32_INDEX(fault_addr)]);
37
38   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pde) == -1) {
39     PrintDebug("Invalid Guest PDE Address: 0x%x\n", guest_cr3);
40     return -1;
41   }
42
43
44   guest_pde_entry = (pde32_t *)&(guest_pde[PDE32_INDEX(fault_addr)]);
45
46   // Check the guest page permissions
47   guest_pde_access = can_access_pde32(guest_pde, fault_addr, error_code);
48
49   if (guest_pde_access != PT_ACCESS_OK) {
50
51     //
52     // inject page fault to the guest (Guest PDE fault)
53     //
54
55     PrintDebug("Guest Page fault (currently not handled)\n");
56     return -1;
57   }
58
59   shadow_pde_access = can_access_pde32(shadow_pde, fault_addr, error_code);
60
61
62   if (shadow_pde_access == PT_ENTRY_NOT_PRESENT) {
63     pte32_t * shadow_pte = NULL;
64
65     V3_AllocPages(shadow_pte, 1);
66     memset(shadow_pte, 0, PAGE_SIZE);
67
68     shadow_pde_entry->pt_base_addr = PD32_BASE_ADDR(shadow_pte);
69     
70
71     shadow_pde_entry->present = 1;
72     shadow_pde_entry->user_page = guest_pde_entry->user_page;
73     
74     // VMM Specific options
75     shadow_pde_entry->write_through = 0;
76     shadow_pde_entry->cache_disable = 0;
77     shadow_pde_entry->global_page = 0;
78     //
79
80     guest_pde_entry->accessed = 1;
81
82     if (guest_pde_entry->large_page == 0) {
83       shadow_pde_entry->writable = guest_pde_entry->writable;
84     } else {
85       /*
86        * Check the Intel manual because we are ignoring Large Page issues here
87        */
88     }
89
90   } else if (shadow_pde_access == PT_WRITE_ERROR) {
91
92     //
93     // Page Directory Entry marked read-only
94     //
95
96     PrintDebug("Shadow Paging Write Error\n");
97     return -1;
98   } else if (shadow_pde_access == PT_USER_ERROR) {
99
100     //
101     // Page Directory Entry marked non-user
102     //
103     
104     PrintDebug("Shadow Paging User access error\n");
105     return -1;
106   } else if (shadow_pde_access == PT_ACCESS_OK) {
107     pte32_t * shadow_pte = (pte32_t *)PDE32_T_ADDR((*shadow_pde_entry));
108     pte32_t * guest_pte = NULL;
109
110     // Page Table entry fault
111     
112     if (guest_pa_to_host_va(info, PDE32_T_ADDR((*guest_pde_entry)), (addr_t*)&guest_pte) == -1) {
113       PrintDebug("Invalid Guest PTE Address: 0x%x\n", PDE32_T_ADDR((*guest_pde_entry)));
114       return -1;
115     }
116
117
118     if (handle_shadow_pte32_fault(info, fault_addr, error_code, shadow_pte, guest_pte)  == -1) {
119       PrintDebug("Error handling Page fault caused by PTE\n");
120       return -1;
121     }
122
123  }
124
125   PrintDebugPageTables(shadow_pde);
126
127   return 0;
128 }
129
130
131
132 /* 
133  * We assume the the guest pte pointer has already been translated to a host virtual address
134  */
135 int handle_shadow_pte32_fault(struct guest_info* info, 
136                               addr_t fault_addr, 
137                               pf_error_t error_code,
138                               pte32_t * shadow_pte, 
139                               pte32_t * guest_pte) {
140
141   pt_access_status_t guest_pte_access;
142   pt_access_status_t shadow_pte_access;
143   //  pte32_t * guest_pte_entry = (pte32_t *)&(guest_pte[PTE32_INDEX(fault_addr)]);;
144   //  pte32_t * shadow_pte_entry = (pte32_t *)&(shadow_pte[PTE32_INDEX(fault_addr)]);
145
146
147   // Check the guest page permissions
148   guest_pte_access = can_access_pte32(guest_pte, fault_addr, error_code);
149
150   if (guest_pte_access != PT_ACCESS_OK) {
151
152     //
153     // Inject page fault into the guest         
154     //
155
156     PrintDebug("Guest Page fault (currently not handled)\n");
157     return -1;
158   }
159
160
161   shadow_pte_access = can_access_pte32(shadow_pte, fault_addr, error_code);
162
163   if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
164
165     //
166     // Page Table Entry Not Present
167     //
168
169   } else if (shadow_pte_access == PT_WRITE_ERROR) {
170
171     //
172     // Page Table Entry marked read-only
173     //
174
175     PrintDebug("Shadow Paging Write Error\n");
176     return -1;
177   } else if (shadow_pte_access == PT_USER_ERROR) {
178
179     //
180     // Page Table Entry marked non-user
181     //
182     
183     PrintDebug("Shadow Paging User access error\n");
184     return -1;
185   } else if (shadow_pte_access == PT_ACCESS_OK) {
186
187     PrintDebug("Page Fault occurred for No Reason\n");
188     return -1;
189   }
190
191
192   return 0;
193 }
194
195
196
197 addr_t create_new_shadow_pt32(struct guest_info * info) {
198   void * host_pde = 0;
199
200   V3_AllocPages(host_pde, 1);
201   memset(host_pde, 0, PAGE_SIZE);
202
203   return (addr_t)host_pde;
204 }
205
206
207
208
209 addr_t setup_shadow_pt32(struct guest_info * info, addr_t virt_cr3) {
210   addr_t cr3_guest_addr = CR3_TO_PDE32(virt_cr3);
211   pde32_t * guest_pde;
212   pde32_t * host_pde = NULL;
213   int i;
214   
215   // Setup up guest_pde to point to the PageDir in host addr
216   if (guest_pa_to_host_va(info, cr3_guest_addr, (addr_t*)&guest_pde) == -1) {
217     return 0;
218   }
219   
220   V3_AllocPages(host_pde, 1);
221   memset(host_pde, 0, PAGE_SIZE);
222
223   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
224     if (guest_pde[i].present == 1) {
225       addr_t pt_host_addr;
226       addr_t host_pte;
227
228       if (guest_pa_to_host_va(info, PDE32_T_ADDR(guest_pde[i]), &pt_host_addr) == -1) {
229         return 0;
230       }
231
232       if ((host_pte = setup_shadow_pte32(info, pt_host_addr)) == 0) {
233         return 0;
234       }
235
236       host_pde[i].present = 1;
237       host_pde[i].pt_base_addr = PD32_BASE_ADDR(host_pte);
238
239       //
240       // Set Page DIR flags
241       //
242     }
243   }
244
245   PrintDebugPageTables(host_pde);
246
247   return (addr_t)host_pde;
248 }
249
250
251
252 addr_t setup_shadow_pte32(struct guest_info * info, addr_t pt_host_addr) {
253   pte32_t * guest_pte = (pte32_t *)pt_host_addr;
254   pte32_t * host_pte = NULL;
255   int i;
256
257   V3_AllocPages(host_pte, 1);
258   memset(host_pte, 0, PAGE_SIZE);
259
260   for (i = 0; i < MAX_PTE32_ENTRIES; i++) {
261     if (guest_pte[i].present == 1) {
262       addr_t guest_pa = PTE32_T_ADDR(guest_pte[i]);
263       shadow_mem_type_t page_type;
264       addr_t host_pa = 0;
265
266       page_type = get_shadow_addr_type(info, guest_pa);
267
268       if (page_type == HOST_REGION_PHYSICAL_MEMORY) {
269         host_pa = get_shadow_addr(info, guest_pa);
270       } else {
271         
272         //
273         // Setup various memory types
274         //
275       }
276
277       host_pte[i].page_base_addr = PT32_BASE_ADDR(host_pa);
278       host_pte[i].present = 1;
279     }
280   }
281
282   return (addr_t)host_pte;
283 }
284
285