From 18b144ea424e476f14839e9d9d3b81fb4820a613 Mon Sep 17 00:00:00 2001 From: vanjeff Date: Sun, 12 Sep 2010 06:43:36 +0000 Subject: Import SourceLevelDebugPkg. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10867 6f19259b-4bc3-4df7-8a09-765794883524 --- .../DebugAgentCommon/X64/ArchDebugSupport.c | 255 +++++++++++++ .../DebugAgentCommon/X64/ArchDebugSupport.h | 31 ++ .../DebugAgentCommon/X64/ArchReadGroupRegister.c | 259 +++++++++++++ .../DebugAgentCommon/X64/ArchRegisters.h | 329 +++++++++++++++++ .../DebugAgent/DebugAgentCommon/X64/AsmFuncs.S | 401 +++++++++++++++++++++ .../DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm | 364 +++++++++++++++++++ .../DebugAgentCommon/X64/DebugException.h | 36 ++ 7 files changed, 1675 insertions(+) create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm create mode 100644 SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h (limited to 'SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64') diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c new file mode 100644 index 0000000000..3c18b8676f --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c @@ -0,0 +1,255 @@ +/** @file + Supporting functions for x64 architecture. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ 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; +} diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h new file mode 100644 index 0000000000..0b25a78d13 --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h @@ -0,0 +1,31 @@ +/** @file + X64 specific defintions for debug agent library instance. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ 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 diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c new file mode 100644 index 0000000000..72d30fcf53 --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c @@ -0,0 +1,259 @@ +/** @file + x64 Group registers read support functions. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ 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; +} diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h new file mode 100644 index 0000000000..e7a5a33089 --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h @@ -0,0 +1,329 @@ +/** @file + X64 register defintions needed by debug transfer protocol. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ 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 diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S new file mode 100644 index 0000000000..0d78e7d774 --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S @@ -0,0 +1,401 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# 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 diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm new file mode 100644 index 0000000000..b712c428c8 --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm @@ -0,0 +1,364 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2010, Intel Corporation. All rights reserved.
+; 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 diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h new file mode 100644 index 0000000000..13a7d23a0d --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h @@ -0,0 +1,36 @@ +/** @file + Exception defintions. + + Copyright (c) 2010, Intel Corporation. All rights reserved.
+ 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 -- cgit v1.2.3