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
) ();
38 IVT_ENTRY IvtEntryTable
[NUM_IVT_ENTRIES
];
41 // IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists
42 // within the buffer and still have a large enough buffer to hold a whole IPF context record.
44 UINT8 IpfContextBuf
[sizeof (EFI_SYSTEM_CONTEXT_IPF
) + 512];
47 // The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched
48 // with the common handler.
50 UINT8 PatchSaveBuffer
[0x400];
51 UINTN ExternalInterruptCount
;
54 This is the worker function that uninstalls and removes all handlers.
56 @param ExceptionType Exception Type
57 @param NewBundles New Boundles
58 @param NewCallback New Callback
60 @retval EFI_ALEADY_STARTED Ivt already hooked.
61 @retval others Indicates the request was not satisfied.
62 @retval EFI_SUCCESS Successfully uninstalled.
67 IN EFI_EXCEPTION_TYPE ExceptionType
,
68 IN BUNDLE NewBundles
[4],
69 IN
VOID (*NewCallback
) ()
73 Saves original IVT contents and inserts a few new bundles which are fixed up
74 to store the ExceptionType and then call the common handler.
76 @param ExceptionType Exception Type
77 @param NewBundles New Boundles
78 @param NewCallback New Callback
83 IN EFI_EXCEPTION_TYPE ExceptionType
,
84 IN BUNDLE NewBundles
[4],
85 IN
VOID (*NewCallback
) ()
89 Restores original IVT contents when unregistering a callback function.
91 @param ExceptionType Exception Type
96 IN EFI_EXCEPTION_TYPE ExceptionType
100 Sets up cache flush and calls assembly function to chain external interrupt.
102 Records new callback in IvtEntryTable.
104 @param NewCallback New Callback.
108 ChainExternalInterrupt (
109 IN
VOID (*NewCallback
) ()
113 Sets up cache flush and calls assembly function to restore external interrupt.
114 Removes registered callback from IvtEntryTable.
118 UnchainExternalInterrupt (
123 Given an integer number, return the physical address of the entry point in the IFT.
125 @param HandlerIndex Index of the Handler
126 @param EntryPoint IFT Entrypoint
130 GetHandlerEntryPoint (
137 IPF specific DebugSupport driver initialization.
139 Must be public because it's referenced from DebugSupport.c
141 @retval EFI_SUCCESS Always.
145 PlInitializeDebugSupportDriver (
149 ZeroMem (IvtEntryTable
, sizeof (IvtEntryTable
));
150 ExternalInterruptCount
= 0;
155 Unload handler that is called during UnloadImage() - deallocates pool memory
156 used by the driver. Must be public because it's referenced from DebugSuport.c
158 @param ImageHandle The firmware allocated handle for the EFI image.
160 @retval EFI_SUCCESS Always.
165 PlUnloadDebugSupportDriver (
166 IN EFI_HANDLE ImageHandle
169 EFI_EXCEPTION_TYPE ExceptionType
;
171 for (ExceptionType
= 0; ExceptionType
< NUM_IVT_ENTRIES
; ExceptionType
++) {
172 ManageIvtEntryTable (ExceptionType
, NULL
, NULL
);
179 C routine that is called for all registered exceptions. This is the main
180 exception dispatcher. Must be public because it's referenced from AsmFuncs.s.
182 @param ExceptionType Exception Type
183 @param Context System Context
187 IN EFI_EXCEPTION_TYPE ExceptionType
,
188 IN EFI_SYSTEM_CONTEXT Context
193 DEBUG ((EFI_D_INFO
, "ERROR: Re-entered debugger!\n"
194 " ExceptionType == %X\n"
196 " Context.SystemContextIpf->CrIip == %X\n"
197 " Context.SystemContextIpf->CrIpsr == %X\n"
198 " mInHandler == %X\n",
201 Context
.SystemContextIpf
->CrIip
,
202 Context
.SystemContextIpf
->CrIpsr
,
207 ASSERT (!mInHandler
);
209 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
210 if (ExceptionType
!= EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
211 IvtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, Context
.SystemContextIpf
);
213 IvtEntryTable
[ExceptionType
].RegisteredCallback (Context
.SystemContextIpf
);
223 Given an integer number, return the physical address of the entry point in the IFT.
225 @param HandlerIndex Index of the Handler
226 @param EntryPoint IFT Entrypoint
230 GetHandlerEntryPoint (
238 // get base address of IVT
242 if (HandlerIndex
< 20) {
244 // first 20 provide 64 bundles per vector
246 TempPtr
+= 0x400 * HandlerIndex
;
249 // the rest provide 16 bundles per vector
251 TempPtr
+= 0x5000 + 0x100 * (HandlerIndex
- 20);
254 *EntryPoint
= (VOID
*) TempPtr
;
258 This is the worker function that uninstalls and removes all handlers.
260 @param ExceptionType Exception Type
261 @param NewBundles New Boundles
262 @param NewCallback New Callback
264 @retval EFI_ALEADY_STARTED Ivt already hooked.
265 @retval others Indicates the request was not satisfied.
266 @retval EFI_SUCCESS Successfully uninstalled.
270 ManageIvtEntryTable (
271 IN EFI_EXCEPTION_TYPE ExceptionType
,
272 IN BUNDLE NewBundles
[NUM_BUNDLES_IN_STUB
],
273 IN
VOID (*NewCallback
) ()
277 UINT64 InterruptFlags
;
281 // Get address of bundle 0
283 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
285 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
287 // we've already installed to this vector
289 if (NewCallback
!= NULL
) {
291 // if the input handler is non-null, error
293 return EFI_ALREADY_STARTED
;
296 // else remove the previously installed handler
298 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
299 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
300 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
301 UnchainExternalInterrupt ();
303 UnhookEntry (ExceptionType
);
306 ProgramInterruptFlags (InterruptFlags
);
307 gBS
->RestoreTPL (OldTpl
);
309 // re-init IvtEntryTable
311 ZeroMem (&IvtEntryTable
[ExceptionType
], sizeof (IVT_ENTRY
));
315 // no user handler installed on this vector
317 if (NewCallback
!= NULL
) {
318 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
319 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
320 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
321 ChainExternalInterrupt (NewCallback
);
323 HookEntry (ExceptionType
, NewBundles
, NewCallback
);
326 ProgramInterruptFlags (InterruptFlags
);
327 gBS
->RestoreTPL (OldTpl
);
335 Saves original IVT contents and inserts a few new bundles which are fixed up
336 to store the ExceptionType and then call the common handler.
338 @param ExceptionType Exception Type
339 @param NewBundles New Boundles
340 @param NewCallback New Callback
345 IN EFI_EXCEPTION_TYPE ExceptionType
,
346 IN BUNDLE NewBundles
[4],
347 IN
VOID (*NewCallback
) ()
354 // Get address of bundle 0
356 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
359 // copy original bundles from IVT to IvtEntryTable so we can restore them later
362 IvtEntryTable
[ExceptionType
].OrigBundles
,
364 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
369 CopyMem (B0Ptr
, NewBundles
, sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
);
372 // fixup IVT entry so it stores its index and whether or not to chain...
374 FixupBundle
= B0Ptr
+ 2;
375 FixupBundle
->high
|= ExceptionType
<< 36;
377 InstructionCacheFlush (B0Ptr
, 5);
378 IvtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
382 Restores original IVT contents when unregistering a callback function.
384 @param ExceptionType Exception Type
389 IN EFI_EXCEPTION_TYPE ExceptionType
395 // Get address of bundle 0
397 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
399 // restore original bundles in IVT
403 IvtEntryTable
[ExceptionType
].OrigBundles
,
404 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
406 InstructionCacheFlush (B0Ptr
, 5);
410 Sets up cache flush and calls assembly function to chain external interrupt.
412 Records new callback in IvtEntryTable.
414 @param NewCallback New Callback
418 ChainExternalInterrupt (
419 IN
VOID (*NewCallback
) ()
424 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
425 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NewCallback
;
427 InstructionCacheFlush (Start
, 0x400);
431 Sets up cache flush and calls assembly function to restore external interrupt.
432 Removes registered callback from IvtEntryTable.
436 UnchainExternalInterrupt (
442 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
444 InstructionCacheFlush (Start
, 0x400);
445 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NULL
;
449 // The rest of the functions in this file are all member functions for the
450 // DebugSupport protocol
454 This is a DebugSupport protocol member function, hard
455 coded to support only 1 processor for now.
457 @param This The DebugSupport instance
458 @param MaxProcessorIndex The maximuim supported processor index
460 @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.
465 GetMaximumProcessorIndex (
466 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
467 OUT UINTN
*MaxProcessorIndex
470 *MaxProcessorIndex
= 0;
471 return (EFI_SUCCESS
);
475 DebugSupport protocol member function.
477 @param This The DebugSupport instance
478 @param ProcessorIndex Which processor the callback applies to.
479 @param PeriodicCallback Callback function
481 @retval EFI_SUCCESS Indicates the callback was registered.
482 @retval others Callback was not registered.
487 RegisterPeriodicCallback (
488 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
489 IN UINTN ProcessorIndex
,
490 IN EFI_PERIODIC_CALLBACK PeriodicCallback
493 return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT
, NULL
, PeriodicCallback
);
497 DebugSupport protocol member function.
499 @param This The DebugSupport instance
500 @param ProcessorIndex Which processor the callback applies to.
501 @param NewCallback Callback function
502 @param ExceptionType Which exception to hook
504 @retval EFI_SUCCESS Indicates the callback was registered.
505 @retval others Callback was not registered.
510 RegisterExceptionCallback (
511 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
512 IN UINTN ProcessorIndex
,
513 IN EFI_EXCEPTION_CALLBACK NewCallback
,
514 IN EFI_EXCEPTION_TYPE ExceptionType
517 return ManageIvtEntryTable (
519 (BUNDLE
*) ((EFI_PLABEL
*) HookStub
)->EntryPoint
,
525 DebugSupport protocol member function. Calls assembly routine to flush cache.
527 @param This The DebugSupport instance
528 @param ProcessorIndex Which processor the callback applies to.
529 @param Start Physical base of the memory range to be invalidated
530 @param Length mininum number of bytes in instruction cache to invalidate
532 @retval EFI_SUCCESS Always returned.
537 InvalidateInstructionCache (
538 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
539 IN UINTN ProcessorIndex
,
544 InstructionCacheFlush (Start
, Length
);