static DWORD WINAPI EmulateGetCurrentProcessorNumber(VOID) { const ApicId apicId = GetApicId(); const DWORD processor = (DWORD)ProcessorFromApicId(apicId); ASSERT(processor < os_cpu_MaxProcessors); return processor; }
/** This return the handle number for the calling processor. @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance. @param[out] ProcessorNumber The handle number of currently executing processor. @retval EFI_SUCCESS The current processor handle number was returned in ProcessorNumber. @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. **/ EFI_STATUS EFIAPI SmmWhoAmI ( IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This, OUT UINTN *ProcessorNumber ) { UINTN Index; UINT64 ApicId; // // Check parameter // if (ProcessorNumber == NULL) { return EFI_INVALID_PARAMETER; } ApicId = GetApicId (); for (Index = 0; Index < mMaxNumberOfCpus; Index++) { if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) { *ProcessorNumber = Index; return EFI_SUCCESS; } } // // This should not happen // ASSERT (FALSE); return EFI_NOT_FOUND; }
/** Get the current processor's index. @return Processor index value. **/ UINT32 GetProcessorIndex ( VOID ) { UINT32 Index; UINT16 LocalApicID; LocalApicID = (UINT16) GetApicId (); AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock); for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) { if (mDebugCpuData.ApicID[Index] == LocalApicID) { break; } } if (Index == mDebugCpuData.CpuCount) { mDebugCpuData.ApicID[Index] = LocalApicID; mDebugCpuData.CpuCount ++ ; } ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock); return Index; }
/** Configures an I/O APIC interrupt. Configure an I/O APIC Redirection Table Entry to deliver an interrupt in physical mode to the Local APIC of the currntly executing CPU. The default state of the entry is for the interrupt to be disabled (masked). IoApicEnableInterrupts() must be used to enable(unmask) the I/O APIC Interrupt. If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT(). If Vector >= 0x100, then ASSERT(). If DeliveryMode is not supported, then ASSERT(). @param Irq Specifies the I/O APIC interrupt to initialize. @param Vector The 8-bit interrupt vector associated with the I/O APIC Interrupt. Must be in the range 0x10..0xFE. @param DeliveryMode A 3-bit value that specifies how the recept of the I/O APIC interrupt is handled. The only supported values are: 0: IO_APIC_DELIVERY_MODE_FIXED 1: IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY 2: IO_APIC_DELIVERY_MODE_SMI 4: IO_APIC_DELIVERY_MODE_NMI 5: IO_APIC_DELIVERY_MODE_INIT 7: IO_APIC_DELIVERY_MODE_EXTINT @param LevelTriggered TRUE specifies a level triggered interrupt. FALSE specifies an edge triggered interrupt. @param AssertionLevel TRUE specified an active high interrupt. FALSE specifies an active low interrupt. **/ VOID EFIAPI IoApicConfigureInterrupt ( IN UINTN Irq, IN UINTN Vector, IN UINTN DeliveryMode, IN BOOLEAN LevelTriggered, IN BOOLEAN AssertionLevel ) { IO_APIC_VERSION_REGISTER Version; IO_APIC_REDIRECTION_TABLE_ENTRY Entry; Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX); ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0); ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry); ASSERT (Vector <= 0xFF); ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3); Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2); Entry.Bits.Vector = (UINT8)Vector; Entry.Bits.DeliveryMode = (UINT32)DeliveryMode; Entry.Bits.DestinationMode = 0; Entry.Bits.Polarity = AssertionLevel ? 0 : 1; Entry.Bits.TriggerMode = LevelTriggered ? 1 : 0; Entry.Bits.Mask = 1; IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low); Entry.Uint32.High = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1); Entry.Bits.DestinationID = GetApicId (); IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1, Entry.Uint32.High); }
/** C function for SMI handler. To change all processor's SMMBase Register. **/ VOID EFIAPI SmmInitHandler ( VOID ) { UINT32 ApicId; UINTN Index; // // Update SMM IDT entries' code segment and load IDT // AsmWriteIdtr (&gcSmiIdtr); ApicId = GetApicId (); ASSERT (mNumberOfCpus <= mMaxNumberOfCpus); for (Index = 0; Index < mNumberOfCpus; Index++) { if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) { // // Initialize SMM specific features on the currently executing CPU // SmmCpuFeaturesInitializeProcessor ( Index, mIsBsp, gSmmCpuPrivate->ProcessorInfo, &mCpuHotPlugData ); if (!mSmmS3Flag) { // // Check XD and BTS features on each processor on normal boot // CheckFeatureSupported (); } if (mIsBsp) { // // BSP rebase is already done above. // Initialize private data during S3 resume // InitializeMpSyncData (); } // // Hook return after RSM to set SMM re-based flag // SemaphoreHook (Index, &mRebased[Index]); return; } } ASSERT (FALSE); }
/** Get CPU Index from APIC ID. **/ UINTN GetCpuIndex ( VOID ) { UINTN Index; UINT32 ApicId; ApicId = GetApicId (); for (Index = 0; Index < mMaxNumberOfCpus; Index++) { if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) { return Index; } } ASSERT (FALSE); return 0; }
/** Get CPU Index from APIC ID. **/ UINTN GetCpuIndex ( VOID ) { UINTN Index; UINT32 ApicId; ApicId = GetApicId (); for (Index = 0; Index < PcdGet32 (PcdCpuMaxLogicalProcessorNumber); Index++) { if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) { return Index; } } ASSERT (FALSE); return 0; }
/** * * Run code on every AP in the system. * * @param[in] ApParams AP task pointer. * @param[in] StdHeader Handle to config for library and services * * @return The most severe AGESA_STATUS returned by an AP. * */ AGESA_STATUS RunLateApTaskOnAllAPs ( IN AP_EXE_PARAMS *ApParams, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 NumberOfSockets; UINT32 NumberOfCores; UINT8 Socket; UINT8 Core; UINT8 ApicId; UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; AGESA_STATUS CalledStatus; AGESA_STATUS IgnoredStatus; AGESA_STATUS AgesaStatus; ASSERT (IsBsp (StdHeader, &IgnoredStatus)); AgesaStatus = AGESA_SUCCESS; IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredStatus); NumberOfSockets = GetPlatformNumberOfSockets (); for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) { for (Core = 0; Core < NumberOfCores; Core++) { if ((Socket != BscSocket) || (Core != BscCoreNum)) { GetApicId (StdHeader, Socket, Core, &ApicId, &IgnoredStatus); AGESA_TESTPOINT (TpIfBeforeRunApFromAllAps, StdHeader); CalledStatus = AgesaRunFcnOnAp ((UINTN) ApicId, ApParams); AGESA_TESTPOINT (TpIfAfterRunApFromAllAps, StdHeader); if (CalledStatus > AgesaStatus) { AgesaStatus = CalledStatus; } } } } } return AgesaStatus; }
/** * * Run code on core 0 of every socket in the system. * * @param[in] ApParams AP task pointer. * @param[in] StdHeader Handle to config for library and services * * @return The most severe AGESA_STATUS returned by an AP. * */ AGESA_STATUS RunLateApTaskOnAllCore0s ( IN AP_EXE_PARAMS *ApParams, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 NumberOfSockets; UINT8 Socket; UINT8 ApicId; UINT32 BscSocket; UINT32 IgnoredModule; UINT32 IgnoredCore; AGESA_STATUS CalledStatus; AGESA_STATUS IgnoredStatus; AGESA_STATUS AgesaStatus; ASSERT (IsBsp (StdHeader, &IgnoredStatus)); AgesaStatus = AGESA_SUCCESS; IdentifyCore (StdHeader, &BscSocket, &IgnoredModule, &IgnoredCore, &IgnoredStatus); NumberOfSockets = GetPlatformNumberOfSockets (); for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { if (Socket != BscSocket) { GetApicId (StdHeader, Socket, 0, &ApicId, &IgnoredStatus); AGESA_TESTPOINT (TpIfBeforeRunApFromAllCore0s, StdHeader); CalledStatus = AgesaRunFcnOnAp ((UINTN) ApicId, ApParams); AGESA_TESTPOINT (TpIfAfterRunApFromAllCore0s, StdHeader); if (CalledStatus > AgesaStatus) { AgesaStatus = CalledStatus; } } } } return AgesaStatus; }
/** Relocate SmmBases for each processor. Execute on first boot and all S3 resumes **/ VOID EFIAPI SmmRelocateBases ( VOID ) { UINT8 BakBuf[BACK_BUF_SIZE]; SMRAM_SAVE_STATE_MAP BakBuf2; SMRAM_SAVE_STATE_MAP *CpuStatePtr; UINT8 *U8Ptr; UINT32 ApicId; UINTN Index; UINTN BspIndex; // // Make sure the reserved size is large enough for procedure SmmInitTemplate. // ASSERT (sizeof (BakBuf) >= gcSmmInitSize); // // Patch ASM code template with current CR0, CR3, and CR4 values // gSmmCr0 = (UINT32)AsmReadCr0 (); gSmmCr3 = (UINT32)AsmReadCr3 (); gSmmCr4 = (UINT32)AsmReadCr4 (); // // Patch GDTR for SMM base relocation // gcSmiInitGdtr.Base = gcSmiGdtr.Base; gcSmiInitGdtr.Limit = gcSmiGdtr.Limit; U8Ptr = (UINT8*)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET); CpuStatePtr = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET); // // Backup original contents at address 0x38000 // CopyMem (BakBuf, U8Ptr, sizeof (BakBuf)); CopyMem (&BakBuf2, CpuStatePtr, sizeof (BakBuf2)); // // Load image for relocation // CopyMem (U8Ptr, gcSmmInitTemplate, gcSmmInitSize); // // Retrieve the local APIC ID of current processor // ApicId = GetApicId (); // // Relocate SM bases for all APs // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate // mIsBsp = FALSE; BspIndex = (UINTN)-1; for (Index = 0; Index < mNumberOfCpus; Index++) { mRebased[Index] = FALSE; if (ApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) { SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId); // // Wait for this AP to finish its 1st SMI // while (!mRebased[Index]); } else { // // BSP will be Relocated later // BspIndex = Index; } } // // Relocate BSP's SMM base // ASSERT (BspIndex != (UINTN)-1); mIsBsp = TRUE; SendSmiIpi (ApicId); // // Wait for the BSP to finish its 1st SMI // while (!mRebased[BspIndex]); // // Restore contents at address 0x38000 // CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2)); CopyMem (U8Ptr, BakBuf, sizeof (BakBuf)); }
/** The Page fault handler to save SMM profile data. @param Rip The RIP when exception happens. @param ErrorCode The Error code of exception. **/ VOID SmmProfilePFHandler ( UINTN Rip, UINTN ErrorCode ) { UINT64 *PageTable; UINT64 PFAddress; UINTN CpuIndex; UINTN Index; UINT64 InstructionAddress; UINTN MaxEntryNumber; UINTN CurrentEntryNumber; BOOLEAN IsValidPFAddress; SMM_PROFILE_ENTRY *SmmProfileEntry; UINT64 SmiCommand; EFI_STATUS Status; UINT8 SoftSmiValue; EFI_SMM_SAVE_STATE_IO_INFO IoInfo; if (!mSmmProfileStart) { // // If SMM profile does not start, call original page fault handler. // SmiDefaultPFHandler (); return; } if (mBtsSupported) { DisableBTS (); } IsValidPFAddress = FALSE; PageTable = (UINT64 *)AsmReadCr3 (); PFAddress = AsmReadCr2 (); CpuIndex = GetCpuIndex (); if (PFAddress <= 0xFFFFFFFF) { RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode); } else { RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress); } if (!IsValidPFAddress) { InstructionAddress = Rip; if ((ErrorCode & IA32_PF_EC_ID) != 0 && (mBtsSupported)) { // // If it is instruction fetch failure, get the correct IP from BTS. // InstructionAddress = GetSourceFromDestinationOnBts (CpuIndex, Rip); if (InstructionAddress == 0) { // // It indicates the instruction which caused page fault is not a jump instruction, // set instruction address same as the page fault address. // InstructionAddress = PFAddress; } } // // Indicate it is not software SMI // SmiCommand = 0xFFFFFFFFFFFFFFFFULL; for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { Status = SmmReadSaveState(&mSmmCpu, sizeof(IoInfo), EFI_SMM_SAVE_STATE_REGISTER_IO, Index, &IoInfo); if (EFI_ERROR (Status)) { continue; } if (IoInfo.IoPort == mSmiCommandPort) { // // A software SMI triggered by SMI command port has been found, get SmiCommand from SMI command port. // SoftSmiValue = IoRead8 (mSmiCommandPort); SmiCommand = (UINT64)SoftSmiValue; break; } } SmmProfileEntry = (SMM_PROFILE_ENTRY *)(UINTN)(mSmmProfileBase + 1); // // Check if there is already a same entry in profile data. // for (Index = 0; Index < (UINTN) mSmmProfileBase->CurDataEntries; Index++) { if ((SmmProfileEntry[Index].ErrorCode == (UINT64)ErrorCode) && (SmmProfileEntry[Index].Address == PFAddress) && (SmmProfileEntry[Index].CpuNum == (UINT64)CpuIndex) && (SmmProfileEntry[Index].Instruction == InstructionAddress) && (SmmProfileEntry[Index].SmiCmd == SmiCommand)) { // // Same record exist, need not save again. // break; } } if (Index == mSmmProfileBase->CurDataEntries) { CurrentEntryNumber = (UINTN) mSmmProfileBase->CurDataEntries; MaxEntryNumber = (UINTN) mSmmProfileBase->MaxDataEntries; if (FeaturePcdGet (PcdCpuSmmProfileRingBuffer)) { CurrentEntryNumber = CurrentEntryNumber % MaxEntryNumber; } if (CurrentEntryNumber < MaxEntryNumber) { // // Log the new entry // SmmProfileEntry[CurrentEntryNumber].SmiNum = mSmmProfileBase->NumSmis; SmmProfileEntry[CurrentEntryNumber].ErrorCode = (UINT64)ErrorCode; SmmProfileEntry[CurrentEntryNumber].ApicId = (UINT64)GetApicId (); SmmProfileEntry[CurrentEntryNumber].CpuNum = (UINT64)CpuIndex; SmmProfileEntry[CurrentEntryNumber].Address = PFAddress; SmmProfileEntry[CurrentEntryNumber].Instruction = InstructionAddress; SmmProfileEntry[CurrentEntryNumber].SmiCmd = SmiCommand; // // Update current entry index and data size in the header. // mSmmProfileBase->CurDataEntries++; mSmmProfileBase->CurDataSize = MultU64x64 (mSmmProfileBase->CurDataEntries, sizeof (SMM_PROFILE_ENTRY)); } } } // // Flush TLB // CpuFlushTlb (); if (mBtsSupported) { EnableBTS (); } }
/** Display CPU information. @param ExceptionType Exception type. @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. **/ VOID DumpCpuContent ( IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ) { UINTN ImageBase; UINTN EntryPoint; InternalPrintMessage ( "!!!! IA32 Exception Type - %08x CPU Apic ID - %08x !!!!\n", ExceptionType, GetApicId () ); InternalPrintMessage ( "EIP - %08x, CS - %08x, EFLAGS - %08x\n", SystemContext.SystemContextIa32->Eip, SystemContext.SystemContextIa32->Cs, SystemContext.SystemContextIa32->Eflags ); if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) { InternalPrintMessage ( "ExceptionData - %08x\n", SystemContext.SystemContextIa32->ExceptionData ); } InternalPrintMessage ( "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n", SystemContext.SystemContextIa32->Eax, SystemContext.SystemContextIa32->Ecx, SystemContext.SystemContextIa32->Edx, SystemContext.SystemContextIa32->Ebx ); InternalPrintMessage ( "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n", SystemContext.SystemContextIa32->Esp, SystemContext.SystemContextIa32->Ebp, SystemContext.SystemContextIa32->Esi, SystemContext.SystemContextIa32->Edi ); InternalPrintMessage ( "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n", SystemContext.SystemContextIa32->Ds, SystemContext.SystemContextIa32->Es, SystemContext.SystemContextIa32->Fs, SystemContext.SystemContextIa32->Gs, SystemContext.SystemContextIa32->Ss ); InternalPrintMessage ( "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n", SystemContext.SystemContextIa32->Cr0, SystemContext.SystemContextIa32->Cr2, SystemContext.SystemContextIa32->Cr3, SystemContext.SystemContextIa32->Cr4 ); InternalPrintMessage ( "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n", SystemContext.SystemContextIa32->Dr0, SystemContext.SystemContextIa32->Dr1, SystemContext.SystemContextIa32->Dr2, SystemContext.SystemContextIa32->Dr3 ); InternalPrintMessage ( "DR6 - %08x, DR7 - %08x\n", SystemContext.SystemContextIa32->Dr6, SystemContext.SystemContextIa32->Dr7 ); InternalPrintMessage ( "GDTR - %08x %08x, IDTR - %08x %08x\n", SystemContext.SystemContextIa32->Gdtr[0], SystemContext.SystemContextIa32->Gdtr[1], SystemContext.SystemContextIa32->Idtr[0], SystemContext.SystemContextIa32->Idtr[1] ); InternalPrintMessage ( "LDTR - %08x, TR - %08x\n", SystemContext.SystemContextIa32->Ldtr, SystemContext.SystemContextIa32->Tr ); InternalPrintMessage ( "FXSAVE_STATE - %08x\n", &SystemContext.SystemContextIa32->FxSaveState ); // // Find module image base and module entry point by RIP // ImageBase = FindModuleImageBase (SystemContext.SystemContextIa32->Eip, &EntryPoint); if (ImageBase != 0) { InternalPrintMessage ( " (ImageBase=%08x, EntryPoint=%08x) !!!!\n", ImageBase, EntryPoint ); } }
/** Display CPU information. @param ExceptionType Exception type. @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. **/ VOID DumpCpuContent ( IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ) { UINTN ImageBase; UINTN EntryPoint; InternalPrintMessage ( "!!!! X64 Exception Type - %016lx CPU Apic ID - %08x !!!!\n", ExceptionType, GetApicId () ); InternalPrintMessage ( "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n", SystemContext.SystemContextX64->Rip, SystemContext.SystemContextX64->Cs, SystemContext.SystemContextX64->Rflags ); if (mErrorCodeFlag & (1 << ExceptionType)) { InternalPrintMessage ( "ExceptionData - %016lx\n", SystemContext.SystemContextX64->ExceptionData ); } InternalPrintMessage ( "RAX - %016lx, RCX - %016lx, RDX - %016lx\n", SystemContext.SystemContextX64->Rax, SystemContext.SystemContextX64->Rcx, SystemContext.SystemContextX64->Rdx ); InternalPrintMessage ( "RBX - %016lx, RSP - %016lx, RBP - %016lx\n", SystemContext.SystemContextX64->Rbx, SystemContext.SystemContextX64->Rsp, SystemContext.SystemContextX64->Rbp ); InternalPrintMessage ( "RSI - %016lx, RDI - %016lx\n", SystemContext.SystemContextX64->Rsi, SystemContext.SystemContextX64->Rdi ); InternalPrintMessage ( "R8 - %016lx, R9 - %016lx, R10 - %016lx\n", SystemContext.SystemContextX64->R8, SystemContext.SystemContextX64->R9, SystemContext.SystemContextX64->R10 ); InternalPrintMessage ( "R11 - %016lx, R12 - %016lx, R13 - %016lx\n", SystemContext.SystemContextX64->R11, SystemContext.SystemContextX64->R12, SystemContext.SystemContextX64->R13 ); InternalPrintMessage ( "R14 - %016lx, R15 - %016lx\n", SystemContext.SystemContextX64->R14, SystemContext.SystemContextX64->R15 ); InternalPrintMessage ( "DS - %016lx, ES - %016lx, FS - %016lx\n", SystemContext.SystemContextX64->Ds, SystemContext.SystemContextX64->Es, SystemContext.SystemContextX64->Fs ); InternalPrintMessage ( "GS - %016lx, SS - %016lx\n", SystemContext.SystemContextX64->Gs, SystemContext.SystemContextX64->Ss ); InternalPrintMessage ( "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n", SystemContext.SystemContextX64->Cr0, SystemContext.SystemContextX64->Cr2, SystemContext.SystemContextX64->Cr3 ); InternalPrintMessage ( "CR4 - %016lx, CR8 - %016lx\n", SystemContext.SystemContextX64->Cr4, SystemContext.SystemContextX64->Cr8 ); InternalPrintMessage ( "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n", SystemContext.SystemContextX64->Dr0, SystemContext.SystemContextX64->Dr1, SystemContext.SystemContextX64->Dr2 ); InternalPrintMessage ( "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n", SystemContext.SystemContextX64->Dr3, SystemContext.SystemContextX64->Dr6, SystemContext.SystemContextX64->Dr7 ); InternalPrintMessage ( "GDTR - %016lx %016lx, LDTR - %016lx\n", SystemContext.SystemContextX64->Gdtr[0], SystemContext.SystemContextX64->Gdtr[1], SystemContext.SystemContextX64->Ldtr ); InternalPrintMessage ( "IDTR - %016lx %016lx, TR - %016lx\n", SystemContext.SystemContextX64->Idtr[0], SystemContext.SystemContextX64->Idtr[1], SystemContext.SystemContextX64->Tr ); InternalPrintMessage ( "FXSAVE_STATE - %016lx\n", &SystemContext.SystemContextX64->FxSaveState ); // // Find module image base and module entry point by RIP // ImageBase = FindModuleImageBase (SystemContext.SystemContextX64->Rip, &EntryPoint); if (ImageBase != 0) { InternalPrintMessage ( " (ImageBase=%016lx, EntryPoint=%016lx) !!!!\n", ImageBase, EntryPoint ); } }
/** Internal worker function for common exception handler. @param ExceptionType Exception type. @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. @param ExceptionHandlerData Pointer to exception handler data. **/ VOID CommonExceptionHandlerWorker ( IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext, IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData ) { EXCEPTION_HANDLER_CONTEXT *ExceptionHandlerContext; RESERVED_VECTORS_DATA *ReservedVectors; EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler; ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32); ReservedVectors = ExceptionHandlerData->ReservedVectors; ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler; switch (ReservedVectors[ExceptionType].Attribute) { case EFI_VECTOR_HANDOFF_HOOK_BEFORE: // // Need to jmp to old IDT handler after this exception handler // ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE; ExceptionHandlerContext->OldIdtHandler = ReservedVectors[ExceptionType].ExceptonHandler; break; case EFI_VECTOR_HANDOFF_HOOK_AFTER: while (TRUE) { // // If if anyone has gotten SPIN_LOCK for owner running hook after // if (AcquireSpinLockOrFail (&ReservedVectors[ExceptionType].SpinLock)) { // // Need to execute old IDT handler before running this exception handler // ReservedVectors[ExceptionType].ApicId = GetApicId (); ArchSaveExceptionContext (ExceptionType, SystemContext, ExceptionHandlerData); ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE; ExceptionHandlerContext->OldIdtHandler = ReservedVectors[ExceptionType].ExceptonHandler; return; } // // If failed to acquire SPIN_LOCK, check if it was locked by processor itself // if (ReservedVectors[ExceptionType].ApicId == GetApicId ()) { // // Old IDT handler has been executed, then restore CPU exception content to // run new exception handler. // ArchRestoreExceptionContext (ExceptionType, SystemContext, ExceptionHandlerData); // // Rlease spin lock for ApicId // ReleaseSpinLock (&ReservedVectors[ExceptionType].SpinLock); break; } CpuPause (); } break; case 0xffffffff: break; default: // // It should never reach here // CpuDeadLoop (); break; } if (ExternalInterruptHandler != NULL && ExternalInterruptHandler[ExceptionType] != NULL) { (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); } else if (ExceptionType < CPU_EXCEPTION_NUM) { // // Get Spinlock to display CPU information // while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) { CpuPause (); } // // Display ExceptionType, CPU information and Image information // DumpCpuContent (ExceptionType, SystemContext); // // Release Spinlock of output message // ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock); // // Enter a dead loop if needn't to execute old IDT handler further // if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { CpuDeadLoop (); } } }