summaryrefslogtreecommitdiffstats
path: root/ArmPkg/Library/ArmMmuLib
Commit message (Collapse)AuthorAgeFilesLines
* ArmPkg/ArmMmuLib: Use function pointer typeMichael Kubacki2023-11-285-13/+33
| | | | | | | | | | | | | | | | | | | mReplaceLiveEntryFunc is a function pointer but assigned as a VOID* pointer: mReplaceLiveEntryFunc = *(VOID **)GET_GUID_HOB_DATA (Hob); This leads to the Visual Studio warning: nonstandard extension, function/data pointer conversion in expression This change updates the assignment to avoid using a data pointer and defines a type for the function pointer to succinctly and accurately refer to the type when it is used in the library code. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
* ArmPkg/ArmMmuLib: Drop buggy secure memory type checkArd Biesheuvel2023-09-121-2/+0
| | | | | | | | | | | | | | | Jake reports that the IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE() macro is no longer accurate since commit 852227a9d52e3cb9 ("ArmPkg/Mmu: Remove handling of NONSECURE memory regions"). Fortunately, it only affects the NS bit in level 1 short descriptors, which is ignored when executing in non-secure mode. And given that running UEFI in the secure world is not a use case we aim to support, let's just drop this logic altogether. Reported-by: Jake Garver <jake@nvidia.com> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg: Drop individual memory permission helpersArd Biesheuvel2023-06-272-240/+0
| | | | | | | | | | Now that we have a sane API to set and clear memory permissions that works the same on ARM and AArch64, we no longer have a need for the individual set/clear no-access/read-only/no-exec helpers so let's drop them. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: Extend API to manage memory permissions betterArd Biesheuvel2023-06-262-14/+130
| | | | | | | | | | | | | | | | | | | | | | | | | | Currently, ArmSetMemoryAttributes () takes a combination of EFI_MEMORY_xx constants describing the memory type and permission attributes that should be set on a region of memory. In cases where the memory type is omitted, we assume that the memory permissions being set are final, and that existing memory permissions can be discarded. This is problematic, because we aim to map memory non-executable (EFI_MEMORY_XP) by default, and only relax this requirement for code regions that are mapped read-only (EFI_MEMORY_RO). Currently, setting one permission clears the other, and so code managing these permissions has to be aware of the existing permissions in order to be able to preserve them, and this is not always tractable (e.g., the UEFI memory attribute protocol implements an abstraction that promises to preserve memory permissions that it is not operating on explicitly). So let's add an AttributeMask parameter to ArmSetMemoryAttributes(), which is permitted to be non-zero if no memory type is being provided, in which case only memory permission attributes covered in the mask will be affected by the update. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Oliver Smith-Denny <osde@linux.microsoft.com> Reviewed-by: Michael Kubacki <michael.kubacki@microsoft.com>
* ArmPkg/ArmMmuLib AARCH64: Add missing ISB after page table updateArd Biesheuvel2023-05-231-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | The helper that updates live page table entries writes a zero entry, invalidates the covered address range from the TLBs, and finally writes the actual entry. This ensures that no TLB conflicts can occur. Writing the final entry needs to complete before any translations can be performed, as otherwise, the zero entry, which describes an invalid translation, may be observed by the page table walker, resulting in a translation fault. For this reason, the final write is followed by a DSB barrier instruction. However, this barrier will not stall the pipeline, and instruction fetches may still hit this invalid translation, as has been observed and reported by Oliver. To ensure that the new translation is fully active before returning from this helper, we have to insert an ISB barrier as well. Reported-by: Oliver Steffen <osteffen@redhat.com> Tested-by: Oliver Steffen <osteffen@redhat.com> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com> Acked-by: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
* ArmPkg/ArmMmuLib: Fix ArmReplaceLiveTranslationEntry() alignmentMarvin Häuser2023-04-201-6/+8
| | | | | | | | | | | | | | | | | | As the ASM_FUNC() macro performs a section switch, the preceding .balign directive applies the alignment constraint to the current location in the previous section. As the linker may not merge the sections in-order, ArmReplaceLiveTranslationEntry() may be left unaligned. Replace the explicit invocation of .balign with the ASM_FUNC_ALIGN() macro, which guarantees the alignment constraint is applied correctly. To make sure related issues are reliably caught in the future, align the end of the function before checking the total occupied size. This ensures crossing a 0x200 boundary will cause a compilation error. Signed-off-by: Marvin Häuser <mhaeuser@posteo.de> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
* ArmPkg: Update code to be more C11 compliant by using __func__Rebecca Cran2023-04-101-2/+2
| | | | | | | | | | | | __FUNCTION__ is a pre-standard extension that gcc and Visual C++ among others support, while __func__ was standardized in C99. Since it's more standard, replace __FUNCTION__ with __func__ throughout ArmPkg. Signed-off-by: Rebecca Cran <rebecca@bsdio.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
* ArmPkg/ArmMmuLib: Introduce region types for RO/XP WB cached memoryArd Biesheuvel2023-03-162-6/+41
| | | | | | | | | | | | | | | | To prepare for the enablement of booting EFI with the SCTLR.WXN control enabled, which makes all writeable memory regions non-executable by default, introduce a memory type that we will use to describe the flash region that carries the SEC and PEIM modules that execute in place. Even if these are implicitly read-only due to the ROM nature, they need to be mapped with read-only attributes in the page tables to be able to execute from them. Also add the XP counterpart which will be used for all normal DRAM right at the outset. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/Mmu: Remove handling of NONSECURE memory regionsArd Biesheuvel2023-03-162-32/+6
| | | | | | | | | | | | Non-secure memory is a distinction that only matters when executing code in the secure world that reasons about the secure vs non-secure address spaces. EDK2 was not designed for that, and the AArch64 version of the MMU handling library already treats them as identical, so let's just drop the ARM memory region types that mark memory as 'non-secure' explicitly. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: Avoid splitting block entries if possibleArd Biesheuvel2023-03-162-0/+21
| | | | | | | | | | | | | | | | | Currently, the ARM MMU page table logic will break down any block entry that overlaps with the region being mapped, even if the block entry in question is using the same attributes as the new region. This means that creating a non-executable mapping inside a region that is already mapped non-executable at a coarser granularity may trigger a call to AllocatePages (), which may recurse back into the page table code to update the attributes on the newly allocated page tables. Let's avoid this, by preserving the block entry if it already covers the region being mapped with the correct attributes. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: Implement EFI_MEMORY_RP using access flagArd Biesheuvel2023-03-162-3/+103
| | | | | | | | | | | Implement support for read-protected memory by wiring it up to the access flag in the page table descriptor. The resulting mapping is implicitly non-writable and non-executable as well, but this is good enough for implementing this attribute, as we never rely on write or execute permissions without read permissions. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib ARM: Clear individual permission bitsArd Biesheuvel2023-03-161-13/+81
| | | | | | | | | | | | | | | | | Currently, the MMU code that is supposed to clear the RO or XP attributes from a region just clears both unconditionally. This approximates the desired behavior to some extent, but it does mean that setting the RO bit first on a code region, and then clearing the XP bit results both RO and XP being cleared, and we end up with writable code, and avoiding that is the point of all these protections. Once we introduce RP support, this will only get worse, so let's fix this up, by reshuffling the attribute update code to take the entry mask from the caller, and use the mask to preserve other attributes when clearing RO or XP. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib ARM: Isolate the access flag from AP maskArd Biesheuvel2023-03-162-2/+11
| | | | | | | | | | | Split the ARM permission fields in the short descriptors into an access flag and AP[2:1] as per the recommendation in the ARM ARM. This makes the access flag available separately, which allows us to implement EFI_MEMORY_RP memory analogous to how it will be implemented for AArch64. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib ARM: Split off XN page descriptor bit from type fieldArd Biesheuvel2023-03-161-6/+6
| | | | | | | | | | | With large page support out of the picture, we can treat bits 1 and 0 of the page descriptor as individual valid and XN bits, instead of treating XN as a page type. Doing so aligns the handling of the attribute with the section descriptor layout, as well as the XN handling on AArch64, and this is beneficial for maintainability. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib ARM: Remove half baked large page supportArd Biesheuvel2023-03-163-6/+5
| | | | | | | | | | | | | | | | | | Large page support on 32-bit ARM is essentially a glorified contiguous bit where 16 consecutive entries describing a contiguous range with the same attributes are presented in a way that permits the TLB to cache its translation with a single entry. This was never wired up completely, and does not add a lot of value in EFI, where the page granularity is 4k and we expect to be able to set RO and XP permissions on individual pages. Given that large page support complicates the handling of the XN bit at the page level (which is in a different place depending on whether the page is small or large), let's just rip it out. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: Reuse XIP MMU routines when splitting entriesArd Biesheuvel2022-10-194-10/+42
| | | | | | | | | | | | | | In order to reduce the likelihood that we will need to rely on the logic that disables and re-enables the MMU for updating a page table entry safely, expose the XIP version of the helper routine via a HOB and use it instead of the one that is copied into DRAM. Since the XIP copy is already clean to the PoC, and will never end up getting unmapped during a block entry split, we can use it safely without any cache maintenance, and without running the risk of pulling the rug from under our feet when updating an entry by going through an invalid mapping. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: permit initial configuration with MMU enabledArd Biesheuvel2022-10-191-22/+26
| | | | | | | | | | | | | | Permit the use of this library with the MMU and caches already enabled. This removes the need for any cache maintenance for coherency, and is generally better for robustness and performance, especially when running under virtualization. Note that this means we have to defer assignment of TTBR0 until the page tables are ready to be used, and so UpdateRegionMapping() can no longer read back TTBR0 directly to discover the root table address. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: Disable and re-enable MMU only when neededArd Biesheuvel2022-10-192-26/+119
| | | | | | | | | | | | | When updating a page table descriptor in a way that requires break before make, we temporarily disable the MMU to ensure that we don't unmap the memory region that the code itself is executing from. However, this is a condition we can check in a straight-forward manner, and if the regions are disjoint, we don't have to bother with the MMU controls, and we can just perform an ordinary break before make. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg/ArmMmuLib: don't replace table entries with block entriesArd Biesheuvel2022-10-191-18/+2
| | | | | | | | | | | | Drop the optimization that replaces table entries with block entries and frees the page tables in the subhierarchy that is being replaced. This rarely occurs in practice anyway, and will require more elaborate TLB maintenance once we switch to a different approach where we no longer disable the MMU and nuke the TLB entirely every time we update a descriptor in a way that requires break-before-make (BBM). Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg: Remove duplicated wordsPierre Gondois2022-09-051-1/+1
| | | | | | | | | In an effort to clean the documentation of the above package, remove duplicated words, and fix a typo while at it. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Reviewed-by: Sami Mujawar <sami.muajwar@arm.com> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
* ArmPkg: Remove RVCT supportRebecca Cran2022-05-132-27/+0
| | | | | | | | RVCT is obsolete and no longer used. Remove support for it. Signed-off-by: Rebecca Cran <quic_rcran@quicinc.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
* ArmPkg/ArmMmuLib AARCH64: avoid EL0 accessible mappingsArd Biesheuvel2022-02-011-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | We never run any code at EL0, and so it would seem that any access permissions set for EL0 (via the AP[1] attribute in the page tables) are irrelevant. We currently set EL0 and EL1 permissions to the same value arbitrarily. However, this causes problems on hardware like the Apple M1 running the MacOS hypervisor framework, which enters EL1 with SCTLR_EL1.SPAN enabled, causing the Privileged Access Never (PAN) feature to be enabled on any exception taken to EL1, including the IRQ exceptions that handle our timer interrupt. When PAN is enabled, EL1 has no access to any mappings that are also accessible to EL0, causing the firmware to crash if it attempts to access such a mapping. Even though it is debatable whether or not SCTLR_EL1.SPAN should be disabled at entry or whether the firmware should put all UNKNOWN bits in all system registers in a consistent state (which it should), using EL0 permissions serves no purpose whatsoever so let's fix that regardless. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Tested-by: Alexander Graf <agraf@csgraf.de> Acked-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg: Apply uncrustify changesMichael Kubacki2021-12-075-324/+414
| | | | | | | | | | | | REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the ArmPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
* ArmPkg: Change use of EFI_D_* to DEBUG_*Michael D Kinney2021-12-071-2/+2
| | | | | | | | | | | | | REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3739 Update all use of EFI_D_* defines in DEBUG() macros to DEBUG_* defines. Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael Kubacki <michael.kubacki@microsoft.com> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
* ArmPkg: Correct small typosPierre Gondois2021-04-281-2/+2
| | | | | | | | | | | | | The 'cspell' CI test detected some small typos in ArmPkg. Correct them. Cc: Bret Barkelew <bret.barkelew@microsoft.com> Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Sami Mujawar <sami.mujawar@arm.com> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
* ArmPkg: Fix Ecc error 5007 in ArmMmuLibPierre Gondois2021-01-061-1/+3
| | | | | | | | | This patch fixes the following Ecc reported error: There should be no initialization of a variable as part of its declaration Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
* ArmPkg: Fix Ecc error 3002 in ArmMmuLibPierre Gondois2021-01-062-16/+16
| | | | | | | | | This patch fixes the following Ecc reported error: Non-Boolean comparisons should use a compare operator (==, !=, >, < >=, <=) Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
* ArmPkg: Format header to fix Ecc crash in ArmMmuLibPierre Gondois2021-01-061-7/+7
| | | | | | | | | | | | | | The header of the file is not formatted properly, making the Ecc tool crash when running on the ArmPkg. The following command was run: ./BaseTools/BinWrappers/PosixLike/Ecc -c BaseTools/Source/Python/Ecc/config.ini -e BaseTools/Source/Python/Ecc/exception.xml -t ArmPkg -r ArmPkgEcc.xls Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
* ArmPkg/ArmMmuLib: Explicitly cast function pointer argumentMichael Kubacki2020-10-221-1/+1
| | | | | | | | | | | | | | | | | | | The function ArmReplaceLiveTranslationEntry () is passed as a VOID pointer to WriteBackDataCacheRange (). This produces the following warning on VS2019: warning C4152: nonstandard extension, function/data pointer conversion in expression This change explicitly casts the argument to the formal parameter type VOID*. This can be reproduced with the following build command: build -b DEBUG -a AARCH64 -t VS2019 -p ArmPkg/ArmPkg.dsc -m ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
* ArmPkg/ArmMmuLib: Explicitly cast UINT32 data conversionsMichael Kubacki2020-10-222-4/+4
| | | | | | | | | | | | | | | | | | | | | | | REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2835 There's several occurrences of a UINT64 or an EFI_PHYSICAL_ADDRESS being assigned to a UINT32 value in ArmMmuLib. These result in warning C4244 in VS2019: warning C4244: '=': conversion from 'UINT64' to 'UINT32', possible loss of data warning C4244: '=': conversion from 'EFI_PHYSICAL_ADDRESS' to 'UINT32', possible loss of data This change explicitly casts the values to UINT32. These can be reproduced with the following build command: build -b DEBUG -a ARM -t VS2019 -p ArmPkg/ArmPkg.dsc -m ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
* ArmPkg/ArmMmuLib: Fix implicit castPierre Gondois2020-06-271-1/+1
| | | | | | | | | | | | | | | | | | | | While building with the following command line: build -b DEBUG -a AARCH64 -t VS2017 -p MdeModulePkg\MdeModulePkg.dsc A missing cast triggers the following warning, then triggering an error: ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c(652): warning C4152: nonstandard extension, function/data pointer conversion in expression This patch first casts the function pointer to (UINTN), then to (VOID *), followowing the C99 standard s6.3.2.3 "Pointer", paragraphs 5 and 6. This suppresses the warning. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Suggested-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
* ArmPkg/ArmMmuLib: drop unused TT_ATTR_INDX_INVALID CPP macroArd Biesheuvel2020-04-021-3/+0
| | | | | | | | | | | TT_ATTR_INDX_INVALID is #define'd but never used so drop it. Note that this leaves a CPP macro of the same name in CpuDxe, but there, it is actually being used, and although the name suggests that this value is somehow defined by the architecture, this is really not the case and it only has meaning within the scope of CpuDxe's implementation. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib: get rid of GetRootTranslationTableInfo()Ard Biesheuvel2020-04-021-16/+6
| | | | | | | | | Only a single call to GetRootTranslationTableInfo() remains, which only provides the root table level. So let's create a new static helper function that returns just this value, and use it instead. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib: drop pointless LookupAddresstoRootTable() routineArd Biesheuvel2020-04-021-34/+15
| | | | | | | | | | | | | | LookupAddresstoRootTable() uses a loop to go over its MaxAddress argument, essentially to do a log2() and determine how many bits are needed to represent it. Since the argument is the result of a shift-left expression, there is some room for improvement here, and we can simply use the bit count directly to calculate the value of T0SZ. At the same time, we can omit calling GetRootTranslationTableInfo() to determine the number of root table entries, and add a new helper that applies the trivial calculation directly. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/CpuDxe: move PageAttributeToGcdAttribute() out of ArmMmuLibArd Biesheuvel2020-04-021-45/+0
| | | | | | | | | The routine PageAttributeToGcdAttribute() is exported by ArmMmuLib but only ever used in the implementation of CpuDxe. So let's move the function there and make it STATIC. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib AARCH64: preserve attributes when replacing a table entryArd Biesheuvel2020-03-261-4/+21
| | | | | | | | | | | | | | | | | | | | | | Currently, depending on the size of the region being (re)mapped, the page table manipulation code may replace a table entry with a block entry, even if the existing table entry uses different mapping attributes to describe different parts of the region it covers. This is undesirable, and instead, we should avoid doing so unless we are disregarding the original attributes anyway. And if we make such a replacement, we should free all the page tables that have become orphaned in the process. So let's implement this, by taking the table entry path through the code for block sized regions if a table entry already exists, and the clear mask is set (which means we are preserving attributes from the existing mapping). And when we do replace a table entry with a block entry, free all the pages that are no longer referenced. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com> Reviewed-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Laszlo Ersek <lersek@redhat.com>
* ArmPkg/ArmMmuLib AARCH64: use helpers to determine table entry typesArd Biesheuvel2020-03-261-5/+35
| | | | | | | | | | | | Given how the meaning of the attribute bits for page table entry types is slightly awkward, and changes between levels, add some helpers to abstract from this. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com> Reviewed-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Laszlo Ersek <lersek@redhat.com>
* ArmPkg/ArmMmuLib AARCH64: limit recursion when freeing page tablesArd Biesheuvel2020-03-261-6/+12
| | | | | | | | | | | | | | | | | | | | FreePageTablesRecursive () traverses the page table tree depth first to free all pages that it finds, without taking into account the level at which it is operating. Since TT_TYPE_TABLE_ENTRY aliases TT_TYPE_BLOCK_ENTRY_LEVEL3, we cannot distinguish table entries from block entries unless we take the level into account, and so we may be dereferencing garbage if we happen to try and free a hierarchy of page tables that has level 3 pages in it. Let's fix this by passing the level into FreePageTablesRecursive (), and limit the recursion to levels < 3. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com> Reviewed-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Laszlo Ersek <lersek@redhat.com>
* ArmPkg/ArmMmuLib AARCH64: cosmetic fixupsArd Biesheuvel2020-03-101-19/+37
| | | | | | | | | | | Some cosmetic fixups to the AArch64 MMU code: - reflow overly long lines unless it hurts legibility - add/remove whitespace according to the [de facto] coding style - use camel case for goto labels Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Message-Id: <20200307091008.14918-3-ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib AARCH64: drop pointless page table memory type checkArd Biesheuvel2020-03-101-15/+0
| | | | | | | | | | | This is the AARCH64 counterpart of commit 1f3b1eb3082206e4, to remove a pointless check against the memory type of the allocations that the page tables happened to land in. On ArmV8, we use writeback cacheable exclusively for all memory. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Message-Id: <20200307091008.14918-2-ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib AARCH64: invalidate page tables before populating themArd Biesheuvel2020-03-101-0/+14
| | | | | | | | | | | | As it turns out, ARMv8 also permits accesses made with the MMU and caches off to hit in the caches, so to ensure that any modifications we make before enabling the MMU are visible afterwards as well, we should invalidate page tables right after allocation like we do now on ARM, if the MMU is still disabled at that point. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com> Message-Id: <20200307083849.8940-3-ard.biesheuvel@linaro.org>
* ArmPkg/ArmMmuLib AARCH64: rewrite page table codeArd Biesheuvel2020-03-101-238/+143
| | | | | | | | | | | | | | Replace the slightly overcomplicated page table management code with a simplified, recursive implementation that should be far easier to reason about. Note that, as a side effect, this extends the per-entry cache invalidation that we do on page table entries to block and page entries, whereas the previous change inadvertently only affected the creation of table entries. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Message-Id: <20200307083849.8940-2-ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib ARM: drop memory type check for page tablesArd Biesheuvel2020-03-051-18/+2
| | | | | | | | | | We already expect normal memory to be mapped writeback cacheable if EDK2 itself is to make use of it, so doing an early sanity check on the memory type of the allocation that the page tables happened to land in isn't very useful. So let's drop it. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib ARM: simplify assignment of TTBR0 system registerArd Biesheuvel2020-03-051-1/+1
| | | | | | | | | | | | | | | The expression passed into ArmSetTTBR0 () in ArmConfigureMmu() is sub-optimal at several levels: - TranslationTable is already aligned, and if it wasn't, doing it here wouldn't help - TTBRAttributes is guaranteed not to have any bits set outside of the 0x7f mask, so the mask operation is pointless as well, - an additional (UINTN) cast for good measure is also not needed. So simplify the expression. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib AARCH64: cache-invalidate initial page table entriesArd Biesheuvel2020-03-051-9/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the AARCH64 version of ArmMmuLib, we are currently relying on set/way invalidation to ensure that the caches are in a consistent state with respect to main memory once we turn the MMU on. Even if set/way operations were the appropriate method to achieve this, doing an invalidate-all first and then populating the page table entries creates a window where page table entries could be loaded speculatively into the caches before we modify them, and shadow the new values that we write there. So let's get rid of the blanket clean/invalidate operations, and instead, update ArmUpdateTranslationTableEntry () to invalidate each page table entry *after* it is written if the MMU is still disabled at this point. On ARMv8, it is guaranteed that memory accesses done by the page table walker are cache coherent, and so we can ignore the case where the MMU is on. Since the MMU and D-cache are already off when we reach this point, we can drop the MMU and D-cache disables as well. Maintenance of the I-cache is unnecessary, since we are not modifying any code, and the installed mapping is guaranteed to be 1:1. This means we can also leave it enabled while the page table population code is running. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib ARM: cache-invalidate initial page table entriesArd Biesheuvel2020-03-051-14/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the ARM version of ArmMmuLib, we are currently relying on set/way invalidation to ensure that the caches are in a consistent state with respect to main memory once we turn the MMU on. Even if set/way operations were the appropriate method to achieve this, doing an invalidate-all first and then populating the page table entries creates a window where page table entries could be loaded speculatively into the caches before we modify them, and shadow the new values that we write there. So let's get rid of the blanket clean/invalidate operations, and instead, invalidate each page table right after allocating it, and each section entry after it is updated (to address all the little corner cases that the ARMv7 spec permits), and invalidate sets of level 2 entries in blocks, using the generic invalidation routine from CacheMaintenanceLib On ARMv7, cache maintenance may be required also when the MMU is enabled, in case the page table walker is not cache coherent. However, the code being updated here is guaranteed to run only when the MMU is still off, and so we can disregard the case when the MMU and caches are on. Since the MMU and D-cache are already off when we reach this point, we can drop the MMU and D-cache disables as well. Maintenance of the I-cache is unnecessary, since we are not modifying any code, and the installed mapping is guaranteed to be 1:1. This means we can also leave it enabled while the page table population code is running. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib ARM: use AllocateAlignedPages() for alignmentArd Biesheuvel2020-03-051-9/+10
| | | | | | | | | | | | Instead of overallocating memory and align the resulting base address manually, use the AllocateAlignedPages () helper, which achieves the same, and might even manage that without leaking a chunk of memory of the same size as the allocation itself. While at it, fix up a variable declaration in the same hunk, and drop a comment whose contents add nothing to the following line of code. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
* ArmPkg/ArmMmuLib ARM: split ArmMmuLibCore.c into core and update codeArd Biesheuvel2020-03-054-434/+469
| | | | | | | | | | | | | | | | | | | Unlike the AArch64 implementation of ArmMmuLib, which combines the initial page table population code with the code that runs at later stages to manage permission attributes in the page tables, ARM uses two completely separate sets of routines for this. Since ArmMmuLib is a static library, we can prevent duplication of this code between different users, which usually only need one or the other. (Note that LTO should also achieve the same.) This also makes it easier to reason about modifying the cache maintenance handling, and replace the set/way ops with by-VA ops, since the code that performs the set/way ops only executes when the MMU is still off. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg/ArmMmuLib ARM: remove dummy constructorArd Biesheuvel2020-03-052-9/+2
| | | | | | | | Make the CONSTRUCTOR define in the .INF AARCH64 only, so we can drop the empty stub that exists for ARM. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
* ArmPkg: strip trailing whitespaceLeif Lindholm2019-10-041-2/+2
| | | | | | | Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>