mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/CpuDxe: Fix multiple entries of RT_CODE in memory map
More than one entry of RT_CODE memory might cause boot problem for some old OSs. This patch will fix this issue to keep OS compatibility as much as possible. More detailed information, please refer to https://bugzilla.tianocore.org/show_bug.cgi?id=753 Laszlo did a thorough test on OVMF emulated platform. The details can be found at https://bugzilla.tianocore.org/show_bug.cgi?id=753#c10 Cc: Eric Dong <eric.dong@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang <jian.j.wang@intel.com> Tested-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
56fb9faa60
commit
768bd96784
|
@ -769,6 +769,20 @@ AssignMemoryPageAttributes (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if Execute Disable feature is enabled or not.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsExecuteDisableEnabled (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
MSR_CORE_IA32_EFER_REGISTER MsrEfer;
|
||||||
|
|
||||||
|
MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
|
||||||
|
return (MsrEfer.Bits.NXE == 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Update GCD memory space attributes according to current page table setup.
|
Update GCD memory space attributes according to current page table setup.
|
||||||
**/
|
**/
|
||||||
|
@ -790,7 +804,7 @@ RefreshGcdMemoryAttributesFromPaging (
|
||||||
UINT64 PageStartAddress;
|
UINT64 PageStartAddress;
|
||||||
UINT64 Attributes;
|
UINT64 Attributes;
|
||||||
UINT64 Capabilities;
|
UINT64 Capabilities;
|
||||||
BOOLEAN DoUpdate;
|
UINT64 NewAttributes;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -802,17 +816,50 @@ RefreshGcdMemoryAttributesFromPaging (
|
||||||
|
|
||||||
GetCurrentPagingContext (&PagingContext);
|
GetCurrentPagingContext (&PagingContext);
|
||||||
|
|
||||||
DoUpdate = FALSE;
|
Attributes = 0;
|
||||||
Capabilities = 0;
|
NewAttributes = 0;
|
||||||
Attributes = 0;
|
BaseAddress = 0;
|
||||||
BaseAddress = 0;
|
PageLength = 0;
|
||||||
PageLength = 0;
|
|
||||||
|
if (IsExecuteDisableEnabled ()) {
|
||||||
|
Capabilities = EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP;
|
||||||
|
} else {
|
||||||
|
Capabilities = EFI_MEMORY_RO | EFI_MEMORY_RP;
|
||||||
|
}
|
||||||
|
|
||||||
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
||||||
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
|
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sync the actual paging related capabilities back to GCD service first.
|
||||||
|
// As a side effect (good one), this can also help to avoid unnecessary
|
||||||
|
// memory map entries due to the different capabilities of the same type
|
||||||
|
// memory, such as multiple RT_CODE and RT_DATA entries in memory map,
|
||||||
|
// which could cause boot failure of some old Linux distro (before v4.3).
|
||||||
|
//
|
||||||
|
Status = gDS->SetMemorySpaceCapabilities (
|
||||||
|
MemorySpaceMap[Index].BaseAddress,
|
||||||
|
MemorySpaceMap[Index].Length,
|
||||||
|
MemorySpaceMap[Index].Capabilities | Capabilities
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// If we cannot udpate the capabilities, we cannot update its
|
||||||
|
// attributes either. So just simply skip current block of memory.
|
||||||
|
//
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_WARN,
|
||||||
|
"Failed to update capability: [%lu] %016lx - %016lx (%016lx -> %016lx)\r\n",
|
||||||
|
(UINT64)Index, MemorySpaceMap[Index].BaseAddress,
|
||||||
|
MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,
|
||||||
|
MemorySpaceMap[Index].Capabilities,
|
||||||
|
MemorySpaceMap[Index].Capabilities | Capabilities
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress + PageLength)) {
|
if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress + PageLength)) {
|
||||||
//
|
//
|
||||||
// Current memory space starts at a new page. Resetting PageLength will
|
// Current memory space starts at a new page. Resetting PageLength will
|
||||||
|
@ -826,7 +873,9 @@ RefreshGcdMemoryAttributesFromPaging (
|
||||||
PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress);
|
PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync real page attributes to GCD
|
//
|
||||||
|
// Sync actual page attributes to GCD
|
||||||
|
//
|
||||||
BaseAddress = MemorySpaceMap[Index].BaseAddress;
|
BaseAddress = MemorySpaceMap[Index].BaseAddress;
|
||||||
MemorySpaceLength = MemorySpaceMap[Index].Length;
|
MemorySpaceLength = MemorySpaceMap[Index].Length;
|
||||||
while (MemorySpaceLength > 0) {
|
while (MemorySpaceLength > 0) {
|
||||||
|
@ -842,23 +891,26 @@ RefreshGcdMemoryAttributesFromPaging (
|
||||||
PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask(PageAttribute);
|
PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask(PageAttribute);
|
||||||
PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress);
|
PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress);
|
||||||
Attributes = GetAttributesFromPageEntry (PageEntry);
|
Attributes = GetAttributesFromPageEntry (PageEntry);
|
||||||
|
|
||||||
if (Attributes != (MemorySpaceMap[Index].Attributes & EFI_MEMORY_PAGETYPE_MASK)) {
|
|
||||||
DoUpdate = TRUE;
|
|
||||||
Attributes |= (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_PAGETYPE_MASK);
|
|
||||||
Capabilities = Attributes | MemorySpaceMap[Index].Capabilities;
|
|
||||||
} else {
|
|
||||||
DoUpdate = FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Length = MIN (PageLength, MemorySpaceLength);
|
Length = MIN (PageLength, MemorySpaceLength);
|
||||||
if (DoUpdate) {
|
if (Attributes != (MemorySpaceMap[Index].Attributes &
|
||||||
gDS->SetMemorySpaceCapabilities (BaseAddress, Length, Capabilities);
|
EFI_MEMORY_PAGETYPE_MASK)) {
|
||||||
gDS->SetMemorySpaceAttributes (BaseAddress, Length, Attributes);
|
NewAttributes = (MemorySpaceMap[Index].Attributes &
|
||||||
DEBUG ((DEBUG_INFO, "Update memory space attribute: [%02d] %016lx - %016lx (%08lx -> %08lx)\r\n",
|
~EFI_MEMORY_PAGETYPE_MASK) | Attributes;
|
||||||
Index, BaseAddress, BaseAddress + Length - 1,
|
Status = gDS->SetMemorySpaceAttributes (
|
||||||
MemorySpaceMap[Index].Attributes, Attributes));
|
BaseAddress,
|
||||||
|
Length,
|
||||||
|
NewAttributes
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"Updated memory space attribute: [%lu] %016lx - %016lx (%016lx -> %016lx)\r\n",
|
||||||
|
(UINT64)Index, BaseAddress, BaseAddress + Length - 1,
|
||||||
|
MemorySpaceMap[Index].Attributes,
|
||||||
|
NewAttributes
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLength -= Length;
|
PageLength -= Length;
|
||||||
|
|
Loading…
Reference in New Issue