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>
This commit is contained in:
Michael Kinney 2016-10-26 15:26:03 -07:00
parent a6f5a5b51f
commit 70830df6dc
1 changed files with 13 additions and 2 deletions

View File

@ -492,11 +492,17 @@ TimerDriverSetTimerPeriod (
IN UINT64 TimerPeriod IN UINT64 TimerPeriod
) )
{ {
EFI_TPL Tpl;
UINT64 MainCounter; UINT64 MainCounter;
UINT64 Delta; UINT64 Delta;
UINT64 CurrentComparator; UINT64 CurrentComparator;
HPET_TIMER_MSI_ROUTE_REGISTER HpetTimerMsiRoute; HPET_TIMER_MSI_ROUTE_REGISTER HpetTimerMsiRoute;
//
// Disable interrupts
//
Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
// //
// Disable HPET timer when adjusting the timer period // Disable HPET timer when adjusting the timer period
// //
@ -616,7 +622,12 @@ TimerDriverSetTimerPeriod (
// is disabled. // is disabled.
// //
HpetEnable (TRUE); HpetEnable (TRUE);
//
// Restore interrupts
//
gBS->RestoreTPL (Tpl);
return EFI_SUCCESS; return EFI_SUCCESS;
} }