Switching from the ArmPlatformPkg/NorFlashDxe driver to the
OvmfPkg/VirtNorFlashDxe driver had the side effect that flash address
space got registered as EFI_MEMORY_WC instead of EFI_MEMORY_UC.
That confuses the linux kernel's numa code, seems this makes kernel
consider the flash being node memory. "lsmem" changes from ...
RANGE SIZE STATE REMOVABLE BLOCK
0x0000000040000000-0x000000013fffffff 4G online yes 8-39
... to ...
RANGE SIZE STATE REMOVABLE BLOCK
0x0000000000000000-0x0000000007ffffff 128M online yes 0
0x0000000040000000-0x000000013fffffff 4G online yes 8-39
... and in the kernel log got new error lines:
NUMA: Warning: invalid memblk node 512 [mem 0x0000000004000000-0x0000000007ffffff]
NUMA: Faking a node at [mem 0x0000000004000000-0x000000013fffffff]
Changing the attributes back to EFI_MEMORY_UC fixes this.
Fixes: b92298af82 ("ArmVirtPkg/ArmVirtQemu: migrate to OVMF's VirtNorFlashDxe")
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
NOR flash emulation under KVM involves switching between two modes,
where array mode is backed by a read-only memslot, and programming mode
is fully emulated, i.e., the memory region is not backed by anything,
and the faulting accesses are forwarded to the VMM by the hypervisor,
which translates them into NOR flash programming commands.
Normally, we are limited to the use of device attributes when mapping
such regions, given that the programming mode has MMIO semantics.
However, when running under KVM, the chosen memory attributes only take
effect when in array mode, since no memory mapping exists otherwise.
This means we can tune the memory mapping so it behaves a bit more like
a ROM, by switching to EFI_MEMORY_WC attributes. This means we no longer
need a special CopyMem() implementation that avoids unaligned accesses
at all cost.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
Currently, when dealing with small updates that can be written out
directly (i.e., if they only involve clearing bits and not setting bits,
as the latter requires a block level erase), we iterate over the data
one word at a time, read the old value, compare it, write the new value,
and repeat, unless we encountered a value that we cannot write (0->1
transition), in which case we fall back to a block level operation.
This is inefficient for two reasons:
- reading and writing a word at a time involves switching between array
and programming mode for every word of data, which is
disproportionately costly when running under KVM;
- we end up writing some data twice, as we may not notice that a block
erase is needed until after some data has been written to flash.
So replace this sequence with a single read of up to twice the buffered
write maximum size, followed by one or two buffered writes if the data
can be written directly. Otherwise, fall back to the existing block
level sequence, but without writing out part of the data twice.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
NorFlashWriteSingleWord() switches into programming mode and back into
array mode for every single word that it writes. Under KVM, this
involves tearing down the read-only memslot, and setting it up again,
which is costly and unnecessary.
Instead, move the array mode switch into the callers, and only make the
switch when the writing is done.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
We never boot from NOR flash, and generally rely on the firmware volume
PI protocols to expose the contents. So drop the block I/O protocol
implementation from VirtNorFlashDxe.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
We only use NOR flash for firmware volumes, either for executable images
or for the variable store. So we have no need for exposing disk I/O on
top of the NOR flash partitions so let's remove it.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
We inherited a feature from the ArmPlatformPkg version of this driver
that never gets enabled. Let's remove it.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
QEMU's mach-virt is loosely based on ARM Versatile Express, and inherits
its NOR flash driver, which is now being used on other QEMU emulated
architectures as well.
In order to permit ourselves the freedom to optimize this driver for
use under KVM emulation, let's clone it into OvmfPkg, so we have a
version we can hack without the risk of regressing bare metal platforms.
The cloned version is mostly identical to the original, but it depends
on the newly added VirtNorFlashPlatformLib library class instead of the
original one from ArmPlatformPkg. Beyond that, only cosmetic changes
related to #include order etc were made.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>