VirtualBox

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

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

VMM/PGM,NEM: Moved the StatProfQueryGpaRangeDirtyBitmap NEM stat up to PGM. bugref:10122

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.8 KB
Line 
1/* $Id: NEMInternal.h 92177 2021-11-02 13:48:55Z vboxsync $ */
2/** @file
3 * NEM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2018-2020 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#endif
34
35RT_C_DECLS_BEGIN
36
37
38/** @defgroup grp_nem_int Internal
39 * @ingroup grp_nem
40 * @internal
41 * @{
42 */
43
44#if defined(VBOX_WITH_PGM_NEM_MODE) && !defined(VBOX_WITH_NATIVE_NEM)
45# error "VBOX_WITH_PGM_NEM_MODE requires VBOX_WITH_NATIVE_NEM to be defined"
46#endif
47
48
49#ifdef RT_OS_WINDOWS
50/*
51 * Windows: Code configuration.
52 */
53# ifndef VBOX_WITH_PGM_NEM_MODE
54# define NEM_WIN_USE_HYPERCALLS_FOR_PAGES
55#endif
56//# define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS /**< Applies to ring-3 code only. Useful for testing VID API. */
57//# define NEM_WIN_USE_OUR_OWN_RUN_API /**< Applies to ring-3 code only. Useful for testing VID API. */
58//# define NEM_WIN_WITH_RING0_RUNLOOP /**< Enables the ring-0 runloop. */
59//# define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT /**< For quickly testing ring-3 API without messing with CFGM. */
60# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
61# error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
62# endif
63# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
64# error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
65# endif
66# if defined(NEM_WIN_WITH_RING0_RUNLOOP) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
67# error "NEM_WIN_WITH_RING0_RUNLOOP requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
68# endif
69# if defined(VBOX_WITH_PGM_NEM_MODE) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
70# error "VBOX_WITH_PGM_NEM_MODE cannot be used together with NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
71# endif
72
73/**
74 * Windows VID I/O control information.
75 */
76typedef struct NEMWINIOCTL
77{
78 /** The I/O control function number. */
79 uint32_t uFunction;
80 uint32_t cbInput;
81 uint32_t cbOutput;
82} NEMWINIOCTL;
83
84/** @name Windows: Our two-bit physical page state for PGMPAGE
85 * @{ */
86# define NEM_WIN_PAGE_STATE_NOT_SET 0
87# define NEM_WIN_PAGE_STATE_UNMAPPED 1
88# define NEM_WIN_PAGE_STATE_READABLE 2
89# define NEM_WIN_PAGE_STATE_WRITABLE 3
90/** @} */
91
92/** Windows: Checks if a_GCPhys is subject to the limited A20 gate emulation. */
93# define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys) ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)
94/** Windows: Checks if a_GCPhys is relevant to the limited A20 gate emulation. */
95# define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys) \
96 ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )
97
98/** The CPUMCTX_EXTRN_XXX mask for IEM. */
99# define NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM ( IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT \
100 | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI )
101/** The CPUMCTX_EXTRN_XXX mask for IEM when raising exceptions. */
102# define NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT (IEM_CPUMCTX_EXTRN_XCPT_MASK | NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM)
103
104/** @name Windows: Interrupt window flags (NEM_WIN_INTW_F_XXX).
105 * @{ */
106# define NEM_WIN_INTW_F_NMI UINT8_C(0x01)
107# define NEM_WIN_INTW_F_REGULAR UINT8_C(0x02)
108# define NEM_WIN_INTW_F_PRIO_MASK UINT8_C(0x3c)
109# define NEM_WIN_INTW_F_PRIO_SHIFT 2
110/** @} */
111
112#endif /* RT_OS_WINDOWS */
113
114
115/** Trick to make slickedit see the static functions in the template. */
116#ifndef IN_SLICKEDIT
117# define NEM_TMPL_STATIC static
118#else
119# define NEM_TMPL_STATIC
120#endif
121
122
123/**
124 * Generic NEM exit type enumeration for use with EMHistoryAddExit.
125 *
126 * On windows we've got two different set of exit types and they are both jumping
127 * around the place value wise, so EM can use their values.
128 *
129 * @note We only have exit types for exits not covered by EM here.
130 */
131typedef enum NEMEXITTYPE
132{
133 /* windows: */
134 NEMEXITTYPE_UNRECOVERABLE_EXCEPTION = 1,
135 NEMEXITTYPE_INVALID_VP_REGISTER_VALUE,
136 NEMEXITTYPE_INTTERRUPT_WINDOW,
137 NEMEXITTYPE_HALT,
138 NEMEXITTYPE_XCPT_UD,
139 NEMEXITTYPE_XCPT_DB,
140 NEMEXITTYPE_XCPT_BP,
141 NEMEXITTYPE_CANCELED,
142 NEMEXITTYPE_MEMORY_ACCESS
143} NEMEXITTYPE;
144
145
146/**
147 * NEM VM Instance data.
148 */
149typedef struct NEM
150{
151 /** NEM_MAGIC. */
152 uint32_t u32Magic;
153
154 /** Set if enabled. */
155 bool fEnabled;
156 /** Set if long mode guests are allowed. */
157 bool fAllow64BitGuests;
158#ifdef RT_OS_WINDOWS
159 /** Set if we've created the EMTs. */
160 bool fCreatedEmts : 1;
161 /** WHvRunVpExitReasonX64Cpuid is supported. */
162 bool fExtendedMsrExit : 1;
163 /** WHvRunVpExitReasonX64MsrAccess is supported. */
164 bool fExtendedCpuIdExit : 1;
165 /** WHvRunVpExitReasonException is supported. */
166 bool fExtendedXcptExit : 1;
167 /** Set if we're using the ring-0 API to do the work. */
168 bool fUseRing0Runloop : 1;
169# ifdef NEM_WIN_WITH_A20
170 /** Set if we've started more than one CPU and cannot mess with A20. */
171 bool fA20Fixed : 1;
172 /** Set if A20 is enabled. */
173 bool fA20Enabled : 1;
174# endif
175 /** The reported CPU vendor. */
176 CPUMCPUVENDOR enmCpuVendor;
177 /** Cache line flush size as a power of two. */
178 uint8_t cCacheLineFlushShift;
179 /** The result of WHvCapabilityCodeProcessorFeatures. */
180 union
181 {
182 /** 64-bit view. */
183 uint64_t u64;
184# ifdef _WINHVAPIDEFS_H_
185 /** Interpreed features. */
186 WHV_PROCESSOR_FEATURES u;
187# endif
188 } uCpuFeatures;
189
190 /** The partition handle. */
191# ifdef _WINHVAPIDEFS_H_
192 WHV_PARTITION_HANDLE
193# else
194 RTHCUINTPTR
195# endif
196 hPartition;
197 /** The device handle for the partition, for use with Vid APIs or direct I/O
198 * controls. */
199 RTR3PTR hPartitionDevice;
200 /** The Hyper-V partition ID. */
201 uint64_t idHvPartition;
202
203 /** Number of currently mapped pages. */
204 uint32_t volatile cMappedPages;
205# ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
206 /** Max number of pages we dare map at once. */
207 uint32_t cMaxMappedPages;
208# endif
209 STAMCOUNTER StatMapPage;
210 STAMCOUNTER StatUnmapPage;
211# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
212 STAMCOUNTER StatRemapPage;
213 STAMCOUNTER StatRemapPageFailed;
214# elif !defined(VBOX_WITH_PGM_NEM_MODE)
215 STAMCOUNTER StatUnmapAllPages;
216# endif
217 STAMCOUNTER StatMapPageFailed;
218 STAMCOUNTER StatUnmapPageFailed;
219# ifdef VBOX_WITH_PGM_NEM_MODE
220 STAMPROFILE StatProfMapGpaRange;
221 STAMPROFILE StatProfUnmapGpaRange;
222# endif
223# ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
224 STAMPROFILE StatProfMapGpaRangePage;
225 STAMPROFILE StatProfUnmapGpaRangePage;
226# endif
227
228# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
229 /** Info about the VidGetHvPartitionId I/O control interface. */
230 NEMWINIOCTL IoCtlGetHvPartitionId;
231 /** Info about the VidGetPartitionProperty I/O control interface. */
232 NEMWINIOCTL IoCtlGetPartitionProperty;
233# endif
234# ifdef NEM_WIN_WITH_RING0_RUNLOOP
235 /** Info about the VidStartVirtualProcessor I/O control interface. */
236 NEMWINIOCTL IoCtlStartVirtualProcessor;
237 /** Info about the VidStopVirtualProcessor I/O control interface. */
238 NEMWINIOCTL IoCtlStopVirtualProcessor;
239 /** Info about the VidStopVirtualProcessor I/O control interface. */
240 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
241# endif
242
243 /** Statistics updated by NEMR0UpdateStatistics. */
244 struct
245 {
246 uint64_t cPagesAvailable;
247 uint64_t cPagesInUse;
248 } R0Stats;
249#endif /* RT_OS_WINDOWS */
250} NEM;
251/** Pointer to NEM VM instance data. */
252typedef NEM *PNEM;
253
254/** NEM::u32Magic value. */
255#define NEM_MAGIC UINT32_C(0x004d454e)
256/** NEM::u32Magic value after termination. */
257#define NEM_MAGIC_DEAD UINT32_C(0xdead1111)
258
259
260/**
261 * NEM VMCPU Instance data.
262 */
263typedef struct NEMCPU
264{
265 /** NEMCPU_MAGIC. */
266 uint32_t u32Magic;
267 /** Whether \#UD needs to be intercepted and presented to GIM. */
268 bool fGIMTrapXcptUD : 1;
269 /** Whether \#GP needs to be intercept for mesa driver workaround. */
270 bool fTrapXcptGpForLovelyMesaDrv: 1;
271#ifdef RT_OS_WINDOWS
272 /** The current state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
273 uint8_t fCurrentInterruptWindows;
274 /** The desired state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
275 uint8_t fDesiredInterruptWindows;
276 /** Last copy of HV_X64_VP_EXECUTION_STATE::InterruptShadow. */
277 bool fLastInterruptShadow : 1;
278# ifdef NEM_WIN_WITH_RING0_RUNLOOP
279 /** Pending VINF_NEM_FLUSH_TLB. */
280 int32_t rcPending;
281# else
282 uint32_t uPadding;
283# endif
284 /** The VID_MSHAGN_F_XXX flags.
285 * Either VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE or zero. */
286 uint32_t fHandleAndGetFlags;
287 /** What VidMessageSlotMap returns and is used for passing exit info. */
288 RTR3PTR pvMsgSlotMapping;
289 /** The windows thread handle. */
290 RTR3PTR hNativeThreadHandle;
291 /** Parameters for making Hyper-V hypercalls. */
292 union
293 {
294 uint8_t ab[64];
295 /** Arguments for NEMR0MapPages (HvCallMapGpaPages). */
296 struct
297 {
298 RTGCPHYS GCPhysSrc;
299 RTGCPHYS GCPhysDst; /**< Same as GCPhysSrc except maybe when the A20 gate is disabled. */
300 uint32_t cPages;
301 HV_MAP_GPA_FLAGS fFlags;
302 } MapPages;
303 /** Arguments for NEMR0UnmapPages (HvCallUnmapGpaPages). */
304 struct
305 {
306 RTGCPHYS GCPhys;
307 uint32_t cPages;
308 } UnmapPages;
309 /** Result from NEMR0QueryCpuTick. */
310 struct
311 {
312 uint64_t cTicks;
313 uint32_t uAux;
314 } QueryCpuTick;
315 /** Input and output for NEMR0DoExperiment. */
316 struct
317 {
318 uint32_t uItem;
319 bool fSuccess;
320 uint64_t uStatus;
321 uint64_t uLoValue;
322 uint64_t uHiValue;
323 } Experiment;
324 } Hypercall;
325 /** I/O control buffer, we always use this for I/O controls. */
326 union
327 {
328 uint8_t ab[64];
329 HV_PARTITION_ID idPartition;
330 HV_VP_INDEX idCpu;
331 struct
332 {
333 uint64_t enmProperty;
334 uint64_t uValue;
335 } GetProp;
336# ifdef VID_MSHAGN_F_GET_NEXT_MESSAGE
337 VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT MsgSlotHandleAndGetNext;
338# endif
339 } uIoCtlBuf;
340
341 /** @name Statistics
342 * @{ */
343 STAMCOUNTER StatExitPortIo;
344 STAMCOUNTER StatExitMemUnmapped;
345 STAMCOUNTER StatExitMemIntercept;
346 STAMCOUNTER StatExitHalt;
347 STAMCOUNTER StatExitInterruptWindow;
348 STAMCOUNTER StatExitCpuId;
349 STAMCOUNTER StatExitMsr;
350 STAMCOUNTER StatExitException;
351 STAMCOUNTER StatExitExceptionBp;
352 STAMCOUNTER StatExitExceptionDb;
353 STAMCOUNTER StatExitExceptionGp;
354 STAMCOUNTER StatExitExceptionGpMesa;
355 STAMCOUNTER StatExitExceptionUd;
356 STAMCOUNTER StatExitExceptionUdHandled;
357 STAMCOUNTER StatExitUnrecoverable;
358 STAMCOUNTER StatGetMsgTimeout;
359 STAMCOUNTER StatStopCpuSuccess;
360 STAMCOUNTER StatStopCpuPending;
361 STAMCOUNTER StatStopCpuPendingAlerts;
362 STAMCOUNTER StatStopCpuPendingOdd;
363 STAMCOUNTER StatCancelChangedState;
364 STAMCOUNTER StatCancelAlertedThread;
365 STAMCOUNTER StatBreakOnCancel;
366 STAMCOUNTER StatBreakOnFFPre;
367 STAMCOUNTER StatBreakOnFFPost;
368 STAMCOUNTER StatBreakOnStatus;
369 STAMCOUNTER StatImportOnDemand;
370 STAMCOUNTER StatImportOnReturn;
371 STAMCOUNTER StatImportOnReturnSkipped;
372 STAMCOUNTER StatQueryCpuTick;
373 /** @} */
374#endif /* RT_OS_WINDOWS */
375} NEMCPU;
376/** Pointer to NEM VMCPU instance data. */
377typedef NEMCPU *PNEMCPU;
378
379/** NEMCPU::u32Magic value. */
380#define NEMCPU_MAGIC UINT32_C(0x4d454e20)
381/** NEMCPU::u32Magic value after termination. */
382#define NEMCPU_MAGIC_DEAD UINT32_C(0xdead2222)
383
384
385#ifdef IN_RING0
386# ifdef RT_OS_WINDOWS
387/**
388 * Windows: Hypercall input/ouput page info.
389 */
390typedef struct NEMR0HYPERCALLDATA
391{
392 /** Host physical address of the hypercall input/output page. */
393 RTHCPHYS HCPhysPage;
394 /** Pointer to the hypercall input/output page. */
395 uint8_t *pbPage;
396 /** Handle to the memory object of the hypercall input/output page. */
397 RTR0MEMOBJ hMemObj;
398} NEMR0HYPERCALLDATA;
399/** Pointer to a Windows hypercall input/output page info. */
400typedef NEMR0HYPERCALLDATA *PNEMR0HYPERCALLDATA;
401# endif /* RT_OS_WINDOWS */
402
403/**
404 * NEM GVMCPU instance data.
405 */
406typedef struct NEMR0PERVCPU
407{
408# if defined(RT_OS_WINDOWS) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
409 /** Hypercall input/ouput page. */
410 NEMR0HYPERCALLDATA HypercallData;
411 /** Delta to add to convert a ring-0 pointer to a ring-3 one. */
412 uintptr_t offRing3ConversionDelta;
413# else
414 uint32_t uDummy;
415# endif
416} NEMR0PERVCPU;
417
418/**
419 * NEM GVM instance data.
420 */
421typedef struct NEMR0PERVM
422{
423# ifdef RT_OS_WINDOWS
424# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
425 /** The partition ID. */
426 uint64_t idHvPartition;
427 /** I/O control context. */
428 PSUPR0IOCTLCTX pIoCtlCtx;
429 /** Info about the VidGetHvPartitionId I/O control interface. */
430 NEMWINIOCTL IoCtlGetHvPartitionId;
431 /** Info about the VidGetPartitionProperty I/O control interface. */
432 NEMWINIOCTL IoCtlGetPartitionProperty;
433# endif
434# ifdef NEM_WIN_WITH_RING0_RUNLOOP
435 /** Info about the VidStartVirtualProcessor I/O control interface. */
436 NEMWINIOCTL IoCtlStartVirtualProcessor;
437 /** Info about the VidStopVirtualProcessor I/O control interface. */
438 NEMWINIOCTL IoCtlStopVirtualProcessor;
439 /** Info about the VidStopVirtualProcessor I/O control interface. */
440 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
441 /** Whether we may use the ring-0 runloop or not. */
442 bool fMayUseRing0Runloop;
443# endif
444
445# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
446 /** Hypercall input/ouput page for non-EMT. */
447 NEMR0HYPERCALLDATA HypercallData;
448 /** Critical section protecting use of HypercallData. */
449 RTCRITSECT HypercallDataCritSect;
450# endif
451
452# else
453 uint32_t uDummy;
454# endif
455} NEMR0PERVM;
456
457#endif /* IN_RING*/
458
459
460#ifdef IN_RING3
461int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced);
462int nemR3NativeInitAfterCPUM(PVM pVM);
463int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
464int nemR3NativeTerm(PVM pVM);
465void nemR3NativeReset(PVM pVM);
466void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi);
467VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu);
468bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu);
469bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable);
470void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
471#endif
472
473void nemHCNativeNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
474void nemHCNativeNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
475 RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
476int nemHCNativeNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
477 PGMPAGETYPE enmType, uint8_t *pu2State);
478
479
480#ifdef RT_OS_WINDOWS
481/** Maximum number of pages we can map in a single NEMR0MapPages call. */
482# define NEM_MAX_MAP_PAGES ((PAGE_SIZE - RT_UOFFSETOF(HV_INPUT_MAP_GPA_PAGES, PageList)) / sizeof(HV_SPA_PAGE_NUMBER))
483/** Maximum number of pages we can unmap in a single NEMR0UnmapPages call. */
484# define NEM_MAX_UNMAP_PAGES 4095
485
486#endif
487/** @} */
488
489RT_C_DECLS_END
490
491#endif /* !VMM_INCLUDED_SRC_include_NEMInternal_h */
492
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