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.


free up telemetry state and free backend state for the virtio devices
[palacios.git] / palacios / src / palacios / vmm_shadow_paging.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
21 #include <palacios/vmm_shadow_paging.h>
22
23
24 #include <palacios/vmm.h>
25 #include <palacios/vm_guest_mem.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vmm_ctrl_regs.h>
28
29 #include <palacios/vmm_hashtable.h>
30
31 #include <palacios/vmm_direct_paging.h>
32
33
34
35
36 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
37 #include <palacios/vmm_telemetry.h>
38 #endif
39
40 #ifdef CONFIG_SYMBIOTIC_SWAP
41 #include <palacios/vmm_sym_swap.h>
42 #endif
43
44 #ifndef CONFIG_DEBUG_SHADOW_PAGING
45 #undef PrintDebug
46 #define PrintDebug(fmt, args...)
47 #endif
48
49
50 static const char default_strategy[] = "VTLB";
51
52
53 static struct hashtable * master_shdw_pg_table = NULL;
54
55 static uint_t shdw_pg_hash_fn(addr_t key) {
56     char * name = (char *)key;
57     return v3_hash_buffer((uint8_t *)name, strlen(name));
58 }
59
60 static int shdw_pg_eq_fn(addr_t key1, addr_t key2) {
61     char * name1 = (char *)key1;
62     char * name2 = (char *)key2;
63
64     return (strcmp(name1, name2) == 0);
65 }
66
67
68 int V3_init_shdw_paging() {
69     extern struct v3_shdw_pg_impl * __start__v3_shdw_pg_impls[];
70     extern struct v3_shdw_pg_impl * __stop__v3_shdw_pg_impls[];
71     struct v3_shdw_pg_impl ** tmp_impl = __start__v3_shdw_pg_impls;
72     int i = 0;
73
74     master_shdw_pg_table = v3_create_htable(0, shdw_pg_hash_fn, shdw_pg_eq_fn);
75
76
77     while (tmp_impl != __stop__v3_shdw_pg_impls) {
78         V3_Print("Registering Shadow Paging Impl (%s)\n", (*tmp_impl)->name);
79
80         if (v3_htable_search(master_shdw_pg_table, (addr_t)((*tmp_impl)->name))) {
81             PrintError("Multiple instances of shadow paging impl (%s)\n", (*tmp_impl)->name);
82             return -1;
83         }
84
85         if (v3_htable_insert(master_shdw_pg_table, 
86                              (addr_t)((*tmp_impl)->name),
87                              (addr_t)(*tmp_impl)) == 0) {
88             PrintError("Could not register shadow paging impl (%s)\n", (*tmp_impl)->name);
89             return -1;
90         }
91
92         tmp_impl = &(__start__v3_shdw_pg_impls[++i]);
93     }
94
95     return 0;
96 }
97
98
99
100 /*** 
101  ***  There be dragons
102  ***/
103
104
105 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
106 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
107     int i = 0;
108     for (i = 0; i < vm->num_cores; i++) {
109         struct guest_info * core = &(vm->cores[i]);
110
111         V3_Print("%s Guest Page faults: %d\n", hdr, core->shdw_pg_state.guest_faults);
112     }
113 }
114 #endif
115
116
117
118 int v3_init_shdw_pg_state(struct guest_info * core) {
119     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
120     struct v3_shdw_pg_impl * impl = core->vm_info->shdw_impl.current_impl;
121   
122
123     state->guest_cr3 = 0;
124     state->guest_cr0 = 0;
125     state->guest_efer.value = 0x0LL;
126
127
128     if (impl->local_init(core) == -1) {
129         PrintError("Error in Shadow paging local initialization (%s)\n", impl->name);
130         return -1;
131     }
132
133
134 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
135     v3_add_telemetry_cb(core->vm_info, telemetry_cb, NULL);
136 #endif
137   
138     return 0;
139 }
140
141
142 int v3_deinit_shdw_pg_state(struct guest_info * core) {
143     struct v3_shdw_pg_impl * impl = core->vm_info->shdw_impl.current_impl;
144
145     if (impl->local_deinit(core) == -1) {
146         PrintError("Error deinitializing shadow paging state\n");
147         return -1;
148     }
149
150 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
151     v3_remove_telemetry_cb(core->vm_info, telemetry_cb, NULL);
152 #endif
153
154     return 0;
155 }
156
157
158
159 int v3_init_shdw_impl(struct v3_vm_info * vm) {
160     struct v3_shdw_impl_state * impl_state = &(vm->shdw_impl);
161     v3_cfg_tree_t * pg_cfg = v3_cfg_subtree(vm->cfg_data->cfg, "paging");
162     char * pg_mode = v3_cfg_val(pg_cfg, "mode");
163     char * pg_strat = v3_cfg_val(pg_cfg, "strategy");
164     struct v3_shdw_pg_impl * impl = NULL;
165    
166     PrintDebug("Checking if shadow paging requested.\n");
167     if ((pg_mode != NULL) && (strcasecmp(pg_mode, "nested") == 0)) {
168         PrintDebug("Nested paging specified - not initializing shadow paging.\n");
169         return 0;
170     }
171
172     if (pg_strat == NULL) {
173         pg_strat = (char *)default_strategy;
174     }
175         
176     V3_Print("Initialization of Shadow Paging implementation\n");
177
178     impl = (struct v3_shdw_pg_impl *)v3_htable_search(master_shdw_pg_table, (addr_t)pg_strat);
179
180     if (impl == NULL) {
181         PrintError("Could not find shadow paging impl (%s)\n", pg_strat);
182         return -1;
183     }
184    
185     impl_state->current_impl = impl;
186
187     if (impl->init(vm, pg_cfg) == -1) {
188         PrintError("Could not initialize Shadow paging implemenation (%s)\n", impl->name);
189         return -1;
190     }
191
192     return 0;
193 }
194
195 int v3_deinit_shdw_impl(struct v3_vm_info * vm) {
196     struct v3_shdw_pg_impl * impl = vm->shdw_impl.current_impl;
197
198     if (impl->deinit(vm) == -1) {
199         PrintError("Error deinitializing shadow paging implementation\n");
200         return -1;
201     }
202
203     return 0;
204 }
205
206
207 // Reads the guest CR3 register
208 // creates new shadow page tables
209 // updates the shadow CR3 register to point to the new pts
210 int v3_activate_shadow_pt(struct guest_info * core) {
211     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
212     struct v3_shdw_pg_impl * impl = state->current_impl;
213     return impl->activate_shdw_pt(core);
214 }
215
216
217
218 // This must flush any caches
219 // and reset the cr3 value to the correct value
220 int v3_invalidate_shadow_pts(struct guest_info * core) {
221     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
222     struct v3_shdw_pg_impl * impl = state->current_impl;
223     return impl->invalidate_shdw_pt(core);
224 }
225
226
227 int v3_handle_shadow_pagefault(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
228   
229     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) {
230         // If paging is not turned on we need to handle the special cases
231         return v3_handle_passthrough_pagefault(core, fault_addr, error_code);
232     } else if (v3_get_vm_mem_mode(core) == VIRTUAL_MEM) {
233         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
234         struct v3_shdw_pg_impl * impl = state->current_impl;
235
236         return impl->handle_pagefault(core, fault_addr, error_code);
237     } else {
238         PrintError("Invalid Memory mode\n");
239         return -1;
240     }
241 }
242
243
244 int v3_handle_shadow_invlpg(struct guest_info * core) {
245     uchar_t instr[15];
246     struct x86_instr dec_instr;
247     int ret = 0;
248     addr_t vaddr = 0;
249
250     if (v3_get_vm_mem_mode(core) != VIRTUAL_MEM) {
251         // Paging must be turned on...
252         // should handle with some sort of fault I think
253         PrintError("ERROR: INVLPG called in non paged mode\n");
254         return -1;
255     }
256
257     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) { 
258         ret = v3_read_gpa_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
259     } else { 
260         ret = v3_read_gva_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
261     }
262
263     if (ret == -1) {
264         PrintError("Could not read instruction into buffer\n");
265         return -1;
266     }
267
268     if (v3_decode(core, (addr_t)instr, &dec_instr) == -1) {
269         PrintError("Decoding Error\n");
270         return -1;
271     }
272   
273     if ((dec_instr.op_type != V3_OP_INVLPG) || 
274         (dec_instr.num_operands != 1) ||
275         (dec_instr.dst_operand.type != MEM_OPERAND)) {
276         PrintError("Decoder Error: Not a valid INVLPG instruction...\n");
277         return -1;
278     }
279
280     vaddr = dec_instr.dst_operand.operand;
281
282     core->rip += dec_instr.instr_length;
283
284     {
285         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
286         struct v3_shdw_pg_impl * impl = state->current_impl;
287
288         return impl->handle_invlpg(core, vaddr);
289     }
290 }
291
292
293
294
295
296
297 int v3_inject_guest_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
298     core->ctrl_regs.cr2 = fault_addr;
299
300 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
301     core->shdw_pg_state.guest_faults++;
302 #endif
303
304     return v3_raise_exception_with_error(core, PF_EXCEPTION, *(uint_t *)&error_code);
305 }
306
307
308 int v3_is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
309     /* basically the reasoning is that there can be multiple reasons for a page fault:
310        If there is a permissions failure for a page present in the guest _BUT_
311        the reason for the fault was that the page is not present in the shadow,
312        _THEN_ we have to map the shadow page in and reexecute, this will generate
313        a permissions fault which is _THEN_ valid to send to the guest
314        _UNLESS_ both the guest and shadow have marked the page as not present
315
316        whew...
317     */
318     if (guest_access != PT_ACCESS_OK) {
319         // Guest Access Error
320
321         if ((shadow_access != PT_ACCESS_NOT_PRESENT) &&
322             (guest_access != PT_ACCESS_NOT_PRESENT)) {
323             // aka (guest permission error)
324             return 1;
325         }
326
327         /*
328           if ((shadow_access == PT_ACCESS_NOT_PRESENT) &&
329           (guest_access == PT_ACCESS_NOT_PRESENT)) {
330           // Page tables completely blank, handle guest first
331           return 1;
332           }
333         */
334
335         if (guest_access == PT_ACCESS_NOT_PRESENT) {
336             // Page tables completely blank, handle guest first
337             return 1;
338         }
339         
340         // Otherwise we'll handle the guest fault later...?
341     }
342
343     return 0;
344 }
345
346