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.


added invlpg support
[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->page_mode == SHADOW_PAGING) {
119     switch (guest_info->cpu_mode) {
120     case REAL:
121     case PROTECTED:
122     case LONG:
123     case PROTECTED_PAE:
124       // guest virtual address is the same as the physical
125       *guest_pa = guest_va;
126       return 0;
127     case PROTECTED_PG:
128       {
129         addr_t tmp_pa = 0;
130         pde32_t * pde = 0;
131         addr_t guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3);
132
133         if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) {
134           PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde);
135           return -1;
136         }
137
138
139         switch (pde32_lookup(pde, guest_va, &tmp_pa)) {
140         case PDE32_ENTRY_NOT_PRESENT: 
141           *guest_pa = 0;
142           return -1;
143         case PDE32_ENTRY_LARGE_PAGE:
144           *guest_pa = tmp_pa;
145           return 0;
146         case PDE32_ENTRY_PTE32:
147           {
148             pte32_t * pte = 0;
149
150
151             if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) {
152               PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa);
153               return -1;
154             }
155             
156             PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa);
157
158             if (pte32_lookup(pte, guest_va, guest_pa) != 0) {
159               PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte);
160               //              PrintPT32(PDE32_INDEX(guest_va) << 22, pte);
161               return -1;
162             }
163
164             return 0;
165           }
166         default:
167           return -1;
168         }
169       }
170       case PROTECTED_PAE_PG:
171         {
172           // Fill in
173         }
174       case LONG_PG:
175         {
176           // Fill in
177         }
178     default:
179       return -1;
180     }
181   } else if (guest_info->page_mode == NESTED_PAGING) {
182
183     // Fill in
184
185   } else {
186     return -1;
187   }
188
189
190   return 0;
191 }
192
193
194
195 /* !! Currently not implemented !! */
196 /* This will be a real pain.... its your standard page table walker in guest memory
197  * 
198  * For now we ignore it...
199  */
200 int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) {
201   *guest_va = 0;
202   PrintDebug("ERROR!!: GPA->GVA Not Implemented!!\n");
203   return -1;
204 }
205
206
207 /**********************************/
208 /* GROUP 2                        */
209 /**********************************/
210
211
212 int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) {
213   addr_t guest_pa = 0;
214
215   *host_pa = 0;
216
217   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
218     PrintDebug("In GVA->HPA: Invalid GVA(%x)->GPA lookup\n", guest_va);
219     return -1;
220   }
221   
222   if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) {
223     PrintDebug("In GVA->HPA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
224     return -1;
225   }
226
227   return 0;
228 }
229
230 /* !! Currently not implemented !! */
231 int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) {
232   addr_t guest_pa = 0;
233
234   *guest_va = 0;
235
236   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
237     PrintDebug("In HPA->GVA: Invalid HPA(%x)->GPA lookup\n", host_pa);
238     return -1;
239   }
240
241   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
242     PrintDebug("In HPA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
243     return -1;
244   }
245
246   return 0;
247 }
248
249
250
251
252 int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) {
253   addr_t guest_pa = 0;
254   addr_t host_pa = 0;
255
256   *host_va = 0;
257
258   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
259     PrintDebug("In GVA->HVA: Invalid GVA(%x)->GPA lookup\n", guest_va);
260     return -1;
261   }
262
263   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
264     PrintDebug("In GVA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
265     return -1;
266   }
267
268   if (host_pa_to_host_va(host_pa, host_va) != 0) {
269     PrintDebug("In GVA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
270     return -1;
271   }
272
273   return 0;
274 }
275
276
277 /* !! Currently not implemented !! */
278 int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) {
279   addr_t host_pa = 0;
280   addr_t guest_pa = 0;
281
282   *guest_va = 0;
283
284   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
285     PrintDebug("In HVA->GVA: Invalid HVA(%x)->HPA lookup\n", host_va);
286     return -1;
287   }
288
289   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
290     PrintDebug("In HVA->GVA: Invalid HPA(%x)->GPA lookup\n", host_va);
291     return -1;
292   }
293
294   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
295     PrintDebug("In HVA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
296     return -1;
297   }
298
299   return 0;
300 }
301
302
303
304
305
306
307 /* This is a straight address conversion + copy, 
308  *   except for the tiny little issue of crossing page boundries.....
309  */
310 int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int count, char * dest) {
311   addr_t cursor = guest_va;
312   int bytes_read = 0;
313
314
315
316   while (count > 0) {
317     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
318     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
319     addr_t host_addr = 0;
320
321     if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
322       PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor);
323       return bytes_read;
324     }
325
326     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
327     
328     bytes_read += bytes_to_copy;
329     count -= bytes_to_copy;
330     cursor += bytes_to_copy;    
331   }
332
333   return bytes_read;
334 }
335
336
337
338
339
340
341 /* This is a straight address conversion + copy, 
342  *   except for the tiny little issue of crossing page boundries.....
343  */
344 int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * dest) {
345   addr_t cursor = guest_pa;
346   int bytes_read = 0;
347
348   while (count > 0) {
349     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
350     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
351     addr_t host_addr = 0;
352
353     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
354       return bytes_read;
355     }
356
357     
358     /*
359       PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
360       PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
361       PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
362       PrintDebug("guest_pa=0x%x\n", guest_pa);
363     */
364     
365     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
366
367     bytes_read += bytes_to_copy;
368     count -= bytes_to_copy;
369     cursor += bytes_to_copy;
370   }
371
372   return bytes_read;
373 }
374
375
376
377
378 /* This is a straight address conversion + copy, 
379  *   except for the tiny little issue of crossing page boundries.....
380  */
381 int write_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * src) {
382   addr_t cursor = guest_pa;
383   int bytes_written = 0;
384
385   while (count > 0) {
386     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
387     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
388     addr_t host_addr;
389
390     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
391       return bytes_written;
392     }
393
394
395     memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
396
397     bytes_written += bytes_to_copy;
398     count -= bytes_to_copy;
399     cursor += bytes_to_copy;    
400   }
401
402   return bytes_written;
403 }
404