VirtualBox

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


Ignore:
Timestamp:
Dec 11, 2015 12:43:04 AM (9 years ago)
Author:
vboxsync
Message:

DBGF: Tried to rework the generic event config API, still not quite there - deadlocks on DBGC shutdown.

File:
1 edited

Legend:

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

    r59074 r59084  
    516516
    517517
     518/**
     519 * Processes a pending event on the current CPU.
     520 *
     521 * This is called by EM in response to VINF_EM_DBG_EVENT.
     522 *
     523 * @returns Strict VBox status code.
     524 * @param   pVM         The cross context VM structure.
     525 * @param   pVCpu       The cross context per CPU structure.
     526 *
     527 * @thread  EMT(pVCpu)
     528 */
    518529VMMR3_INT_DECL(VBOXSTRICTRC) DBGFR3EventHandlePending(PVM pVM, PVMCPU pVCpu)
    519530{
    520     return VINF_SUCCESS;
     531    VMCPU_ASSERT_EMT(pVCpu);
     532
     533    /*
     534     * Check that we've got an event first.
     535     */
     536    AssertReturn(pVCpu->dbgf.s.cEvents > 0, VINF_SUCCESS);
     537    AssertReturn(pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].enmState == DBGFEVENTSTATE_CURRENT, VINF_SUCCESS);
     538    PDBGFEVENT pEvent = &pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].Event;
     539
     540    /*
     541     * Make sure we've got a debugger and is allowed to speak to it.
     542     */
     543    int rc = dbgfR3EventPrologue(pVM, pEvent->enmType);
     544    if (RT_FAILURE(rc))
     545        return rc;
     546
     547/** @todo SMP + debugger speaker logic  */
     548    /*
     549     * Copy the event over and mark it as ignore.
     550     */
     551    pVM->dbgf.s.DbgEvent = *pEvent;
     552    pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].enmState = DBGFEVENTSTATE_IGNORE;
     553    return dbgfR3SendEvent(pVM);
    521554}
    522555
     
    12241257
    12251258
    1226 /**
    1227  * @callback_method_impl{FNVMMEMTRENDEZVOUS}
    1228  */
    1229 static DECLCALLBACK(VBOXSTRICTRC) dbgfR3EventConfigNotifyAllCpus(PVM pVM, PVMCPU pVCpu, void *pvUser)
    1230 {
    1231     if (pvUser /*fIsHmEnabled*/)
     1259
     1260/**
     1261 * dbgfR3EventConfigEx argument packet.
     1262 */
     1263typedef struct DBGFR3EVENTCONFIGEXARGS
     1264{
     1265    PCDBGFEVENTCONFIG   paConfigs;
     1266    size_t              cConfigs;
     1267    int                 rc;
     1268} DBGFR3EVENTCONFIGEXARGS;
     1269/** Pointer to a dbgfR3EventConfigEx argument packet. */
     1270typedef DBGFR3EVENTCONFIGEXARGS *PDBGFR3EVENTCONFIGEXARGS;
     1271
     1272
     1273/**
     1274 * @callback_method_impl{FNVMMEMTRENDEZVOUS, Worker for DBGFR3EventConfigEx.}
     1275 */
     1276static DECLCALLBACK(VBOXSTRICTRC) dbgfR3EventConfigEx(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1277{
     1278    if (pVCpu->idCpu == 0)
     1279    {
     1280        PDBGFR3EVENTCONFIGEXARGS        pArgs = (PDBGFR3EVENTCONFIGEXARGS)pvUser;
     1281        DBGFEVENTCONFIG volatile const *paConfigs = pArgs->paConfigs;
     1282        size_t                          cConfigs  = pArgs->cConfigs;
     1283
     1284        /*
     1285         * Apply the changes.
     1286         */
     1287        unsigned cChanges = 0;
     1288        for (uint32_t i = 0; i < cConfigs; i++)
     1289        {
     1290            DBGFEVENTTYPE enmType = paConfigs[i].enmType;
     1291            AssertReturn(enmType >= DBGFEVENT_FIRST_SELECTABLE && enmType < DBGFEVENT_END, VERR_INVALID_PARAMETER);
     1292            if (paConfigs[i].fEnabled)
     1293                cChanges += ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, enmType) == false;
     1294            else
     1295                cChanges += ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, enmType) == true;
     1296        }
     1297
     1298        /*
     1299         * Inform HM about changes.
     1300         */
     1301        if (cChanges > 0 && HMIsEnabled(pVM))
     1302        {
     1303            HMR3NotifyDebugEventChanged(pVM);
     1304            HMR3NotifyDebugEventChangedPerCpu(pVM, pVCpu);
     1305        }
     1306    }
     1307    else if (HMIsEnabled(pVM))
    12321308        HMR3NotifyDebugEventChangedPerCpu(pVM, pVCpu);
     1309
    12331310    return VINF_SUCCESS;
    12341311}
     
    12361313
    12371314/**
    1238  * Worker for DBGFR3EventConfigEx.
    1239  *
    1240  * @returns VBox status code. Will not return VBOX_INTERRUPTED.
     1315 * Configures (enables/disables) multiple selectable debug events.
     1316 *
     1317 * @returns VBox status code.
    12411318 * @param   pUVM        The user mode VM handle.
    12421319 * @param   paConfigs   The event to configure and their new state.
    12431320 * @param   cConfigs    Number of entries in @a paConfigs.
    12441321 */
    1245 static DECLCALLBACK(int) dbgfR3EventConfigEx(PUVM pUVM, DBGFEVENTCONFIG volatile const *paConfigs, size_t cConfigs)
    1246 {
     1322VMMR3DECL(int) DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs)
     1323{
     1324    /*
     1325     * Validate input.
     1326     */
     1327    size_t i = cConfigs;
     1328    while (i-- > 0)
     1329    {
     1330        AssertReturn(paConfigs[i].enmType >= DBGFEVENT_FIRST_SELECTABLE, VERR_INVALID_PARAMETER);
     1331        AssertReturn(paConfigs[i].enmType <  DBGFEVENT_END, VERR_INVALID_PARAMETER);
     1332    }
     1333    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    12471334    PVM pVM = pUVM->pVM;
    12481335    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    12491336
    12501337    /*
    1251      * Apply the changes.
    1252      */
    1253     unsigned cChanges = 0;
    1254     for (uint32_t i = 0; i < cConfigs; i++)
    1255     {
    1256         DBGFEVENTTYPE enmType = paConfigs[i].enmType;
    1257         AssertReturn(enmType >= DBGFEVENT_FIRST_SELECTABLE && enmType < DBGFEVENT_END, VERR_INVALID_PARAMETER);
    1258         if (paConfigs[i].fEnabled)
    1259             cChanges += ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, enmType) == false;
    1260         else
    1261             cChanges += ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, enmType) == true;
    1262     }
    1263 
    1264     /*
    1265      * Inform HM about changes.  In an SMP setup, interrupt execution on the
    1266      * other CPUs so their execution loop can be reselected.
    1267      */
    1268     int rc = VINF_SUCCESS;
    1269     if (cChanges > 0)
    1270     {
    1271         bool const fIsHmEnabled = HMIsEnabled(pVM);
    1272         if (fIsHmEnabled)
    1273             HMR3NotifyDebugEventChanged(pVM);
    1274         if (pVM->cCpus > 1 || fIsHmEnabled)
    1275             rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus,
    1276                                     (void *)(uintptr_t)fIsHmEnabled);
    1277     }
     1338     * Apply the changes in EMT(0) and rendezvous with the other CPUs so they
     1339     * can sync their data and execution with new debug state.
     1340     */
     1341    DBGFR3EVENTCONFIGEXARGS Args = { paConfigs, cConfigs, VINF_SUCCESS };
     1342    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING, dbgfR3EventConfigEx, &Args);
     1343    if (RT_SUCCESS(rc))
     1344        rc = Args.rc;
    12781345    return rc;
    1279 }
    1280 
    1281 
    1282 /**
    1283  * Configures (enables/disables) multiple selectable debug events.
    1284  *
    1285  * @returns VBox status code.
    1286  * @param   pUVM        The user mode VM handle.
    1287  * @param   paConfigs   The event to configure and their new state.
    1288  * @param   cConfigs    Number of entries in @a paConfigs.
    1289  */
    1290 VMMR3DECL(int) DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs)
    1291 {
    1292     /*
    1293      * Validate input.
    1294      */
    1295     UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    1296     size_t i = cConfigs;
    1297     while (i-- > 0)
    1298     {
    1299         AssertReturn(paConfigs[i].enmType >= DBGFEVENT_FIRST_SELECTABLE, VERR_INVALID_PARAMETER);
    1300         AssertReturn(paConfigs[i].enmType <  DBGFEVENT_END, VERR_INVALID_PARAMETER);
    1301     }
    1302 
    1303     /*
    1304      * Apply the changes in EMT(0).
    1305      */
    1306     return VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3EventConfigEx, 3, pUVM, paConfigs, cConfigs);
    13071346}
    13081347
     
    13711410     * Validate input.
    13721411     */
    1373     UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1412    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    13741413    PVM pVM = pUVM->pVM;
    1375     VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1414    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    13761415
    13771416    for (size_t i = 0; i < cConfigs; i++)
     
    13921431
    13931432/**
    1394  * Worker for DBGFR3InterruptConfigEx.
    1395  *
    1396  * @returns VBox status code. Will not return VBOX_INTERRUPTED.
    1397  * @param   pUVM        The user mode VM handle.
    1398  * @param   paConfigs   The event to configure and their new state.
    1399  * @param   cConfigs    Number of entries in @a paConfigs.
    1400  */
    1401 static DECLCALLBACK(int) dbgfR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs)
    1402 {
    1403     PVM pVM = pUVM->pVM;
    1404     VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    1405 
    1406     /*
    1407      * Apply the changes.
    1408      */
    1409     bool fChanged = false;
    1410     bool fThis;
    1411     for (uint32_t i = 0; i < cConfigs; i++)
    1412     {
     1433 * dbgfR3InterruptConfigEx argument packet.
     1434 */
     1435typedef struct DBGFR3INTERRUPTCONFIGEXARGS
     1436{
     1437    PCDBGFINTERRUPTCONFIG   paConfigs;
     1438    size_t                  cConfigs;
     1439    int                     rc;
     1440} DBGFR3INTERRUPTCONFIGEXARGS;
     1441/** Pointer to a dbgfR3InterruptConfigEx argument packet. */
     1442typedef DBGFR3INTERRUPTCONFIGEXARGS *PDBGFR3INTERRUPTCONFIGEXARGS;
     1443
     1444/**
     1445 * @callback_method_impl{FNVMMEMTRENDEZVOUS,
     1446 *      Worker for DBGFR3InterruptConfigEx.}
     1447 */
     1448static DECLCALLBACK(VBOXSTRICTRC) dbgfR3InterruptConfigEx(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1449{
     1450    if (pVCpu->idCpu == 0)
     1451    {
     1452        PDBGFR3INTERRUPTCONFIGEXARGS    pArgs = (PDBGFR3INTERRUPTCONFIGEXARGS)pvUser;
     1453        PCDBGFINTERRUPTCONFIG           paConfigs = pArgs->paConfigs;
     1454        size_t                          cConfigs  = pArgs->cConfigs;
     1455
    14131456        /*
    1414          * Hardware interrupts.
     1457         * Apply the changes.
    14151458         */
    1416         if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
    1417         {
    1418             fChanged |= fThis = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == false;
    1419             if (fThis)
     1459        bool fChanged = false;
     1460        bool fThis;
     1461        for (uint32_t i = 0; i < cConfigs; i++)
     1462        {
     1463            /*
     1464             * Hardware interrupts.
     1465             */
     1466            if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
    14201467            {
    1421                 Assert(pVM->dbgf.s.cHardIntBreakpoints < 256);
    1422                 pVM->dbgf.s.cHardIntBreakpoints++;
     1468                fChanged |= fThis = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == false;
     1469                if (fThis)
     1470                {
     1471                    Assert(pVM->dbgf.s.cHardIntBreakpoints < 256);
     1472                    pVM->dbgf.s.cHardIntBreakpoints++;
     1473                }
    14231474            }
    1424         }
    1425         else if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_DISABLED)
    1426         {
    1427             fChanged |= fThis = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == true;
    1428             if (fThis)
     1475            else if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_DISABLED)
    14291476            {
    1430                 Assert(pVM->dbgf.s.cHardIntBreakpoints > 0);
    1431                 pVM->dbgf.s.cHardIntBreakpoints--;
     1477                fChanged |= fThis = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == true;
     1478                if (fThis)
     1479                {
     1480                    Assert(pVM->dbgf.s.cHardIntBreakpoints > 0);
     1481                    pVM->dbgf.s.cHardIntBreakpoints--;
     1482                }
    14321483            }
     1484
     1485            /*
     1486             * Software interrupts.
     1487             */
     1488            if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
     1489            {
     1490                fChanged |= fThis = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == false;
     1491                if (fThis)
     1492                {
     1493                    Assert(pVM->dbgf.s.cSoftIntBreakpoints < 256);
     1494                    pVM->dbgf.s.cSoftIntBreakpoints++;
     1495                }
     1496            }
     1497            else if (paConfigs[i].enmSoftState == DBGFINTERRUPTSTATE_DISABLED)
     1498            {
     1499                fChanged |= fThis = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == true;
     1500                if (fThis)
     1501                {
     1502                    Assert(pVM->dbgf.s.cSoftIntBreakpoints > 0);
     1503                    pVM->dbgf.s.cSoftIntBreakpoints--;
     1504                }
     1505            }
    14331506        }
    14341507
    14351508        /*
    1436          * Software interrupts.
     1509         * Update the event bitmap entries.
    14371510         */
    1438         if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
    1439         {
    1440             fChanged |= fThis = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == false;
    1441             if (fThis)
    1442             {
    1443                 Assert(pVM->dbgf.s.cSoftIntBreakpoints < 256);
    1444                 pVM->dbgf.s.cSoftIntBreakpoints++;
    1445             }
    1446         }
    1447         else if (paConfigs[i].enmSoftState == DBGFINTERRUPTSTATE_DISABLED)
    1448         {
    1449             fChanged |= fThis = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == true;
    1450             if (fThis)
    1451             {
    1452                 Assert(pVM->dbgf.s.cSoftIntBreakpoints > 0);
    1453                 pVM->dbgf.s.cSoftIntBreakpoints--;
    1454             }
    1455         }
    1456     }
    1457 
    1458     /*
    1459      * Update the event bitmap entries.
    1460      */
    1461     if (pVM->dbgf.s.cHardIntBreakpoints > 0)
    1462         fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == false;
    1463     else
    1464         fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == true;
    1465 
    1466     if (pVM->dbgf.s.cSoftIntBreakpoints > 0)
    1467         fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == false;
    1468     else
    1469         fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == true;
    1470 
    1471 
    1472     /*
    1473      * Inform HM about changes.  In an SMP setup, interrupt execution on the
    1474      * other CPUs so their execution loop can be reselected.
    1475      */
    1476     int rc = VINF_SUCCESS;
    1477     if (fChanged)
    1478     {
    1479         bool const fIsHmEnabled = HMIsEnabled(pVM);
    1480         if (fIsHmEnabled)
     1511        if (pVM->dbgf.s.cHardIntBreakpoints > 0)
     1512            fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == false;
     1513        else
     1514            fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == true;
     1515
     1516        if (pVM->dbgf.s.cSoftIntBreakpoints > 0)
     1517            fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == false;
     1518        else
     1519            fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == true;
     1520
     1521        /*
     1522         * Inform HM about changes.
     1523         */
     1524        if (fChanged && HMIsEnabled(pVM))
     1525        {
    14811526            HMR3NotifyDebugEventChanged(pVM);
    1482         if (pVM->cCpus > 1 || fIsHmEnabled)
    1483             rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus,
    1484                                     (void *)(uintptr_t)fIsHmEnabled);
    1485     }
    1486     return rc;
     1527            HMR3NotifyDebugEventChangedPerCpu(pVM, pVCpu);
     1528        }
     1529    }
     1530    else if (HMIsEnabled(pVM))
     1531        HMR3NotifyDebugEventChangedPerCpu(pVM, pVCpu);
     1532
     1533    return VINF_SUCCESS;
    14871534}
    14881535
     
    15021549     * Validate input.
    15031550     */
    1504     UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    15051551    size_t i = cConfigs;
    15061552    while (i-- > 0)
     
    15101556    }
    15111557
    1512     /*
    1513      * Apply the changes in EMT(0).
    1514      */
    1515     return VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3InterruptConfigEx, 3, pUVM, paConfigs, cConfigs);
     1558    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     1559    PVM pVM = pUVM->pVM;
     1560    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1561
     1562    /*
     1563     * Apply the changes in EMT(0) and rendezvous with the other CPUs so they
     1564     * can sync their data and execution with new debug state.
     1565     */
     1566    DBGFR3INTERRUPTCONFIGEXARGS Args = { paConfigs, cConfigs, VINF_SUCCESS };
     1567    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING, dbgfR3InterruptConfigEx, &Args);
     1568    if (RT_SUCCESS(rc))
     1569        rc = Args.rc;
     1570    return rc;
    15161571}
    15171572
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