| /** @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; | |
| } |