VirtualBox

Changeset 71129 in vbox


Ignore:
Timestamp:
Feb 26, 2018 3:58:50 PM (7 years ago)
Author:
vboxsync
Message:

VMM/NEM/win: Reimplemented virtual process API, optimizing the cancel case and prepping for doing this from ring-0. bugref:9044

Location:
trunk
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/vm.h

    r71075 r71129  
    7979    /** Executing guest code using NEM. */
    8080    VMCPUSTATE_STARTED_EXEC_NEM,
     81    VMCPUSTATE_STARTED_EXEC_NEM_WAIT,
     82    VMCPUSTATE_STARTED_EXEC_NEM_CANCELED,
    8183    /** Halted. */
    8284    VMCPUSTATE_STARTED_HALTED,
  • trunk/include/VBox/vmm/vmapi.h

    r69107 r71129  
    485485VMMR3_INT_DECL(RTCPUID)     VMR3GetVMCPUId(PVM pVM);
    486486VMMR3_INT_DECL(bool)        VMR3IsLongModeAllowed(PVM pVM);
     487VMMR3_INT_DECL(RTTHREAD)    VMR3GetThreadHandle(PUVMCPU pUVCpu);
    487488VMMR3DECL(RTTHREAD)         VMR3GetVMCPUThread(PUVM pUVM);
    488489VMMR3DECL(RTNATIVETHREAD)   VMR3GetVMCPUNativeThread(PVM pVM);
  • trunk/include/iprt/nt/hyperv.h

    r71087 r71129  
    2828#define ___iprt_nt_hyperv_h
    2929
     30
    3031#ifndef IN_IDA_PRO
    3132# include <iprt/types.h>
     
    5354/** Hyper-V unsigned 128-bit integer type.   */
    5455typedef struct { uint64_t Low64, High64; } HV_UINT128;
     56/** Hyper-V port ID. */
     57typedef union
     58{
     59    uint32_t        AsUINT32;
     60    struct
     61    {
     62        uint32_t    Id       : 24;
     63        uint32_t    Reserved : 8;
     64    };
     65} HV_PORT_ID;
     66/** Pointer to a Hyper-V port ID. */
     67typedef HV_PORT_ID *PHV_PORT_ID;
    5568
    5669
     
    917930    };
    918931} HV_X64_SEGMENT_REGISTER;
     932AssertCompileSize(HV_X64_SEGMENT_REGISTER, 16);
    919933/** Pointer to a value of HvX64RegisterEs..Tr. */
    920934typedef HV_X64_SEGMENT_REGISTER *PHV_X64_SEGMENT_REGISTER;
     
    928942    uint64_t            Base;
    929943} HV_X64_TABLE_REGISTER;
     944AssertCompileSize(HV_X64_TABLE_REGISTER, 16);
    930945/** Pointer to a value of HvX64RegisterIdtr/Gdtrr. */
    931946typedef HV_X64_TABLE_REGISTER *PHV_X64_TABLE_REGISTER;
     
    10831098
    10841099
     1100
     1101/**
     1102 * Hyper-V SyncIC message types.
     1103 */
     1104typedef enum
     1105{
     1106    HvMessageTypeNone = 0x00000000,
     1107
     1108    HvMessageTypeUnmappedGpa = 0x80000000,
     1109    HvMessageTypeGpaIntercept,
     1110
     1111    HvMessageTimerExpired = 0x80000010,
     1112
     1113    HvMessageTypeInvalidVpRegisterValue = 0x80000020,
     1114    HvMessageTypeUnrecoverableException,
     1115    HvMessageTypeUnsupportedFeature,
     1116    HvMessageTypeTlbPageSizeMismatch,                   /**< @since v5 */
     1117
     1118    /** @note Same as HvMessageTypeX64ApicEoi? Gone in 5.0.  Missing from 7600 WDK
     1119     *        headers even if it's in the 2.0 docs.  */
     1120    HvMessageTypeApicEoi = 0x80000030,
     1121    /** @note Same as HvMessageTypeX64LegacyFpError? Gone in 5.0, whereas 4.0b
     1122     *        calls it HvMessageTypeX64LegacyFpError.  Missing from 7600 WDK
     1123     *        headers even if it's in the 2.0 docs. */
     1124    HvMessageTypeFerrAsserted,
     1125
     1126    HvMessageTypeEventLogBufferComplete = 0x80000040,
     1127
     1128    HvMessageTypeX64IoPortIntercept = 0x80010000,
     1129    HvMessageTypeX64MsrIntercept,
     1130    HvMessageTypeX64CpuidIntercept,
     1131    HvMessageTypeX64ExceptionIntercept,
     1132    /** @note Appeared in 5.0 docs, but were here in 7600 WDK headers already. */
     1133    HvMessageTypeX64ApicEoi,
     1134    /** @note Appeared in 5.0 docs, but were here in 7600 WDK headers already. */
     1135    HvMessageTypeX64LegacyFpError,
     1136    /** @since v5   */
     1137    HvMessageTypeX64RegisterIntercept,
     1138    /** @since WinHvPlatform? */
     1139    HvMessageTypeX64Halt,
     1140    /** @since WinHvPlatform? */
     1141    HvMessageTypeX64InterruptWindow
     1142
     1143} HV_MESSAGE_TYPE;
     1144AssertCompileSize(HV_MESSAGE_TYPE, 4);
     1145AssertCompile(HvMessageTypeX64RegisterIntercept == 0x80010006);
     1146AssertCompile(HvMessageTypeX64Halt == 0x80010007);
     1147AssertCompile(HvMessageTypeX64InterruptWindow == 0x80010008);
     1148/** Pointer to a Hyper-V SyncIC message type. */
     1149typedef HV_MESSAGE_TYPE *PHV_MESSAGE_TYPE;
     1150
     1151/** Flag set for hypervisor messages, guest cannot send messages with this
     1152 *  flag set. */
     1153#define HV_MESSAGE_TYPE_HYPERVISOR_MASK     UINT32_C(0x80000000)
     1154
     1155/** Hyper-V SynIC message size (they are fixed sized). */
     1156#define HV_MESSAGE_SIZE                     256
     1157/** Maximum Hyper-V SynIC message payload size in bytes. */
     1158#define HV_MESSAGE_MAX_PAYLOAD_BYTE_COUNT   (HV_MESSAGE_SIZE - 16)
     1159/** Maximum Hyper-V SynIC message payload size in QWORDs (uint64_t). */
     1160#define HV_MESSAGE_MAX_PAYLOAD_QWORD_COUNT  (HV_MESSAGE_MAX_PAYLOAD_BYTE_COUNT / 8)
     1161
     1162/** SynIC message flags.   */
     1163typedef union
     1164{
     1165    uint8_t             AsUINT8;
     1166    struct
     1167    {
     1168        /** Messages are pending in the queue. */
     1169        uint8_t         MessagePending : 1;
     1170        uint8_t         Reserved : 7;
     1171    };
     1172} HV_MESSAGE_FLAGS;
     1173AssertCompileSize(HV_MESSAGE_FLAGS, 1);
     1174
     1175/** SynIC message header. */
     1176typedef struct
     1177{
     1178    HV_MESSAGE_TYPE     MessageType;
     1179    /** The 2.0-5.0b docs all have this incorrectly switched with 'Reserved', WDK 7600 got it right. */
     1180    uint8_t             PayloadSize;
     1181    HV_MESSAGE_FLAGS    MessageFlags;
     1182    uint16_t            Reserved;
     1183    union
     1184    {
     1185        uint64_t        OriginationId;
     1186        HV_PARTITION_ID Sender;
     1187        HV_PORT_ID      Port;
     1188    };
     1189} HV_MESSAGE_HEADER;
     1190AssertCompileSize(HV_MESSAGE_HEADER, 16);
     1191/** Pointer to a Hyper-V message header. */
     1192typedef HV_MESSAGE_HEADER *PHV_MESSAGE_HEADER;
     1193/** Pointer to a const Hyper-V message header. */
     1194typedef HV_MESSAGE_HEADER const *PCHV_MESSAGE_HEADER;
     1195
     1196
     1197
     1198/** @name Intercept access type.
     1199 * @{ */
     1200typedef uint8_t HV_INTERCEPT_ACCESS_TYPE;
     1201#define HV_INTERCEPT_ACCESS_READ            0
     1202#define HV_INTERCEPT_ACCESS_WRITE           1
     1203#define HV_INTERCEPT_ACCESS_EXECUTE         2
     1204/** @} */
     1205
     1206/** @name Intercept access type mask.
     1207 * @{ */
     1208typedef uint32_t HV_INTERCEPT_ACCESS_TYPE_MASK;
     1209#define HV_INTERCEPT_ACCESS_MASK_NONE       0
     1210#define HV_INTERCEPT_ACCESS_MASK_READ       1
     1211#define HV_INTERCEPT_ACCESS_MASK_WRITE      2
     1212#define HV_INTERCEPT_ACCESS_MASK_EXECUTE    4
     1213/** @} */
     1214
     1215/** X64 intercept execution state.
     1216 * @sa WHV_X64_VP_EXECUTION_STATE */
     1217typedef union
     1218{
     1219    uint16_t            AsUINT16;
     1220    struct
     1221    {
     1222        uint16_t        Cpl                 : 2;
     1223        uint16_t        Cr0Pe               : 1;
     1224        uint16_t        Cr0Am               : 1;
     1225        uint16_t        EferLma             : 1;
     1226        uint16_t        DebugActive         : 1;
     1227        uint16_t        InterruptionPending : 1;
     1228        uint16_t        Reserved0           : 5;
     1229        uint16_t        InterruptShadow     : 1;
     1230        uint16_t        Reserved1           : 3;
     1231    };
     1232} HV_X64_VP_EXECUTION_STATE;
     1233AssertCompileSize(HV_X64_VP_EXECUTION_STATE, 2);
     1234/** Pointer to X86 intercept execution state. */
     1235typedef HV_X64_VP_EXECUTION_STATE *PHV_X64_VP_EXECUTION_STATE;
     1236/** Pointer to const X86 intercept execution state. */
     1237typedef HV_X64_VP_EXECUTION_STATE const *PCHV_X64_VP_EXECUTION_STATE;
     1238
     1239/** X64 intercept message header. */
     1240typedef struct
     1241{
     1242    HV_VP_INDEX                     VpIndex;                /**< 0x00 */
     1243    uint8_t                         InstructionLength;      /**< 0x04: Zero if not available, instruction fetch exit, ... */
     1244    HV_INTERCEPT_ACCESS_TYPE        InterceptAccessType;    /**< 0x05 */
     1245    HV_X64_VP_EXECUTION_STATE       ExecutionState;         /**< 0x06 */
     1246    HV_X64_SEGMENT_REGISTER         CsSegment;              /**< 0x08 */
     1247    uint64_t                        Rip;                    /**< 0x18 */
     1248    uint64_t                        Rflags;                 /**< 0x20 */
     1249} HV_X64_INTERCEPT_MESSAGE_HEADER;
     1250AssertCompileSize(HV_X64_INTERCEPT_MESSAGE_HEADER, 40);
     1251/** Pointer to a x86 intercept message header. */
     1252typedef HV_X64_INTERCEPT_MESSAGE_HEADER *PHV_X64_INTERCEPT_MESSAGE_HEADER;
     1253
     1254
     1255/** X64 memory access flags (HvMessageTypeGpaIntercept, HvMessageTypeUnmappedGpa).
     1256 * @sa WHV_MEMORY_ACCESS_INFO */
     1257typedef union
     1258{
     1259    uint8_t             AsUINT8;
     1260    struct
     1261    {
     1262        uint8_t         GvaValid : 1;
     1263        uint8_t         Reserved : 7;
     1264    };
     1265} HV_X64_MEMORY_ACCESS_INFO;
     1266AssertCompileSize(HV_X64_MEMORY_ACCESS_INFO, 1);
     1267
     1268/** The payload format for HvMessageTypeGpaIntercept and HvMessageTypeUnmappedGpa.
     1269 * @sa   WHV_MEMORY_ACCESS_CONTEXT
     1270 * @note max message size. */
     1271typedef struct
     1272{
     1273    HV_X64_INTERCEPT_MESSAGE_HEADER Header;                 /**< 0x00 */
     1274    HV_CACHE_TYPE                   CacheType;              /**< 0x28 */
     1275    uint8_t                         InstructionByteCount;   /**< 0x2c */
     1276    HV_X64_MEMORY_ACCESS_INFO       MemoryAccessInfo;       /**< 0x2d */
     1277    uint16_t                        Reserved1;              /**< 0x2e */
     1278    uint64_t                        GuestVirtualAddress;    /**< 0x30 */
     1279    uint64_t                        GuestPhysicalAddress;   /**< 0x38 */
     1280    uint8_t                         InstructionBytes[16];   /**< 0x40 */
     1281    /* We don't the following (v5 / WinHvPlatform): */
     1282    HV_X64_SEGMENT_REGISTER         DsSegment;              /**< 0x50 */
     1283    HV_X64_SEGMENT_REGISTER         SsSegment;              /**< 0x60 */
     1284    uint64_t                        Rax;                    /**< 0x70 */
     1285    uint64_t                        Rcx;                    /**< 0x78 */
     1286    uint64_t                        Rdx;                    /**< 0x80 */
     1287    uint64_t                        Rbx;                    /**< 0x88 */
     1288    uint64_t                        Rsp;                    /**< 0x90 */
     1289    uint64_t                        Rbp;                    /**< 0x98 */
     1290    uint64_t                        Rsi;                    /**< 0xa0 */
     1291    uint64_t                        Rdi;                    /**< 0xa8 */
     1292    uint64_t                        R8;                     /**< 0xb0 */
     1293    uint64_t                        R9;                     /**< 0xb8 */
     1294    uint64_t                        R10;                    /**< 0xc0 */
     1295    uint64_t                        R11;                    /**< 0xc8 */
     1296    uint64_t                        R12;                    /**< 0xd0 */
     1297    uint64_t                        R13;                    /**< 0xd8 */
     1298    uint64_t                        R14;                    /**< 0xe0 */
     1299    uint64_t                        R15;                    /**< 0xe8 */
     1300} HV_X64_MEMORY_INTERCEPT_MESSAGE;
     1301AssertCompileSize(HV_X64_MEMORY_INTERCEPT_MESSAGE, 0xf0);
     1302AssertCompileMemberOffset(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment, 0x50);
     1303/** Pointer to a HvMessageTypeGpaIntercept or HvMessageTypeUnmappedGpa payload. */
     1304typedef HV_X64_MEMORY_INTERCEPT_MESSAGE *PHV_X64_MEMORY_INTERCEPT_MESSAGE;
     1305/** Pointer to a const HvMessageTypeGpaIntercept or HvMessageTypeUnmappedGpa payload. */
     1306typedef HV_X64_MEMORY_INTERCEPT_MESSAGE const *PCHV_X64_MEMORY_INTERCEPT_MESSAGE;
     1307
     1308
     1309/** X64 I/O port access information (HvMessageTypeX64IoPortIntercept). */
     1310typedef union HV_X64_IO_PORT_ACCESS_INFO
     1311{
     1312    uint8_t             AsUINT8;
     1313    struct
     1314    {
     1315        uint8_t         AccessSize  : 3;
     1316        uint8_t         StringOp    : 1;
     1317        uint8_t         RepPrefix   : 1;
     1318        uint8_t         Reserved    : 3;
     1319    };
     1320} HV_X64_IO_PORT_ACCESS_INFO;
     1321AssertCompileSize(HV_X64_IO_PORT_ACCESS_INFO, 1);
     1322
     1323/** The payload format for HvMessageTypeX64IoPortIntercept.  */
     1324typedef struct _HV_X64_IO_PORT_INTERCEPT_MESSAGE
     1325{
     1326    HV_X64_INTERCEPT_MESSAGE_HEADER     Header;                 /**< 0x00 */
     1327    uint16_t                            PortNumber;             /**< 0x28 */
     1328    HV_X64_IO_PORT_ACCESS_INFO          AccessInfo;             /**< 0x2a */
     1329    uint8_t                             InstructionByteCount;   /**< 0x2b */
     1330    uint32_t                            Reserved;               /**< 0x2c */
     1331    uint64_t                            Rax;                    /**< 0x30 */
     1332    uint8_t                             InstructionBytes[16];   /**< 0x38 */
     1333    HV_X64_SEGMENT_REGISTER             DsSegment;              /**< 0x48 */
     1334    HV_X64_SEGMENT_REGISTER             EsSegment;              /**< 0x58 */
     1335    uint64_t                            Rcx;                    /**< 0x68 */
     1336    uint64_t                            Rsi;                    /**< 0x70 */
     1337    uint64_t                            Rdi;                    /**< 0x78 */
     1338} HV_X64_IO_PORT_INTERCEPT_MESSAGE;
     1339AssertCompileSize(HV_X64_IO_PORT_INTERCEPT_MESSAGE, 128);
     1340/** Pointer to a HvMessageTypeX64IoPortIntercept payload. */
     1341typedef HV_X64_IO_PORT_INTERCEPT_MESSAGE *PHV_X64_IO_PORT_INTERCEPT_MESSAGE;
     1342/** Pointer to a const HvMessageTypeX64IoPortIntercept payload. */
     1343typedef HV_X64_IO_PORT_INTERCEPT_MESSAGE const *PCHV_X64_IO_PORT_INTERCEPT_MESSAGE;
     1344
     1345/** Full I/O port message. */
     1346typedef struct
     1347{
     1348    HV_MESSAGE_HEADER                   MsgHdr;
     1349    HV_X64_IO_PORT_INTERCEPT_MESSAGE    Payload;
     1350} HV_X64_IO_PORT_INTERCEPT_MESSAGE_FULL;
     1351
     1352
     1353/** X64 exception information (HvMessageTypeX64ExceptionIntercept).
     1354 * @sa WHV_VP_EXCEPTION_INFO */
     1355typedef union
     1356{
     1357    uint8_t             AsUINT8;
     1358    struct
     1359    {
     1360        uint8_t         ErrorCodeValid : 1;
     1361        /** @todo WHV_VP_EXCEPTION_INFO::SoftwareException   */
     1362        uint8_t         Reserved       : 7;
     1363    };
     1364} HV_X64_EXCEPTION_INFO;
     1365AssertCompileSize(HV_X64_EXCEPTION_INFO, 1);
     1366
     1367/** The payload format for HvMessageTypeX64ExceptionIntercept.
     1368 * @sa   WHV_VP_EXCEPTION_CONTEXT
     1369 * @note max message size. */
     1370typedef struct
     1371{
     1372    HV_X64_INTERCEPT_MESSAGE_HEADER     Header;                 /**< 0x00 */
     1373    uint16_t                            ExceptionVector;        /**< 0x28 */
     1374    HV_X64_EXCEPTION_INFO               ExceptionInfo;          /**< 0x2a */
     1375    uint8_t                             InstructionByteCount;   /**< 0x2b */
     1376    uint32_t                            ErrorCode;              /**< 0x2c */
     1377    uint64_t                            ExceptionParameter;     /**< 0x30 */
     1378    uint64_t                            Reserved;               /**< 0x38 */
     1379    uint8_t                             InstructionBytes[16];   /**< 0x40 */
     1380    HV_X64_SEGMENT_REGISTER             DsSegment;              /**< 0x50 */
     1381    HV_X64_SEGMENT_REGISTER             SsSegment;              /**< 0x60 */
     1382    uint64_t                            Rax;                    /**< 0x70 */
     1383    uint64_t                            Rcx;                    /**< 0x78 */
     1384    uint64_t                            Rdx;                    /**< 0x80 */
     1385    uint64_t                            Rbx;                    /**< 0x88 */
     1386    uint64_t                            Rsp;                    /**< 0x90 */
     1387    uint64_t                            Rbp;                    /**< 0x98 */
     1388    uint64_t                            Rsi;                    /**< 0xa0 */
     1389    uint64_t                            Rdi;                    /**< 0xa8 */
     1390    uint64_t                            R8;                     /**< 0xb0 */
     1391    uint64_t                            R9;                     /**< 0xb8 */
     1392    uint64_t                            R10;                    /**< 0xc0 */
     1393    uint64_t                            R11;                    /**< 0xc8 */
     1394    uint64_t                            R12;                    /**< 0xd0 */
     1395    uint64_t                            R13;                    /**< 0xd8 */
     1396    uint64_t                            R14;                    /**< 0xe0 */
     1397    uint64_t                            R15;                    /**< 0xe8 */
     1398} HV_X64_EXCEPTION_INTERCEPT_MESSAGE;
     1399AssertCompileSize(HV_X64_EXCEPTION_INTERCEPT_MESSAGE, 0xf0);
     1400/** Pointer to a HvMessageTypeX64ExceptionIntercept payload. */
     1401typedef HV_X64_EXCEPTION_INTERCEPT_MESSAGE *PHV_X64_EXCEPTION_INTERCEPT_MESSAGE;
     1402/** Pointer to a ocnst HvMessageTypeX64ExceptionIntercept payload. */
     1403typedef HV_X64_EXCEPTION_INTERCEPT_MESSAGE const *PCHV_X64_EXCEPTION_INTERCEPT_MESSAGE;
     1404
     1405
     1406/**
     1407 * The payload format for HvMessageTypeX64Halt,
     1408 *
     1409 * @note This message does not include HV_X64_INTERCEPT_MESSAGE_HEADER!
     1410 */
     1411typedef struct
     1412{
     1413    /** Seems to be a zero 64-bit field here.  */
     1414    uint64_t    u64Reserved;
     1415} HV_X64_HALT_MESSAGE;
     1416/** Pointer to a HvMessageTypeX64Halt payload. */
     1417typedef HV_X64_HALT_MESSAGE *PHV_X64_HALT_MESSAGE;
     1418/** Pointer to a const HvMessageTypeX64Halt payload. */
     1419typedef HV_X64_HALT_MESSAGE const *PCHV_X64_HALT_MESSAGE;
     1420
     1421/** Full HvMessageTypeX64Halt message. */
     1422typedef struct
     1423{
     1424    HV_MESSAGE_HEADER                   MsgHdr;
     1425    HV_X64_HALT_MESSAGE                 Payload;
     1426} HV_X64_HALT_MESSAGE_FULL;
     1427
     1428
     1429
     1430/** Hyper-V SynIC message. */
     1431typedef struct
     1432{
     1433    HV_MESSAGE_HEADER   Header;
     1434    /** 0x10 */
     1435    union
     1436    {
     1437        uint64_t                            Payload[HV_MESSAGE_MAX_PAYLOAD_QWORD_COUNT];
     1438
     1439        /** Common header for X64 intercept messages. */
     1440        HV_X64_INTERCEPT_MESSAGE_HEADER     X64InterceptHeader;
     1441        /** HvMessageTypeGpaIntercept, HvMessageTypeUnmappedGpa. */
     1442        HV_X64_MEMORY_INTERCEPT_MESSAGE     X86MemoryIntercept;
     1443        /** HvMessageTypeX64IoPortIntercept */
     1444        HV_X64_IO_PORT_INTERCEPT_MESSAGE    X64IoPortIntercept;
     1445        /** HvMessageTypeX64ExceptionIntercept */
     1446        HV_X64_EXCEPTION_INTERCEPT_MESSAGE  X64ExceptionIntercept;
     1447        /** HvMessageTypeX64Halt. */
     1448        HV_X64_HALT_MESSAGE                 X64Halt;
     1449    };
     1450} HV_MESSAGE;
     1451AssertCompileSize(HV_MESSAGE, HV_MESSAGE_SIZE);
     1452/** Pointer to a Hyper-V SynIC message. */
     1453typedef HV_MESSAGE *PHV_MESSAGE;
     1454/** Pointer to const a Hyper-V SynIC message. */
     1455typedef HV_MESSAGE const *PCHV_MESSAGE;
     1456
    10851457#endif
    10861458
  • trunk/src/VBox/VMM/Makefile.kmk

    r71075 r71129  
    313313 VBoxVMM_SOURCES.win.amd64 += VMMR3/NEMR3Native-win.cpp
    314314 VBoxVMM_DEFS.win.amd64    += VBOX_WITH_NATIVE_NEM
     315 VBoxVMM_SDKS.win          += VBOX_NTDLL
    315316 VMMR3/NEMR3Native-win.cpp_DEFS.amd64 = _AMD64_
    316317 VMMR3/NEMR3Native-win.cpp_INCS = \
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r71087 r71129  
    2929#include <iprt/nt/nt-and-windows.h>
    3030#include <iprt/nt/hyperv.h>
     31#include <iprt/nt/vid.h>
    3132#include <WinHvPlatform.h>
    3233
     
    7879
    7980
    80 #define NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    81 #define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    82 
    8381
    8482/*********************************************************************************************************************************
    8583*   Structures and Typedefs                                                                                                      *
    8684*********************************************************************************************************************************/
    87 /** WHvRegisterInterruptState layout, reconstructed from the v7.1 DDK. */
    88 typedef union MISSINGINTERUPTSTATEREG
    89 {
    90     /** 64-bit view. */
    91     uint64_t au64[2];
    92     struct /* unamed */
    93     {
    94         uint64_t fInterruptShadow : 1;
    95         uint64_t fNmiMasked : 2;
    96         uint64_t uReserved0 : 61;
    97         uint64_t uReserved1;
    98     };
    99 } MISSINGINTERUPTSTATEREG;
    100 AssertCompileSize(MISSINGINTERUPTSTATEREG, 16);
    101 
    10285
    10386
     
    11699static decltype(WHvUnmapGpaRange) *                 g_pfnWHvUnmapGpaRange;
    117100static decltype(WHvTranslateGva) *                  g_pfnWHvTranslateGva;
     101#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    118102static decltype(WHvCreateVirtualProcessor) *        g_pfnWHvCreateVirtualProcessor;
    119103static decltype(WHvDeleteVirtualProcessor) *        g_pfnWHvDeleteVirtualProcessor;
     
    123107static decltype(WHvGetVirtualProcessorRegisters) *  g_pfnWHvGetVirtualProcessorRegisters;
    124108static decltype(WHvSetVirtualProcessorRegisters) *  g_pfnWHvSetVirtualProcessorRegisters;
     109#endif
    125110/** @} */
    126111
    127112/** @name APIs imported from Vid.dll
    128113 * @{ */
    129 static BOOL (WINAPI *g_pfnVidGetHvPartitionId)(HANDLE hPartition, HV_PARTITION_ID *pidPartition);
     114static decltype(VidGetHvPartitionId)               *g_pfnVidGetHvPartitionId;
     115static decltype(VidStartVirtualProcessor)          *g_pfnVidStartVirtualProcessor;
     116static decltype(VidStopVirtualProcessor)           *g_pfnVidStopVirtualProcessor;
     117static decltype(VidMessageSlotMap)                 *g_pfnVidMessageSlotMap;
     118static decltype(VidMessageSlotHandleAndGetNext)    *g_pfnVidMessageSlotHandleAndGetNext;
     119#ifdef LOG_ENABLED
     120static decltype(VidGetVirtualProcessorRunningStatus) *g_pfnVidGetVirtualProcessorRunningStatus;
     121#endif
    130122/** @} */
    131123
     
    152144    NEM_WIN_IMPORT(0, false, WHvUnmapGpaRange),
    153145    NEM_WIN_IMPORT(0, false, WHvTranslateGva),
     146#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    154147    NEM_WIN_IMPORT(0, false, WHvCreateVirtualProcessor),
    155148    NEM_WIN_IMPORT(0, false, WHvDeleteVirtualProcessor),
    156149    NEM_WIN_IMPORT(0, false, WHvRunVirtualProcessor),
     150    NEM_WIN_IMPORT(0, false, WHvCancelRunVirtualProcessor),
    157151    NEM_WIN_IMPORT(0, false, WHvGetRunExitContextSize),
    158     NEM_WIN_IMPORT(0, false, WHvCancelRunVirtualProcessor),
    159152    NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorRegisters),
    160153    NEM_WIN_IMPORT(0, false, WHvSetVirtualProcessorRegisters),
     154#endif
    161155    NEM_WIN_IMPORT(1, false, VidGetHvPartitionId),
     156    NEM_WIN_IMPORT(1, false, VidMessageSlotMap),
     157    NEM_WIN_IMPORT(1, false, VidMessageSlotHandleAndGetNext),
     158    NEM_WIN_IMPORT(1, false, VidStartVirtualProcessor),
     159    NEM_WIN_IMPORT(1, false, VidStopVirtualProcessor),
     160#ifdef LOG_ENABLED
     161    NEM_WIN_IMPORT(1, false, VidGetVirtualProcessorRunningStatus),
     162#endif
    162163#undef NEM_WIN_IMPORT
    163164};
     
    202203
    203204/** The real NtDeviceIoControlFile API in NTDLL.   */
    204 static decltype(NtDeviceIoControlFile) *g_pfnNtDeviceIoControlFile;
     205static decltype(NtDeviceIoControlFile)       *g_pfnNtDeviceIoControlFile;
     206/** Mapping slot for CPU #0.
     207 * @{  */
     208static VID_MESSAGE_MAPPING_HEADER            *g_pMsgSlotMapping = NULL;
     209static const HV_MESSAGE_HEADER               *g_pHvMsgHdr;
     210static const HV_X64_INTERCEPT_MESSAGE_HEADER *g_pX64MsgHdr;
     211/** @} */
     212
    205213
    206214/**
     
    214222                                         PVOID pvOutput, ULONG cbOutput)
    215223{
     224    char szFunction[32];
     225    const char *pszFunction;
     226    switch (uFunction)
     227    {
     228        case 0x2210cb: pszFunction = "VidMessageSlotHandleAndGetNext"; break;
     229        case 0x2210cc: pszFunction = "VidMessageSlotMap"; break;
     230        case 0x221164: pszFunction = "VidStopVirtualProcessor"; break;
     231        case 0x221158: pszFunction = "VidStartVirtualProcessor"; break;
     232        case 0x2210a7: pszFunction = "VidGetVirtualProcessorState"; break;
     233        case 0x221153: pszFunction = "VidSetVirtualProcessorState"; break;
     234        default:
     235            RTStrPrintf(szFunction, sizeof(szFunction), "%#x", uFunction);
     236            pszFunction = szFunction;
     237            break;
     238    }
     239
     240    if (cbInput > 0 && pvInput)
     241        Log12(("VID!NtDeviceIoControlFile: %s/input: %.*Rhxs\n", pszFunction, RT_MIN(cbInput, 32), pvInput));
    216242    NTSTATUS rcNt = g_pfnNtDeviceIoControlFile(hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, uFunction,
    217243                                               pvInput, cbInput, pvOutput, cbOutput);
    218244    if (!hEvt && !pfnApcCallback && !pvApcCtx)
    219         Log12(("VID!NtDeviceIoControlFile: hFile=%#zx pIos=%p->{s:%#x, i:%#zx} uFunction=%#x Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
    220                hFile, pIos, pIos->Status, pIos->Information, uFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
     245        Log12(("VID!NtDeviceIoControlFile: hFile=%#zx pIos=%p->{s:%#x, i:%#zx} uFunction=%s Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
     246               hFile, pIos, pIos->Status, pIos->Information, pszFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
    221247    else
    222         Log12(("VID!NtDeviceIoControlFile: hFile=%#zx hEvt=%#zx Apc=%p/%p pIos=%p->{s:%#x, i:%#zx} uFunction=%#x Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
    223                hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, uFunction,
     248        Log12(("VID!NtDeviceIoControlFile: hFile=%#zx hEvt=%#zx Apc=%p/%p pIos=%p->{s:%#x, i:%#zx} uFunction=%s Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
     249               hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, pszFunction,
    224250               pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
     251    if (cbOutput > 0 && pvOutput)
     252    {
     253        Log12(("VID!NtDeviceIoControlFile: %s/output: %.*Rhxs\n", pszFunction, RT_MIN(cbOutput, 32), pvOutput));
     254        if (uFunction == 0x2210cc && g_pMsgSlotMapping == NULL && cbOutput >= sizeof(void *))
     255        {
     256            g_pMsgSlotMapping = *(VID_MESSAGE_MAPPING_HEADER **)pvOutput;
     257            g_pHvMsgHdr       = (const HV_MESSAGE_HEADER               *)(g_pMsgSlotMapping + 1);
     258            g_pX64MsgHdr      = (const HV_X64_INTERCEPT_MESSAGE_HEADER *)(g_pHvMsgHdr + 1);
     259            Log12(("VID!NtDeviceIoControlFile: Message slot mapping: %p\n", g_pMsgSlotMapping));
     260        }
     261    }
     262    if (g_pMsgSlotMapping && (uFunction == 0x2210cb || uFunction == 0x2210cc || uFunction == 0x221164))
     263        Log12(("VID!NtDeviceIoControlFile: enmVidMsgType=%#x cb=%#x msg=%#x payload=%u cs:rip=%04x:%08RX64 (%s)\n",
     264               g_pMsgSlotMapping->enmVidMsgType, g_pMsgSlotMapping->cbMessage,
     265               g_pHvMsgHdr->MessageType, g_pHvMsgHdr->PayloadSize,
     266               g_pX64MsgHdr->CsSegment.Selector, g_pX64MsgHdr->Rip, pszFunction));
     267
    225268    return rcNt;
    226269}
     
    304347    Assert(fSuccess);
    305348}
    306 #endif
    307 
     349
     350#endif /* NEM_WIN_INTERCEPT_NT_IO_CTLS */
    308351
    309352
     
    456499        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    457500                             "WHvGetCapability/WHvCapabilityCodeHypervisorPresent failed: %Rhrc (Last=%#x/%u)",
    458                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     501                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    459502    if (!Caps.HypervisorPresent)
    460503    {
     
    475518        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    476519                             "WHvGetCapability/WHvCapabilityCodeExtendedVmExits failed: %Rhrc (Last=%#x/%u)",
    477                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     520                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    478521    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeExtendedVmExits", "%'#018RX64", Caps.ExtendedVmExits.AsUINT64);
    479522    pVM->nem.s.fExtendedMsrExit   = RT_BOOL(Caps.ExtendedVmExits.X64MsrExit);
     
    495538        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    496539                             "WHvGetCapability/WHvCapabilityCodeFeatures failed: %Rhrc (Last=%#x/%u)",
    497                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     540                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    498541    if (Caps.Features.AsUINT64 & ~(uint64_t)0)
    499542        LogRel(("NEM: Warning! Unknown feature definitions: %#RX64\n", Caps.Features.AsUINT64));
     
    508551        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    509552                             "WHvGetCapability/WHvCapabilityCodeProcessorVendor failed: %Rhrc (Last=%#x/%u)",
    510                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     553                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    511554    switch (Caps.ProcessorVendor)
    512555    {
     
    533576        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    534577                             "WHvGetCapability/WHvCapabilityCodeProcessorFeatures failed: %Rhrc (Last=%#x/%u)",
    535                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     578                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    536579    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorFeatures", "%'#018RX64", Caps.ProcessorFeatures.AsUINT64);
    537580#define NEM_LOG_REL_CPU_FEATURE(a_Field)    NEM_LOG_REL_CAP_SUB(#a_Field, Caps.ProcessorFeatures.a_Field)
     
    592635        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    593636                             "WHvGetCapability/WHvCapabilityCodeProcessorClFlushSize failed: %Rhrc (Last=%#x/%u)",
    594                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     637                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    595638    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorClFlushSize", "2^%u", Caps.ProcessorClFlushSize);
    596639    if (Caps.ProcessorClFlushSize < 8 && Caps.ProcessorClFlushSize > 9)
     
    650693    if (FAILED(hrc))
    651694        return RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, "WHvCreatePartition failed with %Rhrc (Last=%#x/%u)",
    652                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     695                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    653696
    654697    int rc;
     
    696739        rc = RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED,
    697740                           "Failed setting WHvPartitionPropertyCodeProcessorCount to %u: %Rhrc (Last=%#x/%u)",
    698                            pVM->cCpus, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     741                           pVM->cCpus, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    699742    WHvDeletePartition(hPartition);
    700743
     
    799842        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    800843                          "Failed to set WHvPartitionPropertyCodeProcessorVendor to %u: %Rhrc (Last=%#x/%u)",
    801                           Property.ProcessorVendor, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     844                          Property.ProcessorVendor, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    802845
    803846    /* Not sure if we really need to set the cache line flush size. */
     
    809852        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    810853                          "Failed to set WHvPartitionPropertyCodeProcessorClFlushSize to %u: %Rhrc (Last=%#x/%u)",
    811                           pVM->nem.s.cCacheLineFlushShift, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     854                          pVM->nem.s.cCacheLineFlushShift, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    812855
    813856    /*
     
    824867        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    825868                          "Failed to set WHvPartitionPropertyCodeProcessorFeatures to %'#RX64: %Rhrc (Last=%#x/%u)",
    826                           pVM->nem.s.uCpuFeatures.u64, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     869                          pVM->nem.s.uCpuFeatures.u64, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    827870
    828871    /*
     
    836879        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    837880                          "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)",
    838                           hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     881                          hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    839882
    840883    /* Get the handle. */
     
    858901        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    859902                          "Failed to get device handle and/or partition ID for %p (hPartitionDevice=%p, Last=%#x/%u)",
    860                           hPartition, hPartitionDevice, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     903                          hPartition, hPartitionDevice, RTNtLastStatusValue(), RTNtLastErrorValue());
    861904    pVM->nem.s.hPartitionDevice = hPartitionDevice;
    862905    pVM->nem.s.idHvPartition    = idHvPartition;
    863906
    864907    /*
    865      * Create EMTs.
     908     * Setup the EMTs.
    866909     */
    867910    VMCPUID iCpu;
    868911    for (iCpu = 0; iCpu < pVM->cCpus; iCpu++)
    869912    {
     913        PVMCPU pVCpu = &pVM->aCpus[iCpu];
     914
     915        pVCpu->nem.s.hNativeThreadHandle = (RTR3PTR)RTThreadGetNativeHandle(VMR3GetThreadHandle(pVCpu->pUVCpu));
     916        Assert((HANDLE)pVCpu->nem.s.hNativeThreadHandle != INVALID_HANDLE_VALUE);
     917
     918#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     919        VID_MAPPED_MESSAGE_SLOT MappedMsgSlot = { NULL, UINT32_MAX, UINT32_MAX };
     920        if (g_pfnVidMessageSlotMap(hPartitionDevice, &MappedMsgSlot, iCpu))
     921        {
     922            AssertLogRelMsg(MappedMsgSlot.iCpu == iCpu && MappedMsgSlot.uParentAdvisory == UINT32_MAX,
     923                            ("%#x %#x (iCpu=%#x)\n", MappedMsgSlot.iCpu, MappedMsgSlot.uParentAdvisory, iCpu));
     924            pVCpu->nem.s.pvMsgSlotMapping = MappedMsgSlot.pMsgBlock;
     925        }
     926        else
     927        {
     928            NTSTATUS const rcNtLast  = RTNtLastStatusValue();
     929            DWORD const    dwErrLast = RTNtLastErrorValue();
     930            return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     931                              "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
     932        }
     933#else
    870934        hrc = WHvCreateVirtualProcessor(hPartition, iCpu, 0 /*fFlags*/);
    871935        if (FAILED(hrc))
    872936        {
    873             NTSTATUS const rcNtLast  = RTNtCurrentTeb()->LastStatusValue;
    874             DWORD const    dwErrLast = RTNtCurrentTeb()->LastErrorValue;
     937            NTSTATUS const rcNtLast  = RTNtLastStatusValue();
     938            DWORD const    dwErrLast = RTNtLastErrorValue();
    875939            while (iCpu-- > 0)
    876940            {
    877941                HRESULT hrc2 = WHvDeleteVirtualProcessor(hPartition, iCpu);
    878942                AssertLogRelMsg(SUCCEEDED(hrc2), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
    879                                                   hPartition, iCpu, hrc2, RTNtCurrentTeb()->LastStatusValue,
    880                                                   RTNtCurrentTeb()->LastErrorValue));
     943                                                  hPartition, iCpu, hrc2, RTNtLastStatusValue(),
     944                                                  RTNtLastErrorValue()));
    881945            }
    882946            return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    883947                              "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
    884948        }
     949#endif /* !NEM_WIN_USE_OUR_OWN_RUN_API */
    885950    }
    886951    pVM->nem.s.fCreatedEmts = true;
     
    912977        while (iCpu-- > 0)
    913978        {
     979#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     980            pVM->aCpus[iCpu].nem.s.pvMsgSlotMapping = NULL;
     981#else
    914982            HRESULT hrc = WHvDeleteVirtualProcessor(hPartition, iCpu);
    915983            AssertLogRelMsg(SUCCEEDED(hrc), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
    916                                              hPartition, iCpu, hrc, RTNtCurrentTeb()->LastStatusValue,
    917                                              RTNtCurrentTeb()->LastErrorValue));
     984                                             hPartition, iCpu, hrc, RTNtLastStatusValue(),
     985                                             RTNtLastErrorValue()));
     986#endif
    918987        }
    919988        WHvDeletePartition(hPartition);
     
    12931362    AssertLogRelMsgFailed(("WHvSetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
    12941363                           pVM->nem.s.hPartition, pVCpu->idCpu, iReg,
    1295                            hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     1364                           hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    12961365    return VERR_INTERNAL_ERROR;
    12971366#endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
     
    16661735    AssertLogRelMsgFailed(("WHvGetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
    16671736                           pVM->nem.s.hPartition, pVCpu->idCpu, cRegs,
    1668                            hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     1737                           hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    16691738    return VERR_INTERNAL_ERROR;
    16701739#endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
     
    16731742
    16741743#ifdef LOG_ENABLED
     1744/**
     1745 * Get the virtual processor running status.
     1746 */
     1747DECLINLINE(VID_PROCESSOR_STATUS) nemR3WinCpuGetRunningStatus(PVMCPU pVCpu)
     1748{
     1749    RTERRVARS Saved;
     1750    RTErrVarsSave(&Saved);
     1751
     1752    /*
     1753     * This API is disabled in release builds, it seems.  On build 17101 it requires
     1754     * the following patch to be enabled (windbg): eb vid+12180 0f 84 98 00 00 00
     1755     */
     1756    VID_PROCESSOR_STATUS enmCpuStatus = VidProcessorStatusUndefined;
     1757    NTSTATUS rcNt = g_pfnVidGetVirtualProcessorRunningStatus(pVCpu->pVMR3->nem.s.hPartitionDevice, pVCpu->idCpu, &enmCpuStatus);
     1758    AssertRC(rcNt);
     1759
     1760    RTErrVarsRestore(&Saved);
     1761    return enmCpuStatus;
     1762}
     1763#endif
     1764
     1765
     1766#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1767
     1768/**
     1769 * Our own WHvCancelRunVirtualProcessor that can later be moved to ring-0.
     1770 *
     1771 * This is an experiment only.
     1772 *
     1773 * @returns VBox status code.
     1774 * @param   pVM             The cross context VM structure.
     1775 * @param   pVCpu           The cross context virtual CPU structure of the
     1776 *                          calling EMT.
     1777 */
     1778static int nemR3WinCancelRunVirtualProcessor(PVM pVM, PVMCPU pVCpu)
     1779{
     1780    /*
     1781     * Work the state.
     1782     *
     1783     * From the looks of things, we should let the EMT call VidStopVirtualProcessor.
     1784     * So, we just need to modify the state and kick the EMT if it's waiting on
     1785     * messages.  For the latter we use QueueUserAPC / KeAlterThread.
     1786     */
     1787    for (;;)
     1788    {
     1789        VMCPUSTATE enmState = VMCPU_GET_STATE(pVCpu);
     1790        switch (enmState)
     1791        {
     1792            case VMCPUSTATE_STARTED_EXEC_NEM:
     1793                if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM))
     1794                {
     1795                    Log8(("nemR3WinCancelRunVirtualProcessor: Switched %u to canceled state\n", pVCpu->idCpu));
     1796                    return VINF_SUCCESS;
     1797                }
     1798                break;
     1799
     1800            case VMCPUSTATE_STARTED_EXEC_NEM_WAIT:
     1801            {
     1802                if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT))
     1803                {
     1804                    NTSTATUS rcNt = NtAlertThread(pVCpu->nem.s.hNativeThreadHandle);
     1805                    Log8(("nemR3WinCancelRunVirtualProcessor: Alerted %u: %#x\n", pVCpu->idCpu, rcNt));
     1806                    Assert(rcNt == STATUS_SUCCESS);
     1807                    if (NT_SUCCESS(rcNt))
     1808                        return VINF_SUCCESS;
     1809                    AssertLogRelMsgFailedReturn(("NtAlertThread failed: %#x\n", rcNt), RTErrConvertFromNtStatus(rcNt));
     1810                }
     1811                break;
     1812            }
     1813
     1814            default:
     1815                return VINF_SUCCESS;
     1816        }
     1817
     1818        ASMNopPause();
     1819        RT_NOREF(pVM);
     1820    }
     1821}
     1822
     1823
     1824/**
     1825 * Fills in WHV_VP_EXIT_CONTEXT from HV_X64_INTERCEPT_MESSAGE_HEADER.
     1826 */
     1827DECLINLINE(void) nemR3WinConvertX64MsgHdrToVpExitCtx(HV_X64_INTERCEPT_MESSAGE_HEADER const *pHdr, WHV_VP_EXIT_CONTEXT *pCtx)
     1828{
     1829    pCtx->ExecutionState.AsUINT16   = pHdr->ExecutionState.AsUINT16;
     1830    pCtx->InstructionLength         = pHdr->InstructionLength;
     1831    pCtx->Cs.Base                   = pHdr->CsSegment.Base;
     1832    pCtx->Cs.Limit                  = pHdr->CsSegment.Limit;
     1833    pCtx->Cs.Selector               = pHdr->CsSegment.Selector;
     1834    pCtx->Cs.Attributes             = pHdr->CsSegment.Attributes;
     1835    pCtx->Rip                       = pHdr->Rip;
     1836    pCtx->Rflags                    = pHdr->Rflags;
     1837}
     1838
     1839
     1840/**
     1841 * Convert hyper-V exit message to the WinHvPlatform structures.
     1842 *
     1843 * @returns VBox status code
     1844 * @param   pMsgHdr         The message to convert.
     1845 * @param   pExitCtx        The output structure. Assumes zeroed.
     1846 */
     1847static int nemR3WinRunVirtualProcessorConvertPending(HV_MESSAGE_HEADER const *pMsgHdr, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx)
     1848{
     1849    switch (pMsgHdr->MessageType)
     1850    {
     1851        case HvMessageTypeUnmappedGpa:
     1852        case HvMessageTypeGpaIntercept:
     1853        {
     1854            PCHV_X64_MEMORY_INTERCEPT_MESSAGE pMemMsg = (PCHV_X64_MEMORY_INTERCEPT_MESSAGE)(pMsgHdr + 1);
     1855            Assert(pMsgHdr->PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment));
     1856
     1857            pExitCtx->ExitReason                            = WHvRunVpExitReasonMemoryAccess;
     1858            nemR3WinConvertX64MsgHdrToVpExitCtx(&pMemMsg->Header, &pExitCtx->MemoryAccess.VpContext);
     1859            pExitCtx->MemoryAccess.InstructionByteCount     = pMemMsg->InstructionByteCount;
     1860            ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[0] = ((uint64_t const *)pMemMsg->InstructionBytes)[0];
     1861            ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[1] = ((uint64_t const *)pMemMsg->InstructionBytes)[1];
     1862
     1863            pExitCtx->MemoryAccess.AccessInfo.AccessType    = pMemMsg->Header.InterceptAccessType;
     1864            pExitCtx->MemoryAccess.AccessInfo.GpaUnmapped   = pMsgHdr->MessageType == HvMessageTypeUnmappedGpa;
     1865            pExitCtx->MemoryAccess.AccessInfo.GvaValid      = pMemMsg->MemoryAccessInfo.GvaValid;
     1866            pExitCtx->MemoryAccess.AccessInfo.Reserved      = pMemMsg->MemoryAccessInfo.Reserved;
     1867            pExitCtx->MemoryAccess.Gpa                      = pMemMsg->GuestPhysicalAddress;
     1868            pExitCtx->MemoryAccess.Gva                      = pMemMsg->GuestVirtualAddress;
     1869            return VINF_SUCCESS;
     1870        }
     1871
     1872        case HvMessageTypeX64IoPortIntercept:
     1873        {
     1874            PCHV_X64_IO_PORT_INTERCEPT_MESSAGE pPioMsg= (PCHV_X64_IO_PORT_INTERCEPT_MESSAGE)(pMsgHdr + 1);
     1875            Assert(pMsgHdr->PayloadSize == sizeof(*pPioMsg));
     1876
     1877            pExitCtx->ExitReason                            = WHvRunVpExitReasonX64IoPortAccess;
     1878            nemR3WinConvertX64MsgHdrToVpExitCtx(&pPioMsg->Header, &pExitCtx->IoPortAccess.VpContext);
     1879            pExitCtx->IoPortAccess.InstructionByteCount     = pPioMsg->InstructionByteCount;
     1880            ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[0] = ((uint64_t const *)pPioMsg->InstructionBytes)[0];
     1881            ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[1] = ((uint64_t const *)pPioMsg->InstructionBytes)[1];
     1882
     1883            pExitCtx->IoPortAccess.AccessInfo.IsWrite       = pPioMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE;
     1884            pExitCtx->IoPortAccess.AccessInfo.AccessSize    = pPioMsg->AccessInfo.AccessSize;
     1885            pExitCtx->IoPortAccess.AccessInfo.StringOp      = pPioMsg->AccessInfo.StringOp;
     1886            pExitCtx->IoPortAccess.AccessInfo.RepPrefix     = pPioMsg->AccessInfo.RepPrefix;
     1887            pExitCtx->IoPortAccess.AccessInfo.Reserved      = pPioMsg->AccessInfo.Reserved;
     1888            pExitCtx->IoPortAccess.PortNumber               = pPioMsg->PortNumber;
     1889            pExitCtx->IoPortAccess.Rax                      = pPioMsg->Rax;
     1890            pExitCtx->IoPortAccess.Rcx                      = pPioMsg->Rcx;
     1891            pExitCtx->IoPortAccess.Rsi                      = pPioMsg->Rsi;
     1892            pExitCtx->IoPortAccess.Rdi                      = pPioMsg->Rdi;
     1893            pExitCtx->IoPortAccess.Ds.Base                  = pPioMsg->DsSegment.Base;
     1894            pExitCtx->IoPortAccess.Ds.Limit                 = pPioMsg->DsSegment.Limit;
     1895            pExitCtx->IoPortAccess.Ds.Selector              = pPioMsg->DsSegment.Selector;
     1896            pExitCtx->IoPortAccess.Ds.Attributes            = pPioMsg->DsSegment.Attributes;
     1897            pExitCtx->IoPortAccess.Es.Base                  = pPioMsg->EsSegment.Base;
     1898            pExitCtx->IoPortAccess.Es.Limit                 = pPioMsg->EsSegment.Limit;
     1899            pExitCtx->IoPortAccess.Es.Selector              = pPioMsg->EsSegment.Selector;
     1900            pExitCtx->IoPortAccess.Es.Attributes            = pPioMsg->EsSegment.Attributes;
     1901            return VINF_SUCCESS;
     1902        }
     1903
     1904        case HvMessageTypeX64Halt:
     1905        {
     1906            PCHV_X64_HALT_MESSAGE pHaltMsg = (PCHV_X64_HALT_MESSAGE)(pMsgHdr + 1);
     1907            AssertMsg(pHaltMsg->u64Reserved == 0, ("HALT reserved: %#RX64\n", pHaltMsg->u64Reserved));
     1908            pExitCtx->ExitReason = WHvRunVpExitReasonX64Halt;
     1909            return VINF_SUCCESS;
     1910        }
     1911
     1912        case HvMessageTypeX64InterruptWindow:
     1913            AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1914
     1915        case HvMessageTypeInvalidVpRegisterValue:
     1916        case HvMessageTypeUnrecoverableException:
     1917        case HvMessageTypeUnsupportedFeature:
     1918        case HvMessageTypeTlbPageSizeMismatch:
     1919            AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1920
     1921        case HvMessageTypeX64MsrIntercept:
     1922        case HvMessageTypeX64CpuidIntercept:
     1923        case HvMessageTypeX64ExceptionIntercept:
     1924        case HvMessageTypeX64ApicEoi:
     1925        case HvMessageTypeX64LegacyFpError:
     1926        case HvMessageTypeX64RegisterIntercept:
     1927        case HvMessageTypeApicEoi:
     1928        case HvMessageTypeFerrAsserted:
     1929        case HvMessageTypeEventLogBufferComplete:
     1930        case HvMessageTimerExpired:
     1931            AssertLogRelMsgFailedReturn(("Unexpected message type #x!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1932
     1933        default:
     1934            AssertLogRelMsgFailedReturn(("Unknown message type #x!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1935    }
     1936}
     1937
     1938
     1939/**
     1940 * Our own WHvRunVirtualProcessor that can later be moved to ring-0.
     1941 *
     1942 * This is an experiment only.
     1943 *
     1944 * @returns VBox status code.
     1945 * @param   pVM             The cross context VM structure.
     1946 * @param   pVCpu           The cross context virtual CPU structure of the
     1947 *                          calling EMT.
     1948 * @param   pExitCtx        Where to return exit information.
     1949 * @param   cbExitCtx       Size of the exit information area.
     1950 */
     1951static int nemR3WinRunVirtualProcessor(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx, size_t cbExitCtx)
     1952{
     1953    RT_BZERO(pExitCtx, cbExitCtx);
     1954
     1955    /*
     1956     * Tell the CPU to execute stuff if we haven't got a pending message.
     1957     */
     1958    VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader = (VID_MESSAGE_MAPPING_HEADER volatile *)pVCpu->nem.s.pvMsgSlotMapping;
     1959    uint32_t                             fHandleAndGetFlags;
     1960    if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED))
     1961    {
     1962        uint8_t const bMsgState = pVCpu->nem.s.bMsgState;
     1963        if (bMsgState == NEM_WIN_MSG_STATE_PENDING_MSG)
     1964        {
     1965            Assert(pMappingHeader->enmVidMsgType == VidMessageHypervisorMessage);
     1966            fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE | VID_MSHAGN_F_HANDLE_MESSAGE;
     1967            Log8(("nemR3WinRunVirtualProcessor: #1: msg pending, no need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     1968        }
     1969        else if (bMsgState != NEM_WIN_MSG_STATE_STARTED)
     1970        {
     1971            if (bMsgState == NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG)
     1972            {
     1973                Log8(("nemR3WinRunVirtualProcessor: #0: pending stop+message (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     1974                /* ACK the pending message and get the stop message. */
     1975                BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     1976                                                                 VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE, 5000);
     1977                AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
     1978
     1979                /* ACK the stop message. */
     1980                fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     1981                                                                 VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
     1982                AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
     1983
     1984                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
     1985            }
     1986
     1987            Log8(("nemR3WinRunVirtualProcessor: #1: starting CPU (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     1988            if (g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu))
     1989                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
     1990            else
     1991            {
     1992                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM);
     1993                AssertLogRelMsgFailedReturn(("VidStartVirtualProcessor failed for CPU #%u: rcNt=%#x dwErr=%u\n",
     1994                                             pVCpu->idCpu, RTNtLastStatusValue(), RTNtLastErrorValue()),
     1995                                            VERR_INTERNAL_ERROR_3);
     1996            }
     1997            fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
     1998        }
     1999        else
     2000        {
     2001            /* This shouldn't happen. */
     2002            fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
     2003            Log8(("nemR3WinRunVirtualProcessor: #1: NO MSG PENDING! No need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     2004        }
     2005    }
     2006    else
     2007    {
     2008        Log8(("nemR3WinRunVirtualProcessor: #1: state=%u -> canceled (cpu status %u)\n",
     2009              VMCPU_GET_STATE(pVCpu), nemR3WinCpuGetRunningStatus(pVCpu)));
     2010        pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2011        return VINF_SUCCESS;
     2012    }
     2013
     2014    /*
     2015     * Wait for it to stop and give us a reason to work with.
     2016     */
     2017    uint32_t cMillies = 5000; // Starting low so we can experiment without getting stuck.
     2018    for (;;)
     2019    {
     2020        if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM))
     2021        {
     2022            Log8(("nemR3WinRunVirtualProcessor: #2: Waiting %#x (cpu status %u)...\n",
     2023                  fHandleAndGetFlags, nemR3WinCpuGetRunningStatus(pVCpu)));
     2024            BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     2025                                                             fHandleAndGetFlags, cMillies);
     2026            if (fWait)
     2027            {
     2028                /* Not sure yet, but we have to check whether there is anything pending
     2029                   and retry if there isn't. */
     2030                VID_MESSAGE_TYPE const enmVidMsgType = pMappingHeader->enmVidMsgType;
     2031                if (enmVidMsgType == VidMessageHypervisorMessage)
     2032                {
     2033                    if (!VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT))
     2034                        VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED);
     2035                    Log8(("nemR3WinRunVirtualProcessor: #3: wait succeeded: %#x / %#x (cpu status %u)\n",
     2036                          enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType,
     2037                          nemR3WinCpuGetRunningStatus(pVCpu) ));
     2038                    pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG;
     2039                    return nemR3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);
     2040                }
     2041
     2042                /* This shouldn't happen, and I think its wrong. */
     2043                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
     2044#ifdef DEBUG_bird
     2045                __debugbreak();
     2046#endif
     2047                Log8(("nemR3WinRunVirtualProcessor: #3: wait succeeded, but nothing pending: %#x / %#x (cpu status %u)\n",
     2048                      enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2049                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
     2050                AssertLogRelMsgReturnStmt(enmVidMsgType == VidMessageStopRequestComplete,
     2051                                          ("enmVidMsgType=%#x\n", enmVidMsgType),
     2052                                          g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
     2053                                          VERR_INTERNAL_ERROR_3);
     2054                fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE;
     2055            }
     2056            else
     2057            {
     2058                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
     2059
     2060                /* Note! VID.SYS merges STATUS_ALERTED and STATUS_USER_APC into STATUS_TIMEOUT. */
     2061                DWORD const dwErr = RTNtLastErrorValue();
     2062                AssertLogRelMsgReturnStmt(   dwErr == STATUS_TIMEOUT
     2063                                          || dwErr == STATUS_ALERTED || dwErr == STATUS_USER_APC, /* just in case */
     2064                                          ("dwErr=%u (%#x) (cpu status %u)\n", dwErr, dwErr, nemR3WinCpuGetRunningStatus(pVCpu)),
     2065                                          g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
     2066                                          VERR_INTERNAL_ERROR_3);
     2067                Log8(("nemR3WinRunVirtualProcessor: #3: wait timed out (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     2068                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
     2069                fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE;
     2070            }
     2071        }
     2072        else
     2073        {
     2074            /*
     2075             * State changed and we need to return.
     2076             *
     2077             * We must ensure that the processor is not running while we
     2078             * return, and that can be a bit complicated.
     2079             */
     2080            Log8(("nemR3WinRunVirtualProcessor: #4: state changed to %u (cpu status %u)\n",
     2081                  VMCPU_GET_STATE(pVCpu), nemR3WinCpuGetRunningStatus(pVCpu) ));
     2082            VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED);
     2083
     2084            /* If we haven't marked the pervious message as handled, simply return
     2085               without doing anything special. */
     2086            if (fHandleAndGetFlags & VID_MSHAGN_F_HANDLE_MESSAGE)
     2087            {
     2088                Log8(("nemR3WinRunVirtualProcessor: #5: Didn't resume previous message.\n"));
     2089                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG;
     2090                pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2091                return VINF_SUCCESS;
     2092            }
     2093
     2094            /* The processor is running, so try stop it. */
     2095            BOOL fStop = g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu);
     2096            if (fStop)
     2097            {
     2098                Log8(("nemR3WinRunVirtualProcessor: #5: Stopping CPU succeeded (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     2099                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
     2100                pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2101                return VINF_SUCCESS;
     2102            }
     2103
     2104            /* Dang, the CPU stopped by itself with a message pending. */
     2105            DWORD dwErr = RTNtLastErrorValue();
     2106            Log8(("nemR3WinRunVirtualProcessor: #5: Stopping CPU failed (%u/%#x) - cpu status %u\n",
     2107                  dwErr, dwErr, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2108            pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2109            AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u\n", dwErr), VERR_INTERNAL_ERROR_3);
     2110
     2111            /* Get the pending message. */
     2112            BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     2113                                                             VID_MSHAGN_F_GET_NEXT_MESSAGE, 5000);
     2114            AssertLogRelMsgReturn(fWait, ("error=%#u\n", RTNtLastErrorValue()), VERR_INTERNAL_ERROR_3);
     2115
     2116            VID_MESSAGE_TYPE const enmVidMsgType = pMappingHeader->enmVidMsgType;
     2117            if (enmVidMsgType == VidMessageHypervisorMessage)
     2118            {
     2119                Log8(("nemR3WinRunVirtualProcessor: #6: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,
     2120                      ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2121                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG;
     2122                return nemR3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);
     2123            }
     2124
     2125            /* ACK the stop message, if that's what it is.  Don't think we'll ever get here. */
     2126            Log8(("nemR3WinRunVirtualProcessor: #6b: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,
     2127                  ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2128            AssertLogRelMsgReturn(enmVidMsgType == VidMessageStopRequestComplete, ("enmVidMsgType=%#x\n", enmVidMsgType),
     2129                                  VERR_INTERNAL_ERROR_3);
     2130            fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     2131                                                        VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
     2132            AssertLogRelMsgReturn(fWait, ("dwErr=%#u\n", RTNtLastErrorValue()), VERR_INTERNAL_ERROR_3);
     2133
     2134            pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
     2135            pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2136            return VINF_SUCCESS;
     2137        }
     2138
     2139        /** @todo check flags and stuff? */
     2140    }
     2141}
     2142
     2143#endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
     2144
     2145#ifdef LOG_ENABLED
     2146
    16752147/**
    16762148 * Log the full details of an exit reason.
     
    18902362#else
    18912363        LogRel(("nemR3WinUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    1892                 GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtCurrentTeb()->LastStatusValue,
    1893                 RTNtCurrentTeb()->LastErrorValue, pVM->nem.s.cMappedPages));
     2364                GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtLastStatusValue(),
     2365                RTNtLastErrorValue(), pVM->nem.s.cMappedPages));
    18942366#endif
    18952367        *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET;
     
    20722544#else
    20732545    LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    2074             GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue,
     2546            GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue(),
    20752547            pVM->nem.s.cMappedPages));
    20762548
     
    23152787            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
    23162788        {
     2789#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2790            int rc2 = nemR3WinRunVirtualProcessor(pVM, pVCpu, &ExitReason, sizeof(ExitReason));
     2791            AssertRCBreakStmt(rc2, rcStrict = rc2);
     2792#else
     2793            Log8(("Calling WHvRunVirtualProcessor\n"));
    23172794            VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED);
    23182795            HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
     
    23202797            AssertLogRelMsgBreakStmt(SUCCEEDED(hrc),
    23212798                                     ("WHvRunVirtualProcessor(%p, %u,,) -> %Rhrc (Last=%#x/%u)\n", pVM->nem.s.hPartition, pVCpu->idCpu,
    2322                                       hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue),
     2799                                      hrc, RTNtLastStatusValue(), RTNtLastErrorValue()),
    23232800                                     rcStrict = VERR_INTERNAL_ERROR);
    2324             Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d)\n", hrc, ExitReason.ExitReason, ExitReason.ExitReason));
     2801            Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d) (cpu status %u)\n",
     2802                  hrc, ExitReason.ExitReason, ExitReason.ExitReason, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2803#endif
    23252804        }
    23262805        else
     
    24942973void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags)
    24952974{
     2975#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2976    nemR3WinCancelRunVirtualProcessor(pVM, pVCpu);
     2977#else
     2978    Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu));
    24962979    HRESULT hrc = WHvCancelRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, 0);
    24972980    AssertMsg(SUCCEEDED(hrc), ("WHvCancelRunVirtualProcessor -> hrc=%Rhrc\n", hrc));
    2498 
    24992981    RT_NOREF_PV(hrc);
     2982#endif
    25002983    RT_NOREF_PV(fFlags);
    25012984}
     
    25773060            {
    25783061                LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2579                         GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3062                        GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    25803063                return VERR_NEM_INIT_FAILED;
    25813064            }
     
    26443127#else
    26453128            LogRel(("nemR3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2646                     GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3129                    GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    26473130            return VERR_INTERNAL_ERROR_2;
    26483131#endif
     
    28583341            {
    28593342                LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2860                         GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3343                        GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    28613344                return VERR_NEM_INIT_FAILED;
    28623345            }
     
    29013384            }
    29023385            LogRel(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2903                     GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3386                    GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    29043387            return VERR_NEM_INIT_FAILED;
    29053388        }
     
    29413424            }
    29423425            LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2943                     GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3426                    GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    29443427            return VERR_NEM_INIT_FAILED;
    29453428        }
     
    29883471    }
    29893472    LogRel(("nemR3JustUnmapPageFromHyperV(%RGp): failed! hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2990             GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3473            GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    29913474    return VERR_INTERNAL_ERROR_3;
    29923475#endif
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r71040 r71129  
    45334533
    45344534/**
    4535  * Returns the native handle of the current EMT VMCPU thread.
     4535 * Returns the native ID of the current EMT VMCPU thread.
    45364536 *
    45374537 * @returns Handle if this is an EMT thread; NIL_RTNATIVETHREAD otherwise
     
    45514551
    45524552/**
    4553  * Returns the native handle of the current EMT VMCPU thread.
     4553 * Returns the native ID of the current EMT VMCPU thread.
    45544554 *
    45554555 * @returns Handle if this is an EMT thread; NIL_RTNATIVETHREAD otherwise
     
    45824582        return NIL_RTTHREAD;
    45834583
     4584    return pUVCpu->vm.s.ThreadEMT;
     4585}
     4586
     4587
     4588/**
     4589 * Returns the handle of the current EMT VMCPU thread.
     4590 *
     4591 * @returns The IPRT thread handle.
     4592 * @param   pUVCpu          The user mode CPU handle.
     4593 * @thread  EMT
     4594 */
     4595VMMR3_INT_DECL(RTTHREAD) VMR3GetThreadHandle(PUVMCPU pUVCpu)
     4596{
    45844597    return pUVCpu->vm.s.ThreadEMT;
    45854598}
  • trunk/src/VBox/VMM/VMMR3/VMEmt.cpp

    r71040 r71129  
    859859                }
    860860            }
    861             else if (enmState == VMCPUSTATE_STARTED_EXEC_NEM)
     861            else if (   enmState == VMCPUSTATE_STARTED_EXEC_NEM
     862                     || enmState == VMCPUSTATE_STARTED_EXEC_NEM_WAIT)
    862863                NEMR3NotifyFF(pUVCpu->pVM, pVCpu, fFlags);
    863864#ifdef VBOX_WITH_REM
     
    10011002        {
    10021003            VMCPUSTATE enmState = pVCpu->enmState;
    1003             if (enmState == VMCPUSTATE_STARTED_EXEC_NEM)
     1004            if (   enmState == VMCPUSTATE_STARTED_EXEC_NEM
     1005                || enmState == VMCPUSTATE_STARTED_EXEC_NEM_WAIT)
    10041006                NEMR3NotifyFF(pUVCpu->pVM, pVCpu, fFlags);
    10051007#ifdef VBOX_WITH_REM
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r71076 r71129  
    3737 * @{
    3838 */
     39
     40
     41#ifdef RT_OS_WINDOWS
     42/*
     43 * Windows: Code configuration.
     44 */
     45# define NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     46# define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
     47# define NEM_WIN_USE_OUR_OWN_RUN_API
     48# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
     49#  error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
     50# endif
     51#endif
    3952
    4053/**
     
    102115#define NEM_MAGIC_DEAD          UINT32_C(0xdead1111)
    103116
     117#if defined(RT_OS_WINDOWS) && defined(NEM_WIN_USE_OUR_OWN_RUN_API)
     118/** @name NEM_WIN_MSG_STATE_XXX - Windows message handling state.
     119 * @{ */
     120/** The CPU has not been started. */
     121# define NEM_WIN_MSG_STATE_STOPPED              UINT8_C(0x00)
     122/** The CPU has been started, no messages are pending. */
     123# define NEM_WIN_MSG_STATE_STARTED              UINT8_C(0x01)
     124/** Message is pending and needs to be ACKed. */
     125# define NEM_WIN_MSG_STATE_PENDING_MSG          UINT8_C(0x02)
     126/** Both a message and execution stopping is pending.  We need to ACK the
     127 * current message and get the stop message, then ACK the stop message before
     128 *  the CPU can be started again.  */
     129# define NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG UINT8_C(0x03)
     130/** @} */
     131#endif
    104132
    105133/**
     
    111139    uint32_t                    u32Magic;
    112140#ifdef RT_OS_WINDOWS
     141# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     142    /** We've got a message pending (NEM_WIN_MSG_STATE_XXX). */
     143    uint8_t                     bMsgState;
     144    /** What VidMessageSlotMap returns and is used for passing exit info. */
     145    RTR3PTR                     pvMsgSlotMapping;
     146# endif
     147    /** The windows thread handle. */
     148    RTR3PTR                     hNativeThreadHandle;
    113149    /** Parameters for making Hyper-V hypercalls. */
    114150    union
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette