Gerd Hoffmann <kra...@redhat.com> 于2021年8月24日周二 下午8:02写道: > > 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 ... >
Gerd's patch just remind my approach here, Just add here: https://mail.gnu.org/archive/html/qemu-devel/2020-09/msg00906.html But I check and record it in the device MR handler. Thanks, Li Qiang > 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 >