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.


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