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.


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