Skip to content

9p/xen: grant each ring page by its own frame - #72

Merged
kdaula merged 1 commit into
edera/mainlinefrom
kavi/9p-xen-grant-each-page
Nov 3, 2026
Merged

kdaula merged 1 commit into
edera/mainlinefrom
kavi/9p-xen-grant-each-page

Conversation

@kdaula

@kdaula kdaula commented Nov 3, 2026 •

Copy link
Copy Markdown

The frontend currently assumes that a ring's data pages are contiguous in machine memory and calculates each frame by adding the page index to the first page's frame. That assumption doesn't hold for PV guests. alloc_pages_exact() only guarantees pseudo-physical contiguity, so the actual machine frames can be scattered. When that happens, the backend ends up mapping the wrong frames. Sometimes it reads unrelated guest pages and the requests come back as garbage. Other times Xen refuses the grant and the mapping fails with EINVAL.

We haven't seen this consistently because freshly created PV zones usually get machine-contiguous pages within a 2 MiB block. But when a PV zone is restored from a snapshot, memory is allocated one page at a time, so that assumption breaks. The first request on ring 0 ends up with an invalid frame mapping and the mount hangs. This explains the intermittent snapshot import failures in edera-dev/protect#4749. The dumped grant entries also show consecutive frames that Xen refuses to map.

The fix is to look up the actual machine frame for each page instead of assuming they're sequential. I haven't built or tested this locally yet.

The data pages of a ring are granted as the first page's frame plus the
page index. That holds for auto-translated guests, whose grant frames are
pseudo-physical. A PV guest grants machine frames, and alloc_pages_exact()
only promises pseudo-physical contiguity. When the pages are not
machine-contiguous the backend maps the frames that follow the first one.
Some of those are other pages of the guest, so requests read as garbage,
and some cannot be granted at all, so the mapping fails.

A freshly built PV guest is usually machine-contiguous within a 2 MiB
block, which hid this. A PV guest restored from a snapshot gets its frames
one page at a time, so its first request on ring 0 after the restore
arrives as a malformed frame and the mount hangs.

Look up the frame of each page instead.

Signed-off-by: Kavi Daula <kavi@edera.dev>
@kdaula
kdaula marked this pull request as ready for review November 3, 2026 00:51
@kdaula
kdaula merged commit 6990bf0 into edera/mainline Nov 3, 2026
1 check passed
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

Backport to edera/6.18-lts: proposed in #73

Checks and builds passed.

Run log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants