EFI runtime services should use temporary mms, but EFI runtime services want IRQs on. Preemption must still be disabled in a temporary mm context. At some point, the entirely temporary mm mechanism should be moved out of arch code. Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxx> --- arch/x86/mm/tlb.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 4e371f30e2ab..36ce9dffb963 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -708,18 +708,23 @@ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) * that override the kernel memory protections (e.g., W^X), without exposing the * temporary page-table mappings that are required for these write operations to * other CPUs. Using a temporary mm also allows to avoid TLB shootdowns when the - * mapping is torn down. + * mapping is torn down. Temporary mms can also be used for EFI runtime service + * calls or similar functionality. * - * Context: The temporary mm needs to be used exclusively by a single core. To - * harden security IRQs must be disabled while the temporary mm is - * loaded, thereby preventing interrupt handler bugs from overriding - * the kernel memory protection. + * It is illegal to schedule while using a temporary mm -- the context switch + * code is unaware of the temporary mm and does not know how to context switch. + * Use a real (non-temporary) mm in a kernel thread if you need to sleep. + * + * Note: For sensitive memory writes, the temporary mm needs to be used + * exclusively by a single core, and IRQs should be disabled while the + * temporary mm is loaded, thereby preventing interrupt handler bugs from + * overriding the kernel memory protection. */ temp_mm_state_t use_temporary_mm(struct mm_struct *mm) { temp_mm_state_t temp_state; - lockdep_assert_irqs_disabled(); + lockdep_assert_preemption_disabled(); /* * Make sure not to be in TLB lazy mode, as otherwise we'll end up @@ -751,7 +756,7 @@ temp_mm_state_t use_temporary_mm(struct mm_struct *mm) void unuse_temporary_mm(temp_mm_state_t prev_state) { - lockdep_assert_irqs_disabled(); + lockdep_assert_preemption_disabled(); switch_mm_irqs_off(NULL, prev_state.mm, current); /* -- 2.33.1