Skip to content

physical: a sparse, host-mapped decode table over a 40-bit address space - #324

Merged
techomancer merged 1 commit into
mainfrom
physaddrspace
Oct 25, 2026
Merged

techomancer merged 1 commit into
mainfrom
physaddrspace

Conversation

@techomancer

Copy link
Copy Markdown
Owner

Physical found the device behind an address with one indexed load from a 1 MB array of fat pointers covering 32 bits. An Octane decodes 40 bits, which would make that array 256 MB, almost all of it the same few pointers.

The table is now SparseDeviceMap (src/ppmem/devmap.rs), built on ppmem's AddrSpace and SharedMem: a 256 MB reservation, 64 KB table pages (4096 entries, 256 MB of guest space each, one mapping per page so the Windows placeholder backend works unchanged), pages of one device sharing one constant page, mixed pages from a pool. The hot path is still one load.

Changes build the new page through a staging view and swap it in with MAP_FIXED; every table view is read-only. The DMA worker dispatching through the table during a MEMCFG remap sees whole pages, never a torn 16-byte pointer. Entries are compared on both halves, since the zero-sized UnmappedRam shares its address with the next field.

A page nobody filled stays reserved. A load from one is a host fault; a SIGSEGV/SIGBUS handler (Unix, chaining to the previous handler for foreign faults) or a vectored exception handler (Windows) maps the page to the table's default device, prints the guest address, and resumes. The Indy and Indigo2 fill their 32-bit space at init as before, so this path only matters above 4 GB. An Indy's table is four committed pages.

Monitor: phys map shows the table as named runs, page counts and faults. The BusDevice trait still takes u32; widening it is the next step.

Physical found the device behind an address with one indexed load from a
1 MB array of fat pointers covering 32 bits. An Octane decodes 40 bits,
which would make that array 256 MB, almost all of it the same few pointers.

The table is now SparseDeviceMap (src/ppmem/devmap.rs), built on ppmem's
AddrSpace and SharedMem: a 256 MB reservation, 64 KB table pages (4096
entries, 256 MB of guest space each, one mapping per page so the Windows
placeholder backend works unchanged), pages of one device sharing one
constant page, mixed pages from a pool. The hot path is still one load.

Changes build the new page through a staging view and swap it in with
MAP_FIXED; every table view is read-only. The DMA worker dispatching
through the table during a MEMCFG remap sees whole pages, never a torn
16-byte pointer. Entries are compared on both halves, since the zero-sized
UnmappedRam shares its address with the next field.

A page nobody filled stays reserved. A load from one is a host fault; a
SIGSEGV/SIGBUS handler (Unix, chaining to the previous handler for foreign
faults) or a vectored exception handler (Windows) maps the page to the
table's default device, prints the guest address, and resumes. The Indy and
Indigo2 fill their 32-bit space at init as before, so this path only
matters above 4 GB. An Indy's table is four committed pages.

Monitor: `phys map` shows the table as named runs, page counts and faults.
The BusDevice trait still takes u32; widening it is the next step.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@techomancer
techomancer merged commit 81a88ac into main Oct 25, 2026
7 checks passed
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.

1 participant