VirtualBox

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

Last change on this file since 96860 was 96407, checked in by vboxsync, 22 months ago

scm copyright and license note update

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

© 2023 Oracle
ContactPrivacy policyTerms of Use