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.


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