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.


added initial memory hook support, still need decoder
[palacios.git] / palacios / src / palacios / vmm_mem.c
1 #include <palacios/vmm_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmm_util.h>
4 #include <palacios/vmm_emulate.h>
5
6
7
8 void init_shadow_region(struct shadow_region * entry,
9                         addr_t               guest_addr_start,
10                         addr_t               guest_addr_end,
11                         guest_region_type_t  guest_region_type,
12                         host_region_type_t   host_region_type)
13 {
14   entry->guest_type = guest_region_type;
15   entry->guest_start = guest_addr_start;
16   entry->guest_end = guest_addr_end;
17   entry->host_type = host_region_type;
18   entry->host_addr = 0;
19   entry->next=entry->prev = NULL;
20 }
21
22 int add_shadow_region_passthrough( struct guest_info *  guest_info,
23                                    addr_t               guest_addr_start,
24                                    addr_t               guest_addr_end,
25                                    addr_t               host_addr)
26 {
27   struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
28
29   init_shadow_region(entry, guest_addr_start, guest_addr_end, 
30                      GUEST_REGION_PHYSICAL_MEMORY, HOST_REGION_PHYSICAL_MEMORY);
31   entry->host_addr = host_addr;
32
33   return add_shadow_region(&(guest_info->mem_map), entry);
34 }
35
36 int hook_guest_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
37                    int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
38                    int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
39                    void * priv_data) {
40   
41   struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
42   struct vmm_mem_hook * hook = (struct vmm_mem_hook *)V3_Malloc(sizeof(struct vmm_mem_hook));
43
44   memset(hook, 0, sizeof(struct vmm_mem_hook));
45
46   hook->read = read;
47   hook->write = write;
48   hook->region = entry;
49   hook->priv_data = priv_data;
50
51
52   init_shadow_region(entry, guest_addr_start, guest_addr_end, 
53                      GUEST_REGION_PHYSICAL_MEMORY, HOST_REGION_HOOK);
54
55   entry->host_addr = (addr_t)hook;
56
57   return add_shadow_region(&(info->mem_map), entry);
58 }
59
60
61 struct vmm_mem_hook * get_mem_hook(struct guest_info * info, addr_t guest_addr) {
62   struct shadow_region * region = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
63
64   if (region == NULL) {
65     PrintDebug("Could not find shadow region for addr: %x\n", guest_addr);
66     return NULL;
67   }
68
69   return (struct vmm_mem_hook *)(region->host_addr);
70 }
71
72
73 int mem_hook_dispatch(struct guest_info * info, addr_t mem_addr, pf_error_t access_info, struct vmm_mem_hook * hook) {
74
75   if (access_info.write == 1) {
76     void * src = NULL;
77     uint_t length = 0;
78     PrintDebug("Memory hook write\n");
79     return -1;
80
81     if (hook->write(mem_addr, src, length, hook->priv_data) != length) {
82       return -1;
83     }
84   } else {
85     PrintDebug("Memory hook read\n");
86     return -1;
87   }    
88
89   return -1;
90 }
91
92
93 int handle_special_page_fault(struct guest_info * info, addr_t mem_addr, pf_error_t access_info) {
94   struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), mem_addr);
95
96   switch (reg->host_type) {
97   case HOST_REGION_HOOK:
98     return mem_hook_dispatch(info, mem_addr, access_info, (struct vmm_mem_hook *)(reg->host_addr));
99   default:
100     return -1;
101   }
102
103   return 0;
104
105 }
106
107
108
109 void init_shadow_map(struct shadow_map * map) {
110   map->num_regions = 0;
111
112   map->head = NULL;
113 }
114
115
116 void free_shadow_map(struct shadow_map * map) {
117   struct shadow_region * cursor = map->head;
118   struct shadow_region * tmp = NULL;
119
120   while(cursor) {
121     tmp = cursor;
122     cursor = cursor->next;
123     V3_Free(tmp);
124   }
125
126   V3_Free(map);
127 }
128
129
130
131
132 int add_shadow_region(struct shadow_map * map,
133                       struct shadow_region * region) 
134 {
135   struct shadow_region * cursor = map->head;
136
137   PrintDebug("Adding Shadow Region: (0x%x-0x%x)\n", region->guest_start, region->guest_end);
138
139   if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
140     region->prev = NULL;
141     region->next = cursor;
142     map->num_regions++;
143     map->head = region;
144     return 0;
145   }
146
147   while (cursor) {
148     // Check if it overlaps with the current cursor
149     if ((cursor->guest_end > region->guest_start) && (cursor->guest_start < region->guest_start)) {
150       // overlaps not allowed
151       return -1;
152     }
153     
154     if (!(cursor->next)) {
155       // add to the end of the list
156       cursor->next = region;
157       region->prev = cursor;
158       region->next = NULL;
159       map->num_regions++;
160       return 0;
161     } else if (cursor->next->guest_start >= region->guest_end) {
162       // add here
163       region->next = cursor->next;
164       region->prev = cursor;
165       
166       cursor->next->prev = region;
167       cursor->next = region;
168
169       map->num_regions++;
170       
171       return 0;
172     } else if (cursor->next->guest_end <= region->guest_start) {
173       cursor = cursor->next;
174     } else {
175       PrintDebug("WTF?\n");
176       // This cannot happen!
177       // we should panic here
178       return -1;
179     }
180   }
181   
182   // This cannot happen
183   // We should panic here
184   return -1;
185 }
186
187
188 int delete_shadow_region(struct shadow_map * map,
189                          addr_t guest_start,
190                          addr_t guest_end) {
191   return -1;
192 }
193
194
195
196 struct shadow_region *get_shadow_region_by_index(struct shadow_map *  map,
197                                                uint_t index) {
198   struct shadow_region * reg = map->head;
199   uint_t i = 0;
200
201   while (reg) { 
202     if (i == index) { 
203       return reg;
204     }
205     reg = reg->next;
206     i++;
207   }
208   return NULL;
209 }
210
211
212 struct shadow_region * get_shadow_region_by_addr(struct shadow_map * map,
213                                                addr_t addr) {
214   struct shadow_region * reg = map->head;
215
216   while (reg) {
217     if ((reg->guest_start <= addr) && (reg->guest_end > addr)) {
218       return reg;
219     } else if (reg->guest_start > addr) {
220       return NULL;
221     } else {
222       reg = reg->next;
223     }
224   }
225   return NULL;
226 }
227
228
229 host_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr) {
230   struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
231
232   if (!reg) {
233     return HOST_REGION_INVALID;
234   } else {
235     return reg->host_type;
236   }
237 }
238
239 addr_t get_shadow_addr(struct guest_info * info, addr_t guest_addr) {
240   struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
241
242   if (!reg) {
243     return 0;
244   } else {
245     return (guest_addr - reg->guest_start) + reg->host_addr;
246   }
247 }
248
249
250 host_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr) {
251   struct shadow_region * reg = get_shadow_region_by_addr(map, guest_addr);
252
253   if (!reg) {
254     // No mapping exists
255     return HOST_REGION_INVALID;
256   } else {
257     switch (reg->host_type) {
258     case HOST_REGION_PHYSICAL_MEMORY:
259      *host_addr = (guest_addr - reg->guest_start) + reg->host_addr;
260      return reg->host_type;
261     case HOST_REGION_MEMORY_MAPPED_DEVICE:
262     case HOST_REGION_UNALLOCATED:
263       // ... 
264     default:
265       *host_addr = 0;
266       return reg->host_type;
267     }
268   }
269 }
270
271
272 void print_shadow_map(struct shadow_map * map) {
273   struct shadow_region * cur = map->head;
274   int i = 0;
275
276   PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
277
278   while (cur) {
279     PrintDebug("%d:  0x%x - 0x%x (%s) -> ", i, cur->guest_start, cur->guest_end - 1,
280                cur->guest_type == GUEST_REGION_PHYSICAL_MEMORY ? "GUEST_REGION_PHYSICAL_MEMORY" :
281                cur->guest_type == GUEST_REGION_NOTHING ? "GUEST_REGION_NOTHING" :
282                cur->guest_type == GUEST_REGION_MEMORY_MAPPED_DEVICE ? "GUEST_REGION_MEMORY_MAPPED_DEVICE" :
283                "UNKNOWN");
284     if (cur->host_type == HOST_REGION_PHYSICAL_MEMORY || 
285         cur->host_type == HOST_REGION_UNALLOCATED ||
286         cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) { 
287       PrintDebug("0x%x", cur->host_addr);
288     }
289     PrintDebug("(%s)\n",
290                cur->host_type == HOST_REGION_PHYSICAL_MEMORY ? "HOST_REGION_PHYSICAL_MEMORY" :
291                cur->host_type == HOST_REGION_UNALLOCATED ? "HOST_REGION_UNALLOACTED" :
292                cur->host_type == HOST_REGION_HOOK ? "HOST_REGION_HOOK" :
293                cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE ? "HOST_REGION_MEMORY_MAPPED_DEVICE" :
294                cur->host_type == HOST_REGION_REMOTE ? "HOST_REGION_REMOTE" : 
295                cur->host_type == HOST_REGION_SWAPPED ? "HOST_REGION_SWAPPED" :
296                "UNKNOWN");
297     cur = cur->next;
298     i++;
299   }
300 }
301
302
303
304
305
306
307
308
309
310
311 #ifdef VMM_MEM_TEST
312
313
314 #include <stdlib.h>
315 #include <stdio.h>
316 #include <stdarg.h>
317
318
319
320
321
322 struct vmm_os_hooks * os_hooks;
323
324 void * TestMalloc(uint_t size) {
325   return malloc(size);
326 }
327
328 void * TestAllocatePages(int size) {
329   return malloc(4096 * size);
330 }
331
332
333 void TestPrint(const char * fmt, ...) {
334   va_list args;
335
336   va_start(args, fmt);
337   vprintf(fmt, args);
338   va_end(args);
339 }
340
341 int mem_list_add_test_1(  vmm_mem_list_t * list) {
342
343   uint_t offset = 0;
344
345   PrintDebug("\n\nTesting Memory List\n");
346
347   init_mem_list(list);
348
349   offset = PAGE_SIZE * 6;
350   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
351   add_mem_list_pages(list, offset, 10);
352   print_mem_list(list);
353
354
355   offset = 0;
356   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
357   add_mem_list_pages(list, offset, 4);
358   print_mem_list(list);
359
360   offset = PAGE_SIZE * 20;
361   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
362   add_mem_list_pages(list, offset, 1);
363   print_mem_list(list);
364
365   offset = PAGE_SIZE * 21;
366   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 3));
367   add_mem_list_pages(list, offset, 3);
368   print_mem_list(list);
369
370
371   offset = PAGE_SIZE * 10;
372   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
373   add_mem_list_pages(list, offset, 30);
374   print_mem_list(list);
375
376
377   offset = PAGE_SIZE * 5;
378   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
379   add_mem_list_pages(list, offset, 1);
380   print_mem_list(list);
381
382  
383
384   return 0;
385 }
386
387
388 int mem_layout_add_test_1(vmm_mem_layout_t * layout) {
389
390   
391   uint_t start = 0;
392   uint_t end = 0;
393
394   PrintDebug("\n\nTesting Memory Layout\n");
395
396   init_mem_layout(layout);
397
398   start = 0x6000;
399   end = 0x10000;;
400   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
401   add_guest_mem_range(layout, start, end);
402   print_mem_layout(layout);
403
404
405   start = 0x1000;
406   end = 0x3000;
407   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
408   add_guest_mem_range(layout, start, end);
409   print_mem_layout(layout);
410
411   start = 0x2000;
412   end = 0x6000;
413   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
414   add_guest_mem_range(layout, start, end);
415   print_mem_layout(layout);
416
417   start = 0x4000;
418   end = 0x5000;
419   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
420   add_guest_mem_range(layout, start, end);
421   print_mem_layout(layout);
422
423
424   start = 0x5000;
425   end = 0x7000;
426   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
427   add_guest_mem_range(layout, start, end);
428   print_mem_layout(layout);
429
430
431
432
433   return 0;
434 }
435
436
437
438 int main(int argc, char ** argv) {
439   struct vmm_os_hooks dummy_hooks;
440   os_hooks = &dummy_hooks;
441
442   vmm_mem_layout_t layout;
443   vmm_mem_list_t list;
444
445   os_hooks->malloc = &TestMalloc;
446   os_hooks->free = &free;
447   os_hooks->print_debug = &TestPrint;
448   os_hooks->allocate_pages = &TestAllocatePages;
449
450
451
452   printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list));
453   printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout));
454
455   return 0;
456 }
457 #endif
458
459
460
461
462
463