- Timestamp:
- Sep 13, 2020 7:17:19 AM (4 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGCCmdHlp.cpp
r84653 r86098 1347 1347 1348 1348 /** 1349 * @interface_method_impl{DBGCCMDHLP,pfnRegPrintf} 1350 */ 1351 static 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 /** 1349 1442 * Initializes the Command Helpers for a DBGC instance. 1350 1443 * … … 1376 1469 pDbgc->CmdHlp.pfnGetCurrentCpu = dbgcHlpGetCurrentCpu; 1377 1470 pDbgc->CmdHlp.pfnGetCpuMode = dbgcHlpGetCpuMode; 1471 pDbgc->CmdHlp.pfnRegPrintf = dbgcHlpRegPrintf; 1378 1472 pDbgc->CmdHlp.u32EndMarker = DBGCCMDHLP_MAGIC; 1379 1473 } -
trunk/src/VBox/Debugger/DBGCCommands.cpp
r83088 r86098 233 233 { 1, 1, DBGCVAR_CAT_SYMBOL, 0, "var", "Variable name." }, 234 234 { 1, 1, DBGCVAR_CAT_ANY, 0, "value", "Value to assign to the variable." }, 235 }; 236 237 /** 'stop' arguments */ 238 static const DBGCVARDESC g_aArgStop[] = 239 { 240 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */ 241 { 0, 1, DBGCVAR_CAT_NUMBER, 0, "idCpu", "CPU ID." }, 235 242 }; 236 243 … … 298 305 { "set", 2, 2, &g_aArgSet[0], RT_ELEMENTS(g_aArgSet), 0, dbgcCmdSet, "<var> <value>", "Sets a global variable." }, 299 306 { "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.)" }, 301 308 { "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." }, 302 309 { "unloadplugin", 1, ~0U, &g_aArgPlugIn[0], RT_ELEMENTS(g_aArgPlugIn), 0, dbgcCmdUnloadPlugIn, "<plugin1> [plugin2..N]", "Unloads one or more plugins." }, … … 938 945 static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs) 939 946 { 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 } 946 961 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) 950 972 rc = VWRN_DBGC_CMD_PENDING; 973 else if (idCpu == VMCPUID_ALL) 974 rc = DBGCCmdHlpPrintf(pCmdHlp, "warning: The VM is already halted...\n"); 951 975 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 956 981 return rc; 957 982 } -
trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp
r83082 r86098 237 237 { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to write." }, 238 238 { 1, ~0U, DBGCVAR_CAT_NUMBER, 0, "value", "Value to write." }, 239 }; 240 241 242 /** 'g' arguments. */ 243 static const DBGCVARDESC g_aArgGo[] = 244 { 245 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */ 246 { 0, 1, DBGCVAR_CAT_NUMBER, 0, "idCpu", "CPU ID." }, 239 247 }; 240 248 … … 425 433 { "ed", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 4-byte value to memory." }, 426 434 { "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.)" }, 428 436 { "gu", 0, 0, NULL, 0, 0, dbgcCmdGoUp, "", "Go up - continue execution till after return." }, 429 437 { "k", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack." }, … … 651 659 652 660 /* 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"); 664 689 } 665 690 … … 2466 2491 || ( strcmp(pCmd->pszCmd, "rg32") != 0 2467 2492 && 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); 2549 2494 } 2550 2495 return dbgcCmdRegCommon(pCmd, pCmdHlp, pUVM, paArgs, cArgs, ""); -
trunk/src/VBox/Debugger/DBGCGdbRemoteStub.cpp
r85367 r86098 1565 1565 case 'c': 1566 1566 { 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); 1569 1569 break; 1570 1570 } … … 1581 1581 case 't': 1582 1582 { 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); 1585 1585 /* The reply will be send in the event loop. */ 1586 1586 break; … … 1732 1732 case 'c': /* Continue, no response */ 1733 1733 { 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); 1736 1736 break; 1737 1737 } … … 2174 2174 { 2175 2175 /* 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); 2178 2178 /* The reply will be send in the event loop. */ 2179 2179 } … … 2403 2403 break; 2404 2404 } 2405 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM ))2405 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL)) 2406 2406 { 2407 2407 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r"); … … 2589 2589 * Wait for a debug event. 2590 2590 */ 2591 PCDBGFEVENT pEvent;2592 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, & pEvent);2591 DBGFEVENT Event; 2592 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Event); 2593 2593 if (RT_SUCCESS(rc)) 2594 2594 { 2595 rc = dbgcGdbStubCtxProcessEvent(pThis, pEvent);2595 rc = dbgcGdbStubCtxProcessEvent(pThis, &Event); 2596 2596 if (RT_FAILURE(rc)) 2597 2597 break; … … 2840 2840 //dbgcRunInitScripts(pDbgc); Not yet 2841 2841 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); 2844 2844 2845 2845 /* -
trunk/src/VBox/Debugger/DBGConsole.cpp
r84708 r86098 648 648 bool fPrintPrompt = true; 649 649 int rc = VINF_SUCCESS; 650 VMCPUID const idCpuSaved = pDbgc->idCpu; 650 651 switch (pEvent->enmType) 651 652 { … … 655 656 case DBGFEVENT_HALT_DONE: 656 657 { 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)); 659 662 if (RT_SUCCESS(rc)) 660 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");663 rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse); 661 664 break; 662 665 } … … 668 671 case DBGFEVENT_FATAL_ERROR: 669 672 { 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)); 672 676 if (RT_SUCCESS(rc)) 673 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");677 rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse); 674 678 break; 675 679 } … … 680 684 case DBGFEVENT_BREAKPOINT_HYPER: 681 685 { 686 pDbgc->idCpu = pEvent->idCpu; 682 687 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp); 683 688 switch (rc) 684 689 { 685 690 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)); 688 693 break; 689 694 690 695 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)); 693 698 break; 694 699 695 700 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)); 698 703 break; 699 704 … … 701 706 break; 702 707 } 703 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM ))708 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, pEvent->idCpu)) 704 709 { 705 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");710 rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse); 706 711 707 712 /* Set the resume flag to ignore the breakpoint when resuming execution. */ … … 710 715 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1"); 711 716 } 717 else 718 pDbgc->idCpu = idCpuSaved; 712 719 break; 713 720 } … … 716 723 case DBGFEVENT_STEPPED_HYPER: 717 724 { 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)); 720 728 else 721 729 pDbgc->cMultiStepsLeft -= 1; … … 723 731 { 724 732 if (pDbgc->fStepTraceRegs) 725 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");733 rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse); 726 734 else 727 735 { … … 739 747 740 748 /* If multi-stepping, take the next step: */ 741 if (pDbgc->cMultiStepsLeft > 0 )749 if (pDbgc->cMultiStepsLeft > 0 && pEvent->idCpu != idCpuSaved) 742 750 { 743 751 int rc2 = DBGFR3StepEx(pDbgc->pUVM, pDbgc->idCpu, DBGF_STEP_F_INTO, NULL, NULL, 0, pDbgc->uMultiStepStrideLength); … … 747 755 DBGCCmdHlpFailRc(&pDbgc->CmdHlp, pDbgc->pMultiStepCmd, rc2, "DBGFR3StepEx(,,DBGF_STEP_F_INTO,) failed"); 748 756 } 757 else 758 pDbgc->idCpu = pEvent->idCpu; 749 759 break; 750 760 } … … 752 762 case DBGFEVENT_ASSERTION_HYPER: 753 763 { 764 pDbgc->idCpu = pEvent->idCpu; 754 765 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, 755 "\ndbgf event : Hypervisor Assertion! (%s)\n"766 "\ndbgf event/%u: Hypervisor Assertion! (%s)\n" 756 767 "%s" 757 768 "%s" 758 769 "\n", 770 pEvent->idCpu, 759 771 dbgcGetEventCtx(pEvent->enmCtx), 760 772 pEvent->u.Assert.pszMsg1, 761 773 pEvent->u.Assert.pszMsg2); 762 774 if (RT_SUCCESS(rc)) 763 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");775 rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse); 764 776 break; 765 777 } … … 767 779 case DBGFEVENT_DEV_STOP: 768 780 { 781 pDbgc->idCpu = pEvent->idCpu; 769 782 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, 770 783 "\n" 771 "dbgf event : DBGFSTOP (%s)\n"784 "dbgf event/%u: DBGFSTOP (%s)\n" 772 785 "File: %s\n" 773 786 "Line: %d\n" 774 787 "Function: %s\n", 788 pEvent->idCpu, 775 789 dbgcGetEventCtx(pEvent->enmCtx), 776 790 pEvent->u.Src.pszFile, … … 782 796 pEvent->u.Src.pszMessage); 783 797 if (RT_SUCCESS(rc)) 784 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");798 rc = DBGCCmdHlpRegPrintf(&pDbgc->CmdHlp, pEvent->idCpu, -1, pDbgc->fRegTerse); 785 799 break; 786 800 } … … 816 830 Assert(pEvtDesc->pszDesc); 817 831 Assert(pEvent->u.Generic.cArgs == 1); 818 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event : %s no %#llx! (%s)\n",819 pEv tDesc->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); 820 834 } 821 835 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK) … … 826 840 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2], 827 841 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->psz Desc ? "- " : "", 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); 831 845 } 832 846 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG) … … 836 850 { 837 851 if (pEvtDesc->pszDesc) 838 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event : %s - %s!",839 pEv tDesc->pszName, pEvtDesc->pszDesc);852 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s - %s!", 853 pEvent->idCpu, pEvtDesc->pszName, pEvtDesc->pszDesc); 840 854 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); 842 857 if (pEvent->u.Generic.cArgs <= 1) 843 858 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]); … … 852 867 { 853 868 if (pEvtDesc->pszDesc) 854 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event : %s - %s!\n",855 pEv tDesc->pszName, pEvtDesc->pszDesc);869 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event/%u: %s - %s!\n", 870 pEvent->idCpu, pEvtDesc->pszName, pEvtDesc->pszDesc); 856 871 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); 858 874 } 859 875 } 860 876 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); 862 879 break; 863 880 } … … 869 886 if (fPrintPrompt && RT_SUCCESS(rc)) 870 887 { 888 /** @todo add CPU indicator to the prompt if an SMP VM? */ 871 889 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> "); 872 890 pDbgc->fReady = true; … … 938 956 * Wait for a debug event. 939 957 */ 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); 942 960 if (RT_SUCCESS(rc)) 943 961 { 944 rc = dbgcProcessEvent(pDbgc, pEvent);962 rc = dbgcProcessEvent(pDbgc, &Event); 945 963 if (RT_FAILURE(rc)) 946 964 break; -
trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp
r82968 r86098 94 94 return VERR_INTERNAL_ERROR; 95 95 } 96 VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, P CDBGFEVENT *ppEvent)96 VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PDBGFEVENT pEvent) 97 97 { 98 98 return VERR_INTERNAL_ERROR; … … 107 107 } 108 108 109 VMMR3DECL(int) DBGFR3Halt(PUVM pUVM )109 VMMR3DECL(int) DBGFR3Halt(PUVM pUVM, VMCPUID idCpu) 110 110 { 111 111 return VERR_INTERNAL_ERROR; … … 122 122 { 123 123 } 124 VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM )124 VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM, VMCPUID idCpu) 125 125 { 126 126 return true; … … 164 164 return VERR_DBG_LINE_NOT_FOUND; 165 165 } 166 VMMR3DECL(int) DBGFR3Resume(PUVM pUVM )166 VMMR3DECL(int) DBGFR3Resume(PUVM pUVM, VMCPUID idCpu) 167 167 { 168 168 return VERR_INTERNAL_ERROR; -
trunk/src/VBox/VMM/VMMR3/DBGF.cpp
r84458 r86098 75 75 #include <VBox/vmm/em.h> 76 76 #include <VBox/vmm/hm.h> 77 #include <VBox/vmm/mm.h> 77 78 #include "DBGFInternal.h" 78 79 #include <VBox/vmm/vm.h> … … 110 111 * Internal Functions * 111 112 *********************************************************************************************************************************/ 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); 113 DECLINLINE(int) dbgfR3SendEventWait(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx); 114 DECLINLINE(DBGFCMD) dbgfR3CpuGetCmd(PUVMCPU pUVCpu); 115 static int dbgfR3CpuWait(PVMCPU pVCpu); 116 static int dbgfR3CpuCmd(PVMCPU pVCpu, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution); 115 117 static 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 } 118 static bool dbgfStepAreWeThereYet(PVM pVM, PVMCPU pVCpu); 119 145 120 146 121 … … 244 219 VMMR3_INT_DECL(void) DBGFR3PowerOff(PVM pVM) 245 220 { 246 247 221 /* 248 222 * Send a termination event to any attached debugger. 249 223 */ 250 /* wait to become the speaker (we should already be that). */251 if ( pVM->dbgf.s.fAttached252 && RTSemPingShouldWait(&pVM->dbgf.s.PingPong))253 RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);254 255 224 if (pVM->dbgf.s.fAttached) 256 225 { 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); 339 234 } 340 235 } … … 371 266 * First a message. 372 267 */ 373 #ifndef RT_OS_L4 374 375 # if !defined(DEBUG) || defined(DEBUG_sandervl) || defined(DEBUG_frank) 268 #if !defined(DEBUG) 376 269 int cWait = 10; 377 # 270 #else 378 271 int cWait = !VM_IS_RAW_MODE_ENABLED(pVM) 379 272 && ( enmEvent == DBGFEVENT_ASSERTION_HYPER … … 382 275 ? 10 383 276 : 150; 384 # 277 #endif 385 278 RTStrmPrintf(g_pStdErr, "DBGF: No debugger attached, waiting %d second%s for one to attach (event=%d)\n", 386 279 cWait / 10, cWait != 10 ? "s" : "", enmEvent); … … 394 287 RTStrmFlush(g_pStdErr); 395 288 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 } 396 301 } 397 302 … … 405 310 if (rc != VINF_SUCCESS) 406 311 { 312 /** @todo Ignoring these could be bad. */ 407 313 RTStrmPrintf(g_pStdErr, "[rcReq=%Rrc, ignored!]", rc); 408 314 RTStrmFlush(g_pStdErr); … … 418 324 cWait--; 419 325 } 420 #endif421 326 422 327 RTStrmPrintf(g_pStdErr, "Stopping the VM!\n"); … … 444 349 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 445 350 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 448 363 /* 449 364 * Command pending? Process it. 450 365 */ 451 if (pVM->dbgf.s.enmVMMCmd != DBGFCMD_NO_COMMAND) 366 PUVMCPU pUVCpu = pVCpu->pUVCpu; 367 if (pUVCpu->dbgf.s.enmDbgfCmd != DBGFCMD_NO_COMMAND) 452 368 { 453 369 bool fResumeExecution; 454 DBGFCMDDATA CmdData = p VM->dbgf.s.VMMCmdData;455 DBGFCMD enmCmd = dbgfR3 SetCmd(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); 457 373 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); 471 375 if ( rcStrict2 != VINF_SUCCESS 472 376 && ( rcStrict == VINF_SUCCESS … … 482 386 483 387 /** 484 * Flag whether the event implies that we're stopped in the hypervisor code485 * 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 /**507 388 * Try to determine the event context. 508 389 * 509 390 * @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 */ 393 static DBGFEVENTCTX dbgfR3FigureEventCtx(PVMCPU pVCpu) 394 { 517 395 switch (EMGetState(pVCpu)) 518 396 { 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: 519 404 case EMSTATE_RAW: 405 case EMSTATE_IEM_THEN_REM: 406 case EMSTATE_DEBUG_GUEST_IEM: 520 407 case EMSTATE_DEBUG_GUEST_RAW: 521 408 return DBGFEVENTCTX_RAW; 409 522 410 523 411 case EMSTATE_REM: … … 534 422 } 535 423 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 */ 436 static 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 */ 491 DECLINLINE(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 */ 511 DECLINLINE(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 */ 531 DECLINLINE(int) dbgfR3SendEventNoWait(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmType, DBGFEVENTCTX enmCtx) 532 { 533 return dbgfR3SendEventWorker(pVM, pVCpu, enmType, enmCtx, NULL, 0); 534 } 535 536 536 537 /** 537 538 * 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). 540 542 * 541 543 * @returns VBox status code. 542 544 * @param pVM The cross context VM structure. 545 * @param pVCpu The vCPU cross context structure. 543 546 * @param enmEvent The event to be sent. 544 547 */ 545 static int dbgfR3EventPrologue(PVM pVM, DBGFEVENTTYPE enmEvent) 546 { 547 /** @todo SMP */ 548 PVMCPU pVCpu = VMMGetCpu(pVM); 549 548 static int dbgfR3EventPrologue(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent) 549 { 550 550 /* 551 551 * Check if a debugger is attached. … … 554 554 && !dbgfR3WaitForAttach(pVM, pVCpu, enmEvent)) 555 555 { 556 Log((" DBGFR3VMMEventSrc: enmEvent=%d - debugger not attached\n", enmEvent));556 Log(("dbgfR3EventPrologue: enmEvent=%d - debugger not attached\n", enmEvent)); 557 557 return VERR_DBGF_NOT_ATTACHED; 558 558 } 559 560 /*561 * Set flag.562 */563 dbgfR3EventSetStoppedInHyperFlag(pVM, enmEvent);564 559 565 560 /* … … 573 568 574 569 /** 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 /**595 570 * Processes a pending event on the current CPU. 596 571 * … … 618 593 * Make sure we've got a debugger and is allowed to speak to it. 619 594 */ 620 int rc = dbgfR3EventPrologue(pVM, p Event->enmType);595 int rc = dbgfR3EventPrologue(pVM, pVCpu, pEvent->enmType); 621 596 if (RT_FAILURE(rc)) 622 597 { 623 598 /** @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)); 632 607 pVCpu->dbgf.s.aEvents[pVCpu->dbgf.s.cEvents - 1].enmState = DBGFEVENTSTATE_IGNORE; 633 return dbgfR3SendEvent(pVM);608 return rcStrict; 634 609 } 635 610 … … 645 620 VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent) 646 621 { 622 PVMCPU pVCpu = VMMGetCpu(pVM); 623 AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT); 624 647 625 /* 648 626 * Do stepping filtering. … … 653 631 || enmEvent == DBGFEVENT_STEPPED_HYPER) 654 632 { 655 if (!dbgfStepAreWeThereYet(pVM, VMMGetCpu(pVM)))633 if (!dbgfStepAreWeThereYet(pVM, pVCpu)) 656 634 return VINF_EM_DBG_STEP; 657 635 } 658 636 659 int rc = dbgfR3EventPrologue(pVM, enmEvent);637 int rc = dbgfR3EventPrologue(pVM, pVCpu, enmEvent); 660 638 if (RT_FAILURE(rc)) 661 639 return rc; … … 664 642 * Send the event and process the reply communication. 665 643 */ 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); 669 645 } 670 646 … … 708 684 VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args) 709 685 { 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); 711 690 if (RT_FAILURE(rc)) 712 691 return rc; … … 726 705 * Send the event and process the reply communication. 727 706 */ 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)); 735 713 } 736 714 … … 747 725 VMMR3_INT_DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2) 748 726 { 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); 750 731 if (RT_FAILURE(rc)) 751 732 return rc; … … 754 735 * Send the event and process the reply communication. 755 736 */ 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)); 761 741 } 762 742 … … 772 752 VMMR3_INT_DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent) 773 753 { 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); 775 758 if (RT_FAILURE(rc)) 776 759 return rc; … … 779 762 * Send the event and process the reply communication. 780 763 */ 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; 786 766 pVCpu->dbgf.s.iActiveBp = ~0U; 787 767 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. */ 792 776 #if 0 /** @todo get flat PC api! */ 793 777 uint32_t eip = CPUMGetGuestEIP(pVM); 794 778 #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; 798 781 #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 */ 800 DECLINLINE(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 */ 814 DECLINLINE(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 */ 837 DECLINLINE(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 */ 852 DECLINLINE(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; 810 863 } 811 864 … … 815 868 * 816 869 * @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 */ 872 static int dbgfR3CpuWait(PVMCPU pVCpu) 873 { 874 PVM pVM = pVCpu->CTX_SUFF(pVM); 875 PUVMCPU pUVCpu = pVCpu->pUVCpu; 876 877 LogFlow(("dbgfR3CpuWait:\n")); 824 878 int rcRet = VINF_SUCCESS; 879 880 ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, true); 825 881 826 882 /* … … 832 888 * Wait. 833 889 */ 834 uint32_t cPollHack = 1; /** @todo this interface is horrible now that we're using lots of VMR3ReqCall stuff all over DBGF. */835 890 for (;;) 836 891 { 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)) 840 897 { 841 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack); 842 if (RT_SUCCESS(rc)) 898 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_DBGF)) 843 899 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)) 845 906 { 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); 847 972 return rc; 848 973 } 849 974 } 850 851 if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS)) 975 else if (pVM->dbgf.s.fAttached) 852 976 { 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 } 865 984 } 866 985 else 867 986 { 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; 911 990 } 912 991 } … … 915 994 * Process the command. 916 995 */ 996 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_DBGF); 917 997 bool fResumeExecution; 918 DBGFCMDDATA CmdData = p VM->dbgf.s.VMMCmdData;919 DBGFCMD enmCmd = dbgfR3 SetCmd(pVM, DBGFCMD_NO_COMMAND);920 int rc = dbgfR3 VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);998 DBGFCMDDATA CmdData = pUVCpu->dbgf.s.DbgfCmdData; 999 DBGFCMD enmCmd = dbgfR3CpuGetCmd(pUVCpu); 1000 int rc = dbgfR3CpuCmd(pVCpu, enmCmd, &CmdData, &fResumeExecution); 921 1001 if (fResumeExecution) 922 1002 { … … 927 1007 && (rc < rcRet || rcRet == VINF_SUCCESS)) 928 1008 rcRet = rc; 929 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rcRet)); 1009 LogFlow(("dbgfR3CpuWait: returns %Rrc\n", rcRet)); 1010 ASMAtomicWriteBool(&pUVCpu->dbgf.s.fStopped, false); 930 1011 return rcRet; 931 1012 } … … 941 1022 * 942 1023 * @returns VBox status code. (clearify!) 943 * @param pV M The cross context VMstructure.1024 * @param pVCpu The cross context vCPU structure. 944 1025 * @param enmCmd The command in question. 945 1026 * @param pCmdData Pointer to the command data. 946 1027 * @param pfResumeExecution Where to store the resume execution / continue waiting indicator. 947 1028 */ 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 1029 static 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; 956 1038 switch (enmCmd) 957 1039 { … … 961 1043 case DBGFCMD_HALT: 962 1044 { 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; 967 1047 break; 968 1048 } … … 970 1050 971 1051 /* 972 * Resume is not answered we'lljust resume execution.1052 * Resume is not answered, we just resume execution. 973 1053 */ 974 1054 case DBGFCMD_GO: 975 1055 { 976 /** @todo SMP */977 PVMCPU pVCpu = VMMGetCpu0(pVM);978 1056 pVCpu->dbgf.s.fSingleSteppingRaw = false; 979 fSendEvent = false; 980 fResume = true; 981 break; 1057 *pfResumeExecution = true; 1058 return VINF_SUCCESS; 982 1059 } 983 1060 984 1061 /** @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 }1011 1062 1012 1063 /* … … 1016 1067 { 1017 1068 Log2(("Single step\n")); 1018 /** @todo SMP */ 1019 PVMCPU pVCpu = VMMGetCpu0(pVM); 1069 PVM pVM = pVCpu->CTX_SUFF(pVM); 1020 1070 if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_OVER) 1021 1071 { … … 1026 1076 { 1027 1077 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; 1031 1080 } 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; 1042 1086 break; 1043 1087 } … … 1048 1092 default: 1049 1093 { 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; 1054 1096 break; 1055 1097 } … … 1057 1099 1058 1100 /* 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); 1077 1106 return rc; 1107 } 1108 1109 1110 /** 1111 * @callback_method_impl{FNVMMEMTRENDEZVOUS, 1112 * EMT rendezvous worker for DBGFR3Attach - only called on one EMT.} 1113 */ 1114 static 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; 1078 1180 } 1079 1181 … … 1094 1196 1095 1197 /* 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 */ 1213 static 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 1130 1267 return VINF_SUCCESS; 1131 1268 } … … 1143 1280 { 1144 1281 LogFlow(("DBGFR3Detach:\n")); 1145 int rc;1146 1282 1147 1283 /* … … 1160 1296 return VERR_DBGF_NOT_ATTACHED; 1161 1297 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); 1189 1299 } 1190 1300 … … 1196 1306 * @param pUVM The user mode VM handle. 1197 1307 * @param cMillies Number of millis to wait. 1198 * @param p pEvent Where to store the event pointer.1199 */ 1200 VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, P CDBGFEVENT *ppEvent)1308 * @param pEvent Where to store the event data. 1309 */ 1310 VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PDBGFEVENT pEvent) 1201 1311 { 1202 1312 /* … … 1207 1317 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1208 1318 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 1215 1336 if (RT_SUCCESS(rc)) 1216 1337 { 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)); 1222 1346 return rc; 1223 1347 } … … 1231 1355 * 1232 1356 * @returns VBox status code. 1357 * @retval VWRN_DBGF_ALREADY_HALTED if @a idCpu is VMCPUID_ALL and all vCPUs 1358 * are halted. 1233 1359 * @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 */ 1362 VMMR3DECL(int) DBGFR3Halt(PUVM pUVM, VMCPUID idCpu) 1236 1363 { 1237 1364 /* … … 1242 1369 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1243 1370 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. 1263 1411 * @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 */ 1415 VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM, VMCPUID idCpu) 1266 1416 { 1267 1417 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false); … … 1270 1420 AssertReturn(pVM->dbgf.s.fAttached, false); 1271 1421 1272 RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker; 1273 return enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED 1274 || enmSpeaker == RTPINGPONGSPEAKER_PONG; 1422 return dbgfR3CpuAreAnyHaltedByCpuId(pUVM, idCpu); 1275 1423 } 1276 1424 … … 1303 1451 return VERR_DBGF_NOT_ATTACHED; 1304 1452 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; */ 1308 1454 return VINF_SUCCESS; 1309 1455 } … … 1316 1462 * 1317 1463 * @returns VBox status code. 1464 * @retval VWRN_DBGF_ALREADY_RUNNING if the specified vCPUs are all running. 1318 1465 * @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 */ 1468 VMMR3DECL(int) DBGFR3Resume(PUVM pUVM, VMCPUID idCpu) 1469 { 1470 /* 1471 * Validate input and attachment state. 1324 1472 */ 1325 1473 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); … … 1327 1475 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1328 1476 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 } 1331 1491 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 } 1340 1505 1341 1506 return rc; … … 1621 1786 1622 1787 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))) 1624 1790 { /* likely */ } 1625 1791 else … … 1628 1794 1629 1795 /* 1630 * Send the ping back to the emulation thread telling it to run.1796 * Send the emulation thread a single-step command. 1631 1797 */ 1632 1798 if (fFlags == DBGF_STEP_F_INTO) … … 1654 1820 pVM->dbgf.s.SteppingFilter.uCallDepth = 0; 1655 1821 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); 1661 1824 } 1662 1825 -
trunk/src/VBox/VMM/include/DBGFInternal.h
r84766 r86098 578 578 DBGFCMD_GO, 579 579 /** 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 588 581 } DBGFCMD; 589 582 … … 806 799 */ 807 800 bool volatile fAttached; 808 809 /** Stopped in the Hypervisor.810 * Set if we're stopped on a trace, breakpoint or assertion inside811 * 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 side817 * 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 is824 * either a response to a command or to a break/watch point issued825 * 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 member832 * is set. The VMM will reset this member to the no-command state833 * when it have processed it.834 */835 DBGFCMD volatile enmVMMCmd;836 /** The Command data.837 * Not all commands take data. */838 DBGFCMDDATA VMMCmdData;839 801 840 802 /** Stepping filtering. */ … … 906 868 } BugCheck; 907 869 } DBGF; 908 AssertCompileMemberAlignment(DBGF, DbgEvent, 8);909 870 AssertCompileMemberAlignment(DBGF, aHwBreakpoints, 8); 910 871 AssertCompileMemberAlignment(DBGF, bmHardIntBreakpoints, 8); … … 1065 1026 PDBGFTRACERINSR3 pTracerR3; 1066 1027 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 1067 1048 /** The type database lock. */ 1068 1049 RTSEMRW hTypeDbLock; … … 1084 1065 { 1085 1066 /** The guest register set for this CPU. Can be NULL. */ 1086 R3PTRTYPE(struct DBGFREGSET *) pGuestRegSet;1067 R3PTRTYPE(struct DBGFREGSET *) pGuestRegSet; 1087 1068 /** 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 1089 1087 } DBGFUSERPERVMCPU; 1090 1088 -
trunk/src/VBox/VMM/testcase/tstVMStruct.h
r82968 r86098 275 275 GEN_CHECK_OFF(DBGF, cSelectedEvents); 276 276 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);282 277 //GEN_CHECK_OFF(DBGF, pInfoFirst); 283 278 //GEN_CHECK_OFF(DBGF, InfoCritSect);
Note:
See TracChangeset
for help on using the changeset viewer.