1 /** @file
2   x64 CPU Exception Handler.
3 
4   Copyright (c) 2012 - 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 "CpuExceptionCommon.h"
16 
17 /**
18   Return address map of exception handler template so that C code can generate
19   exception tables.
20 
21   @param IdtEntry          Pointer to IDT entry to be updated.
22   @param InterruptHandler  IDT handler value.
23 **/
24 VOID
ArchUpdateIdtEntry(IN IA32_IDT_GATE_DESCRIPTOR * IdtEntry,IN UINTN InterruptHandler)25 ArchUpdateIdtEntry (
26   IN IA32_IDT_GATE_DESCRIPTOR        *IdtEntry,
27   IN UINTN                           InterruptHandler
28   )
29 {
30   IdtEntry->Bits.OffsetLow   = (UINT16)(UINTN)InterruptHandler;
31   IdtEntry->Bits.OffsetHigh  = (UINT16)((UINTN)InterruptHandler >> 16);
32   IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
33   IdtEntry->Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;
34 }
35 
36 /**
37   Read IDT handler value from IDT entry.
38 
39   @param IdtEntry          Pointer to IDT entry to be read.
40 
41 **/
42 UINTN
ArchGetIdtHandler(IN IA32_IDT_GATE_DESCRIPTOR * IdtEntry)43 ArchGetIdtHandler (
44   IN IA32_IDT_GATE_DESCRIPTOR        *IdtEntry
45   )
46 {
47   return IdtEntry->Bits.OffsetLow + (((UINTN) IdtEntry->Bits.OffsetHigh)  << 16) +
48                                     (((UINTN) IdtEntry->Bits.OffsetUpper) << 32);
49 }
50 
51 /**
52   Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
53 
54   @param ExceptionType  Exception type.
55   @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
56 **/
57 VOID
ArchSaveExceptionContext(IN UINTN ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext)58 ArchSaveExceptionContext (
59   IN UINTN                ExceptionType,
60   IN EFI_SYSTEM_CONTEXT   SystemContext
61   )
62 {
63   IA32_EFLAGS32           Eflags;
64   //
65   // Save Exception context in global variable
66   //
67   mReservedVectors[ExceptionType].OldSs         = SystemContext.SystemContextX64->Ss;
68   mReservedVectors[ExceptionType].OldSp         = SystemContext.SystemContextX64->Rsp;
69   mReservedVectors[ExceptionType].OldFlags      = SystemContext.SystemContextX64->Rflags;
70   mReservedVectors[ExceptionType].OldCs         = SystemContext.SystemContextX64->Cs;
71   mReservedVectors[ExceptionType].OldIp         = SystemContext.SystemContextX64->Rip;
72   mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData;
73   //
74   // Clear IF flag to avoid old IDT handler enable interrupt by IRET
75   //
76   Eflags.UintN = SystemContext.SystemContextX64->Rflags;
77   Eflags.Bits.IF = 0;
78   SystemContext.SystemContextX64->Rflags = Eflags.UintN;
79   //
80   // Modify the EIP in stack, then old IDT handler will return to the stub code
81   //
82   SystemContext.SystemContextX64->Rip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;
83 }
84 
85 /**
86   Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
87 
88   @param ExceptionType  Exception type.
89   @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
90 **/
91 VOID
ArchRestoreExceptionContext(IN UINTN ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext)92 ArchRestoreExceptionContext (
93   IN UINTN                ExceptionType,
94   IN EFI_SYSTEM_CONTEXT   SystemContext
95   )
96 {
97   SystemContext.SystemContextX64->Ss            = mReservedVectors[ExceptionType].OldSs;
98   SystemContext.SystemContextX64->Rsp           = mReservedVectors[ExceptionType].OldSp;
99   SystemContext.SystemContextX64->Rflags        = mReservedVectors[ExceptionType].OldFlags;
100   SystemContext.SystemContextX64->Cs            = mReservedVectors[ExceptionType].OldCs;
101   SystemContext.SystemContextX64->Rip           = mReservedVectors[ExceptionType].OldIp;
102   SystemContext.SystemContextX64->ExceptionData = mReservedVectors[ExceptionType].ExceptionData;
103 }
104 
105 /**
106   Display CPU information.
107 
108   @param ExceptionType  Exception type.
109   @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
110 **/
111 VOID
DumpCpuContent(IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext)112 DumpCpuContent (
113   IN EFI_EXCEPTION_TYPE   ExceptionType,
114   IN EFI_SYSTEM_CONTEXT   SystemContext
115   )
116 {
117   UINTN                   ImageBase;
118   UINTN                   EntryPoint;
119 
120   InternalPrintMessage (
121     "!!!! X64 Exception Type - %02x(%a)  CPU Apic ID - %08x !!!!\n",
122     ExceptionType,
123     GetExceptionNameStr (ExceptionType),
124     GetApicId ()
125     );
126 
127   InternalPrintMessage (
128     "RIP  - %016lx, CS  - %016lx, RFLAGS - %016lx\n",
129     SystemContext.SystemContextX64->Rip,
130     SystemContext.SystemContextX64->Cs,
131     SystemContext.SystemContextX64->Rflags
132     );
133   if (mErrorCodeFlag & (1 << ExceptionType)) {
134     InternalPrintMessage (
135       "ExceptionData - %016lx\n",
136       SystemContext.SystemContextX64->ExceptionData
137       );
138   }
139   InternalPrintMessage (
140     "RAX  - %016lx, RCX - %016lx, RDX - %016lx\n",
141     SystemContext.SystemContextX64->Rax,
142     SystemContext.SystemContextX64->Rcx,
143     SystemContext.SystemContextX64->Rdx
144     );
145   InternalPrintMessage (
146     "RBX  - %016lx, RSP - %016lx, RBP - %016lx\n",
147     SystemContext.SystemContextX64->Rbx,
148     SystemContext.SystemContextX64->Rsp,
149     SystemContext.SystemContextX64->Rbp
150     );
151   InternalPrintMessage (
152     "RSI  - %016lx, RDI - %016lx\n",
153     SystemContext.SystemContextX64->Rsi,
154     SystemContext.SystemContextX64->Rdi
155     );
156   InternalPrintMessage (
157     "R8   - %016lx, R9  - %016lx, R10 - %016lx\n",
158     SystemContext.SystemContextX64->R8,
159     SystemContext.SystemContextX64->R9,
160     SystemContext.SystemContextX64->R10
161     );
162   InternalPrintMessage (
163     "R11  - %016lx, R12 - %016lx, R13 - %016lx\n",
164     SystemContext.SystemContextX64->R11,
165     SystemContext.SystemContextX64->R12,
166     SystemContext.SystemContextX64->R13
167     );
168   InternalPrintMessage (
169     "R14  - %016lx, R15 - %016lx\n",
170     SystemContext.SystemContextX64->R14,
171     SystemContext.SystemContextX64->R15
172     );
173   InternalPrintMessage (
174     "DS   - %016lx, ES  - %016lx, FS  - %016lx\n",
175     SystemContext.SystemContextX64->Ds,
176     SystemContext.SystemContextX64->Es,
177     SystemContext.SystemContextX64->Fs
178     );
179   InternalPrintMessage (
180     "GS   - %016lx, SS  - %016lx\n",
181     SystemContext.SystemContextX64->Gs,
182     SystemContext.SystemContextX64->Ss
183     );
184   InternalPrintMessage (
185     "CR0  - %016lx, CR2 - %016lx, CR3 - %016lx\n",
186     SystemContext.SystemContextX64->Cr0,
187     SystemContext.SystemContextX64->Cr2,
188     SystemContext.SystemContextX64->Cr3
189     );
190   InternalPrintMessage (
191     "CR4  - %016lx, CR8 - %016lx\n",
192     SystemContext.SystemContextX64->Cr4,
193     SystemContext.SystemContextX64->Cr8
194     );
195   InternalPrintMessage (
196     "DR0  - %016lx, DR1 - %016lx, DR2 - %016lx\n",
197     SystemContext.SystemContextX64->Dr0,
198     SystemContext.SystemContextX64->Dr1,
199     SystemContext.SystemContextX64->Dr2
200     );
201   InternalPrintMessage (
202     "DR3  - %016lx, DR6 - %016lx, DR7 - %016lx\n",
203     SystemContext.SystemContextX64->Dr3,
204     SystemContext.SystemContextX64->Dr6,
205     SystemContext.SystemContextX64->Dr7
206     );
207   InternalPrintMessage (
208     "GDTR - %016lx %016lx, LDTR - %016lx\n",
209     SystemContext.SystemContextX64->Gdtr[0],
210     SystemContext.SystemContextX64->Gdtr[1],
211     SystemContext.SystemContextX64->Ldtr
212     );
213   InternalPrintMessage (
214     "IDTR - %016lx %016lx,   TR - %016lx\n",
215     SystemContext.SystemContextX64->Idtr[0],
216     SystemContext.SystemContextX64->Idtr[1],
217     SystemContext.SystemContextX64->Tr
218     );
219 	InternalPrintMessage (
220     "FXSAVE_STATE - %016lx\n",
221     &SystemContext.SystemContextX64->FxSaveState
222     );
223 
224   //
225   // Find module image base and module entry point by RIP
226   //
227   ImageBase = FindModuleImageBase (SystemContext.SystemContextX64->Rip, &EntryPoint);
228   if (ImageBase != 0) {
229     InternalPrintMessage (
230       " (ImageBase=%016lx, EntryPoint=%016lx) !!!!\n",
231       ImageBase,
232       EntryPoint
233       );
234   }
235 }
236