summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/X64/ArchExceptionHandlerTest.c
blob: c0d962f26d9f5f1dbab8a3766a7871189f6135bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/** @file
  Unit tests of the CpuExceptionHandlerLib.

  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "CpuExceptionHandlerTest.h"

GENERAL_REGISTER  mActualContextInHandler;
GENERAL_REGISTER  mActualContextAfterException;

//
// In TestCpuContextConsistency, Cpu registers will be set to mExpectedContextInHandler/mExpectedContextAfterException.
// Rcx in mExpectedContextInHandler is set runtime since Rcx is needed in assembly code.
// For GP and PF, Rcx is set to FaultParameter. For other exception triggered by INTn, Rcx is set to ExceptionType.
//
GENERAL_REGISTER  mExpectedContextInHandler      = { 1, 2, 3, 4, 5, 0, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe };
GENERAL_REGISTER  mExpectedContextAfterException = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e };

/**
  Special handler for fault exception.
  Rip/Eip in SystemContext will be modified to the instruction after the exception instruction.

  @param ExceptionType  Exception type.
  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
EFIAPI
AdjustRipForFaultHandler (
  IN EFI_EXCEPTION_TYPE  ExceptionType,
  IN EFI_SYSTEM_CONTEXT  SystemContext
  )
{
  mExceptionType                       = ExceptionType;
  SystemContext.SystemContextX64->Rip += mFaultInstructionLength;
}

/**
  Special handler for ConsistencyOfCpuContext test case.

  @param ExceptionType  Exception type.
  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
EFIAPI
AdjustCpuContextHandler (
  IN EFI_EXCEPTION_TYPE  ExceptionType,
  IN EFI_SYSTEM_CONTEXT  SystemContext
  )
{
  //
  // Store SystemContext in mActualContextInHandler.
  //
  mActualContextInHandler.Rdi = SystemContext.SystemContextX64->Rdi;
  mActualContextInHandler.Rsi = SystemContext.SystemContextX64->Rsi;
  mActualContextInHandler.Rbx = SystemContext.SystemContextX64->Rbx;
  mActualContextInHandler.Rdx = SystemContext.SystemContextX64->Rdx;
  mActualContextInHandler.Rcx = SystemContext.SystemContextX64->Rcx;
  mActualContextInHandler.Rax = SystemContext.SystemContextX64->Rax;
  mActualContextInHandler.R8  = SystemContext.SystemContextX64->R8;
  mActualContextInHandler.R9  = SystemContext.SystemContextX64->R9;
  mActualContextInHandler.R10 = SystemContext.SystemContextX64->R10;
  mActualContextInHandler.R11 = SystemContext.SystemContextX64->R11;
  mActualContextInHandler.R12 = SystemContext.SystemContextX64->R12;
  mActualContextInHandler.R13 = SystemContext.SystemContextX64->R13;
  mActualContextInHandler.R14 = SystemContext.SystemContextX64->R14;
  mActualContextInHandler.R15 = SystemContext.SystemContextX64->R15;

  //
  // Modify cpu context. These registers will be stored in mActualContextAfterException.
  // Do not handle Rsp and Rbp. CpuExceptionHandlerLib doesn't set Rsp and Rbp register
  // to the value in SystemContext.
  //
  SystemContext.SystemContextX64->Rdi = mExpectedContextAfterException.Rdi;
  SystemContext.SystemContextX64->Rsi = mExpectedContextAfterException.Rsi;
  SystemContext.SystemContextX64->Rbx = mExpectedContextAfterException.Rbx;
  SystemContext.SystemContextX64->Rdx = mExpectedContextAfterException.Rdx;
  SystemContext.SystemContextX64->Rcx = mExpectedContextAfterException.Rcx;
  SystemContext.SystemContextX64->Rax = mExpectedContextAfterException.Rax;
  SystemContext.SystemContextX64->R8  = mExpectedContextAfterException.R8;
  SystemContext.SystemContextX64->R9  = mExpectedContextAfterException.R9;
  SystemContext.SystemContextX64->R10 = mExpectedContextAfterException.R10;
  SystemContext.SystemContextX64->R11 = mExpectedContextAfterException.R11;
  SystemContext.SystemContextX64->R12 = mExpectedContextAfterException.R12;
  SystemContext.SystemContextX64->R13 = mExpectedContextAfterException.R13;
  SystemContext.SystemContextX64->R14 = mExpectedContextAfterException.R14;
  SystemContext.SystemContextX64->R15 = mExpectedContextAfterException.R15;

  //
  // When fault exception happens, eip/rip points to the faulting instruction.
  // For now, olny GP and PF are tested in fault exception.
  //
  if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) || (ExceptionType == EXCEPT_IA32_GP_FAULT)) {
    AdjustRipForFaultHandler (ExceptionType, SystemContext);
  }
}

/**
  Compare cpu context in ConsistencyOfCpuContext test case.
  1.Compare mActualContextInHandler with mExpectedContextInHandler.
  2.Compare mActualContextAfterException with mActualContextAfterException.

  @retval  UNIT_TEST_PASSED             The Unit test has completed and it was successful.
  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed.
**/
UNIT_TEST_STATUS
CompareCpuContext (
  VOID
  )
{
  UT_ASSERT_EQUAL (mActualContextInHandler.Rdi, mExpectedContextInHandler.Rdi);
  UT_ASSERT_EQUAL (mActualContextInHandler.Rsi, mExpectedContextInHandler.Rsi);
  UT_ASSERT_EQUAL (mActualContextInHandler.Rbx, mExpectedContextInHandler.Rbx);
  UT_ASSERT_EQUAL (mActualContextInHandler.Rdx, mExpectedContextInHandler.Rdx);
  UT_ASSERT_EQUAL (mActualContextInHandler.Rcx, mExpectedContextInHandler.Rcx);
  UT_ASSERT_EQUAL (mActualContextInHandler.Rax, mExpectedContextInHandler.Rax);
  UT_ASSERT_EQUAL (mActualContextInHandler.R8, mExpectedContextInHandler.R8);
  UT_ASSERT_EQUAL (mActualContextInHandler.R9, mExpectedContextInHandler.R9);
  UT_ASSERT_EQUAL (mActualContextInHandler.R10, mExpectedContextInHandler.R10);
  UT_ASSERT_EQUAL (mActualContextInHandler.R11, mExpectedContextInHandler.R11);
  UT_ASSERT_EQUAL (mActualContextInHandler.R12, mExpectedContextInHandler.R12);
  UT_ASSERT_EQUAL (mActualContextInHandler.R13, mExpectedContextInHandler.R13);
  UT_ASSERT_EQUAL (mActualContextInHandler.R14, mExpectedContextInHandler.R14);
  UT_ASSERT_EQUAL (mActualContextInHandler.R15, mExpectedContextInHandler.R15);

  UT_ASSERT_EQUAL (mActualContextAfterException.Rdi, mExpectedContextAfterException.Rdi);
  UT_ASSERT_EQUAL (mActualContextAfterException.Rsi, mExpectedContextAfterException.Rsi);
  UT_ASSERT_EQUAL (mActualContextAfterException.Rbx, mExpectedContextAfterException.Rbx);
  UT_ASSERT_EQUAL (mActualContextAfterException.Rdx, mExpectedContextAfterException.Rdx);
  UT_ASSERT_EQUAL (mActualContextAfterException.Rcx, mExpectedContextAfterException.Rcx);
  UT_ASSERT_EQUAL (mActualContextAfterException.Rax, mExpectedContextAfterException.Rax);
  UT_ASSERT_EQUAL (mActualContextAfterException.R8, mExpectedContextAfterException.R8);
  UT_ASSERT_EQUAL (mActualContextAfterException.R9, mExpectedContextAfterException.R9);
  UT_ASSERT_EQUAL (mActualContextAfterException.R10, mExpectedContextAfterException.R10);
  UT_ASSERT_EQUAL (mActualContextAfterException.R11, mExpectedContextAfterException.R11);
  UT_ASSERT_EQUAL (mActualContextAfterException.R12, mExpectedContextAfterException.R12);
  UT_ASSERT_EQUAL (mActualContextAfterException.R13, mExpectedContextAfterException.R13);
  UT_ASSERT_EQUAL (mActualContextAfterException.R14, mExpectedContextAfterException.R14);
  UT_ASSERT_EQUAL (mActualContextAfterException.R15, mExpectedContextAfterException.R15);
  return UNIT_TEST_PASSED;
}

/**
  Special handler for CpuStackGuard test case.

  @param ExceptionType  Exception type.
  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.

**/
VOID
EFIAPI
CpuStackGuardExceptionHandler (
  IN EFI_EXCEPTION_TYPE  ExceptionType,
  IN EFI_SYSTEM_CONTEXT  SystemContext
  )
{
  UINTN  LocalVariable;

  AdjustRipForFaultHandler (ExceptionType, SystemContext);
  mRspAddress[0] = (UINTN)SystemContext.SystemContextX64->Rsp;
  mRspAddress[1] = (UINTN)(&LocalVariable);

  return;
}