@@ -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
@@ -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);
@@ -52,7 +52,9 @@
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
- gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
+ gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
+ gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
+ gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
[Depex]
gHardwareInterruptProtocolGuid
@@ -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);
+ }
}
@@ -42,5 +42,9 @@
[Protocols]
gEfiCpuArchProtocolGuid
+[FeaturePcd]
+ gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual
+
[FixedPcd]
gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
+
@@ -44,5 +44,8 @@
[Protocols]
gEfiCpuArchProtocolGuid
+[FeaturePcd]
+ gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual
+
[FixedPcd]
gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
@@ -39,5 +39,8 @@
[Protocols]
gEfiCpuArchProtocolGuid
+[FeaturePcd]
+ gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual
+
[FixedPcd]
gArmTokenSpaceGuid.PcdArmCacheOperationThreshold