VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/SELMAll.cpp@ 80317

最後變更 在這個檔案從80317是 80281,由 vboxsync 提交於 6 年 前

VMM,++: Refactoring code to use VMMC & VMMCPUCC. bugref:9217

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 13.0 KB
 
1/* $Id: SELMAll.cpp 80281 2019-08-15 07:29:37Z vboxsync $ */
2/** @file
3 * SELM All contexts.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define VBOX_BUGREF_9217_PART_I
23#define LOG_GROUP LOG_GROUP_SELM
24#include <VBox/vmm/selm.h>
25#include <VBox/vmm/stam.h>
26#include <VBox/vmm/em.h>
27#include <VBox/vmm/mm.h>
28#include <VBox/vmm/hm.h>
29#include <VBox/vmm/pgm.h>
30#include <VBox/vmm/hm.h>
31#include "SELMInternal.h"
32#include <VBox/vmm/vmcc.h>
33#include <VBox/err.h>
34#include <VBox/param.h>
35#include <iprt/assert.h>
36#include <VBox/vmm/vmm.h>
37#include <iprt/x86.h>
38#include <iprt/string.h>
39
40
41
42/**
43 * Converts a GC selector based address to a flat address.
44 *
45 * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
46 * for that.
47 *
48 * @returns Flat address.
49 * @param pVM The cross context VM structure.
50 * @param SelReg Selector register
51 * @param pCtxCore CPU context
52 * @param Addr Address part.
53 */
54VMMDECL(RTGCPTR) SELMToFlat(PVMCC pVM, DISSELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr)
55{
56 PCPUMSELREG pSReg;
57 PVMCPUCC pVCpu = VMMGetCpu(pVM);
58
59 int rc = DISFetchRegSegEx(pCtxCore, SelReg, &pSReg); AssertRC(rc);
60
61 /*
62 * Deal with real & v86 mode first.
63 */
64 if ( pCtxCore->eflags.Bits.u1VM
65 || CPUMIsGuestInRealMode(pVCpu))
66 {
67 uint32_t uFlat = (uint32_t)Addr & 0xffff;
68 if (CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg))
69 uFlat += (uint32_t)pSReg->u64Base;
70 else
71 uFlat += (uint32_t)pSReg->Sel << 4;
72 return (RTGCPTR)uFlat;
73 }
74
75 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg));
76 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pCtxCore->cs));
77
78 /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
79 (Intel® 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
80 if ( pCtxCore->cs.Attr.n.u1Long
81 && CPUMIsGuestInLongMode(pVCpu))
82 {
83 switch (SelReg)
84 {
85 case DISSELREG_FS:
86 case DISSELREG_GS:
87 return (RTGCPTR)(pSReg->u64Base + Addr);
88
89 default:
90 return Addr; /* base 0 */
91 }
92 }
93
94 /* AMD64 manual: compatibility mode ignores the high 32 bits when calculating an effective address. */
95 Assert(pSReg->u64Base <= 0xffffffff);
96 return (uint32_t)pSReg->u64Base + (uint32_t)Addr;
97}
98
99
100/**
101 * Converts a GC selector based address to a flat address.
102 *
103 * Some basic checking is done, but not all kinds yet.
104 *
105 * @returns VBox status
106 * @param pVCpu The cross context virtual CPU structure.
107 * @param SelReg Selector register.
108 * @param pCtxCore CPU context.
109 * @param Addr Address part.
110 * @param fFlags SELMTOFLAT_FLAGS_*
111 * GDT entires are valid.
112 * @param ppvGC Where to store the GC flat address.
113 */
114VMMDECL(int) SELMToFlatEx(PVMCPU pVCpu, DISSELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr, uint32_t fFlags, PRTGCPTR ppvGC)
115{
116 /*
117 * Fetch the selector first.
118 */
119 PCPUMSELREG pSReg;
120 int rc = DISFetchRegSegEx(pCtxCore, SelReg, &pSReg);
121 AssertRCReturn(rc, rc); AssertPtr(pSReg);
122
123 /*
124 * Deal with real & v86 mode first.
125 */
126 if ( pCtxCore->eflags.Bits.u1VM
127 || CPUMIsGuestInRealMode(pVCpu))
128 {
129 if (ppvGC)
130 {
131 uint32_t uFlat = (uint32_t)Addr & 0xffff;
132 if (CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg))
133 *ppvGC = (uint32_t)pSReg->u64Base + uFlat;
134 else
135 *ppvGC = ((uint32_t)pSReg->Sel << 4) + uFlat;
136 }
137 return VINF_SUCCESS;
138 }
139
140 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg));
141 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pCtxCore->cs));
142
143 /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
144 (Intel® 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
145 RTGCPTR pvFlat;
146 bool fCheckLimit = true;
147 if ( pCtxCore->cs.Attr.n.u1Long
148 && CPUMIsGuestInLongMode(pVCpu))
149 {
150 fCheckLimit = false;
151 switch (SelReg)
152 {
153 case DISSELREG_FS:
154 case DISSELREG_GS:
155 pvFlat = pSReg->u64Base + Addr;
156 break;
157
158 default:
159 pvFlat = Addr;
160 break;
161 }
162 }
163 else
164 {
165 /* AMD64 manual: compatibility mode ignores the high 32 bits when calculating an effective address. */
166 Assert(pSReg->u64Base <= UINT32_C(0xffffffff));
167 pvFlat = (uint32_t)pSReg->u64Base + (uint32_t)Addr;
168 Assert(pvFlat <= UINT32_MAX);
169 }
170
171 /*
172 * Check type if present.
173 */
174 if (pSReg->Attr.n.u1Present)
175 {
176 switch (pSReg->Attr.n.u4Type)
177 {
178 /* Read only selector type. */
179 case X86_SEL_TYPE_RO:
180 case X86_SEL_TYPE_RO_ACC:
181 case X86_SEL_TYPE_RW:
182 case X86_SEL_TYPE_RW_ACC:
183 case X86_SEL_TYPE_EO:
184 case X86_SEL_TYPE_EO_ACC:
185 case X86_SEL_TYPE_ER:
186 case X86_SEL_TYPE_ER_ACC:
187 if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
188 {
189 /** @todo fix this mess */
190 }
191 /* check limit. */
192 if (fCheckLimit && Addr > pSReg->u32Limit)
193 return VERR_OUT_OF_SELECTOR_BOUNDS;
194 /* ok */
195 if (ppvGC)
196 *ppvGC = pvFlat;
197 return VINF_SUCCESS;
198
199 case X86_SEL_TYPE_EO_CONF:
200 case X86_SEL_TYPE_EO_CONF_ACC:
201 case X86_SEL_TYPE_ER_CONF:
202 case X86_SEL_TYPE_ER_CONF_ACC:
203 if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
204 {
205 /** @todo fix this mess */
206 }
207 /* check limit. */
208 if (fCheckLimit && Addr > pSReg->u32Limit)
209 return VERR_OUT_OF_SELECTOR_BOUNDS;
210 /* ok */
211 if (ppvGC)
212 *ppvGC = pvFlat;
213 return VINF_SUCCESS;
214
215 case X86_SEL_TYPE_RO_DOWN:
216 case X86_SEL_TYPE_RO_DOWN_ACC:
217 case X86_SEL_TYPE_RW_DOWN:
218 case X86_SEL_TYPE_RW_DOWN_ACC:
219 if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
220 {
221 /** @todo fix this mess */
222 }
223 /* check limit. */
224 if (fCheckLimit)
225 {
226 if (!pSReg->Attr.n.u1Granularity && Addr > UINT32_C(0xffff))
227 return VERR_OUT_OF_SELECTOR_BOUNDS;
228 if (Addr <= pSReg->u32Limit)
229 return VERR_OUT_OF_SELECTOR_BOUNDS;
230 }
231 /* ok */
232 if (ppvGC)
233 *ppvGC = pvFlat;
234 return VINF_SUCCESS;
235
236 default:
237 return VERR_INVALID_SELECTOR;
238
239 }
240 }
241 return VERR_SELECTOR_NOT_PRESENT;
242}
243
244
245
246/**
247 * Validates and converts a GC selector based code address to a flat
248 * address when in real or v8086 mode.
249 *
250 * @returns VINF_SUCCESS.
251 * @param pVCpu The cross context virtual CPU structure.
252 * @param SelCS Selector part.
253 * @param pSReg The hidden CS register part. Optional.
254 * @param Addr Address part.
255 * @param ppvFlat Where to store the flat address.
256 */
257DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVMCPU pVCpu, RTSEL SelCS, PCCPUMSELREGHID pSReg, RTGCPTR Addr,
258 PRTGCPTR ppvFlat)
259{
260 NOREF(pVCpu);
261 uint32_t uFlat = Addr & 0xffff;
262 if (!pSReg || !CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg))
263 uFlat += (uint32_t)SelCS << 4;
264 else
265 uFlat += (uint32_t)pSReg->u64Base;
266 *ppvFlat = uFlat;
267 return VINF_SUCCESS;
268}
269
270
271/**
272 * Validates and converts a GC selector based code address to a flat address
273 * when in protected/long mode using the standard hidden selector registers
274 *
275 * @returns VBox status code.
276 * @param pVCpu The cross context virtual CPU structure.
277 * @param SelCPL Current privilege level. Get this from SS - CS might be
278 * conforming! A full selector can be passed, we'll only
279 * use the RPL part.
280 * @param SelCS Selector part.
281 * @param pSRegCS The full CS selector register.
282 * @param Addr The address (think IP/EIP/RIP).
283 * @param ppvFlat Where to store the flat address upon successful return.
284 */
285DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, PCCPUMSELREGHID pSRegCS,
286 RTGCPTR Addr, PRTGCPTR ppvFlat)
287{
288 NOREF(SelCPL); NOREF(SelCS);
289
290 /*
291 * Check if present.
292 */
293 if (pSRegCS->Attr.n.u1Present)
294 {
295 /*
296 * Type check.
297 */
298 if ( pSRegCS->Attr.n.u1DescType == 1
299 && (pSRegCS->Attr.n.u4Type & X86_SEL_TYPE_CODE))
300 {
301 /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0
302 (Intel® 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
303 if ( pSRegCS->Attr.n.u1Long
304 && CPUMIsGuestInLongMode(pVCpu))
305 {
306 *ppvFlat = Addr;
307 return VINF_SUCCESS;
308 }
309
310 /*
311 * Limit check. Note that the limit in the hidden register is the
312 * final value. The granularity bit was included in its calculation.
313 */
314 uint32_t u32Limit = pSRegCS->u32Limit;
315 if ((uint32_t)Addr <= u32Limit)
316 {
317 *ppvFlat = (uint32_t)Addr + (uint32_t)pSRegCS->u64Base;
318 return VINF_SUCCESS;
319 }
320
321 return VERR_OUT_OF_SELECTOR_BOUNDS;
322 }
323 return VERR_NOT_CODE_SELECTOR;
324 }
325 return VERR_SELECTOR_NOT_PRESENT;
326}
327
328
329/**
330 * Validates and converts a GC selector based code address to a flat address.
331 *
332 * @returns VBox status code.
333 * @param pVCpu The cross context virtual CPU structure.
334 * @param Efl Current EFLAGS.
335 * @param SelCPL Current privilege level. Get this from SS - CS might be
336 * conforming! A full selector can be passed, we'll only
337 * use the RPL part.
338 * @param SelCS Selector part.
339 * @param pSRegCS The full CS selector register.
340 * @param Addr The address (think IP/EIP/RIP).
341 * @param ppvFlat Where to store the flat address upon successful return.
342 */
343VMMDECL(int) SELMValidateAndConvertCSAddr(PVMCPU pVCpu, X86EFLAGS Efl, RTSEL SelCPL, RTSEL SelCS, PCPUMSELREG pSRegCS,
344 RTGCPTR Addr, PRTGCPTR ppvFlat)
345{
346 if ( Efl.Bits.u1VM
347 || CPUMIsGuestInRealMode(pVCpu))
348 return selmValidateAndConvertCSAddrRealMode(pVCpu, SelCS, pSRegCS, Addr, ppvFlat);
349
350 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSRegCS));
351 Assert(pSRegCS->Sel == SelCS);
352
353 return selmValidateAndConvertCSAddrHidden(pVCpu, SelCPL, SelCS, pSRegCS, Addr, ppvFlat);
354}
355
356
357/**
358 * Gets info about the current TSS.
359 *
360 * @returns VBox status code.
361 * @retval VINF_SUCCESS if we've got a TSS loaded.
362 * @retval VERR_SELM_NO_TSS if we haven't got a TSS (rather unlikely).
363 *
364 * @param pVM The cross context VM structure.
365 * @param pVCpu The cross context virtual CPU structure.
366 * @param pGCPtrTss Where to store the TSS address.
367 * @param pcbTss Where to store the TSS size limit.
368 * @param pfCanHaveIOBitmap Where to store the can-have-I/O-bitmap indicator. (optional)
369 */
370VMMDECL(int) SELMGetTSSInfo(PVM pVM, PVMCPU pVCpu, PRTGCUINTPTR pGCPtrTss, PRTGCUINTPTR pcbTss, bool *pfCanHaveIOBitmap)
371{
372 NOREF(pVM);
373
374 /*
375 * The TR hidden register is always valid.
376 */
377 CPUMSELREGHID trHid;
378 RTSEL tr = CPUMGetGuestTR(pVCpu, &trHid);
379 if (!(tr & X86_SEL_MASK_OFF_RPL))
380 return VERR_SELM_NO_TSS;
381
382 *pGCPtrTss = trHid.u64Base;
383 *pcbTss = trHid.u32Limit + (trHid.u32Limit != UINT32_MAX); /* be careful. */
384 if (pfCanHaveIOBitmap)
385 *pfCanHaveIOBitmap = trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_AVAIL
386 || trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY;
387 return VINF_SUCCESS;
388}
389
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette