VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp@ 92561

Last change on this file since 92561 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.1 KB
Line 
1/* $Id: TRPMAll.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * TRPM - Trap Monitor - Any Context.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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_TRPM
23#include <VBox/vmm/trpm.h>
24#include <VBox/vmm/pgm.h>
25#include <VBox/vmm/mm.h>
26#include <VBox/vmm/hm.h>
27#include <VBox/vmm/selm.h>
28#include <VBox/vmm/stam.h>
29#include <VBox/vmm/dbgf.h>
30#include "TRPMInternal.h"
31#include <VBox/vmm/vmcc.h>
32#include <VBox/err.h>
33#include <VBox/vmm/em.h>
34#include <VBox/log.h>
35#include <iprt/assert.h>
36#include <iprt/asm.h>
37#include <iprt/asm-amd64-x86.h>
38#include <iprt/param.h>
39#include <iprt/x86.h>
40
41
42
43/**
44 * Query info about the current active trap/interrupt.
45 * If no trap is active active an error code is returned.
46 *
47 * @returns VBox status code.
48 * @param pVCpu The cross context virtual CPU structure.
49 * @param pu8TrapNo Where to store the trap number.
50 * @param penmType Where to store the trap type
51 */
52VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *penmType)
53{
54 /*
55 * Check if we have a trap at present.
56 */
57 if (pVCpu->trpm.s.uActiveVector != ~0U)
58 {
59 if (pu8TrapNo)
60 *pu8TrapNo = (uint8_t)pVCpu->trpm.s.uActiveVector;
61 if (penmType)
62 *penmType = pVCpu->trpm.s.enmActiveType;
63 return VINF_SUCCESS;
64 }
65
66 return VERR_TRPM_NO_ACTIVE_TRAP;
67}
68
69
70/**
71 * Gets the trap number for the current trap.
72 *
73 * The caller is responsible for making sure there is an active trap which
74 * takes an error code when making this request.
75 *
76 * @returns The current trap number.
77 * @param pVCpu The cross context virtual CPU structure.
78 */
79VMMDECL(uint8_t) TRPMGetTrapNo(PVMCPU pVCpu)
80{
81 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
82 return (uint8_t)pVCpu->trpm.s.uActiveVector;
83}
84
85
86/**
87 * Gets the error code for the current trap.
88 *
89 * The caller is responsible for making sure there is an active trap which
90 * takes an error code when making this request.
91 *
92 * @returns Error code.
93 * @param pVCpu The cross context virtual CPU structure.
94 */
95VMMDECL(uint32_t) TRPMGetErrorCode(PVMCPU pVCpu)
96{
97 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
98#ifdef VBOX_STRICT
99 switch (pVCpu->trpm.s.uActiveVector)
100 {
101 case X86_XCPT_TS:
102 case X86_XCPT_NP:
103 case X86_XCPT_SS:
104 case X86_XCPT_GP:
105 case X86_XCPT_PF:
106 case X86_XCPT_AC:
107 case X86_XCPT_DF:
108 break;
109 default:
110 AssertMsgFailed(("This trap (%#x) doesn't have any error code\n", pVCpu->trpm.s.uActiveVector));
111 break;
112 }
113#endif
114 return pVCpu->trpm.s.uActiveErrorCode;
115}
116
117
118/**
119 * Gets the fault address for the current trap.
120 *
121 * The caller is responsible for making sure there is an active trap 0x0e when
122 * making this request.
123 *
124 * @returns Fault address associated with the trap.
125 * @param pVCpu The cross context virtual CPU structure.
126 */
127VMMDECL(RTGCUINTPTR) TRPMGetFaultAddress(PVMCPU pVCpu)
128{
129 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
130 AssertMsg(pVCpu->trpm.s.uActiveVector == X86_XCPT_PF, ("Not page-fault trap!\n"));
131 return pVCpu->trpm.s.uActiveCR2;
132}
133
134
135/**
136 * Gets the instruction-length for the current trap (only relevant for software
137 * interrupts and software exceptions \#BP and \#OF).
138 *
139 * The caller is responsible for making sure there is an active trap 0x0e when
140 * making this request.
141 *
142 * @returns Fault address associated with the trap.
143 * @param pVCpu The cross context virtual CPU structure.
144 */
145VMMDECL(uint8_t) TRPMGetInstrLength(PVMCPU pVCpu)
146{
147 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
148 return pVCpu->trpm.s.cbInstr;
149}
150
151
152/**
153 * Checks if the current \#DB exception is due to an INT1/ICEBP instruction.
154 *
155 * The caller is responsible for making sure there is an active trap.
156 *
157 * @returns @c true if it's due to INT1/ICEBP, @c false if not.
158 *
159 * @param pVCpu The cross context virtual CPU structure.
160 */
161VMMDECL(bool) TRPMIsTrapDueToIcebp(PVMCPU pVCpu)
162{
163 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
164 return pVCpu->trpm.s.fIcebp;
165}
166
167
168/**
169 * Clears the current active trap/exception/interrupt.
170 *
171 * The caller is responsible for making sure there is an active trap
172 * when making this request.
173 *
174 * @returns VBox status code.
175 * @param pVCpu The cross context virtual CPU structure.
176 */
177VMMDECL(int) TRPMResetTrap(PVMCPU pVCpu)
178{
179 /*
180 * Cannot reset non-existing trap!
181 */
182 if (pVCpu->trpm.s.uActiveVector == ~0U)
183 {
184 AssertMsgFailed(("No active trap!\n"));
185 return VERR_TRPM_NO_ACTIVE_TRAP;
186 }
187
188 /*
189 * Reset it.
190 */
191 pVCpu->trpm.s.uActiveVector = ~0U;
192 return VINF_SUCCESS;
193}
194
195
196/**
197 * Assert trap/exception/interrupt.
198 *
199 * The caller is responsible for making sure there is no active trap
200 * when making this request.
201 *
202 * @returns VBox status code.
203 * @param pVCpu The cross context virtual CPU structure.
204 * @param u8TrapNo The trap vector to assert.
205 * @param enmType Trap type.
206 */
207VMMDECL(int) TRPMAssertTrap(PVMCPUCC pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType)
208{
209 Log2(("TRPMAssertTrap: u8TrapNo=%02x type=%d\n", u8TrapNo, enmType));
210
211 /*
212 * Cannot assert a trap when one is already active.
213 */
214 if (pVCpu->trpm.s.uActiveVector != ~0U)
215 {
216 AssertMsgFailed(("CPU%d: Active trap %#x\n", pVCpu->idCpu, pVCpu->trpm.s.uActiveVector));
217 return VERR_TRPM_ACTIVE_TRAP;
218 }
219
220 pVCpu->trpm.s.uActiveVector = u8TrapNo;
221 pVCpu->trpm.s.enmActiveType = enmType;
222 pVCpu->trpm.s.uActiveErrorCode = ~0U;
223 pVCpu->trpm.s.uActiveCR2 = 0xdeadface;
224 pVCpu->trpm.s.cbInstr = UINT8_MAX;
225 pVCpu->trpm.s.fIcebp = false;
226 return VINF_SUCCESS;
227}
228
229
230/**
231 * Assert a page-fault exception.
232 *
233 * The caller is responsible for making sure there is no active trap
234 * when making this request.
235 *
236 * @returns VBox status code.
237 * @param pVCpu The cross context virtual CPU structure.
238 * @param uCR2 The new fault address.
239 * @param uErrorCode The error code for the page-fault.
240 */
241VMMDECL(int) TRPMAssertXcptPF(PVMCPUCC pVCpu, RTGCUINTPTR uCR2, uint32_t uErrorCode)
242{
243 Log2(("TRPMAssertXcptPF: uCR2=%RGv uErrorCode=%#RX32\n", uCR2, uErrorCode));
244
245 /*
246 * Cannot assert a trap when one is already active.
247 */
248 if (pVCpu->trpm.s.uActiveVector != ~0U)
249 {
250 AssertMsgFailed(("CPU%d: Active trap %#x\n", pVCpu->idCpu, pVCpu->trpm.s.uActiveVector));
251 return VERR_TRPM_ACTIVE_TRAP;
252 }
253
254 pVCpu->trpm.s.uActiveVector = X86_XCPT_PF;
255 pVCpu->trpm.s.enmActiveType = TRPM_TRAP;
256 pVCpu->trpm.s.uActiveErrorCode = uErrorCode;
257 pVCpu->trpm.s.uActiveCR2 = uCR2;
258 pVCpu->trpm.s.cbInstr = UINT8_MAX;
259 return VINF_SUCCESS;
260}
261
262
263/**
264 * Sets the error code of the current trap.
265 * (This function is for use in trap handlers and such.)
266 *
267 * The caller is responsible for making sure there is an active trap
268 * which takes an errorcode when making this request.
269 *
270 * @param pVCpu The cross context virtual CPU structure.
271 * @param uErrorCode The new error code.
272 */
273VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, uint32_t uErrorCode)
274{
275 Log2(("TRPMSetErrorCode: uErrorCode=%#RX32\n", uErrorCode));
276 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
277 AssertMsg( pVCpu->trpm.s.enmActiveType == TRPM_TRAP
278 || ( pVCpu->trpm.s.enmActiveType == TRPM_SOFTWARE_INT && pVCpu->trpm.s.uActiveVector == X86_XCPT_DB),
279 ("Not hardware exception or privileged software exception (INT1/ICEBP)!\n"));
280 pVCpu->trpm.s.uActiveErrorCode = uErrorCode;
281#ifdef VBOX_STRICT
282 if (pVCpu->trpm.s.enmActiveType == TRPM_TRAP)
283 {
284 switch (pVCpu->trpm.s.uActiveVector)
285 {
286 case X86_XCPT_TS: case X86_XCPT_NP: case X86_XCPT_SS: case X86_XCPT_GP: case X86_XCPT_PF:
287 AssertMsg(uErrorCode != ~0U, ("Invalid uErrorCode=%#x u8TrapNo=%u\n", uErrorCode, pVCpu->trpm.s.uActiveVector));
288 break;
289 case X86_XCPT_AC: case X86_XCPT_DF:
290 AssertMsg(uErrorCode == 0, ("Invalid uErrorCode=%#x u8TrapNo=%u\n", uErrorCode, pVCpu->trpm.s.uActiveVector));
291 break;
292 default:
293 AssertMsg(uErrorCode == ~0U, ("Invalid uErrorCode=%#x u8TrapNo=%u\n", uErrorCode, pVCpu->trpm.s.uActiveVector));
294 break;
295 }
296 }
297#endif
298}
299
300
301/**
302 * Sets the fault address of the current \#PF trap. (This function is for use in
303 * trap handlers and such.)
304 *
305 * The caller is responsible for making sure there is an active trap 0e
306 * when making this request.
307 *
308 * @param pVCpu The cross context virtual CPU structure.
309 * @param uCR2 The new fault address (cr2 register).
310 */
311VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2)
312{
313 Log2(("TRPMSetFaultAddress: uCR2=%RGv\n", uCR2));
314 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
315 AssertMsg(pVCpu->trpm.s.enmActiveType == TRPM_TRAP, ("Not hardware exception!\n"));
316 AssertMsg(pVCpu->trpm.s.uActiveVector == X86_XCPT_PF, ("Not trap 0e!\n"));
317 pVCpu->trpm.s.uActiveCR2 = uCR2;
318}
319
320
321/**
322 * Sets the instruction-length of the current trap (relevant for software
323 * interrupts and software exceptions like \#BP, \#OF).
324 *
325 * The caller is responsible for making sure there is an active trap when making
326 * this request.
327 *
328 * @param pVCpu The cross context virtual CPU structure.
329 * @param cbInstr The instruction length.
330 */
331VMMDECL(void) TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr)
332{
333 Log2(("TRPMSetInstrLength: cbInstr=%u\n", cbInstr));
334 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
335 AssertMsg( pVCpu->trpm.s.enmActiveType == TRPM_SOFTWARE_INT
336 || ( pVCpu->trpm.s.enmActiveType == TRPM_TRAP
337 && ( pVCpu->trpm.s.uActiveVector == X86_XCPT_BP
338 || pVCpu->trpm.s.uActiveVector == X86_XCPT_OF)),
339 ("Invalid trap type %#x\n", pVCpu->trpm.s.enmActiveType));
340 pVCpu->trpm.s.cbInstr = cbInstr;
341}
342
343
344/**
345 * Sets if the current \#DB exception is due to an INT1/ICEBP instruction.
346 *
347 * The caller is responsible for making sure there is an active trap and it's a
348 * \#DB.
349 *
350 * @param pVCpu The cross context virtual CPU structure.
351 */
352VMMDECL(void) TRPMSetTrapDueToIcebp(PVMCPU pVCpu)
353{
354 AssertMsg(pVCpu->trpm.s.enmActiveType == TRPM_SOFTWARE_INT, ("Trap type for INT1/ICEBP invalid!"));
355 AssertMsg(pVCpu->trpm.s.uActiveVector == X86_XCPT_DB, ("INT1/ICEBP must be indicated by a #DB!\n"));
356 pVCpu->trpm.s.fIcebp = true;
357}
358
359
360/**
361 * Checks if the current active trap/interrupt/exception/fault/whatever is a software
362 * interrupt or not.
363 *
364 * The caller is responsible for making sure there is an active trap
365 * when making this request.
366 *
367 * @returns true if software interrupt, false if not.
368 *
369 * @param pVCpu The cross context virtual CPU structure.
370 */
371VMMDECL(bool) TRPMIsSoftwareInterrupt(PVMCPU pVCpu)
372{
373 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
374 return (pVCpu->trpm.s.enmActiveType == TRPM_SOFTWARE_INT);
375}
376
377
378/**
379 * Check if there is an active trap.
380 *
381 * @returns true if trap active, false if not.
382 * @param pVCpu The cross context virtual CPU structure.
383 */
384VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu)
385{
386 return pVCpu->trpm.s.uActiveVector != ~0U;
387}
388
389
390/**
391 * Query all info about the current active trap/interrupt.
392 * If no trap is active active an error code is returned.
393 *
394 * @returns VBox status code.
395 * @param pVCpu The cross context virtual CPU structure.
396 * @param pu8TrapNo Where to store the trap number.
397 * @param pEnmType Where to store the trap type.
398 * @param puErrorCode Where to store the error code associated with some
399 * traps. ~0U is stored if the trap has no error code.
400 * @param puCR2 Where to store the CR2 associated with a trap 0E.
401 * @param pcbInstr Where to store the instruction-length associated with
402 * some traps.
403 * @param pfIcebp Where to store whether the trap is a \#DB caused by an
404 * INT1/ICEBP instruction.
405 */
406VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType, uint32_t *puErrorCode, PRTGCUINTPTR puCR2,
407 uint8_t *pcbInstr, bool *pfIcebp)
408{
409 /*
410 * Check if we have an active trap.
411 */
412 if (pVCpu->trpm.s.uActiveVector == ~0U)
413 return VERR_TRPM_NO_ACTIVE_TRAP;
414
415 if (pu8TrapNo)
416 *pu8TrapNo = (uint8_t)pVCpu->trpm.s.uActiveVector;
417 if (pEnmType)
418 *pEnmType = pVCpu->trpm.s.enmActiveType;
419 if (puErrorCode)
420 *puErrorCode = pVCpu->trpm.s.uActiveErrorCode;
421 if (puCR2)
422 *puCR2 = pVCpu->trpm.s.uActiveCR2;
423 if (pcbInstr)
424 *pcbInstr = pVCpu->trpm.s.cbInstr;
425 if (pfIcebp)
426 *pfIcebp = pVCpu->trpm.s.fIcebp;
427 return VINF_SUCCESS;
428}
429
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