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.


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