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.


freeing of virtual paging state during guest deinitialization
[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 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     page_tail->page_pa = (addr_t)V3_AllocPages(1);
86
87     PrintDebug("Allocating new shadow Page: %p (cur_cr3=%p)\n", 
88                (void *)(addr_t)page_tail->page_pa, 
89                (void *)(addr_t)cur_cr3);
90
91     page_tail->cr3 = cur_cr3;
92     list_add(&(page_tail->page_list_node), &(impl_state->page_list));
93
94     shdw_page = (addr_t)V3_VAddr((void *)(page_tail->page_pa));
95     memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
96
97     return page_tail;
98 }
99
100
101
102 static int vtlb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
103
104     V3_Print("VTLB initialization\n");
105     return 0;
106 }
107
108 static int vtlb_deinit(struct v3_vm_info * vm) {
109     return 0;
110 }
111
112 static int vtlb_local_init(struct guest_info * core) {
113     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
114     struct vtlb_local_state * vtlb_state = NULL;
115
116     V3_Print("VTLB local initialization\n");
117
118     vtlb_state = (struct vtlb_local_state *)V3_Malloc(sizeof(struct vtlb_local_state));
119
120     INIT_LIST_HEAD(&(vtlb_state->page_list));
121
122     state->local_impl_data = vtlb_state;
123
124     return 0;
125 }
126
127
128 static int vtlb_local_deinit(struct guest_info * core) {
129     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
130     struct vtlb_local_state * vtlb_state = state->local_impl_data;
131
132     struct shadow_page_data * shdw_pg = NULL;
133     struct shadow_page_data * tmp = NULL;
134
135     // free page list...
136     list_for_each_entry_safe(shdw_pg, tmp, &(vtlb_state->page_list), page_list_node) {
137         list_del(&(shdw_pg->page_list_node));
138         V3_FreePages((void *)shdw_pg->page_pa, 1);
139         V3_Free(shdw_pg);
140     }
141
142
143     V3_Free(vtlb_state);
144
145     return 0;
146 }
147
148
149 static int vtlb_activate_shdw_pt(struct guest_info * core) {
150     switch (v3_get_vm_cpu_mode(core)) {
151
152         case PROTECTED:
153             return activate_shadow_pt_32(core);
154         case PROTECTED_PAE:
155             return activate_shadow_pt_32pae(core);
156         case LONG:
157         case LONG_32_COMPAT:
158         case LONG_16_COMPAT:
159             return activate_shadow_pt_64(core);
160         default:
161             PrintError("Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
162             return -1;
163     }
164
165     return 0;
166 }
167
168 static int vtlb_invalidate_shdw_pt(struct guest_info * core) {
169     return vtlb_activate_shdw_pt(core);
170 }
171
172
173 static int vtlb_handle_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
174
175         switch (v3_get_vm_cpu_mode(core)) {
176             case PROTECTED:
177                 return handle_shadow_pagefault_32(core, fault_addr, error_code);
178                 break;
179             case PROTECTED_PAE:
180                 return handle_shadow_pagefault_32pae(core, fault_addr, error_code);
181             case LONG:
182             case LONG_32_COMPAT:
183             case LONG_16_COMPAT:
184                 return handle_shadow_pagefault_64(core, fault_addr, error_code);
185                 break;
186             default:
187                 PrintError("Unhandled CPU Mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
188                 return -1;
189         }
190 }
191
192
193 static int vtlb_handle_invlpg(struct guest_info * core, addr_t vaddr) {
194
195     switch (v3_get_vm_cpu_mode(core)) {
196         case PROTECTED:
197             return handle_shadow_invlpg_32(core, vaddr);
198         case PROTECTED_PAE:
199             return handle_shadow_invlpg_32pae(core, vaddr);
200         case LONG:
201         case LONG_32_COMPAT:
202         case LONG_16_COMPAT:
203             return handle_shadow_invlpg_64(core, vaddr);
204         default:
205             PrintError("Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
206             return -1;
207     }
208 }
209
210 static struct v3_shdw_pg_impl vtlb_impl =  {
211     .name = "VTLB",
212     .init = vtlb_init,
213     .deinit = vtlb_deinit,
214     .local_init = vtlb_local_init,
215     .local_deinit = vtlb_local_deinit,
216     .handle_pagefault = vtlb_handle_pf,
217     .handle_invlpg = vtlb_handle_invlpg,
218     .activate_shdw_pt = vtlb_activate_shdw_pt,
219     .invalidate_shdw_pt = vtlb_invalidate_shdw_pt
220 };
221
222
223
224
225
226 register_shdw_pg_impl(&vtlb_impl);