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.


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