/** @file | |
Task priority (TPL) functions. | |
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "DxeMain.h" | |
#include "Event.h" | |
/** | |
Set Interrupt State. | |
@param Enable The state of enable or disable interrupt | |
**/ | |
VOID | |
CoreSetInterruptState ( | |
IN BOOLEAN Enable | |
) | |
{ | |
EFI_STATUS Status; | |
BOOLEAN InSmm; | |
if (gCpu == NULL) { | |
return; | |
} | |
if (!Enable) { | |
gCpu->DisableInterrupt (gCpu); | |
return; | |
} | |
if (gSmmBase2 == NULL) { | |
gCpu->EnableInterrupt (gCpu); | |
return; | |
} | |
Status = gSmmBase2->InSmm (gSmmBase2, &InSmm); | |
if (!EFI_ERROR (Status) && !InSmm) { | |
gCpu->EnableInterrupt (gCpu); | |
} | |
} | |
/** | |
Raise the task priority level to the new level. | |
High level is implemented by disabling processor interrupts. | |
@param NewTpl New task priority level | |
@return The previous task priority level | |
**/ | |
EFI_TPL | |
EFIAPI | |
CoreRaiseTpl ( | |
IN EFI_TPL NewTpl | |
) | |
{ | |
EFI_TPL OldTpl; | |
OldTpl = gEfiCurrentTpl; | |
if (OldTpl > NewTpl) { | |
DEBUG ((DEBUG_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > NewTpl(0x%x)\n", OldTpl, NewTpl)); | |
ASSERT (FALSE); | |
} | |
ASSERT (VALID_TPL (NewTpl)); | |
// | |
// If raising to high level, disable interrupts | |
// | |
if ((NewTpl >= TPL_HIGH_LEVEL) && (OldTpl < TPL_HIGH_LEVEL)) { | |
CoreSetInterruptState (FALSE); | |
} | |
// | |
// Set the new value | |
// | |
gEfiCurrentTpl = NewTpl; | |
return OldTpl; | |
} | |
/** | |
Lowers the task priority to the previous value. If the new | |
priority unmasks events at a higher priority, they are dispatched. | |
@param NewTpl New, lower, task priority | |
**/ | |
VOID | |
EFIAPI | |
CoreRestoreTpl ( | |
IN EFI_TPL NewTpl | |
) | |
{ | |
EFI_TPL OldTpl; | |
EFI_TPL PendingTpl; | |
OldTpl = gEfiCurrentTpl; | |
if (NewTpl > OldTpl) { | |
DEBUG ((DEBUG_ERROR, "FATAL ERROR - RestoreTpl with NewTpl(0x%x) > OldTpl(0x%x)\n", NewTpl, OldTpl)); | |
ASSERT (FALSE); | |
} | |
ASSERT (VALID_TPL (NewTpl)); | |
// | |
// If lowering below HIGH_LEVEL, make sure | |
// interrupts are enabled | |
// | |
if ((OldTpl >= TPL_HIGH_LEVEL) && (NewTpl < TPL_HIGH_LEVEL)) { | |
gEfiCurrentTpl = TPL_HIGH_LEVEL; | |
} | |
// | |
// Dispatch any pending events | |
// | |
while (gEventPending != 0) { | |
PendingTpl = (UINTN)HighBitSet64 (gEventPending); | |
if (PendingTpl <= NewTpl) { | |
break; | |
} | |
gEfiCurrentTpl = PendingTpl; | |
if (gEfiCurrentTpl < TPL_HIGH_LEVEL) { | |
CoreSetInterruptState (TRUE); | |
} | |
CoreDispatchEventNotifies (gEfiCurrentTpl); | |
} | |
// | |
// Set the new value | |
// | |
gEfiCurrentTpl = NewTpl; | |
// | |
// If lowering below HIGH_LEVEL, make sure | |
// interrupts are enabled | |
// | |
if (gEfiCurrentTpl < TPL_HIGH_LEVEL) { | |
CoreSetInterruptState (TRUE); | |
} | |
} |