Repository navigation
Conversation
158cce7 to
9445195
Compare
a2bb5a7 to
32a1ff9
Compare
|
I think there are 2 races, one might already be present: The first would be to make sure that it can't be re-enabled by the current kernel after shutting down. The second (which may already be present) is to make sure hardware ack's the enablement before trying to disable. The SDM manual says: When the OS clears bit 0, hardware sets the IA32_PACKAGE_THERM_STATUS[bit 26] to 1 to acknowledge |
oh yeah that's a good catch... fixed it with a the second one as you noted is already present in the other disable paths. I think we can skip it for now, at least for this patch set. |
HFI is enabled per package by writing the physical address of a table to MSR_IA32_HW_FEEDBACK_PTR and setting the enable bit in MSR_IA32_HW_FEEDBACK_CONFIG. From then on, hardware writes performance and energy efficiency updates to that table on its own. Nothing disables HFI when the kernel shuts down. After a kexec, hardware keeps writing to the old kernel's table, which is now ordinary free memory in the new kernel. The new kernel does not reprogram HFI unless a thermal netlink client subscribes to events, so the writes continue indefinitely. This was observed on dual-socket Sapphire Rapids systems (Xeon Platinum 8462Y+) that boot a Debian 6.1 kernel and kexec into a 7.0 kernel. Both packages kept writing HFI updates (a timestamp, a changed flag and one row per CPU) into the old kernel's table pages. When the inode hash table landed on one of those pages, the new kernel oopsed in find_inode_fast(). Disabling HFI before kexec made the writes stop. Add a syscore shutdown callback that disables HFI on every package with an online CPU. syscore_shutdown() runs on reboot, power off and kexec, after CPU hotplug is disabled and while the other CPUs are still online, so each package can be reached with smp_call_function_single(). Do not enable HFI again once the callback has run. On kexec, user space keeps running on the other CPUs until machine_shutdown() stops them, and kernel_kexec() enables CPU hotplug again after syscore_shutdown(). A new thermal netlink client, or the first CPU of a package coming online, would otherwise enable HFI after it was disabled. Skip packages where HFI is already disabled. hfi_disable() waits up to 2 ms for hardware to set HFI_UPDATED, which a package that is not running HFI may never do. Fixes: ab09b07 ("thermal: intel: hfi: Enable notification interrupt") Cc: stable@vger.kernel.org
Since commit b33f3d2 ("thermal: intel: hfi: Enable HFI only when required"), the kernel only programs HFI when a thermal netlink client subscribes to events. Before that, the first CPU of each package to come online wrote a fresh table address and enabled HFI, which replaced any setup a previous kernel left behind. Now, if the previous kernel left HFI enabled, for example across kexec, nothing touches it. Hardware keeps writing updates into the previous kernel's table, which is free memory in this kernel and can be allocated for anything. On dual-socket Sapphire Rapids systems kexec'ing from a 6.1 kernel into 7.0, these writes corrupted the inode hash table and caused oopses in find_inode_fast(). When the first CPU of a package comes online, check MSR_IA32_HW_FEEDBACK_CONFIG and disable HFI if it is already enabled. If a client subscribes later, HFI is re-enabled with this kernel's table as before. This narrows the window but cannot close it. Hardware may still write to the old table until the package's first CPU reaches the thermal online callback, which runs from a device initcall. On the systems above that was about 30 seconds after this kernel started, 21 of which were spent in acpi_init(). In testing there, hardware wrote the table once right after HFI was enabled and not again over several minutes, idle or with every CPU busy, but the rate under other loads is unknown. The complete fix is for the previous kernel to disable HFI on shutdown, as "thermal: intel: hfi: Disable HFI on shutdown and kexec" does; this covers previous kernels that do not. Also update the kernel-doc of intel_hfi_online(), which still described it as always enabling HFI. Fixes: b33f3d2 ("thermal: intel: hfi: Enable HFI only when required") Cc: stable@vger.kernel.org
|
thanks for all the comments, lots of good catches! I think I've addressed all of them. I also fiddled a bunch with the commit messages and added the cover letter that I plan to use. |
Internal review before these two patches go upstream to linux-pm. This PR never merges: once it's reviewed, the patches go to the mailing list with
b4, and review tags (Reviewed-by,Tested-by) get added to the commits from approvals here.The base branch
hfi-kexec-baseis linux-pm'slinux-nextat 70f331d, which is where the HFI driver changes land.The bug
HFI hardware writes updates to a table at a physical address the kernel programs. Nothing turns HFI off on shutdown. Since b33f3d2, a kernel with no thermal netlink subscribers never touches HFI. So after a kexec, hardware keeps writing into the old kernel's table, which the new kernel treats as free memory. On dual-socket Sapphire Rapids hosts that kexec from a 6.1 kernel into 7.0, the 6.1 kernel's tables ended up under the 7.0 kernel's inode hash table, and the 7.0 kernel crashed.
The patches
machine_shutdown()and CPU hotplug is re-enabled, so a new thermal netlink subscriber or a CPU coming online would otherwise enable it again.Testing
On one of those hosts (Xeon Platinum 8462Y+, HPE Cray XD670), with a kernel built from this branch.
Re-enable after shutdown (forced). A test-only commit made the shutdown callback sleep for 5 s, and a process waiting on
/dev/kmsgfor that point subscribed to thermal netlink events. Each run kexecs into a kernel with patch 2, which reports whether HFI was left enabled.hfi_shutdown_donecheck: the next kernel loggedHFI left enabledfor both packages, andHW_FEEDBACK_PTRhad changed to the old kernel's new table address.HFI left enabledlines, andHW_FEEDBACK_PTRwas unchanged.Kexec loop. Run on patch 1 with the
hfi_shutdown_donecheck, beforehfi_disable_if_enabled()was factored out (which doesn't change behavior). The previous revision, without the check, also passed. 100 kexecs alternating between this kernel and stock 7.0, viakexec_file_load+reboot(LINUX_REBOOT_CMD_KEXEC). Before each kexec, a thermal netlinkeventsubscriber turned HFI on (CONFIG=0x1on both packages). All 100 passed.CONFIG=0x0on both packages. Stock 7.0 has neither patch, so only the shutdown callback can have turned HFI off.intel-hfi: HFI left enabled on package N, disabledfor both packages and readCONFIG=0x0.Before sending upstream
Signed-off-by: Jez Ng. Kernel rules forbid AI tools from adding it, so the commits have none yet.Reviewed-bytag for each person who approves this PR, to the patches they reviewed.Documentation/process/generated-content.rstasks.Cover letter
This is the cover letter b4 will send, verbatim.
🤖 Generated with Claude Code