1 | /** @file
|
---|
2 |
|
---|
3 | Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
---|
4 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
5 |
|
---|
6 | Four test cases are created in this Unit Test module.
|
---|
7 | a.Test if exception handler can be registered/unregistered for no error code exception
|
---|
8 | In this test case, only no error code exception is triggered and tested by INTn instruction.
|
---|
9 | The special hanlder for these exception will modify a global variable for check.
|
---|
10 |
|
---|
11 | b.Test if exception handler can be registered/unregistered for GP and PF.
|
---|
12 | In this test case, GP exception is triggered and tested by setting CR4_RESERVED_BIT to 1.
|
---|
13 | PF exception is triggered and tested by writting to not-present or RO addres.
|
---|
14 | The special hanlder for these exceptions will set a global vartiable for check and adjust Rip to return from fault exception.
|
---|
15 |
|
---|
16 | c.Test if Cpu Context is consistent before and after exception.
|
---|
17 | In this test case:
|
---|
18 | 1. Set Cpu register to mExpectedContextInHandler before exception.
|
---|
19 | 2. Trigger exception specified by ExceptionType.
|
---|
20 | 3. Store SystemContext in mActualContextInHandler and set SystemContext to mExpectedContextAfterException in handler.
|
---|
21 | 4. After return from exception, store Cpu registers in mActualContextAfterException.
|
---|
22 | The expectation is:
|
---|
23 | 1. Register values in mActualContextInHandler are the same with register values in mExpectedContextInHandler.
|
---|
24 | 2. Register values in mActualContextAfterException are the same with register values mActualContextAfterException.
|
---|
25 |
|
---|
26 | d.Test if stack overflow can be captured by CpuStackGuard in both Bsp and AP.
|
---|
27 | In this test case, stack overflow is triggered by a funtion which calls itself continuously. This test case triggers stack
|
---|
28 | overflow in both BSP and AP. All AP use same Idt with Bsp. The expectation is:
|
---|
29 | 1. PF exception is triggered (leading to a DF if sepereated stack is not prepared for PF) when Rsp <= StackBase + SIZE_4KB
|
---|
30 | since [StackBase, StackBase + SIZE_4KB] is marked as not present in page table when PcdCpuStackGuard is TRUE.
|
---|
31 | 2. Stack for PF/DF exception handler in both Bsp and AP is succussfully switched by InitializeSeparateExceptionStacks.
|
---|
32 |
|
---|
33 | **/
|
---|
34 |
|
---|
35 | #ifndef CPU_EXCEPTION_HANDLER_TEST_H_
|
---|
36 | #define CPU_EXCEPTION_HANDLER_TEST_H_
|
---|
37 |
|
---|
38 | #include <Uefi.h>
|
---|
39 | #include <Library/BaseLib.h>
|
---|
40 | #include <Library/BaseMemoryLib.h>
|
---|
41 | #include <Library/DebugLib.h>
|
---|
42 | #include <Library/UnitTestLib.h>
|
---|
43 | #include <Library/MemoryAllocationLib.h>
|
---|
44 | #include <Library/UnitTestHostBaseLib.h>
|
---|
45 | #include <Library/CpuExceptionHandlerLib.h>
|
---|
46 | #include <Library/UefiLib.h>
|
---|
47 | #include <Library/SerialPortLib.h>
|
---|
48 | #include <Library/HobLib.h>
|
---|
49 | #include <Library/CpuPageTableLib.h>
|
---|
50 | #include <Guid/MemoryAllocationHob.h>
|
---|
51 | #include <Protocol/MpService.h>
|
---|
52 | #include <PiPei.h>
|
---|
53 | #include <Ppi/MpServices2.h>
|
---|
54 |
|
---|
55 | #define UNIT_TEST_APP_NAME "Cpu Exception Handler Lib Unit Tests"
|
---|
56 | #define UNIT_TEST_APP_VERSION "1.0"
|
---|
57 |
|
---|
58 | #define CPU_INTERRUPT_NUM 256
|
---|
59 | #define SPEC_MAX_EXCEPTION_NUM 22
|
---|
60 | #define CR4_RESERVED_BIT BIT15
|
---|
61 |
|
---|
62 | typedef struct {
|
---|
63 | IA32_DESCRIPTOR OriginalGdtr;
|
---|
64 | IA32_DESCRIPTOR OriginalIdtr;
|
---|
65 | UINT16 Tr;
|
---|
66 | } CPU_REGISTER_BUFFER;
|
---|
67 |
|
---|
68 | typedef union {
|
---|
69 | EDKII_PEI_MP_SERVICES2_PPI *Ppi;
|
---|
70 | EFI_MP_SERVICES_PROTOCOL *Protocol;
|
---|
71 | } MP_SERVICES;
|
---|
72 |
|
---|
73 | typedef struct {
|
---|
74 | VOID *Buffer;
|
---|
75 | UINTN BufferSize;
|
---|
76 | EFI_STATUS Status;
|
---|
77 | } EXCEPTION_STACK_SWITCH_CONTEXT;
|
---|
78 |
|
---|
79 | typedef struct {
|
---|
80 | UINT64 Rdi;
|
---|
81 | UINT64 Rsi;
|
---|
82 | UINT64 Rbx;
|
---|
83 | UINT64 Rdx;
|
---|
84 | UINT64 Rcx;
|
---|
85 | UINT64 Rax;
|
---|
86 | UINT64 R8;
|
---|
87 | UINT64 R9;
|
---|
88 | UINT64 R10;
|
---|
89 | UINT64 R11;
|
---|
90 | UINT64 R12;
|
---|
91 | UINT64 R13;
|
---|
92 | UINT64 R14;
|
---|
93 | UINT64 R15;
|
---|
94 | } GENERAL_REGISTER;
|
---|
95 |
|
---|
96 | typedef struct {
|
---|
97 | UINT32 Edi;
|
---|
98 | UINT32 Esi;
|
---|
99 | UINT32 Ebx;
|
---|
100 | UINT32 Edx;
|
---|
101 | UINT32 Ecx;
|
---|
102 | UINT32 Eax;
|
---|
103 | } GENERAL_REGISTER_IA32;
|
---|
104 |
|
---|
105 | extern UINTN mFaultInstructionLength;
|
---|
106 | extern EFI_EXCEPTION_TYPE mExceptionType;
|
---|
107 | extern UINTN mRspAddress[];
|
---|
108 |
|
---|
109 | /**
|
---|
110 | Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR buffer.
|
---|
111 | In PEIM, store original PeiServicePointer before new Idt table.
|
---|
112 |
|
---|
113 | @return Pointer to the allocated IA32_DESCRIPTOR buffer.
|
---|
114 | **/
|
---|
115 | VOID *
|
---|
116 | InitializeBspIdt (
|
---|
117 | VOID
|
---|
118 | );
|
---|
119 |
|
---|
120 | /**
|
---|
121 | Trigger no error code exception by INT n instruction.
|
---|
122 |
|
---|
123 | @param[in] ExceptionType No error code exception type.
|
---|
124 | **/
|
---|
125 | VOID
|
---|
126 | EFIAPI
|
---|
127 | TriggerINTnException (
|
---|
128 | IN EFI_EXCEPTION_TYPE ExceptionType
|
---|
129 | );
|
---|
130 |
|
---|
131 | /**
|
---|
132 | Trigger GP exception by setting CR4_RESERVED_BIT to 1.
|
---|
133 |
|
---|
134 | @param[in] Cr4ReservedBit Cr4 reserved bit.
|
---|
135 | **/
|
---|
136 | VOID
|
---|
137 | EFIAPI
|
---|
138 | TriggerGPException (
|
---|
139 | UINTN Cr4ReservedBit
|
---|
140 | );
|
---|
141 |
|
---|
142 | /**
|
---|
143 | Trigger PF exception by write to not present or ReadOnly address.
|
---|
144 |
|
---|
145 | @param[in] PFAddress Not present or ReadOnly address in page table.
|
---|
146 | **/
|
---|
147 | VOID
|
---|
148 | EFIAPI
|
---|
149 | TriggerPFException (
|
---|
150 | UINTN PFAddress
|
---|
151 | );
|
---|
152 |
|
---|
153 | /**
|
---|
154 | Special handler for fault exception.
|
---|
155 | This handler sets Rip/Eip in SystemContext to the instruction address after the exception instruction.
|
---|
156 |
|
---|
157 | @param ExceptionType Exception type.
|
---|
158 | @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
|
---|
159 | **/
|
---|
160 | VOID
|
---|
161 | EFIAPI
|
---|
162 | AdjustRipForFaultHandler (
|
---|
163 | IN EFI_EXCEPTION_TYPE ExceptionType,
|
---|
164 | IN EFI_SYSTEM_CONTEXT SystemContext
|
---|
165 | );
|
---|
166 |
|
---|
167 | /**
|
---|
168 | Test consistency of Cpu context. Four steps:
|
---|
169 | 1. Set Cpu register to mExpectedContextInHandler before exception.
|
---|
170 | 2. Trigger exception specified by ExceptionType.
|
---|
171 | 3. Store SystemContext in mActualContextInHandler and set SystemContext to mExpectedContextAfterException in handler.
|
---|
172 | 4. After return from exception, store Cpu registers in mActualContextAfterException.
|
---|
173 |
|
---|
174 | Rcx/Ecx in mExpectedContextInHandler is decided by different exception type runtime since Rcx/Ecx is needed in assembly code.
|
---|
175 | For GP and PF, Rcx/Ecx is set to FaultParameter. For other exception triggered by INTn, Rcx/Ecx is set to ExceptionType.
|
---|
176 |
|
---|
177 | @param[in] ExceptionType Exception type.
|
---|
178 | @param[in] FaultParameter Parameter for GP and PF. OPTIONAL
|
---|
179 | **/
|
---|
180 | VOID
|
---|
181 | EFIAPI
|
---|
182 | AsmTestConsistencyOfCpuContext (
|
---|
183 | IN EFI_EXCEPTION_TYPE ExceptionType,
|
---|
184 | IN UINTN FaultParameter OPTIONAL
|
---|
185 | );
|
---|
186 |
|
---|
187 | /**
|
---|
188 | Special handler for ConsistencyOfCpuContext test case. General register in SystemContext
|
---|
189 | is modified to mExpectedContextInHandler in this handler.
|
---|
190 |
|
---|
191 | @param ExceptionType Exception type.
|
---|
192 | @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
|
---|
193 | **/
|
---|
194 | VOID
|
---|
195 | EFIAPI
|
---|
196 | AdjustCpuContextHandler (
|
---|
197 | IN EFI_EXCEPTION_TYPE ExceptionType,
|
---|
198 | IN EFI_SYSTEM_CONTEXT SystemContext
|
---|
199 | );
|
---|
200 |
|
---|
201 | /**
|
---|
202 | Compare cpu context in ConsistencyOfCpuContext test case.
|
---|
203 | 1.Compare mActualContextInHandler with mExpectedContextInHandler.
|
---|
204 | 2.Compare mActualContextAfterException with mActualContextAfterException.
|
---|
205 |
|
---|
206 | @retval UNIT_TEST_PASSED The Unit test has completed and it was successful.
|
---|
207 | @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
|
---|
208 | **/
|
---|
209 | UNIT_TEST_STATUS
|
---|
210 | CompareCpuContext (
|
---|
211 | VOID
|
---|
212 | );
|
---|
213 |
|
---|
214 | /**
|
---|
215 | Get EFI_MP_SERVICES_PROTOCOL/EDKII_PEI_MP_SERVICES2_PPI pointer.
|
---|
216 |
|
---|
217 | @param[out] MpServices Pointer to the MP_SERVICES buffer
|
---|
218 |
|
---|
219 | @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL/PPI interface is returned
|
---|
220 | @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL/PPI interface is not found
|
---|
221 | **/
|
---|
222 | EFI_STATUS
|
---|
223 | GetMpServices (
|
---|
224 | OUT MP_SERVICES *MpServices
|
---|
225 | );
|
---|
226 |
|
---|
227 | /**
|
---|
228 | Create CpuExceptionLibUnitTestSuite and add test case.
|
---|
229 |
|
---|
230 | @param[in] FrameworkHandle Unit test framework.
|
---|
231 |
|
---|
232 | @return EFI_SUCCESS The unit test suite was created.
|
---|
233 | @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
|
---|
234 | initialize the unit test suite.
|
---|
235 | **/
|
---|
236 | EFI_STATUS
|
---|
237 | AddCommonTestCase (
|
---|
238 | IN UNIT_TEST_FRAMEWORK_HANDLE Framework
|
---|
239 | );
|
---|
240 |
|
---|
241 | /**
|
---|
242 | Execute a caller provided function on all enabled APs.
|
---|
243 |
|
---|
244 | @param[in] MpServices MP_SERVICES structure.
|
---|
245 | @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
|
---|
246 | @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
|
---|
247 | one by one, in ascending order of processor handle number.
|
---|
248 | If FALSE, then all the enabled APs execute the function specified by Procedure
|
---|
249 | simultaneously.
|
---|
250 | @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for APs to return from Procedure,
|
---|
251 | for blocking mode only. Zero means infinity.
|
---|
252 | @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
|
---|
253 |
|
---|
254 | @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
|
---|
255 | @retval Others Execute a caller provided function on all enabled APs unsuccessfully
|
---|
256 | **/
|
---|
257 | EFI_STATUS
|
---|
258 | MpServicesUnitTestStartupAllAPs (
|
---|
259 | IN MP_SERVICES MpServices,
|
---|
260 | IN EFI_AP_PROCEDURE Procedure,
|
---|
261 | IN BOOLEAN SingleThread,
|
---|
262 | IN UINTN TimeoutInMicroSeconds,
|
---|
263 | IN VOID *ProcedureArgument
|
---|
264 | );
|
---|
265 |
|
---|
266 | /**
|
---|
267 | Caller gets one enabled AP to execute a caller-provided function.
|
---|
268 |
|
---|
269 | @param[in] MpServices MP_SERVICES structure.
|
---|
270 | @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
|
---|
271 | @param[in] ProcessorNumber The handle number of the AP.
|
---|
272 | @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for APs to return from Procedure,
|
---|
273 | for blocking mode only. Zero means infinity.
|
---|
274 | @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
|
---|
275 |
|
---|
276 |
|
---|
277 | @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
|
---|
278 | @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
|
---|
279 | **/
|
---|
280 | EFI_STATUS
|
---|
281 | MpServicesUnitTestStartupThisAP (
|
---|
282 | IN MP_SERVICES MpServices,
|
---|
283 | IN EFI_AP_PROCEDURE Procedure,
|
---|
284 | IN UINTN ProcessorNumber,
|
---|
285 | IN UINTN TimeoutInMicroSeconds,
|
---|
286 | IN VOID *ProcedureArgument
|
---|
287 | );
|
---|
288 |
|
---|
289 | /**
|
---|
290 | Get the handle number for the calling processor.
|
---|
291 |
|
---|
292 | @param[in] MpServices MP_SERVICES structure.
|
---|
293 | @param[out] ProcessorNumber The handle number for the calling processor.
|
---|
294 |
|
---|
295 | @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
|
---|
296 | @retval Others Get the handle number for the calling processor unsuccessfully.
|
---|
297 | **/
|
---|
298 | EFI_STATUS
|
---|
299 | MpServicesUnitTestWhoAmI (
|
---|
300 | IN MP_SERVICES MpServices,
|
---|
301 | OUT UINTN *ProcessorNumber
|
---|
302 | );
|
---|
303 |
|
---|
304 | /**
|
---|
305 | Retrieve the number of logical processor in the platform and the number of those logical processors that
|
---|
306 | are enabled on this boot.
|
---|
307 |
|
---|
308 | @param[in] MpServices MP_SERVICES structure.
|
---|
309 | @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
|
---|
310 | the BSP and disabled APs.
|
---|
311 | @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
|
---|
312 |
|
---|
313 | @retval EFI_SUCCESS Retrieve the number of logical processor successfully
|
---|
314 | @retval Others Retrieve the number of logical processor unsuccessfully
|
---|
315 | **/
|
---|
316 | EFI_STATUS
|
---|
317 | MpServicesUnitTestGetNumberOfProcessors (
|
---|
318 | IN MP_SERVICES MpServices,
|
---|
319 | OUT UINTN *NumberOfProcessors,
|
---|
320 | OUT UINTN *NumberOfEnabledProcessors
|
---|
321 | );
|
---|
322 |
|
---|
323 | /**
|
---|
324 | Trigger stack overflow by calling itself continuously.
|
---|
325 | **/
|
---|
326 | VOID
|
---|
327 | EFIAPI
|
---|
328 | TriggerStackOverflow (
|
---|
329 | VOID
|
---|
330 | );
|
---|
331 |
|
---|
332 | /**
|
---|
333 | Special handler for CpuStackGuard test case.
|
---|
334 |
|
---|
335 | @param ExceptionType Exception type.
|
---|
336 | @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
|
---|
337 | **/
|
---|
338 | VOID
|
---|
339 | EFIAPI
|
---|
340 | CpuStackGuardExceptionHandler (
|
---|
341 | IN EFI_EXCEPTION_TYPE ExceptionType,
|
---|
342 | IN EFI_SYSTEM_CONTEXT SystemContext
|
---|
343 | );
|
---|
344 |
|
---|
345 | #endif
|
---|