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 new control register handlers
[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_decoder.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 guest_info * info) {
110   struct shadow_map * map = &(info->mem_map);
111
112   map->num_regions = 0;
113
114   map->head = NULL;
115 }
116
117
118 void free_shadow_map(struct shadow_map * map) {
119   struct shadow_region * cursor = map->head;
120   struct shadow_region * tmp = NULL;
121
122   while(cursor) {
123     tmp = cursor;
124     cursor = cursor->next;
125     V3_Free(tmp);
126   }
127
128   V3_Free(map);
129 }
130
131
132
133
134 int add_shadow_region(struct shadow_map * map,
135                       struct shadow_region * region) 
136 {
137   struct shadow_region * cursor = map->head;
138
139   PrintDebug("Adding Shadow Region: (0x%x-0x%x)\n", region->guest_start, region->guest_end);
140
141   if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
142     region->prev = NULL;
143     region->next = cursor;
144     map->num_regions++;
145     map->head = region;
146     return 0;
147   }
148
149   while (cursor) {
150     // Check if it overlaps with the current cursor
151     if ((cursor->guest_end > region->guest_start) && (cursor->guest_start < region->guest_start)) {
152       // overlaps not allowed
153       return -1;
154     }
155     
156     if (!(cursor->next)) {
157       // add to the end of the list
158       cursor->next = region;
159       region->prev = cursor;
160       region->next = NULL;
161       map->num_regions++;
162       return 0;
163     } else if (cursor->next->guest_start >= region->guest_end) {
164       // add here
165       region->next = cursor->next;
166       region->prev = cursor;
167       
168       cursor->next->prev = region;
169       cursor->next = region;
170
171       map->num_regions++;
172       
173       return 0;
174     } else if (cursor->next->guest_end <= region->guest_start) {
175       cursor = cursor->next;
176     } else {
177       // This cannot happen!
178       // we should panic here
179       return -1;
180     }
181   }
182   
183   // This cannot happen
184   // We should panic here
185   return -1;
186 }
187
188
189 int delete_shadow_region(struct shadow_map * map,
190                          addr_t guest_start,
191                          addr_t guest_end) {
192   return -1;
193 }
194
195
196
197 struct shadow_region *get_shadow_region_by_index(struct shadow_map *  map,
198                                                uint_t index) {
199   struct shadow_region * reg = map->head;
200   uint_t i = 0;
201
202   while (reg) { 
203     if (i == index) { 
204       return reg;
205     }
206     reg = reg->next;
207     i++;
208   }
209   return NULL;
210 }
211
212
213 struct shadow_region * get_shadow_region_by_addr(struct shadow_map * map,
214                                                addr_t addr) {
215   struct shadow_region * reg = map->head;
216
217   while (reg) {
218     if ((reg->guest_start <= addr) && (reg->guest_end > addr)) {
219       return reg;
220     } else if (reg->guest_start > addr) {
221       return NULL;
222     } else {
223       reg = reg->next;
224     }
225   }
226   return NULL;
227 }
228
229
230 host_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr) {
231   struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
232
233   if (!reg) {
234     return HOST_REGION_INVALID;
235   } else {
236     return reg->host_type;
237   }
238 }
239
240 addr_t get_shadow_addr(struct guest_info * info, addr_t guest_addr) {
241   struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
242
243   if (!reg) {
244     return 0;
245   } else {
246     return (guest_addr - reg->guest_start) + reg->host_addr;
247   }
248 }
249
250
251 host_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr) {
252   struct shadow_region * reg = get_shadow_region_by_addr(map, guest_addr);
253
254   if (!reg) {
255     // No mapping exists
256     return HOST_REGION_INVALID;
257   } else {
258     switch (reg->host_type) {
259     case HOST_REGION_PHYSICAL_MEMORY:
260      *host_addr = (guest_addr - reg->guest_start) + reg->host_addr;
261      return reg->host_type;
262     case HOST_REGION_MEMORY_MAPPED_DEVICE:
263     case HOST_REGION_UNALLOCATED:
264       // ... 
265     default:
266       *host_addr = 0;
267       return reg->host_type;
268     }
269   }
270 }
271
272
273 void print_shadow_map(struct shadow_map * map) {
274   struct shadow_region * cur = map->head;
275   int i = 0;
276
277   PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
278
279   while (cur) {
280     PrintDebug("%d:  0x%x - 0x%x (%s) -> ", i, cur->guest_start, cur->guest_end - 1,
281                cur->guest_type == GUEST_REGION_PHYSICAL_MEMORY ? "GUEST_REGION_PHYSICAL_MEMORY" :
282                cur->guest_type == GUEST_REGION_NOTHING ? "GUEST_REGION_NOTHING" :
283                cur->guest_type == GUEST_REGION_MEMORY_MAPPED_DEVICE ? "GUEST_REGION_MEMORY_MAPPED_DEVICE" :
284                "UNKNOWN");
285     if (cur->host_type == HOST_REGION_PHYSICAL_MEMORY || 
286         cur->host_type == HOST_REGION_UNALLOCATED ||
287         cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) { 
288       PrintDebug("0x%x", cur->host_addr);
289     }
290     PrintDebug("(%s)\n",
291                cur->host_type == HOST_REGION_PHYSICAL_MEMORY ? "HOST_REGION_PHYSICAL_MEMORY" :
292                cur->host_type == HOST_REGION_UNALLOCATED ? "HOST_REGION_UNALLOACTED" :
293                cur->host_type == HOST_REGION_HOOK ? "HOST_REGION_HOOK" :
294                cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE ? "HOST_REGION_MEMORY_MAPPED_DEVICE" :
295                cur->host_type == HOST_REGION_REMOTE ? "HOST_REGION_REMOTE" : 
296                cur->host_type == HOST_REGION_SWAPPED ? "HOST_REGION_SWAPPED" :
297                "UNKNOWN");
298     cur = cur->next;
299     i++;
300   }
301 }
302
303
304
305
306
307
308
309
310
311
312 #ifdef VMM_MEM_TEST
313
314
315 #include <stdlib.h>
316 #include <stdio.h>
317 #include <stdarg.h>
318
319
320
321
322
323 struct vmm_os_hooks * os_hooks;
324
325 void * TestMalloc(uint_t size) {
326   return malloc(size);
327 }
328
329 void * TestAllocatePages(int size) {
330   return malloc(4096 * size);
331 }
332
333
334 void TestPrint(const char * fmt, ...) {
335   va_list args;
336
337   va_start(args, fmt);
338   vprintf(fmt, args);
339   va_end(args);
340 }
341
342 int mem_list_add_test_1(  vmm_mem_list_t * list) {
343
344   uint_t offset = 0;
345
346   PrintDebug("\n\nTesting Memory List\n");
347
348   init_mem_list(list);
349
350   offset = PAGE_SIZE * 6;
351   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
352   add_mem_list_pages(list, offset, 10);
353   print_mem_list(list);
354
355
356   offset = 0;
357   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
358   add_mem_list_pages(list, offset, 4);
359   print_mem_list(list);
360
361   offset = PAGE_SIZE * 20;
362   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
363   add_mem_list_pages(list, offset, 1);
364   print_mem_list(list);
365
366   offset = PAGE_SIZE * 21;
367   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 3));
368   add_mem_list_pages(list, offset, 3);
369   print_mem_list(list);
370
371
372   offset = PAGE_SIZE * 10;
373   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
374   add_mem_list_pages(list, offset, 30);
375   print_mem_list(list);
376
377
378   offset = PAGE_SIZE * 5;
379   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
380   add_mem_list_pages(list, offset, 1);
381   print_mem_list(list);
382
383  
384
385   return 0;
386 }
387
388
389 int mem_layout_add_test_1(vmm_mem_layout_t * layout) {
390
391   
392   uint_t start = 0;
393   uint_t end = 0;
394
395   PrintDebug("\n\nTesting Memory Layout\n");
396
397   init_mem_layout(layout);
398
399   start = 0x6000;
400   end = 0x10000;;
401   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
402   add_guest_mem_range(layout, start, end);
403   print_mem_layout(layout);
404
405
406   start = 0x1000;
407   end = 0x3000;
408   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
409   add_guest_mem_range(layout, start, end);
410   print_mem_layout(layout);
411
412   start = 0x2000;
413   end = 0x6000;
414   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
415   add_guest_mem_range(layout, start, end);
416   print_mem_layout(layout);
417
418   start = 0x4000;
419   end = 0x5000;
420   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
421   add_guest_mem_range(layout, start, end);
422   print_mem_layout(layout);
423
424
425   start = 0x5000;
426   end = 0x7000;
427   PrintDebug("Adding 0x%x - 0x%x\n", start, end);
428   add_guest_mem_range(layout, start, end);
429   print_mem_layout(layout);
430
431
432
433
434   return 0;
435 }
436
437
438
439 int main(int argc, char ** argv) {
440   struct vmm_os_hooks dummy_hooks;
441   os_hooks = &dummy_hooks;
442
443   vmm_mem_layout_t layout;
444   vmm_mem_list_t list;
445
446   os_hooks->malloc = &TestMalloc;
447   os_hooks->free = &free;
448   os_hooks->print_debug = &TestPrint;
449   os_hooks->allocate_pages = &TestAllocatePages;
450
451
452
453   printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list));
454   printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout));
455
456   return 0;
457 }
458 #endif
459
460
461
462
463
464