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.


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