VirtualBox

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

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

VMM/NEM/win: No mapping limits when in simplified memory management mode. bugref:10122

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.5 KB
Line 
1/* $Id: NEMInternal.h 91958 2021-10-21 14:34:49Z 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 /** Set if we've started more than one CPU and cannot mess with A20. */
170 bool fA20Fixed : 1;
171 /** Set if A20 is enabled. */
172 bool fA20Enabled : 1;
173 /** The reported CPU vendor. */
174 CPUMCPUVENDOR enmCpuVendor;
175 /** Cache line flush size as a power of two. */
176 uint8_t cCacheLineFlushShift;
177 /** The result of WHvCapabilityCodeProcessorFeatures. */
178 union
179 {
180 /** 64-bit view. */
181 uint64_t u64;
182# ifdef _WINHVAPIDEFS_H_
183 /** Interpreed features. */
184 WHV_PROCESSOR_FEATURES u;
185# endif
186 } uCpuFeatures;
187
188 /** The partition handle. */
189# ifdef _WINHVAPIDEFS_H_
190 WHV_PARTITION_HANDLE
191# else
192 RTHCUINTPTR
193# endif
194 hPartition;
195 /** The device handle for the partition, for use with Vid APIs or direct I/O
196 * controls. */
197 RTR3PTR hPartitionDevice;
198 /** The Hyper-V partition ID. */
199 uint64_t idHvPartition;
200
201 /** Number of currently mapped pages. */
202 uint32_t volatile cMappedPages;
203# ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
204 /** Max number of pages we dare map at once. */
205 uint32_t cMaxMappedPages;
206# endif
207 STAMCOUNTER StatMapPage;
208 STAMCOUNTER StatUnmapPage;
209# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
210 STAMCOUNTER StatRemapPage;
211 STAMCOUNTER StatRemapPageFailed;
212# elif !defined(VBOX_WITH_PGM_NEM_MODE)
213 STAMCOUNTER StatUnmapAllPages;
214# endif
215 STAMCOUNTER StatMapPageFailed;
216 STAMCOUNTER StatUnmapPageFailed;
217
218# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
219 /** Info about the VidGetHvPartitionId I/O control interface. */
220 NEMWINIOCTL IoCtlGetHvPartitionId;
221 /** Info about the VidGetPartitionProperty I/O control interface. */
222 NEMWINIOCTL IoCtlGetPartitionProperty;
223# endif
224# ifdef NEM_WIN_WITH_RING0_RUNLOOP
225 /** Info about the VidStartVirtualProcessor I/O control interface. */
226 NEMWINIOCTL IoCtlStartVirtualProcessor;
227 /** Info about the VidStopVirtualProcessor I/O control interface. */
228 NEMWINIOCTL IoCtlStopVirtualProcessor;
229 /** Info about the VidStopVirtualProcessor I/O control interface. */
230 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
231# endif
232
233 /** Statistics updated by NEMR0UpdateStatistics. */
234 struct
235 {
236 uint64_t cPagesAvailable;
237 uint64_t cPagesInUse;
238 } R0Stats;
239#endif /* RT_OS_WINDOWS */
240} NEM;
241/** Pointer to NEM VM instance data. */
242typedef NEM *PNEM;
243
244/** NEM::u32Magic value. */
245#define NEM_MAGIC UINT32_C(0x004d454e)
246/** NEM::u32Magic value after termination. */
247#define NEM_MAGIC_DEAD UINT32_C(0xdead1111)
248
249
250/**
251 * NEM VMCPU Instance data.
252 */
253typedef struct NEMCPU
254{
255 /** NEMCPU_MAGIC. */
256 uint32_t u32Magic;
257 /** Whether \#UD needs to be intercepted and presented to GIM. */
258 bool fGIMTrapXcptUD : 1;
259 /** Whether \#GP needs to be intercept for mesa driver workaround. */
260 bool fTrapXcptGpForLovelyMesaDrv: 1;
261#ifdef RT_OS_WINDOWS
262 /** The current state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
263 uint8_t fCurrentInterruptWindows;
264 /** The desired state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
265 uint8_t fDesiredInterruptWindows;
266 /** Last copy of HV_X64_VP_EXECUTION_STATE::InterruptShadow. */
267 bool fLastInterruptShadow : 1;
268# ifdef NEM_WIN_WITH_RING0_RUNLOOP
269 /** Pending VINF_NEM_FLUSH_TLB. */
270 int32_t rcPending;
271# else
272 uint32_t uPadding;
273# endif
274 /** The VID_MSHAGN_F_XXX flags.
275 * Either VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE or zero. */
276 uint32_t fHandleAndGetFlags;
277 /** What VidMessageSlotMap returns and is used for passing exit info. */
278 RTR3PTR pvMsgSlotMapping;
279 /** The windows thread handle. */
280 RTR3PTR hNativeThreadHandle;
281 /** Parameters for making Hyper-V hypercalls. */
282 union
283 {
284 uint8_t ab[64];
285 /** Arguments for NEMR0MapPages (HvCallMapGpaPages). */
286 struct
287 {
288 RTGCPHYS GCPhysSrc;
289 RTGCPHYS GCPhysDst; /**< Same as GCPhysSrc except maybe when the A20 gate is disabled. */
290 uint32_t cPages;
291 HV_MAP_GPA_FLAGS fFlags;
292 } MapPages;
293 /** Arguments for NEMR0UnmapPages (HvCallUnmapGpaPages). */
294 struct
295 {
296 RTGCPHYS GCPhys;
297 uint32_t cPages;
298 } UnmapPages;
299 /** Result from NEMR0QueryCpuTick. */
300 struct
301 {
302 uint64_t cTicks;
303 uint32_t uAux;
304 } QueryCpuTick;
305 /** Input and output for NEMR0DoExperiment. */
306 struct
307 {
308 uint32_t uItem;
309 bool fSuccess;
310 uint64_t uStatus;
311 uint64_t uLoValue;
312 uint64_t uHiValue;
313 } Experiment;
314 } Hypercall;
315 /** I/O control buffer, we always use this for I/O controls. */
316 union
317 {
318 uint8_t ab[64];
319 HV_PARTITION_ID idPartition;
320 HV_VP_INDEX idCpu;
321 struct
322 {
323 uint64_t enmProperty;
324 uint64_t uValue;
325 } GetProp;
326# ifdef VID_MSHAGN_F_GET_NEXT_MESSAGE
327 VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT MsgSlotHandleAndGetNext;
328# endif
329 } uIoCtlBuf;
330
331 /** @name Statistics
332 * @{ */
333 STAMCOUNTER StatExitPortIo;
334 STAMCOUNTER StatExitMemUnmapped;
335 STAMCOUNTER StatExitMemIntercept;
336 STAMCOUNTER StatExitHalt;
337 STAMCOUNTER StatExitInterruptWindow;
338 STAMCOUNTER StatExitCpuId;
339 STAMCOUNTER StatExitMsr;
340 STAMCOUNTER StatExitException;
341 STAMCOUNTER StatExitExceptionBp;
342 STAMCOUNTER StatExitExceptionDb;
343 STAMCOUNTER StatExitExceptionGp;
344 STAMCOUNTER StatExitExceptionGpMesa;
345 STAMCOUNTER StatExitExceptionUd;
346 STAMCOUNTER StatExitExceptionUdHandled;
347 STAMCOUNTER StatExitUnrecoverable;
348 STAMCOUNTER StatGetMsgTimeout;
349 STAMCOUNTER StatStopCpuSuccess;
350 STAMCOUNTER StatStopCpuPending;
351 STAMCOUNTER StatStopCpuPendingAlerts;
352 STAMCOUNTER StatStopCpuPendingOdd;
353 STAMCOUNTER StatCancelChangedState;
354 STAMCOUNTER StatCancelAlertedThread;
355 STAMCOUNTER StatBreakOnCancel;
356 STAMCOUNTER StatBreakOnFFPre;
357 STAMCOUNTER StatBreakOnFFPost;
358 STAMCOUNTER StatBreakOnStatus;
359 STAMCOUNTER StatImportOnDemand;
360 STAMCOUNTER StatImportOnReturn;
361 STAMCOUNTER StatImportOnReturnSkipped;
362 STAMCOUNTER StatQueryCpuTick;
363 /** @} */
364#endif /* RT_OS_WINDOWS */
365} NEMCPU;
366/** Pointer to NEM VMCPU instance data. */
367typedef NEMCPU *PNEMCPU;
368
369/** NEMCPU::u32Magic value. */
370#define NEMCPU_MAGIC UINT32_C(0x4d454e20)
371/** NEMCPU::u32Magic value after termination. */
372#define NEMCPU_MAGIC_DEAD UINT32_C(0xdead2222)
373
374
375#ifdef IN_RING0
376# ifdef RT_OS_WINDOWS
377/**
378 * Windows: Hypercall input/ouput page info.
379 */
380typedef struct NEMR0HYPERCALLDATA
381{
382 /** Host physical address of the hypercall input/output page. */
383 RTHCPHYS HCPhysPage;
384 /** Pointer to the hypercall input/output page. */
385 uint8_t *pbPage;
386 /** Handle to the memory object of the hypercall input/output page. */
387 RTR0MEMOBJ hMemObj;
388} NEMR0HYPERCALLDATA;
389/** Pointer to a Windows hypercall input/output page info. */
390typedef NEMR0HYPERCALLDATA *PNEMR0HYPERCALLDATA;
391# endif /* RT_OS_WINDOWS */
392
393/**
394 * NEM GVMCPU instance data.
395 */
396typedef struct NEMR0PERVCPU
397{
398# if defined(RT_OS_WINDOWS) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
399 /** Hypercall input/ouput page. */
400 NEMR0HYPERCALLDATA HypercallData;
401 /** Delta to add to convert a ring-0 pointer to a ring-3 one. */
402 uintptr_t offRing3ConversionDelta;
403# else
404 uint32_t uDummy;
405# endif
406} NEMR0PERVCPU;
407
408/**
409 * NEM GVM instance data.
410 */
411typedef struct NEMR0PERVM
412{
413# ifdef RT_OS_WINDOWS
414# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
415 /** The partition ID. */
416 uint64_t idHvPartition;
417 /** I/O control context. */
418 PSUPR0IOCTLCTX pIoCtlCtx;
419 /** Info about the VidGetHvPartitionId I/O control interface. */
420 NEMWINIOCTL IoCtlGetHvPartitionId;
421 /** Info about the VidGetPartitionProperty I/O control interface. */
422 NEMWINIOCTL IoCtlGetPartitionProperty;
423# endif
424# ifdef NEM_WIN_WITH_RING0_RUNLOOP
425 /** Info about the VidStartVirtualProcessor I/O control interface. */
426 NEMWINIOCTL IoCtlStartVirtualProcessor;
427 /** Info about the VidStopVirtualProcessor I/O control interface. */
428 NEMWINIOCTL IoCtlStopVirtualProcessor;
429 /** Info about the VidStopVirtualProcessor I/O control interface. */
430 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
431 /** Whether we may use the ring-0 runloop or not. */
432 bool fMayUseRing0Runloop;
433# endif
434
435# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
436 /** Hypercall input/ouput page for non-EMT. */
437 NEMR0HYPERCALLDATA HypercallData;
438 /** Critical section protecting use of HypercallData. */
439 RTCRITSECT HypercallDataCritSect;
440# endif
441
442# else
443 uint32_t uDummy;
444# endif
445} NEMR0PERVM;
446
447#endif /* IN_RING*/
448
449
450#ifdef IN_RING3
451int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced);
452int nemR3NativeInitAfterCPUM(PVM pVM);
453int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
454int nemR3NativeTerm(PVM pVM);
455void nemR3NativeReset(PVM pVM);
456void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi);
457VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu);
458bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu);
459bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable);
460void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
461
462void nemR3NativeNotifySetA20(PVMCPU pVCpu, bool fEnabled);
463#endif
464
465void nemHCNativeNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
466void nemHCNativeNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
467 RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
468int nemHCNativeNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
469 PGMPAGETYPE enmType, uint8_t *pu2State);
470
471
472#ifdef RT_OS_WINDOWS
473/** Maximum number of pages we can map in a single NEMR0MapPages call. */
474# define NEM_MAX_MAP_PAGES ((PAGE_SIZE - RT_UOFFSETOF(HV_INPUT_MAP_GPA_PAGES, PageList)) / sizeof(HV_SPA_PAGE_NUMBER))
475/** Maximum number of pages we can unmap in a single NEMR0UnmapPages call. */
476# define NEM_MAX_UNMAP_PAGES 4095
477
478#endif
479/** @} */
480
481RT_C_DECLS_END
482
483#endif /* !VMM_INCLUDED_SRC_include_NEMInternal_h */
484
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