summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/include/SELMInternal.h
blob: f5c0e023e390dda3d8d11db7349fc2e02984b1ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* $Id: SELMInternal.h $ */
/** @file
 * SELM - Internal header file.
 */

/*
 * Copyright (C) 2006-2012 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#ifndef ___SELMInternal_h
#define ___SELMInternal_h

#include <VBox/cdefs.h>
#include <VBox/types.h>
#include <VBox/vmm/stam.h>
#include <VBox/vmm/cpum.h>
#include <VBox/log.h>
#include <iprt/x86.h>



/** @defgroup grp_selm_int   Internals
 * @ingroup grp_selm
 * @internal
 * @{
 */

/** Enable or disable tracking of Shadow GDT/LDT/TSS.
 * @{
 */
#if defined(VBOX_WITH_RAW_MODE) || defined(DOXYGEN_RUNNING)
# define SELM_TRACK_SHADOW_GDT_CHANGES
# define SELM_TRACK_SHADOW_LDT_CHANGES
# define SELM_TRACK_SHADOW_TSS_CHANGES
#endif
/** @} */

/** Enable or disable tracking of Guest GDT/LDT/TSS.
 * @{
 */
#if defined(VBOX_WITH_RAW_MODE) || defined(DOXYGEN_RUNNING)
# define SELM_TRACK_GUEST_GDT_CHANGES
# define SELM_TRACK_GUEST_LDT_CHANGES
# define SELM_TRACK_GUEST_TSS_CHANGES
#endif
/** @} */


/** The number of GDTS allocated for our GDT. (full size) */
#define SELM_GDT_ELEMENTS                   8192

/** aHyperSel index to retrieve hypervisor selectors */
/** The Flat CS selector used by the VMM inside the GC. */
#define SELM_HYPER_SEL_CS                   0
/** The Flat DS selector used by the VMM inside the GC. */
#define SELM_HYPER_SEL_DS                   1
/** The 64-bit mode CS selector used by the VMM inside the GC. */
#define SELM_HYPER_SEL_CS64                 2
/** The TSS selector used by the VMM inside the GC. */
#define SELM_HYPER_SEL_TSS                  3
/** The TSS selector for taking trap 08 (\#DF). */
#define SELM_HYPER_SEL_TSS_TRAP08           4
/** Number of GDTs we need for internal use */
#define SELM_HYPER_SEL_MAX                  (SELM_HYPER_SEL_TSS_TRAP08 + 1)


/** Default GDT selectors we use for the hypervisor. */
#define SELM_HYPER_DEFAULT_SEL_CS           ((SELM_GDT_ELEMENTS - 0x1) << 3)
#define SELM_HYPER_DEFAULT_SEL_DS           ((SELM_GDT_ELEMENTS - 0x2) << 3)
#define SELM_HYPER_DEFAULT_SEL_CS64         ((SELM_GDT_ELEMENTS - 0x3) << 3)
#define SELM_HYPER_DEFAULT_SEL_TSS          ((SELM_GDT_ELEMENTS - 0x4) << 3)
#define SELM_HYPER_DEFAULT_SEL_TSS_TRAP08   ((SELM_GDT_ELEMENTS - 0x5) << 3)
/** The lowest value default we use. */
#define SELM_HYPER_DEFAULT_BASE             SELM_HYPER_DEFAULT_SEL_TSS_TRAP08

/**
 * Converts a SELM pointer into a VM pointer.
 * @returns Pointer to the VM structure the SELM is part of.
 * @param   pSELM   Pointer to SELM instance data.
 */
#define SELM2VM(pSELM)  ( (PVM)((char *)pSELM - pSELM->offVM) )



/**
 * SELM Data (part of VM)
 */
typedef struct SELM
{
    /** Offset to the VM structure.
     * See SELM2VM(). */
    RTINT                   offVM;

    /** Flat CS, DS, 64 bit mode CS, TSS & trap 8 TSS. */
    RTSEL                   aHyperSel[SELM_HYPER_SEL_MAX];

    /** Pointer to the GCs - R3 Ptr.
     * This size is governed by SELM_GDT_ELEMENTS. */
    R3PTRTYPE(PX86DESC)     paGdtR3;
    /** Pointer to the GCs - RC Ptr.
     * This is not initialized until the first relocation because it's used to
     * check if the shadow GDT virtual handler requires deregistration. */
    RCPTRTYPE(PX86DESC)     paGdtRC;
    /** Current (last) Guest's GDTR.
     * The pGdt member is set to RTRCPTR_MAX if we're not monitoring the guest GDT. */
    VBOXGDTR                GuestGdtr;
    /** The current (last) effective Guest GDT size. */
    RTUINT                  cbEffGuestGdtLimit;

    uint32_t                padding0;

    /** R3 pointer to the LDT shadow area in HMA. */
    R3PTRTYPE(void *)       pvLdtR3;
    /** RC pointer to the LDT shadow area in HMA. */
    RCPTRTYPE(void *)       pvLdtRC;
#if GC_ARCH_BITS == 64
    RTRCPTR                 padding1;
#endif
    /** The address of the guest LDT.
     * RTRCPTR_MAX if not monitored. */
    RTGCPTR                 GCPtrGuestLdt;
    /** Current LDT limit, both Guest and Shadow. */
    RTUINT                  cbLdtLimit;
    /** Current LDT offset relative to pvLdtR3/pvLdtRC. */
    RTUINT                  offLdtHyper;
#if HC_ARCH_BITS == 32 && GC_ARCH_BITS == 64
    uint32_t                padding2[2];
#endif
    /** TSS. (This is 16 byte aligned!)
      * @todo I/O bitmap & interrupt redirection table? */
    VBOXTSS                 Tss;

    /** TSS for trap 08 (\#DF). */
    VBOXTSS                 TssTrap08;

    /** Monitored shadow TSS address. */
    RCPTRTYPE(void *)       pvMonShwTssRC;
#if GC_ARCH_BITS == 64
    RTRCPTR                 padding3;
#endif
    /** GC Pointer to the current Guest's TSS.
     * RTRCPTR_MAX if not monitored. */
    RTGCPTR                 GCPtrGuestTss;
    /** The size of the guest TSS. */
    RTUINT                  cbGuestTss;
    /** Set if it's a 32-bit TSS. */
    bool                    fGuestTss32Bit;
    /** The size of the Guest's TSS part we're monitoring. */
    RTUINT                  cbMonitoredGuestTss;
    /** The guest TSS selector at last sync (part of monitoring).
     * Contains RTSEL_MAX if not set. */
    RTSEL                   GCSelTss;
    /** The last known offset of the I/O bitmap.
     * This is only used if we monitor the bitmap. */
    uint16_t                offGuestIoBitmap;

    /** Indicates that the Guest GDT access handler have been registered. */
    bool                    fGDTRangeRegistered;

    /** Indicates whether the TSS stack selector & base address need to be refreshed.  */
    bool                    fSyncTSSRing0Stack;
    bool                    fPadding2[4];

    /** SELMR3UpdateFromCPUM() profiling. */
    STAMPROFILE             StatUpdateFromCPUM;
    /** SELMR3SyncTSS() profiling. */
    STAMPROFILE             StatTSSSync;

    /** GC: The number of handled writes to the Guest's GDT. */
    STAMCOUNTER             StatRCWriteGuestGDTHandled;
    /** GC: The number of unhandled write to the Guest's GDT. */
    STAMCOUNTER             StatRCWriteGuestGDTUnhandled;
    /** GC: The number of times writes to Guest's LDT was detected. */
    STAMCOUNTER             StatRCWriteGuestLDT;
    /** GC: The number of handled writes to the Guest's TSS. */
    STAMCOUNTER             StatRCWriteGuestTSSHandled;
    /** GC: The number of handled writes to the Guest's TSS where we detected a change. */
    STAMCOUNTER             StatRCWriteGuestTSSHandledChanged;
    /** GC: The number of handled redir writes to the Guest's TSS where we detected a change. */
    STAMCOUNTER             StatRCWriteGuestTSSRedir;
    /** GC: The number of unhandled writes to the Guest's TSS. */
    STAMCOUNTER             StatRCWriteGuestTSSUnhandled;
    /** The number of times we had to relocate our hypervisor selectors. */
    STAMCOUNTER             StatHyperSelsChanged;
    /** The number of times we had find free hypervisor selectors. */
    STAMCOUNTER             StatScanForHyperSels;
    /** Counts the times we detected state selectors in SELMR3UpdateFromCPUM. */
    STAMCOUNTER             aStatDetectedStaleSReg[X86_SREG_COUNT];
    /** Counts the times we were called with already state selectors in
     * SELMR3UpdateFromCPUM. */
    STAMCOUNTER             aStatAlreadyStaleSReg[X86_SREG_COUNT];
    /** Counts the times we found a stale selector becomming valid again. */
    STAMCOUNTER             StatStaleToUnstaleSReg;
#ifdef VBOX_WITH_STATISTICS
    /** Times we updated hidden selector registers in CPUMR3UpdateFromCPUM. */
    STAMCOUNTER             aStatUpdatedSReg[X86_SREG_COUNT];
    STAMCOUNTER             StatLoadHidSelGst;
    STAMCOUNTER             StatLoadHidSelShw;
#endif
    STAMCOUNTER             StatLoadHidSelReadErrors;
    STAMCOUNTER             StatLoadHidSelGstNoGood;
} SELM, *PSELM;

RT_C_DECLS_BEGIN

VMMRCDECL(int) selmRCGuestGDTWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
VMMRCDECL(int) selmRCGuestLDTWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
VMMRCDECL(int) selmRCGuestTSSWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);

VMMRCDECL(int) selmRCShadowGDTWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
VMMRCDECL(int) selmRCShadowLDTWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
VMMRCDECL(int) selmRCShadowTSSWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);

void           selmSetRing1Stack(PVM pVM, uint32_t ss, RTGCPTR32 esp);
#ifdef VBOX_WITH_RAW_RING1
void           selmSetRing2Stack(PVM pVM, uint32_t ss, RTGCPTR32 esp);
#endif

RT_C_DECLS_END

/** @} */

#endif