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.


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