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]>
