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.


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