ArmPkg/ArmMmuLib AARCH64: get rid of needless TLB invalidation

Currently, we always invalidate the TLBs entirely after making
any modification to the page tables. Now that we have introduced
strict memory permissions in quite a number of places, such
modifications occur much more often, and it is better for performance
to flush only those TLB entries that are actually affected by
the changes.

At the same time, relax some system wide data synchronization barriers
to non-shared. When running in UEFI, we don't share virtual address
translations with other masters, unless we are running under virt, but
in that case, the host will upgrade them as appropriate (by setting
an override at EL2)

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
This commit is contained in:
Ard Biesheuvel 2019-01-07 08:15:01 +01:00
parent f34b38fae6
commit d5788777bc
4 changed files with 22 additions and 21 deletions

View File

@ -59,7 +59,8 @@ VOID
EFIAPI EFIAPI
ArmReplaceLiveTranslationEntry ( ArmReplaceLiveTranslationEntry (
IN UINT64 *Entry, IN UINT64 *Entry,
IN UINT64 Value IN UINT64 Value,
IN UINT64 RegionStart
); );
EFI_STATUS EFI_STATUS

View File

@ -124,15 +124,15 @@ ASM_FUNC(ArmSetMAIR)
// IN VOID *MVA // X1 // IN VOID *MVA // X1
// ); // );
ASM_FUNC(ArmUpdateTranslationTableEntry) ASM_FUNC(ArmUpdateTranslationTableEntry)
dc civac, x0 // Clean and invalidate data line dsb nshst
dsb sy lsr x1, x1, #12
EL1_OR_EL2_OR_EL3(x0) EL1_OR_EL2_OR_EL3(x0)
1: tlbi vaae1, x1 // TLB Invalidate VA , EL1 1: tlbi vaae1, x1 // TLB Invalidate VA , EL1
b 4f b 4f
2: tlbi vae2, x1 // TLB Invalidate VA , EL2 2: tlbi vae2, x1 // TLB Invalidate VA , EL2
b 4f b 4f
3: tlbi vae3, x1 // TLB Invalidate VA , EL3 3: tlbi vae3, x1 // TLB Invalidate VA , EL3
4: dsb sy 4: dsb nsh
isb isb
ret ret

View File

@ -129,13 +129,14 @@ STATIC
VOID VOID
ReplaceLiveEntry ( ReplaceLiveEntry (
IN UINT64 *Entry, IN UINT64 *Entry,
IN UINT64 Value IN UINT64 Value,
IN UINT64 RegionStart
) )
{ {
if (!ArmMmuEnabled ()) { if (!ArmMmuEnabled ()) {
*Entry = Value; *Entry = Value;
} else { } else {
ArmReplaceLiveTranslationEntry (Entry, Value); ArmReplaceLiveTranslationEntry (Entry, Value, RegionStart);
} }
} }
@ -296,7 +297,8 @@ GetBlockEntryListFromAddress (
// Fill the BlockEntry with the new TranslationTable // Fill the BlockEntry with the new TranslationTable
ReplaceLiveEntry (BlockEntry, ReplaceLiveEntry (BlockEntry,
((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY); (UINTN)TranslationTable | TableAttributes | TT_TYPE_TABLE_ENTRY,
RegionStart);
} }
} else { } else {
if (IndexLevel != PageLevel) { if (IndexLevel != PageLevel) {
@ -375,6 +377,8 @@ UpdateRegionMapping (
*BlockEntry &= BlockEntryMask; *BlockEntry &= BlockEntryMask;
*BlockEntry |= (RegionStart & TT_ADDRESS_MASK_BLOCK_ENTRY) | Attributes | Type; *BlockEntry |= (RegionStart & TT_ADDRESS_MASK_BLOCK_ENTRY) | Attributes | Type;
ArmUpdateTranslationTableEntry (BlockEntry, (VOID *)RegionStart);
// Go to the next BlockEntry // Go to the next BlockEntry
RegionStart += BlockEntrySize; RegionStart += BlockEntrySize;
RegionLength -= BlockEntrySize; RegionLength -= BlockEntrySize;
@ -487,9 +491,6 @@ ArmSetMemoryAttributes (
return Status; return Status;
} }
// Invalidate all TLB entries so changes are synced
ArmInvalidateTlb ();
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -512,9 +513,6 @@ SetMemoryRegionAttribute (
return Status; return Status;
} }
// Invalidate all TLB entries so changes are synced
ArmInvalidateTlb ();
return EFI_SUCCESS; return EFI_SUCCESS;
} }

View File

@ -32,13 +32,14 @@
dmb sy dmb sy
dc ivac, x0 dc ivac, x0
// flush the TLBs // flush translations for the target address from the TLBs
lsr x2, x2, #12
.if \el == 1 .if \el == 1
tlbi vmalle1 tlbi vaae1, x2
.else .else
tlbi alle\el tlbi vae\el, x2
.endif .endif
dsb sy dsb nsh
// re-enable the MMU // re-enable the MMU
msr sctlr_el\el, x8 msr sctlr_el\el, x8
@ -48,19 +49,20 @@
//VOID //VOID
//ArmReplaceLiveTranslationEntry ( //ArmReplaceLiveTranslationEntry (
// IN UINT64 *Entry, // IN UINT64 *Entry,
// IN UINT64 Value // IN UINT64 Value,
// IN UINT64 Address
// ) // )
ASM_FUNC(ArmReplaceLiveTranslationEntry) ASM_FUNC(ArmReplaceLiveTranslationEntry)
// disable interrupts // disable interrupts
mrs x2, daif mrs x4, daif
msr daifset, #0xf msr daifset, #0xf
isb isb
// clean and invalidate first so that we don't clobber // clean and invalidate first so that we don't clobber
// adjacent entries that are dirty in the caches // adjacent entries that are dirty in the caches
dc civac, x0 dc civac, x0
dsb ish dsb nsh
EL1_OR_EL2_OR_EL3(x3) EL1_OR_EL2_OR_EL3(x3)
1:__replace_entry 1 1:__replace_entry 1
@ -69,7 +71,7 @@ ASM_FUNC(ArmReplaceLiveTranslationEntry)
b 4f b 4f
3:__replace_entry 3 3:__replace_entry 3
4:msr daif, x2 4:msr daif, x4
ret ret
ASM_GLOBAL ASM_PFX(ArmReplaceLiveTranslationEntrySize) ASM_GLOBAL ASM_PFX(ArmReplaceLiveTranslationEntrySize)