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.


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