Index: /trunk/src/VBox/VMM/VMMR3/APIC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 61565)
+++ /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 61566)
@@ -405,9 +405,12 @@
  * Dumps basic APIC state.
  *
- * @param   pVCpu   The cross context virtual CPU structure.
- * @param   pHlp    The debug output helper.
- */
-static void apicR3DbgInfoBasic(PVMCPU pVCpu, PCDBGFINFOHLP pHlp)
-{
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pHlp        The info helpers.
+ * @param   pszArgs     Arguments, ignored.
+ */
+static DECLCALLBACK(void) apicR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    NOREF(pszArgs);
+    PVMCPU       pVCpu       = VMMGetCpu(pVM); AssertFatalMsg(pVCpu, ("Invalid EMT thread. pVCpu=%p\n", pVCpu));
     PCAPICCPU    pApicCpu    = VMCPU_TO_APICCPU(pVCpu);
     PCXAPICPAGE  pXApicPage  = VMCPU_TO_CXAPICPAGE(pVCpu);
@@ -499,5 +502,5 @@
  * @param   pHlp    The debug output helper.
  */
-static void apicR3DbgInfoLvtTimer(PVMCPU pVCpu, PCDBGFINFOHLP pHlp)
+static void apicR3InfoLvtTimer(PVMCPU pVCpu, PCDBGFINFOHLP pHlp)
 {
     PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
@@ -514,14 +517,17 @@
 
 /**
- * Dumps APIC Local Vector Table (LVT) state.
- *
- * @param   pVCpu   The cross context virtual CPU structure.
- * @param   pHlp    The debug output helper.
- */
-static void apicR3DbgInfoLvt(PVMCPU pVCpu, PCDBGFINFOHLP pHlp)
-{
+ * Dumps APIC Local Vector Table (LVT) information.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pHlp        The info helpers.
+ * @param   pszArgs     Arguments, ignored.
+ */
+static DECLCALLBACK(void) apicR3InfoLvt(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    NOREF(pszArgs);
+    PVMCPU      pVCpu      = VMMGetCpu(pVM); AssertFatalMsg(pVCpu, ("Invalid EMT thread. pVCpu=%p\n", pVCpu));
     PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
 
-    apicR3DbgInfoLvtTimer(pVCpu, pHlp);
+    apicR3InfoLvtTimer(pVCpu, pHlp);
 
 #if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
@@ -582,11 +588,14 @@
 
 /**
- * Dumps APIC Timer state.
- *
- * @param   pVCpu   The cross context virtual CPU structure.
- * @param   pHlp    The debug output helper.
- */
-static void apicR3DbgInfoTimer(PVMCPU pVCpu, PCDBGFINFOHLP pHlp)
-{
+ * Dumps the APIC timer information.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pHlp        The info helpers.
+ * @param   pszArgs     Arguments, ignored.
+ */
+static DECLCALLBACK(void) apicR3InfoTimer(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    NOREF(pszArgs);
+    PVMCPU      pVCpu      = VMMGetCpu(pVM); AssertFatalMsg(pVCpu, ("Invalid EMT thread. pVCpu=%p\n", pVCpu));
     PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
     PCAPICCPU   pApicCpu   = VMCPU_TO_APICCPU(pVCpu);
@@ -600,26 +609,5 @@
     pHlp->pfnPrintf(pHlp, "\n");
 
-    apicR3DbgInfoLvtTimer(pVCpu, pHlp);
-}
-
-
-/**
- * @callback_method_impl{FNDBGFHANDLERDEV,
- *      Dumps the APIC state according to given argument for debugging purposes.}
- */
-static DECLCALLBACK(void) apicR3DbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    PVM       pVM   = PDMDevHlpGetVM(pDevIns);
-    PVMCPU    pVCpu = VMMGetCpu(pVM);
-    Assert(pVCpu);
-
-    if (pszArgs == NULL || !*pszArgs || !strcmp(pszArgs, "basic"))
-        apicR3DbgInfoBasic(pVCpu, pHlp);
-    else if (!strcmp(pszArgs, "lvt"))
-        apicR3DbgInfoLvt(pVCpu, pHlp);
-    else if (!strcmp(pszArgs, "timer"))
-        apicR3DbgInfoTimer(pVCpu, pHlp);
-    else
-        pHlp->pfnPrintf(pHlp, "Invalid argument. Recognized arguments are 'basic', 'lvt', 'timer'\n");
+    apicR3InfoLvtTimer(pVCpu, pHlp);
 }
 
@@ -1644,8 +1632,13 @@
 
     /*
-     * Register debugger info callback.
-     */
-    rc = PDMDevHlpDBGFInfoRegister(pDevIns, "apic", "Display local APIC state for current CPU. Recognizes "
-                                                    "'basic', 'lvt', 'timer' as arguments, defaults to 'basic'.", apicR3DbgInfo);
+     * Register debugger info callbacks.
+     *
+     * We use separate callbacks rather than arguments so they can also be
+     * dumped in an automated fashion while collecting crash diagnostics and
+     * not just used during live debugging via the VM debugger.
+     */
+    rc  = DBGFR3InfoRegisterInternalEx(pVM, "apic",      "Dumps APIC basic information.", apicR3Info,      DBGFINFO_FLAGS_RUN_ON_EMT);
+    rc |= DBGFR3InfoRegisterInternalEx(pVM, "apiclvt",   "Dumps APIC LVT information.",   apicR3InfoLvt,   DBGFINFO_FLAGS_RUN_ON_EMT);
+    rc |= DBGFR3InfoRegisterInternalEx(pVM, "apictimer", "Dumps APIC timer information.", apicR3InfoTimer, DBGFINFO_FLAGS_RUN_ON_EMT);
     AssertRCReturn(rc, rc);
 
