From: Laszlo Ersek <lersek@redhat.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Leif Lindholm <leif.lindholm@linaro.org>,
"Cohen, Eugene" <eugene@hp.com>
Cc: edk2-devel@ml01.01.org, tanxiaojun@huawei.com,
Marc Zyngier <marc.zyngier@arm.com>,
Christoffer Dall <christoffer.dall@arm.com>
Subject: Re: [PATCH] ArmPkg: update InvalidateInstructionCacheRange to flush only to PoU
Date: Tue, 22 Jan 2019 16:09:44 +0100 [thread overview]
Message-ID: <f2c9c8cc-ab0c-f094-f921-aa207a730d1b@redhat.com> (raw)
In-Reply-To: <1449471969-16949-1-git-send-email-ard.biesheuvel@linaro.org>
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" <eugene@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 <eugene@hp.com>
>
> Added AARCH64 and ARM/GCC implementations of the above.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@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?
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.
The crash reproduces intermittently / unpredictably, and it happens on
unspecified hardware. Personally I couldn't reproduce it on my APM
Mustang A3, using the exact same guest ISO.
So, I'm thinking that, as soon as CoreStartImage() calls
Image->EntryPoint(), the instruction fetch blows up, because we didn't
clean the dcache / invalidate the icache *to PoC* in CoreLoadImage(),
and KVM moved VCPU#0 to a different physical socket meanwhile.
Am I totally lost? :)
(I plan to undo commit cf580da1bc4c ("ArmPkg/ArmLib: don't invalidate
entire I-cache on range operation", 2016-05-12) and commit b7de7e3cab3f
("ArmPkg: update InvalidateInstructionCacheRange to flush only to PoU",
2015-12-08), and to ask the reporter to reproduce the issue like that,
but I figured I'd ask first.)
Thanks!
Laszlo
next parent reply other threads:[~2019-01-22 15:09 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1449471969-16949-1-git-send-email-ard.biesheuvel@linaro.org>
2019-01-22 15:09 ` Laszlo Ersek [this message]
2019-01-22 15:33 ` [PATCH] ArmPkg: update InvalidateInstructionCacheRange to flush only to PoU Laszlo Ersek
2019-01-22 15:37 ` Ard Biesheuvel
2019-01-23 9:14 ` Laszlo Ersek
2019-01-23 9:26 ` Ard Biesheuvel
2019-01-23 9:54 ` Laszlo Ersek
2019-01-23 14:02 ` Ard Biesheuvel
2019-01-23 23:04 ` Laszlo Ersek
2019-01-28 10:23 ` Mark Rutland
2019-01-28 10:27 ` Ard Biesheuvel
2019-01-28 10:46 ` Mark Rutland
2019-01-28 11:54 ` Laszlo Ersek
[not found] ` <5C4EFF06.2050600@huawei.com>
2019-01-28 13:46 ` Mark Rutland
[not found] ` <5C4FF71B.1060606@huawei.com>
[not found] ` <5C5036DF.9060905@hisilicon.com>
2019-01-29 13:23 ` Laszlo Ersek
2019-01-28 15:01 ` Laszlo Ersek
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=f2c9c8cc-ab0c-f094-f921-aa207a730d1b@redhat.com \
--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