VirtualBox

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


Ignore:
Timestamp:
Oct 16, 2024 1:30:47 PM (3 months ago)
Author:
vboxsync
Message:

VMM/NEMR3Native-darwin-armv8.cpp: Implement support for breakpoints and single stepping in the VM debugger, bugref:10393

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin-armv8.cpp

    r106145 r106372  
    13741374        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    13751375                          "Setting MPIDR_EL1 failed on vCPU %u: %#x (%Rrc)", idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
    1376 
    1377 #if 0 /* Will triger an VM-exit if the guest hits a breakpoint, handy for debugging the MS bootloader. */
    1378     hrc != hv_vcpu_set_trap_debug_exceptions(pVCpu->nem.s.hVCpu, true);
    1379     if (hrc != HV_SUCCESS)
    1380         return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    1381                           "Trapping debug exceptions on vCPU %u: %#x (%Rrc)", idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
    1382 #endif
    13831376
    13841377    return VINF_SUCCESS;
     
    18621855            nemR3DarwinSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED);
    18631856    }
     1857
    18641858    /** @todo What to do if immediate is != 0? */
    18651859
     
    19531947            return VINF_EM_HALT;
    19541948        }
     1949        case ARMV8_ESR_EL2_EC_AARCH64_BRK_INSN:
     1950        {
     1951            VBOXSTRICTRC rcStrict = DBGFTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, &pVCpu->cpum.GstCtx);
     1952            /** @todo Forward genuine guest traps to the guest by either single stepping instruction with debug exception trapping turned off
     1953             * or create instruction interpreter and inject exception ourselves. */
     1954            Assert(rcStrict == VINF_EM_DBG_BREAKPOINT);
     1955            return rcStrict;
     1956        }
     1957        case ARMV8_ESR_EL2_SS_EXCEPTION_FROM_LOWER_EL:
     1958            return VINF_EM_DBG_STEPPED;
    19551959        case ARMV8_ESR_EL2_EC_UNKNOWN:
    19561960        default:
     
    20442048#endif
    20452049
    2046     /** @todo */ RT_NOREF(fSingleStepping);
    20472050    int rc = nemR3DarwinExportGuestState(pVM, pVCpu);
    20482051    AssertRCReturn(rc, rc);
     2052
     2053    /* In single stepping mode we will re-read SPSR and MDSCR and enable the software step bits. */
     2054    if (fSingleStepping)
     2055    {
     2056        uint64_t u64Tmp;
     2057        hv_return_t hrc = hv_vcpu_get_reg(pVCpu->nem.s.hVCpu, HV_REG_CPSR, &u64Tmp);
     2058        if (hrc == HV_SUCCESS)
     2059        {
     2060            u64Tmp |= ARMV8_SPSR_EL2_AARCH64_SS;
     2061            hrc = hv_vcpu_set_reg(pVCpu->nem.s.hVCpu, HV_REG_CPSR, u64Tmp);
     2062        }
     2063
     2064        hrc |= hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_MDSCR_EL1, &u64Tmp);
     2065        if (hrc == HV_SUCCESS)
     2066        {
     2067            u64Tmp |= ARMV8_MDSCR_EL1_AARCH64_SS;
     2068            hrc = hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_MDSCR_EL1, u64Tmp);
     2069        }
     2070
     2071        AssertReturn(hrc == HV_SUCCESS, VERR_NEM_IPE_9);
     2072    }
    20492073
    20502074    /* Check whether the vTimer interrupt was handled by the guest and we can unmask the vTimer. */
     
    21782202
    21792203
     2204/**
     2205 * The debug runloop.
     2206 *
     2207 * @returns Strict VBox status code.
     2208 * @param   pVM         The cross context VM structure.
     2209 * @param   pVCpu       The cross context virtual CPU structure.
     2210 */
     2211static VBOXSTRICTRC nemR3DarwinRunGuestDebug(PVM pVM, PVMCPU pVCpu)
     2212{
     2213    /*
     2214     * The run loop.
     2215     *
     2216     * Current approach to state updating to use the sledgehammer and sync
     2217     * everything every time.  This will be optimized later.
     2218     */
     2219
     2220    bool const fSavedSingleInstruction = pVCpu->nem.s.fSingleInstruction;
     2221    pVCpu->nem.s.fSingleInstruction    = pVCpu->nem.s.fSingleInstruction || DBGFIsStepping(pVCpu);
     2222    pVCpu->nem.s.fUsingDebugLoop       = true;
     2223
     2224    /* Trap any debug exceptions. */
     2225    hv_return_t hrc = hv_vcpu_set_trap_debug_exceptions(pVCpu->nem.s.hVCpu, true);
     2226    if (hrc != HV_SUCCESS)
     2227        return VMSetError(pVM, VERR_NEM_SET_REGISTERS_FAILED, RT_SRC_POS,
     2228                          "Trapping debug exceptions on vCPU %u failed: %#x (%Rrc)", pVCpu->idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
     2229
     2230    /* Update the vTimer offset after resuming if instructed. */
     2231    if (pVCpu->nem.s.fVTimerOffUpdate)
     2232    {
     2233        hrc = hv_vcpu_set_vtimer_offset(pVCpu->nem.s.hVCpu, pVM->nem.s.u64VTimerOff);
     2234        if (hrc != HV_SUCCESS)
     2235            return nemR3DarwinHvSts2Rc(hrc);
     2236
     2237        pVCpu->nem.s.fVTimerOffUpdate = false;
     2238
     2239        hrc = hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CTL_EL0, pVCpu->cpum.GstCtx.CntvCtlEl0);
     2240        if (hrc == HV_SUCCESS)
     2241            hrc = hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CVAL_EL0, pVCpu->cpum.GstCtx.CntvCValEl0);
     2242        if (hrc != HV_SUCCESS)
     2243            return nemR3DarwinHvSts2Rc(hrc);
     2244    }
     2245
     2246    /* Save the guest MDSCR_EL1 */
     2247    CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_SYSREG_DEBUG | CPUMCTX_EXTRN_PSTATE);
     2248    uint64_t u64RegMdscrEl1 = pVCpu->cpum.GstCtx.Mdscr.u64;
     2249
     2250    /*
     2251     * Poll timers and run for a bit.
     2252     */
     2253    /** @todo See if we cannot optimize this TMTimerPollGIP by only redoing
     2254     *        the whole polling job when timers have changed... */
     2255    uint64_t       offDeltaIgnored;
     2256    uint64_t const nsNextTimerEvt = TMTimerPollGIP(pVM, pVCpu, &offDeltaIgnored); NOREF(nsNextTimerEvt);
     2257    VBOXSTRICTRC    rcStrict        = VINF_SUCCESS;
     2258    for (unsigned iLoop = 0;; iLoop++)
     2259    {
     2260        bool const fStepping = pVCpu->nem.s.fSingleInstruction;
     2261
     2262        rcStrict = nemR3DarwinPreRunGuest(pVM, pVCpu, fStepping);
     2263        if (rcStrict != VINF_SUCCESS)
     2264            break;
     2265
     2266        hrc = nemR3DarwinRunGuest(pVM, pVCpu);
     2267        if (hrc == HV_SUCCESS)
     2268        {
     2269            /*
     2270             * Deal with the message.
     2271             */
     2272            rcStrict = nemR3DarwinHandleExit(pVM, pVCpu);
     2273            if (rcStrict == VINF_SUCCESS)
     2274            { /* hopefully likely */ }
     2275            else
     2276            {
     2277                LogFlow(("NEM/%u: breaking: nemR3DarwinHandleExit -> %Rrc\n", pVCpu->idCpu, VBOXSTRICTRC_VAL(rcStrict) ));
     2278                STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnStatus);
     2279                break;
     2280            }
     2281        }
     2282        else
     2283        {
     2284            AssertLogRelMsgFailedReturn(("hv_vcpu_run()) failed for CPU #%u: %#x \n",
     2285                                        pVCpu->idCpu, hrc), VERR_NEM_IPE_0);
     2286        }
     2287    } /* the run loop */
     2288
     2289    /* Restore single stepping state. */
     2290    if (pVCpu->nem.s.fSingleInstruction)
     2291    {
     2292        /** @todo This ASSUMES that guest code being single stepped is not modifying the MDSCR_EL1 register. */
     2293        CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_SYSREG_DEBUG | CPUMCTX_EXTRN_PSTATE);
     2294        Assert(pVCpu->cpum.GstCtx.Mdscr.u64 & ARMV8_MDSCR_EL1_AARCH64_SS);
     2295
     2296        pVCpu->cpum.GstCtx.Mdscr.u64 = u64RegMdscrEl1;
     2297    }
     2298
     2299    /* Restore debug exceptions trapping. */
     2300    hrc != hv_vcpu_set_trap_debug_exceptions(pVCpu->nem.s.hVCpu, false);
     2301    if (hrc != HV_SUCCESS)
     2302        return VMSetError(pVM, VERR_NEM_SET_REGISTERS_FAILED, RT_SRC_POS,
     2303                          "Clearing trapping of debug exceptions on vCPU %u failed: %#x (%Rrc)", pVCpu->idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
     2304
     2305    pVCpu->nem.s.fUsingDebugLoop     = false;
     2306    pVCpu->nem.s.fSingleInstruction  = fSavedSingleInstruction;
     2307
     2308    return rcStrict;
     2309
     2310}
     2311
     2312
    21802313VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu)
    21812314{
     
    22432376
    22442377    VBOXSTRICTRC rcStrict;
    2245 #if 0
    22462378    if (   !pVCpu->nem.s.fUseDebugLoop
    2247         && !nemR3DarwinAnyExpensiveProbesEnabled()
     2379        /*&& !nemR3DarwinAnyExpensiveProbesEnabled()*/
    22482380        && !DBGFIsStepping(pVCpu)
    2249         && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
    2250 #endif
     2381        && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledSwBreakpoints)
    22512382        rcStrict = nemR3DarwinRunGuestNormal(pVM, pVCpu);
    2252 #if 0
    22532383    else
    22542384        rcStrict = nemR3DarwinRunGuestDebug(pVM, pVCpu);
    2255 #endif
    22562385
    22572386    if (rcStrict == VINF_EM_RAW_TO_R3)
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