1
/* $Id: SELMAll.cpp 4211 2007-08-18 01:34:04Z vboxsync $ */
7
* Copyright (C) 2006-2007 innotek GmbH
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.
19
/*******************************************************************************
21
*******************************************************************************/
22
#define LOG_GROUP LOG_GROUP_SELM
23
#include <VBox/selm.h>
24
#include <VBox/stam.h>
27
#include "SELMInternal.h"
31
#include <VBox/param.h>
32
#include <iprt/assert.h>
38
* Converts a GC selector based address to a flat address.
40
* No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
43
* @returns Flat address.
44
* @param pVM VM Handle.
45
* @param Sel Selector part.
46
* @param Addr Address part.
48
static RTGCPTR selmToFlat(PVM pVM, RTSEL Sel, RTGCPTR Addr)
50
Assert(!CPUMAreHiddenSelRegsValid(pVM));
52
/** @todo check the limit. */
54
if (!(Sel & X86_SEL_LDT))
55
Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
58
/** @todo handle LDT pages not present! */
60
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
62
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
64
Desc = paLDT[Sel >> X86_SEL_SHIFT];
67
return (RTGCPTR)( (RTGCUINTPTR)Addr
68
+ ( (Desc.Gen.u8BaseHigh2 << 24)
69
| (Desc.Gen.u8BaseHigh1 << 16)
70
| Desc.Gen.u16BaseLow));
75
* Converts a GC selector based address to a flat address.
77
* No limit checks are done. Use the SELMToFlat*() or SELMValidate*() functions
80
* @returns Flat address.
81
* @param pVM VM Handle.
82
* @param eflags Current eflags
83
* @param Sel Selector part.
84
* @param pHiddenSel Hidden selector register
85
* @param Addr Address part.
87
SELMDECL(RTGCPTR) SELMToFlat(PVM pVM, X86EFLAGS eflags, RTSEL Sel, CPUMSELREGHID *pHiddenSel, RTGCPTR Addr)
89
Assert(pHiddenSel || !CPUMAreHiddenSelRegsValid(pVM));
92
* Deal with real & v86 mode first.
94
if ( CPUMIsGuestInRealMode(pVM)
97
RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
99
if (CPUMAreHiddenSelRegsValid(pVM))
100
uFlat += pHiddenSel->u32Base;
102
uFlat += ((RTGCUINTPTR)Sel << 4);
103
return (RTGCPTR)uFlat;
106
/** @todo when we're in 16 bits mode, we should cut off the address as well.. */
107
if (!CPUMAreHiddenSelRegsValid(pVM))
108
return selmToFlat(pVM, Sel, Addr);
109
return (RTGCPTR)(pHiddenSel->u32Base + (RTGCUINTPTR)Addr);
114
* Converts a GC selector based address to a flat address.
116
* Some basic checking is done, but not all kinds yet.
118
* @returns VBox status
119
* @param pVM VM Handle.
120
* @param eflags Current eflags
121
* @param Sel Selector part.
122
* @param Addr Address part.
123
* @param pHiddenSel Hidden selector register (can be NULL)
124
* @param fFlags SELMTOFLAT_FLAGS_*
125
* GDT entires are valid.
126
* @param ppvGC Where to store the GC flat address.
127
* @param pcb Where to store the bytes from *ppvGC which can be accessed according to
128
* the selector. NULL is allowed.
130
SELMDECL(int) SELMToFlatEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
133
* Deal with real & v86 mode first.
135
if ( CPUMIsGuestInRealMode(pVM)
138
RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
142
&& CPUMAreHiddenSelRegsValid(pVM))
143
*ppvGC = (RTGCPTR)(pHiddenSel->u32Base + uFlat);
145
*ppvGC = (RTGCPTR)(((RTGCUINTPTR)Sel << 4) + uFlat);
148
*pcb = 0x10000 - uFlat;
155
uint32_t u1Present, u1DescType, u1Granularity, u4Type;
157
/** @todo when we're in 16 bits mode, we should cut off the address as well.. */
159
&& CPUMAreHiddenSelRegsValid(pVM))
161
u1Present = pHiddenSel->Attr.n.u1Present;
162
u1Granularity = pHiddenSel->Attr.n.u1Granularity;
163
u1DescType = pHiddenSel->Attr.n.u1DescType;
164
u4Type = pHiddenSel->Attr.n.u4Type;
166
u32Limit = pHiddenSel->u32Limit;
167
pvFlat = (RTGCPTR)(pHiddenSel->u32Base + (RTGCUINTPTR)Addr);
173
if (!(Sel & X86_SEL_LDT))
175
if ( !(fFlags & SELMTOFLAT_FLAGS_HYPER)
176
&& (unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.GuestGdtr.cbGdt)
177
return VERR_INVALID_SELECTOR;
178
Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
182
if ((unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.cbLdtLimit)
183
return VERR_INVALID_SELECTOR;
185
/** @todo handle LDT page(s) not present! */
187
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
189
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
191
Desc = paLDT[Sel >> X86_SEL_SHIFT];
195
u32Limit = Desc.Gen.u4LimitHigh << 16 | Desc.Gen.u16LimitLow;
196
if (Desc.Gen.u1Granularity)
197
u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
199
/* calc address assuming straight stuff. */
200
pvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr
201
+ ( (Desc.Gen.u8BaseHigh2 << 24)
202
| (Desc.Gen.u8BaseHigh1 << 16)
203
| Desc.Gen.u16BaseLow )
206
u1Present = Desc.Gen.u1Present;
207
u1Granularity = Desc.Gen.u1Granularity;
208
u1DescType = Desc.Gen.u1DescType;
209
u4Type = Desc.Gen.u4Type;
220
#define BOTH(a, b) ((a << 16) | b)
221
switch (BOTH(u1DescType, u4Type))
224
/** Read only selector type. */
225
case BOTH(1,X86_SEL_TYPE_RO):
226
case BOTH(1,X86_SEL_TYPE_RO_ACC):
227
case BOTH(1,X86_SEL_TYPE_RW):
228
case BOTH(1,X86_SEL_TYPE_RW_ACC):
229
case BOTH(1,X86_SEL_TYPE_EO):
230
case BOTH(1,X86_SEL_TYPE_EO_ACC):
231
case BOTH(1,X86_SEL_TYPE_ER):
232
case BOTH(1,X86_SEL_TYPE_ER_ACC):
233
if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
235
/** @todo fix this mess */
238
if ((RTGCUINTPTR)Addr > u32Limit)
239
return VERR_OUT_OF_SELECTOR_BOUNDS;
244
*pcb = u32Limit - (uint32_t)Addr + 1;
247
case BOTH(1,X86_SEL_TYPE_EO_CONF):
248
case BOTH(1,X86_SEL_TYPE_EO_CONF_ACC):
249
case BOTH(1,X86_SEL_TYPE_ER_CONF):
250
case BOTH(1,X86_SEL_TYPE_ER_CONF_ACC):
251
if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
253
/** @todo fix this mess */
256
if ((RTGCUINTPTR)Addr > u32Limit)
257
return VERR_OUT_OF_SELECTOR_BOUNDS;
262
*pcb = u32Limit - (uint32_t)Addr + 1;
265
case BOTH(1,X86_SEL_TYPE_RO_DOWN):
266
case BOTH(1,X86_SEL_TYPE_RO_DOWN_ACC):
267
case BOTH(1,X86_SEL_TYPE_RW_DOWN):
268
case BOTH(1,X86_SEL_TYPE_RW_DOWN_ACC):
269
if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
271
/** @todo fix this mess */
274
if (!u1Granularity && (RTGCUINTPTR)Addr > (RTGCUINTPTR)0xffff)
275
return VERR_OUT_OF_SELECTOR_BOUNDS;
276
if ((RTGCUINTPTR)Addr <= u32Limit)
277
return VERR_OUT_OF_SELECTOR_BOUNDS;
283
*pcb = (RTGCUINTPTR)(u1Granularity ? 0xffffffff : 0xffff) - (RTGCUINTPTR)Addr + 1;
286
case BOTH(0,X86_SEL_TYPE_SYS_286_TSS_AVAIL):
287
case BOTH(0,X86_SEL_TYPE_SYS_LDT):
288
case BOTH(0,X86_SEL_TYPE_SYS_286_TSS_BUSY):
289
case BOTH(0,X86_SEL_TYPE_SYS_286_CALL_GATE):
290
case BOTH(0,X86_SEL_TYPE_SYS_TASK_GATE):
291
case BOTH(0,X86_SEL_TYPE_SYS_286_INT_GATE):
292
case BOTH(0,X86_SEL_TYPE_SYS_286_TRAP_GATE):
293
case BOTH(0,X86_SEL_TYPE_SYS_386_TSS_AVAIL):
294
case BOTH(0,X86_SEL_TYPE_SYS_386_TSS_BUSY):
295
case BOTH(0,X86_SEL_TYPE_SYS_386_CALL_GATE):
296
case BOTH(0,X86_SEL_TYPE_SYS_386_INT_GATE):
297
case BOTH(0,X86_SEL_TYPE_SYS_386_TRAP_GATE):
298
if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
300
/** @todo fix this mess */
303
if ((RTGCUINTPTR)Addr > u32Limit)
304
return VERR_OUT_OF_SELECTOR_BOUNDS;
309
*pcb = 0xffffffff - (RTGCUINTPTR)pvFlat + 1; /* Depends on the type.. fixme if we care. */
313
return VERR_INVALID_SELECTOR;
318
return VERR_SELECTOR_NOT_PRESENT;
323
* Validates and converts a GC selector based code address to a flat address.
325
* @returns Flat address.
326
* @param pVM VM Handle.
327
* @param SelCPL Current privilege level. Get this from SS - CS might be conforming!
328
* A full selector can be passed, we'll only use the RPL part.
329
* @param SelCS Selector part.
330
* @param Addr Address part.
331
* @param ppvFlat Where to store the flat address.
333
static int selmValidateAndConvertCSAddr(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
335
Assert(!CPUMAreHiddenSelRegsValid(pVM));
337
/** @todo validate limit! */
339
if (!(SelCS & X86_SEL_LDT))
340
Desc = pVM->selm.s.CTXSUFF(paGdt)[SelCS >> X86_SEL_SHIFT];
343
/** @todo handle LDT page(s) not present! */
345
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
347
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
349
Desc = paLDT[SelCS >> X86_SEL_SHIFT];
355
if (Desc.Gen.u1Present)
360
if ( Desc.Gen.u1DescType == 1
361
&& (Desc.Gen.u4Type & X86_SEL_TYPE_CODE))
366
unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL);
367
if ( !(Desc.Gen.u4Type & X86_SEL_TYPE_CONF)
368
? uLevel <= Desc.Gen.u2Dpl
369
: uLevel >= Desc.Gen.u2Dpl /* hope I got this right now... */
375
uint32_t u32Limit = Desc.Gen.u4LimitHigh << 16 | Desc.Gen.u16LimitLow;
376
if (Desc.Gen.u1Granularity)
377
u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
378
if ((RTGCUINTPTR)Addr <= u32Limit)
381
*ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr
382
+ ( (Desc.Gen.u8BaseHigh2 << 24)
383
| (Desc.Gen.u8BaseHigh1 << 16)
384
| Desc.Gen.u16BaseLow)
388
return VERR_OUT_OF_SELECTOR_BOUNDS;
390
return VERR_INVALID_RPL;
392
return VERR_NOT_CODE_SELECTOR;
394
return VERR_SELECTOR_NOT_PRESENT;
399
* Validates and converts a GC selector based code address to a flat address.
401
* @returns Flat address.
402
* @param pVM VM Handle.
403
* @param eflags Current eflags
404
* @param SelCPL Current privilege level. Get this from SS - CS might be conforming!
405
* A full selector can be passed, we'll only use the RPL part.
406
* @param SelCS Selector part.
407
* @param pHiddenSel The hidden CS selector register.
408
* @param Addr Address part.
409
* @param ppvFlat Where to store the flat address.
411
SELMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, CPUMSELREGHID *pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat)
414
* Deal with real & v86 mode first.
416
if ( CPUMIsGuestInRealMode(pVM)
421
RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
423
if (!CPUMAreHiddenSelRegsValid(pVM))
424
uFlat += ((RTGCUINTPTR)SelCS << 4);
426
uFlat += pHiddenCSSel->u32Base;
428
*ppvFlat = (RTGCPTR)uFlat;
433
/** @todo when we're in 16 bits mode, we should cut off the address as well.. */
435
if (!CPUMAreHiddenSelRegsValid(pVM))
436
return selmValidateAndConvertCSAddr(pVM, SelCPL, SelCS, Addr, ppvFlat);
441
if (pHiddenCSSel->Attr.n.u1Present)
446
if ( pHiddenCSSel->Attr.n.u1DescType == 1
447
&& (pHiddenCSSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
452
unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL);
453
if ( !(pHiddenCSSel->Attr.n.u4Type & X86_SEL_TYPE_CONF)
454
? uLevel <= pHiddenCSSel->Attr.n.u2Dpl
455
: uLevel >= pHiddenCSSel->Attr.n.u2Dpl /* hope I got this right now... */
461
uint32_t u32Limit = pHiddenCSSel->u32Limit;
462
/** @todo correct with hidden limit value?? */
463
if (pHiddenCSSel->Attr.n.u1Granularity)
464
u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
465
if ((RTGCUINTPTR)Addr <= u32Limit)
468
*ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr + pHiddenCSSel->u32Base );
472
return VERR_OUT_OF_SELECTOR_BOUNDS;
474
return VERR_INVALID_RPL;
476
return VERR_NOT_CODE_SELECTOR;
478
return VERR_SELECTOR_NOT_PRESENT;
483
* Checks if a selector is 32-bit or 16-bit.
485
* @returns True if it is 32-bit.
486
* @returns False if it is 16-bit.
487
* @param pVM VM Handle.
488
* @param Sel The selector.
490
static bool selmIsSelector32Bit(PVM pVM, RTSEL Sel)
492
Assert(!CPUMAreHiddenSelRegsValid(pVM));
494
/** @todo validate limit! */
496
if (!(Sel & X86_SEL_LDT))
497
Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
500
/** @todo handle LDT page(s) not present! */
501
PVBOXDESC paLDT = (PVBOXDESC)((char *)pVM->selm.s.CTXMID(,PtrLdt) + pVM->selm.s.offLdtHyper);
502
Desc = paLDT[Sel >> X86_SEL_SHIFT];
504
return Desc.Gen.u1DefBig;
509
* Checks if a selector is 32-bit or 16-bit.
511
* @returns True if it is 32-bit.
512
* @returns False if it is 16-bit.
513
* @param pVM VM Handle.
514
* @param eflags Current eflags register
515
* @param Sel The selector.
516
* @param pHiddenSel The hidden selector register.
518
SELMDECL(bool) SELMIsSelector32Bit(PVM pVM, X86EFLAGS eflags, RTSEL Sel, CPUMSELREGHID *pHiddenSel)
520
if (!CPUMAreHiddenSelRegsValid(pVM))
523
* Deal with real & v86 mode first.
525
if ( CPUMIsGuestInRealMode(pVM)
529
return selmIsSelector32Bit(pVM, Sel);
531
return pHiddenSel->Attr.n.u1DefBig;
536
* Returns Hypervisor's Trap 08 (\#DF) selector.
538
* @returns Hypervisor's Trap 08 (\#DF) selector.
539
* @param pVM VM Handle.
541
SELMDECL(RTSEL) SELMGetTrap8Selector(PVM pVM)
543
return pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08];
548
* Sets EIP of Hypervisor's Trap 08 (\#DF) TSS.
550
* @param pVM VM Handle.
551
* @param u32EIP EIP of Trap 08 handler.
553
SELMDECL(void) SELMSetTrap8EIP(PVM pVM, uint32_t u32EIP)
555
pVM->selm.s.TssTrap08.eip = u32EIP;
560
* Sets ss:esp for ring1 in main Hypervisor's TSS.
562
* @param pVM VM Handle.
563
* @param ss Ring1 SS register value.
564
* @param esp Ring1 ESP register value.
566
SELMDECL(void) SELMSetRing1Stack(PVM pVM, uint32_t ss, uint32_t esp)
568
pVM->selm.s.Tss.ss1 = ss;
569
pVM->selm.s.Tss.esp1 = esp;
574
* Gets ss:esp for ring1 in main Hypervisor's TSS.
576
* @returns VBox status code.
577
* @param pVM VM Handle.
578
* @param pSS Ring1 SS register value.
579
* @param pEsp Ring1 ESP register value.
581
SELMDECL(int) SELMGetRing1Stack(PVM pVM, uint32_t *pSS, uint32_t *pEsp)
583
if (pVM->selm.s.fSyncTSSRing0Stack)
585
GCPTRTYPE(uint8_t *) GCPtrTss = (GCPTRTYPE(uint8_t *))pVM->selm.s.GCPtrGuestTss;
589
Assert(pVM->selm.s.GCPtrGuestTss && pVM->selm.s.cbMonitoredGuestTss);
592
bool fTriedAlready = false;
595
rc = MMGCRamRead(pVM, &tss.ss0, GCPtrTss + RT_OFFSETOF(VBOXTSS, ss0), sizeof(tss.ss0));
596
rc |= MMGCRamRead(pVM, &tss.esp0, GCPtrTss + RT_OFFSETOF(VBOXTSS, esp0), sizeof(tss.esp0));
598
rc |= MMGCRamRead(pVM, &tss.offIoBitmap, GCPtrTss + RT_OFFSETOF(VBOXTSS, offIoBitmap), sizeof(tss.offIoBitmap));
601
if (VBOX_FAILURE(rc))
605
/* Shadow page might be out of sync. Sync and try again */
606
/** @todo might cross page boundary */
607
fTriedAlready = true;
608
rc = PGMPrefetchPage(pVM, GCPtrTss);
609
if (rc != VINF_SUCCESS)
613
AssertMsgFailed(("Unable to read TSS structure at %08X\n", GCPtrTss));
618
/* Reading too much. Could be cheaper than two seperate calls though. */
619
rc = PGMPhysReadGCPtr(pVM, &tss, GCPtrTss, sizeof(VBOXTSS));
620
if (VBOX_FAILURE(rc))
622
AssertReleaseMsgFailed(("Unable to read TSS structure at %08X\n", GCPtrTss));
628
uint32_t ssr0 = pVM->selm.s.Tss.ss1;
629
uint32_t espr0 = pVM->selm.s.Tss.esp1;
632
if (ssr0 != tss.ss0 || espr0 != tss.esp0)
633
Log(("SELMGetRing1Stack: Updating TSS ring 0 stack to %04X:%08X\n", tss.ss0, tss.esp0));
635
Log(("offIoBitmap=%#x\n", tss.offIoBitmap));
637
/* Update our TSS structure for the guest's ring 1 stack */
638
SELMSetRing1Stack(pVM, tss.ss0 | 1, tss.esp0);
639
pVM->selm.s.fSyncTSSRing0Stack = false;
642
*pSS = pVM->selm.s.Tss.ss1;
643
*pEsp = pVM->selm.s.Tss.esp1;
650
* Returns Guest TSS pointer
652
* @param pVM VM Handle.
654
SELMDECL(RTGCPTR) SELMGetGuestTSS(PVM pVM)
656
return (RTGCPTR)pVM->selm.s.GCPtrGuestTss;
661
* Validates a CS selector.
663
* @returns VBox status code.
664
* @param pSelInfo Pointer to the selector information for the CS selector.
665
* @param SelCPL The selector defining the CPL (SS).
667
SELMDECL(int) SELMSelInfoValidateCS(PCSELMSELINFO pSelInfo, RTSEL SelCPL)
672
if (pSelInfo->Raw.Gen.u1Present)
677
if ( pSelInfo->Raw.Gen.u1DescType == 1
678
&& (pSelInfo->Raw.Gen.u4Type & X86_SEL_TYPE_CODE))
683
unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, pSelInfo->Sel & X86_SEL_RPL);
684
if ( !(pSelInfo->Raw.Gen.u4Type & X86_SEL_TYPE_CONF)
685
? uLevel <= pSelInfo->Raw.Gen.u2Dpl
686
: uLevel >= pSelInfo->Raw.Gen.u2Dpl /* hope I got this right now... */
689
return VERR_INVALID_RPL;
691
return VERR_NOT_CODE_SELECTOR;
693
return VERR_SELECTOR_NOT_PRESENT;
698
* Gets the hypervisor code selector (CS).
699
* @returns CS selector.
700
* @param pVM The VM handle.
702
SELMDECL(RTSEL) SELMGetHyperCS(PVM pVM)
704
return pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS];
709
* Gets the 64-mode hypervisor code selector (CS64).
710
* @returns CS selector.
711
* @param pVM The VM handle.
713
SELMDECL(RTSEL) SELMGetHyperCS64(PVM pVM)
715
return pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64];
720
* Gets the hypervisor data selector (DS).
721
* @returns DS selector.
722
* @param pVM The VM handle.
724
SELMDECL(RTSEL) SELMGetHyperDS(PVM pVM)
726
return pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS];
731
* Gets the hypervisor TSS selector.
732
* @returns TSS selector.
733
* @param pVM The VM handle.
735
SELMDECL(RTSEL) SELMGetHyperTSS(PVM pVM)
737
return pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS];
742
* Gets the hypervisor TSS Trap 8 selector.
743
* @returns TSS Trap 8 selector.
744
* @param pVM The VM handle.
746
SELMDECL(RTSEL) SELMGetHyperTSSTrap08(PVM pVM)
748
return pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08];
753
* Gets the address for the hypervisor GDT.
755
* @returns The GDT address.
756
* @param pVM The VM handle.
757
* @remark This is intended only for very special use, like in the world
758
* switchers. Don't exploit this API!
760
SELMDECL(RTGCPTR) SELMGetHyperGDT(PVM pVM)
763
* Always convert this from the HC pointer since. We're can be
764
* called before the first relocation and have to work correctly
765
* without having dependencies on the relocation order.
767
return MMHyperHC2GC(pVM, pVM->selm.s.paGdtHC);
772
* Gets info about the current TSS.
774
* @returns VBox status code.
775
* @retval VINF_SUCCESS if we've got a TSS loaded.
776
* @retval VERR_SELM_NO_TSS if we haven't got a TSS (rather unlikely).
778
* @param pVM The VM handle.
779
* @param pGCPtrTss Where to store the TSS address.
780
* @param pcbTss Where to store the TSS size limit.
781
* @param pfCanHaveIOBitmap Where to store the can-have-I/O-bitmap indicator. (optional)
783
SELMDECL(int) SELMGetTSSInfo(PVM pVM, PRTGCUINTPTR pGCPtrTss, PRTGCUINTPTR pcbTss, bool *pfCanHaveIOBitmap)
785
if (!CPUMAreHiddenSelRegsValid(pVM))
788
* Do we have a valid TSS?
790
if ( pVM->selm.s.GCSelTss == (RTSEL)~0
791
|| !pVM->selm.s.fGuestTss32Bit)
792
return VERR_SELM_NO_TSS;
795
* Fill in return values.
797
*pGCPtrTss = (RTGCUINTPTR)pVM->selm.s.GCPtrGuestTss;
798
*pcbTss = pVM->selm.s.cbGuestTss;
799
if (pfCanHaveIOBitmap)
800
*pfCanHaveIOBitmap = pVM->selm.s.fGuestTss32Bit;
804
CPUMSELREGHID *pHiddenTRReg;
806
pHiddenTRReg = CPUMGetGuestTRHid(pVM);
808
*pGCPtrTss = pHiddenTRReg->u32Base;
809
*pcbTss = pHiddenTRReg->u32Limit;
811
if (pfCanHaveIOBitmap)
812
*pfCanHaveIOBitmap = pHiddenTRReg->Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_AVAIL
813
|| pHiddenTRReg->Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY;