hw/block/pflash_cfi01.c | 5 ++++- hw/block/pflash_cfi02.c | 3 +++ system/physmem.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-)
When pflash_cfi01/02 are out of Read Array mode and being reprogrammed
or erased (such as a firmware update) by a guest under TCG, TBs from
when the guest was executing instructions from the pflash are never
invalidated. After re-enabling Read Array, the guest continues to
execute instructions from the stale TBs.
Call memory_region_flush_rom_device() from pflash_update() so the TBs
over the updated range are invalidated.
memory_region_flush_rom_device() asserted that the memory region was in
romd_mode (i.e. Read Array mode), but the pflash is not in romd_mode
when processing MemoryRegionOps->write() commands. Since the RAM can
change even when !romd_mode, relax the assertion so it only checks
rom_device.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4490
Suggested-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Elliot Berman <elliotjb+anduril@elliotjb.com>
---
hw/block/pflash_cfi01.c | 5 ++++-
hw/block/pflash_cfi02.c | 3 +++
system/physmem.c | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 486fc6350d..66ecdb0969 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -388,12 +388,15 @@ static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset,
return ret;
}
-/* update flash content on disk */
+/* update flash content on disk and invalidate the guest view of RAM */
static void pflash_update(PFlashCFI01 *pfl, int offset,
int size)
{
int offset_end;
int ret;
+
+ memory_region_flush_rom_device(&pfl->mem, offset, size);
+
if (pfl->blk) {
offset_end = offset + size;
/* widen to sector boundaries */
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 4f72c438c0..22b27366ee 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -419,6 +419,9 @@ static void pflash_update(PFlashCFI02 *pfl, int offset, int size)
{
int offset_end;
int ret;
+
+ memory_region_flush_rom_device(&pfl->orig_mem, offset, size);
+
if (pfl->blk) {
offset_end = offset + size;
/* widen to sector boundaries */
diff --git a/system/physmem.c b/system/physmem.c
index db3dda563d..c532e29571 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -3162,7 +3162,7 @@ void memory_region_flush_rom_device(MemoryRegion *mr, hwaddr addr, hwaddr size)
* necessary. Other memory regions should use the
* address_space_read/write() APIs.
*/
- assert(memory_region_is_romd(mr));
+ assert(mr->rom_device);
invalidate_and_set_dirty(mr, addr, size);
}
---
base-commit: 7e8d3c7fc460fe7cd28a3e423d7466fa292bc269
change-id: 20261015-pflash-update-invalidate-tbs-7d7e9fa3a3cf
Best regards,
--
Elliot Berman <elliotjb+anduril@elliotjb.com>
© 2016 - 2026 Red Hat, Inc.