VirtualBox

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

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

NEM: Separate stats for odd and alerts when stopping the CPU. bugref:9044.

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