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.


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