Skip to content

loader: keep the page table region off a large page boundary - #4382

Closed
Ben Hillis (benhillis) wants to merge 1 commit into
microsoft:mainfrom
benhillis:main-pt-align-fix
Closed

loader: keep the page table region off a large page boundary#4382
Ben Hillis (benhillis) wants to merge 1 commit into
microsoft:mainfrom
benhillis:main-pt-align-fix

Conversation

@benhillis

@benhillis Ben Hillis (benhillis) commented Sep 3, 2026

Copy link
Copy Markdown
Member

The paravisor loader places the page table region immediately after the relocation region and excludes it from that region, but the boot identity map uses large pages.

A relocating loader only fixes up an identity map leaf entry when the range it maps overlaps the relocation region. When the page table region starts exactly on a large page boundary there is no overlap, so its leaf stays identity mapped at the pre-relocation address. cr3 is relocated and the page table pages are physically moved, so the relocated cr3 has no mapping and the first page table access triple faults VTL2 with no IDT loaded:

triple fault vtl=Vtl2 vp=0x0
  faulting instruction "mov r13,[r12+0FF8h]"
  r12=0x1a4a00000  cr3=0x1a4a00000  cr2=0x80  idtr base=0 limit=ffff

This is latent. The region start is just the running total of everything loaded before it, so unrelated image growth decides whether it lands on the boundary — roughly 1 in 512. main is currently at 0xcb20000 and passes by luck; release/1.8.2607 landed on 0xca00000 and every hyperv_openhcl_* test fails.

Pad by a page so the region always shares a large page with the relocation region. Verified on 1.8: 713/713 tests pass with the region at 0xca01000.

The page table region sits immediately after the relocation region and is
excluded from it, but the boot identity map uses large pages. A relocating
loader only fixes up a leaf entry when the region it maps overlaps the
relocation region, so when the page table region starts exactly on a large
page boundary its leaf stays identity mapped at the pre-relocation address.
The relocated cr3 is then unmapped and the first page table access triple
faults VTL2 with no IDT loaded.

Latent; only trips when unrelated image growth lands the region on the
boundary. Pad by a page so it always shares a large page with the
relocation region.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 3, 2026 20:12
@benhillis
Ben Hillis (benhillis) requested a review from a team as a code owner September 3, 2026 20:12
@benhillis Ben Hillis (benhillis) added the backport_1.8.2607 Change should be backported to the release/1.8.2607 branch label Sep 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new padding is applied unconditionally but is only necessary when relocation is enabled, and changing layout in non-relocation configurations can waste memory or risk NotEnoughMemory in tighter setups.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes a latent relocation failure in the paravisor loader where the page-table region could start exactly on a large-page boundary, causing the identity-map leaf covering the page tables to remain unrelocated and leading to a VTL2 triple fault after cr3 relocation.

Changes:

  • Add a 4KB pad when the end of the relocation region lands exactly on a large-page boundary (x64: 2MB, arm64: 2MB) so the page-table region shares a large page with the relocation region.
  • Apply the same layout fix for both x64 (offset) and arm64 (next_addr) loader paths.
File summaries
File Description
vm/loader/src/paravisor.rs Adds a one-page padding rule to avoid large-page-boundary placement of the page-table region, preventing relocation/identity-map mismatches.
Review details

Suppressed comments (1)

vm/loader/src/paravisor.rs:1256

  • This padding is only relevant when relocation is enabled (it’s meant to ensure the identity-map leaf covering the page-table region overlaps the relocation region). Applying it unconditionally changes the layout and used_end for non-relocation boots and could waste memory. Gate it on with_relocation to keep non-relocation layouts unchanged.
    // Keep the page table region sharing a large page with the relocation
    // region, so the identity map entry covering it is relocated with it.
    if next_addr.is_multiple_of(u64::from(Arm64PageSize::Large)) {
        next_addr += HV_PAGE_SIZE;
    }
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +486 to +491
// Relocating loaders only fix up identity map entries that overlap the
// relocation region, so keep the page table region sharing a large page
// with it. Otherwise the relocated cr3 is unmapped and VTL2 triple faults.
if offset.is_multiple_of(X64_LARGE_PAGE_SIZE) {
offset += HV_PAGE_SIZE;
}
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

@benhillis Ben Hillis (benhillis) removed the backport_1.8.2607 Change should be backported to the release/1.8.2607 branch label Sep 3, 2026
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