VirtualBox

source: vbox/trunk/src/VBox/VMM/include/NEMInternal.h@ 106443

Last change on this file since 106443 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.6 KB
Line 
1/* $Id: NEMInternal.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * NEM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2018-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef VMM_INCLUDED_SRC_include_NEMInternal_h
29#define VMM_INCLUDED_SRC_include_NEMInternal_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/cdefs.h>
35#include <VBox/types.h>
36#include <VBox/vmm/nem.h>
37#include <VBox/vmm/cpum.h> /* For CPUMCPUVENDOR. */
38#include <VBox/vmm/stam.h>
39#include <VBox/vmm/vmapi.h>
40#ifdef RT_OS_WINDOWS
41#include <iprt/nt/hyperv.h>
42#include <iprt/critsect.h>
43#elif defined(RT_OS_DARWIN)
44# if defined(VBOX_VMM_TARGET_ARMV8)
45# include <Hypervisor/Hypervisor.h>
46# else
47# include "VMXInternal.h"
48# endif
49#endif
50
51RT_C_DECLS_BEGIN
52
53
54/** @defgroup grp_nem_int Internal
55 * @ingroup grp_nem
56 * @internal
57 * @{
58 */
59
60#if defined(VBOX_WITH_NATIVE_NEM) && !defined(VBOX_WITH_PGM_NEM_MODE)
61# error "VBOX_WITH_NATIVE_NEM requires VBOX_WITH_PGM_NEM_MODE to be defined"
62#endif
63
64
65#ifdef RT_OS_WINDOWS
66/*
67 * Windows: Code configuration.
68 */
69/* nothing at the moment */
70
71/**
72 * Windows VID I/O control information.
73 */
74typedef struct NEMWINIOCTL
75{
76 /** The I/O control function number. */
77 uint32_t uFunction;
78 uint32_t cbInput;
79 uint32_t cbOutput;
80} NEMWINIOCTL;
81
82/** @name Windows: Our two-bit physical page state for PGMPAGE
83 * @{ */
84# define NEM_WIN_PAGE_STATE_NOT_SET 0
85# define NEM_WIN_PAGE_STATE_UNMAPPED 1
86# define NEM_WIN_PAGE_STATE_READABLE 2
87# define NEM_WIN_PAGE_STATE_WRITABLE 3
88/** @} */
89
90/** Windows: Checks if a_GCPhys is subject to the limited A20 gate emulation. */
91# define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys) ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)
92/** Windows: Checks if a_GCPhys is relevant to the limited A20 gate emulation. */
93# define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys) \
94 ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )
95
96/** The CPUMCTX_EXTRN_XXX mask for IEM. */
97# define NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM ( IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_INHIBIT_INT \
98 | CPUMCTX_EXTRN_INHIBIT_NMI )
99/** The CPUMCTX_EXTRN_XXX mask for IEM when raising exceptions. */
100# define NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT (IEM_CPUMCTX_EXTRN_XCPT_MASK | NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM)
101
102/** @name Windows: Interrupt window flags (NEM_WIN_INTW_F_XXX).
103 * @{ */
104# define NEM_WIN_INTW_F_NMI UINT8_C(0x01)
105# define NEM_WIN_INTW_F_REGULAR UINT8_C(0x02)
106# define NEM_WIN_INTW_F_PRIO_MASK UINT8_C(0x3c)
107# define NEM_WIN_INTW_F_PRIO_SHIFT 2
108/** @} */
109
110#endif /* RT_OS_WINDOWS */
111
112
113#ifdef RT_OS_DARWIN
114# if !defined(VBOX_VMM_TARGET_ARMV8)
115/** vCPU ID declaration to avoid dragging in HV headers here. */
116typedef unsigned hv_vcpuid_t;
117/** The HV VM memory space ID (ASID). */
118typedef unsigned hv_vm_space_t;
119# endif
120
121
122/** @name Darwin: Our two-bit physical page state for PGMPAGE
123 * @{ */
124# define NEM_DARWIN_PAGE_STATE_UNMAPPED 0
125# define NEM_DARWIN_PAGE_STATE_RX 1
126# define NEM_DARWIN_PAGE_STATE_RW 2
127# define NEM_DARWIN_PAGE_STATE_RWX 3
128/** @} */
129
130# if defined(VBOX_VMM_TARGET_ARMV8)
131/** The CPUMCTX_EXTRN_XXX mask for IEM. */
132# define NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM ( IEM_CPUMCTX_EXTRN_MUST_MASK )
133# else
134/** The CPUMCTX_EXTRN_XXX mask for IEM. */
135# define NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM ( IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_INHIBIT_INT \
136 | CPUMCTX_EXTRN_INHIBIT_NMI )
137#endif
138
139/** The CPUMCTX_EXTRN_XXX mask for IEM when raising exceptions. */
140# define NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT (IEM_CPUMCTX_EXTRN_XCPT_MASK | NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM)
141
142
143# if defined(VBOX_VMM_TARGET_ARMV8)
144/**
145 * MMIO2 tracking region.
146 */
147typedef struct
148{
149 /* Start of the region. */
150 RTGCPHYS GCPhysStart;
151 /** End of the region. */
152 RTGCPHYS GCPhysLast;
153 /** Whether the region was accessed since last time. */
154 bool fDirty;
155} NEMHVMMIO2REGION;
156/** Pointer to a MMIO2 tracking region. */
157typedef NEMHVMMIO2REGION *PNEMHVMMIO2REGION;
158# endif
159
160#endif
161
162
163/** Trick to make slickedit see the static functions in the template. */
164#ifndef IN_SLICKEDIT
165# define NEM_TMPL_STATIC static
166#else
167# define NEM_TMPL_STATIC
168#endif
169
170
171/**
172 * Generic NEM exit type enumeration for use with EMHistoryAddExit.
173 *
174 * On windows we've got two different set of exit types and they are both jumping
175 * around the place value wise, so EM can use their values.
176 *
177 * @note We only have exit types for exits not covered by EM here.
178 */
179typedef enum NEMEXITTYPE
180{
181 NEMEXITTYPE_INVALID = 0,
182
183 /* Common: */
184 NEMEXITTYPE_INTTERRUPT_WINDOW,
185 NEMEXITTYPE_HALT,
186
187 /* Windows: */
188 NEMEXITTYPE_UNRECOVERABLE_EXCEPTION,
189 NEMEXITTYPE_INVALID_VP_REGISTER_VALUE,
190 NEMEXITTYPE_XCPT_UD,
191 NEMEXITTYPE_XCPT_DB,
192 NEMEXITTYPE_XCPT_BP,
193 NEMEXITTYPE_CANCELED,
194 NEMEXITTYPE_MEMORY_ACCESS,
195
196 /* Linux: */
197 NEMEXITTYPE_INTERNAL_ERROR_EMULATION,
198 NEMEXITTYPE_INTERNAL_ERROR_FATAL,
199 NEMEXITTYPE_INTERRUPTED,
200 NEMEXITTYPE_FAILED_ENTRY,
201
202 /* End of valid types. */
203 NEMEXITTYPE_END
204} NEMEXITTYPE;
205
206
207/**
208 * NEM VM Instance data.
209 */
210typedef struct NEM
211{
212 /** NEM_MAGIC. */
213 uint32_t u32Magic;
214
215 /** Set if enabled. */
216 bool fEnabled;
217 /** Set if long mode guests are allowed. */
218 bool fAllow64BitGuests;
219 /** Set when the debug facility has breakpoints/events enabled that requires
220 * us to use the debug execution loop. */
221 bool fUseDebugLoop;
222
223#if defined(VBOX_VMM_TARGET_ARMV8)
224 /** The PPI interrupt number of the vTimer. */
225 uint32_t u32GicPpiVTimer;
226#endif
227
228#if defined(RT_OS_LINUX)
229 /** The '/dev/kvm' file descriptor. */
230 int32_t fdKvm;
231 /** The KVM_CREATE_VM file descriptor. */
232 int32_t fdVm;
233
234 /** KVM_GET_VCPU_MMAP_SIZE. */
235 uint32_t cbVCpuMmap;
236 /** KVM_CAP_NR_MEMSLOTS. */
237 uint32_t cMaxMemSlots;
238# ifdef RT_ARCH_ARM64
239 /** KVM_CAP_ARM_VM_IPA_SIZE. */
240 uint32_t cIpaBits;
241# else
242 /** KVM_CAP_X86_ROBUST_SINGLESTEP. */
243 bool fRobustSingleStep;
244# endif
245
246 /** Hint where there might be a free slot. */
247 uint16_t idPrevSlot;
248 /** Memory slot ID allocation bitmap. */
249 uint64_t bmSlotIds[_32K / 8 / sizeof(uint64_t)];
250
251#elif defined(RT_OS_WINDOWS)
252 /** Set if we've created the EMTs. */
253 bool fCreatedEmts : 1;
254# if defined(VBOX_VMM_TARGET_ARMV8)
255 bool fHypercallExit : 1;
256 bool fGpaAccessFaultExit : 1;
257 /** Cache line flush size as a power of two. */
258 uint8_t cPhysicalAddressWidth;
259# else
260 /** WHvRunVpExitReasonX64Cpuid is supported. */
261 bool fExtendedMsrExit : 1;
262 /** WHvRunVpExitReasonX64MsrAccess is supported. */
263 bool fExtendedCpuIdExit : 1;
264 /** WHvRunVpExitReasonException is supported. */
265 bool fExtendedXcptExit : 1;
266# ifdef NEM_WIN_WITH_A20
267 /** Set if we've started more than one CPU and cannot mess with A20. */
268 bool fA20Fixed : 1;
269 /** Set if A20 is enabled. */
270 bool fA20Enabled : 1;
271# endif
272# endif
273 /** The reported CPU vendor. */
274 CPUMCPUVENDOR enmCpuVendor;
275 /** Cache line flush size as a power of two. */
276 uint8_t cCacheLineFlushShift;
277 /** The result of WHvCapabilityCodeProcessorFeatures. */
278 union
279 {
280 /** 64-bit view. */
281 uint64_t u64;
282# ifdef _WINHVAPIDEFS_H_
283 /** Interpreed features. */
284 WHV_PROCESSOR_FEATURES u;
285# endif
286 } uCpuFeatures;
287
288 /** The partition handle. */
289# ifdef _WINHVAPIDEFS_H_
290 WHV_PARTITION_HANDLE
291# else
292 RTHCUINTPTR
293# endif
294 hPartition;
295 /** The device handle for the partition, for use with Vid APIs or direct I/O
296 * controls. */
297 RTR3PTR hPartitionDevice;
298
299 /** Number of currently mapped pages. */
300 uint32_t volatile cMappedPages;
301 uint32_t u32Padding;
302 STAMCOUNTER StatMapPage;
303 STAMCOUNTER StatUnmapPage;
304 STAMCOUNTER StatMapPageFailed;
305 STAMCOUNTER StatUnmapPageFailed;
306 STAMPROFILE StatProfMapGpaRange;
307 STAMPROFILE StatProfUnmapGpaRange;
308 STAMPROFILE StatProfMapGpaRangePage;
309 STAMPROFILE StatProfUnmapGpaRangePage;
310
311 /** Statistics updated by NEMR0UpdateStatistics. */
312 struct
313 {
314 uint64_t cPagesAvailable;
315 uint64_t cPagesInUse;
316 } R0Stats;
317
318#elif defined(RT_OS_DARWIN)
319 /** Set if we've created the EMTs. */
320 bool fCreatedEmts : 1;
321 /** Set if hv_vm_create() was called successfully. */
322 bool fCreatedVm : 1;
323 /** Set if EL2 is enabled. */
324 bool fEl2Enabled : 1;
325# if defined(VBOX_VMM_TARGET_ARMV8)
326 /** @name vTimer related state.
327 * @{ */
328 /** The counter frequency in Hz as obtained from CNTFRQ_EL0. */
329 uint64_t u64CntFrqHz;
330 /** The vTimer offset programmed. */
331 uint64_t u64VTimerOff;
332 /** Dirty tracking slots. */
333 NEMHVMMIO2REGION aMmio2DirtyTracking[8];
334 /** The vCPU config. */
335 hv_vcpu_config_t hVCpuCfg;
336 /** @} */
337# else
338 /** Set if hv_vm_space_create() was called successfully. */
339 bool fCreatedAsid : 1;
340 /** Set if Last Branch Record (LBR) is enabled. */
341 bool fLbr;
342 /** The ASID for this VM (only valid if fCreatedAsid is true). */
343 hv_vm_space_t uVmAsid;
344 /** Number of mach time units per NS, for hv_vcpu_run_until(). */
345 uint64_t cMachTimePerNs;
346 /** Pause-loop exiting (PLE) gap in ticks. */
347 uint32_t cPleGapTicks;
348 /** Pause-loop exiting (PLE) window in ticks. */
349 uint32_t cPleWindowTicks;
350
351 /** The host LBR TOS (top-of-stack) MSR id. */
352 uint32_t idLbrTosMsr;
353 /** The host LBR select MSR id. */
354 uint32_t idLbrSelectMsr;
355 /** The host last event record from IP MSR id. */
356 uint32_t idLerFromIpMsr;
357 /** The host last event record to IP MSR id. */
358 uint32_t idLerToIpMsr;
359
360 /** The first valid host LBR branch-from-IP stack range. */
361 uint32_t idLbrFromIpMsrFirst;
362 /** The last valid host LBR branch-from-IP stack range. */
363 uint32_t idLbrFromIpMsrLast;
364
365 /** The first valid host LBR branch-to-IP stack range. */
366 uint32_t idLbrToIpMsrFirst;
367 /** The last valid host LBR branch-to-IP stack range. */
368 uint32_t idLbrToIpMsrLast;
369
370 /** The first valid host LBR info stack range. */
371 uint32_t idLbrInfoMsrFirst;
372 /** The last valid host LBR info stack range. */
373 uint32_t idLbrInfoMsrLast;
374# endif
375
376 STAMCOUNTER StatMapPage;
377 STAMCOUNTER StatUnmapPage;
378 STAMCOUNTER StatMapPageFailed;
379 STAMCOUNTER StatUnmapPageFailed;
380#endif /* RT_OS_WINDOWS */
381} NEM;
382/** Pointer to NEM VM instance data. */
383typedef NEM *PNEM;
384
385/** NEM::u32Magic value. */
386#define NEM_MAGIC UINT32_C(0x004d454e)
387/** NEM::u32Magic value after termination. */
388#define NEM_MAGIC_DEAD UINT32_C(0xdead1111)
389
390
391/**
392 * NEM VMCPU Instance data.
393 */
394typedef struct NEMCPU
395{
396 /** NEMCPU_MAGIC. */
397 uint32_t u32Magic;
398 /** Whether \#UD needs to be intercepted and presented to GIM. */
399 bool fGIMTrapXcptUD : 1;
400 /** Whether \#GP needs to be intercept for mesa driver workaround. */
401 bool fTrapXcptGpForLovelyMesaDrv: 1;
402 /** Whether we should use the debug loop because of single stepping or special
403 * debug breakpoints / events are armed. */
404 bool fUseDebugLoop : 1;
405 /** Whether we're executing a single instruction. */
406 bool fSingleInstruction : 1;
407 /** Set if we using the debug loop and wish to intercept RDTSC. */
408 bool fDebugWantRdTscExit : 1;
409 /** Whether we are currently executing in the debug loop.
410 * Mainly for assertions. */
411 bool fUsingDebugLoop : 1;
412 /** Set if we need to clear the trap flag because of single stepping. */
413 bool fClearTrapFlag : 1;
414 /** Whether we're using the hyper DR7 or guest DR7. */
415 bool fUsingHyperDR7 : 1;
416 /** Whether \#DE needs to be intercepted for GIM. */
417 bool fGCMTrapXcptDE : 1;
418
419#if defined(RT_OS_LINUX)
420 uint8_t abPadding[3];
421 /** The KVM VCpu file descriptor. */
422 int32_t fdVCpu;
423 /** Pointer to the KVM_RUN data exchange region. */
424 R3PTRTYPE(struct kvm_run *) pRun;
425# if defined(VBOX_VMM_TARGET_ARMV8)
426 /** The IRQ device levels from device_irq_level. */
427 uint64_t fIrqDeviceLvls;
428 /** Status of the IRQ line when last seen. */
429 bool fIrqLastSeen;
430 /** Status of the FIQ line when last seen. */
431 bool fFiqLastSeen;
432# else
433 /** The MSR_IA32_APICBASE value known to KVM. */
434 uint64_t uKvmApicBase;
435#endif
436
437 /** @name Statistics
438 * @{ */
439 STAMCOUNTER StatExitTotal;
440 STAMCOUNTER StatExitIo;
441 STAMCOUNTER StatExitMmio;
442 STAMCOUNTER StatExitSetTpr;
443 STAMCOUNTER StatExitTprAccess;
444 STAMCOUNTER StatExitRdMsr;
445 STAMCOUNTER StatExitWrMsr;
446 STAMCOUNTER StatExitIrqWindowOpen;
447 STAMCOUNTER StatExitHalt;
448 STAMCOUNTER StatExitIntr;
449 STAMCOUNTER StatExitHypercall;
450 STAMCOUNTER StatExitDebug;
451 STAMCOUNTER StatExitBusLock;
452 STAMCOUNTER StatExitInternalErrorEmulation;
453 STAMCOUNTER StatExitInternalErrorFatal;
454# if 0
455 STAMCOUNTER StatExitCpuId;
456 STAMCOUNTER StatExitUnrecoverable;
457 STAMCOUNTER StatGetMsgTimeout;
458 STAMCOUNTER StatStopCpuSuccess;
459 STAMCOUNTER StatStopCpuPending;
460 STAMCOUNTER StatStopCpuPendingAlerts;
461 STAMCOUNTER StatStopCpuPendingOdd;
462 STAMCOUNTER StatCancelChangedState;
463 STAMCOUNTER StatCancelAlertedThread;
464# endif
465 STAMCOUNTER StatBreakOnCancel;
466 STAMCOUNTER StatBreakOnFFPre;
467 STAMCOUNTER StatBreakOnFFPost;
468 STAMCOUNTER StatBreakOnStatus;
469 STAMCOUNTER StatFlushExitOnReturn;
470 STAMCOUNTER StatFlushExitOnReturn1Loop;
471 STAMCOUNTER StatFlushExitOnReturn2Loops;
472 STAMCOUNTER StatFlushExitOnReturn3Loops;
473 STAMCOUNTER StatFlushExitOnReturn4PlusLoops;
474 STAMCOUNTER StatImportOnDemand;
475 STAMCOUNTER StatImportOnReturn;
476 STAMCOUNTER StatImportOnReturnSkipped;
477 STAMCOUNTER StatImportPendingInterrupt;
478 STAMCOUNTER StatExportPendingInterrupt;
479 STAMCOUNTER StatQueryCpuTick;
480 /** @} */
481
482
483#elif defined(RT_OS_WINDOWS)
484# ifdef VBOX_VMM_TARGET_ARMV8
485 /** Flag whether the ID registers were synced to the guest context
486 * (for first guest exec call on the EMT after loading the saved state). */
487 bool fIdRegsSynced;
488# else
489 /** The current state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
490 uint8_t fCurrentInterruptWindows;
491 /** The desired state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
492 uint8_t fDesiredInterruptWindows;
493 /** Last copy of HV_X64_VP_EXECUTION_STATE::InterruptShadow. */
494 bool fLastInterruptShadow : 1;
495 uint32_t uPadding;
496 /** The VID_MSHAGN_F_XXX flags.
497 * Either VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE or zero. */
498 uint32_t fHandleAndGetFlags;
499 /** What VidMessageSlotMap returns and is used for passing exit info. */
500 RTR3PTR pvMsgSlotMapping;
501 /** The windows thread handle. */
502 RTR3PTR hNativeThreadHandle;
503# endif
504
505 /** @name Statistics
506 * @{ */
507 STAMCOUNTER StatExitPortIo;
508 STAMCOUNTER StatExitMemUnmapped;
509 STAMCOUNTER StatExitMemIntercept;
510 STAMCOUNTER StatExitHalt;
511 STAMCOUNTER StatExitInterruptWindow;
512 STAMCOUNTER StatExitCpuId;
513 STAMCOUNTER StatExitMsr;
514 STAMCOUNTER StatExitException;
515 STAMCOUNTER StatExitExceptionBp;
516 STAMCOUNTER StatExitExceptionDb;
517 STAMCOUNTER StatExitExceptionGp;
518 STAMCOUNTER StatExitExceptionGpMesa;
519 STAMCOUNTER StatExitExceptionUd;
520 STAMCOUNTER StatExitExceptionUdHandled;
521 STAMCOUNTER StatExitUnrecoverable;
522 STAMCOUNTER StatGetMsgTimeout;
523 STAMCOUNTER StatStopCpuSuccess;
524 STAMCOUNTER StatStopCpuPending;
525 STAMCOUNTER StatStopCpuPendingAlerts;
526 STAMCOUNTER StatStopCpuPendingOdd;
527 STAMCOUNTER StatCancelChangedState;
528 STAMCOUNTER StatCancelAlertedThread;
529 STAMCOUNTER StatBreakOnCancel;
530 STAMCOUNTER StatBreakOnFFPre;
531 STAMCOUNTER StatBreakOnFFPost;
532 STAMCOUNTER StatBreakOnStatus;
533 STAMCOUNTER StatImportOnDemand;
534 STAMCOUNTER StatImportOnReturn;
535 STAMCOUNTER StatImportOnReturnSkipped;
536 STAMCOUNTER StatQueryCpuTick;
537 /** @} */
538
539#elif defined(RT_OS_DARWIN)
540# if defined(VBOX_VMM_TARGET_ARMV8)
541 /** The vCPU handle associated with the EMT executing this vCPU. */
542 hv_vcpu_t hVCpu;
543 /** Pointer to the exit information structure. */
544 hv_vcpu_exit_t *pHvExit;
545 /** Flag whether an event is pending. */
546 bool fEventPending;
547 /** Flag whether the vTimer got activated and is masked. */
548 bool fVTimerActivated;
549 /** Flag whether to update the vTimer offset. */
550 bool fVTimerOffUpdate;
551 /** Flag whether the ID registers were synced to the guest context
552 * (for first guest exec call on the EMT after loading the saved state). */
553 bool fIdRegsSynced;
554# else
555 /** The vCPU handle associated with the EMT executing this vCPU. */
556 hv_vcpuid_t hVCpuId;
557
558 /** @name State shared with the VT-x code.
559 * @{ */
560 /** An additional error code used for some gurus. */
561 uint32_t u32HMError;
562 /** The last exit-to-ring-3 reason. */
563 int32_t rcLastExitToR3;
564 /** CPU-context changed flags (see HM_CHANGED_xxx). */
565 uint64_t fCtxChanged;
566
567 /** The guest VMCS information. */
568 VMXVMCSINFO VmcsInfo;
569
570 /** VT-x data. */
571 struct HMCPUVMX
572 {
573 /** @name Guest information.
574 * @{ */
575 /** Guest VMCS information shared with ring-3. */
576 VMXVMCSINFOSHARED VmcsInfo;
577 /** Nested-guest VMCS information shared with ring-3. */
578 VMXVMCSINFOSHARED VmcsInfoNstGst;
579 /** Whether the nested-guest VMCS was the last current VMCS (shadow copy for ring-3).
580 * @see HMR0PERVCPU::vmx.fSwitchedToNstGstVmcs */
581 bool fSwitchedToNstGstVmcsCopyForRing3;
582 /** Whether the static guest VMCS controls has been merged with the
583 * nested-guest VMCS controls. */
584 bool fMergedNstGstCtls;
585 /** Whether the nested-guest VMCS has been copied to the shadow VMCS. */
586 bool fCopiedNstGstToShadowVmcs;
587 /** Whether flushing the TLB is required due to switching to/from the
588 * nested-guest. */
589 bool fSwitchedNstGstFlushTlb;
590 /** Alignment. */
591 bool afAlignment0[4];
592 /** Cached guest APIC-base MSR for identifying when to map the APIC-access page. */
593 uint64_t u64GstMsrApicBase;
594 /** @} */
595
596 /** @name Error reporting and diagnostics.
597 * @{ */
598 /** VT-x error-reporting (mainly for ring-3 propagation). */
599 struct
600 {
601 RTCPUID idCurrentCpu;
602 RTCPUID idEnteredCpu;
603 RTHCPHYS HCPhysCurrentVmcs;
604 uint32_t u32VmcsRev;
605 uint32_t u32InstrError;
606 uint32_t u32ExitReason;
607 uint32_t u32GuestIntrState;
608 } LastError;
609 /** @} */
610 } vmx;
611
612 /** Event injection state. */
613 HMEVENT Event;
614
615 /** Current shadow paging mode for updating CR4.
616 * @todo move later (@bugref{9217}). */
617 PGMMODE enmShadowMode;
618 uint32_t u32TemporaryPadding;
619
620 /** The PAE PDPEs used with Nested Paging (only valid when
621 * VMCPU_FF_HM_UPDATE_PAE_PDPES is set). */
622 X86PDPE aPdpes[4];
623 /** Pointer to the VMX statistics. */
624 PVMXSTATISTICS pVmxStats;
625# endif
626
627 /** @name Statistics
628 * @{ */
629 STAMCOUNTER StatExitAll;
630 STAMCOUNTER StatBreakOnCancel;
631 STAMCOUNTER StatBreakOnFFPre;
632 STAMCOUNTER StatBreakOnFFPost;
633 STAMCOUNTER StatBreakOnStatus;
634 STAMCOUNTER StatImportOnDemand;
635 STAMCOUNTER StatImportOnReturn;
636 STAMCOUNTER StatImportOnReturnSkipped;
637 STAMCOUNTER StatQueryCpuTick;
638#ifdef VBOX_WITH_STATISTICS
639 STAMPROFILEADV StatProfGstStateImport;
640 STAMPROFILEADV StatProfGstStateExport;
641#endif
642 /** @} */
643
644 /** @} */
645#endif /* RT_OS_DARWIN */
646} NEMCPU;
647/** Pointer to NEM VMCPU instance data. */
648typedef NEMCPU *PNEMCPU;
649
650/** NEMCPU::u32Magic value. */
651#define NEMCPU_MAGIC UINT32_C(0x4d454e20)
652/** NEMCPU::u32Magic value after termination. */
653#define NEMCPU_MAGIC_DEAD UINT32_C(0xdead2222)
654
655
656#ifdef IN_RING0
657# ifdef RT_OS_WINDOWS
658/**
659 * Windows: Hypercall input/ouput page info.
660 */
661typedef struct NEMR0HYPERCALLDATA
662{
663 /** Host physical address of the hypercall input/output page. */
664 RTHCPHYS HCPhysPage;
665 /** Pointer to the hypercall input/output page. */
666 uint8_t *pbPage;
667 /** Handle to the memory object of the hypercall input/output page. */
668 RTR0MEMOBJ hMemObj;
669} NEMR0HYPERCALLDATA;
670/** Pointer to a Windows hypercall input/output page info. */
671typedef NEMR0HYPERCALLDATA *PNEMR0HYPERCALLDATA;
672# endif /* RT_OS_WINDOWS */
673
674/**
675 * NEM GVMCPU instance data.
676 */
677typedef struct NEMR0PERVCPU
678{
679 uint32_t uDummy;
680} NEMR0PERVCPU;
681
682/**
683 * NEM GVM instance data.
684 */
685typedef struct NEMR0PERVM
686{
687 uint32_t uDummy;
688} NEMR0PERVM;
689
690#endif /* IN_RING*/
691
692
693#ifdef IN_RING3
694
695int nemR3DisableCpuIsaExt(PVM pVM, const char *pszIsaExt);
696
697int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced);
698int nemR3NativeInitAfterCPUM(PVM pVM);
699int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
700int nemR3NativeTerm(PVM pVM);
701void nemR3NativeReset(PVM pVM);
702void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi);
703VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu);
704bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu);
705bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable);
706
707/**
708 * Forced flag notification call from VMEmt.h.
709 *
710 * This is only called when pVCpu is in the VMCPUSTATE_STARTED_EXEC_NEM state.
711 *
712 * @param pVM The cross context VM structure.
713 * @param pVCpu The cross context virtual CPU structure of the CPU
714 * to be notified.
715 * @param fFlags Notification flags, VMNOTIFYFF_FLAGS_XXX.
716 */
717void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
718
719/**
720 * Called by NEMR3NotifyDebugEventChanged() to let the native backend take the final decision
721 * on whether to switch to the debug loop.
722 *
723 * @returns Final flag whether to switch to the debug loop.
724 * @param pVM The VM cross context VM structure.
725 * @param fUseDebugLoop The current value determined by NEMR3NotifyDebugEventChanged().
726 * @thread EMT(0)
727 */
728DECLHIDDEN(bool) nemR3NativeNotifyDebugEventChanged(PVM pVM, bool fUseDebugLoop);
729
730
731/**
732 * Called by NEMR3NotifyDebugEventChangedPerCpu() to let the native backend take the final decision
733 * on whether to switch to the debug loop.
734 *
735 * @returns Final flag whether to switch to the debug loop.
736 * @param pVM The VM cross context VM structure.
737 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
738 * @param fUseDebugLoop The current value determined by NEMR3NotifyDebugEventChangedPerCpu().
739 */
740DECLHIDDEN(bool) nemR3NativeNotifyDebugEventChangedPerCpu(PVM pVM, PVMCPU pVCpu, bool fUseDebugLoop);
741
742#endif /* IN_RING3 */
743
744void nemHCNativeNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
745void nemHCNativeNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
746 RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
747int nemHCNativeNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
748 PGMPAGETYPE enmType, uint8_t *pu2State);
749
750
751#ifdef RT_OS_WINDOWS
752/** Maximum number of pages we can map in a single NEMR0MapPages call. */
753# define NEM_MAX_MAP_PAGES ((HOST_PAGE_SIZE - RT_UOFFSETOF(HV_INPUT_MAP_GPA_PAGES, PageList)) / sizeof(HV_SPA_PAGE_NUMBER))
754/** Maximum number of pages we can unmap in a single NEMR0UnmapPages call. */
755# define NEM_MAX_UNMAP_PAGES 4095
756
757#endif
758/** @} */
759
760RT_C_DECLS_END
761
762#endif /* !VMM_INCLUDED_SRC_include_NEMInternal_h */
763
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