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, Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
11 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
12 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21 #include <palacios/vmm_direct_paging.h>
22 #include <palacios/vmm_paging.h>
23 #include <palacios/vmm.h>
24 #include <palacios/vm_guest_mem.h>
25 #include <palacios/vm_guest.h>
26 #include <palacios/vmm_ctrl_regs.h>
29 #ifndef V3_CONFIG_DEBUG_NESTED_PAGING
31 #define PrintDebug(fmt, args...)
35 static addr_t create_generic_pt_page(struct guest_info *core) {
39 temp = V3_AllocPagesExtended(1, PAGE_SIZE_4KB, -1, 0); // no constraints
42 PrintError(VM_NONE, VCORE_NONE,"Cannot allocate page\n");
46 page = V3_VAddr(temp);
47 memset(page, 0, PAGE_SIZE);
52 // Inline handler functions for each cpu mode
53 #include "vmm_direct_paging_32.h"
54 #include "vmm_direct_paging_32pae.h"
55 #include "vmm_direct_paging_64.h"
57 int v3_init_passthrough_pts(struct guest_info * info) {
58 info->direct_map_pt = (addr_t)V3_PAddr((void *)create_generic_pt_page(info));
63 int v3_free_passthrough_pts(struct guest_info * core) {
64 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
66 // Delete the old direct map page tables
70 // Intentional fallthrough here
71 // There are *only* PAE tables
75 // Long mode will only use 32PAE page tables...
76 delete_page_tables_32pae((pdpe32pae_t *)V3_VAddr((void *)(core->direct_map_pt)));
79 PrintError(core->vm_info, core, "Unknown CPU Mode\n");
88 int v3_reset_passthrough_pts(struct guest_info * core) {
90 v3_free_passthrough_pts(core);
92 // create new direct map page table
93 v3_init_passthrough_pts(core);
100 int v3_activate_passthrough_pt(struct guest_info * info) {
101 // For now... But we need to change this....
102 // As soon as shadow paging becomes active the passthrough tables are hosed
103 // So this will cause chaos if it is called at that time
104 struct cr3_32_PAE * shadow_cr3 = (struct cr3_32_PAE *) &(info->ctrl_regs.cr3);
105 struct cr4_32 * shadow_cr4 = (struct cr4_32 *) &(info->ctrl_regs.cr4);
106 addr_t shadow_pt_addr = *(addr_t*)&(info->direct_map_pt);
107 // Passthrough PTs will only be PAE page tables.
108 shadow_cr3->pdpt_base_addr = shadow_pt_addr >> 5;
110 PrintDebug(info->vm_info, info, "Activated Passthrough Page tables\n");
115 int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
116 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(info);
121 // Note intentional fallthrough here
122 // There are only PAE page tables now
126 // Long mode will only use 32PAE page tables...
127 return handle_passthrough_pagefault_32pae(info, fault_addr, error_code);
130 PrintError(info->vm_info, info, "Unknown CPU Mode\n");
138 int v3_handle_nested_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
139 v3_cpu_mode_t mode = v3_get_host_cpu_mode();
142 PrintDebug(info->vm_info, info, "Nested PageFault: fault_addr=%p, error_code=%u\n", (void *)fault_addr, *(uint_t *)&error_code);
147 return handle_passthrough_pagefault_32(info, fault_addr, error_code);
150 return handle_passthrough_pagefault_32pae(info, fault_addr, error_code);
154 return handle_passthrough_pagefault_64(info, fault_addr, error_code);
157 PrintError(info->vm_info, info, "Unknown CPU Mode\n");
163 int v3_invalidate_passthrough_addr(struct guest_info * info, addr_t inv_addr) {
164 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(info);
169 // Intentional fallthrough - there
170 // are only PAE page tables now
174 // Long mode will only use 32PAE page tables...
175 return invalidate_addr_32pae(info, inv_addr);
178 PrintError(info->vm_info, info, "Unknown CPU Mode\n");
185 int v3_invalidate_passthrough_addr_range(struct guest_info * info,
186 addr_t inv_addr_start, addr_t inv_addr_end) {
187 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(info);
192 // Intentional fallthrough
193 // There are only PAE PTs now
197 // Long mode will only use 32PAE page tables...
198 return invalidate_addr_32pae_range(info, inv_addr_start, inv_addr_end);
201 PrintError(info->vm_info, info, "Unknown CPU Mode\n");
207 int v3_invalidate_nested_addr(struct guest_info * info, addr_t inv_addr) {
210 v3_cpu_mode_t mode = LONG;
212 v3_cpu_mode_t mode = PROTECTED;
218 return invalidate_addr_32(info, inv_addr);
221 return invalidate_addr_32pae(info, inv_addr);
225 return invalidate_addr_64(info, inv_addr);
228 PrintError(info->vm_info, info, "Unknown CPU Mode\n");
235 int v3_invalidate_nested_addr_range(struct guest_info * info,
236 addr_t inv_addr_start, addr_t inv_addr_end) {
239 v3_cpu_mode_t mode = LONG;
241 v3_cpu_mode_t mode = PROTECTED;
247 return invalidate_addr_32_range(info, inv_addr_start, inv_addr_end);
250 return invalidate_addr_32pae_range(info, inv_addr_start, inv_addr_end);
254 return invalidate_addr_64_range(info, inv_addr_start, inv_addr_end);
257 PrintError(info->vm_info, info, "Unknown CPU Mode\n");