summaryrefslogtreecommitdiffstats
path: root/include/iprt/nt/vid.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/iprt/nt/vid.h')
-rw-r--r--include/iprt/nt/vid.h313
1 files changed, 313 insertions, 0 deletions
diff --git a/include/iprt/nt/vid.h b/include/iprt/nt/vid.h
new file mode 100644
index 00000000..b8eed6bf
--- /dev/null
+++ b/include/iprt/nt/vid.h
@@ -0,0 +1,313 @@
+/** @file
+ * Virtualization Infrastructure Driver (VID) API.
+ */
+
+/*
+ * Copyright (C) 2018-2023 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 */
+