summaryrefslogtreecommitdiffstats
path: root/PcAtChipsetPkg
diff options
context:
space:
mode:
authorMichael Kinney <michael.d.kinney@intel.com>2016-10-26 15:26:03 -0700
committerMichael Kinney <michael.d.kinney@intel.com>2016-10-27 21:46:42 -0700
commit70830df6dc72b4fea5e5e9eef07f0039a8a77afe (patch)
tree4bfa832aca95815faebba21a46860c5bfa8dcae2 /PcAtChipsetPkg
parenta6f5a5b51f0f4e6915f1ac2b799574fd4591c440 (diff)
downloadedk2-70830df6dc72b4fea5e5e9eef07f0039a8a77afe.tar.gz
edk2-70830df6dc72b4fea5e5e9eef07f0039a8a77afe.tar.bz2
edk2-70830df6dc72b4fea5e5e9eef07f0039a8a77afe.zip
PcAtChipsetPkg/HpetTimerDxe: Fix race condition in SetTimerPeriod()
https://bugzilla.tianocore.org/show_bug.cgi?id=182 The function TimerDriverSetTimerPeriod() disables the HPET timer while the HPET timer HW is reprogrammed with a new timer period. However, the MMIO write to disable the HPET timer HW can be delayed and an HPET timer interrupt may be processed in the middle of reprogramming the HPET timer HW and this may produced unexpected results. The fix is to raise TPL to TPL_HIGH_LEVEL in TimerDriverSetTimerPeriod() during the time the HPET timer HW is reprogrammed. This guarantees that no timer interrupts are processed during reprogramming. The TimerDriverGenerateSoftInterrupt() function in this same driver also raises TPL to TPL_HIGH_LEVEL, so this fix matches the logic that is already used in another function for the same reason. Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney <michael.d.kinney@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Diffstat (limited to 'PcAtChipsetPkg')
-rw-r--r--PcAtChipsetPkg/HpetTimerDxe/HpetTimer.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/PcAtChipsetPkg/HpetTimerDxe/HpetTimer.c b/PcAtChipsetPkg/HpetTimerDxe/HpetTimer.c
index 0ed874357b..c62c3a9b2b 100644
--- a/PcAtChipsetPkg/HpetTimerDxe/HpetTimer.c
+++ b/PcAtChipsetPkg/HpetTimerDxe/HpetTimer.c
@@ -492,11 +492,17 @@ TimerDriverSetTimerPeriod (
IN UINT64 TimerPeriod
)
{
+ EFI_TPL Tpl;
UINT64 MainCounter;
UINT64 Delta;
UINT64 CurrentComparator;
HPET_TIMER_MSI_ROUTE_REGISTER HpetTimerMsiRoute;
-
+
+ //
+ // Disable interrupts
+ //
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
//
// Disable HPET timer when adjusting the timer period
//
@@ -616,7 +622,12 @@ TimerDriverSetTimerPeriod (
// is disabled.
//
HpetEnable (TRUE);
-
+
+ //
+ // Restore interrupts
+ //
+ gBS->RestoreTPL (Tpl);
+
return EFI_SUCCESS;
}