mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-26 07:04:28 +02:00
Removed the assumption on APIC timer initial Count is all 1s and updated it to handle the long delay that timer initial count.
Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14603 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
4e39b75e7e
commit
3eb695cfb7
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Timer Library functions built upon local APIC on IA32/x64.
|
Timer Library functions built upon local APIC on IA32/x64.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -87,6 +87,22 @@ InternalX86GetTimerTick (
|
|||||||
return MmioRead32 (ApicBase + APIC_TMCCT);
|
return MmioRead32 (ApicBase + APIC_TMCCT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal function to read the initial timer count of local APIC.
|
||||||
|
|
||||||
|
@param ApicBase The base address of memory mapped registers of local APIC.
|
||||||
|
|
||||||
|
@return The initial timer count read.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
InternalX86GetInitTimerCount (
|
||||||
|
IN UINTN ApicBase
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return MmioRead32 (ApicBase + APIC_TMICT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Stalls the CPU for at least the given number of ticks.
|
Stalls the CPU for at least the given number of ticks.
|
||||||
|
|
||||||
@ -105,22 +121,49 @@ InternalX86Delay (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
INT32 Ticks;
|
INT32 Ticks;
|
||||||
UINT32 PowerOfTwoCounter;
|
UINT32 Times;
|
||||||
|
UINT32 InitCount;
|
||||||
|
UINT32 StartTick;
|
||||||
|
|
||||||
//
|
//
|
||||||
// The target timer count is calculated here
|
// In case Delay is too larger, separate it into several small delay slot.
|
||||||
|
// Devided Delay by half value of Init Count is to avoid Delay close to
|
||||||
|
// the Init Count, timeout maybe missing if the time consuming between 2
|
||||||
|
// GetApicTimerCurrentCount() invoking is larger than the time gap between
|
||||||
|
// Delay and the Init Count.
|
||||||
//
|
//
|
||||||
Ticks = InternalX86GetTimerTick (ApicBase) - Delay;
|
InitCount = InternalX86GetInitTimerCount (ApicBase);
|
||||||
|
Times = Delay / (InitCount / 2);
|
||||||
|
Delay = Delay % (InitCount / 2);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Wait until time out
|
// Get Start Tick and do delay
|
||||||
// Delay > 2^31 could not be handled by this function
|
|
||||||
// Timer wrap-arounds are handled correctly by this function
|
|
||||||
//
|
//
|
||||||
PowerOfTwoCounter = GetPowerOfTwo32 (MmioRead32 (ApicBase + APIC_TMICT));
|
StartTick = InternalX86GetTimerTick (ApicBase);
|
||||||
while (((UINT32)(InternalX86GetTimerTick (ApicBase) - Ticks) & PowerOfTwoCounter) == 0) {
|
do {
|
||||||
CpuPause ();
|
//
|
||||||
}
|
// Wait until time out by Delay value
|
||||||
|
//
|
||||||
|
do {
|
||||||
|
CpuPause ();
|
||||||
|
//
|
||||||
|
// Get Ticks from Start to Current.
|
||||||
|
//
|
||||||
|
Ticks = StartTick - InternalX86GetTimerTick (ApicBase);
|
||||||
|
//
|
||||||
|
// Ticks < 0 means Timer wrap-arounds happens.
|
||||||
|
//
|
||||||
|
if (Ticks < 0) {
|
||||||
|
Ticks += InitCount;
|
||||||
|
}
|
||||||
|
} while ((UINT32)Ticks < Delay);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update StartTick and Delay for next delay slot
|
||||||
|
//
|
||||||
|
StartTick -= (StartTick > Delay) ? Delay : (Delay - InitCount);
|
||||||
|
Delay = InitCount / 2;
|
||||||
|
} while (Times-- > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -242,11 +285,7 @@ GetPerformanceCounterProperties (
|
|||||||
ApicBase = InternalX86GetApicBase ();
|
ApicBase = InternalX86GetApicBase ();
|
||||||
|
|
||||||
if (StartValue != NULL) {
|
if (StartValue != NULL) {
|
||||||
*StartValue = MmioRead32 (ApicBase + APIC_TMICT);
|
*StartValue = (UINT64)InternalX86GetInitTimerCount (ApicBase);
|
||||||
//
|
|
||||||
// make sure StartValue is all 1s from High Bit
|
|
||||||
//
|
|
||||||
ASSERT ((*StartValue & (*StartValue + 1)) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EndValue != NULL) {
|
if (EndValue != NULL) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user