2 IPF specific debug support functions
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.
16 // private header files
18 #include "PlDebugSupport.h"
20 BOOLEAN mInHandler
= FALSE
;
28 // number of bundles to swap in ivt
30 #define NUM_BUNDLES_IN_STUB 5
31 #define NUM_IVT_ENTRIES 64
34 BUNDLE OrigBundles
[NUM_BUNDLES_IN_STUB
];
35 VOID (*RegisteredCallback
) ();
39 This is the worker function that uninstalls and removes all handlers.
41 @param ExceptionType Exception Type
42 @param NewBundles New Boundles
43 @param NewCallback New Callback
45 @retval EFI_ALEADY_STARTED Ivt already hooked.
46 @retval others Indicates the request was not satisfied.
47 @retval EFI_SUCCESS Successfully uninstalled.
52 IN EFI_EXCEPTION_TYPE ExceptionType
,
53 IN BUNDLE NewBundles
[4],
54 IN
VOID (*NewCallback
) ()
58 Saves original IVT contents and inserts a few new bundles which are fixed up
59 to store the ExceptionType and then call the common handler.
61 @param ExceptionType Exception Type
62 @param NewBundles New Boundles
63 @param NewCallback New Callback
68 IN EFI_EXCEPTION_TYPE ExceptionType
,
69 IN BUNDLE NewBundles
[4],
70 IN
VOID (*NewCallback
) ()
74 Restores original IVT contents when unregistering a callback function.
76 @param ExceptionType Exception Type
81 IN EFI_EXCEPTION_TYPE ExceptionType
85 Sets up cache flush and calls assembly function to chain external interrupt.
87 Records new callback in IvtEntryTable.
89 @param NewCallback New Callback.
93 ChainExternalInterrupt (
94 IN
VOID (*NewCallback
) ()
98 Sets up cache flush and calls assembly function to restore external interrupt.
99 Removes registered callback from IvtEntryTable.
103 UnchainExternalInterrupt (
108 Given an integer number, return the physical address of the entry point in the IFT.
110 @param HandlerIndex Index of the Handler
111 @param EntryPoint IFT Entrypoint
115 GetHandlerEntryPoint (
120 IVT_ENTRY IvtEntryTable
[NUM_IVT_ENTRIES
];
123 // IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists
124 // within the buffer and still have a large enough buffer to hold a whole IPF context record.
126 UINT8 IpfContextBuf
[sizeof (EFI_SYSTEM_CONTEXT_IPF
) + 512];
129 // The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched
130 // with the common handler.
132 UINT8 PatchSaveBuffer
[0x400];
133 UINTN ExternalInterruptCount
;
136 IPF specific DebugSupport driver initialization.
138 Must be public because it's referenced from DebugSupport.c
140 @retval EFI_SUCCESS Always.
144 PlInitializeDebugSupportDriver (
148 SetMem (IvtEntryTable
, sizeof (IvtEntryTable
), 0);
149 ExternalInterruptCount
= 0;
154 Unload handler that is called during UnloadImage() - deallocates pool memory
155 used by the driver. Must be public because it's referenced from DebugSuport.c
157 @param ImageHandle The firmware allocated handle for the EFI image.
159 @retval EFI_SUCCESS Always.
164 PlUnloadDebugSupportDriver (
165 IN EFI_HANDLE ImageHandle
168 EFI_EXCEPTION_TYPE ExceptionType
;
170 for (ExceptionType
= 0; ExceptionType
< NUM_IVT_ENTRIES
; ExceptionType
++) {
171 ManageIvtEntryTable (ExceptionType
, NULL
, NULL
);
178 C routine that is called for all registered exceptions. This is the main
179 exception dispatcher. Must be public because it's referenced from AsmFuncs.s.
181 @param ExceptionType Exception Type
182 @param Context System Context
186 IN EFI_EXCEPTION_TYPE ExceptionType
,
187 IN EFI_SYSTEM_CONTEXT Context
192 DEBUG ((EFI_D_INFO
, "ERROR: Re-entered debugger!\n"
193 " ExceptionType == %X\n"
195 " Context.SystemContextIpf->CrIip == %X\n"
196 " Context.SystemContextIpf->CrIpsr == %X\n"
197 " mInHandler == %X\n",
200 Context
.SystemContextIpf
->CrIip
,
201 Context
.SystemContextIpf
->CrIpsr
,
206 ASSERT (!mInHandler
);
208 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
209 if (ExceptionType
!= EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
210 IvtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, Context
.SystemContextIpf
);
212 IvtEntryTable
[ExceptionType
].RegisteredCallback (Context
.SystemContextIpf
);
222 Given an integer number, return the physical address of the entry point in the IFT.
224 @param HandlerIndex Index of the Handler
225 @param EntryPoint IFT Entrypoint
229 GetHandlerEntryPoint (
237 // get base address of IVT
241 if (HandlerIndex
< 20) {
243 // first 20 provide 64 bundles per vector
245 TempPtr
+= 0x400 * HandlerIndex
;
248 // the rest provide 16 bundles per vector
250 TempPtr
+= 0x5000 + 0x100 * (HandlerIndex
- 20);
253 *EntryPoint
= (VOID
*) TempPtr
;
257 This is the worker function that uninstalls and removes all handlers.
259 @param ExceptionType Exception Type
260 @param NewBundles New Boundles
261 @param NewCallback New Callback
263 @retval EFI_ALEADY_STARTED Ivt already hooked.
264 @retval others Indicates the request was not satisfied.
265 @retval EFI_SUCCESS Successfully uninstalled.
269 ManageIvtEntryTable (
270 IN EFI_EXCEPTION_TYPE ExceptionType
,
271 IN BUNDLE NewBundles
[NUM_BUNDLES_IN_STUB
],
272 IN
VOID (*NewCallback
) ()
276 UINT64 InterruptFlags
;
280 // Get address of bundle 0
282 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
284 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
286 // we've already installed to this vector
288 if (NewCallback
!= NULL
) {
290 // if the input handler is non-null, error
292 return EFI_ALREADY_STARTED
;
295 // else remove the previously installed handler
297 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
298 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
299 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
300 UnchainExternalInterrupt ();
302 UnhookEntry (ExceptionType
);
305 ProgramInterruptFlags (InterruptFlags
);
306 gBS
->RestoreTPL (OldTpl
);
308 // re-init IvtEntryTable
310 SetMem (&IvtEntryTable
[ExceptionType
], sizeof (IVT_ENTRY
), 0);
314 // no user handler installed on this vector
316 if (NewCallback
!= NULL
) {
317 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
318 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
319 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
320 ChainExternalInterrupt (NewCallback
);
322 HookEntry (ExceptionType
, NewBundles
, NewCallback
);
325 ProgramInterruptFlags (InterruptFlags
);
326 gBS
->RestoreTPL (OldTpl
);
334 Saves original IVT contents and inserts a few new bundles which are fixed up
335 to store the ExceptionType and then call the common handler.
337 @param ExceptionType Exception Type
338 @param NewBundles New Boundles
339 @param NewCallback New Callback
344 IN EFI_EXCEPTION_TYPE ExceptionType
,
345 IN BUNDLE NewBundles
[4],
346 IN
VOID (*NewCallback
) ()
353 // Get address of bundle 0
355 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
358 // copy original bundles from IVT to IvtEntryTable so we can restore them later
361 IvtEntryTable
[ExceptionType
].OrigBundles
,
363 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
368 CopyMem (B0Ptr
, NewBundles
, sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
);
371 // fixup IVT entry so it stores its index and whether or not to chain...
373 FixupBundle
= B0Ptr
+ 2;
374 FixupBundle
->high
|= ExceptionType
<< 36;
376 InstructionCacheFlush (B0Ptr
, 5);
377 IvtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
381 Restores original IVT contents when unregistering a callback function.
383 @param ExceptionType Exception Type
388 IN EFI_EXCEPTION_TYPE ExceptionType
394 // Get address of bundle 0
396 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
398 // restore original bundles in IVT
402 IvtEntryTable
[ExceptionType
].OrigBundles
,
403 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
405 InstructionCacheFlush (B0Ptr
, 5);
409 Sets up cache flush and calls assembly function to chain external interrupt.
411 Records new callback in IvtEntryTable.
413 @param NewCallback New Callback
417 ChainExternalInterrupt (
418 IN
VOID (*NewCallback
) ()
423 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
424 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NewCallback
;
426 InstructionCacheFlush (Start
, 0x400);
430 Sets up cache flush and calls assembly function to restore external interrupt.
431 Removes registered callback from IvtEntryTable.
435 UnchainExternalInterrupt (
441 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
443 InstructionCacheFlush (Start
, 0x400);
444 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NULL
;
448 // The rest of the functions in this file are all member functions for the
449 // DebugSupport protocol
453 This is a DebugSupport protocol member function, hard
454 coded to support only 1 processor for now.
456 @param This The DebugSupport instance
457 @param MaxProcessorIndex The maximuim supported processor index
459 @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.
464 GetMaximumProcessorIndex (
465 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
466 OUT UINTN
*MaxProcessorIndex
469 *MaxProcessorIndex
= 0;
470 return (EFI_SUCCESS
);
474 DebugSupport protocol member function.
476 @param This The DebugSupport instance
477 @param ProcessorIndex Which processor the callback applies to.
478 @param PeriodicCallback Callback function
480 @retval EFI_SUCCESS Indicates the callback was registered.
481 @retval others Callback was not registered.
486 RegisterPeriodicCallback (
487 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
488 IN UINTN ProcessorIndex
,
489 IN EFI_PERIODIC_CALLBACK PeriodicCallback
492 return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT
, NULL
, PeriodicCallback
);
496 DebugSupport protocol member function.
498 @param This The DebugSupport instance
499 @param ProcessorIndex Which processor the callback applies to.
500 @param NewCallback Callback function
501 @param ExceptionType Which exception to hook
503 @retval EFI_SUCCESS Indicates the callback was registered.
504 @retval others Callback was not registered.
509 RegisterExceptionCallback (
510 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
511 IN UINTN ProcessorIndex
,
512 IN EFI_EXCEPTION_CALLBACK NewCallback
,
513 IN EFI_EXCEPTION_TYPE ExceptionType
516 return ManageIvtEntryTable (
518 (BUNDLE
*) ((EFI_PLABEL
*) HookStub
)->EntryPoint
,
524 DebugSupport protocol member function. Calls assembly routine to flush cache.
526 @param This The DebugSupport instance
527 @param ProcessorIndex Which processor the callback applies to.
528 @param Start Physical base of the memory range to be invalidated
529 @param Length mininum number of bytes in instruction cache to invalidate
531 @retval EFI_SUCCESS Always returned.
536 InvalidateInstructionCache (
537 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
538 IN UINTN ProcessorIndex
,
543 InstructionCacheFlush (Start
, Length
);