VirtualBox

Changeset 71031 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Feb 15, 2018 4:47:13 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120894
Message:

NEM: More code. bugref:9044

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/EMR3Nem.cpp

    r70980 r71031  
    463463        TMTimerPollVoid(pVM, pVCpu);
    464464#endif
    465         if (    VM_FF_IS_PENDING(pVM, VM_FF_ALL_MASK)
    466             ||  VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_ALL_MASK))
     465        if (   VM_FF_IS_PENDING(pVM, VM_FF_ALL_MASK)
     466            || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_ALL_MASK))
    467467        {
    468468            rcStrict = emR3ForcedActions(pVM, pVCpu, VBOXSTRICTRC_TODO(rcStrict));
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r71020 r71031  
    22/** @file
    33 * NEM - Native execution manager, native ring-3 Windows backend.
     4 *
     5 * Log group 2: Exit logging.
     6 * Log group 3: Log context on exit.
    47 */
    58
     
    3740
    3841#include <VBox/vmm/nem.h>
     42#include <VBox/vmm/iem.h>
     43#include <VBox/vmm/em.h>
    3944#include <VBox/vmm/apic.h>
    4045#include "NEMInternal.h"
     
    143148# define WHvSetVirtualProcessorRegisters            g_pfnWHvSetVirtualProcessorRegisters
    144149#endif
     150
     151
     152/*********************************************************************************************************************************
     153*   Internal Functions                                                                                                           *
     154*********************************************************************************************************************************/
     155static int nemR3NativeSetPhysPage(PVM pVM, RTGCPHYS GCPhys, uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged);
    145156
    146157
     
    604615     */
    605616    /**
    606      * @todo Someone at microsoft please explain another weird API:
     617     * @todo Someone at Microsoft please explain another weird API:
    607618     *  - Why this API doesn't take the WHV_PARTITION_PROPERTY_CODE value as an
    608619     *    argument rather than as part of the struct.  That is so weird if you've
     
    870881
    871882
    872 static int nemR3WinCopyOutState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     883static int nemR3WinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    873884{
    874885    WHV_REGISTER_NAME  aenmNames[128];
     
    962973
    963974    /* Debug registers. */
    964 /** @todo fixme */
     975/** @todo fixme. Figure out what the hyper-v version of KVM_SET_GUEST_DEBUG would be. */
    965976    aenmNames[iReg]     = WHvX64RegisterDr0;
    966     aValues[iReg].Reg64 = CPUMGetHyperDR0(pVCpu);
     977    //aValues[iReg].Reg64 = CPUMGetHyperDR0(pVCpu);
     978    aValues[iReg].Reg64 = pCtx->dr[0];
    967979    iReg++;
    968980    aenmNames[iReg]     = WHvX64RegisterDr1;
    969     aValues[iReg].Reg64 = CPUMGetHyperDR1(pVCpu);
     981    //aValues[iReg].Reg64 = CPUMGetHyperDR1(pVCpu);
     982    aValues[iReg].Reg64 = pCtx->dr[1];
    970983    iReg++;
    971984    aenmNames[iReg]     = WHvX64RegisterDr2;
    972     aValues[iReg].Reg64 = CPUMGetHyperDR2(pVCpu);
     985    //aValues[iReg].Reg64 = CPUMGetHyperDR2(pVCpu);
     986    aValues[iReg].Reg64 = pCtx->dr[2];
    973987    iReg++;
    974988    aenmNames[iReg]     = WHvX64RegisterDr3;
    975     aValues[iReg].Reg64 = CPUMGetHyperDR3(pVCpu);
     989    //aValues[iReg].Reg64 = CPUMGetHyperDR3(pVCpu);
     990    aValues[iReg].Reg64 = pCtx->dr[3];
    976991    iReg++;
    977992    aenmNames[iReg]     = WHvX64RegisterDr6;
    978     aValues[iReg].Reg64 = CPUMGetHyperDR6(pVCpu);
     993    //aValues[iReg].Reg64 = CPUMGetHyperDR6(pVCpu);
     994    aValues[iReg].Reg64 = pCtx->dr[6];
    979995    iReg++;
    980996    aenmNames[iReg]     = WHvX64RegisterDr7;
    981     aValues[iReg].Reg64 = CPUMGetHyperDR7(pVCpu);
     997    //aValues[iReg].Reg64 = CPUMGetHyperDR7(pVCpu);
     998    aValues[iReg].Reg64 = pCtx->dr[7];
    982999    iReg++;
    9831000
     
    10981115                                                        | ((uint64_t)pCtx->pXStateR3->x87.Rsrvd2 << 48);
    10991116    aValues[iReg].XmmControlStatus.XmmStatusControl     = pCtx->pXStateR3->x87.MXCSR;
    1100     aValues[iReg].XmmControlStatus.XmmStatusControlMask = pCtx->pXStateR3->x87.MXCSR_MASK; /* ??? (Isn't this an output field?) */
     1117    aValues[iReg].XmmControlStatus.XmmStatusControlMask = pCtx->pXStateR3->x87.MXCSR_MASK; /** @todo ??? (Isn't this an output field?) */
    11011118    iReg++;
    11021119
     
    11551172}
    11561173
     1174static int nemR3WinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     1175{
     1176    WHV_REGISTER_NAME  aenmNames[128];
     1177
     1178    /* GPRs */
     1179    aenmNames[0]  = WHvX64RegisterRax;
     1180    aenmNames[1]  = WHvX64RegisterRcx;
     1181    aenmNames[2]  = WHvX64RegisterRdx;
     1182    aenmNames[3]  = WHvX64RegisterRbx;
     1183    aenmNames[4]  = WHvX64RegisterRsp;
     1184    aenmNames[5]  = WHvX64RegisterRbp;
     1185    aenmNames[6]  = WHvX64RegisterRsi;
     1186    aenmNames[7]  = WHvX64RegisterRdi;
     1187    aenmNames[8]  = WHvX64RegisterR8;
     1188    aenmNames[9]  = WHvX64RegisterR9;
     1189    aenmNames[10] = WHvX64RegisterR10;
     1190    aenmNames[11] = WHvX64RegisterR11;
     1191    aenmNames[12] = WHvX64RegisterR12;
     1192    aenmNames[13] = WHvX64RegisterR13;
     1193    aenmNames[14] = WHvX64RegisterR14;
     1194    aenmNames[15] = WHvX64RegisterR15;
     1195
     1196    /* RIP & Flags */
     1197    aenmNames[16] = WHvX64RegisterRip;
     1198    aenmNames[17] = WHvX64RegisterRflags;
     1199
     1200    /* Segments */
     1201    aenmNames[18] = WHvX64RegisterEs;
     1202    aenmNames[19] = WHvX64RegisterCs;
     1203    aenmNames[20] = WHvX64RegisterSs;
     1204    aenmNames[21] = WHvX64RegisterDs;
     1205    aenmNames[22] = WHvX64RegisterFs;
     1206    aenmNames[23] = WHvX64RegisterGs;
     1207    aenmNames[24] = WHvX64RegisterLdtr;
     1208    aenmNames[25] = WHvX64RegisterTr;
     1209
     1210    /* Descriptor tables. */
     1211    aenmNames[26] = WHvX64RegisterIdtr;
     1212    aenmNames[27] = WHvX64RegisterGdtr;
     1213
     1214    /* Control registers. */
     1215    aenmNames[28] = WHvX64RegisterCr0;
     1216    aenmNames[29] = WHvX64RegisterCr2;
     1217    aenmNames[30] = WHvX64RegisterCr3;
     1218    aenmNames[31] = WHvX64RegisterCr4;
     1219    aenmNames[32] = WHvX64RegisterCr8;
     1220
     1221    /* Debug registers. */
     1222    aenmNames[33] = WHvX64RegisterDr0;
     1223    aenmNames[34] = WHvX64RegisterDr1;
     1224    aenmNames[35] = WHvX64RegisterDr2;
     1225    aenmNames[36] = WHvX64RegisterDr3;
     1226    aenmNames[37] = WHvX64RegisterDr6;
     1227    aenmNames[38] = WHvX64RegisterDr7;
     1228
     1229    /* Vector state. */
     1230    aenmNames[39] = WHvX64RegisterXmm0;
     1231    aenmNames[40] = WHvX64RegisterXmm1;
     1232    aenmNames[41] = WHvX64RegisterXmm2;
     1233    aenmNames[42] = WHvX64RegisterXmm3;
     1234    aenmNames[43] = WHvX64RegisterXmm4;
     1235    aenmNames[44] = WHvX64RegisterXmm5;
     1236    aenmNames[45] = WHvX64RegisterXmm6;
     1237    aenmNames[46] = WHvX64RegisterXmm7;
     1238    aenmNames[47] = WHvX64RegisterXmm8;
     1239    aenmNames[48] = WHvX64RegisterXmm9;
     1240    aenmNames[49] = WHvX64RegisterXmm10;
     1241    aenmNames[50] = WHvX64RegisterXmm11;
     1242    aenmNames[51] = WHvX64RegisterXmm12;
     1243    aenmNames[52] = WHvX64RegisterXmm13;
     1244    aenmNames[53] = WHvX64RegisterXmm14;
     1245    aenmNames[54] = WHvX64RegisterXmm15;
     1246
     1247    /* Floating point state. */
     1248    aenmNames[55] = WHvX64RegisterFpMmx0;
     1249    aenmNames[56] = WHvX64RegisterFpMmx1;
     1250    aenmNames[57] = WHvX64RegisterFpMmx2;
     1251    aenmNames[58] = WHvX64RegisterFpMmx3;
     1252    aenmNames[59] = WHvX64RegisterFpMmx4;
     1253    aenmNames[60] = WHvX64RegisterFpMmx5;
     1254    aenmNames[61] = WHvX64RegisterFpMmx6;
     1255    aenmNames[62] = WHvX64RegisterFpMmx7;
     1256    aenmNames[63] = WHvX64RegisterFpControlStatus;
     1257    aenmNames[64] = WHvX64RegisterXmmControlStatus;
     1258
     1259    /* MSRs */
     1260    // WHvX64RegisterTsc - don't touch
     1261    aenmNames[65] = WHvX64RegisterEfer;
     1262    aenmNames[66] = WHvX64RegisterKernelGsBase;
     1263    aenmNames[67] = WHvX64RegisterApicBase;
     1264    aenmNames[68] = WHvX64RegisterPat;
     1265    aenmNames[69] = WHvX64RegisterSysenterCs;
     1266    aenmNames[70] = WHvX64RegisterSysenterEip;
     1267    aenmNames[71] = WHvX64RegisterSysenterEsp;
     1268    aenmNames[72] = WHvX64RegisterStar;
     1269    aenmNames[73] = WHvX64RegisterLstar;
     1270    aenmNames[74] = WHvX64RegisterCstar;
     1271    aenmNames[75] = WHvX64RegisterSfmask;
     1272
     1273    /* event injection */
     1274    aenmNames[76] = WHvRegisterPendingInterruption;
     1275    aenmNames[77] = WHvRegisterPendingInterruption;
     1276    aenmNames[78] = WHvRegisterInterruptState;
     1277    aenmNames[79] = WHvRegisterPendingEvent0;
     1278    aenmNames[80] = WHvRegisterPendingEvent1;
     1279    unsigned const cRegs = 81;
     1280
     1281    /*
     1282     * Get the registers.
     1283     */
     1284    WHV_REGISTER_VALUE aValues[cRegs];
     1285    RT_ZERO(aValues);
     1286    Assert(RT_ELEMENTS(aValues) >= cRegs);
     1287    Assert(RT_ELEMENTS(aenmNames) >= cRegs);
     1288#ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
     1289    Log6(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
     1290          pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues));
     1291#endif
     1292    HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues);
     1293    if (SUCCEEDED(hrc))
     1294    {
     1295        /* GPRs */
     1296        Assert(aenmNames[0]  == WHvX64RegisterRax);
     1297        Assert(aenmNames[15] == WHvX64RegisterR15);
     1298        pCtx->rax = aValues[0].Reg64;
     1299        pCtx->rcx = aValues[1].Reg64;
     1300        pCtx->rdx = aValues[2].Reg64;
     1301        pCtx->rbx = aValues[3].Reg64;
     1302        pCtx->rsp = aValues[4].Reg64;
     1303        pCtx->rbp = aValues[5].Reg64;
     1304        pCtx->rsi = aValues[6].Reg64;
     1305        pCtx->rdi = aValues[7].Reg64;
     1306        pCtx->r8  = aValues[8].Reg64;
     1307        pCtx->r9  = aValues[9].Reg64;
     1308        pCtx->r10 = aValues[10].Reg64;
     1309        pCtx->r11 = aValues[11].Reg64;
     1310        pCtx->r12 = aValues[12].Reg64;
     1311        pCtx->r13 = aValues[13].Reg64;
     1312        pCtx->r14 = aValues[14].Reg64;
     1313        pCtx->r15 = aValues[15].Reg64;
     1314
     1315        /* RIP & Flags */
     1316        Assert(aenmNames[16] == WHvX64RegisterRip);
     1317        pCtx->rip      = aValues[16].Reg64;
     1318        pCtx->rflags.u = aValues[17].Reg64;
     1319
     1320        /* Segments */
     1321#define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
     1322            do { \
     1323                Assert(aenmNames[a_idx] == a_enmName); \
     1324                (a_SReg).u64Base  = aValues[a_idx].Segment.Base; \
     1325                (a_SReg).u32Limit = aValues[a_idx].Segment.Limit; \
     1326                (a_SReg).ValidSel = (a_SReg).Sel = aValues[a_idx].Segment.Selector; \
     1327                (a_SReg).Attr.u   = aValues[a_idx].Segment.Attributes; \
     1328                (a_SReg).fFlags   = CPUMSELREG_FLAGS_VALID; \
     1329            } while (0)
     1330        COPY_BACK_SEG(18, WHvX64RegisterEs,   pCtx->es);
     1331        COPY_BACK_SEG(19, WHvX64RegisterCs,   pCtx->cs);
     1332        COPY_BACK_SEG(20, WHvX64RegisterSs,   pCtx->ss);
     1333        COPY_BACK_SEG(21, WHvX64RegisterDs,   pCtx->ds);
     1334        COPY_BACK_SEG(22, WHvX64RegisterFs,   pCtx->fs);
     1335        COPY_BACK_SEG(23, WHvX64RegisterGs,   pCtx->gs);
     1336        COPY_BACK_SEG(24, WHvX64RegisterLdtr, pCtx->ldtr);
     1337        COPY_BACK_SEG(25, WHvX64RegisterTr,   pCtx->tr);
     1338
     1339        /* Descriptor tables. */
     1340        Assert(aenmNames[26] == WHvX64RegisterIdtr);
     1341        pCtx->idtr.cbIdt = aValues[26].Table.Limit;
     1342        pCtx->idtr.pIdt  = aValues[26].Table.Base;
     1343        Assert(aenmNames[27] == WHvX64RegisterGdtr);
     1344        pCtx->gdtr.cbGdt = aValues[27].Table.Limit;
     1345        pCtx->gdtr.pGdt  = aValues[27].Table.Base;
     1346
     1347        /* Control registers. */
     1348        Assert(aenmNames[28] == WHvX64RegisterCr0);
     1349        if (pCtx->cr0 != aValues[28].Reg64)
     1350        {
     1351            CPUMSetGuestCR0(pVCpu, aValues[28].Reg64);
     1352            /** @todo more to do here! */
     1353        }
     1354        pCtx->cr2 = aValues[29].Reg64;
     1355        if (pCtx->cr3 != aValues[30].Reg64)
     1356        {
     1357            CPUMSetGuestCR3(pVCpu, aValues[30].Reg64);
     1358            /** @todo more to do here! */
     1359        }
     1360        if (pCtx->cr4 != aValues[31].Reg64)
     1361        {
     1362            CPUMSetGuestCR4(pVCpu, aValues[31].Reg64);
     1363            /** @todo more to do here! */
     1364        }
     1365        APICSetTpr(pVCpu, (uint8_t)aValues[32].Reg64 << 4);
     1366
     1367        /* Debug registers. */
     1368        Assert(aenmNames[33] == WHvX64RegisterDr0);
     1369    /** @todo fixme */
     1370        if (pCtx->dr[0] != aValues[33].Reg64)
     1371            CPUMSetGuestDR0(pVCpu, aValues[33].Reg64);
     1372        if (pCtx->dr[1] != aValues[34].Reg64)
     1373            CPUMSetGuestDR1(pVCpu, aValues[34].Reg64);
     1374        if (pCtx->dr[2] != aValues[35].Reg64)
     1375            CPUMSetGuestDR2(pVCpu, aValues[35].Reg64);
     1376        if (pCtx->dr[3] != aValues[36].Reg64)
     1377            CPUMSetGuestDR3(pVCpu, aValues[36].Reg64);
     1378        Assert(aenmNames[37] == WHvX64RegisterDr6);
     1379        Assert(aenmNames[38] == WHvX64RegisterDr7);
     1380        if (pCtx->dr[6] != aValues[37].Reg64)
     1381            CPUMSetGuestDR6(pVCpu, aValues[37].Reg64);
     1382        if (pCtx->dr[7] != aValues[38].Reg64)
     1383            CPUMSetGuestDR6(pVCpu, aValues[38].Reg64);
     1384
     1385        /* Vector state. */
     1386        Assert(aenmNames[39] == WHvX64RegisterXmm0);
     1387        Assert(aenmNames[54] == WHvX64RegisterXmm15);
     1388        pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Lo  = aValues[39].Reg128.Low64;
     1389        pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Hi  = aValues[39].Reg128.High64;
     1390        pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Lo  = aValues[40].Reg128.Low64;
     1391        pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Hi  = aValues[40].Reg128.High64;
     1392        pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Lo  = aValues[41].Reg128.Low64;
     1393        pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Hi  = aValues[41].Reg128.High64;
     1394        pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Lo  = aValues[42].Reg128.Low64;
     1395        pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Hi  = aValues[42].Reg128.High64;
     1396        pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Lo  = aValues[43].Reg128.Low64;
     1397        pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Hi  = aValues[43].Reg128.High64;
     1398        pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Lo  = aValues[44].Reg128.Low64;
     1399        pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Hi  = aValues[44].Reg128.High64;
     1400        pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Lo  = aValues[45].Reg128.Low64;
     1401        pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Hi  = aValues[45].Reg128.High64;
     1402        pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Lo  = aValues[46].Reg128.Low64;
     1403        pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Hi  = aValues[46].Reg128.High64;
     1404        pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Lo  = aValues[47].Reg128.Low64;
     1405        pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Hi  = aValues[47].Reg128.High64;
     1406        pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Lo  = aValues[48].Reg128.Low64;
     1407        pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Hi  = aValues[48].Reg128.High64;
     1408        pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Lo = aValues[49].Reg128.Low64;
     1409        pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Hi = aValues[49].Reg128.High64;
     1410        pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Lo = aValues[50].Reg128.Low64;
     1411        pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Hi = aValues[50].Reg128.High64;
     1412        pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Lo = aValues[51].Reg128.Low64;
     1413        pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Hi = aValues[51].Reg128.High64;
     1414        pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Lo = aValues[52].Reg128.Low64;
     1415        pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Hi = aValues[52].Reg128.High64;
     1416        pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Lo = aValues[53].Reg128.Low64;
     1417        pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Hi = aValues[53].Reg128.High64;
     1418        pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Lo = aValues[54].Reg128.Low64;
     1419        pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Hi = aValues[54].Reg128.High64;
     1420
     1421        /* Floating point state. */
     1422        Assert(aenmNames[55] == WHvX64RegisterFpMmx0);
     1423        Assert(aenmNames[62] == WHvX64RegisterFpMmx7);
     1424        pCtx->pXStateR3->x87.aRegs[0].au64[0] = aValues[55].Fp.AsUINT128.Low64;
     1425        pCtx->pXStateR3->x87.aRegs[0].au64[1] = aValues[55].Fp.AsUINT128.High64;
     1426        pCtx->pXStateR3->x87.aRegs[1].au64[0] = aValues[56].Fp.AsUINT128.Low64;
     1427        pCtx->pXStateR3->x87.aRegs[1].au64[1] = aValues[56].Fp.AsUINT128.High64;
     1428        pCtx->pXStateR3->x87.aRegs[2].au64[0] = aValues[57].Fp.AsUINT128.Low64;
     1429        pCtx->pXStateR3->x87.aRegs[2].au64[1] = aValues[57].Fp.AsUINT128.High64;
     1430        pCtx->pXStateR3->x87.aRegs[3].au64[0] = aValues[58].Fp.AsUINT128.Low64;
     1431        pCtx->pXStateR3->x87.aRegs[3].au64[1] = aValues[58].Fp.AsUINT128.High64;
     1432        pCtx->pXStateR3->x87.aRegs[4].au64[0] = aValues[59].Fp.AsUINT128.Low64;
     1433        pCtx->pXStateR3->x87.aRegs[4].au64[1] = aValues[59].Fp.AsUINT128.High64;
     1434        pCtx->pXStateR3->x87.aRegs[5].au64[0] = aValues[60].Fp.AsUINT128.Low64;
     1435        pCtx->pXStateR3->x87.aRegs[5].au64[1] = aValues[60].Fp.AsUINT128.High64;
     1436        pCtx->pXStateR3->x87.aRegs[6].au64[0] = aValues[61].Fp.AsUINT128.Low64;
     1437        pCtx->pXStateR3->x87.aRegs[6].au64[1] = aValues[61].Fp.AsUINT128.High64;
     1438        pCtx->pXStateR3->x87.aRegs[7].au64[0] = aValues[62].Fp.AsUINT128.Low64;
     1439        pCtx->pXStateR3->x87.aRegs[7].au64[1] = aValues[62].Fp.AsUINT128.High64;
     1440
     1441        Assert(aenmNames[63] == WHvX64RegisterFpControlStatus);
     1442        pCtx->pXStateR3->x87.FCW        = aValues[63].FpControlStatus.FpControl;
     1443        pCtx->pXStateR3->x87.FSW        = aValues[63].FpControlStatus.FpStatus;
     1444        pCtx->pXStateR3->x87.FTW        = aValues[63].FpControlStatus.FpTag
     1445                                        /*| (aValues[63].FpControlStatus.Reserved << 8)*/;
     1446        pCtx->pXStateR3->x87.FOP        = aValues[63].FpControlStatus.LastFpOp;
     1447        pCtx->pXStateR3->x87.FPUIP      = (uint32_t)aValues[63].FpControlStatus.LastFpRip;
     1448        pCtx->pXStateR3->x87.CS         = (uint16_t)(aValues[63].FpControlStatus.LastFpRip >> 32);
     1449        pCtx->pXStateR3->x87.Rsrvd1     = (uint16_t)(aValues[63].FpControlStatus.LastFpRip >> 48);
     1450
     1451        Assert(aenmNames[64] == WHvX64RegisterXmmControlStatus);
     1452        pCtx->pXStateR3->x87.FPUDP      = (uint32_t)aValues[64].XmmControlStatus.LastFpRdp;
     1453        pCtx->pXStateR3->x87.DS         = (uint16_t)(aValues[64].XmmControlStatus.LastFpRdp >> 32);
     1454        pCtx->pXStateR3->x87.Rsrvd2     = (uint16_t)(aValues[64].XmmControlStatus.LastFpRdp >> 48);
     1455        pCtx->pXStateR3->x87.MXCSR      = aValues[64].XmmControlStatus.XmmStatusControl;
     1456        pCtx->pXStateR3->x87.MXCSR_MASK = aValues[64].XmmControlStatus.XmmStatusControlMask; /** @todo ??? (Isn't this an output field?) */
     1457
     1458        /* MSRs */
     1459        // WHvX64RegisterTsc - don't touch
     1460        Assert(aenmNames[65] == WHvX64RegisterEfer);
     1461        if (aValues[65].Reg64 != pCtx->msrEFER)
     1462        {
     1463            pCtx->msrEFER = aValues[65].Reg64;
     1464            /** @todo more to do here! */
     1465        }
     1466
     1467        Assert(aenmNames[66] == WHvX64RegisterKernelGsBase);
     1468        pCtx->msrKERNELGSBASE = aValues[66].Reg64;
     1469
     1470        Assert(aenmNames[67] == WHvX64RegisterApicBase);
     1471        if (aValues[67].Reg64 != APICGetBaseMsrNoCheck(pVCpu))
     1472        {
     1473            VBOXSTRICTRC rc2 = APICSetBaseMsr(pVCpu, aValues[67].Reg64);
     1474            Assert(rc2 == VINF_SUCCESS); NOREF(rc2);
     1475        }
     1476
     1477        Assert(aenmNames[68] == WHvX64RegisterPat);
     1478        pCtx->msrPAT    = aValues[68].Reg64;
     1479        /// @todo WHvX64RegisterSysenterCs
     1480        /// @todo WHvX64RegisterSysenterEip
     1481        /// @todo WHvX64RegisterSysenterEsp
     1482        Assert(aenmNames[72] == WHvX64RegisterStar);
     1483        pCtx->msrSTAR   = aValues[72].Reg64;
     1484        Assert(aenmNames[73] == WHvX64RegisterLstar);
     1485        pCtx->msrLSTAR  = aValues[73].Reg64;
     1486        Assert(aenmNames[74] == WHvX64RegisterCstar);
     1487        pCtx->msrCSTAR  = aValues[74].Reg64;
     1488        Assert(aenmNames[75] == WHvX64RegisterSfmask);
     1489        pCtx->msrSFMASK = aValues[75].Reg64;
     1490
     1491        /* event injection */
     1492        /// @todo WHvRegisterPendingInterruption
     1493        /// @todo WHvRegisterInterruptState
     1494        /// @todo WHvRegisterPendingEvent0
     1495        /// @todo WHvRegisterPendingEvent1
     1496
     1497
     1498        return VINF_SUCCESS;
     1499    }
     1500
     1501    AssertLogRelMsgFailed(("WHvGetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
     1502                           pVM->nem.s.hPartition, pVCpu->idCpu, cRegs,
     1503                           hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     1504    return VERR_INTERNAL_ERROR;
     1505}
     1506
    11571507
    11581508#ifdef LOG_ENABLED
     
    11691519    {
    11701520        case WHvRunVpExitReasonMemoryAccess:
    1171             Log2(("Exit: Memory access GCPhys=%RGp GCVirt=%RGv %s %s %s\n",
     1521            Log2(("Exit: Memory access: GCPhys=%RGp GCVirt=%RGv %s %s %s\n",
    11721522                  pExitReason->MemoryAccess.Gpa, pExitReason->MemoryAccess.Gva,
    11731523                  pExitReason->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessRead ? "read"
     
    11821532
    11831533        case WHvRunVpExitReasonX64IoPortAccess:
    1184             Log2(("Exit: Memory access IoPort=%#x LB %u %s%s%s rax=%#RX64 rcx=%#RX64 rsi=%#RX64 rdi=%#RX64\n",
     1534            Log2(("Exit: I/O port access: IoPort=%#x LB %u %s%s%s rax=%#RX64 rcx=%#RX64 rsi=%#RX64 rdi=%#RX64\n",
    11851535                  pExitReason->IoPortAccess.PortNumber,
    11861536                  pExitReason->IoPortAccess.AccessInfo.AccessSize,
     
    11921542                  pExitReason->IoPortAccess.Rsi,
    11931543                  pExitReason->IoPortAccess.Rdi));
    1194             Log2(("Exit: ds=%#x:{%#RX64 LB %#RX32, %#x}  es=%#x:{%#RX64 LB %#RX32, %#x}\n",
     1544            Log2(("Exit: + ds=%#x:{%#RX64 LB %#RX32, %#x}  es=%#x:{%#RX64 LB %#RX32, %#x}\n",
    11951545                  pExitReason->IoPortAccess.Ds.Selector,
    11961546                  pExitReason->IoPortAccess.Ds.Base,
     
    12471597    {
    12481598        const WHV_VP_EXIT_CONTEXT *pVpCtx = &pExitReason->IoPortAccess.VpContext;
    1249         Log2(("Exit: CS:RIP=%04x:%08RX64 RFLAGS=%06RX64 cbInstr=%u CS={%RX64 L %#RX32, %#x}\n",
     1599        Log2(("Exit: + CS:RIP=%04x:%08RX64 RFLAGS=%06RX64 cbInstr=%u CS={%RX64 L %#RX32, %#x}\n",
    12501600              pVpCtx->Cs.Selector,
    12511601              pVpCtx->Rip,
     
    12531603              pVpCtx->InstructionLength,
    12541604              pVpCtx->Cs.Base, pVpCtx->Cs.Limit, pVpCtx->Cs.Attributes));
    1255         Log2(("Exit: cpl=%d CR0.PE=%d CR0.AM=%d EFER.LMA=%d DebugActive=%d InterruptionPending=%d InterruptShadow=%d\n",
     1605        Log2(("Exit: + cpl=%d CR0.PE=%d CR0.AM=%d EFER.LMA=%d DebugActive=%d InterruptionPending=%d InterruptShadow=%d\n",
    12561606              pVpCtx->ExecutionState.Cpl,
    12571607              pVpCtx->ExecutionState.Cr0Pe,
     
    12641614                  ("ExecutionState.AsUINT16=%#x\n", pVpCtx->ExecutionState.AsUINT16));
    12651615
    1266         /** @todo Someone please explain why the InstructionBytes fields are 16 bytes
    1267          * long, when 15 would've been sufficent and saved 3-7 bytes of alignment
    1268          * padding?  Intel max length is 15, so is this sSome ARM stuff?  Aren't ARM
     1616        /** @todo Someone at Microsoft please explain why the InstructionBytes fields
     1617         * are 16 bytes long, when 15 would've been sufficent and saved 3-7 bytes of
     1618         * alignment padding?  Intel max length is 15, so is this sSome ARM stuff?
     1619         * Aren't ARM
    12691620         * instructions max 32-bit wide?  Confused. */
    12701621        if (fExitInstr && pExitReason->IoPortAccess.InstructionByteCount > 0)
    1271             Log2(("Exit: Instruction %.*Rhxs\n",
     1622            Log2(("Exit: + Instruction %.*Rhxs\n",
    12721623                  pExitReason->IoPortAccess.InstructionByteCount, pExitReason->IoPortAccess.InstructionBytes));
    12731624    }
    12741625}
     1626
     1627
     1628/**
     1629 * Logs the current CPU state.
     1630 */
     1631static void nemR3WinLogState(PVM pVM, PVMCPU pVCpu)
     1632{
     1633    if (LogIs3Enabled())
     1634    {
     1635        char szRegs[4096];
     1636        DBGFR3RegPrintf(pVM->pUVM, pVCpu->idCpu, &szRegs[0], sizeof(szRegs),
     1637                        "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
     1638                        "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
     1639                        "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
     1640                        "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
     1641                        "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
     1642                        "cs={%04VR{cs} base=%016VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} cr0=%016VR{cr0}\n"
     1643                        "ds={%04VR{ds} base=%016VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} cr2=%016VR{cr2}\n"
     1644                        "es={%04VR{es} base=%016VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} cr3=%016VR{cr3}\n"
     1645                        "fs={%04VR{fs} base=%016VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr4=%016VR{cr4}\n"
     1646                        "gs={%04VR{gs} base=%016VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr8=%016VR{cr8}\n"
     1647                        "ss={%04VR{ss} base=%016VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}}\n"
     1648                        "dr0=%016VR{dr0} dr1=%016VR{dr1} dr2=%016VR{dr2} dr3=%016VR{dr3}\n"
     1649                        "dr6=%016VR{dr6} dr7=%016VR{dr7}\n"
     1650                        "gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim}  idtr=%016VR{idtr_base}:%04VR{idtr_lim}  rflags=%08VR{rflags}\n"
     1651                        "ldtr={%04VR{ldtr} base=%016VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%08VR{ldtr_attr}}\n"
     1652                        "tr  ={%04VR{tr} base=%016VR{tr_base} limit=%08VR{tr_lim} flags=%08VR{tr_attr}}\n"
     1653                        "    sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
     1654                        "        efer=%016VR{efer}\n"
     1655                        "         pat=%016VR{pat}\n"
     1656                        "     sf_mask=%016VR{sf_mask}\n"
     1657                        "krnl_gs_base=%016VR{krnl_gs_base}\n"
     1658                        "       lstar=%016VR{lstar}\n"
     1659                        "        star=%016VR{star} cstar=%016VR{cstar}\n"
     1660                        "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
     1661                        );
     1662
     1663        char szInstr[256];
     1664        DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, 0, 0,
     1665                           DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_DEFAULT_MODE,
     1666                           szInstr, sizeof(szInstr), NULL);
     1667        Log3(("%s%s\n", szRegs, szInstr));
     1668    }
     1669}
     1670
    12751671#endif /* LOG_ENABLED */
    12761672
     1673
     1674/**
     1675 * Advances the guest RIP and clear EFLAGS.RF.
     1676 *
     1677 * This may clear VMCPU_FF_INHIBIT_INTERRUPTS.
     1678 *
     1679 * @param   pVCpu           The cross context virtual CPU structure.
     1680 * @param   pCtx            The CPU context to update.
     1681 * @param   pExitCtx        The exit context.
     1682 */
     1683DECLINLINE(void) nemR3WinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx)
     1684{
     1685    /* Advance the RIP. */
     1686    Assert(pExitCtx->InstructionLength > 0 && pExitCtx->InstructionLength < 16);
     1687    pCtx->rip += pExitCtx->InstructionLength;
     1688    pCtx->rflags.Bits.u1RF = 0;
     1689
     1690    /* Update interrupt inhibition. */
     1691    if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
     1692    { /* likely */ }
     1693    else if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
     1694        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
     1695}
     1696
     1697
     1698static VBOXSTRICTRC nemR3WinHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1699{
     1700    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1701    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1702}
     1703
     1704
     1705/**
     1706 * @callback_method_impl{FNPGMPHYSNEMQUERYCHECKER}
     1707 */
     1708static DECLCALLBACK(int) nemR3WinHandleMemoryAccessPageCheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys,
     1709                                                                       PPGMPHYSNEMPAGEINFO pInfo, void *pvUser)
     1710{
     1711    uint8_t u2State = pInfo->u2NemState;
     1712    int rc = nemR3NativeSetPhysPage(pVM, GCPhys, pInfo->fNemProt, &u2State,
     1713                                    u2State <= NEM_WIN_PAGE_STATE_UNMAPPED /*fBackingChanged*/);
     1714    pInfo->u2NemState = u2State;
     1715    RT_NOREF(pVCpu, pvUser);
     1716    return rc;
     1717}
     1718
     1719
     1720/**
     1721 * Handles an memory access VMEXIT.
     1722 *
     1723 * This can be triggered by a number of things.
     1724 *
     1725 * @returns Strict VBox status code.
     1726 * @param   pVM             The cross context VM structure.
     1727 * @param   pVCpu           The cross context virtual CPU structure.
     1728 * @param   pCtx            The CPU context to update.
     1729 * @param   pExitReason     The exit reason information.
     1730 */
     1731static VBOXSTRICTRC nemR3WinHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx)
     1732{
     1733    /*
     1734     * Ask PGM for information about the given GCPhys.  We need to check if we're
     1735     * out of sync first.
     1736     */
     1737    PGMPHYSNEMPAGEINFO Info;
     1738    int rc = PGMPhysNemQueryPageInfo(pVM, pVCpu, pMemCtx->Gpa, &Info, nemR3WinHandleMemoryAccessPageCheckerCallback, NULL);
     1739    if (RT_SUCCESS(rc))
     1740    {
     1741        if (Info.fNemProt & (pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite ? NEM_PAGE_PROT_WRITE :NEM_PAGE_PROT_READ))
     1742            return VINF_SUCCESS;
     1743    }
     1744
     1745    /*
     1746     * Emulate the memory access, either access handler or special memory.
     1747     */
     1748    VBOXSTRICTRC rcStrict;
     1749    if (pMemCtx->InstructionByteCount > 0)
     1750        rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMemCtx->VpContext.Rip,
     1751                                                pMemCtx->InstructionBytes, pMemCtx->InstructionByteCount);
     1752    else
     1753        rcStrict = IEMExecOne(pVCpu);
     1754    /** @todo do we need to do anything wrt debugging here?   */
     1755    return rcStrict;
     1756}
     1757
     1758
     1759/**
     1760 * Handles an I/O port access VMEXIT.
     1761 *
     1762 * We ASSUME that the hypervisor has don't I/O port access control.
     1763 *
     1764 * @returns Strict VBox status code.
     1765 * @param   pVM             The cross context VM structure.
     1766 * @param   pVCpu           The cross context virtual CPU structure.
     1767 * @param   pCtx            The CPU context to update.
     1768 * @param   pExitReason     The exit reason information.
     1769 */
     1770static VBOXSTRICTRC nemR3WinHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx,
     1771                                               WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx)
     1772{
     1773    VBOXSTRICTRC rcStrict;
     1774    if (!pIoPortCtx->AccessInfo.StringOp)
     1775    {
     1776        /*
     1777         * Simple port I/O.
     1778         */
     1779        Assert(pCtx->rax == pIoPortCtx->Rax);
     1780
     1781        static uint32_t const s_fAndMask[8] =
     1782        {   UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX };
     1783        uint32_t const fAndMask = s_fAndMask[pIoPortCtx->AccessInfo.AccessSize];
     1784        if (pIoPortCtx->AccessInfo.IsWrite)
     1785        {
     1786            rcStrict = IOMIOPortWrite(pVM, pVCpu, pIoPortCtx->PortNumber, (uint32_t)pIoPortCtx->Rax & fAndMask,
     1787                                      pIoPortCtx->AccessInfo.AccessSize);
     1788            if (IOM_SUCCESS(rcStrict))
     1789                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);
     1790        }
     1791        else
     1792        {
     1793            uint32_t uValue = 0;
     1794            rcStrict = IOMIOPortRead(pVM, pVCpu, pIoPortCtx->PortNumber, &uValue,
     1795                                     pIoPortCtx->AccessInfo.AccessSize);
     1796            if (IOM_SUCCESS(rcStrict))
     1797            {
     1798                pCtx->eax = (pCtx->eax & ~fAndMask) | (uValue & fAndMask);
     1799                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);
     1800            }
     1801        }
     1802    }
     1803    else
     1804    {
     1805        /*
     1806         * String port I/O.
     1807         */
     1808        /** @todo Someone at Microsoft please explain how we can get the address mode
     1809         * from the IoPortAccess.VpContext.  CS.Attributes is only sufficient for
     1810         * getting the default mode, it can always be overridden by a prefix.   This
     1811         * forces us to interpret the instruction from opcodes, which is suboptimal.
     1812         * Both AMD-V and VT-x includes the address size in the exit info, at least on
     1813         * CPUs that are reasonably new. */
     1814        Assert(   pIoPortCtx->Ds.Base     == pCtx->ds.u64Base
     1815               && pIoPortCtx->Ds.Limit    == pCtx->ds.u32Limit
     1816               && pIoPortCtx->Ds.Selector == pCtx->ds.Sel);
     1817        Assert(   pIoPortCtx->Es.Base     == pCtx->es.u64Base
     1818               && pIoPortCtx->Es.Limit    == pCtx->es.u32Limit
     1819               && pIoPortCtx->Es.Selector == pCtx->es.Sel);
     1820        Assert(pIoPortCtx->Rdi == pCtx->rdi);
     1821        Assert(pIoPortCtx->Rsi == pCtx->rsi);
     1822        Assert(pIoPortCtx->Rcx == pCtx->rcx);
     1823        Assert(pIoPortCtx->Rcx == pCtx->rcx);
     1824
     1825        rcStrict = IEMExecOne(pVCpu);
     1826    }
     1827    if (IOM_SUCCESS(rcStrict))
     1828    {
     1829        /*
     1830         * Do debug checks.
     1831         */
     1832        if (   pIoPortCtx->VpContext.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflext DR7? */
     1833            || (pIoPortCtx->VpContext.Rflags & X86_EFL_TF)
     1834            || DBGFBpIsHwIoArmed(pVM) )
     1835        {
     1836            /** @todo Debugging. */
     1837        }
     1838    }
     1839    return rcStrict;
     1840}
     1841
     1842
     1843static VBOXSTRICTRC nemR3WinHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1844{
     1845    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1846    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1847}
     1848
     1849
     1850static VBOXSTRICTRC nemR3WinHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1851{
     1852    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1853    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1854}
     1855
     1856
     1857static VBOXSTRICTRC nemR3WinHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1858{
     1859    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1860    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1861}
     1862
     1863
     1864static VBOXSTRICTRC nemR3WinHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1865{
     1866    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1867    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1868}
     1869
     1870
     1871static VBOXSTRICTRC nemR3WinHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1872{
     1873    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1874    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1875}
     1876
     1877
     1878static VBOXSTRICTRC nemR3WinHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1879{
     1880    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1881    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1882}
     1883
     1884
     1885static VBOXSTRICTRC nemR3WinHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1886{
     1887    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     1888    AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
     1889}
     1890
     1891
    12771892VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu)
    12781893{
    1279     /*
    1280      * Just some simple experiment here that runs a couple of instructions.
    1281      */
    1282     PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
    1283     int rc = nemR3WinCopyOutState(pVM, pVCpu, pCtx);
    1284     if (RT_SUCCESS(rc))
    1285     {
     1894#ifdef LOG_ENABLED
     1895    if (LogIs3Enabled())
     1896    {
     1897        Log3(("nemR3NativeRunGC: Entering #%u\n", pVCpu->idCpu));
     1898        nemR3WinLogState(pVM, pVCpu);
     1899    }
     1900#endif
     1901
     1902    /*
     1903     * The run loop.
     1904     *
     1905     * Current approach to state updating to use the sledgehammer and sync
     1906     * everything every time.  This will be optimized later.
     1907     */
     1908    const bool   fSingleStepping = false; /** @todo get this from somewhere. */
     1909    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
     1910    for (;;)
     1911    {
     1912        /*
     1913         * Copy the state.
     1914         */
     1915        PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
     1916        int rc2 = nemR3WinCopyStateToHyperV(pVM, pVCpu, pCtx);
     1917        AssertRCBreakStmt(rc2, rcStrict = rc2);
     1918
     1919        /*
     1920         * Run a bit.
     1921         */
    12861922        WHV_RUN_VP_EXIT_CONTEXT ExitReason;
    12871923        RT_ZERO(ExitReason);
    1288         HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
    1289         Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d)\n", hrc, ExitReason.ExitReason));
     1924        if (   !VM_FF_IS_PENDING(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
     1925            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
     1926        {
     1927            HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
     1928            AssertLogRelMsgBreakStmt(SUCCEEDED(hrc),
     1929                                     ("WHvRunVirtualProcessor(%p, %u,,) -> %Rhrc (Last=%#x/%u)\n", pVM->nem.s.hPartition, pVCpu->idCpu,
     1930                                      hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue),
     1931                                     rcStrict = VERR_INTERNAL_ERROR);
     1932            Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d)\n", hrc, ExitReason.ExitReason, ExitReason.ExitReason));
     1933        }
     1934        else
     1935        {
     1936            LogFlow(("nemR3NativeRunGC: returning: pending FF (pre exec)\n"));
     1937            break;
     1938        }
     1939
     1940        /*
     1941         * Copy back the state.
     1942         */
     1943        rc2 = nemR3WinCopyStateFromHyperV(pVM, pVCpu, pCtx);
     1944        AssertRCBreakStmt(rc2, rcStrict = rc2);
     1945
     1946#ifdef VBOX_STRICT
     1947        /* Assert that the VpContext field makes sense. */
     1948        switch (ExitReason.ExitReason)
     1949        {
     1950            case WHvRunVpExitReasonMemoryAccess:
     1951            case WHvRunVpExitReasonX64IoPortAccess:
     1952            case WHvRunVpExitReasonX64MsrAccess:
     1953            case WHvRunVpExitReasonX64Cpuid:
     1954            case WHvRunVpExitReasonException:
     1955            case WHvRunVpExitReasonUnrecoverableException:
     1956                Assert(ExitReason.IoPortAccess.VpContext.InstructionLength > 0);
     1957                Assert(ExitReason.IoPortAccess.VpContext.InstructionLength < 16);
     1958                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cpl == CPUMGetGuestCPL(pVCpu));
     1959                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cr0Pe == RT_BOOL(pCtx->cr0 & X86_CR0_PE));
     1960                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cr0Am == RT_BOOL(pCtx->cr0 & X86_CR0_AM));
     1961                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.EferLma == RT_BOOL(pCtx->msrEFER & MSR_K6_EFER_LMA));
     1962                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.DebugActive == RT_BOOL(pCtx->dr[7] & X86_DR7_ENABLED_MASK));
     1963                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Reserved0 == 0);
     1964                Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Reserved1 == 0);
     1965                Assert(ExitReason.IoPortAccess.VpContext.Rip == pCtx->rip);
     1966                Assert(ExitReason.IoPortAccess.VpContext.Rflags == pCtx->rflags.u);
     1967                Assert(   ExitReason.IoPortAccess.VpContext.Cs.Base     == pCtx->cs.u64Base
     1968                       && ExitReason.IoPortAccess.VpContext.Cs.Limit    == pCtx->cs.u32Limit
     1969                       && ExitReason.IoPortAccess.VpContext.Cs.Selector == pCtx->cs.Sel);
     1970                break;
     1971            default: break; /* shut up compiler. */
     1972        }
     1973#endif
     1974
     1975#ifdef LOG_ENABLED
     1976        /*
     1977         * Do some logging.
     1978         */
    12901979        if (LogIs2Enabled())
    12911980            nemR3WinLogExitReason(&ExitReason);
    1292 
    1293         rc = VERR_NOT_IMPLEMENTED;
    1294     }
    1295     return rc;
     1981        if (LogIs3Enabled())
     1982            nemR3WinLogState(pVM, pVCpu);
     1983#endif
     1984
     1985        /*
     1986         * Deal with the exit.
     1987         */
     1988        switch (ExitReason.ExitReason)
     1989        {
     1990            /* Frequent exits: */
     1991            case WHvRunVpExitReasonCanceled:
     1992            case WHvRunVpExitReasonAlerted:
     1993                rcStrict = VINF_SUCCESS;
     1994                break;
     1995
     1996            case WHvRunVpExitReasonX64Halt:
     1997                rcStrict = nemR3WinHandleHalt(pVM, pVCpu, pCtx, &ExitReason);
     1998                break;
     1999
     2000            case WHvRunVpExitReasonMemoryAccess:
     2001                rcStrict = nemR3WinHandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess);
     2002                break;
     2003
     2004            case WHvRunVpExitReasonX64IoPortAccess:
     2005                rcStrict = nemR3WinHandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess);
     2006                break;
     2007
     2008            case WHvRunVpExitReasonX64InterruptWindow:
     2009                rcStrict = nemR3WinHandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason);
     2010                break;
     2011
     2012            case WHvRunVpExitReasonX64MsrAccess: /* needs configuring */
     2013                rcStrict = nemR3WinHandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason);
     2014                break;
     2015
     2016            case WHvRunVpExitReasonX64Cpuid: /* needs configuring */
     2017                rcStrict = nemR3WinHandleCpuId(pVM, pVCpu, pCtx, &ExitReason);
     2018                break;
     2019
     2020            case WHvRunVpExitReasonException: /* needs configuring */
     2021                rcStrict = nemR3WinHandleException(pVM, pVCpu, pCtx, &ExitReason);
     2022                break;
     2023
     2024            /* Unlikely exits: */
     2025            case WHvRunVpExitReasonUnsupportedFeature:
     2026                rcStrict = nemR3WinHandleUD(pVM, pVCpu, pCtx, &ExitReason);
     2027                break;
     2028
     2029            case WHvRunVpExitReasonUnrecoverableException:
     2030                rcStrict = nemR3WinHandleTripleFault(pVM, pVCpu, pCtx, &ExitReason);
     2031                break;
     2032
     2033            case WHvRunVpExitReasonInvalidVpRegisterValue:
     2034                rcStrict = nemR3WinHandleInvalidState(pVM, pVCpu, pCtx, &ExitReason);
     2035                break;
     2036
     2037            /* Undesired exits: */
     2038            case WHvRunVpExitReasonNone:
     2039            default:
     2040                AssertLogRelMsgFailed(("Unknown ExitReason: %#x\n", ExitReason.ExitReason));
     2041                rcStrict = VERR_INTERNAL_ERROR_3;
     2042                break;
     2043        }
     2044        if (rcStrict != VINF_SUCCESS)
     2045        {
     2046            LogFlow(("nemR3NativeRunGC: returning: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     2047            break;
     2048        }
     2049
     2050        /* If any FF is pending, return to the EM loops.  That's okay for the
     2051           current sledgehammer approach. */
     2052        if (   VM_FF_IS_PENDING(   pVM,   !fSingleStepping ? VM_FF_HP_R0_PRE_HM_MASK    : VM_FF_HP_R0_PRE_HM_STEP_MASK)
     2053            || VMCPU_FF_IS_PENDING(pVCpu, !fSingleStepping ? VMCPU_FF_HP_R0_PRE_HM_MASK : VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
     2054        {
     2055            LogFlow(("nemR3NativeRunGC: returning: pending FF\n"));
     2056            break;
     2057        }
     2058    }
     2059
     2060    return rcStrict;
    12962061}
    12972062
Note: See TracChangeset for help on using the changeset viewer.

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