VirtualBox

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


Ignore:
Timestamp:
Aug 8, 2013 7:06:45 PM (11 years ago)
Author:
vboxsync
Message:

EM: Started on HM single stepping for IEM verification purposes. Trying to fix the HM debugging in the proccess. VT-x only atm.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/HMAll.cpp

    r46420 r47619  
    3333#include <iprt/asm.h>
    3434#include <iprt/string.h>
     35#include <iprt/thread.h>
    3536#include <iprt/x86.h>
    3637#include <iprt/asm-amd64-x86.h>
     
    426427}
    427428
     429
     430/**
     431 * Sets or clears the single instruction flag.
     432 *
     433 * When set, HM will try its best to return to ring-3 after executing a single
     434 * instruction.  This can be used for debugging.  See also
     435 * EMR3HmSingleInstruction.
     436 *
     437 * @returns The old flag state.
     438 * @param   pVCpu               Pointer to the cross context CPU structure of
     439 *                              the calling EMT.
     440 * @param   fEnable             The new flag state.
     441 */
     442VMM_INT_DECL(bool) HMSetSingleInstruction(PVMCPU pVCpu, bool fEnable)
     443{
     444    VMCPU_ASSERT_EMT(pVCpu);
     445    bool fOld = pVCpu->hm.s.fSingleInstruction;
     446    pVCpu->hm.s.fSingleInstruction = fEnable;
     447    return fOld;
     448}
     449
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r47586 r47619  
    33173317    bool fInterceptDB     = false;
    33183318    bool fInterceptMovDRx = false;
    3319     if (DBGFIsStepping(pVCpu))
     3319    if (DBGFIsStepping(pVCpu) || pVCpu->hm.s.fSingleInstruction)
    33203320    {
    33213321        /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
     
    62826282            {
    62836283                /*
    6284                  * The pending-debug exceptions field is cleared on all VM-exits except VMX_EXIT_TPR_BELOW_THRESHOLD, VMX_EXIT_MTF
    6285                  * VMX_EXIT_APIC_WRITE, VMX_EXIT_VIRTUALIZED_EOI. See Intel spec. 27.3.4 "Saving Non-Register State".
     6284                 * The pending-debug exceptions field is cleared on all VM-exits except VMX_EXIT_TPR_BELOW_THRESHOLD,
     6285                 * VMX_EXIT_MTF VMX_EXIT_APIC_WRITE, VMX_EXIT_VIRTUALIZED_EOI. See Intel spec. 27.3.4 "Saving Non-Register State".
    62866286                 */
    62876287                rc2 = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS);
     
    86658665    AssertRCReturn(rc, rc);
    86668666    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitMtf);
    8667     return VINF_EM_DBG_STOP;
     8667    return VINF_EM_DBG_STEPPED;
    86688668}
    86698669
     
    87608760    int rc = VERR_INTERNAL_ERROR_5;
    87618761    if (   !DBGFIsStepping(pVCpu)
     8762        && !pVCpu->hm.s.fSingleInstruction
    87628763        && !CPUMIsHyperDebugStateActive(pVCpu))
    87638764    {
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r47444 r47619  
    9191static const char *emR3GetStateName(EMSTATE enmState);
    9292#endif
    93 static int emR3Debug(PVM pVM, PVMCPU pVCpu, int rc);
     93static VBOXSTRICTRC emR3Debug(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc);
    9494static int emR3RemStep(PVM pVM, PVMCPU pVCpu);
    9595static int emR3RemExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
     
    775775        case EMSTATE_TERMINATING:       return "EMSTATE_TERMINATING";
    776776        case EMSTATE_DEBUG_GUEST_RAW:   return "EMSTATE_DEBUG_GUEST_RAW";
     777        case EMSTATE_DEBUG_GUEST_HM:    return "EMSTATE_DEBUG_GUEST_HM";
     778        case EMSTATE_DEBUG_GUEST_IEM:   return "EMSTATE_DEBUG_GUEST_IEM";
    777779        case EMSTATE_DEBUG_GUEST_REM:   return "EMSTATE_DEBUG_GUEST_REM";
    778780        case EMSTATE_DEBUG_HYPER:       return "EMSTATE_DEBUG_HYPER";
     
    792794 * @param   rc      Current EM VBox status code.
    793795 */
    794 static int emR3Debug(PVM pVM, PVMCPU pVCpu, int rc)
     796static VBOXSTRICTRC emR3Debug(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc)
    795797{
    796798    for (;;)
    797799    {
    798         Log(("emR3Debug: rc=%Rrc\n", rc));
    799         const int rcLast = rc;
     800        Log(("emR3Debug: rc=%Rrc\n", VBOXSTRICTRC_VAL(rc)));
     801        const VBOXSTRICTRC rcLast = rc;
    800802
    801803        /*
    802804         * Debug related RC.
    803805         */
    804         switch (rc)
     806        switch (VBOXSTRICTRC_VAL(rc))
    805807        {
    806808            /*
     
    808810             */
    809811            case VINF_EM_DBG_STEP:
     812                if (   pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_RAW
     813                    || pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER
     814                    || pVCpu->em.s.fForceRAW /* paranoia */)
    810815#ifdef VBOX_WITH_RAW_MODE
    811                 if (    pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_RAW
    812                     ||  pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER
    813                     ||  pVCpu->em.s.fForceRAW /* paranoia */)
    814816                    rc = emR3RawStep(pVM, pVCpu);
     817#else
     818                    AssertLogRelMsgFailedStmt(("Bad EM state."), VERR_EM_INTERNAL_ERROR);
     819#endif
     820                else if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HM)
     821                    rc = EMR3HmSingleInstruction(pVM, pVCpu);
     822#ifdef VBOX_WITH_REM
     823                else if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_REM)
     824                    rc = emR3RemStep(pVM, pVCpu);
     825#endif
    815826                else
    816827                {
    817                     Assert(pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_REM);
    818                     rc = emR3RemStep(pVM, pVCpu);
     828                    rc = IEMExecOne(pVCpu); /** @todo add dedicated interface... */
     829                    if (rc == VINF_SUCCESS || rc == VINF_EM_RESCHEDULE)
     830                        rc = VINF_EM_DBG_STEPPED;
    819831                }
    820 #else
    821                 AssertLogRelMsgFailed(("%Rrc\n", rc));
    822                 rc = VERR_EM_INTERNAL_ERROR;
    823 #endif
    824832                break;
    825833
     
    873881        do
    874882        {
    875             switch (rc)
     883            switch (VBOXSTRICTRC_VAL(rc))
    876884            {
    877885                /*
     
    905913                            continue;
    906914#else
    907                         AssertLogRelMsgFailedReturn(("Not implemented\n", rc), VERR_EM_INTERNAL_ERROR);
     915                        AssertLogRelMsgFailedReturn(("Not implemented\n"), VERR_EM_INTERNAL_ERROR);
    908916#endif
    909917                    }
     
    917925                 */
    918926                case VERR_DBGF_NOT_ATTACHED:
    919                     switch (rcLast)
     927                    switch (VBOXSTRICTRC_VAL(rcLast))
    920928                    {
    921929                        case VINF_EM_DBG_HYPER_STEPPED:
     
    961969                 */
    962970                default:
    963                     AssertMsgFailed(("Unexpected rc %Rrc!\n", rc));
     971                    AssertMsgFailed(("Unexpected rc %Rrc!\n", VBOXSTRICTRC_VAL(rc)));
    964972                    break;
    965973            }
     
    18401848                /** @todo this really isn't nice, should properly handle this */
    18411849                rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
    1842                 if (pVM->em.s.fIemExecutesAll && rc2 == VINF_EM_RESCHEDULE_REM)
     1850                if (pVM->em.s.fIemExecutesAll && (rc2 == VINF_EM_RESCHEDULE_REM || rc2 == VINF_EM_RESCHEDULE_HM || rc2 == VINF_EM_RESCHEDULE_RAW))
    18431851                    rc2 = VINF_EM_RESCHEDULE;
    18441852#ifdef VBOX_STRICT
     
    22492257                 */
    22502258                case VINF_EM_DBG_STEPPED:
    2251                     /* Commenting this assertion for now as it hinders with single-stepping in new AMD-V code
    2252                      * (using guest EFLAGS.TF) and returning VINF_EM_DBG_STEPPED in the #DB handler. */
    2253 #if 0
    2254                     AssertMsgFailed(("VINF_EM_DBG_STEPPED cannot be here!"));
    2255 #endif
    22562259                case VINF_EM_DBG_STOP:
    22572260                case VINF_EM_DBG_BREAKPOINT:
     
    22622265                        pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_RAW;
    22632266                    }
    2264                     else
     2267                    else if (enmOldState == EMSTATE_HM)
     2268                    {
     2269                        Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_HM));
     2270                        pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_HM;
     2271                    }
     2272                    else if (enmOldState == EMSTATE_REM)
    22652273                    {
    22662274                        Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_REM));
    22672275                        pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_REM;
     2276                    }
     2277                    else
     2278                    {
     2279                        Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_IEM));
     2280                        pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_IEM;
    22682281                    }
    22692282                    break;
     
    23222335                        || enmNewState == EMSTATE_DEBUG_GUEST_RAW
    23232336                        || enmNewState == EMSTATE_DEBUG_GUEST_HM
     2337                        || enmNewState == EMSTATE_DEBUG_GUEST_IEM
    23242338                        || enmNewState == EMSTATE_DEBUG_GUEST_REM) )
    23252339                {
     
    23842398                 */
    23852399                case EMSTATE_IEM:
    2386                     rc = VBOXSTRICTRC_TODO(IEMExecLots(pVCpu));
     2400#if 0 /* For testing purposes. */
     2401                    rc = VBOXSTRICTRC_TODO(EMR3HmSingleInstruction(pVM, pVCpu));
     2402                    if (rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_RESCHEDULE_HM || rc == VINF_EM_RESCHEDULE_REM || rc == VINF_EM_RESCHEDULE_RAW)
     2403                        rc = VINF_SUCCESS;
     2404                    else if (rc == VERR_EM_CANNOT_EXEC_GUEST)
     2405#endif
     2406                        rc = VBOXSTRICTRC_TODO(IEMExecLots(pVCpu));
    23872407                    if (pVM->em.s.fIemExecutesAll)
    23882408                    {
     
    24372457                 * Debugging in the guest.
    24382458                 */
     2459                case EMSTATE_DEBUG_GUEST_RAW:
     2460                case EMSTATE_DEBUG_GUEST_HM:
     2461                case EMSTATE_DEBUG_GUEST_IEM:
    24392462                case EMSTATE_DEBUG_GUEST_REM:
    2440                 case EMSTATE_DEBUG_GUEST_RAW:
    24412463                    TMR3NotifySuspend(pVM, pVCpu);
    2442                     rc = emR3Debug(pVM, pVCpu, rc);
     2464                    rc = VBOXSTRICTRC_TODO(emR3Debug(pVM, pVCpu, rc));
    24432465                    TMR3NotifyResume(pVM, pVCpu);
    24442466                    Log2(("EMR3ExecuteVM: enmr3Debug -> %Rrc (state %d)\n", rc, pVCpu->em.s.enmState));
     
    24532475                    STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
    24542476
    2455                     rc = emR3Debug(pVM, pVCpu, rc);
     2477                    rc = VBOXSTRICTRC_TODO(emR3Debug(pVM, pVCpu, rc));
    24562478                    Log2(("EMR3ExecuteVM: enmr3Debug -> %Rrc (state %d)\n", rc, pVCpu->em.s.enmState));
    24572479                    if (rc != VINF_SUCCESS)
  • trunk/src/VBox/VMM/VMMR3/EMHM.cpp

    r47548 r47619  
    152152
    153153#endif /* DEBUG */
     154
     155
     156/**
     157 * Executes instruction in HM mode if we can.
     158 *
     159 * This is somewhat comparable to REMR3EmulateInstruction.
     160 *
     161 * @returns VBox strict status code.
     162 * @retval  VINF_EM_DBG_STEPPED on success.
     163 * @retval  VERR_EM_CANNOT_EXEC_GUEST if we cannot execute guest instructions in
     164 *          HM right now.
     165 *
     166 * @param   pVM                 Pointer to the cross context VM structure.
     167 * @param   pVCpu               Pointer to the cross context CPU structure for
     168 *                              the calling EMT.
     169 * @thread  EMT.
     170 */
     171VMMR3_INT_DECL(VBOXSTRICTRC) EMR3HmSingleInstruction(PVM pVM, PVMCPU pVCpu)
     172{
     173    if (!HMR3CanExecuteGuest(pVM, pVCpu->em.s.pCtx))
     174        return VINF_EM_RESCHEDULE;
     175
     176    /*
     177     * Service necessary FFs before going into HM.
     178     */
     179    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
     180    if (    VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
     181        ||  VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
     182    {
     183        VBOXSTRICTRC rcStrict = emR3HmForcedActions(pVM, pVCpu, pCtx);
     184        if (rcStrict != VINF_SUCCESS)
     185        {
     186            Log(("EMR3HmSingleInstruction: FFs before -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     187            return rcStrict;
     188        }
     189    }
     190
     191    /*
     192     * Go execute it.
     193     */
     194    bool fOld = HMSetSingleInstruction(pVCpu, true);
     195    VBOXSTRICTRC rcStrict = VMMR3HmRunGC(pVM, pVCpu);
     196    HMSetSingleInstruction(pVCpu, fOld);
     197    LogFlow(("EMR3HmSingleInstruction: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     198
     199    /*
     200     * Handle high priority FFs and informational status codes.  We don't do
     201     * normal FF processing the caller or the next call can deal with them.
     202     */
     203    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
     204    if (    VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
     205        ||  VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
     206    {
     207        rcStrict = emR3HighPriorityPostForcedActions(pVM, pVCpu, VBOXSTRICTRC_TODO(rcStrict));
     208        LogFlow(("EMR3HmSingleInstruction: FFs after -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     209    }
     210
     211    if (rcStrict != VINF_SUCCESS && (rcStrict < VINF_EM_FIRST || rcStrict > VINF_EM_LAST))
     212    {
     213        rcStrict = emR3HmHandleRC(pVM, pVCpu, pCtx, VBOXSTRICTRC_TODO(rcStrict));
     214        Log(("EMR3HmSingleInstruction: emR3HmHandleRC -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     215    }
     216
     217    return rcStrict;
     218}
    154219
    155220
  • trunk/src/VBox/VMM/include/HMInternal.h

    r47123 r47619  
    538538    /** Set when the TLB has been checked until we return from the world switch. */
    539539    volatile bool               fCheckedTLBFlush;
    540     uint8_t                     u8Alignment[4];
     540    /** Whether we're executing a single instruction. */
     541    bool                        fSingleInstruction;
     542    uint8_t                     abAlignment[3];
    541543
    542544    /** World switch exit counter. */
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