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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
15 * Author: Chunxiao Diao <chunxiaodiao2012@u.northwestern.edu>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22 #include <palacios/vmm_shadow_paging.h>
23 #include <palacios/vmm_ctrl_regs.h>
25 #include <palacios/vm_guest.h>
26 #include <palacios/vm_guest_mem.h>
29 #ifndef V3_CONFIG_DEBUG_SHDW_PG_VTLB
31 #define PrintDebug(fmt, ...)
35 struct shadow_page_data {
39 struct list_head page_list_node;
43 struct vtlb_local_state {
45 struct list_head page_list;
50 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
53 #include "vmm_shdw_pg_tlb_32.h"
54 #include "vmm_shdw_pg_tlb_32pae.h"
55 #include "vmm_shdw_pg_tlb_64.h"
57 static inline int get_constraints(struct guest_info *core)
59 // the current version of VTLB does not require any constraints
60 // on where page tables are allocated since it will use
61 // 32PAE page tables on a 64 bit machine even in 32 bit mode and below
66 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
67 struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
68 struct vtlb_local_state * impl_state = (struct vtlb_local_state *)(state->local_impl_data);
69 v3_reg_t cur_cr3 = core->ctrl_regs.cr3;
70 struct shadow_page_data * page_tail = NULL;
73 if (!list_empty(&(impl_state->page_list))) {
74 page_tail = list_tail_entry(&(impl_state->page_list), struct shadow_page_data, page_list_node);
77 if (page_tail->cr3 != cur_cr3) {
78 PrintDebug(core->vm_info, core, "Reusing old shadow Page: %p (cur_CR3=%p)(page_cr3=%p) \n",
79 (void *)(addr_t)page_tail->page_pa,
80 (void *)(addr_t)cur_cr3,
81 (void *)(addr_t)(page_tail->cr3));
83 list_move(&(page_tail->page_list_node), &(impl_state->page_list));
85 memset(V3_VAddr((void *)(page_tail->page_pa)), 0, PAGE_SIZE_4KB);
94 page_tail = (struct shadow_page_data *)V3_Malloc(sizeof(struct shadow_page_data));
97 PrintError(core->vm_info, core, "Cannot allocate\n");
101 page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,get_constraints(core));
103 if (!page_tail->page_pa) {
104 PrintError(core->vm_info, core, "Cannot allocate page\n");
108 PrintDebug(core->vm_info, core, "Allocating new shadow Page: %p (cur_cr3=%p)\n",
109 (void *)(addr_t)page_tail->page_pa,
110 (void *)(addr_t)cur_cr3);
112 page_tail->cr3 = cur_cr3;
113 list_add(&(page_tail->page_list_node), &(impl_state->page_list));
115 shdw_page = (addr_t)V3_VAddr((void *)(page_tail->page_pa));
116 memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
123 static int vtlb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
125 V3_Print(vm, VCORE_NONE, "VTLB initialization\n");
129 static int vtlb_deinit(struct v3_vm_info * vm) {
133 static int vtlb_local_init(struct guest_info * core) {
134 struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
135 struct vtlb_local_state * vtlb_state = NULL;
137 V3_Print(core->vm_info, core, "VTLB local initialization\n");
139 vtlb_state = (struct vtlb_local_state *)V3_Malloc(sizeof(struct vtlb_local_state));
142 PrintError(core->vm_info, core, "Cannot allocate\n");
146 INIT_LIST_HEAD(&(vtlb_state->page_list));
148 state->local_impl_data = vtlb_state;
154 static int vtlb_local_deinit(struct guest_info * core) {
155 struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
156 struct vtlb_local_state * vtlb_state = state->local_impl_data;
158 struct shadow_page_data * shdw_pg = NULL;
159 struct shadow_page_data * tmp = NULL;
162 list_for_each_entry_safe(shdw_pg, tmp, &(vtlb_state->page_list), page_list_node) {
163 list_del(&(shdw_pg->page_list_node));
164 V3_FreePages((void *)shdw_pg->page_pa, 1);
175 static int vtlb_activate_shdw_pt(struct guest_info * core) {
176 switch (v3_get_vm_cpu_mode(core)) {
179 return activate_shadow_pt_32(core);
182 return activate_shadow_pt_32pae(core);
187 return activate_shadow_pt_64(core);
190 PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
198 static int vtlb_invalidate_shdw_pt(struct guest_info * core) {
199 return vtlb_activate_shdw_pt(core);
203 static int vtlb_handle_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
205 switch (v3_get_vm_cpu_mode(core)) {
207 return handle_shadow_pagefault_32(core, fault_addr, error_code);
210 return handle_shadow_pagefault_32pae(core, fault_addr, error_code);
214 return handle_shadow_pagefault_64(core, fault_addr, error_code);
217 PrintError(core->vm_info, core, "Unhandled CPU Mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
223 static int vtlb_handle_invlpg(struct guest_info * core, addr_t vaddr) {
225 switch (v3_get_vm_cpu_mode(core)) {
227 return handle_shadow_invlpg_32(core, vaddr);
229 return handle_shadow_invlpg_32pae(core, vaddr);
233 return handle_shadow_invlpg_64(core, vaddr);
235 PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
240 static struct v3_shdw_pg_impl vtlb_impl = {
243 .deinit = vtlb_deinit,
244 .local_init = vtlb_local_init,
245 .local_deinit = vtlb_local_deinit,
246 .handle_pagefault = vtlb_handle_pf,
247 .handle_invlpg = vtlb_handle_invlpg,
248 .activate_shdw_pt = vtlb_activate_shdw_pt,
249 .invalidate_shdw_pt = vtlb_invalidate_shdw_pt
256 register_shdw_pg_impl(&vtlb_impl);