VirtualBox

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

Last change on this file since 72515 was 72462, checked in by vboxsync, 7 years ago

EM,IEM,HM: Consolidated VMMHypercallsDisable/VMMHypercallsEnable into EMSetHypercallInstructionsEnabled and made the information available thru EMAreHypercallInstructionsEnabled(). Adjusted the vmmcall implementation so it works without HM. bugref:9044

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