All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: tglx@linutronix.de, mingo@kernel.org, will@kernel.org
Cc: x86@kernel.org, linux-kernel@vger.kernel.org, elver@google.com,
	paulmck@kernel.org, rostedt@goodmis.org, rjw@rjwysocki.net,
	peterz@infradead.org
Subject: [RFC][PATCH 2/3] locking,entry: #PF vs TRACE_IRQFLAGS
Date: Fri, 07 Aug 2020 21:23:38 +0200	[thread overview]
Message-ID: <20200807193018.060388629@infradead.org> (raw)
In-Reply-To: 20200807192336.405068898@infradead.org

Much of the complexity in irqenter_{enter,exit}() is due to #PF being
the sole exception that can schedule from kernel context.

One additional wrinkle with #PF is that it is non-maskable, it can
happen _anywhere_. Due to this, and the wonders of tracing, we can get
the 'normal' NMI nesting vs TRACE_IRQFLAGS:

	local_irq_disable()
	  raw_local_irq_disable();
	  trace_hardirqs_off();

	local_irq_enable();
	  trace_hardirqs_on();
	  <#PF>
	    trace_hardirqs_off()
	    ...
	    if (!regs_irqs_disabled(regs)
	      trace_hardirqs_on();
	  </#PF>
	  // WHOOPS -- lockdep thinks IRQs are disabled again!
	  raw_local_irqs_enable();

Rework irqenter_{enter,exit}() to save/restore the software state.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 include/linux/entry-common.h |    1 
 kernel/entry/common.c        |   52 ++++++++++++++++++++-----------------------
 2 files changed, 26 insertions(+), 27 deletions(-)

--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -310,6 +310,7 @@ void irqentry_exit_to_user_mode(struct p
 #ifndef irqentry_state
 typedef struct irqentry_state {
 	bool	exit_rcu;
+	bool	irqs_enabled;
 } irqentry_state_t;
 #endif
 
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -260,6 +260,7 @@ noinstr irqentry_state_t irqentry_enter(
 {
 	irqentry_state_t ret = {
 		.exit_rcu = false,
+		.irqs_enabled = lockdep_hardirqs_enabled(),
 	};
 
 	if (user_mode(regs)) {
@@ -340,35 +341,32 @@ noinstr void irqentry_exit(struct pt_reg
 	/* Check whether this returns to user mode */
 	if (user_mode(regs)) {
 		irqentry_exit_to_user_mode(regs);
-	} else if (!regs_irqs_disabled(regs)) {
-		/*
-		 * If RCU was not watching on entry this needs to be done
-		 * carefully and needs the same ordering of lockdep/tracing
-		 * and RCU as the return to user mode path.
-		 */
-		if (state.exit_rcu) {
-			instrumentation_begin();
-			/* Tell the tracer that IRET will enable interrupts */
-			trace_hardirqs_on_prepare();
-			lockdep_hardirqs_on_prepare(CALLER_ADDR0);
-			instrumentation_end();
-			rcu_irq_exit();
-			lockdep_hardirqs_on(CALLER_ADDR0);
-			return;
-		}
+		return;
+	}
 
-		instrumentation_begin();
+	instrumentation_begin();
+	/*
+	 * When returning to interrupts enabled, and RCU was watching see if we
+	 * need preemption.
+	 */
+	if (!regs_irqs_disabled(regs) && !state.exit_rcu) {
 		if (IS_ENABLED(CONFIG_PREEMPTION))
 			irqentry_exit_cond_resched();
-		/* Covers both tracing and lockdep */
-		trace_hardirqs_on();
-		instrumentation_end();
-	} else {
-		/*
-		 * IRQ flags state is correct already. Just tell RCU if it
-		 * was not watching on entry.
-		 */
-		if (state.exit_rcu)
-			rcu_irq_exit();
 	}
+
+	/*
+	 * Return the TRACE_IRQFLAGS state to what we found on entry.
+	 * Observe the correct order vs RCU.
+	 */
+	if (state.irqs_enabled) {
+		trace_hardirqs_on_prepare();
+		lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+	}
+	instrumentation_end();
+
+	if (state.exit_rcu)
+		rcu_irq_exit();
+
+	if (state.irqs_enabled)
+		lockdep_hardirqs_on(CALLER_ADDR0);
 }



  parent reply	other threads:[~2020-08-07 19:34 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-07 19:23 [RFC][PATCH 0/3] Tracing, Idle, RCU and such goodness Peter Zijlstra
2020-08-07 19:23 ` [RFC][PATCH 1/3] sched,idle,rcu: Push rcu_idle deeper into the idle path Peter Zijlstra
2020-08-07 19:23 ` Peter Zijlstra [this message]
2020-08-07 20:21   ` [RFC][PATCH 2/3] locking,entry: #PF vs TRACE_IRQFLAGS Steven Rostedt
2020-08-10 11:57     ` peterz
2020-08-10 12:05       ` David Laight
2020-08-10 13:49   ` peterz
2020-08-07 19:23 ` [RFC][PATCH 3/3] lockdep,trace: Expose tracepoints Peter Zijlstra
2020-08-07 20:34   ` Steven Rostedt
2020-08-10 12:26   ` [RFC][PATCH v1.1 " peterz
2020-08-10  9:55 ` [RFC][PATCH 0/3] Tracing, Idle, RCU and such goodness Marco Elver
2020-08-10 12:11   ` peterz
2020-08-11 16:08     ` Paul E. McKenney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200807193018.060388629@infradead.org \
    --to=peterz@infradead.org \
    --cc=elver@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=paulmck@kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.