2 Top level module for the EBC virtual machine implementation.
3 Provides auxiliary support routines for the VM. That is, routines
4 that are not particularly related to VM execution of EBC instructions.
6 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "EbcExecute.h"
19 #include "EbcDebuggerHook.h"
22 // We'll keep track of all thunks we create in a linked list. Each
23 // thunk is tied to an image handle, so we have a linked list of
24 // image handles, with each having a linked list of thunks allocated
25 // to that image handle.
27 typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST
;
28 struct _EBC_THUNK_LIST
{
33 typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST
;
34 struct _EBC_IMAGE_LIST
{
36 EFI_HANDLE ImageHandle
;
37 EBC_THUNK_LIST
*ThunkList
;
41 This routine is called by the core when an image is being unloaded from
42 memory. Basically we now have the opportunity to do any necessary cleanup.
43 Typically this will include freeing any memory allocated for thunk-creation.
45 @param This A pointer to the EFI_EBC_PROTOCOL instance.
46 @param ImageHandle Handle of image for which the thunk is being
49 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
50 internal list of EBC image handles.
51 @retval EFI_SUCCESS The function completed successfully.
57 IN EFI_EBC_PROTOCOL
*This
,
58 IN EFI_HANDLE ImageHandle
62 This is the top-level routine plugged into the EBC protocol. Since thunks
63 are very processor-specific, from here we dispatch directly to the very
64 processor-specific routine EbcCreateThunks().
66 @param This A pointer to the EFI_EBC_PROTOCOL instance.
67 @param ImageHandle Handle of image for which the thunk is being
68 created. The EBC interpreter may use this to
69 keep track of any resource allocations
70 performed in loading and executing the image.
71 @param EbcEntryPoint Address of the actual EBC entry point or
72 protocol service the thunk should call.
73 @param Thunk Returned pointer to a thunk created.
75 @retval EFI_SUCCESS The function completed successfully.
76 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
77 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
83 IN EFI_EBC_PROTOCOL
*This
,
84 IN EFI_HANDLE ImageHandle
,
85 IN VOID
*EbcEntryPoint
,
90 Called to get the version of the interpreter.
92 @param This A pointer to the EFI_EBC_PROTOCOL instance.
93 @param Version Pointer to where to store the returned version
96 @retval EFI_SUCCESS The function completed successfully.
97 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
103 IN EFI_EBC_PROTOCOL
*This
,
104 IN OUT UINT64
*Version
108 To install default Callback function for the VM interpreter.
110 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
113 @retval EFI_SUCCESS The function completed successfully.
114 @retval Others Some error occurs when creating periodic event.
119 InitializeEbcCallback (
120 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
124 The default Exception Callback for the VM interpreter.
125 In this function, we report status code, and print debug information
126 about EBC_CONTEXT, then dead loop.
128 @param InterruptType Interrupt type.
129 @param SystemContext EBC system context.
134 CommonEbcExceptionHandler (
135 IN EFI_EXCEPTION_TYPE InterruptType
,
136 IN EFI_SYSTEM_CONTEXT SystemContext
140 The periodic callback function for EBC VM interpreter, which is used
141 to support the EFI debug support protocol.
143 @param Event The Periodic Callback Event.
144 @param Context It should be the address of VM_CONTEXT pointer.
149 EbcPeriodicNotifyFunction (
155 The VM interpreter calls this function on a periodic basis to support
156 the EFI debug support protocol.
158 @param VmPtr Pointer to a VM context for passing info to the
161 @retval EFI_SUCCESS The function completed successfully.
171 // These two functions and the GUID are used to produce an EBC test protocol.
172 // This functionality is definitely not required for execution.
175 Produces an EBC VM test protocol that can be used for regression tests.
177 @param IHandle Handle on which to install the protocol.
179 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
180 @retval EFI_SUCCESS The function completed successfully.
184 InitEbcVmTestProtocol (
185 IN EFI_HANDLE
*IHandle
189 Returns the EFI_UNSUPPORTED Status.
191 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
196 EbcVmTestUnsupported (
201 Registers a callback function that the EBC interpreter calls to flush the
202 processor instruction cache following creation of thunks.
204 @param This A pointer to the EFI_EBC_PROTOCOL instance.
205 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
207 @retval EFI_SUCCESS The function completed successfully.
212 EbcRegisterICacheFlush (
213 IN EFI_EBC_PROTOCOL
*This
,
214 IN EBC_ICACHE_FLUSH Flush
218 This EBC debugger protocol service is called by the debug agent
220 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
222 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
223 maximum supported processor index is returned.
225 @retval EFI_SUCCESS The function completed successfully.
230 EbcDebugGetMaximumProcessorIndex (
231 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
232 OUT UINTN
*MaxProcessorIndex
236 This protocol service is called by the debug agent to register a function
237 for us to call on a periodic basis.
239 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
241 @param ProcessorIndex Specifies which processor the callback function
243 @param PeriodicCallback A pointer to a function of type
244 PERIODIC_CALLBACK that is the main periodic
245 entry point of the debug agent. It receives as a
246 parameter a pointer to the full context of the
247 interrupted execution thread.
249 @retval EFI_SUCCESS The function completed successfully.
250 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
251 callback function was previously registered.
252 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
253 callback function was previously registered.
258 EbcDebugRegisterPeriodicCallback (
259 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
260 IN UINTN ProcessorIndex
,
261 IN EFI_PERIODIC_CALLBACK PeriodicCallback
265 This protocol service is called by the debug agent to register a function
266 for us to call when we detect an exception.
268 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
270 @param ProcessorIndex Specifies which processor the callback function
272 @param ExceptionCallback A pointer to a function of type
273 EXCEPTION_CALLBACK that is called when the
274 processor exception specified by ExceptionType
275 occurs. Passing NULL unregisters any previously
276 registered function associated with
278 @param ExceptionType Specifies which processor exception to hook.
280 @retval EFI_SUCCESS The function completed successfully.
281 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
282 callback function was previously registered.
283 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
285 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
286 callback function was previously registered.
291 EbcDebugRegisterExceptionCallback (
292 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
293 IN UINTN ProcessorIndex
,
294 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
295 IN EFI_EXCEPTION_TYPE ExceptionType
299 This EBC debugger protocol service is called by the debug agent. Required
300 for DebugSupport compliance but is only stubbed out for EBC.
302 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
304 @param ProcessorIndex Specifies which processor the callback function
306 @param Start StartSpecifies the physical base of the memory
307 range to be invalidated.
308 @param Length Specifies the minimum number of bytes in the
309 processor's instruction cache to invalidate.
311 @retval EFI_SUCCESS The function completed successfully.
316 EbcDebugInvalidateInstructionCache (
317 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
318 IN UINTN ProcessorIndex
,
324 // We have one linked list of image handles for the whole world. Since
325 // there should only be one interpreter, make them global. They must
326 // also be global since the execution of an EBC image does not provide
329 EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
332 // Callback function to flush the icache after thunk creation
334 EBC_ICACHE_FLUSH mEbcICacheFlush
;
337 // These get set via calls by the debug agent
339 EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
340 EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
342 VOID
*mStackBuffer
[MAX_STACK_NUM
];
343 EFI_HANDLE mStackBufferIndex
[MAX_STACK_NUM
];
347 // Event for Periodic callback
349 EFI_EVENT mEbcPeriodicEvent
;
350 VM_CONTEXT
*mVmPtr
= NULL
;
354 Initializes the VM EFI interface. Allocates memory for the VM interface
355 and registers the VM protocol.
357 @param ImageHandle EFI image handle.
358 @param SystemTable Pointer to the EFI system table.
360 @return Standard EFI status code.
365 InitializeEbcDriver (
366 IN EFI_HANDLE ImageHandle
,
367 IN EFI_SYSTEM_TABLE
*SystemTable
370 EFI_EBC_PROTOCOL
*EbcProtocol
;
371 EFI_EBC_PROTOCOL
*OldEbcProtocol
;
373 EFI_DEBUG_SUPPORT_PROTOCOL
*EbcDebugProtocol
;
374 EFI_HANDLE
*HandleBuffer
;
380 EbcDebugProtocol
= NULL
;
383 // Allocate memory for our protocol. Then fill in the blanks.
385 EbcProtocol
= AllocatePool (sizeof (EFI_EBC_PROTOCOL
));
387 if (EbcProtocol
== NULL
) {
388 return EFI_OUT_OF_RESOURCES
;
391 EbcProtocol
->CreateThunk
= EbcCreateThunk
;
392 EbcProtocol
->UnloadImage
= EbcUnloadImage
;
393 EbcProtocol
->RegisterICacheFlush
= EbcRegisterICacheFlush
;
394 EbcProtocol
->GetVersion
= EbcGetVersion
;
395 mEbcICacheFlush
= NULL
;
398 // Find any already-installed EBC protocols and uninstall them
402 Status
= gBS
->LocateHandleBuffer (
404 &gEfiEbcProtocolGuid
,
409 if (Status
== EFI_SUCCESS
) {
411 // Loop through the handles
413 for (Index
= 0; Index
< NumHandles
; Index
++) {
414 Status
= gBS
->HandleProtocol (
416 &gEfiEbcProtocolGuid
,
417 (VOID
**) &OldEbcProtocol
419 if (Status
== EFI_SUCCESS
) {
420 if (gBS
->ReinstallProtocolInterface (
422 &gEfiEbcProtocolGuid
,
432 if (HandleBuffer
!= NULL
) {
433 FreePool (HandleBuffer
);
437 // Add the protocol so someone can locate us if we haven't already.
440 Status
= gBS
->InstallProtocolInterface (
442 &gEfiEbcProtocolGuid
,
443 EFI_NATIVE_INTERFACE
,
446 if (EFI_ERROR (Status
)) {
447 FreePool (EbcProtocol
);
452 Status
= InitEBCStack();
453 if (EFI_ERROR(Status
)) {
458 // Allocate memory for our debug protocol. Then fill in the blanks.
460 EbcDebugProtocol
= AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL
));
462 if (EbcDebugProtocol
== NULL
) {
466 EbcDebugProtocol
->Isa
= IsaEbc
;
467 EbcDebugProtocol
->GetMaximumProcessorIndex
= EbcDebugGetMaximumProcessorIndex
;
468 EbcDebugProtocol
->RegisterPeriodicCallback
= EbcDebugRegisterPeriodicCallback
;
469 EbcDebugProtocol
->RegisterExceptionCallback
= EbcDebugRegisterExceptionCallback
;
470 EbcDebugProtocol
->InvalidateInstructionCache
= EbcDebugInvalidateInstructionCache
;
473 // Add the protocol so the debug agent can find us
475 Status
= gBS
->InstallProtocolInterface (
477 &gEfiDebugSupportProtocolGuid
,
478 EFI_NATIVE_INTERFACE
,
482 // This is recoverable, so free the memory and continue.
484 if (EFI_ERROR (Status
)) {
485 FreePool (EbcDebugProtocol
);
489 // Install EbcDebugSupport Protocol Successfully
490 // Now we need to initialize the Ebc default Callback
492 Status
= InitializeEbcCallback (EbcDebugProtocol
);
495 // Produce a VM test interface protocol. Not required for execution.
498 InitEbcVmTestProtocol (&ImageHandle
);
501 EbcDebuggerHookInit (ImageHandle
, EbcDebugProtocol
);
508 Status
= gBS
->LocateHandleBuffer (
510 &gEfiEbcProtocolGuid
,
515 if (Status
== EFI_SUCCESS
) {
517 // Loop through the handles
519 for (Index
= 0; Index
< NumHandles
; Index
++) {
520 Status
= gBS
->HandleProtocol (
522 &gEfiEbcProtocolGuid
,
523 (VOID
**) &OldEbcProtocol
525 if (Status
== EFI_SUCCESS
) {
526 gBS
->UninstallProtocolInterface (
528 &gEfiEbcProtocolGuid
,
535 if (HandleBuffer
!= NULL
) {
536 FreePool (HandleBuffer
);
540 FreePool (EbcProtocol
);
547 This is the top-level routine plugged into the EBC protocol. Since thunks
548 are very processor-specific, from here we dispatch directly to the very
549 processor-specific routine EbcCreateThunks().
551 @param This A pointer to the EFI_EBC_PROTOCOL instance.
552 @param ImageHandle Handle of image for which the thunk is being
553 created. The EBC interpreter may use this to
554 keep track of any resource allocations
555 performed in loading and executing the image.
556 @param EbcEntryPoint Address of the actual EBC entry point or
557 protocol service the thunk should call.
558 @param Thunk Returned pointer to a thunk created.
560 @retval EFI_SUCCESS The function completed successfully.
561 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
562 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
568 IN EFI_EBC_PROTOCOL
*This
,
569 IN EFI_HANDLE ImageHandle
,
570 IN VOID
*EbcEntryPoint
,
576 Status
= EbcCreateThunks (
580 FLAG_THUNK_ENTRY_POINT
587 This EBC debugger protocol service is called by the debug agent
589 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
591 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
592 maximum supported processor index is returned.
594 @retval EFI_SUCCESS The function completed successfully.
599 EbcDebugGetMaximumProcessorIndex (
600 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
601 OUT UINTN
*MaxProcessorIndex
604 *MaxProcessorIndex
= 0;
610 This protocol service is called by the debug agent to register a function
611 for us to call on a periodic basis.
613 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
615 @param ProcessorIndex Specifies which processor the callback function
617 @param PeriodicCallback A pointer to a function of type
618 PERIODIC_CALLBACK that is the main periodic
619 entry point of the debug agent. It receives as a
620 parameter a pointer to the full context of the
621 interrupted execution thread.
623 @retval EFI_SUCCESS The function completed successfully.
624 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
625 callback function was previously registered.
626 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
627 callback function was previously registered.
632 EbcDebugRegisterPeriodicCallback (
633 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
634 IN UINTN ProcessorIndex
,
635 IN EFI_PERIODIC_CALLBACK PeriodicCallback
638 if ((mDebugPeriodicCallback
== NULL
) && (PeriodicCallback
== NULL
)) {
639 return EFI_INVALID_PARAMETER
;
641 if ((mDebugPeriodicCallback
!= NULL
) && (PeriodicCallback
!= NULL
)) {
642 return EFI_ALREADY_STARTED
;
645 mDebugPeriodicCallback
= PeriodicCallback
;
651 This protocol service is called by the debug agent to register a function
652 for us to call when we detect an exception.
654 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
656 @param ProcessorIndex Specifies which processor the callback function
658 @param ExceptionCallback A pointer to a function of type
659 EXCEPTION_CALLBACK that is called when the
660 processor exception specified by ExceptionType
661 occurs. Passing NULL unregisters any previously
662 registered function associated with
664 @param ExceptionType Specifies which processor exception to hook.
666 @retval EFI_SUCCESS The function completed successfully.
667 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
668 callback function was previously registered.
669 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
671 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
672 callback function was previously registered.
677 EbcDebugRegisterExceptionCallback (
678 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
679 IN UINTN ProcessorIndex
,
680 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
681 IN EFI_EXCEPTION_TYPE ExceptionType
684 if ((ExceptionType
< 0) || (ExceptionType
> MAX_EBC_EXCEPTION
)) {
685 return EFI_INVALID_PARAMETER
;
687 if ((mDebugExceptionCallback
[ExceptionType
] == NULL
) && (ExceptionCallback
== NULL
)) {
688 return EFI_INVALID_PARAMETER
;
690 if ((mDebugExceptionCallback
[ExceptionType
] != NULL
) && (ExceptionCallback
!= NULL
)) {
691 return EFI_ALREADY_STARTED
;
693 mDebugExceptionCallback
[ExceptionType
] = ExceptionCallback
;
699 This EBC debugger protocol service is called by the debug agent. Required
700 for DebugSupport compliance but is only stubbed out for EBC.
702 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
704 @param ProcessorIndex Specifies which processor the callback function
706 @param Start StartSpecifies the physical base of the memory
707 range to be invalidated.
708 @param Length Specifies the minimum number of bytes in the
709 processor's instruction cache to invalidate.
711 @retval EFI_SUCCESS The function completed successfully.
716 EbcDebugInvalidateInstructionCache (
717 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
718 IN UINTN ProcessorIndex
,
728 The VM interpreter calls this function when an exception is detected.
730 @param ExceptionType Specifies the processor exception detected.
731 @param ExceptionFlags Specifies the exception context.
732 @param VmPtr Pointer to a VM context for passing info to the
735 @retval EFI_SUCCESS This function completed successfully.
739 EbcDebugSignalException (
740 IN EFI_EXCEPTION_TYPE ExceptionType
,
741 IN EXCEPTION_FLAGS ExceptionFlags
,
745 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
746 EFI_SYSTEM_CONTEXT SystemContext
;
748 ASSERT ((ExceptionType
>= 0) && (ExceptionType
<= MAX_EBC_EXCEPTION
));
750 // Save the exception in the context passed in
752 VmPtr
->ExceptionFlags
|= ExceptionFlags
;
753 VmPtr
->LastException
= (UINTN
) ExceptionType
;
755 // If it's a fatal exception, then flag it in the VM context in case an
756 // attached debugger tries to return from it.
758 if ((ExceptionFlags
& EXCEPTION_FLAG_FATAL
) != 0) {
759 VmPtr
->StopFlags
|= STOPFLAG_APP_DONE
;
763 // If someone's registered for exception callbacks, then call them.
765 // EBC driver will register default exception callback to report the
766 // status code via the status code API
768 if (mDebugExceptionCallback
[ExceptionType
] != NULL
) {
771 // Initialize the context structure
773 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
774 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
775 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
776 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
777 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
778 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
779 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
780 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
781 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
782 EbcContext
.Flags
= VmPtr
->Flags
;
783 EbcContext
.ControlFlags
= 0;
784 SystemContext
.SystemContextEbc
= &EbcContext
;
786 mDebugExceptionCallback
[ExceptionType
] (ExceptionType
, SystemContext
);
788 // Restore the context structure and continue to execute
790 VmPtr
->Gpr
[0] = EbcContext
.R0
;
791 VmPtr
->Gpr
[1] = EbcContext
.R1
;
792 VmPtr
->Gpr
[2] = EbcContext
.R2
;
793 VmPtr
->Gpr
[3] = EbcContext
.R3
;
794 VmPtr
->Gpr
[4] = EbcContext
.R4
;
795 VmPtr
->Gpr
[5] = EbcContext
.R5
;
796 VmPtr
->Gpr
[6] = EbcContext
.R6
;
797 VmPtr
->Gpr
[7] = EbcContext
.R7
;
798 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
799 VmPtr
->Flags
= EbcContext
.Flags
;
807 To install default Callback function for the VM interpreter.
809 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
812 @retval EFI_SUCCESS The function completed successfully.
813 @retval Others Some error occurs when creating periodic event.
818 InitializeEbcCallback (
819 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
826 // For ExceptionCallback
828 for (Index
= 0; Index
<= MAX_EBC_EXCEPTION
; Index
++) {
829 EbcDebugRegisterExceptionCallback (
832 CommonEbcExceptionHandler
,
838 // For PeriodicCallback
840 Status
= gBS
->CreateEvent (
841 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
843 EbcPeriodicNotifyFunction
,
847 if (EFI_ERROR(Status
)) {
851 Status
= gBS
->SetTimer (
854 EBC_VM_PERIODIC_CALLBACK_RATE
856 if (EFI_ERROR(Status
)) {
865 The default Exception Callback for the VM interpreter.
866 In this function, we report status code, and print debug information
867 about EBC_CONTEXT, then dead loop.
869 @param InterruptType Interrupt type.
870 @param SystemContext EBC system context.
875 CommonEbcExceptionHandler (
876 IN EFI_EXCEPTION_TYPE InterruptType
,
877 IN EFI_SYSTEM_CONTEXT SystemContext
881 // We print debug information to let user know what happen.
885 "EBC Interrupter Version - 0x%016lx\n",
886 (UINT64
) (((VM_MAJOR_VERSION
& 0xFFFF) << 16) | ((VM_MINOR_VERSION
& 0xFFFF)))
890 "Exception Type - 0x%016lx\n",
891 (UINT64
)(UINTN
)InterruptType
895 " R0 - 0x%016lx, R1 - 0x%016lx\n",
896 SystemContext
.SystemContextEbc
->R0
,
897 SystemContext
.SystemContextEbc
->R1
901 " R2 - 0x%016lx, R3 - 0x%016lx\n",
902 SystemContext
.SystemContextEbc
->R2
,
903 SystemContext
.SystemContextEbc
->R3
907 " R4 - 0x%016lx, R5 - 0x%016lx\n",
908 SystemContext
.SystemContextEbc
->R4
,
909 SystemContext
.SystemContextEbc
->R5
913 " R6 - 0x%016lx, R7 - 0x%016lx\n",
914 SystemContext
.SystemContextEbc
->R6
,
915 SystemContext
.SystemContextEbc
->R7
919 " Flags - 0x%016lx\n",
920 SystemContext
.SystemContextEbc
->Flags
924 " ControlFlags - 0x%016lx\n",
925 SystemContext
.SystemContextEbc
->ControlFlags
929 " Ip - 0x%016lx\n\n",
930 SystemContext
.SystemContextEbc
->Ip
934 // We deadloop here to make it easy to debug this issue.
943 The periodic callback function for EBC VM interpreter, which is used
944 to support the EFI debug support protocol.
946 @param Event The Periodic Callback Event.
947 @param Context It should be the address of VM_CONTEXT pointer.
952 EbcPeriodicNotifyFunction (
959 VmPtr
= *(VM_CONTEXT
**)Context
;
962 EbcDebugPeriodic (VmPtr
);
970 The VM interpreter calls this function on a periodic basis to support
971 the EFI debug support protocol.
973 @param VmPtr Pointer to a VM context for passing info to the
976 @retval EFI_SUCCESS The function completed successfully.
985 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
986 EFI_SYSTEM_CONTEXT SystemContext
;
989 // If someone's registered for periodic callbacks, then call them.
991 if (mDebugPeriodicCallback
!= NULL
) {
994 // Initialize the context structure
996 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
997 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
998 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
999 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
1000 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
1001 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
1002 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
1003 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
1004 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
1005 EbcContext
.Flags
= VmPtr
->Flags
;
1006 EbcContext
.ControlFlags
= 0;
1007 SystemContext
.SystemContextEbc
= &EbcContext
;
1009 mDebugPeriodicCallback (SystemContext
);
1012 // Restore the context structure and continue to execute
1014 VmPtr
->Gpr
[0] = EbcContext
.R0
;
1015 VmPtr
->Gpr
[1] = EbcContext
.R1
;
1016 VmPtr
->Gpr
[2] = EbcContext
.R2
;
1017 VmPtr
->Gpr
[3] = EbcContext
.R3
;
1018 VmPtr
->Gpr
[4] = EbcContext
.R4
;
1019 VmPtr
->Gpr
[5] = EbcContext
.R5
;
1020 VmPtr
->Gpr
[6] = EbcContext
.R6
;
1021 VmPtr
->Gpr
[7] = EbcContext
.R7
;
1022 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
1023 VmPtr
->Flags
= EbcContext
.Flags
;
1031 This routine is called by the core when an image is being unloaded from
1032 memory. Basically we now have the opportunity to do any necessary cleanup.
1033 Typically this will include freeing any memory allocated for thunk-creation.
1035 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1036 @param ImageHandle Handle of image for which the thunk is being
1039 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
1040 internal list of EBC image handles.
1041 @retval EFI_SUCCESS The function completed successfully.
1047 IN EFI_EBC_PROTOCOL
*This
,
1048 IN EFI_HANDLE ImageHandle
1051 EBC_THUNK_LIST
*ThunkList
;
1052 EBC_THUNK_LIST
*NextThunkList
;
1053 EBC_IMAGE_LIST
*ImageList
;
1054 EBC_IMAGE_LIST
*PrevImageList
;
1056 // First go through our list of known image handles and see if we've already
1057 // created an image list element for this image handle.
1059 ReturnEBCStackByHandle(ImageHandle
);
1060 PrevImageList
= NULL
;
1061 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1062 if (ImageList
->ImageHandle
== ImageHandle
) {
1066 // Save the previous so we can connect the lists when we remove this one
1068 PrevImageList
= ImageList
;
1071 if (ImageList
== NULL
) {
1072 return EFI_INVALID_PARAMETER
;
1075 // Free up all the thunk buffers and thunks list elements for this image
1078 ThunkList
= ImageList
->ThunkList
;
1079 while (ThunkList
!= NULL
) {
1080 NextThunkList
= ThunkList
->Next
;
1081 FreePool (ThunkList
->ThunkBuffer
);
1082 FreePool (ThunkList
);
1083 ThunkList
= NextThunkList
;
1086 // Now remove this image list element from the chain
1088 if (PrevImageList
== NULL
) {
1092 mEbcImageList
= ImageList
->Next
;
1094 PrevImageList
->Next
= ImageList
->Next
;
1097 // Now free up the image list element
1099 FreePool (ImageList
);
1101 EbcDebuggerHookEbcUnloadImage (ImageHandle
);
1108 Add a thunk to our list of thunks for a given image handle.
1109 Also flush the instruction cache since we've written thunk code
1110 to memory that will be executed eventually.
1112 @param ImageHandle The image handle to which the thunk is tied.
1113 @param ThunkBuffer The buffer that has been created/allocated.
1114 @param ThunkSize The size of the thunk memory allocated.
1116 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1117 @retval EFI_SUCCESS The function completed successfully.
1122 IN EFI_HANDLE ImageHandle
,
1123 IN VOID
*ThunkBuffer
,
1127 EBC_THUNK_LIST
*ThunkList
;
1128 EBC_IMAGE_LIST
*ImageList
;
1132 // It so far so good, then flush the instruction cache
1134 if (mEbcICacheFlush
!= NULL
) {
1135 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
1136 if (EFI_ERROR (Status
)) {
1141 // Go through our list of known image handles and see if we've already
1142 // created a image list element for this image handle.
1144 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1145 if (ImageList
->ImageHandle
== ImageHandle
) {
1150 if (ImageList
== NULL
) {
1152 // Allocate a new one
1154 ImageList
= AllocatePool (sizeof (EBC_IMAGE_LIST
));
1156 if (ImageList
== NULL
) {
1157 return EFI_OUT_OF_RESOURCES
;
1160 ImageList
->ThunkList
= NULL
;
1161 ImageList
->ImageHandle
= ImageHandle
;
1162 ImageList
->Next
= mEbcImageList
;
1163 mEbcImageList
= ImageList
;
1166 // Ok, now create a new thunk element to add to the list
1168 ThunkList
= AllocatePool (sizeof (EBC_THUNK_LIST
));
1170 if (ThunkList
== NULL
) {
1171 return EFI_OUT_OF_RESOURCES
;
1174 // Add it to the head of the list
1176 ThunkList
->Next
= ImageList
->ThunkList
;
1177 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1178 ImageList
->ThunkList
= ThunkList
;
1183 Registers a callback function that the EBC interpreter calls to flush the
1184 processor instruction cache following creation of thunks.
1186 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1187 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
1189 @retval EFI_SUCCESS The function completed successfully.
1194 EbcRegisterICacheFlush (
1195 IN EFI_EBC_PROTOCOL
*This
,
1196 IN EBC_ICACHE_FLUSH Flush
1199 mEbcICacheFlush
= Flush
;
1204 Called to get the version of the interpreter.
1206 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1207 @param Version Pointer to where to store the returned version
1210 @retval EFI_SUCCESS The function completed successfully.
1211 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
1217 IN EFI_EBC_PROTOCOL
*This
,
1218 IN OUT UINT64
*Version
1221 if (Version
== NULL
) {
1222 return EFI_INVALID_PARAMETER
;
1225 *Version
= GetVmVersion ();
1230 Returns the stack index and buffer assosicated with the Handle parameter.
1232 @param Handle The EFI handle as the index to the EBC stack.
1233 @param StackBuffer A pointer to hold the returned stack buffer.
1234 @param BufferIndex A pointer to hold the returned stack index.
1236 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any
1238 @retval EFI_SUCCESS The stack index and buffer were found and
1239 returned to the caller.
1244 IN EFI_HANDLE Handle
,
1245 OUT VOID
**StackBuffer
,
1246 OUT UINTN
*BufferIndex
1251 OldTpl
= gBS
->RaiseTPL(TPL_HIGH_LEVEL
);
1252 for (Index
= 0; Index
< mStackNum
; Index
++) {
1253 if (mStackBufferIndex
[Index
] == NULL
) {
1254 mStackBufferIndex
[Index
] = Handle
;
1258 gBS
->RestoreTPL(OldTpl
);
1259 if (Index
== mStackNum
) {
1260 return EFI_OUT_OF_RESOURCES
;
1262 *BufferIndex
= Index
;
1263 *StackBuffer
= mStackBuffer
[Index
];
1268 Returns from the EBC stack by stack Index.
1270 @param Index Specifies which EBC stack to return from.
1272 @retval EFI_SUCCESS The function completed successfully.
1280 mStackBufferIndex
[Index
] = NULL
;
1285 Returns from the EBC stack associated with the Handle parameter.
1287 @param Handle Specifies the EFI handle to find the EBC stack with.
1289 @retval EFI_SUCCESS The function completed successfully.
1293 ReturnEBCStackByHandle(
1294 IN EFI_HANDLE Handle
1298 for (Index
= 0; Index
< mStackNum
; Index
++) {
1299 if (mStackBufferIndex
[Index
] == Handle
) {
1303 if (Index
== mStackNum
) {
1304 return EFI_NOT_FOUND
;
1306 mStackBufferIndex
[Index
] = NULL
;
1311 Allocates memory to hold all the EBC stacks.
1313 @retval EFI_SUCCESS The EBC stacks were allocated successfully.
1314 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.
1322 for (mStackNum
= 0; mStackNum
< MAX_STACK_NUM
; mStackNum
++) {
1323 mStackBuffer
[mStackNum
] = AllocatePool(STACK_POOL_SIZE
);
1324 mStackBufferIndex
[mStackNum
] = NULL
;
1325 if (mStackBuffer
[mStackNum
] == NULL
) {
1329 if (mStackNum
== 0) {
1330 return EFI_OUT_OF_RESOURCES
;
1337 Free all EBC stacks allocated before.
1339 @retval EFI_SUCCESS All the EBC stacks were freed.
1348 for (Index
= 0; Index
< mStackNum
; Index
++) {
1349 FreePool(mStackBuffer
[Index
]);
1355 Produces an EBC VM test protocol that can be used for regression tests.
1357 @param IHandle Handle on which to install the protocol.
1359 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1360 @retval EFI_SUCCESS The function completed successfully.
1364 InitEbcVmTestProtocol (
1365 IN EFI_HANDLE
*IHandle
1370 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1373 // Allocate memory for the protocol, then fill in the fields
1375 EbcVmTestProtocol
= AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL
));
1376 if (EbcVmTestProtocol
== NULL
) {
1377 return EFI_OUT_OF_RESOURCES
;
1379 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1381 DEBUG_CODE_BEGIN ();
1382 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1383 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1387 // Publish the protocol
1390 Status
= gBS
->InstallProtocolInterface (&Handle
, &gEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1391 if (EFI_ERROR (Status
)) {
1392 FreePool (EbcVmTestProtocol
);
1399 Returns the EFI_UNSUPPORTED Status.
1401 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
1406 EbcVmTestUnsupported (
1410 return EFI_UNSUPPORTED
;