Memory Runtime Physical Owners - Mainkill1/SpiritBoot GitHub Wiki
Current SpiritBoot physical RAM owners
Matched capture and scope
This is a new merged main d4350b60 / reconstructed tree 1277f2b7... / release64 physical census. The unchanged public allocation/lifetime guest completes all 576 allocations across 18 sizes and 40 thread lifetimes, then xemu pauses. The local diagnostic captured owned SpiritBoot RAM and registers, translated its live page tables, and read its own allocator state with exact current symbols. No Windows or Deck session was altered. The guest completes its checks and enters its terminal wait. The observer then pauses and quits xemu, which exits normally with status zero. This is not a game-performance benchmark.
16,052 available pages and 332 unavailable pages account for all 16,384 pages of 64 MiB. The allocator free flags independently equal MmAvailablePages; every unavailable page has one owner category, with assertions rejecting overlaps and free-page claims. The total unavailable backing is 1,328 KiB. It includes hardware and title allocations and must not be described as pure firmware overhead.
This capture uses the same frozen guest and seeds as the current main allocation qualification. Initial availability is 16,083 pages; final availability is 16,052 after its allocation history. The retained Complex public result is 16,226 at both its corresponding initial and final checkpoints. Therefore the initial availability gap is 572 KiB, and this final gap is 696 KiB. These differ because of the intervening workload. No unseen reference heap/object layout is inferred from those two scalar values.
Disjoint physical ownership
| Owner category | Pages | KiB |
|---|---|---|
| Resident kernel headers and sections | 102 | 408 |
| Page-supply links and pin state | 24 | 96 |
| Pool allocation metadata | 3 | 12 |
| Installed page-directory/page-table backing | 17 | 68 |
| Residual PFN and working-set backing | 2 | 8 |
| Low boot reservations | 6 | 24 |
| NV2A padding | 16 | 64 |
| Pool window, cache included | 86 | 344 |
| Other system-PTE allocations | 37 | 148 |
| Title virtual allocations | 37 | 148 |
| Live contiguous allocations | 2 | 8 |
| Total unavailable | 332 | 1,328 |
Kernel section PFNs confirm the 102-page atlas. INIT and resource content are unmapped here; they are not extra resident owners. The former loader/scratch ranges now contain free or new workload-owned pages, so their old addresses cannot be relabelled as still-reserved boot memory. Six low pages retain boot reservation status; this establishes current ownership, not that each still serves a necessary live function.
The 37 other system-PTE pages equal the current public stack counter, but a VA interval alone does not assign them to individual threads. The two contiguous allocations requested 264 and 572 bytes and each own a whole page; neither request is silently labelled waste. Installed tables include the active page directory and shared/aliased table backing, charged once.
Pool statistics and cache overlap
The actual pool window owns 86 pages / 344 KiB. The public statistics report 70 pool pages plus 16 cache pages. MmQueryStatistics subtracts the public cache count and any pool-backed stack count from the raw pool commitment; this capture has zero pool-backed stack pages. The ordinary file cache is 64 KiB. The two private 16 KiB write-back reserve blocks are included in raw pool ownership but excluded from public cache capacity. They remain within the reported pool remainder, so adding another reserve subtotal to 86 pages would double-count.
Owned source references: ntoskrnl/xb/mm/api.c statistics construction; poolpages.c committed mapping counter; cache.c ordinary/reserve admission and FscGetCacheSize. See Cache-and-Pinning for why recursive write-back reserves exist.
Small pool objects and empty backing
The current production header stores tag, class and allocation magic, but not the original request size. Thus this census can establish exact block capacity, header bytes and free slots; it cannot compute exact internal fragmentation relative to every live request. It reads all 4,096 per-window-page states and checks every bucket block header against the recorded live count. Free-list payload is not mistaken for a live object.
| Block size including 8-byte header | Bucket pages | Entirely empty pages | Live objects | Free slots |
|---|---|---|---|---|
| 32 | 2 | 0 | 147 | 109 |
| 64 | 3 | 1 | 102 | 90 |
| 128 | 3 | 1 | 54 | 42 |
| 256 | 4 | 2 | 31 | 33 |
| 512 | 13 | 4 | 69 | 35 |
| 1024 | 13 | 8 | 18 | 34 |
| 2048 | 20 | 15 | 8 | 32 |
| Total | 58 | 31 | 429 | 375 |
All bucket pages together own 232 KiB. The 429 live objects have 92,792 bytes of usable capacity plus 3,432 bytes of allocation headers. This is usable capacity, not actual bytes requested. Their whole backing contains 141,344 bytes outside live blocks, of which 126,976 bytes / 124 KiB are completely empty pages. Free slots on partially occupied pages cannot be reclaimed without moving live objects.
Twenty pages belong to the 2,048-byte class, and fifteen are empty. Thirty-two simultaneous 1,024-byte requests choose this class after the 8-byte header is added, rather than fitting in the 1,024-byte class. Their allocation burst alone can establish a sixteen-page capacity requirement. This is why finer size classes and burst-aware retention are meaningful investigations, but neither is justified by deleting unobserved code.
The remaining 28 raw pool pages are non-bucket allocations. Their category includes file-cache buffers and other whole-page objects; this ledger does not infer an individual buffer owner without resolving that object. The exact cache reserve contract provides a separate source-supported subtotal, not another physical page charge.
Draft #131 keeps one empty page per class/domain, recovering 100 KiB after the same workload. It also measured substantially slower repeated bursts due to page destruction/recreation. The difference between 124 KiB of measured empty backing and 100 KiB recovered by the draft is retained reserve capacity. Those are different policies/results; the draft is not part of main.
Physical intervals
Intervals are half-open and belong to this one completed guest. RAM aliases and multiple PTE references do not create additional physical pages.
| Owner | Physical intervals (beginβend) | Pages |
|---|---|---|
page_supply_links |
0x382b000β0x383b000 |
16 |
page_supply_pin_state |
0x383b000β0x3843000 |
8 |
pool_metadata |
0x3843000β0x3846000 |
3 |
kernel_headers |
0x3400000β0x3401000 |
1 |
residual_pfn_backing |
0x3820000β0x3821000 |
1 |
working_set_backing |
0x3bfe000β0x3bff000 |
1 |
low_boot_reservations |
0x0β0x1000; 0xd000β0xf000; 0x10000β0x11000; 0x30000β0x31000; 0x3f000β0x40000 |
6 |
nv2a_padding |
0x3ff0000β0x4000000 |
16 |
kernel_.text |
0x3401000β0x3452000 |
81 |
kernel_.data |
0x3452000β0x3453000 |
1 |
kernel_.rdata |
0x3453000β0x345a000 |
7 |
kernel_.bss |
0x345a000β0x3465000 |
11 |
kernel_PAGE |
0x3465000β0x3466000 |
1 |
installed_page_tables |
0xf000β0x10000; 0x3821000β0x382b000; 0x3bd3000β0x3bd6000; 0x3bf9000β0x3bfa000; 0x3bfd000β0x3bfe000; 0x3bff000β0x3c00000 |
17 |
live_contiguous |
0x3ba0000β0x3ba1000; 0x3ba2000β0x3ba3000 |
2 |
pool_window |
0x3466000β0x346d000; 0x380d000β0x381d000; 0x3b8e000β0x3b9d000; 0x3ba1000β0x3ba2000; 0x3ba3000β0x3bab000; 0x3bae000β0x3bc0000; 0x3bd2000β0x3bd3000; 0x3bd6000β0x3bde000; 0x3be4000β0x3be5000; 0x3beb000β0x3bec000; 0x3bf2000β0x3bf9000; 0x3bfa000β0x3bfd000 |
86 |
other_system_pte |
0x346d000β0x347d000; 0x3b9d000β0x3ba0000; 0x3bab000β0x3bae000; 0x3bde000β0x3be4000; 0x3be5000β0x3beb000; 0x3bec000β0x3bef000 |
37 |
title_virtual |
0x3800000β0x380d000; 0x381d000β0x3820000; 0x3bc0000β0x3bd2000; 0x3bef000β0x3bf2000 |
37 |
What this proves and leaves open
- Complete physical category accounting for this exact main release64 checkpoint, with current image page mappings and allocation headers.
- A 124 KiB empty-bucket retention mechanism after the public workload, without assuming that every retained page can be released at no performance cost.
- Cache/public-statistic overlap that explains why scalar statistics are insufficient for a complete owner ledger.
- No function or callback is declared unused from this capture. No true per-thread stack high-water data, game allocation history, or complete reference dynamic-object census is claimed.
The private owned capture stays in the lab. Original numeric owner, size and interval results are published here. Reproducibility artifacts include the exact production manifest, unchanged probe identity, observer, census-owned.py, owned-runtime-census.json, source assertions and page/owner atlas. Evidence is not merged into product main.