VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp@ 73009

Last change on this file since 73009 was 72967, checked in by vboxsync, 6 years ago

VMM/HMSVM: bugref:9193 Stop passing pCtx around and use pVCpu->cpum.GstCtx instead where possible.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.7 KB
Line 
1/* $Id: HMSVMAll.cpp 72967 2018-07-08 10:38:08Z vboxsync $ */
2/** @file
3 * HM SVM (AMD-V) - All contexts.
4 */
5
6/*
7 * Copyright (C) 2017 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_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include "HMInternal.h"
25#include <VBox/vmm/apic.h>
26#include <VBox/vmm/gim.h>
27#include <VBox/vmm/hm.h>
28#include <VBox/vmm/iem.h>
29#include <VBox/vmm/vm.h>
30#include <VBox/vmm/hm_svm.h>
31
32
33#ifndef IN_RC
34
35/**
36 * Emulates a simple MOV TPR (CR8) instruction.
37 *
38 * Used for TPR patching on 32-bit guests. This simply looks up the patch record
39 * at EIP and does the required.
40 *
41 * This VMMCALL is used a fallback mechanism when mov to/from cr8 isn't exactly
42 * like how we want it to be (e.g. not followed by shr 4 as is usually done for
43 * TPR). See hmR3ReplaceTprInstr() for the details.
44 *
45 * @returns VBox status code.
46 * @retval VINF_SUCCESS if the access was handled successfully, RIP + RFLAGS updated.
47 * @retval VERR_NOT_FOUND if no patch record for this RIP could be found.
48 * @retval VERR_SVM_UNEXPECTED_PATCH_TYPE if the found patch type is invalid.
49 *
50 * @param pVCpu The cross context virtual CPU structure.
51 * @param pCtx Pointer to the guest-CPU context.
52 */
53int hmSvmEmulateMovTpr(PVMCPU pVCpu)
54{
55 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
56 Log4(("Emulated VMMCall TPR access replacement at RIP=%RGv\n", pCtx->rip));
57
58 /*
59 * We do this in a loop as we increment the RIP after a successful emulation
60 * and the new RIP may be a patched instruction which needs emulation as well.
61 */
62 bool fPatchFound = false;
63 PVM pVM = pVCpu->CTX_SUFF(pVM);
64 for (;;)
65 {
66 PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
67 if (!pPatch)
68 break;
69 fPatchFound = true;
70
71 uint8_t u8Tpr;
72 switch (pPatch->enmType)
73 {
74 case HMTPRINSTR_READ:
75 {
76 bool fPending;
77 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPending, NULL /* pu8PendingIrq */);
78 AssertRC(rc);
79
80 rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pPatch->uDstOperand, u8Tpr);
81 AssertRC(rc);
82 pCtx->rip += pPatch->cbOp;
83 pCtx->eflags.Bits.u1RF = 0;
84 break;
85 }
86
87 case HMTPRINSTR_WRITE_REG:
88 case HMTPRINSTR_WRITE_IMM:
89 {
90 if (pPatch->enmType == HMTPRINSTR_WRITE_REG)
91 {
92 uint32_t u32Val;
93 int rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pPatch->uSrcOperand, &u32Val);
94 AssertRC(rc);
95 u8Tpr = u32Val;
96 }
97 else
98 u8Tpr = (uint8_t)pPatch->uSrcOperand;
99
100 int rc2 = APICSetTpr(pVCpu, u8Tpr);
101 AssertRC(rc2);
102 pCtx->rip += pPatch->cbOp;
103 pCtx->eflags.Bits.u1RF = 0;
104 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR
105 | HM_CHANGED_GUEST_RIP
106 | HM_CHANGED_GUEST_RFLAGS);
107 break;
108 }
109
110 default:
111 {
112 AssertMsgFailed(("Unexpected patch type %d\n", pPatch->enmType));
113 pVCpu->hm.s.u32HMError = pPatch->enmType;
114 return VERR_SVM_UNEXPECTED_PATCH_TYPE;
115 }
116 }
117 }
118
119 return fPatchFound ? VINF_SUCCESS : VERR_NOT_FOUND;
120}
121
122#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
123/**
124 * Notification callback for when a \#VMEXIT happens outside SVM R0 code (e.g.
125 * in IEM).
126 *
127 * @param pVCpu The cross context virtual CPU structure.
128 * @param pCtx Pointer to the guest-CPU context.
129 *
130 * @sa hmR0SvmVmRunCacheVmcb.
131 */
132VMM_INT_DECL(void) HMSvmNstGstVmExitNotify(PVMCPU pVCpu, PCPUMCTX pCtx)
133{
134 PSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
135 if (pVmcbNstGstCache->fCacheValid)
136 {
137 /*
138 * Restore fields as our own code might look at the VMCB controls as part
139 * of the #VMEXIT handling in IEM. Otherwise, strictly speaking we don't need to
140 * restore these fields because currently none of them are written back to memory
141 * by a physical CPU on #VMEXIT.
142 */
143 PSVMVMCBCTRL pVmcbNstGstCtrl = &pCtx->hwvirt.svm.CTX_SUFF(pVmcb)->ctrl;
144 pVmcbNstGstCtrl->u16InterceptRdCRx = pVmcbNstGstCache->u16InterceptRdCRx;
145 pVmcbNstGstCtrl->u16InterceptWrCRx = pVmcbNstGstCache->u16InterceptWrCRx;
146 pVmcbNstGstCtrl->u16InterceptRdDRx = pVmcbNstGstCache->u16InterceptRdDRx;
147 pVmcbNstGstCtrl->u16InterceptWrDRx = pVmcbNstGstCache->u16InterceptWrDRx;
148 pVmcbNstGstCtrl->u16PauseFilterThreshold = pVmcbNstGstCache->u16PauseFilterThreshold;
149 pVmcbNstGstCtrl->u16PauseFilterCount = pVmcbNstGstCache->u16PauseFilterCount;
150 pVmcbNstGstCtrl->u32InterceptXcpt = pVmcbNstGstCache->u32InterceptXcpt;
151 pVmcbNstGstCtrl->u64InterceptCtrl = pVmcbNstGstCache->u64InterceptCtrl;
152 pVmcbNstGstCtrl->u64TSCOffset = pVmcbNstGstCache->u64TSCOffset;
153 pVmcbNstGstCtrl->IntCtrl.n.u1VIntrMasking = pVmcbNstGstCache->fVIntrMasking;
154 pVmcbNstGstCtrl->NestedPagingCtrl.n.u1NestedPaging = pVmcbNstGstCache->fNestedPaging;
155 pVmcbNstGstCtrl->LbrVirt.n.u1LbrVirt = pVmcbNstGstCache->fLbrVirt;
156 pVmcbNstGstCache->fCacheValid = false;
157 }
158
159 /*
160 * Transitions to ring-3 flag a full CPU-state change except if we transition to ring-3
161 * in response to a physical CPU interrupt as no changes to the guest-CPU state are
162 * expected (see VINF_EM_RAW_INTERRUPT handling in hmR0SvmExitToRing3).
163 *
164 * However, with nested-guests, the state -can- change on trips to ring-3 for we might
165 * try to inject a nested-guest physical interrupt and cause a SVM_EXIT_INTR #VMEXIT for
166 * the nested-guest from ring-3. Hence we signal the required CPU state change here.
167 */
168 /** @todo Figure out why using HM_CHANGED_SVM_VMEXIT_MASK instead of
169 * HM_CHANGED_ALL_GUEST breaks nested guests (XP Pro, DSL etc.), see also
170 * hmR0SvmHandleExitNested(). */
171 AssertMsg(!(pVCpu->cpum.GstCtx.fExtrn & IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK),
172 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", pVCpu->cpum.GstCtx.fExtrn, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK));
173 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
174}
175#endif
176
177/**
178 * Checks if the Virtual GIF (Global Interrupt Flag) feature is supported and
179 * enabled for the VM.
180 *
181 * @returns @c true if VGIF is enabled, @c false otherwise.
182 * @param pVM The cross context VM structure.
183 *
184 * @remarks This value returned by this functions is expected by the callers not
185 * to change throughout the lifetime of the VM.
186 */
187VMM_INT_DECL(bool) HMSvmIsVGifActive(PVM pVM)
188{
189 bool const fVGif = RT_BOOL(pVM->hm.s.svm.u32Features & X86_CPUID_SVM_FEATURE_EDX_VGIF);
190 bool const fUseVGif = fVGif && pVM->hm.s.svm.fVGif;
191
192 return HMIsEnabled(pVM) && fVGif && fUseVGif;
193}
194
195
196/**
197 * Applies the TSC offset of an SVM nested-guest if any and returns the new TSC
198 * value for the nested-guest.
199 *
200 * @returns The TSC offset after applying any nested-guest TSC offset.
201 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
202 * @param uTicks The guest TSC.
203 *
204 * @remarks This function looks at the VMCB cache rather than directly at the
205 * nested-guest VMCB. The latter may have been modified for executing
206 * using hardware-assisted SVM.
207 *
208 * @note If you make any changes to this function, please check if
209 * hmR0SvmNstGstUndoTscOffset() needs adjusting.
210 *
211 * @sa CPUMApplyNestedGuestTscOffset(), hmR0SvmNstGstUndoTscOffset().
212 */
213VMM_INT_DECL(uint64_t) HMSvmNstGstApplyTscOffset(PVMCPU pVCpu, uint64_t uTicks)
214{
215 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
216 Assert(CPUMIsGuestInSvmNestedHwVirtMode(pCtx)); RT_NOREF(pCtx);
217 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
218 Assert(pVmcbNstGstCache->fCacheValid);
219 return uTicks + pVmcbNstGstCache->u64TSCOffset;
220}
221
222
223/**
224 * Interface used by IEM to handle patched TPR accesses.
225 *
226 * @returns VBox status code
227 * @retval VINF_SUCCESS if hypercall was handled, RIP + RFLAGS all dealt with.
228 * @retval VERR_NOT_FOUND if hypercall was _not_ handled.
229 * @retval VERR_SVM_UNEXPECTED_PATCH_TYPE on IPE.
230 *
231 * @param pVCpu The cross context virtual CPU structure.
232 */
233VMM_INT_DECL(int) HMHCSvmMaybeMovTprHypercall(PVMCPU pVCpu)
234{
235 PVM pVM = pVCpu->CTX_SUFF(pVM);
236 if (pVM->hm.s.fTprPatchingAllowed)
237 {
238 int rc = hmSvmEmulateMovTpr(pVCpu);
239 if (RT_SUCCESS(rc))
240 return VINF_SUCCESS;
241 return rc;
242 }
243 return VERR_NOT_FOUND;
244}
245
246#endif /* !IN_RC */
247
248/**
249 * Converts an SVM event type to a TRPM event type.
250 *
251 * @returns The TRPM event type.
252 * @retval TRPM_32BIT_HACK if the specified type of event isn't among the set
253 * of recognized trap types.
254 *
255 * @param pEvent Pointer to the SVM event.
256 */
257VMM_INT_DECL(TRPMEVENT) HMSvmEventToTrpmEventType(PCSVMEVENT pEvent)
258{
259 uint8_t const uType = pEvent->n.u3Type;
260 switch (uType)
261 {
262 case SVM_EVENT_EXTERNAL_IRQ: return TRPM_HARDWARE_INT;
263 case SVM_EVENT_SOFTWARE_INT: return TRPM_SOFTWARE_INT;
264 case SVM_EVENT_EXCEPTION:
265 case SVM_EVENT_NMI: return TRPM_TRAP;
266 default:
267 break;
268 }
269 AssertMsgFailed(("HMSvmEventToTrpmEvent: Invalid pending-event type %#x\n", uType));
270 return TRPM_32BIT_HACK;
271}
272
273
274/**
275 * Gets the MSR permission bitmap byte and bit offset for the specified MSR.
276 *
277 * @returns VBox status code.
278 * @param idMsr The MSR being requested.
279 * @param pbOffMsrpm Where to store the byte offset in the MSR permission
280 * bitmap for @a idMsr.
281 * @param puMsrpmBit Where to store the bit offset starting at the byte
282 * returned in @a pbOffMsrpm.
283 */
284VMM_INT_DECL(int) HMSvmGetMsrpmOffsetAndBit(uint32_t idMsr, uint16_t *pbOffMsrpm, uint8_t *puMsrpmBit)
285{
286 Assert(pbOffMsrpm);
287 Assert(puMsrpmBit);
288
289 /*
290 * MSRPM Layout:
291 * Byte offset MSR range
292 * 0x000 - 0x7ff 0x00000000 - 0x00001fff
293 * 0x800 - 0xfff 0xc0000000 - 0xc0001fff
294 * 0x1000 - 0x17ff 0xc0010000 - 0xc0011fff
295 * 0x1800 - 0x1fff Reserved
296 *
297 * Each MSR is represented by 2 permission bits (read and write).
298 */
299 if (idMsr <= 0x00001fff)
300 {
301 /* Pentium-compatible MSRs. */
302 uint32_t const bitoffMsr = idMsr << 1;
303 *pbOffMsrpm = bitoffMsr >> 3;
304 *puMsrpmBit = bitoffMsr & 7;
305 return VINF_SUCCESS;
306 }
307
308 if ( idMsr >= 0xc0000000
309 && idMsr <= 0xc0001fff)
310 {
311 /* AMD Sixth Generation x86 Processor MSRs. */
312 uint32_t const bitoffMsr = (idMsr - 0xc0000000) << 1;
313 *pbOffMsrpm = 0x800 + (bitoffMsr >> 3);
314 *puMsrpmBit = bitoffMsr & 7;
315 return VINF_SUCCESS;
316 }
317
318 if ( idMsr >= 0xc0010000
319 && idMsr <= 0xc0011fff)
320 {
321 /* AMD Seventh and Eighth Generation Processor MSRs. */
322 uint32_t const bitoffMsr = (idMsr - 0xc0010000) << 1;
323 *pbOffMsrpm = 0x1000 + (bitoffMsr >> 3);
324 *puMsrpmBit = bitoffMsr & 7;
325 return VINF_SUCCESS;
326 }
327
328 *pbOffMsrpm = 0;
329 *puMsrpmBit = 0;
330 return VERR_OUT_OF_RANGE;
331}
332
333
334/**
335 * Determines whether an IOIO intercept is active for the nested-guest or not.
336 *
337 * @param pvIoBitmap Pointer to the nested-guest IO bitmap.
338 * @param u16Port The IO port being accessed.
339 * @param enmIoType The type of IO access.
340 * @param cbReg The IO operand size in bytes.
341 * @param cAddrSizeBits The address size bits (for 16, 32 or 64).
342 * @param iEffSeg The effective segment number.
343 * @param fRep Whether this is a repeating IO instruction (REP prefix).
344 * @param fStrIo Whether this is a string IO instruction.
345 * @param pIoExitInfo Pointer to the SVMIOIOEXITINFO struct to be filled.
346 * Optional, can be NULL.
347 */
348VMM_INT_DECL(bool) HMSvmIsIOInterceptActive(void *pvIoBitmap, uint16_t u16Port, SVMIOIOTYPE enmIoType, uint8_t cbReg,
349 uint8_t cAddrSizeBits, uint8_t iEffSeg, bool fRep, bool fStrIo,
350 PSVMIOIOEXITINFO pIoExitInfo)
351{
352 Assert(cAddrSizeBits == 16 || cAddrSizeBits == 32 || cAddrSizeBits == 64);
353 Assert(cbReg == 1 || cbReg == 2 || cbReg == 4 || cbReg == 8);
354
355 /*
356 * The IOPM layout:
357 * Each bit represents one 8-bit port. That makes a total of 0..65535 bits or
358 * two 4K pages.
359 *
360 * For IO instructions that access more than a single byte, the permission bits
361 * for all bytes are checked; if any bit is set to 1, the IO access is intercepted.
362 *
363 * Since it's possible to do a 32-bit IO access at port 65534 (accessing 4 bytes),
364 * we need 3 extra bits beyond the second 4K page.
365 */
366 static const uint16_t s_auSizeMasks[] = { 0, 1, 3, 0, 0xf, 0, 0, 0 };
367
368 uint16_t const offIopm = u16Port >> 3;
369 uint16_t const fSizeMask = s_auSizeMasks[(cAddrSizeBits >> SVM_IOIO_OP_SIZE_SHIFT) & 7];
370 uint8_t const cShift = u16Port - (offIopm << 3);
371 uint16_t const fIopmMask = (1 << cShift) | (fSizeMask << cShift);
372
373 uint8_t const *pbIopm = (uint8_t *)pvIoBitmap;
374 Assert(pbIopm);
375 pbIopm += offIopm;
376 uint16_t const u16Iopm = *(uint16_t *)pbIopm;
377 if (u16Iopm & fIopmMask)
378 {
379 if (pIoExitInfo)
380 {
381 static const uint32_t s_auIoOpSize[] =
382 { SVM_IOIO_32_BIT_OP, SVM_IOIO_8_BIT_OP, SVM_IOIO_16_BIT_OP, 0, SVM_IOIO_32_BIT_OP, 0, 0, 0 };
383
384 static const uint32_t s_auIoAddrSize[] =
385 { 0, SVM_IOIO_16_BIT_ADDR, SVM_IOIO_32_BIT_ADDR, 0, SVM_IOIO_64_BIT_ADDR, 0, 0, 0 };
386
387 pIoExitInfo->u = s_auIoOpSize[cbReg & 7];
388 pIoExitInfo->u |= s_auIoAddrSize[(cAddrSizeBits >> 4) & 7];
389 pIoExitInfo->n.u1Str = fStrIo;
390 pIoExitInfo->n.u1Rep = fRep;
391 pIoExitInfo->n.u3Seg = iEffSeg & 7;
392 pIoExitInfo->n.u1Type = enmIoType;
393 pIoExitInfo->n.u16Port = u16Port;
394 }
395 return true;
396 }
397
398 /** @todo remove later (for debugging as VirtualBox always traps all IO
399 * intercepts). */
400 AssertMsgFailed(("iemSvmHandleIOIntercept: We expect an IO intercept here!\n"));
401 return false;
402}
403
404
405/**
406 * Returns whether HM has cached the nested-guest VMCB.
407 *
408 * If the VMCB is cached by HM, it means HM may have potentially modified the
409 * VMCB for execution using hardware-assisted SVM.
410 *
411 * @returns true if HM has cached the nested-guest VMCB, false otherwise.
412 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
413 */
414VMM_INT_DECL(bool) HMHasGuestSvmVmcbCached(PVMCPU pVCpu)
415{
416 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
417 return pVmcbNstGstCache->fCacheValid;
418}
419
420
421/**
422 * Checks if the nested-guest VMCB has the specified ctrl/instruction intercept
423 * active.
424 *
425 * @returns @c true if in intercept is set, @c false otherwise.
426 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
427 * @param fIntercept The SVM control/instruction intercept, see
428 * SVM_CTRL_INTERCEPT_*.
429 */
430VMM_INT_DECL(bool) HMIsGuestSvmCtrlInterceptSet(PVMCPU pVCpu, uint64_t fIntercept)
431{
432 Assert(HMHasGuestSvmVmcbCached(pVCpu));
433 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
434 return RT_BOOL(pVmcbNstGstCache->u64InterceptCtrl & fIntercept);
435}
436
437
438/**
439 * Checks if the nested-guest VMCB has the specified CR read intercept active.
440 *
441 * @returns @c true if in intercept is set, @c false otherwise.
442 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
443 * @param uCr The CR register number (0 to 15).
444 */
445VMM_INT_DECL(bool) HMIsGuestSvmReadCRxInterceptSet(PVMCPU pVCpu, uint8_t uCr)
446{
447 Assert(uCr < 16);
448 Assert(HMHasGuestSvmVmcbCached(pVCpu));
449 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
450 return RT_BOOL(pVmcbNstGstCache->u16InterceptRdCRx & (1 << uCr));
451}
452
453
454/**
455 * Checks if the nested-guest VMCB has the specified CR write intercept active.
456 *
457 * @returns @c true if in intercept is set, @c false otherwise.
458 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
459 * @param uCr The CR register number (0 to 15).
460 */
461VMM_INT_DECL(bool) HMIsGuestSvmWriteCRxInterceptSet(PVMCPU pVCpu, uint8_t uCr)
462{
463 Assert(uCr < 16);
464 Assert(HMHasGuestSvmVmcbCached(pVCpu));
465 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
466 return RT_BOOL(pVmcbNstGstCache->u16InterceptWrCRx & (1 << uCr));
467}
468
469
470/**
471 * Checks if the nested-guest VMCB has the specified DR read intercept active.
472 *
473 * @returns @c true if in intercept is set, @c false otherwise.
474 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
475 * @param uDr The DR register number (0 to 15).
476 */
477VMM_INT_DECL(bool) HMIsGuestSvmReadDRxInterceptSet(PVMCPU pVCpu, uint8_t uDr)
478{
479 Assert(uDr < 16);
480 Assert(HMHasGuestSvmVmcbCached(pVCpu));
481 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
482 return RT_BOOL(pVmcbNstGstCache->u16InterceptRdDRx & (1 << uDr));
483}
484
485
486/**
487 * Checks if the nested-guest VMCB has the specified DR write intercept active.
488 *
489 * @returns @c true if in intercept is set, @c false otherwise.
490 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
491 * @param uDr The DR register number (0 to 15).
492 */
493VMM_INT_DECL(bool) HMIsGuestSvmWriteDRxInterceptSet(PVMCPU pVCpu, uint8_t uDr)
494{
495 Assert(uDr < 16);
496 Assert(HMHasGuestSvmVmcbCached(pVCpu));
497 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
498 return RT_BOOL(pVmcbNstGstCache->u16InterceptWrDRx & (1 << uDr));
499}
500
501
502/**
503 * Checks if the nested-guest VMCB has the specified exception intercept active.
504 *
505 * @returns true if in intercept is active, false otherwise.
506 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
507 * @param uVector The exception / interrupt vector.
508 */
509VMM_INT_DECL(bool) HMIsGuestSvmXcptInterceptSet(PVMCPU pVCpu, uint8_t uVector)
510{
511 Assert(uVector < 32);
512 Assert(HMHasGuestSvmVmcbCached(pVCpu));
513 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
514 return RT_BOOL(pVmcbNstGstCache->u32InterceptXcpt & (1 << uVector));
515}
516
517
518/**
519 * Checks if the nested-guest VMCB has virtual-interrupts masking enabled.
520 *
521 * @returns true if virtual-interrupts are masked, @c false otherwise.
522 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
523 */
524VMM_INT_DECL(bool) HMIsGuestSvmVirtIntrMasking(PVMCPU pVCpu)
525{
526 Assert(HMHasGuestSvmVmcbCached(pVCpu));
527 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
528 return pVmcbNstGstCache->fVIntrMasking;
529}
530
531
532/**
533 * Checks if the nested-guest VMCB has nested-paging enabled.
534 *
535 * @returns true if nested-paging is enabled, @c false otherwise.
536 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
537 */
538VMM_INT_DECL(bool) HMIsGuestSvmNestedPagingEnabled(PVMCPU pVCpu)
539{
540 Assert(HMHasGuestSvmVmcbCached(pVCpu));
541 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
542 return pVmcbNstGstCache->fNestedPaging;
543}
544
545
546/**
547 * Returns the nested-guest VMCB pause-filter count.
548 *
549 * @returns The pause-filter count.
550 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
551 */
552VMM_INT_DECL(uint16_t) HMGetGuestSvmPauseFilterCount(PVMCPU pVCpu)
553{
554 Assert(HMHasGuestSvmVmcbCached(pVCpu));
555 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
556 return pVmcbNstGstCache->u16PauseFilterCount;
557}
558
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