Re: [PATCH v4 2/3] system/memory: Use qemu_ram_move() for directly accessible regions
Peter Maydell <[email protected]> Tue, 28 Jul 2026 10:01:43 +0100
| Newsgroups | org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CAFEAcA9HbTSj9cJfv8o=jYSuPhScr-RVKWCos4kpUJ+T1S6g5Q@mail.gmail.com> |
On Tue, 28 Jul 2026 at 04:01, Gavin Shan <[email protected]> wrote: > > On 7/27/26 10:51 PM, Peter Maydell wrote: > >> +void qemu_ram_move(void *dst, const void *src, size_t n) > >> +{ > >> + uintptr_t test, len; > >> + > >> + if (src == dst || n == 0) { > > > > I think we should not bother testing for src == dst. It's > > vanishingly unlikely to actually happen, and if it does > > happen then the code will work fine, and it's probably better > > to actually do the access in that case than to skip it. > > > > We can drop the check of (src == dst), but it will introduce inconsistent > behaviors. For example, qemu_ram_move(0x1, 0x1, 0x2) is finally turned to > memmove(0x1, 0x1,0x2) where no memory movement happens in glibc::memmove(), > but qemu_ram_move(0x0, 0x0, 0x2) is turned to qatomic_set((uint16_t *)dst, > qatomic_read((uint16_t *)src)) where we do have memory movement happening. > So I would like to keep the check of (src == dst) in order for the consistent > behaviors. Well, it depends on which kind of consistency you want. If we do the src == dst check, then we have the inconsistency that a small aligned access always happens exactly once, *unless* it happens that src == dst, in which case it doesn't happen even though the caller asked for it. You can see this in the documentation comment I suggested above: if you don't check 'src == dst' then you can document it as "memmove, plus for a small access where src and dst are naturally aligned we guarantee it to happen exactly once atomically". If you do check src == dst then it gets more complicated, because you have to say "memmove, plus for a small access where src and dest are naturally aligned *and* src != dst then ...". I think that because it's the small sized accesses where we know that it might be necessary to really actually do the access, that we should do that also for src == dst. > >> + test = (uintptr_t)src | (uintptr_t)dst | n; > >> + len = test & -test; > > > > What is this doing? I am not a fan of clever bit twiddling > > that isn't commented to explain itself. Readers of the code > > shouldn't have to go off and search for an explanation of what > > is going on. > > > > The following comments will be added for (v5). > > /* > * Maximal length of aligned access that are determined by @src, > * @dst and @n > */ What I mean is more that it ought to say why "x & -x" achieves that goal. -- PMM