VirtualBox

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

Last change on this file since 74442 was 73282, checked in by vboxsync, 6 years ago

NEM/win: Kicked out VINF/VERR_NEM_UPDATE_APIC_BASE and VINF/VERR_NEM_CHANGE_PGM_MODE and associated complications. bugref:9044

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