Skip to content

Report one memory total from sysinfo and meminfo - #300

Merged
jserv merged 1 commit into
sysprog21:mainfrom
xalestar:meminfo-sysinfo-agree
Aug 17, 2026
Merged

Report one memory total from sysinfo and meminfo#300
jserv merged 1 commit into
sysprog21:mainfrom
xalestar:meminfo-sysinfo-agree

Conversation

@xalestar

@xalestar xalestar commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

sysinfo(2) caps totalram at a hardcoded 4094595072 bytes while /proc/meminfo reports sysctl(HW_MEMSIZE), so the two surfaces describe different machines: 3998628 kB against 25165824 kB on a 24 GiB host.

A guest that reads both then subtracts one from the other. busybox free takes total and free from sysinfo and buff/cache from /proc/meminfo and computes used = total - free - cached; a Cached larger than the whole of totalram wraps that subtraction, and free prints the total and a used of 18014398505005547 run together into a single 24-digit field:

              total        used        free      shared  buff/cache   available
Mem:        399862818014398505005547       35065           0     8440000     8660688

To the question in the review: the ceiling is cosmetic. Nothing outside sys.c reads it, no test pins it, and no guest is known to choke on a large MemTotal, so this deletes it rather than keeping the machinery that services it. Both surfaces take the total from sys_guest_ram_bytes(), which is HW_MEMSIZE. That retires the proportional scaling the ceiling required and the 64-bit overflow inside it, and a guest sizing a heap or a job count from MemTotal reads the machine it runs on rather than a sixth of it.

Free is reported once as well, since busybox subtracts sysinfo's freeram rather than MemFree and the two were separate host_statistics64 samples that drift against each other. sys_guest_ram_free() serves both from the snapshot sysinfo reports.

Deleting the cap does not retire the clamp. The Mach counters do not partition: a purgeable page is also counted in inactive, so free plus inactive plus purgeable can exceed physical memory whatever the total is derived from. proc_open_meminfo() clamps Cached against what MemFree leaves, which is the invariant the guest's subtraction actually needs. Cached gives up the precision rather than MemFree, since MemFree has to keep matching freeram.

The test asserts the agreement rather than either number, since the totals are host-dependent, and it runs in test-matrix against a real kernel where the two surfaces come from one si_meminfo() and agree by construction.

With the change in place the reproducer above reports

              total        used        free      shared  buff/cache   available
Mem:       25165824    16527232      282896           0     8355696     8638592

and 25165824 - 282896 - 8355696 = 16527232, which is the used column.

The new assertion fails without the fix rather than passing vacuously. The same test binary run against a build of main gives

sysinfo agrees with /proc/meminfo FAIL: sysinfo and /proc/meminfo disagree

Verified on an Apple Silicon host (Darwin 25.6, 24 GiB), on a branch rebased onto main at 3541d18. make check, make lint and the .ci/ format, newline and security checks all pass. The three test-matrix modes stay within their baselines with zero failures: elfuse-aarch64 252 passed, qemu-aarch64 231 passed, elfuse-x86_64 78 passed. test-sysinfo passes in both the elfuse-aarch64 and qemu-aarch64 columns, so the assertion holds against a real kernel as well.

cubic-dev-ai[bot]

This comment was marked as resolved.

@xalestar
xalestar force-pushed the meminfo-sysinfo-agree branch from 1005633 to 7bef252 Compare August 16, 2026 12:50
@jserv
jserv requested a review from henrybear327 August 16, 2026 13:26
jserv

This comment was marked as resolved.

jserv

This comment was marked as resolved.

sysinfo(2) caps totalram at a hardcoded 4094595072 bytes while
/proc/meminfo reports sysctl(HW_MEMSIZE), so the two surfaces describe
different machines: 3998628 kB against 25165824 kB on a 24 GiB host. A
guest that reads both subtracts one from the other. busybox free takes
total and free from sysinfo and buff/cache from /proc/meminfo and
computes used = total - free - cached; a Cached larger than the whole of
totalram wraps that subtraction, and free prints the total and a used of
18014398500886155 run together into a single 24-digit field:

    Mem:        399862818014398500886155      257465           0 ...

Nothing outside sys.c reads the ceiling and no test pins it, so deleting
it is the shortest route to agreement: both surfaces take the total from
sys_guest_ram_bytes(), which is HW_MEMSIZE. That also retires the
proportional scaling the ceiling required, and a 64-bit overflow inside
it where scaling in bytes multiplied the host figure by the capped total
and left 64 bits once host free memory reached about 4.2 GiB. A guest
sizing a heap or a job count from MemTotal reads the machine it runs on
rather than a sixth of it.

Free has to be reported once as well: busybox subtracts sysinfo's
freeram rather than MemFree, and the two are separate host_statistics64
samples that drift against each other. sys_guest_ram_free() serves both
from the snapshot sysinfo reports.

The Mach counters do not partition. A purgeable page is also counted in
inactive, so free plus inactive plus purgeable can exceed physical
memory whatever the total is, and scaling or not scaling makes no
difference to that. proc_open_meminfo() clamps Cached against what
MemFree leaves, which is the invariant the guest's subtraction needs.
Cached gives up the precision rather than MemFree, since MemFree has to
keep matching freeram.

The test asserts the agreement rather than either number, since the
totals are host-dependent, and it runs in test-matrix against a real
kernel where both come from one si_meminfo() and agree by construction.
@xalestar
xalestar force-pushed the meminfo-sysinfo-agree branch from 7bef252 to e567706 Compare August 17, 2026 07:23
@xalestar

Copy link
Copy Markdown
Contributor Author

The cap is cosmetic, so it is deleted rather than justified. Nothing outside sys.c reads it, no test pins it, and I have no guest that chokes on a large MemTotal -- a 24 GiB host reporting 3998628 kB was the only thing it bought. Both surfaces take the total from sys_guest_ram_bytes(), which is HW_MEMSIZE, and the scaling helper and its overflow go with it.

The clamp stays, because it does not depend on the cap: the Mach counters double-count purgeable pages inside inactive, so free plus inactive plus purgeable can exceed physical memory whatever the total is derived from.

Rebased onto main at 3541d18.

@jserv
jserv merged commit 667a703 into sysprog21:main Aug 17, 2026
14 checks passed
@xalestar
xalestar deleted the meminfo-sysinfo-agree branch August 18, 2026 04:09
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