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.


5f5be4c559f4e31e0e5060c86e49085417c45dfb
[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
27
28 #ifndef V3_CONFIG_DEBUG_NESTED_PAGING
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34 static addr_t create_generic_pt_page(struct guest_info *core) {
35     void * page = 0;
36     void *temp;
37
38     temp = V3_AllocPagesExtended(1, PAGE_SIZE_4KB, -1, 
39                                  core->shdw_pg_mode==SHADOW_PAGING ? V3_ALLOC_PAGES_CONSTRAINT_4GB : 0);
40     if (!temp) { 
41         PrintError(VM_NONE, VCORE_NONE,"Cannot allocate page\n");
42         return 0;
43     }
44
45     page = V3_VAddr(temp);
46     memset(page, 0, PAGE_SIZE);
47
48     return (addr_t)page;
49 }
50
51 // Inline handler functions for each cpu mode
52 #include "vmm_direct_paging_32.h"
53 #include "vmm_direct_paging_32pae.h"
54 #include "vmm_direct_paging_64.h"
55
56 int v3_init_passthrough_pts(struct guest_info * info) {
57     info->direct_map_pt = (addr_t)V3_PAddr((void *)create_generic_pt_page(info));
58     return 0;
59 }
60
61
62 int v3_free_passthrough_pts(struct guest_info * core) {
63     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
64
65     // Delete the old direct map page tables
66     switch(mode) {
67         case REAL:
68         case PROTECTED:
69             delete_page_tables_32((pde32_t *)V3_VAddr((void *)(core->direct_map_pt)));
70             break;
71         case PROTECTED_PAE:
72         case LONG:
73         case LONG_32_COMPAT:
74             // Long mode will only use 32PAE page tables...
75             delete_page_tables_32pae((pdpe32pae_t *)V3_VAddr((void *)(core->direct_map_pt)));
76             break;
77         default:
78             PrintError(core->vm_info, core, "Unknown CPU Mode\n");
79             return -1;
80             break;
81     }
82
83     return 0;
84 }
85
86
87 int v3_reset_passthrough_pts(struct guest_info * core) {
88
89     v3_free_passthrough_pts(core);
90
91     // create new direct map page table
92     v3_init_passthrough_pts(core);
93     
94     return 0;
95 }
96
97
98
99 int v3_activate_passthrough_pt(struct guest_info * info) {
100     // For now... But we need to change this....
101     // As soon as shadow paging becomes active the passthrough tables are hosed
102     // So this will cause chaos if it is called at that time
103
104     info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
105     //PrintError(info->vm_info, info, "Activate Passthrough Page tables not implemented\n");
106     return 0;
107 }
108
109
110 int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
111     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(info);
112
113     switch(mode) {
114         case REAL:
115         case PROTECTED:
116             return handle_passthrough_pagefault_32(info, fault_addr, error_code);
117
118         case PROTECTED_PAE:
119         case LONG:
120         case LONG_32_COMPAT:
121             // Long mode will only use 32PAE page tables...
122             return handle_passthrough_pagefault_32pae(info, fault_addr, error_code);
123
124         default:
125             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
126             break;
127     }
128     return -1;
129 }
130
131
132
133 int v3_handle_nested_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
134     v3_cpu_mode_t mode = v3_get_host_cpu_mode();
135
136
137     PrintDebug(info->vm_info, info, "Nested PageFault: fault_addr=%p, error_code=%u\n", (void *)fault_addr, *(uint_t *)&error_code);
138
139     switch(mode) {
140         case REAL:
141         case PROTECTED:
142             return handle_passthrough_pagefault_32(info, fault_addr, error_code);
143
144         case PROTECTED_PAE:
145             return handle_passthrough_pagefault_32pae(info, fault_addr, error_code);
146
147         case LONG:
148         case LONG_32_COMPAT:
149             return handle_passthrough_pagefault_64(info, fault_addr, error_code);           
150         
151         default:
152             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
153             break;
154     }
155     return -1;
156 }
157
158 int v3_invalidate_passthrough_addr(struct guest_info * info, addr_t inv_addr) {
159     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(info);
160
161     switch(mode) {
162         case REAL:
163         case PROTECTED:
164             return invalidate_addr_32(info, inv_addr);
165
166         case PROTECTED_PAE:
167         case LONG:
168         case LONG_32_COMPAT:
169             // Long mode will only use 32PAE page tables...
170             return invalidate_addr_32pae(info, inv_addr);
171
172         default:
173             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
174             break;
175     }
176     return -1;
177 }
178
179
180 int v3_invalidate_passthrough_addr_range(struct guest_info * info, 
181                                          addr_t inv_addr_start, addr_t inv_addr_end) {
182     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(info);
183
184     switch(mode) {
185         case REAL:
186         case PROTECTED:
187             return invalidate_addr_32_range(info, inv_addr_start, inv_addr_end);
188
189         case PROTECTED_PAE:
190         case LONG:
191         case LONG_32_COMPAT:
192             // Long mode will only use 32PAE page tables...
193             return invalidate_addr_32pae_range(info, inv_addr_start, inv_addr_end);
194
195         default:
196             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
197             break;
198     }
199     return -1;
200 }
201
202 int v3_invalidate_nested_addr(struct guest_info * info, addr_t inv_addr) {
203
204 #ifdef __V3_64BIT__
205     v3_cpu_mode_t mode = LONG;
206 #else 
207     v3_cpu_mode_t mode = PROTECTED;
208 #endif
209
210     switch(mode) {
211         case REAL:
212         case PROTECTED:
213             return invalidate_addr_32(info, inv_addr);
214
215         case PROTECTED_PAE:
216             return invalidate_addr_32pae(info, inv_addr);
217
218         case LONG:
219         case LONG_32_COMPAT:
220             return invalidate_addr_64(info, inv_addr);      
221         
222         default:
223             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
224             break;
225     }
226
227     return -1;
228 }
229
230 int v3_invalidate_nested_addr_range(struct guest_info * info, 
231                                     addr_t inv_addr_start, addr_t inv_addr_end) {
232
233 #ifdef __V3_64BIT__
234     v3_cpu_mode_t mode = LONG;
235 #else 
236     v3_cpu_mode_t mode = PROTECTED;
237 #endif
238
239     switch(mode) {
240         case REAL:
241         case PROTECTED:
242             return invalidate_addr_32_range(info, inv_addr_start, inv_addr_end);
243
244         case PROTECTED_PAE:
245             return invalidate_addr_32pae_range(info, inv_addr_start, inv_addr_end);
246
247         case LONG:
248         case LONG_32_COMPAT:
249             return invalidate_addr_64_range(info, inv_addr_start, inv_addr_end);            
250         
251         default:
252             PrintError(info->vm_info, info, "Unknown CPU Mode\n");
253             break;
254     }
255
256     return -1;
257 }