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.


Semi-functional SMP (boots Kitten guest with two cores)
[palacios.git] / palacios / src / palacios / vmm_mem_hook.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.h>
21 #include <palacios/vm_guest.h>
22 #include <palacios/vmm_mem_hook.h>
23 #include <palacios/vmm_emulator.h>
24 #include <palacios/vm_guest_mem.h>
25
26 struct mem_hook {
27   
28     // Called when data is read from a memory page
29     int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
30     // Called when data is written to a memory page
31     int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
32
33     void * priv_data;
34     addr_t hook_hva;
35     
36
37 };
38
39
40
41 int v3_init_mem_hooks(struct v3_vm_info * vm) {
42     struct v3_mem_hooks * hooks = &(vm->mem_hooks);
43
44     hooks->hook_hvas = V3_VAddr(V3_AllocPages(vm->num_cores));
45
46     INIT_LIST_HEAD(&(hooks->hook_list));
47
48     return 0;
49 }
50
51
52
53
54 static int handle_mem_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
55                            struct v3_mem_region * reg, pf_error_t access_info) {
56     struct mem_hook * hook = reg->priv_data;
57     addr_t op_addr = 0;
58
59     if (reg->flags.alloced == 0) {
60         op_addr = hook->hook_hva;
61     } else {
62         if (v3_gpa_to_hva(info, guest_pa, &op_addr) == -1) {
63             PrintError("Could not translate hook address (%p)\n", (void *)guest_pa);
64             return -1;
65         }
66     }
67
68     
69     if (access_info.write == 1) { 
70         // Write Operation 
71         if (v3_emulate_write_op(info, guest_va, guest_pa, op_addr, 
72                                 hook->write, hook->priv_data) == -1) {
73             PrintError("Write Full Hook emulation failed\n");
74             return -1;
75         }
76     } else {
77         // Read Operation
78         
79         if (reg->flags.read == 1) {
80             PrintError("Tried to emulate read for a guest Readable page\n");
81             return -1;
82         }
83
84         if (v3_emulate_read_op(info, guest_va, guest_pa, op_addr, 
85                                hook->read, hook->write, 
86                                hook->priv_data) == -1) {
87             PrintError("Read Full Hook emulation failed\n");
88             return -1;
89         }
90
91     }
92
93
94     return 0;
95 }
96
97
98
99
100 int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id,
101                       addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr,
102                       int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data),
103                       void * priv_data) {
104     struct v3_mem_region * entry = NULL;
105     struct mem_hook * hook = V3_Malloc(sizeof(struct mem_hook));
106     //    struct v3_mem_hooks * hooks = &(vm->mem_hooks);
107
108     memset(hook, 0, sizeof(struct mem_hook));
109
110     hook->write = write;
111     hook->read = NULL;
112     hook->priv_data = priv_data;
113     hook->hook_hva = (addr_t)V3_VAddr((void *)host_addr);
114
115     entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end);
116     
117     entry->host_addr = host_addr;
118     entry->unhandled = handle_mem_hook;
119     entry->priv_data = hook;
120
121     entry->flags.read = 1;
122     entry->flags.exec = 1;
123     entry->flags.alloced = 1;
124
125     if (v3_insert_mem_region(vm, entry) == -1) {
126         V3_Free(entry);
127         V3_Free(hook);
128         return -1;
129     }
130
131     return 0;  
132 }
133
134
135
136 int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, 
137                      addr_t guest_addr_start, addr_t guest_addr_end,
138                      int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data),
139                      int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data),
140                      void * priv_data) {
141   
142     struct v3_mem_region * entry = NULL;
143     struct mem_hook * hook = V3_Malloc(sizeof(struct mem_hook));
144     struct v3_mem_hooks * hooks = &(vm->mem_hooks);
145
146     memset(hook, 0, sizeof(struct mem_hook));
147
148     hook->write = write;
149     hook->read = read;
150     hook->priv_data = priv_data;
151     hook->hook_hva = (addr_t)hooks->hook_hvas + (PAGE_SIZE_4KB * core_id);
152
153     entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end);
154
155     entry->unhandled = handle_mem_hook;
156     entry->priv_data = hook;
157
158     if (v3_insert_mem_region(vm, entry)) {
159         V3_Free(entry);
160         V3_Free(hook);
161         return -1;
162     }
163
164     return 0;
165 }
166
167
168
169 // This will unhook the memory hook registered at start address
170 // We do not support unhooking subregions
171 int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start) {
172     struct v3_mem_region * reg = v3_get_mem_region(vm, core_id, guest_addr_start);
173     struct mem_hook * hook = reg->priv_data;
174
175     V3_Free(hook);
176   
177     v3_delete_mem_region(vm, reg);
178
179     return 0;
180 }
181
182