From: Josh Poimboeuf <jpoimboe@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: tglx@linutronix.de, x86@kernel.org, linux-kernel@vger.kernel.org,
luto@kernel.org
Subject: Re: [RFC][PATCH 3/3] x86/entry, ORC: Teach objtool/unwind_orc about stack irq swizzles
Date: Thu, 7 May 2020 13:30:48 -0500 [thread overview]
Message-ID: <20200507183048.rlf2bgj4cf2g4jy6@treble> (raw)
In-Reply-To: <20200507173809.GK5298@hirez.programming.kicks-ass.net>
On Thu, May 07, 2020 at 07:38:09PM +0200, Peter Zijlstra wrote:
> On Thu, May 07, 2020 at 06:10:23PM +0200, Peter Zijlstra wrote:
> > Thomas would very much like objtool to understand and generate correct
> > ORC unwind information for the minimal stack swizzle sequence:
> >
> > mov %rsp, (%[ts])
> > mov %[ts], %rsp
> > ...
> > pop %rsp
> >
> > This sequence works for the fp and guess unwinders -- all they need is
> > that top-of-stack link set up by the first instruction.
> >
> > The previous entry_64.S code worked with "UNWIND_HINT_REGS indirect=1"
> > hints to inform the unwinder about the stack-swizzle, but because
> > we've now already entered C, we can no longer point to a REGS. In
> > fact, due to being in C we don't even have a reliable sp_offset to
> > anything.
> >
> > None of the existing UNWIND_HINT() functionality is quite sufficient
> > to generate the right thing, but SP_INDIRECT is still the closest, so
> > extend it.
> >
> > When SP_INDIRECT is combined with .end=1 (which is otherwise unused,
> > except for sp_reg == UNDEFINED):
> >
> > - change it from (sp+sp_offset) to (sp)+sp_offset
> > - have objtool preserve sp_offset from the previous state
> > - change "pop %rsp" handling to restore the CFI state from before the
> > hint.
> >
> > NOTES:
> >
> > - We now have an instruction with stackops and a hint; make hint take
> > precedence over stackops.
> >
> > - Due to the reverse search in "pop %rsp" we must
> > fill_alternative_cfi() before validate_branch().
> >
> > - This all isn't really pretty, but it works and gets Thomas the code
> > sequence he wants.
> >
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > ---
>
> Much simpler, also works.
Doing the stack switch in inline asm is just nasty.
Also, a frame pointer makes this SO much easier for ORC/objtool, no
funky hints needed. In fact maybe we can get rid of the indirect hint
things altogether, which means even more deleted code.
This is much cleaner, and it boots:
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 3f9b2555e6fb..4a25f72f969f 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -718,15 +718,6 @@ __visible void __xen_pv_evtchn_do_upcall(void)
irq_exit_rcu();
}
-/*
- * Separate function as objtool is unhappy about having
- * the macro at the call site.
- */
-static noinstr void run_on_irqstack(void)
-{
- RUN_ON_IRQSTACK(__xen_pv_evtchn_do_upcall);
-}
-
__visible noinstr void xen_pv_evtchn_do_upcall(struct pt_regs *regs)
{
struct pt_regs *old_regs;
@@ -739,7 +730,7 @@ __visible noinstr void xen_pv_evtchn_do_upcall(struct pt_regs *regs)
__xen_pv_evtchn_do_upcall();
instr_end();
} else {
- run_on_irqstack();
+ RUN_ON_IRQSTACK(__xen_pv_evtchn_do_upcall);
}
set_irq_regs(old_regs);
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 3046dfc69b8c..d036dc831a23 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -1295,3 +1295,31 @@ SYM_CODE_START(rewind_stack_do_exit)
call do_exit
SYM_CODE_END(rewind_stack_do_exit)
.popsection
+
+/*
+ * rdi: new stack pointer
+ * rsi: function pointer
+ * rdx: arg1 (can be NULL if none)
+ */
+SYM_FUNC_START(call_on_stack)
+ /*
+ * Save the frame pointer unconditionally. This allows the ORC
+ * unwinder to handle the stack switch.
+ */
+ pushq %rbp
+ mov %rsp, %rbp
+
+ /*
+ * The unwinder relies on the word at the end of the new stack page
+ * linking back to the previous RSP.
+ */
+ mov %rsp, -8(%rdi)
+ lea -8(%rdi), %rsp
+ mov %rdx, %rdi
+ CALL_NOSPEC rsi
+
+ /* Restore the previous stack pointer from RBP. */
+ leaveq
+
+ ret
+SYM_FUNC_END(call_on_stack)
diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h
index f307d4c27f84..131a6c689b1c 100644
--- a/arch/x86/include/asm/irq_stack.h
+++ b/arch/x86/include/asm/irq_stack.h
@@ -7,42 +7,26 @@
#include <asm/processor.h>
#ifdef CONFIG_X86_64
+
+void call_on_stack(void *stack, void *func, void *arg);
+
static __always_inline bool irqstack_active(void)
{
return __this_cpu_read(irq_count) != -1;
}
-#define __RUN_ON_IRQSTACK(_asm, ...) \
+#define __RUN_ON_IRQSTACK(func, arg) \
do { \
- unsigned long tos; \
- \
lockdep_assert_irqs_disabled(); \
- \
- tos = ((unsigned long)__this_cpu_read(hardirq_stack_ptr)) - 8; \
- \
- __this_cpu_add(irq_count, 1); \
- asm volatile( \
- "movq %%rsp, (%[ts]) \n" \
- "movq %[ts], %%rsp \n" \
- ASM_INSTR_BEGIN \
- _asm " \n" \
- ASM_INSTR_END \
- "popq %%rsp \n" \
- : \
- : [ts] "r" (tos), ##__VA_ARGS__ \
- : "memory" \
- ); \
+ call_on_stack(__this_cpu_read(hardirq_stack_ptr), func, arg); \
__this_cpu_sub(irq_count, 1); \
} while (0)
-/*
- * Macro to emit code for running @func on the irq stack.
- */
#define RUN_ON_IRQSTACK(func) \
- __RUN_ON_IRQSTACK("call" __ASM_FORM(func))
+ __RUN_ON_IRQSTACK(func, NULL)
#define RUN_ON_IRQSTACK_ARG1(func, arg) \
- __RUN_ON_IRQSTACK("call" __ASM_FORM(func), "D" (arg))
+ __RUN_ON_IRQSTACK(func, arg)
#else /* CONFIG_X86_64 */
static __always_inline bool irqstack_active(void) { return false; }
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index c41b0a2859d7..30b6ddf64dc7 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -74,7 +74,7 @@ int irq_init_percpu_irqstack(unsigned int cpu)
static noinstr void handle_irq_on_irqstack(struct irq_desc *desc)
{
- __RUN_ON_IRQSTACK(CALL_NOSPEC, THUNK_TARGET(desc->handle_irq), "D" (desc));
+ RUN_ON_IRQSTACK_ARG1(desc->handle_irq, desc);
}
void handle_irq(struct irq_desc *desc, struct pt_regs *regs)
next prev parent reply other threads:[~2020-05-07 18:30 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-07 16:10 [RFC][PATCH 0/3] objtool vs irqstack swizzles Peter Zijlstra
2020-05-07 16:10 ` [RFC][PATCH 1/3] x86/entry: Collapse the 3 IRQ stack instances into a single macro Peter Zijlstra
2020-05-07 16:10 ` [RFC][PATCH 2/3] x86/entry: Provide ASM_INSTR_{BEGIN,END} Peter Zijlstra
2020-05-07 16:10 ` [RFC][PATCH 3/3] x86/entry, ORC: Teach objtool/unwind_orc about stack irq swizzles Peter Zijlstra
2020-05-07 17:38 ` Peter Zijlstra
2020-05-07 18:30 ` Josh Poimboeuf [this message]
2020-05-07 21:24 ` Thomas Gleixner
2020-05-08 10:12 ` Peter Zijlstra
2020-05-08 12:26 ` Thomas Gleixner
2020-05-08 12:40 ` Peter Zijlstra
2020-05-08 12:44 ` 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=20200507183048.rlf2bgj4cf2g4jy6@treble \
--to=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=peterz@infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®