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.


really fixed the gpa->hpa error check
[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     struct v3_shadow_region * shdw_reg = v3_get_shadow_region(guest_info, guest_pa);
70
71     if (shdw_reg == NULL) {
72         PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (NULL REGION)\n", 
73                    (void *)guest_pa);
74         return -1;
75     }
76     
77     if ((shdw_reg->host_type == SHDW_REGION_INVALID) ||
78         (shdw_reg->host_type == SHDW_REGION_FULL_HOOK)) {
79         PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (reg_type=%s)\n", 
80                    (void *)guest_pa, v3_shdw_region_type_to_str(shdw_reg->host_type));
81         return -1;
82     }
83     
84     *host_pa = v3_get_shadow_addr(shdw_reg, guest_pa);
85
86     return 0;
87 }
88
89
90 /* !! Currently not implemented !! */
91 // This is a scan of the shadow map
92 // For now we ignore it
93 // 
94 int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_pa) {
95     *guest_pa = 0;
96     PrintError("ERROR!!! HPA->GPA currently not implemented!!!\n");
97
98     return -1;
99 }
100
101
102
103 /**********************************/
104 /* GROUP 1                        */
105 /**********************************/
106
107
108 /* !! Currently not implemented !! */
109 // This will return negative until we implement host_pa_to_guest_pa()
110 int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t * guest_pa) {
111     addr_t host_pa = 0;
112     *guest_pa = 0;
113
114     if (host_va_to_host_pa(host_va, &host_pa) != 0) {
115         PrintError("In HVA->GPA: Invalid HVA(%p)->HPA lookup\n", 
116                    (void *)host_va);
117         return -1;
118     }
119
120     if (host_pa_to_guest_pa(guest_info, host_pa, guest_pa) != 0) {
121         PrintError("In HVA->GPA: Invalid HPA(%p)->GPA lookup\n", 
122                    (void *)host_pa);
123         return -1;
124     }
125
126     return 0;
127 }
128
129
130
131
132 int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_va) {
133     addr_t host_pa = 0;
134
135     *host_va = 0;
136
137     if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
138         PrintError("In GPA->HVA: Invalid GPA(%p)->HPA lookup\n", 
139                    (void *)guest_pa);
140         return -1;
141     }
142   
143     if (host_pa_to_host_va(host_pa, host_va) != 0) {
144         PrintError("In GPA->HVA: Invalid HPA(%p)->HVA lookup\n", 
145                    (void *)host_pa);
146         return -1;
147     }
148
149     return 0;
150 }
151
152
153 int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * guest_pa) {
154     v3_reg_t guest_cr3 = 0;
155
156     if (guest_info->mem_mode == PHYSICAL_MEM) {
157         // guest virtual address is the same as the physical
158         *guest_pa = guest_va;
159         return 0;
160     }
161
162     if (guest_info->shdw_pg_mode == SHADOW_PAGING) {
163         guest_cr3 = guest_info->shdw_pg_state.guest_cr3;
164     } else {
165         guest_cr3 = guest_info->ctrl_regs.cr3;
166     }
167
168
169     // Guest Is in Paged mode
170     switch (guest_info->cpu_mode) {
171         case PROTECTED:
172             if (v3_translate_guest_pt_32(guest_info, guest_cr3, guest_va, guest_pa) == -1) {
173                 PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n", 
174                            (void *)guest_va, (void *)(addr_t)guest_cr3);
175                 return -1;
176             }
177             break;
178         case PROTECTED_PAE:
179             if (v3_translate_guest_pt_32pae(guest_info, guest_cr3, guest_va, guest_pa) == -1) {
180                 PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n", 
181                            (void *)guest_va, (void *)(addr_t)guest_cr3);
182                 return -1;
183             }
184             break;
185         case LONG:
186         case LONG_32_COMPAT:
187         case LONG_16_COMPAT:
188             if (v3_translate_guest_pt_64(guest_info, guest_cr3, guest_va, guest_pa) == -1) {
189                 PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n", 
190                            (void *)guest_va, (void *)(addr_t)guest_cr3);
191                 return -1;
192             }
193             break;
194         default:
195             return -1;
196     }
197   
198     return 0;
199 }
200
201
202
203 /* !! Currently not implemented !! */
204 /* This will be a real pain.... its your standard page table walker in guest memory
205  * 
206  * For now we ignore it...
207  */
208 int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) {
209     *guest_va = 0;
210     PrintError("ERROR!!: GPA->GVA Not Implemented!!\n");
211     return -1;
212 }
213
214
215 /**********************************/
216 /* GROUP 2                        */
217 /**********************************/
218
219
220 int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) {
221     addr_t guest_pa = 0;
222
223     *host_pa = 0;
224
225     if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
226         PrintError("In GVA->HPA: Invalid GVA(%p)->GPA lookup\n", 
227                    (void *)guest_va);
228         return -1;
229     }
230   
231     if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) {
232         PrintError("In GVA->HPA: Invalid GPA(%p)->HPA lookup\n", 
233                    (void *)guest_pa);
234         return -1;
235     }
236
237     return 0;
238 }
239
240 /* !! Currently not implemented !! */
241 int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) {
242     addr_t guest_pa = 0;
243
244     *guest_va = 0;
245
246     if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
247         PrintError("In HPA->GVA: Invalid HPA(%p)->GPA lookup\n", 
248                    (void *)host_pa);
249         return -1;
250     }
251
252     if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
253         PrintError("In HPA->GVA: Invalid GPA(%p)->GVA lookup\n", 
254                    (void *)guest_pa);
255         return -1;
256     }
257
258     return 0;
259 }
260
261
262
263
264 int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) {
265     addr_t guest_pa = 0;
266     addr_t host_pa = 0;
267
268     *host_va = 0;
269
270     if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
271         PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
272                    (void *)guest_va);
273         return -1;
274     }
275
276     if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
277         PrintError("In GVA->HVA: Invalid GPA(%p)->HPA lookup\n", 
278                    (void *)guest_pa);
279         return -1;
280     }
281
282     if (host_pa_to_host_va(host_pa, host_va) != 0) {
283         PrintError("In GVA->HVA: Invalid HPA(%p)->HVA lookup\n", 
284                    (void *)host_pa);
285         return -1;
286     }
287
288     return 0;
289 }
290
291
292 /* !! Currently not implemented !! */
293 int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) {
294     addr_t host_pa = 0;
295     addr_t guest_pa = 0;
296
297     *guest_va = 0;
298
299     if (host_va_to_host_pa(host_va, &host_pa) != 0) {
300         PrintError("In HVA->GVA: Invalid HVA(%p)->HPA lookup\n", 
301                    (void *)host_va);
302         return -1;
303     }
304
305     if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
306         PrintError("In HVA->GVA: Invalid HPA(%p)->GPA lookup\n", 
307                    (void *)host_va);
308         return -1;
309     }
310
311     if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
312         PrintError("In HVA->GVA: Invalid GPA(%p)->GVA lookup\n", 
313                    (void *)guest_pa);
314         return -1;
315     }
316
317     return 0;
318 }
319
320
321
322
323
324
325 /* This is a straight address conversion + copy, 
326  *   except for the tiny little issue of crossing page boundries.....
327  */
328 int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int count, uchar_t * dest) {
329     addr_t cursor = guest_va;
330     int bytes_read = 0;
331
332
333
334     while (count > 0) {
335         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
336         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
337         addr_t host_addr = 0;
338
339     
340         if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
341             PrintDebug("Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
342             return bytes_read;
343         }
344     
345     
346
347         memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
348     
349         bytes_read += bytes_to_copy;
350         count -= bytes_to_copy;
351         cursor += bytes_to_copy;    
352     }
353
354     return bytes_read;
355 }
356
357
358
359
360
361
362 /* This is a straight address conversion + copy, 
363  *   except for the tiny little issue of crossing page boundries.....
364  */
365 int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, uchar_t * dest) {
366     addr_t cursor = guest_pa;
367     int bytes_read = 0;
368
369     while (count > 0) {
370         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
371         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
372         addr_t host_addr = 0;
373
374         if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
375             return bytes_read;
376         }    
377     
378         /*
379           PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
380           PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
381           PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
382           PrintDebug("guest_pa=0x%x\n", guest_pa);
383         */
384     
385         memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
386
387         bytes_read += bytes_to_copy;
388         count -= bytes_to_copy;
389         cursor += bytes_to_copy;
390     }
391
392     return bytes_read;
393 }
394
395
396
397
398 /* This is a straight address conversion + copy, 
399  *   except for the tiny little issue of crossing page boundries.....
400  */
401 int write_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, uchar_t * src) {
402     addr_t cursor = guest_pa;
403     int bytes_written = 0;
404
405     while (count > 0) {
406         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
407         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
408         addr_t host_addr;
409
410         if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
411             return bytes_written;
412         }
413
414
415         memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
416
417         bytes_written += bytes_to_copy;
418         count -= bytes_to_copy;
419         cursor += bytes_to_copy;    
420     }
421
422     return bytes_written;
423 }
424