VirtualBox

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

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

VMM/NEM/win: New approach to A20: Reschedule to IEM. Logging. 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 92120 2021-10-28 00:31:35Z 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
220# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
221 /** Info about the VidGetHvPartitionId I/O control interface. */
222 NEMWINIOCTL IoCtlGetHvPartitionId;
223 /** Info about the VidGetPartitionProperty I/O control interface. */
224 NEMWINIOCTL IoCtlGetPartitionProperty;
225# endif
226# ifdef NEM_WIN_WITH_RING0_RUNLOOP
227 /** Info about the VidStartVirtualProcessor I/O control interface. */
228 NEMWINIOCTL IoCtlStartVirtualProcessor;
229 /** Info about the VidStopVirtualProcessor I/O control interface. */
230 NEMWINIOCTL IoCtlStopVirtualProcessor;
231 /** Info about the VidStopVirtualProcessor I/O control interface. */
232 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
233# endif
234
235 /** Statistics updated by NEMR0UpdateStatistics. */
236 struct
237 {
238 uint64_t cPagesAvailable;
239 uint64_t cPagesInUse;
240 } R0Stats;
241#endif /* RT_OS_WINDOWS */
242} NEM;
243/** Pointer to NEM VM instance data. */
244typedef NEM *PNEM;
245
246/** NEM::u32Magic value. */
247#define NEM_MAGIC UINT32_C(0x004d454e)
248/** NEM::u32Magic value after termination. */
249#define NEM_MAGIC_DEAD UINT32_C(0xdead1111)
250
251
252/**
253 * NEM VMCPU Instance data.
254 */
255typedef struct NEMCPU
256{
257 /** NEMCPU_MAGIC. */
258 uint32_t u32Magic;
259 /** Whether \#UD needs to be intercepted and presented to GIM. */
260 bool fGIMTrapXcptUD : 1;
261 /** Whether \#GP needs to be intercept for mesa driver workaround. */
262 bool fTrapXcptGpForLovelyMesaDrv: 1;
263#ifdef RT_OS_WINDOWS
264 /** The current state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
265 uint8_t fCurrentInterruptWindows;
266 /** The desired state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
267 uint8_t fDesiredInterruptWindows;
268 /** Last copy of HV_X64_VP_EXECUTION_STATE::InterruptShadow. */
269 bool fLastInterruptShadow : 1;
270# ifdef NEM_WIN_WITH_RING0_RUNLOOP
271 /** Pending VINF_NEM_FLUSH_TLB. */
272 int32_t rcPending;
273# else
274 uint32_t uPadding;
275# endif
276 /** The VID_MSHAGN_F_XXX flags.
277 * Either VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE or zero. */
278 uint32_t fHandleAndGetFlags;
279 /** What VidMessageSlotMap returns and is used for passing exit info. */
280 RTR3PTR pvMsgSlotMapping;
281 /** The windows thread handle. */
282 RTR3PTR hNativeThreadHandle;
283 /** Parameters for making Hyper-V hypercalls. */
284 union
285 {
286 uint8_t ab[64];
287 /** Arguments for NEMR0MapPages (HvCallMapGpaPages). */
288 struct
289 {
290 RTGCPHYS GCPhysSrc;
291 RTGCPHYS GCPhysDst; /**< Same as GCPhysSrc except maybe when the A20 gate is disabled. */
292 uint32_t cPages;
293 HV_MAP_GPA_FLAGS fFlags;
294 } MapPages;
295 /** Arguments for NEMR0UnmapPages (HvCallUnmapGpaPages). */
296 struct
297 {
298 RTGCPHYS GCPhys;
299 uint32_t cPages;
300 } UnmapPages;
301 /** Result from NEMR0QueryCpuTick. */
302 struct
303 {
304 uint64_t cTicks;
305 uint32_t uAux;
306 } QueryCpuTick;
307 /** Input and output for NEMR0DoExperiment. */
308 struct
309 {
310 uint32_t uItem;
311 bool fSuccess;
312 uint64_t uStatus;
313 uint64_t uLoValue;
314 uint64_t uHiValue;
315 } Experiment;
316 } Hypercall;
317 /** I/O control buffer, we always use this for I/O controls. */
318 union
319 {
320 uint8_t ab[64];
321 HV_PARTITION_ID idPartition;
322 HV_VP_INDEX idCpu;
323 struct
324 {
325 uint64_t enmProperty;
326 uint64_t uValue;
327 } GetProp;
328# ifdef VID_MSHAGN_F_GET_NEXT_MESSAGE
329 VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT MsgSlotHandleAndGetNext;
330# endif
331 } uIoCtlBuf;
332
333 /** @name Statistics
334 * @{ */
335 STAMCOUNTER StatExitPortIo;
336 STAMCOUNTER StatExitMemUnmapped;
337 STAMCOUNTER StatExitMemIntercept;
338 STAMCOUNTER StatExitHalt;
339 STAMCOUNTER StatExitInterruptWindow;
340 STAMCOUNTER StatExitCpuId;
341 STAMCOUNTER StatExitMsr;
342 STAMCOUNTER StatExitException;
343 STAMCOUNTER StatExitExceptionBp;
344 STAMCOUNTER StatExitExceptionDb;
345 STAMCOUNTER StatExitExceptionGp;
346 STAMCOUNTER StatExitExceptionGpMesa;
347 STAMCOUNTER StatExitExceptionUd;
348 STAMCOUNTER StatExitExceptionUdHandled;
349 STAMCOUNTER StatExitUnrecoverable;
350 STAMCOUNTER StatGetMsgTimeout;
351 STAMCOUNTER StatStopCpuSuccess;
352 STAMCOUNTER StatStopCpuPending;
353 STAMCOUNTER StatStopCpuPendingAlerts;
354 STAMCOUNTER StatStopCpuPendingOdd;
355 STAMCOUNTER StatCancelChangedState;
356 STAMCOUNTER StatCancelAlertedThread;
357 STAMCOUNTER StatBreakOnCancel;
358 STAMCOUNTER StatBreakOnFFPre;
359 STAMCOUNTER StatBreakOnFFPost;
360 STAMCOUNTER StatBreakOnStatus;
361 STAMCOUNTER StatImportOnDemand;
362 STAMCOUNTER StatImportOnReturn;
363 STAMCOUNTER StatImportOnReturnSkipped;
364 STAMCOUNTER StatQueryCpuTick;
365 /** @} */
366#endif /* RT_OS_WINDOWS */
367} NEMCPU;
368/** Pointer to NEM VMCPU instance data. */
369typedef NEMCPU *PNEMCPU;
370
371/** NEMCPU::u32Magic value. */
372#define NEMCPU_MAGIC UINT32_C(0x4d454e20)
373/** NEMCPU::u32Magic value after termination. */
374#define NEMCPU_MAGIC_DEAD UINT32_C(0xdead2222)
375
376
377#ifdef IN_RING0
378# ifdef RT_OS_WINDOWS
379/**
380 * Windows: Hypercall input/ouput page info.
381 */
382typedef struct NEMR0HYPERCALLDATA
383{
384 /** Host physical address of the hypercall input/output page. */
385 RTHCPHYS HCPhysPage;
386 /** Pointer to the hypercall input/output page. */
387 uint8_t *pbPage;
388 /** Handle to the memory object of the hypercall input/output page. */
389 RTR0MEMOBJ hMemObj;
390} NEMR0HYPERCALLDATA;
391/** Pointer to a Windows hypercall input/output page info. */
392typedef NEMR0HYPERCALLDATA *PNEMR0HYPERCALLDATA;
393# endif /* RT_OS_WINDOWS */
394
395/**
396 * NEM GVMCPU instance data.
397 */
398typedef struct NEMR0PERVCPU
399{
400# if defined(RT_OS_WINDOWS) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
401 /** Hypercall input/ouput page. */
402 NEMR0HYPERCALLDATA HypercallData;
403 /** Delta to add to convert a ring-0 pointer to a ring-3 one. */
404 uintptr_t offRing3ConversionDelta;
405# else
406 uint32_t uDummy;
407# endif
408} NEMR0PERVCPU;
409
410/**
411 * NEM GVM instance data.
412 */
413typedef struct NEMR0PERVM
414{
415# ifdef RT_OS_WINDOWS
416# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
417 /** The partition ID. */
418 uint64_t idHvPartition;
419 /** I/O control context. */
420 PSUPR0IOCTLCTX pIoCtlCtx;
421 /** Info about the VidGetHvPartitionId I/O control interface. */
422 NEMWINIOCTL IoCtlGetHvPartitionId;
423 /** Info about the VidGetPartitionProperty I/O control interface. */
424 NEMWINIOCTL IoCtlGetPartitionProperty;
425# endif
426# ifdef NEM_WIN_WITH_RING0_RUNLOOP
427 /** Info about the VidStartVirtualProcessor I/O control interface. */
428 NEMWINIOCTL IoCtlStartVirtualProcessor;
429 /** Info about the VidStopVirtualProcessor I/O control interface. */
430 NEMWINIOCTL IoCtlStopVirtualProcessor;
431 /** Info about the VidStopVirtualProcessor I/O control interface. */
432 NEMWINIOCTL IoCtlMessageSlotHandleAndGetNext;
433 /** Whether we may use the ring-0 runloop or not. */
434 bool fMayUseRing0Runloop;
435# endif
436
437# ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
438 /** Hypercall input/ouput page for non-EMT. */
439 NEMR0HYPERCALLDATA HypercallData;
440 /** Critical section protecting use of HypercallData. */
441 RTCRITSECT HypercallDataCritSect;
442# endif
443
444# else
445 uint32_t uDummy;
446# endif
447} NEMR0PERVM;
448
449#endif /* IN_RING*/
450
451
452#ifdef IN_RING3
453int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced);
454int nemR3NativeInitAfterCPUM(PVM pVM);
455int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
456int nemR3NativeTerm(PVM pVM);
457void nemR3NativeReset(PVM pVM);
458void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi);
459VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu);
460bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu);
461bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable);
462void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
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