VirtualBox

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

Last change on this file since 93582 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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

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