VirtualBox

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

Last change on this file since 95085 was 93725, checked in by vboxsync, 3 years ago

VMM: More arm64 adjustments. bugref:9898

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