Import SourceLevelDebugPkg.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10867 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
1195
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Normal file
1195
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,308 @@
|
||||
/** @file
|
||||
Command header of for Debug Agent library instance.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _DEBUG_AGENT_H_
|
||||
#define _DEBUG_AGENT_H_
|
||||
|
||||
#include <Register/LocalApic.h>
|
||||
|
||||
#include <Guid/DebugAgentGuid.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/ResetSystemLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/DebugCommunicationLib.h>
|
||||
#include <Library/DebugAgentLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/SynchronizationLib.h>
|
||||
#include <Library/LocalApicLib.h>
|
||||
|
||||
#include <TransferProtocol.h>
|
||||
#include <ImageDebugSupport.h>
|
||||
|
||||
#include "DebugMp.h"
|
||||
#include "DebugTimer.h"
|
||||
#include "ArchDebugSupport.h"
|
||||
|
||||
#define DEBUG_AGENT_REVISION ((0 << 16) | 01)
|
||||
#define DEBUG_AGENT_CAPABILITIES 0
|
||||
|
||||
#define DEBUG_INT1_VECTOR 1
|
||||
#define DEBUG_INT3_VECTOR 3
|
||||
#define DEBUG_TIMER_VECTOR 32
|
||||
#define DEBUG_MAILBOX_VECTOR 33
|
||||
|
||||
#define SOFT_INTERRUPT_SIGNATURE SIGNATURE_32('S','O','F','T')
|
||||
#define SYSTEM_RESET_SIGNATURE SIGNATURE_32('S','Y','S','R')
|
||||
#define MEMORY_READY_SIGNATURE SIGNATURE_32('M','E','M','R')
|
||||
|
||||
extern UINTN Exception0Handle;
|
||||
extern UINTN TimerInterruptHandle;
|
||||
extern UINT16 ExceptionStubHeaderSize;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 HostPresent : 1;
|
||||
UINT32 BreakOnNextSmi : 1;
|
||||
UINT32 Reserved : 30;
|
||||
} Bits;
|
||||
UINT32 Uint32;
|
||||
} DEBUG_AGENT_FLAG;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
DEBUG_AGENT_FLAG DebugFlag;
|
||||
UINT64 DebugPortHandle;
|
||||
} DEBUG_AGENT_MAILBOX;
|
||||
#pragma pack()
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 LimitLow : 16;
|
||||
UINT32 BaseLow : 16;
|
||||
UINT32 BaseMid : 8;
|
||||
UINT32 Type : 4;
|
||||
UINT32 System : 1;
|
||||
UINT32 Dpl : 2;
|
||||
UINT32 Present : 1;
|
||||
UINT32 LimitHigh : 4;
|
||||
UINT32 Software : 1;
|
||||
UINT32 Reserved : 1;
|
||||
UINT32 DefaultSize : 1;
|
||||
UINT32 Granularity : 1;
|
||||
UINT32 BaseHigh : 8;
|
||||
} Bits;
|
||||
UINT64 Uint64;
|
||||
} IA32_GDT;
|
||||
|
||||
/**
|
||||
Caller provided function to be invoked at the end of DebugPortInitialize().
|
||||
|
||||
Refer to the descrption for DebugPortInitialize() for more details.
|
||||
|
||||
@param[in] Context The first input argument of DebugPortInitialize().
|
||||
@param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InitializeDebugAgentPhase2 (
|
||||
IN VOID *Context,
|
||||
IN DEBUG_PORT_HANDLE DebugPortHandle
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize IDT entries to support source level debug.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDebugIdt (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Write specified register into save CPU context.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Index Register index value.
|
||||
@param[in] Offset Offset in register address range
|
||||
@param[in] Width Data width to read.
|
||||
@param[in] RegisterBuffer Pointer to input buffer with data.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ArchWriteRegisterBuffer (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Offset,
|
||||
IN UINT8 Width,
|
||||
IN UINT8 *RegisterBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
Read register value from saved CPU context.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Index Register index value.
|
||||
@param[in] Offset Offset in register address range
|
||||
@param[in] Width Data width to read.
|
||||
|
||||
@return The address of register value.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
ArchReadRegisterBuffer (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Offset,
|
||||
IN UINT8 *Width
|
||||
);
|
||||
|
||||
/**
|
||||
Send packet with response data to HOST.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Data Pointer to response data buffer.
|
||||
@param[in] DataSize Size of response data in byte.
|
||||
|
||||
@retval RETURN_SUCCESS Response data was sent successfully.
|
||||
@retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
SendDataResponsePacket (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 *Data,
|
||||
IN UINT16 DataSize
|
||||
);
|
||||
|
||||
/**
|
||||
Read segment selector by register index.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterIndex Register Index.
|
||||
|
||||
@return Value of segment selector.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
ReadRegisterSelectorByIndex (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 RegisterIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Read group register of common registers.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroup Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroup (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
|
||||
);
|
||||
|
||||
/**
|
||||
Read group register of Segment Base.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroupSegBase Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroupSegBase (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase
|
||||
);
|
||||
|
||||
/**
|
||||
Read gourp register of Segment Limit.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroupSegLim Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroupSegLim (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim
|
||||
);
|
||||
|
||||
/**
|
||||
Read group register by group index.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] GroupIndex Group Index.
|
||||
|
||||
@retval RETURN_SUCCESS Read successfully.
|
||||
@retval RETURN_NOT_SUPPORTED Group index cannot be supported.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
ArchReadRegisterGroup (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 GroupIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Send acknowledge packet to HOST.
|
||||
|
||||
@param AckCommand Type of Acknowledge packet.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SendAckPacket (
|
||||
IN UINT8 AckCommand
|
||||
);
|
||||
|
||||
/**
|
||||
Receive acknowledge packet OK from HOST in specified time.
|
||||
|
||||
@param[in] Timeout Time out value to wait for acknowlege from HOST.
|
||||
The unit is microsecond.
|
||||
@param[out] BreakReceived If BreakReceived is not NULL,
|
||||
TRUE is retured if break-in symbol received.
|
||||
FALSE is retured if break-in symbol not received.
|
||||
|
||||
@retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
|
||||
the type of acknowlege packet saved in Ack.
|
||||
@retval RETURN_TIMEOUT Specified timeout value was up.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
WaitForAckPacketOK (
|
||||
IN UINTN Timeout,
|
||||
OUT BOOLEAN *BreakReceived OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Check if HOST is connected based on Mailbox.
|
||||
|
||||
@retval TRUE HOST is connected.
|
||||
@retval FALSE HOST is not connected.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsHostConnected (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Get Debug Agent Mailbox pointer.
|
||||
|
||||
@return Mailbox pointer.
|
||||
|
||||
**/
|
||||
DEBUG_AGENT_MAILBOX *
|
||||
GetMailboxPointer (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Get debug port handle.
|
||||
|
||||
@return Debug port handle.
|
||||
|
||||
**/
|
||||
DEBUG_PORT_HANDLE
|
||||
GetDebugPortHandle (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,365 @@
|
||||
/** @file
|
||||
Multi-Processor support functions implementation.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,0,0,0,0,0,0,FALSE,FALSE};
|
||||
|
||||
DEBUG_CPU_DATA volatile mDebugCpuData = {0};
|
||||
|
||||
/**
|
||||
Acquire access control on debug port.
|
||||
|
||||
It will block in the function if cannot get the access control.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireDebugPortControl (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (!MultiProcessorDebugSupport) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {
|
||||
break;
|
||||
}
|
||||
CpuPause ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Release access control on debug port.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseDebugPortControl (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (!MultiProcessorDebugSupport) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);
|
||||
}
|
||||
|
||||
/**
|
||||
Acquire access control on MP context.
|
||||
|
||||
It will block in the function if cannot get the access control.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireMpContextControl (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {
|
||||
break;
|
||||
}
|
||||
CpuPause ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Release access control on MP context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseMpContextControl (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);
|
||||
}
|
||||
|
||||
/**
|
||||
Break the other processor by send IPI.
|
||||
|
||||
@param[in] CurrentProcessorIndex Current processor index value.
|
||||
|
||||
**/
|
||||
VOID
|
||||
HaltOtherProcessors (
|
||||
IN UINT32 CurrentProcessorIndex
|
||||
)
|
||||
{
|
||||
|
||||
if (!IsBsp (CurrentProcessorIndex)) {
|
||||
SetIpiSentByApFlag (TRUE);;
|
||||
}
|
||||
|
||||
mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;
|
||||
|
||||
//
|
||||
// Send fixed IPI to other processors.
|
||||
//
|
||||
SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Get the current processor's index.
|
||||
|
||||
@return Processor index value.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
GetProcessorIndex (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
UINT16 LocalApicID;
|
||||
|
||||
LocalApicID = (UINT16) GetApicId ();
|
||||
|
||||
AcquireMpContextControl ();
|
||||
|
||||
for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {
|
||||
if (mDebugCpuData.ApicID[Index] == LocalApicID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index == mDebugCpuData.CpuCount) {
|
||||
mDebugCpuData.ApicID[Index] = LocalApicID;
|
||||
mDebugCpuData.CpuCount ++ ;
|
||||
}
|
||||
|
||||
ReleaseMpContextControl ();
|
||||
|
||||
return Index;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the specified processor is BSP or not.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
|
||||
@retval TRUE It is BSP.
|
||||
@retval FALSE It isn't BSP.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsBsp (
|
||||
IN UINT32 ProcessorIndex
|
||||
)
|
||||
{
|
||||
if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {
|
||||
if (mDebugMpContext.BspIndex != ProcessorIndex) {
|
||||
AcquireMpContextControl ();
|
||||
mDebugMpContext.BspIndex = ProcessorIndex;
|
||||
ReleaseMpContextControl ();
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set processor stop flag bitmask in MP context.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
@param[in] StopFlag TRUE means set stop flag.
|
||||
FALSE means clean break flag.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetCpuStopFlagByIndex (
|
||||
IN UINT32 ProcessorIndex,
|
||||
IN BOOLEAN StopFlag
|
||||
)
|
||||
{
|
||||
UINT8 Value;
|
||||
UINTN Index;
|
||||
|
||||
AcquireMpContextControl ();
|
||||
|
||||
Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];
|
||||
Index = ProcessorIndex % 8;
|
||||
if (StopFlag) {
|
||||
Value = BitFieldWrite8 (Value, Index, Index, 1);
|
||||
} else {
|
||||
Value = BitFieldWrite8 (Value, Index, Index, 0);
|
||||
}
|
||||
mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;
|
||||
|
||||
ReleaseMpContextControl ();
|
||||
}
|
||||
|
||||
/**
|
||||
Set processor break flag bitmask in MP context.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
@param[in] BreakFlag TRUE means set break flag.
|
||||
FALSE means clean break flag.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetCpuBreakFlagByIndex (
|
||||
IN UINT32 ProcessorIndex,
|
||||
IN BOOLEAN BreakFlag
|
||||
)
|
||||
{
|
||||
UINT8 Value;
|
||||
UINTN Index;
|
||||
|
||||
AcquireMpContextControl ();
|
||||
|
||||
Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];
|
||||
Index = ProcessorIndex % 8;
|
||||
if (BreakFlag) {
|
||||
Value = BitFieldWrite8 (Value, Index, Index, 1);
|
||||
} else {
|
||||
Value = BitFieldWrite8 (Value, Index, Index, 0);
|
||||
}
|
||||
mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;
|
||||
|
||||
ReleaseMpContextControl ();
|
||||
}
|
||||
|
||||
/**
|
||||
Check if processor is stopped already.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
|
||||
@retval TRUE Processor is stopped already.
|
||||
@retval TRUE Processor isn't stopped.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsCpuStopped (
|
||||
IN UINT32 ProcessorIndex
|
||||
)
|
||||
{
|
||||
UINT8 CpuMask;
|
||||
|
||||
CpuMask = (UINT8) (1 << (ProcessorIndex % 8));
|
||||
|
||||
if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set the run command flag.
|
||||
|
||||
@param[in] RunningFlag TRUE means run command flag is set.
|
||||
FALSE means run command flag is cleared.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetCpuRunningFlag (
|
||||
IN BOOLEAN RunningFlag
|
||||
)
|
||||
{
|
||||
AcquireMpContextControl ();
|
||||
|
||||
mDebugMpContext.RunCommandSet = RunningFlag;
|
||||
|
||||
ReleaseMpContextControl ();
|
||||
}
|
||||
|
||||
/**
|
||||
Set the current view point to be debugged.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetDebugViewPoint (
|
||||
IN UINT32 ProcessorIndex
|
||||
)
|
||||
{
|
||||
AcquireMpContextControl ();
|
||||
|
||||
mDebugMpContext.ViewPointIndex = ProcessorIndex;
|
||||
|
||||
ReleaseMpContextControl ();
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize debug timer.
|
||||
|
||||
@param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
|
||||
FALSE means this IPI is sent by BSP.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetIpiSentByApFlag (
|
||||
IN BOOLEAN IpiSentByApFlag
|
||||
)
|
||||
{
|
||||
AcquireMpContextControl ();
|
||||
|
||||
mDebugMpContext.IpiSentByAp = IpiSentByApFlag;
|
||||
|
||||
ReleaseMpContextControl ();
|
||||
}
|
||||
|
||||
/**
|
||||
Check if any processor breaks.
|
||||
|
||||
@retval others There is at least one processor broken, the minimum
|
||||
index number of Processor returned.
|
||||
@retval -1 No any processor broken.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
FindCpuNotRunning (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
|
||||
if (mDebugMpContext.CpuBreakMask[Index] != 0) {
|
||||
return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;
|
||||
}
|
||||
}
|
||||
return (UINT32)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if all processors are in running status.
|
||||
|
||||
@retval TRUE All processors run.
|
||||
@retval FALSE At least one processor does not run.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsAllCpuRunning (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
|
||||
if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -0,0 +1,221 @@
|
||||
/** @file
|
||||
Header file for Multi-Processor support.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _DEBUG_MP_H_
|
||||
#define _DEBUG_MP_H_
|
||||
|
||||
#define DEBUG_CPU_MAX_COUNT 256
|
||||
|
||||
typedef struct {
|
||||
UINT32 CpuCount; ///< Processor count
|
||||
UINT16 ApicID[DEBUG_CPU_MAX_COUNT]; ///< Record the local apic id for each processor
|
||||
} DEBUG_CPU_DATA;
|
||||
|
||||
typedef struct {
|
||||
SPIN_LOCK MpContextSpinLock; ///< Lock for writting MP context
|
||||
SPIN_LOCK DebugPortSpinLock; ///< Lock for access debug port
|
||||
UINT8 CpuBreakMask[DEBUG_CPU_MAX_COUNT/8]; ///< Bitmask of all breaking CPUs
|
||||
UINT8 CpuStopStatusMask[DEBUG_CPU_MAX_COUNT/8]; ///< Bitmask of CPU stop status
|
||||
UINT32 ViewPointIndex; ///< Current view point to be debugged
|
||||
UINT32 BspIndex; ///< Processor index value of BSP
|
||||
UINT32 BreakAtCpuIndex; ///< Processor index value of the current breaking CPU
|
||||
UINT32 DebugTimerInitCount; ///< Record BSP's init timer count
|
||||
BOOLEAN IpiSentByAp; ///< TRUR: IPI is sent by AP. TALSE: IPI is sent by BSP
|
||||
BOOLEAN RunCommandSet; ///< TRUE: RUN commmand is not executed. FALSE : RUN command is executed.
|
||||
} DEBUG_MP_CONTEXT;
|
||||
|
||||
extern CONST BOOLEAN MultiProcessorDebugSupport;
|
||||
extern DEBUG_MP_CONTEXT volatile mDebugMpContext;
|
||||
extern DEBUG_CPU_DATA volatile mDebugCpuData;
|
||||
|
||||
/**
|
||||
Break the other processor by send IPI.
|
||||
|
||||
@param[in] CurrentProcessorIndex Current processor index value.
|
||||
|
||||
**/
|
||||
VOID
|
||||
HaltOtherProcessors (
|
||||
IN UINT32 CurrentProcessorIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Get the current processor's index.
|
||||
|
||||
@return Processor index value.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
GetProcessorIndex (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Acquire access control on MP context.
|
||||
|
||||
It will block in the function if cannot get the access control.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireMpContextControl (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Release access control on MP context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseMpContextControl (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Acquire access control on debug port.
|
||||
|
||||
It will block in the function if cannot get the access control.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireDebugPortControl (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Release access control on debug port.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseDebugPortControl (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the specified processor is BSP or not.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
|
||||
@retval TRUE It is BSP.
|
||||
@retval FALSE It isn't BSP.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsBsp (
|
||||
IN UINT32 ProcessorIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Set processor stop flag bitmask in MP context.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
@param[in] StopFlag TRUE means set stop flag.
|
||||
FALSE means clean break flag.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetCpuStopFlagByIndex (
|
||||
IN UINT32 ProcessorIndex,
|
||||
IN BOOLEAN StopFlag
|
||||
);
|
||||
|
||||
/**
|
||||
Set processor break flag bitmask in MP context.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
@param[in] BreakFlag TRUE means set break flag.
|
||||
FALSE means clean break flag.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetCpuBreakFlagByIndex (
|
||||
IN UINT32 ProcessorIndex,
|
||||
IN BOOLEAN BreakFlag
|
||||
);
|
||||
|
||||
/**
|
||||
Check if processor is stopped already.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
|
||||
@retval TRUE Processor is stopped already.
|
||||
@retval FALSE Processor isn't stopped.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsCpuStopped (
|
||||
IN UINT32 ProcessorIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Set the run command flag.
|
||||
|
||||
@param[in] RunningFlag TRUE means run command flag is set.
|
||||
FALSE means run command flag is cleared.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetCpuRunningFlag (
|
||||
IN BOOLEAN RunningFlag
|
||||
);
|
||||
|
||||
/**
|
||||
Set the current view point to be debugged.
|
||||
|
||||
@param[in] ProcessorIndex Processor index value.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetDebugViewPoint (
|
||||
IN UINT32 ProcessorIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize debug timer.
|
||||
|
||||
@param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
|
||||
FALSE means this IPI is sent by BSP.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetIpiSentByApFlag (
|
||||
IN BOOLEAN IpiSentByApFlag
|
||||
);
|
||||
|
||||
/**
|
||||
Check if any processor breaks.
|
||||
|
||||
@retval others There is at least one processor broken, the minimum
|
||||
index number of Processor returned.
|
||||
@retval -1 No any processor broken.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
FindCpuNotRunning (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Check if all processors are in running status.
|
||||
|
||||
@retval TRUE All processors run.
|
||||
@retval FALSE At least one processor does not run.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsAllCpuRunning (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,83 @@
|
||||
/** @file
|
||||
Code for debug timer to support debug agent library implementation.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
/**
|
||||
Initialize CPU local APIC timer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDebugTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN ApicTimerDivisor;
|
||||
UINT32 InitialCount;
|
||||
|
||||
GetApicTimerState (&ApicTimerDivisor, NULL, NULL);
|
||||
|
||||
//
|
||||
// Cpu Local Apic timer interrupt frequency, it is set to 0.1s
|
||||
//
|
||||
InitialCount = (UINT32)DivU64x32 (
|
||||
MultU64x64 (
|
||||
PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor,
|
||||
100
|
||||
),
|
||||
1000
|
||||
);
|
||||
|
||||
InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);
|
||||
|
||||
if (MultiProcessorDebugSupport) {
|
||||
mDebugMpContext.DebugTimerInitCount = InitialCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Enable/Disable the interrupt of debug timer and return the interrupt state
|
||||
prior to the operation.
|
||||
|
||||
If EnableStatus is TRUE, enable the interrupt of debug timer.
|
||||
If EnableStatus is FALSE, disable the interrupt of debug timer.
|
||||
|
||||
@param[in] EnableStatus Enable/Disable.
|
||||
|
||||
@retval TRUE Debug timer interrupt were enabled on entry to this call.
|
||||
@retval FALSE Debug timer interrupt were disabled on entry to this call.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SaveAndSetDebugTimerInterrupt (
|
||||
IN BOOLEAN EnableStatus
|
||||
)
|
||||
{
|
||||
BOOLEAN OldInterruptState;
|
||||
BOOLEAN OldDebugTimerInterruptState;
|
||||
|
||||
OldInterruptState = SaveAndDisableInterrupts ();
|
||||
OldDebugTimerInterruptState = GetApicTimerInterruptState ();
|
||||
|
||||
if (EnableStatus) {
|
||||
EnableApicTimerInterrupt ();
|
||||
} else {
|
||||
DisableApicTimerInterrupt ();
|
||||
}
|
||||
|
||||
SetInterruptState (OldInterruptState);
|
||||
return OldDebugTimerInterruptState;
|
||||
}
|
||||
|
@@ -0,0 +1,28 @@
|
||||
/** @file
|
||||
Header file for debug timer to support debug agent library implementation.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _DEBUG_TIMER_H_
|
||||
#define _DEBUG_TIMER_H_
|
||||
|
||||
/**
|
||||
Initialize debug timer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDebugTimer (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,242 @@
|
||||
/** @file
|
||||
Public include file for Debug Port Library.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
/**
|
||||
Read the offset of FP / MMX / XMM registers by register index.
|
||||
|
||||
@param[in] Index Register index.
|
||||
@param[out] Width Register width returned.
|
||||
|
||||
@return Offset in register address range.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
ArchReadFxStatOffset (
|
||||
IN UINT8 Index,
|
||||
OUT UINT8 *Width
|
||||
)
|
||||
{
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
|
||||
switch (Index) {
|
||||
case SOFT_DEBUGGER_REGISTER_FP_FCW:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fcw);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_FSW:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fsw);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_FTW:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ftw);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Opcode);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_EIP:
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Eip);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_CS:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Cs);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, DataOffset);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_DS:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ds);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr_Mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {
|
||||
*Width = 10;
|
||||
} else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {
|
||||
*Width = 16;
|
||||
} else {
|
||||
*Width = 8;
|
||||
Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
|
||||
}
|
||||
|
||||
return (UINT16)(OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16);
|
||||
}
|
||||
|
||||
/**
|
||||
Write specified register into save CPU context.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Index Register index value.
|
||||
@param[in] Offset Offset in register address range.
|
||||
@param[in] Width Data width to read.
|
||||
@param[in] RegisterBuffer Pointer to input buffer with data.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ArchWriteRegisterBuffer (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Offset,
|
||||
IN UINT8 Width,
|
||||
IN UINT8 *RegisterBuffer
|
||||
)
|
||||
{
|
||||
UINT8 *Buffer;
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
|
||||
Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;
|
||||
} else {
|
||||
//
|
||||
// If it is MMX register, adjust its index position
|
||||
//
|
||||
if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {
|
||||
Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
|
||||
}
|
||||
//
|
||||
// FPU/MMX/XMM registers
|
||||
//
|
||||
Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);
|
||||
}
|
||||
|
||||
CopyMem (Buffer + Offset, RegisterBuffer, Width);
|
||||
}
|
||||
|
||||
/**
|
||||
Read register value from saved CPU context.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Index Register index value.
|
||||
@param[in] Offset Offset in register address range
|
||||
@param[in] Width Data width to read.
|
||||
|
||||
@return The address of register value.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
ArchReadRegisterBuffer (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Offset,
|
||||
IN UINT8 *Width
|
||||
)
|
||||
{
|
||||
UINT8 *Buffer;
|
||||
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
|
||||
Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;
|
||||
if (*Width == 0) {
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// FPU/MMX/XMM registers
|
||||
//
|
||||
Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);
|
||||
}
|
||||
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
Read group register of common registers.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroup Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroup (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
|
||||
)
|
||||
{
|
||||
RegisterGroup->Cs = (UINT16) CpuContext->Cs;
|
||||
RegisterGroup->Ds = (UINT16) CpuContext->Ds;
|
||||
RegisterGroup->Es = (UINT16) CpuContext->Es;
|
||||
RegisterGroup->Fs = (UINT16) CpuContext->Fs;
|
||||
RegisterGroup->Gs = (UINT16) CpuContext->Gs;
|
||||
RegisterGroup->Ss = (UINT16) CpuContext->Ss;
|
||||
RegisterGroup->Eflags = CpuContext->Eflags;
|
||||
RegisterGroup->Ebp = CpuContext->Ebp;
|
||||
RegisterGroup->Eip = CpuContext->Eip;
|
||||
RegisterGroup->Esp = CpuContext->Esp;
|
||||
RegisterGroup->Eax = CpuContext->Eax;
|
||||
RegisterGroup->Ebx = CpuContext->Ebx;
|
||||
RegisterGroup->Ecx = CpuContext->Ecx;
|
||||
RegisterGroup->Edx = CpuContext->Edx;
|
||||
RegisterGroup->Esi = CpuContext->Esi;
|
||||
RegisterGroup->Edi = CpuContext->Edi;
|
||||
RegisterGroup->Dr0 = CpuContext->Dr0;
|
||||
RegisterGroup->Dr1 = CpuContext->Dr1;
|
||||
RegisterGroup->Dr2 = CpuContext->Dr2;
|
||||
RegisterGroup->Dr3 = CpuContext->Dr3;
|
||||
RegisterGroup->Dr6 = CpuContext->Dr6;
|
||||
RegisterGroup->Dr7 = CpuContext->Dr7;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize IDT entries to support source level debug.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDebugIdt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
||||
UINTN InterruptHandler;
|
||||
IA32_DESCRIPTOR IdtDescriptor;
|
||||
UINTN Index;
|
||||
UINT16 CodeSegment;
|
||||
|
||||
AsmReadIdtr (&IdtDescriptor);
|
||||
|
||||
//
|
||||
// Use current CS as the segment selector of interrupt gate in IDT
|
||||
//
|
||||
CodeSegment = AsmReadCs ();
|
||||
|
||||
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
|
||||
|
||||
for (Index = 0; Index < 20; Index ++) {
|
||||
if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
|
||||
//
|
||||
// If the exception is masked to be reserved, skip it
|
||||
//
|
||||
continue;
|
||||
}
|
||||
InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;
|
||||
IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
|
||||
IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
|
||||
IdtEntry[Index].Bits.Selector = CodeSegment;
|
||||
IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
||||
}
|
||||
|
||||
InterruptHandler = (UINTN) &TimerInterruptHandle;
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
|
||||
IdtEntry[Index].Bits.Selector = CodeSegment;
|
||||
IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
IA32 specific defintions for debug agent library instance.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARCH_DEBUG_SUPPORT_H_
|
||||
#define _ARCH_DEBUG_SUPPORT_H_
|
||||
|
||||
#include "ArchRegisters.h"
|
||||
#include "TransferProtocol.h"
|
||||
|
||||
typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP;
|
||||
typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM;
|
||||
typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE;
|
||||
|
||||
#define DEBUG_SW_BREAKPOINT_SYMBOL 0xcc
|
||||
|
||||
#define DEBUG_ARCH_SYMBOL DEBUG_DATA_BREAK_CPU_ARCH_IA32
|
||||
|
||||
typedef DEBUG_DATA_IA32_SYSTEM_CONTEXT DEBUG_CPU_CONTEXT;
|
||||
|
||||
#endif
|
@@ -0,0 +1,210 @@
|
||||
/** @file
|
||||
IA32 Group registers read support functions.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
/**
|
||||
Read group register of Segment Base.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroupSegBase Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroupSegBase (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase
|
||||
)
|
||||
{
|
||||
IA32_DESCRIPTOR *Ia32Descriptor;
|
||||
IA32_GDT *Ia32Gdt;
|
||||
UINTN Index;
|
||||
|
||||
Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
|
||||
Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
|
||||
|
||||
Index = CpuContext->Cs / 8;
|
||||
RegisterGroupSegBase->CsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Ss / 8;
|
||||
RegisterGroupSegBase->SsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Gs / 8;
|
||||
RegisterGroupSegBase->GsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Fs / 8;
|
||||
RegisterGroupSegBase->FsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Es / 8;
|
||||
RegisterGroupSegBase->EsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Ds / 8;
|
||||
RegisterGroupSegBase->DsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
|
||||
RegisterGroupSegBase->LdtBas = 0;
|
||||
RegisterGroupSegBase->TssBas = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Read gourp register of Segment Limit.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroupSegLim Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroupSegLim (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim
|
||||
)
|
||||
{
|
||||
IA32_DESCRIPTOR *Ia32Descriptor;
|
||||
IA32_GDT *Ia32Gdt;
|
||||
UINTN Index;
|
||||
|
||||
Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
|
||||
Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
|
||||
|
||||
Index = CpuContext->Cs / 8;
|
||||
RegisterGroupSegLim->CsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->CsLim = (RegisterGroupSegLim->CsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Ss / 8;
|
||||
RegisterGroupSegLim->SsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->SsLim = (RegisterGroupSegLim->SsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Gs / 8;
|
||||
RegisterGroupSegLim->GsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->GsLim = (RegisterGroupSegLim->GsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Fs / 8;
|
||||
RegisterGroupSegLim->FsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->FsLim = (RegisterGroupSegLim->FsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Es / 8;
|
||||
RegisterGroupSegLim->EsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->EsLim = (RegisterGroupSegLim->EsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Ds / 8;
|
||||
RegisterGroupSegLim->DsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->DsLim = (RegisterGroupSegLim->DsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
RegisterGroupSegLim->LdtLim = 0xffff;
|
||||
RegisterGroupSegLim->TssLim = 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
Read group register by group index.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] GroupIndex Group Index.
|
||||
|
||||
@retval RETURN_SUCCESS Read successfully.
|
||||
@retval RETURN_NOT_SUPPORTED Group index cannot be supported.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
ArchReadRegisterGroup (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 GroupIndex
|
||||
)
|
||||
{
|
||||
DEBUG_DATA_REPONSE_READ_REGISTER_GROUP RegisterGroup;
|
||||
DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;
|
||||
DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;
|
||||
|
||||
switch (GroupIndex) {
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_GPDRS32:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_LIMITS32:
|
||||
ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupSegLim, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES32:
|
||||
ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupSegBase, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE));
|
||||
break;
|
||||
|
||||
default:
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Read segment selector by register index.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterIndex Register Index.
|
||||
|
||||
@return Value of segment selector.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
ReadRegisterSelectorByIndex (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 RegisterIndex
|
||||
)
|
||||
{
|
||||
IA32_DESCRIPTOR *Ia32Descriptor;
|
||||
IA32_GDT *Ia32Gdt;
|
||||
UINT16 Selector;
|
||||
UINT32 Data32;
|
||||
|
||||
Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
|
||||
Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
|
||||
|
||||
Selector = 0;
|
||||
|
||||
switch (RegisterIndex) {
|
||||
case SOFT_DEBUGGER_REGISTER_CSAS:
|
||||
Selector = (UINT16) CpuContext->Cs;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_SSAS:
|
||||
Selector = (UINT16) CpuContext->Ss;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_GSAS:
|
||||
Selector = (UINT16) CpuContext->Gs;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_FSAS:
|
||||
Selector = (UINT16) CpuContext->Fs;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_ESAS:
|
||||
Selector = (UINT16) CpuContext->Es;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_DSAS:
|
||||
Selector = (UINT16) CpuContext->Ds;
|
||||
case SOFT_DEBUGGER_REGISTER_LDTAS:
|
||||
case SOFT_DEBUGGER_REGISTER_TSSAS:
|
||||
return 0x00820000;
|
||||
break;
|
||||
}
|
||||
|
||||
Data32 = (UINT32) RShiftU64 (Ia32Gdt[Selector / 8].Uint64, 24);
|
||||
return (Data32 & (UINT32)(~0xff)) | Selector;
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,156 @@
|
||||
/** @file
|
||||
IA32 register defintions needed by debug transfer protocol.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARCH_REGISTERS_H_
|
||||
#define _ARCH_REGISTERS_H_
|
||||
|
||||
///
|
||||
/// FXSAVE_STATE
|
||||
/// FP / MMX / XMM registers (see fxrstor instruction definition)
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Fcw;
|
||||
UINT16 Fsw;
|
||||
UINT16 Ftw;
|
||||
UINT16 Opcode;
|
||||
UINT32 Eip;
|
||||
UINT16 Cs;
|
||||
UINT16 Reserved1;
|
||||
UINT32 DataOffset;
|
||||
UINT16 Ds;
|
||||
UINT8 Reserved2[2];
|
||||
UINT32 Mxcsr;
|
||||
UINT32 Mxcsr_Mask;
|
||||
UINT8 St0Mm0[10];
|
||||
UINT8 Reserved3[6];
|
||||
UINT8 St1Mm1[10];
|
||||
UINT8 Reserved4[6];
|
||||
UINT8 St2Mm2[10];
|
||||
UINT8 Reserved5[6];
|
||||
UINT8 St3Mm3[10];
|
||||
UINT8 Reserved6[6];
|
||||
UINT8 St4Mm4[10];
|
||||
UINT8 Reserved7[6];
|
||||
UINT8 St5Mm5[10];
|
||||
UINT8 Reserved8[6];
|
||||
UINT8 St6Mm6[10];
|
||||
UINT8 Reserved9[6];
|
||||
UINT8 St7Mm7[10];
|
||||
UINT8 Reserved10[6];
|
||||
UINT8 Xmm0[16];
|
||||
UINT8 Xmm1[16];
|
||||
UINT8 Xmm2[16];
|
||||
UINT8 Xmm3[16];
|
||||
UINT8 Xmm4[16];
|
||||
UINT8 Xmm5[16];
|
||||
UINT8 Xmm6[16];
|
||||
UINT8 Xmm7[16];
|
||||
UINT8 Reserved11[14 * 16];
|
||||
} DEBUG_DATA_IA32_FX_SAVE_STATE;
|
||||
|
||||
///
|
||||
/// IA-32 processor context definition
|
||||
///
|
||||
typedef struct {
|
||||
DEBUG_DATA_IA32_FX_SAVE_STATE FxSaveState;
|
||||
UINT32 Dr0;
|
||||
UINT32 Dr1;
|
||||
UINT32 Dr2;
|
||||
UINT32 Dr3;
|
||||
UINT32 Dr6;
|
||||
UINT32 Dr7;
|
||||
UINT32 Eflags;
|
||||
UINT32 Ldtr;
|
||||
UINT32 Tr;
|
||||
UINT32 Gdtr[2];
|
||||
UINT32 Idtr[2];
|
||||
UINT32 Eip;
|
||||
UINT32 Gs;
|
||||
UINT32 Fs;
|
||||
UINT32 Es;
|
||||
UINT32 Ds;
|
||||
UINT32 Cs;
|
||||
UINT32 Ss;
|
||||
UINT32 Cr0;
|
||||
UINT32 Cr1; ///< Reserved
|
||||
UINT32 Cr2;
|
||||
UINT32 Cr3;
|
||||
UINT32 Cr4;
|
||||
UINT32 Edi;
|
||||
UINT32 Esi;
|
||||
UINT32 Ebp;
|
||||
UINT32 Esp;
|
||||
UINT32 Edx;
|
||||
UINT32 Ecx;
|
||||
UINT32 Ebx;
|
||||
UINT32 Eax;
|
||||
} DEBUG_DATA_IA32_SYSTEM_CONTEXT;
|
||||
|
||||
///
|
||||
/// IA32 GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Cs;
|
||||
UINT16 Ds;
|
||||
UINT16 Es;
|
||||
UINT16 Fs;
|
||||
UINT16 Gs;
|
||||
UINT16 Ss;
|
||||
UINT32 Eflags;
|
||||
UINT32 Ebp;
|
||||
UINT32 Eip;
|
||||
UINT32 Esp;
|
||||
UINT32 Eax;
|
||||
UINT32 Ebx;
|
||||
UINT32 Ecx;
|
||||
UINT32 Edx;
|
||||
UINT32 Esi;
|
||||
UINT32 Edi;
|
||||
UINT32 Dr0;
|
||||
UINT32 Dr1;
|
||||
UINT32 Dr2;
|
||||
UINT32 Dr3;
|
||||
UINT32 Dr6;
|
||||
UINT32 Dr7;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_IA32;
|
||||
|
||||
///
|
||||
/// IA32 Segment Limit GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 CsLim;
|
||||
UINT32 SsLim;
|
||||
UINT32 GsLim;
|
||||
UINT32 FsLim;
|
||||
UINT32 EsLim;
|
||||
UINT32 DsLim;
|
||||
UINT32 LdtLim;
|
||||
UINT32 TssLim;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_IA32;
|
||||
|
||||
///
|
||||
/// IA32 Segment Base GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 CsBas;
|
||||
UINT32 SsBas;
|
||||
UINT32 GsBas;
|
||||
UINT32 FsBas;
|
||||
UINT32 EsBas;
|
||||
UINT32 DsBas;
|
||||
UINT32 LdtBas;
|
||||
UINT32 TssBas;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_IA32;
|
||||
|
||||
#endif
|
@@ -0,0 +1,360 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# AsmFuncs.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Debug interrupt handle functions.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#include "DebugException.h"
|
||||
|
||||
ASM_GLOBAL ASM_PFX(InterruptProcess)
|
||||
ASM_GLOBAL ASM_PFX(Exception0Handle)
|
||||
ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)
|
||||
ASM_GLOBAL ASM_PFX(TimerInterruptHandle)
|
||||
ASM_GLOBAL ASM_PFX(CommonEntry)
|
||||
|
||||
.data
|
||||
|
||||
ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)
|
||||
|
||||
.text
|
||||
|
||||
ASM_PFX(Exception0Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $0, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception1Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $1, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception2Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $2, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception3Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $3, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception4Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $4, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception5Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $5, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception6Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $6, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception7Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $7, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception8Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $8, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception9Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $9, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception10Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $10, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception11Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $11, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception12Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $12, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception13Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $13, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception14Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $14, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception15Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $15, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception16Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $16, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception17Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $17, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception18Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $18, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception19Handle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $19, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
|
||||
ASM_PFX(TimerInterruptHandle):
|
||||
cli
|
||||
pushl %eax
|
||||
mov $32, %eax
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
|
||||
|
||||
ASM_PFX(CommonEntry):
|
||||
|
||||
#---------------------------------------;
|
||||
# _CommonEntry ;
|
||||
#----------------------------------------------------------------------------;
|
||||
# The follow algorithm is used for the common interrupt routine.
|
||||
# Entry from each interrupt with a push eax and eax=interrupt number
|
||||
#
|
||||
# +---------------------+
|
||||
# + EFlags +
|
||||
# +---------------------+
|
||||
# + CS +
|
||||
# +---------------------+
|
||||
# + EIP +
|
||||
# +---------------------+
|
||||
# + Error Code +
|
||||
# +---------------------+
|
||||
# + EAX / Vector Number +
|
||||
# +---------------------+
|
||||
# + EBP +
|
||||
# +---------------------+ <-- EBP
|
||||
#
|
||||
|
||||
# We need to determine if any extra data was pushed by the exception
|
||||
cmpl $DEBUG_EXCEPT_DOUBLE_FAULT, %eax
|
||||
je NoExtrPush
|
||||
cmpl $DEBUG_EXCEPT_INVALID_TSS, %eax
|
||||
je NoExtrPush
|
||||
cmpl $DEBUG_EXCEPT_SEG_NOT_PRESENT, %eax
|
||||
je NoExtrPush
|
||||
cmpl $DEBUG_EXCEPT_STACK_FAULT, %eax
|
||||
je NoExtrPush
|
||||
cmpl $DEBUG_EXCEPT_GP_FAULT, %eax
|
||||
je NoExtrPush
|
||||
cmpl $DEBUG_EXCEPT_PAGE_FAULT, %eax
|
||||
je NoExtrPush
|
||||
cmpl $DEBUG_EXCEPT_ALIGNMENT_CHECK, %eax
|
||||
je NoExtrPush
|
||||
|
||||
pushl (%esp)
|
||||
movl $0, 4(%esp)
|
||||
|
||||
NoExtrPush:
|
||||
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
|
||||
#
|
||||
# Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
|
||||
# is 16-byte aligned
|
||||
#
|
||||
andl $0xfffffff0,%esp
|
||||
subl $12,%esp
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pushl 0x4(%ebp)
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
mov %eax, %ebx # save vector in ebx
|
||||
leal 24(%ebp),%ecx
|
||||
pushl %ecx # save original ESP
|
||||
pushl (%ebp)
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
movl %cr4, %eax
|
||||
orl $0x208,%eax
|
||||
movl %eax, %cr4
|
||||
pushl %eax
|
||||
movl %cr3, %eax
|
||||
pushl %eax
|
||||
movl %cr2, %eax
|
||||
pushl %eax
|
||||
xorl %eax,%eax
|
||||
pushl %eax
|
||||
movl %cr0, %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
movl %ss,%eax
|
||||
pushl %eax
|
||||
movzwl 16(%ebp), %eax
|
||||
pushl %eax
|
||||
movl %ds,%eax
|
||||
pushl %eax
|
||||
movl %es,%eax
|
||||
pushl %eax
|
||||
movl %fs,%eax
|
||||
pushl %eax
|
||||
movl %gs,%eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Eip;
|
||||
pushl 12(%ebp)
|
||||
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
subl $8,%esp
|
||||
sidt (%esp)
|
||||
subl $8,%esp
|
||||
sgdt (%esp)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
xorl %eax,%eax
|
||||
strl %eax
|
||||
pushl %eax
|
||||
sldtl %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 EFlags;
|
||||
pushl 20(%ebp)
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
movl %dr7, %eax
|
||||
pushl %eax
|
||||
## clear Dr7 while executing debugger itself
|
||||
xorl %eax,%eax
|
||||
# movl %eax, %dr7
|
||||
|
||||
movl %dr6, %eax
|
||||
pushl %eax
|
||||
## insure all status bits in dr6 are clear...
|
||||
xorl %eax,%eax
|
||||
movl %eax, %dr6
|
||||
|
||||
movl %dr3, %eax
|
||||
pushl %eax
|
||||
movl %dr2, %eax
|
||||
pushl %eax
|
||||
movl %dr1, %eax
|
||||
pushl %eax
|
||||
movl %dr0, %eax
|
||||
pushl %eax
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
subl $512,%esp
|
||||
movl %esp,%edi
|
||||
.byte 0x0f, 0xae, 0x07 # fxsave [edi]
|
||||
|
||||
## Clear Direction Flag
|
||||
cld
|
||||
|
||||
## Prepare parameter and call C function
|
||||
pushl %esp
|
||||
pushl %ebx
|
||||
call ASM_PFX(InterruptProcess)
|
||||
addl $8,%esp
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
movl %esp,%esi
|
||||
.byte 0x0f, 0xae, 0x0e # fxrstor [esi]
|
||||
addl $512,%esp
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
popl %eax
|
||||
movl %eax, %dr0
|
||||
popl %eax
|
||||
movl %eax, %dr1
|
||||
popl %eax
|
||||
movl %eax, %dr2
|
||||
popl %eax
|
||||
movl %eax, %dr3
|
||||
## skip restore of dr6. We cleared dr6 during the context save.
|
||||
addl $4,%esp
|
||||
popl %eax
|
||||
movl %eax, %dr7
|
||||
|
||||
## UINT32 EFlags;
|
||||
popl 20(%ebp)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
## Best not let anyone mess with these particular registers...
|
||||
addl $24,%esp
|
||||
|
||||
## UINT32 Eip;
|
||||
pop 12(%ebp)
|
||||
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
## NOTE - modified segment registers could hang the debugger... We
|
||||
## could attempt to insulate ourselves against this possibility,
|
||||
## but that poses risks as well.
|
||||
##
|
||||
popl %gs
|
||||
popl %fs
|
||||
popl %es
|
||||
popl %ds
|
||||
popl 16(%ebp)
|
||||
popl %ss
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
popl %eax
|
||||
movl %eax, %cr0
|
||||
addl $4,%esp # not for Cr1
|
||||
popl %eax
|
||||
movl %eax, %cr2
|
||||
popl %eax
|
||||
movl %eax, %cr3
|
||||
popl %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popl %edi
|
||||
popl %esi
|
||||
addl $4,%esp # not for ebp
|
||||
addl $4,%esp # not for esp
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
popl %eax
|
||||
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
addl $8,%esp # skip eax
|
||||
iretl
|
||||
|
@@ -0,0 +1,365 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; AsmFuncs.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Debug interrupt handle functions.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
#include "DebugException.h"
|
||||
|
||||
.686p
|
||||
.xmm
|
||||
.model flat,c
|
||||
|
||||
;
|
||||
; InterruptProcess()
|
||||
;
|
||||
InterruptProcess PROTO C
|
||||
|
||||
public Exception0Handle, TimerInterruptHandle, ExceptionStubHeaderSize
|
||||
|
||||
.data
|
||||
|
||||
ExceptionStubHeaderSize DW Exception1Handle - Exception0Handle
|
||||
CommonEntryAddr DD CommonEntry
|
||||
|
||||
.code
|
||||
|
||||
Exception0Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 0
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception1Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 1
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception2Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 2
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception3Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 3
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception4Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 4
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception5Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 5
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception6Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 6
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception7Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 7
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception8Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 8
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception9Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 9
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception10Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 10
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception11Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 11
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception12Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 12
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception13Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 13
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception14Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 14
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception15Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 15
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception16Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 16
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception17Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 17
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception18Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 18
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
Exception19Handle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 19
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
|
||||
TimerInterruptHandle:
|
||||
cli
|
||||
push eax
|
||||
mov eax, 32
|
||||
jmp dword ptr [CommonEntryAddr]
|
||||
|
||||
CommonEntry:
|
||||
;
|
||||
; +---------------------+
|
||||
; + EFlags +
|
||||
; +---------------------+
|
||||
; + CS +
|
||||
; +---------------------+
|
||||
; + EIP +
|
||||
; +---------------------+
|
||||
; + Error Code +
|
||||
; +---------------------+
|
||||
; + EAX / Vector Number +
|
||||
; +---------------------+
|
||||
; + EBP +
|
||||
; +---------------------+ <-- EBP
|
||||
;
|
||||
cmp eax, DEBUG_EXCEPT_DOUBLE_FAULT
|
||||
je NoExtrPush
|
||||
cmp eax, DEBUG_EXCEPT_INVALID_TSS
|
||||
je NoExtrPush
|
||||
cmp eax, DEBUG_EXCEPT_SEG_NOT_PRESENT
|
||||
je NoExtrPush
|
||||
cmp eax, DEBUG_EXCEPT_STACK_FAULT
|
||||
je NoExtrPush
|
||||
cmp eax, DEBUG_EXCEPT_GP_FAULT
|
||||
je NoExtrPush
|
||||
cmp eax, DEBUG_EXCEPT_PAGE_FAULT
|
||||
je NoExtrPush
|
||||
cmp eax, DEBUG_EXCEPT_ALIGNMENT_CHECK
|
||||
je NoExtrPush
|
||||
|
||||
push [esp]
|
||||
mov dword ptr [esp + 4], 0
|
||||
|
||||
NoExtrPush:
|
||||
|
||||
push ebp
|
||||
mov ebp, esp ; save esp in ebp
|
||||
;
|
||||
; Make stack 16-byte alignment to make sure save fxrstor later
|
||||
;
|
||||
and esp, 0fffffff0h
|
||||
sub esp, 12
|
||||
|
||||
; store UINT32 Edi, Esi, Ebp, Ebx, Edx, Ecx, Eax;
|
||||
push dword ptr [ebp + 4] ; original eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
mov ebx, eax ; save vector in ebx
|
||||
mov eax, ebp
|
||||
add eax, 4 * 6
|
||||
push eax ; original ESP
|
||||
push dword ptr [ebp] ; EBP
|
||||
push esi
|
||||
push edi
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
;; insure FXSAVE/FXRSTOR is enabled in CR4...
|
||||
;; ... while we're at it, make sure DE is also enabled...
|
||||
mov eax, cr4
|
||||
push eax ; push cr4 firstly
|
||||
or eax, 208h
|
||||
mov cr4, eax
|
||||
mov eax, cr3
|
||||
push eax
|
||||
mov eax, cr2
|
||||
push eax
|
||||
push 0 ; cr0 will not saved???
|
||||
mov eax, cr0
|
||||
push eax
|
||||
|
||||
xor ecx, ecx
|
||||
mov ecx, Ss
|
||||
push ecx
|
||||
mov ecx, Cs
|
||||
push ecx
|
||||
mov ecx, Ds
|
||||
push ecx
|
||||
mov ecx, Es
|
||||
push ecx
|
||||
mov ecx, Fs
|
||||
push ecx
|
||||
mov ecx, Gs
|
||||
push ecx
|
||||
|
||||
;; EIP
|
||||
mov ecx, [ebp + 4 * 3] ; EIP
|
||||
push ecx
|
||||
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
sub esp, 8
|
||||
sidt fword ptr [esp]
|
||||
sub esp, 8
|
||||
sgdt fword ptr [esp]
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
xor eax, eax
|
||||
str ax
|
||||
push eax
|
||||
sldt ax
|
||||
push eax
|
||||
|
||||
;; EFlags
|
||||
mov ecx, [ebp + 4 * 5]
|
||||
push ecx
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov eax, dr7
|
||||
push eax
|
||||
|
||||
;; clear Dr7 while executing debugger itself
|
||||
xor eax, eax
|
||||
;; mov dr7, eax
|
||||
|
||||
;; Dr6
|
||||
mov eax, dr6
|
||||
push eax
|
||||
|
||||
;; insure all status bits in dr6 are clear...
|
||||
xor eax, eax
|
||||
mov dr6, eax
|
||||
|
||||
mov eax, dr3
|
||||
push eax
|
||||
mov eax, dr2
|
||||
push eax
|
||||
mov eax, dr1
|
||||
push eax
|
||||
mov eax, dr0
|
||||
push eax
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
sub esp, 512
|
||||
mov edi, esp
|
||||
db 0fh, 0aeh, 00000111y ;fxsave [edi]
|
||||
|
||||
;; Clear Direction Flag
|
||||
cld
|
||||
|
||||
; call the C interrupt process function
|
||||
push esp ; Structure
|
||||
push ebx ; vector
|
||||
call InterruptProcess
|
||||
add esp, 8
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
mov esi, esp
|
||||
db 0fh, 0aeh, 00001110y ; fxrstor [esi]
|
||||
add esp, 512
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
pop eax
|
||||
mov dr0, eax
|
||||
pop eax
|
||||
mov dr1, eax
|
||||
pop eax
|
||||
mov dr2, eax
|
||||
pop eax
|
||||
mov dr3, eax
|
||||
;; skip restore of dr6. We cleared dr6 during the context save.
|
||||
add esp, 4
|
||||
pop eax
|
||||
mov dr7, eax
|
||||
|
||||
;; set EFlags
|
||||
pop dword ptr [ebp + 4 * 5] ; set EFLAGS in stack
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
;; Best not let anyone mess with these particular registers...
|
||||
add esp, 24
|
||||
|
||||
;; UINT32 Eip;
|
||||
pop dword ptr [ebp + 4 * 3] ; set EIP in stack
|
||||
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; NOTE - modified segment registers could hang the debugger... We
|
||||
;; could attempt to insulate ourselves against this possibility,
|
||||
;; but that poses risks as well.
|
||||
;;
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
pop dword ptr [ebp + 4 * 4] ; set CS in stack
|
||||
pop ss
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
pop eax
|
||||
mov cr0, eax
|
||||
add esp, 4 ; skip for Cr1
|
||||
pop eax
|
||||
mov cr2, eax
|
||||
pop eax
|
||||
mov cr3, eax
|
||||
pop eax
|
||||
mov cr4, eax
|
||||
|
||||
;; restore general register
|
||||
pop edi
|
||||
pop esi
|
||||
pop dword ptr [ebp] ; save updated ebp
|
||||
pop dword ptr [ebp + 4] ; save updated esp
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
|
||||
mov esp, ebp
|
||||
pop ebp ; restore ebp maybe updated
|
||||
pop esp ; restore esp maybe updated
|
||||
sub esp, 4 * 3 ; restore interupt pushced stack
|
||||
|
||||
iretd
|
||||
|
||||
END
|
@@ -0,0 +1,36 @@
|
||||
/** @file
|
||||
Exception defintions.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _DEBUG_EXCEPTION_H_
|
||||
#define _DEBUG_EXCEPTION_H_
|
||||
|
||||
#define DEBUG_EXCEPT_DIVIDE_ERROR 0
|
||||
#define DEBUG_EXCEPT_DEBUG 1
|
||||
#define DEBUG_EXCEPT_NMI 2
|
||||
#define DEBUG_EXCEPT_BREAKPOINT 3
|
||||
#define DEBUG_EXCEPT_OVERFLOW 4
|
||||
#define DEBUG_EXCEPT_BOUND 5
|
||||
#define DEBUG_EXCEPT_INVALID_OPCODE 6
|
||||
#define DEBUG_EXCEPT_DOUBLE_FAULT 8
|
||||
#define DEBUG_EXCEPT_INVALID_TSS 10
|
||||
#define DEBUG_EXCEPT_SEG_NOT_PRESENT 11
|
||||
#define DEBUG_EXCEPT_STACK_FAULT 12
|
||||
#define DEBUG_EXCEPT_GP_FAULT 13
|
||||
#define DEBUG_EXCEPT_PAGE_FAULT 14
|
||||
#define DEBUG_EXCEPT_FP_ERROR 16
|
||||
#define DEBUG_EXCEPT_ALIGNMENT_CHECK 17
|
||||
#define DEBUG_EXCEPT_MACHINE_CHECK 18
|
||||
#define DEBUG_EXCEPT_SIMD 19
|
||||
|
||||
#endif
|
@@ -0,0 +1,255 @@
|
||||
/** @file
|
||||
Supporting functions for x64 architecture.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
/**
|
||||
Read the offset of FP / MMX / XMM registers by register index.
|
||||
|
||||
@param[in] Index Register index.
|
||||
@param[out] Width Register width returned.
|
||||
|
||||
@return Offset in register address range.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
ArchReadFxStatOffset (
|
||||
IN UINT8 Index,
|
||||
OUT UINT8 *Width
|
||||
)
|
||||
{
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
|
||||
switch (Index) {
|
||||
case SOFT_DEBUGGER_REGISTER_FP_FCW:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Fcw);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_FSW:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Fsw);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_FTW:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Ftw);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
|
||||
*Width = (UINT8) sizeof (UINT16);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Opcode);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_EIP:
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Rip);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, DataOffset);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
|
||||
*Width = (UINT8) sizeof (UINT32);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Mxcsr);
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
|
||||
*Width = (UINT8) sizeof (UINT32);
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Mxcsr_Mask);
|
||||
|
||||
default:
|
||||
return (UINT16) (-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {
|
||||
*Width = 10;
|
||||
} else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {
|
||||
*Width = 16;
|
||||
} else {
|
||||
*Width = 8;
|
||||
Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
|
||||
}
|
||||
|
||||
return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;
|
||||
}
|
||||
|
||||
/**
|
||||
Write specified register into save CPU context.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Index Register index value.
|
||||
@param[in] Offset Offset in register address range
|
||||
@param[in] Width Data width to read.
|
||||
@param[in] RegisterBuffer Pointer to input buffer with data.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ArchWriteRegisterBuffer (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Offset,
|
||||
IN UINT8 Width,
|
||||
IN UINT8 *RegisterBuffer
|
||||
)
|
||||
{
|
||||
UINT8 *Buffer;
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
|
||||
Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_X64_FX_SAVE_STATE) + Index * 8;
|
||||
} else {
|
||||
//
|
||||
// If it is MMX register, adjust its index position
|
||||
//
|
||||
if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {
|
||||
Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
|
||||
}
|
||||
|
||||
//
|
||||
// FPU/MMX/XMM registers
|
||||
//
|
||||
Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);
|
||||
}
|
||||
|
||||
CopyMem (Buffer + Offset, RegisterBuffer, Width);
|
||||
}
|
||||
|
||||
/**
|
||||
Read register value from saved CPU context.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] Index Register index value.
|
||||
@param[in] Offset Offset in register address range
|
||||
@param[in] Width Data width to read.
|
||||
|
||||
@return The address of register value.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
ArchReadRegisterBuffer (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Offset,
|
||||
IN UINT8 *Width
|
||||
)
|
||||
{
|
||||
UINT8 *Buffer;
|
||||
|
||||
if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
|
||||
Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_X64_FX_SAVE_STATE) + Index * 8;
|
||||
if (*Width == 0) {
|
||||
*Width = (UINT8) sizeof (UINTN);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// FPU/MMX/XMM registers
|
||||
//
|
||||
Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);
|
||||
}
|
||||
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
Read group register of common registers.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroup Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroup (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
|
||||
)
|
||||
{
|
||||
RegisterGroup->Cs = (UINT16) CpuContext->Cs;
|
||||
RegisterGroup->Ds = (UINT16) CpuContext->Ds;
|
||||
RegisterGroup->Es = (UINT16) CpuContext->Es;
|
||||
RegisterGroup->Fs = (UINT16) CpuContext->Fs;
|
||||
RegisterGroup->Gs = (UINT16) CpuContext->Gs;
|
||||
RegisterGroup->Ss = (UINT16) CpuContext->Ss;
|
||||
RegisterGroup->Eflags = (UINT32) CpuContext->Eflags;
|
||||
RegisterGroup->Rbp = CpuContext->Rbp;
|
||||
RegisterGroup->Eip = CpuContext->Eip;
|
||||
RegisterGroup->Rsp = CpuContext->Rsp;
|
||||
RegisterGroup->Eax = CpuContext->Rax;
|
||||
RegisterGroup->Rbx = CpuContext->Rbx;
|
||||
RegisterGroup->Rcx = CpuContext->Rcx;
|
||||
RegisterGroup->Rdx = CpuContext->Rdx;
|
||||
RegisterGroup->Rsi = CpuContext->Rsi;
|
||||
RegisterGroup->Rdi = CpuContext->Rdi;
|
||||
RegisterGroup->R8 = CpuContext->R8;
|
||||
RegisterGroup->R9 = CpuContext->R9;
|
||||
RegisterGroup->R10 = CpuContext->R10;
|
||||
RegisterGroup->R11 = CpuContext->R11;
|
||||
RegisterGroup->R12 = CpuContext->R12;
|
||||
RegisterGroup->R13 = CpuContext->R13;
|
||||
RegisterGroup->R14 = CpuContext->R14;
|
||||
RegisterGroup->R15 = CpuContext->R15;
|
||||
RegisterGroup->Dr0 = CpuContext->Dr0;
|
||||
RegisterGroup->Dr1 = CpuContext->Dr1;
|
||||
RegisterGroup->Dr2 = CpuContext->Dr2;
|
||||
RegisterGroup->Dr3 = CpuContext->Dr3;
|
||||
RegisterGroup->Dr6 = CpuContext->Dr6;
|
||||
RegisterGroup->Dr7 = CpuContext->Dr7;
|
||||
RegisterGroup->Cr0 = CpuContext->Cr0;
|
||||
RegisterGroup->Cr2 = CpuContext->Cr2;
|
||||
RegisterGroup->Cr3 = CpuContext->Cr3;
|
||||
RegisterGroup->Cr4 = CpuContext->Cr4;
|
||||
RegisterGroup->Cr8 = CpuContext->Cr8;
|
||||
|
||||
CopyMem ((UINT8 *) &RegisterGroup->Xmm0[0], (UINT8 *) &CpuContext->FxSaveState.Xmm0[0], 16 * 10);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize IDT entries to support source level debug.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDebugIdt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
||||
UINTN InterruptHandler;
|
||||
IA32_DESCRIPTOR IdtDescriptor;
|
||||
UINTN Index;
|
||||
UINT16 CodeSegment;
|
||||
|
||||
AsmReadIdtr (&IdtDescriptor);
|
||||
|
||||
//
|
||||
// Use current CS as the segment selector of interrupt gate in IDT
|
||||
//
|
||||
CodeSegment = AsmReadCs ();
|
||||
|
||||
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
|
||||
|
||||
for (Index = 0; Index < 20; Index ++) {
|
||||
if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
|
||||
//
|
||||
// If the exception is masked to be reserved, skip it
|
||||
//
|
||||
continue;
|
||||
}
|
||||
InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;
|
||||
IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
|
||||
IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
|
||||
IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
|
||||
IdtEntry[Index].Bits.Selector = CodeSegment;
|
||||
IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
||||
}
|
||||
|
||||
InterruptHandler = (UINTN) &TimerInterruptHandle;
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment;
|
||||
IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
X64 specific defintions for debug agent library instance.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARCH_DEBUG_SUPPORT_H_
|
||||
#define _ARCH_DEBUG_SUPPORT_H_
|
||||
|
||||
#include "ArchRegisters.h"
|
||||
#include "TransferProtocol.h"
|
||||
|
||||
typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP;
|
||||
typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM;
|
||||
typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE;
|
||||
|
||||
#define DEBUG_SW_BREAKPOINT_SYMBOL 0xcc
|
||||
|
||||
#define DEBUG_ARCH_SYMBOL DEBUG_DATA_BREAK_CPU_ARCH_X64
|
||||
|
||||
typedef DEBUG_DATA_X64_SYSTEM_CONTEXT DEBUG_CPU_CONTEXT;
|
||||
|
||||
#endif
|
@@ -0,0 +1,259 @@
|
||||
/** @file
|
||||
x64 Group registers read support functions.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
/**
|
||||
Read segment selector by register index.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterIndex Register Index.
|
||||
|
||||
@return Value of segment selector.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
ReadRegisterSelectorByIndex (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 RegisterIndex
|
||||
)
|
||||
{
|
||||
IA32_DESCRIPTOR *Ia32Descriptor;
|
||||
IA32_GDT *Ia32Gdt;
|
||||
UINT16 Selector;
|
||||
UINT32 Data32;
|
||||
|
||||
Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
|
||||
Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
|
||||
|
||||
Selector = 0;
|
||||
|
||||
switch (RegisterIndex) {
|
||||
case SOFT_DEBUGGER_REGISTER_CSAS:
|
||||
Selector = (UINT16) CpuContext->Cs;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_SSAS:
|
||||
Selector = (UINT16) CpuContext->Ss;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_GSAS:
|
||||
Selector = (UINT16) CpuContext->Gs;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_FSAS:
|
||||
Selector = (UINT16) CpuContext->Fs;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_ESAS:
|
||||
Selector = (UINT16) CpuContext->Es;
|
||||
break;
|
||||
case SOFT_DEBUGGER_REGISTER_DSAS:
|
||||
Selector = (UINT16) CpuContext->Ds;
|
||||
case SOFT_DEBUGGER_REGISTER_LDTAS:
|
||||
case SOFT_DEBUGGER_REGISTER_TSSAS:
|
||||
return 0x00820000;
|
||||
break;
|
||||
}
|
||||
|
||||
Data32 = (UINT32) RShiftU64 (Ia32Gdt[Selector / 8].Uint64, 24);
|
||||
return (Data32 & (UINT32)(~0xff)) | Selector;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Read group register of Segment Base.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroupSegBase Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroupSegBase (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase
|
||||
)
|
||||
{
|
||||
IA32_DESCRIPTOR *Ia32Descriptor;
|
||||
IA32_GDT *Ia32Gdt;
|
||||
UINTN Index;
|
||||
|
||||
Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
|
||||
Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
|
||||
|
||||
Index = CpuContext->Cs / 8;
|
||||
RegisterGroupSegBase->CsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Ss / 8;
|
||||
RegisterGroupSegBase->SsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Gs / 8;
|
||||
RegisterGroupSegBase->GsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Fs / 8;
|
||||
RegisterGroupSegBase->FsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Es / 8;
|
||||
RegisterGroupSegBase->EsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
Index = CpuContext->Ds / 8;
|
||||
RegisterGroupSegBase->DsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
|
||||
|
||||
RegisterGroupSegBase->LdtBas = 0;
|
||||
RegisterGroupSegBase->TssBas = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Read group register of Segment Limit.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] RegisterGroupSegLim Pointer to Group registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReadRegisterGroupSegLim (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim
|
||||
)
|
||||
{
|
||||
IA32_DESCRIPTOR *Ia32Descriptor;
|
||||
IA32_GDT *Ia32Gdt;
|
||||
UINTN Index;
|
||||
|
||||
Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
|
||||
Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
|
||||
|
||||
Index = CpuContext->Cs / 8;
|
||||
RegisterGroupSegLim->CsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->CsLim = (RegisterGroupSegLim->CsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Ss / 8;
|
||||
RegisterGroupSegLim->SsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->SsLim = (RegisterGroupSegLim->SsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Gs / 8;
|
||||
RegisterGroupSegLim->GsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->GsLim = (RegisterGroupSegLim->GsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Fs / 8;
|
||||
RegisterGroupSegLim->FsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->FsLim = (RegisterGroupSegLim->FsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Es / 8;
|
||||
RegisterGroupSegLim->EsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->EsLim = (RegisterGroupSegLim->EsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
Index = CpuContext->Ds / 8;
|
||||
RegisterGroupSegLim->DsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
|
||||
if (Ia32Gdt[Index].Bits.Granularity == 1) {
|
||||
RegisterGroupSegLim->DsLim = (RegisterGroupSegLim->DsLim << 12) | 0xfff;
|
||||
}
|
||||
|
||||
RegisterGroupSegLim->LdtLim = 0xffff;
|
||||
RegisterGroupSegLim->TssLim = 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
Read group register by group index.
|
||||
|
||||
@param[in] CpuContext Pointer to saved CPU context.
|
||||
@param[in] GroupIndex Group Index.
|
||||
|
||||
@retval RETURN_SUCCESS Read successfully.
|
||||
@retval RETURN_NOT_SUPPORTED Group index cannot be supported.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
ArchReadRegisterGroup (
|
||||
IN DEBUG_CPU_CONTEXT *CpuContext,
|
||||
IN UINT8 GroupIndex
|
||||
)
|
||||
{
|
||||
UINTN DataN;
|
||||
DEBUG_DATA_REPONSE_READ_REGISTER_GROUP RegisterGroup;
|
||||
DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM RegisterGroupBasLim;
|
||||
DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64 RegisterGroupBases64;
|
||||
|
||||
switch (GroupIndex) {
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT64:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BAS_LIM64:
|
||||
DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);
|
||||
RegisterGroupBasLim.IdtLim = DataN;
|
||||
DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);
|
||||
RegisterGroupBasLim.GdtLim = DataN;
|
||||
DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);
|
||||
DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], sizeof (UINTN) * 8 - 16);
|
||||
RegisterGroupBasLim.IdtBas = DataN;
|
||||
DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);
|
||||
DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], sizeof (UINTN) * 8 - 16);
|
||||
RegisterGroupBasLim.GdtBas = DataN;
|
||||
|
||||
ReadRegisterGroupSegLim (CpuContext, (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *) &RegisterGroupBasLim.CsLim);
|
||||
ReadRegisterGroupSegBase (CpuContext, (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *) &RegisterGroupBasLim.CsBas);
|
||||
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupBasLim, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_GP2_64:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Eflags, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP2));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_GP64:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Eax, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_DR64:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr0, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_DR));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES64:
|
||||
RegisterGroupBases64.Ldtr = (UINT16) CpuContext->Ldtr;
|
||||
RegisterGroupBases64.Tr = (UINT16) CpuContext->Tr;
|
||||
|
||||
RegisterGroupBases64.Csas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_CSAS);
|
||||
RegisterGroupBases64.Ssas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_SSAS);
|
||||
RegisterGroupBases64.Gsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_GSAS);
|
||||
RegisterGroupBases64.Fsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_FSAS);
|
||||
RegisterGroupBases64.Esas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_ESAS);
|
||||
RegisterGroupBases64.Dsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_DSAS);
|
||||
RegisterGroupBases64.Ldtas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_LDTAS);
|
||||
RegisterGroupBases64.Tssas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_TSSAS);
|
||||
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupBases64, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_CR64:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr7 + 8, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_CR));
|
||||
break;
|
||||
|
||||
case SOFT_DEBUGGER_REGISTER_GROUP_XMM64:
|
||||
ReadRegisterGroup (CpuContext, &RegisterGroup);
|
||||
SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr7 + 8 * 6, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_XMM));
|
||||
break;
|
||||
|
||||
default:
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
@@ -0,0 +1,329 @@
|
||||
/** @file
|
||||
X64 register defintions needed by debug transfer protocol.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARCH_REGISTERS_H_
|
||||
#define _ARCH_REGISTERS_H_
|
||||
|
||||
///
|
||||
/// FXSAVE_STATE (promoted operation)
|
||||
/// FP / MMX / XMM registers (see fxrstor instruction definition)
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Fcw;
|
||||
UINT16 Fsw;
|
||||
UINT16 Ftw;
|
||||
UINT16 Opcode;
|
||||
UINT64 Rip;
|
||||
UINT64 DataOffset;
|
||||
UINT32 Mxcsr;
|
||||
UINT32 Mxcsr_Mask;
|
||||
UINT8 St0Mm0[10];
|
||||
UINT8 Reserved2[6];
|
||||
UINT8 St1Mm1[10];
|
||||
UINT8 Reserved3[6];
|
||||
UINT8 St2Mm2[10];
|
||||
UINT8 Reserved4[6];
|
||||
UINT8 St3Mm3[10];
|
||||
UINT8 Reserved5[6];
|
||||
UINT8 St4Mm4[10];
|
||||
UINT8 Reserved6[6];
|
||||
UINT8 St5Mm5[10];
|
||||
UINT8 Reserved7[6];
|
||||
UINT8 St6Mm6[10];
|
||||
UINT8 Reserved8[6];
|
||||
UINT8 St7Mm7[10];
|
||||
UINT8 Reserved9[6];
|
||||
UINT8 Xmm0[16];
|
||||
UINT8 Xmm1[16];
|
||||
UINT8 Xmm2[16];
|
||||
UINT8 Xmm3[16];
|
||||
UINT8 Xmm4[16];
|
||||
UINT8 Xmm5[16];
|
||||
UINT8 Xmm6[16];
|
||||
UINT8 Xmm7[16];
|
||||
UINT8 Xmm8[16];
|
||||
UINT8 Xmm9[16];
|
||||
UINT8 Xmm10[16];
|
||||
UINT8 Xmm11[16];
|
||||
UINT8 Xmm12[16];
|
||||
UINT8 Xmm13[16];
|
||||
UINT8 Xmm14[16];
|
||||
UINT8 Xmm15[16];
|
||||
UINT8 Reserved11[6 * 16];
|
||||
} DEBUG_DATA_X64_FX_SAVE_STATE;
|
||||
|
||||
///
|
||||
/// x64 processor context definition
|
||||
///
|
||||
typedef struct {
|
||||
DEBUG_DATA_X64_FX_SAVE_STATE FxSaveState;
|
||||
UINT64 Dr0;
|
||||
UINT64 Dr1;
|
||||
UINT64 Dr2;
|
||||
UINT64 Dr3;
|
||||
UINT64 Dr6;
|
||||
UINT64 Dr7;
|
||||
UINT64 Eflags;
|
||||
UINT64 Ldtr;
|
||||
UINT64 Tr;
|
||||
UINT64 Gdtr[2];
|
||||
UINT64 Idtr[2];
|
||||
UINT64 Eip;
|
||||
UINT64 Gs;
|
||||
UINT64 Fs;
|
||||
UINT64 Es;
|
||||
UINT64 Ds;
|
||||
UINT64 Cs;
|
||||
UINT64 Ss;
|
||||
UINT64 Cr0;
|
||||
UINT64 Cr1; /* Reserved */
|
||||
UINT64 Cr2;
|
||||
UINT64 Cr3;
|
||||
UINT64 Cr4;
|
||||
UINT64 Rdi;
|
||||
UINT64 Rsi;
|
||||
UINT64 Rbp;
|
||||
UINT64 Rsp;
|
||||
UINT64 Rdx;
|
||||
UINT64 Rcx;
|
||||
UINT64 Rbx;
|
||||
UINT64 Rax;
|
||||
UINT64 Cr8;
|
||||
UINT64 R8;
|
||||
UINT64 R9;
|
||||
UINT64 R10;
|
||||
UINT64 R11;
|
||||
UINT64 R12;
|
||||
UINT64 R13;
|
||||
UINT64 R14;
|
||||
UINT64 R15;
|
||||
} DEBUG_DATA_X64_SYSTEM_CONTEXT;
|
||||
|
||||
|
||||
///
|
||||
/// x64 GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Cs;
|
||||
UINT16 Ds;
|
||||
UINT16 Es;
|
||||
UINT16 Fs;
|
||||
UINT16 Gs;
|
||||
UINT16 Ss;
|
||||
UINT32 Eflags;
|
||||
UINT64 Rbp;
|
||||
UINT64 Eip;
|
||||
UINT64 Rsp;
|
||||
UINT64 Eax;
|
||||
UINT64 Rbx;
|
||||
UINT64 Rcx;
|
||||
UINT64 Rdx;
|
||||
UINT64 Rsi;
|
||||
UINT64 Rdi;
|
||||
UINT64 R8;
|
||||
UINT64 R9;
|
||||
UINT64 R10;
|
||||
UINT64 R11;
|
||||
UINT64 R12;
|
||||
UINT64 R13;
|
||||
UINT64 R14;
|
||||
UINT64 R15;
|
||||
UINT64 Dr0;
|
||||
UINT64 Dr1;
|
||||
UINT64 Dr2;
|
||||
UINT64 Dr3;
|
||||
UINT64 Dr6;
|
||||
UINT64 Dr7;
|
||||
UINT64 Cr0;
|
||||
UINT64 Cr2;
|
||||
UINT64 Cr3;
|
||||
UINT64 Cr4;
|
||||
UINT64 Cr8;
|
||||
UINT8 Xmm0[16];
|
||||
UINT8 Xmm1[16];
|
||||
UINT8 Xmm2[16];
|
||||
UINT8 Xmm3[16];
|
||||
UINT8 Xmm4[16];
|
||||
UINT8 Xmm5[16];
|
||||
UINT8 Xmm6[16];
|
||||
UINT8 Xmm7[16];
|
||||
UINT8 Xmm8[16];
|
||||
UINT8 Xmm9[16];
|
||||
UINT8 Xmm10[16];
|
||||
UINT8 Xmm11[16];
|
||||
UINT8 Xmm12[16];
|
||||
UINT8 Xmm13[16];
|
||||
UINT8 Xmm14[16];
|
||||
UINT8 Xmm15[16];
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_X64;
|
||||
|
||||
///
|
||||
/// x64 Segment Limit GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT64 CsLim;
|
||||
UINT64 SsLim;
|
||||
UINT64 GsLim;
|
||||
UINT64 FsLim;
|
||||
UINT64 EsLim;
|
||||
UINT64 DsLim;
|
||||
UINT64 LdtLim;
|
||||
UINT64 TssLim;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_X64;
|
||||
|
||||
///
|
||||
/// x64 Segment Base GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT64 CsBas;
|
||||
UINT64 SsBas;
|
||||
UINT64 GsBas;
|
||||
UINT64 FsBas;
|
||||
UINT64 EsBas;
|
||||
UINT64 DsBas;
|
||||
UINT64 LdtBas;
|
||||
UINT64 TssBas;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_X64;
|
||||
|
||||
///
|
||||
/// x64 Segment Base/Limit GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT64 IdtBas;
|
||||
UINT64 IdtLim;
|
||||
UINT64 GdtBas;
|
||||
UINT64 GdtLim;
|
||||
UINT64 CsLim;
|
||||
UINT64 SsLim;
|
||||
UINT64 GsLim;
|
||||
UINT64 FsLim;
|
||||
UINT64 EsLim;
|
||||
UINT64 DsLim;
|
||||
UINT64 LdtLim;
|
||||
UINT64 TssLim;
|
||||
UINT64 CsBas;
|
||||
UINT64 SsBas;
|
||||
UINT64 GsBas;
|
||||
UINT64 FsBas;
|
||||
UINT64 EsBas;
|
||||
UINT64 DsBas;
|
||||
UINT64 LdtBas;
|
||||
UINT64 TssBas;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM;
|
||||
|
||||
///
|
||||
/// x64 register GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT32 Eflags;
|
||||
UINT64 Rbp;
|
||||
UINT64 Eip;
|
||||
UINT64 Rsp;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP2;
|
||||
|
||||
///
|
||||
/// x64 general register GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT64 Eax;
|
||||
UINT64 Rbx;
|
||||
UINT64 Rcx;
|
||||
UINT64 Rdx;
|
||||
UINT64 Rsi;
|
||||
UINT64 Rdi;
|
||||
UINT64 R8;
|
||||
UINT64 R9;
|
||||
UINT64 R10;
|
||||
UINT64 R11;
|
||||
UINT64 R12;
|
||||
UINT64 R13;
|
||||
UINT64 R14;
|
||||
UINT64 R15;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP;
|
||||
|
||||
///
|
||||
/// x64 Segment GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Cs;
|
||||
UINT16 Ds;
|
||||
UINT16 Es;
|
||||
UINT16 Fs;
|
||||
UINT16 Gs;
|
||||
UINT16 Ss;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT;
|
||||
|
||||
///
|
||||
/// x64 Debug Register GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT64 Dr0;
|
||||
UINT64 Dr1;
|
||||
UINT64 Dr2;
|
||||
UINT64 Dr3;
|
||||
UINT64 Dr6;
|
||||
UINT64 Dr7;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_DR;
|
||||
|
||||
///
|
||||
/// x64 Control Register GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT64 Cr0;
|
||||
UINT64 Cr2;
|
||||
UINT64 Cr3;
|
||||
UINT64 Cr4;
|
||||
UINT64 Cr8;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_CR;
|
||||
|
||||
///
|
||||
/// x64 XMM Register GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Xmm0[16];
|
||||
UINT8 Xmm1[16];
|
||||
UINT8 Xmm2[16];
|
||||
UINT8 Xmm3[16];
|
||||
UINT8 Xmm4[16];
|
||||
UINT8 Xmm5[16];
|
||||
UINT8 Xmm6[16];
|
||||
UINT8 Xmm7[16];
|
||||
UINT8 Xmm8[16];
|
||||
UINT8 Xmm9[16];
|
||||
UINT8 Xmm10[16];
|
||||
UINT8 Xmm11[16];
|
||||
UINT8 Xmm12[16];
|
||||
UINT8 Xmm13[16];
|
||||
UINT8 Xmm14[16];
|
||||
UINT8 Xmm15[16];
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_XMM;
|
||||
|
||||
///
|
||||
/// x64 Segment Base GROUP register
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 Ldtr;
|
||||
UINT16 Tr;
|
||||
UINT64 Csas;
|
||||
UINT64 Ssas;
|
||||
UINT64 Gsas;
|
||||
UINT64 Fsas;
|
||||
UINT64 Esas;
|
||||
UINT64 Dsas;
|
||||
UINT64 Ldtas;
|
||||
UINT64 Tssas;
|
||||
} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64;
|
||||
|
||||
|
||||
#endif
|
@@ -0,0 +1,401 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# AsmFuncs.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Debug interrupt handle functions.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#include "DebugException.h"
|
||||
|
||||
ASM_GLOBAL ASM_PFX(InterruptProcess)
|
||||
|
||||
ASM_GLOBAL ASM_PFX(Exception0Handle)
|
||||
ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)
|
||||
ASM_GLOBAL ASM_PFX(TimerInterruptHandle)
|
||||
ASM_GLOBAL ASM_PFX(CommonEntry)
|
||||
|
||||
.data
|
||||
|
||||
ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)
|
||||
|
||||
|
||||
.text
|
||||
|
||||
ASM_PFX(Exception0Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $0, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception1Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $1, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception2Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $2, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception3Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $3, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception4Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $4, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception5Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $5, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception6Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $6, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception7Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $7, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception8Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $8, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception9Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $9, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception10Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $10, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception11Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $11, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception12Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $12, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception13Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $13, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception14Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $14, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception15Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $15, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception16Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $16, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception17Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $17, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception18Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $18, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
ASM_PFX(Exception19Handle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $19, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
|
||||
ASM_PFX(TimerInterruptHandle):
|
||||
cli
|
||||
pushq %rcx
|
||||
mov $32, %rcx
|
||||
jmp ASM_PFX(CommonEntry)
|
||||
|
||||
|
||||
ASM_PFX(CommonEntry):
|
||||
|
||||
#---------------------------------------;
|
||||
# CommonInterruptEntry ;
|
||||
#---------------------------------------;
|
||||
# The follow algorithm is used for the common interrupt routine.
|
||||
|
||||
#
|
||||
# +---------------------+ <-- 16-byte aligned ensured by processor
|
||||
# + Old SS +
|
||||
# +---------------------+
|
||||
# + Old RSP +
|
||||
# +---------------------+
|
||||
# + RFlags +
|
||||
# +---------------------+
|
||||
# + CS +
|
||||
# +---------------------+
|
||||
# + RIP +
|
||||
# +---------------------+
|
||||
# + Error Code +
|
||||
# +---------------------+
|
||||
# + RCX / Vector Number +
|
||||
# +---------------------+
|
||||
# + RBP +
|
||||
# +---------------------+ <-- RBP, 16-byte aligned
|
||||
#
|
||||
|
||||
# We need to determine if any extra data was pushed by the exception
|
||||
cmpq $DEBUG_EXCEPT_DOUBLE_FAULT, %rcx
|
||||
je NoExtrPush
|
||||
cmpq $DEBUG_EXCEPT_INVALID_TSS, %rcx
|
||||
je NoExtrPush
|
||||
cmpq $DEBUG_EXCEPT_SEG_NOT_PRESENT, %rcx
|
||||
je NoExtrPush
|
||||
cmpq $DEBUG_EXCEPT_STACK_FAULT, %rcx
|
||||
je NoExtrPush
|
||||
cmpq $DEBUG_EXCEPT_GP_FAULT, %rcx
|
||||
je NoExtrPush
|
||||
cmpq $DEBUG_EXCEPT_PAGE_FAULT, %rcx
|
||||
je NoExtrPush
|
||||
cmpq $DEBUG_EXCEPT_ALIGNMENT_CHECK, %rcx
|
||||
je NoExtrPush
|
||||
|
||||
pushq (%rsp)
|
||||
movq $0, 8(%rsp)
|
||||
|
||||
NoExtrPush:
|
||||
#
|
||||
# All interrupt handlers are invoked through interrupt gates, so
|
||||
# IF flag automatically cleared at the entry point
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
|
||||
#
|
||||
# Since here the stack pointer is 16-byte aligned, so
|
||||
# EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
|
||||
# is 16-byte aligned
|
||||
#
|
||||
|
||||
## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
|
||||
movq %cr8, %r8
|
||||
pushq %r8
|
||||
|
||||
## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
pushq %rax
|
||||
pushq %rbx
|
||||
pushq 8(%rbp) # original rcx
|
||||
pushq %rdx
|
||||
pushq 48(%rbp) # original rsp
|
||||
pushq (%rbp) # original rbp
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
|
||||
## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
movq %cr4, %rax
|
||||
orq $0x208, %rax
|
||||
movq %rax, %cr4
|
||||
pushq %rax
|
||||
movq %cr3, %rax
|
||||
pushq %rax
|
||||
movq %cr2, %rax
|
||||
pushq %rax
|
||||
xorq %rax, %rax
|
||||
pushq %rax
|
||||
movq %cr0, %rax
|
||||
pushq %rax
|
||||
|
||||
## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
xorq %rax, %rax # set rax to 0
|
||||
movzwq 56(%rbp), %rax
|
||||
# movq %ss, %rax
|
||||
pushq %rax
|
||||
movzwq 32(%rbp), %rax
|
||||
# movq %cs, %rax
|
||||
pushq %rax
|
||||
movq %ds, %rax
|
||||
pushq %rax
|
||||
movq %es, %rax
|
||||
pushq %rax
|
||||
movq %fs, %rax
|
||||
pushq %rax
|
||||
movq %gs, %rax
|
||||
pushq %rax
|
||||
|
||||
## UINT64 Rip;
|
||||
pushq 24(%rbp)
|
||||
|
||||
## UINT64 Gdtr[2], Idtr[2];
|
||||
subq $16, %rsp
|
||||
sidt (%rsp)
|
||||
subq $16, %rsp
|
||||
sgdt (%rsp)
|
||||
|
||||
## UINT64 Ldtr, Tr;
|
||||
xorq %rax, %rax
|
||||
strw %ax
|
||||
pushq %rax
|
||||
sldtw %ax
|
||||
pushq %rax
|
||||
|
||||
## UINT64 RFlags;
|
||||
pushq 40(%rbp)
|
||||
|
||||
## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
movq %dr7, %rax
|
||||
pushq %rax
|
||||
## clear Dr7 while executing debugger itself
|
||||
xorq %rax, %rax
|
||||
#debug movq %rax, %dr7
|
||||
|
||||
movq %dr6, %rax
|
||||
pushq %rax
|
||||
## insure all status bits in dr6 are clear...
|
||||
xorq %rax, %rax
|
||||
movq %rax, %dr6
|
||||
|
||||
movq %dr3, %rax
|
||||
pushq %rax
|
||||
movq %dr2, %rax
|
||||
pushq %rax
|
||||
movq %dr1, %rax
|
||||
pushq %rax
|
||||
movq %dr0, %rax
|
||||
pushq %rax
|
||||
|
||||
## FX_SAVE_STATE_X64 FxSaveState;
|
||||
subq $512, %rsp
|
||||
movq %rsp, %rdi
|
||||
.byte 0x0f, 0xae, 0b00000111
|
||||
|
||||
## Clear Direction Flag
|
||||
cld
|
||||
|
||||
## Prepare parameter and call
|
||||
# movq 8(%rbp), %rcx
|
||||
movq %rsp, %rdx
|
||||
movq %rcx, %r15 # save vector in r15
|
||||
#
|
||||
# Per X64 calling convention, allocate maximum parameter stack space
|
||||
# and make sure RSP is 16-byte aligned
|
||||
#
|
||||
subq $(4 * 8), %rsp
|
||||
call ASM_PFX(InterruptProcess)
|
||||
addq $(4 * 8), %rsp
|
||||
|
||||
## FX_SAVE_STATE_X64 FxSaveState;
|
||||
|
||||
movq %rsp, %rsi
|
||||
.byte 0x0f, 0xae, 0b00001110
|
||||
addq $512, %rsp
|
||||
|
||||
## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
popq %rax
|
||||
movq %rax, %dr0
|
||||
popq %rax
|
||||
movq %rax, %dr1
|
||||
popq %rax
|
||||
movq %rax, %dr2
|
||||
popq %rax
|
||||
movq %rax, %dr3
|
||||
## skip restore of dr6. We cleared dr6 during the context save.
|
||||
addq $8, %rsp
|
||||
popq %rax
|
||||
movq %rax, %dr7
|
||||
|
||||
## UINT64 RFlags;
|
||||
popq 40(%rbp)
|
||||
|
||||
## UINT64 Ldtr, Tr;
|
||||
## UINT64 Gdtr[2], Idtr[2];
|
||||
## Best not let anyone mess with these particular registers...
|
||||
addq $48, %rsp
|
||||
|
||||
## UINT64 Rip;
|
||||
popq 24(%rbp)
|
||||
|
||||
## UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
popq %rax
|
||||
# mov gs, rax ; not for gs
|
||||
popq %rax
|
||||
# mov fs, rax ; not for fs
|
||||
# (X64 will not use fs and gs, so we do not restore it)
|
||||
popq %rax
|
||||
movw %rax, %es
|
||||
popq %rax
|
||||
movw %rax, %ds
|
||||
popq 32(%rbp)
|
||||
popq 56(%rbp)
|
||||
|
||||
## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
popq %rax
|
||||
movq %rax, %cr0
|
||||
addq $8, %rsp
|
||||
popq %rax
|
||||
movq %rax, %cr2
|
||||
popq %rax
|
||||
movq %rax, %cr3
|
||||
popq %rax
|
||||
movq %rax, %cr4
|
||||
|
||||
## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
addq $8, %rsp
|
||||
addq $8, %rsp
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
popq %rax
|
||||
|
||||
popq %r8
|
||||
movq %r8, %cr8
|
||||
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
movq %rbp, %rsp
|
||||
popq %rbp
|
||||
addq $16, %rsp
|
||||
iretq
|
@@ -0,0 +1,364 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; AsmFuncs.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Debug interrupt handle functions.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
#include "DebugException.h"
|
||||
|
||||
|
||||
externdef InterruptProcess:near
|
||||
|
||||
data SEGMENT
|
||||
|
||||
public Exception0Handle, TimerInterruptHandle, ExceptionStubHeaderSize
|
||||
|
||||
ExceptionStubHeaderSize dw Exception1Handle - Exception0Handle ;
|
||||
CommonEntryAddr dq CommonEntry ;
|
||||
|
||||
.code
|
||||
|
||||
Exception0Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 0
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception1Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 1
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception2Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 2
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception3Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 3
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception4Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 4
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception5Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 5
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception6Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 6
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception7Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 7
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception8Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 8
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception9Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 9
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception10Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 10
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception11Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 11
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception12Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 12
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception13Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 13
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception14Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 14
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception15Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 15
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception16Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 16
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception17Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 17
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception18Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 18
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
Exception19Handle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 19
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
|
||||
TimerInterruptHandle:
|
||||
cli
|
||||
push rcx
|
||||
mov rcx, 32
|
||||
jmp qword ptr [CommonEntryAddr]
|
||||
|
||||
CommonEntry:
|
||||
; We need to determine if any extra data was pushed by the exception
|
||||
cmp rcx, DEBUG_EXCEPT_DOUBLE_FAULT
|
||||
je NoExtrPush
|
||||
cmp rcx, DEBUG_EXCEPT_INVALID_TSS
|
||||
je NoExtrPush
|
||||
cmp rcx, DEBUG_EXCEPT_SEG_NOT_PRESENT
|
||||
je NoExtrPush
|
||||
cmp rcx, DEBUG_EXCEPT_STACK_FAULT
|
||||
je NoExtrPush
|
||||
cmp rcx, DEBUG_EXCEPT_GP_FAULT
|
||||
je NoExtrPush
|
||||
cmp rcx, DEBUG_EXCEPT_PAGE_FAULT
|
||||
je NoExtrPush
|
||||
cmp rcx, DEBUG_EXCEPT_ALIGNMENT_CHECK
|
||||
je NoExtrPush
|
||||
|
||||
push [rsp]
|
||||
mov qword ptr [rsp + 8], 0
|
||||
|
||||
NoExtrPush:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
|
||||
mov r8, cr8
|
||||
push r8
|
||||
|
||||
; store UINT64 Rdi, Rsi, Rbp, Rsp, Rdx, Rcx, Rbx, Rax;
|
||||
push rax
|
||||
push rbx
|
||||
push qword ptr [rbp + 8] ; original rcx
|
||||
push rdx
|
||||
push qword ptr [rbp + 6 * 8] ; original rsp
|
||||
push qword ptr [rbp] ; original rbp
|
||||
push rsi
|
||||
push rdi
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
;; insure FXSAVE/FXRSTOR is enabled in CR4...
|
||||
;; ... while we're at it, make sure DE is also enabled...
|
||||
mov rax, cr4
|
||||
or rax, 208h
|
||||
mov cr4, rax
|
||||
push rax
|
||||
mov rax, cr3
|
||||
push rax
|
||||
mov rax, cr2
|
||||
push rax
|
||||
push 0 ; cr0 will not saved???
|
||||
mov rax, cr0
|
||||
push rax
|
||||
|
||||
xor rax, rax
|
||||
mov rax, Ss
|
||||
push rax
|
||||
mov rax, Cs
|
||||
push rax
|
||||
mov rax, Ds
|
||||
push rax
|
||||
mov rax, Es
|
||||
push rax
|
||||
mov rax, Fs
|
||||
push rax
|
||||
mov rax, Gs
|
||||
push rax
|
||||
|
||||
;; EIP
|
||||
mov rax, [rbp + 8 * 3] ; EIP
|
||||
push rax
|
||||
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
sub rsp, 16
|
||||
sidt fword ptr [rsp]
|
||||
sub rsp, 16
|
||||
sgdt fword ptr [rsp]
|
||||
|
||||
;; UINT64 Ldtr, Tr;
|
||||
xor rax, rax
|
||||
str ax
|
||||
push rax
|
||||
sldt ax
|
||||
push rax
|
||||
|
||||
;; EFlags
|
||||
mov rax, [rbp + 8 * 5]
|
||||
push rax
|
||||
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov rax, dr7
|
||||
push rax
|
||||
|
||||
;; clear Dr7 while executing debugger itself
|
||||
xor rax, rax
|
||||
mov dr7, rax
|
||||
|
||||
;; Dr6
|
||||
mov rax, dr6
|
||||
push rax
|
||||
|
||||
;; insure all status bits in dr6 are clear...
|
||||
xor rax, rax
|
||||
mov dr6, rax
|
||||
|
||||
mov rax, dr3
|
||||
push rax
|
||||
mov rax, dr2
|
||||
push rax
|
||||
mov rax, dr1
|
||||
push rax
|
||||
mov rax, dr0
|
||||
push rax
|
||||
|
||||
sub rsp, 512
|
||||
mov rdi, rsp
|
||||
db 0fh, 0aeh, 00000111y ;fxsave [rdi]
|
||||
|
||||
;; Clear Direction Flag
|
||||
cld
|
||||
|
||||
; call the C interrupt process function
|
||||
mov rdx, rsp ; Structure
|
||||
mov r15, rcx ; save vector in r15
|
||||
|
||||
sub rsp, 32
|
||||
call InterruptProcess
|
||||
add rsp, 32
|
||||
|
||||
mov rsi, rsp
|
||||
db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
|
||||
add rsp, 512
|
||||
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
pop rax
|
||||
mov dr0, rax
|
||||
pop rax
|
||||
mov dr1, rax
|
||||
pop rax
|
||||
mov dr2, rax
|
||||
pop rax
|
||||
mov dr3, rax
|
||||
;; skip restore of dr6. We cleared dr6 during the context save.
|
||||
add rsp, 8
|
||||
pop rax
|
||||
mov dr7, rax
|
||||
|
||||
;; set EFlags
|
||||
pop qword ptr [rbp + 8 * 5]
|
||||
|
||||
;; UINT64 Ldtr, Tr;
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
;; Best not let anyone mess with these particular registers...
|
||||
add rsp, 24 * 2
|
||||
|
||||
;; UINT64 Eip;
|
||||
pop qword ptr [rbp + 8 * 3] ; set EIP in stack
|
||||
|
||||
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; NOTE - modified segment registers could hang the debugger... We
|
||||
;; could attempt to insulate ourselves against this possibility,
|
||||
;; but that poses risks as well.
|
||||
;;
|
||||
pop rax
|
||||
pop rax
|
||||
pop rax
|
||||
mov es, rax
|
||||
pop rax
|
||||
mov ds, rax
|
||||
pop qword ptr [rbp + 8 * 4] ; Set CS in stack
|
||||
pop rax
|
||||
mov ss, rax
|
||||
|
||||
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
pop rax
|
||||
mov cr0, rax
|
||||
add rsp, 8 ; skip for Cr1
|
||||
pop rax
|
||||
mov cr2, rax
|
||||
pop rax
|
||||
mov cr3, rax
|
||||
pop rax
|
||||
mov cr4, rax
|
||||
|
||||
;; restore general register
|
||||
pop rdi
|
||||
pop rsi
|
||||
add rsp, 8 ; skip rbp
|
||||
add rsp, 8 ; skip rsp
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
pop r8
|
||||
mov cr8, r8
|
||||
|
||||
; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
|
||||
mov rsp, rbp
|
||||
pop rbp
|
||||
add rsp, 16 ; skip rcx and error code
|
||||
|
||||
iretq
|
||||
|
||||
END
|
@@ -0,0 +1,36 @@
|
||||
/** @file
|
||||
Exception defintions.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _DEBUG_EXCEPTION_H_
|
||||
#define _DEBUG_EXCEPTION_H_
|
||||
|
||||
#define DEBUG_EXCEPT_DIVIDE_ERROR 0
|
||||
#define DEBUG_EXCEPT_DEBUG 1
|
||||
#define DEBUG_EXCEPT_NMI 2
|
||||
#define DEBUG_EXCEPT_BREAKPOINT 3
|
||||
#define DEBUG_EXCEPT_OVERFLOW 4
|
||||
#define DEBUG_EXCEPT_BOUND 5
|
||||
#define DEBUG_EXCEPT_INVALID_OPCODE 6
|
||||
#define DEBUG_EXCEPT_DOUBLE_FAULT 8
|
||||
#define DEBUG_EXCEPT_INVALID_TSS 10
|
||||
#define DEBUG_EXCEPT_SEG_NOT_PRESENT 11
|
||||
#define DEBUG_EXCEPT_STACK_FAULT 12
|
||||
#define DEBUG_EXCEPT_GP_FAULT 13
|
||||
#define DEBUG_EXCEPT_PAGE_FAULT 14
|
||||
#define DEBUG_EXCEPT_FP_ERROR 16
|
||||
#define DEBUG_EXCEPT_ALIGNMENT_CHECK 17
|
||||
#define DEBUG_EXCEPT_MACHINE_CHECK 18
|
||||
#define DEBUG_EXCEPT_SIMD 19
|
||||
|
||||
#endif
|
@@ -0,0 +1,247 @@
|
||||
/** @file
|
||||
Debug Agent library implementition for Dxe Core and Dxr modules.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "DxeDebugAgentLib.h"
|
||||
|
||||
DEBUG_AGENT_MAILBOX mMailbox;
|
||||
|
||||
DEBUG_AGENT_MAILBOX *mMailboxPointer;
|
||||
|
||||
IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];
|
||||
|
||||
BOOLEAN mConfigurationTableNeeded = FALSE;
|
||||
|
||||
CONST BOOLEAN MultiProcessorDebugSupport = TRUE;
|
||||
|
||||
/**
|
||||
Constructor allocates the NVS memory to store Mailbox and install configuration table
|
||||
in system table to store its pointer.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval RETURN_SUCCESS Allocate the global memory space to store guid and function tables.
|
||||
@retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
DxeDebugAgentLibConstructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
|
||||
if (!mConfigurationTableNeeded) {
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
Address = 0;
|
||||
Status = gBS->AllocatePages (
|
||||
AllocateAnyPages,
|
||||
EfiACPIMemoryNVS,
|
||||
EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX)),
|
||||
&Address
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyMem (
|
||||
(UINT8 *) (UINTN) Address,
|
||||
(UINT8 *) (UINTN) mMailboxPointer,
|
||||
sizeof (DEBUG_AGENT_MAILBOX)
|
||||
);
|
||||
|
||||
mMailboxPointer = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;
|
||||
|
||||
return gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the pointer to Mailbox from the GUIDed HOB.
|
||||
|
||||
@param[in] HobStart The starting HOB pointer to search from.
|
||||
|
||||
@return Pointer to Mailbox.
|
||||
|
||||
**/
|
||||
DEBUG_AGENT_MAILBOX *
|
||||
GetMailboxFromHob (
|
||||
IN VOID *HobStart
|
||||
)
|
||||
{
|
||||
EFI_HOB_GUID_TYPE *GuidHob;
|
||||
|
||||
GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);
|
||||
if (GuidHob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (DEBUG_AGENT_MAILBOX *) (GET_GUID_HOB_DATA(GuidHob));
|
||||
}
|
||||
|
||||
/**
|
||||
Get Debug Agent Mailbox pointer.
|
||||
|
||||
@return Mailbox pointer.
|
||||
|
||||
**/
|
||||
DEBUG_AGENT_MAILBOX *
|
||||
GetMailboxPointer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return mMailboxPointer;
|
||||
}
|
||||
|
||||
/**
|
||||
Get debug port handle.
|
||||
|
||||
@return Debug port handle.
|
||||
|
||||
**/
|
||||
DEBUG_PORT_HANDLE
|
||||
GetDebugPortHandle (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize debug agent.
|
||||
|
||||
This function is used to set up debug enviroment for DXE phase.
|
||||
|
||||
If this function is called by DXE Core, Context must be the pointer
|
||||
to HOB list which will be used to get GUIDed HOB. It will enable
|
||||
interrupt to support break-in feature.
|
||||
If this function is called by DXE module, Context must be NULL. It
|
||||
will enable interrupt to support break-in feature.
|
||||
|
||||
@param[in] InitFlag Init flag is used to decide initialize process.
|
||||
@param[in] Context Context needed according to InitFlag.
|
||||
@param[in] Function Continue function called by debug agent library; it was
|
||||
optional.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InitializeDebugAgent (
|
||||
IN UINT32 InitFlag,
|
||||
IN VOID *Context, OPTIONAL
|
||||
IN DEBUG_AGENT_CONTINUE Function OPTIONAL
|
||||
)
|
||||
{
|
||||
DEBUG_AGENT_MAILBOX *Mailbox;
|
||||
IA32_DESCRIPTOR Idtr;
|
||||
UINT16 IdtEntryCount;
|
||||
BOOLEAN InterruptStatus;
|
||||
|
||||
if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&
|
||||
InitFlag != DEBUG_AGENT_INIT_S3 &&
|
||||
InitFlag != DEBUG_AGENT_INIT_DXE_AP) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Save and disable original interrupt status
|
||||
//
|
||||
InterruptStatus = SaveAndDisableInterrupts ();
|
||||
|
||||
if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
|
||||
//
|
||||
// Try to get Mailbox from GUIDed HOB.
|
||||
//
|
||||
mConfigurationTableNeeded = TRUE;
|
||||
Mailbox = GetMailboxFromHob (Context);
|
||||
|
||||
} else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
|
||||
|
||||
EnableInterrupts ();
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
//
|
||||
// If it is in S3 path, needn't to install configuration table.
|
||||
//
|
||||
Mailbox = NULL;
|
||||
}
|
||||
|
||||
if (Mailbox != NULL) {
|
||||
//
|
||||
// If Mailbox exists, copy it into one global variable.
|
||||
//
|
||||
CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
|
||||
mMailbox.DebugPortHandle = 0;
|
||||
} else {
|
||||
//
|
||||
// If Mailbox not exists, used the local Mailbox.
|
||||
//
|
||||
ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
|
||||
}
|
||||
|
||||
mMailboxPointer = &mMailbox;
|
||||
|
||||
//
|
||||
// Get original IDT address and size.
|
||||
//
|
||||
AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
|
||||
IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
|
||||
if (IdtEntryCount < 33) {
|
||||
Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
|
||||
Idtr.Base = (UINTN) &mIdtEntryTable;
|
||||
AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the IDT table entries to support source level debug.
|
||||
//
|
||||
InitializeDebugIdt ();
|
||||
|
||||
//
|
||||
// Initialize debug communication port
|
||||
//
|
||||
mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize (NULL, NULL);
|
||||
|
||||
InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
|
||||
InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
|
||||
|
||||
if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
|
||||
//
|
||||
// Initialize Debug Timer hardware and enable interrupt.
|
||||
//
|
||||
InitializeDebugTimer ();
|
||||
EnableInterrupts ();
|
||||
|
||||
return;
|
||||
} else {
|
||||
//
|
||||
// Disable Debug Timer interrupt in S3 path.
|
||||
//
|
||||
SaveAndSetDebugTimerInterrupt (FALSE);
|
||||
|
||||
//
|
||||
// Restore interrupt state.
|
||||
//
|
||||
SetInterruptState (InterruptStatus);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,25 @@
|
||||
/** @file
|
||||
Header file for Dxe Core Debug Agent Library instance.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _DXE_CORE_DEBUG_AGENT_LIB_H_
|
||||
#define _DXE_CORE_DEBUG_AGENT_LIB_H_
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
#endif
|
87
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
Normal file
87
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
Normal file
@@ -0,0 +1,87 @@
|
||||
## @file
|
||||
# Debug Agent library instance for Dxe Core and Dxe modules.
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = DxeDebugAgentLib
|
||||
FILE_GUID = BA6BAD25-B814-4747-B0B0-0FBB61D40B90
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 0.7
|
||||
LIBRARY_CLASS = DebugAgentLib|DXE_CORE DXE_DRIVER
|
||||
|
||||
CONSTRUCTOR = DxeDebugAgentLibConstructor
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
DxeDebugAgent/DxeDebugAgentLib.c
|
||||
DxeDebugAgent/DxeDebugAgentLib.h
|
||||
DebugAgentCommon/DebugAgent.c
|
||||
DebugAgentCommon/DebugAgent.h
|
||||
DebugAgentCommon/DebugTimer.c
|
||||
DebugAgentCommon/DebugTimer.h
|
||||
DebugAgentCommon/DebugMp.c
|
||||
DebugAgentCommon/DebugMp.h
|
||||
|
||||
[Sources.Ia32]
|
||||
DebugAgentCommon/Ia32/AsmFuncs.S | GCC
|
||||
DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT
|
||||
DebugAgentCommon/Ia32/ArchDebugSupport.h
|
||||
DebugAgentCommon/Ia32/ArchDebugSupport.c
|
||||
DebugAgentCommon/Ia32/ArchReadGroupRegister.c
|
||||
DebugAgentCommon/Ia32/ArchRegisters.h
|
||||
DebugAgentCommon/Ia32/DebugException.h
|
||||
|
||||
[Sources.X64]
|
||||
DebugAgentCommon/X64/AsmFuncs.S | GCC
|
||||
DebugAgentCommon/X64/AsmFuncs.asm | MSFT
|
||||
DebugAgentCommon/X64/ArchDebugSupport.h
|
||||
DebugAgentCommon/X64/ArchDebugSupport.c
|
||||
DebugAgentCommon/X64/ArchReadGroupRegister.c
|
||||
DebugAgentCommon/X64/ArchRegisters.h
|
||||
DebugAgentCommon/X64/DebugException.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
ResetSystemLib
|
||||
IoLib
|
||||
HobLib
|
||||
DebugCommunicationLib
|
||||
UefiBootServicesTableLib
|
||||
UefiLib
|
||||
PcdLib
|
||||
SynchronizationLib
|
||||
MemoryAllocationLib
|
||||
LocalApicLib
|
||||
|
||||
[Guids]
|
||||
gEfiDebugAgentGuid ## PRODUCES ## Configuration Table
|
||||
gEfiDebugAgentGuid ## CONSUMES ## HOB
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES
|
||||
|
@@ -0,0 +1,307 @@
|
||||
/** @file
|
||||
SEC Core Debug Agent Library instance implementition.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "SecPeiDebugAgentLib.h"
|
||||
|
||||
CONST BOOLEAN MultiProcessorDebugSupport = FALSE;
|
||||
|
||||
/**
|
||||
Get pointer to Mailbox from IDT entry before memory is ready.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
GetMailboxPointerInIdtEntry (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
||||
IA32_DESCRIPTOR IdtDescriptor;
|
||||
UINTN Mailbox;
|
||||
|
||||
AsmReadIdtr (&IdtDescriptor);
|
||||
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
|
||||
|
||||
Mailbox = IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16);
|
||||
return (VOID *) Mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pointer of Mailbox into IDT entry before memory is ready.
|
||||
|
||||
@param[in] Mailbox The pointer of Mailbox.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetMailboxPointerInIdtEntry (
|
||||
IN VOID *Mailbox
|
||||
)
|
||||
{
|
||||
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
||||
IA32_DESCRIPTOR IdtDescriptor;
|
||||
|
||||
AsmReadIdtr (&IdtDescriptor);
|
||||
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
|
||||
|
||||
IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)Mailbox;
|
||||
IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)Mailbox >> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the pointer to Mailbox from IDT entry and build the Mailbox into GUIDed Hob
|
||||
after memory is ready.
|
||||
|
||||
@return Pointer to Mailbox.
|
||||
|
||||
**/
|
||||
DEBUG_AGENT_MAILBOX *
|
||||
BuildMailboxHob (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DEBUG_AGENT_MAILBOX *Mailbox;
|
||||
|
||||
Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
|
||||
|
||||
return BuildGuidDataHob (
|
||||
&gEfiDebugAgentGuid,
|
||||
Mailbox,
|
||||
sizeof (DEBUG_AGENT_MAILBOX)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Get Debug Agent Mailbox pointer.
|
||||
|
||||
@return Mailbox pointer.
|
||||
|
||||
**/
|
||||
DEBUG_AGENT_MAILBOX *
|
||||
GetMailboxPointer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
|
||||
}
|
||||
|
||||
/**
|
||||
Get debug port handle.
|
||||
|
||||
@return Debug port handle.
|
||||
|
||||
**/
|
||||
DEBUG_PORT_HANDLE
|
||||
GetDebugPortHandle (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DEBUG_AGENT_MAILBOX *DebugAgentMailbox;
|
||||
|
||||
DebugAgentMailbox = (DEBUG_AGENT_MAILBOX *)GetMailboxPointerInIdtEntry ();
|
||||
|
||||
return (DEBUG_PORT_HANDLE) (UINTN)(DebugAgentMailbox->DebugPortHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
Trigger one software interrupt to debug agent to handle it.
|
||||
|
||||
@param Signature Software interrupt signature.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TriggerSoftInterrupt (
|
||||
UINT32 Signature
|
||||
)
|
||||
{
|
||||
UINTN Dr0;
|
||||
UINTN Dr1;
|
||||
|
||||
//
|
||||
// Save Debug Register State
|
||||
//
|
||||
Dr0 = AsmReadDr0 ();
|
||||
Dr1 = AsmReadDr1 ();
|
||||
|
||||
//
|
||||
// DR0 = Signature
|
||||
//
|
||||
AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);
|
||||
AsmWriteDr1 (Signature);
|
||||
|
||||
//
|
||||
// Do INT3 to communicate with HOST side
|
||||
//
|
||||
CpuBreakpoint ();
|
||||
|
||||
//
|
||||
// Restore Debug Register State only when Host didn't change it inside exception handler.
|
||||
// Dr registers can only be changed by setting the HW breakpoint.
|
||||
//
|
||||
AsmWriteDr0 (Dr0);
|
||||
AsmWriteDr1 (Dr1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize debug agent.
|
||||
|
||||
This function is used to set up debug environment for SEC and PEI phase.
|
||||
|
||||
If InitFlag is DEBUG_AGENT_INIT_PREMEM_SEC, it will overirde IDT table entries
|
||||
and initialize debug port. It will enable interrupt to support break-in feature.
|
||||
It will set up debug agent Mailbox in cache-as-ramfrom. It will be called before
|
||||
physical memory is ready.
|
||||
If InitFlag is DEBUG_AGENT_INIT_POSTMEM_SEC, debug agent will build one GUIDed
|
||||
HOB to copy debug agent Mailbox. It will be called after physical memory is ready.
|
||||
|
||||
This function is used to set up debug environment to support source level debugging.
|
||||
If certain Debug Agent Library instance has to save some private data in the stack,
|
||||
this function must work on the mode that doesn't return to the caller, then
|
||||
the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
|
||||
function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
|
||||
responsible to invoke the passing-in function at the end of InitializeDebugAgent().
|
||||
|
||||
If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by
|
||||
passing in the Context to be its parameter.
|
||||
|
||||
If Function() is NULL, Debug Agent Library instance will return after setup debug
|
||||
environment.
|
||||
|
||||
@param[in] InitFlag Init flag is used to decide the initialize process.
|
||||
@param[in] Context Context needed according to InitFlag; it was optional.
|
||||
@param[in] Function Continue function called by debug agent library; it was
|
||||
optional.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InitializeDebugAgent (
|
||||
IN UINT32 InitFlag,
|
||||
IN VOID *Context, OPTIONAL
|
||||
IN DEBUG_AGENT_CONTINUE Function OPTIONAL
|
||||
)
|
||||
{
|
||||
DEBUG_AGENT_MAILBOX *Mailbox;
|
||||
DEBUG_AGENT_MAILBOX MailboxInStack;
|
||||
DEBUG_AGENT_PHASE2_CONTEXT Phase2Context;
|
||||
DEBUG_AGENT_CONTEXT_POSTMEM_SEC *DebugAgentContext;
|
||||
|
||||
if (InitFlag != DEBUG_AGENT_INIT_PREMEM_SEC &&
|
||||
InitFlag != DEBUG_AGENT_INIT_POSTMEM_SEC) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisableInterrupts ();
|
||||
|
||||
if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {
|
||||
|
||||
//
|
||||
// Memory has been ready
|
||||
//
|
||||
if (IsHostConnected()) {
|
||||
//
|
||||
// Trigger one software interrupt to inform HOST
|
||||
//
|
||||
TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
|
||||
}
|
||||
|
||||
DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context;
|
||||
|
||||
Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
|
||||
Mailbox->DebugPortHandle = Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset;
|
||||
|
||||
Mailbox = BuildMailboxHob ();
|
||||
Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->HeapMigrateOffset);
|
||||
|
||||
SetMailboxPointerInIdtEntry ((VOID *) Mailbox);
|
||||
|
||||
EnableInterrupts ();
|
||||
|
||||
if (Function != NULL) {
|
||||
Function (Context);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
InitializeDebugIdt ();
|
||||
|
||||
Mailbox = &MailboxInStack;
|
||||
ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
|
||||
|
||||
//
|
||||
// Get and save debug port handle and set the length of memory block.
|
||||
//
|
||||
SetMailboxPointerInIdtEntry ((VOID *) Mailbox);
|
||||
|
||||
InitializeDebugTimer ();
|
||||
|
||||
Phase2Context.Context = Context;
|
||||
Phase2Context.Function = Function;
|
||||
DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Caller provided function to be invoked at the end of DebugPortInitialize().
|
||||
|
||||
Refer to the descrption for DebugPortInitialize() for more details.
|
||||
|
||||
@param[in] Context The first input argument of DebugPortInitialize().
|
||||
@param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InitializeDebugAgentPhase2 (
|
||||
IN VOID *Context,
|
||||
IN DEBUG_PORT_HANDLE DebugPortHandle
|
||||
)
|
||||
{
|
||||
DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context;
|
||||
DEBUG_AGENT_MAILBOX *Mailbox;
|
||||
EFI_SEC_PEI_HAND_OFF *SecCoreData;
|
||||
|
||||
Mailbox = GetMailboxPointerInIdtEntry ();
|
||||
Mailbox->DebugPortHandle = (UINT64) (UINTN)DebugPortHandle;
|
||||
|
||||
//
|
||||
// Trigger one software interrupt to inform HOST
|
||||
//
|
||||
TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
|
||||
|
||||
//
|
||||
// If Temporary RAM region is below 128 MB, then send message to
|
||||
// host to disable low memory filtering.
|
||||
//
|
||||
Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;
|
||||
SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;
|
||||
if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB) {
|
||||
TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
|
||||
}
|
||||
|
||||
//
|
||||
// Enable CPU interrupts so debug timer interrupts can be delivered
|
||||
//
|
||||
EnableInterrupts ();
|
||||
|
||||
//
|
||||
// Call continuation function is it is not NULL.
|
||||
//
|
||||
if (Phase2Context->Function != NULL) {
|
||||
Phase2Context->Function (Phase2Context->Context);
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/** @file
|
||||
Header file for Sec Core Debug Agent Library instance.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SEC_CORE_DEBUG_AGENT_LIB_H_
|
||||
#define _SEC_CORE_DEBUG_AGENT_LIB_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
typedef struct {
|
||||
VOID *Context;
|
||||
DEBUG_AGENT_CONTINUE Function;
|
||||
} DEBUG_AGENT_PHASE2_CONTEXT;
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,81 @@
|
||||
## @file
|
||||
# Debug Agent library instance for SEC Core and PEI modules.
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SecPeiDebugAgentLib
|
||||
FILE_GUID = 508B7D59-CD4E-4a6b-A45B-6D3B2D90111E
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 0.7
|
||||
LIBRARY_CLASS = DebugAgentLib|SEC PEIM
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
SecPeiDebugAgent/SecPeiDebugAgentLib.c
|
||||
SecPeiDebugAgent/SecPeiDebugAgentLib.h
|
||||
DebugAgentCommon/DebugAgent.c
|
||||
DebugAgentCommon/DebugAgent.h
|
||||
DebugAgentCommon/DebugTimer.c
|
||||
DebugAgentCommon/DebugTimer.h
|
||||
DebugAgentCommon/DebugMp.c
|
||||
DebugAgentCommon/DebugMp.h
|
||||
|
||||
[Sources.Ia32]
|
||||
DebugAgentCommon/Ia32/AsmFuncs.S | GCC
|
||||
DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT
|
||||
DebugAgentCommon/Ia32/ArchDebugSupport.h
|
||||
DebugAgentCommon/Ia32/ArchDebugSupport.c
|
||||
DebugAgentCommon/Ia32/ArchReadGroupRegister.c
|
||||
DebugAgentCommon/Ia32/ArchRegisters.h
|
||||
DebugAgentCommon/Ia32/DebugException.h
|
||||
|
||||
[Sources.X64]
|
||||
DebugAgentCommon/X64/AsmFuncs.S | GCC
|
||||
DebugAgentCommon/X64/AsmFuncs.asm | MSFT
|
||||
DebugAgentCommon/X64/ArchDebugSupport.h
|
||||
DebugAgentCommon/X64/ArchDebugSupport.c
|
||||
DebugAgentCommon/X64/ArchReadGroupRegister.c
|
||||
DebugAgentCommon/X64/ArchRegisters.h
|
||||
DebugAgentCommon/X64/DebugException.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
ResetSystemLib
|
||||
IoLib
|
||||
HobLib
|
||||
PcdLib
|
||||
DebugCommunicationLib
|
||||
SynchronizationLib
|
||||
LocalApicLib
|
||||
|
||||
[Guids]
|
||||
gEfiDebugAgentGuid ## PRODUCES ## HOB
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES
|
||||
|
@@ -0,0 +1,157 @@
|
||||
/** @file
|
||||
Debug Agent library implementition.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "SmmDebugAgentLib.h"
|
||||
|
||||
DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_AGENT_MAILBOX mLocalMailbox;
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSavedDebugRegisters[6];
|
||||
|
||||
CONST BOOLEAN MultiProcessorDebugSupport = FALSE;
|
||||
|
||||
|
||||
/**
|
||||
Get Debug Agent Mailbox pointer.
|
||||
|
||||
@return Mailbox pointer.
|
||||
|
||||
**/
|
||||
DEBUG_AGENT_MAILBOX *
|
||||
GetMailboxPointer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return mMailboxPointer;
|
||||
}
|
||||
|
||||
/**
|
||||
Get debug port handle.
|
||||
|
||||
@return Debug port handle.
|
||||
|
||||
**/
|
||||
DEBUG_PORT_HANDLE
|
||||
GetDebugPortHandle (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
Store debug register when SMI exit.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SaveDebugRegister (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
mSavedDebugRegisters[0] = AsmReadDr0 ();
|
||||
mSavedDebugRegisters[1] = AsmReadDr1 ();
|
||||
mSavedDebugRegisters[2] = AsmReadDr2 ();
|
||||
mSavedDebugRegisters[3] = AsmReadDr3 ();
|
||||
mSavedDebugRegisters[4] = AsmReadDr6 ();
|
||||
mSavedDebugRegisters[5] = AsmReadDr7 ();
|
||||
}
|
||||
|
||||
/**
|
||||
Restore debug register when SMI exit.
|
||||
|
||||
**/
|
||||
VOID
|
||||
RestoreDebugRegister (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
AsmWriteDr7 (0);
|
||||
AsmWriteDr0 (mSavedDebugRegisters[0]);
|
||||
AsmWriteDr1 (mSavedDebugRegisters[1]);
|
||||
AsmWriteDr2 (mSavedDebugRegisters[2]);
|
||||
AsmWriteDr3 (mSavedDebugRegisters[3]);
|
||||
AsmWriteDr6 (mSavedDebugRegisters[4]);
|
||||
AsmWriteDr7 (mSavedDebugRegisters[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize debug agent.
|
||||
|
||||
This function is used to set up debug enviroment for source level debug
|
||||
in SMM code.
|
||||
|
||||
If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries
|
||||
and initialize debug port. It will get debug agent Mailbox from GUIDed HOB,
|
||||
it it exists, debug agent wiil copied it into the local Mailbox in SMM space.
|
||||
it will overirde IDT table entries and initialize debug port. Context will be
|
||||
NULL.
|
||||
If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug
|
||||
Registers and get local Mailbox in SMM space. Context will be NULL.
|
||||
If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug
|
||||
Registers. Context will be NULL.
|
||||
|
||||
@param[in] InitFlag Init flag is used to decide initialize process.
|
||||
@param[in] Context Context needed according to InitFlag.
|
||||
@param[in] Function Continue function called by debug agent library; it was
|
||||
optional.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InitializeDebugAgent (
|
||||
IN UINT32 InitFlag,
|
||||
IN VOID *Context, OPTIONAL
|
||||
IN DEBUG_AGENT_CONTINUE Function OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 DebugPortHandle;
|
||||
|
||||
switch (InitFlag) {
|
||||
case DEBUG_AGENT_INIT_SMM:
|
||||
Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &mMailboxPointer);
|
||||
if (EFI_ERROR (Status) || mMailboxPointer == NULL) {
|
||||
ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));
|
||||
mMailboxPointer = &mLocalMailbox;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DEBUG_AGENT_INIT_ENTER_SMI:
|
||||
SaveDebugRegister ();
|
||||
InitializeDebugIdt ();
|
||||
|
||||
if (mMailboxPointer != NULL) {
|
||||
//
|
||||
// Initialize debug communication port
|
||||
//
|
||||
DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)mMailboxPointer->DebugPortHandle, NULL);
|
||||
mMailboxPointer->DebugPortHandle = DebugPortHandle;
|
||||
|
||||
if (mMailboxPointer->DebugFlag.Bits.BreakOnNextSmi == 1) {
|
||||
//
|
||||
// If SMM entry break is set, SMM code will be break at here.
|
||||
//
|
||||
CpuBreakpoint ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DEBUG_AGENT_INIT_EXIT_SMI:
|
||||
RestoreDebugRegister ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,24 @@
|
||||
/** @file
|
||||
Header file for Smm Debug Agent Library instance.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SMM_DEBUG_AGENT_LIB_H_
|
||||
#define _SMM_DEBUG_AGENT_LIB_H_
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include "DebugAgent.h"
|
||||
|
||||
#endif
|
81
SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
Normal file
81
SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
Normal file
@@ -0,0 +1,81 @@
|
||||
## @file
|
||||
# Debug Agent library instance for SMM modules.
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SecDebugAgentLib
|
||||
FILE_GUID = CB07D74C-598F-4268-A5D1-644FB4A481E8
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
VERSION_STRING = 0.7
|
||||
LIBRARY_CLASS = DebugAgentLib|DXE_SMM_DRIVER
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
SmmDebugAgent/SmmDebugAgentLib.c
|
||||
SmmDebugAgent/SmmDebugAgentLib.h
|
||||
DebugAgentCommon/DebugAgent.c
|
||||
DebugAgentCommon/DebugAgent.h
|
||||
DebugAgentCommon/DebugTimer.c
|
||||
DebugAgentCommon/DebugTimer.h
|
||||
DebugAgentCommon/DebugMp.c
|
||||
DebugAgentCommon/DebugMp.h
|
||||
|
||||
[Sources.Ia32]
|
||||
DebugAgentCommon/Ia32/AsmFuncs.S | GCC
|
||||
DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT
|
||||
DebugAgentCommon/Ia32/ArchDebugSupport.h
|
||||
DebugAgentCommon/Ia32/ArchDebugSupport.c
|
||||
DebugAgentCommon/Ia32/ArchReadGroupRegister.c
|
||||
DebugAgentCommon/Ia32/ArchRegisters.h
|
||||
DebugAgentCommon/Ia32/DebugException.h
|
||||
|
||||
[Sources.X64]
|
||||
DebugAgentCommon/X64/AsmFuncs.S | GCC
|
||||
DebugAgentCommon/X64/AsmFuncs.asm | MSFT
|
||||
DebugAgentCommon/X64/ArchDebugSupport.h
|
||||
DebugAgentCommon/X64/ArchDebugSupport.c
|
||||
DebugAgentCommon/X64/ArchReadGroupRegister.c
|
||||
DebugAgentCommon/X64/ArchRegisters.h
|
||||
DebugAgentCommon/X64/DebugException.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
ResetSystemLib
|
||||
IoLib
|
||||
DebugCommunicationLib
|
||||
UefiLib
|
||||
PcdLib
|
||||
SynchronizationLib
|
||||
LocalApicLib
|
||||
|
||||
[Guids]
|
||||
gEfiDebugAgentGuid ## CONSUMES ## Configuration Table
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES
|
||||
|
@@ -0,0 +1,169 @@
|
||||
/** @file
|
||||
Debug Port Library implementation based on serial port.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
|
||||
#include <Library/DebugCommunicationLib.h>
|
||||
#include <Library/SerialPortLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
|
||||
/**
|
||||
Initialize the debug port.
|
||||
|
||||
This function will initialize debug port to get it ready for data transmition. If
|
||||
certain Debug Communication Library instance has to save some private data in the
|
||||
stack, this function must work on the mode that doesn't return to the caller, then
|
||||
the caller needs to wrap up all rest of logic after DebugPortInitialize() into one
|
||||
function and pass it into DebugPortInitialize(). DebugPortInitialize() is
|
||||
responsible to invoke the passing-in funciton at the end of DebugPortInitialize().
|
||||
|
||||
If the paramter Function is not NULL, Debug Communication Libary instance will
|
||||
invoke it by passing in the Context to be the first parameter. Debug Communication
|
||||
Library instance could create one debug port handle to be the second parameter
|
||||
passing into the Function. Debug Communication Library instance also could pass
|
||||
NULL to be the second parameter if it doesn't create the debug port handle.
|
||||
|
||||
If the parameter Function is NULL, and Context is not NULL. At this time, Context
|
||||
is the debug port handle created by the previous Debug Communication Library
|
||||
instance.
|
||||
a) If the instance can understand and continue use the private data of the previous
|
||||
instance, it could return the same handle as passed in (as Context parameter).
|
||||
b) If the instance does not understand, or does not want to continue use the
|
||||
private data of the previous instance, it could ignore the input Context parameter
|
||||
and create the new hanlde to be returned.
|
||||
|
||||
If Function() is NULL and Context is NULL, Debug Communication Library could create a
|
||||
new handle and return it. NULL is also a valid handle to be returned.
|
||||
|
||||
@param[in] Context Context needed by callback function; it was optional.
|
||||
@param[in] Function Continue function called by Debug Communication library;
|
||||
it was optional.
|
||||
|
||||
@return The debug port handle created by Debug Communication Library if Function
|
||||
is not NULL.
|
||||
|
||||
**/
|
||||
DEBUG_PORT_HANDLE
|
||||
EFIAPI
|
||||
DebugPortInitialize (
|
||||
IN VOID *Context,
|
||||
IN DEBUG_PORT_CONTINUE Function
|
||||
)
|
||||
{
|
||||
SerialPortInitialize ();
|
||||
|
||||
if (Function != NULL) {
|
||||
Function (Context, NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Read data from debug device and save the datas in buffer.
|
||||
|
||||
Reads NumberOfBytes data bytes from a debug device into the buffer
|
||||
specified by Buffer. The number of bytes actually read is returned.
|
||||
If the return value is less than NumberOfBytes, then the rest operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Handle Debug port handle.
|
||||
@param Buffer Pointer to the data buffer to store the data read from the debug device.
|
||||
@param NumberOfBytes Number of bytes which will be read.
|
||||
@param Timeout Timeout value for reading from debug device. It unit is Microsecond.
|
||||
|
||||
@retval 0 Read data failed, no data is to be read.
|
||||
@retval >0 Actual number of bytes read from debug device.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
DebugPortReadBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes,
|
||||
IN UINTN Timeout
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
INTN Elapsed;
|
||||
|
||||
for (Index = 0; Index < NumberOfBytes; Index ++) {
|
||||
Elapsed = (INTN) Timeout;
|
||||
while (TRUE) {
|
||||
if (SerialPortPoll () || Timeout == 0) {
|
||||
SerialPortRead (Buffer + Index, 1);
|
||||
break;
|
||||
}
|
||||
MicroSecondDelay (1000);
|
||||
Elapsed -= 1000;
|
||||
if (Elapsed < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NumberOfBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
Write data from buffer to debug device.
|
||||
|
||||
Writes NumberOfBytes data bytes from Buffer to the debug device.
|
||||
The number of bytes actually written to the debug device is returned.
|
||||
If the return value is less than NumberOfBytes, then the write operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Handle Debug port handle.
|
||||
@param Buffer Pointer to the data buffer to be written.
|
||||
@param NumberOfBytes Number of bytes to written to the debug device.
|
||||
|
||||
@retval 0 NumberOfBytes is 0.
|
||||
@retval >0 The number of bytes written to the debug device.
|
||||
If this value is less than NumberOfBytes, then the read operation failed.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
DebugPortWriteBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
return SerialPortWrite (Buffer, NumberOfBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
Polls a debug device to see if there is any data waiting to be read.
|
||||
|
||||
Polls a debug device to see if there is any data waiting to be read.
|
||||
If there is data waiting to be read from the debug device, then TRUE is returned.
|
||||
If there is no data waiting to be read from the debug device, then FALSE is returned.
|
||||
|
||||
@param Handle Debug port handle.
|
||||
|
||||
@retval TRUE Data is waiting to be read from the debug device.
|
||||
@retval FALSE There is no data waiting to be read from the serial device.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
DebugPortPollBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle
|
||||
)
|
||||
{
|
||||
return SerialPortPoll ();
|
||||
}
|
||||
|
@@ -0,0 +1,38 @@
|
||||
## @file
|
||||
# Debug Communication Library instance based on serila port.
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = DebugCommunicationLibSerialPort
|
||||
FILE_GUID = 8CC435C5-6330-4269-B0C3-E3BD05C86FB8
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 0.7
|
||||
LIBRARY_CLASS = DebugCommunicationLib
|
||||
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
DebugCommunicationLibSerialPort.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
SerialPortLib
|
||||
TimerLib
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
## @file
|
||||
# Debug Communication Library instance based on usb debug port.
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = DebugCommunicationLibUsb
|
||||
FILE_GUID = 87438836-AD8D-4e3e-9249-895120A67240
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 0.7
|
||||
LIBRARY_CLASS = DebugCommunicationLib
|
||||
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
DebugCommunicationLibUsb.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
|
||||
|
||||
[Pcd]
|
||||
## The memory BAR of usb debug port, it may be different with the memory bar of ehci host controller.
|
||||
## Note that the memory BAR address is only used before Pci bus resource allocation.
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbDebugPortMemorySpaceBase
|
||||
|
||||
## The memory BAR of ehci host controller, in which usb debug feature is enabled.
|
||||
## Note that the memory BAR address is only used before Pci bus resource allocation.
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbEhciMemorySpaceBase
|
||||
|
||||
## The pci address of ehci host controller, in which usb debug feature is enabled.
|
||||
## The format of pci address please refer to SourceLevelDebugPkg.dec
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbEhciPciAddress
|
||||
|
||||
[LibraryClasses]
|
||||
TimerLib
|
||||
IoLib
|
||||
PciLib
|
||||
PcdLib
|
||||
|
@@ -0,0 +1,269 @@
|
||||
/** @file
|
||||
PE/Coff Extra Action library instances.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/PeCoffExtraActionLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
#include <ImageDebugSupport.h>
|
||||
|
||||
#define DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT 1
|
||||
#define DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3 2
|
||||
|
||||
/**
|
||||
Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
|
||||
|
||||
It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
|
||||
|
||||
|
||||
@param RegisterIndex Index of Dr register. The value range is from 0 to 3.
|
||||
@param Dr7 Value of Dr7 register.
|
||||
|
||||
@return TRUE The hardware breakpoint specified in the Drx is enabled.
|
||||
@return FALSE The hardware breakpoint specified in the Drx is disabled.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsDrxEnabled (
|
||||
IN UINT8 RegisterIndex,
|
||||
IN UINTN Dr7
|
||||
)
|
||||
{
|
||||
return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
|
||||
}
|
||||
|
||||
/**
|
||||
Performs additional actions after a PE/COFF image has been loaded and relocated.
|
||||
|
||||
If ImageContext is NULL, then ASSERT().
|
||||
|
||||
@param ImageContext Pointer to the image context structure that describes the
|
||||
PE/COFF image that has already been loaded and relocated.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PeCoffLoaderRelocateImageExtraAction (
|
||||
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
||||
)
|
||||
{
|
||||
BOOLEAN InterruptState;
|
||||
UINTN Dr0;
|
||||
UINTN Dr1;
|
||||
UINTN Dr2;
|
||||
UINTN Dr3;
|
||||
UINTN Dr7;
|
||||
UINTN Cr4;
|
||||
UINTN NewDr7;
|
||||
UINT8 LoadImageMethod;
|
||||
UINT8 DebugAgentStatus;
|
||||
|
||||
ASSERT (ImageContext != NULL);
|
||||
|
||||
if (ImageContext->PdbPointer != NULL) {
|
||||
DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
|
||||
}
|
||||
|
||||
//
|
||||
// Disable interrupts and save the current interrupt state
|
||||
//
|
||||
InterruptState = SaveAndDisableInterrupts ();
|
||||
|
||||
//
|
||||
// Save Debug Register State
|
||||
//
|
||||
Dr0 = AsmReadDr0 ();
|
||||
Dr1 = AsmReadDr1 ();
|
||||
Dr2 = AsmReadDr2 ();
|
||||
Dr3 = AsmReadDr3 ();
|
||||
Dr7 = AsmReadDr7 ();
|
||||
Cr4 = AsmReadCr4 ();
|
||||
|
||||
//
|
||||
// DR0 = IMAGE_LOAD_SIGNATURE
|
||||
// DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
|
||||
// DR2 = The pointer to the ImageContext structure
|
||||
// DR3 = IO_PORT_BREAKPOINT_ADDRESS
|
||||
// DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
|
||||
// CR4 = Make sure DE(BIT3) is set
|
||||
//
|
||||
AsmWriteDr7 (0);
|
||||
AsmWriteDr0 (IMAGE_LOAD_SIGNATURE);
|
||||
AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
|
||||
AsmWriteDr2 ((UINTN)ImageContext);
|
||||
AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
|
||||
|
||||
LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
|
||||
if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
|
||||
AsmWriteDr7 (0x20000480);
|
||||
AsmWriteCr4 (Cr4 | BIT3);
|
||||
//
|
||||
// Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
|
||||
// returns a read value other than DEBUG_AGENT_IMAGE_WAIT
|
||||
//
|
||||
do {
|
||||
DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
|
||||
} while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
|
||||
|
||||
} else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
|
||||
//
|
||||
// Generate a software break point.
|
||||
//
|
||||
CpuBreakpoint ();
|
||||
}
|
||||
|
||||
//
|
||||
// Restore Debug Register State only when Host didn't change it inside exception handler.
|
||||
// E.g.: User halts the target and sets the HW breakpoint while target is
|
||||
// in the above exception handler
|
||||
//
|
||||
NewDr7 = AsmReadDr7 ();
|
||||
if (!IsDrxEnabled (0, NewDr7)) {
|
||||
AsmWriteDr0 (Dr0);
|
||||
}
|
||||
if (!IsDrxEnabled (1, NewDr7)) {
|
||||
AsmWriteDr1 (Dr1);
|
||||
}
|
||||
if (!IsDrxEnabled (2, NewDr7)) {
|
||||
AsmWriteDr2 (Dr2);
|
||||
}
|
||||
if (!IsDrxEnabled (3, NewDr7)) {
|
||||
AsmWriteDr3 (Dr3);
|
||||
}
|
||||
if (AsmReadCr4 () == (Cr4 | BIT3)) {
|
||||
AsmWriteCr4 (Cr4);
|
||||
}
|
||||
if (NewDr7 == 0x20000480) {
|
||||
AsmWriteDr7 (Dr7);
|
||||
}
|
||||
//
|
||||
// Restore the interrupt state
|
||||
//
|
||||
SetInterruptState (InterruptState);
|
||||
}
|
||||
|
||||
/**
|
||||
Performs additional actions just before a PE/COFF image is unloaded. Any resources
|
||||
that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
|
||||
|
||||
If ImageContext is NULL, then ASSERT().
|
||||
|
||||
@param ImageContext Pointer to the image context structure that describes the
|
||||
PE/COFF image that is being unloaded.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PeCoffLoaderUnloadImageExtraAction (
|
||||
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
||||
)
|
||||
{
|
||||
BOOLEAN InterruptState;
|
||||
UINTN Dr0;
|
||||
UINTN Dr1;
|
||||
UINTN Dr2;
|
||||
UINTN Dr3;
|
||||
UINTN Dr7;
|
||||
UINTN Cr4;
|
||||
UINTN NewDr7;
|
||||
UINT8 LoadImageMethod;
|
||||
UINT8 DebugAgentStatus;
|
||||
|
||||
ASSERT (ImageContext != NULL);
|
||||
|
||||
if (ImageContext->PdbPointer != NULL) {
|
||||
DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
|
||||
}
|
||||
|
||||
//
|
||||
// Disable interrupts and save the current interrupt state
|
||||
//
|
||||
InterruptState = SaveAndDisableInterrupts ();
|
||||
|
||||
//
|
||||
// Save Debug Register State
|
||||
//
|
||||
Dr0 = AsmReadDr0 ();
|
||||
Dr1 = AsmReadDr1 ();
|
||||
Dr2 = AsmReadDr2 ();
|
||||
Dr3 = AsmReadDr3 ();
|
||||
Dr7 = AsmReadDr7 ();
|
||||
Cr4 = AsmReadCr4 ();
|
||||
|
||||
//
|
||||
// DR0 = IMAGE_UNLOAD_SIGNATURE
|
||||
// DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
|
||||
// DR2 = The pointer to the ImageContext structure
|
||||
// DR3 = IO_PORT_BREAKPOINT_ADDRESS
|
||||
// DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
|
||||
// CR4 = Make sure DE(BIT3) is set
|
||||
//
|
||||
AsmWriteDr7 (0);
|
||||
AsmWriteDr0 (IMAGE_UNLOAD_SIGNATURE);
|
||||
AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
|
||||
AsmWriteDr2 ((UINTN)ImageContext);
|
||||
AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
|
||||
|
||||
LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
|
||||
if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
|
||||
AsmWriteDr7 (0x20000480);
|
||||
AsmWriteCr4 (Cr4 | BIT3);
|
||||
//
|
||||
// Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
|
||||
// returns a read value other than DEBUG_AGENT_IMAGE_WAIT
|
||||
//
|
||||
do {
|
||||
DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
|
||||
} while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
|
||||
|
||||
} else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
|
||||
//
|
||||
// Generate a software break point.
|
||||
//
|
||||
CpuBreakpoint ();
|
||||
}
|
||||
|
||||
//
|
||||
// Restore Debug Register State only when Host didn't change it inside exception handler.
|
||||
// E.g.: User halts the target and sets the HW breakpoint while target is
|
||||
// in the above exception handler
|
||||
//
|
||||
NewDr7 = AsmReadDr7 ();
|
||||
if (!IsDrxEnabled (0, NewDr7)) {
|
||||
AsmWriteDr0 (Dr0);
|
||||
}
|
||||
if (!IsDrxEnabled (1, NewDr7)) {
|
||||
AsmWriteDr1 (Dr1);
|
||||
}
|
||||
if (!IsDrxEnabled (2, NewDr7)) {
|
||||
AsmWriteDr2 (Dr2);
|
||||
}
|
||||
if (!IsDrxEnabled (3, NewDr7)) {
|
||||
AsmWriteDr3 (Dr3);
|
||||
}
|
||||
if (AsmReadCr4 () == (Cr4 | BIT3)) {
|
||||
AsmWriteCr4 (Cr4);
|
||||
}
|
||||
if (NewDr7 == 0x20000480) {
|
||||
AsmWriteDr7 (Dr7);
|
||||
}
|
||||
|
||||
//
|
||||
// Restore the interrupt state
|
||||
//
|
||||
SetInterruptState (InterruptState);
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
## @file
|
||||
# PeCoffExtraAction Library to support source level debug.
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PeCoffExtraActionLib
|
||||
FILE_GUID = 8F01CBD5-E069-44d7-90C9-35F0318603AD
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 0.7
|
||||
LIBRARY_CLASS = PeCoffExtraActionLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
PeCoffExtraActionLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
|
||||
[Pcd]
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod
|
||||
|
Reference in New Issue
Block a user