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