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.


added ability to inject an env variable into guest user process
[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->cpu_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 /* KCH: currently only checks if we can perform a user-mode write
321    return 1 on success */
322 int v3_gva_can_access(struct guest_info * core, addr_t gva) {
323
324     v3_reg_t guest_cr3 = 0;
325     pf_error_t access_type;
326     pt_access_status_t access_status;
327
328     access_type.write = 1;
329     access_type.user = 1;
330     
331     if (core->mem_mode == PHYSICAL_MEM) {
332         return -1;
333     }
334     
335     if (core->shdw_pg_mode == SHADOW_PAGING) {
336         guest_cr3 = core->shdw_pg_state.guest_cr3;
337     } else {
338         guest_cr3 = core->ctrl_regs.cr3;
339     }
340     
341     // guest is in paged mode
342     switch (core->cpu_mode) {
343     case PROTECTED:
344         if (v3_check_guest_pt_32(core, guest_cr3, gva, access_type, &access_status) == -1) {
345             return -1;
346         }
347         break;
348     case PROTECTED_PAE:
349         if (v3_check_guest_pt_32pae(core, guest_cr3, gva, access_type, &access_status) == -1) {
350             return -1;
351         }
352         break;
353     case LONG:
354     case LONG_32_COMPAT:
355     case LONG_16_COMPAT:
356         if (v3_check_guest_pt_64(core, guest_cr3, gva, access_type, &access_status) == -1) {
357             return -1;
358         }
359         break;
360     default:
361         return -1;
362     }
363
364     if (access_status != PT_ACCESS_OK) {
365         return 0;
366     } else {
367         return 1;
368     }
369 }
370
371
372
373 /* This is a straight address conversion + copy, 
374  *   except for the tiny little issue of crossing page boundries.....
375  */
376 int v3_read_gva_memory(struct guest_info * guest_info, addr_t gva, int count, uchar_t * dest) {
377     addr_t cursor = gva;
378     int bytes_read = 0;
379
380
381
382     while (count > 0) {
383         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
384         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
385         addr_t host_addr = 0;
386
387     
388         if (v3_gva_to_hva(guest_info, cursor, &host_addr) != 0) {
389             PrintDebug("Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
390             return bytes_read;
391         }
392     
393     
394
395         memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
396     
397         bytes_read += bytes_to_copy;
398         count -= bytes_to_copy;
399         cursor += bytes_to_copy;    
400     }
401
402     return bytes_read;
403 }
404
405
406
407
408
409
410 /* This is a straight address conversion + copy, 
411  *   except for the tiny little issue of crossing page boundries.....
412  */
413 int v3_read_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t * dest) {
414     addr_t cursor = gpa;
415     int bytes_read = 0;
416
417     while (count > 0) {
418         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
419         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
420         addr_t host_addr = 0;
421
422         if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
423             return bytes_read;
424         }    
425     
426         /*
427           PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
428           PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
429           PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
430           PrintDebug("guest_pa=0x%x\n", guest_pa);
431         */
432     
433         memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
434
435         bytes_read += bytes_to_copy;
436         count -= bytes_to_copy;
437         cursor += bytes_to_copy;
438     }
439
440     return bytes_read;
441 }
442
443
444
445
446 /* This is a straight address conversion + copy, 
447  *   except for the tiny little issue of crossing page boundries.....
448  */
449 int v3_write_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t * src) {
450     addr_t cursor = gpa;
451     int bytes_written = 0;
452
453     while (count > 0) {
454         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
455         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
456         addr_t host_addr;
457
458         if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
459             return bytes_written;
460         }
461
462
463         memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
464
465         bytes_written += bytes_to_copy;
466         count -= bytes_to_copy;
467         cursor += bytes_to_copy;    
468     }
469
470     return bytes_written;
471 }
472