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
;
21 IA32_IDT_GATE_DESCRIPTOR NullDesc
= {0};
24 Read IDT Gate Descriptor from IDT Table.
26 @param Vector Specifies vector number.
27 @param IdtGateDescriptor Pointer to IDT Gate Descriptor read from IDT Table.
31 ReadIdtGateDescriptor (
32 IN EFI_EXCEPTION_TYPE Vector
,
33 OUT IA32_IDT_GATE_DESCRIPTOR
*IdtGateDescriptor
36 IA32_DESCRIPTOR IdtrValue
;
37 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
39 AsmReadIdtr (&IdtrValue
);
40 IdtTable
= (IA32_IDT_GATE_DESCRIPTOR
*) IdtrValue
.Base
;
42 CopyMem ((VOID
*) IdtGateDescriptor
, (VOID
*) &(IdtTable
)[Vector
], sizeof (IA32_IDT_GATE_DESCRIPTOR
));
46 Write IDT Gate Descriptor into IDT Table.
48 @param Vector Specifies vector number.
49 @param IdtGateDescriptor Pointer to IDT Gate Descriptor written into IDT Table.
53 WriteIdtGateDescriptor (
54 EFI_EXCEPTION_TYPE Vector
,
55 IA32_IDT_GATE_DESCRIPTOR
*IdtGateDescriptor
58 IA32_DESCRIPTOR IdtrValue
;
59 IA32_IDT_GATE_DESCRIPTOR
*IdtTable
;
61 AsmReadIdtr (&IdtrValue
);
62 IdtTable
= (IA32_IDT_GATE_DESCRIPTOR
*) IdtrValue
.Base
;
64 CopyMem ((VOID
*) &(IdtTable
)[Vector
], (VOID
*) IdtGateDescriptor
, sizeof (IA32_IDT_GATE_DESCRIPTOR
));
68 Creates a nes entry stub. Then saves the current IDT entry and replaces it
69 with an interrupt gate for the new entry point. The IdtEntryTable is updated
70 with the new registered function.
72 This code executes in boot services context. The stub entry executes in interrupt
75 @param ExceptionType Specifies which vector to hook.
76 @param NewCallback A pointer to the new function to be registered.
81 IN EFI_EXCEPTION_TYPE ExceptionType
,
82 IN
VOID (*NewCallback
) ()
85 BOOLEAN OldIntFlagState
;
87 CreateEntryStub (ExceptionType
, (VOID
**) &IdtEntryTable
[ExceptionType
].StubEntry
);
90 // Disables CPU interrupts and returns the previous interrupt state
92 OldIntFlagState
= SaveAndDisableInterrupts ();
94 ReadIdtGateDescriptor (ExceptionType
, &(IdtEntryTable
[ExceptionType
].OrigDesc
));
95 IdtEntryTable
[ExceptionType
].OrigVector
= (DEBUG_PROC
) GetInterruptHandleFromIdt (&(IdtEntryTable
[ExceptionType
].OrigDesc
));
97 Vect2Desc (&IdtEntryTable
[ExceptionType
].NewDesc
, IdtEntryTable
[ExceptionType
].StubEntry
);
98 IdtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
99 WriteIdtGateDescriptor (ExceptionType
, &(IdtEntryTable
[ExceptionType
].NewDesc
));
102 // restore interrupt state
104 SetInterruptState (OldIntFlagState
);
110 Undoes HookEntry. This code executes in boot services context.
112 @param ExceptionType Specifies which entry to unhook
117 IN EFI_EXCEPTION_TYPE ExceptionType
120 BOOLEAN OldIntFlagState
;
123 // Disables CPU interrupts and returns the previous interrupt state
125 OldIntFlagState
= SaveAndDisableInterrupts ();
128 // restore the default IDT Date Descriptor
130 WriteIdtGateDescriptor (ExceptionType
, &(IdtEntryTable
[ExceptionType
].OrigDesc
));
133 // restore interrupt state
135 SetInterruptState (OldIntFlagState
);
141 Returns the maximum value that may be used for the ProcessorIndex parameter in
142 RegisterPeriodicCallback() and RegisterExceptionCallback().
144 Hard coded to support only 1 processor for now.
146 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
147 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported
148 processor index is returned. Always 0 returned.
150 @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.
155 GetMaximumProcessorIndex (
156 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
157 OUT UINTN
*MaxProcessorIndex
160 *MaxProcessorIndex
= 0;
165 Registers a function to be called back periodically in interrupt context.
167 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
168 @param ProcessorIndex Specifies which processor the callback function applies to.
169 @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main
170 periodic entry point of the debug agent.
172 @retval EFI_SUCCESS The function completed successfully.
173 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback
174 function was previously registered.
175 @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback
180 RegisterPeriodicCallback (
181 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
182 IN UINTN ProcessorIndex
,
183 IN EFI_PERIODIC_CALLBACK PeriodicCallback
186 return ManageIdtEntryTable (PeriodicCallback
, SYSTEM_TIMER_VECTOR
);
190 Registers a function to be called when a given processor exception occurs.
192 This code executes in boot services context.
194 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
195 @param ProcessorIndex Specifies which processor the callback function applies to.
196 @param ExceptionCallback A pointer to a function of type EXCEPTION_CALLBACK that is called
197 when the processor exception specified by ExceptionType occurs.
198 @param ExceptionType Specifies which processor exception to hook.
200 @retval EFI_SUCCESS The function completed successfully.
201 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback
202 function was previously registered.
203 @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback
208 RegisterExceptionCallback (
209 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
210 IN UINTN ProcessorIndex
,
211 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
212 IN EFI_EXCEPTION_TYPE ExceptionType
215 return ManageIdtEntryTable (ExceptionCallback
, ExceptionType
);
219 Invalidates processor instruction cache for a memory range. Subsequent execution in this range
220 causes a fresh memory fetch to retrieve code to be executed.
222 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
223 @param ProcessorIndex Specifies which processor's instruction cache is to be invalidated.
224 @param Start Specifies the physical base of the memory range to be invalidated.
225 @param Length Specifies the minimum number of bytes in the processor's instruction
228 @retval EFI_SUCCESS Always returned.
233 InvalidateInstructionCache (
234 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
235 IN UINTN ProcessorIndex
,
245 Common piece of code that invokes the registered handlers.
247 This code executes in exception context so no efi calls are allowed.
249 @param ExceptionType Exception type
250 @param ContextRecord System context
254 InterruptDistrubutionHub (
255 EFI_EXCEPTION_TYPE ExceptionType
,
256 EFI_SYSTEM_CONTEXT_IA32
*ContextRecord
259 if (IdtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
260 if (ExceptionType
!= SYSTEM_TIMER_VECTOR
) {
261 IdtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, ContextRecord
);
263 OrigVector
= IdtEntryTable
[ExceptionType
].OrigVector
;
264 IdtEntryTable
[ExceptionType
].RegisteredCallback (ContextRecord
);
270 This is the callback that is written to the Loaded Image protocol instance
271 on the image handle. It uninstalls all registered handlers and frees all entry
274 @param ImageHandle The firmware allocated handle for the EFI image.
276 @retval EFI_SUCCESS Always.
281 PlUnloadDebugSupportDriver (
282 IN EFI_HANDLE ImageHandle
285 EFI_EXCEPTION_TYPE ExceptionType
;
287 for (ExceptionType
= 0; ExceptionType
< NUM_IDT_ENTRIES
; ExceptionType
++) {
288 ManageIdtEntryTable (NULL
, ExceptionType
);
290 // Free space for each Interrupt Stub precedure.
292 if (IdtEntryTable
[ExceptionType
].StubEntry
!= NULL
) {
293 FreePool ((VOID
*)(UINTN
)IdtEntryTable
[ExceptionType
].StubEntry
);
297 FreePool (IdtEntryTable
);
303 Initializes driver's handler registration database.
305 This code executes in boot services context.
306 Must be public because it's referenced from DebugSupport.c
308 @retval EFI_UNSUPPORTED If IA32/x64 processor does not support FXSTOR/FXRSTOR instructions,
309 the context save will fail, so these processors are not supported.
310 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory.
311 @retval EFI_SUCCESS Initializes successfully.
315 PlInitializeDebugSupportDriver (
319 EFI_EXCEPTION_TYPE ExceptionType
;
322 // Check whether FxStor instructions are supported.
324 if (!FxStorSupport ()) {
325 return EFI_UNSUPPORTED
;
328 IdtEntryTable
= AllocateZeroPool (sizeof (IDT_ENTRY
) * NUM_IDT_ENTRIES
);
329 if (IdtEntryTable
== NULL
) {
330 return EFI_OUT_OF_RESOURCES
;
333 for (ExceptionType
= 0; ExceptionType
< NUM_IDT_ENTRIES
; ExceptionType
++) {
334 IdtEntryTable
[ExceptionType
].StubEntry
= (DEBUG_PROC
) (UINTN
) AllocatePool (StubSize
);
335 if (IdtEntryTable
[ExceptionType
].StubEntry
== NULL
) {
340 // Copy Interrupt stub code.
342 CopyMem ((VOID
*)(UINTN
)IdtEntryTable
[ExceptionType
].StubEntry
, InterruptEntryStub
, StubSize
);
348 for (ExceptionType
= 0; ExceptionType
< NUM_IDT_ENTRIES
; ExceptionType
++) {
349 if (IdtEntryTable
[ExceptionType
].StubEntry
!= NULL
) {
350 FreePool ((VOID
*)(UINTN
)IdtEntryTable
[ExceptionType
].StubEntry
);
353 FreePool (IdtEntryTable
);
355 return EFI_OUT_OF_RESOURCES
;