From patchwork Tue Dec 12 11:39:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Torsten Duwe X-Patchwork-Id: 847457 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ywydc1MK7z9s81 for ; Tue, 12 Dec 2017 22:43:48 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3ywydb6jqszDrVZ for ; Tue, 12 Dec 2017 22:43:47 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lst.de (client-ip=213.95.11.211; helo=newverein.lst.de; envelope-from=duwe@lst.de; receiver=) Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3ywyXQ6TWmzDqmM for ; Tue, 12 Dec 2017 22:39:16 +1100 (AEDT) Received: by newverein.lst.de (Postfix, from userid 2005) id BCDD368B01; Tue, 12 Dec 2017 12:39:12 +0100 (CET) Date: Tue, 12 Dec 2017 12:39:12 +0100 From: Torsten Duwe To: Michael Ellerman , Jiri Kosina Subject: [PATCH] On ppc64le we HAVE_RELIABLE_STACKTRACE Message-ID: <20171212113912.GA1907@lst.de> References: <20171004152516.25803-1-kamalesh@linux.vnet.ibm.com> <20171005124313.GA25100@lst.de> <9f388c9a-8d74-865a-b113-f77322918b39@linux.vnet.ibm.com> <20171017144733.GB2136@lst.de> <95e6f942-88b7-0208-0eb0-2f5462aec410@linux.vnet.ibm.com> <20171020120739.GA20306@lst.de> <1508547548.5662.2.camel@gmail.com> <39bb7180-1adf-4df6-c9ba-c6f92754767f@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <39bb7180-1adf-4df6-c9ba-c6f92754767f@linux.vnet.ibm.com> User-Agent: Mutt/1.5.17 (2007-11-01) X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: live-patching@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Hi all, The "Power Architecture 64-Bit ELF V2 ABI" says in section 2.3.2.3: [...] There are several rules that must be adhered to in order to ensure reliable and consistent call chain backtracing: * Before a function calls any other function, it shall establish its own stack frame, whose size shall be a multiple of 16 bytes. – In instances where a function’s prologue creates a stack frame, the back-chain word of the stack frame shall be updated atomically with the value of the stack pointer (r1) when a back chain is implemented. (This must be supported as default by all ELF V2 ABI-compliant environments.) [...] – The function shall save the link register that contains its return address in the LR save doubleword of its caller’s stack frame before calling another function. To me this sounds like the equivalent of HAVE_RELIABLE_STACKTRACE. This patch may be unneccessarily limited to ppc64le, but OTOH the only user of this flag so far is livepatching, which is only implemented on PPCs with 64-LE, a.k.a. ELF ABI v2. Signed-off-by: Torsten Duwe diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c51e6ce42e7a..3e3a6ab2e089 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -218,6 +218,7 @@ config PPC select HAVE_PERF_USER_STACK_DUMP select HAVE_RCU_TABLE_FREE if SMP select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RELIABLE_STACKTRACE if PPC64 && CPU_LITTLE_ENDIAN select HAVE_SYSCALL_TRACEPOINTS select HAVE_VIRT_CPU_ACCOUNTING select HAVE_IRQ_TIME_ACCOUNTING From patchwork Tue Feb 27 16:09:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Torsten Duwe X-Patchwork-Id: 878672 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zrNx51Gksz9s1B for ; Wed, 28 Feb 2018 03:11:37 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lst.de Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3zrNx46h0DzF1Vd for ; Wed, 28 Feb 2018 03:11:36 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=lst.de X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lst.de (client-ip=213.95.11.211; helo=newverein.lst.de; envelope-from=duwe@lst.de; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=lst.de Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3zrNtl0K31zF1JT for ; Wed, 28 Feb 2018 03:09:27 +1100 (AEDT) Received: by newverein.lst.de (Postfix, from userid 2005) id 3408E68DBB; Tue, 27 Feb 2018 17:09:24 +0100 (CET) Date: Tue, 27 Feb 2018 17:09:24 +0100 From: Torsten Duwe To: Miroslav Benes Subject: [PATCH 2/2] ppc64le save_stack_trace_tsk_reliable (Was: HAVE_RELIABLE_STACKTRACE) Message-ID: <20180227160924.GA19111@lst.de> References: <20171004152516.25803-1-kamalesh@linux.vnet.ibm.com> <20171005124313.GA25100@lst.de> <9f388c9a-8d74-865a-b113-f77322918b39@linux.vnet.ibm.com> <20171017144733.GB2136@lst.de> <95e6f942-88b7-0208-0eb0-2f5462aec410@linux.vnet.ibm.com> <20171020120739.GA20306@lst.de> <1508547548.5662.2.camel@gmail.com> <39bb7180-1adf-4df6-c9ba-c6f92754767f@linux.vnet.ibm.com> <20171212113912.GA1907@lst.de> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.17 (2007-11-01) X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-kernel@vger.kernel.org, Jiri Kosina , live-patching@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" On Tue, Dec 12, 2017 at 01:12:37PM +0100, Miroslav Benes wrote: > > I think that this is not enough. You need to also implement > save_stack_trace_tsk_reliable() for powerpc defined as __weak in > kernel/stacktrace.c. So here is my initial proposal. I'd really like to get the successful exit stricter, i.e. hit the initial stack value exactly instead of just a window. Also, the check for kernel code looks clumsy IMHO. IOW: Comments more than welcome! Most of it is Copy&Waste, nonetheless: Signed-off-by: Torsten Duwe Acked-by: Balbir Singh diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index d534ed901538..e08af49e71d0 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -76,3 +77,58 @@ save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) save_context_stack(trace, regs->gpr[1], current, 0); } EXPORT_SYMBOL_GPL(save_stack_trace_regs); + +#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE +int +save_stack_trace_tsk_reliable(struct task_struct *tsk, + struct stack_trace *trace) +{ + unsigned long sp; + unsigned long stack_page = (unsigned long)task_stack_page(tsk); + /* the last frame (unwinding first) may not yet have saved its LR onto the stack. */ + int firstframe = 1; + + if (tsk == current) + sp = current_stack_pointer(); + else + sp = tsk->thread.ksp; + + if (sp < stack_page + sizeof(struct thread_struct) + || sp > stack_page + THREAD_SIZE - STACK_FRAME_OVERHEAD) + return 1; + + for (;;) { + unsigned long *stack = (unsigned long *) sp; + unsigned long newsp, ip; + + newsp = stack[0]; + /* Stack grows downwards; unwinder may only go up */ + if (newsp <= sp) + return 1; + + if (newsp >= stack_page + THREAD_SIZE) + return 1; /* invalid backlink, too far up! */ + + /* Examine the saved LR: it must point into kernel code. */ + ip = stack[STACK_FRAME_LR_SAVE]; + if ( (ip & 0xEFFF000000000000) != CONFIG_KERNEL_START + && !firstframe) + return 1; + firstframe = 0; + + if (!trace->skip) + trace->entries[trace->nr_entries++] = ip; + else + trace->skip--; + + if (newsp > stack_page + THREAD_SIZE - STACK_FRAME_OVERHEAD) + break; /* hit the window for last frame */ + + if (trace->nr_entries >= trace->max_entries) + return -E2BIG; + + sp = newsp; + } + return 0; +} +#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */