Stall.c revision 4fd606d1f5abe38e1f42c38de1d2e895166bd0f4
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/** @file
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi UEFI Miscellaneous boot Services Stall service implementation
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiCopyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiThis program and the accompanying materials
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiare licensed and made available under the terms and conditions of the BSD License
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiwhich accompanies this distribution. The full text of the license may be found at
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchihttp://opensource.org/licenses/bsd-license.php
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi**/
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi//
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi// Include statements
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi//
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "DxeMain.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/**
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Internal worker function to call the Metronome Architectural Protocol for
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi the number of ticks specified by the UINT64 Counter value. WaitForTick()
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi service of the Metronome Architectural Protocol uses a UINT32 for the number
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi of ticks to wait, so this function loops when Counter is larger than 0xffffffff.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi @param Counter Number of ticks to wait.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi**/
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiVOID
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiCoreInternalWaitForTick (
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi IN UINT64 Counter
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi )
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi while ((Counter & 0xffffffff00000000ULL) != 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gMetronome->WaitForTick (gMetronome, 0xffffffff);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Counter -= 0xffffffff;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gMetronome->WaitForTick (gMetronome, (UINT32)Counter);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/**
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Introduces a fine-grained stall.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi @param Microseconds The number of microseconds to stall execution.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi @retval EFI_SUCCESS Execution was stalled for at least the requested
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi amount of microseconds.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi @retval EFI_NOT_AVAILABLE_YET gMetronome is not available yet
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi**/
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiEFI_STATUS
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiEFIAPI
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiCoreStall (
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi IN UINTN Microseconds
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi )
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi UINT64 Counter;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi UINT32 Remainder;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi UINTN Index;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (gMetronome == NULL) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return EFI_NOT_AVAILABLE_YET;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // Counter = Microseconds * 10 / gMetronome->TickPeriod
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // 0x1999999999999999 = (2^64 - 1) / 10
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#if MAX_ADDRESS > 0x1999999999999999ULL /* VBox: Annoying GCC range warnings. */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (Microseconds > 0x1999999999999999ULL) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#else
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#endif
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // Microseconds is too large to multiple by 10 first. Perform the divide
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // operation first and loop 10 times to avoid 64-bit math overflow.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Counter = DivU64x32Remainder (
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Microseconds,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gMetronome->TickPeriod,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi &Remainder
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi );
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi for (Index = 0; Index < 10; Index++) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi CoreInternalWaitForTick (Counter);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (Remainder != 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // If Remainder was not zero, then normally, Counter would be rounded
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // up by 1 tick. In this case, since a loop for 10 counts was used
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // to emulate the multiply by 10 operation, Counter needs to be rounded
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // up by 10 counts.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi CoreInternalWaitForTick (10);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi } else {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // Calculate the number of ticks by dividing the number of microseconds by
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // the TickPeriod. Calculation is based on 100ns unit.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Counter = DivU64x32Remainder (
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi MultU64x32 (Microseconds, 10),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gMetronome->TickPeriod,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi &Remainder
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi );
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (Remainder != 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi // If Remainder is not zero, then round Counter up by one tick.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi //
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Counter++;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi CoreInternalWaitForTick (Counter);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return EFI_SUCCESS;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi