On 01/22/19 16:37, Ard Biesheuvel wrote: > On Tue, 22 Jan 2019 at 16:09, Laszlo Ersek <ler...@redhat.com> wrote: >> >> Performing thread-necromancy on a patch from 2015, which is today known >> as commit b7de7e3cab3f. Also CC'ing Christoffer and Marc. >> >> Question at the bottom. >> >> On 12/07/15 08:06, Ard Biesheuvel wrote: >>> From: "Cohen, Eugene" <eug...@hp.com> >>> >>> This patch updates the ArmPkg variant of InvalidateInstructionCacheRange to >>> flush the data cache only to the point of unification (PoU). This improves >>> performance and also allows invalidation in scenarios where it would be >>> inappropriate to flush to the point of coherency (like when executing code >>> from L2 configured as cache-as-ram). >>> >>> Contributed-under: TianoCore Contribution Agreement 1.0 >>> Signed-off-by: Eugene Cohen <eug...@hp.com> >>> >>> Added AARCH64 and ARM/GCC implementations of the above. >>> >>> Contributed-under: TianoCore Contribution Agreement 1.0 >>> Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org> >>> --- >>> ArmPkg/Include/Library/ArmLib.h | 8 +++++++- >>> ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c | 2 +- >>> ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 6 ++++++ >>> ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S | 6 ++++++ >>> ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm | 5 +++++ >>> 5 files changed, 25 insertions(+), 2 deletions(-) >>> >>> diff --git a/ArmPkg/Include/Library/ArmLib.h >>> b/ArmPkg/Include/Library/ArmLib.h >>> index 9622444ec63f..85fa1f600ba9 100644 >>> --- a/ArmPkg/Include/Library/ArmLib.h >>> +++ b/ArmPkg/Include/Library/ArmLib.h >>> @@ -183,12 +183,18 @@ ArmInvalidateDataCacheEntryByMVA ( >>> >>> VOID >>> EFIAPI >>> -ArmCleanDataCacheEntryByMVA ( >>> +ArmCleanDataCacheEntryToPoUByMVA( >>> IN UINTN Address >>> ); >>> >>> VOID >>> EFIAPI >>> +ArmCleanDataCacheEntryByMVA( >>> +IN UINTN Address >>> +); >>> + >>> +VOID >>> +EFIAPI >>> ArmCleanInvalidateDataCacheEntryByMVA ( >>> IN UINTN Address >>> ); >>> diff --git a/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c >>> b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c >>> index feab4497ac1b..1045f9068f4d 100644 >>> --- a/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c >>> +++ b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c >>> @@ -64,7 +64,7 @@ InvalidateInstructionCacheRange ( >>> IN UINTN Length >>> ) >>> { >>> - CacheRangeOperation (Address, Length, ArmCleanDataCacheEntryByMVA); >>> + CacheRangeOperation (Address, Length, ArmCleanDataCacheEntryToPoUByMVA); >>> ArmInvalidateInstructionCache (); >>> return Address; >>> } >>> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S >>> b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S >>> index c530d19e897e..db21f73f0ed7 100644 >>> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S >>> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S >>> @@ -22,6 +22,7 @@ >>> GCC_ASM_EXPORT (ArmInvalidateInstructionCache) >>> GCC_ASM_EXPORT (ArmInvalidateDataCacheEntryByMVA) >>> GCC_ASM_EXPORT (ArmCleanDataCacheEntryByMVA) >>> +GCC_ASM_EXPORT (ArmCleanDataCacheEntryToPoUByMVA) >>> GCC_ASM_EXPORT (ArmCleanInvalidateDataCacheEntryByMVA) >>> GCC_ASM_EXPORT (ArmInvalidateDataCacheEntryBySetWay) >>> GCC_ASM_EXPORT (ArmCleanDataCacheEntryBySetWay) >>> @@ -72,6 +73,11 @@ ASM_PFX(ArmCleanDataCacheEntryByMVA): >>> ret >>> >>> >>> +ASM_PFX(ArmCleanDataCacheEntryToPoUByMVA): >>> + dc cvau, x0 // Clean single data cache line to PoU >>> + ret >>> + >>> + >>> ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): >>> dc civac, x0 // Clean and invalidate single data cache line >>> ret >>> diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S >>> b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S >>> index 5f030d92de31..7de1b11ef818 100644 >>> --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S >>> +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S >>> @@ -19,6 +19,7 @@ >>> GCC_ASM_EXPORT (ArmInvalidateInstructionCache) >>> GCC_ASM_EXPORT (ArmInvalidateDataCacheEntryByMVA) >>> GCC_ASM_EXPORT (ArmCleanDataCacheEntryByMVA) >>> +GCC_ASM_EXPORT (ArmCleanDataCacheEntryToPoUByMVA) >>> GCC_ASM_EXPORT (ArmCleanInvalidateDataCacheEntryByMVA) >>> GCC_ASM_EXPORT (ArmInvalidateDataCacheEntryBySetWay) >>> GCC_ASM_EXPORT (ArmCleanDataCacheEntryBySetWay) >>> @@ -69,6 +70,11 @@ ASM_PFX(ArmCleanDataCacheEntryByMVA): >>> bx lr >>> >>> >>> +ASM_PFX(ArmCleanDataCacheEntryToPoUByMVA): >>> + mcr p15, 0, r0, c7, c11, 1 @clean single data cache line to PoU >>> + bx lr >>> + >>> + >>> ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): >>> mcr p15, 0, r0, c7, c14, 1 @clean and invalidate single data cache >>> line >>> bx lr >>> diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm >>> b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm >>> index df7e22dca2d9..a460bd2da7a9 100644 >>> --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm >>> +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm >>> @@ -34,6 +34,11 @@ CTRL_I_BIT EQU (1 << 12) >>> bx lr >>> >>> >>> + RVCT_ASM_EXPORT ArmCleanDataCacheEntryToPoUByMVA >>> + mcr p15, 0, r0, c7, c11, 1 ; clean single data cache line to PoU >>> + bx lr >>> + >>> + >>> RVCT_ASM_EXPORT ArmCleanInvalidateDataCacheEntryByMVA >>> mcr p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache >>> line >>> bx lr >>> >> >> The implementation of the LoadImage boot service calls >> InvalidateInstructionCacheRange(): >> >> CoreLoadImage() >> [MdeModulePkg/Core/Dxe/Image/Image.c] >> CoreLoadImageCommon() >> [MdeModulePkg/Core/Dxe/Image/Image.c] >> CoreLoadPeImage() >> [MdeModulePkg/Core/Dxe/Image/Image.c] >> InvalidateInstructionCacheRange() >> [ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c] >> >> Assuming that this code runs in a virtual machine, is any one the >> following scenarios plausible? >> >> (1) the dcache is flushed to PoU on physical socket #M, and the icache >> is invalidated to PoU on physical socket #N, M being unequal to N >> >> (2) the dcache cleaning + icache invalidation happen on the same >> physical socket #M, but the image execution (via StartImage) >> commences on socket #N >> >> In either case, DRAM (PoC) would not form a "bridge" between the >> physical CPUs sitting in said sockets. If the host kernel / KVM >> re-scheduled VCPU#0 from socket #M to socket #N in the "middle" of the >> above scenarios (1) and (2), could that result in StartImage executing >> *not* what LoadImage loaded? >> > > Cache maintenance by virtual address to the PoU is broadcast to the > inner shareable shareability domain. So this should be sufficient to > ensure that the CPU executing the instruction sees the correct data. > > Our code uses full system barriers after each stage of cache > maintenance, so the code looks correct to me. However, it does rely on > the host firmware to configure the inner shareable shareability domain > correctly (and use the correct memory attributes for all memory it > maps)
OK, thank you. >> Because, we got a report >> <https://bugzilla.redhat.com/show_bug.cgi?id=1666280> -- sorry, private >> bug :/ -- in which the *very first* instruction of grub crashes. That >> is, the instruction that forms the entry point of the image. The symptom >> is: >> >>> ESR : EC 0x21 IL 0x1 ISS 0x0000000E >>> >>> Instruction abort: Permission fault, second level >> >> If I'm parsing the ARM ARM correctly: >> >> - "ESR" stands for "Exception Syndrome Register". >> >> - "EC 0x21" stands for Exception Class 0x21, "Instruction Abort taken >> without a change of Exception level. Used for MMU faults generated by >> instruction accesses, and for synchronous external aborts, including >> synchronous parity errors." >> >> - "ISS" stands for "Instruction Specific Syndrome". >> >> - "ISS 0x00E" (24 bit value), given EC 0x21, stands for "Permission >> fault, second level", as the log itself says. >> > > This appears to be a TLB maintenance issue, not a cache maintenance > issue. Level 2 mappings are 2 MB block mappings, and so we usually > have smaller mappings for executables (unless GRUB is much larger than > 2 MB and it covers an entire 2 MB naturally aligned block) > > Does it happen in DEBUG mode? Yes, it does, with full debug logs enabled. > Is SetUefiImageMemoryAttributes() being > called to remap the memory R-X ? No, it is not; the grub binary in question doesn't have the required section alignment (... I hope at least that that's what your question refers to): > ProtectUefiImageCommon - 0x3E6C54C0 > - 0x000000013BEEF000 - 0x0000000000030600 > !!!!!!!! ProtectUefiImageCommon - Section Alignment(0x200) is incorrect !!!!!!!! Thank you, Laszlo _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel