All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	X86 ML <x86@kernel.org>, "Paul E. McKenney" <paulmck@kernel.org>,
	Alexandre Chartre <alexandre.chartre@oracle.com>,
	Frederic Weisbecker <frederic@kernel.org>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Sean Christopherson <sean.j.christopherson@intel.com>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Petr Mladek <pmladek@suse.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Joel Fernandes <joel@joelfernandes.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Juergen Gross <jgross@suse.com>, Brian Gerst <brgerst@gmail.com>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Will Deacon <will@kernel.org>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Wei Liu <wei.liu@kernel.org>,
	Michael Kelley <mikelley@microsoft.com>,
	Jason Chen CJ <jason.cj.chen@intel.com>,
	Zhao Yakui <yakui.zhao@intel.com>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>
Subject: [patch V9 04/39] x86/entry: Provide idtentry_entry/exit_cond_rcu()
Date: Thu, 21 May 2020 22:05:17 +0200	[thread overview]
Message-ID: <20200521202117.181397835@linutronix.de> (raw)
In-Reply-To: 20200521200513.656533920@linutronix.de

From: Thomas Gleixner <tglx@linutronix.de>

After a lengthy discussion [1] it turned out that RCU does not need a full
rcu_irq_enter/exit() when RCU is already watching. All it needs if
NOHZ_FULL is active is to check whether the tick needs to be restarted.

This allows to avoid a separate variant for the pagefault handler which
cannot invoke rcu_irq_enter() on a kernel pagefault which might sleep.

The cond_rcu argument is only temporary and will be removed once the
existing users of idtentry_enter/exit() have been cleaned up. After that
the code can be significantly simplified.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: [1] https://lkml.kernel.org/r/20200515235125.628629605@linutronix.de
---
V9: Reworked to the new RCU mode
---
 arch/x86/entry/common.c         |   84 ++++++++++++++++++++++++++++++----------
 arch/x86/include/asm/idtentry.h |   14 +++++-
 2 files changed, 77 insertions(+), 21 deletions(-)

--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -512,8 +512,10 @@ SYSCALL_DEFINE0(ni_syscall)
 }
 
 /**
- * idtentry_enter - Handle state tracking on idtentry
+ * idtentry_enter_cond_rcu - Handle state tracking on idtentry with conditional
+ *			     RCU handling
  * @regs:	Pointer to pt_regs of interrupted context
+ * @cond_rcu:	Invoke rcu_irq_enter() only if RCU is not watching
  *
  * Invokes:
  *  - lockdep irqflag state tracking as low level ASM entry disabled
@@ -521,40 +523,81 @@ SYSCALL_DEFINE0(ni_syscall)
  *
  *  - Context tracking if the exception hit user mode.
  *
- *  - RCU notification if the exception hit kernel mode.
- *
  *  - The hardirq tracer to keep the state consistent as low level ASM
  *    entry disabled interrupts.
+ *
+ * For kernel mode entries RCU handling is done conditional. If RCU is
+ * watching then the only RCU requirement is to check whether the tick has
+ * to be restarted. If RCU is not watching then rcu_irq_enter() has to be
+ * invoked on entry and rcu_irq_exit() on exit.
+ *
+ * Avoiding the rcu_irq_enter/exit() calls is an optimization but also
+ * solves the problem of kernel mode pagefaults which can schedule, which
+ * is not possible after invoking rcu_irq_enter() without undoing it.
+ *
+ * For user mode entries enter_from_user_mode() must be invoked to
+ * establish the proper context for NOHZ_FULL. Otherwise scheduling on exit
+ * would not be possible.
+ *
+ * Returns: True if RCU has been adjusted on a kernel entry
+ *	    False otherwise
+ *
+ * The return value must be fed into the rcu_exit argument of
+ * idtentry_exit_cond_rcu().
  */
-void noinstr idtentry_enter(struct pt_regs *regs)
+bool noinstr idtentry_enter_cond_rcu(struct pt_regs *regs, bool cond_rcu)
 {
 	if (user_mode(regs)) {
 		enter_from_user_mode();
 	} else {
-		lockdep_hardirqs_off(CALLER_ADDR0);
-		rcu_irq_enter();
-		instrumentation_begin();
-		trace_hardirqs_off_prepare();
-		instrumentation_end();
+		if (!cond_rcu || !__rcu_is_watching()) {
+			/*
+			 * If RCU is not watching then the same careful
+			 * sequence vs. lockdep and tracing is required
+			 * as in enter_from_user_mode().
+			 *
+			 * This only happens for IRQs that hits the idle
+			 * loop, i.e. if idle is not using MWAIT.
+			 */
+			lockdep_hardirqs_off(CALLER_ADDR0);
+			rcu_irq_enter();
+			instrumentation_begin();
+			trace_hardirqs_off_prepare();
+			instrumentation_end();
+			return true;
+		} else {
+			/*
+			 * If RCU is watching then RCU only wants to check
+			 * whether it needs to restart the tick in NOHZ
+			 * mode.
+			 */
+			instrumentation_begin();
+			rcu_irq_enter_check_tick();
+			/* Use the combo lockdep/tracing function */
+			trace_hardirqs_off();
+			instrumentation_end();
+		}
 	}
+	return false;
 }
 
 /**
- * idtentry_exit - Common code to handle return from exceptions
+ * idtentry_exit_cond_rcu - Handle return from exception with conditional RCU
+ *			    handling
  * @regs:	Pointer to pt_regs (exception entry regs)
+ * @rcu_exit:	Invoke rcu_irq_exit() if true
  *
  * Depending on the return target (kernel/user) this runs the necessary
- * preemption and work checks if possible and required and returns to
+ * preemption and work checks if possible and reguired and returns to
  * the caller with interrupts disabled and no further work pending.
  *
  * This is the last action before returning to the low level ASM code which
  * just needs to return to the appropriate context.
  *
- * Invoked by all exception/interrupt IDTENTRY handlers which are not
- * returning through the paranoid exit path (all except NMI, #DF and the IST
- * variants of #MC and #DB) and are therefore on the thread stack.
+ * Counterpart to idtentry_enter_cond_rcu(). The return value of the entry
+ * function must be fed into the @rcu_exit argument.
  */
-void noinstr idtentry_exit(struct pt_regs *regs)
+void noinstr idtentry_exit_cond_rcu(struct pt_regs *regs, bool rcu_exit)
 {
 	lockdep_assert_irqs_disabled();
 
@@ -580,7 +623,8 @@ void noinstr idtentry_exit(struct pt_reg
 				if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
 					WARN_ON_ONCE(!on_thread_stack());
 				instrumentation_begin();
-				rcu_irq_exit_preempt();
+				if (rcu_exit)
+					rcu_irq_exit_preempt();
 				if (need_resched())
 					preempt_schedule_irq();
 				/* Covers both tracing and lockdep */
@@ -602,10 +646,12 @@ void noinstr idtentry_exit(struct pt_reg
 		trace_hardirqs_on_prepare();
 		lockdep_hardirqs_on_prepare(CALLER_ADDR0);
 		instrumentation_end();
-		rcu_irq_exit();
+		if (rcu_exit)
+			rcu_irq_exit();
 		lockdep_hardirqs_on(CALLER_ADDR0);
 	} else {
-		/* IRQ flags state is correct already. Just tell RCU */
-		rcu_irq_exit();
+		/* IRQ flags state is correct already. Just tell RCU. */
+		if (rcu_exit)
+			rcu_irq_exit();
 	}
 }
--- a/arch/x86/include/asm/idtentry.h
+++ b/arch/x86/include/asm/idtentry.h
@@ -7,8 +7,18 @@
 
 #ifndef __ASSEMBLY__
 
-void idtentry_enter(struct pt_regs *regs);
-void idtentry_exit(struct pt_regs *regs);
+bool idtentry_enter_cond_rcu(struct pt_regs *regs, bool cond_rcu);
+void idtentry_exit_cond_rcu(struct pt_regs *regs, bool rcu_exit);
+
+static __always_inline void idtentry_enter(struct pt_regs *regs)
+{
+	idtentry_enter_cond_rcu(regs, false);
+}
+
+static __always_inline void idtentry_exit(struct pt_regs *regs)
+{
+	idtentry_exit_cond_rcu(regs, true);
+}
 
 /**
  * DECLARE_IDTENTRY - Declare functions for simple IDT entry points


  parent reply	other threads:[~2020-05-21 20:31 UTC|newest]

Thread overview: 132+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-21 20:05 [patch V9 00/39] x86/entry: Rework leftovers (was part V) Thomas Gleixner
2020-05-21 20:05 ` [patch V9 01/39] nmi, tracing: Make hardware latency tracing noinstr safe Thomas Gleixner
2020-05-27  8:12   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 02/39] rcu: Abstract out rcu_irq_enter_check_tick() from rcu_nmi_enter() Thomas Gleixner
2020-05-21 21:03   ` Paul E. McKenney
2020-05-21 21:25     ` Thomas Gleixner
2020-05-26  8:14     ` Ingo Molnar
2020-05-26 15:34       ` Paul E. McKenney
2020-05-27  8:12   ` [tip: x86/entry] " tip-bot2 for Paul E. McKenney
2020-05-21 20:05 ` [patch V9 03/39] rcu: Provide rcu_irq_exit_check_preempt() Thomas Gleixner
2020-05-27  8:12   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` Thomas Gleixner [this message]
2020-05-21 21:06   ` [patch V9 04/39] x86/entry: Provide idtentry_entry/exit_cond_rcu() Paul E. McKenney
2020-05-26  8:23   ` Ingo Molnar
2020-05-26  8:58     ` Thomas Gleixner
2020-05-21 20:05 ` [patch V9 05/39] x86/entry: Provide idtentry_enter/exit_user() Thomas Gleixner
2020-05-27  8:12   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 06/39] x86/idtentry: Switch to conditional RCU handling Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 07/39] x86/entry: Cleanup idtentry_enter/exit() leftovers Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] x86/entry: Clean up " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 08/39] genirq: Provide irq_enter/exit_rcu() Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 09/39] genirq: Provide __irq_enter/exit_raw() Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 10/39] x86/entry: Provide helpers for execute on irqstack Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] x86/entry: Provide helpers for executing on the irqstack tip-bot2 for Thomas Gleixner
2020-06-05 17:18   ` [patch V9 10/39] x86/entry: Provide helpers for execute on irqstack Qian Cai
2020-06-05 17:36     ` Peter Zijlstra
2020-06-05 17:52       ` Qian Cai
2020-06-07 11:59         ` Thomas Gleixner
2020-06-07 18:27           ` Qian Cai
2020-06-08 16:01       ` Qian Cai
2020-06-08 22:20         ` Thomas Gleixner
2020-06-09  2:32           ` Qian Cai
2020-06-09 20:33             ` Thomas Gleixner
2020-06-09 20:50               ` Thomas Gleixner
2020-06-10 12:38                 ` Qian Cai
2020-06-10 19:38                   ` Thomas Gleixner
2020-06-13 13:55                     ` Qian Cai
2020-06-13 14:03                       ` Thomas Gleixner
2020-06-13 21:41                         ` Qian Cai
2020-06-14  8:59                           ` Thomas Gleixner
2020-05-21 20:05 ` [patch V9 11/39] x86/entry/64: Move do_softirq_own_stack() to C Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 12/39] x86/entry: Split out idtentry_exit_cond_resched() Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 13/39] x86/entry: Switch XEN/PV hypercall entry to IDTENTRY Thomas Gleixner
2020-05-22 18:32   ` [patch V9-1 " Thomas Gleixner
2020-05-26  7:44     ` Jürgen Groß
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 14/39] x86/entry/64: Simplify idtentry_body Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 15/39] x86/entry: Switch page fault exception to IDTENTRY_RAW Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 16/39] x86/entry: Remove the transition leftovers Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 17/39] x86/entry: Change exit path of xen_failsafe_callback Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 18/39] x86/entry/64: Remove error_exit Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] x86/entry/64: Remove error_exit() tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 19/39] x86/entry/32: Remove common_exception Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] x86/entry/32: Remove common_exception() tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 20/39] x86/irq: Use generic irq_regs implementation Thomas Gleixner
2020-05-26 18:39   ` damian
2020-05-28  9:50     ` Thomas Gleixner
2020-05-28 20:20       ` damian
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 21/39] x86/irq: Convey vector as argument and not in ptregs Thomas Gleixner
2020-05-22 19:34   ` Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-08-24 17:29   ` [patch V9 21/39] " Alexander Graf
2020-08-25 10:28     ` Thomas Gleixner
2020-08-25 23:17       ` Alexander Graf
2020-08-25 23:41         ` Andy Lutomirski
2020-08-26  0:04           ` Alexander Graf
2020-08-26  1:03             ` Brian Gerst
2020-08-26  0:55           ` Thomas Gleixner
2020-05-21 20:05 ` [patch V9 22/39] x86/irq: Rework handle_irq() for 64bit Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] x86/irq: Rework handle_irq() for 64-bit tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 23/39] x86/entry: Add IRQENTRY_IRQ macro Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 24/39] x86/entry: Use idtentry for interrupts Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 25/39] x86/entry: Provide IDTENTRY_SYSVEC Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 26/39] x86/entry: Convert APIC interrupts to IDTENTRY_SYSVEC Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 27/39] x86/entry: Convert SMP system vectors " Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 28/39] x86/entry: Convert various system vectors Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 29/39] x86/entry: Convert KVM vectors to IDTENTRY_SYSVEC* Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 30/39] x86/entry: Convert various hypervisor vectors to IDTENTRY_SYSVEC Thomas Gleixner
2020-05-26  9:29   ` Wei Liu
2020-05-27  1:46   ` Boqun Feng
2020-05-27  8:38     ` Wei Liu
2020-05-27 12:09       ` Wei Liu
2020-05-27 23:06         ` Boqun Feng
2020-05-27 12:30       ` Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 31/39] x86/entry: Convert XEN hypercall vector " Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 32/39] x86/entry: Convert reschedule interrupt to IDTENTRY_SYSVEC_SIMPLE Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 33/39] x86/entry: Remove the apic/BUILD interrupt leftovers Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 34/39] x86/entry/64: Remove IRQ stack switching ASM Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 35/39] x86/entry: Make enter_from_user_mode() static Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 36/39] x86/entry/32: Remove redundant irq disable code Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 37/39] x86/entry/64: Remove TRACE_IRQS_*_DEBUG Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 38/39] x86/entry: Move paranoid irq tracing out of ASM code Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-21 20:05 ` [patch V9 39/39] x86/entry: Remove the TRACE_IRQS cruft Thomas Gleixner
2020-05-27  8:11   ` [tip: x86/entry] " tip-bot2 for Thomas Gleixner
2020-05-22  7:20 ` [patch V9 00/39] x86/entry: Rework leftovers (was part V) Andrew Cooper
2020-05-22 21:17   ` Peter Zijlstra
2020-06-03 19:18     ` Andrew Cooper
2020-06-04 13:25       ` Peter Zijlstra
2020-06-04 13:29         ` Paolo Bonzini
2020-06-04 13:35           ` Peter Zijlstra
2020-06-04 15:42             ` Andy Lutomirski
2020-06-04 15:55               ` Peter Zijlstra
2020-05-22 14:26 ` Boris Ostrovsky
2020-05-22 17:47   ` Thomas Gleixner
2020-05-22 18:08     ` Thomas Gleixner
2020-05-26  4:33 ` Andy Lutomirski

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=20200521202117.181397835@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=alexandre.chartre@oracle.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=brgerst@gmail.com \
    --cc=frederic@kernel.org \
    --cc=jason.cj.chen@intel.com \
    --cc=jgross@suse.com \
    --cc=joel@joelfernandes.org \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=mikelley@microsoft.com \
    --cc=paulmck@kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=sean.j.christopherson@intel.com \
    --cc=thomas.lendacky@amd.com \
    --cc=wei.liu@kernel.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    --cc=yakui.zhao@intel.com \
    /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.