diff options
| author | Ard Biesheuvel <ardb@kernel.org> | 2026-05-01 09:16:38 +0200 |
|---|---|---|
| committer | Ard Biesheuvel <ardb@kernel.org> | 2026-05-05 09:31:28 +0200 |
| commit | 2c340aab5485ebe9e33c01437dd4815ef33c8df5 (patch) | |
| tree | b1535735d73b6dac44fc29fc386cc4be9cf2bfaf /net | |
| parent | 088f65e206087bf903743bd18417261d7a4c9644 (diff) | |
x86/efi: Restore IRQ state in EFI page fault handler
The kernel's softirq API does not permit re-enabling softirqs while IRQs
are disabled. The reason for this is that local_bh_enable() will not
only re-enable delivery of softirqs over the back of IRQs, it will also
handle any pending softirqs immediately, regardless of whether IRQs are
enabled at that point.
For this reason, commit
d02198550423 ("x86/fpu: Improve crypto performance by making kernel-mode FPU reliably usable in softirqs")
disables softirqs only when IRQs are enabled, as it is not permitted
otherwise, but also unnecessary, given that asynchronous softirq
delivery never happens to begin with while IRQs are disabled.
However, this does mean that entering a kernel mode FPU section with
IRQs enabled and leaving it with IRQs disabled leads to problems, as
identified by Sashiko [0]: the EFI page fault handler is called from
page_fault_oops() with IRQs disabled, and thus ends the kernel mode FPU
section with IRQs disabled as well, regardless of whether IRQs were
enabled when it was started. This may result in schedule() being called
with a non-zero preempt_count, causing a BUG().
So take care to re-enable IRQs when handling any EFI page faults if they
were taken with IRQs enabled.
[0] https://sashiko.dev/#/patchset/20260430074107.27051-1-ivan.hu%40canonical.com
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Ivan Hu <ivan.hu@canonical.com>
Cc: x86@kernel.org
Cc: <stable@vger.kernel.org>
Fixes: d02198550423 ("x86/fpu: Improve crypto performance by making kernel-mode FPU reliably usable in softirqs")
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'net')
0 files changed, 0 insertions, 0 deletions
