From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=209.132.183.28; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 05F0B2034C5F8 for ; Mon, 20 Nov 2017 12:27:20 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F177B5F7AC; Mon, 20 Nov 2017 20:31:34 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-222.rdu2.redhat.com [10.10.120.222]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3C45960BE0; Mon, 20 Nov 2017 20:31:33 +0000 (UTC) To: Jian J Wang , edk2-devel@lists.01.org Cc: Jiewen Yao , Eric Dong , Star Zeng , Ard Biesheuvel References: <20171116072700.11456-1-jian.j.wang@intel.com> <20171116072700.11456-3-jian.j.wang@intel.com> From: Laszlo Ersek Message-ID: <5a87ed78-58da-e3a2-9f52-8318fb121b4c@redhat.com> Date: Mon, 20 Nov 2017 21:31:32 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: <20171116072700.11456-3-jian.j.wang@intel.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 20 Nov 2017 20:31:35 +0000 (UTC) Subject: Re: [PATCH 2/2] UefiCpuPkg/CpuDxe: Fix multiple entries of RT_CODE in memory map X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Nov 2017 20:27:21 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 11/16/17 08:27, Jian J Wang wrote: >> v6: >> Add ExecuteDisable feature check to include/exclude EFI_MEMORY_XP Another change relative to v5 is the fixing of the first DEBUG_WARN message -- in my v5 review I had missed that the DEBUG_WARN arguments didn't match the preceding gDS->SetMemorySpaceCapabilities() arguments. Yet another change that could have been (maybe) possible for this patch is to replace the remaining occurrences of EFI_MEMORY_PAGETYPE_MASK with "Capabilities". Namely, in v6, the attributes are enforced on a mask that is possibly wider than supported by the hardware (i.e., in case NX is not supported). However, this should not be a functionality problem, because with NX unavailable, the GetAttributesFromPageEntry() function should never return EFI_MEMORY_XP. Thus, the "wider than needed" attribute setting will just clear EFI_MEMORY_XP. Reviewed-by: Laszlo Ersek (I hope that Star and/or Jiewen will also R-b this patch.) In addition, I will follow up with test results for the series. Thanks Laszlo >> v5: >> Coding style clean-up > >> v4: >> a. Remove DoUpdate and check attributes mismatch all the time to avoid >> a logic hole >> b. Add warning message if failed to update capability >> c. Add local variable to hold new attributes to make code cleaner > >> v3: >> a. Add comment to explain more on updating memory capabilities >> b. Fix logic hole in updating attributes >> c. Instead of checking illegal memory space address and size, use return >> status of gDS->SetMemorySpaceCapabilities() to skip memory block which >> cannot be updated with new capabilities. > >> v2 >> a. Fix an issue which will cause setting capability failure if size is smaller >> than a page. > > 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 > > Cc: Eric Dong > Cc: Jiewen Yao > Cc: Star Zeng > Cc: Laszlo Ersek > Cc: Ard Biesheuvel > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Jian J Wang > --- > UefiCpuPkg/CpuDxe/CpuPageTable.c | 94 +++++++++++++++++++++++++++++++--------- > 1 file changed, 73 insertions(+), 21 deletions(-) > > diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTable.c > index d312eb66f8..3297c1900b 100644 > --- a/UefiCpuPkg/CpuDxe/CpuPageTable.c > +++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c > @@ -769,6 +769,20 @@ AssignMemoryPageAttributes ( > 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. > **/ > @@ -790,7 +804,7 @@ RefreshGcdMemoryAttributesFromPaging ( > UINT64 PageStartAddress; > UINT64 Attributes; > UINT64 Capabilities; > - BOOLEAN DoUpdate; > + UINT64 NewAttributes; > UINTN Index; > > // > @@ -802,17 +816,50 @@ RefreshGcdMemoryAttributesFromPaging ( > > GetCurrentPagingContext (&PagingContext); > > - DoUpdate = FALSE; > - Capabilities = 0; > - Attributes = 0; > - BaseAddress = 0; > - PageLength = 0; > + Attributes = 0; > + NewAttributes = 0; > + BaseAddress = 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++) { > if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) { > 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)) { > // > // Current memory space starts at a new page. Resetting PageLength will > @@ -826,7 +873,9 @@ RefreshGcdMemoryAttributesFromPaging ( > PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress); > } > > - // Sync real page attributes to GCD > + // > + // Sync actual page attributes to GCD > + // > BaseAddress = MemorySpaceMap[Index].BaseAddress; > MemorySpaceLength = MemorySpaceMap[Index].Length; > while (MemorySpaceLength > 0) { > @@ -842,23 +891,26 @@ RefreshGcdMemoryAttributesFromPaging ( > PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask(PageAttribute); > PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress); > 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); > - if (DoUpdate) { > - gDS->SetMemorySpaceCapabilities (BaseAddress, Length, Capabilities); > - gDS->SetMemorySpaceAttributes (BaseAddress, Length, Attributes); > - DEBUG ((DEBUG_INFO, "Update memory space attribute: [%02d] %016lx - %016lx (%08lx -> %08lx)\r\n", > - Index, BaseAddress, BaseAddress + Length - 1, > - MemorySpaceMap[Index].Attributes, Attributes)); > + if (Attributes != (MemorySpaceMap[Index].Attributes & > + EFI_MEMORY_PAGETYPE_MASK)) { > + NewAttributes = (MemorySpaceMap[Index].Attributes & > + ~EFI_MEMORY_PAGETYPE_MASK) | Attributes; > + Status = gDS->SetMemorySpaceAttributes ( > + 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; >