Hi, > I was vaguely tossing an idea around in the back of my mind > about whether you could have a flag on devices that marked > them as "this device is currently involved in IO", such that > you could then just fail the last DMA (or qemu_irq_set, or > whatever) that would complete the loop back to a device that > was already doing IO. But that would need a lot of thinking > through to figure out if it's feasible, and it's probably > a lot of code change.
Quick & dirty hack trying the above. Not much code, it is opt-in per MemoryRegion (so less overhead for devices which already handle all DMA in a BH), tracks state in DeviceState. Adds a check to a rather hot code path though. Not tested yet (stopped investigating when I noticed Philippe tries to fix the same thing with another approach). Not benchmarked. Maybe it helps ... take care, Gerd >From 80e58a2cd2c630f0bddd9d0eaee71abb7eeb9440 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kra...@redhat.com> Date: Tue, 17 Aug 2021 07:35:37 +0200 Subject: [PATCH] allow track active mmio handlers --- include/exec/memory.h | 1 + include/hw/qdev-core.h | 1 + softmmu/memory.c | 24 ++++++++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index c3d417d317f0..b1883d45e817 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -265,6 +265,7 @@ struct MemoryRegionOps { */ bool unaligned; } impl; + bool block_reenter; }; typedef struct MemoryRegionClass { diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index bafc311bfa1b..4cf281a81fa9 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -191,6 +191,7 @@ struct DeviceState { int instance_id_alias; int alias_required_for_version; ResettableState reset; + bool io_handler_active; }; struct DeviceListener { diff --git a/softmmu/memory.c b/softmmu/memory.c index bfedaf9c4dfc..5eb5dd465dd2 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -437,7 +437,18 @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr, { uint64_t tmp; - tmp = mr->ops->read(mr->opaque, addr, size); + if (mr->ops->block_reenter) { + DeviceState *dev = DEVICE(mr->owner); + if (!dev->io_handler_active) { + dev->io_handler_active = true; + tmp = mr->ops->read(mr->opaque, addr, size); + dev->io_handler_active = false; + } else { + tmp = MEMTX_OK; + } + } else { + tmp = mr->ops->read(mr->opaque, addr, size); + } if (mr->subpage) { trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size); } else if (trace_event_get_state_backends(TRACE_MEMORY_REGION_OPS_READ)) { @@ -489,7 +500,16 @@ static MemTxResult memory_region_write_accessor(MemoryRegion *mr, trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size, memory_region_name(mr)); } - mr->ops->write(mr->opaque, addr, tmp, size); + if (mr->ops->block_reenter) { + DeviceState *dev = DEVICE(mr->owner); + if (!dev->io_handler_active) { + dev->io_handler_active = true; + mr->ops->write(mr->opaque, addr, tmp, size); + dev->io_handler_active = false; + } + } else { + mr->ops->write(mr->opaque, addr, tmp, size); + } return MEMTX_OK; } -- 2.31.1