VirtualBox

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

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/** @file
2 *
3 * SELM All contexts.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_SELM
27#include <VBox/selm.h>
28#include <VBox/stam.h>
29#include <VBox/mm.h>
30#include "SELMInternal.h"
31#include <VBox/vm.h>
32#include <VBox/x86.h>
33#include <VBox/err.h>
34#include <VBox/param.h>
35#include <iprt/assert.h>
36#include <VBox/log.h>
37
38
39
40/**
41 * Converts a GC selector based address to a flat address.
42 *
43 * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
44 * for that.
45 *
46 * @returns Flat address.
47 * @param pVM VM Handle.
48 * @param Sel Selector part.
49 * @param Addr Address part.
50 */
51static RTGCPTR selmToFlat(PVM pVM, RTSEL Sel, RTGCPTR Addr)
52{
53 Assert(!CPUMAreHiddenSelRegsValid(pVM));
54
55 /** @todo check the limit. */
56 VBOXDESC Desc;
57 if (!(Sel & X86_SEL_LDT))
58 Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
59 else
60 {
61 /** @todo handle LDT pages not present! */
62 #ifdef IN_GC
63 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
64 #else
65 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
66 #endif
67 Desc = paLDT[Sel >> X86_SEL_SHIFT];
68 }
69
70 return (RTGCPTR)( (RTGCUINTPTR)Addr
71 + ( (Desc.Gen.u8BaseHigh2 << 24)
72 | (Desc.Gen.u8BaseHigh1 << 16)
73 | Desc.Gen.u16BaseLow));
74}
75
76
77/**
78 * Converts a GC selector based address to a flat address.
79 *
80 * No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
81 * for that.
82 *
83 * @returns Flat address.
84 * @param pVM VM Handle.
85 * @param Sel Selector part.
86 * @param Addr Address part.
87 */
88SELMDECL(RTGCPTR) SELMToFlat(PVM pVM, RTSEL Sel, CPUMSELREGHID *pHiddenSel, RTGCPTR Addr)
89{
90 if (!CPUMAreHiddenSelRegsValid(pVM))
91 return selmToFlat(pVM, Sel, Addr);
92
93 return (RTGCPTR)(pHiddenSel->u32Base + (RTGCUINTPTR)Addr);
94}
95
96
97/**
98 * Converts a GC selector based address to a flat address.
99 *
100 * Some basic checking is done, but not all kinds yet.
101 *
102 * @returns VBox status
103 * @param pVM VM Handle.
104 * @param Sel Selector part.
105 * @param Addr Address part.
106 * @param fFlags SELMTOFLAT_FLAGS_*
107 * GDT entires are valid.
108 * @param ppvGC Where to store the GC flat address.
109 * @param pcb Where to store the bytes from *ppvGC which can be accessed according to
110 * the selector. NULL is allowed.
111 */
112SELMDECL(int) SELMToFlatEx(PVM pVM, RTSEL Sel, RTGCPTR Addr, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
113{
114 /*
115 * Deal with real mode first.
116 */
117 if (CPUMIsGuestInRealMode(pVM)
118 /** @todo || (fFlags & SELMTOFLAT_FLAGS_V86)*/)
119 {
120 if (pcb)
121 *pcb = 0x10000 - ((RTGCUINTPTR)Addr & 0xffff);
122 if (ppvGC)
123 {
124 RTGCUINTPTR uFlat = ((RTGCUINTPTR)Addr & 0xffff) + (Sel << 4);
125 *ppvGC = (RTGCPTR)uFlat;
126 }
127 return VINF_SUCCESS;
128 }
129
130 Assert(!CPUMAreHiddenSelRegsValid(pVM));
131
132 VBOXDESC Desc;
133 if (!(Sel & X86_SEL_LDT))
134 {
135 if ( !(fFlags & SELMTOFLAT_FLAGS_HYPER)
136 && (unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.GuestGdtr.cbGdt)
137 return VERR_INVALID_SELECTOR;
138 Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
139 }
140 else
141 {
142 if ((unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.cbLdtLimit)
143 return VERR_INVALID_SELECTOR;
144
145 /** @todo handle LDT page(s) not present! */
146 #ifdef IN_GC
147 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
148 #else
149 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
150 #endif
151 Desc = paLDT[Sel >> X86_SEL_SHIFT];
152 }
153
154 /*
155 * Check if present.
156 */
157 if (Desc.Gen.u1Present)
158 {
159 /* calc limit. */
160 uint32_t u32Limit = Desc.Gen.u4LimitHigh << 16 | Desc.Gen.u16LimitLow;
161 if (Desc.Gen.u1Granularity)
162 u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
163
164 /* calc address assuming straight stuff. */
165 RTGCPTR pvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr
166 + ( (Desc.Gen.u8BaseHigh2 << 24)
167 | (Desc.Gen.u8BaseHigh1 << 16)
168 | Desc.Gen.u16BaseLow )
169 );
170 /*
171 * Type check.
172 */
173 #define BOTH(a, b) ((a << 16) | b)
174 switch (BOTH(Desc.Gen.u1DescType, Desc.Gen.u4Type))
175 {
176
177 /** Read only selector type. */
178 case BOTH(1,X86_SEL_TYPE_RO):
179 case BOTH(1,X86_SEL_TYPE_RO_ACC):
180 case BOTH(1,X86_SEL_TYPE_RW):
181 case BOTH(1,X86_SEL_TYPE_RW_ACC):
182 case BOTH(1,X86_SEL_TYPE_EO):
183 case BOTH(1,X86_SEL_TYPE_EO_ACC):
184 case BOTH(1,X86_SEL_TYPE_ER):
185 case BOTH(1,X86_SEL_TYPE_ER_ACC):
186 if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
187 {
188 /** @todo fix this mess */
189 }
190 /* check limit. */
191 if ((RTGCUINTPTR)Addr > u32Limit)
192 return VERR_OUT_OF_SELECTOR_BOUNDS;
193 /* ok */
194 if (ppvGC)
195 *ppvGC = pvFlat;
196 if (pcb)
197 *pcb = u32Limit - (uint32_t)Addr + 1;
198 return VINF_SUCCESS;
199 case BOTH(1,X86_SEL_TYPE_EO_CONF):
200 case BOTH(1,X86_SEL_TYPE_EO_CONF_ACC):
201 case BOTH(1,X86_SEL_TYPE_ER_CONF):
202 case BOTH(1,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 ((RTGCUINTPTR)Addr > u32Limit)
209 return VERR_OUT_OF_SELECTOR_BOUNDS;
210 /* ok */
211 if (ppvGC)
212 *ppvGC = pvFlat;
213 if (pcb)
214 *pcb = u32Limit - (uint32_t)Addr + 1;
215 return VINF_SUCCESS;
216
217 case BOTH(1,X86_SEL_TYPE_RO_DOWN):
218 case BOTH(1,X86_SEL_TYPE_RO_DOWN_ACC):
219 case BOTH(1,X86_SEL_TYPE_RW_DOWN):
220 case BOTH(1,X86_SEL_TYPE_RW_DOWN_ACC):
221 if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
222 {
223 /** @todo fix this mess */
224 }
225 /* check limit. */
226 /** @todo check the manual on this!!! */
227 if ((RTGCUINTPTR)(Desc.Gen.u1Granularity ? 0xffffffff : 0xfffff) - (RTGCUINTPTR)Addr > u32Limit)
228 return VERR_OUT_OF_SELECTOR_BOUNDS;
229
230 /* ok */
231 if (ppvGC)
232 *ppvGC = pvFlat;
233 if (pcb)
234 *pcb = (Desc.Gen.u1Granularity ? 0xffffffff : 0xfffff) - (RTGCUINTPTR)Addr + 1;
235 return VINF_SUCCESS;
236
237 case BOTH(0,X86_SEL_TYPE_SYS_286_TSS_AVAIL):
238 case BOTH(0,X86_SEL_TYPE_SYS_LDT):
239 case BOTH(0,X86_SEL_TYPE_SYS_286_TSS_BUSY):
240 case BOTH(0,X86_SEL_TYPE_SYS_286_CALL_GATE):
241 case BOTH(0,X86_SEL_TYPE_SYS_TASK_GATE):
242 case BOTH(0,X86_SEL_TYPE_SYS_286_INT_GATE):
243 case BOTH(0,X86_SEL_TYPE_SYS_286_TRAP_GATE):
244 case BOTH(0,X86_SEL_TYPE_SYS_386_TSS_AVAIL):
245 case BOTH(0,X86_SEL_TYPE_SYS_386_TSS_BUSY):
246 case BOTH(0,X86_SEL_TYPE_SYS_386_CALL_GATE):
247 case BOTH(0,X86_SEL_TYPE_SYS_386_INT_GATE):
248 case BOTH(0,X86_SEL_TYPE_SYS_386_TRAP_GATE):
249 if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
250 {
251 /** @todo fix this mess */
252 }
253 /* check limit. */
254 if ((RTGCUINTPTR)Addr > u32Limit)
255 return VERR_OUT_OF_SELECTOR_BOUNDS;
256 /* ok */
257 if (ppvGC)
258 *ppvGC = pvFlat;
259 if (pcb)
260 *pcb = 0xffffffff - (RTGCUINTPTR)pvFlat + 1; /* Depends on the type.. fixme if we care. */
261 return VINF_SUCCESS;
262
263 default:
264 return VERR_INVALID_SELECTOR;
265
266 }
267 #undef BOTH
268 }
269 return VERR_SELECTOR_NOT_PRESENT;
270}
271
272
273/**
274 * Validates and converts a GC selector based code address to a flat address.
275 *
276 * @returns Flat address.
277 * @param pVM VM Handle.
278 * @param SelCPL Current privilege level. Get this from SS - CS might be conforming!
279 * A full selector can be passed, we'll only use the RPL part.
280 * @param SelCS Selector part.
281 * @param Addr Address part.
282 * @param ppvFlat Where to store the flat address.
283 */
284static int selmValidateAndConvertCSAddr(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
285{
286 Assert(!CPUMAreHiddenSelRegsValid(pVM));
287
288 /** @todo validate limit! */
289 VBOXDESC Desc;
290 if (!(SelCS & X86_SEL_LDT))
291 Desc = pVM->selm.s.CTXSUFF(paGdt)[SelCS >> X86_SEL_SHIFT];
292 else
293 {
294 /** @todo handle LDT page(s) not present! */
295 #ifdef IN_GC
296 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
297 #else
298 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
299 #endif
300 Desc = paLDT[SelCS >> X86_SEL_SHIFT];
301 }
302
303 /*
304 * Check if present.
305 */
306 if (Desc.Gen.u1Present)
307 {
308 /*
309 * Type check.
310 */
311 if ( Desc.Gen.u1DescType == 1
312 && (Desc.Gen.u4Type & X86_SEL_TYPE_CODE))
313 {
314 /*
315 * Check level.
316 */
317 unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL);
318 if ( !(Desc.Gen.u4Type & X86_SEL_TYPE_CONF)
319 ? uLevel <= Desc.Gen.u2Dpl
320 : uLevel >= Desc.Gen.u2Dpl /* hope I got this right now... */
321 )
322 {
323 /*
324 * Limit check.
325 */
326 uint32_t u32Limit = Desc.Gen.u4LimitHigh << 16 | Desc.Gen.u16LimitLow;
327 if (Desc.Gen.u1Granularity)
328 u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
329 if ((RTGCUINTPTR)Addr <= u32Limit)
330 {
331 if (ppvFlat)
332 *ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr
333 + ( (Desc.Gen.u8BaseHigh2 << 24)
334 | (Desc.Gen.u8BaseHigh1 << 16)
335 | Desc.Gen.u16BaseLow)
336 );
337 return VINF_SUCCESS;
338 }
339 return VERR_OUT_OF_SELECTOR_BOUNDS;
340 }
341 return VERR_INVALID_RPL;
342 }
343 return VERR_NOT_CODE_SELECTOR;
344 }
345 return VERR_SELECTOR_NOT_PRESENT;
346}
347
348
349/**
350 * Validates and converts a GC selector based code address to a flat address.
351 *
352 * @returns Flat address.
353 * @param pVM VM Handle.
354 * @param SelCPL Current privilege level. Get this from SS - CS might be conforming!
355 * A full selector can be passed, we'll only use the RPL part.
356 * @param SelCS Selector part.
357 * @param pHiddenSel The hidden CS selector register.
358 * @param Addr Address part.
359 * @param ppvFlat Where to store the flat address.
360 */
361SELMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, RTSEL SelCPL, RTSEL SelCS, CPUMSELREGHID *pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat)
362{
363 if (!CPUMAreHiddenSelRegsValid(pVM))
364 return selmValidateAndConvertCSAddr(pVM, SelCPL, SelCS, Addr, ppvFlat);
365
366 /*
367 * Check if present.
368 */
369 if (pHiddenCSSel->Attr.n.u1Present)
370 {
371 /*
372 * Type check.
373 */
374 if ( pHiddenCSSel->Attr.n.u1DescType == 1
375 && (pHiddenCSSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
376 {
377 /*
378 * Check level.
379 */
380 unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL);
381 if ( !(pHiddenCSSel->Attr.n.u4Type & X86_SEL_TYPE_CONF)
382 ? uLevel <= pHiddenCSSel->Attr.n.u2Dpl
383 : uLevel >= pHiddenCSSel->Attr.n.u2Dpl /* hope I got this right now... */
384 )
385 {
386 /*
387 * Limit check.
388 */
389 uint32_t u32Limit = pHiddenCSSel->u32Limit;
390 /** @todo correct with hidden limit value?? */
391 if (pHiddenCSSel->Attr.n.u1Granularity)
392 u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
393 if ((RTGCUINTPTR)Addr <= u32Limit)
394 {
395 if (ppvFlat)
396 *ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr + pHiddenCSSel->u32Base );
397
398 return VINF_SUCCESS;
399 }
400 return VERR_OUT_OF_SELECTOR_BOUNDS;
401 }
402 return VERR_INVALID_RPL;
403 }
404 return VERR_NOT_CODE_SELECTOR;
405 }
406 return VERR_SELECTOR_NOT_PRESENT;
407}
408
409
410/**
411 * Checks if a selector is 32-bit or 16-bit.
412 *
413 * @returns True if it is 32-bit.
414 * @returns False if it is 16-bit.
415 * @param pVM VM Handle.
416 * @param Sel The selector.
417 */
418static bool selmIsSelector32Bit(PVM pVM, RTSEL Sel)
419{
420 Assert(!CPUMAreHiddenSelRegsValid(pVM));
421
422 /** @todo validate limit! */
423 VBOXDESC Desc;
424 if (!(Sel & X86_SEL_LDT))
425 Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
426 else
427 {
428 /** @todo handle LDT page(s) not present! */
429 PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.CTXMID(,PtrLdt) + pVM->selm.s.offLdtHyper);
430 Desc = paLDT[Sel >> X86_SEL_SHIFT];
431 }
432 return Desc.Gen.u1DefBig;
433}
434
435
436/**
437 * Checks if a selector is 32-bit or 16-bit.
438 *
439 * @returns True if it is 32-bit.
440 * @returns False if it is 16-bit.
441 * @param pVM VM Handle.
442 * @param Sel The selector.
443 * @param pHiddenSel The hidden selector register.
444 */
445SELMDECL(bool) SELMIsSelector32Bit(PVM pVM, RTSEL Sel, CPUMSELREGHID *pHiddenSel)
446{
447 if (!CPUMAreHiddenSelRegsValid(pVM))
448 return selmIsSelector32Bit(pVM, Sel);
449
450 return pHiddenSel->Attr.n.u1DefBig;
451}
452
453
454/**
455 * Returns Hypervisor's Trap 08 (\#DF) selector.
456 *
457 * @returns Hypervisor's Trap 08 (\#DF) selector.
458 * @param pVM VM Handle.
459 */
460SELMDECL(RTSEL) SELMGetTrap8Selector(PVM pVM)
461{
462 return pVM->selm.s.SelTSSTrap08;
463}
464
465
466/**
467 * Sets EIP of Hypervisor's Trap 08 (\#DF) TSS.
468 *
469 * @param pVM VM Handle.
470 * @param u32EIP EIP of Trap 08 handler.
471 */
472SELMDECL(void) SELMSetTrap8EIP(PVM pVM, uint32_t u32EIP)
473{
474 pVM->selm.s.TssTrap08.eip = u32EIP;
475}
476
477
478/**
479 * Sets ss:esp for ring1 in main Hypervisor's TSS.
480 *
481 * @param pVM VM Handle.
482 * @param ss Ring1 SS register value.
483 * @param esp Ring1 ESP register value.
484 */
485SELMDECL(void) SELMSetRing1Stack(PVM pVM, uint32_t ss, uint32_t esp)
486{
487 pVM->selm.s.Tss.ss1 = ss;
488 pVM->selm.s.Tss.esp1 = esp;
489}
490
491
492/**
493 * Gets ss:esp for ring1 in main Hypervisor's TSS.
494 *
495 * @param pVM VM Handle.
496 * @param pSS Ring1 SS register value.
497 * @param pEsp Ring1 ESP register value.
498 */
499SELMDECL(void) SELMGetRing1Stack(PVM pVM, uint32_t *pSS, uint32_t *pEsp)
500{
501 *pSS = pVM->selm.s.Tss.ss1;
502 *pEsp = pVM->selm.s.Tss.esp1;
503}
504
505
506/**
507 * Returns Guest TSS pointer
508 *
509 * @param pVM VM Handle.
510 */
511SELMDECL(RTGCPTR) SELMGetGuestTSS(PVM pVM)
512{
513 return (RTGCPTR)pVM->selm.s.GCPtrGuestTss;
514}
515
516
517/**
518 * Validates a CS selector.
519 *
520 * @returns VBox status code.
521 * @param pSelInfo Pointer to the selector information for the CS selector.
522 * @param SelCPL The selector defining the CPL (SS).
523 */
524SELMDECL(int) SELMSelInfoValidateCS(PCSELMSELINFO pSelInfo, RTSEL SelCPL)
525{
526 /*
527 * Check if present.
528 */
529 if (pSelInfo->Raw.Gen.u1Present)
530 {
531 /*
532 * Type check.
533 */
534 if ( pSelInfo->Raw.Gen.u1DescType == 1
535 && (pSelInfo->Raw.Gen.u4Type & X86_SEL_TYPE_CODE))
536 {
537 /*
538 * Check level.
539 */
540 unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, pSelInfo->Sel & X86_SEL_RPL);
541 if ( !(pSelInfo->Raw.Gen.u4Type & X86_SEL_TYPE_CONF)
542 ? uLevel <= pSelInfo->Raw.Gen.u2Dpl
543 : uLevel >= pSelInfo->Raw.Gen.u2Dpl /* hope I got this right now... */
544 )
545 return VINF_SUCCESS;
546 return VERR_INVALID_RPL;
547 }
548 return VERR_NOT_CODE_SELECTOR;
549 }
550 return VERR_SELECTOR_NOT_PRESENT;
551}
552
553
554/**
555 * Gets the hypervisor code selector (CS).
556 * @returns CS selector.
557 * @param pVM The VM handle.
558 */
559SELMDECL(RTSEL) SELMGetHyperCS(PVM pVM)
560{
561 return pVM->selm.s.SelCS;
562}
563
564
565/**
566 * Gets the 64-mode hypervisor code selector (CS64).
567 * @returns CS selector.
568 * @param pVM The VM handle.
569 */
570SELMDECL(RTSEL) SELMGetHyperCS64(PVM pVM)
571{
572 return pVM->selm.s.SelCS64;
573}
574
575
576/**
577 * Gets the hypervisor data selector (DS).
578 * @returns DS selector.
579 * @param pVM The VM handle.
580 */
581SELMDECL(RTSEL) SELMGetHyperDS(PVM pVM)
582{
583 return pVM->selm.s.SelDS;
584}
585
586
587/**
588 * Gets the hypervisor TSS selector.
589 * @returns TSS selector.
590 * @param pVM The VM handle.
591 */
592SELMDECL(RTSEL) SELMGetHyperTSS(PVM pVM)
593{
594 return pVM->selm.s.SelTSS;
595}
596
597
598/**
599 * Gets the hypervisor TSS Trap 8 selector.
600 * @returns TSS Trap 8 selector.
601 * @param pVM The VM handle.
602 */
603SELMDECL(RTSEL) SELMGetHyperTSSTrap08(PVM pVM)
604{
605 return pVM->selm.s.SelTSSTrap08;
606}
607
608
609/**
610 * Gets the address for the hypervisor GDT.
611 *
612 * @returns The GDT address.
613 * @param pVM The VM handle.
614 * @remark This is intended only for very special use, like in the world
615 * switchers. Don't exploit this API!
616 */
617SELMDECL(RTGCPTR) SELMGetHyperGDT(PVM pVM)
618{
619 /*
620 * Always convert this from the HC pointer since. We're can be
621 * called before the first relocation and have to work correctly
622 * without having dependencies on the relocation order.
623 */
624 return MMHyperHC2GC(pVM, pVM->selm.s.paGdtHC);
625}
626
627
628/**
629 * Gets info about the current TSS.
630 *
631 * @returns VBox status code.
632 * @retval VINF_SUCCESS if we've got a TSS loaded.
633 * @retval VERR_SELM_NO_TSS if we haven't got a TSS (rather unlikely).
634 *
635 * @param pVM The VM handle.
636 * @param pGCPtrTss Where to store the TSS address.
637 * @param pcbTss Where to store the TSS size limit.
638 * @param pfCanHaveIOBitmap Where to store the can-have-I/O-bitmap indicator. (optional)
639 */
640SELMDECL(int) SELMGetTSSInfo(PVM pVM, PRTGCUINTPTR pGCPtrTss, PRTGCUINTPTR pcbTss, bool *pfCanHaveIOBitmap)
641{
642 if (!CPUMAreHiddenSelRegsValid(pVM))
643 {
644 /*
645 * Do we have a valid TSS?
646 */
647 if ( pVM->selm.s.GCSelTss == (RTSEL)~0
648 || !pVM->selm.s.fGuestTss32Bit)
649 return VERR_SELM_NO_TSS;
650
651 /*
652 * Fill in return values.
653 */
654 *pGCPtrTss = (RTGCUINTPTR)pVM->selm.s.GCPtrGuestTss;
655 *pcbTss = pVM->selm.s.cbGuestTss;
656 if (pfCanHaveIOBitmap)
657 *pfCanHaveIOBitmap = pVM->selm.s.fGuestTss32Bit;
658 }
659 else
660 {
661 CPUMSELREGHID *pHiddenTRReg;
662
663 pHiddenTRReg = CPUMGetGuestTRHid(pVM);
664
665 *pGCPtrTss = pHiddenTRReg->u32Base;
666 *pcbTss = pHiddenTRReg->u32Limit;
667
668 if (pfCanHaveIOBitmap)
669 *pfCanHaveIOBitmap = pHiddenTRReg->Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_AVAIL
670 || pHiddenTRReg->Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY;
671 }
672 return VINF_SUCCESS;
673}
Note: See TracBrowser for help on using the repository browser.

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