]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/TimerDxe/TimerDxe.c
ArmPkg/TimerDxe: Add ISB for timer compare value reload
[mirror_edk2.git] / ArmPkg / Drivers / TimerDxe / TimerDxe.c
index 40ccf161be637461db6fd089c168d8f40b450655..a3202fa056f3026cd1c6ab3781649923d848d62c 100644 (file)
@@ -24,7 +24,7 @@
 #include <Library/UefiLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <Library/IoLib.h>\r
-#include <Library/ArmArchTimer.h>\r
+#include <Library/ArmGenericTimerCounterLib.h>\r
 \r
 #include <Protocol/Timer.h>\r
 #include <Protocol/HardwareInterrupt.h>\r
@@ -101,7 +101,7 @@ ExitBootServicesEvent (
   IN VOID       *Context\r
   )\r
 {\r
-  ArmArchTimerDisableTimer ();\r
+  ArmGenericTimerDisableTimer ();\r
 }\r
 \r
 /**\r
@@ -144,13 +144,13 @@ TimerDriverSetTimerPeriod (
   EFI_TPL     OriginalTPL;\r
 \r
   // Always disable the timer\r
-  ArmArchTimerDisableTimer ();\r
+  ArmGenericTimerDisableTimer ();\r
 \r
   if (TimerPeriod != 0) {\r
     // mTimerTicks = TimerPeriod in 1ms unit x Frequency.10^-3\r
     //             = TimerPeriod.10^-4 x Frequency.10^-3\r
     //             = (TimerPeriod x Frequency) x 10^-7\r
-    TimerTicks = MultU64x32 (TimerPeriod, FixedPcdGet32 (PcdArmArchTimerFreqInHz));\r
+    TimerTicks = MultU64x32 (TimerPeriod, ArmGenericTimerGetTimerFreq ());\r
     TimerTicks = DivU64x32 (TimerTicks, 10000000U);\r
 \r
     // Raise TPL to update the mTimerTicks and mTimerPeriod to ensure these values\r
@@ -163,13 +163,13 @@ TimerDriverSetTimerPeriod (
 \r
     gBS->RestoreTPL (OriginalTPL);\r
 \r
-    // Get value of the current physical timer\r
-    CounterValue = ArmReadCntPct ();\r
+    // Get value of the current timer\r
+    CounterValue = ArmGenericTimerGetSystemCount ();\r
     // Set the interrupt in Current Time + mTimerTick\r
-    ArmWriteCntpCval (CounterValue + mTimerTicks);\r
+    ArmGenericTimerSetCompareVal (CounterValue + mTimerTicks);\r
 \r
     // Enable the timer\r
-    ArmArchTimerEnableTimer ();\r
+    ArmGenericTimerEnableTimer ();\r
   } else {\r
     // Save the new timer period\r
     mTimerPeriod   = TimerPeriod;\r
@@ -306,11 +306,12 @@ TimerInterruptHandler (
   //\r
   OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
 \r
-  // Check if the timer interrupt is active\r
-  if ((ArmArchTimerGetTimerCtrlReg () ) & ARM_ARCH_TIMER_ISTATUS) {\r
+  // Signal end of interrupt early to help avoid losing subsequent ticks\r
+  // from long duration handlers\r
+  gInterrupt->EndOfInterrupt (gInterrupt, Source);\r
 \r
-    // Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers\r
-    gInterrupt->EndOfInterrupt (gInterrupt, Source);\r
+  // Check if the timer interrupt is active\r
+  if ((ArmGenericTimerGetTimerCtrlReg () ) & ARM_ARCH_TIMER_ISTATUS) {\r
 \r
     if (mTimerNotifyFunction) {\r
       mTimerNotifyFunction (mTimerPeriod * mElapsedPeriod);\r
@@ -321,9 +322,9 @@ TimerInterruptHandler (
     //\r
 \r
     // Get current counter value\r
-    CurrentValue = ArmReadCntPct ();\r
+    CurrentValue = ArmGenericTimerGetSystemCount ();\r
     // Get the counter value to compare with\r
-    CompareValue = ArmReadCntpCval ();\r
+    CompareValue = ArmGenericTimerGetCompareVal ();\r
 \r
     // This loop is needed in case we missed interrupts (eg: case when the interrupt handling\r
     // has taken longer than mTickPeriod).\r
@@ -335,12 +336,11 @@ TimerInterruptHandler (
     } while (CompareValue < CurrentValue);\r
 \r
     // Set next compare value\r
-    ArmWriteCntpCval (CompareValue);\r
+    ArmGenericTimerSetCompareVal (CompareValue);\r
+    ArmGenericTimerEnableTimer ();\r
+    ArmInstructionSynchronizationBarrier ();\r
   }\r
 \r
-  // Enable timer interrupts\r
-  gInterrupt->EnableInterruptSource (gInterrupt, Source);\r
-\r
   gBS->RestoreTPL (OriginalTPL);\r
 }\r
 \r
@@ -367,7 +367,8 @@ TimerInitialize (
 {\r
   EFI_HANDLE  Handle = NULL;\r
   EFI_STATUS  Status;\r
-  UINTN TimerCtrlReg;\r
+  UINTN       TimerCtrlReg;\r
+  UINT32      TimerHypIntrNum;\r
 \r
   if (ArmIsArchTimerImplemented () == 0) {\r
     DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence cann't use this Driver \n"));\r
@@ -379,10 +380,10 @@ TimerInitialize (
   ASSERT_EFI_ERROR (Status);\r
 \r
   // Disable the timer\r
-  TimerCtrlReg = ArmArchTimerGetTimerCtrlReg ();\r
+  TimerCtrlReg = ArmGenericTimerGetTimerCtrlReg ();\r
   TimerCtrlReg |= ARM_ARCH_TIMER_IMASK;\r
   TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;\r
-  ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);\r
+  ArmGenericTimerSetTimerCtrlReg (TimerCtrlReg);\r
   Status = TimerDriverSetTimerPeriod (&gTimer, 0);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -390,6 +391,19 @@ TimerInitialize (
   // Note: Because it is not possible to determine the security state of the\r
   // CPU dynamically, we just install interrupt handler for both sec and non-sec\r
   // timer PPI\r
+  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerVirtIntrNum), TimerInterruptHandler);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // The hypervisor timer interrupt may be omitted by implementations that\r
+  // execute under virtualization.\r
+  //\r
+  TimerHypIntrNum = PcdGet32 (PcdArmArchTimerHypIntrNum);\r
+  if (TimerHypIntrNum != 0) {\r
+    Status = gInterrupt->RegisterInterruptSource (gInterrupt, TimerHypIntrNum, TimerInterruptHandler);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
   Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -410,7 +424,7 @@ TimerInitialize (
 \r
   // Everything is ready, unmask and enable timer interrupts\r
   TimerCtrlReg = ARM_ARCH_TIMER_ENABLE;\r
-  ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);\r
+  ArmGenericTimerSetTimerCtrlReg (TimerCtrlReg);\r
 \r
   // Register for an ExitBootServicesEvent\r
   Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);\r