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.


Convert shadow paging to use 32 PAE (Direct Paging)
[palacios.git] / palacios / src / palacios / vmm_direct_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, 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.
14  *
15  * Author: Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
16  *
17  * This is free software.  You are permitted to use,
18  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19  */
20
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>
27
28
29 #ifndef V3_CONFIG_DEBUG_NESTED_PAGING
30 #undef PrintDebug
31 #define PrintDebug(fmt, args...)
32 #endif
33
34
35 static addr_t create_generic_pt_page(struct guest_info *core) {
36     void * page = 0;
37     void *temp;
38
39     temp = V3_AllocPagesExtended(1, PAGE_SIZE_4KB, -1, 0); // no constraints
40
41     if (!temp) {  
42         PrintError(VM_NONE, VCORE_NONE,"Cannot allocate page\n");
43         return 0;
44     }
45
46     page = V3_VAddr(temp);
47     memset(page, 0, PAGE_SIZE);
48
49     return (addr_t)page;
50 }
51
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"
56
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));
59     return 0;
60 }
61
62
63 int v3_free_passthrough_pts(struct guest_info * core) {
64     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
65
66     // Delete the old direct map page tables
67     switch(mode) {
68         case REAL:
69         case PROTECTED:
70           // Intentional fallthrough here
71           // There are *only* PAE tables
72         case PROTECTED_PAE:
73         case LONG:
74         case LONG_32_COMPAT:
75             // Long mode will only use 32PAE page tables...
76             delete_page_tables_32pae((pdpe32pae_t *)V3_VAddr((void *)(core->direct_map_pt)));
77             break;
78         default:
79             PrintError(core->vm_info, core, "Unknown CPU Mode\n");
80             return -1;
81             break;
82     }
83
84     return 0;
85 }
86
87
88 int v3_reset_passthrough_pts(struct guest_info * core) {
89
90     v3_free_passthrough_pts(core);
91
92     // create new direct map page table
93     v3_init_passthrough_pts(core);
94     
95     return 0;
96 }
97
98
99
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;
109     shadow_cr4->pae = 1;
110     PrintDebug(info->vm_info, info, "Activated Passthrough Page tables\n");
111     return 0;
112 }
113
114
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);
117
118     switch(mode) {
119         case REAL:
120         case PROTECTED:
121           // Note intentional fallthrough here
122           // There are only PAE page tables now
123         case PROTECTED_PAE:
124         case LONG:
125         case LONG_32_COMPAT:
126             // Long mode will only use 32PAE page tables...
127             return handle_passthrough_pagefault_32pae(info, fault_addr, error_code);
128
129         default:
130             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
131             break;
132     }
133     return -1;
134 }
135
136
137
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();
140
141
142     PrintDebug(info->vm_info, info, "Nested PageFault: fault_addr=%p, error_code=%u\n", (void *)fault_addr, *(uint_t *)&error_code);
143
144     switch(mode) {
145         case REAL:
146         case PROTECTED:
147             return handle_passthrough_pagefault_32(info, fault_addr, error_code);
148
149         case PROTECTED_PAE:
150             return handle_passthrough_pagefault_32pae(info, fault_addr, error_code);
151
152         case LONG:
153         case LONG_32_COMPAT:
154             return handle_passthrough_pagefault_64(info, fault_addr, error_code);           
155         
156         default:
157             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
158             break;
159     }
160     return -1;
161 }
162
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);
165
166     switch(mode) {
167         case REAL:
168         case PROTECTED:
169           // Intentional fallthrough - there
170           // are only PAE page tables now
171         case PROTECTED_PAE:
172         case LONG:
173         case LONG_32_COMPAT:
174             // Long mode will only use 32PAE page tables...
175             return invalidate_addr_32pae(info, inv_addr);
176
177         default:
178             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
179             break;
180     }
181     return -1;
182 }
183
184
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);
188
189     switch(mode) {
190         case REAL:
191         case PROTECTED:
192           // Intentional fallthrough
193           // There are only PAE PTs now
194         case PROTECTED_PAE:
195         case LONG:
196         case LONG_32_COMPAT:
197             // Long mode will only use 32PAE page tables...
198             return invalidate_addr_32pae_range(info, inv_addr_start, inv_addr_end);
199
200         default:
201             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
202             break;
203     }
204     return -1;
205 }
206
207 int v3_invalidate_nested_addr(struct guest_info * info, addr_t inv_addr) {
208
209 #ifdef __V3_64BIT__
210     v3_cpu_mode_t mode = LONG;
211 #else 
212     v3_cpu_mode_t mode = PROTECTED;
213 #endif
214
215     switch(mode) {
216         case REAL:
217         case PROTECTED:
218             return invalidate_addr_32(info, inv_addr);
219
220         case PROTECTED_PAE:
221             return invalidate_addr_32pae(info, inv_addr);
222
223         case LONG:
224         case LONG_32_COMPAT:
225             return invalidate_addr_64(info, inv_addr);      
226         
227         default:
228             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
229             break;
230     }
231
232     return -1;
233 }
234
235 int v3_invalidate_nested_addr_range(struct guest_info * info, 
236                                     addr_t inv_addr_start, addr_t inv_addr_end) {
237
238 #ifdef __V3_64BIT__
239     v3_cpu_mode_t mode = LONG;
240 #else 
241     v3_cpu_mode_t mode = PROTECTED;
242 #endif
243
244     switch(mode) {
245         case REAL:
246         case PROTECTED:
247             return invalidate_addr_32_range(info, inv_addr_start, inv_addr_end);
248
249         case PROTECTED_PAE:
250             return invalidate_addr_32pae_range(info, inv_addr_start, inv_addr_end);
251
252         case LONG:
253         case LONG_32_COMPAT:
254             return invalidate_addr_64_range(info, inv_addr_start, inv_addr_end);            
255         
256         default:
257             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
258             break;
259     }
260
261     return -1;
262 }