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 <[email protected]>
Signed-off-by: Elliot Berman <[email protected]>
---
 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 <[email protected]>


Reply via email to