VirtualBox

Changeset 86098 in vbox for trunk/src


Ignore:
Timestamp:
Sep 13, 2020 7:17:19 AM (4 years ago)
Author:
vboxsync
Message:

VMM/DBGF: Rework part 1 to make it work well with SMP VMs. bugref:9822

Location:
trunk/src/VBox
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGCCmdHlp.cpp

    r84653 r86098  
    13471347
    13481348/**
     1349 * @interface_method_impl{DBGCCMDHLP,pfnRegPrintf}
     1350 */
     1351static DECLCALLBACK(int) dbgcHlpRegPrintf(PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse)
     1352{
     1353    PDBGC pDbgc   = DBGC_CMDHLP2DBGC(pCmdHlp);
     1354    char  szDisAndRegs[8192];
     1355    int   rc;
     1356
     1357    if (f64BitMode < 0)
     1358        f64BitMode = DBGFR3CpuIsIn64BitCode(pDbgc->pUVM, idCpu);
     1359
     1360    if (fTerse)
     1361    {
     1362        if (f64BitMode)
     1363            rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, &szDisAndRegs[0], sizeof(szDisAndRegs),
     1364                                 "u %016VR{rip} L 0\n"
     1365                                 "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
     1366                                 "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
     1367                                 "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
     1368                                 "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
     1369                                 "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
     1370                                 "cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss}                     rflags=%08VR{rflags}\n");
     1371        else
     1372            rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, szDisAndRegs, sizeof(szDisAndRegs),
     1373                                 "u %04VR{cs}:%08VR{eip} L 0\n"
     1374                                 "eax=%08VR{eax} ebx=%08VR{ebx} ecx=%08VR{ecx} edx=%08VR{edx} esi=%08VR{esi} edi=%08VR{edi}\n"
     1375                                 "eip=%08VR{eip} esp=%08VR{esp} ebp=%08VR{ebp} %VRF{eflags}\n"
     1376                                 "cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss}               eflags=%08VR{eflags}\n");
     1377    }
     1378    else
     1379    {
     1380        if (f64BitMode)
     1381            rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, &szDisAndRegs[0], sizeof(szDisAndRegs),
     1382                                 "u %016VR{rip} L 0\n"
     1383                                 "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
     1384                                 "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
     1385                                 "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
     1386                                 "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
     1387                                 "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
     1388                                 "cs={%04VR{cs} base=%016VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} cr0=%016VR{cr0}\n"
     1389                                 "ds={%04VR{ds} base=%016VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} cr2=%016VR{cr2}\n"
     1390                                 "es={%04VR{es} base=%016VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} cr3=%016VR{cr3}\n"
     1391                                 "fs={%04VR{fs} base=%016VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr4=%016VR{cr4}\n"
     1392                                 "gs={%04VR{gs} base=%016VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr8=%016VR{cr8}\n"
     1393                                 "ss={%04VR{ss} base=%016VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}}\n"
     1394                                 "dr0=%016VR{dr0} dr1=%016VR{dr1} dr2=%016VR{dr2} dr3=%016VR{dr3}\n"
     1395                                 "dr6=%016VR{dr6} dr7=%016VR{dr7}\n"
     1396                                 "gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim}  idtr=%016VR{idtr_base}:%04VR{idtr_lim}  rflags=%08VR{rflags}\n"
     1397                                 "ldtr={%04VR{ldtr} base=%016VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%08VR{ldtr_attr}}\n"
     1398                                 "tr  ={%04VR{tr} base=%016VR{tr_base} limit=%08VR{tr_lim} flags=%08VR{tr_attr}}\n"
     1399                                 "    sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
     1400                                 "        efer=%016VR{efer}\n"
     1401                                 "         pat=%016VR{pat}\n"
     1402                                 "     sf_mask=%016VR{sf_mask}\n"
     1403                                 "krnl_gs_base=%016VR{krnl_gs_base}\n"
     1404                                 "       lstar=%016VR{lstar}\n"
     1405                                 "        star=%016VR{star} cstar=%016VR{cstar}\n"
     1406                                 "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
     1407                                 );
     1408        else
     1409            rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, szDisAndRegs, sizeof(szDisAndRegs),
     1410                                 "u %04VR{cs}:%08VR{eip} L 0\n"
     1411                                 "eax=%08VR{eax} ebx=%08VR{ebx} ecx=%08VR{ecx} edx=%08VR{edx} esi=%08VR{esi} edi=%08VR{edi}\n"
     1412                                 "eip=%08VR{eip} esp=%08VR{esp} ebp=%08VR{ebp} %VRF{eflags}\n"
     1413                                 "cs={%04VR{cs} base=%08VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} dr0=%08VR{dr0} dr1=%08VR{dr1}\n"
     1414                                 "ds={%04VR{ds} base=%08VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} dr2=%08VR{dr2} dr3=%08VR{dr3}\n"
     1415                                 "es={%04VR{es} base=%08VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} dr6=%08VR{dr6} dr7=%08VR{dr7}\n"
     1416                                 "fs={%04VR{fs} base=%08VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr0=%08VR{cr0} cr2=%08VR{cr2}\n"
     1417                                 "gs={%04VR{gs} base=%08VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr3=%08VR{cr3} cr4=%08VR{cr4}\n"
     1418                                 "ss={%04VR{ss} base=%08VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}} cr8=%08VR{cr8}\n"
     1419                                 "gdtr=%08VR{gdtr_base}:%04VR{gdtr_lim}  idtr=%08VR{idtr_base}:%04VR{idtr_lim}  eflags=%08VR{eflags}\n"
     1420                                 "ldtr={%04VR{ldtr} base=%08VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%04VR{ldtr_attr}}\n"
     1421                                 "tr  ={%04VR{tr} base=%08VR{tr_base} limit=%08VR{tr_lim} flags=%04VR{tr_attr}}\n"
     1422                                 "sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
     1423                                 "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
     1424                                 );
     1425    }
     1426    if (RT_FAILURE(rc))
     1427        return DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegPrintf failed");
     1428    char *pszRegs = strchr(szDisAndRegs, '\n');
     1429    *pszRegs++ = '\0';
     1430    rc = DBGCCmdHlpPrintf(pCmdHlp, "%s", pszRegs);
     1431
     1432    /*
     1433     * Disassemble one instruction at cs:[r|e]ip.
     1434     */
     1435    if (!f64BitMode && strstr(pszRegs, " vm ")) /* a bit ugly... */
     1436        return pCmdHlp->pfnExec(pCmdHlp, "uv86 %s", szDisAndRegs + 2);
     1437    return pCmdHlp->pfnExec(pCmdHlp, "%s", szDisAndRegs);
     1438}
     1439
     1440
     1441/**
    13491442 * Initializes the Command Helpers for a DBGC instance.
    13501443 *
     
    13761469    pDbgc->CmdHlp.pfnGetCurrentCpu      = dbgcHlpGetCurrentCpu;
    13771470    pDbgc->CmdHlp.pfnGetCpuMode         = dbgcHlpGetCpuMode;
     1471    pDbgc->CmdHlp.pfnRegPrintf          = dbgcHlpRegPrintf;
    13781472    pDbgc->CmdHlp.u32EndMarker          = DBGCCMDHLP_MAGIC;
    13791473}
  • trunk/src/VBox/Debugger/DBGCCommands.cpp

    r83088 r86098  
    233233    {  1,           1,          DBGCVAR_CAT_SYMBOL,     0,                              "var",          "Variable name." },
    234234    {  1,           1,          DBGCVAR_CAT_ANY,        0,                              "value",        "Value to assign to the variable." },
     235};
     236
     237/** 'stop' arguments */
     238static const DBGCVARDESC    g_aArgStop[] =
     239{
     240    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     241    {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "idCpu",        "CPU ID." },
    235242};
    236243
     
    298305    { "set",        2,        2,        &g_aArgSet[0],       RT_ELEMENTS(g_aArgSet),       0, dbgcCmdSet,       "<var> <value>",        "Sets a global variable." },
    299306    { "showvars",   0,        0,        NULL,                0,                            0, dbgcCmdShowVars,  "",                     "List all the defined variables." },
    300     { "stop",       0,        0,        NULL,                0,                            0, dbgcCmdStop,      "",                     "Stop execution." },
     307    { "stop",       0,        1,        &g_aArgStop[0],      RT_ELEMENTS(g_aArgStop),      0, dbgcCmdStop,      "[idCpu]",              "Stop execution either of all or the specified CPU. (The latter is not recommended unless you know exactly what you're doing.)" },
    301308    { "unload",     1,       ~0U,       &g_aArgUnload[0],    RT_ELEMENTS(g_aArgUnload),    0, dbgcCmdUnload,    "<modname1> [modname2..N]", "Unloads one or more modules in the current address space." },
    302309    { "unloadplugin", 1,     ~0U,       &g_aArgPlugIn[0],    RT_ELEMENTS(g_aArgPlugIn),    0, dbgcCmdUnloadPlugIn, "<plugin1> [plugin2..N]", "Unloads one or more plugins." },
     
    938945static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
    939946{
    940     /*
    941      * Check if the VM is halted or not before trying to halt it.
    942      */
    943     int rc;
    944     if (DBGFR3IsHalted(pUVM))
    945         rc = DBGCCmdHlpPrintf(pCmdHlp, "warning: The VM is already halted...\n");
     947    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
     948
     949    /*
     950     * Parse arguments.
     951     */
     952    VMCPUID idCpu = VMCPUID_ALL;
     953    if (cArgs == 1)
     954    {
     955        VMCPUID cCpus = DBGFR3CpuGetCount(pUVM);
     956        if (paArgs[0].u.u64Number >= cCpus)
     957            return DBGCCmdHlpFail(pCmdHlp, pCmd, "idCpu %RU64 is out of range! Highest valid ID is %u.\n",
     958                                  paArgs[0].u.u64Number, cCpus - 1);
     959        idCpu = (VMCPUID)paArgs[0].u.u64Number;
     960    }
    946961    else
    947     {
    948         rc = DBGFR3Halt(pUVM);
    949         if (RT_SUCCESS(rc))
     962        Assert(cArgs == 0);
     963
     964    /*
     965     * Try halt the VM or VCpu.
     966     */
     967    int rc = DBGFR3Halt(pUVM, idCpu);
     968    if (RT_SUCCESS(rc))
     969    {
     970        Assert(rc == VINF_SUCCESS || rc == VWRN_DBGF_ALREADY_HALTED);
     971        if (rc != VWRN_DBGF_ALREADY_HALTED)
    950972            rc = VWRN_DBGC_CMD_PENDING;
     973        else if (idCpu == VMCPUID_ALL)
     974            rc = DBGCCmdHlpPrintf(pCmdHlp, "warning: The VM is already halted...\n");
    951975        else
    952             rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "Executing DBGFR3Halt().");
    953     }
    954 
    955     NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
     976            rc = DBGCCmdHlpPrintf(pCmdHlp, "warning: CPU %u is already halted...\n", idCpu);
     977    }
     978    else
     979        rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "Executing DBGFR3Halt().");
     980
    956981    return rc;
    957982}
  • trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp

    r83082 r86098  
    237237    {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address where to write." },
    238238    {  1,           ~0U,        DBGCVAR_CAT_NUMBER,     0,                              "value",        "Value to write." },
     239};
     240
     241
     242/** 'g' arguments. */
     243static const DBGCVARDESC    g_aArgGo[] =
     244{
     245    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     246    {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "idCpu",        "CPU ID." },
    239247};
    240248
     
    425433    { "ed",         2,        2,        &g_aArgEditMem[0],  RT_ELEMENTS(g_aArgEditMem),     0,       dbgcCmdEditMem,     "<addr> <value>",       "Write a 4-byte value to memory." },
    426434    { "eq",         2,        2,        &g_aArgEditMem[0],  RT_ELEMENTS(g_aArgEditMem),     0,       dbgcCmdEditMem,     "<addr> <value>",       "Write a 8-byte value to memory." },
    427     { "g",          0,        0,        NULL,               0,                              0,       dbgcCmdGo,          "",                     "Continue execution." },
     435    { "g",          0,        1,        &g_aArgGo[0],       RT_ELEMENTS(g_aArgGo),          0,       dbgcCmdGo,          "[idCpu]",              "Continue execution of all or the specified CPU. (The latter is not recommended unless you know exactly what you're doing.)" },
    428436    { "gu",         0,        0,        NULL,               0,                              0,       dbgcCmdGoUp,        "",                     "Go up - continue execution till after return." },
    429437    { "k",          0,        0,        NULL,               0,                              0,       dbgcCmdStack,       "",                     "Callstack." },
     
    651659
    652660    /*
    653      * Check if the VM is halted or not before trying to resume it.
    654      */
    655     if (!DBGFR3IsHalted(pUVM))
    656         return DBGCCmdHlpFail(pCmdHlp, pCmd, "The VM is already running");
    657 
    658     int rc = DBGFR3Resume(pUVM);
    659     if (RT_FAILURE(rc))
    660         return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3Resume");
    661 
    662     NOREF(paArgs); NOREF(cArgs);
    663     return VINF_SUCCESS;
     661     * Parse arguments.
     662     */
     663    VMCPUID idCpu = VMCPUID_ALL;
     664    if (cArgs == 1)
     665    {
     666        VMCPUID cCpus = DBGFR3CpuGetCount(pUVM);
     667        if (paArgs[0].u.u64Number >= cCpus)
     668            return DBGCCmdHlpFail(pCmdHlp, pCmd, "idCpu %RU64 is out of range! Highest valid ID is %u.\n",
     669                                  paArgs[0].u.u64Number, cCpus - 1);
     670        idCpu = (VMCPUID)paArgs[0].u.u64Number;
     671    }
     672    else
     673        Assert(cArgs == 0);
     674
     675    /*
     676     * Try resume the VM or CPU.
     677     */
     678    int rc = DBGFR3Resume(pUVM, idCpu);
     679    if (RT_SUCCESS(rc))
     680    {
     681        Assert(rc == VINF_SUCCESS || rc == VWRN_DBGF_ALREADY_RUNNING);
     682        if (rc != VWRN_DBGF_ALREADY_RUNNING)
     683            return VINF_SUCCESS;
     684        if (idCpu == VMCPUID_ALL)
     685            return DBGCCmdHlpFail(pCmdHlp, pCmd, "The VM is already running");
     686        return DBGCCmdHlpFail(pCmdHlp, pCmd, "CPU %u is already running", idCpu);
     687    }
     688    return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3Resume");
    664689}
    665690
     
    24662491                              || (   strcmp(pCmd->pszCmd, "rg32") != 0
    24672492                                  && DBGFR3CpuIsIn64BitCode(pUVM, pDbgc->idCpu));
    2468         char        szDisAndRegs[8192];
    2469         int         rc;
    2470 
    2471         if (pDbgc->fRegTerse)
    2472         {
    2473             if (f64BitMode)
    2474                 rc = DBGFR3RegPrintf(pUVM, pDbgc->idCpu, &szDisAndRegs[0], sizeof(szDisAndRegs),
    2475                                      "u %016VR{rip} L 0\n"
    2476                                      "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
    2477                                      "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
    2478                                      "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
    2479                                      "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
    2480                                      "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
    2481                                      "cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss}                     rflags=%08VR{rflags}\n");
    2482             else
    2483                 rc = DBGFR3RegPrintf(pUVM, pDbgc->idCpu, szDisAndRegs, sizeof(szDisAndRegs),
    2484                                      "u %04VR{cs}:%08VR{eip} L 0\n"
    2485                                      "eax=%08VR{eax} ebx=%08VR{ebx} ecx=%08VR{ecx} edx=%08VR{edx} esi=%08VR{esi} edi=%08VR{edi}\n"
    2486                                      "eip=%08VR{eip} esp=%08VR{esp} ebp=%08VR{ebp} %VRF{eflags}\n"
    2487                                      "cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss}               eflags=%08VR{eflags}\n");
    2488         }
    2489         else
    2490         {
    2491             if (f64BitMode)
    2492                 rc = DBGFR3RegPrintf(pUVM, pDbgc->idCpu, &szDisAndRegs[0], sizeof(szDisAndRegs),
    2493                                      "u %016VR{rip} L 0\n"
    2494                                      "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
    2495                                      "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
    2496                                      "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
    2497                                      "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
    2498                                      "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
    2499                                      "cs={%04VR{cs} base=%016VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} cr0=%016VR{cr0}\n"
    2500                                      "ds={%04VR{ds} base=%016VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} cr2=%016VR{cr2}\n"
    2501                                      "es={%04VR{es} base=%016VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} cr3=%016VR{cr3}\n"
    2502                                      "fs={%04VR{fs} base=%016VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr4=%016VR{cr4}\n"
    2503                                      "gs={%04VR{gs} base=%016VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr8=%016VR{cr8}\n"
    2504                                      "ss={%04VR{ss} base=%016VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}}\n"
    2505                                      "dr0=%016VR{dr0} dr1=%016VR{dr1} dr2=%016VR{dr2} dr3=%016VR{dr3}\n"
    2506                                      "dr6=%016VR{dr6} dr7=%016VR{dr7}\n"
    2507                                      "gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim}  idtr=%016VR{idtr_base}:%04VR{idtr_lim}  rflags=%08VR{rflags}\n"
    2508                                      "ldtr={%04VR{ldtr} base=%016VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%08VR{ldtr_attr}}\n"
    2509                                      "tr  ={%04VR{tr} base=%016VR{tr_base} limit=%08VR{tr_lim} flags=%08VR{tr_attr}}\n"
    2510                                      "    sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
    2511                                      "        efer=%016VR{efer}\n"
    2512                                      "         pat=%016VR{pat}\n"
    2513                                      "     sf_mask=%016VR{sf_mask}\n"
    2514                                      "krnl_gs_base=%016VR{krnl_gs_base}\n"
    2515                                      "       lstar=%016VR{lstar}\n"
    2516                                      "        star=%016VR{star} cstar=%016VR{cstar}\n"
    2517                                      "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
    2518                                      );
    2519             else
    2520                 rc = DBGFR3RegPrintf(pUVM, pDbgc->idCpu, szDisAndRegs, sizeof(szDisAndRegs),
    2521                                      "u %04VR{cs}:%08VR{eip} L 0\n"
    2522                                      "eax=%08VR{eax} ebx=%08VR{ebx} ecx=%08VR{ecx} edx=%08VR{edx} esi=%08VR{esi} edi=%08VR{edi}\n"
    2523                                      "eip=%08VR{eip} esp=%08VR{esp} ebp=%08VR{ebp} %VRF{eflags}\n"
    2524                                      "cs={%04VR{cs} base=%08VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} dr0=%08VR{dr0} dr1=%08VR{dr1}\n"
    2525                                      "ds={%04VR{ds} base=%08VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} dr2=%08VR{dr2} dr3=%08VR{dr3}\n"
    2526                                      "es={%04VR{es} base=%08VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} dr6=%08VR{dr6} dr7=%08VR{dr7}\n"
    2527                                      "fs={%04VR{fs} base=%08VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr0=%08VR{cr0} cr2=%08VR{cr2}\n"
    2528                                      "gs={%04VR{gs} base=%08VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr3=%08VR{cr3} cr4=%08VR{cr4}\n"
    2529                                      "ss={%04VR{ss} base=%08VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}} cr8=%08VR{cr8}\n"
    2530                                      "gdtr=%08VR{gdtr_base}:%04VR{gdtr_lim}  idtr=%08VR{idtr_base}:%04VR{idtr_lim}  eflags=%08VR{eflags}\n"
    2531                                      "ldtr={%04VR{ldtr} base=%08VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%04VR{ldtr_attr}}\n"
    2532                                      "tr  ={%04VR{tr} base=%08VR{tr_base} limit=%08VR{tr_lim} flags=%04VR{tr_attr}}\n"
    2533                                      "sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
    2534                                      "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
    2535                                      );
    2536         }
    2537         if (RT_FAILURE(rc))
    2538             return DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegPrintf failed");
    2539         char *pszRegs = strchr(szDisAndRegs, '\n');
    2540         *pszRegs++ = '\0';
    2541         rc = DBGCCmdHlpPrintf(pCmdHlp, "%s", pszRegs);
    2542 
    2543         /*
    2544          * Disassemble one instruction at cs:[r|e]ip.
    2545          */
    2546         if (!f64BitMode && strstr(pszRegs, " vm ")) /* a bit ugly... */
    2547             return pCmdHlp->pfnExec(pCmdHlp, "uv86 %s", szDisAndRegs + 2);
    2548         return pCmdHlp->pfnExec(pCmdHlp, "%s", szDisAndRegs);
     2493        return DBGCCmdHlpRegPrintf(pCmdHlp, pDbgc->idCpu, f64BitMode, pDbgc->fRegTerse);
    25492494    }
    25502495    return dbgcCmdRegCommon(pCmd, pCmdHlp, pUVM, paArgs, cArgs, "");
  • trunk/src/VBox/Debugger/DBGCGdbRemoteStub.cpp

    r85367 r86098  
    15651565        case 'c':
    15661566        {
    1567             if (DBGFR3IsHalted(pThis->Dbgc.pUVM))
    1568                 DBGFR3Resume(pThis->Dbgc.pUVM);
     1567            if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
     1568                DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
    15691569            break;
    15701570        }
     
    15811581        case 't':
    15821582        {
    1583             if (!DBGFR3IsHalted(pThis->Dbgc.pUVM))
    1584                 rc = DBGFR3Halt(pThis->Dbgc.pUVM);
     1583            if (!DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
     1584                rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
    15851585            /* The reply will be send in the event loop. */
    15861586            break;
     
    17321732            case 'c': /* Continue, no response */
    17331733            {
    1734                 if (DBGFR3IsHalted(pThis->Dbgc.pUVM))
    1735                     DBGFR3Resume(pThis->Dbgc.pUVM);
     1734                if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
     1735                    DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
    17361736                break;
    17371737            }
     
    21742174        {
    21752175            /* Stop target and send packet to indicate the target has stopped. */
    2176             if (!DBGFR3IsHalted(pThis->Dbgc.pUVM))
    2177                 rc = DBGFR3Halt(pThis->Dbgc.pUVM);
     2176            if (!DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
     2177                rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
    21782178            /* The reply will be send in the event loop. */
    21792179        }
     
    24032403                    break;
    24042404            }
    2405             if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM))
     2405            if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
    24062406            {
    24072407                rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     
    25892589             * Wait for a debug event.
    25902590             */
    2591             PCDBGFEVENT pEvent;
    2592             rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &pEvent);
     2591            DBGFEVENT Event;
     2592            rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Event);
    25932593            if (RT_SUCCESS(rc))
    25942594            {
    2595                 rc = dbgcGdbStubCtxProcessEvent(pThis, pEvent);
     2595                rc = dbgcGdbStubCtxProcessEvent(pThis, &Event);
    25962596                if (RT_FAILURE(rc))
    25972597                    break;
     
    28402840        //dbgcRunInitScripts(pDbgc); Not yet
    28412841
    2842         if (!DBGFR3IsHalted(pThis->Dbgc.pUVM))
    2843             rc = DBGFR3Halt(pThis->Dbgc.pUVM);
     2842        if (!DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
     2843            rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
    28442844
    28452845        /*
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r84708 r86098  
    648648    bool fPrintPrompt = true;
    649649    int rc = VINF_SUCCESS;
     650    VMCPUID const idCpuSaved = pDbgc->idCpu;
    650651    switch (pEvent->enmType)
    651652    {
     
    655656        case DBGFEVENT_HALT_DONE:
    656657        {
    657             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: VM %p is halted! (%s)\n",
    658                                          pDbgc->pVM, dbgcGetEventCtx(pEvent->enmCtx));
     658            /** @todo add option to suppress this on CPUs that aren't selected (like
     659             *        fRegTerse). */
     660            rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: CPU %u has halted! (%s)\n",
     661                                         pEvent->idCpu, pEvent->idCpu, dbgcGetEventCtx(pEvent->enmCtx));
    659662            if (RT_SUCCESS(rc))
    660                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     663                rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse);
    661664            break;
    662665        }
     
    668671        case DBGFEVENT_FATAL_ERROR:
    669672        {
    670             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
    671                                          dbgcGetEventCtx(pEvent->enmCtx));
     673            pDbgc->idCpu = pEvent->idCpu;
     674            rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event/%u: Fatal error! (%s)\n",
     675                                         pEvent->idCpu, dbgcGetEventCtx(pEvent->enmCtx));
    672676            if (RT_SUCCESS(rc))
    673                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     677                rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse);
    674678            break;
    675679        }
     
    680684        case DBGFEVENT_BREAKPOINT_HYPER:
    681685        {
     686            pDbgc->idCpu = pEvent->idCpu;
    682687            rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp);
    683688            switch (rc)
    684689            {
    685690                case VERR_DBGC_BP_NOT_FOUND:
    686                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
    687                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
     691                    rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: Unknown breakpoint %u! (%s)\n",
     692                                                 pEvent->idCpu, pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    688693                    break;
    689694
    690695                case VINF_DBGC_BP_NO_COMMAND:
    691                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
    692                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
     696                    rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: Breakpoint %u! (%s)\n",
     697                                                 pEvent->idCpu, pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    693698                    break;
    694699
    695700                case VINF_BUFFER_OVERFLOW:
    696                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
    697                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
     701                    rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: Breakpoint %u! Command too long to execute! (%s)\n",
     702                                                 pEvent->idCpu, pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    698703                    break;
    699704
     
    701706                    break;
    702707            }
    703             if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM))
     708            if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, pEvent->idCpu))
    704709            {
    705                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     710                rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse);
    706711
    707712                /* Set the resume flag to ignore the breakpoint when resuming execution. */
     
    710715                    rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
    711716            }
     717            else
     718                pDbgc->idCpu = idCpuSaved;
    712719            break;
    713720        }
     
    716723        case DBGFEVENT_STEPPED_HYPER:
    717724        {
    718             if (!pDbgc->cMultiStepsLeft)
    719                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Single step! (%s)\n", dbgcGetEventCtx(pEvent->enmCtx));
     725            if (!pDbgc->cMultiStepsLeft || pEvent->idCpu != idCpuSaved)
     726                rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: Single step! (%s)\n",
     727                                             pEvent->idCpu, dbgcGetEventCtx(pEvent->enmCtx));
    720728            else
    721729                pDbgc->cMultiStepsLeft -= 1;
     
    723731            {
    724732                if (pDbgc->fStepTraceRegs)
    725                     rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     733                    rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse);
    726734                else
    727735                {
     
    739747
    740748            /* If multi-stepping, take the next step: */
    741             if (pDbgc->cMultiStepsLeft > 0)
     749            if (pDbgc->cMultiStepsLeft > 0 && pEvent->idCpu != idCpuSaved)
    742750            {
    743751                int rc2 = DBGFR3StepEx(pDbgc->pUVM, pDbgc->idCpu, DBGF_STEP_F_INTO, NULL, NULL, 0, pDbgc->uMultiStepStrideLength);
     
    747755                    DBGCCmdHlpFailRc(&pDbgc->CmdHlp, pDbgc->pMultiStepCmd, rc2, "DBGFR3StepEx(,,DBGF_STEP_F_INTO,) failed");
    748756            }
     757            else
     758                pDbgc->idCpu = pEvent->idCpu;
    749759            break;
    750760        }
     
    752762        case DBGFEVENT_ASSERTION_HYPER:
    753763        {
     764            pDbgc->idCpu = pEvent->idCpu;
    754765            rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    755                                          "\ndbgf event: Hypervisor Assertion! (%s)\n"
     766                                         "\ndbgf event/%u: Hypervisor Assertion! (%s)\n"
    756767                                         "%s"
    757768                                         "%s"
    758769                                         "\n",
     770                                         pEvent->idCpu,
    759771                                         dbgcGetEventCtx(pEvent->enmCtx),
    760772                                         pEvent->u.Assert.pszMsg1,
    761773                                         pEvent->u.Assert.pszMsg2);
    762774            if (RT_SUCCESS(rc))
    763                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     775                rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse);
    764776            break;
    765777        }
     
    767779        case DBGFEVENT_DEV_STOP:
    768780        {
     781            pDbgc->idCpu = pEvent->idCpu;
    769782            rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    770783                                         "\n"
    771                                          "dbgf event: DBGFSTOP (%s)\n"
     784                                         "dbgf event/%u: DBGFSTOP (%s)\n"
    772785                                         "File:     %s\n"
    773786                                         "Line:     %d\n"
    774787                                         "Function: %s\n",
     788                                         pEvent->idCpu,
    775789                                         dbgcGetEventCtx(pEvent->enmCtx),
    776790                                         pEvent->u.Src.pszFile,
     
    782796                                             pEvent->u.Src.pszMessage);
    783797            if (RT_SUCCESS(rc))
    784                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
     798                rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse);
    785799            break;
    786800        }
     
    816830                    Assert(pEvtDesc->pszDesc);
    817831                    Assert(pEvent->u.Generic.cArgs == 1);
    818                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
    819                                                  pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
     832                    rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s no %#llx! (%s)\n",
     833                                                 pEvent->idCpu, pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
    820834                }
    821835                else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
     
    826840                                         pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
    827841                                         pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
    828                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
    829                                                  pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
    830                                                  szDetails);
     842                    rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s %s%s!\n%s", pEvent->idCpu,
     843                                                 pEvtDesc->pszName, pEvtDesc->pszDesc ? "- " : "",
     844                                                 pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "", szDetails);
    831845                }
    832846                else if (   (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
     
    836850                {
    837851                    if (pEvtDesc->pszDesc)
    838                         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
    839                                                      pEvtDesc->pszName, pEvtDesc->pszDesc);
     852                        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s - %s!",
     853                                                     pEvent->idCpu, pEvtDesc->pszName, pEvtDesc->pszDesc);
    840854                    else
    841                         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
     855                        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s!",
     856                                                     pEvent->idCpu, pEvtDesc->pszName);
    842857                    if (pEvent->u.Generic.cArgs <= 1)
    843858                        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
     
    852867                {
    853868                    if (pEvtDesc->pszDesc)
    854                         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
    855                                                      pEvtDesc->pszName, pEvtDesc->pszDesc);
     869                        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s - %s!\n",
     870                                                     pEvent->idCpu, pEvtDesc->pszName, pEvtDesc->pszDesc);
    856871                    else
    857                         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
     872                        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s!\n",
     873                                                     pEvent->idCpu, pEvtDesc->pszName);
    858874                }
    859875            }
    860876            else
    861                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
     877                rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d on CPU %u!\n",
     878                                             pEvent->enmType, pEvent->idCpu);
    862879            break;
    863880        }
     
    869886    if (fPrintPrompt && RT_SUCCESS(rc))
    870887    {
     888        /** @todo add CPU indicator to the prompt if an SMP VM? */
    871889        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
    872890        pDbgc->fReady = true;
     
    938956             * Wait for a debug event.
    939957             */
    940             PCDBGFEVENT pEvent;
    941             rc = DBGFR3EventWait(pDbgc->pUVM, pDbgc->fLog ? 1 : 32, &pEvent);
     958            DBGFEVENT Event;
     959            rc = DBGFR3EventWait(pDbgc->pUVM, pDbgc->fLog ? 1 : 32, &Event);
    942960            if (RT_SUCCESS(rc))
    943961            {
    944                 rc = dbgcProcessEvent(pDbgc, pEvent);
     962                rc = dbgcProcessEvent(pDbgc, &Event);
    945963                if (RT_FAILURE(rc))
    946964                    break;
  • trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp

    r82968 r86098  
    9494    return VERR_INTERNAL_ERROR;
    9595}
    96 VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent)
     96VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PDBGFEVENT pEvent)
    9797{
    9898    return VERR_INTERNAL_ERROR;
     
    107107}
    108108
    109 VMMR3DECL(int) DBGFR3Halt(PUVM pUVM)
     109VMMR3DECL(int) DBGFR3Halt(PUVM pUVM, VMCPUID idCpu)
    110110{
    111111    return VERR_INTERNAL_ERROR;
     
    122122{
    123123}
    124 VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM)
     124VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM, VMCPUID idCpu)
    125125{
    126126    return true;
     
    164164    return VERR_DBG_LINE_NOT_FOUND;
    165165}
    166 VMMR3DECL(int) DBGFR3Resume(PUVM pUVM)
     166VMMR3DECL(int) DBGFR3Resume(PUVM pUVM, VMCPUID idCpu)
    167167{
    168168    return VERR_INTERNAL_ERROR;
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r84458 r86098  
    7575#include <VBox/vmm/em.h>
    7676#include <VBox/vmm/hm.h>
     77#include <VBox/vmm/mm.h>
    7778#include "DBGFInternal.h"
    7879#include <VBox/vmm/vm.h>
     
    110111*   Internal Functions                                                                                                           *
    111112*********************************************************************************************************************************/
    112 static int dbgfR3VMMWait(PVM pVM);
    113 static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution);
    114 static DECLCALLBACK(int) dbgfR3Attach(PVM pVM);
     113DECLINLINE(int) dbgfR3SendEventWait(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx);
     114DECLINLINE(DBGFCMD) dbgfR3CpuGetCmd(PUVMCPU pUVCpu);
     115static int dbgfR3CpuWait(PVMCPU pVCpu);
     116static int dbgfR3CpuCmd(PVMCPU pVCpu, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution);
    115117static DBGFSTEPINSTRTYPE dbgfStepGetCurInstrType(PVM pVM, PVMCPU pVCpu);
    116 static bool dbgfStepAreWeThereYet(PVM pVM,  PVMCPU pVCpu);
    117 
    118 
    119 /**
    120  * Sets the VMM Debug Command variable.
    121  *
    122  * @returns Previous command.
    123  * @param   pVM     The cross context VM structure.
    124  * @param   enmCmd  The command.
    125  */
    126 DECLINLINE(DBGFCMD) dbgfR3SetCmd(PVM pVM, DBGFCMD enmCmd)
    127 {
    128     DBGFCMD rc;
    129     if (enmCmd == DBGFCMD_NO_COMMAND)
    130     {
    131         Log2(("DBGF: Setting command to %d (DBGFCMD_NO_COMMAND)\n", enmCmd));
    132         rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd);
    133         VM_FF_CLEAR(pVM, VM_FF_DBGF);
    134     }
    135     else
    136     {
    137         Log2(("DBGF: Setting command to %d\n", enmCmd));
    138         AssertMsg(pVM->dbgf.s.enmVMMCmd == DBGFCMD_NO_COMMAND, ("enmCmd=%d enmVMMCmd=%d\n", enmCmd, pVM->dbgf.s.enmVMMCmd));
    139         rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd);
    140         VM_FF_SET(pVM, VM_FF_DBGF);
    141         VMR3NotifyGlobalFFU(pVM->pUVM, 0 /* didn't notify REM */);
    142     }
    143     return rc;
    144 }
     118static bool dbgfStepAreWeThereYet(PVM pVM, PVMCPU pVCpu);
     119
    145120
    146121
     
    244219VMMR3_INT_DECL(void) DBGFR3PowerOff(PVM pVM)
    245220{
    246 
    247221    /*
    248222     * Send a termination event to any attached debugger.
    249223     */
    250     /* wait to become the speaker (we should already be that). */
    251     if (    pVM->dbgf.s.fAttached
    252         &&  RTSemPingShouldWait(&pVM->dbgf.s.PingPong))
    253         RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);
    254 
    255224    if (pVM->dbgf.s.fAttached)
    256225    {
    257         /* Just mark it as detached if we're not in a position to send a power
    258            off event.  It should fail later on. */
    259         if (!RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
    260         {
    261             ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, false);
    262             if (RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
    263                 ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, true);
    264         }
    265 
    266         if (RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
    267         {
    268             /* Try send the power off event. */
    269             int rc;
    270             DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
    271             if (enmCmd == DBGFCMD_DETACH_DEBUGGER)
    272                 /* the debugger beat us to initiating the detaching. */
    273                 rc = VINF_SUCCESS;
    274             else
    275             {
    276                 /* ignore the command (if any). */
    277                 enmCmd = DBGFCMD_NO_COMMAND;
    278                 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_POWERING_OFF;
    279                 pVM->dbgf.s.DbgEvent.enmCtx  = DBGFEVENTCTX_OTHER;
    280                 rc = RTSemPing(&pVM->dbgf.s.PingPong);
    281             }
    282 
    283             /*
    284              * Process commands and priority requests until we get a command
    285              * indicating that the debugger has detached.
    286              */
    287             uint32_t cPollHack = 1;
    288             PVMCPU   pVCpu     = VMMGetCpu(pVM);
    289             while (RT_SUCCESS(rc))
    290             {
    291                 if (enmCmd != DBGFCMD_NO_COMMAND)
    292                 {
    293                     /* process command */
    294                     bool fResumeExecution;
    295                     DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
    296                     rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
    297                     if (enmCmd == DBGFCMD_DETACHED_DEBUGGER)
    298                         break;
    299                     enmCmd = DBGFCMD_NO_COMMAND;
    300                 }
    301                 else
    302                 {
    303                     /* Wait for new command, processing pending priority requests
    304                        first.  The request processing is a bit crazy, but
    305                        unfortunately required by plugin unloading. */
    306                     if (   VM_FF_IS_SET(pVM, VM_FF_REQUEST)
    307                         || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
    308                     {
    309                         LogFlow(("DBGFR3PowerOff: Processes priority requests...\n"));
    310                         rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, true /*fPriorityOnly*/);
    311                         if (rc == VINF_SUCCESS)
    312                             rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, true /*fPriorityOnly*/);
    313                         LogFlow(("DBGFR3PowerOff: VMR3ReqProcess -> %Rrc\n", rc));
    314                         cPollHack = 1;
    315                     }
    316                     /* Need to handle rendezvous too, for generic debug event management. */
    317                     else if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
    318                     {
    319                         rc = VMMR3EmtRendezvousFF(pVM, pVCpu);
    320                         AssertLogRel(rc == VINF_SUCCESS);
    321                         cPollHack = 1;
    322                     }
    323                     else if (cPollHack < 120)
    324                         cPollHack++;
    325 
    326                     rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack);
    327                     if (RT_SUCCESS(rc))
    328                         enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
    329                     else if (rc == VERR_TIMEOUT)
    330                         rc = VINF_SUCCESS;
    331                 }
    332             }
    333 
    334             /*
    335              * Clear the FF so we won't get confused later on.
    336              */
    337             VM_FF_CLEAR(pVM, VM_FF_DBGF);
    338         }
     226        PVMCPU pVCpu = VMMGetCpu(pVM);
     227        int rc = dbgfR3SendEventWait(pVM, pVCpu, DBGFEVENT_POWERING_OFF, DBGFEVENTCTX_OTHER);
     228        AssertLogRelRC(rc);
     229
     230        /*
     231         * Clear the FF so we won't get confused later on.
     232         */
     233        VM_FF_CLEAR(pVM, VM_FF_DBGF);
    339234    }
    340235}
     
    371266     * First a message.
    372267     */
    373 #ifndef RT_OS_L4
    374 
    375 # if !defined(DEBUG) || defined(DEBUG_sandervl) || defined(DEBUG_frank)
     268#if !defined(DEBUG)
    376269    int cWait = 10;
    377 # else
     270#else
    378271    int cWait = !VM_IS_RAW_MODE_ENABLED(pVM)
    379272             && (   enmEvent == DBGFEVENT_ASSERTION_HYPER
     
    382275              ? 10
    383276              : 150;
    384 # endif
     277#endif
    385278    RTStrmPrintf(g_pStdErr, "DBGF: No debugger attached, waiting %d second%s for one to attach (event=%d)\n",
    386279                 cWait / 10, cWait != 10 ? "s" : "", enmEvent);
     
    394287            RTStrmFlush(g_pStdErr);
    395288            return true;
     289        }
     290
     291        /* Process rendezvous (debugger attaching involves such). */
     292        if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
     293        {
     294            int rc = VMMR3EmtRendezvousFF(pVM, pVCpu); AssertRC(rc);
     295            if (rc != VINF_SUCCESS)
     296            {
     297                /** @todo Ignoring these could be bad. */
     298                RTStrmPrintf(g_pStdErr, "[rcRendezvous=%Rrc, ignored!]", rc);
     299                RTStrmFlush(g_pStdErr);
     300            }
    396301        }
    397302
     
    405310            if (rc != VINF_SUCCESS)
    406311            {
     312                /** @todo Ignoring these could be bad. */
    407313                RTStrmPrintf(g_pStdErr, "[rcReq=%Rrc, ignored!]", rc);
    408314                RTStrmFlush(g_pStdErr);
     
    418324        cWait--;
    419325    }
    420 #endif
    421326
    422327    RTStrmPrintf(g_pStdErr, "Stopping the VM!\n");
     
    444349    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    445350
    446     if (VM_FF_TEST_AND_CLEAR(pVM, VM_FF_DBGF))
    447     {
     351    /*
     352     * Dispatch pending events.
     353     */
     354    if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_DBGF))
     355    {
     356        if (   pVCpu->dbgf.s.cEvents > 0
     357            && pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].enmState == DBGFEVENTSTATE_CURRENT)
     358        {
     359            rcStrict = DBGFR3EventHandlePending(pVM, pVCpu);
     360            /** @todo may end up with VERR_DBGF_NOT_ATTACHED here, which will prove fatal... */
     361        }
     362
    448363        /*
    449364         * Command pending? Process it.
    450365         */
    451         if (pVM->dbgf.s.enmVMMCmd != DBGFCMD_NO_COMMAND)
     366        PUVMCPU pUVCpu = pVCpu->pUVCpu;
     367        if (pUVCpu->dbgf.s.enmDbgfCmd != DBGFCMD_NO_COMMAND)
    452368        {
    453369            bool            fResumeExecution;
    454             DBGFCMDDATA     CmdData = pVM->dbgf.s.VMMCmdData;
    455             DBGFCMD         enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
    456             rcStrict = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
     370            DBGFCMDDATA     CmdData = pUVCpu->dbgf.s.DbgfCmdData;
     371            DBGFCMD         enmCmd = dbgfR3CpuGetCmd(pUVCpu);
     372            VBOXSTRICTRC rcStrict2 = dbgfR3CpuCmd(pVCpu, enmCmd, &CmdData, &fResumeExecution);
    457373            if (!fResumeExecution)
    458                 rcStrict = dbgfR3VMMWait(pVM);
    459         }
    460     }
    461 
    462     /*
    463      * Dispatch pending events.
    464      */
    465     if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_DBGF))
    466     {
    467         if (   pVCpu->dbgf.s.cEvents > 0
    468             && pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].enmState == DBGFEVENTSTATE_CURRENT)
    469         {
    470             VBOXSTRICTRC rcStrict2 = DBGFR3EventHandlePending(pVM, pVCpu);
     374                rcStrict2 = dbgfR3CpuWait(pVCpu);
    471375            if (   rcStrict2 != VINF_SUCCESS
    472376                && (   rcStrict == VINF_SUCCESS
     
    482386
    483387/**
    484  * Flag whether the event implies that we're stopped in the hypervisor code
    485  * and have to block certain operations.
    486  *
    487  * @param   pVM         The cross context VM structure.
    488  * @param   enmEvent    The event.
    489  */
    490 static void dbgfR3EventSetStoppedInHyperFlag(PVM pVM, DBGFEVENTTYPE enmEvent)
    491 {
    492     switch (enmEvent)
    493     {
    494         case DBGFEVENT_STEPPED_HYPER:
    495         case DBGFEVENT_ASSERTION_HYPER:
    496         case DBGFEVENT_BREAKPOINT_HYPER:
    497             pVM->dbgf.s.fStoppedInHyper = true;
    498             break;
    499         default:
    500             pVM->dbgf.s.fStoppedInHyper = false;
    501             break;
    502     }
    503 }
    504 
    505 
    506 /**
    507388 * Try to determine the event context.
    508389 *
    509390 * @returns debug event context.
    510  * @param   pVM         The cross context VM structure.
    511  */
    512 static DBGFEVENTCTX dbgfR3FigureEventCtx(PVM pVM)
    513 {
    514     /** @todo SMP support! */
    515     PVMCPU pVCpu = pVM->apCpusR3[0];
    516 
     391 * @param   pVCpu       The cross context vCPU structure.
     392 */
     393static DBGFEVENTCTX dbgfR3FigureEventCtx(PVMCPU pVCpu)
     394{
    517395    switch (EMGetState(pVCpu))
    518396    {
     397        case EMSTATE_HM:
     398        case EMSTATE_NEM:
     399        case EMSTATE_DEBUG_GUEST_HM:
     400        case EMSTATE_DEBUG_GUEST_NEM:
     401            return DBGFEVENTCTX_HM;
     402
     403        case EMSTATE_IEM:
    519404        case EMSTATE_RAW:
     405        case EMSTATE_IEM_THEN_REM:
     406        case EMSTATE_DEBUG_GUEST_IEM:
    520407        case EMSTATE_DEBUG_GUEST_RAW:
    521408            return DBGFEVENTCTX_RAW;
     409
    522410
    523411        case EMSTATE_REM:
     
    534422}
    535423
     424
     425/**
     426 * Sends the event to the debugger (i.e. adds it to the event ring buffer).
     427 *
     428 * @returns VBox status code.
     429 * @param   pVM         The cross context VM structure.
     430 * @param   pVCpu       The CPU sending the event.
     431 * @param   enmType     The event type to send.
     432 * @param   enmCtx      The event context, DBGFEVENTCTX_INVALID will be resolved.
     433 * @param   pvPayload   Event payload (DBGFEVENT::u data), optional.
     434 * @param   cbPayload   The size of the event payload, optional.
     435 */
     436static int dbgfR3SendEventWorker(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx,
     437                                 void const *pvPayload, size_t cbPayload)
     438{
     439    PUVM pUVM = pVM->pUVM;
     440    pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID; /** @todo per vCPU stepping filter. */
     441
     442    /*
     443     * Massage the input a little.
     444     */
     445    AssertStmt(cbPayload <= RT_SIZEOFMEMB(DBGFEVENT, u), cbPayload = RT_SIZEOFMEMB(DBGFEVENT, u));
     446    if (enmCtx == DBGFEVENTCTX_INVALID)
     447        enmCtx = dbgfR3FigureEventCtx(pVCpu);
     448
     449    /*
     450     * Put the event into the ring buffer.
     451     */
     452    RTSemFastMutexRequest(pUVM->dbgf.s.hMtxDbgEvtWr);
     453
     454    uint32_t const cDbgEvtMax     = RT_MAX(1, pUVM->dbgf.s.cDbgEvtMax);
     455    uint32_t const idxDbgEvtWrite = ASMAtomicReadU32(&pUVM->dbgf.s.idxDbgEvtWrite);
     456    uint32_t const idxDbgEvtRead  = ASMAtomicReadU32(&pUVM->dbgf.s.idxDbgEvtRead);
     457    /** @todo Handle full buffer. */ RT_NOREF(idxDbgEvtRead);
     458
     459    PDBGFEVENT pEvent = &pUVM->dbgf.s.paDbgEvts[idxDbgEvtWrite % cDbgEvtMax];
     460
     461#ifdef DEBUG
     462    ASMMemFill32(pEvent, sizeof(*pEvent), UINT32_C(0xdeadbeef));
     463#endif
     464    pEvent->enmType   = enmType;
     465    pEvent->enmCtx    = enmCtx;
     466    pEvent->idCpu     = pVCpu->idCpu;
     467    pEvent->uReserved = 0;
     468    if (cbPayload)
     469        memcpy(&pEvent->u, pvPayload, cbPayload);
     470
     471    ASMAtomicWriteU32(&pUVM->dbgf.s.idxDbgEvtWrite, (idxDbgEvtWrite + 1) % cDbgEvtMax);
     472
     473    RTSemFastMutexRelease(pUVM->dbgf.s.hMtxDbgEvtWr);
     474
     475    /*
     476     * Signal the debugger.
     477     */
     478    return RTSemEventSignal(pUVM->dbgf.s.hEvtWait);
     479}
     480
     481
     482/**
     483 * Send event and wait for the debugger to respond.
     484 *
     485 * @returns Strict VBox status code.
     486 * @param   pVM         The cross context VM structure.
     487 * @param   pVCpu       The CPU sending the event.
     488 * @param   enmType     The event type to send.
     489 * @param   enmCtx      The event context, DBGFEVENTCTX_INVALID will be resolved.
     490 */
     491DECLINLINE(int) dbgfR3SendEventWait(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx)
     492{
     493    int rc = dbgfR3SendEventWorker(pVM, pVCpu, enmType, enmCtx, NULL, 0);
     494    if (RT_SUCCESS(rc))
     495        rc = dbgfR3CpuWait(pVCpu);
     496    return rc;
     497}
     498
     499
     500/**
     501 * Send event and wait for the debugger to respond, extended version.
     502 *
     503 * @returns Strict VBox status code.
     504 * @param   pVM         The cross context VM structure.
     505 * @param   pVCpu       The CPU sending the event.
     506 * @param   enmType     The event type to send.
     507 * @param   enmCtx      The event context, DBGFEVENTCTX_INVALID will be resolved.
     508 * @param   pvPayload   Event payload (DBGFEVENT::u data), optional.
     509 * @param   cbPayload   The size of the event payload, optional.
     510 */
     511DECLINLINE(int) dbgfR3SendEventWaitEx(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx,
     512                                      void const *pvPayload, size_t cbPayload)
     513{
     514    int rc = dbgfR3SendEventWorker(pVM, pVCpu, enmType, enmCtx, pvPayload, cbPayload);
     515    if (RT_SUCCESS(rc))
     516        rc = dbgfR3CpuWait(pVCpu);
     517    return rc;
     518}
     519
     520
     521/**
     522 * Send event but do NOT wait for the debugger.
     523 *
     524 * Currently only used by dbgfR3CpuCmd().
     525 *
     526 * @param   pVM         The cross context VM structure.
     527 * @param   pVCpu       The CPU sending the event.
     528 * @param   enmType     The event type to send.
     529 * @param   enmCtx      The event context, DBGFEVENTCTX_INVALID will be resolved.
     530 */
     531DECLINLINE(int) dbgfR3SendEventNoWait(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx)
     532{
     533    return dbgfR3SendEventWorker(pVM, pVCpu, enmType, enmCtx, NULL, 0);
     534}
     535
     536
    536537/**
    537538 * The common event prologue code.
    538  * It will set the 'stopped-in-hyper' flag, make sure someone is attached,
    539  * and perhaps process any high priority pending actions (none yet).
     539 *
     540 * It will make sure someone is attached, and perhaps process any high priority
     541 * pending actions (none yet).
    540542 *
    541543 * @returns VBox status code.
    542544 * @param   pVM         The cross context VM structure.
     545 * @param   pVCpu       The vCPU cross context structure.
    543546 * @param   enmEvent    The event to be sent.
    544547 */
    545 static int dbgfR3EventPrologue(PVM pVM, DBGFEVENTTYPE enmEvent)
    546 {
    547     /** @todo SMP */
    548     PVMCPU pVCpu = VMMGetCpu(pVM);
    549 
     548static int dbgfR3EventPrologue(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent)
     549{
    550550    /*
    551551     * Check if a debugger is attached.
     
    554554        &&  !dbgfR3WaitForAttach(pVM, pVCpu, enmEvent))
    555555    {
    556         Log(("DBGFR3VMMEventSrc: enmEvent=%d - debugger not attached\n", enmEvent));
     556        Log(("dbgfR3EventPrologue: enmEvent=%d - debugger not attached\n", enmEvent));
    557557        return VERR_DBGF_NOT_ATTACHED;
    558558    }
    559 
    560     /*
    561      * Set flag.
    562      */
    563     dbgfR3EventSetStoppedInHyperFlag(pVM, enmEvent);
    564559
    565560    /*
     
    573568
    574569/**
    575  * Sends the event in the event buffer.
    576  *
    577  * @returns VBox status code.
    578  * @param   pVM     The cross context VM structure.
    579  */
    580 static int dbgfR3SendEvent(PVM pVM)
    581 {
    582     pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
    583 
    584     int rc = RTSemPing(&pVM->dbgf.s.PingPong);
    585     if (RT_SUCCESS(rc))
    586         rc = dbgfR3VMMWait(pVM);
    587 
    588     pVM->dbgf.s.fStoppedInHyper = false;
    589     /** @todo sync VMM -> REM after exitting the debugger. everything may change while in the debugger! */
    590     return rc;
    591 }
    592 
    593 
    594 /**
    595570 * Processes a pending event on the current CPU.
    596571 *
     
    618593     * Make sure we've got a debugger and is allowed to speak to it.
    619594     */
    620     int rc = dbgfR3EventPrologue(pVM, pEvent->enmType);
     595    int rc = dbgfR3EventPrologue(pVM, pVCpu, pEvent->enmType);
    621596    if (RT_FAILURE(rc))
    622597    {
    623598        /** @todo drop them events?   */
    624         return rc;
    625     }
    626 
    627 /** @todo SMP + debugger speaker logic  */
    628     /*
    629      * Copy the event over and mark it as ignore.
    630      */
    631     pVM->dbgf.s.DbgEvent = *pEvent;
     599        return rc; /** @todo this will cause trouble if we're here via an FF! */
     600    }
     601
     602    /*
     603     * Send the event and mark it as ignore.
     604     * ASSUMES no new events get generate while dbgfR3CpuWait is executing!
     605     */
     606    VBOXSTRICTRC rcStrict = dbgfR3SendEventWaitEx(pVM, pVCpu, pEvent->enmType, pEvent->enmCtx, &pEvent->u, sizeof(pEvent->u));
    632607    pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].enmState = DBGFEVENTSTATE_IGNORE;
    633     return dbgfR3SendEvent(pVM);
     608    return rcStrict;
    634609}
    635610
     
    645620VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent)
    646621{
     622    PVMCPU pVCpu = VMMGetCpu(pVM);
     623    AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT);
     624
    647625    /*
    648626     * Do stepping filtering.
     
    653631        || enmEvent == DBGFEVENT_STEPPED_HYPER)
    654632    {
    655         if (!dbgfStepAreWeThereYet(pVM, VMMGetCpu(pVM)))
     633        if (!dbgfStepAreWeThereYet(pVM, pVCpu))
    656634            return VINF_EM_DBG_STEP;
    657635    }
    658636
    659     int rc = dbgfR3EventPrologue(pVM, enmEvent);
     637    int rc = dbgfR3EventPrologue(pVM, pVCpu, enmEvent);
    660638    if (RT_FAILURE(rc))
    661639        return rc;
     
    664642     * Send the event and process the reply communication.
    665643     */
    666     pVM->dbgf.s.DbgEvent.enmType = enmEvent;
    667     pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
    668     return dbgfR3SendEvent(pVM);
     644    return dbgfR3SendEventWait(pVM, pVCpu, enmEvent, DBGFEVENTCTX_INVALID);
    669645}
    670646
     
    708684VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args)
    709685{
    710     int rc = dbgfR3EventPrologue(pVM, enmEvent);
     686    PVMCPU pVCpu = VMMGetCpu(pVM);
     687    AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT);
     688
     689    int rc = dbgfR3EventPrologue(pVM, pVCpu, enmEvent);
    711690    if (RT_FAILURE(rc))
    712691        return rc;
     
    726705     * Send the event and process the reply communication.
    727706     */
    728     pVM->dbgf.s.DbgEvent.enmType = enmEvent;
    729     pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
    730     pVM->dbgf.s.DbgEvent.u.Src.pszFile      = pszFile;
    731     pVM->dbgf.s.DbgEvent.u.Src.uLine        = uLine;
    732     pVM->dbgf.s.DbgEvent.u.Src.pszFunction  = pszFunction;
    733     pVM->dbgf.s.DbgEvent.u.Src.pszMessage   = pszMessage;
    734     return dbgfR3SendEvent(pVM);
     707    DBGFEVENT DbgEvent;  /** @todo split up DBGFEVENT so we can skip the dead wait on the stack? */
     708    DbgEvent.u.Src.pszFile      = pszFile;
     709    DbgEvent.u.Src.uLine        = uLine;
     710    DbgEvent.u.Src.pszFunction  = pszFunction;
     711    DbgEvent.u.Src.pszMessage   = pszMessage;
     712    return dbgfR3SendEventWaitEx(pVM, pVCpu, enmEvent, DBGFEVENTCTX_INVALID, &DbgEvent.u, sizeof(DbgEvent.u.Src));
    735713}
    736714
     
    747725VMMR3_INT_DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2)
    748726{
    749     int rc = dbgfR3EventPrologue(pVM, enmEvent);
     727    PVMCPU pVCpu = VMMGetCpu(pVM);
     728    AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT);
     729
     730    int rc = dbgfR3EventPrologue(pVM, pVCpu, enmEvent);
    750731    if (RT_FAILURE(rc))
    751732        return rc;
     
    754735     * Send the event and process the reply communication.
    755736     */
    756     pVM->dbgf.s.DbgEvent.enmType = enmEvent;
    757     pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
    758     pVM->dbgf.s.DbgEvent.u.Assert.pszMsg1 = pszMsg1;
    759     pVM->dbgf.s.DbgEvent.u.Assert.pszMsg2 = pszMsg2;
    760     return dbgfR3SendEvent(pVM);
     737    DBGFEVENT DbgEvent;
     738    DbgEvent.u.Assert.pszMsg1 = pszMsg1;
     739    DbgEvent.u.Assert.pszMsg2 = pszMsg2;
     740    return dbgfR3SendEventWaitEx(pVM, pVCpu, enmEvent, DBGFEVENTCTX_INVALID, &DbgEvent.u, sizeof(DbgEvent.u.Assert));
    761741}
    762742
     
    772752VMMR3_INT_DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent)
    773753{
    774     int rc = dbgfR3EventPrologue(pVM, enmEvent);
     754    PVMCPU pVCpu = VMMGetCpu(pVM);
     755    AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT);
     756
     757    int rc = dbgfR3EventPrologue(pVM, pVCpu, enmEvent);
    775758    if (RT_FAILURE(rc))
    776759        return rc;
     
    779762     * Send the event and process the reply communication.
    780763     */
    781     /** @todo SMP */
    782     PVMCPU pVCpu = VMMGetCpu0(pVM);
    783 
    784     pVM->dbgf.s.DbgEvent.enmType = enmEvent;
    785     RTUINT iBp = pVM->dbgf.s.DbgEvent.u.Bp.iBp = pVCpu->dbgf.s.iActiveBp;
     764    DBGFEVENT DbgEvent;
     765    RTUINT iBp = DbgEvent.u.Bp.iBp = pVCpu->dbgf.s.iActiveBp;
    786766    pVCpu->dbgf.s.iActiveBp = ~0U;
    787767    if (iBp != ~0U)
    788         pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_RAW;
    789     else
    790     {
    791         /* REM breakpoints has be been searched for. */
     768    {
     769        DbgEvent.enmCtx = DBGFEVENTCTX_RAW;
     770        return dbgfR3SendEventWaitEx(pVM, pVCpu, enmEvent, DBGFEVENTCTX_RAW, &DbgEvent.u, sizeof(DbgEvent.u.Bp));
     771    }
     772
     773    AssertFailed(); /** @todo this should be obsolete now...   */
     774
     775    /* REM breakpoints has be been searched for. */
    792776#if 0   /** @todo get flat PC api! */
    793         uint32_t eip = CPUMGetGuestEIP(pVM);
     777    uint32_t eip = CPUMGetGuestEIP(pVM);
    794778#else
    795         /** @todo SMP support!! */
    796         PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu(pVM));
    797         RTGCPTR  eip = pCtx->rip + pCtx->cs.u64Base;
     779    PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
     780    RTGCPTR  eip = pCtx->rip + pCtx->cs.u64Base;
    798781#endif
    799         for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
    800             if (    pVM->dbgf.s.aBreakpoints[i].enmType == DBGFBPTYPE_REM
    801                 &&  pVM->dbgf.s.aBreakpoints[i].u.Rem.GCPtr == eip)
    802             {
    803                 pVM->dbgf.s.DbgEvent.u.Bp.iBp = pVM->dbgf.s.aBreakpoints[i].iBp;
    804                 break;
    805             }
    806         AssertMsg(pVM->dbgf.s.DbgEvent.u.Bp.iBp != ~0U, ("eip=%08x\n", eip));
    807         pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_REM;
    808     }
    809     return dbgfR3SendEvent(pVM);
     782    for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
     783        if (    pVM->dbgf.s.aBreakpoints[i].enmType == DBGFBPTYPE_REM
     784            &&  pVM->dbgf.s.aBreakpoints[i].u.Rem.GCPtr == eip)
     785        {
     786            DbgEvent.u.Bp.iBp = pVM->dbgf.s.aBreakpoints[i].iBp;
     787            break;
     788        }
     789    AssertMsg(DbgEvent.u.Bp.iBp != ~0U, ("eip=%08x\n", eip));
     790    return dbgfR3SendEventWaitEx(pVM, pVCpu, enmEvent, DBGFEVENTCTX_REM, &DbgEvent.u, sizeof(DbgEvent.u.Bp));
     791}
     792
     793
     794/**
     795 * Returns whether the given vCPU is waiting for the debugger.
     796 *
     797 * @returns Flags whether the vCPU is currently waiting for the debugger.
     798 * @param   pUVCpu              The user mode vCPU structure.
     799 */
     800DECLINLINE(bool) dbgfR3CpuIsHalted(PUVMCPU pUVCpu)
     801{
     802    return ASMAtomicReadBool(&pUVCpu->dbgf.s.fStopped);
     803}
     804
     805
     806/**
     807 * Checks whether the given vCPU is waiting in the debugger.
     808 *
     809 * @returns Flag whether the indicated vCPU is halted, when VMCPUID_ALL
     810 *          is given true is returned when at least one vCPU is halted.
     811 * @param   pUVM        The user mode VM structure.
     812 * @param   idCpu       The CPU ID to check, VMCPUID_ALL to check all vCPUs.
     813 */
     814DECLINLINE(bool) dbgfR3CpuAreAnyHaltedByCpuId(PUVM pUVM, VMCPUID idCpu)
     815{
     816    AssertReturn(idCpu < pUVM->cCpus || idCpu == VMCPUID_ALL, false);
     817
     818    /* Check that either the given vCPU or all are actually halted. */
     819    if (idCpu != VMCPUID_ALL)
     820        return dbgfR3CpuIsHalted(&pUVM->aCpus[idCpu]);
     821
     822    for (VMCPUID i = 0; i < pUVM->cCpus; i++)
     823        if (dbgfR3CpuIsHalted(&pUVM->aCpus[i]))
     824            return true;
     825    return false;
     826}
     827
     828
     829/**
     830 * Gets the pending debug command for this EMT/CPU, replacing it with
     831 * DBGFCMD_NO_COMMAND.
     832 *
     833 * @returns Pending command.
     834 * @param   pUVCpu          The user mode virtual CPU structure.
     835 * @thread  EMT(pUVCpu)
     836 */
     837DECLINLINE(DBGFCMD) dbgfR3CpuGetCmd(PUVMCPU pUVCpu)
     838{
     839    DBGFCMD enmCmd = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pUVCpu->dbgf.s.enmDbgfCmd, DBGFCMD_NO_COMMAND);
     840    Log2(("DBGF: Getting command: %d\n", enmCmd));
     841    return enmCmd;
     842}
     843
     844
     845/**
     846 * Send a debug command to a CPU, making sure to notify it.
     847 *
     848 * @returns VBox status code.
     849 * @param   pUVCpu      The user mode virtual CPU structure.
     850 * @param   enmCmd      The command to submit to the CPU.
     851 */
     852DECLINLINE(int) dbgfR3CpuSetCmdAndNotify(PUVMCPU pUVCpu, DBGFCMD enmCmd)
     853{
     854    Log2(("DBGF: Setting command to %d\n", enmCmd));
     855    Assert(enmCmd != DBGFCMD_NO_COMMAND);
     856    AssertMsg(pUVCpu->dbgf.s.enmDbgfCmd == DBGFCMD_NO_COMMAND, ("enmCmd=%d enmDbgfCmd=%d\n", enmCmd, pUVCpu->dbgf.s.enmDbgfCmd));
     857
     858    ASMAtomicWriteU32((uint32_t volatile *)(void *)&pUVCpu->dbgf.s.enmDbgfCmd, enmCmd);
     859    VMCPU_FF_SET(pUVCpu->pVCpu, VMCPU_FF_DBGF);
     860
     861    VMR3NotifyCpuFFU(pUVCpu, 0 /*fFlags*/);
     862    return VINF_SUCCESS;
    810863}
    811864
     
    815868 *
    816869 * @returns VBox status code. (clearify)
    817  * @param   pVM     The cross context VM structure.
    818  */
    819 static int dbgfR3VMMWait(PVM pVM)
    820 {
    821     PVMCPU pVCpu = VMMGetCpu(pVM);
    822 
    823     LogFlow(("dbgfR3VMMWait:\n"));
     870 * @param   pVCpu               The cross context vCPU structure.
     871 */
     872static int dbgfR3CpuWait(PVMCPU pVCpu)
     873{
     874    PVM pVM = pVCpu->CTX_SUFF(pVM);
     875    PUVMCPU pUVCpu = pVCpu->pUVCpu;
     876
     877    LogFlow(("dbgfR3CpuWait:\n"));
    824878    int rcRet = VINF_SUCCESS;
     879
     880    ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, true);
    825881
    826882    /*
     
    832888         * Wait.
    833889         */
    834         uint32_t cPollHack = 1; /** @todo this interface is horrible now that we're using lots of VMR3ReqCall stuff all over DBGF. */
    835890        for (;;)
    836891        {
    837             int rc;
    838             if (    !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_REQUEST)
    839                 &&  !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
     892            /*
     893             * Process forced flags before we go sleep.
     894             */
     895            if (   VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_DBGF | VMCPU_FF_REQUEST)
     896                || VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VMCPU_FF_REQUEST | VM_FF_CHECK_VM_STATE))
    840897            {
    841                 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack);
    842                 if (RT_SUCCESS(rc))
     898                if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_DBGF))
    843899                    break;
    844                 if (rc != VERR_TIMEOUT)
     900
     901                int rc;
     902                if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
     903                    rc = VMMR3EmtRendezvousFF(pVM, pVCpu);
     904                else if (   VM_FF_IS_SET(pVM, VM_FF_REQUEST)
     905                         || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
    845906                {
    846                     LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
     907                    LogFlow(("dbgfR3CpuWait: Processes requests...\n"));
     908                    rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, false /*fPriorityOnly*/);
     909                    if (rc == VINF_SUCCESS)
     910                        rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, false /*fPriorityOnly*/);
     911                    LogFlow(("dbgfR3CpuWait: VMR3ReqProcess -> %Rrc rcRet=%Rrc\n", rc, rcRet));
     912                }
     913                else if (VM_FF_IS_SET(pVM, VM_FF_CHECK_VM_STATE))
     914                {
     915                    VMSTATE enmState = VMR3GetState(pVM);
     916                    switch (enmState)
     917                    {
     918                        case VMSTATE_FATAL_ERROR:
     919                        case VMSTATE_FATAL_ERROR_LS:
     920                        case VMSTATE_GURU_MEDITATION:
     921                        case VMSTATE_GURU_MEDITATION_LS:
     922                            rc = VINF_EM_SUSPEND;
     923                            break;
     924                        case VMSTATE_DESTROYING:
     925                            rc = VINF_EM_TERMINATE;
     926                            break;
     927                        default:
     928                            AssertMsgFailed(("%s\n", VMGetStateName(enmState)));
     929                    }
     930                }
     931                else
     932                    rc = VINF_SUCCESS;
     933                if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
     934                {
     935                    switch (rc)
     936                    {
     937                        case VINF_EM_DBG_BREAKPOINT:
     938                        case VINF_EM_DBG_STEPPED:
     939                        case VINF_EM_DBG_STEP:
     940                        case VINF_EM_DBG_STOP:
     941                        case VINF_EM_DBG_EVENT:
     942                            AssertMsgFailed(("rc=%Rrc\n", rc));
     943                            break;
     944
     945                        /* return straight away */
     946                        case VINF_EM_TERMINATE:
     947                        case VINF_EM_OFF:
     948                            LogFlow(("dbgfR3CpuWait: returns %Rrc\n", rc));
     949                            ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, false);
     950                            return rc;
     951
     952                        /* remember return code. */
     953                        default:
     954                            AssertReleaseMsgFailed(("rc=%Rrc is not in the switch!\n", rc));
     955                            RT_FALL_THRU();
     956                        case VINF_EM_RESET:
     957                        case VINF_EM_SUSPEND:
     958                        case VINF_EM_HALT:
     959                        case VINF_EM_RESUME:
     960                        case VINF_EM_RESCHEDULE:
     961                        case VINF_EM_RESCHEDULE_REM:
     962                        case VINF_EM_RESCHEDULE_RAW:
     963                            if (rc < rcRet || rcRet == VINF_SUCCESS)
     964                                rcRet = rc;
     965                            break;
     966                    }
     967                }
     968                else if (RT_FAILURE(rc))
     969                {
     970                    LogFlow(("dbgfR3CpuWait: returns %Rrc\n", rc));
     971                    ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, false);
    847972                    return rc;
    848973                }
    849974            }
    850 
    851             if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
     975            else if (pVM->dbgf.s.fAttached)
    852976            {
    853                 rc = VMMR3EmtRendezvousFF(pVM, pVCpu);
    854                 cPollHack = 1;
    855             }
    856             else if (   VM_FF_IS_SET(pVM, VM_FF_REQUEST)
    857                      || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
    858             {
    859                 LogFlow(("dbgfR3VMMWait: Processes requests...\n"));
    860                 rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, false /*fPriorityOnly*/);
    861                 if (rc == VINF_SUCCESS)
    862                     rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, false /*fPriorityOnly*/);
    863                 LogFlow(("dbgfR3VMMWait: VMR3ReqProcess -> %Rrc rcRet=%Rrc\n", rc, rcRet));
    864                 cPollHack = 1;
     977                int rc = VMR3WaitU(pUVCpu);
     978                if (RT_FAILURE(rc))
     979                {
     980                    LogFlow(("dbgfR3CpuWait: returns %Rrc (VMR3WaitU)\n", rc));
     981                    ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, false);
     982                    return rc;
     983                }
    865984            }
    866985            else
    867986            {
    868                 rc = VINF_SUCCESS;
    869                 if (cPollHack < 120)
    870                     cPollHack++;
    871             }
    872 
    873             if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
    874             {
    875                 switch (rc)
    876                 {
    877                     case VINF_EM_DBG_BREAKPOINT:
    878                     case VINF_EM_DBG_STEPPED:
    879                     case VINF_EM_DBG_STEP:
    880                     case VINF_EM_DBG_STOP:
    881                     case VINF_EM_DBG_EVENT:
    882                         AssertMsgFailed(("rc=%Rrc\n", rc));
    883                         break;
    884 
    885                     /* return straight away */
    886                     case VINF_EM_TERMINATE:
    887                     case VINF_EM_OFF:
    888                         LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
    889                         return rc;
    890 
    891                     /* remember return code. */
    892                     default:
    893                         AssertReleaseMsgFailed(("rc=%Rrc is not in the switch!\n", rc));
    894                         RT_FALL_THRU();
    895                     case VINF_EM_RESET:
    896                     case VINF_EM_SUSPEND:
    897                     case VINF_EM_HALT:
    898                     case VINF_EM_RESUME:
    899                     case VINF_EM_RESCHEDULE:
    900                     case VINF_EM_RESCHEDULE_REM:
    901                     case VINF_EM_RESCHEDULE_RAW:
    902                         if (rc < rcRet || rcRet == VINF_SUCCESS)
    903                             rcRet = rc;
    904                         break;
    905                 }
    906             }
    907             else if (RT_FAILURE(rc))
    908             {
    909                 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
    910                 return rc;
     987                LogFlow(("dbgfR3CpuWait: Debugger detached, continuing normal execution (%Rrc)\n", rcRet));
     988                ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, false);
     989                return rcRet;
    911990            }
    912991        }
     
    915994         * Process the command.
    916995         */
     996        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_DBGF);
    917997        bool            fResumeExecution;
    918         DBGFCMDDATA     CmdData = pVM->dbgf.s.VMMCmdData;
    919         DBGFCMD         enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
    920         int rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
     998        DBGFCMDDATA     CmdData = pUVCpu->dbgf.s.DbgfCmdData;
     999        DBGFCMD         enmCmd = dbgfR3CpuGetCmd(pUVCpu);
     1000        int rc = dbgfR3CpuCmd(pVCpu, enmCmd, &CmdData, &fResumeExecution);
    9211001        if (fResumeExecution)
    9221002        {
     
    9271007                     &&  (rc < rcRet || rcRet == VINF_SUCCESS))
    9281008                rcRet = rc;
    929             LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rcRet));
     1009            LogFlow(("dbgfR3CpuWait: returns %Rrc\n", rcRet));
     1010            ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, false);
    9301011            return rcRet;
    9311012        }
     
    9411022 *
    9421023 * @returns VBox status code. (clearify!)
    943  * @param   pVM                 The cross context VM structure.
     1024 * @param   pVCpu               The cross context vCPU structure.
    9441025 * @param   enmCmd              The command in question.
    9451026 * @param   pCmdData            Pointer to the command data.
    9461027 * @param   pfResumeExecution   Where to store the resume execution / continue waiting indicator.
    9471028 */
    948 static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution)
    949 {
    950     bool    fSendEvent;
    951     bool    fResume;
    952     int     rc = VINF_SUCCESS;
    953 
    954     NOREF(pCmdData); /* for later */
    955 
     1029static int dbgfR3CpuCmd(PVMCPU pVCpu, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution)
     1030{
     1031    RT_NOREF(pCmdData); /* for later */
     1032
     1033    /*
     1034     * The cases in this switch returns directly if no event to send.
     1035     */
     1036    DBGFEVENTTYPE enmEvent;
     1037    DBGFEVENTCTX  enmCtx = DBGFEVENTCTX_INVALID;
    9561038    switch (enmCmd)
    9571039    {
     
    9611043        case DBGFCMD_HALT:
    9621044        {
    963             pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_HALT_DONE;
    964             pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
    965             fSendEvent = true;
    966             fResume = false;
     1045            *pfResumeExecution = false;
     1046            enmEvent = DBGFEVENT_HALT_DONE;
    9671047            break;
    9681048        }
     
    9701050
    9711051        /*
    972          * Resume is not answered we'll just resume execution.
     1052         * Resume is not answered, we just resume execution.
    9731053         */
    9741054        case DBGFCMD_GO:
    9751055        {
    976             /** @todo SMP */
    977             PVMCPU pVCpu = VMMGetCpu0(pVM);
    9781056            pVCpu->dbgf.s.fSingleSteppingRaw = false;
    979             fSendEvent = false;
    980             fResume = true;
    981             break;
     1057            *pfResumeExecution = true;
     1058            return VINF_SUCCESS;
    9821059        }
    9831060
    9841061        /** @todo implement (and define) the rest of the commands. */
    985 
    986         /*
    987          * Disable breakpoints and stuff.
    988          * Send an everythings cool event to the debugger thread and resume execution.
    989          */
    990         case DBGFCMD_DETACH_DEBUGGER:
    991         {
    992             ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, false);
    993             pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_DETACH_DONE;
    994             pVM->dbgf.s.DbgEvent.enmCtx  = DBGFEVENTCTX_OTHER;
    995             pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
    996             fSendEvent = true;
    997             fResume = true;
    998             break;
    999         }
    1000 
    1001         /*
    1002          * The debugger has detached successfully.
    1003          * There is no reply to this event.
    1004          */
    1005         case DBGFCMD_DETACHED_DEBUGGER:
    1006         {
    1007             fSendEvent = false;
    1008             fResume = true;
    1009             break;
    1010         }
    10111062
    10121063        /*
     
    10161067        {
    10171068            Log2(("Single step\n"));
    1018             /** @todo SMP */
    1019             PVMCPU pVCpu = VMMGetCpu0(pVM);
     1069            PVM pVM = pVCpu->CTX_SUFF(pVM);
    10201070            if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_OVER)
    10211071            {
     
    10261076            {
    10271077                pVCpu->dbgf.s.fSingleSteppingRaw = true;
    1028                 fSendEvent = false;
    1029                 fResume = true;
    1030                 rc = VINF_EM_DBG_STEP;
     1078                *pfResumeExecution = true;
     1079                return VINF_EM_DBG_STEP;
    10311080            }
    1032             else
    1033             {
    1034                 /* Stop after zero steps. Nonsense, but whatever. */
    1035                 pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
    1036                 pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
    1037                 pVM->dbgf.s.DbgEvent.enmType = pVM->dbgf.s.DbgEvent.enmCtx != DBGFEVENTCTX_HYPER
    1038                                              ? DBGFEVENT_STEPPED : DBGFEVENT_STEPPED_HYPER;
    1039                 fSendEvent = false;
    1040                 fResume = false;
    1041             }
     1081            /* Stop after zero steps. Nonsense, but whatever. */
     1082            pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
     1083            *pfResumeExecution = false;
     1084            enmCtx   = dbgfR3FigureEventCtx(pVCpu);
     1085            enmEvent = enmCtx != DBGFEVENTCTX_HYPER ? DBGFEVENT_STEPPED : DBGFEVENT_STEPPED_HYPER;
    10421086            break;
    10431087        }
     
    10481092        default:
    10491093        {
    1050             pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_INVALID_COMMAND;
    1051             pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
    1052             fSendEvent = true;
    1053             fResume = false;
     1094            *pfResumeExecution = false;
     1095            enmEvent = DBGFEVENT_INVALID_COMMAND;
    10541096            break;
    10551097        }
     
    10571099
    10581100    /*
    1059      * Send pending event.
    1060      */
    1061     if (fSendEvent)
    1062     {
    1063         Log2(("DBGF: Emulation thread: sending event %d\n", pVM->dbgf.s.DbgEvent.enmType));
    1064         int rc2 = RTSemPing(&pVM->dbgf.s.PingPong);
    1065         if (RT_FAILURE(rc2))
    1066         {
    1067             AssertRC(rc2);
    1068             *pfResumeExecution = true;
    1069             return rc2;
    1070         }
    1071     }
    1072 
    1073     /*
    1074      * Return.
    1075      */
    1076     *pfResumeExecution = fResume;
     1101     * Send the pending event.
     1102     */
     1103    Log2(("DBGF: Emulation thread: sending event %d\n", enmEvent));
     1104    int rc = dbgfR3SendEventNoWait(pVCpu->CTX_SUFF(pVM), pVCpu, enmEvent, enmCtx);
     1105    AssertRCStmt(rc, *pfResumeExecution = true);
    10771106    return rc;
     1107}
     1108
     1109
     1110/**
     1111 * @callback_method_impl{FNVMMEMTRENDEZVOUS,
     1112 * EMT rendezvous worker for DBGFR3Attach - only called on one EMT.}
     1113 */
     1114static DECLCALLBACK(VBOXSTRICTRC) dbgfR3Attach(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1115{
     1116    PUVM pUVM = pVM->pUVM;
     1117    int *prcAttach = (int *)pvUser;
     1118    RT_NOREF(pVCpu);
     1119
     1120    if (pVM->dbgf.s.fAttached)
     1121    {
     1122        Log(("dbgfR3Attach: Debugger already attached\n"));
     1123        *prcAttach = VERR_DBGF_ALREADY_ATTACHED;
     1124        return VINF_SUCCESS;
     1125    }
     1126
     1127    /*
     1128     * The per-CPU bits.
     1129     */
     1130    for (uint32_t i = 0; i < pUVM->cCpus; i++)
     1131    {
     1132        PUVMCPU pUVCpu = &pUVM->aCpus[i];
     1133
     1134        pUVCpu->dbgf.s.enmDbgfCmd = DBGFCMD_NO_COMMAND;
     1135        RT_ZERO(pUVCpu->dbgf.s.DbgfCmdData);
     1136    }
     1137
     1138    /*
     1139     * Init of the VM -> Debugger communication part living in the global VM structure.
     1140     */
     1141    pUVM->dbgf.s.cDbgEvtMax      = pVM->cCpus * 5 + 10; /* Initial size of event ring, increased when being full. */
     1142    pUVM->dbgf.s.idxDbgEvtWrite  = 0;
     1143    pUVM->dbgf.s.idxDbgEvtRead   = 0;
     1144    pUVM->dbgf.s.hEvtWait        = NIL_RTSEMEVENT;
     1145    pUVM->dbgf.s.hEvtRingBufFull = NIL_RTSEMEVENTMULTI;
     1146    pUVM->dbgf.s.hMtxDbgEvtWr    = NIL_RTSEMFASTMUTEX;
     1147    int rc;
     1148    pUVM->dbgf.s.paDbgEvts       = (PDBGFEVENT)MMR3HeapAllocU(pUVM, MM_TAG_DBGF, pUVM->dbgf.s.cDbgEvtMax * sizeof(DBGFEVENT));
     1149    if (pUVM->dbgf.s.paDbgEvts)
     1150    {
     1151        rc = RTSemEventCreate(&pUVM->dbgf.s.hEvtWait);
     1152        if (RT_SUCCESS(rc))
     1153        {
     1154            rc = RTSemFastMutexCreate(&pUVM->dbgf.s.hMtxDbgEvtWr);
     1155            if (RT_SUCCESS(rc))
     1156            {
     1157                rc = RTSemEventMultiCreate(&pUVM->dbgf.s.hEvtRingBufFull);
     1158                if (RT_SUCCESS(rc))
     1159                {
     1160                    /*
     1161                     * At last, set the attached flag.
     1162                     */
     1163                    ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, true);
     1164                    *prcAttach = VINF_SUCCESS;
     1165                    return VINF_SUCCESS;
     1166                }
     1167
     1168                RTSemFastMutexDestroy(pUVM->dbgf.s.hMtxDbgEvtWr);
     1169                pUVM->dbgf.s.hMtxDbgEvtWr = NIL_RTSEMFASTMUTEX;
     1170            }
     1171            RTSemEventDestroy(pUVM->dbgf.s.hEvtWait);
     1172            pUVM->dbgf.s.hEvtWait = NIL_RTSEMEVENT;
     1173        }
     1174    }
     1175    else
     1176        rc = VERR_NO_MEMORY;
     1177
     1178    *prcAttach = rc;
     1179    return VINF_SUCCESS;
    10781180}
    10791181
     
    10941196
    10951197    /*
    1096      * Call the VM, use EMT for serialization.
    1097      *
    1098      * Using a priority call here so we can actually attach a debugger during
    1099      * the countdown in dbgfR3WaitForAttach.
    1100      */
    1101     /** @todo SMP */
    1102     return VMR3ReqPriorityCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3Attach, 1, pVM);
    1103 }
    1104 
    1105 
    1106 /**
    1107  * EMT worker for DBGFR3Attach.
    1108  *
    1109  * @returns VBox status code.
    1110  * @param   pVM     The cross context VM structure.
    1111  */
    1112 static DECLCALLBACK(int) dbgfR3Attach(PVM pVM)
    1113 {
    1114     if (pVM->dbgf.s.fAttached)
    1115     {
    1116         Log(("dbgR3Attach: Debugger already attached\n"));
    1117         return VERR_DBGF_ALREADY_ATTACHED;
    1118     }
    1119 
    1120     /*
    1121      * Create the Ping-Pong structure.
    1122      */
    1123     int rc = RTSemPingPongInit(&pVM->dbgf.s.PingPong);
    1124     AssertRCReturn(rc, rc);
    1125 
    1126     /*
    1127      * Set the attached flag.
    1128      */
    1129     ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, true);
     1198     * Call the VM, use EMT rendezvous for serialization.
     1199     */
     1200    int rcAttach = VERR_IPE_UNINITIALIZED_STATUS;
     1201    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE | VMMEMTRENDEZVOUS_FLAGS_PRIORITY, dbgfR3Attach, &rcAttach);
     1202    if (RT_SUCCESS(rc))
     1203        rc = rcAttach;
     1204
     1205    return rc;
     1206}
     1207
     1208
     1209/**
     1210 * @callback_method_impl{FNVMMEMTRENDEZVOUS,
     1211 * EMT rendezvous worker for DBGFR3Detach - called on all EMTs (why?).}
     1212 */
     1213static DECLCALLBACK(VBOXSTRICTRC) dbgfR3Detach(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1214{
     1215    if (pVCpu->idCpu == 0)
     1216    {
     1217        PUVM pUVM = (PUVM)pvUser;
     1218
     1219        /*
     1220         * Per-CPU cleanup.
     1221         */
     1222        for (VMCPUID i = 0; i < pUVM->cCpus; i++)
     1223        {
     1224            PUVMCPU pUVCpu = &pUVM->aCpus[i];
     1225
     1226            pUVCpu->dbgf.s.enmDbgfCmd = DBGFCMD_NO_COMMAND;
     1227            RT_ZERO(pUVCpu->dbgf.s.DbgfCmdData);
     1228        }
     1229
     1230        /*
     1231         * De-init of the VM -> Debugger communication part living in the global VM structure.
     1232         */
     1233        if (pUVM->dbgf.s.paDbgEvts)
     1234        {
     1235            MMR3HeapFree(pUVM->dbgf.s.paDbgEvts);
     1236            pUVM->dbgf.s.paDbgEvts = NULL;
     1237        }
     1238
     1239        if (pUVM->dbgf.s.hEvtWait != NIL_RTSEMEVENT)
     1240        {
     1241            RTSemEventDestroy(pUVM->dbgf.s.hEvtWait);
     1242            pUVM->dbgf.s.hEvtWait = NIL_RTSEMEVENT;
     1243        }
     1244
     1245        if (pUVM->dbgf.s.hMtxDbgEvtWr != NIL_RTSEMFASTMUTEX)
     1246        {
     1247            RTSemFastMutexDestroy(pUVM->dbgf.s.hMtxDbgEvtWr);
     1248            pUVM->dbgf.s.hMtxDbgEvtWr = NIL_RTSEMFASTMUTEX;
     1249        }
     1250
     1251        if (pUVM->dbgf.s.hEvtRingBufFull != NIL_RTSEMEVENTMULTI)
     1252        {
     1253            RTSemEventMultiDestroy(pUVM->dbgf.s.hEvtRingBufFull);
     1254            pUVM->dbgf.s.hEvtRingBufFull = NIL_RTSEMEVENTMULTI;
     1255        }
     1256
     1257        pUVM->dbgf.s.cDbgEvtMax      = 0;
     1258        pUVM->dbgf.s.idxDbgEvtWrite  = 0;
     1259        pUVM->dbgf.s.idxDbgEvtRead   = 0;
     1260        pUVM->dbgf.s.hEvtWait        = NIL_RTSEMEVENT;
     1261        pUVM->dbgf.s.hEvtRingBufFull = NIL_RTSEMEVENTMULTI;
     1262        pUVM->dbgf.s.hMtxDbgEvtWr    = NIL_RTSEMFASTMUTEX;
     1263
     1264        ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, false);
     1265    }
     1266
    11301267    return VINF_SUCCESS;
    11311268}
     
    11431280{
    11441281    LogFlow(("DBGFR3Detach:\n"));
    1145     int rc;
    11461282
    11471283    /*
     
    11601296        return VERR_DBGF_NOT_ATTACHED;
    11611297
    1162     /*
    1163      * Try send the detach command.
    1164      * Keep in mind that we might be racing EMT, so, be extra careful.
    1165      */
    1166     DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACH_DEBUGGER);
    1167     if (RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong))
    1168     {
    1169         rc = RTSemPong(&pVM->dbgf.s.PingPong);
    1170         AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
    1171         LogRel(("DBGFR3Detach: enmCmd=%d (pong -> ping)\n", enmCmd));
    1172     }
    1173 
    1174     /*
    1175      * Wait for the OK event.
    1176      */
    1177     rc = RTSemPongWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
    1178     AssertLogRelMsgRCReturn(rc, ("Wait on detach command failed, rc=%Rrc\n", rc), rc);
    1179 
    1180     /*
    1181      * Send the notification command indicating that we're really done.
    1182      */
    1183     enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACHED_DEBUGGER);
    1184     rc = RTSemPong(&pVM->dbgf.s.PingPong);
    1185     AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
    1186 
    1187     LogFlowFunc(("returns VINF_SUCCESS\n"));
    1188     return VINF_SUCCESS;
     1298    return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE | VMMEMTRENDEZVOUS_FLAGS_PRIORITY, dbgfR3Detach, pUVM);
    11891299}
    11901300
     
    11961306 * @param   pUVM        The user mode VM handle.
    11971307 * @param   cMillies    Number of millis to wait.
    1198  * @param   ppEvent     Where to store the event pointer.
    1199  */
    1200 VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent)
     1308 * @param   pEvent      Where to store the event data.
     1309 */
     1310VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PDBGFEVENT pEvent)
    12011311{
    12021312    /*
     
    12071317    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    12081318    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    1209     *ppEvent = NULL;
    1210 
    1211     /*
    1212      * Wait.
    1213      */
    1214     int rc = RTSemPongWait(&pVM->dbgf.s.PingPong, cMillies);
     1319
     1320    RT_BZERO(pEvent, sizeof(*pEvent));
     1321
     1322    /*
     1323     * Wait for an event to arrive if there are none.
     1324     */
     1325    int rc = VINF_SUCCESS;
     1326    uint32_t idxDbgEvtRead = ASMAtomicReadU32(&pUVM->dbgf.s.idxDbgEvtRead);
     1327    if (idxDbgEvtRead == ASMAtomicReadU32(&pUVM->dbgf.s.idxDbgEvtWrite))
     1328    {
     1329        do
     1330        {
     1331            rc = RTSemEventWait(pUVM->dbgf.s.hEvtWait, cMillies);
     1332        } while (   RT_SUCCESS(rc)
     1333                 && idxDbgEvtRead == ASMAtomicReadU32(&pUVM->dbgf.s.idxDbgEvtWrite));
     1334    }
     1335
    12151336    if (RT_SUCCESS(rc))
    12161337    {
    1217         *ppEvent = &pVM->dbgf.s.DbgEvent;
    1218         Log2(("DBGF: Debugger thread: receiving event %d\n", (*ppEvent)->enmType));
    1219         return VINF_SUCCESS;
    1220     }
    1221 
     1338        Assert(idxDbgEvtRead != ASMAtomicReadU32(&pUVM->dbgf.s.idxDbgEvtWrite));
     1339
     1340        uint32_t const cDbgEvtMax = RT_MAX(1, pUVM->dbgf.s.cDbgEvtMax);
     1341        memcpy(pEvent, &pUVM->dbgf.s.paDbgEvts[idxDbgEvtRead % cDbgEvtMax], sizeof(*pEvent));
     1342        ASMAtomicWriteU32(&pUVM->dbgf.s.idxDbgEvtRead, (idxDbgEvtRead + 1) % cDbgEvtMax);
     1343    }
     1344
     1345    Log2(("DBGFR3EventWait: rc=%Rrc (event type %d)\n", rc, pEvent->enmType));
    12221346    return rc;
    12231347}
     
    12311355 *
    12321356 * @returns VBox status code.
     1357 * @retval  VWRN_DBGF_ALREADY_HALTED if @a idCpu is VMCPUID_ALL and all vCPUs
     1358 *          are halted.
    12331359 * @param   pUVM        The user mode VM handle.
    1234  */
    1235 VMMR3DECL(int) DBGFR3Halt(PUVM pUVM)
     1360 * @param   idCpu       The vCPU to halt, VMCPUID_ALL halts all still running vCPUs.
     1361 */
     1362VMMR3DECL(int) DBGFR3Halt(PUVM pUVM, VMCPUID idCpu)
    12361363{
    12371364    /*
     
    12421369    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    12431370    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    1244     RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
    1245     if (   enmSpeaker == RTPINGPONGSPEAKER_PONG
    1246         || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED)
    1247         return VWRN_DBGF_ALREADY_HALTED;
    1248 
    1249     /*
    1250      * Send command.
    1251      */
    1252     dbgfR3SetCmd(pVM, DBGFCMD_HALT);
    1253 
    1254     return VINF_SUCCESS;
    1255 }
    1256 
    1257 
    1258 /**
    1259  * Checks if the VM is halted by the debugger.
    1260  *
    1261  * @returns True if halted.
    1262  * @returns False if not halted.
     1371    AssertReturn(idCpu == VMCPUID_ALL || idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
     1372
     1373    /*
     1374     * Halt the requested CPUs as needed.
     1375     */
     1376    int rc;
     1377    if (idCpu != VMCPUID_ALL)
     1378    {
     1379        PUVMCPU pUVCpu = &pUVM->aCpus[idCpu];
     1380        if (!dbgfR3CpuIsHalted(pUVCpu))
     1381        {
     1382            dbgfR3CpuSetCmdAndNotify(pUVCpu, DBGFCMD_HALT);
     1383            rc = VINF_SUCCESS;
     1384        }
     1385        else
     1386            rc = VWRN_DBGF_ALREADY_HALTED;
     1387    }
     1388    else
     1389    {
     1390        rc = VWRN_DBGF_ALREADY_HALTED;
     1391        for (VMCPUID i = 0; i < pUVM->cCpus; i++)
     1392        {
     1393            PUVMCPU pUVCpu = &pUVM->aCpus[i];
     1394            if (!dbgfR3CpuIsHalted(pUVCpu))
     1395            {
     1396                dbgfR3CpuSetCmdAndNotify(pUVCpu, DBGFCMD_HALT);
     1397                rc = VINF_SUCCESS;
     1398            }
     1399        }
     1400    }
     1401
     1402    return rc;
     1403}
     1404
     1405
     1406/**
     1407 * Checks if any of the specified vCPUs have been halted by the debugger.
     1408 *
     1409 * @returns True if at least one halted vCPUs.
     1410 * @returns False if no halted vCPUs.
    12631411 * @param   pUVM        The user mode VM handle.
    1264  */
    1265 VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM)
     1412 * @param   idCpu       The CPU id to check for, VMCPUID_ALL will return true if
     1413 *                      at least a single vCPU is halted in the debugger.
     1414 */
     1415VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM, VMCPUID idCpu)
    12661416{
    12671417    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     
    12701420    AssertReturn(pVM->dbgf.s.fAttached, false);
    12711421
    1272     RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
    1273     return enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
    1274         || enmSpeaker == RTPINGPONGSPEAKER_PONG;
     1422    return dbgfR3CpuAreAnyHaltedByCpuId(pUVM, idCpu);
    12751423}
    12761424
     
    13031451        return VERR_DBGF_NOT_ATTACHED;
    13041452
    1305     if (!RTSemPongShouldWait(&pVM->dbgf.s.PingPong))
    1306         return VERR_SEM_OUT_OF_TURN;
    1307 
     1453    /** @todo was: if (!RTSemPongShouldWait(...)) return VERR_SEM_OUT_OF_TURN; */
    13081454    return VINF_SUCCESS;
    13091455}
     
    13161462 *
    13171463 * @returns VBox status code.
     1464 * @retval  VWRN_DBGF_ALREADY_RUNNING if the specified vCPUs are all running.
    13181465 * @param   pUVM        The user mode VM handle.
    1319  */
    1320 VMMR3DECL(int) DBGFR3Resume(PUVM pUVM)
    1321 {
    1322     /*
    1323      * Check state.
     1466 * @param   idCpu       The vCPU to resume, VMCPUID_ALL resumes all still halted vCPUs.
     1467 */
     1468VMMR3DECL(int) DBGFR3Resume(PUVM pUVM, VMCPUID idCpu)
     1469{
     1470    /*
     1471     * Validate input and attachment state.
    13241472     */
    13251473    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     
    13271475    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    13281476    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    1329     if (RT_LIKELY(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong)))
    1330     { /* likely */ }
     1477
     1478    /*
     1479     * Ping the halted emulation threads, telling them to run.
     1480     */
     1481    int rc = VWRN_DBGF_ALREADY_RUNNING;
     1482    if (idCpu != VMCPUID_ALL)
     1483    {
     1484        PUVMCPU pUVCpu = &pUVM->aCpus[idCpu];
     1485        if (dbgfR3CpuIsHalted(pUVCpu))
     1486        {
     1487            rc = dbgfR3CpuSetCmdAndNotify(pUVCpu, DBGFCMD_GO);
     1488            AssertRC(rc);
     1489        }
     1490    }
    13311491    else
    1332         return VERR_SEM_OUT_OF_TURN;
    1333 
    1334     /*
    1335      * Send the ping back to the emulation thread telling it to run.
    1336      */
    1337     dbgfR3SetCmd(pVM, DBGFCMD_GO);
    1338     int rc = RTSemPong(&pVM->dbgf.s.PingPong);
    1339     AssertRC(rc);
     1492    {
     1493        for (VMCPUID i = 0; i < pUVM->cCpus; i++)
     1494        {
     1495            PUVMCPU pUVCpu = &pUVM->aCpus[i];
     1496            if (dbgfR3CpuIsHalted(pUVCpu))
     1497            {
     1498                int rc2 = dbgfR3CpuSetCmdAndNotify(pUVCpu, DBGFCMD_GO);
     1499                AssertRC(rc2);
     1500                if (rc == VWRN_DBGF_ALREADY_RUNNING || RT_FAILURE(rc2))
     1501                    rc = rc2;
     1502            }
     1503        }
     1504    }
    13401505
    13411506    return rc;
     
    16211786
    16221787    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    1623     if (RT_LIKELY(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong)))
     1788    PUVMCPU pUVCpu = &pUVM->aCpus[idCpu];
     1789    if (RT_LIKELY(dbgfR3CpuIsHalted(pUVCpu)))
    16241790    { /* likely */ }
    16251791    else
     
    16281794
    16291795    /*
    1630      * Send the ping back to the emulation thread telling it to run.
     1796     * Send the emulation thread a single-step command.
    16311797     */
    16321798    if (fFlags == DBGF_STEP_F_INTO)
     
    16541820    pVM->dbgf.s.SteppingFilter.uCallDepth   = 0;
    16551821
    1656 /** @todo SMP (idCpu) */
    1657     dbgfR3SetCmd(pVM, DBGFCMD_SINGLE_STEP);
    1658     int rc = RTSemPong(&pVM->dbgf.s.PingPong);
    1659     AssertRC(rc);
    1660     return rc;
     1822    Assert(dbgfR3CpuIsHalted(pUVCpu));
     1823    return dbgfR3CpuSetCmdAndNotify(pUVCpu, DBGFCMD_SINGLE_STEP);
    16611824}
    16621825
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r84766 r86098  
    578578    DBGFCMD_GO,
    579579    /** Single step execution - stepping into calls. */
    580     DBGFCMD_SINGLE_STEP,
    581     /** Detaches the debugger.
    582      * Disabling all breakpoints, watch points and the like. */
    583     DBGFCMD_DETACH_DEBUGGER,
    584     /** Detached the debugger.
    585      * The isn't a command as such, it's just that it's necessary for the
    586      * detaching protocol to be racefree. */
    587     DBGFCMD_DETACHED_DEBUGGER
     580    DBGFCMD_SINGLE_STEP
    588581} DBGFCMD;
    589582
     
    806799     */
    807800    bool volatile               fAttached;
    808 
    809     /** Stopped in the Hypervisor.
    810      * Set if we're stopped on a trace, breakpoint or assertion inside
    811      * the hypervisor and have to restrict the available operations.
    812      */
    813     bool volatile               fStoppedInHyper;
    814 
    815     /**
    816      * Ping-Pong construct where the Ping side is the VMM and the Pong side
    817      * the Debugger.
    818      */
    819     RTPINGPONG                  PingPong;
    820     RTHCUINTPTR                 uPtrPadding; /**< Alignment padding. */
    821 
    822     /** The Event to the debugger.
    823      * The VMM will ping the debugger when the event is ready. The event is
    824      * either a response to a command or to a break/watch point issued
    825      * previously.
    826      */
    827     DBGFEVENT                   DbgEvent;
    828 
    829     /** The Command to the VMM.
    830      * Operated in an atomic fashion since the VMM will poll on this.
    831      * This means that a the command data must be written before this member
    832      * is set. The VMM will reset this member to the no-command state
    833      * when it have processed it.
    834      */
    835     DBGFCMD volatile            enmVMMCmd;
    836     /** The Command data.
    837      * Not all commands take data. */
    838     DBGFCMDDATA                 VMMCmdData;
    839801
    840802    /** Stepping filtering. */
     
    906868    } BugCheck;
    907869} DBGF;
    908 AssertCompileMemberAlignment(DBGF, DbgEvent, 8);
    909870AssertCompileMemberAlignment(DBGF, aHwBreakpoints, 8);
    910871AssertCompileMemberAlignment(DBGF, bmHardIntBreakpoints, 8);
     
    10651026    PDBGFTRACERINSR3            pTracerR3;
    10661027
     1028    /** @name VM -> Debugger event communication.
     1029     * @{ */
     1030    /** The event semaphore the debugger waits on for new events to arrive. */
     1031    RTSEMEVENT                  hEvtWait;
     1032    /** Multi event semaphore the vCPUs wait on in case the debug event ringbuffer is
     1033     * full and require growing (done from the thread waiting for events). */
     1034    RTSEMEVENTMULTI             hEvtRingBufFull;
     1035    /** Fast mutex protecting the event ring from concurrent write accesses by multiple vCPUs. */
     1036    RTSEMFASTMUTEX              hMtxDbgEvtWr;
     1037    /** Ringbuffer of events, dynamically allocated based on the number of available vCPUs
     1038     * (+ some safety entries). */
     1039    PDBGFEVENT                  paDbgEvts;
     1040    /** Number of entries in the event ring buffer. */
     1041    uint32_t                    cDbgEvtMax;
     1042    /** Next free entry to write to (vCPU thread). */
     1043    volatile uint32_t           idxDbgEvtWrite;
     1044    /** Next event entry to from (debugger thread). */
     1045    volatile uint32_t           idxDbgEvtRead;
     1046    /** @} */
     1047
    10671048    /** The type database lock. */
    10681049    RTSEMRW                     hTypeDbLock;
     
    10841065{
    10851066    /** The guest register set for this CPU.  Can be NULL. */
    1086     R3PTRTYPE(struct DBGFREGSET *) pGuestRegSet;
     1067    R3PTRTYPE(struct DBGFREGSET *)  pGuestRegSet;
    10871068    /** The hypervisor register set for this CPU.  Can be NULL. */
    1088     R3PTRTYPE(struct DBGFREGSET *) pHyperRegSet;
     1069    R3PTRTYPE(struct DBGFREGSET *)  pHyperRegSet;
     1070
     1071    /** @name Debugger -> vCPU command communication.
     1072     * @{ */
     1073    /** Flag whether this vCPU is currently stopped waiting in the debugger. */
     1074    bool volatile                   fStopped;
     1075    /** The Command to the vCPU.
     1076     * Operated in an atomic fashion since the vCPU will poll on this.
     1077     * This means that a the command data must be written before this member
     1078     * is set. The VMM will reset this member to the no-command state
     1079     * when it have processed it.
     1080     */
     1081    DBGFCMD volatile                enmDbgfCmd;
     1082    /** The Command data.
     1083     * Not all commands take data. */
     1084    DBGFCMDDATA                     DbgfCmdData;
     1085    /** @} */
     1086
    10891087} DBGFUSERPERVMCPU;
    10901088
  • trunk/src/VBox/VMM/testcase/tstVMStruct.h

    r82968 r86098  
    275275    GEN_CHECK_OFF(DBGF, cSelectedEvents);
    276276    GEN_CHECK_OFF(DBGF, fAttached);
    277     GEN_CHECK_OFF(DBGF, fStoppedInHyper);
    278     GEN_CHECK_OFF(DBGF, PingPong);
    279     GEN_CHECK_OFF(DBGF, DbgEvent);
    280     GEN_CHECK_OFF(DBGF, enmVMMCmd);
    281     GEN_CHECK_OFF(DBGF, VMMCmdData);
    282277    //GEN_CHECK_OFF(DBGF, pInfoFirst);
    283278    //GEN_CHECK_OFF(DBGF, InfoCritSect);
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