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