VirtualBox

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

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

VMM/NEM-win: Just drop the ring-0 bits when NEM/PGM mode is enabled. bugref:10122 bugref:10162

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.6 KB
Line 
1/* $Id: NEMInternal.h 93207 2022-01-12 19:14:56Z vboxsync $ */
2/** @file
3 * NEM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2018-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#ifndef VMM_INCLUDED_SRC_include_NEMInternal_h
19#define VMM_INCLUDED_SRC_include_NEMInternal_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <VBox/cdefs.h>
25#include <VBox/types.h>
26#include <VBox/vmm/nem.h>
27#include <VBox/vmm/cpum.h> /* For CPUMCPUVENDOR. */
28#include <VBox/vmm/stam.h>
29#include <VBox/vmm/vmapi.h>
30#ifdef RT_OS_WINDOWS
31#include <iprt/nt/hyperv.h>
32#include <iprt/critsect.h>
33#elif defined(RT_OS_DARWIN)
34# include "VMXInternal.h"
35#endif
36
37RT_C_DECLS_BEGIN
38
39
40/** @defgroup grp_nem_int Internal
41 * @ingroup grp_nem
42 * @internal
43 * @{
44 */
45
46#if defined(VBOX_WITH_PGM_NEM_MODE) && !defined(VBOX_WITH_NATIVE_NEM)
47# error "VBOX_WITH_PGM_NEM_MODE requires VBOX_WITH_NATIVE_NEM to be defined"
48#endif
49
50
51#ifdef RT_OS_WINDOWS
52/*
53 * Windows: Code configuration.
54 */
55# ifndef VBOX_WITH_PGM_NEM_MODE
56# define NEM_WIN_USE_HYPERCALLS_FOR_PAGES
57#endif
58//# define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS /**< Applies to ring-3 code only. Useful for testing VID API. */
59//# define NEM_WIN_USE_OUR_OWN_RUN_API /**< Applies to ring-3 code only. Useful for testing VID API. */
60//# define NEM_WIN_WITH_RING0_RUNLOOP /**< Enables the ring-0 runloop. */
61//# define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT /**< For quickly testing ring-3 API without messing with CFGM. */
62# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
63# error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
64# endif
65# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
66# error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
67# endif
68# if defined(NEM_WIN_WITH_RING0_RUNLOOP) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
69# error "NEM_WIN_WITH_RING0_RUNLOOP requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
70# endif
71# if defined(VBOX_WITH_PGM_NEM_MODE) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
72# error "VBOX_WITH_PGM_NEM_MODE cannot be used together with NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
73# endif
74
75/**
76 * Windows VID I/O control information.
77 */
78typedef struct NEMWINIOCTL
79{
80 /** The I/O control function number. */
81 uint32_t uFunction;
82 uint32_t cbInput;
83 uint32_t cbOutput;
84} NEMWINIOCTL;
85
86/** @name Windows: Our two-bit physical page state for PGMPAGE
87 * @{ */
88# define NEM_WIN_PAGE_STATE_NOT_SET 0
89# define NEM_WIN_PAGE_STATE_UNMAPPED 1
90# define NEM_WIN_PAGE_STATE_READABLE 2
91# define NEM_WIN_PAGE_STATE_WRITABLE 3
92/** @} */
93
94/** Windows: Checks if a_GCPhys is subject to the limited A20 gate emulation. */
95# define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys) ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)
96/** Windows: Checks if a_GCPhys is relevant to the limited A20 gate emulation. */
97# define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys) \
98 ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )
99
100/** The CPUMCTX_EXTRN_XXX mask for IEM. */
101# define NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM ( IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_INHIBIT_INT \
102 | CPUMCTX_EXTRN_INHIBIT_NMI )
103/** The CPUMCTX_EXTRN_XXX mask for IEM when raising exceptions. */
104# define NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT (IEM_CPUMCTX_EXTRN_XCPT_MASK | NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM)
105
106/** @name Windows: Interrupt window flags (NEM_WIN_INTW_F_XXX).
107 * @{ */
108# define NEM_WIN_INTW_F_NMI UINT8_C(0x01)
109# define NEM_WIN_INTW_F_REGULAR UINT8_C(0x02)
110# define NEM_WIN_INTW_F_PRIO_MASK UINT8_C(0x3c)
111# define NEM_WIN_INTW_F_PRIO_SHIFT 2
112/** @} */
113
114#endif /* RT_OS_WINDOWS */
115
116
117#ifdef RT_OS_DARWIN
118/** vCPU ID declaration to avoid dragging in HV headers here. */
119typedef unsigned hv_vcpuid_t;
120/** The HV VM memory space ID (ASID). */
121typedef unsigned hv_vm_space_t;
122
123
124/** @name Darwin: Our two-bit physical page state for PGMPAGE
125 * @{ */
126# define NEM_DARWIN_PAGE_STATE_NOT_SET 0
127# define NEM_DARWIN_PAGE_STATE_UNMAPPED 1
128# define NEM_DARWIN_PAGE_STATE_READABLE 2
129# define NEM_DARWIN_PAGE_STATE_WRITABLE 3
130/** @} */
131
132/** The CPUMCTX_EXTRN_XXX mask for IEM. */
133# define NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM ( IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_INHIBIT_INT \
134 | CPUMCTX_EXTRN_INHIBIT_NMI )
135/** The CPUMCTX_EXTRN_XXX mask for IEM when raising exceptions. */
136# define NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT (IEM_CPUMCTX_EXTRN_XCPT_MASK | NEM_DARWIN_CPUMCTX_EXTRN_MASK_FOR_IEM)
137
138#endif
139
140
141/** Trick to make slickedit see the static functions in the template. */
142#ifndef IN_SLICKEDIT
143# define NEM_TMPL_STATIC static
144#else
145# define NEM_TMPL_STATIC
146#endif
147
148
149/**
150 * Generic NEM exit type enumeration for use with EMHistoryAddExit.
151 *
152 * On windows we've got two different set of exit types and they are both jumping
153 * around the place value wise, so EM can use their values.
154 *
155 * @note We only have exit types for exits not covered by EM here.
156 */
157typedef enum NEMEXITTYPE
158{
159 NEMEXITTYPE_INVALID = 0,
160
161 /* Common: */
162 NEMEXITTYPE_INTTERRUPT_WINDOW,
163 NEMEXITTYPE_HALT,
164
165 /* Windows: */
166 NEMEXITTYPE_UNRECOVERABLE_EXCEPTION,
167 NEMEXITTYPE_INVALID_VP_REGISTER_VALUE,
168 NEMEXITTYPE_XCPT_UD,
169 NEMEXITTYPE_XCPT_DB,
170 NEMEXITTYPE_XCPT_BP,
171 NEMEXITTYPE_CANCELED,
172 NEMEXITTYPE_MEMORY_ACCESS,
173
174 /* Linux: */
175 NEMEXITTYPE_INTERNAL_ERROR_EMULATION,
176 NEMEXITTYPE_INTERNAL_ERROR_FATAL,
177 NEMEXITTYPE_INTERRUPTED,
178 NEMEXITTYPE_FAILED_ENTRY,
179
180 /* End of valid types. */
181 NEMEXITTYPE_END
182} NEMEXITTYPE;
183
184
185/**
186 * NEM VM Instance data.
187 */
188typedef struct NEM
189{
190 /** NEM_MAGIC. */
191 uint32_t u32Magic;
192
193 /** Set if enabled. */
194 bool fEnabled;
195 /** Set if long mode guests are allowed. */
196 bool fAllow64BitGuests;
197
198#if defined(RT_OS_LINUX)
199 /** The '/dev/kvm' file descriptor. */
200 int32_t fdKvm;
201 /** The KVM_CREATE_VM file descriptor. */
202 int32_t fdVm;
203
204 /** KVM_GET_VCPU_MMAP_SIZE. */
205 uint32_t cbVCpuMmap;
206 /** KVM_CAP_NR_MEMSLOTS. */
207 uint32_t cMaxMemSlots;
208 /** KVM_CAP_X86_ROBUST_SINGLESTEP. */
209 bool fRobustSingleStep;
210
211 /** Hint where there might be a free slot. */
212 uint16_t idPrevSlot;
213 /** Memory slot ID allocation bitmap. */
214 uint64_t bmSlotIds[_32K / 8 / sizeof(uint64_t)];
215
216#elif defined(RT_OS_WINDOWS)
217 /** Set if we've created the EMTs. */
218 bool fCreatedEmts : 1;
219 /** WHvRunVpExitReasonX64Cpuid is supported. */
220 bool fExtendedMsrExit : 1;
221 /** WHvRunVpExitReasonX64MsrAccess is supported. */
222 bool fExtendedCpuIdExit : 1;
223 /** WHvRunVpExitReasonException is supported. */
224 bool fExtendedXcptExit : 1;
225# ifndef VBOX_WITH_PGM_NEM_MODE
226 /** Set if we're using the ring-0 API to do the work. */
227 bool fUseRing0Runloop : 1;
228# endif
229# ifdef NEM_WIN_WITH_A20
230 /** Set if we've started more than one CPU and cannot mess with A20. */
231 bool fA20Fixed : 1;
232 /** Set if A20 is enabled. */
233 bool fA20Enabled : 1;
234# endif
235 /** The reported CPU vendor. */
236 CPUMCPUVENDOR enmCpuVendor;
237 /** Cache line flush size as a power of two. */
238 uint8_t cCacheLineFlushShift;
239 /** The result of WHvCapabilityCodeProcessorFeatures. */
240 union
241 {
242 /** 64-bit view. */
243 uint64_t u64;
244# ifdef _WINHVAPIDEFS_H_
245 /** Interpreed features. */
246 WHV_PROCESSOR_FEATURES u;
247# endif
248 } uCpuFeatures;
249
250 /** The partition handle. */
251# ifdef _WINHVAPIDEFS_H_
252 WHV_PARTITION_HANDLE
253# else
254 RTHCUINTPTR
255# endif
256 hPartition;
257 /** The device handle for the partition, for use with Vid APIs or direct I/O
258 * controls. */
259 RTR3PTR hPartitionDevice;
260 /** The Hyper-V partition ID. */
261 uint64_t idHvPartition;
262
263 /** Number of currently mapped pages. */
264 uint32_t volatile cMappedPages;
265# ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
266 /** Max number of pages we dare map at once. */
267 uint32_t cMaxMappedPages;
268# endif
269 STAMCOUNTER StatMapPage;
270 STAMCOUNTER StatUnmapPage;
271# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
272 STAMCOUNTER StatRemapPage;
273 STAMCOUNTER StatRemapPageFailed;
274# elif !defined(VBOX_WITH_PGM_NEM_MODE)
275 STAMCOUNTER StatUnmapAllPages;
276# endif
277 STAMCOUNTER StatMapPageFailed;
278 STAMCOUNTER StatUnmapPageFailed;
279# ifdef VBOX_WITH_PGM_NEM_MODE
280 STAMPROFILE StatProfMapGpaRange;
281 STAMPROFILE StatProfUnmapGpaRange;
282# endif
283# ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
284 STAMPROFILE StatProfMapGpaRangePage;
285 STAMPROFILE StatProfUnmapGpaRangePage;
286# endif
287
288# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
289 /** Info about the VidGetHvPartitionId I/O control interface. */
290 NEMWINIOCTL IoCtlGetHvPartitionId;
291 /** Info about the VidGetPartitionProperty I/O control interface. */
292 NEMWINIOCTL IoCtlGetPartitionProperty;
293# endif
294# ifdef NEM_WIN_WITH_RING0_RUNLOOP
295 /** Info about the VidStartVirtualProcessor I/O control interface. */
296 NEMWINIOCTL IoCtlStartVirtualProcessor;
297 /** Info about the VidStopVirtualProcessor I/O control interface. */
298 NEMWINIOCTL IoCtlStopVirtualProcessor;
299 /** Info about the VidStopVirtualProcessor I/O control interface. */
300 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
301# endif
302
303 /** Statistics updated by NEMR0UpdateStatistics. */
304 struct
305 {
306 uint64_t cPagesAvailable;
307 uint64_t cPagesInUse;
308 } R0Stats;
309
310#elif defined(RT_OS_DARWIN)
311 /** Set if we've created the EMTs. */
312 bool fCreatedEmts : 1;
313 /** Set if hv_vm_create() was called successfully. */
314 bool fCreatedVm : 1;
315 /** Set if hv_vm_space_create() was called successfully. */
316 bool fCreatedAsid : 1;
317 /** The ASID for this VM (only valid if fCreatedAsid is true). */
318 hv_vm_space_t uVmAsid;
319 STAMCOUNTER StatMapPage;
320 STAMCOUNTER StatUnmapPage;
321 STAMCOUNTER StatMapPageFailed;
322 STAMCOUNTER StatUnmapPageFailed;
323#endif /* RT_OS_WINDOWS */
324} NEM;
325/** Pointer to NEM VM instance data. */
326typedef NEM *PNEM;
327
328/** NEM::u32Magic value. */
329#define NEM_MAGIC UINT32_C(0x004d454e)
330/** NEM::u32Magic value after termination. */
331#define NEM_MAGIC_DEAD UINT32_C(0xdead1111)
332
333
334/**
335 * NEM VMCPU Instance data.
336 */
337typedef struct NEMCPU
338{
339 /** NEMCPU_MAGIC. */
340 uint32_t u32Magic;
341 /** Whether \#UD needs to be intercepted and presented to GIM. */
342 bool fGIMTrapXcptUD : 1;
343 /** Whether \#GP needs to be intercept for mesa driver workaround. */
344 bool fTrapXcptGpForLovelyMesaDrv: 1;
345
346#if defined(RT_OS_LINUX)
347 uint8_t abPadding[3];
348 /** The KVM VCpu file descriptor. */
349 int32_t fdVCpu;
350 /** Pointer to the KVM_RUN data exchange region. */
351 R3PTRTYPE(struct kvm_run *) pRun;
352 /** The MSR_IA32_APICBASE value known to KVM. */
353 uint64_t uKvmApicBase;
354
355 /** @name Statistics
356 * @{ */
357 STAMCOUNTER StatExitTotal;
358 STAMCOUNTER StatExitIo;
359 STAMCOUNTER StatExitMmio;
360 STAMCOUNTER StatExitSetTpr;
361 STAMCOUNTER StatExitTprAccess;
362 STAMCOUNTER StatExitRdMsr;
363 STAMCOUNTER StatExitWrMsr;
364 STAMCOUNTER StatExitIrqWindowOpen;
365 STAMCOUNTER StatExitHalt;
366 STAMCOUNTER StatExitIntr;
367 STAMCOUNTER StatExitHypercall;
368 STAMCOUNTER StatExitDebug;
369 STAMCOUNTER StatExitBusLock;
370 STAMCOUNTER StatExitInternalErrorEmulation;
371 STAMCOUNTER StatExitInternalErrorFatal;
372# if 0
373 STAMCOUNTER StatExitCpuId;
374 STAMCOUNTER StatExitUnrecoverable;
375 STAMCOUNTER StatGetMsgTimeout;
376 STAMCOUNTER StatStopCpuSuccess;
377 STAMCOUNTER StatStopCpuPending;
378 STAMCOUNTER StatStopCpuPendingAlerts;
379 STAMCOUNTER StatStopCpuPendingOdd;
380 STAMCOUNTER StatCancelChangedState;
381 STAMCOUNTER StatCancelAlertedThread;
382# endif
383 STAMCOUNTER StatBreakOnCancel;
384 STAMCOUNTER StatBreakOnFFPre;
385 STAMCOUNTER StatBreakOnFFPost;
386 STAMCOUNTER StatBreakOnStatus;
387 STAMCOUNTER StatFlushExitOnReturn;
388 STAMCOUNTER StatFlushExitOnReturn1Loop;
389 STAMCOUNTER StatFlushExitOnReturn2Loops;
390 STAMCOUNTER StatFlushExitOnReturn3Loops;
391 STAMCOUNTER StatFlushExitOnReturn4PlusLoops;
392 STAMCOUNTER StatImportOnDemand;
393 STAMCOUNTER StatImportOnReturn;
394 STAMCOUNTER StatImportOnReturnSkipped;
395 STAMCOUNTER StatImportPendingInterrupt;
396 STAMCOUNTER StatExportPendingInterrupt;
397 STAMCOUNTER StatQueryCpuTick;
398 /** @} */
399
400
401#elif defined(RT_OS_WINDOWS)
402 /** The current state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
403 uint8_t fCurrentInterruptWindows;
404 /** The desired state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
405 uint8_t fDesiredInterruptWindows;
406 /** Last copy of HV_X64_VP_EXECUTION_STATE::InterruptShadow. */
407 bool fLastInterruptShadow : 1;
408# ifdef NEM_WIN_WITH_RING0_RUNLOOP
409 /** Pending VINF_NEM_FLUSH_TLB. */
410 int32_t rcPending;
411# else
412 uint32_t uPadding;
413# endif
414 /** The VID_MSHAGN_F_XXX flags.
415 * Either VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE or zero. */
416 uint32_t fHandleAndGetFlags;
417 /** What VidMessageSlotMap returns and is used for passing exit info. */
418 RTR3PTR pvMsgSlotMapping;
419 /** The windows thread handle. */
420 RTR3PTR hNativeThreadHandle;
421 /** Parameters for making Hyper-V hypercalls. */
422 union
423 {
424 uint8_t ab[64];
425 /** Arguments for NEMR0MapPages (HvCallMapGpaPages). */
426 struct
427 {
428 RTGCPHYS GCPhysSrc;
429 RTGCPHYS GCPhysDst; /**< Same as GCPhysSrc except maybe when the A20 gate is disabled. */
430 uint32_t cPages;
431 HV_MAP_GPA_FLAGS fFlags;
432 } MapPages;
433 /** Arguments for NEMR0UnmapPages (HvCallUnmapGpaPages). */
434 struct
435 {
436 RTGCPHYS GCPhys;
437 uint32_t cPages;
438 } UnmapPages;
439 /** Result from NEMR0QueryCpuTick. */
440 struct
441 {
442 uint64_t cTicks;
443 uint32_t uAux;
444 } QueryCpuTick;
445 /** Input and output for NEMR0DoExperiment. */
446 struct
447 {
448 uint32_t uItem;
449 bool fSuccess;
450 uint64_t uStatus;
451 uint64_t uLoValue;
452 uint64_t uHiValue;
453 } Experiment;
454 } Hypercall;
455 /** I/O control buffer, we always use this for I/O controls. */
456 union
457 {
458 uint8_t ab[64];
459 HV_PARTITION_ID idPartition;
460 HV_VP_INDEX idCpu;
461 struct
462 {
463 uint64_t enmProperty;
464 uint64_t uValue;
465 } GetProp;
466# ifdef VID_MSHAGN_F_GET_NEXT_MESSAGE
467 VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT MsgSlotHandleAndGetNext;
468# endif
469 } uIoCtlBuf;
470
471 /** @name Statistics
472 * @{ */
473 STAMCOUNTER StatExitPortIo;
474 STAMCOUNTER StatExitMemUnmapped;
475 STAMCOUNTER StatExitMemIntercept;
476 STAMCOUNTER StatExitHalt;
477 STAMCOUNTER StatExitInterruptWindow;
478 STAMCOUNTER StatExitCpuId;
479 STAMCOUNTER StatExitMsr;
480 STAMCOUNTER StatExitException;
481 STAMCOUNTER StatExitExceptionBp;
482 STAMCOUNTER StatExitExceptionDb;
483 STAMCOUNTER StatExitExceptionGp;
484 STAMCOUNTER StatExitExceptionGpMesa;
485 STAMCOUNTER StatExitExceptionUd;
486 STAMCOUNTER StatExitExceptionUdHandled;
487 STAMCOUNTER StatExitUnrecoverable;
488 STAMCOUNTER StatGetMsgTimeout;
489 STAMCOUNTER StatStopCpuSuccess;
490 STAMCOUNTER StatStopCpuPending;
491 STAMCOUNTER StatStopCpuPendingAlerts;
492 STAMCOUNTER StatStopCpuPendingOdd;
493 STAMCOUNTER StatCancelChangedState;
494 STAMCOUNTER StatCancelAlertedThread;
495 STAMCOUNTER StatBreakOnCancel;
496 STAMCOUNTER StatBreakOnFFPre;
497 STAMCOUNTER StatBreakOnFFPost;
498 STAMCOUNTER StatBreakOnStatus;
499 STAMCOUNTER StatImportOnDemand;
500 STAMCOUNTER StatImportOnReturn;
501 STAMCOUNTER StatImportOnReturnSkipped;
502 STAMCOUNTER StatQueryCpuTick;
503 /** @} */
504
505#elif defined(RT_OS_DARWIN)
506 /** The vCPU handle associated with the EMT executing this vCPU. */
507 hv_vcpuid_t hVCpuId;
508
509 /** @name State shared with the VT-x code.
510 * @{ */
511 /** Whether we should use the debug loop because of single stepping or special
512 * debug breakpoints / events are armed. */
513 bool fUseDebugLoop;
514 /** Whether we're executing a single instruction. */
515 bool fSingleInstruction;
516
517 bool afAlignment0[2];
518
519 /** An additional error code used for some gurus. */
520 uint32_t u32HMError;
521 /** The last exit-to-ring-3 reason. */
522 int32_t rcLastExitToR3;
523 /** CPU-context changed flags (see HM_CHANGED_xxx). */
524 uint64_t fCtxChanged;
525
526 /** The guest VMCS information. */
527 VMXVMCSINFO VmcsInfo;
528
529 /** VT-x data. */
530 struct HMCPUVMX
531 {
532 /** @name Guest information.
533 * @{ */
534 /** Guest VMCS information shared with ring-3. */
535 VMXVMCSINFOSHARED VmcsInfo;
536 /** Nested-guest VMCS information shared with ring-3. */
537 VMXVMCSINFOSHARED VmcsInfoNstGst;
538 /** Whether the nested-guest VMCS was the last current VMCS (shadow copy for ring-3).
539 * @see HMR0PERVCPU::vmx.fSwitchedToNstGstVmcs */
540 bool fSwitchedToNstGstVmcsCopyForRing3;
541 /** Whether the static guest VMCS controls has been merged with the
542 * nested-guest VMCS controls. */
543 bool fMergedNstGstCtls;
544 /** Whether the nested-guest VMCS has been copied to the shadow VMCS. */
545 bool fCopiedNstGstToShadowVmcs;
546 /** Whether flushing the TLB is required due to switching to/from the
547 * nested-guest. */
548 bool fSwitchedNstGstFlushTlb;
549 /** Alignment. */
550 bool afAlignment0[4];
551 /** Cached guest APIC-base MSR for identifying when to map the APIC-access page. */
552 uint64_t u64GstMsrApicBase;
553 /** @} */
554
555 /** @name Error reporting and diagnostics.
556 * @{ */
557 /** VT-x error-reporting (mainly for ring-3 propagation). */
558 struct
559 {
560 RTCPUID idCurrentCpu;
561 RTCPUID idEnteredCpu;
562 RTHCPHYS HCPhysCurrentVmcs;
563 uint32_t u32VmcsRev;
564 uint32_t u32InstrError;
565 uint32_t u32ExitReason;
566 uint32_t u32GuestIntrState;
567 } LastError;
568 /** @} */
569 } vmx;
570
571 /** Event injection state. */
572 HMEVENT Event;
573
574 /** Current shadow paging mode for updating CR4.
575 * @todo move later (@bugref{9217}). */
576 PGMMODE enmShadowMode;
577 uint32_t u32TemporaryPadding;
578
579 /** The PAE PDPEs used with Nested Paging (only valid when
580 * VMCPU_FF_HM_UPDATE_PAE_PDPES is set). */
581 X86PDPE aPdpes[4];
582 /** Pointer to the VMX statistics. */
583 PVMXSTATISTICS pVmxStats;
584
585 /** @name Statistics
586 * @{ */
587 STAMCOUNTER StatExitAll;
588 STAMCOUNTER StatBreakOnCancel;
589 STAMCOUNTER StatBreakOnFFPre;
590 STAMCOUNTER StatBreakOnFFPost;
591 STAMCOUNTER StatBreakOnStatus;
592 STAMCOUNTER StatImportOnDemand;
593 STAMCOUNTER StatImportOnReturn;
594 STAMCOUNTER StatImportOnReturnSkipped;
595 STAMCOUNTER StatQueryCpuTick;
596#ifdef VBOX_WITH_STATISTICS
597 STAMPROFILEADV StatProfGstStateImport;
598 STAMPROFILEADV StatProfGstStateExport;
599#endif
600 /** @} */
601
602 /** @} */
603#endif /* RT_OS_DARWIN */
604} NEMCPU;
605/** Pointer to NEM VMCPU instance data. */
606typedef NEMCPU *PNEMCPU;
607
608/** NEMCPU::u32Magic value. */
609#define NEMCPU_MAGIC UINT32_C(0x4d454e20)
610/** NEMCPU::u32Magic value after termination. */
611#define NEMCPU_MAGIC_DEAD UINT32_C(0xdead2222)
612
613
614#ifdef IN_RING0
615# ifdef RT_OS_WINDOWS
616/**
617 * Windows: Hypercall input/ouput page info.
618 */
619typedef struct NEMR0HYPERCALLDATA
620{
621 /** Host physical address of the hypercall input/output page. */
622 RTHCPHYS HCPhysPage;
623 /** Pointer to the hypercall input/output page. */
624 uint8_t *pbPage;
625 /** Handle to the memory object of the hypercall input/output page. */
626 RTR0MEMOBJ hMemObj;
627} NEMR0HYPERCALLDATA;
628/** Pointer to a Windows hypercall input/output page info. */
629typedef NEMR0HYPERCALLDATA *PNEMR0HYPERCALLDATA;
630# endif /* RT_OS_WINDOWS */
631
632/**
633 * NEM GVMCPU instance data.
634 */
635typedef struct NEMR0PERVCPU
636{
637# if defined(RT_OS_WINDOWS) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
638 /** Hypercall input/ouput page. */
639 NEMR0HYPERCALLDATA HypercallData;
640 /** Delta to add to convert a ring-0 pointer to a ring-3 one. */
641 uintptr_t offRing3ConversionDelta;
642# else
643 uint32_t uDummy;
644# endif
645} NEMR0PERVCPU;
646
647/**
648 * NEM GVM instance data.
649 */
650typedef struct NEMR0PERVM
651{
652# ifdef RT_OS_WINDOWS
653# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
654 /** The partition ID. */
655 uint64_t idHvPartition;
656 /** I/O control context. */
657 PSUPR0IOCTLCTX pIoCtlCtx;
658 /** Info about the VidGetHvPartitionId I/O control interface. */
659 NEMWINIOCTL IoCtlGetHvPartitionId;
660 /** Info about the VidGetPartitionProperty I/O control interface. */
661 NEMWINIOCTL IoCtlGetPartitionProperty;
662# endif
663# ifdef NEM_WIN_WITH_RING0_RUNLOOP
664 /** Info about the VidStartVirtualProcessor I/O control interface. */
665 NEMWINIOCTL IoCtlStartVirtualProcessor;
666 /** Info about the VidStopVirtualProcessor I/O control interface. */
667 NEMWINIOCTL IoCtlStopVirtualProcessor;
668 /** Info about the VidStopVirtualProcessor I/O control interface. */
669 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
670 /** Whether we may use the ring-0 runloop or not. */
671 bool fMayUseRing0Runloop;
672# endif
673
674# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
675 /** Hypercall input/ouput page for non-EMT. */
676 NEMR0HYPERCALLDATA HypercallData;
677 /** Critical section protecting use of HypercallData. */
678 RTCRITSECT HypercallDataCritSect;
679# endif
680
681# else
682 uint32_t uDummy;
683# endif
684} NEMR0PERVM;
685
686#endif /* IN_RING*/
687
688
689#ifdef IN_RING3
690int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced);
691int nemR3NativeInitAfterCPUM(PVM pVM);
692int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
693int nemR3NativeTerm(PVM pVM);
694void nemR3NativeReset(PVM pVM);
695void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi);
696VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu);
697bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu);
698bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable);
699void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
700#endif
701
702void nemHCNativeNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
703void nemHCNativeNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
704 RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
705int nemHCNativeNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
706 PGMPAGETYPE enmType, uint8_t *pu2State);
707
708
709#ifdef RT_OS_WINDOWS
710/** Maximum number of pages we can map in a single NEMR0MapPages call. */
711# define NEM_MAX_MAP_PAGES ((PAGE_SIZE - RT_UOFFSETOF(HV_INPUT_MAP_GPA_PAGES, PageList)) / sizeof(HV_SPA_PAGE_NUMBER))
712/** Maximum number of pages we can unmap in a single NEMR0UnmapPages call. */
713# define NEM_MAX_UNMAP_PAGES 4095
714
715#endif
716/** @} */
717
718RT_C_DECLS_END
719
720#endif /* !VMM_INCLUDED_SRC_include_NEMInternal_h */
721
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette