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.


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