mbox series

[kvmtool,v4,0/5] Add CFI flash emulation

Message ID 20200423173844.24220-1-andre.przywara@arm.com (mailing list archive)
Headers show
Series Add CFI flash emulation | expand

Message

Andre Przywara April 23, 2020, 5:38 p.m. UTC
Hi,

an update for the CFI flash emulation, addressing Alex' comments and
adding direct mapping support.
The actual code changes to the flash emulation are minimal, mostly this
is about renaming and cleanups.
This versions now adds some patches. 1/5 is a required fix, the last
three patches add mapping support as an extension. See below.

In addition to a branch with this series[1], I also put a git branch with
all the changes compared to v3[2] as separate patches on the server, please
have a look if you want to verify against a previous review.

===============
The EDK II UEFI firmware implementation requires some storage for the EFI
variables, which is typically some flash storage.
Since this is already supported on the EDK II side, and looks like a
generic standard, this series adds a CFI flash emulation to kvmtool.

Patch 2/5 is the actual emulation code, patch 1/5 is a bug-fix for
registering MMIO devices, which is needed for this device.
Patches 3-5 add support for mapping the flash memory into guest, should
it be in read-array mode. For this to work, patch 3/5 is cherry-picked
from Alex' PCIe reassignable BAR series, to support removing a memslot
mapping. Patch 4/5 adds support for read-only mappings, while patch 5/5
adds or removes the mapping based on the current state.
I am happy to squash 5/5 into 2/5, if we agree that patch 3/5 should be
merged either separately or the PCIe series is actually merged before
this one.

This is one missing piece towards a working UEFI boot with kvmtool on
ARM guests, the other is to provide writable PCI BARs, which is WIP.
This series alone already enables UEFI boot, but only with virtio-mmio.

Cheers,
Andre

[1] http://www.linux-arm.org/git?p=kvmtool.git;a=log;h=refs/heads/cfi-flash/v4
[2] http://www.linux-arm.org/git?p=kvmtool.git;a=log;h=refs/heads/cfi-flash/v3
git://linux-arm.org/kvmtool.git (branches cfi-flash/v3 and cfi-flash/v4)

Changelog v3 .. v4:
- Rename file to cfi-flash.c (dash instead of underscore).
- Unify macro names for states, modes and commands.
- Enforce one or two chips only.
- Comment on pow2_size() function.
- Use more consistent identifier spellings.
- Assign symbols to status register values.
- Drop RCR register emulation.
- Use numerical offsets instead of names for query offsets to match spec.
- Cleanup error path and reword info message in create_flash_device_file().
- Add fix to allow non-virtio MMIO device emulations.
- Support tearing down and adding read-only memslots.
- Add read-only memslot mapping when in read mode.

Changelog v2 .. v3:
- Breaking MMIO handling into three separate functions.
- Assing the flash base address in the memory map, but stay at 32 MB for now.
  The MMIO area has been moved up to 48 MB, to never overlap with the
  flash.
- Impose a limit of 16 MB for the flash size, mostly to fit into the
  (for now) fixed memory map.
- Trim flash size down to nearest power-of-2, to match hardware.
- Announce forced flash size trimming.
- Rework the CFI query table slightly, to add the addresses as array
  indicies.
- Fix error handling when creating the flash device.
- Fix pow2_size implementation for 0 and 1 as input values.
- Fix write buffer size handling.
- Improve some comments.

Changelog v1 .. v2:
- Add locking for MMIO handling.
- Fold flash read into handler.
- Move pow2_size() into generic header.
- Spell out flash base address.

Comments

Ard Biesheuvel April 23, 2020, 5:55 p.m. UTC | #1
On Thu, 23 Apr 2020 at 19:39, Andre Przywara <andre.przywara@arm.com> wrote:
>
> Hi,
>
> an update for the CFI flash emulation, addressing Alex' comments and
> adding direct mapping support.
> The actual code changes to the flash emulation are minimal, mostly this
> is about renaming and cleanups.
> This versions now adds some patches. 1/5 is a required fix, the last
> three patches add mapping support as an extension. See below.
>
> In addition to a branch with this series[1], I also put a git branch with
> all the changes compared to v3[2] as separate patches on the server, please
> have a look if you want to verify against a previous review.
>
> ===============
> The EDK II UEFI firmware implementation requires some storage for the EFI
> variables, which is typically some flash storage.
> Since this is already supported on the EDK II side, and looks like a
> generic standard, this series adds a CFI flash emulation to kvmtool.
>
> Patch 2/5 is the actual emulation code, patch 1/5 is a bug-fix for
> registering MMIO devices, which is needed for this device.
> Patches 3-5 add support for mapping the flash memory into guest, should
> it be in read-array mode. For this to work, patch 3/5 is cherry-picked
> from Alex' PCIe reassignable BAR series, to support removing a memslot
> mapping. Patch 4/5 adds support for read-only mappings, while patch 5/5
> adds or removes the mapping based on the current state.
> I am happy to squash 5/5 into 2/5, if we agree that patch 3/5 should be
> merged either separately or the PCIe series is actually merged before
> this one.
>
> This is one missing piece towards a working UEFI boot with kvmtool on
> ARM guests, the other is to provide writable PCI BARs, which is WIP.
> This series alone already enables UEFI boot, but only with virtio-mmio.
>

Excellent! Thanks for taking the time to implement the r/o memslot for
the flash, it really makes the UEFI firmware much more usable.

I will test this as soon as I get a chance, probably tomorrow.


>
> [1] http://www.linux-arm.org/git?p=kvmtool.git;a=log;h=refs/heads/cfi-flash/v4
> [2] http://www.linux-arm.org/git?p=kvmtool.git;a=log;h=refs/heads/cfi-flash/v3
> git://linux-arm.org/kvmtool.git (branches cfi-flash/v3 and cfi-flash/v4)
>
> Changelog v3 .. v4:
> - Rename file to cfi-flash.c (dash instead of underscore).
> - Unify macro names for states, modes and commands.
> - Enforce one or two chips only.
> - Comment on pow2_size() function.
> - Use more consistent identifier spellings.
> - Assign symbols to status register values.
> - Drop RCR register emulation.
> - Use numerical offsets instead of names for query offsets to match spec.
> - Cleanup error path and reword info message in create_flash_device_file().
> - Add fix to allow non-virtio MMIO device emulations.
> - Support tearing down and adding read-only memslots.
> - Add read-only memslot mapping when in read mode.
>
> Changelog v2 .. v3:
> - Breaking MMIO handling into three separate functions.
> - Assing the flash base address in the memory map, but stay at 32 MB for now.
>   The MMIO area has been moved up to 48 MB, to never overlap with the
>   flash.
> - Impose a limit of 16 MB for the flash size, mostly to fit into the
>   (for now) fixed memory map.
> - Trim flash size down to nearest power-of-2, to match hardware.
> - Announce forced flash size trimming.
> - Rework the CFI query table slightly, to add the addresses as array
>   indicies.
> - Fix error handling when creating the flash device.
> - Fix pow2_size implementation for 0 and 1 as input values.
> - Fix write buffer size handling.
> - Improve some comments.
>
> Changelog v1 .. v2:
> - Add locking for MMIO handling.
> - Fold flash read into handler.
> - Move pow2_size() into generic header.
> - Spell out flash base address.
Ard Biesheuvel April 23, 2020, 8:43 p.m. UTC | #2
On Thu, 23 Apr 2020 at 19:55, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Thu, 23 Apr 2020 at 19:39, Andre Przywara <andre.przywara@arm.com> wrote:
> >
> > Hi,
> >
> > an update for the CFI flash emulation, addressing Alex' comments and
> > adding direct mapping support.
> > The actual code changes to the flash emulation are minimal, mostly this
> > is about renaming and cleanups.
> > This versions now adds some patches. 1/5 is a required fix, the last
> > three patches add mapping support as an extension. See below.
> >
> > In addition to a branch with this series[1], I also put a git branch with
> > all the changes compared to v3[2] as separate patches on the server, please
> > have a look if you want to verify against a previous review.
> >
> > ===============
> > The EDK II UEFI firmware implementation requires some storage for the EFI
> > variables, which is typically some flash storage.
> > Since this is already supported on the EDK II side, and looks like a
> > generic standard, this series adds a CFI flash emulation to kvmtool.
> >
> > Patch 2/5 is the actual emulation code, patch 1/5 is a bug-fix for
> > registering MMIO devices, which is needed for this device.
> > Patches 3-5 add support for mapping the flash memory into guest, should
> > it be in read-array mode. For this to work, patch 3/5 is cherry-picked
> > from Alex' PCIe reassignable BAR series, to support removing a memslot
> > mapping. Patch 4/5 adds support for read-only mappings, while patch 5/5
> > adds or removes the mapping based on the current state.
> > I am happy to squash 5/5 into 2/5, if we agree that patch 3/5 should be
> > merged either separately or the PCIe series is actually merged before
> > this one.
> >
> > This is one missing piece towards a working UEFI boot with kvmtool on
> > ARM guests, the other is to provide writable PCI BARs, which is WIP.
> > This series alone already enables UEFI boot, but only with virtio-mmio.
> >
>
> Excellent! Thanks for taking the time to implement the r/o memslot for
> the flash, it really makes the UEFI firmware much more usable.
>
> I will test this as soon as I get a chance, probably tomorrow.
>

I tested this on a SynQuacer box as a host, using EFI firmware [0]
built from patches provided by Sami.

I booted the Debian buster installer, completed the installation, and
could boot into the system. The only glitch was the fact that the
reboot didn't work, but I suppose we are not preserving the memory the
contains the firmware image, so there is nothing to reboot into. But
just restarting kvmtool with the flash image containing the EFI
variables got me straight into GRUB and the installed OS.

Tested-by: Ard Biesheuvel <ardb@kernel.org>

Thanks again for getting this sorted.


[0] https://people.linaro.org/~ard.biesheuvel/KVMTOOL_EFI.fd
Andre Przywara April 23, 2020, 9:31 p.m. UTC | #3
On 23/04/2020 21:43, Ard Biesheuvel wrote:

Hi Ard,

> On Thu, 23 Apr 2020 at 19:55, Ard Biesheuvel <ardb@kernel.org> wrote:
>>
>> On Thu, 23 Apr 2020 at 19:39, Andre Przywara <andre.przywara@arm.com> wrote:
>>>
>>> Hi,
>>>
>>> an update for the CFI flash emulation, addressing Alex' comments and
>>> adding direct mapping support.
>>> The actual code changes to the flash emulation are minimal, mostly this
>>> is about renaming and cleanups.
>>> This versions now adds some patches. 1/5 is a required fix, the last
>>> three patches add mapping support as an extension. See below.
>>>
>>> In addition to a branch with this series[1], I also put a git branch with
>>> all the changes compared to v3[2] as separate patches on the server, please
>>> have a look if you want to verify against a previous review.
>>>
>>> ===============
>>> The EDK II UEFI firmware implementation requires some storage for the EFI
>>> variables, which is typically some flash storage.
>>> Since this is already supported on the EDK II side, and looks like a
>>> generic standard, this series adds a CFI flash emulation to kvmtool.
>>>
>>> Patch 2/5 is the actual emulation code, patch 1/5 is a bug-fix for
>>> registering MMIO devices, which is needed for this device.
>>> Patches 3-5 add support for mapping the flash memory into guest, should
>>> it be in read-array mode. For this to work, patch 3/5 is cherry-picked
>>> from Alex' PCIe reassignable BAR series, to support removing a memslot
>>> mapping. Patch 4/5 adds support for read-only mappings, while patch 5/5
>>> adds or removes the mapping based on the current state.
>>> I am happy to squash 5/5 into 2/5, if we agree that patch 3/5 should be
>>> merged either separately or the PCIe series is actually merged before
>>> this one.
>>>
>>> This is one missing piece towards a working UEFI boot with kvmtool on
>>> ARM guests, the other is to provide writable PCI BARs, which is WIP.
>>> This series alone already enables UEFI boot, but only with virtio-mmio.
>>>
>>
>> Excellent! Thanks for taking the time to implement the r/o memslot for
>> the flash, it really makes the UEFI firmware much more usable.
>>
>> I will test this as soon as I get a chance, probably tomorrow.
>>
> 
> I tested this on a SynQuacer box as a host, using EFI firmware [0]
> built from patches provided by Sami.
> 
> I booted the Debian buster installer, completed the installation, and
> could boot into the system. The only glitch was the fact that the
> reboot didn't work, but I suppose we are not preserving the memory the
> contains the firmware image, so there is nothing to reboot into.

It's even worth, kvmtool does actually not support reset at all:
https://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git/tree/kvm-cpu.c#n220

And yeah, the UEFI firmware is loaded at the beginning of RAM, so most
of it is long gone by then.
kvmtool could reload the image and reset the VCPUs, but every device
emulation would need to be reset, for which there is no code yet.

> But
> just restarting kvmtool with the flash image containing the EFI
> variables got me straight into GRUB and the installed OS.

So, yeah, this is the way to do it ;-)

> Tested-by: Ard Biesheuvel <ardb@kernel.org>

Many thanks for that!

> Thanks again for getting this sorted.

It was actually easier than I thought (see the last patch).

Just curious: the images Sami gave me this morning did not show any
issues anymore (no no-syndrome fault, no alignment issues), even without
the mapping [1]. And even though I saw the 800k read traps, I didn't
notice any real performance difference (on a Juno). The PXE timeout was
definitely much more noticeable.

So did you see any performance impact with this series?

> [0] https://people.linaro.org/~ard.biesheuvel/KVMTOOL_EFI.fd

Ah, nice, will this stay there for a while? I can't provide binaries,
but wanted others to be able to easily test this.

Cheers,
Andre.

[1]
http://www.linux-arm.org/git?p=kvmtool.git;a=commitdiff;h=2f2cf67f9514894d88e9ca799bb9dacd1f7557d4
Ard Biesheuvel April 24, 2020, 6:45 a.m. UTC | #4
On Thu, 23 Apr 2020 at 23:32, André Przywara <andre.przywara@arm.com> wrote:
>
> On 23/04/2020 21:43, Ard Biesheuvel wrote:
>
> Hi Ard,
>
> > On Thu, 23 Apr 2020 at 19:55, Ard Biesheuvel <ardb@kernel.org> wrote:
> >>
> >> On Thu, 23 Apr 2020 at 19:39, Andre Przywara <andre.przywara@arm.com> wrote:
> >>>
> >>> Hi,
> >>>
> >>> an update for the CFI flash emulation, addressing Alex' comments and
> >>> adding direct mapping support.
> >>> The actual code changes to the flash emulation are minimal, mostly this
> >>> is about renaming and cleanups.
> >>> This versions now adds some patches. 1/5 is a required fix, the last
> >>> three patches add mapping support as an extension. See below.
> >>>
> >>> In addition to a branch with this series[1], I also put a git branch with
> >>> all the changes compared to v3[2] as separate patches on the server, please
> >>> have a look if you want to verify against a previous review.
> >>>
> >>> ===============
> >>> The EDK II UEFI firmware implementation requires some storage for the EFI
> >>> variables, which is typically some flash storage.
> >>> Since this is already supported on the EDK II side, and looks like a
> >>> generic standard, this series adds a CFI flash emulation to kvmtool.
> >>>
> >>> Patch 2/5 is the actual emulation code, patch 1/5 is a bug-fix for
> >>> registering MMIO devices, which is needed for this device.
> >>> Patches 3-5 add support for mapping the flash memory into guest, should
> >>> it be in read-array mode. For this to work, patch 3/5 is cherry-picked
> >>> from Alex' PCIe reassignable BAR series, to support removing a memslot
> >>> mapping. Patch 4/5 adds support for read-only mappings, while patch 5/5
> >>> adds or removes the mapping based on the current state.
> >>> I am happy to squash 5/5 into 2/5, if we agree that patch 3/5 should be
> >>> merged either separately or the PCIe series is actually merged before
> >>> this one.
> >>>
> >>> This is one missing piece towards a working UEFI boot with kvmtool on
> >>> ARM guests, the other is to provide writable PCI BARs, which is WIP.
> >>> This series alone already enables UEFI boot, but only with virtio-mmio.
> >>>
> >>
> >> Excellent! Thanks for taking the time to implement the r/o memslot for
> >> the flash, it really makes the UEFI firmware much more usable.
> >>
> >> I will test this as soon as I get a chance, probably tomorrow.
> >>
> >
> > I tested this on a SynQuacer box as a host, using EFI firmware [0]
> > built from patches provided by Sami.
> >
> > I booted the Debian buster installer, completed the installation, and
> > could boot into the system. The only glitch was the fact that the
> > reboot didn't work, but I suppose we are not preserving the memory the
> > contains the firmware image, so there is nothing to reboot into.
>
> It's even worth, kvmtool does actually not support reset at all:
> https://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git/tree/kvm-cpu.c#n220
>
> And yeah, the UEFI firmware is loaded at the beginning of RAM, so most
> of it is long gone by then.
> kvmtool could reload the image and reset the VCPUs, but every device
> emulation would need to be reset, for which there is no code yet.
>

Fair enough. For my use case, it doesn't really matter anyway.

> > But
> > just restarting kvmtool with the flash image containing the EFI
> > variables got me straight into GRUB and the installed OS.
>
> So, yeah, this is the way to do it ;-)
>
> > Tested-by: Ard Biesheuvel <ardb@kernel.org>
>
> Many thanks for that!
>
> > Thanks again for getting this sorted.
>
> It was actually easier than I thought (see the last patch).
>
> Just curious: the images Sami gave me this morning did not show any
> issues anymore (no no-syndrome fault, no alignment issues), even without
> the mapping [1]. And even though I saw the 800k read traps, I didn't
> notice any real performance difference (on a Juno). The PXE timeout was
> definitely much more noticeable.
>
> So did you see any performance impact with this series?
>

You normally don't PXE boot. There is an issue with the iSCSI driver
as well, which causes a boot delay for some reason, so I disabled that
in my build.

I definitely *feels* faster :-) But in any case, exposing the array
mode as a r/o memslot is definitely the right way to deal with this.
Even if Sami did find a workaround that masks the error, it is no
guarantee that all accesses go through that library.


> > [0] https://people.linaro.org/~ard.biesheuvel/KVMTOOL_EFI.fd
>
> Ah, nice, will this stay there for a while? I can't provide binaries,
> but wanted others to be able to easily test this.
>

Sure, I will leave it up until Linaro decides to take down my account.
Will Deacon April 24, 2020, 8:40 a.m. UTC | #5
On Thu, Apr 23, 2020 at 06:38:39PM +0100, Andre Przywara wrote:
> an update for the CFI flash emulation, addressing Alex' comments and
> adding direct mapping support.
> The actual code changes to the flash emulation are minimal, mostly this
> is about renaming and cleanups.
> This versions now adds some patches. 1/5 is a required fix, the last
> three patches add mapping support as an extension. See below.

Cheers, this mostly looks good to me. I've left a couple of minor comments,
and I'll give Alexandru a chance to have another look, but hopefully we can
merge it soon.

Will
Andre Przywara April 24, 2020, 12:08 p.m. UTC | #6
On 24/04/2020 07:45, Ard Biesheuvel wrote:

Hi,

(adding Leif for EDK-2 discussion)

> On Thu, 23 Apr 2020 at 23:32, André Przywara <andre.przywara@arm.com> wrote:
>>
>> On 23/04/2020 21:43, Ard Biesheuvel wrote:

[ ... kvmtool series to add CFI flash emulation allowing EDK-2 to store
variables. Starting with this version (v4) the flash memory region is
presented as a read-only memslot to KVM, to allow direct guest accesses
as opposed to trap-and-emulate even read accesses to the array.]

>>
>>
>> Just curious: the images Sami gave me this morning did not show any
>> issues anymore (no no-syndrome fault, no alignment issues), even without
>> the mapping [1]. And even though I saw the 800k read traps, I didn't
>> notice any real performance difference (on a Juno). The PXE timeout was
>> definitely much more noticeable.
>>
>> So did you see any performance impact with this series?
>>
> 
> You normally don't PXE boot. There is an issue with the iSCSI driver
> as well, which causes a boot delay for some reason, so I disabled that
> in my build.
> 
> I definitely *feels* faster :-) But in any case, exposing the array
> mode as a r/o memslot is definitely the right way to deal with this.
> Even if Sami did find a workaround that masks the error, it is no
> guarantee that all accesses go through that library.

So I was wondering about this, maybe you can confirm or debunk this:
- Any memory given to the compiler (through a pointer) is assumed to be
"normal" memory: the compiler can re-arrange accesses, split them up or
collate them. Also unaligned accesses should be allowed - although I
guess most compilers would avoid them.
- This normally forbids to give a pointer to memory mapped as "device
memory" to the compiler, since this would violate all of the assumptions
above.
- If the device mapped as "device memory" is actually memory (SRAM,
ROM/flash, framebuffer), then most of the assumptions are met, except
the alignment requirement, which is bound to the mapping type, not the
actual device (ARMv8 ARM: Unaligned accesses to device memory always
trap, regardless of SCTLR.A)
- To accommodate the latter, GCC knows the option -malign-strict, to
avoid unaligned accesses. TF-A and U-Boot use this option, to run
without the MMU enabled.

Now if EDK-2 lets the compiler deal with the flash memory region
directly, I think this would still be prone to alignment faults. In fact
an earlier build I got from Sami faulted on exactly that, when I ran it,
even with the r/o memslot mapping in place.

So should EDK-2 add -malign-strict to be safe?
	or
Should EDK-2 add an additional or alternate mapping using a non-device
memory type (with all the mismatched attributes consequences)?
	or
Should EDK-2 only touch the flash region using MMIO accessors, and
forbid the compiler direct access to that region?

So does EDK-2 get away with this because the compiler typically avoids
unaligned accesses?

Cheers,
Andre

>>> [0] https://people.linaro.org/~ard.biesheuvel/KVMTOOL_EFI.fd
>>
>> Ah, nice, will this stay there for a while? I can't provide binaries,
>> but wanted others to be able to easily test this.
>>
> 
> Sure, I will leave it up until Linaro decides to take down my account.
>
Ard Biesheuvel April 24, 2020, 12:25 p.m. UTC | #7
On Fri, 24 Apr 2020 at 14:08, André Przywara <andre.przywara@arm.com> wrote:
>
> On 24/04/2020 07:45, Ard Biesheuvel wrote:
>
> Hi,
>
> (adding Leif for EDK-2 discussion)
>
> > On Thu, 23 Apr 2020 at 23:32, André Przywara <andre.przywara@arm.com> wrote:
> >>
> >> On 23/04/2020 21:43, Ard Biesheuvel wrote:
>
> [ ... kvmtool series to add CFI flash emulation allowing EDK-2 to store
> variables. Starting with this version (v4) the flash memory region is
> presented as a read-only memslot to KVM, to allow direct guest accesses
> as opposed to trap-and-emulate even read accesses to the array.]
>
> >>
> >>
> >> Just curious: the images Sami gave me this morning did not show any
> >> issues anymore (no no-syndrome fault, no alignment issues), even without
> >> the mapping [1]. And even though I saw the 800k read traps, I didn't
> >> notice any real performance difference (on a Juno). The PXE timeout was
> >> definitely much more noticeable.
> >>
> >> So did you see any performance impact with this series?
> >>
> >
> > You normally don't PXE boot. There is an issue with the iSCSI driver
> > as well, which causes a boot delay for some reason, so I disabled that
> > in my build.
> >
> > I definitely *feels* faster :-) But in any case, exposing the array
> > mode as a r/o memslot is definitely the right way to deal with this.
> > Even if Sami did find a workaround that masks the error, it is no
> > guarantee that all accesses go through that library.
>
> So I was wondering about this, maybe you can confirm or debunk this:
> - Any memory given to the compiler (through a pointer) is assumed to be
> "normal" memory: the compiler can re-arrange accesses, split them up or
> collate them. Also unaligned accesses should be allowed - although I
> guess most compilers would avoid them.
> - This normally forbids to give a pointer to memory mapped as "device
> memory" to the compiler, since this would violate all of the assumptions
> above.
> - If the device mapped as "device memory" is actually memory (SRAM,
> ROM/flash, framebuffer), then most of the assumptions are met, except
> the alignment requirement, which is bound to the mapping type, not the
> actual device (ARMv8 ARM: Unaligned accesses to device memory always
> trap, regardless of SCTLR.A)
> - To accommodate the latter, GCC knows the option -malign-strict, to
> avoid unaligned accesses. TF-A and U-Boot use this option, to run
> without the MMU enabled.
>
> Now if EDK-2 lets the compiler deal with the flash memory region
> directly, I think this would still be prone to alignment faults. In fact
> an earlier build I got from Sami faulted on exactly that, when I ran it,
> even with the r/o memslot mapping in place.
>
> So should EDK-2 add -malign-strict to be safe?

It already uses this in various places where it matters.

>         or
> Should EDK-2 add an additional or alternate mapping using a non-device
> memory type (with all the mismatched attributes consequences)?

The memory mapped NOR flash in UEFI is really a special case, since we
need the OS to map it for us at runtime, and we cannot tell it to
switch between normal-NC and device attributes depending on which mode
the firmware is using it in.

Note that this is not any different on bare metal.

>         or
> Should EDK-2 only touch the flash region using MMIO accessors, and
> forbid the compiler direct access to that region?
>

It should only touch those regions using abstractions it defines
itself, and which can be backed in different ways. This is already the
case in EDK2: it has its own CopyMem, ZeroMem, etc string library, and
bans the use the standard C ones. On top of that, it bans struct
assignment, initializers for automatic variables and are things that
result in such calls to be emitted implicitly.

So in practice, this issue is under control, unless you use a version
of those abstractions that willingly uses unaligned accesses (we have
optimized versions based on the cortex-strings library). So my
suspicion is that this may have caused the crash: on bare metal, we
have to switch to the non-optimized string library for the variable
driver for this reason.

The real solution is to fix EDK2, and make the variable stack work
with NOR flash that is non-memory mapped. This is something that has
come up before, and the other day, Sami and I were just discussing
logging this as a wishlist item for the firmware team.


> So does EDK-2 get away with this because the compiler typically avoids
> unaligned accesses?
>

There are certainly some places in the current code base where it is
the compiler that is emitting reads from the NOR flash region, but
there aren't that many. Moving the variable data itself in and out
will typically use the abstractions, since it is moving anonymous
chunks of data. However, there are places where, e.g., fields in the
FS metadata are being read by the code, and there it just casts an
address pointing into the NOR flash region to the appropriate struct
type, and dereferences the fields.
Will Deacon April 24, 2020, 5:03 p.m. UTC | #8
On Fri, Apr 24, 2020 at 09:40:51AM +0100, Will Deacon wrote:
> On Thu, Apr 23, 2020 at 06:38:39PM +0100, Andre Przywara wrote:
> > an update for the CFI flash emulation, addressing Alex' comments and
> > adding direct mapping support.
> > The actual code changes to the flash emulation are minimal, mostly this
> > is about renaming and cleanups.
> > This versions now adds some patches. 1/5 is a required fix, the last
> > three patches add mapping support as an extension. See below.
> 
> Cheers, this mostly looks good to me. I've left a couple of minor comments,
> and I'll give Alexandru a chance to have another look, but hopefully we can
> merge it soon.

Ok, I pushed this out along with the follow-up patch.

Thanks!

Will
Ard Biesheuvel April 25, 2020, 3:16 p.m. UTC | #9
On Fri, 24 Apr 2020 at 19:03, Will Deacon <will@kernel.org> wrote:
>
> On Fri, Apr 24, 2020 at 09:40:51AM +0100, Will Deacon wrote:
> > On Thu, Apr 23, 2020 at 06:38:39PM +0100, Andre Przywara wrote:
> > > an update for the CFI flash emulation, addressing Alex' comments and
> > > adding direct mapping support.
> > > The actual code changes to the flash emulation are minimal, mostly this
> > > is about renaming and cleanups.
> > > This versions now adds some patches. 1/5 is a required fix, the last
> > > three patches add mapping support as an extension. See below.
> >
> > Cheers, this mostly looks good to me. I've left a couple of minor comments,
> > and I'll give Alexandru a chance to have another look, but hopefully we can
> > merge it soon.
>
> Ok, I pushed this out along with the follow-up patch.
>

Cheers for that, this is useful stuff.

For the record, I did a quick benchmark on RPi4 booting Debian in a
VM, and I get the following delays (with GRUB and EFI timeouts both
set to 0)

17:04:58.487065
17:04:58.563700 UEFI firmware (version  built at 22:13:20 on Apr 23 2020)
17:04:58.853653 Welcome to GRUB!
17:04:58.924606 Booting `Debian GNU/Linux'
17:04:58.927835 Loading Linux 5.5.0-2-arm64 ...
17:04:59.063490 Loading initial ramdisk ...
17:05:01.303560 /dev/vda2: recovering journal
17:05:01.408861 /dev/vda2: clean, 37882/500960 files, 457154/2001920 blocks
17:05:09.646023 Debian GNU/Linux bullseye/sid rpi4vm64 ttyS0

So it takes less than 400 ms from starting kvmtool to entering GRUB
when the boot path is set normally. Any other delays you are observing
may be due to the fact that no boot path has been configured yet,
which is why it attempts PXE boot or other things.

Also, note that you can pass the --rng option to kvmtool to get the
EFI_RNG_PROTOCOL to be exposed to the EFI stub, for KASLR and for
seeding the kernel's RNG.