linux/arch/x86/mm
Ard Biesheuvel 2c340aab54 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

  d021985504 ("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: d021985504 ("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>
2026-05-05 09:31:28 +02:00
..
pat x86/mm: Revert INVLPGB optimization for set_memory code 2026-04-24 15:42:48 +02:00
amdtopology.c x86/platform/amd: Move the <asm/amd_nb.h> header to <asm/amd/nb.h> 2025-04-14 09:34:14 +02:00
cpu_entry_area.c x86/cpu_entry_area: Annotate percpu_setup_exception_stacks() as __init 2024-08-25 14:29:38 +02:00
debug_pagetables.c x86/bugs: Rename CONFIG_PAGE_TABLE_ISOLATION => CONFIG_MITIGATION_PAGE_TABLE_ISOLATION 2024-01-10 10:52:28 +01:00
dump_pagetables.c x86/mm: Drop unnecessary export of "ptdump_walk_pgd_level_debugfs" 2025-11-12 15:24:42 -08:00
extable.c x86/bug: Handle __WARN_printf() trap in early_fixup_exception() 2026-02-23 11:19:11 +01:00
fault.c x86/efi: Restore IRQ state in EFI page fault handler 2026-05-05 09:31:28 +02:00
hugetlbpage.c mm, arch: consolidate hugetlb CMA reservation 2026-01-26 20:02:19 -08:00
ident_map.c x86/mm/ident_map: Fix theoretical virtual address overflow to zero 2025-03-19 11:12:29 +01:00
init_32.c arch, mm: consolidate initialization of SPARSE memory model 2026-01-26 20:02:18 -08:00
init_64.c arch, mm: consolidate initialization of SPARSE memory model 2026-01-26 20:02:18 -08:00
init.c mm.git review status for linus..mm-stable 2026-02-12 11:32:37 -08:00
iomap_32.c
ioremap.c mm, x86: use for_each_valid_pfn() from __ioremap_check_ram() 2025-05-12 23:50:44 -07:00
kasan_init_64.c kasan: call kasan_init_generic in kasan_init 2025-09-21 14:21:58 -07:00
kaslr.c x86/kaslr: Recognize all ZONE_DEVICE users as physaddr consumers 2026-01-05 18:05:55 -07:00
kmmio.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
kmsan_shadow.c
maccess.c x86/mm: Disallow vsyscall page read for copy_from_kernel_nofault() 2024-02-15 19:21:39 -08:00
Makefile x86/kexec: Disable KCOV instrumentation after load_segments() 2026-03-30 14:15:25 +02:00
mem_encrypt_amd.c x86/sev: Avoid global variable to store virtual address of SVSM area 2025-09-03 17:58:15 +02:00
mem_encrypt_boot.S x86/boot: Create a confined code area for startup code 2025-09-03 18:00:01 +02:00
mem_encrypt.c x86/sev: Add Secure TSC support for SNP guests 2025-01-07 20:27:23 +01:00
mm_internal.h arch, mm: consolidate initialization of nodes, zones and memory map 2026-01-26 20:02:18 -08:00
mmap.c mm: constify arch_pick_mmap_layout() for improved const-correctness 2025-09-21 14:22:14 -07:00
mmio-mod.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
numa.c x86/numa: Store extra copy of numa_nodes_parsed 2026-03-04 16:35:08 +01:00
pf_in.c
pf_in.h
pgprot.c mm: change vm_get_page_prot() to accept vm_flags_t argument 2025-07-09 22:42:13 -07:00
pgtable_32.c
pgtable.c mm: change to return bool for pudp_test_and_clear_young() 2026-04-05 13:53:35 -07:00
physaddr.c x86/mm: Unify __phys_addr_symbol() 2025-10-24 22:13:00 +02:00
physaddr.h
pkeys.c mm/pkeys: remove unused tsk parameter from arch_set_user_pkey_access() 2026-04-05 13:52:57 -07:00
pti.c x86/cpu: Disable FRED when PTI is forced on 2026-04-21 15:11:40 -07:00
srat.c x86/numa: Store extra copy of numa_nodes_parsed 2026-03-04 16:35:08 +01:00
testmmiotrace.c x86/mm: add testmmiotrace MODULE_DESCRIPTION() 2024-09-01 20:43:31 -07:00
tlb.c x86/mm/tlb: Make enter_lazy_tlb() always inline on x86 2026-03-06 06:21:27 +01:00