VirtualBox

Changeset 72446 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jun 5, 2018 8:53:01 AM (7 years ago)
Author:
vboxsync
Message:

NEM/win: Working on intercepting VMMCALL and VMCALL. bugref:9044

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r72427 r72446  
    25202520#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    25212521
     2522
     2523/**
     2524 * Worker for nemHCWinHandleMessageException & nemR3WinHandleExitException that
     2525 * checks if the given opcodes are of interest at all.
     2526 *
     2527 * @returns true if interesting, false if not.
     2528 * @param   cbOpcodes           Number of opcode bytes available.
     2529 * @param   pbOpcodes           The opcode bytes.
     2530 * @param   f64BitMode          Whether we're in 64-bit mode.
     2531 */
     2532DECLINLINE(bool) nemHcWinIsInterestingUndefinedOpcode(uint8_t cbOpcodes, uint8_t const *pbOpcodes, bool f64BitMode)
     2533{
     2534    /*
     2535     * Currently only interested in VMCALL and VMMCALL.
     2536     */
     2537    while (cbOpcodes >= 3)
     2538    {
     2539        switch (pbOpcodes[0])
     2540        {
     2541            case 0x0f:
     2542                switch (pbOpcodes[1])
     2543                {
     2544                    case 0x01:
     2545                        switch (pbOpcodes[2])
     2546                        {
     2547                            case 0xc1: /* 0f 01 c1  VMCALL */
     2548                                return true;
     2549                            case 0xd9: /* 0f 01 d9  VMMCALL */
     2550                                return true;
     2551                            default:
     2552                                break;
     2553                        }
     2554                        break;
     2555                }
     2556                break;
     2557
     2558            default:
     2559                return false;
     2560
     2561            /* prefixes */
     2562            case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
     2563            case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
     2564                if (!f64BitMode)
     2565                    return false;
     2566                RT_FALL_THRU();
     2567            case X86_OP_PRF_CS:
     2568            case X86_OP_PRF_SS:
     2569            case X86_OP_PRF_DS:
     2570            case X86_OP_PRF_ES:
     2571            case X86_OP_PRF_FS:
     2572            case X86_OP_PRF_GS:
     2573            case X86_OP_PRF_SIZE_OP:
     2574            case X86_OP_PRF_SIZE_ADDR:
     2575            case X86_OP_PRF_LOCK:
     2576            case X86_OP_PRF_REPZ:
     2577            case X86_OP_PRF_REPNZ:
     2578                cbOpcodes--;
     2579                pbOpcodes++;
     2580                continue;
     2581        }
     2582        break;
     2583    }
     2584    return false;
     2585}
     2586
     2587
     2588#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2589/**
     2590 * Copies state included in a exception intercept message.
     2591 *
     2592 * @param   pVCpu           The cross context per CPU structure.
     2593 * @param   pMsg            The message.
     2594 * @param   pCtx            The register context.
     2595 * @param   fClearXcpt      Clear pending exception.
     2596 */
     2597DECLINLINE(void) nemHCWinCopyStateFromExceptionMessage(PVMCPU pVCpu, HV_X64_EXCEPTION_INTERCEPT_MESSAGE const *pMsg,
     2598                                                       PCPUMCTX pCtx, bool fClearXcpt)
     2599{
     2600    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
     2601    pCtx->fExtrn &= ~(  CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_DS
     2602                      | (fClearXcpt ? CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT : 0) );
     2603    pCtx->rax = pMsg->Rax;
     2604    pCtx->rcx = pMsg->Rcx;
     2605    pCtx->rdx = pMsg->Rdx;
     2606    pCtx->rbx = pMsg->Rbx;
     2607    pCtx->rsp = pMsg->Rsp;
     2608    pCtx->rbp = pMsg->Rbp;
     2609    pCtx->rsi = pMsg->Rsi;
     2610    pCtx->rdi = pMsg->Rdi;
     2611    pCtx->r8  = pMsg->R8;
     2612    pCtx->r9  = pMsg->R9;
     2613    pCtx->r10 = pMsg->R10;
     2614    pCtx->r11 = pMsg->R11;
     2615    pCtx->r12 = pMsg->R12;
     2616    pCtx->r13 = pMsg->R13;
     2617    pCtx->r14 = pMsg->R14;
     2618    pCtx->r15 = pMsg->R15;
     2619    NEM_WIN_COPY_BACK_SEG(pCtx->ds, pMsg->DsSegment);
     2620    NEM_WIN_COPY_BACK_SEG(pCtx->ss, pMsg->SsSegment);
     2621}
     2622#elif defined(IN_RING3)
     2623/**
     2624 * Copies state included in a exception intercept exit.
     2625 *
     2626 * @param   pVCpu           The cross context per CPU structure.
     2627 * @param   pExit           The VM exit information.
     2628 * @param   pCtx            The register context.
     2629 * @param   fClearXcpt      Clear pending exception.
     2630 */
     2631DECLINLINE(void) nemR3WinCopyStateFromExceptionMessage(PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit,
     2632                                                       PCPUMCTX pCtx, bool fClearXcpt)
     2633{
     2634    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2635    if (fClearXcpt)
     2636        pCtx->fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT;
     2637}
     2638#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2639
     2640
     2641#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2642/**
     2643 * Deals with exception intercept message (HvMessageTypeX64ExceptionIntercept).
     2644 *
     2645 * @returns Strict VBox status code.
     2646 * @param   pVCpu           The cross context per CPU structure.
     2647 * @param   pMsg            The message.
     2648 * @param   pCtx            The register context.
     2649 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
     2650 * @sa      nemR3WinHandleExitMsr
     2651 */
     2652NEM_TMPL_STATIC VBOXSTRICTRC
     2653nemHCWinHandleMessageException(PVMCPU pVCpu, HV_X64_EXCEPTION_INTERCEPT_MESSAGE const *pMsg, PCPUMCTX pCtx, PGVMCPU pGVCpu)
     2654{
     2655    /*
     2656     * Assert sanity.
     2657     */
     2658    AssertMsg(pMsg->Header.InstructionLength < 0x10, ("%#x\n", pMsg->Header.InstructionLength));
     2659    Assert(   pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ
     2660           || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE
     2661           || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_EXECUTE);
     2662    Assert(pMsg->Header.ExecutionState.InterruptionPending);
     2663
     2664    /*
     2665     * Handle the intercept.
     2666     */
     2667    switch (pMsg->ExceptionVector)
     2668    {
     2669        /*
     2670         * We get undefined opcodes on VMMCALL(AMD) & VMCALL(Intel) instructions
     2671         * and need to turn them over to GIM.
     2672         */
     2673        case X86_XCPT_UD:
     2674            if (nemHcWinIsInterestingUndefinedOpcode(pMsg->InstructionByteCount, pMsg->InstructionBytes,
     2675                                                     pMsg->Header.ExecutionState.EferLma && pMsg->Header.CsSegment.Long ))
     2676            {
     2677                nemHCWinCopyStateFromExceptionMessage(pVCpu, pMsg, pCtx, true /*fClearXcpt*/);
     2678                VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx,
     2679                                                                          NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "#UD");
     2680                if (rcStrict == VINF_SUCCESS)
     2681                {
     2682                    rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMsg->Header.Rip, pMsg->InstructionBytes,
     2683                                                            pMsg->InstructionByteCount);
     2684                    Log4(("XcptExit/%u: %04x:%08RX64/%s: #UD -> emulated -> %Rrc\n", pVCpu->idCpu, pMsg->Header.CsSegment.Selector,
     2685                          pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), VBOXSTRICTRC_VAL(rcStrict) ));
     2686                }
     2687                else
     2688                    Log4(("XcptExit/%u: %04x:%08RX64/%s: #UD -> state import (emulate) -> %Rrc\n",
     2689                          pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
     2690                          nemHCWinExecStateToLogStr(&pMsg->Header), VBOXSTRICTRC_VAL(rcStrict) ));
     2691                return rcStrict;
     2692            }
     2693            Log4(("XcptExit/%u: %04x:%08RX64/%s: #UD [%.*Rhxs] -> re-injected\n", pVCpu->idCpu, pMsg->Header.CsSegment.Selector,
     2694                  pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),  pMsg->InstructionByteCount, pMsg->InstructionBytes ));
     2695            break;
     2696
     2697        /*
     2698         * Filter debug exceptions.
     2699         */
     2700        case X86_XCPT_DB:
     2701            break;
     2702
     2703        case X86_XCPT_BP:
     2704            break;
     2705
     2706        /* This shouldn't happen. */
     2707        default:
     2708            AssertLogRelMsgFailedReturn(("ExceptionVector=%#x\n", pMsg->ExceptionVector),  VERR_IEM_IPE_6);
     2709    }
     2710
     2711    return VINF_SUCCESS;
     2712}
     2713#elif defined(IN_RING3)
     2714/**
     2715 * Deals with MSR access exits (WHvRunVpExitReasonException).
     2716 *
     2717 * @returns Strict VBox status code.
     2718 * @param   pVM             The cross context VM structure.
     2719 * @param   pVCpu           The cross context per CPU structure.
     2720 * @param   pExit           The VM exit information to handle.
     2721 * @param   pCtx            The register context.
     2722 * @sa      nemR3WinHandleExitException
     2723 */
     2724NEM_TMPL_STATIC VBOXSTRICTRC
     2725nemR3WinHandleExitException(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2726{
     2727    /*
     2728     * Assert sanity.
     2729     */
     2730    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     2731#if 0
     2732    Log4(("XcptExit/%u: %04x:%08RX64/%s: %x\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpException.ExceptionType));
     2733    nemR3WinCopyStateFromExceptionMessage(pVCpu, pExit, pCtx, true /*fClearXcpt*/);
     2734    VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "#UD");
     2735    if (rcStrict != VINF_SUCCESS)
     2736        return rcStrict;
     2737#endif
     2738    Assert(pExit->VpContext.ExecutionState.InterruptionPending);
     2739
     2740    /*
     2741     * Handle the intercept.
     2742     */
     2743    switch (pExit->VpException.ExceptionType)
     2744    {
     2745        /*
     2746         * We get undefined opcodes on VMMCALL(AMD) & VMCALL(Intel) instructions
     2747         * and need to turn them over to GIM.
     2748         */
     2749        case X86_XCPT_UD:
     2750            if (nemHcWinIsInterestingUndefinedOpcode(pExit->VpException.InstructionByteCount, pExit->VpException.InstructionBytes,
     2751                                                     pExit->VpContext.ExecutionState.EferLma && pExit->VpContext.Cs.Long ))
     2752            {
     2753                nemR3WinCopyStateFromExceptionMessage(pVCpu, pExit, pCtx, true /*fClearXcpt*/);
     2754                VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx,
     2755                                                                          NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "#UD");
     2756                if (rcStrict == VINF_SUCCESS)
     2757                {
     2758                    rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pExit->VpContext.Rip,
     2759                                                            pExit->VpException.InstructionBytes,
     2760                                                            pExit->VpException.InstructionByteCount);
     2761                    Log4(("XcptExit/%u: %04x:%08RX64/%s: #UD -> emulated -> %Rrc\n",
     2762                          pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip,
     2763                          nemR3WinExecStateToLogStr(&pExit->VpContext), VBOXSTRICTRC_VAL(rcStrict) ));
     2764                }
     2765                else
     2766                    Log4(("XcptExit/%u: %04x:%08RX64/%s: #UD -> state import (emulate) -> %Rrc\n",
     2767                          pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip,
     2768                          nemR3WinExecStateToLogStr(&pExit->VpContext), VBOXSTRICTRC_VAL(rcStrict) ));
     2769                return rcStrict;
     2770            }
     2771            Log4(("XcptExit/%u: %04x:%08RX64/%s: #UD [%.*Rhxs] -> re-injected\n", pVCpu->idCpu,
     2772                  pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2773                  pExit->VpException.InstructionByteCount, pExit->VpException.InstructionBytes ));
     2774            break;
     2775
     2776        /*
     2777         * Filter debug exceptions.
     2778         */
     2779        case X86_XCPT_DB:
     2780            break;
     2781
     2782        case X86_XCPT_BP:
     2783            break;
     2784
     2785        /* This shouldn't happen. */
     2786        default:
     2787            AssertLogRelMsgFailedReturn(("ExceptionType=%#x\n", pExit->VpException.ExceptionType),  VERR_IEM_IPE_6);
     2788    }
     2789
     2790    RT_NOREF_PV(pVM);
     2791    return VINF_SUCCESS;
     2792}
     2793#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2794
     2795
    25222796#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    25232797/**
     
    26932967                return nemHCWinHandleMessageMsr(pVCpu, &pMsg->X64MsrIntercept, pCtx, pGVCpu);
    26942968
     2969            case HvMessageTypeX64ExceptionIntercept:
     2970                Assert(pMsg->Header.PayloadSize == sizeof(pMsg->X64ExceptionIntercept));
     2971                STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitException);
     2972                return nemHCWinHandleMessageException(pVCpu, &pMsg->X64ExceptionIntercept, pCtx, pGVCpu);
     2973
    26952974            case HvMessageTypeUnrecoverableException:
    26962975                Assert(pMsg->Header.PayloadSize == sizeof(pMsg->X64InterceptHeader));
     
    27052984                                            VERR_NEM_IPE_3);
    27062985
    2707             case HvMessageTypeX64ExceptionIntercept:
    27082986            case HvMessageTypeX64ApicEoi:
    27092987            case HvMessageTypeX64LegacyFpError:
     
    27713049            return nemR3WinHandleExitMsr(pVM, pVCpu, pExit, pCtx);
    27723050
     3051        case WHvRunVpExitReasonException:
     3052            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitException);
     3053            return nemR3WinHandleExitException(pVM, pVCpu, pExit, pCtx);
     3054
    27733055        case WHvRunVpExitReasonUnrecoverableException:
    27743056            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitUnrecoverable);
    27753057            return nemR3WinHandleExitUnrecoverableException(pVM, pVCpu, pExit, pCtx);
    27763058
    2777         case WHvRunVpExitReasonException: /* needs configuring */
    27783059        case WHvRunVpExitReasonUnsupportedFeature:
    27793060        case WHvRunVpExitReasonInvalidVpRegisterValue:
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r72430 r72446  
    612612    hrc = WHvGetCapabilityWrapper(WHvCapabilityCodeExceptionExitBitmap, &Caps, sizeof(Caps));
    613613    if (SUCCEEDED(hrc))
    614         LogRel(("NEM: Warning! Supported exception exit bitmap: %#RX64\n", Caps.Features.AsUINT64));
     614        LogRel(("NEM: Supported exception exit bitmap: %#RX64\n", Caps.ExceptionExitBitmap));
    615615    else
    616616        LogRel(("NEM: Warning! WHvGetCapability/WHvCapabilityCodeExceptionExitBitmap failed: %Rhrc (Last=%#x/%u)",
     
    10521052        Property.ExtendedVmExits.X64CpuidExit  = pVM->nem.s.fExtendedCpuIdExit; /** @todo Register fixed results and restrict cpuid exits */
    10531053        Property.ExtendedVmExits.X64MsrExit    = pVM->nem.s.fExtendedMsrExit;
    1054 #if 0 /** @todo handle some MSRs too. */
    10551054        Property.ExtendedVmExits.ExceptionExit = pVM->nem.s.fExtendedXcptExit;
    1056 #endif
    10571055        hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeExtendedVmExits, &Property, sizeof(Property));
    10581056        if (SUCCEEDED(hrc))
     
    12181216                            STAMR3RegisterF(pVM, &pNemCpu->StatExitCpuId,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of CPUID exits",                  "/NEM/CPU%u/ExitCpuId", iCpu);
    12191217                            STAMR3RegisterF(pVM, &pNemCpu->StatExitMsr,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of MSR access exits",             "/NEM/CPU%u/ExitMsr", iCpu);
     1218                            STAMR3RegisterF(pVM, &pNemCpu->StatExitException,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of exception exits",           "/NEM/CPU%u/ExitException", iCpu);
    12201219                            STAMR3RegisterF(pVM, &pNemCpu->StatExitUnrecoverable,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of unrecoverable exits",          "/NEM/CPU%u/ExitUnrecoverable", iCpu);
    12211220                            STAMR3RegisterF(pVM, &pNemCpu->StatGetMsgTimeout,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of get message timeouts/alerts",  "/NEM/CPU%u/GetMsgTimeout", iCpu);
     
    13011300                          "Failed to set WHvPartitionPropertyCodeProcessorClFlushSize to %u: %Rhrc (Last=%#x/%u)",
    13021301                          pVM->nem.s.cCacheLineFlushShift, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
     1302
     1303    /* Intercept #DB, #BP and #UD exceptions. */
     1304    RT_ZERO(Property);
     1305    Property.ExceptionExitBitmap = RT_BIT_64(WHvX64ExceptionTypeDivideErrorFault)
     1306                                 | RT_BIT_64(WHvX64ExceptionTypeBreakpointTrap)
     1307                                 | RT_BIT_64(WHvX64ExceptionTypeInvalidOpcodeFault);
     1308    hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeExceptionExitBitmap, &Property, sizeof(Property));
     1309    if (FAILED(hrc))
     1310        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     1311                          "Failed to set WHvPartitionPropertyCodeExceptionExitBitmap to %#RX64: %Rhrc (Last=%#x/%u)",
     1312                          Property.ExceptionExitBitmap, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
     1313
    13031314
    13041315    /*
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r72412 r72446  
    251251    STAMCOUNTER                 StatExitCpuId;
    252252    STAMCOUNTER                 StatExitMsr;
     253    STAMCOUNTER                 StatExitException;
    253254    STAMCOUNTER                 StatExitUnrecoverable;
    254255    STAMCOUNTER                 StatGetMsgTimeout;
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