2 Generic debug support functions for IA32/x64.
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. 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
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.
15 #include "DebugSupport.h"
18 // This the global main table to keep track of the interrupts
20 IDT_ENTRY
*IdtEntryTable
= NULL
;
23 Read IDT Gate Descriptor from IDT Table.
25 @param Vector Specifies vector number.
26 @param IdtGateDescriptor Pointer to IDT Gate Descriptor read from IDT Table.
30 ReadIdtGateDescriptor (
31 IN EFI_EXCEPTION_TYPE Vector
,
32 OUT IA32_IDT_GATE_DESCRIPTOR
*IdtGateDescriptor
35 IA32_DESCRIPTOR IdtrValue
;
36 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
38 AsmReadIdtr (&IdtrValue
);
39 IdtTable
= (IA32_IDT_GATE_DESCRIPTOR
*) IdtrValue
.Base
;
41 CopyMem ((VOID
*) IdtGateDescriptor
, (VOID
*) &(IdtTable
)[Vector
], sizeof (IA32_IDT_GATE_DESCRIPTOR
));
45 Write IDT Gate Descriptor into IDT Table.
47 @param Vector Specifies vector number.
48 @param IdtGateDescriptor Pointer to IDT Gate Descriptor written into IDT Table.
52 WriteIdtGateDescriptor (
53 EFI_EXCEPTION_TYPE Vector
,
54 IA32_IDT_GATE_DESCRIPTOR
*IdtGateDescriptor
57 IA32_DESCRIPTOR IdtrValue
;
58 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
60 AsmReadIdtr (&IdtrValue
);
61 IdtTable
= (IA32_IDT_GATE_DESCRIPTOR
*) IdtrValue
.Base
;
63 CopyMem ((VOID
*) &(IdtTable
)[Vector
], (VOID
*) IdtGateDescriptor
, sizeof (IA32_IDT_GATE_DESCRIPTOR
));
67 Creates a nes entry stub. Then saves the current IDT entry and replaces it
68 with an interrupt gate for the new entry point. The IdtEntryTable is updated
69 with the new registered function.
71 This code executes in boot services context. The stub entry executes in interrupt
74 @param ExceptionType Specifies which vector to hook.
75 @param NewCallback A pointer to the new function to be registered.
80 IN EFI_EXCEPTION_TYPE ExceptionType
,
81 IN
VOID (*NewCallback
) ()
84 BOOLEAN OldIntFlagState
;
86 CreateEntryStub (ExceptionType
, (VOID
**) &IdtEntryTable
[ExceptionType
].StubEntry
);
89 // Disables CPU interrupts and returns the previous interrupt state
91 OldIntFlagState
= SaveAndDisableInterrupts ();
93 ReadIdtGateDescriptor (ExceptionType
, &(IdtEntryTable
[ExceptionType
].OrigDesc
));
94 IdtEntryTable
[ExceptionType
].OrigVector
= (DEBUG_PROC
) GetInterruptHandleFromIdt (&(IdtEntryTable
[ExceptionType
].OrigDesc
));
96 Vect2Desc (&IdtEntryTable
[ExceptionType
].NewDesc
, IdtEntryTable
[ExceptionType
].StubEntry
);
97 IdtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
98 WriteIdtGateDescriptor (ExceptionType
, &(IdtEntryTable
[ExceptionType
].NewDesc
));
101 // restore interrupt state
103 SetInterruptState (OldIntFlagState
);
109 Undoes HookEntry. This code executes in boot services context.
111 @param ExceptionType Specifies which entry to unhook
116 IN EFI_EXCEPTION_TYPE ExceptionType
119 BOOLEAN OldIntFlagState
;
122 // Disables CPU interrupts and returns the previous interrupt state
124 OldIntFlagState
= SaveAndDisableInterrupts ();
127 // restore the default IDT Date Descriptor
129 WriteIdtGateDescriptor (ExceptionType
, &(IdtEntryTable
[ExceptionType
].OrigDesc
));
132 // restore interrupt state
134 SetInterruptState (OldIntFlagState
);
140 Returns the maximum value that may be used for the ProcessorIndex parameter in
141 RegisterPeriodicCallback() and RegisterExceptionCallback().
143 Hard coded to support only 1 processor for now.
145 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
146 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported
147 processor index is returned. Always 0 returned.
149 @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.
154 GetMaximumProcessorIndex (
155 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
156 OUT UINTN
*MaxProcessorIndex
159 *MaxProcessorIndex
= 0;
164 Registers a function to be called back periodically in interrupt context.
166 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
167 @param ProcessorIndex Specifies which processor the callback function applies to.
168 @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main
169 periodic entry point of the debug agent.
171 @retval EFI_SUCCESS The function completed successfully.
172 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback
173 function was previously registered.
174 @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback
179 RegisterPeriodicCallback (
180 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
181 IN UINTN ProcessorIndex
,
182 IN EFI_PERIODIC_CALLBACK PeriodicCallback
185 return ManageIdtEntryTable (PeriodicCallback
, SYSTEM_TIMER_VECTOR
);
189 Registers a function to be called when a given processor exception occurs.
191 This code executes in boot services context.
193 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
194 @param ProcessorIndex Specifies which processor the callback function applies to.
195 @param ExceptionCallback A pointer to a function of type EXCEPTION_CALLBACK that is called
196 when the processor exception specified by ExceptionType occurs.
197 @param ExceptionType Specifies which processor exception to hook.
199 @retval EFI_SUCCESS The function completed successfully.
200 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback
201 function was previously registered.
202 @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback
207 RegisterExceptionCallback (
208 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
209 IN UINTN ProcessorIndex
,
210 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
211 IN EFI_EXCEPTION_TYPE ExceptionType
214 return ManageIdtEntryTable (ExceptionCallback
, ExceptionType
);
218 Invalidates processor instruction cache for a memory range. Subsequent execution in this range
219 causes a fresh memory fetch to retrieve code to be executed.
221 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
222 @param ProcessorIndex Specifies which processor's instruction cache is to be invalidated.
223 @param Start Specifies the physical base of the memory range to be invalidated.
224 @param Length Specifies the minimum number of bytes in the processor's instruction
227 @retval EFI_SUCCESS Always returned.
232 InvalidateInstructionCache (
233 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
234 IN UINTN ProcessorIndex
,
244 Common piece of code that invokes the registered handlers.
246 This code executes in exception context so no efi calls are allowed.
248 @param ExceptionType Exception type
249 @param ContextRecord System context
253 InterruptDistrubutionHub (
254 EFI_EXCEPTION_TYPE ExceptionType
,
255 EFI_SYSTEM_CONTEXT_IA32
*ContextRecord
258 if (IdtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
259 if (ExceptionType
!= SYSTEM_TIMER_VECTOR
) {
260 IdtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, ContextRecord
);
262 OrigVector
= IdtEntryTable
[ExceptionType
].OrigVector
;
263 IdtEntryTable
[ExceptionType
].RegisteredCallback (ContextRecord
);
269 This is the callback that is written to the Loaded Image protocol instance
270 on the image handle. It uninstalls all registered handlers and frees all entry
273 @param ImageHandle The firmware allocated handle for the EFI image.
275 @retval EFI_SUCCESS Always.
280 PlUnloadDebugSupportDriver (
281 IN EFI_HANDLE ImageHandle
284 EFI_EXCEPTION_TYPE ExceptionType
;
286 for (ExceptionType
= 0; ExceptionType
< NUM_IDT_ENTRIES
; ExceptionType
++) {
287 ManageIdtEntryTable (NULL
, ExceptionType
);
289 // Free space for each Interrupt Stub precedure.
291 if (IdtEntryTable
[ExceptionType
].StubEntry
!= NULL
) {
292 FreePool ((VOID
*)(UINTN
)IdtEntryTable
[ExceptionType
].StubEntry
);
296 FreePool (IdtEntryTable
);
302 Initializes driver's handler registration database.
304 This code executes in boot services context.
305 Must be public because it's referenced from DebugSupport.c
307 @retval EFI_UNSUPPORTED If IA32/x64 processor does not support FXSTOR/FXRSTOR instructions,
308 the context save will fail, so these processors are not supported.
309 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory.
310 @retval EFI_SUCCESS Initializes successfully.
314 PlInitializeDebugSupportDriver (
318 EFI_EXCEPTION_TYPE ExceptionType
;
321 // Check whether FxStor instructions are supported.
323 if (!FxStorSupport ()) {
324 return EFI_UNSUPPORTED
;
327 IdtEntryTable
= AllocateZeroPool (sizeof (IDT_ENTRY
) * NUM_IDT_ENTRIES
);
328 if (IdtEntryTable
== NULL
) {
329 return EFI_OUT_OF_RESOURCES
;
332 for (ExceptionType
= 0; ExceptionType
< NUM_IDT_ENTRIES
; ExceptionType
++) {
333 IdtEntryTable
[ExceptionType
].StubEntry
= (DEBUG_PROC
) (UINTN
) AllocatePool (StubSize
);
334 if (IdtEntryTable
[ExceptionType
].StubEntry
== NULL
) {
339 // Copy Interrupt stub code.
341 CopyMem ((VOID
*)(UINTN
)IdtEntryTable
[ExceptionType
].StubEntry
, InterruptEntryStub
, StubSize
);
347 for (ExceptionType
= 0; ExceptionType
< NUM_IDT_ENTRIES
; ExceptionType
++) {
348 if (IdtEntryTable
[ExceptionType
].StubEntry
!= NULL
) {
349 FreePool ((VOID
*)(UINTN
)IdtEntryTable
[ExceptionType
].StubEntry
);
352 FreePool (IdtEntryTable
);
354 return EFI_OUT_OF_RESOURCES
;