]> git.proxmox.com Git - mirror_edk2.git/blobdiff - PcAtChipsetPkg/HpetTimerDxe/HpetTimer.c
PcAtChipsetPkg/HpetTimerDxe: Fix race condition in SetTimerPeriod()
[mirror_edk2.git] / PcAtChipsetPkg / HpetTimerDxe / HpetTimer.c
index b38963157cc1267569c0a9558ee3c1dd96c68ed5..c62c3a9b2b98d23dd6f30f1bf291201af85fa2f2 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Timer Architectural Protocol module using High Precesion Event Timer (HPET)\r
 \r
-  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -142,7 +142,7 @@ TimerDriverGetTimerPeriod (
   @param  This  The EFI_TIMER_ARCH_PROTOCOL instance.\r
 \r
   @retval  EFI_SUCCESS       The soft timer interrupt was generated.\r
-  @retval  EFI_UNSUPPORTEDT  The platform does not support the generation of soft \r
+  @retval  EFI_UNSUPPORTED   The platform does not support the generation of soft\r
                              timer interrupts.\r
 \r
 **/\r
@@ -183,11 +183,21 @@ EFI_TIMER_NOTIFY  mTimerNotifyFunction = NULL;
 UINT64  mTimerPeriod = 0;\r
 \r
 ///\r
-/// Accumulates HPET timer ticks to account for time passed when the \r
-/// HPET timer is disabled or when there is no timer notification function\r
-/// registered.\r
+/// The number of HPET timer ticks required for the current HPET rate specified by mTimerPeriod.\r
 ///\r
-volatile UINT64  mTimerAccumulator = 0;\r
+UINT64  mTimerCount;\r
+\r
+///\r
+/// Mask used for counter and comparator calculations to adjust for a 32-bit or 64-bit counter.\r
+///\r
+UINT64  mCounterMask;\r
+\r
+///\r
+/// The HPET main counter value from the most recent HPET timer interrupt.\r
+///\r
+volatile UINT64  mPreviousMainCounter;\r
+\r
+volatile UINT64  mPreviousComparator;\r
 \r
 ///\r
 /// The index of the HPET timer being managed by this driver.\r
@@ -288,8 +298,11 @@ TimerInterruptHandler (
   IN EFI_SYSTEM_CONTEXT   SystemContext\r
   )\r
 {\r
+  UINT64  MainCounter;\r
+  UINT64  Comparator;\r
   UINT64  TimerPeriod;\r
-  \r
+  UINT64  Delta;\r
+\r
   //\r
   // Count number of ticks\r
   //\r
@@ -306,15 +319,51 @@ TimerInterruptHandler (
   SendApicEoi ();\r
 \r
   //\r
-  // Accumulate time from the HPET main counter value\r
+  // Disable HPET timer when adjusting the COMPARATOR value to prevent a missed interrupt\r
+  //\r
+  HpetEnable (FALSE);\r
+  \r
+  //\r
+  // Capture main counter value\r
   //\r
-  mTimerAccumulator += HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
+  MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
 \r
   //\r
-  // Reset HPET main counter to 0\r
+  // Get the previous comparator counter\r
   //\r
-  HpetWrite (HPET_MAIN_COUNTER_OFFSET, 0);\r
+  mPreviousComparator = HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);\r
 \r
+  //\r
+  // Set HPET COMPARATOR to the value required for the next timer tick\r
+  //\r
+  Comparator = (mPreviousComparator + mTimerCount) & mCounterMask;\r
+\r
+  if ((mPreviousMainCounter < MainCounter) && (mPreviousComparator > Comparator)) {\r
+    //\r
+    // When comparator overflows\r
+    //\r
+    HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, Comparator);\r
+  } else if ((mPreviousMainCounter > MainCounter) && (mPreviousComparator < Comparator)) {\r
+    //\r
+    // When main counter overflows\r
+    //\r
+    HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (MainCounter + mTimerCount) & mCounterMask);\r
+  } else {\r
+    //\r
+    // When both main counter and comparator do not overflow or both do overflow\r
+    //\r
+    if (Comparator > MainCounter) {\r
+      HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, Comparator);\r
+    } else {\r
+      HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (MainCounter + mTimerCount) & mCounterMask);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Enable the HPET counter once the new COMPARATOR value has been set.\r
+  //\r
+  HpetEnable (TRUE);\r
+  \r
   //\r
   // Check to see if there is a registered notification function\r
   //\r
@@ -322,14 +371,24 @@ TimerInterruptHandler (
     //\r
     // Compute time since last notification in 100 ns units (10 ^ -7) \r
     //\r
+    if (MainCounter > mPreviousMainCounter) {\r
+      //\r
+      // Main counter does not overflow\r
+      //\r
+      Delta = MainCounter - mPreviousMainCounter;\r
+    } else {\r
+      //\r
+      // Main counter overflows, first usb, then add\r
+      //\r
+      Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;\r
+    }\r
     TimerPeriod = DivU64x32 (\r
                     MultU64x32 (\r
-                      mTimerAccumulator, \r
+                      Delta & mCounterMask,\r
                       mHpetGeneralCapabilities.Bits.CounterClockPeriod\r
                       ), \r
                     100000000\r
                     );\r
-    mTimerAccumulator = 0;\r
                     \r
     //\r
     // Call registered notification function passing in the time since the last\r
@@ -337,6 +396,11 @@ TimerInterruptHandler (
     //    \r
     mTimerNotifyFunction (TimerPeriod);\r
   }\r
+  \r
+  //\r
+  // Save main counter value\r
+  //\r
+  mPreviousMainCounter = MainCounter;\r
 }\r
 \r
 /**\r
@@ -428,7 +492,16 @@ TimerDriverSetTimerPeriod (
   IN UINT64                   TimerPeriod\r
   )\r
 {\r
-  UINT64  TimerCount;\r
+  EFI_TPL                        Tpl;\r
+  UINT64                         MainCounter;\r
+  UINT64                         Delta;\r
+  UINT64                         CurrentComparator;\r
+  HPET_TIMER_MSI_ROUTE_REGISTER  HpetTimerMsiRoute;\r
+\r
+  //\r
+  // Disable interrupts\r
+  //\r
+  Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
 \r
   //\r
   // Disable HPET timer when adjusting the timer period\r
@@ -436,6 +509,29 @@ TimerDriverSetTimerPeriod (
   HpetEnable (FALSE);\r
   \r
   if (TimerPeriod == 0) {\r
+    if (mTimerPeriod != 0) {\r
+      //\r
+      // Check if there is possibly a pending interrupt\r
+      //\r
+      MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
+      if (MainCounter < mPreviousMainCounter) {\r
+        Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;\r
+      } else { \r
+        Delta = MainCounter - mPreviousMainCounter;\r
+      }\r
+      if ((Delta & mCounterMask) >= mTimerCount) {\r
+        //\r
+        // Interrupt still happens after disable HPET, wait to be processed\r
+        // Wait until interrupt is processed and comparator is increased\r
+        //\r
+        CurrentComparator = HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);\r
+        while (CurrentComparator == mPreviousComparator) {\r
+          CurrentComparator = HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);\r
+          CpuPause();\r
+        }\r
+      }\r
+    }\r
+\r
     //\r
     // If TimerPeriod is 0, then mask HPET Timer interrupts\r
     //\r
@@ -463,42 +559,37 @@ TimerDriverSetTimerPeriod (
     // per tick of the HPET counter to determine the number of HPET counter ticks\r
     // in TimerPeriod 100 ns units.\r
     // \r
-    TimerCount = DivU64x32 (\r
-                   MultU64x32 (TimerPeriod, 100000000),\r
-                   mHpetGeneralCapabilities.Bits.CounterClockPeriod\r
-                   );\r
+    mTimerCount = DivU64x32 (\r
+                    MultU64x32 (TimerPeriod, 100000000),\r
+                    mHpetGeneralCapabilities.Bits.CounterClockPeriod\r
+                    );\r
 \r
     //\r
     // Program the HPET Comparator with the number of ticks till the next interrupt\r
     //\r
-    HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, TimerCount);\r
-\r
-    //\r
-    // Capture the number of ticks since the last HPET Timer interrupt before \r
-    // clearing the main counter.  This value will be used in the next HPET\r
-    // timer interrupt handler to compute the total amount of time since the\r
-    // last HPET timer interrupt\r
-    //    \r
-    mTimerAccumulator = HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
-    \r
-    //\r
-    // If the number of ticks since the last timer interrupt is greater than the\r
-    // timer period, reduce the number of ticks till the next interrupt to 1, so \r
-    // a timer interrupt will be generated as soon as the HPET counter is enabled.\r
-    //    \r
-    if (mTimerAccumulator >= TimerCount) {\r
-      HpetWrite (HPET_MAIN_COUNTER_OFFSET, TimerCount - 1);\r
-      //\r
-      // Adjust the accumulator down by TimerCount ticks because TimerCount\r
-      // ticks will be added to the accumulator on the next interrupt\r
-      //\r
-      mTimerAccumulator -= TimerCount;\r
+    MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
+    if (MainCounter > mPreviousMainCounter) {\r
+      Delta = MainCounter - mPreviousMainCounter;\r
+    } else { \r
+      Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;\r
+    }\r
+    if ((Delta & mCounterMask) >= mTimerCount) {\r
+      HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (MainCounter + 1) & mCounterMask);\r
+    } else {  \r
+      HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (mPreviousMainCounter + mTimerCount) & mCounterMask);\r
     }\r
     \r
     //\r
     // Enable HPET Timer interrupt generation\r
     //\r
     if (mTimerConfiguration.Bits.MsiInterruptCapablity != 0 && FeaturePcdGet (PcdHpetMsiEnable)) {\r
+      //\r
+      // Program MSI Address and MSI Data values in the selected HPET Timer\r
+      // Program HPET register with APIC ID of current BSP in case BSP has been switched\r
+      //\r
+      HpetTimerMsiRoute.Bits.Address = GetApicMsiAddress ();\r
+      HpetTimerMsiRoute.Bits.Value   = (UINT32)GetApicMsiValue (PcdGet8 (PcdHpetLocalApicVector), LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY, FALSE, FALSE);\r
+      HpetWrite (HPET_TIMER_MSI_ROUTE_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, HpetTimerMsiRoute.Uint64);\r
       //\r
       // Enable HPET MSI Interrupt\r
       //\r
@@ -506,7 +597,9 @@ TimerDriverSetTimerPeriod (
     } else {\r
       //\r
       // Enable timer interrupt through I/O APIC\r
+      // Program IOAPIC register with APIC ID of current BSP in case BSP has been switched\r
       //\r
+      IoApicConfigureInterrupt (mTimerIrq, PcdGet8 (PcdHpetLocalApicVector), IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY, TRUE, FALSE);\r
       IoApicEnableInterrupt (mTimerIrq, TRUE);\r
     }\r
 \r
@@ -529,7 +622,12 @@ TimerDriverSetTimerPeriod (
   // is disabled.\r
   //\r
   HpetEnable (TRUE);\r
-  \r
+\r
+  //\r
+  // Restore interrupts\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -575,7 +673,7 @@ TimerDriverGetTimerPeriod (
   @param  This  The EFI_TIMER_ARCH_PROTOCOL instance.\r
 \r
   @retval  EFI_SUCCESS       The soft timer interrupt was generated.\r
-  @retval  EFI_UNSUPPORTEDT  The platform does not support the generation of soft \r
+  @retval  EFI_UNSUPPORTED   The platform does not support the generation of soft\r
                              timer interrupts.\r
 \r
 **/\r
@@ -585,23 +683,20 @@ TimerDriverGenerateSoftInterrupt (
   IN EFI_TIMER_ARCH_PROTOCOL  *This\r
   )\r
 {\r
+  UINT64   MainCounter;\r
   EFI_TPL  Tpl;\r
   UINT64   TimerPeriod;\r
+  UINT64   Delta;\r
 \r
   //\r
   // Disable interrupts\r
   //  \r
   Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
-\r
-  //\r
-  // Read the current HPET main counter value\r
-  //\r
-  mTimerAccumulator += HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
-\r
+  \r
   //\r
-  // Reset HPET main counter to 0\r
+  // Capture main counter value\r
   //\r
-  HpetWrite (HPET_MAIN_COUNTER_OFFSET, 0);\r
+  MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
 \r
   //\r
   // Check to see if there is a registered notification function\r
@@ -610,14 +705,25 @@ TimerDriverGenerateSoftInterrupt (
     //\r
     // Compute time since last interrupt in 100 ns units (10 ^ -7) \r
     //\r
+    if (MainCounter > mPreviousMainCounter) {\r
+      //\r
+      // Main counter does not overflow\r
+      //\r
+      Delta = MainCounter - mPreviousMainCounter;\r
+    } else {\r
+      //\r
+      // Main counter overflows, first usb, then add\r
+      //\r
+      Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;\r
+    }\r
+\r
     TimerPeriod = DivU64x32 (\r
                     MultU64x32 (\r
-                      mTimerAccumulator, \r
+                      Delta & mCounterMask,\r
                       mHpetGeneralCapabilities.Bits.CounterClockPeriod\r
                       ), \r
                     100000000\r
                     );\r
-    mTimerAccumulator = 0;\r
                     \r
     //\r
     // Call registered notification function passing in the time since the last\r
@@ -626,6 +732,11 @@ TimerDriverGenerateSoftInterrupt (
     mTimerNotifyFunction (TimerPeriod);\r
   }\r
 \r
+  //\r
+  // Save main counter value\r
+  //\r
+  mPreviousMainCounter = MainCounter;\r
+  \r
   //\r
   // Restore interrupts\r
   //  \r
@@ -696,19 +807,24 @@ TimerDriverInitialize (
   // Dump HPET Configuration Information\r
   //  \r
   DEBUG_CODE (\r
-    DEBUG ((DEBUG_INFO, "HPET Base Address = %08x\n", PcdGet32 (PcdHpetBaseAddress)));\r
-    DEBUG ((DEBUG_INFO, "  HPET_GENERAL_CAPABILITIES_ID  = %016lx\n", mHpetGeneralCapabilities));\r
-    DEBUG ((DEBUG_INFO, "  HPET_GENERAL_CONFIGURATION    = %016lx\n", mHpetGeneralConfiguration.Uint64));\r
-    DEBUG ((DEBUG_INFO, "  HPET_GENERAL_INTERRUPT_STATUS = %016lx\n", HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)));\r
-    DEBUG ((DEBUG_INFO, "  HPET_MAIN_COUNTER             = %016lx\n", HpetRead (HPET_MAIN_COUNTER_OFFSET)));\r
+    DEBUG ((DEBUG_INFO, "HPET Base Address = 0x%08x\n", PcdGet32 (PcdHpetBaseAddress)));\r
+    DEBUG ((DEBUG_INFO, "  HPET_GENERAL_CAPABILITIES_ID  = 0x%016lx\n", mHpetGeneralCapabilities));\r
+    DEBUG ((DEBUG_INFO, "  HPET_GENERAL_CONFIGURATION    = 0x%016lx\n", mHpetGeneralConfiguration.Uint64));\r
+    DEBUG ((DEBUG_INFO, "  HPET_GENERAL_INTERRUPT_STATUS = 0x%016lx\n", HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)));\r
+    DEBUG ((DEBUG_INFO, "  HPET_MAIN_COUNTER             = 0x%016lx\n", HpetRead (HPET_MAIN_COUNTER_OFFSET)));\r
     DEBUG ((DEBUG_INFO, "  HPET Main Counter Period      = %d (fs)\n", mHpetGeneralCapabilities.Bits.CounterClockPeriod));\r
     for (TimerIndex = 0; TimerIndex <= mHpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {\r
-      DEBUG ((DEBUG_INFO, "  HPET_TIMER%d_CONFIGURATION     = %016lx\n", TimerIndex, HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)));\r
-      DEBUG ((DEBUG_INFO, "  HPET_TIMER%d_COMPARATOR        = %016lx\n", TimerIndex, HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + TimerIndex * HPET_TIMER_STRIDE)));\r
-      DEBUG ((DEBUG_INFO, "  HPET_TIMER%d_MSI_ROUTE         = %016lx\n", TimerIndex, HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + TimerIndex * HPET_TIMER_STRIDE)));\r
+      DEBUG ((DEBUG_INFO, "  HPET_TIMER%d_CONFIGURATION     = 0x%016lx\n", TimerIndex, HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)));\r
+      DEBUG ((DEBUG_INFO, "  HPET_TIMER%d_COMPARATOR        = 0x%016lx\n", TimerIndex, HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + TimerIndex * HPET_TIMER_STRIDE)));\r
+      DEBUG ((DEBUG_INFO, "  HPET_TIMER%d_MSI_ROUTE         = 0x%016lx\n", TimerIndex, HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + TimerIndex * HPET_TIMER_STRIDE)));\r
     }\r
   );\r
   \r
+  //\r
+  // Capture the current HPET main counter value.\r
+  //\r
+  mPreviousMainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);\r
+  \r
   //\r
   // Determine the interrupt mode to use for the HPET Timer.  \r
   // Look for MSI first, then unused PIC mode interrupt, then I/O APIC mode interrupt\r
@@ -801,8 +917,29 @@ TimerDriverInitialize (
   //\r
   mTimerConfiguration.Bits.InterruptEnable         = 0;\r
   mTimerConfiguration.Bits.PeriodicInterruptEnable = 0;\r
-  mTimerConfiguration.Bits.CounterSizeEnable       = 0;\r
+  mTimerConfiguration.Bits.CounterSizeEnable       = 1;\r
   HpetWrite (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, mTimerConfiguration.Uint64);\r
+  \r
+  //\r
+  // Read the HPET Timer Capabilities and Configuration register back again.\r
+  // CounterSizeEnable will be read back as a 0 if it is a 32-bit only timer\r
+  //\r
+  mTimerConfiguration.Uint64 = HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);\r
+  if ((mTimerConfiguration.Bits.CounterSizeEnable == 1) && (sizeof (UINTN) == sizeof (UINT64))) {\r
+    DEBUG ((DEBUG_INFO, "Choose 64-bit HPET timer.\n"));\r
+    //\r
+    // 64-bit BIOS can use 64-bit HPET timer\r
+    //\r
+    mCounterMask = 0xffffffffffffffffULL;\r
+    //\r
+    // Set timer back to 64-bit\r
+    //\r
+    mTimerConfiguration.Bits.CounterSizeEnable = 0;\r
+    HpetWrite (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, mTimerConfiguration.Uint64);\r
+  } else {\r
+    DEBUG ((DEBUG_INFO, "Choose 32-bit HPET timer.\n"));\r
+    mCounterMask = 0x00000000ffffffffULL;\r
+  }\r
 \r
   //\r
   // Install interrupt handler for selected HPET Timer\r
@@ -832,12 +969,15 @@ TimerDriverInitialize (
       DEBUG ((DEBUG_INFO, "HPET Interrupt Mode MSI\n"));\r
     } else {\r
       DEBUG ((DEBUG_INFO, "HPET Interrupt Mode I/O APIC\n"));\r
-      DEBUG ((DEBUG_INFO, "HPET I/O APIC IRQ         = %02x\n",   mTimerIrq));\r
+      DEBUG ((DEBUG_INFO, "HPET I/O APIC IRQ         = 0x%02x\n",  mTimerIrq));\r
     }  \r
-    DEBUG ((DEBUG_INFO, "HPET Interrupt Vector     = %02x\n",   PcdGet8 (PcdHpetLocalApicVector)));\r
-    DEBUG ((DEBUG_INFO, "HPET_TIMER%d_CONFIGURATION = %016lx\n", mTimerIndex, HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE)));\r
-    DEBUG ((DEBUG_INFO, "HPET_TIMER%d_COMPARATOR    = %016lx\n", mTimerIndex, HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + mTimerIndex * HPET_TIMER_STRIDE)));\r
-    DEBUG ((DEBUG_INFO, "HPET_TIMER%d_MSI_ROUTE     = %016lx\n", mTimerIndex, HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + mTimerIndex * HPET_TIMER_STRIDE)));\r
+    DEBUG ((DEBUG_INFO, "HPET Interrupt Vector     = 0x%02x\n",    PcdGet8 (PcdHpetLocalApicVector)));\r
+    DEBUG ((DEBUG_INFO, "HPET Counter Mask         = 0x%016lx\n",  mCounterMask));\r
+    DEBUG ((DEBUG_INFO, "HPET Timer Period         = %d\n",        mTimerPeriod));\r
+    DEBUG ((DEBUG_INFO, "HPET Timer Count          = 0x%016lx\n",  mTimerCount));\r
+    DEBUG ((DEBUG_INFO, "HPET_TIMER%d_CONFIGURATION = 0x%016lx\n", mTimerIndex, HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE)));\r
+    DEBUG ((DEBUG_INFO, "HPET_TIMER%d_COMPARATOR    = 0x%016lx\n", mTimerIndex, HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + mTimerIndex * HPET_TIMER_STRIDE)));\r
+    DEBUG ((DEBUG_INFO, "HPET_TIMER%d_MSI_ROUTE     = 0x%016lx\n", mTimerIndex, HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + mTimerIndex * HPET_TIMER_STRIDE)));\r
 \r
     //\r
     // Wait for a few timer interrupts to fire before continuing\r