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.


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