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.


some nested paging fixes
[palacios.git] / palacios / src / palacios / vm_guest_mem.c
1 #include <palacios/vm_guest_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmm_paging.h>
4
5 extern struct vmm_os_hooks * os_hooks;
6
7
8 /**********************************/
9 /* GROUP 0                        */
10 /**********************************/
11
12 int host_va_to_host_pa(addr_t host_va, addr_t * host_pa) {
13   if ((os_hooks) && (os_hooks)->vaddr_to_paddr) {
14
15     *host_pa = (addr_t)(os_hooks)->vaddr_to_paddr((void *)host_va);
16   
17     if (*host_pa == 0) {
18       PrintDebug("In HVA->HPA: Invalid HVA(%x)->HPA lookup\n", host_va);
19       return -1;
20     }
21   } else {
22     PrintDebug("In HVA->HPA: os_hooks not defined\n");
23     return -1;
24   }
25   return 0;
26 }
27
28
29 int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) {
30   if ((os_hooks) && (os_hooks)->paddr_to_vaddr) {
31
32     *host_va = (addr_t)(os_hooks)->paddr_to_vaddr((void *)host_pa);
33     
34     if (*host_va == 0) {
35       PrintDebug("In HPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
36       return -1;
37     }
38   } else {
39     PrintDebug("In HPA->HVA: os_hooks not defined\n");
40     return -1;
41   }
42   return 0;
43 }
44
45
46
47 int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) {
48   // we use the shadow map here...
49   if (lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa) != HOST_REGION_PHYSICAL_MEMORY) {
50     PrintDebug("In GPA->HPA: Could not find address in shadow map (addr=%x)\n", guest_pa);
51     return -1;
52   }
53
54   return 0;
55 }
56
57
58 /* !! Currently not implemented !! */
59 // This is a scan of the shadow map
60 // For now we ignore it
61 // 
62 int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_pa) {
63   *guest_pa = 0;
64   PrintDebug("ERROR!!! HPA->GPA currently not implemented!!!\n");
65
66   return -1;
67 }
68
69
70
71 /**********************************/
72 /* GROUP 1                        */
73 /**********************************/
74
75
76 /* !! Currently not implemented !! */
77 // This will return negative until we implement host_pa_to_guest_pa()
78 int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t * guest_pa) {
79   addr_t host_pa = 0;
80   *guest_pa = 0;
81
82   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
83     PrintDebug("In HVA->GPA: Invalid HVA(%x)->HPA lookup\n", host_va);
84     return -1;
85   }
86
87   if (host_pa_to_guest_pa(guest_info, host_pa, guest_pa) != 0) {
88     PrintDebug("In HVA->GPA: Invalid HPA(%x)->GPA lookup\n", host_pa);
89     return -1;
90   }
91
92   return 0;
93 }
94
95
96
97
98 int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_va) {
99   addr_t host_pa = 0;
100
101   *host_va = 0;
102
103   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
104     PrintDebug("In GPA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
105     return -1;
106   }
107   
108   if (host_pa_to_host_va(host_pa, host_va) != 0) {
109     PrintDebug("In GPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
110     return -1;
111   }
112
113   return 0;
114 }
115
116
117 int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * guest_pa) {
118   if (guest_info->mem_mode == PHYSICAL_MEM) {
119     // guest virtual address is the same as the physical
120     *guest_pa = guest_va;
121     return 0;
122   }
123
124
125
126   // Guest Is in Paged mode
127   switch (guest_info->cpu_mode) {
128   case PROTECTED:
129     {
130       addr_t tmp_pa = 0;
131       pde32_t * pde = 0;
132       addr_t guest_pde = 0;
133       
134       if (guest_info->shdw_pg_mode == SHADOW_PAGING) {
135         guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3);
136       } else if (guest_info->shdw_pg_mode == NESTED_PAGING) {
137         guest_pde = CR3_TO_PDE32(guest_info->ctrl_regs.cr3);
138       }
139       
140       if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) {
141         PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde);
142         return -1;
143       }
144       
145       
146       switch (pde32_lookup(pde, guest_va, &tmp_pa)) {
147       case PDE32_ENTRY_NOT_PRESENT: 
148         *guest_pa = 0;
149         return -1;
150       case PDE32_ENTRY_LARGE_PAGE:
151         *guest_pa = tmp_pa;
152         return 0;
153       case PDE32_ENTRY_PTE32:
154         {
155           pte32_t * pte = 0;
156           
157           
158           if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) {
159             PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa);
160             return -1;
161           }
162           
163           PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa);
164           
165           if (pte32_lookup(pte, guest_va, guest_pa) != 0) {
166             PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte);
167             //        PrintPT32(PDE32_INDEX(guest_va) << 22, pte);
168             return -1;
169           }
170           
171           return 0;
172         }
173       default:
174         return -1;
175       }
176     }
177   case PROTECTED_PAE:
178     {
179       // Fill in
180     }
181   case LONG:
182     {
183       // Fill in
184     }
185   default:
186     return -1;
187   }
188   
189   
190   
191   return 0;
192 }
193
194
195
196 /* !! Currently not implemented !! */
197 /* This will be a real pain.... its your standard page table walker in guest memory
198  * 
199  * For now we ignore it...
200  */
201 int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) {
202   *guest_va = 0;
203   PrintDebug("ERROR!!: GPA->GVA Not Implemented!!\n");
204   return -1;
205 }
206
207
208 /**********************************/
209 /* GROUP 2                        */
210 /**********************************/
211
212
213 int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) {
214   addr_t guest_pa = 0;
215
216   *host_pa = 0;
217
218   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
219     PrintDebug("In GVA->HPA: Invalid GVA(%x)->GPA lookup\n", guest_va);
220     return -1;
221   }
222   
223   if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) {
224     PrintDebug("In GVA->HPA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
225     return -1;
226   }
227
228   return 0;
229 }
230
231 /* !! Currently not implemented !! */
232 int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) {
233   addr_t guest_pa = 0;
234
235   *guest_va = 0;
236
237   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
238     PrintDebug("In HPA->GVA: Invalid HPA(%x)->GPA lookup\n", host_pa);
239     return -1;
240   }
241
242   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
243     PrintDebug("In HPA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
244     return -1;
245   }
246
247   return 0;
248 }
249
250
251
252
253 int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) {
254   addr_t guest_pa = 0;
255   addr_t host_pa = 0;
256
257   *host_va = 0;
258
259   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
260     PrintDebug("In GVA->HVA: Invalid GVA(%x)->GPA lookup\n", guest_va);
261     return -1;
262   }
263
264   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
265     PrintDebug("In GVA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
266     return -1;
267   }
268
269   if (host_pa_to_host_va(host_pa, host_va) != 0) {
270     PrintDebug("In GVA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
271     return -1;
272   }
273
274   return 0;
275 }
276
277
278 /* !! Currently not implemented !! */
279 int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) {
280   addr_t host_pa = 0;
281   addr_t guest_pa = 0;
282
283   *guest_va = 0;
284
285   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
286     PrintDebug("In HVA->GVA: Invalid HVA(%x)->HPA lookup\n", host_va);
287     return -1;
288   }
289
290   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
291     PrintDebug("In HVA->GVA: Invalid HPA(%x)->GPA lookup\n", host_va);
292     return -1;
293   }
294
295   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
296     PrintDebug("In HVA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
297     return -1;
298   }
299
300   return 0;
301 }
302
303
304
305
306
307
308 /* This is a straight address conversion + copy, 
309  *   except for the tiny little issue of crossing page boundries.....
310  */
311 int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int count, char * dest) {
312   addr_t cursor = guest_va;
313   int bytes_read = 0;
314
315
316
317   while (count > 0) {
318     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
319     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
320     addr_t host_addr = 0;
321
322
323
324     /* JRL FIXME:
325      * This should be somewhere else....
326      */
327     /*  
328   addr_t tmp_addr;
329       
330     addr_t shadow_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.shadow_cr3);
331     
332     // Check the Shadow Page Tables first (Virtual TLB)
333     if (pt32_lookup((pde32_t *)shadow_pde, cursor, &tmp_addr) == 0) {
334       host_addr = tmp_addr;
335
336       if (host_pa_to_host_va(tmp_addr, &host_addr) != 0) {
337         return bytes_read;
338       }
339     } else {
340     
341       // No entry in the VTLB, do a guest page table walk
342    
343       if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
344         PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor);
345         return bytes_read;
346       }
347     }
348 */
349     /* JRL: END GRUESOME HACK */
350
351
352     
353     if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
354       PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor);
355       return bytes_read;
356     }
357     
358     
359
360     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
361     
362     bytes_read += bytes_to_copy;
363     count -= bytes_to_copy;
364     cursor += bytes_to_copy;    
365   }
366
367   return bytes_read;
368 }
369
370
371
372
373
374
375 /* This is a straight address conversion + copy, 
376  *   except for the tiny little issue of crossing page boundries.....
377  */
378 int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * dest) {
379   addr_t cursor = guest_pa;
380   int bytes_read = 0;
381
382   while (count > 0) {
383     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
384     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
385     addr_t host_addr = 0;
386
387     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
388       return bytes_read;
389     }    
390     
391     /*
392       PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
393       PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
394       PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
395       PrintDebug("guest_pa=0x%x\n", guest_pa);
396     */
397     
398     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
399
400     bytes_read += bytes_to_copy;
401     count -= bytes_to_copy;
402     cursor += bytes_to_copy;
403   }
404
405   return bytes_read;
406 }
407
408
409
410
411 /* This is a straight address conversion + copy, 
412  *   except for the tiny little issue of crossing page boundries.....
413  */
414 int write_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * src) {
415   addr_t cursor = guest_pa;
416   int bytes_written = 0;
417
418   while (count > 0) {
419     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
420     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
421     addr_t host_addr;
422
423     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
424       return bytes_written;
425     }
426
427
428     memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
429
430     bytes_written += bytes_to_copy;
431     count -= bytes_to_copy;
432     cursor += bytes_to_copy;    
433   }
434
435   return bytes_written;
436 }
437