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.


moved further along in the boot process....
[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->shdw_pg_mode == SHADOW_PAGING) {
119     if (guest_info->mem_mode == PHYSICAL_MEM) {
120       // guest virtual address is the same as the physical
121       *guest_pa = guest_va;
122       return 0;
123     }
124     
125     
126
127     // Guest Is in Paged mode
128     switch (guest_info->cpu_mode) {
129     case PROTECTED:
130       {
131         addr_t tmp_pa = 0;
132         pde32_t * pde = 0;
133         addr_t guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3);
134
135
136         if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) {
137           PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde);
138           return -1;
139         }
140
141
142         switch (pde32_lookup(pde, guest_va, &tmp_pa)) {
143         case PDE32_ENTRY_NOT_PRESENT: 
144           *guest_pa = 0;
145           return -1;
146         case PDE32_ENTRY_LARGE_PAGE:
147           *guest_pa = tmp_pa;
148           return 0;
149         case PDE32_ENTRY_PTE32:
150           {
151             pte32_t * pte = 0;
152
153
154             if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) {
155               PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa);
156               return -1;
157             }
158             
159             PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa);
160
161             if (pte32_lookup(pte, guest_va, guest_pa) != 0) {
162               PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte);
163               //              PrintPT32(PDE32_INDEX(guest_va) << 22, pte);
164               return -1;
165             }
166
167             return 0;
168           }
169         default:
170           return -1;
171         }
172       }
173       case PROTECTED_PAE:
174         {
175           // Fill in
176         }
177       case LONG:
178         {
179           // Fill in
180         }
181     default:
182       return -1;
183     }
184   } else if (guest_info->shdw_pg_mode == NESTED_PAGING) {
185
186     // Fill in
187
188   } else {
189     return -1;
190   }
191
192
193   return 0;
194 }
195
196
197
198 /* !! Currently not implemented !! */
199 /* This will be a real pain.... its your standard page table walker in guest memory
200  * 
201  * For now we ignore it...
202  */
203 int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) {
204   *guest_va = 0;
205   PrintDebug("ERROR!!: GPA->GVA Not Implemented!!\n");
206   return -1;
207 }
208
209
210 /**********************************/
211 /* GROUP 2                        */
212 /**********************************/
213
214
215 int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) {
216   addr_t guest_pa = 0;
217
218   *host_pa = 0;
219
220   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
221     PrintDebug("In GVA->HPA: Invalid GVA(%x)->GPA lookup\n", guest_va);
222     return -1;
223   }
224   
225   if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) {
226     PrintDebug("In GVA->HPA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
227     return -1;
228   }
229
230   return 0;
231 }
232
233 /* !! Currently not implemented !! */
234 int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) {
235   addr_t guest_pa = 0;
236
237   *guest_va = 0;
238
239   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
240     PrintDebug("In HPA->GVA: Invalid HPA(%x)->GPA lookup\n", host_pa);
241     return -1;
242   }
243
244   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
245     PrintDebug("In HPA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
246     return -1;
247   }
248
249   return 0;
250 }
251
252
253
254
255 int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) {
256   addr_t guest_pa = 0;
257   addr_t host_pa = 0;
258
259   *host_va = 0;
260
261   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
262     PrintDebug("In GVA->HVA: Invalid GVA(%x)->GPA lookup\n", guest_va);
263     return -1;
264   }
265
266   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
267     PrintDebug("In GVA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
268     return -1;
269   }
270
271   if (host_pa_to_host_va(host_pa, host_va) != 0) {
272     PrintDebug("In GVA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
273     return -1;
274   }
275
276   return 0;
277 }
278
279
280 /* !! Currently not implemented !! */
281 int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) {
282   addr_t host_pa = 0;
283   addr_t guest_pa = 0;
284
285   *guest_va = 0;
286
287   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
288     PrintDebug("In HVA->GVA: Invalid HVA(%x)->HPA lookup\n", host_va);
289     return -1;
290   }
291
292   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
293     PrintDebug("In HVA->GVA: Invalid HPA(%x)->GPA lookup\n", host_va);
294     return -1;
295   }
296
297   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
298     PrintDebug("In HVA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
299     return -1;
300   }
301
302   return 0;
303 }
304
305
306
307
308
309
310 /* This is a straight address conversion + copy, 
311  *   except for the tiny little issue of crossing page boundries.....
312  */
313 int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int count, char * dest) {
314   addr_t cursor = guest_va;
315   int bytes_read = 0;
316
317
318
319   while (count > 0) {
320     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
321     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
322     addr_t host_addr = 0;
323
324
325
326     /* JRL FIXME:
327      * This should be somewhere else....
328      */
329     addr_t tmp_addr;
330       
331     addr_t shadow_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.shadow_cr3);
332     
333     // Check the Shadow Page Tables first (Virtual TLB)
334     if (pt32_lookup((pde32_t *)shadow_pde, cursor, &tmp_addr) == 0) {
335       host_addr = tmp_addr;
336
337       if (host_pa_to_host_va(tmp_addr, &host_addr) != 0) {
338         return bytes_read;
339       }
340     } else {
341     
342       // No entry in the VTLB, do a guest page table walk
343    
344       if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
345         PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor);
346         return bytes_read;
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