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.


cleaned up emulation interface
[palacios.git] / palacios / src / palacios / vmm_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/vmm_mem.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_util.h>
23 //#include <palacios/vmm_decoder.h>
24 #include <palacios/vmm_emulator.h>
25
26
27
28
29
30
31 static inline
32 struct v3_shadow_region * insert_shadow_region(struct guest_info * info, 
33                                                struct v3_shadow_region * region);
34
35
36
37 void v3_init_shadow_map(struct guest_info * info) {
38   v3_shdw_map_t * map = &(info->mem_map);
39
40   map->shdw_regions.rb_node = NULL;
41   map->hook_hva = (addr_t)V3_VAddr(V3_AllocPages(1));
42
43 }
44
45 void v3_delete_shadow_map(struct guest_info * info) {
46   struct rb_node * node = v3_rb_first(&(info->mem_map.shdw_regions));
47   struct v3_shadow_region * reg;
48   struct rb_node * tmp_node = NULL;
49   
50    while (node) {
51     reg = rb_entry(node, struct v3_shadow_region, tree_node);
52     tmp_node = node;
53     node = v3_rb_next(node);
54
55     v3_delete_shadow_region(info, reg);
56   }
57 }
58
59
60
61
62 int v3_add_shadow_mem( struct guest_info *  info,
63                        addr_t               guest_addr_start,
64                        addr_t               guest_addr_end,
65                        addr_t               host_addr)
66 {
67   struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region));
68
69   entry->guest_start = guest_addr_start;
70   entry->guest_end = guest_addr_end;
71   entry->host_type = SHDW_REGION_ALLOCATED;
72   entry->host_addr = host_addr;
73   entry->write_hook = NULL;
74   entry->read_hook = NULL;
75   entry->priv_data = NULL;
76
77   if (insert_shadow_region(info, entry)) {
78     V3_Free(entry);
79     return -1;
80   }
81
82   return 0;
83 }
84
85
86
87 int v3_hook_write_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end, 
88                       addr_t host_addr,
89                       int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
90                       void * priv_data) {
91
92   struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region));
93
94
95   entry->guest_start = guest_addr_start;
96   entry->guest_end = guest_addr_end;
97   entry->host_type = SHDW_REGION_WRITE_HOOK;
98   entry->host_addr = host_addr;
99   entry->write_hook = write;
100   entry->read_hook = NULL;
101   entry->priv_data = priv_data;
102
103   if (insert_shadow_region(info, entry)) {
104     V3_Free(entry);
105     return -1;
106   }
107
108   return 0;  
109 }
110
111 int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
112                      int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
113                      int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
114                      void * priv_data) {
115   
116   struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region));
117
118   entry->guest_start = guest_addr_start;
119   entry->guest_end = guest_addr_end;
120   entry->host_type = SHDW_REGION_FULL_HOOK;
121   entry->host_addr = (addr_t)NULL;
122   entry->write_hook = write;
123   entry->read_hook = read;
124   entry->priv_data = priv_data;
125   
126   if (insert_shadow_region(info, entry)) {
127     V3_Free(entry);
128     return -1;
129   }
130
131   return 0;
132 }
133
134
135
136
137 static inline 
138 struct v3_shadow_region * __insert_shadow_region(struct guest_info * info, 
139                                                  struct v3_shadow_region * region) {
140   struct rb_node ** p = &(info->mem_map.shdw_regions.rb_node);
141   struct rb_node * parent = NULL;
142   struct v3_shadow_region * tmp_region;
143
144   while (*p) {
145     parent = *p;
146     tmp_region = rb_entry(parent, struct v3_shadow_region, tree_node);
147
148     if (region->guest_end <= tmp_region->guest_start) {
149       p = &(*p)->rb_left;
150     } else if (region->guest_start >= tmp_region->guest_end) {
151       p = &(*p)->rb_right;
152     } else {
153       return tmp_region;
154     }
155   }
156
157   rb_link_node(&(region->tree_node), parent, p);
158   
159   return NULL;
160 }
161
162
163 static inline
164 struct v3_shadow_region * insert_shadow_region(struct guest_info * info, 
165                                                struct v3_shadow_region * region) {
166   struct v3_shadow_region * ret;
167
168   if ((ret = __insert_shadow_region(info, region))) {
169     return ret;
170   }
171   
172   v3_rb_insert_color(&(region->tree_node), &(info->mem_map.shdw_regions));
173
174   return NULL;
175 }
176                                                  
177
178
179
180
181
182
183
184 int handle_special_page_fault(struct guest_info * info, 
185                               addr_t fault_gva, addr_t fault_gpa, 
186                               pf_error_t access_info) 
187 {
188  struct v3_shadow_region * reg = v3_get_shadow_region(info, fault_gpa);
189
190   PrintDebug("Handling Special Page Fault\n");
191
192   switch (reg->host_type) {
193   case SHDW_REGION_WRITE_HOOK:
194     return v3_handle_mem_wr_hook(info, fault_gva, fault_gpa, reg, access_info);
195   case SHDW_REGION_FULL_HOOK:
196     return v3_handle_mem_full_hook(info, fault_gva, fault_gpa, reg, access_info);
197   default:
198     return -1;
199   }
200
201   return 0;
202
203 }
204
205 int v3_handle_mem_wr_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
206                           struct v3_shadow_region * reg, pf_error_t access_info) {
207   addr_t dst_addr = 0;
208   
209   dst_addr = v3_get_shadow_addr(reg, guest_pa);
210
211   if (v3_emulate_write_op(info, guest_va, guest_pa, dst_addr, reg->write_hook, reg->priv_data) == -1) {
212     PrintError("Write hook emulation failed\n");
213     return -1;
214   }
215
216   return 0;
217 }
218
219 int v3_handle_mem_full_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
220                             struct v3_shadow_region * reg, pf_error_t access_info) {
221   
222   addr_t op_addr = info->mem_map.hook_hva;
223
224   if (access_info.write == 1) {
225     if (v3_emulate_write_op(info, guest_va, guest_pa, op_addr, reg->write_hook, reg->priv_data) == -1) {
226       PrintError("Read Full Hook emulation faild\n");
227       return -1;
228     }
229   } else {
230     if (v3_emulate_read_op(info, guest_va, guest_pa, op_addr, reg->read_hook, reg->priv_data) == -1) {
231       PrintError("Write Full Hook emulation faild\n");
232       return -1;
233     }
234   }
235
236   return 0;
237 }
238
239
240
241 struct v3_shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t guest_addr) {
242   struct rb_node * n = info->mem_map.shdw_regions.rb_node;
243   struct v3_shadow_region * reg = NULL;
244
245   while (n) {
246     reg = rb_entry(n, struct v3_shadow_region, tree_node);
247
248     if (guest_addr < reg->guest_start) {
249       n = n->rb_left;
250     } else if (guest_addr >= reg->guest_end) {
251       n = n->rb_right;
252     } else {
253       return reg;
254     }
255   }
256
257   return NULL;
258 }
259
260
261
262 addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) {
263   if ((reg) && 
264       (reg->host_type != SHDW_REGION_FULL_HOOK) &&
265       (reg->host_type != SHDW_REGION_INVALID)) {
266     return (guest_addr - reg->guest_start) + reg->host_addr;
267   } else {
268     PrintError("MEM Region Invalid\n");
269     return 0;
270   }
271 }
272
273
274
275 void v3_delete_shadow_region(struct guest_info * info, struct v3_shadow_region * reg) {
276   if (reg != NULL) {
277     v3_rb_erase(&(reg->tree_node), &(info->mem_map.shdw_regions));
278
279     V3_Free(reg);
280   }
281 }
282
283
284
285
286 void print_shadow_map(struct guest_info * info) {
287   struct rb_node * node = v3_rb_first(&(info->mem_map.shdw_regions));
288   struct v3_shadow_region * reg;
289   int i = 0;
290
291   PrintDebug("Memory Layout:\n");
292
293   do {
294     reg = rb_entry(node, struct v3_shadow_region, tree_node);
295
296     PrintDebug("%d:  0x%p - 0x%p -> 0x%p\n", i, 
297                (void *)(reg->guest_start), 
298                (void *)(reg->guest_end - 1), 
299                (void *)(reg->host_addr));
300
301     PrintDebug("\t(%s) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", 
302                v3_shdw_region_type_to_str(reg->host_type),
303                (void *)(reg->write_hook), 
304                (void *)(reg->read_hook));
305     
306     i++;
307   } while ((node = v3_rb_next(node)));
308 }
309
310
311 static const uchar_t  SHDW_REGION_INVALID_STR[] = "SHDW_REGION_INVALID";
312 static const uchar_t  SHDW_REGION_WRITE_HOOK_STR[] = "SHDW_REGION_WRITE_HOOK";
313 static const uchar_t  SHDW_REGION_FULL_HOOK_STR[] = "SHDW_REGION_FULL_HOOK";
314 static const uchar_t  SHDW_REGION_ALLOCATED_STR[] = "SHDW_REGION_ALLOCATED";
315
316
317
318 const uchar_t * v3_shdw_region_type_to_str(v3_shdw_region_type_t type) {
319   switch (type) {
320   case SHDW_REGION_WRITE_HOOK:
321     return SHDW_REGION_WRITE_HOOK_STR;
322   case SHDW_REGION_FULL_HOOK:
323     return SHDW_REGION_FULL_HOOK_STR;
324   case SHDW_REGION_ALLOCATED:
325     return SHDW_REGION_ALLOCATED_STR;
326   default:
327     return SHDW_REGION_INVALID_STR;
328   }
329 }
330