Skip to content

Commit 94a6df2

Browse files
committed
Merge tag 'powerpc-4.12-7' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: "Some more powerpc fixes for 4.12. Most of these actually came in last week but got held up for some more testing. - three fixes for kprobes/ftrace/livepatch interactions. - properly handle data breakpoints when using the Radix MMU. - fix for perf sampling of registers during call_usermodehelper(). - properly initialise the thread_info on our emergency stacks - add an explicit flush when doing TLB invalidations for a process using NPU2. Thanks to: Alistair Popple, Naveen N. Rao, Nicholas Piggin, Ravi Bangoria, Masami Hiramatsu" * tag 'powerpc-4.12-7' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/64: Initialise thread_info for emergency stacks powerpc/powernv/npu-dma: Add explicit flush when sending an ATSD powerpc/perf: Fix oops when kthread execs user process powerpc/64s: Handle data breakpoints in Radix mode powerpc/kprobes: Skip livepatch_handler() for jprobes powerpc/ftrace: Pass the correct stack pointer for DYNAMIC_FTRACE_WITH_REGS powerpc/kprobes: Pause function_graph tracing during jprobes handling
2 parents cd5545a + 34f19ff commit 94a6df2

File tree

7 files changed

+166
-50
lines changed

7 files changed

+166
-50
lines changed

arch/powerpc/include/asm/kprobes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
103103
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
104104
extern int kprobe_handler(struct pt_regs *regs);
105105
extern int kprobe_post_handler(struct pt_regs *regs);
106+
extern int is_current_kprobe_addr(unsigned long addr);
106107
#ifdef CONFIG_KPROBES_ON_FTRACE
107108
extern int skip_singlestep(struct kprobe *p, struct pt_regs *regs,
108109
struct kprobe_ctlblk *kcb);

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,10 +1411,8 @@ USE_TEXT_SECTION()
14111411
.balign IFETCH_ALIGN_BYTES
14121412
do_hash_page:
14131413
#ifdef CONFIG_PPC_STD_MMU_64
1414-
andis. r0,r4,0xa410 /* weird error? */
1414+
andis. r0,r4,0xa450 /* weird error? */
14151415
bne- handle_page_fault /* if not, try to insert a HPTE */
1416-
andis. r0,r4,DSISR_DABRMATCH@h
1417-
bne- handle_dabr_fault
14181416
CURRENT_THREAD_INFO(r11, r1)
14191417
lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */
14201418
andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */
@@ -1438,11 +1436,16 @@ do_hash_page:
14381436

14391437
/* Error */
14401438
blt- 13f
1439+
1440+
/* Reload DSISR into r4 for the DABR check below */
1441+
ld r4,_DSISR(r1)
14411442
#endif /* CONFIG_PPC_STD_MMU_64 */
14421443

14431444
/* Here we have a page fault that hash_page can't handle. */
14441445
handle_page_fault:
1445-
11: ld r4,_DAR(r1)
1446+
11: andis. r0,r4,DSISR_DABRMATCH@h
1447+
bne- handle_dabr_fault
1448+
ld r4,_DAR(r1)
14461449
ld r5,_DSISR(r1)
14471450
addi r3,r1,STACK_FRAME_OVERHEAD
14481451
bl do_page_fault

arch/powerpc/kernel/kprobes.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
4343

4444
struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
4545

46+
int is_current_kprobe_addr(unsigned long addr)
47+
{
48+
struct kprobe *p = kprobe_running();
49+
return (p && (unsigned long)p->addr == addr) ? 1 : 0;
50+
}
51+
4652
bool arch_within_kprobe_blacklist(unsigned long addr)
4753
{
4854
return (addr >= (unsigned long)__kprobes_text_start &&
@@ -617,6 +623,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
617623
regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc);
618624
#endif
619625

626+
/*
627+
* jprobes use jprobe_return() which skips the normal return
628+
* path of the function, and this messes up the accounting of the
629+
* function graph tracer.
630+
*
631+
* Pause function graph tracing while performing the jprobe function.
632+
*/
633+
pause_graph_tracing();
634+
620635
return 1;
621636
}
622637
NOKPROBE_SYMBOL(setjmp_pre_handler);
@@ -642,6 +657,8 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
642657
* saved regs...
643658
*/
644659
memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
660+
/* It's OK to start function graph tracing again */
661+
unpause_graph_tracing();
645662
preempt_enable_no_resched();
646663
return 1;
647664
}

arch/powerpc/kernel/setup_64.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,24 @@ void __init exc_lvl_early_init(void)
615615
}
616616
#endif
617617

618+
/*
619+
* Emergency stacks are used for a range of things, from asynchronous
620+
* NMIs (system reset, machine check) to synchronous, process context.
621+
* We set preempt_count to zero, even though that isn't necessarily correct. To
622+
* get the right value we'd need to copy it from the previous thread_info, but
623+
* doing that might fault causing more problems.
624+
* TODO: what to do with accounting?
625+
*/
626+
static void emerg_stack_init_thread_info(struct thread_info *ti, int cpu)
627+
{
628+
ti->task = NULL;
629+
ti->cpu = cpu;
630+
ti->preempt_count = 0;
631+
ti->local_flags = 0;
632+
ti->flags = 0;
633+
klp_init_thread_info(ti);
634+
}
635+
618636
/*
619637
* Stack space used when we detect a bad kernel stack pointer, and
620638
* early in SMP boots before relocation is enabled. Exclusive emergency
@@ -633,24 +651,31 @@ void __init emergency_stack_init(void)
633651
* Since we use these as temporary stacks during secondary CPU
634652
* bringup, we need to get at them in real mode. This means they
635653
* must also be within the RMO region.
654+
*
655+
* The IRQ stacks allocated elsewhere in this file are zeroed and
656+
* initialized in kernel/irq.c. These are initialized here in order
657+
* to have emergency stacks available as early as possible.
636658
*/
637659
limit = min(safe_stack_limit(), ppc64_rma_size);
638660

639661
for_each_possible_cpu(i) {
640662
struct thread_info *ti;
641663
ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
642-
klp_init_thread_info(ti);
664+
memset(ti, 0, THREAD_SIZE);
665+
emerg_stack_init_thread_info(ti, i);
643666
paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
644667

645668
#ifdef CONFIG_PPC_BOOK3S_64
646669
/* emergency stack for NMI exception handling. */
647670
ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
648-
klp_init_thread_info(ti);
671+
memset(ti, 0, THREAD_SIZE);
672+
emerg_stack_init_thread_info(ti, i);
649673
paca[i].nmi_emergency_sp = (void *)ti + THREAD_SIZE;
650674

651675
/* emergency stack for machine check exception handling. */
652676
ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
653-
klp_init_thread_info(ti);
677+
memset(ti, 0, THREAD_SIZE);
678+
emerg_stack_init_thread_info(ti, i);
654679
paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
655680
#endif
656681
}

arch/powerpc/kernel/trace/ftrace_64_mprofile.S

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,14 @@ _GLOBAL(ftrace_caller)
4545
stdu r1,-SWITCH_FRAME_SIZE(r1)
4646

4747
/* Save all gprs to pt_regs */
48-
SAVE_8GPRS(0,r1)
49-
SAVE_8GPRS(8,r1)
50-
SAVE_8GPRS(16,r1)
51-
SAVE_8GPRS(24,r1)
48+
SAVE_GPR(0, r1)
49+
SAVE_10GPRS(2, r1)
50+
SAVE_10GPRS(12, r1)
51+
SAVE_10GPRS(22, r1)
52+
53+
/* Save previous stack pointer (r1) */
54+
addi r8, r1, SWITCH_FRAME_SIZE
55+
std r8, GPR1(r1)
5256

5357
/* Load special regs for save below */
5458
mfmsr r8
@@ -95,18 +99,44 @@ ftrace_call:
9599
bl ftrace_stub
96100
nop
97101

98-
/* Load ctr with the possibly modified NIP */
99-
ld r3, _NIP(r1)
100-
mtctr r3
102+
/* Load the possibly modified NIP */
103+
ld r15, _NIP(r1)
104+
101105
#ifdef CONFIG_LIVEPATCH
102-
cmpd r14,r3 /* has NIP been altered? */
106+
cmpd r14, r15 /* has NIP been altered? */
107+
#endif
108+
109+
#if defined(CONFIG_LIVEPATCH) && defined(CONFIG_KPROBES_ON_FTRACE)
110+
/* NIP has not been altered, skip over further checks */
111+
beq 1f
112+
113+
/* Check if there is an active kprobe on us */
114+
subi r3, r14, 4
115+
bl is_current_kprobe_addr
116+
nop
117+
118+
/*
119+
* If r3 == 1, then this is a kprobe/jprobe.
120+
* else, this is livepatched function.
121+
*
122+
* The conditional branch for livepatch_handler below will use the
123+
* result of this comparison. For kprobe/jprobe, we just need to branch to
124+
* the new NIP, not call livepatch_handler. The branch below is bne, so we
125+
* want CR0[EQ] to be true if this is a kprobe/jprobe. Which means we want
126+
* CR0[EQ] = (r3 == 1).
127+
*/
128+
cmpdi r3, 1
129+
1:
103130
#endif
104131

132+
/* Load CTR with the possibly modified NIP */
133+
mtctr r15
134+
105135
/* Restore gprs */
106-
REST_8GPRS(0,r1)
107-
REST_8GPRS(8,r1)
108-
REST_8GPRS(16,r1)
109-
REST_8GPRS(24,r1)
136+
REST_GPR(0,r1)
137+
REST_10GPRS(2,r1)
138+
REST_10GPRS(12,r1)
139+
REST_10GPRS(22,r1)
110140

111141
/* Restore possibly modified LR */
112142
ld r0, _LINK(r1)
@@ -119,7 +149,10 @@ ftrace_call:
119149
addi r1, r1, SWITCH_FRAME_SIZE
120150

121151
#ifdef CONFIG_LIVEPATCH
122-
/* Based on the cmpd above, if the NIP was altered handle livepatch */
152+
/*
153+
* Based on the cmpd or cmpdi above, if the NIP was altered and we're
154+
* not on a kprobe/jprobe, then handle livepatch.
155+
*/
123156
bne- livepatch_handler
124157
#endif
125158

arch/powerpc/perf/perf_regs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,6 @@ void perf_get_regs_user(struct perf_regs *regs_user,
101101
struct pt_regs *regs_user_copy)
102102
{
103103
regs_user->regs = task_pt_regs(current);
104-
regs_user->abi = perf_reg_abi(current);
104+
regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
105+
PERF_SAMPLE_REGS_ABI_NONE;
105106
}

0 commit comments

Comments
 (0)