summaryrefslogtreecommitdiff
path: root/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
diff options
context:
space:
mode:
Diffstat (limited to 'SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c')
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c255
1 files changed, 255 insertions, 0 deletions
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.<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;
+}