Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ept-devel/vmm/core/vt_ept.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (show annotations) (download) (as text)
Fri May 4 15:02:17 2012 UTC (12 months, 2 weeks ago) by yuichi_xy
File MIME type: text/x-csrc
File size: 8327 byte(s)
BIOS が設定した MTTR の値から物理メモリアドレス領域のキャッシュ属性を取得し、EPT に反映するようにした。不要な関数テーブルである struct cpuid_func と struct msr_func を削除した。
1 /*
2 * Copyright (c) 2007, 2008 University of Tsukuba
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. Neither the name of the University of Tsukuba nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*
30 * Copyright (c) 2010-2012 Yuichi Watanabe
31 */
32
33 #include <core/mm.h>
34 #include <core/printf.h>
35 #include <core/thread.h>
36 #include "apic_pass.h"
37 #include "asm.h"
38 #include "cpu_mmu.h"
39 #include "mm.h"
40 #include "mtrr.h"
41 #include "vt_internal.h"
42 #include "constants.h"
43 #include "current.h"
44
45 #define EPT_MAX_LEVEL 4
46 #define EPT_LEVEL_STRIDE (9)
47 #define EPT_LEVEL_MASK ((1 << EPT_LEVEL_STRIDE) - 1)
48
49 #define EPT_READ 0x1
50 #define EPT_WRITE 0x2
51 #define EPT_EXECUTE 0x4
52 #define EPT_VAILED_MASK 0x7
53 #define EPT_MEMTYPE_TO_PTE(memtype) ((memtype) << 3)
54
55 #define VMCS_EPT_POINTER_ADDR_WB 0x6
56 #define VMCS_EPT_POINTER_ADDR_EPT_LENGTH ((EPT_MAX_LEVEL - 1) << 3)
57
58 #define VMCS_EXIT_QUALIFICATION_READ_BIT 0x1
59 #define VMCS_EXIT_QUALIFICATION_WRITE_BIT 0x2
60 #define VMCS_EXIT_QUALIFICATION_INST_BIT 0x4
61 #define VMCS_EXIT_QUALIFICATION_LINEAR_ADDR_VALID_BIT 0x80
62
63
64 #define ept_offset(addr, level) \
65 ((addr >> (PAGE_SHIFT + (level - 1) * EPT_LEVEL_STRIDE)) \
66 & EPT_LEVEL_MASK)
67
68 static void
69 vt_ept_invalidate_tlb(void)
70 {
71 struct {
72 u64 ept_l4tbl;
73 u64 reserved;
74 } desc;
75
76 desc.ept_l4tbl = current->vm->vt.ept_l4tbl;
77 desc.reserved = 0;
78 asm_invept(&desc);
79 }
80
81 void
82 vt_ept_init(void)
83 {
84 struct vt_vm_data *vt_data = &current->vm->vt;
85 u32 ctls_or, ctls_and;
86 u32 ctls2_or, ctls2_and;
87 ulong ctls;
88 void *vaddr;
89 vmmerr_t err;
90
91 asm_rdmsr32(MSR_IA32_VMX_PROCBASED_CTLS, &ctls_or, &ctls_and);
92 if ((ctls_and & VMCS_PROC_BASED_VMEXEC_CTL_SEC_CTL_BIT) == 0 ||
93 ctls_or & VMCS_PROC_BASED_VMEXEC_CTL_INVLPGEXIT_BIT) {
94 return;
95 }
96 asm_rdmsr32(MSR_IA32_VMX_PROCBASED_CTLS2, &ctls2_or, &ctls2_and);
97 if ((ctls2_and & VMCS_PROC_BASED_VMEXEC_CTL2_EPT_BIT) == 0) {
98 return;
99 }
100
101 if (cpu_is_bsp()) {
102 printf("Enabling EPT\n");
103 }
104
105 current->u.vt.ept_enabled = true;
106
107 spinlock_lock(&vt_data->ept_lock);
108 if (vt_data->ept_l4tbl == 0) {
109 err = alloc_page(&vaddr, &vt_data->ept_l4tbl);
110 if (err) {
111 panic("Failed to allocate a ept l4tbl.");
112 }
113 memset(vaddr, 0, PAGE_SIZE);
114 }
115 spinlock_unlock(&vt_data->ept_lock);
116
117 ctls = ctls2_or | VMCS_PROC_BASED_VMEXEC_CTL2_EPT_BIT;
118 asm_vmwrite(VMCS_PROC_BASED_VMEXEC_CTL2, ctls);
119
120 asm_vmread(VMCS_PROC_BASED_VMEXEC_CTL, &ctls);
121 ctls &= ~VMCS_PROC_BASED_VMEXEC_CTL_INVLPGEXIT_BIT;
122 ctls |= VMCS_PROC_BASED_VMEXEC_CTL_SEC_CTL_BIT;
123 asm_vmwrite(VMCS_PROC_BASED_VMEXEC_CTL, ctls);
124
125 asm_vmwrite (VMCS_EXCEPTION_BMP, 0xffffbfff);
126 asm_vmwrite (VMCS_PAGEFAULT_ERRCODE_MASK, 0);
127 asm_vmwrite (VMCS_PAGEFAULT_ERRCODE_MATCH, 0xffffffff);
128
129 asm_vmwrite64(VMCS_EPT_POINTER_ADDR,
130 vt_data->ept_l4tbl |
131 VMCS_EPT_POINTER_ADDR_WB |
132 VMCS_EPT_POINTER_ADDR_EPT_LENGTH);
133 }
134
135 static u64 *
136 vt_ept_walk(phys_t gphys, void *ept_l4tbl)
137 {
138 u64 *tbl;
139 int offset;
140 u64 *pte;
141 int cur_level;
142 void *vaddr;
143 phys_t phys;
144 vmmerr_t ret;
145
146 tbl = ept_l4tbl;
147
148 for (cur_level = EPT_MAX_LEVEL; cur_level >= 2; cur_level--) {
149 offset = ept_offset(gphys, cur_level);
150 pte = &tbl[offset];
151
152 if ((*pte & EPT_VAILED_MASK) == 0) {
153 ret = alloc_page(&vaddr, &phys);
154 if (ret != VMMERR_SUCCESS) {
155 return NULL;
156 }
157 memset(vaddr, 0, PAGE_SIZE);
158
159 *pte = (phys & PAGE_MASK) |
160 EPT_READ | EPT_WRITE | EPT_EXECUTE;
161 } else {
162 phys = *pte & PAGE_MASK;
163 vaddr = (void *)phys_to_virt(phys);
164 }
165 tbl = (u64 *)vaddr;
166 };
167
168 return tbl + ept_offset(gphys, cur_level);
169 }
170
171 static void
172 vt_ept_generate_pagefault(vmmerr_t vmmerr)
173 {
174 bool wr, us;
175 ulong linear_addr;
176 ulong qual;
177
178 asm_vmread(VMCS_EXIT_QUALIFICATION, &qual);
179 if ((qual & VMCS_EXIT_QUALIFICATION_LINEAR_ADDR_VALID_BIT) == 0) {
180 panic("EPT violation without linear address. qual 0x%lx",
181 qual);
182 }
183 wr = qual & VMCS_EXIT_QUALIFICATION_WRITE_BIT ? true : false;
184 us = seg_user_mode();
185 asm_vmread(VMCS_GUEST_LINEAR_ADDR, &linear_addr);
186 printf("vt_ept_generate_pagefault 0x%lx wr %d us %d\n",
187 linear_addr, wr, us);
188 mmu_generate_pagefault(vmmerr, wr, us, linear_addr);
189 }
190
191 void
192 vt_ept_violation(void)
193 {
194 struct vt_vm_data *vt_data = &current->vm->vt;
195 void *ept_l4tbl;
196 u64 *pte;
197 u8 memtype;
198 phys_t gphys;
199 phys_t hphys;
200 vmmerr_t ret;
201
202 asm_vmread64(VMCS_GUEST_PHYS_ADDR, &gphys);
203
204 mmio_lock();
205 ret = mmio_pagefault(gphys);
206 mmio_unlock();
207 if (ret != VMMERR_NODEV) {
208 if (ret == VMMERR_SUCCESS) {
209 return;
210 }
211 if (ret < VMMERR_PAGE_NOT_PRESENT ||
212 ret > VMMERR_PAGE_BAD_RESERVED_BIT) {
213 panic("Failed to emulate accessing to MMIO area. ret 0x%x",
214 ret);
215 }
216 vt_ept_generate_pagefault(ret);
217 return;
218 }
219
220 hphys = current->vm->gmm.gp2hp(gphys);
221 if (hphys == GMM_NO_MAPPING) {
222 ret = cpu_interpreter();
223 if (ret == VMMERR_SUCCESS) {
224 return;
225 }
226 if (ret < VMMERR_PAGE_NOT_PRESENT ||
227 ret > VMMERR_PAGE_BAD_RESERVED_BIT) {
228 panic("Failed to emulate accessing to no mapping area. ret 0x%x",
229 ret);
230 }
231 vt_ept_generate_pagefault(ret);
232 return;
233 }
234
235 memtype = mtrr_get_mem_type(hphys);
236
237 spinlock_lock(&vt_data->ept_lock);
238 ept_l4tbl = (void *)phys_to_virt(vt_data->ept_l4tbl);
239 pte = vt_ept_walk(gphys, ept_l4tbl);
240
241 if (*pte & EPT_VAILED_MASK) {
242 if ((*pte & PAGE_MASK) != (hphys & PAGE_MASK)) {
243 panic("EPT PTE is already set. "
244 "gphys 0x%llx, hphys 0x%llx, pte 0x%llx",
245 gphys, hphys, *pte);
246 }
247 } else {
248 *pte = (hphys & PAGE_MASK) |
249 EPT_READ | EPT_WRITE | EPT_EXECUTE |
250 EPT_MEMTYPE_TO_PTE(memtype) |
251 0x40; /* Force ept mem type for now */
252 }
253
254 spinlock_unlock(&vt_data->ept_lock);
255
256 }
257
258 void
259 vt_ept_pg_change(bool pg)
260 {
261 ulong cr4;
262 ulong ctls;
263
264 if (!current->u.vt.ept_enabled) {
265 return;
266 }
267
268 if (pg) {
269 asm_vmread(VMCS_PROC_BASED_VMEXEC_CTL2, &ctls);
270 ctls |= VMCS_PROC_BASED_VMEXEC_CTL2_EPT_BIT;
271 asm_vmwrite(VMCS_PROC_BASED_VMEXEC_CTL2, ctls);
272
273 asm_vmread(VMCS_PROC_BASED_VMEXEC_CTL, &ctls);
274 ctls &= ~VMCS_PROC_BASED_VMEXEC_CTL_INVLPGEXIT_BIT;
275 asm_vmwrite(VMCS_PROC_BASED_VMEXEC_CTL, ctls);
276
277 asm_vmwrite(VMCS_EXCEPTION_BMP, 0xffffbfff);
278 asm_vmwrite(VMCS_PAGEFAULT_ERRCODE_MASK, 0);
279 asm_vmwrite(VMCS_PAGEFAULT_ERRCODE_MATCH, 0xffffffff);
280
281 asm_vmwrite(VMCS_GUEST_CR3, current->u.vt.vr.cr3);
282 } else {
283 asm_vmread(VMCS_PROC_BASED_VMEXEC_CTL2, &ctls);
284 ctls &= ~VMCS_PROC_BASED_VMEXEC_CTL2_EPT_BIT;
285 asm_vmwrite(VMCS_PROC_BASED_VMEXEC_CTL2, ctls);
286
287 asm_vmread(VMCS_PROC_BASED_VMEXEC_CTL, &ctls);
288 ctls |= VMCS_PROC_BASED_VMEXEC_CTL_INVLPGEXIT_BIT;
289 asm_vmwrite(VMCS_PROC_BASED_VMEXEC_CTL, ctls);
290
291 asm_vmwrite(VMCS_EXCEPTION_BMP, 0xffffffff);
292 asm_vmwrite(VMCS_PAGEFAULT_ERRCODE_MASK, 0);
293 asm_vmwrite(VMCS_PAGEFAULT_ERRCODE_MATCH, 0);
294
295 /*
296 * Guest CR3 will be updated by cpu_mmu_spt_updatecr3,
297 * so that we don't need to set guest CR3 here.
298 */
299 }
300 vt_read_control_reg(CONTROL_REG_CR4, &cr4);
301 vt_write_control_reg(CONTROL_REG_CR4, cr4);
302
303 vt_ept_invalidate_tlb();
304 }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.