X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FPiSmmCpuDxeSmm%2FPiSmmCpuDxeSmm.c;h=19979d5418e85dabac919c3268136b4de975b70d;hb=31fb333431da1dfdd49ed4e12a7866e467a17030;hp=d06148263c8e565a2081f044a0234ef6df1873b2;hpb=8491e302e1450db96822838a83c283962c6a35f7;p=mirror_edk2.git diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c old mode 100755 new mode 100644 index d06148263c..19979d5418 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -1,7 +1,7 @@ /** @file Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU. -Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
This program and the accompanying materials @@ -76,6 +76,15 @@ EFI_SMM_CPU_PROTOCOL mSmmCpu = { SmmWriteSaveState }; +/// +/// SMM Memory Attribute Protocol instance +/// +EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute = { + EdkiiSmmGetMemoryAttributes, + EdkiiSmmSetMemoryAttributes, + EdkiiSmmClearMemoryAttributes +}; + EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER]; // @@ -108,6 +117,20 @@ UINT64 mAddressEncMask = 0; // SPIN_LOCK *mConfigSmmCodeAccessCheckLock = NULL; +// +// Saved SMM ranges information +// +EFI_SMRAM_DESCRIPTOR *mSmmCpuSmramRanges; +UINTN mSmmCpuSmramRangeCount; + +UINT8 mPhysicalAddressBits; + +// +// Control register contents saved for SMM S3 resume state initialization. +// +UINT32 mSmmCr0; +UINT32 mSmmCr4; + /** Initialize IDT to setup exception handlers for SMM. @@ -167,48 +190,17 @@ DumpModuleInfoByIp ( ) { UINTN Pe32Data; - EFI_IMAGE_DOS_HEADER *DosHdr; - EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; VOID *PdbPointer; - UINT64 DumpIpAddress; // // Find Image Base // - Pe32Data = CallerIpAddress & ~(SIZE_4KB - 1); - while (Pe32Data != 0) { - DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; - if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { - // - // DOS image header is present, so read the PE header after the DOS image header. - // - Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); - // - // Make sure PE header address does not overflow and is less than the initial address. - // - if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < CallerIpAddress)) { - if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { - // - // It's PE image. - // - break; - } - } - } - - // - // Not found the image base, check the previous aligned address - // - Pe32Data -= SIZE_4KB; - } - - DumpIpAddress = CallerIpAddress; - DEBUG ((EFI_D_ERROR, "It is invoked from the instruction before IP(0x%lx)", DumpIpAddress)); - + Pe32Data = PeCoffSearchImageBase (CallerIpAddress); if (Pe32Data != 0) { + DEBUG ((DEBUG_ERROR, "It is invoked from the instruction before IP(0x%p)", (VOID *) CallerIpAddress)); PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data); if (PdbPointer != NULL) { - DEBUG ((EFI_D_ERROR, " in module (%a)", PdbPointer)); + DEBUG ((DEBUG_ERROR, " in module (%a)\n", PdbPointer)); } } } @@ -245,6 +237,11 @@ SmmReadSaveState ( if ((CpuIndex >= gSmst->NumberOfCpus) || (Buffer == NULL)) { return EFI_INVALID_PARAMETER; } + // + // The AsmLfence() call here is to ensure the above check for the CpuIndex + // has been completed before the execution of subsequent codes. + // + AsmLfence (); // // Check for special EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID @@ -419,9 +416,11 @@ SmmRelocateBases ( // // Patch ASM code template with current CR0, CR3, and CR4 values // - gSmmCr0 = (UINT32)AsmReadCr0 (); - gSmmCr3 = (UINT32)AsmReadCr3 (); - gSmmCr4 = (UINT32)AsmReadCr4 (); + mSmmCr0 = (UINT32)AsmReadCr0 (); + PatchInstructionX86 (gPatchSmmCr0, mSmmCr0, 4); + PatchInstructionX86 (gPatchSmmCr3, AsmReadCr3 (), 4); + mSmmCr4 = (UINT32)AsmReadCr4 (); + PatchInstructionX86 (gPatchSmmCr4, mSmmCr4, 4); // // Patch GDTR for SMM base relocation @@ -556,6 +555,12 @@ PiCpuSmmEntry ( UINTN ModelId; UINT32 Cr3; + // + // Initialize address fixup + // + PiSmmCpuSmmInitFixupAddress (); + PiSmmCpuSmiEntryFixupAddress (); + // // Initialize Debug Agent to support source level debug in SMM code // @@ -569,13 +574,6 @@ PiCpuSmmEntry ( EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT ); - // - // Fix segment address of the long-mode-switch jump - // - if (sizeof (UINTN) == sizeof (UINT64)) { - gSmmJmpAddr.Segment = LONG_MODE_CODE_SEGMENT; - } - // // Find out SMRR Base and SMRR Size // @@ -855,7 +853,11 @@ PiCpuSmmEntry ( // // Set SMI stack for SMM base relocation // - gSmmInitStack = (UINTN) (Stacks + mSmmStackSize - sizeof (UINTN)); + PatchInstructionX86 ( + gPatchSmmInitStack, + (UINTN) (Stacks + mSmmStackSize - sizeof (UINTN)), + sizeof (UINTN) + ); // // Initialize IDT @@ -916,6 +918,17 @@ PiCpuSmmEntry ( ); ASSERT_EFI_ERROR (Status); + // + // Install the SMM Memory Attribute Protocol into SMM protocol database + // + Status = gSmst->SmmInstallProtocolInterface ( + &mSmmCpuHandle, + &gEdkiiSmmMemoryAttributeProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSmmMemoryAttribute + ); + ASSERT_EFI_ERROR (Status); + // // Expose address of CPU Hot Plug Data structure if CPU hot plug is supported. // @@ -971,8 +984,6 @@ FindSmramInfo ( UINTN Size; EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; EFI_SMRAM_DESCRIPTOR *CurrentSmramRange; - EFI_SMRAM_DESCRIPTOR *SmramRanges; - UINTN SmramRangeCount; UINTN Index; UINT64 MaxSize; BOOLEAN Found; @@ -990,31 +1001,31 @@ FindSmramInfo ( Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); ASSERT (Status == EFI_BUFFER_TOO_SMALL); - SmramRanges = (EFI_SMRAM_DESCRIPTOR *)AllocatePool (Size); - ASSERT (SmramRanges != NULL); + mSmmCpuSmramRanges = (EFI_SMRAM_DESCRIPTOR *)AllocatePool (Size); + ASSERT (mSmmCpuSmramRanges != NULL); - Status = SmmAccess->GetCapabilities (SmmAccess, &Size, SmramRanges); + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmmCpuSmramRanges); ASSERT_EFI_ERROR (Status); - SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + mSmmCpuSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); // // Find the largest SMRAM range between 1MB and 4GB that is at least 256K - 4K in size // CurrentSmramRange = NULL; - for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < SmramRangeCount; Index++) { + for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < mSmmCpuSmramRangeCount; Index++) { // // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization // - if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) { + if ((mSmmCpuSmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) { continue; } - if (SmramRanges[Index].CpuStart >= BASE_1MB) { - if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) <= BASE_4GB) { - if (SmramRanges[Index].PhysicalSize >= MaxSize) { - MaxSize = SmramRanges[Index].PhysicalSize; - CurrentSmramRange = &SmramRanges[Index]; + if (mSmmCpuSmramRanges[Index].CpuStart >= BASE_1MB) { + if ((mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize) <= SMRR_MAX_ADDRESS) { + if (mSmmCpuSmramRanges[Index].PhysicalSize >= MaxSize) { + MaxSize = mSmmCpuSmramRanges[Index].PhysicalSize; + CurrentSmramRange = &mSmmCpuSmramRanges[Index]; } } } @@ -1027,19 +1038,19 @@ FindSmramInfo ( do { Found = FALSE; - for (Index = 0; Index < SmramRangeCount; Index++) { - if (SmramRanges[Index].CpuStart < *SmrrBase && *SmrrBase == (SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize)) { - *SmrrBase = (UINT32)SmramRanges[Index].CpuStart; - *SmrrSize = (UINT32)(*SmrrSize + SmramRanges[Index].PhysicalSize); + for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) { + if (mSmmCpuSmramRanges[Index].CpuStart < *SmrrBase && + *SmrrBase == (mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize)) { + *SmrrBase = (UINT32)mSmmCpuSmramRanges[Index].CpuStart; + *SmrrSize = (UINT32)(*SmrrSize + mSmmCpuSmramRanges[Index].PhysicalSize); Found = TRUE; - } else if ((*SmrrBase + *SmrrSize) == SmramRanges[Index].CpuStart && SmramRanges[Index].PhysicalSize > 0) { - *SmrrSize = (UINT32)(*SmrrSize + SmramRanges[Index].PhysicalSize); + } else if ((*SmrrBase + *SmrrSize) == mSmmCpuSmramRanges[Index].CpuStart && mSmmCpuSmramRanges[Index].PhysicalSize > 0) { + *SmrrSize = (UINT32)(*SmrrSize + mSmmCpuSmramRanges[Index].PhysicalSize); Found = TRUE; } } } while (Found); - FreePool (SmramRanges); DEBUG ((EFI_D_INFO, "SMRR Base: 0x%x, SMRR Size: 0x%x\n", *SmrrBase, *SmrrSize)); } @@ -1144,7 +1155,12 @@ ConfigSmmCodeAccessCheck ( // for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { if (Index != gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) { - + if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == INVALID_APIC_ID) { + // + // If this processor does not exist + // + continue; + } // // Acquire Config SMM Code Access Check spin lock. The AP will release the // spin lock when it is done executing ConfigSmmCodeAccessCheckOnCurrentProcessor().