[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 5/6] memory_ldst: Add atomic ops for PTE updates
From: |
Benjamin Herrenschmidt |
Subject: |
Re: [Qemu-devel] [PATCH 5/6] memory_ldst: Add atomic ops for PTE updates |
Date: |
Mon, 15 Apr 2019 15:12:48 +1000 |
On Mon, 2019-04-15 at 13:38 +1000, David Gibson wrote:
> On Thu, Apr 11, 2019 at 10:00:03AM +0200, Cédric Le Goater wrote:
> > From: Benjamin Herrenschmidt <address@hidden>
> >
> > On some architectures, PTE updates for dirty and changed bits need
> > to be performed atomically. This adds a couple of
> > address_space_cmpxchg*
> > helpers for that purpose.
> >
> > Signed-off-by: Benjamin Herrenschmidt <address@hidden>
> > Signed-off-by: Cédric Le Goater <address@hidden>
>
> Reviewed-by: David Gibson <address@hidden>
>
> But I think this needs to go past Paolo for review as memory
> subsystem maintainer.
This needs to go to rth and Peter. They were talking about a change in
the abstraction to do these more cleanly... that said, it might be
worthwhile merging the fixes first.
Cheers,
Ben.
>
> > ---
> > include/exec/memory_ldst.inc.h | 6 +++
> > memory_ldst.inc.c | 80
> > ++++++++++++++++++++++++++++++++++
> > 2 files changed, 86 insertions(+)
> >
> > diff --git a/include/exec/memory_ldst.inc.h
> > b/include/exec/memory_ldst.inc.h
> > index 272c20f02eae..f3cfa7e9a622 100644
> > --- a/include/exec/memory_ldst.inc.h
> > +++ b/include/exec/memory_ldst.inc.h
> > @@ -28,6 +28,12 @@ extern uint64_t glue(address_space_ldq,
> > SUFFIX)(ARG1_DECL,
> > hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
> > extern void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
> > hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult
> > *result);
> > +extern uint32_t glue(address_space_cmpxchgl_notdirty,
> > SUFFIX)(ARG1_DECL,
> > + hwaddr addr, uint32_t old, uint32_t new, MemTxAttrs attrs,
> > + MemTxResult *result);
> > +extern uint32_t glue(address_space_cmpxchgq_notdirty,
> > SUFFIX)(ARG1_DECL,
> > + hwaddr addr, uint64_t old, uint64_t new, MemTxAttrs attrs,
> > + MemTxResult *result);
> > extern void glue(address_space_stw, SUFFIX)(ARG1_DECL,
> > hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult
> > *result);
> > extern void glue(address_space_stl, SUFFIX)(ARG1_DECL,
> > diff --git a/memory_ldst.inc.c b/memory_ldst.inc.c
> > index acf865b900d7..1d58d2fea67d 100644
> > --- a/memory_ldst.inc.c
> > +++ b/memory_ldst.inc.c
> > @@ -320,6 +320,86 @@ void glue(address_space_stl_notdirty,
> > SUFFIX)(ARG1_DECL,
> > RCU_READ_UNLOCK();
> > }
> >
> > +/* This is meant to be used for atomic PTE updates under MT-TCG */
> > +uint32_t glue(address_space_cmpxchgl_notdirty, SUFFIX)(ARG1_DECL,
> > + hwaddr addr, uint32_t old, uint32_t new, MemTxAttrs attrs,
> > + MemTxResult *result)
> > +{
> > + uint8_t *ptr;
> > + MemoryRegion *mr;
> > + hwaddr l = 4;
> > + hwaddr addr1;
> > + MemTxResult r;
> > + uint8_t dirty_log_mask;
> > +
> > + /* Must test result */
> > + assert(result);
> > +
> > + RCU_READ_LOCK();
> > + mr = TRANSLATE(addr, &addr1, &l, true, attrs);
> > + if (l < 4 || !memory_access_is_direct(mr, true)) {
> > + r = MEMTX_ERROR;
> > + } else {
> > + uint32_t orig = old;
> > +
> > + ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> > + old = atomic_cmpxchg(ptr, orig, new);
> > +
> > + if (old == orig) {
> > + dirty_log_mask = memory_region_get_dirty_log_mask(mr);
> > + dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
> > + cpu_physical_memory_set_dirty_range(memory_region_get_
> > ram_addr(mr) +
> > + addr, 4,
> > dirty_log_mask);
> > + }
> > + r = MEMTX_OK;
> > + }
> > + *result = r;
> > + RCU_READ_UNLOCK();
> > +
> > + return old;
> > +}
> > +
> > +#ifdef CONFIG_ATOMIC64
> > +/* This is meant to be used for atomic PTE updates under MT-TCG */
> > +uint32_t glue(address_space_cmpxchgq_notdirty, SUFFIX)(ARG1_DECL,
> > + hwaddr addr, uint64_t old, uint64_t new, MemTxAttrs attrs,
> > + MemTxResult *result)
> > +{
> > + uint8_t *ptr;
> > + MemoryRegion *mr;
> > + hwaddr l = 8;
> > + hwaddr addr1;
> > + MemTxResult r;
> > + uint8_t dirty_log_mask;
> > +
> > + /* Must test result */
> > + assert(result);
> > +
> > + RCU_READ_LOCK();
> > + mr = TRANSLATE(addr, &addr1, &l, true, attrs);
> > + if (l < 8 || !memory_access_is_direct(mr, true)) {
> > + r = MEMTX_ERROR;
> > + } else {
> > + uint32_t orig = old;
> > +
> > + ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> > + old = atomic_cmpxchg(ptr, orig, new);
> > +
> > + if (old == orig) {
> > + dirty_log_mask = memory_region_get_dirty_log_mask(mr);
> > + dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
> > + cpu_physical_memory_set_dirty_range(memory_region_get_
> > ram_addr(mr) +
> > + addr, 8,
> > dirty_log_mask);
> > + }
> > + r = MEMTX_OK;
> > + }
> > + *result = r;
> > + RCU_READ_UNLOCK();
> > +
> > + return old;
> > +}
> > +#endif /* CONFIG_ATOMIC64 */
> > +
> > /* warning: addr must be aligned */
> > static inline void glue(address_space_stl_internal,
> > SUFFIX)(ARG1_DECL,
> > hwaddr addr, uint32_t val, MemTxAttrs attrs,
>
>
- [Qemu-devel] [PATCH 2/6] ppc/spapr: Use proper HPTE accessors for H_READ, (continued)
- [Qemu-devel] [PATCH 2/6] ppc/spapr: Use proper HPTE accessors for H_READ, Cédric Le Goater, 2019/04/11
- [Qemu-devel] [PATCH 1/6] target/ppc: Don't check UPRT in radix mode when in HV real mode, Cédric Le Goater, 2019/04/11
- [Qemu-devel] [PATCH 3/6] ppc/hash64: Rework R and C bit updates, Cédric Le Goater, 2019/04/11
- [Qemu-devel] [PATCH 4/6] ppc/hash32: Rework R and C bit updates, Cédric Le Goater, 2019/04/11
- [Qemu-devel] [PATCH 5/6] memory_ldst: Add atomic ops for PTE updates, Cédric Le Goater, 2019/04/11
- [Qemu-devel] [PATCH 6/6] ppc: Fix radix RC updates, Cédric Le Goater, 2019/04/11