2 IPF specific debug support functions
4 Copyright (c) 2006, 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"
26 // number of bundles to swap in ivt
28 #define NUM_BUNDLES_IN_STUB 5
29 #define NUM_IVT_ENTRIES 64
32 BUNDLE OrigBundles
[NUM_BUNDLES_IN_STUB
];
33 VOID (*RegisteredCallback
) ();
39 IN EFI_EXCEPTION_TYPE ExceptionType
,
40 IN BUNDLE NewBundles
[4],
41 IN
VOID (*NewCallback
) ()
47 IN EFI_EXCEPTION_TYPE ExceptionType
,
48 IN BUNDLE NewBundles
[4],
49 IN
VOID (*NewCallback
) ()
55 IN EFI_EXCEPTION_TYPE ExceptionType
60 ChainExternalInterrupt (
61 IN
VOID (*NewCallback
) ()
66 UnchainExternalInterrupt (
72 GetHandlerEntryPoint (
77 IVT_ENTRY IvtEntryTable
[NUM_IVT_ENTRIES
];
80 // IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists
81 // within the buffer and still have a large enough buffer to hold a whole IPF context record.
83 UINT8 IpfContextBuf
[sizeof (EFI_SYSTEM_CONTEXT_IPF
) + 512];
86 // The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched
87 // with the common handler.
89 UINT8 PatchSaveBuffer
[0x400];
90 UINTN ExternalInterruptCount
;
93 plInitializeDebugSupportDriver (
99 IPF specific DebugSupport driver initialization. Must be public because it's
100 referenced from DebugSupport.c
110 SetMem (IvtEntryTable
, sizeof (IvtEntryTable
), 0);
111 ExternalInterruptCount
= 0;
117 plUnloadDebugSupportDriver (
118 IN EFI_HANDLE ImageHandle
123 Unload handler that is called during UnloadImage() - deallocates pool memory
124 used by the driver. Must be public because it's referenced from DebugSuport.c
127 ImageHandle - Image handle
131 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
135 EFI_EXCEPTION_TYPE ExceptionType
;
137 for (ExceptionType
= 0; ExceptionType
< NUM_IVT_ENTRIES
; ExceptionType
++) {
138 ManageIvtEntryTable (ExceptionType
, NULL
, NULL
);
146 IN EFI_EXCEPTION_TYPE ExceptionType
,
147 IN EFI_SYSTEM_CONTEXT Context
152 C routine that is called for all registered exceptions. This is the main
153 exception dispatcher. Must be public because it's referenced from AsmFuncs.s.
156 ExceptionType - Exception Type
157 Context - System Context
165 static BOOLEAN InHandler
= FALSE
;
169 DEBUG ((EFI_D_INFO
, "ERROR: Re-entered debugger!\n"
170 " ExceptionType == %X\n"
172 " Context.SystemContextIpf->CrIip == %X\n"
173 " Context.SystemContextIpf->CrIpsr == %X\n"
174 " InHandler == %X\n",
177 Context
.SystemContextIpf
->CrIip
,
178 Context
.SystemContextIpf
->CrIpsr
,
185 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
186 if (ExceptionType
!= EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
187 IvtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, Context
.SystemContextIpf
);
189 IvtEntryTable
[ExceptionType
].RegisteredCallback (Context
.SystemContextIpf
);
200 GetHandlerEntryPoint (
207 Given an integer number, return the physical address of the entry point in the IFT
210 HandlerIndex - Index of the Handler
211 EntryPoint - IFT Entrypoint
222 // get base address of IVT
226 if (HandlerIndex
< 20) {
228 // first 20 provide 64 bundles per vector
230 TempPtr
+= 0x400 * HandlerIndex
;
233 // the rest provide 16 bundles per vector
235 TempPtr
+= 0x5000 + 0x100 * (HandlerIndex
- 20);
238 *EntryPoint
= (VOID
*) TempPtr
;
243 ManageIvtEntryTable (
244 IN EFI_EXCEPTION_TYPE ExceptionType
,
245 IN BUNDLE NewBundles
[NUM_BUNDLES_IN_STUB
],
246 IN
VOID (*NewCallback
) ()
251 This is the worker function that installs and removes all handlers
254 ExceptionType - Exception Type
255 NewBundles - New Boundles
256 NewCallback - New Callback
260 EFI_STATUS - any return other than EFI_SUCCESS indicates the request was not
262 EFI_ALEADY_STARTED - Ivt already hooked.
267 UINT64 InterruptFlags
;
271 // Get address of bundle 0
273 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
275 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
277 // we've already installed to this vector
279 if (NewCallback
!= NULL
) {
281 // if the input handler is non-null, error
283 return EFI_ALREADY_STARTED
;
286 // else remove the previously installed handler
288 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
289 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
290 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
291 UnchainExternalInterrupt ();
293 UnhookEntry (ExceptionType
);
296 ProgramInterruptFlags (InterruptFlags
);
297 gBS
->RestoreTPL (OldTpl
);
299 // re-init IvtEntryTable
301 SetMem (&IvtEntryTable
[ExceptionType
], sizeof (IVT_ENTRY
), 0);
305 // no user handler installed on this vector
307 if (NewCallback
!= NULL
) {
308 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
309 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
310 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
311 ChainExternalInterrupt (NewCallback
);
313 HookEntry (ExceptionType
, NewBundles
, NewCallback
);
316 ProgramInterruptFlags (InterruptFlags
);
317 gBS
->RestoreTPL (OldTpl
);
327 IN EFI_EXCEPTION_TYPE ExceptionType
,
328 IN BUNDLE NewBundles
[4],
329 IN
VOID (*NewCallback
) ()
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.
338 ExceptionType - Exception Type
339 NewBundles - New Boundles
340 NewCallback - New Callback
352 // Get address of bundle 0
354 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
357 // copy original bundles from IVT to IvtEntryTable so we can restore them later
360 IvtEntryTable
[ExceptionType
].OrigBundles
,
362 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
367 CopyMem (B0Ptr
, NewBundles
, sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
);
370 // fixup IVT entry so it stores its index and whether or not to chain...
372 FixupBundle
= B0Ptr
+ 2;
373 FixupBundle
->high
|= ExceptionType
<< 36;
375 InstructionCacheFlush (B0Ptr
, 5);
376 IvtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
382 IN EFI_EXCEPTION_TYPE ExceptionType
387 Restores original IVT contents when unregistering a callback function
390 ExceptionType - Exception Type
391 NewBundles - New Boundles
392 NewCallback - New Callback
403 // Get address of bundle 0
405 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
407 // restore original bundles in IVT
411 IvtEntryTable
[ExceptionType
].OrigBundles
,
412 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
414 InstructionCacheFlush (B0Ptr
, 5);
419 ChainExternalInterrupt (
420 IN
VOID (*NewCallback
) ()
425 Sets up cache flush and calls assembly function to chain external interrupt.
426 Records new callback in IvtEntryTable.
429 NewCallback - New Callback
439 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
440 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NewCallback
;
442 InstructionCacheFlush (Start
, 0x400);
447 UnchainExternalInterrupt (
453 Sets up cache flush and calls assembly function to restore external interrupt.
454 Removes registered callback from IvtEntryTable.
467 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
469 InstructionCacheFlush (Start
, 0x400);
470 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NULL
;
474 // The rest of the functions in this file are all member functions for the
475 // DebugSupport protocol
480 GetMaximumProcessorIndex (
481 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
482 OUT UINTN
*MaxProcessorIndex
486 Routine Description: This is a DebugSupport protocol member function. Hard
487 coded to support only 1 processor for now.
490 This - The DebugSupport instance
491 MaxProcessorIndex - The maximuim supported processor index
494 Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0
498 *MaxProcessorIndex
= 0;
499 return (EFI_SUCCESS
);
504 RegisterPeriodicCallback (
505 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
506 IN UINTN ProcessorIndex
,
507 IN EFI_PERIODIC_CALLBACK NewPeriodicCallback
512 DebugSupport protocol member function
515 This - The DebugSupport instance
516 ProcessorIndex - Which processor the callback applies to.
517 PeriodicCallback - Callback function
521 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
525 return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT
, NULL
, NewPeriodicCallback
);
530 RegisterExceptionCallback (
531 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
532 IN UINTN ProcessorIndex
,
533 IN EFI_EXCEPTION_CALLBACK NewCallback
,
534 IN EFI_EXCEPTION_TYPE ExceptionType
539 DebugSupport protocol member function
542 This - The DebugSupport instance
543 ProcessorIndex - Which processor the callback applies to.
544 NewCallback - Callback function
545 ExceptionType - Which exception to hook
549 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
553 return ManageIvtEntryTable (
555 (BUNDLE
*) ((EFI_PLABEL
*) HookStub
)->EntryPoint
,
562 InvalidateInstructionCache (
563 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
564 IN UINTN ProcessorIndex
,
571 DebugSupport protocol member function. Calls assembly routine to flush cache.
574 This - The DebugSupport instance
575 ProcessorIndex - Which processor the callback applies to.
576 Start - Physical base of the memory range to be invalidated
577 Length - mininum number of bytes in instruction cache to invalidate
584 InstructionCacheFlush (Start
, Length
);
585 return (EFI_SUCCESS
);