mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Andy Lutomirski <luto@kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Sean Christopherson <sean.j.christopherson@intel.com>
Subject: [patch V2 20/29] x86/dumpstack/64: Speedup in_exception_stack()
Date: Fri, 05 Apr 2019 17:07:18 +0200	[thread overview]
Message-ID: <20190405150930.219316964@linutronix.de> (raw)
In-Reply-To: <20190405150658.237064784@linutronix.de>

The current implementation of in_exception_stack() iterates over the
exception stacks array. Most of the time this is an useless exercise, but
even for the actual use cases (perf and ftrace) it takes at least 2
iterations to get to the NMI stack.

As the exception stacks and the guard pages are page aligned the loop can
be avoided completely.

Add a initial check whether the stack pointer is inside the full exception
stack area and leave early if not.

Create a lookup table which describes the stack area. The table index is
the page offset from the beginning of the exception stacks. So for any
given stack pointer the page offset is computed and a lookup in the
description table is performed. If it is inside a guard page, return. If
not, use the descriptor to fill in the info structure.

The table is filled at compile time and for the !KASAN case the interesting
page descriptors exactly fit into a single cache line. Just the last guard
page descriptor is in the next cacheline, but that should not be accessed
in the regular case.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Simplify the macro maze
---
 arch/x86/kernel/dumpstack_64.c |   90 +++++++++++++++++++++++++----------------
 1 file changed, 55 insertions(+), 35 deletions(-)

--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -50,52 +50,72 @@ const char *stack_type_name(enum stack_t
 	return NULL;
 }
 
-struct estack_layout {
-	unsigned int	begin;
-	unsigned int	end;
+/**
+ * struct estack_pages - Page descriptor for exception stacks
+ * @offs:	Offset from the start of the exception stack area
+ * @size:	Size of the exception stack
+ * @type:	Type to store in the stack_info struct
+ */
+struct estack_pages {
+	u32	offs;
+	u16	size;
+	u16	type;
 };
 
-#define	ESTACK_ENTRY(x)	{						  \
-	.begin	= offsetof(struct cea_exception_stacks, x## _stack),	  \
-	.end	= offsetof(struct cea_exception_stacks, x## _stack_guard) \
-	}
-
-static const struct estack_layout layout[] = {
-	[ ISTACK_DF	]	= ESTACK_ENTRY(DF),
-	[ ISTACK_NMI	]	= ESTACK_ENTRY(NMI),
-	[ ISTACK_DB2	]	= { .begin = 0, .end = 0},
-	[ ISTACK_DB1	]	= ESTACK_ENTRY(DB1),
-	[ ISTACK_DB	]	= ESTACK_ENTRY(DB),
-	[ ISTACK_MCE	]	= ESTACK_ENTRY(MCE),
+#define EPAGERANGE(st)							\
+	[PFN_DOWN(CEA_ESTACK_OFFS(st)) ...				\
+	 PFN_DOWN(CEA_ESTACK_OFFS(st) + CEA_ESTACK_SIZE(st) - 1)] = {	\
+		.offs	= CEA_ESTACK_OFFS(st),				\
+		.size	= CEA_ESTACK_SIZE(st),				\
+		.type	= STACK_TYPE_EXCEPTION + ISTACK_ ##st, }
+
+/*
+ * Array of exception stack page descriptors. If the stack is larger than
+ * PAGE_SIZE, all pages covering a particular stack will have the same
+ * info. The guard pages including the not mapped DB2 stack are zeroed
+ * out.
+ */
+static const
+struct estack_pages estack_pages[CEA_ESTACK_PAGES] ____cacheline_aligned = {
+	EPAGERANGE(DF),
+	EPAGERANGE(NMI),
+	EPAGERANGE(DB1),
+	EPAGERANGE(DB),
+	EPAGERANGE(MCE),
 };
 
 static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
 {
-	unsigned long estacks, begin, end, stk = (unsigned long)stack;
+	unsigned long begin, end, stk = (unsigned long)stack;
+	const struct estack_pages *ep;
 	struct pt_regs *regs;
 	unsigned int k;
 
 	BUILD_BUG_ON(N_EXCEPTION_STACKS != 6);
 
-	estacks = (unsigned long)__this_cpu_read(cea_exception_stacks);
-
-	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
-		begin = estacks + layout[k].begin;
-		end   = estacks + layout[k].end;
-		regs  = (struct pt_regs *)end - 1;
-
-		if (stk < begin || stk >= end)
-			continue;
-
-		info->type	= STACK_TYPE_EXCEPTION + k;
-		info->begin	= (unsigned long *)begin;
-		info->end	= (unsigned long *)end;
-		info->next_sp	= (unsigned long *)regs->sp;
-
-		return true;
-	}
-
-	return false;
+	begin = (unsigned long)__this_cpu_read(cea_exception_stacks);
+	end = begin + sizeof(struct cea_exception_stacks);
+	/* Bail if @stack is outside the exception stack area. */
+	if (stk < begin || stk >= end)
+		return false;
+
+	/* Calc page offset from start of exception stacks */
+	k = (stk - begin) >> PAGE_SHIFT;
+	/* Lookup the page descriptor */
+	ep = &estack_pages[k];
+	/* Guard page? */
+	if (!ep->size)
+		return false;
+
+	begin += (unsigned long)ep->offs;
+	end = begin + (unsigned long)ep->size;
+	regs = (struct pt_regs *)end - 1;
+
+	info->type	= ep->type;
+	info->begin	= (unsigned long *)begin;
+	info->end	= (unsigned long *)end;
+	info->next_sp	= (unsigned long *)regs->sp;
+	return true;
 }
 
 static bool in_irq_stack(unsigned long *stack, struct stack_info *info)



  parent reply	other threads:[~2019-04-05 15:11 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-05 15:06 [patch V2 00/29] x86: Add guard pages to exception and interrupt stacks Thomas Gleixner
2019-04-05 15:06 ` [patch V2 01/29] x86/irq/64: Limit IST stack overflow check to #DB stack Thomas Gleixner
2019-04-05 15:07 ` [patch V2 02/29] x86/dumpstack: Fix off-by-one errors in stack identification Thomas Gleixner
2019-04-05 15:44   ` Sean Christopherson
2019-04-05 15:07 ` [patch V2 03/29] x86/irq/64: Remove a hardcoded irq_stack_union access Thomas Gleixner
2019-04-05 16:37   ` Sean Christopherson
2019-04-05 16:38     ` Sean Christopherson
2019-04-05 17:18     ` Josh Poimboeuf
2019-04-05 17:47       ` Thomas Gleixner
2019-04-05 15:07 ` [patch V2 04/29] x86/irq/64: Sanitize the top/bottom confusion Thomas Gleixner
2019-04-05 16:54   ` Sean Christopherson
2019-04-05 15:07 ` [patch V2 05/29] x86/idt: Remove unused macro SISTG Thomas Gleixner
2019-04-05 15:07 ` [patch V2 06/29] x86/exceptions: Remove unused stack defines on 32bit Thomas Gleixner
2019-04-05 15:07 ` [patch V2 07/29] x86/exceptions: Make IST index zero based Thomas Gleixner
2019-04-05 18:59   ` Sean Christopherson
2019-04-05 15:07 ` [patch V2 08/29] x86/cpu_entry_area: Cleanup setup functions Thomas Gleixner
2019-04-05 19:25   ` Sean Christopherson
2019-04-05 15:07 ` [patch V2 09/29] x86/exceptions: Add structs for exception stacks Thomas Gleixner
2019-04-05 20:48   ` Sean Christopherson
2019-04-05 20:50     ` Sean Christopherson
2019-04-05 21:00     ` Thomas Gleixner
2019-04-05 15:07 ` [patch V2 10/29] x86/cpu_entry_area: Prepare for IST guard pages Thomas Gleixner
2019-04-05 15:07 ` [patch V2 11/29] x86/cpu_entry_area: Provide exception stack accessor Thomas Gleixner
2019-04-05 15:07 ` [patch V2 12/29] x86/traps: Use cpu_entry_area instead of orig_ist Thomas Gleixner
2019-04-05 15:07 ` [patch V2 13/29] x86/irq/64: Use cpu entry area " Thomas Gleixner
2019-04-05 15:07 ` [patch V2 14/29] x86/dumpstack/64: Use cpu_entry_area " Thomas Gleixner
2019-04-05 15:07 ` [patch V2 15/29] x86/cpu: Prepare TSS.IST setup for guard pages Thomas Gleixner
2019-04-05 15:07 ` [patch V2 16/29] x86/cpu: Remove orig_ist array Thomas Gleixner
2019-04-05 15:07 ` [patch V2 17/29] x86/exceptions: Disconnect IST index and stack order Thomas Gleixner
2019-04-05 21:57   ` Josh Poimboeuf
2019-04-05 22:00     ` Thomas Gleixner
2019-04-05 15:07 ` [patch V2 18/29] x86/exceptions: Enable IST guard pages Thomas Gleixner
2019-04-05 15:07 ` [patch V2 19/29] x86/exceptions: Split debug IST stack Thomas Gleixner
2019-04-05 20:55   ` Sean Christopherson
2019-04-05 21:01     ` Thomas Gleixner
2019-04-05 15:07 ` Thomas Gleixner [this message]
2019-04-05 21:55   ` [patch V2 20/29] x86/dumpstack/64: Speedup in_exception_stack() Josh Poimboeuf
2019-04-05 21:56     ` Thomas Gleixner
2019-04-05 15:07 ` [patch V2 21/29] x86/irq/32: Define IRQ_STACK_SIZE Thomas Gleixner
2019-04-05 15:07 ` [patch V2 22/29] x86/irq/32: Make irq stack a character array Thomas Gleixner
2019-04-05 15:07 ` [patch V2 23/29] x86/irq/32: Rename hard/softirq_stack to hard/softirq_stack_ptr Thomas Gleixner
2019-04-05 15:07 ` [patch V2 24/29] x86/irq/64: Rename irq_stack_ptr to hardirq_stack_ptr Thomas Gleixner
2019-04-05 15:07 ` [patch V2 25/29] x86/irq/32: Invoke irq_ctx_init() from init_IRQ() Thomas Gleixner
2019-04-05 15:27   ` Juergen Gross
2019-04-05 15:07 ` [patch V2 26/29] x86/irq/32: Handle irq stack allocation failure proper Thomas Gleixner
2019-04-05 15:07 ` [patch V2 27/29] x86/irq/64: Split the IRQ stack into its own pages Thomas Gleixner
2019-04-05 15:07 ` [patch V2 28/29] x86/irq/64: Remap the IRQ stack with guard pages Thomas Gleixner
2019-04-07  4:56   ` Andy Lutomirski
2019-04-07  6:08     ` Thomas Gleixner
2019-04-07  9:28       ` Andy Lutomirski
2019-04-07  9:34         ` Thomas Gleixner
2019-04-07 14:03           ` Andy Lutomirski
2019-04-07 22:44     ` Thomas Gleixner
2019-04-08  2:23       ` Andy Lutomirski
2019-04-08  6:46         ` Thomas Gleixner
2019-04-08 16:18           ` Andy Lutomirski
2019-04-08 16:36             ` Josh Poimboeuf
2019-04-08 16:44             ` Thomas Gleixner
2019-04-08 18:19               ` Thomas Gleixner
2019-04-05 15:07 ` [patch V2 29/29] x86/irq/64: Remove stack overflow debug code Thomas Gleixner

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=20190405150930.219316964@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=sean.j.christopherson@intel.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome