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.


e2ca0bf929f2e8a84b1773248e1bceaaf470815d
[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       PrintError("In HVA->HPA: Invalid HVA(%x)->HPA lookup\n", host_va);
19       return -1;
20     }
21   } else {
22     PrintError("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       PrintError("In HPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
36       return -1;
37     }
38   } else {
39     PrintError("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     PrintError("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   PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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         PrintError("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             PrintError("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             PrintError("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   PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     PrintError("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     if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
324       PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor);
325       return bytes_read;
326     }
327     
328     
329
330     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
331     
332     bytes_read += bytes_to_copy;
333     count -= bytes_to_copy;
334     cursor += bytes_to_copy;    
335   }
336
337   return bytes_read;
338 }
339
340
341
342
343
344
345 /* This is a straight address conversion + copy, 
346  *   except for the tiny little issue of crossing page boundries.....
347  */
348 int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * dest) {
349   addr_t cursor = guest_pa;
350   int bytes_read = 0;
351
352   while (count > 0) {
353     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
354     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
355     addr_t host_addr = 0;
356
357     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
358       return bytes_read;
359     }    
360     
361     /*
362       PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
363       PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
364       PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
365       PrintDebug("guest_pa=0x%x\n", guest_pa);
366     */
367     
368     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
369
370     bytes_read += bytes_to_copy;
371     count -= bytes_to_copy;
372     cursor += bytes_to_copy;
373   }
374
375   return bytes_read;
376 }
377
378
379
380
381 /* This is a straight address conversion + copy, 
382  *   except for the tiny little issue of crossing page boundries.....
383  */
384 int write_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * src) {
385   addr_t cursor = guest_pa;
386   int bytes_written = 0;
387
388   while (count > 0) {
389     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
390     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
391     addr_t host_addr;
392
393     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
394       return bytes_written;
395     }
396
397
398     memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
399
400     bytes_written += bytes_to_copy;
401     count -= bytes_to_copy;
402     cursor += bytes_to_copy;    
403   }
404
405   return bytes_written;
406 }
407