Index: /trunk/include/VBox/vmm/pdmdev.h
===================================================================
--- /trunk/include/VBox/vmm/pdmdev.h	(revision 81937)
+++ /trunk/include/VBox/vmm/pdmdev.h	(revision 81938)
@@ -1436,5 +1436,5 @@
 
 /**
- * I/O APIC registration structure.
+ * I/O APIC registration structure (all contexts).
  */
 typedef struct PDMIOAPICREG
@@ -1454,11 +1454,5 @@
      *          Actually, as per 2018-07-21 this isn't true (bird).
      */
-    DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
-
-    /** The name of the RC SetIrq entry point. */
-    const char         *pszSetIrqRC;
-
-    /** The name of the R0 SetIrq entry point. */
-    const char         *pszSetIrqR0;
+    DECLCALLBACKMEMBER(void, pfnSetIrq)(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc);
 
     /**
@@ -1473,11 +1467,5 @@
      *          Actually, as per 2018-07-21 this isn't true (bird).
      */
-    DECLR3CALLBACKMEMBER(void, pfnSendMsiR3,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc));
-
-    /** The name of the RC SendMsi entry point. */
-    const char         *pszSendMsiRC;
-
-    /** The name of the R0 SendMsi entry point. */
-    const char         *pszSendMsiR0;
+    DECLCALLBACKMEMBER(void, pfnSendMsi)(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc);
 
     /**
@@ -1494,11 +1482,8 @@
      *          Actually, as per 2018-07-21 this isn't true (bird).
      */
-    DECLR3CALLBACKMEMBER(int, pfnSetEoiR3,(PPDMDEVINS pDevIns, uint8_t u8Vector));
-
-    /** The name of the RC SetEoi entry point. */
-    const char         *pszSetEoiRC;
-
-    /** The name of the R0 SetEoi entry point. */
-    const char         *pszSetEoiR0;
+    DECLCALLBACKMEMBER(int, pfnSetEoi)(PPDMDEVINS pDevIns, uint8_t u8Vector);
+
+    /** Just a safety precaution. */
+    uint32_t                u32TheEnd;
 } PDMIOAPICREG;
 /** Pointer to an APIC registration structure. */
@@ -1506,13 +1491,13 @@
 
 /** Current PDMAPICREG version number. */
-#define PDM_IOAPICREG_VERSION                   PDM_VERSION_MAKE(0xfff2, 5, 0)
-
-
-/**
- * IOAPIC RC helpers.
- */
-typedef struct PDMIOAPICHLPRC
-{
-    /** Structure version. PDM_IOAPICHLPRC_VERSION defines the current version. */
+#define PDM_IOAPICREG_VERSION                   PDM_VERSION_MAKE(0xfff2, 6, 0)
+
+
+/**
+ * IOAPIC helpers, same in all contexts.
+ */
+typedef struct PDMIOAPICHLP
+{
+    /** Structure version. PDM_IOAPICHLP_VERSION defines the current version. */
     uint32_t                u32Version;
 
@@ -1532,6 +1517,6 @@
      * @param   uTagSrc         The IRQ tag and source (for tracing).
      */
-    DECLRCCALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
-                                                  uint8_t uVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+    DECLCALLBACKMEMBER(int, pfnApicBusDeliver)(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
+                                               uint8_t uVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc);
 
     /**
@@ -1543,5 +1528,5 @@
      * @param   rc              What to return if we fail to acquire the lock.
      */
-    DECLRCCALLBACKMEMBER(int,   pfnLock,(PPDMDEVINS pDevIns, int rc));
+    DECLCALLBACKMEMBER(int,   pfnLock)(PPDMDEVINS pDevIns, int rc);
 
     /**
@@ -1550,147 +1535,16 @@
      * @param   pDevIns         The IOAPIC device instance.
      */
-    DECLRCCALLBACKMEMBER(void,  pfnUnlock,(PPDMDEVINS pDevIns));
+    DECLCALLBACKMEMBER(void,  pfnUnlock)(PPDMDEVINS pDevIns);
 
     /** Just a safety precaution. */
     uint32_t                u32TheEnd;
-} PDMIOAPICHLPRC;
-/** Pointer to IOAPIC RC helpers. */
-typedef RCPTRTYPE(PDMIOAPICHLPRC *) PPDMIOAPICHLPRC;
+} PDMIOAPICHLP;
+/** Pointer to IOAPIC helpers. */
+typedef PDMIOAPICHLP * PPDMIOAPICHLP;
 /** Pointer to const IOAPIC helpers. */
-typedef RCPTRTYPE(const PDMIOAPICHLPRC *) PCPDMIOAPICHLPRC;
-
-/** Current PDMIOAPICHLPRC version number. */
-#define PDM_IOAPICHLPRC_VERSION                 PDM_VERSION_MAKE(0xfff1, 2, 0)
-
-
-/**
- * IOAPIC R0 helpers.
- */
-typedef struct PDMIOAPICHLPR0
-{
-    /** Structure version. PDM_IOAPICHLPR0_VERSION defines the current version. */
-    uint32_t                u32Version;
-
-    /**
-     * Private interface between the IOAPIC and APIC.
-     *
-     * See comments about this hack on PDMAPICREG::pfnBusDeliverR3.
-     *
-     * @returns status code.
-     * @param   pDevIns         Device instance of the IOAPIC.
-     * @param   u8Dest          See APIC implementation.
-     * @param   u8DestMode      See APIC implementation.
-     * @param   u8DeliveryMode  See APIC implementation.
-     * @param   uVector         See APIC implementation.
-     * @param   u8Polarity      See APIC implementation.
-     * @param   u8TriggerMode   See APIC implementation.
-     * @param   uTagSrc         The IRQ tag and source (for tracing).
-     */
-    DECLR0CALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
-                                                  uint8_t uVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
-
-    /**
-     * Acquires the PDM lock.
-     *
-     * @returns VINF_SUCCESS on success.
-     * @returns rc if we failed to acquire the lock.
-     * @param   pDevIns         The IOAPIC device instance.
-     * @param   rc              What to return if we fail to acquire the lock.
-     */
-    DECLR0CALLBACKMEMBER(int,   pfnLock,(PPDMDEVINS pDevIns, int rc));
-
-    /**
-     * Releases the PDM lock.
-     *
-     * @param   pDevIns         The IOAPIC device instance.
-     */
-    DECLR0CALLBACKMEMBER(void,  pfnUnlock,(PPDMDEVINS pDevIns));
-
-    /** Just a safety precaution. */
-    uint32_t                u32TheEnd;
-} PDMIOAPICHLPR0;
-/** Pointer to IOAPIC R0 helpers. */
-typedef R0PTRTYPE(PDMIOAPICHLPR0 *) PPDMIOAPICHLPR0;
-/** Pointer to const IOAPIC helpers. */
-typedef R0PTRTYPE(const PDMIOAPICHLPR0 *) PCPDMIOAPICHLPR0;
-
-/** Current PDMIOAPICHLPR0 version number. */
-#define PDM_IOAPICHLPR0_VERSION                 PDM_VERSION_MAKE(0xfff0, 2, 0)
-
-/**
- * IOAPIC R3 helpers.
- */
-typedef struct PDMIOAPICHLPR3
-{
-    /** Structure version. PDM_IOAPICHLPR3_VERSION defines the current version. */
-    uint32_t                u32Version;
-
-    /**
-     * Private interface between the IOAPIC and APIC.
-     *
-     * See comments about this hack on PDMAPICREG::pfnBusDeliverR3.
-     *
-     * @returns status code
-     * @param   pDevIns         Device instance of the IOAPIC.
-     * @param   u8Dest          See APIC implementation.
-     * @param   u8DestMode      See APIC implementation.
-     * @param   u8DeliveryMode  See APIC implementation.
-     * @param   uVector         See APIC implementation.
-     * @param   u8Polarity      See APIC implementation.
-     * @param   u8TriggerMode   See APIC implementation.
-     * @param   uTagSrc         The IRQ tag and source (for tracing).
-     */
-    DECLR3CALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
-                                                  uint8_t uVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
-
-    /**
-     * Acquires the PDM lock.
-     *
-     * @returns VINF_SUCCESS on success.
-     * @returns Fatal error on failure.
-     * @param   pDevIns         The IOAPIC device instance.
-     * @param   rc              Dummy for making the interface identical to the GC and R0 versions.
-     */
-    DECLR3CALLBACKMEMBER(int,   pfnLock,(PPDMDEVINS pDevIns, int rc));
-
-    /**
-     * Releases the PDM lock.
-     *
-     * @param   pDevIns         The IOAPIC device instance.
-     */
-    DECLR3CALLBACKMEMBER(void,  pfnUnlock,(PPDMDEVINS pDevIns));
-
-    /**
-     * Gets the address of the RC IOAPIC helpers.
-     *
-     * This should be called at both construction and relocation time
-     * to obtain the correct address of the RC helpers.
-     *
-     * @returns RC pointer to the IOAPIC helpers.
-     * @param   pDevIns         Device instance of the IOAPIC.
-     */
-    DECLR3CALLBACKMEMBER(PCPDMIOAPICHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
-
-    /**
-     * Gets the address of the R0 IOAPIC helpers.
-     *
-     * This should be called at both construction and relocation time
-     * to obtain the correct address of the R0 helpers.
-     *
-     * @returns R0 pointer to the IOAPIC helpers.
-     * @param   pDevIns         Device instance of the IOAPIC.
-     */
-    DECLR3CALLBACKMEMBER(PCPDMIOAPICHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
-
-    /** Just a safety precaution. */
-    uint32_t                u32TheEnd;
-} PDMIOAPICHLPR3;
-/** Pointer to IOAPIC R3 helpers. */
-typedef R3PTRTYPE(PDMIOAPICHLPR3 *) PPDMIOAPICHLPR3;
-/** Pointer to const IOAPIC helpers. */
-typedef R3PTRTYPE(const PDMIOAPICHLPR3 *) PCPDMIOAPICHLPR3;
-
-/** Current PDMIOAPICHLPR3 version number. */
-#define PDM_IOAPICHLPR3_VERSION                 PDM_VERSION_MAKE(0xffef, 2, 0)
+typedef const PDMIOAPICHLP * PCPDMIOAPICHLP;
+
+/** Current PDMIOAPICHLP version number. */
+#define PDM_IOAPICHLP_VERSION                   PDM_VERSION_MAKE(0xfff0, 2, 0)
 
 
@@ -2144,5 +1998,5 @@
 
 /** Current PDMDEVHLPR3 version number. */
-#define PDM_DEVHLPR3_VERSION                    PDM_VERSION_MAKE_PP(0xffe7, 35, 0)
+#define PDM_DEVHLPR3_VERSION                    PDM_VERSION_MAKE_PP(0xffe7, 36, 0)
 
 /**
@@ -3919,8 +3773,8 @@
      * @param   pDevIns             The device instance.
      * @param   pIoApicReg          Pointer to a I/O APIC registration structure.
-     * @param   ppIoApicHlpR3       Where to store the pointer to the IOAPIC
+     * @param   ppIoApicHlp         Where to store the pointer to the IOAPIC
      *                              helpers.
      */
-    DECLR3CALLBACKMEMBER(int, pfnIOAPICRegister,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3));
+    DECLR3CALLBACKMEMBER(int, pfnIoApicRegister,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp));
 
     /**
@@ -4823,5 +4677,5 @@
 
     /**
-     * Sets up the PIC for the raw-mode context.
+     * Sets up the PIC for the ring-0 context.
      *
      * This must be called after ring-3 has registered the PIC using
@@ -4832,7 +4686,21 @@
      * @param   pPicReg     The PIC registration information for ring-0,
      *                      considered volatile and copied.
-     * @param   ppPicHlp    Where to return the raw-mode PIC helpers.
-     */
-    DECLRCCALLBACKMEMBER(int, pfnPCISetUpContext,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp));
+     * @param   ppPicHlp    Where to return the ring-0 PIC helpers.
+     */
+    DECLR0CALLBACKMEMBER(int, pfnPICSetUpContext,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp));
+
+    /**
+     * Sets up the IOAPIC for the ring-0 context.
+     *
+     * This must be called after ring-3 has registered the PIC using
+     * PDMDevHlpIoApicRegister().
+     *
+     * @returns VBox status code.
+     * @param   pDevIns     The device instance.
+     * @param   pIoApicReg  The PIC registration information for ring-0,
+     *                      considered volatile and copied.
+     * @param   ppIoApicHlp Where to return the ring-0 IOAPIC helpers.
+     */
+    DECLR0CALLBACKMEMBER(int, pfnIoApicSetUpContext,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp));
 
     /** Space reserved for future members.
@@ -4859,5 +4727,5 @@
 
 /** Current PDMDEVHLP version number. */
-#define PDM_DEVHLPRC_VERSION                    PDM_VERSION_MAKE(0xffe6, 11, 0)
+#define PDM_DEVHLPRC_VERSION                    PDM_VERSION_MAKE(0xffe6, 12, 0)
 
 
@@ -5315,4 +5183,18 @@
     DECLR0CALLBACKMEMBER(int, pfnPICSetUpContext,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp));
 
+    /**
+     * Sets up the IOAPIC for the ring-0 context.
+     *
+     * This must be called after ring-3 has registered the PIC using
+     * PDMDevHlpIoApicRegister().
+     *
+     * @returns VBox status code.
+     * @param   pDevIns     The device instance.
+     * @param   pIoApicReg  The PIC registration information for ring-0,
+     *                      considered volatile and copied.
+     * @param   ppIoApicHlp Where to return the ring-0 IOAPIC helpers.
+     */
+    DECLR0CALLBACKMEMBER(int, pfnIoApicSetUpContext,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp));
+
     /** Space reserved for future members.
      * @{ */
@@ -5338,5 +5220,5 @@
 
 /** Current PDMDEVHLP version number. */
-#define PDM_DEVHLPR0_VERSION                    PDM_VERSION_MAKE(0xffe5, 12, 0)
+#define PDM_DEVHLPR0_VERSION                    PDM_VERSION_MAKE(0xffe5, 13, 0)
 
 
@@ -7825,9 +7707,9 @@
 
 /**
- * @copydoc PDMDEVHLPR3::pfnIOAPICRegister
- */
-DECLINLINE(int) PDMDevHlpIOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
-{
-    return pDevIns->pHlpR3->pfnIOAPICRegister(pDevIns, pIoApicReg, ppIoApicHlpR3);
+ * @copydoc PDMDEVHLPR3::pfnIoApicRegister
+ */
+DECLINLINE(int) PDMDevHlpIoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+    return pDevIns->pHlpR3->pfnIoApicRegister(pDevIns, pIoApicReg, ppIoApicHlp);
 }
 
@@ -7970,4 +7852,12 @@
 {
     return pDevIns->CTX_SUFF(pHlp)->pfnPICSetUpContext(pDevIns, pPicReg, ppPicHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnIoApicSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpIoApicSetUpContext(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+    return pDevIns->CTX_SUFF(pHlp)->pfnIoApicSetUpContext(pDevIns, pIoApicReg, ppIoApicHlp);
 }
 
Index: /trunk/src/VBox/Devices/PC/DevIoApic.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/DevIoApic.cpp	(revision 81937)
+++ /trunk/src/VBox/Devices/PC/DevIoApic.cpp	(revision 81938)
@@ -185,17 +185,17 @@
 {
     /** The device instance - R3 Ptr. */
-    PPDMDEVINSR3            pDevInsR3;
+    PPDMDEVINSR3                pDevInsR3;
     /** The IOAPIC helpers - R3 Ptr. */
-    PCPDMIOAPICHLPR3        pIoApicHlpR3;
+    R3PTRTYPE(PCPDMIOAPICHLP)   pIoApicHlpR3;
 
     /** The device instance - R0 Ptr. */
-    PPDMDEVINSR0            pDevInsR0;
+    PPDMDEVINSR0                pDevInsR0;
     /** The IOAPIC helpers - R0 Ptr. */
-    PCPDMIOAPICHLPR0        pIoApicHlpR0;
+    R0PTRTYPE(PCPDMIOAPICHLP)   pIoApicHlpR0;
 
     /** The device instance - RC Ptr. */
-    PPDMDEVINSRC            pDevInsRC;
+    PPDMDEVINSRC                pDevInsRC;
     /** The IOAPIC helpers - RC Ptr. */
-    PCPDMIOAPICHLPRC        pIoApicHlpRC;
+    RCPTRTYPE(PCPDMIOAPICHLP)   pIoApicHlpRC;
 
     /** The ID register. */
@@ -1136,5 +1136,5 @@
 
     pThis->pDevInsRC    = PDMDEVINS_2_RCPTR(pDevIns);
-    pThis->pIoApicHlpRC = pThis->pIoApicHlpR3->pfnGetRCHelpers(pDevIns);
+    pThis->pIoApicHlpRC += offDelta;
 }
 
@@ -1169,5 +1169,6 @@
 {
     PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
-    PIOAPIC pThis = PDMDEVINS_2_DATA(pDevIns, PIOAPIC);
+    PIOAPIC         pThis = PDMDEVINS_2_DATA(pDevIns, PIOAPIC);
+    PCPDMDEVHLPR3   pHlp  = pDevIns->pHlpR3;
     LogFlow(("IOAPIC: ioapicR3Construct: pThis=%p iInstance=%d\n", pThis, iInstance));
     Assert(iInstance == 0); RT_NOREF(iInstance);
@@ -1183,21 +1184,16 @@
      * Validate and read the configuration.
      */
-    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "NumCPUs|RZEnabled|ChipType", "");
+    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "NumCPUs|ChipType", "");
 
     /* The number of CPUs is currently unused, but left in CFGM and saved-state in case an ID of 0 is
        upsets some guest which we haven't yet tested. */
     uint32_t cCpus;
-    int rc = CFGMR3QueryU32Def(pCfg, "NumCPUs", &cCpus, 1);
+    int rc = pHlp->pfnCFGMQueryU32Def(pCfg, "NumCPUs", &cCpus, 1);
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query integer value \"NumCPUs\""));
     pThis->cCpus = (uint8_t)cCpus;
 
-    bool fRZEnabled;
-    rc = CFGMR3QueryBoolDef(pCfg, "RZEnabled", &fRZEnabled, true);
-    if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query boolean value \"RZEnabled\""));
-
     char szChipType[16];
-    rc = CFGMR3QueryStringDef(pCfg, "ChipType", &szChipType[0], sizeof(szChipType), "ICH9");
+    rc = pHlp->pfnCFGMQueryStringDef(pCfg, "ChipType", &szChipType[0], sizeof(szChipType), "ICH9");
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query string value \"ChipType\""));
@@ -1235,10 +1231,7 @@
     }
     else
-    {
         return PDMDevHlpVMSetError(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, RT_SRC_POS,
-                                   N_("I/O APIC configuration error: The \"ChipType\" value \"%s\" is unsupported"),
-                                   szChipType);
-    }
-    Log2(("IOAPIC: cCpus=%u fRZEnabled=%RTbool szChipType=%s\n", cCpus, fRZEnabled, szChipType));
+                                   N_("I/O APIC configuration error: The \"ChipType\" value \"%s\" is unsupported"), szChipType);
+    Log2(("IOAPIC: cCpus=%u fRZEnabled=%RTbool szChipType=%s\n", cCpus, pDevIns->fR0Enabled | pDevIns->fRCEnabled, szChipType));
 
     /*
@@ -1253,6 +1246,5 @@
      */
     rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "IOAPIC");
-    if (RT_FAILURE(rc))
-        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("IOAPIC: Failed to create critical section. rc=%Rrc"), rc);
+    AssertRCReturn(rc, rc);
 # endif
 
@@ -1261,26 +1253,11 @@
      */
     PDMIOAPICREG IoApicReg;
-    RT_ZERO(IoApicReg);
     IoApicReg.u32Version   = PDM_IOAPICREG_VERSION;
-    IoApicReg.pfnSetIrqR3  = ioapicSetIrq;
-    IoApicReg.pfnSendMsiR3 = ioapicSendMsi;
-    IoApicReg.pfnSetEoiR3  = ioapicSetEoi;
-    if (fRZEnabled)
-    {
-        IoApicReg.pszSetIrqRC  = "ioapicSetIrq";
-        IoApicReg.pszSetIrqR0  = "ioapicSetIrq";
-
-        IoApicReg.pszSendMsiRC = "ioapicSendMsi";
-        IoApicReg.pszSendMsiR0 = "ioapicSendMsi";
-
-        IoApicReg.pszSetEoiRC = "ioapicSetEoi";
-        IoApicReg.pszSetEoiR0 = "ioapicSetEoi";
-    }
-    rc = PDMDevHlpIOAPICRegister(pDevIns, &IoApicReg, &pThis->pIoApicHlpR3);
-    if (RT_FAILURE(rc))
-    {
-        AssertMsgFailed(("IOAPIC: PDMDevHlpIOAPICRegister failed! rc=%Rrc\n", rc));
-        return rc;
-    }
+    IoApicReg.pfnSetIrq    = ioapicSetIrq;
+    IoApicReg.pfnSendMsi   = ioapicSendMsi;
+    IoApicReg.pfnSetEoi    = ioapicSetEoi;
+    IoApicReg.u32TheEnd    = PDM_IOAPICREG_VERSION;
+    rc = PDMDevHlpIoApicRegister(pDevIns, &IoApicReg, &pThis->pIoApicHlpR3);
+    AssertRCReturn(rc, rc);
 
     /*
@@ -1290,23 +1267,14 @@
                                IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_DWORD_ZEROED, ioapicMmioWrite, ioapicMmioRead,
                                "I/O APIC");
-    if (RT_SUCCESS(rc))
+    AssertRCReturn(rc, rc);
+    if (pDevIns->fR0Enabled | pDevIns->fRCEnabled)
     {
-        if (fRZEnabled)
-        {
-            pThis->pIoApicHlpRC = pThis->pIoApicHlpR3->pfnGetRCHelpers(pDevIns);
-            rc = PDMDevHlpMMIORegisterRC(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, NIL_RTRCPTR /* pvUser */,
-                                         "ioapicMmioWrite", "ioapicMmioRead");
-            AssertRCReturn(rc, rc);
-
-            pThis->pIoApicHlpR0 = pThis->pIoApicHlpR3->pfnGetR0Helpers(pDevIns);
-            rc = PDMDevHlpMMIORegisterR0(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, NIL_RTR0PTR /* pvUser */,
-                                         "ioapicMmioWrite", "ioapicMmioRead");
-            AssertRCReturn(rc, rc);
-        }
-    }
-    else
-    {
-        LogRel(("IOAPIC: PDMDevHlpMMIORegister failed! rc=%Rrc\n", rc));
-        return rc;
+        rc = PDMDevHlpMMIORegisterRC(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, NIL_RTRCPTR /* pvUser */,
+                                     "ioapicMmioWrite", "ioapicMmioRead");
+        AssertRCReturn(rc, rc);
+
+        rc = PDMDevHlpMMIORegisterR0(pDevIns, IOAPIC_MMIO_BASE_PHYSADDR, IOAPIC_MMIO_SIZE, NIL_RTR0PTR /* pvUser */,
+                                     "ioapicMmioWrite", "ioapicMmioRead");
+        AssertRCReturn(rc, rc);
     }
 
@@ -1315,9 +1283,5 @@
      */
     rc = PDMDevHlpSSMRegister(pDevIns, IOAPIC_SAVED_STATE_VERSION, sizeof(*pThis), ioapicR3SaveExec, ioapicR3LoadExec);
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("IOAPIC: PDMDevHlpSSMRegister failed! rc=%Rrc\n", rc));
-        return rc;
-    }
+    AssertRCReturn(rc, rc);
 
     /*
@@ -1337,23 +1301,23 @@
      * Statistics.
      */
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReadRZ,  STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/MmioReadRZ",  STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in RZ.");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWriteRZ, STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/MmioWriteRZ", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in RZ.");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqRZ,    STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/SetIrqRZ",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in RZ.");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiRZ,    STAMTYPE_COUNTER, "/Devices/IOAPIC/RZ/SetEoiRZ",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in RZ.");
-
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReadR3,  STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/MmioReadR3",  STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in R3");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWriteR3, STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/MmioWriteR3", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in R3.");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqR3,    STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/SetIrqR3",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in R3.");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiR3,    STAMTYPE_COUNTER, "/Devices/IOAPIC/R3/SetEoiR3",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in R3.");
-
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantEdgeIntr,   STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantEdgeIntr",   STAMUNIT_OCCURENCES, "Number of redundant edge-triggered interrupts (no IRR change).");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr,  STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantLevelIntr",  STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change).");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR.");
-
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiContention,    STAMTYPE_COUNTER, "/Devices/IOAPIC/CritSect/ContentionSetEoi", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during EOI writes causing trips to R3.");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetRteContention, STAMTYPE_COUNTER, "/Devices/IOAPIC/CritSect/ContentionSetRte", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during RTE writes causing trips to R3.");
-
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatLevelIrqSent, STAMTYPE_COUNTER, "/Devices/IOAPIC/LevelIntr/Sent", STAMUNIT_OCCURENCES, "Number of level-triggered interrupts sent to the local APIC(s).");
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiReceived,  STAMTYPE_COUNTER, "/Devices/IOAPIC/LevelIntr/Recv", STAMUNIT_OCCURENCES, "Number of EOIs received for level-triggered interrupts from the local APIC(s).");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReadRZ,  STAMTYPE_COUNTER, "RZ/MmioReadRZ",  STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in RZ.");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWriteRZ, STAMTYPE_COUNTER, "RZ/MmioWriteRZ", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in RZ.");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqRZ,    STAMTYPE_COUNTER, "RZ/SetIrqRZ",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in RZ.");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiRZ,    STAMTYPE_COUNTER, "RZ/SetEoiRZ",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in RZ.");
+
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioReadR3,  STAMTYPE_COUNTER, "R3/MmioReadR3",  STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in R3");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMmioWriteR3, STAMTYPE_COUNTER, "R3/MmioWriteR3", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in R3.");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqR3,    STAMTYPE_COUNTER, "R3/SetIrqR3",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in R3.");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiR3,    STAMTYPE_COUNTER, "R3/SetEoiR3",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in R3.");
+
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantEdgeIntr,   STAMTYPE_COUNTER, "RedundantEdgeIntr",   STAMUNIT_OCCURENCES, "Number of redundant edge-triggered interrupts (no IRR change).");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr,  STAMTYPE_COUNTER, "RedundantLevelIntr",  STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change).");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR.");
+
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiContention,    STAMTYPE_COUNTER, "CritSect/ContentionSetEoi", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during EOI writes causing trips to R3.");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetRteContention, STAMTYPE_COUNTER, "CritSect/ContentionSetRte", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during RTE writes causing trips to R3.");
+
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatLevelIrqSent, STAMTYPE_COUNTER, "LevelIntr/Sent", STAMUNIT_OCCURENCES, "Number of level-triggered interrupts sent to the local APIC(s).");
+    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiReceived,  STAMTYPE_COUNTER, "LevelIntr/Recv", STAMUNIT_OCCURENCES, "Number of EOIs received for level-triggered interrupts from the local APIC(s).");
 # endif
 
@@ -1367,5 +1331,30 @@
 }
 
-#endif /* IN_RING3 */
+#else /* !IN_RING3 */
+
+/**
+ * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
+ */
+static DECLCALLBACK(int) ioapicRZConstruct(PPDMDEVINS pDevIns)
+{
+    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+    PIOAPIC pThis = PDMDEVINS_2_DATA(pDevIns, PIOAPIC);
+
+    int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+    AssertRCReturn(rc, rc);
+
+    PDMIOAPICREG IoApicReg;
+    IoApicReg.u32Version   = PDM_IOAPICREG_VERSION;
+    IoApicReg.pfnSetIrq    = ioapicSetIrq;
+    IoApicReg.pfnSendMsi   = ioapicSendMsi;
+    IoApicReg.pfnSetEoi    = ioapicSetEoi;
+    IoApicReg.u32TheEnd    = PDM_IOAPICREG_VERSION;
+    rc = PDMDevHlpIoApicSetUpContext(pDevIns, &IoApicReg, &pThis->CTX_SUFF(pIoApicHlp));
+    AssertRCReturn(rc, rc);
+
+    return VINF_SUCCESS;
+}
+
+#endif /* !IN_RING3 */
 
 /**
@@ -1414,5 +1403,5 @@
 #elif defined(IN_RING0)
     /* .pfnEarlyConstruct = */      NULL,
-    /* .pfnConstruct = */           NULL,
+    /* .pfnConstruct = */           ioapicRZConstruct,
     /* .pfnDestruct = */            NULL,
     /* .pfnFinalDestruct = */       NULL,
@@ -1427,5 +1416,5 @@
     /* .pfnReserved7 = */           NULL,
 #elif defined(IN_RC)
-    /* .pfnConstruct = */           NULL,
+    /* .pfnConstruct = */           ioapicRZConstruct,
     /* .pfnReserved0 = */           NULL,
     /* .pfnReserved1 = */           NULL,
Index: /trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp	(revision 81937)
+++ /trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp	(revision 81938)
@@ -55,5 +55,5 @@
 extern DECLEXPORT(const PDMDEVHLPR0)    g_pdmR0DevHlp;
 extern DECLEXPORT(const PDMPICHLP)      g_pdmR0PicHlp;
-extern DECLEXPORT(const PDMIOAPICHLPR0) g_pdmR0IoApicHlp;
+extern DECLEXPORT(const PDMIOAPICHLP)   g_pdmR0IoApicHlp;
 extern DECLEXPORT(const PDMPCIHLPR0)    g_pdmR0PciHlp;
 extern DECLEXPORT(const PDMHPETHLPR0)   g_pdmR0HpetHlp;
@@ -1110,10 +1110,10 @@
     AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
                     ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
-                    VERR_INVALID_PARAMETER);
+                    VERR_VERSION_MISMATCH);
     AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
     AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
     AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
                     ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
-                    VERR_INVALID_PARAMETER);
+                    VERR_VERSION_MISMATCH);
     AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
 
@@ -1140,4 +1140,53 @@
     *ppPicHlp = &g_pdmR0PicHlp;
     LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+    return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnIoApicSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_IoApicSetUpContext(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+    PDMDEV_ASSERT_DEVINS(pDevIns);
+    LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
+             pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
+    PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+    /*
+     * Validate input.
+     */
+    AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
+                    ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
+                    VERR_VERSION_MISMATCH);
+    AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
+    AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
+    AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
+    AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
+                    ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
+                    VERR_VERSION_MISMATCH);
+    AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
+
+    VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+    VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+    /* Check that it's the same device as made the ring-3 registrations: */
+    AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR3 == pDevIns->pDevInsForR3,
+                          ("%p vs %p\n", pGVM->pdm.s.IoApic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
+
+    /* Check that it isn't already registered in ring-0: */
+    AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.IoApic.pDevInsR0, pDevIns),
+                          VERR_ALREADY_EXISTS);
+
+    /*
+     * Take down the callbacks and instance.
+     */
+    pGVM->pdm.s.IoApic.pDevInsR0    = pDevIns;
+    pGVM->pdm.s.IoApic.pfnSetIrqR0  = pIoApicReg->pfnSetIrq;
+    pGVM->pdm.s.IoApic.pfnSendMsiR0 = pIoApicReg->pfnSendMsi;
+    pGVM->pdm.s.IoApic.pfnSetEoiR0  = pIoApicReg->pfnSetEoi;
+    Log(("PDM: Registered IOAPIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+    /* set the helper pointer and return. */
+    *ppIoApicHlp = &g_pdmR0IoApicHlp;
+    LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
     return VINF_SUCCESS;
 }
@@ -1222,4 +1271,5 @@
     pdmR0DevHlp_PCIBusSetUpContext,
     pdmR0DevHlp_PICSetUpContext,
+    pdmR0DevHlp_IoApicSetUpContext,
     NULL /*pfnReserved1*/,
     NULL /*pfnReserved2*/,
@@ -1302,5 +1352,5 @@
  */
 
-/** @interface_method_impl{PDMIOAPICHLPR0,pfnApicBusDeliver} */
+/** @interface_method_impl{PDMIOAPICHLP,pfnApicBusDeliver} */
 static DECLCALLBACK(int) pdmR0IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
                                                        uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
@@ -1315,5 +1365,5 @@
 
 
-/** @interface_method_impl{PDMIOAPICHLPR0,pfnLock} */
+/** @interface_method_impl{PDMIOAPICHLP,pfnLock} */
 static DECLCALLBACK(int) pdmR0IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
 {
@@ -1323,5 +1373,5 @@
 
 
-/** @interface_method_impl{PDMIOAPICHLPR0,pfnUnlock} */
+/** @interface_method_impl{PDMIOAPICHLP,pfnUnlock} */
 static DECLCALLBACK(void) pdmR0IoApicHlp_Unlock(PPDMDEVINS pDevIns)
 {
@@ -1334,11 +1384,11 @@
  * The Ring-0 I/O APIC Helper Callbacks.
  */
-extern DECLEXPORT(const PDMIOAPICHLPR0) g_pdmR0IoApicHlp =
-{
-    PDM_IOAPICHLPR0_VERSION,
+extern DECLEXPORT(const PDMIOAPICHLP) g_pdmR0IoApicHlp =
+{
+    PDM_IOAPICHLP_VERSION,
     pdmR0IoApicHlp_ApicBusDeliver,
     pdmR0IoApicHlp_Lock,
     pdmR0IoApicHlp_Unlock,
-    PDM_IOAPICHLPR0_VERSION
+    PDM_IOAPICHLP_VERSION
 };
 
Index: /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp	(revision 81937)
+++ /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp	(revision 81938)
@@ -3756,76 +3756,25 @@
 
 
-/** @interface_method_impl{PDMDEVHLPR3,pfnIOAPICRegister} */
-static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
 {
     PDMDEV_ASSERT_DEVINS(pDevIns);
     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
-    LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
-             pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
-             pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
+    LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
+             pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
 
     /*
      * Validate input.
      */
-    if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
-    {
-        AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (!pIoApicReg->pfnSetIrqR3 || !pIoApicReg->pfnSendMsiR3 || !pIoApicReg->pfnSetEoiR3)
-    {
-        Assert(pIoApicReg->pfnSetIrqR3);
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (    pIoApicReg->pszSetIrqRC
-        &&  !VALID_PTR(pIoApicReg->pszSetIrqRC))
-    {
-        Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (    pIoApicReg->pszSendMsiRC
-        &&  !VALID_PTR(pIoApicReg->pszSendMsiRC))
-    {
-        Assert(VALID_PTR(pIoApicReg->pszSendMsiRC));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (    pIoApicReg->pszSetEoiRC
-        &&  !VALID_PTR(pIoApicReg->pszSetEoiRC))
-    {
-        Assert(VALID_PTR(pIoApicReg->pszSetEoiRC));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (    pIoApicReg->pszSetIrqR0
-        &&  !VALID_PTR(pIoApicReg->pszSetIrqR0))
-    {
-        Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (    pIoApicReg->pszSendMsiR0
-        &&  !VALID_PTR(pIoApicReg->pszSendMsiR0))
-    {
-        Assert(VALID_PTR(pIoApicReg->pszSendMsiR0));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (    pIoApicReg->pszSetEoiR0
-        &&  !VALID_PTR(pIoApicReg->pszSetEoiR0))
-    {
-        Assert(VALID_PTR(pIoApicReg->pszSetEoiR0));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-    if (!ppIoApicHlpR3)
-    {
-        Assert(ppIoApicHlpR3);
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (ppApicHlp)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
+    AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
+                    ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
+                    VERR_VERSION_MISMATCH);
+    AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
+    AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
+    AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
+    AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
+                    ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
+                    VERR_VERSION_MISMATCH);
+    AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
 
     /*
@@ -3834,144 +3783,25 @@
      */
     PVM pVM = pDevIns->Internal.s.pVMR3;
-    if (!pVM->pdm.s.Apic.pDevInsR3)
-    {
-        AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-#if 0
-    if (    pIoApicReg->pszSetIrqRC
-        &&  !pVM->pdm.s.Apic.pDevInsRC)
-    {
-        AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no GC APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-#endif
+    AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 != NULL, ("Configuration error / Init order error! No APIC!\n"), VERR_WRONG_ORDER);
 
     /*
      * Only one I/O APIC device.
      */
-    if (pVM->pdm.s.IoApic.pDevInsR3)
-    {
-        AssertMsgFailed(("Only one ioapic device is supported!\n"));
-        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (only one)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
-        return VERR_INVALID_PARAMETER;
-    }
-
-    /*
-     * Resolve & initialize the GC bits.
-     */
-    if (pIoApicReg->pszSetIrqRC)
-    {
-        int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
-        AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetIrqRC, rc));
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
-            return rc;
-        }
-        pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
-    }
-    else
-    {
-        pVM->pdm.s.IoApic.pDevInsRC   = 0;
-        pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
-    }
-
-    if (pIoApicReg->pszSendMsiRC)
-    {
-        int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSendMsiRC, &pVM->pdm.s.IoApic.pfnSendMsiRC);
-        AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSendMsiRC, rc));
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
-            return rc;
-        }
-    }
-    else
-    {
-        pVM->pdm.s.IoApic.pfnSendMsiRC = 0;
-    }
-
-    if (pIoApicReg->pszSetEoiRC)
-    {
-        int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetEoiRC, &pVM->pdm.s.IoApic.pfnSetEoiRC);
-        AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetEoiRC, rc));
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
-            return rc;
-        }
-    }
-    else
-    {
-        pVM->pdm.s.IoApic.pfnSetEoiRC = 0;
-    }
-
-    /*
-     * Resolve & initialize the R0 bits.
-     */
-    if (pIoApicReg->pszSetIrqR0)
-    {
-        int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
-        AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetIrqR0, rc));
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
-            return rc;
-        }
-        pVM->pdm.s.IoApic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
-        Assert(pVM->pdm.s.IoApic.pDevInsR0);
-    }
-    else
-    {
-        pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
-        pVM->pdm.s.IoApic.pDevInsR0   = 0;
-    }
-
-    if (pIoApicReg->pszSendMsiR0)
-    {
-        int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSendMsiR0, &pVM->pdm.s.IoApic.pfnSendMsiR0);
-        AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSendMsiR0, rc));
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
-            return rc;
-        }
-    }
-    else
-    {
-        pVM->pdm.s.IoApic.pfnSendMsiR0 = 0;
-    }
-
-    if (pIoApicReg->pszSetEoiR0)
-    {
-        int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetEoiR0, &pVM->pdm.s.IoApic.pfnSetEoiR0);
-        AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetEoiR0, rc));
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
-            return rc;
-        }
-    }
-    else
-    {
-        pVM->pdm.s.IoApic.pfnSetEoiR0 = 0;
-    }
-
+    AssertMsgReturn(pVM->pdm.s.IoApic.pDevInsR3 == NULL,
+                    ("Only one ioapic device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
+                    VERR_ALREADY_EXISTS);
 
     /*
      * Initialize the R3 bits.
      */
-    pVM->pdm.s.IoApic.pDevInsR3   = pDevIns;
-    pVM->pdm.s.IoApic.pfnSetIrqR3  = pIoApicReg->pfnSetIrqR3;
-    pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsiR3;
-    pVM->pdm.s.IoApic.pfnSetEoiR3  = pIoApicReg->pfnSetEoiR3;
+    pVM->pdm.s.IoApic.pDevInsR3    = pDevIns;
+    pVM->pdm.s.IoApic.pfnSetIrqR3  = pIoApicReg->pfnSetIrq;
+    pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsi;
+    pVM->pdm.s.IoApic.pfnSetEoiR3  = pIoApicReg->pfnSetEoi;
     Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
 
     /* set the helper pointer and return. */
-    *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
-    LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+    *ppIoApicHlp = &g_pdmR3DevIoApicHlp;
+    LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
     return VINF_SUCCESS;
 }
@@ -4727,5 +4557,5 @@
     pdmR3DevHlp_PICRegister,
     pdmR3DevHlp_APICRegister,
-    pdmR3DevHlp_IOAPICRegister,
+    pdmR3DevHlp_IoApicRegister,
     pdmR3DevHlp_HPETRegister,
     pdmR3DevHlp_PciRawRegister,
@@ -5223,5 +5053,5 @@
     pdmR3DevHlp_PICRegister,
     pdmR3DevHlp_APICRegister,
-    pdmR3DevHlp_IOAPICRegister,
+    pdmR3DevHlp_IoApicRegister,
     pdmR3DevHlp_HPETRegister,
     pdmR3DevHlp_PciRawRegister,
Index: /trunk/src/VBox/VMM/VMMR3/PDMDevMiscHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMDevMiscHlp.cpp	(revision 81937)
+++ /trunk/src/VBox/VMM/VMMR3/PDMDevMiscHlp.cpp	(revision 81938)
@@ -109,5 +109,5 @@
  */
 
-/** @interface_method_impl{PDMIOAPICHLPR3,pfnApicBusDeliver} */
+/** @interface_method_impl{PDMIOAPICHLP,pfnApicBusDeliver} */
 static DECLCALLBACK(int) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
                                                        uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
@@ -122,5 +122,5 @@
 
 
-/** @interface_method_impl{PDMIOAPICHLPR3,pfnLock} */
+/** @interface_method_impl{PDMIOAPICHLP,pfnLock} */
 static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
 {
@@ -131,5 +131,5 @@
 
 
-/** @interface_method_impl{PDMIOAPICHLPR3,pfnUnlock} */
+/** @interface_method_impl{PDMIOAPICHLP,pfnUnlock} */
 static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
 {
@@ -140,53 +140,14 @@
 
 
-/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetRCHelpers} */
-static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
-{
-    PDMDEV_ASSERT_DEVINS(pDevIns);
-    PVM pVM = pDevIns->Internal.s.pVMR3;
-    VM_ASSERT_EMT(pVM);
-
-    RTRCPTR pRCHelpers = NIL_RTRCPTR;
-    if (VM_IS_RAW_MODE_ENABLED(pVM))
-    {
-        int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCIoApicHlp", &pRCHelpers);
-        AssertReleaseRC(rc);
-        AssertRelease(pRCHelpers);
-    }
-
-    LogFlow(("pdmR3IoApicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
-             pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
-    return pRCHelpers;
-}
-
-
-/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetR0Helpers} */
-static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
-{
-    PDMDEV_ASSERT_DEVINS(pDevIns);
-    PVM pVM = pDevIns->Internal.s.pVMR3;
-    VM_ASSERT_EMT(pVM);
-    PCPDMIOAPICHLPR0 pR0Helpers = 0;
-    int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
-    AssertReleaseRC(rc);
-    AssertRelease(pR0Helpers);
-    LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
-             pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
-    return pR0Helpers;
-}
-
-
 /**
  * I/O APIC Device Helpers.
  */
-const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
-{
-    PDM_IOAPICHLPR3_VERSION,
+const PDMIOAPICHLP g_pdmR3DevIoApicHlp =
+{
+    PDM_IOAPICHLP_VERSION,
     pdmR3IoApicHlp_ApicBusDeliver,
     pdmR3IoApicHlp_Lock,
     pdmR3IoApicHlp_Unlock,
-    pdmR3IoApicHlp_GetRCHelpers,
-    pdmR3IoApicHlp_GetR0Helpers,
-    PDM_IOAPICHLPR3_VERSION /* the end */
+    PDM_IOAPICHLP_VERSION /* the end */
 };
 
Index: /trunk/src/VBox/VMM/include/PDMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/PDMInternal.h	(revision 81937)
+++ /trunk/src/VBox/VMM/include/PDMInternal.h	(revision 81938)
@@ -1389,5 +1389,5 @@
 extern const PDMDEVHLPR3    g_pdmR3DevHlpUnTrusted;
 extern const PDMPICHLP      g_pdmR3DevPicHlp;
-extern const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp;
+extern const PDMIOAPICHLP   g_pdmR3DevIoApicHlp;
 extern const PDMFWHLPR3     g_pdmR3DevFirmwareHlp;
 extern const PDMPCIHLPR3    g_pdmR3DevPciHlp;
