Repository navigation
chore(port): port boot performance improvements to 6.18-lts - #28
Merged
Merged
Conversation
xen_init_time_common() points x86_platform.calibrate_tsc at xen_tsc_khz() but leaves calibrate_cpu native, so tsc_early_init() -> determine_cpu_tsc_frequencies() still calls native_calibrate_cpu_early() for cpu_khz. That tries CPUID 0x16, then MSR_PLATFORM_INFO, and then falls through to quick_pit_calibrate() -- which on a PVH guest waits out its full 50ms timeout on a PIT that is not there, prints "Fast TSC calibration failed", and arrives at a value the hypervisor had already been asked for a moment later. It is 48ms of every boot, and it is the largest single item in one: a 512 MiB PVH guest reached "Run /init as init process" at 0.330s, and 0.118s once this and the xenbus boot wait were out of the way. There is nothing for the calibration to find out here. Xen reports the TSC frequency, tsc_khz already comes from it, and cpu_khz differing from tsc_khz under a hypervisor is not information -- determine_cpu_tsc_frequencies() would overwrite cpu_khz with tsc_khz anyway once they disagree by more than 10%. Note that tsc_early_khz= does not help: it only short-circuits calibrate_tsc, and the 50ms is spent in calibrate_cpu. Set in xen_init_time_common() so PV and PVH/HVM guests both get it, which is where calibrate_tsc is already set for the same reason. Signed-off-by: Alex Zenla <alex@edera.dev>
boot_wait_for_devices() sleeps HZ/10 between checks, so on a CONFIG_HZ=100 kernel it waits a tenth of a second to notice something that has already happened. What it is waiting for is not slow: a toolstack has every backend sitting in XenbusStateInitWait before it unpauses the guest, so the wait covers the frontend half of the handshake, which finishes a few milliseconds after the late_initcall starts looking. Measured on a PVH guest, the last frontend connected at 0.232s and init started at 0.311s -- 79ms of sleeping past the event. Frontends move to XenbusStateConnected (and blkfront sets is_ready) from their otherend_changed callback, which runs from the frontend bus's backend_changed() watch. Bump a sequence count and wake a wait queue there, and have wait_for_devices() sleep on it instead of for a fixed interval. The sequence is sampled before each check, so a change that lands between the check and the sleep still wakes the waiter. The HZ/10 interruptible sleep stays as the timeout, so state changes that do not come through the watch are noticed no later than before, and the 30/270-second budgets and their reporting are unchanged. Signed-off-by: Alex Zenla <alex@edera.dev>
kaniini
approved these changes
Oct 15, 2026
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.
This commits were missed during our automated rebase swap-over. They are present on mainline but are not present in 6.18-lts. This ports them manually to 6.18-lts.