From: Leif Lindholm <leif.lindholm@linaro.org>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: edk2-devel@lists.01.org, lersek@redhat.com
Subject: Re: [PATCH v2 2/4] ArmPkg/CpuDxe ARM: avoid unnecessary cache/TLB maintenance
Date: Mon, 6 Mar 2017 14:27:59 +0000 [thread overview]
Message-ID: <20170306142759.GU16034@bivouac.eciton.net> (raw)
In-Reply-To: <1488450976-16257-3-git-send-email-ard.biesheuvel@linaro.org>
On Thu, Mar 02, 2017 at 10:36:14AM +0000, Ard Biesheuvel wrote:
> Page and section entries in the page tables are updated using the
> helper ArmUpdateTranslationTableEntry(), which cleans the page
> table entry to the PoC, and invalidates the TLB entry covering
> the page described by the entry being updated.
>
> Since we may be updating section entries, we might be leaving stale
> TLB entries at this point (for all pages in the section except the
> first one), which will be invalidated wholesale at the end of
> SetMemoryAttributes(). At that point, all caches are cleaned *and*
> invalidated as well.
>
> This cache maintenance is costly and unnecessary. The TLB maintenance
> is only necessary if we updated any section entries, since any page
> by page entries that have been updated will have been invalidated
> individually by ArmUpdateTranslationTableEntry().
>
> So drop the clean/invalidate of the caches, and only perform the
> full TLB flush if UpdateSectionEntries() was called, or if sections
> were split by UpdatePageEntries(). Finally, make the cache maintenance
> on the remapped regions themselves conditional on whether any memory
> type attributes were modified.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> ArmPkg/Drivers/CpuDxe/Arm/Mmu.c | 60 +++++++++++---------
> 1 file changed, 34 insertions(+), 26 deletions(-)
>
> diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
> index ce4d529bda67..26b637e7658f 100644
> --- a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
> +++ b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
> @@ -347,10 +347,11 @@ SyncCacheConfig (
>
> EFI_STATUS
> UpdatePageEntries (
> - IN EFI_PHYSICAL_ADDRESS BaseAddress,
> - IN UINT64 Length,
> - IN UINT64 Attributes,
> - IN EFI_PHYSICAL_ADDRESS VirtualMask
> + IN EFI_PHYSICAL_ADDRESS BaseAddress,
> + IN UINT64 Length,
> + IN UINT64 Attributes,
> + IN EFI_PHYSICAL_ADDRESS VirtualMask,
> + OUT BOOLEAN *FlushTlbs
> )
> {
> EFI_STATUS Status;
> @@ -446,6 +447,9 @@ UpdatePageEntries (
>
> // Re-read descriptor
> Descriptor = FirstLevelTable[FirstLevelIdx];
> + if (FlushTlbs != NULL) {
If FlushTlbs is optional, should it not be marked OPTIONAL above?
If you fold that in:
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
> + *FlushTlbs = TRUE;
> + }
> }
>
> // Obtain page table base address
> @@ -471,15 +475,16 @@ UpdatePageEntries (
>
> if (CurrentPageTableEntry != PageTableEntry) {
> Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));
> - if ((CurrentPageTableEntry & TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) == TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) {
> - // The current section mapping is cacheable so Clean/Invalidate the MVA of the page
> - // Note assumes switch(Attributes), not ARMv7 possibilities
> - WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE);
> - }
>
> // Only need to update if we are changing the entry
> PageTable[PageTableIndex] = PageTableEntry;
> ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);
> +
> + // Clean/invalidate the cache for this page, but only
> + // if we are modifying the memory type attributes
> + if (((CurrentPageTableEntry ^ PageTableEntry) & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) != 0) {
> + WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE);
> + }
> }
>
> Status = EFI_SUCCESS;
> @@ -581,7 +586,12 @@ UpdateSectionEntries (
> // has this descriptor already been coverted to pages?
> if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {
> // forward this 1MB range to page table function instead
> - Status = UpdatePageEntries ((FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT, TT_DESCRIPTOR_SECTION_SIZE, Attributes, VirtualMask);
> + Status = UpdatePageEntries (
> + (FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,
> + TT_DESCRIPTOR_SECTION_SIZE,
> + Attributes,
> + VirtualMask,
> + NULL);
> } else {
> // still a section entry
>
> @@ -596,15 +606,16 @@ UpdateSectionEntries (
>
> if (CurrentDescriptor != Descriptor) {
> Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
> - if ((CurrentDescriptor & TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) == TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) {
> - // The current section mapping is cacheable so Clean/Invalidate the MVA of the section
> - // Note assumes switch(Attributes), not ARMv7 possabilities
> - WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);
> - }
>
> // Only need to update if we are changing the descriptor
> FirstLevelTable[FirstLevelIdx + i] = Descriptor;
> ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);
> +
> + // Clean/invalidate the cache for this section, but only
> + // if we are modifying the memory type attributes
> + if (((CurrentDescriptor ^ Descriptor) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) != 0) {
> + WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);
> + }
> }
>
> Status = EFI_SUCCESS;
> @@ -680,6 +691,7 @@ SetMemoryAttributes (
> {
> EFI_STATUS Status;
> UINT64 ChunkLength;
> + BOOLEAN FlushTlbs;
>
> //
> // Ignore invocations that only modify permission bits
> @@ -688,6 +700,7 @@ SetMemoryAttributes (
> return EFI_SUCCESS;
> }
>
> + FlushTlbs = FALSE;
> while (Length > 0) {
> if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&
> Length >= TT_DESCRIPTOR_SECTION_SIZE) {
> @@ -700,6 +713,8 @@ SetMemoryAttributes (
>
> Status = UpdateSectionEntries (BaseAddress, ChunkLength, Attributes,
> VirtualMask);
> +
> + FlushTlbs = TRUE;
> } else {
>
> //
> @@ -717,7 +732,7 @@ SetMemoryAttributes (
> BaseAddress, ChunkLength, Attributes));
>
> Status = UpdatePageEntries (BaseAddress, ChunkLength, Attributes,
> - VirtualMask);
> + VirtualMask, &FlushTlbs);
> }
>
> if (EFI_ERROR (Status)) {
> @@ -728,16 +743,9 @@ SetMemoryAttributes (
> Length -= ChunkLength;
> }
>
> - // Flush d-cache so descriptors make it back to uncached memory for subsequent table walks
> - // flush and invalidate pages
> - //TODO: Do we really need to invalidate the caches everytime we change the memory attributes ?
> - ArmCleanInvalidateDataCache ();
> -
> - ArmInvalidateInstructionCache ();
> -
> - // Invalidate all TLB entries so changes are synced
> - ArmInvalidateTlb ();
> -
> + if (FlushTlbs) {
> + ArmInvalidateTlb ();
> + }
> return Status;
> }
>
> --
> 2.7.4
>
next prev parent reply other threads:[~2017-03-06 14:28 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-02 10:36 [PATCH v2 0/4] ArmPkg, ArmVirtpkg ARM: enable strict memory protection Ard Biesheuvel
2017-03-02 10:36 ` [PATCH v2 1/4] ArmPkg/CpuDxe ARM: avoid splitting page table sections unnecessarily Ard Biesheuvel
2017-03-06 14:12 ` Leif Lindholm
2017-03-06 14:55 ` Ard Biesheuvel
2017-03-06 16:24 ` Leif Lindholm
2017-03-02 10:36 ` [PATCH v2 2/4] ArmPkg/CpuDxe ARM: avoid unnecessary cache/TLB maintenance Ard Biesheuvel
2017-03-06 14:27 ` Leif Lindholm [this message]
2017-03-06 15:06 ` Ard Biesheuvel
2017-03-02 10:36 ` [PATCH v2 3/4] ArmPkg/CpuDxe ARM: honour RO/XP attributes in SetMemoryAttributes() Ard Biesheuvel
2017-03-06 14:48 ` Leif Lindholm
2017-03-06 15:11 ` Ard Biesheuvel
2017-03-06 16:40 ` Leif Lindholm
2017-03-02 10:36 ` [PATCH v2 4/4] ArmVirtPkg: enable PE/COFF image and memory protection for ARM platforms Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170306142759.GU16034@bivouac.eciton.net \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox