membacking: add private anonymous memory backend for guest RAM#2849
Draft
jstarks wants to merge 6 commits intomicrosoft:mainfrom
Draft
membacking: add private anonymous memory backend for guest RAM#2849jstarks wants to merge 6 commits intomicrosoft:mainfrom
jstarks wants to merge 6 commits intomicrosoft:mainfrom
Conversation
Add commit() and decommit() methods to SparseMapping for managing the commit state of pages within an existing VA reservation. On Windows: - decommit() calls VirtualFreeEx with MEM_DECOMMIT to release physical pages while keeping the VA range reserved - commit() calls VirtualAlloc2 with MEM_COMMIT to make pages accessible, working idempotently on already-committed pages On Linux: - decommit() calls madvise(MADV_DONTNEED) to release pages back to the kernel (subsequent reads return zeroes) - commit() is a no-op since the kernel handles page faults transparently for MAP_ANONYMOUS regions These primitives enable a private memory mode where guest RAM uses anonymous virtual memory instead of file-backed shared memory sections.
Add a private_ram flag to VaMapper that enables a mode where the backing SparseMapping uses committed anonymous memory instead of file-backed mappings for guest RAM. In private-RAM mode: - page_fault() on Windows commits 64KB-aligned chunks via SparseMapping::commit() and returns PageFaultAction::Retry, allowing the hypervisor to retry the faulting access - page_fault() on Linux returns PageFaultAction::Fail since the kernel handles faults transparently for MAP_ANONYMOUS regions - alloc_range() eagerly commits a range of pages - decommit() releases pages back (for future balloon/free-page-reporting) Add new_private_mapper() to MappingManagerClient that creates a VaMapper in private-RAM mode, bypassing the mapper cache since private mappers cannot be shared across partitions.
Add a private_memory option to GuestMemoryBuilder that allocates guest RAM from committed anonymous virtual memory instead of a shared memory section. When private_memory is enabled: - No shared memory file/section is created (guest_ram is None) - A private VaMapper is used via new_private_mapper() - RAM ranges are eagerly committed with alloc_range() - File-backed add_mapping() calls are skipped for RAM regions - Memory prefetch is disabled (pages are already committed) Validation rejects private_memory combined with: - Legacy memory layout (x86_legacy_support) which requires shared memory - Pre-existing memory backing (shared_memory_region_base) The guest_ram field is changed to Option<Mappable> to reflect that private memory mode does not produce a shareable backing object.
Add the --private-memory CLI flag to OpenVMM and wire it through the configuration pipeline: - Add private_memory field to MemoryConfig in openvmm_defs - Add --private-memory boolean flag to CLI argument parser - Wire the flag from CLI args to MemoryConfig in openvmm_entry - Pass private_memory to GuestMemoryBuilder in dispatch.rs - Default private_memory to false in ttrpc and petri config construction
Add unit tests covering the new private memory functionality: sparse_mmap (3 tests): - test_decommit_zeros_pages: verify decommit returns pages to zero - test_commit_after_decommit: verify commit restores access after decommit - test_commit_idempotent: verify commit on already-committed pages is safe membacking (4 tests): - test_private_ram_alloc_write_read: basic alloc/write/read cycle - test_private_ram_decommit_zeros: verify decommit zeros private pages - test_private_ram_recommit_after_decommit: verify recommit after decommit - test_private_ram_commit_idempotent: verify double-commit is safe All tests use direct SparseMapping operations to avoid async infrastructure complexity, exercising the actual platform commit/decommit code paths.
|
This PR modifies files containing For more on why we check whole files, instead of just diffs, check out the Rustonomicon |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add a
--private-memorymode that allocates guest RAM using private anonymousmemory (VirtualAlloc on Windows, mmap MAP_ANONYMOUS on Linux) instead of
page-file-backed shared memory sections. This is the foundation for supporting
confidential VM scenarios where guest memory must not be aliased or backed by a
named file mapping.
Motivation
Today, OpenVMM allocates guest RAM as a shared memory section (file mapping)
that gets mapped into the VMM process. This section-backed model makes it
easy to share RAM between processes, but it's fundamentally incompatible with
hardware-enforced private memory (SEV-SNP, TDX, Hyper-V VSM): once a page is
assigned to a guest as private, the host can't map it. For those scenarios we
need a memory model where the VMM manages virtual address ranges directly
using commit/decommit, without a backing file object.
Approach
Layer 1:
sparse_mmap—commit()/decommit()VirtualAlloc2(MEM_COMMIT)/VirtualFreeEx(MEM_DECOMMIT)madvise(MADV_DONTNEED)Layer 2:
VaMapper— private-RAM modeprivate_ramflag onVaMapper; when set,page_fault()commits memoryon demand (Windows) or returns
Failsince Linux auto-faults.alloc_range()eagerly commits a VA range;decommit()releases it.new_private_mapper()onMappingManagerClientcreates a private mapper usingthe existing
MAPPER_CACHEfor correct single-instancing.Layer 3:
GuestMemoryBuilder— conditional allocation.private_memory(true)builder option.alloc_shared_memory()for guest RAM; uses the private mapper instead.alloc_range()during build.add_mapping()for RAM ranges (no file-backed mapping to register).Layer 4: CLI / config wiring
--private-memoryflag incli_args.rs, plumbed throughMemoryConfigtothe builder.
Layer 5: Petri boot test
boot_private_memorytest inmultiarch.rsvalidates end-to-end boot withprivate memory enabled.
Testing
sparse_mmapunit tests + 5membackingunit tests, all passing onboth Linux and Windows (
x86_64-pc-windows-msvccross-compile)--private-memorycargo xtask fmt --fixandcargo doccleanFuture work
decommit()to the balloon driver so deflatedpages release physical memory (Phase 4 from the design).