From fb822e6076d972691c5dd33431c10f82dda94ae9 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Wed, 2 Mar 2016 15:25:17 +0530 Subject: powerpc/hw_breakpoint: Fix oops when destroying hw_breakpoint event When destroying a hw_breakpoint event, the kernel oopses as follows: Unable to handle kernel paging request for data at address 0x00000c07 NIP [c0000000000291d0] arch_unregister_hw_breakpoint+0x40/0x60 LR [c00000000020b6b4] release_bp_slot+0x44/0x80 Call chain: hw_breakpoint_event_init() bp->destroy = bp_perf_event_destroy; do_exit() perf_event_exit_task() perf_event_exit_task_context() WRITE_ONCE(child_ctx->task, TASK_TOMBSTONE); perf_event_exit_event() free_event() _free_event() bp_perf_event_destroy() // event->destroy(event); release_bp_slot() arch_unregister_hw_breakpoint() perf_event_exit_task_context() sets child_ctx->task as TASK_TOMBSTONE which is (void *)-1. arch_unregister_hw_breakpoint() tries to fetch 'thread' attribute of 'task' resulting in oops. Peterz points out that the code shouldn't be using bp->ctx anyway, but fixing that will require a decent amount of rework. So for now to fix the oops, check if bp->ctx->task has been set to (void *)-1, before dereferencing it. We don't use TASK_TOMBSTONE, because that would require exporting it and it's supposed to be an internal detail. Fixes: 63b6da39bb38 ("perf: Fix perf_event_exit_task() race") Signed-off-by: Ravi Bangoria Acked-by: Peter Zijlstra (Intel) Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/hw_breakpoint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index 05e804cdecaa..aec9a1b1d25b 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -109,8 +109,9 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp) * If the breakpoint is unregistered between a hw_breakpoint_handler() * and the single_step_dabr_instruction(), then cleanup the breakpoint * restoration variables to prevent dangling pointers. + * FIXME, this should not be using bp->ctx at all! Sayeth peterz. */ - if (bp->ctx && bp->ctx->task) + if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L)) bp->ctx->task->thread.last_hit_ubp = NULL; } -- cgit v1.2.3 From 37c5e942bb2eedd98c1cd1fa1f94d79f6b830c38 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Wed, 2 Mar 2016 22:51:04 -0600 Subject: powerpc/fsl-book3e: Avoid lbarx on e5500 lbarx/stbcx. are implemented on e6500, but not on e5500. Likewise, SMT is on e6500, but not on e5500. So, avoid executing an unimplemented instruction by only locking when needed (i.e. in the presence of SMT). Signed-off-by: Scott Wood --- arch/powerpc/mm/hugetlbpage-book3e.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/mm/hugetlbpage-book3e.c b/arch/powerpc/mm/hugetlbpage-book3e.c index 7e6d0880813f..83a8be791e06 100644 --- a/arch/powerpc/mm/hugetlbpage-book3e.c +++ b/arch/powerpc/mm/hugetlbpage-book3e.c @@ -8,6 +8,8 @@ #include #include +#include + #ifdef CONFIG_PPC_FSL_BOOK3E #ifdef CONFIG_PPC64 static inline int tlb1_next(void) @@ -60,6 +62,14 @@ static inline void book3e_tlb_lock(void) unsigned long tmp; int token = smp_processor_id() + 1; + /* + * Besides being unnecessary in the absence of SMT, this + * check prevents trying to do lbarx/stbcx. on e5500 which + * doesn't implement either feature. + */ + if (!cpu_has_feature(CPU_FTR_SMT)) + return; + asm volatile("1: lbarx %0, 0, %1;" "cmpwi %0, 0;" "bne 2f;" @@ -80,6 +90,9 @@ static inline void book3e_tlb_unlock(void) { struct paca_struct *paca = get_paca(); + if (!cpu_has_feature(CPU_FTR_SMT)) + return; + isync(); paca->tcd_ptr->lock = 0; } -- cgit v1.2.3