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.


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