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.


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