Hi Manos,
You mentioned you are looking at a Rust implementation of our PFlash
model. IMHO better would be to implement from scratch without looking
at the C code. In case you need to, here are few notes about some
oddities I unfortunately inherited as maintainer.
[*] Interface to write sector to underlying Block Layer is common
W.r.t. accessing underlying Block Layer, AMD/Intel models duplicate
a lot of identical code logic. Except for eventually writing the
current block (which can be cancelled by the guest). For Intel this
was fixed in commit 284a7ee2e29 ("hw/pflash: implement update buffer
for block writes"), for AMD -- which is considered less important
because not used by cloud VMs -- it is still incorrect.
[*] Sector size isn't uniform.
"recent" devices do support more than 1 single block size. Blocks of
different size can't be mixed, they are grouped in "regions". A region
contains blocks of same sector size.
QEMU started only exposing the "num-blocks" and "sector-length"
properties, so we couldn't model regions of different sector size.
At some point the AMD model was extended to use up to 4 groups of
different sizes, via the "num-blocks[0..3]" and "sector-length[0..3]"
properties. This isn't specific to AMD, but we only implemented there.
The "old-multiple-chip-handling" is likely a related kludge for Intel.
Possibly correctly implementing regions might allow to emulate non
power-of-2 virtual parallel NOR flashes, if proven useful to (such
config has been requested for SD cards).
[*] Bus wiring doesn't belong to PFlash models
All the "width", "device-width", "max-device-width", "mappings" and
"big-endian" properties are related to how the DATA and ADDRess lines
are wired on a bus. Models can come with 8bit or 16bit DATA lines, and
there are many possible combinations to wire such devices [1]. Since
PFlash are considered "slow", hardware engineers noticed they could
speed accesses by "interleaving" devices [2], so the following configs
are common:
- 4x 8-bit flashes
- 2x 8-bit flashes (emulated word mode, host endianness matters)
- 2x 16-bit flashes (host endianness matters)
The "mappings" property is related to the ADDRess lines w.r.t. the
host, and is usually described as "aliasing" [3]. I.e. if the host
is configured to see a flash I/O region 2-bit wider than the flash
addressing range, the host will see 2^2 = 4 consecutive times the
same flash I/O region.
Note, it might not be practical (as in, get fast emulation) to use
interleaved memory when the region is executed in place, as these
ROMD devices. Although I believe we could figure something out in
software, reducing the code complexity and simplifying maintenance.
[*] "unlock-addr[0,1]" are not necessary
The unlock sequence is always 0x555 (0b010101010101) then 0xaaa (opposite
0b101010101010) but depending how the address bits are wired and if
the access is byte or word, less address bits will be compared.
[*] "secure" property is a QEMU kludge
PFlashes support region / bank (write) protection, but this wasn't
modelled in QEMU when it was needed. OVMF was developed for virtual
x86 machines and was not interested in doing firmware upgrade, it only
needed a read-only executable storage. Unfortunately instead of using
a plain ROM, it used a PFlash device. "secure" property is enabled to
put a flash in write-protected equivalent, or even fuse-protected,
because the guest could try to unlock banks but will never be able to.
I suppose it is too late to rectify because OVMF uses CFI query to get
the pflash size, although it is fixed.
If re-implementing this today, I'd use the S29GL512T (or S29GL01GT)
datasheet as reference, being the biggest parallel NOR flash produced
(then the industry switched to SPI NOR flashes). It is big enough to
be used by all our boards except the SBSA-Ref (justification in [4]).
[1] "adapt bus wiring in device" in QEMU model is common, for example
we also use it as "regshift" / "endianness" properties when
MMIO-mapping the 8250 UART (TYPE_SERIAL_MM) or IDE (TYPE_MMIO_IDE).
[2] For interleaved I/O regions, see discussion
https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg05395.html
and implementation:
https://lore.kernel.org/qemu-devel/20200817161853.593247-1-f4...@amsat.org/
[3] For MMIO aliasing, see
https://lore.kernel.org/qemu-devel/20210419094329.1402767-2-f4...@amsat.org/
in particular for AMD flash:
https://lore.kernel.org/qemu-devel/20210419094329.1402767-7-f4...@amsat.org/
or q800:
https://lore.kernel.org/qemu-devel/20210326002728.1069834-11-f4...@amsat.org/
[4] CFI-compliant virtual parallel NOR flash on QEMU:
https://lore.kernel.org/qemu-devel/CAFEAcA9qVBdLZMO4e+oSaL6kwpF9WS+RdeL3DxBNKVMPwnQ=t...@mail.gmail.com/
Yes I know, I should respin all of these series...
Hope that helps.
Regards,
Phil.