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.


Lots of pedantic error checking in Palacios proper, especially for memory
[palacios.git] / palacios / src / palacios / mmu / vmm_shdw_pg_tlb.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_shadow_paging.h>
21 #include <palacios/vmm_ctrl_regs.h>
22
23 #include <palacios/vm_guest.h>
24 #include <palacios/vm_guest_mem.h>
25
26
27 #ifndef V3_CONFIG_DEBUG_SHDW_PG_VTLB
28 #undef PrintDebug
29 #define PrintDebug(fmt, ...)
30 #endif
31
32
33 struct shadow_page_data {
34     v3_reg_t cr3;
35     addr_t page_pa;
36   
37     struct list_head page_list_node;
38 };
39
40
41 struct vtlb_local_state {
42  
43     struct list_head page_list;
44
45 };
46
47
48 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
49
50
51 #include "vmm_shdw_pg_tlb_32.h"
52 #include "vmm_shdw_pg_tlb_32pae.h"
53 #include "vmm_shdw_pg_tlb_64.h"
54
55
56 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
57     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
58     struct vtlb_local_state * impl_state = (struct vtlb_local_state *)(state->local_impl_data);
59     v3_reg_t cur_cr3 = core->ctrl_regs.cr3;
60     struct shadow_page_data * page_tail = NULL;
61     addr_t shdw_page = 0;
62
63     if (!list_empty(&(impl_state->page_list))) {
64         page_tail = list_tail_entry(&(impl_state->page_list), struct shadow_page_data, page_list_node);
65
66
67         if (page_tail->cr3 != cur_cr3) {
68             PrintDebug("Reusing old shadow Page: %p (cur_CR3=%p)(page_cr3=%p) \n",
69                        (void *)(addr_t)page_tail->page_pa, 
70                        (void *)(addr_t)cur_cr3, 
71                        (void *)(addr_t)(page_tail->cr3));
72
73             list_move(&(page_tail->page_list_node), &(impl_state->page_list));
74
75             memset(V3_VAddr((void *)(page_tail->page_pa)), 0, PAGE_SIZE_4KB);
76
77
78             return page_tail;
79         }
80     }
81
82     // else  
83
84     page_tail = (struct shadow_page_data *)V3_Malloc(sizeof(struct shadow_page_data));
85
86     if (!page_tail) {
87         PrintError("Cannot allocate\n");
88         return NULL;
89     }
90
91     page_tail->page_pa = (addr_t)V3_AllocPages(1);
92
93     if (!page_tail->page_pa) {
94         PrintError("Cannot allocate page\n");
95         return NULL;
96     }
97
98     PrintDebug("Allocating new shadow Page: %p (cur_cr3=%p)\n", 
99                (void *)(addr_t)page_tail->page_pa, 
100                (void *)(addr_t)cur_cr3);
101
102     page_tail->cr3 = cur_cr3;
103     list_add(&(page_tail->page_list_node), &(impl_state->page_list));
104
105     shdw_page = (addr_t)V3_VAddr((void *)(page_tail->page_pa));
106     memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
107
108     return page_tail;
109 }
110
111
112
113 static int vtlb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
114
115     V3_Print("VTLB initialization\n");
116     return 0;
117 }
118
119 static int vtlb_deinit(struct v3_vm_info * vm) {
120     return 0;
121 }
122
123 static int vtlb_local_init(struct guest_info * core) {
124     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
125     struct vtlb_local_state * vtlb_state = NULL;
126
127     V3_Print("VTLB local initialization\n");
128
129     vtlb_state = (struct vtlb_local_state *)V3_Malloc(sizeof(struct vtlb_local_state));
130
131     if (!vtlb_state) {
132         PrintError("Cannot allocate\n");
133         return -1;
134     }
135
136     INIT_LIST_HEAD(&(vtlb_state->page_list));
137
138     state->local_impl_data = vtlb_state;
139
140     return 0;
141 }
142
143
144 static int vtlb_local_deinit(struct guest_info * core) {
145     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
146     struct vtlb_local_state * vtlb_state = state->local_impl_data;
147
148     struct shadow_page_data * shdw_pg = NULL;
149     struct shadow_page_data * tmp = NULL;
150
151     // free page list...
152     list_for_each_entry_safe(shdw_pg, tmp, &(vtlb_state->page_list), page_list_node) {
153         list_del(&(shdw_pg->page_list_node));
154         V3_FreePages((void *)shdw_pg->page_pa, 1);
155         V3_Free(shdw_pg);
156     }
157
158
159     V3_Free(vtlb_state);
160
161     return 0;
162 }
163
164
165 static int vtlb_activate_shdw_pt(struct guest_info * core) {
166     switch (v3_get_vm_cpu_mode(core)) {
167
168         case PROTECTED:
169             return activate_shadow_pt_32(core);
170         case PROTECTED_PAE:
171             return activate_shadow_pt_32pae(core);
172         case LONG:
173         case LONG_32_COMPAT:
174         case LONG_16_COMPAT:
175             return activate_shadow_pt_64(core);
176         default:
177             PrintError("Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
178             return -1;
179     }
180
181     return 0;
182 }
183
184 static int vtlb_invalidate_shdw_pt(struct guest_info * core) {
185     return vtlb_activate_shdw_pt(core);
186 }
187
188
189 static int vtlb_handle_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
190
191         switch (v3_get_vm_cpu_mode(core)) {
192             case PROTECTED:
193                 return handle_shadow_pagefault_32(core, fault_addr, error_code);
194                 break;
195             case PROTECTED_PAE:
196                 return handle_shadow_pagefault_32pae(core, fault_addr, error_code);
197             case LONG:
198             case LONG_32_COMPAT:
199             case LONG_16_COMPAT:
200                 return handle_shadow_pagefault_64(core, fault_addr, error_code);
201                 break;
202             default:
203                 PrintError("Unhandled CPU Mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
204                 return -1;
205         }
206 }
207
208
209 static int vtlb_handle_invlpg(struct guest_info * core, addr_t vaddr) {
210
211     switch (v3_get_vm_cpu_mode(core)) {
212         case PROTECTED:
213             return handle_shadow_invlpg_32(core, vaddr);
214         case PROTECTED_PAE:
215             return handle_shadow_invlpg_32pae(core, vaddr);
216         case LONG:
217         case LONG_32_COMPAT:
218         case LONG_16_COMPAT:
219             return handle_shadow_invlpg_64(core, vaddr);
220         default:
221             PrintError("Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
222             return -1;
223     }
224 }
225
226 static struct v3_shdw_pg_impl vtlb_impl =  {
227     .name = "VTLB",
228     .init = vtlb_init,
229     .deinit = vtlb_deinit,
230     .local_init = vtlb_local_init,
231     .local_deinit = vtlb_local_deinit,
232     .handle_pagefault = vtlb_handle_pf,
233     .handle_invlpg = vtlb_handle_invlpg,
234     .activate_shdw_pt = vtlb_activate_shdw_pt,
235     .invalidate_shdw_pt = vtlb_invalidate_shdw_pt
236 };
237
238
239
240
241
242 register_shdw_pg_impl(&vtlb_impl);