linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* entry: Fix the incorrect ordering of lockdep and RCU check
@ 2020-11-04 13:06 Thomas Gleixner
  2020-11-04 16:29 ` Mark Rutland
  2020-11-04 17:10 ` [tip: core/urgent] " tip-bot2 for Thomas Gleixner
  0 siblings, 2 replies; 3+ messages in thread
From: Thomas Gleixner @ 2020-11-04 13:06 UTC (permalink / raw)
  To: LKML; +Cc: Mark Rutland, Peter Zijlstra, Paul E. McKenney, x86

When an exception/interrupt hits kernel space and the kernel is not
currently in the idle task then RCU must be watching.

irqentry_enter() validates this via rcu_irq_enter_check_tick(), which in
turn invokes lockdep when taking a lock. But at that point lockdep does not
yet know about the fact that interrupts have been disabled by the CPU,
which triggers a lockdep splat complaining about inconsistent state.

Invoking trace_hardirqs_off() before rcu_irq_enter_check_tick() defeats the
point of rcu_irq_enter_check_tick() because trace_hardirqs_off() uses RCU.

So use the same sequence as for the idle case and tell lockdep about the
irq state change first, invoke the RCU check and then do the lockdep and
tracer update.

Fixes: a5497bab5f72 ("entry: Provide generic interrupt entry/exit code")
Reported-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
---
 kernel/entry/common.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -337,10 +337,10 @@ noinstr irqentry_state_t irqentry_enter(
 	 * already contains a warning when RCU is not watching, so no point
 	 * in having another one here.
 	 */
+	lockdep_hardirqs_off(CALLER_ADDR0);
 	instrumentation_begin();
 	rcu_irq_enter_check_tick();
-	/* Use the combo lockdep/tracing function */
-	trace_hardirqs_off();
+	trace_hardirqs_off_finish();
 	instrumentation_end();
 
 	return ret;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: entry: Fix the incorrect ordering of lockdep and RCU check
  2020-11-04 13:06 entry: Fix the incorrect ordering of lockdep and RCU check Thomas Gleixner
@ 2020-11-04 16:29 ` Mark Rutland
  2020-11-04 17:10 ` [tip: core/urgent] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Rutland @ 2020-11-04 16:29 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: LKML, Peter Zijlstra, Paul E. McKenney, x86

On Wed, Nov 04, 2020 at 02:06:23PM +0100, Thomas Gleixner wrote:
> When an exception/interrupt hits kernel space and the kernel is not
> currently in the idle task then RCU must be watching.
> 
> irqentry_enter() validates this via rcu_irq_enter_check_tick(), which in
> turn invokes lockdep when taking a lock. But at that point lockdep does not
> yet know about the fact that interrupts have been disabled by the CPU,
> which triggers a lockdep splat complaining about inconsistent state.
> 
> Invoking trace_hardirqs_off() before rcu_irq_enter_check_tick() defeats the
> point of rcu_irq_enter_check_tick() because trace_hardirqs_off() uses RCU.
> 
> So use the same sequence as for the idle case and tell lockdep about the
> irq state change first, invoke the RCU check and then do the lockdep and
> tracer update.
> 
> Fixes: a5497bab5f72 ("entry: Provide generic interrupt entry/exit code")
> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: stable@vger.kernel.org

I just gave this a spin on x86_64 defconfig + PROVE_LOCKING +
DEBUG_LOCKDEP + NO_HZ_FULL + CONTEXT_TRACKING_FORCE, and it gets rid of
the boot-time splat. So FWIW:

Tested-by: Mark Rutland <mark.rutland@arm.com>

Mark.

> ---
>  kernel/entry/common.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> --- a/kernel/entry/common.c
> +++ b/kernel/entry/common.c
> @@ -337,10 +337,10 @@ noinstr irqentry_state_t irqentry_enter(
>  	 * already contains a warning when RCU is not watching, so no point
>  	 * in having another one here.
>  	 */
> +	lockdep_hardirqs_off(CALLER_ADDR0);
>  	instrumentation_begin();
>  	rcu_irq_enter_check_tick();
> -	/* Use the combo lockdep/tracing function */
> -	trace_hardirqs_off();
> +	trace_hardirqs_off_finish();
>  	instrumentation_end();
>  
>  	return ret;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip: core/urgent] entry: Fix the incorrect ordering of lockdep and RCU check
  2020-11-04 13:06 entry: Fix the incorrect ordering of lockdep and RCU check Thomas Gleixner
  2020-11-04 16:29 ` Mark Rutland
@ 2020-11-04 17:10 ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2020-11-04 17:10 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Mark Rutland, Thomas Gleixner, stable, x86, LKML

The following commit has been merged into the core/urgent branch of tip:

Commit-ID:     9d820f68b2bdba5b2e7bf135123c3f57c5051d05
Gitweb:        https://git.kernel.org/tip/9d820f68b2bdba5b2e7bf135123c3f57c5051d05
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 04 Nov 2020 14:06:23 +01:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 04 Nov 2020 18:06:14 +01:00

entry: Fix the incorrect ordering of lockdep and RCU check

When an exception/interrupt hits kernel space and the kernel is not
currently in the idle task then RCU must be watching.

irqentry_enter() validates this via rcu_irq_enter_check_tick(), which in
turn invokes lockdep when taking a lock. But at that point lockdep does not
yet know about the fact that interrupts have been disabled by the CPU,
which triggers a lockdep splat complaining about inconsistent state.

Invoking trace_hardirqs_off() before rcu_irq_enter_check_tick() defeats the
point of rcu_irq_enter_check_tick() because trace_hardirqs_off() uses RCU.

So use the same sequence as for the idle case and tell lockdep about the
irq state change first, invoke the RCU check and then do the lockdep and
tracer update.

Fixes: a5497bab5f72 ("entry: Provide generic interrupt entry/exit code")
Reported-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/87y2jhl19s.fsf@nanos.tec.linutronix.de

---
 kernel/entry/common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index 2b83666..e9e2df3 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -337,10 +337,10 @@ noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
 	 * already contains a warning when RCU is not watching, so no point
 	 * in having another one here.
 	 */
+	lockdep_hardirqs_off(CALLER_ADDR0);
 	instrumentation_begin();
 	rcu_irq_enter_check_tick();
-	/* Use the combo lockdep/tracing function */
-	trace_hardirqs_off();
+	trace_hardirqs_off_finish();
 	instrumentation_end();
 
 	return ret;

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-11-04 17:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-04 13:06 entry: Fix the incorrect ordering of lockdep and RCU check Thomas Gleixner
2020-11-04 16:29 ` Mark Rutland
2020-11-04 17:10 ` [tip: core/urgent] " tip-bot2 for Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).