Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Peter Zijlstra
On Wed, May 01, 2019 at 09:33:28PM +0200, Jiri Kosina wrote:
> On Wed, 1 May 2019, Steven Rostedt wrote:
> 
> > I never tested the 32 bit version of this. And we could just not
> > implement it (I don't think there's live kernel patching for it
> > either).
> 
> That's correct, there is no livepatching on x86_32 (and no plans for 
> it). CONFIG_LIVEPATCH is not available for 32bit builds at all.

We still want this for static_call(), even on 32bit.


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Jiri Kosina
On Wed, 1 May 2019, Steven Rostedt wrote:

> I never tested the 32 bit version of this. And we could just not
> implement it (I don't think there's live kernel patching for it
> either).

That's correct, there is no livepatching on x86_32 (and no plans for 
it). CONFIG_LIVEPATCH is not available for 32bit builds at all.

-- 
Jiri Kosina
SUSE Labs



Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Peter Zijlstra
On Wed, May 01, 2019 at 12:03:52PM -0700, Linus Torvalds wrote:
> On Wed, May 1, 2019 at 6:11 AM Peter Zijlstra  wrote:
> >
> > Here goes, compile tested only...
> 
> Ugh, two different threads. This has the same bug (same source) as the
> one Steven posted:

This is what Steve started from; lets continue in the other thread.

> > --- a/arch/x86/entry/entry_32.S
> > +++ b/arch/x86/entry/entry_32.S
> > @@ -1479,6 +1479,13 @@ ENTRY(int3)
> > ASM_CLAC
> > pushl   $-1 # mark this as an int
> >
> > +   testl   $SEGMENT_RPL_MASK, PT_CS(%esp)
> > +   jnz .Lfrom_usermode_no_gap
> > +   .rept 6
> > +   pushl   5*4(%esp)
> > +   .endr
> > +.Lfrom_usermode_no_gap:
> 
> This will corrupt things horribly if you still use vm86 mode. Checking
> CS RPL is simply not correct.

I'll go fix; I never really understood that vm86 crud and I cobbled this
32bit thing together based on the 64bit version (that Josh did a while
ago).


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Steven Rostedt
On Wed, 1 May 2019 12:03:52 -0700
Linus Torvalds  wrote:

> On Wed, May 1, 2019 at 6:11 AM Peter Zijlstra  wrote:
> >
> > Here goes, compile tested only...  
> 
> Ugh, two different threads. This has the same bug (same source) as the
> one Steven posted:
> 
> > --- a/arch/x86/entry/entry_32.S
> > +++ b/arch/x86/entry/entry_32.S
> > @@ -1479,6 +1479,13 @@ ENTRY(int3)
> > ASM_CLAC
> > pushl   $-1 # mark this as an int
> >
> > +   testl   $SEGMENT_RPL_MASK, PT_CS(%esp)
> > +   jnz .Lfrom_usermode_no_gap
> > +   .rept 6
> > +   pushl   5*4(%esp)
> > +   .endr
> > +.Lfrom_usermode_no_gap:  
> 
> This will corrupt things horribly if you still use vm86 mode. Checking
> CS RPL is simply not correct.

I never tested the 32 bit version of this. And we could just not
implement it (I don't think there's live kernel patching for it
either).

But this doesn't make it any worse than my version, because under the
full testing of my patch with the trampolines, I would easily crash the
32 bit version. That was one reason I made my last patch only support 64
bit.

Under light load, 32 bit works, but when I stress it (running perf and
ftrace together) it blows up. Could be an NMI issue.

-- Steve



Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Linus Torvalds
On Wed, May 1, 2019 at 6:11 AM Peter Zijlstra  wrote:
>
> Here goes, compile tested only...

Ugh, two different threads. This has the same bug (same source) as the
one Steven posted:

> --- a/arch/x86/entry/entry_32.S
> +++ b/arch/x86/entry/entry_32.S
> @@ -1479,6 +1479,13 @@ ENTRY(int3)
> ASM_CLAC
> pushl   $-1 # mark this as an int
>
> +   testl   $SEGMENT_RPL_MASK, PT_CS(%esp)
> +   jnz .Lfrom_usermode_no_gap
> +   .rept 6
> +   pushl   5*4(%esp)
> +   .endr
> +.Lfrom_usermode_no_gap:

This will corrupt things horribly if you still use vm86 mode. Checking
CS RPL is simply not correct.

 Linus


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Peter Zijlstra
On Wed, May 01, 2019 at 02:58:24PM -0400, Steven Rostedt wrote:
> > +   if (ftrace_location(ip)) {
> > +   int3_emulate_call(regs, ftrace_update_func_call);
> 
> Should be:
> 
>   int3_emulate_call(regs, (unsigned long)ftrace_regs_caller);

Ah, I lost the plot a little there.

> > +   return 1;
> > +   } else if (is_ftrace_caller(ip)) {
> > +   if (!ftrace_update_func_call) {
> > +   int3_emulate_jmp(regs, regs->ip - INT3_INSN_SIZE + 
> > CALL_INSN_SIZE);
> 
> I see what you did here, but I think:
> 
>   int3_emulate_jmp(regs, ip + CALL_INSN_SIZE);
> 
> looks better. But that said, we could in the beginning do:
> 
>   ip = regs->ip - INT3_INSN_SIZE;
> 
> instead of
> 
>   ip = regs->ip - 1;
> 
> I made these updates and posted them to Linus.

I was actually considering:

static inline void int3_emulate_nop(struct pt_regs *regs, unsigned long size)
{
int3_emulate_jmp(regs, regs->ip - INT3_INSN_SIZE + size);
}

And then the above becomes:

int3_emulate_nop(regs, CALL_INSN_SIZE);

Hmm?


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Steven Rostedt
On Wed, 1 May 2019 15:11:17 +0200
Peter Zijlstra  wrote:

> On Tue, Apr 30, 2019 at 11:33:21AM -0700, Linus Torvalds wrote:
> > Anyway, since Andy really likes the entry code change, can we have
> > that patch in parallel and judge the difference that way? Iirc, that
> > was x86-64 specific too.  
> 
> Here goes, compile tested only...
> 
> It obviously needs a self-test, but that shoulnd't be too hard to
> arrange.
> 

I was able to get it applied (with slight tweaking) but it then
crashed. But that was due to incorrect updates in the
ftrace_int3_handler().

> ---
>  arch/x86/entry/entry_32.S|  7 +++
>  arch/x86/entry/entry_64.S| 14 --
>  arch/x86/include/asm/text-patching.h | 20 
>  arch/x86/kernel/ftrace.c | 24 +++-
>  4 files changed, 58 insertions(+), 7 deletions(-)


>  #endif /* _ASM_X86_TEXT_PATCHING_H */
> diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
> index ef49517f6bb2..90d319687d7e 100644
> --- a/arch/x86/kernel/ftrace.c
> +++ b/arch/x86/kernel/ftrace.c
> @@ -29,6 +29,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #ifdef CONFIG_DYNAMIC_FTRACE
>  
> @@ -231,6 +232,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec,
> unsigned long old_addr, }
>  
>  static unsigned long ftrace_update_func;
> +static unsigned long ftrace_update_func_call;
>  
>  static int update_ftrace_func(unsigned long ip, void *new)
>  {
> @@ -259,6 +261,8 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
>   unsigned char *new;
>   int ret;
>  
> + ftrace_update_func_call = (unsigned long)func;
> +
>   new = ftrace_call_replace(ip, (unsigned long)func);
>   ret = update_ftrace_func(ip, new);
>  
> @@ -295,12 +299,19 @@ int ftrace_int3_handler(struct pt_regs *regs)
>   return 0;
>  
>   ip = regs->ip - 1;
> - if (!ftrace_location(ip) && !is_ftrace_caller(ip))
> - return 0;
> -
> - regs->ip += MCOUNT_INSN_SIZE - 1;
> + if (ftrace_location(ip)) {
> + int3_emulate_call(regs, ftrace_update_func_call);

Should be:

int3_emulate_call(regs, (unsigned long)ftrace_regs_caller);

> + return 1;
> + } else if (is_ftrace_caller(ip)) {
> + if (!ftrace_update_func_call) {
> + int3_emulate_jmp(regs, regs->ip - INT3_INSN_SIZE + 
> CALL_INSN_SIZE);

I see what you did here, but I think:

int3_emulate_jmp(regs, ip + CALL_INSN_SIZE);

looks better. But that said, we could in the beginning do:

ip = regs->ip - INT3_INSN_SIZE;

instead of

ip = regs->ip - 1;

I made these updates and posted them to Linus.

-- Steve


> + return 1;
> + }
> + int3_emulate_call(regs, ftrace_update_func_call);
> + return 1;
> + }
>  
> - return 1;
> + return 0;
>  }
>  NOKPROBE_SYMBOL(ftrace_int3_handler);
>  
> @@ -859,6 +870,8 @@ void arch_ftrace_update_trampoline(struct
> ftrace_ops *ops) 
>   func = ftrace_ops_get_func(ops);
>  
> + ftrace_update_func_call = (unsigned long)func;
> +
>   /* Do a safe modify in case the trampoline is executing */
>   new = ftrace_call_replace(ip, (unsigned long)func);
>   ret = update_ftrace_func(ip, new);
> @@ -960,6 +973,7 @@ static int ftrace_mod_jmp(unsigned long ip, void
> *func) {
>   unsigned char *new;
>  
> + ftrace_update_func_call = 0UL;
>   new = ftrace_jmp_replace(ip, (unsigned long)func);
>  
>   return update_ftrace_func(ip, new);


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-05-01 Thread Peter Zijlstra
On Tue, Apr 30, 2019 at 11:33:21AM -0700, Linus Torvalds wrote:
> Anyway, since Andy really likes the entry code change, can we have
> that patch in parallel and judge the difference that way? Iirc, that
> was x86-64 specific too.

Here goes, compile tested only...

It obviously needs a self-test, but that shoulnd't be too hard to
arrange.

---
 arch/x86/entry/entry_32.S|  7 +++
 arch/x86/entry/entry_64.S| 14 --
 arch/x86/include/asm/text-patching.h | 20 
 arch/x86/kernel/ftrace.c | 24 +++-
 4 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 7b23431be5cb..d246302085a3 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -1479,6 +1479,13 @@ ENTRY(int3)
ASM_CLAC
pushl   $-1 # mark this as an int
 
+   testl   $SEGMENT_RPL_MASK, PT_CS(%esp)
+   jnz .Lfrom_usermode_no_gap
+   .rept 6
+   pushl   5*4(%esp)
+   .endr
+.Lfrom_usermode_no_gap:
+
SAVE_ALL switch_stacks=1
ENCODE_FRAME_POINTER
TRACE_IRQS_OFF
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 20e45d9b4e15..268cd9affe04 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -878,7 +878,7 @@ apicinterrupt IRQ_WORK_VECTOR   
irq_work_interrupt  smp_irq_work_interrupt
  * @paranoid == 2 is special: the stub will never switch stacks.  This is for
  * #DF: if the thread stack is somehow unusable, we'll still get a useful OOPS.
  */
-.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 
ist_offset=0
+.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 
ist_offset=0 create_gap=0
 ENTRY(\sym)
UNWIND_HINT_IRET_REGS offset=\has_error_code*8
 
@@ -898,6 +898,16 @@ ENTRY(\sym)
jnz .Lfrom_usermode_switch_stack_\@
.endif
 
+   .if \create_gap == 1
+   testb   $3, CS-ORIG_RAX(%rsp)
+   jnz .Lfrom_usermode_no_gap_\@
+   .rept 6
+   pushq   5*8(%rsp)
+   .endr
+   UNWIND_HINT_IRET_REGS offset=8
+.Lfrom_usermode_no_gap_\@:
+   .endif
+
.if \paranoid
callparanoid_entry
.else
@@ -1129,7 +1139,7 @@ apicinterrupt3 HYPERV_STIMER0_VECTOR \
 #endif /* CONFIG_HYPERV */
 
 idtentry debug do_debughas_error_code=0
paranoid=1 shift_ist=IST_INDEX_DB ist_offset=DB_STACK_OFFSET
-idtentry int3  do_int3 has_error_code=0
+idtentry int3  do_int3 has_error_code=0
create_gap=1
 idtentry stack_segment do_stack_segmenthas_error_code=1
 
 #ifdef CONFIG_XEN_PV
diff --git a/arch/x86/include/asm/text-patching.h 
b/arch/x86/include/asm/text-patching.h
index e85ff65c43c3..ba275b6292db 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -39,4 +39,24 @@ extern int poke_int3_handler(struct pt_regs *regs);
 extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void 
*handler);
 extern int after_bootmem;
 
+static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val)
+{
+   regs->sp -= sizeof(unsigned long);
+   *(unsigned long *)regs->sp = val;
+}
+
+static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
+{
+   regs->ip = ip;
+}
+
+#define INT3_INSN_SIZE 1
+#define CALL_INSN_SIZE 5
+
+static inline void int3_emulate_call(struct pt_regs *regs, unsigned long func)
+{
+   int3_emulate_push(regs, regs->ip - INT3_INSN_SIZE + CALL_INSN_SIZE);
+   int3_emulate_jmp(regs, func);
+}
+
 #endif /* _ASM_X86_TEXT_PATCHING_H */
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index ef49517f6bb2..90d319687d7e 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
@@ -231,6 +232,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned 
long old_addr,
 }
 
 static unsigned long ftrace_update_func;
+static unsigned long ftrace_update_func_call;
 
 static int update_ftrace_func(unsigned long ip, void *new)
 {
@@ -259,6 +261,8 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
unsigned char *new;
int ret;
 
+   ftrace_update_func_call = (unsigned long)func;
+
new = ftrace_call_replace(ip, (unsigned long)func);
ret = update_ftrace_func(ip, new);
 
@@ -295,12 +299,19 @@ int ftrace_int3_handler(struct pt_regs *regs)
return 0;
 
ip = regs->ip - 1;
-   if (!ftrace_location(ip) && !is_ftrace_caller(ip))
-   return 0;
-
-   regs->ip += MCOUNT_INSN_SIZE - 1;
+   if (ftrace_location(ip)) {
+   int3_emulate_call(regs, ftrace_update_func_call);
+   return 1;
+   } else if 

Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-04-30 Thread Steven Rostedt
On Tue, 30 Apr 2019 11:33:21 -0700
Linus Torvalds  wrote:

> > +   "ftrace_emulate_call_update_irqoff:\n\t"
> > +   "push %gs:ftrace_bp_call_return\n\t"
> > +   "sti\n\t"
> > +   "jmp *ftrace_update_func_call\n"  
> 
> .. and this should then use the "push push sti ret" model instead.
> 
> Plus get updated for objtool complaints.

And unfortunately, this blows up on lockdep. Lockdep notices that the
return from the breakpoint handler has interrupts enabled, and will not
enable them in its shadow irqs disabled variable. But then we enabled
them in the trampoline, without telling lockdep and we trigger
something likes this:

[ cut here ]
IRQs not enabled as expected
WARNING: CPU: 2 PID: 0 at kernel/time/tick-sched.c:979 
tick_nohz_idle_enter+0x44/0x8c
Modules linked in:
CPU: 2 PID: 0 Comm: swapper/2 Not tainted 5.1.0-rc3-test+ #123
Hardware name: MSI MS-7823/CSM-H87M-G43 (MS-7823), BIOS V1.6 02/22/2014
EIP: tick_nohz_idle_enter+0x44/0x8c
Code: f0 05 00 00 00 75 26 83 b8 c4 05 00 00 00 75 1d 80 3d 5f 0f 43 c1 00 75 
14 68 72 74 16 c1 c6 05 5f 0f 43 c1 01 e8 33 d7 f8 ff <0f> 0b 58 fa e8 4e 2c 04 
00 bb e0 36 6b c1 64 03 1d 28 81 56 c1 8b
EAX: 001c EBX: ee769f84 ECX:  EDX: 0006
ESI:  EDI: 0002 EBP: ee769f50 ESP: ee769f48
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00210292
CR0: 80050033 CR2:  CR3: 016c4000 CR4: 001406f0
Call Trace:
 do_idle+0x2a/0x1fc
 cpu_startup_entry+0x1e/0x20
 start_secondary+0x1d3/0x1ec
 startup_32_smp+0x164/0x168


I have to fool lockdep with the following:

if (regs->flags & X86_EFLAGS_IF) {
regs->flags &= ~X86_EFLAGS_IF;
regs->ip = (unsigned long) ftrace_emulate_call_irqoff;
/* Tell lockdep here we are enabling interrupts */
trace_hardirqs_on();
} else {
regs->ip = (unsigned long) ftrace_emulate_call_irqon;
}

-- Steve


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-04-30 Thread Steven Rostedt
On Tue, 30 Apr 2019 11:33:21 -0700
Linus Torvalds  wrote:

> On Tue, Apr 30, 2019 at 10:49 AM Steven Rostedt  wrote:
> >
> > +
> > +asm(
> > +   ".text\n"
> > +
> > +   /* Trampoline for function update with interrupts enabled */
> > +   ".global ftrace_emulate_call_irqoff\n"
> > +   ".type ftrace_emulate_call_irqoff, @function\n"
> > +   "ftrace_emulate_call_irqoff:\n\t"
> > +   "push %gs:ftrace_bp_call_return\n\t"  
> 
> Well, as mentioned in my original suggestion, this won't work on
> 32-bit, or on UP. They have different models for per-cpu data (32-bti
> uses %fs, and UP doesn't use a segment override at all).

Ah, yeah, I forgot about 32-bit. I could easily make this use fs as
well, and for UP, just use a static variable.

> 
> Maybe we just don't care about UP at all for this code, of course.
> 
> And maybe we can make the decision to also make 32-bit just not use
> this either - so maybe the code is ok per se, just needs to make sure
> it never triggers for the cases that it's not written for..
> 
> > +   "ftrace_emulate_call_update_irqoff:\n\t"
> > +   "push %gs:ftrace_bp_call_return\n\t"
> > +   "sti\n\t"
> > +   "jmp *ftrace_update_func_call\n"  
> 
> .. and this should then use the "push push sti ret" model instead.
> 
> Plus get updated for objtool complaints.

Yeah, I see that now. Somehow it disappeared when I looked for it after
making some other changes. I can update it.

> 
> Anyway, since Andy really likes the entry code change, can we have
> that patch in parallel and judge the difference that way? Iirc, that
> was x86-64 specific too.

Note, I don't think live kernel patching supports 32 bit anyway, so
that may not be an issue.

Josh,

When you come back to the office, can you look into that method?

-- Steve


Re: [RFC][PATCH] ftrace/x86: Emulate call function while updating in breakpoint handler

2019-04-30 Thread Linus Torvalds
On Tue, Apr 30, 2019 at 10:49 AM Steven Rostedt  wrote:
>
> +
> +asm(
> +   ".text\n"
> +
> +   /* Trampoline for function update with interrupts enabled */
> +   ".global ftrace_emulate_call_irqoff\n"
> +   ".type ftrace_emulate_call_irqoff, @function\n"
> +   "ftrace_emulate_call_irqoff:\n\t"
> +   "push %gs:ftrace_bp_call_return\n\t"

Well, as mentioned in my original suggestion, this won't work on
32-bit, or on UP. They have different models for per-cpu data (32-bti
uses %fs, and UP doesn't use a segment override at all).

Maybe we just don't care about UP at all for this code, of course.

And maybe we can make the decision to also make 32-bit just not use
this either - so maybe the code is ok per se, just needs to make sure
it never triggers for the cases that it's not written for..

> +   "ftrace_emulate_call_update_irqoff:\n\t"
> +   "push %gs:ftrace_bp_call_return\n\t"
> +   "sti\n\t"
> +   "jmp *ftrace_update_func_call\n"

.. and this should then use the "push push sti ret" model instead.

Plus get updated for objtool complaints.

Anyway, since Andy really likes the entry code change, can we have
that patch in parallel and judge the difference that way? Iirc, that
was x86-64 specific too.

   Linus