diff mbox

[edk2,v2,1/8] ArmPkg/TimerDxe: allow virtual timer to be selected

Message ID 1409058229-28802-2-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Aug. 26, 2014, 1:03 p.m. UTC
From: Michael Casadevall <michael.casadevall@linaro.org>

For virtual machines, the physical architected timer may not be available,
so we need to allow the virtual timer to be used instead.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Casadevall <michael.casadevall@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPkg/ArmPkg.dec                                 |  3 +
 ArmPkg/Drivers/TimerDxe/TimerDxe.c                |  6 ++
 ArmPkg/Drivers/TimerDxe/TimerDxe.inf              |  4 +-
 ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c  | 74 +++++++++++++++++++----
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf      |  4 ++
 ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf |  3 +
 ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf   |  3 +
 7 files changed, 84 insertions(+), 13 deletions(-)

Comments

Laszlo Ersek Aug. 26, 2014, 6:23 p.m. UTC | #1
On 08/26/14 15:03, Ard Biesheuvel wrote:
> From: Michael Casadevall <michael.casadevall@linaro.org>
> 
> For virtual machines, the physical architected timer may not be available,
> so we need to allow the virtual timer to be used instead.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Michael Casadevall <michael.casadevall@linaro.org>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  ArmPkg/ArmPkg.dec                                 |  3 +
>  ArmPkg/Drivers/TimerDxe/TimerDxe.c                |  6 ++
>  ArmPkg/Drivers/TimerDxe/TimerDxe.inf              |  4 +-
>  ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c  | 74 +++++++++++++++++++----
>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf      |  4 ++
>  ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf |  3 +
>  ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf   |  3 +
>  7 files changed, 84 insertions(+), 13 deletions(-)

I can't give a "full value" R-b (because I don't know enough about ARM),
but as far as my opinion counts, I'm OK with this one.

Acked-by: Laszlo Ersek <lersek@redhat.com>


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
diff mbox

Patch

diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index a8ca28fccc82..c2551d7c3307 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -69,6 +69,9 @@ 
   # Linux (instead of PSCI)
   gArmTokenSpaceGuid.PcdArmLinuxSpinTable|FALSE|BOOLEAN|0x00000033
 
+  # Whether to use the virtual rather than the physical architected timer
+  gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual|FALSE|BOOLEAN|0x0000003F
+
 [PcdsFixedAtBuild.common]
   gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE|BOOLEAN|0x00000006
 
diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.c b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
index 633876bea6bd..9227be8326b0 100644
--- a/ArmPkg/Drivers/TimerDxe/TimerDxe.c
+++ b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
@@ -347,6 +347,12 @@  TimerInitialize (
   // Note: Because it is not possible to determine the security state of the
   // CPU dynamically, we just install interrupt handler for both sec and non-sec
   // timer PPI
+  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerVirtIntrNum), TimerInterruptHandler);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerHypIntrNum), TimerInterruptHandler);
+  ASSERT_EFI_ERROR (Status);
+
   Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
   ASSERT_EFI_ERROR (Status);
 
diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.inf b/ArmPkg/Drivers/TimerDxe/TimerDxe.inf
index 50477ba42a7a..98b09ba8d203 100644
--- a/ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+++ b/ArmPkg/Drivers/TimerDxe/TimerDxe.inf
@@ -52,7 +52,9 @@ 
   gEmbeddedTokenSpaceGuid.PcdTimerPeriod
   gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
   gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
-  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
+  gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz  
 
 [Depex]
   gHardwareInterruptProtocolGuid
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c b/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c
index fa4f7c741b15..f7ef69d5d4c1 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c
@@ -175,9 +175,25 @@  ArmArchTimerEnableTimer (
 {
   UINTN TimerCtrlReg;
 
-  ArmArchTimerReadReg (CntpCtl, (VOID *)&TimerCtrlReg);
-  TimerCtrlReg |= ARM_ARCH_TIMER_ENABLE;
-  ArmArchTimerWriteReg (CntpCtl, (VOID *)&TimerCtrlReg);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerReadReg (CntvCtl, (VOID *)&TimerCtrlReg);
+    TimerCtrlReg |= ARM_ARCH_TIMER_ENABLE;
+
+    /*
+     * When running under KVM, we need to unmask the interrupt on the timer side
+     * as KVM will mask it when servicing the interrupt at the hypervisor level
+     * and delivering the virtual timer interrupt to the guest. Otherwise, the
+     * interrupt will fire again, trapping into the hypervisor again, etc. etc.
+     * This is scheduled to be fixed on the KVM side, but there is no harm in
+     * leaving this in once KVM gets fixed.
+     */
+    TimerCtrlReg &= ~ARM_ARCH_TIMER_IMASK;
+    ArmArchTimerWriteReg (CntvCtl, (VOID *)&TimerCtrlReg);
+  } else {
+    ArmArchTimerReadReg (CntpCtl, (VOID *)&TimerCtrlReg);
+    TimerCtrlReg |= ARM_ARCH_TIMER_ENABLE;
+    ArmArchTimerWriteReg (CntpCtl, (VOID *)&TimerCtrlReg);
+  }
 }
 
 VOID
@@ -188,9 +204,15 @@  ArmArchTimerDisableTimer (
 {
   UINTN TimerCtrlReg;
 
-  ArmArchTimerReadReg (CntpCtl, (VOID *)&TimerCtrlReg);
-  TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
-  ArmArchTimerWriteReg (CntpCtl, (VOID *)&TimerCtrlReg);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerReadReg (CntvCtl, (VOID *)&TimerCtrlReg);
+    TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
+    ArmArchTimerWriteReg (CntvCtl, (VOID *)&TimerCtrlReg);
+  } else {
+    ArmArchTimerReadReg (CntpCtl, (VOID *)&TimerCtrlReg);
+    TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
+    ArmArchTimerWriteReg (CntpCtl, (VOID *)&TimerCtrlReg);
+  }
 }
 
 VOID
@@ -220,7 +242,12 @@  ArmArchTimerGetTimerVal (
     )
 {
   UINTN ArchTimerVal;
-  ArmArchTimerReadReg (CntpTval, (VOID *)&ArchTimerVal);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerReadReg (CntvTval, (VOID *)&ArchTimerVal);
+  } else {
+    ArmArchTimerReadReg (CntpTval, (VOID *)&ArchTimerVal);
+  }
+
   return ArchTimerVal;
 }
 
@@ -231,7 +258,11 @@  ArmArchTimerSetTimerVal (
     IN   UINTN   Val
     )
 {
-  ArmArchTimerWriteReg (CntpTval, (VOID *)&Val);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerWriteReg (CntvTval, (VOID *)&Val);
+  } else {
+    ArmArchTimerWriteReg (CntpTval, (VOID *)&Val);
+  }
 }
 
 UINT64
@@ -241,7 +272,12 @@  ArmArchTimerGetSystemCount (
     )
 {
   UINT64 SystemCount;
-  ArmArchTimerReadReg (CntPct, (VOID *)&SystemCount);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerReadReg (CntvCt, (VOID *)&SystemCount);
+  } else {
+    ArmArchTimerReadReg (CntPct, (VOID *)&SystemCount);
+  }
+
   return SystemCount;
 }
 
@@ -252,7 +288,13 @@  ArmArchTimerGetTimerCtrlReg (
     )
 {
   UINTN  Val;
-  ArmArchTimerReadReg (CntpCtl, (VOID *)&Val);
+
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerReadReg (CntvCtl, (VOID *)&Val);
+  } else {
+    ArmArchTimerReadReg (CntpCtl, (VOID *)&Val);
+  }
+
   return Val;
 }
 
@@ -262,7 +304,11 @@  ArmArchTimerSetTimerCtrlReg (
     UINTN Val
     )
 {
-  ArmArchTimerWriteReg (CntpCtl, (VOID *)&Val);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerWriteReg (CntvCtl, (VOID *)&Val);
+  } else {
+    ArmArchTimerWriteReg (CntpCtl, (VOID *)&Val);
+  }
 }
 
 VOID
@@ -271,5 +317,9 @@  ArmArchTimerSetCompareVal (
     IN   UINT64   Val
     )
 {
-  ArmArchTimerWriteReg (CntpCval, (VOID *)&Val);
+  if (FeaturePcdGet (PcdArmArchTimerUseVirtual)) {
+    ArmArchTimerWriteReg (CntvCval, (VOID *)&Val);
+  } else {
+    ArmArchTimerWriteReg (CntpCval, (VOID *)&Val);
+  }
 }
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf
index e5247848b549..0dc2f26a21b5 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf
@@ -42,5 +42,9 @@ 
 [Protocols]
   gEfiCpuArchProtocolGuid
 
+[FeaturePcd]
+  gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual
+
 [FixedPcd]
   gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
+
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf b/ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf
index 3a99e1b713cc..081c6fb66cdc 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf
@@ -44,5 +44,8 @@ 
 [Protocols]
   gEfiCpuArchProtocolGuid
 
+[FeaturePcd]
+  gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual
+
 [FixedPcd]
   gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf b/ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf
index 57ac694cd733..1210b337b9c7 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf
@@ -39,5 +39,8 @@ 
 [Protocols]
   gEfiCpuArchProtocolGuid
 
+[FeaturePcd]
+  gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual
+
 [FixedPcd]
   gArmTokenSpaceGuid.PcdArmCacheOperationThreshold