1 /** @file
2   Task priority (TPL) functions.
3 
4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "DxeMain.h"
16 #include "Event.h"
17 
18 /**
19   Set Interrupt State.
20 
21   @param  Enable  The state of enable or disable interrupt
22 
23 **/
24 VOID
CoreSetInterruptState(IN BOOLEAN Enable)25 CoreSetInterruptState (
26   IN BOOLEAN      Enable
27   )
28 {
29   EFI_STATUS  Status;
30   BOOLEAN     InSmm;
31 
32   if (gCpu == NULL) {
33     return;
34   }
35   if (!Enable) {
36     gCpu->DisableInterrupt (gCpu);
37     return;
38   }
39   if (gSmmBase2 == NULL) {
40     gCpu->EnableInterrupt (gCpu);
41     return;
42   }
43   Status = gSmmBase2->InSmm (gSmmBase2, &InSmm);
44   if (!EFI_ERROR (Status) && !InSmm) {
45     gCpu->EnableInterrupt(gCpu);
46   }
47 }
48 
49 
50 /**
51   Raise the task priority level to the new level.
52   High level is implemented by disabling processor interrupts.
53 
54   @param  NewTpl  New task priority level
55 
56   @return The previous task priority level
57 
58 **/
59 EFI_TPL
60 EFIAPI
CoreRaiseTpl(IN EFI_TPL NewTpl)61 CoreRaiseTpl (
62   IN EFI_TPL      NewTpl
63   )
64 {
65   EFI_TPL     OldTpl;
66 
67   OldTpl = gEfiCurrentTpl;
68   if (OldTpl > NewTpl) {
69     DEBUG ((EFI_D_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > NewTpl(0x%x)\n", OldTpl, NewTpl));
70     ASSERT (FALSE);
71   }
72   ASSERT (VALID_TPL (NewTpl));
73 
74   //
75   // If raising to high level, disable interrupts
76   //
77   if (NewTpl >= TPL_HIGH_LEVEL  &&  OldTpl < TPL_HIGH_LEVEL) {
78     CoreSetInterruptState (FALSE);
79   }
80 
81   //
82   // Set the new value
83   //
84   gEfiCurrentTpl = NewTpl;
85 
86   return OldTpl;
87 }
88 
89 
90 
91 
92 /**
93   Lowers the task priority to the previous value.   If the new
94   priority unmasks events at a higher priority, they are dispatched.
95 
96   @param  NewTpl  New, lower, task priority
97 
98 **/
99 VOID
100 EFIAPI
CoreRestoreTpl(IN EFI_TPL NewTpl)101 CoreRestoreTpl (
102   IN EFI_TPL NewTpl
103   )
104 {
105   EFI_TPL     OldTpl;
106 
107   OldTpl = gEfiCurrentTpl;
108   if (NewTpl > OldTpl) {
109     DEBUG ((EFI_D_ERROR, "FATAL ERROR - RestoreTpl with NewTpl(0x%x) > OldTpl(0x%x)\n", NewTpl, OldTpl));
110     ASSERT (FALSE);
111   }
112   ASSERT (VALID_TPL (NewTpl));
113 
114   //
115   // If lowering below HIGH_LEVEL, make sure
116   // interrupts are enabled
117   //
118 
119   if (OldTpl >= TPL_HIGH_LEVEL  &&  NewTpl < TPL_HIGH_LEVEL) {
120     gEfiCurrentTpl = TPL_HIGH_LEVEL;
121   }
122 
123   //
124   // Dispatch any pending events
125   //
126   while (((-2 << NewTpl) & gEventPending) != 0) {
127     gEfiCurrentTpl = (UINTN) HighBitSet64 (gEventPending);
128     if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {
129       CoreSetInterruptState (TRUE);
130     }
131     CoreDispatchEventNotifies (gEfiCurrentTpl);
132   }
133 
134   //
135   // Set the new value
136   //
137 
138   gEfiCurrentTpl = NewTpl;
139 
140   //
141   // If lowering below HIGH_LEVEL, make sure
142   // interrupts are enabled
143   //
144   if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {
145     CoreSetInterruptState (TRUE);
146   }
147 
148 }
149