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.


f4cd053d780759bb500ce590a4810a9f2df17578
[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->mem_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     return v3_translate_guest_pt_32(guest_info, guest_cr3, guest_va, guest_pa);
165   case PROTECTED_PAE:
166     return v3_translate_guest_pt_32pae(guest_info, guest_cr3, guest_va, guest_pa);
167   case LONG:
168   case LONG_32_COMPAT:
169   case LONG_16_COMPAT:
170     return v3_translate_guest_pt_64(guest_info, guest_cr3, guest_va, guest_pa);
171   default:
172     return -1;
173   }
174   
175   return 0;
176 }
177
178
179
180 /* !! Currently not implemented !! */
181 /* This will be a real pain.... its your standard page table walker in guest memory
182  * 
183  * For now we ignore it...
184  */
185 int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) {
186   *guest_va = 0;
187   PrintError("ERROR!!: GPA->GVA Not Implemented!!\n");
188   return -1;
189 }
190
191
192 /**********************************/
193 /* GROUP 2                        */
194 /**********************************/
195
196
197 int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) {
198   addr_t guest_pa = 0;
199
200   *host_pa = 0;
201
202   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
203     PrintError("In GVA->HPA: Invalid GVA(%p)->GPA lookup\n", 
204                 (void *)guest_va);
205     return -1;
206   }
207   
208   if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) {
209     PrintError("In GVA->HPA: Invalid GPA(%p)->HPA lookup\n", 
210                (void *)guest_pa);
211     return -1;
212   }
213
214   return 0;
215 }
216
217 /* !! Currently not implemented !! */
218 int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) {
219   addr_t guest_pa = 0;
220
221   *guest_va = 0;
222
223   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
224     PrintError("In HPA->GVA: Invalid HPA(%p)->GPA lookup\n", 
225                 (void *)host_pa);
226     return -1;
227   }
228
229   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
230     PrintError("In HPA->GVA: Invalid GPA(%p)->GVA lookup\n", 
231                 (void *)guest_pa);
232     return -1;
233   }
234
235   return 0;
236 }
237
238
239
240
241 int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) {
242   addr_t guest_pa = 0;
243   addr_t host_pa = 0;
244
245   *host_va = 0;
246
247   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
248     PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
249                 (void *)guest_va);
250     return -1;
251   }
252
253   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
254     PrintError("In GVA->HVA: Invalid GPA(%p)->HPA lookup\n", 
255                 (void *)guest_pa);
256     return -1;
257   }
258
259   if (host_pa_to_host_va(host_pa, host_va) != 0) {
260     PrintError("In GVA->HVA: Invalid HPA(%p)->HVA lookup\n", 
261                 (void *)host_pa);
262     return -1;
263   }
264
265   return 0;
266 }
267
268
269 /* !! Currently not implemented !! */
270 int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) {
271   addr_t host_pa = 0;
272   addr_t guest_pa = 0;
273
274   *guest_va = 0;
275
276   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
277     PrintError("In HVA->GVA: Invalid HVA(%p)->HPA lookup\n", 
278                 (void *)host_va);
279     return -1;
280   }
281
282   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
283     PrintError("In HVA->GVA: Invalid HPA(%p)->GPA lookup\n", 
284                 (void *)host_va);
285     return -1;
286   }
287
288   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
289     PrintError("In HVA->GVA: Invalid GPA(%p)->GVA lookup\n", 
290                (void *)guest_pa);
291     return -1;
292   }
293
294   return 0;
295 }
296
297
298
299
300
301
302 /* This is a straight address conversion + copy, 
303  *   except for the tiny little issue of crossing page boundries.....
304  */
305 int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int count, uchar_t * dest) {
306   addr_t cursor = guest_va;
307   int bytes_read = 0;
308
309
310
311   while (count > 0) {
312     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
313     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
314     addr_t host_addr = 0;
315
316     
317     if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
318       PrintDebug("Invalid GVA(%p)->HVA lookup\n", (void *)cursor);
319       return bytes_read;
320     }
321     
322     
323
324     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
325     
326     bytes_read += bytes_to_copy;
327     count -= bytes_to_copy;
328     cursor += bytes_to_copy;    
329   }
330
331   return bytes_read;
332 }
333
334
335
336
337
338
339 /* This is a straight address conversion + copy, 
340  *   except for the tiny little issue of crossing page boundries.....
341  */
342 int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, uchar_t * dest) {
343   addr_t cursor = guest_pa;
344   int bytes_read = 0;
345
346   while (count > 0) {
347     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
348     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
349     addr_t host_addr = 0;
350
351     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
352       return bytes_read;
353     }    
354     
355     /*
356       PrintDebug("Trying to read %d bytes\n", bytes_to_copy);
357       PrintDebug("Dist to page edge=%d\n", dist_to_pg_edge);
358       PrintDebug("PAGE_ADDR=0x%x\n", PAGE_ADDR(cursor));
359       PrintDebug("guest_pa=0x%x\n", guest_pa);
360     */
361     
362     memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy);
363
364     bytes_read += bytes_to_copy;
365     count -= bytes_to_copy;
366     cursor += bytes_to_copy;
367   }
368
369   return bytes_read;
370 }
371
372
373
374
375 /* This is a straight address conversion + copy, 
376  *   except for the tiny little issue of crossing page boundries.....
377  */
378 int write_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, uchar_t * src) {
379   addr_t cursor = guest_pa;
380   int bytes_written = 0;
381
382   while (count > 0) {
383     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
384     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
385     addr_t host_addr;
386
387     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
388       return bytes_written;
389     }
390
391
392     memcpy((void*)host_addr, src + bytes_written, bytes_to_copy);
393
394     bytes_written += bytes_to_copy;
395     count -= bytes_to_copy;
396     cursor += bytes_to_copy;    
397   }
398
399   return bytes_written;
400 }
401