Skip to content

feat(libkernel): answer kern.boottime in sysctl and sysctlbyname - #9794

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
Retr0G28:feat/sysctl-kern-boottime
Oct 24, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
Retr0G28:feat/sysctl-kern-boottime

Conversation

@Retr0G28

@Retr0G28 Retr0G28 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What

sysctl threw unsupported MIB 1.21 for kern.boottime ({CTL_KERN, KERN_BOOTTIME}), and sysctlbyname and sysctlnametomib threw for the name. In #9683, Java 25 File I/O (PPSA99866) reads it from HotSpot's os::print_os_info while it writes its hs_err report, and the process aborts at that point instead of writing the report. #9684 fixes the stack-guard error that led to the report in that thread. Any other VM error goes through the same report code, so this is still needed with #9684.

FreeBSD 11.4 declares the node in sys/kern/kern_tc.c as SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD, ...). Its handler, sysctl_kern_boottime, returns a 16-byte struct timeval from getboottime through SYSCTL_OUT. In sys/kern/kern_sysctl.c, sysctl_root returns EPERM for a write to a node without CTLFLAG_WR. sysctl_old_user copies as much as fits and returns ENOMEM when the buffer is short, and userland_sysctl sets the length to what was copied. A size query reports 16. getboottime stays fixed unless the clock is stepped.

sysctl {1, 21}, sysctlbyname("kern.boottime") and sysctlnametomib("kern.boottime") now answer the node. The value is the guest CLOCK_REALTIME minus the guest CLOCK_UPTIME, both read through clock_gettime, so boot time plus uptime matches the current time. It is computed at the first read and then kept. Size queries, short buffers and writes go through the same CopyOut and EPERM paths as the other read-only nodes in the file. A MIB with a component after {1, 21} returns ENOTDIR like the other leaves. A new entry in docs/dev/debt/libkernel.md covers what is left open. A later step of the host clock does not move the value, and the value a PS5 title gets has not been measured.

Test changes in guest_system_configuration:

  • New CheckBootTimeSysctl. A size query reports 16 by MIB and by name. A read gives 0 < tv_sec <= time(nullptr) and 0 <= tv_usec < 1000000, and the value plus clock_gettime(CLOCK_UPTIME) is within one second of clock_gettime(CLOCK_REALTIME). Two reads agree, and the name read agrees with the MIB read. sysctlnametomib gives {1, 21}. An 8-byte buffer gets a length of 8 and ENOMEM with the bytes after it untouched, by MIB and by name, and the MIB read fills it with tv_sec. A write returns EPERM, by MIB and by name.
  • {1, 21} is added to CheckLeafWithTrailingComponent and kern.boottime to CheckNameToMib.

Tested

Windows 11, WinLibs MinGW-w64 GCC 15.2.0 r7, CMake + Ninja, Release, -DBUILD_TESTING=ON, rebased on main 11f976b.

  • Before the fix, guest_system_configuration with the new test fails with terminate called after throwing an instance of 'std::runtime_error', what(): sysctl_nid_postfix: unsupported MIB 1.21 (exit 0xc0000409). With this PR it passes.
  • On this machine the value read was 1792468899.137238. Windows reports LastBootUpTime 1792468899 (Win32_OperatingSystem).
  • Run serially: guest_system_configuration, guest_getrlimit, guest_software_version, guest_thread_sanitizer, guest_hostname, guest_freebsd_clocks, guest_cpu_time_clocks, guest_process_time, guest_process_time_scaled, guest_process_time_counter, guest_process_time_counter_scaled and guest_time_extras. All 12 pass.
  • After the rebase onto 11f976b, with the CLOCK_UPTIME check added after review, guest_system_configuration passes. With the implementation changed to subtract only half the uptime, it fails at that check (exit 0xc0000409).
  • python tools/check_conventions.py --base origin/main reports no errors.
  • Not tested on Linux: no Linux machine here. There, guest CLOCK_UPTIME reads the host CLOCK_MONOTONIC, so the value is the host's boot time moved later by any time spent suspended. That keeps kern.boottime + CLOCK_UPTIME = CLOCK_REALTIME, which is how FreeBSD defines it (tc_setclock sets boottimebin to the real time minus binuptime), and the new check tests that relation on every host.
  • No title or homebrew run.

Overlap: tools/pr_overlap.py reports no shared lines with the PRs it could compare. It could not compare #8553 or #6044, and some PRs that touch only other lines of docs/dev/debt/libkernel.md. None of the open PRs that edit SystemConfiguration.cpp (#8910 unknown names, #9736 kern.proc.env, #8553 MIB mappings) implements kern.boottime. #8910 returns ENOENT for unknown names but still throws for an unknown MIB such as {1, 21}. Textual conflicts are possible:

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: PPSA99866 Java 25 File I/O (PPSA99866) #9683
  • GPUs tested: n/a
  • AI-assisted: yes

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 22, 2026
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 10132 core/libs/prx/libkernel/System/src/SystemConfiguration.cpp L5
docs/dev/debt/libkernel.md L27-28

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 4630 docs/dev/debt/libkernel.md
PR 5021 docs/dev/debt/libkernel.md
PR 6149 docs/dev/debt/libkernel.md
PR 6740 docs/dev/debt/libkernel.md
PR 6830 docs/dev/debt/libkernel.md
PR 6936 docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7090 docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 docs/dev/debt/libkernel.md
PR 7149 docs/dev/debt/libkernel.md
PR 7192 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7511 docs/dev/debt/libkernel.md
PR 8010 docs/dev/debt/libkernel.md
PR 8605 docs/dev/debt/libkernel.md
PR 9156 docs/dev/debt/libkernel.md
PR 9160 docs/dev/debt/libkernel.md
PR 9187 docs/dev/debt/libkernel.md
PR 9199 docs/dev/debt/libkernel.md
PR 9263 docs/dev/debt/libkernel.md
PR 9284 docs/dev/debt/libkernel.md
PR 9293 docs/dev/debt/libkernel.md
PR 9297 docs/dev/debt/libkernel.md
PR 9302 docs/dev/debt/libkernel.md
PR 9509 docs/dev/debt/libkernel.md
PR 9557 docs/dev/debt/libkernel.md
PR 9561 docs/dev/debt/libkernel.md
PR 9566 docs/dev/debt/libkernel.md
PR 9575 docs/dev/debt/libkernel.md
PR 9669 docs/dev/debt/libkernel.md
PR 9693 docs/dev/debt/libkernel.md
PR 9843 docs/dev/debt/libkernel.md
PR 9947 docs/dev/debt/libkernel.md
PR 10179 docs/dev/debt/libkernel.md

@MarcZX10 MarcZX10 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.

The source changes and added MIB/name tests look consistent with the existing sysctl paths. I configured the exact PR head and built guest_system_configuration_tests successfully. The focused CTest could not execute: libkernel stops at its documented host CPU gate because this Xeon E5-1620 v2 lacks LZCNT, BMI1, BMI2, MOVBE and AVX2. The PR reports Windows 11 tests passing, while Linux behavior remains untested; the new value uses Linux CLOCK_MONOTONIC for guest uptime, so please confirm the focused test on a supported Linux host. Hosted checks currently cover eligibility, conventions, intake, labels and report; full product builds were skipped.

The branch is eight commits behind current main (8499ea52e571b0edfc1feecfd3f6b9944012b359). CONTRIBUTING.md requires branches to be based on and kept up to date with main. Please sync it, resolve any conflicts, and provide the Linux focused-test result before merge.

@MarcZX10 MarcZX10 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.

I reviewed the current exact head b95092a431d60c2688335c3b75bfb1f3c8e43b32. Conventions and git diff --check pass, and the merge tree with current main is clean. The new tests cover MIB and name lookup, cached value, size query, short buffers, writes and leaf handling. The reported Windows runs are contributor-reported; hosted product jobs are skipped. The branch remains 21 commits behind current main (11f976b27c16ed91633f00039dba5dfd97dd7cc1), and the PR still reports no Linux test. That matters for this implementation because BootTime() computes realtime minus guest CLOCK_UPTIME, while the existing Linux clock mapping uses CLOCK_MONOTONIC; please rebase and provide the focused Linux test result before merge. I could not rerun the libkernel test locally because this VM’s CPU lacks the required feature set.

FreeBSD 11.4 serves kern.boottime ({CTL_KERN, KERN_BOOTTIME}) from
sysctl_kern_boottime in sys/kern/kern_tc.c as a read-only 16-byte struct
timeval, so a size query reports 16, a short buffer gets a partial copy
and ENOMEM, and a write gets EPERM from sysctl_root. sysctl, sysctlbyname
and sysctlnametomib now answer it with the guest CLOCK_REALTIME minus
CLOCK_UPTIME, taken at the first read and kept. HotSpot reads it while
writing its error report, which aborted with "unsupported MIB 1.21".
@Retr0G28
Retr0G28 force-pushed the feat/sysctl-kern-boottime branch from b95092a to 124dc3b Compare October 22, 2026 17:04
@Retr0G28

Copy link
Copy Markdown
Contributor Author

@MarcZX10 Thanks. Rebased onto main 11f976b (head 124dc3b, no conflicts).

On CLOCK_MONOTONIC: FreeBSD defines the boot time as the real time minus the uptime. tc_setclock in sys/kern/kern_tc.c sets boottimebin to the new real time minus binuptime(), and sysctl_kern_boottime reports that. So the value a guest must see is its own CLOCK_REALTIME minus its own CLOCK_UPTIME, whatever host clock backs them. On Linux, where CLOCK_UPTIME reads CLOCK_MONOTONIC, the result is the host's boot time moved later by any suspended time, and kern.boottime + CLOCK_UPTIME = CLOCK_REALTIME still holds.

To make that checkable on every host, CheckBootTimeSysctl now also requires the value plus clock_gettime(CLOCK_UPTIME) to be within one second of clock_gettime(CLOCK_REALTIME). On Windows it passes, and it fails when the implementation subtracts only half the uptime. I have no Linux machine, so a Linux run of guest_system_configuration is still open; the body says so.

@Dextroid17

Copy link
Copy Markdown
Contributor

Linux run of head 124dc3b3ac, on its own and merged into main at 3e48e2d11b (clean merge; main has also changed SystemConfiguration.cpp and GuestSystemConfiguration.cpp since the branch base).

Setup: CachyOS, kernel 7.3.0-4, GCC 16.2.1, glibc 2.44, CMake 4.4.3, Ninja, -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=OFF.

  • guest_system_configuration. ctest --test-dir build -R '^guest_system_configuration$' -V --no-tests=error --repeat until-fail:3 --timeout 300 passes in each of 3 runs, on both trees. That includes the new CheckBootTimeSysctl check that kern.boottime plus clock_gettime(CLOCK_UPTIME) is within one second of CLOCK_REALTIME, with guest CLOCK_UPTIME backed by host CLOCK_MONOTONIC (Time.cpp, id 5).
  • The new test catches the bug. On the head, I reverse-applied only this PR's change to core/libs/prx/libkernel/System/src/SystemConfiguration.cpp, keeping the new test. guest_system_configuration then aborts with sysctl_nid_postfix: unsupported MIB 1.21. Restoring the change makes it pass again.
  • Full suite on the merge. ctest -j8 after building everything: 1,976 passed, 26 skipped and 3 failed of 2,005. guest_system_configuration passed in that run too. The 3 failures are the agc_driver_sample_order* tests on my RTX 3080 Ti. They fail on plain main 3e48e2d11b too (3 runs on each tree), and on lavapipe, the CI device, they pass or skip on the merge.

No title or console run.

AI-assisted: yes (Claude Code).

@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 24, 2026 10:20

Dismissing a stale review: the requested changes were addressed after it (new head and/or updated description with the asked-for runs) and the merge queue blocks on it. Please request changes again if anything is still open.

@adriadam10
adriadam10 merged commit 6cd36e6 into boykopovar:main Oct 24, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs libkernel unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants