]> 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 2efe0fe4933aa37c3c6a85705dbcb7867fa2d6f6..a3202fa056f3026cd1c6ab3781649923d848d62c 100644 (file)
@@ -25,7 +25,6 @@
 #include <Library/PcdLib.h>\r
 #include <Library/IoLib.h>\r
 #include <Library/ArmGenericTimerCounterLib.h>\r
-#include <Library/ArmArchTimer.h>\r
 \r
 #include <Protocol/Timer.h>\r
 #include <Protocol/HardwareInterrupt.h>\r
@@ -307,12 +306,13 @@ TimerInterruptHandler (
   //\r
   OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
 \r
+  // Signal end of interrupt early to help avoid losing subsequent ticks\r
+  // from long duration handlers\r
+  gInterrupt->EndOfInterrupt (gInterrupt, Source);\r
+\r
   // Check if the timer interrupt is active\r
   if ((ArmGenericTimerGetTimerCtrlReg () ) & ARM_ARCH_TIMER_ISTATUS) {\r
 \r
-    // Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers\r
-    gInterrupt->EndOfInterrupt (gInterrupt, Source);\r
-\r
     if (mTimerNotifyFunction) {\r
       mTimerNotifyFunction (mTimerPeriod * mElapsedPeriod);\r
     }\r
@@ -337,11 +337,10 @@ TimerInterruptHandler (
 \r
     // Set next compare value\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
@@ -368,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
@@ -394,8 +394,15 @@ TimerInitialize (
   Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerVirtIntrNum), TimerInterruptHandler);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerHypIntrNum), TimerInterruptHandler);\r
-  ASSERT_EFI_ERROR (Status);\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