All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Andy Lutomirski <luto@kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
	linux-tip-commits@vger.kernel.org,
	Thomas Gleixner <tglx@linutronix.de>, x86 <x86@kernel.org>
Subject: Re: [tip: x86/entry] x86/entry: Treat BUG/WARN as NMI-like entries
Date: Tue, 16 Jun 2020 13:14:08 +0200	[thread overview]
Message-ID: <20200616111408.GS2531@hirez.programming.kicks-ass.net> (raw)
In-Reply-To: <CALCETrXisDDMb_eaPDq1DWrMuSqo1hDrOd14u7fSR4J_RxJu_A@mail.gmail.com>

On Mon, Jun 15, 2020 at 03:46:00PM -0700, Andy Lutomirski wrote:

> In some sense, #UD and #PF are fundamentally different.  #PF wants to
> be able to schedule in the kernel.  #UD wants to be as minimal as
> possible in the kernel but probably still wants to do the nmi_enter()
> dance in case it's an RCU warning and the warning handler code wants
> to use RCU.
> 
> One solution would be to get rid of ud2 for warnings and replace it
> with CALL warning_thunk :)  But I guess I'm okay with your patch.

Well, the raisin we use UD2 is because it's only 2 bytes, which makes
for nice and compact code. Ideally we'd have a single byte #UD
instruction, but alas.

However, I realized that there's another analogy with #PF that does
transfer to #UD. For #PF we state that in-kernel #PF only happens when
RCU is already watching -- by virtue of us being careful in noinstr.

But similarly we can state we only have UD2 when we want to call
WARN/BUG and can forgo exception entry.

That would then result in something like this...

---
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index af75109485c2..8fe57b07a03b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -216,40 +216,35 @@ static inline void handle_invalid_op(struct pt_regs *regs)
 		      ILL_ILLOPN, error_get_trap_addr(regs));
 }
 
-DEFINE_IDTENTRY_RAW(exc_invalid_op)
+static noinstr bool handle_bug(struct pt_regs *regs)
 {
-	bool rcu_exit;
+	bool handled = false;
 
 	/*
-	 * Handle BUG/WARN like NMIs instead of like normal idtentries:
-	 * if we bugged/warned in a bad RCU context, for example, the last
-	 * thing we want is to BUG/WARN again in the idtentry code, ad
-	 * infinitum.
+	 * All lies, just get the WARN/BUG out.
 	 */
-	if (!user_mode(regs) && is_valid_bugaddr(regs->ip)) {
-		enum bug_trap_type type;
+	instrumentation_begin();
+	if (is_valid_bugaddr(regs->ip) &&
+	    report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
+		regs->ip += LEN_UD2;
+		handled = true;
+	}
+	instrumentation_end();
 
-		nmi_enter();
-		instrumentation_begin();
-		trace_hardirqs_off_finish();
-		type = report_bug(regs->ip, regs);
-		if (regs->flags & X86_EFLAGS_IF)
-			trace_hardirqs_on_prepare();
-		instrumentation_end();
-		nmi_exit();
+	return handled;
+}
 
-		if (type == BUG_TRAP_TYPE_WARN) {
-			/* Skip the ud2. */
-			regs->ip += LEN_UD2;
-			return;
-		}
+DEFINE_IDTENTRY_RAW(exc_invalid_op)
+{
+	bool rcu_exit;
 
-		/*
-		 * Else, if this was a BUG and report_bug returns or if this
-		 * was just a normal #UD, we want to continue onward and
-		 * crash.
-		 */
-	}
+	/*
+	 * We use UD2 as a short encoding for 'CALL __WARN', as such
+	 * handle it before exception entry to avoid recursive WARN
+	 * in case exception entry is the one triggering WARNs.
+	 */
+	if (!user_mode(regs) && handle_bug(regs))
+		return;
 
 	rcu_exit = idtentry_enter_cond_rcu(regs);
 	instrumentation_begin();

      reply	other threads:[~2020-06-16 11:14 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-12  3:26 [PATCH] x86/entry: Treat BUG/WARN as NMI-like entries Andy Lutomirski
2020-06-12  4:13 ` Andy Lutomirski
2020-06-12 19:50 ` [tip: x86/entry] " tip-bot2 for Andy Lutomirski
2020-06-15 14:50   ` Peter Zijlstra
2020-06-15 17:06     ` Andy Lutomirski
2020-06-15 19:44       ` Peter Zijlstra
2020-06-15 21:08         ` Andy Lutomirski
2020-06-15 22:23           ` Peter Zijlstra
2020-06-15 22:46             ` Andy Lutomirski
2020-06-16 11:14               ` Peter Zijlstra [this message]

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=20200616111408.GS2531@hirez.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=tglx@linutronix.de \
    --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.