Changeset 40405 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Mar 8, 2012 6:27:45 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 76724
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFR3Trace.cpp
r39405 r40405 5 5 6 6 /* 7 * Copyright (C) 2011 Oracle Corporation7 * Copyright (C) 2011-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 24 24 #include <VBox/vmm/cfgm.h> 25 25 #include <VBox/vmm/mm.h> 26 #include <VBox/vmm/pdmapi.h> 26 27 #include "DBGFInternal.h" 27 28 #include <VBox/vmm/vm.h> 29 #include "VMMTracing.h" 28 30 29 31 #include <VBox/err.h> … … 32 34 33 35 #include <iprt/assert.h> 36 #include <iprt/ctype.h> 34 37 #include <iprt/trace.h> 35 38 … … 39 42 *******************************************************************************/ 40 43 static DECLCALLBACK(void) dbgfR3TraceInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 44 45 46 /******************************************************************************* 47 * Global Variables * 48 *******************************************************************************/ 49 /** 50 * VMM trace point group translation table. 51 */ 52 static const struct 53 { 54 /** The mask. */ 55 uint32_t fMask; 56 /** The name length. */ 57 uint32_t cchName; 58 /** The group name. */ 59 const char *pszName; 60 } g_aVmmTpGroups[] = 61 { 62 { VMMTPGROUP_EM, RT_STR_TUPLE("em") }, 63 { VMMTPGROUP_HM, RT_STR_TUPLE("hm") }, 64 { VMMTPGROUP_TM, RT_STR_TUPLE("tm") }, 65 }; 41 66 42 67 … … 124 149 * Check the config and enable tracing if requested. 125 150 */ 151 PCFGMNODE pDbgfNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGF"); 126 152 #if defined(DEBUG) || defined(RTTRACE_ENABLED) 127 bool const fDefault = true; 153 bool const fDefault = true; 154 const char * const pszConfigDefault = "*"; 128 155 #else 129 bool const fDefault = false; 156 bool const fDefault = false; 157 const char * const pszConfigDefault = ""; 130 158 #endif 131 bool fTracingEnabled; 132 int rc = CFGMR3QueryBoolDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGF"), "TracingEnabled", 133 &fTracingEnabled, fDefault); 159 bool fTracingEnabled; 160 int rc = CFGMR3QueryBoolDef(pDbgfNode, "TracingEnabled", &fTracingEnabled, fDefault); 134 161 AssertRCReturn(rc, rc); 135 162 if (fTracingEnabled) 163 { 136 164 rc = dbgfR3TraceEnable(pVM, 0, 0); 165 if (RT_SUCCESS(rc)) 166 { 167 char *pszTracingConfig; 168 rc = CFGMR3QueryStringAllocDef(pDbgfNode, "TracingConfig", &pszTracingConfig, pszConfigDefault); 169 if (RT_SUCCESS(rc)) 170 { 171 rc = DBGFR3TraceConfig(pVM, pszTracingConfig); 172 if (RT_FAILURE(rc)) 173 rc = VMSetError(pVM, rc, RT_SRC_POS, "TracingConfig=\"%s\" -> %Rrc", pszTracingConfig, rc); 174 MMR3HeapFree(pszTracingConfig); 175 } 176 } 177 } 137 178 138 179 /* … … 167 208 if (pVM->hTraceBufR3 != NIL_RTTRACEBUF) 168 209 pVM->hTraceBufRC = MMHyperCCToRC(pVM, pVM->hTraceBufR3); 210 } 211 212 213 /** 214 * Change the traceing configuration of the VM. 215 * 216 * @returns VBox status code. 217 * @retval VINF_SUCCESS 218 * @retval VERR_NOT_FOUND if any of the trace point groups mentioned in the 219 * config string cannot be found. (Or if the string cannot be made 220 * sense of.) No change made. 221 * @retval VERR_INVALID_VM_HANDLE 222 * @retval VERR_INVALID_POINTER 223 * 224 * @param pVM The VM handle. 225 * @param pszConfig The configuration change specification. 226 * 227 * Trace point group names, optionally prefixed by a '-' to 228 * indicate that the group is being disabled. A special 229 * group 'all' can be used to enable or disable all trace 230 * points. 231 * 232 * Drivers, devices and USB devices each have their own 233 * trace point group which can be accessed by prefixing 234 * their official PDM name by 'drv', 'dev' or 'usb' 235 * respectively. 236 */ 237 VMMDECL(int) DBGFR3TraceConfig(PVM pVM, const char *pszConfig) 238 { 239 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 240 AssertPtrReturn(pszConfig, VERR_INVALID_POINTER); 241 if (pVM->hTraceBufR3 == NIL_RTTRACEBUF) 242 return VERR_DBGF_NO_TRACE_BUFFER; 243 244 /* 245 * We do this in two passes, the first pass just validates the input string 246 * and the second applies the changes. 247 */ 248 for (uint32_t uPass = 0; uPass < 1; uPass++) 249 { 250 char ch; 251 while ((ch = *pszConfig) != '\0') 252 { 253 if (RT_C_IS_SPACE(ch)) 254 continue; 255 256 /* 257 * Operation prefix. 258 */ 259 bool fNo = false; 260 do 261 { 262 if (ch == 'n' && pszConfig[1] == 'o') 263 { 264 fNo = !fNo; 265 pszConfig++; 266 } 267 else if (ch == '+') 268 fNo = false; 269 else if (ch == '-' || ch == '!' || ch == '~') 270 fNo = !fNo; 271 else 272 break; 273 } while ((ch = *++pszConfig) != '\0'); 274 if (ch == '\0') 275 break; 276 277 /* 278 * Extract the name. 279 */ 280 const char *pszName = pszConfig; 281 while ( ch != '\0' 282 && !RT_C_IS_SPACE(ch) 283 && !RT_C_IS_PUNCT(ch)) 284 ch = *++pszConfig; 285 size_t const cchName = pszConfig - pszName; 286 287 /* 288 * 'all' - special group that enables or disables all trace points. 289 */ 290 if (cchName == 3 && !strncmp(pszName, "all", 3)) 291 { 292 if (uPass != 0) 293 { 294 uint32_t iCpu = pVM->cCpus; 295 if (!fNo) 296 while (iCpu-- > 0) 297 pVM->aCpus[iCpu].fTraceGroups = UINT32_MAX; 298 else 299 while (iCpu-- > 0) 300 pVM->aCpus[iCpu].fTraceGroups = 0; 301 PDMR3TracingConfig(pVM, NULL, 0, !fNo, uPass > 0); 302 } 303 } 304 else 305 { 306 /* 307 * A specific group, try the VMM first then PDM. 308 */ 309 uint32_t i = RT_ELEMENTS(g_aVmmTpGroups); 310 while (i-- > 0) 311 if ( g_aVmmTpGroups[i].cchName == cchName 312 && !strncmp(g_aVmmTpGroups[i].pszName, pszName, cchName)) 313 { 314 if (uPass != 0) 315 { 316 uint32_t iCpu = pVM->cCpus; 317 if (!fNo) 318 while (iCpu-- > 0) 319 pVM->aCpus[iCpu].fTraceGroups |= g_aVmmTpGroups[i].fMask; 320 else 321 while (iCpu-- > 0) 322 pVM->aCpus[iCpu].fTraceGroups &= ~g_aVmmTpGroups[i].fMask; 323 } 324 break; 325 } 326 327 if (i == UINT32_MAX) 328 { 329 int rc = PDMR3TracingConfig(pVM, pszName, cchName, !fNo, uPass > 0); 330 if (RT_FAILURE(rc)) 331 return rc; 332 } 333 } 334 } 335 } 336 337 return VINF_SUCCESS; 338 } 339 340 341 /** 342 * Query the trace configuration specification string. 343 * 344 * @returns VBox status code. 345 * @retval VINF_SUCCESS 346 * @retval VERR_INVALID_VM_HANDLE 347 * @retval VERR_INVALID_POINTER 348 * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. Buffer will be 349 * empty. 350 351 * @param pVM The VM handle. 352 * @param pszConfig Pointer to the output buffer. 353 * @param cbConfig The size of the output buffer. 354 */ 355 VMMDECL(int) DBGFR3TraceQueryConfig(PVM pVM, char *pszConfig, size_t cbConfig) 356 { 357 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 358 AssertPtrReturn(pszConfig, VERR_INVALID_POINTER); 359 if (cbConfig < 1) 360 return VERR_BUFFER_OVERFLOW; 361 *pszConfig = '\0'; 362 363 if (pVM->hTraceBufR3 == NIL_RTTRACEBUF) 364 return VERR_DBGF_NO_TRACE_BUFFER; 365 366 int rc = VINF_SUCCESS; 367 uint32_t const fTraceGroups = pVM->aCpus[0].fTraceGroups; 368 if ( fTraceGroups == UINT32_MAX 369 && PDMR3TracingAreAll(pVM, true /*fEnabled*/)) 370 rc = RTStrCopy(pszConfig, cbConfig, "all"); 371 else if ( fTraceGroups == 0 372 && PDMR3TracingAreAll(pVM, false /*fEnabled*/)) 373 rc = RTStrCopy(pszConfig, cbConfig, "-all"); 374 else 375 { 376 char *pszDst = pszConfig; 377 size_t cbDst = cbConfig; 378 uint32_t i = RT_ELEMENTS(g_aVmmTpGroups); 379 while (i-- > 0) 380 if (g_aVmmTpGroups[i].fMask & fTraceGroups) 381 { 382 size_t cchThis = g_aVmmTpGroups[i].cchName + (pszDst != pszConfig); 383 if (cchThis >= cbDst) 384 { 385 rc = VERR_BUFFER_OVERFLOW; 386 break; 387 } 388 if (pszDst != pszConfig) 389 { 390 *pszDst = ' '; 391 memcpy(pszDst + 1, g_aVmmTpGroups[i].pszName, g_aVmmTpGroups[i].cchName + 1); 392 } 393 else 394 memcpy(pszDst, g_aVmmTpGroups[i].pszName, g_aVmmTpGroups[i].cchName + 1); 395 pszDst += cchThis; 396 cbDst -= cchThis; 397 } 398 399 if (RT_SUCCESS(rc)) 400 rc = PDMR3TracingQueryConfig(pVM, pszDst, cbDst); 401 } 402 403 if (RT_FAILURE(rc)) 404 *pszConfig = '\0'; 405 return rc; 169 406 } 170 407 -
trunk/src/VBox/VMM/VMMR3/PDM.cpp
r39839 r40405 2363 2363 2364 2364 /** 2365 * Worker for DBGFR3TraceConfig that checks if the given tracing group name 2366 * matches a device or driver name and applies the tracing config change. 2367 * 2368 * @returns VINF_SUCCESS or VERR_NOT_FOUND. 2369 * @param pVM The VM handle. 2370 * @param pszName The tracing config group name. This is NULL if 2371 * the operation applies to every device and 2372 * driver. 2373 * @param cchName The length to match. 2374 * @param fEnable Whether to enable or disable the corresponding 2375 * trace points. 2376 * @param fApply Whether to actually apply the changes or just do 2377 * existence checks. 2378 */ 2379 VMMR3_INT_DECL(int) PDMR3TracingConfig(PVM pVM, const char *pszName, size_t cchName, bool fEnable, bool fApply) 2380 { 2381 /** @todo This code is potentially racing driver attaching and detaching. */ 2382 2383 /* 2384 * Applies to all. 2385 */ 2386 if (pszName == NULL) 2387 { 2388 AssertReturn(fApply, VINF_SUCCESS); 2389 2390 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3) 2391 { 2392 pDevIns->fTraceing = fEnable; 2393 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext) 2394 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2395 pDrvIns->fTraceing = fEnable; 2396 } 2397 2398 #ifdef VBOX_WITH_USB 2399 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext) 2400 { 2401 pUsbIns->fTraceing = fEnable; 2402 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext) 2403 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2404 pDrvIns->fTraceing = fEnable; 2405 2406 } 2407 #endif 2408 return VINF_SUCCESS; 2409 } 2410 2411 /* 2412 * Specific devices, USB devices or drivers. 2413 * Decode prefix to figure which of these it applies to. 2414 */ 2415 if (cchName <= 3) 2416 return VERR_NOT_FOUND; 2417 2418 uint32_t cMatches = 0; 2419 if (!strncmp("dev", pszName, 3)) 2420 { 2421 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3) 2422 { 2423 const char *pszDevName = pDevIns->Internal.s.pDevR3->pReg->szName; 2424 size_t cchDevName = strlen(pszDevName); 2425 if ( ( cchDevName == cchName 2426 && RTStrNICmp(pszName, pszDevName, cchDevName)) 2427 || ( cchDevName == cchName - 3 2428 && RTStrNICmp(pszName + 3, pszDevName, cchDevName)) ) 2429 { 2430 cMatches++; 2431 if (fApply) 2432 pDevIns->fTraceing = fEnable; 2433 } 2434 } 2435 } 2436 else if (!strncmp("usb", pszName, 3)) 2437 { 2438 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext) 2439 { 2440 const char *pszUsbName = pUsbIns->Internal.s.pUsbDev->pReg->szName; 2441 size_t cchUsbName = strlen(pszUsbName); 2442 if ( ( cchUsbName == cchName 2443 && RTStrNICmp(pszName, pszUsbName, cchUsbName)) 2444 || ( cchUsbName == cchName - 3 2445 && RTStrNICmp(pszName + 3, pszUsbName, cchUsbName)) ) 2446 { 2447 cMatches++; 2448 if (fApply) 2449 pUsbIns->fTraceing = fEnable; 2450 } 2451 } 2452 } 2453 else if (!strncmp("drv", pszName, 3)) 2454 { 2455 AssertReturn(fApply, VINF_SUCCESS); 2456 2457 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3) 2458 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext) 2459 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2460 { 2461 const char *pszDrvName = pDrvIns->Internal.s.pDrv->pReg->szName; 2462 size_t cchDrvName = strlen(pszDrvName); 2463 if ( ( cchDrvName == cchName 2464 && RTStrNICmp(pszName, pszDrvName, cchDrvName)) 2465 || ( cchDrvName == cchName - 3 2466 && RTStrNICmp(pszName + 3, pszDrvName, cchDrvName)) ) 2467 { 2468 cMatches++; 2469 if (fApply) 2470 pDrvIns->fTraceing = fEnable; 2471 } 2472 } 2473 2474 #ifdef VBOX_WITH_USB 2475 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext) 2476 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext) 2477 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2478 { 2479 const char *pszDrvName = pDrvIns->Internal.s.pDrv->pReg->szName; 2480 size_t cchDrvName = strlen(pszDrvName); 2481 if ( ( cchDrvName == cchName 2482 && RTStrNICmp(pszName, pszDrvName, cchDrvName)) 2483 || ( cchDrvName == cchName - 3 2484 && RTStrNICmp(pszName + 3, pszDrvName, cchDrvName)) ) 2485 { 2486 cMatches++; 2487 if (fApply) 2488 pDrvIns->fTraceing = fEnable; 2489 } 2490 } 2491 #endif 2492 } 2493 else 2494 return VERR_NOT_FOUND; 2495 2496 return cMatches > 0 ? VINF_SUCCESS : VERR_NOT_FOUND; 2497 } 2498 2499 2500 /** 2501 * Worker for DBGFR3TraceQueryConfig that checks whether all drivers, devices, 2502 * and USB device have the same tracing settings. 2503 * 2504 * @returns true / false. 2505 * @param pVM The VM handle. 2506 * @param fEnabled The tracing setting to check for. 2507 */ 2508 VMMR3_INT_DECL(bool) PDMR3TracingAreAll(PVM pVM, bool fEnabled) 2509 { 2510 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3) 2511 { 2512 if (pDevIns->fTraceing != fEnabled) 2513 return false; 2514 2515 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext) 2516 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2517 if (pDrvIns->fTraceing != fEnabled) 2518 return false; 2519 } 2520 2521 #ifdef VBOX_WITH_USB 2522 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext) 2523 { 2524 if (pUsbIns->fTraceing != fEnabled) 2525 return false; 2526 2527 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext) 2528 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2529 if (pDrvIns->fTraceing != fEnabled) 2530 return false; 2531 } 2532 #endif 2533 2534 return true; 2535 } 2536 2537 2538 /** 2539 * Worker for PDMR3TracingQueryConfig that adds a prefixed name to the output 2540 * string. 2541 * 2542 * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW 2543 * @param ppszDst The pointer to the the output buffer pointer. 2544 * @param pcbDst The pointer to the output buffer size. 2545 * @param fSpace Whether to add a space before the name. 2546 * @param pszPrefix The name prefix. 2547 * @param pszName The name. 2548 */ 2549 static int pdmR3TracingAdd(char **ppszDst, size_t *pcbDst, bool fSpace, const char *pszPrefix, const char *pszName) 2550 { 2551 size_t const cchPrefix = strlen(pszPrefix); 2552 if (!RTStrNICmp(pszPrefix, pszName, cchPrefix)) 2553 pszName += cchPrefix; 2554 size_t const cchName = strlen(pszName); 2555 2556 size_t const cchThis = cchName + cchPrefix + fSpace; 2557 if (cchThis >= *pcbDst) 2558 return VERR_BUFFER_OVERFLOW; 2559 if (fSpace) 2560 { 2561 **ppszDst = ' '; 2562 memcpy(*ppszDst + 1, pszPrefix, cchPrefix); 2563 memcpy(*ppszDst + 1 + cchPrefix, pszName, cchName + 1); 2564 } 2565 else 2566 { 2567 memcpy(*ppszDst, pszPrefix, cchPrefix); 2568 memcpy(*ppszDst + cchPrefix, pszName, cchName + 1); 2569 } 2570 *ppszDst += cchThis; 2571 *pcbDst -= cchThis; 2572 return VINF_SUCCESS; 2573 } 2574 2575 2576 /** 2577 * Worker for DBGFR3TraceQueryConfig use when not everything is either enabled 2578 * or disabled. 2579 * 2580 * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW 2581 * @param pVM The VM handle. 2582 * @param pszConfig Where to store the config spec. 2583 * @param cbConfig The size of the output buffer. 2584 */ 2585 VMMR3_INT_DECL(int) PDMR3TracingQueryConfig(PVM pVM, char *pszConfig, size_t cbConfig) 2586 { 2587 int rc; 2588 char *pszDst = pszConfig; 2589 size_t cbDst = cbConfig; 2590 2591 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3) 2592 { 2593 if (pDevIns->fTraceing) 2594 { 2595 rc = pdmR3TracingAdd(&pszDst, &cbDst, pszDst != pszConfig, "dev", pDevIns->Internal.s.pDevR3->pReg->szName); 2596 if (RT_FAILURE(rc)) 2597 return rc; 2598 } 2599 2600 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext) 2601 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2602 if (pDrvIns->fTraceing) 2603 { 2604 rc = pdmR3TracingAdd(&pszDst, &cbDst, pszDst != pszConfig, "drv", pDrvIns->Internal.s.pDrv->pReg->szName); 2605 if (RT_FAILURE(rc)) 2606 return rc; 2607 } 2608 } 2609 2610 #ifdef VBOX_WITH_USB 2611 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext) 2612 { 2613 if (pUsbIns->fTraceing) 2614 { 2615 rc = pdmR3TracingAdd(&pszDst, &cbDst, pszDst != pszConfig, "usb", pUsbIns->Internal.s.pUsbDev->pReg->szName); 2616 if (RT_FAILURE(rc)) 2617 return rc; 2618 } 2619 2620 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext) 2621 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown) 2622 if (pDrvIns->fTraceing) 2623 { 2624 rc = pdmR3TracingAdd(&pszDst, &cbDst, pszDst != pszConfig, "drv", pDrvIns->Internal.s.pDrv->pReg->szName); 2625 if (RT_FAILURE(rc)) 2626 return rc; 2627 } 2628 } 2629 #endif 2630 2631 return VINF_SUCCESS; 2632 } 2633 2634 2635 /** 2365 2636 * Checks that a PDMDRVREG::szName, PDMDEVREG::szName or PDMUSBREG::szName 2366 2637 * field contains only a limited set of ASCII characters.
Note:
See TracChangeset
for help on using the changeset viewer.