Index: trunk/include/VBox/pdmifs.h
===================================================================
--- trunk/include/VBox/pdmifs.h	(revision 27120)
+++ trunk/include/VBox/pdmifs.h	(revision 27121)
@@ -1937,4 +1937,43 @@
 #define PDMIVMMDEVPORT_IID                      "d7e52035-3b6c-422e-9215-2a75646a945d"
 
+/** Pointer to a PIT port interface. */
+typedef struct PDMIPITPORT *PPDMIPITPORT;
+/**
+ * PIT port interface.
+ */
+typedef struct PDMIPITPORT
+{
+    /**
+     * Notify PIT about change of HPET legacy mode.
+     *
+     * @returns VBox status code
+     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
+     * @param   fActivate       If HPET legacy mode activated or deactivated.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnNotifyHpetLegacy,(PPDMIPITPORT pInterface, bool fActivate));
+} PDMIPITPORT;
+/** PDMIPITPORT interface ID. */
+#define PDMIPITPORT_IID                        "06127207-3182-4394-b16e-0ecfeb5cbb27"
+
+/** Pointer to a RTC port interface. */
+typedef struct PDMIRTCPORT *PPDMIRTCPORT;
+/**
+ * RTC port interface.
+ */
+typedef struct PDMIRTCPORT
+{
+    /**
+     * Notify RTC about change of HPET legacy mode.
+     *
+     * @returns VBox status code
+     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
+     * @param   fActivate       If HPET legacy mode activated or deactivated.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnNotifyHpetLegacy,(PPDMIRTCPORT pInterface, bool fActivate));
+} PDMIRTCPORT;
+/** PDMIRTCPORT interface ID. */
+#define PDMIRTCPORT_IID                        "b6af0d7c-56c7-4064-85aa-ba78b43a26e7"
+
+
 /** @name Flags for PDMIVMMDEVPORT::pfnSetCredentials.
  * @{ */
Index: trunk/src/VBox/Devices/PC/DevHPET.cpp
===================================================================
--- trunk/src/VBox/Devices/PC/DevHPET.cpp	(revision 27120)
+++ trunk/src/VBox/Devices/PC/DevHPET.cpp	(revision 27121)
@@ -36,6 +36,4 @@
  *   - not entirely correct time of interrupt, i.e. never
  *     schedule interrupt earlier than in 1ms
- *   - interaction with RTC and PIT in legacy mode not yet fully implemented
- *     (HPET part OK, PDM and PIT/RTC to be done)
  *   - statistics not implemented
  */
@@ -590,5 +588,4 @@
     rc =  VINF_IOM_HC_MMIO_WRITE;
 #else /* IN_RING3 */
-    LogRel(("HPET: cannot update PIT/RTC in legacy mode yet"));
     if (pThis->pHpetHlpR3)
         rc = pThis->pHpetHlpR3->pfnSetLegacyMode(pThis->pDevInsR3, fActivate);
@@ -618,4 +615,20 @@
 
             iOldValue = (uint32_t)(pThis->u64Config);
+
+            /**
+             * This check must be here, before actual update, as hpetLegacyMode
+             * may request retry in R3 - so we must keep state intact.
+             */
+            if (isBitJustSet(iOldValue, iNewValue, HPET_CFG_LEGACY))
+            {
+                rc = hpetLegacyMode(pThis, true);
+            }
+            else if (isBitJustCleared(iOldValue, iNewValue, HPET_CFG_LEGACY))
+            {
+                rc = hpetLegacyMode(pThis, false);
+            }
+            if (rc != VINF_SUCCESS)
+                return rc;
+
             pThis->u64Config = updateMasked(iNewValue, iOldValue, HPET_CFG_WRITE_MASK);
             if (isBitJustSet(iOldValue, iNewValue, HPET_CFG_ENABLE))
@@ -635,13 +648,4 @@
                     TMTimerStop(pThis->aTimers[i].CTX_SUFF(pTimer));
             }
-            /** @todo: implement i8254 and RTC interaction */
-            if (isBitJustSet(iNewValue, iOldValue, HPET_CFG_LEGACY))
-            {                
-                rc = hpetLegacyMode(pThis, true);
-            }
-            else if (isBitJustCleared(iOldValue, iNewValue, HPET_CFG_LEGACY))
-            {
-                rc = hpetLegacyMode(pThis, false);
-            }
             break;
         }
@@ -1077,4 +1081,6 @@
 
     LogFlow(("hpetReset:\n"));
+
+    pThis->u64Config = 0;
     for (i = 0; i < HPET_NUM_TIMERS; i++)
     {
Index: trunk/src/VBox/Devices/PC/DevPit-i8254.cpp
===================================================================
--- trunk/src/VBox/Devices/PC/DevPit-i8254.cpp	(revision 27120)
+++ trunk/src/VBox/Devices/PC/DevPit-i8254.cpp	(revision 27121)
@@ -55,4 +55,10 @@
 #include <iprt/asm.h>
 
+#ifdef IN_RING3
+# include <iprt/alloc.h>
+# include <iprt/string.h>
+# include <iprt/uuid.h>
+#endif /* IN_RING3 */
+
 #include "../Builtins.h"
 
@@ -70,5 +76,8 @@
 
 /** The current saved state version. */
-#define PIT_SAVED_STATE_VERSION             3
+#define PIT_SAVED_STATE_VERSION             4
+/** The saved state version used by VirtualBox 3.1 and earlier.
+ * This did not include disable by HPET flag. */
+#define PIT_SAVED_STATE_VERSION_VBOX_31     3
 /** The saved state version used by VirtualBox 3.0 and earlier.
  * This did not include the config part. */
@@ -147,5 +156,10 @@
     /** Config: Speaker enabled. */
     bool                    fSpeakerCfg;
-    bool                    afAlignment0[HC_ARCH_BITS == 32 ? 1 : 5];
+    uint8_t                 fDisabledByHpet;
+#if HC_ARCH_BITS == 64
+    bool                    afAlignment0[4];
+#endif
+    /** PIT port interface. */
+    PDMIPITPORT             IPITPort;
     /** Pointer to the device instance. */
     PPDMDEVINSR3            pDevIns;
@@ -414,7 +428,16 @@
     /* We just flip-flop the irq level to save that extra timer call, which isn't generally required (we haven't served it for months). */
     pDevIns = s->CTX_SUFF(pPit)->pDevIns;
-    PDMDevHlpISASetIrq(pDevIns, s->irq, irq_level);
-    if (irq_level)
-        PDMDevHlpISASetIrq(pDevIns, s->irq, 0);
+
+    /* If PIT disabled by HPET - just disconnect ticks from interrupt controllers, and not modify
+     * other moments of device functioning.
+     * @todo: is it correct?
+     */
+    if (!s->pPitR3->fDisabledByHpet)
+    {
+        PDMDevHlpISASetIrq(pDevIns, s->irq, irq_level);
+        if (irq_level)
+            PDMDevHlpISASetIrq(pDevIns, s->irq, 0);
+    }
+
     if (irq_level)
     {
@@ -763,9 +786,15 @@
 
     SSMR3PutS32(pSSM, pThis->speaker_data_on);
+
+
 #ifdef FAKE_REFRESH_CLOCK
-    return SSMR3PutS32(pSSM, pThis->dummy_refresh_clock);
+    SSMR3PutS32(pSSM, pThis->dummy_refresh_clock);
 #else
-    return SSMR3PutS32(pSSM, 0);
+    SSMR3PutS32(pSSM, 0);
 #endif
+
+    SSMR3PutU8(pSSM, pThis->fDisabledByHpet);
+
+    return 0;
 }
 
@@ -780,5 +809,6 @@
 
     if (    uVersion != PIT_SAVED_STATE_VERSION
-        &&  uVersion != PIT_SAVED_STATE_VERSION_VBOX_30)
+        &&  uVersion != PIT_SAVED_STATE_VERSION_VBOX_30
+        &&  uVersion != PIT_SAVED_STATE_VERSION_VBOX_31)
         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
@@ -839,9 +869,14 @@
     SSMR3GetS32(pSSM, &pThis->speaker_data_on);
 #ifdef FAKE_REFRESH_CLOCK
-    return SSMR3GetS32(pSSM, &pThis->dummy_refresh_clock);
+    SSMR3GetS32(pSSM, &pThis->dummy_refresh_clock);
 #else
     int32_t u32Dummy;
-    return SSMR3GetS32(pSSM, &u32Dummy);
+    SSMR3GetS32(pSSM, &u32Dummy);
 #endif
+
+    if (uVersion > PIT_SAVED_STATE_VERSION_VBOX_31)
+        SSMR3GetU8(pSSM, &pThis->fDisabledByHpet);
+
+    return 0;
 }
 
@@ -900,4 +935,6 @@
     unsigned i;
     LogFlow(("pitReset: \n"));
+
+    pThis->fDisabledByHpet = false;
 
     for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
@@ -963,6 +1000,32 @@
     pHlp->pfnPrintf(pHlp, "speaker_data_on=%#x\n", pThis->speaker_data_on);
 #endif
-}
-
+    if (pThis->fDisabledByHpet)
+        pHlp->pfnPrintf(pHlp, "Disabled by HPET\n");
+}
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) pitQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+    PPDMDEVINS pDevIns = RT_FROM_MEMBER(pInterface, PDMDEVINS, IBase);
+    PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE,    &pDevIns->IBase);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIPITPORT, &pThis->IPITPort);
+    return NULL;
+}
+
+/**
+ * @interface_method_impl{PDMIPITPORT,pfnNotifyHpetLegacy}
+ *
+ * @returns VBox status code
+ * @param   pInterface      Pointer to the interface structure containing the called function pointer.
+ */
+static DECLCALLBACK(int) pitNotifyHpetLegacy(PPDMIPITPORT pInterface, bool fActivate)
+{
+    PITState *pThis = RT_FROM_MEMBER(pInterface, PITState, IPITPort);
+    pThis->fDisabledByHpet = fActivate;
+    return VINF_SUCCESS;
+}
 
 /**
@@ -1069,4 +1132,12 @@
     if (RT_FAILURE(rc))
         return rc;
+
+    /*
+     * Interfaces
+     */
+    /* IBase */
+    pDevIns->IBase.pfnQueryInterface            = pitQueryInterface;
+    /* IPITPort */
+    pThis->IPITPort.pfnNotifyHpetLegacy         = pitNotifyHpetLegacy;
 
     /*
@@ -1130,5 +1201,5 @@
     /* pfnDetach */
     NULL,
-    /* pfnQueryInterface. */
+    /* pfnQueryInterface */
     NULL,
     /* pfnInitComplete */
Index: trunk/src/VBox/Devices/PC/DevRTC.cpp
===================================================================
--- trunk/src/VBox/Devices/PC/DevRTC.cpp	(revision 27120)
+++ trunk/src/VBox/Devices/PC/DevRTC.cpp	(revision 27121)
@@ -54,4 +54,9 @@
 #include <iprt/assert.h>
 #include <iprt/string.h>
+
+#ifdef IN_RING3
+# include <iprt/alloc.h>
+# include <iprt/uuid.h>
+#endif /* IN_RING3 */
 
 #include "../Builtins.h"
@@ -112,5 +117,8 @@
 
 /** The saved state version. */
-#define RTC_SAVED_STATE_VERSION             2
+#define RTC_SAVED_STATE_VERSION             3
+/** The saved state version used by VirtualBox 3.1 and earlier.
+ * This does not include disabled by HPET state.  */
+#define RTC_SAVED_STATE_VERSION_VBOX_31     2
 /** The saved state version used by VirtualBox 3.0 and earlier.
  * This does not include the configuration.  */
@@ -138,5 +146,6 @@
     uint8_t cmos_data[128];
     uint8_t cmos_index;
-    uint8_t Alignment0[7];
+    uint8_t fDisabledByHpet;
+    uint8_t Alignment0[6];
     struct my_tm current_tm;
     /** The configured IRQ. */
@@ -151,4 +160,7 @@
     int64_t next_second_time;
 
+    /** RTC port interface. */
+    PDMIRTCPORT  IRTCPort;
+
     /** Pointer to the device instance - R3 Ptr. */
     PPDMDEVINSR3 pDevInsR3;
@@ -226,4 +238,11 @@
 }
 
+
+static void rtc_raise_irq(RTCState* pThis, uint32_t iLevel)
+{
+    if (!pThis->fDisabledByHpet)
+        PDMDevHlpISASetIrq(pThis->CTX_SUFF(pDevIns), pThis->irq, iLevel);
+}
+
 static void rtc_periodic_timer(void *opaque)
 {
@@ -232,5 +251,6 @@
     rtc_timer_update(s, s->next_periodic_time);
     s->cmos_data[RTC_REG_C] |= 0xc0;
-    PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), s->irq, 1);
+
+    rtc_raise_irq(s, 1);
 }
 
@@ -446,5 +466,5 @@
 
             s->cmos_data[RTC_REG_C] |= 0xa0;
-            PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), s->irq, 1);
+            rtc_raise_irq(s, 1);
         }
     }
@@ -453,5 +473,5 @@
     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
         s->cmos_data[RTC_REG_C] |= 0x90;
-        PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), s->irq, 1);
+        rtc_raise_irq(s, 1);
     }
 
@@ -486,5 +506,5 @@
         case RTC_REG_C:
             ret = s->cmos_data[s->cmos_index];
-            PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), s->irq, 0);
+            rtc_raise_irq(s, 0);
             s->cmos_data[RTC_REG_C] = 0x00;
             break;
@@ -643,4 +663,6 @@
     TMR3TimerSave(pThis->CTX_SUFF(pSecondTimer2), pSSM);
 
+    SSMR3PutU8(pSSM, pThis->fDisabledByHpet);
+
     return VINF_SUCCESS;
 }
@@ -656,4 +678,5 @@
 
     if (    uVersion != RTC_SAVED_STATE_VERSION
+        &&  uVersion != RTC_SAVED_STATE_VERSION_VBOX_31
         &&  uVersion != RTC_SAVED_STATE_VERSION_VBOX_30)
         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
@@ -714,4 +737,9 @@
     }
     pThis->cRelLogEntries = 0;
+
+
+    if (uVersion > RTC_SAVED_STATE_VERSION_VBOX_31)
+         SSMR3GetU8(pSSM, &pThis->fDisabledByHpet);
+
     return VINF_SUCCESS;
 }
@@ -846,4 +874,25 @@
 }
 
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) rtcQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+    PPDMDEVINS pDevIns = RT_FROM_MEMBER(pInterface, PDMDEVINS, IBase);
+    RTCState *pThis = PDMINS_2_DATA(pDevIns, RTCState *);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE,    &pDevIns->IBase);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIRTCPORT, &pThis->IRTCPort);
+    return NULL;
+}
+
+/**
+ * @interface_method_impl{PDMIRTCPORT,pfnNotifyHpetLegacy}
+ */
+static DECLCALLBACK(int) rtcNotifyHpetLegacy(PPDMIRTCPORT pInterface, bool fActivate)
+{
+    RTCState *pThis = RT_FROM_MEMBER(pInterface, RTCState, IRTCPort);
+    pThis->fDisabledByHpet = fActivate;
+    return VINF_SUCCESS;
+}
 
 /**
@@ -913,4 +962,5 @@
     pThis->RtcReg.pfnRead       = rtcCMOSRead;
     pThis->RtcReg.pfnWrite      = rtcCMOSWrite;
+    pThis->fDisabledByHpet      = false;
 
     /*
@@ -970,5 +1020,14 @@
 
     /*
+     * Interfaces
+     */
+    /* IBase */
+    pDevIns->IBase.pfnQueryInterface            = rtcQueryInterface;
+    /* IRTCPort */
+    pThis->IRTCPort.pfnNotifyHpetLegacy         = rtcNotifyHpetLegacy;
+
+    /*
      * Register ourselves as the RTC/CMOS with PDM.
+     * @todo: maybe use generic iface above?
      */
     rc = PDMDevHlpRTCRegister(pDevIns, &pThis->RtcReg, &pThis->pRtcHlpR3);
@@ -1037,3 +1096,2 @@
 #endif /* IN_RING3 */
 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
-
Index: trunk/src/VBox/VMM/PDMDevMiscHlp.cpp
===================================================================
--- trunk/src/VBox/VMM/PDMDevMiscHlp.cpp	(revision 27120)
+++ trunk/src/VBox/VMM/PDMDevMiscHlp.cpp	(revision 27121)
@@ -561,5 +561,35 @@
     PDMDEV_ASSERT_DEVINS(pDevIns);
     LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: fActivate=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fActivate));
-    return 0;
+
+    PPDMIBASE pBase;
+    int rc;
+
+    rc = PDMR3QueryDevice(pDevIns->Internal.s.pVMR3, "i8254", 0, &pBase);
+    /* No PIT - no problems too */
+    if (RT_SUCCESS(rc))
+    {
+        Assert(pBase);
+        PPDMIPITPORT pPort = PDMIBASE_QUERY_INTERFACE(pBase, PDMIPITPORT);
+
+        rc = pPort ? pPort->pfnNotifyHpetLegacy(pPort, fActivate) : VINF_SUCCESS;
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = PDMR3QueryDevice(pDevIns->Internal.s.pVMR3, "mc146818", 0, &pBase);
+    /* No RTC - no problems too */
+    if (RT_SUCCESS(rc))
+    {
+        Assert(pBase);
+        PPDMIRTCPORT pPort = PDMIBASE_QUERY_INTERFACE(pBase, PDMIRTCPORT);
+        rc = pPort ? pPort->pfnNotifyHpetLegacy(pPort, fActivate) : VINF_SUCCESS;
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    return rc;
 }
 
