1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
|
/** @file
* Virtualization Infrastructure Driver (VID) API.
*/
/*
* Copyright (C) 2018-2025 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef IPRT_INCLUDED_nt_vid_h
#define IPRT_INCLUDED_nt_vid_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include "hyperv.h"
/**
* Output from VidMessageSlotMap.
*/
typedef struct VID_MAPPED_MESSAGE_SLOT
{
/** The message block mapping. */
struct _HV_MESSAGE *pMsgBlock;
/** Copy of input iCpu. */
uint32_t iCpu;
/** Explicit padding. */
uint32_t uParentAdvisory;
} VID_MAPPED_MESSAGE_SLOT;
/** Pointer to VidMessageSlotMap output structure. */
typedef VID_MAPPED_MESSAGE_SLOT *PVID_MAPPED_MESSAGE_SLOT;
/** @name VID_MESSAGE_MAPPING_HEADER::enmVidMsgType values (wild guess).
* @{ */
/** Type mask, strips flags. */
#define VID_MESSAGE_TYPE_MASK UINT32_C(0x00ffffff)
/** No return message necessary. */
#define VID_MESSAGE_TYPE_FLAG_NO_RETURN UINT32_C(0x01000000)
/** Observed message values. */
typedef enum
{
/** Invalid zero value. */
VidMessageInvalid = 0,
/** Guessing this means a message from the hypervisor. */
VidMessageHypervisorMessage = 0x00000c | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
/** Guessing this means stop request completed. Message length is 1 byte. */
VidMessageStopRequestComplete = 0x00000d | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
} VID_MESSAGE_TYPE;
AssertCompileSize(VID_MESSAGE_TYPE, 4);
/** @} */
/**
* Header of the message mapping returned by VidMessageSlotMap.
*/
typedef struct VID_MESSAGE_MAPPING_HEADER
{
/** Current guess is that this is VID_MESSAGE_TYPE. */
VID_MESSAGE_TYPE enmVidMsgType;
/** The message size or so it seems (0x100). */
uint32_t cbMessage;
/** So far these have been zero. */
uint32_t aZeroPPadding[2+4];
} VID_MESSAGE_MAPPING_HEADER;
AssertCompileSize(VID_MESSAGE_MAPPING_HEADER, 32);
/**
* VID processor status (VidGetVirtualProcessorRunningStatus).
*
* @note This is used internally in VID.SYS, in 17101 it's at offset 8 in their
* 'pVCpu' structure.
*/
typedef enum
{
VidProcessorStatusStopped = 0,
VidProcessorStatusRunning,
VidProcessorStatusSuspended,
VidProcessorStatusUndefined = 0xffff
} VID_PROCESSOR_STATUS;
AssertCompileSize(VID_PROCESSOR_STATUS, 4);
/** I/O control input for VidMessageSlotHandleAndGetNext. */
typedef struct VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT
{
HV_VP_INDEX iCpu;
uint32_t fFlags; /**< VID_MSHAGN_F_GET_XXX*/
uint32_t cMillies; /**< Not present in build 17758 as the API changed to always to infinite waits. */
} VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
/** Pointer to input for VidMessageSlotHandleAndGetNext. */
typedef VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT *PVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
/** Pointer to const input for VidMessageSlotHandleAndGetNext. */
typedef VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT const *PCVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
/** @name VID_MSHAGN_F_GET_XXX - Flags for VidMessageSlotHandleAndGetNext
* @{ */
/** This will try get the next message, waiting if necessary.
* It is subject to NtAlertThread processing when it starts waiting. */
#define VID_MSHAGN_F_GET_NEXT_MESSAGE RT_BIT_32(0)
/** ACK the message as handled and resume execution/whatever.
* This is executed before VID_MSHAGN_F_GET_NEXT_MESSAGE and should not be
* subject to NtAlertThread side effects. */
#define VID_MSHAGN_F_HANDLE_MESSAGE RT_BIT_32(1)
/** Cancel VP execution (no other bit set).
* @since about build 17758. */
#define VID_MSHAGN_F_CANCEL RT_BIT_32(2)
/** @} */
/** A 64-bit version of HV_PARTITION_PROPERTY_CODE. */
typedef int64_t VID_PARTITION_PROPERTY_CODE;
#ifdef IN_RING3
RT_C_DECLS_BEGIN
/** Calling convention. */
#ifndef WINAPI
# define VIDAPI __stdcall
#else
# define VIDAPI WINAPI
#endif
/** Partition handle. */
#ifndef WINAPI
typedef void *VID_PARTITION_HANDLE;
#else
typedef HANDLE VID_PARTITION_HANDLE;
#endif
/**
* Gets the partition ID.
*
* The partition ID is the numeric identifier used when making hypercalls to the
* hypervisor.
*
* @note Starting with Windows 11 (or possibly earlier), this does not work on
* Exo partition as created by WHvCreatePartition. It returns a
* STATUS_NOT_IMPLEMENTED as the I/O control code is not allowed through.
* All partitions has an ID though, so just pure annoying blockheadedness
* sprung upon us w/o any chance of doing a memory managment rewrite in
* time.
*/
DECLIMPORT(BOOL) VIDAPI VidGetHvPartitionId(VID_PARTITION_HANDLE hPartition, HV_PARTITION_ID *pidPartition);
/**
* Get a partition property.
*
* @returns Success indicator (details in LastErrorValue).
* @param hPartition The partition handle.
* @param enmProperty The property to get. Is a HV_PARTITION_PROPERTY_CODE
* type, but seems to be passed around as a 64-bit integer
* for some reason.
* @param puValue Where to return the property value.
*/
DECLIMPORT(BOOL) VIDAPI VidGetPartitionProperty(VID_PARTITION_HANDLE hPartition, VID_PARTITION_PROPERTY_CODE enmProperty,
PHV_PARTITION_PROPERTY puValue);
/**
* @copydoc VidGetPartitionProperty
* @note Currently (Windows 11 GA) identical to VidGetPartitionProperty.
*/
DECLIMPORT(BOOL) VIDAPI VidGetExoPartitionProperty(VID_PARTITION_HANDLE hPartition, VID_PARTITION_PROPERTY_CODE enmProperty,
PHV_PARTITION_PROPERTY puValue);
/**
* Starts asynchronous execution of a virtual CPU.
*/
DECLIMPORT(BOOL) VIDAPI VidStartVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
/**
* Stops the asynchronous execution of a virtual CPU.
*
* @retval ERROR_VID_STOP_PENDING if busy with intercept, check messages.
*/
DECLIMPORT(BOOL) VIDAPI VidStopVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
/**
* WHvCreateVirtualProcessor boils down to a call to VidMessageSlotMap and
* some internal WinHvPlatform state fiddling.
*
* Looks like it maps memory and returns the pointer to it.
* VidMessageSlotHandleAndGetNext is later used to wait for the next message and
* put (??) it into that memory mapping.
*
* @returns Success indicator (details in LastErrorValue).
*
* @param hPartition The partition handle.
* @param pOutput Where to return the pointer to the message memory
* mapping. The CPU index is also returned here.
* @param iCpu The CPU to wait-and-get messages for.
*/
DECLIMPORT(BOOL) VIDAPI VidMessageSlotMap(VID_PARTITION_HANDLE hPartition, PVID_MAPPED_MESSAGE_SLOT pOutput, HV_VP_INDEX iCpu);
/**
* This is used by WHvRunVirtualProcessor to wait for the next exit msg.
*
* The message appears in the memory mapping returned by VidMessageSlotMap.
*
* @returns Success indicator (details only in LastErrorValue - LastStatusValue
* is not set).
* @retval STATUS_TIMEOUT for STATUS_TIMEOUT as well as STATUS_USER_APC and
* STATUS_ALERTED.
*
* @param hPartition The partition handle.
* @param iCpu The CPU to wait-and-get messages for.
* @param fFlags Flags, VID_MSHAGN_F_XXX.
*
* When starting or resuming execution, at least one of
* VID_MSHAGN_F_GET_NEXT_MESSAGE (bit 0) and
* VID_MSHAGN_F_HANDLE_MESSAGE (bit 1) must be set.
*
* When cancelling execution only VID_MSHAGN_F_CANCEL (big 2)
* must be set.
*
* @param cMillies The timeout, presumably in milliseconds. This parameter
* was dropped about build 17758.
*
* @todo Would be awfully nice if someone at Microsoft could hit at the
* flags here.
*/
DECLIMPORT(BOOL) VIDAPI VidMessageSlotHandleAndGetNext(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
uint32_t fFlags, uint32_t cMillies);
/**
* Gets the processor running status.
*
* This is probably only available in special builds, as one of the early I/O
* control dispatching routines will not let it thru. Lower down routines does
* implement it, so it's possible to patch it into working. This works for
* build 17101: eb vid+12180 0f 84 98 00 00 00
*
* @retval ERROR_NOT_IMPLEMENTED
*
* @remarks VidExoFastIoControlPartition probably disapproves of this too. It
* could be very handy for debugging upon occation.
*/
DECLIMPORT(BOOL) VIDAPI VidGetVirtualProcessorRunningStatus(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
VID_PROCESSOR_STATUS *penmStatus);
/**
* For query virtual processor registers and other state information.
*
* @returns Success indicator (details in LastErrorValue).
*/
DECLIMPORT(BOOL) VIDAPI VidGetVirtualProcessorState(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
HV_REGISTER_NAME const *paRegNames, uint32_t cRegisters,
HV_REGISTER_VALUE *paRegValues);
/**
* For setting virtual processor registers and other state information.
*
* @returns Success indicator (details in LastErrorValue).
*/
DECLIMPORT(BOOL) VIDAPI VidSetVirtualProcessorState(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
HV_REGISTER_NAME const *paRegNames, uint32_t cRegisters,
HV_REGISTER_VALUE const *paRegValues);
/**
* Wrapper around the HvCallGetMemoryBalance hypercall.
*
* When VID.SYS processes the request, it will also query
* HvPartitionPropertyVirtualTlbPageCount, so we're passing a 3rd return
* parameter in case the API is ever extended to match the I/O control.
*
* @returns Success indicator (details in LastErrorValue).
* @retval ERROR_NOT_IMPLEMENTED for exo partitions.
*
* @param hPartition The partition handle.
* @param pcPagesAvailable Where to return the number of unused pages
* still available to the partition.
* @param pcPagesInUse Where to return the number of pages currently
* in use by the partition.
* @param pReserved Pointer to dummy value, just in case they
* modify the API to include the nested TLB size.
*
* @note Not available for exo partitions, unfortunately. The
* VidExoFastIoControlPartition function deflects it, failing it with
* STATUS_NOT_IMPLEMENTED / ERROR_NOT_IMPLEMENTED.
*/
DECLIMPORT(BOOL) VIDAPI VidGetHvMemoryBalance(VID_PARTITION_HANDLE hPartition, uint64_t *pcPagesAvailable,
uint64_t *pcPagesInUse, uint64_t *pReserved);
RT_C_DECLS_END
#endif /* IN_RING3 */
#endif /* !IPRT_INCLUDED_nt_vid_h */
|