public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>,
	"Cohen, Eugene" <eugene@hp.com>,
	"edk2-devel@lists.01.org" <edk2-devel@ml01.01.org>,
	Tanxiaojun <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: Wed, 23 Jan 2019 10:14:25 +0100	[thread overview]
Message-ID: <2dd4294c-76f0-f433-cbd2-bf0b37114aee@redhat.com> (raw)
In-Reply-To: <CAKv+Gu_sXc9JkY0NAUtRj=kfi-=7WBXz6=Rhm13Apr9GJsRG8w@mail.gmail.com>

On 01/22/19 16:37, Ard Biesheuvel wrote:
> On Tue, 22 Jan 2019 at 16:09, Laszlo Ersek <lersek@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" <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?
>>
> 
> 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


  reply	other threads:[~2019-01-23  9:14 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 ` [PATCH] ArmPkg: update InvalidateInstructionCacheRange to flush only to PoU Laszlo Ersek
2019-01-22 15:33   ` Laszlo Ersek
2019-01-22 15:37   ` Ard Biesheuvel
2019-01-23  9:14     ` Laszlo Ersek [this message]
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=2dd4294c-76f0-f433-cbd2-bf0b37114aee@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