On Wed, Jul 22, 2026 at 07:24:29PM +0530, Aadeshveer Singh wrote:
> > NOTE: I believe in all paths you touched, you assumed host psize is always
> > >= guest psize. Just to mention it's actually possible to have host psize
> > < guest psize. One case is ARM64 using 4K host psize to emulate 64K guest
> > psize. But that's less of a problem; normally production users rarely use
> > such setup, IIUC, so I think we can put it aside for now (however I believe
> > migration core should work with such setup right now in general). But if
> > you can take that into account it'll be even better.
> >
>
> I agree with the looping over and loading pages into the buffer. That
> would be more efficient and would get rid of the assumption I had that
> zero ranges in hugepages should always be zero. I will look into how
> to generalize this for differences between host and guest page sizes.
> That depends on how mapped-ram handles those cases. I might have to
> look into that.
For host/guest psize, it's actually easier for vanilla mapped-ram, and your
feature is slightly more complex.
It used to be non-issue because mapped-ram only cares about guest psize.
It does not care about the size of host pages, being huge or not.
IOW, mapped-ram sync mode directly manipuates the HVA pointer, ignoring
what is underneath, when requesting IOs from qemu_get_buffer_at() from the
snapshot images. Since VM isn't running, destination QEMU doesn't care
about e.g. prepopulation of a huge page with partially filled data when the
first HVA access happens.
Your work will need to consider this though, because in async faults your
feature will depend on userfaultfd, which is host-page aware, and the VM is
running, so we can't populate some host page partially, we can only
populate it always atomically. This is the same to network-based postcopy.
When I said on normal migration code will work with various guest/host page
setups, I meant more on the iteration logic of when we iterate over RAMs.
For example, on the source / saving side (where your series didn't yet
touch, but you will need to start looking into if you want to enable
multifd + postcopy..), we have a loop structure like this:
ram_save_iterate() (NOTE, for complete(), it's the same)
ram_find_and_save_block()
ram_save_host_page() <-------------- [1]
ram_save_target_page() <-------------- [2]
So someone who read the code first may think that QEMU only supports host
psize >= guest psize, because loop [1] is higher in stack, looping over
smaller guest psizes when they don't match. But in reality what happens
is, in loop [2] when guest psize is even larger than host psize, what will
happen is (take example of host psize 4K, guest psize 64K):
- Loop [1], find a host page (e.g. start at address 1M, which is 4K on
the host), try to migrate the "page" (pointed by pss->page)
- At [2], migrate the whole guest "page" (pointed by pss->page), which is
64K (> 4K) return to loop [1].
- Loop [1], found that after sending the guest page, we've already
covered the host psize range (4K), fallbck to ram_find_and_save_block()
to find another dirty host page
- In ram_find_and_save_block(), it'll find the next dirty (e.g. 1M+64K,
rather than 1M+4K, because ramblock->bmap is guest psize based).
You can take time to reference to above (also comments in
pss_host_page_prepare()).
Thanks,
--
Peter Xu