Skip to content

Commit f107505

Browse files
amlutoingomolnar
authored andcommitted
x86/entry/64: Fix irqflag tracing wrt context tracking
Paolo pointed out that enter_from_user_mode could be called while irqflags were traced as though IRQs were on. In principle, this could confuse lockdep. It doesn't cause any problems that I've seen in any configuration, but if I build with CONFIG_DEBUG_LOCKDEP=y, enable a nohz_full CPU, and add code like: if (irqs_disabled()) { spin_lock(&something); spin_unlock(&something); } to the top of enter_from_user_mode, then lockdep will complain without this fix. It seems that lockdep's irqflags sanity checks are too weak to detect this bug without forcing the issue. This patch adds one byte to normal kernels, and it's IMO a bit ugly. I haven't spotted a better way to do this yet, though. The issue is that we can't do TRACE_IRQS_OFF until after SWAPGS (if needed), but we're also supposed to do it before calling C code. An alternative approach would be to call trace_hardirqs_off in enter_from_user_mode. That would be less code and would not bloat normal kernels at all, but it would be harder to see how the code worked. Signed-off-by: Andy Lutomirski <luto@kernel.org> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/86237e362390dfa6fec12de4d75a238acb0ae787.1447361906.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 2d5be37 commit f107505

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

arch/x86/entry/entry_64.S

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,17 @@ END(irq_entries_start)
509509
* tracking that we're in kernel mode.
510510
*/
511511
SWAPGS
512+
513+
/*
514+
* We need to tell lockdep that IRQs are off. We can't do this until
515+
* we fix gsbase, and we should do it before enter_from_user_mode
516+
* (which can take locks). Since TRACE_IRQS_OFF idempotent,
517+
* the simplest way to handle it is to just call it twice if
518+
* we enter from user mode. There's no reason to optimize this since
519+
* TRACE_IRQS_OFF is a no-op if lockdep is off.
520+
*/
521+
TRACE_IRQS_OFF
522+
512523
#ifdef CONFIG_CONTEXT_TRACKING
513524
call enter_from_user_mode
514525
#endif
@@ -1049,12 +1060,18 @@ ENTRY(error_entry)
10491060
SWAPGS
10501061

10511062
.Lerror_entry_from_usermode_after_swapgs:
1063+
/*
1064+
* We need to tell lockdep that IRQs are off. We can't do this until
1065+
* we fix gsbase, and we should do it before enter_from_user_mode
1066+
* (which can take locks).
1067+
*/
1068+
TRACE_IRQS_OFF
10521069
#ifdef CONFIG_CONTEXT_TRACKING
10531070
call enter_from_user_mode
10541071
#endif
1072+
ret
10551073

10561074
.Lerror_entry_done:
1057-
10581075
TRACE_IRQS_OFF
10591076
ret
10601077

0 commit comments

Comments
 (0)