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.


Guest mem gpa/gva memset functions
[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 #ifndef V3_CONFIG_DEBUG_MEM_ERRORS
25 #undef PrintDebug
26 #define PrintDebug(fmt, args...)
27 #endif
28
29 extern struct v3_os_hooks * os_hooks;
30
31
32 /**********************************/
33 /* GROUP 0                        */
34 /**********************************/
35
36 int v3_hva_to_hpa(addr_t hva, addr_t * hpa) {
37     if ((os_hooks) && (os_hooks)->vaddr_to_paddr) {
38
39         *hpa = (addr_t)(os_hooks)->vaddr_to_paddr((void *)hva);
40   
41         if (*hpa == 0) {
42             PrintDebug(VM_NONE, VCORE_NONE, "In HVA->HPA: Invalid HVA(%p)->HPA lookup\n",  
43                        (void *)hva);
44             return -1;
45         }
46     } else {
47         PrintDebug(VM_NONE, VCORE_NONE,"In HVA->HPA: os_hooks not defined\n");
48         return -1;
49     }
50     return 0;
51 }
52
53
54 int v3_hpa_to_hva(addr_t hpa, addr_t * hva) {
55     if ((os_hooks) && (os_hooks)->paddr_to_vaddr) {
56
57         *hva = (addr_t)(os_hooks)->paddr_to_vaddr((void *)hpa);
58     
59         if (*hva == 0) {
60             PrintDebug(VM_NONE, VCORE_NONE,"In HPA->HVA: Invalid HPA(%p)->HVA lookup\n",  
61                        (void *)hpa);
62             return -1;
63         }
64     } else {
65         PrintDebug(VM_NONE, VCORE_NONE,"In HPA->HVA: os_hooks not defined\n");
66         return -1;
67     }
68     return 0;
69 }
70
71 int v3_gpa_to_hpa(struct guest_info * info, addr_t gpa, addr_t * hpa) {
72     struct v3_mem_region * reg = v3_get_mem_region(info->vm_info, info->vcpu_id, gpa);
73
74     if (reg == NULL) {
75         PrintDebug(info->vm_info,info,"In GPA->HPA: Could not find address in shadow map (addr=%p) (NULL REGION)\n", 
76                    (void *)gpa);
77         return -1;
78     }
79     
80     if (reg->flags.alloced == 0) {
81         //PrintDebug(info->vm_info, info, "In GPA->HPA: Tried to translate physical address of non allocated page (addr=%p)\n", 
82         //         (void *)gpa);
83     //v3_print_mem_map(info->vm_info);
84         return -1;
85     }
86         
87     *hpa = (gpa - reg->guest_start) + reg->host_addr;
88
89     return 0;
90 }
91
92
93 /* !! Currently not implemented !! */
94 // This is a scan of the shadow map
95 // For now we ignore it
96 // 
97 int v3_hpa_to_gpa(struct guest_info * guest_info, addr_t hpa, addr_t * gpa) {
98     *gpa = 0;
99     PrintDebug(guest_info->vm_info, guest_info, "ERROR!!! HPA->GPA currently not implemented!!!\n");
100
101     return -1;
102 }
103
104
105
106 /**********************************/
107 /* GROUP 1                        */
108 /**********************************/
109
110
111 /* !! Currently not implemented !! */
112 // This will return negative until we implement hpa_to_guest_pa()
113 int v3_hva_to_gpa(struct guest_info * guest_info, addr_t hva, addr_t * gpa) {
114     addr_t hpa = 0;
115     *gpa = 0;
116
117     if (v3_hva_to_hpa(hva, &hpa) != 0) {
118         PrintDebug(guest_info->vm_info, guest_info, "In HVA->GPA: Invalid HVA(%p)->HPA lookup\n", 
119                    (void *)hva);
120         return -1;
121     }
122
123     if (v3_hpa_to_gpa(guest_info, hpa, gpa) != 0) {
124         PrintDebug(guest_info->vm_info, guest_info, "In HVA->GPA: Invalid HPA(%p)->GPA lookup\n", 
125                    (void *)hpa);
126         return -1;
127     }
128
129     return 0;
130 }
131
132
133
134
135 int v3_gpa_to_hva(struct guest_info * guest_info, addr_t gpa, addr_t * hva) {
136     addr_t hpa = 0;
137
138     *hva = 0;
139
140     if (v3_gpa_to_hpa(guest_info, gpa, &hpa) != 0) {
141         //      PrintDebug(guest_info->vm_info, guest_info, "In GPA->HVA: Invalid GPA(%p)->HPA lookup\n", 
142         //         (void *)gpa);
143         return -1;
144     }
145   
146     if (v3_hpa_to_hva(hpa, hva) != 0) {
147         PrintDebug(guest_info->vm_info, guest_info, "In GPA->HVA: Invalid HPA(%p)->HVA lookup\n", 
148                    (void *)hpa);
149         return -1;
150     }
151
152     return 0;
153 }
154
155
156 int v3_gva_to_gpa(struct guest_info * guest_info, addr_t gva, addr_t * gpa) {
157     v3_reg_t guest_cr3 = 0;
158
159     if (guest_info->mem_mode == PHYSICAL_MEM) {
160         // guest virtual address is the same as the physical
161         *gpa = gva;
162         return 0;
163     }
164
165     if (guest_info->shdw_pg_mode == SHADOW_PAGING) {
166         guest_cr3 = guest_info->shdw_pg_state.guest_cr3;
167     } else {
168         guest_cr3 = guest_info->ctrl_regs.cr3;
169     }
170
171
172     // Guest Is in Paged mode
173     switch (guest_info->cpu_mode) {
174         case PROTECTED:
175             if (v3_translate_guest_pt_32(guest_info, guest_cr3, gva, gpa) == -1) {
176                 PrintDebug(guest_info->vm_info, guest_info, "Could not translate addr (%p) through 32 bit guest PT at %p\n", 
177                            (void *)gva, (void *)(addr_t)guest_cr3);
178                 return -1;
179             }
180             break;
181         case PROTECTED_PAE:
182             if (v3_translate_guest_pt_32pae(guest_info, guest_cr3, gva, gpa) == -1) {
183                 PrintDebug(guest_info->vm_info, guest_info, "Could not translate addr (%p) through 32 bitpae guest PT at %p\n", 
184                            (void *)gva, (void *)(addr_t)guest_cr3);
185                 return -1;
186             }
187             break;
188         case LONG:
189         case LONG_32_COMPAT:
190         case LONG_16_COMPAT:
191             if (v3_translate_guest_pt_64(guest_info, guest_cr3, gva, gpa) == -1) {
192                 PrintDebug(guest_info->vm_info, guest_info, "Could not translate addr (%p) through 64 bit guest PT at %p\n", 
193                            (void *)gva, (void *)(addr_t)guest_cr3);
194                 return -1;
195             }
196             break;
197         default:
198             return -1;
199     }
200   
201     return 0;
202 }
203
204
205
206 /* !! Currently not implemented !! */
207 /* This will be a real pain.... its your standard page table walker in guest memory
208  * 
209  * For now we ignore it...
210  */
211 int v3_gpa_to_gva(struct guest_info * guest_info, addr_t gpa, addr_t * gva) {
212     *gva = 0;
213     PrintDebug(guest_info->vm_info, guest_info, "ERROR!!: GPA->GVA Not Implemented!!\n");
214     return -1;
215 }
216
217
218 /**********************************/
219 /* GROUP 2                        */
220 /**********************************/
221
222
223 int v3_gva_to_hpa(struct guest_info * guest_info, addr_t gva, addr_t * hpa) {
224     addr_t gpa = 0;
225
226     *hpa = 0;
227
228     if (v3_gva_to_gpa(guest_info, gva, &gpa) != 0) {
229         PrintDebug(guest_info->vm_info, guest_info, "In GVA->HPA: Invalid GVA(%p)->GPA lookup\n", 
230                    (void *)gva);
231         return -1;
232     }
233   
234     if (v3_gpa_to_hpa(guest_info, gpa, hpa) != 0) {
235         PrintDebug(guest_info->vm_info, guest_info, "In GVA->HPA: Invalid GPA(%p)->HPA lookup\n", 
236                    (void *)gpa);
237         return -1;
238     }
239
240     return 0;
241 }
242
243 /* !! Currently not implemented !! */
244 int v3_hpa_to_gva(struct guest_info * guest_info, addr_t hpa, addr_t * gva) {
245     addr_t gpa = 0;
246
247     *gva = 0;
248
249     if (v3_hpa_to_gpa(guest_info, hpa, &gpa) != 0) {
250         PrintDebug(guest_info->vm_info, guest_info, "In HPA->GVA: Invalid HPA(%p)->GPA lookup\n", 
251                    (void *)hpa);
252         return -1;
253     }
254
255     if (v3_gpa_to_gva(guest_info, gpa, gva) != 0) {
256         PrintDebug(guest_info->vm_info, guest_info, "In HPA->GVA: Invalid GPA(%p)->GVA lookup\n", 
257                    (void *)gpa);
258         return -1;
259     }
260
261     return 0;
262 }
263
264
265
266
267 int v3_gva_to_hva(struct guest_info * guest_info, addr_t gva, addr_t * hva) {
268     addr_t gpa = 0;
269     addr_t hpa = 0;
270
271     *hva = 0;
272
273     if (v3_gva_to_gpa(guest_info, gva, &gpa) != 0) {
274         PrintDebug(guest_info->vm_info, guest_info, "In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
275                    (void *)gva);
276         return -1;
277     }
278
279     if (v3_gpa_to_hpa(guest_info, gpa, &hpa) != 0) {
280         PrintDebug(guest_info->vm_info, guest_info, "In GVA->HVA: Invalid GPA(%p)->HPA lookup\n", 
281                    (void *)gpa);
282         return -1;
283     }
284
285     if (v3_hpa_to_hva(hpa, hva) != 0) {
286         PrintDebug(guest_info->vm_info, guest_info, "In GVA->HVA: Invalid HPA(%p)->HVA lookup\n", 
287                    (void *)hpa);
288         return -1;
289     }
290
291     return 0;
292 }
293
294
295 /* !! Currently not implemented !! */
296 int v3_hva_to_gva(struct guest_info * guest_info, addr_t hva, addr_t * gva) {
297     addr_t hpa = 0;
298     addr_t gpa = 0;
299
300     *gva = 0;
301
302     if (v3_hva_to_hpa(hva, &hpa) != 0) {
303         PrintDebug(guest_info->vm_info, guest_info, "In HVA->GVA: Invalid HVA(%p)->HPA lookup\n", 
304                    (void *)hva);
305         return -1;
306     }
307
308     if (v3_hpa_to_gpa(guest_info, hpa, &gpa) != 0) {
309         PrintDebug(guest_info->vm_info, guest_info, "In HVA->GVA: Invalid HPA(%p)->GPA lookup\n", 
310                    (void *)hva);
311         return -1;
312     }
313
314     if (v3_gpa_to_gva(guest_info, gpa, gva) != 0) {
315         PrintDebug(guest_info->vm_info, guest_info, "In HVA->GVA: Invalid GPA(%p)->GVA lookup\n", 
316                    (void *)gpa);
317         return -1;
318     }
319
320     return 0;
321 }
322
323
324
325
326
327
328 /* This is a straight address conversion + copy, 
329  *   except for the tiny little issue of crossing page boundries.....
330  */
331 int v3_read_gva_memory(struct guest_info * guest_info, addr_t gva, int count, uchar_t * dest) {
332     addr_t cursor = gva;
333     int bytes_read = 0;
334
335
336
337     while (count > 0) {
338         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
339         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
340         addr_t host_addr = 0;
341
342     
343         if (v3_gva_to_hva(guest_info, cursor, &host_addr) != 0) {
344             PrintDebug(guest_info->vm_info, guest_info, "Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
345             return bytes_read;
346         }
347     
348     
349
350         memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
351     
352         bytes_read += bytes_to_copy;
353         count -= bytes_to_copy;
354         cursor += bytes_to_copy;    
355     }
356
357     return bytes_read;
358 }
359
360
361
362
363
364
365 /* This is a straight address conversion + copy, 
366  *   except for the tiny little issue of crossing page boundries.....
367  */
368 int v3_read_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t * dest) {
369     addr_t cursor = gpa;
370     int bytes_read = 0;
371
372     while (count > 0) {
373         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
374         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
375         addr_t host_addr = 0;
376
377         if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
378             return bytes_read;
379         }    
380     
381         /*
382           PrintDebug(info->vm_info, info, "Trying to read %d bytes\n", bytes_to_copy);
383           PrintDebug(info->vm_info, info, "Dist to page edge=%d\n", dist_to_pg_edge);
384           PrintDebug(info->vm_info, info, "PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
385           PrintDebug(info->vm_info, info, "guest_pa=0x%x\n", guest_pa);
386         */
387     
388         memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
389
390         bytes_read += bytes_to_copy;
391         count -= bytes_to_copy;
392         cursor += bytes_to_copy;
393     }
394
395     return bytes_read;
396 }
397
398
399 /* This clones v3_read_gva_memory
400  *   We write only as far as page translations are available 
401  */
402 int v3_write_gva_memory(struct guest_info * guest_info, addr_t gva, int count, uchar_t * src) {
403     addr_t cursor = gva;
404     int bytes_written = 0;
405
406
407
408     while (count > 0) {
409         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
410         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
411         addr_t host_addr = 0;
412
413     
414         if (v3_gva_to_hva(guest_info, cursor, &host_addr) != 0) {
415             PrintDebug(guest_info->vm_info, guest_info, "Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
416             return bytes_written;
417         }
418     
419     
420
421         memcpy((void*)host_addr,
422                src + bytes_written, 
423                bytes_to_copy);
424     
425         bytes_written += bytes_to_copy;
426         count -= bytes_to_copy;
427         cursor += bytes_to_copy;    
428     }
429
430     return bytes_written;
431 }
432
433 int v3_set_gva_memory(struct guest_info * guest_info, addr_t gva, int count, uchar_t src) {
434     addr_t cursor = gva;
435     int bytes_written = 0;
436
437
438
439     while (count > 0) {
440         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
441         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
442         addr_t host_addr = 0;
443
444     
445         if (v3_gva_to_hva(guest_info, cursor, &host_addr) != 0) {
446             PrintDebug(guest_info->vm_info, guest_info, "Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
447             return bytes_written;
448         }
449     
450     
451
452         memset((void*)host_addr,
453                src,
454                bytes_to_copy);
455     
456         bytes_written += bytes_to_copy;
457         count -= bytes_to_copy;
458         cursor += bytes_to_copy;    
459     }
460
461     return bytes_written;
462 }
463
464
465
466
467 /* This is a straight address conversion + copy, 
468  *   except for the tiny little issue of crossing page boundries.....
469  */
470 int v3_write_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t * src) {
471     addr_t cursor = gpa;
472     int bytes_written = 0;
473
474     while (count > 0) {
475         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
476         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
477         addr_t host_addr;
478
479         if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
480             return bytes_written;
481         }
482
483
484         memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
485
486         bytes_written += bytes_to_copy;
487         count -= bytes_to_copy;
488         cursor += bytes_to_copy;    
489     }
490
491     return bytes_written;
492 }
493
494
495 int v3_set_gpa_memory(struct guest_info * guest_info, addr_t gpa, int count, uchar_t src) {
496     addr_t cursor = gpa;
497     int bytes_written = 0;
498
499     while (count > 0) {
500         int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
501         int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
502         addr_t host_addr;
503
504         if (v3_gpa_to_hva(guest_info, cursor, &host_addr) != 0) {
505             return bytes_written;
506         }
507
508
509         memset((void*)host_addr, src, bytes_to_copy);
510
511         bytes_written += bytes_to_copy;
512         count -= bytes_to_copy;
513         cursor += bytes_to_copy;    
514     }
515
516     return bytes_written;
517 }
518