Module Name: src Committed By: jdc Date: Thu Aug 9 06:52:14 UTC 2012
Modified Files: src/sys/arch/powerpc/booke [netbsd-6]: genassym.cf trap_subr.S src/sys/arch/powerpc/include [netbsd-6]: frame.h Log Message: Pull up revisions: src/sys/arch/powerpc/booke/genassym.cf revision 1.9 src/sys/arch/powerpc/booke/trap_subr.S revision 1.8 src/sys/arch/powerpc/include/frame.h revision 1.25 (requested by matt in ticket #461). Fix a problem where the kernel could randomly reset due to a watchdog event. When an exception happens, the srr0 (exception PC) was being saved in the normal location of the current callframe. This was fine except when the routine was in its prologue after it had saved LR but had not yet updated the stack pointer or when the routine was in its epilogue after it has restored the stack pointer but not yet loaded the LR. In either case this would cause the LR to be corrupted (either running the routine forever or by branching to itself forever). Now we save and restore the contents of that memory location so the corruption can't happen. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.8.8.1 src/sys/arch/powerpc/booke/genassym.cf cvs rdiff -u -r1.6 -r1.6.8.1 src/sys/arch/powerpc/booke/trap_subr.S cvs rdiff -u -r1.23 -r1.23.8.1 src/sys/arch/powerpc/include/frame.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/powerpc/booke/genassym.cf diff -u src/sys/arch/powerpc/booke/genassym.cf:1.8 src/sys/arch/powerpc/booke/genassym.cf:1.8.8.1 --- src/sys/arch/powerpc/booke/genassym.cf:1.8 Wed Jun 29 06:06:04 2011 +++ src/sys/arch/powerpc/booke/genassym.cf Thu Aug 9 06:52:14 2012 @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.8 2011/06/29 06:06:04 matt Exp $ +# $NetBSD: genassym.cf,v 1.8.8.1 2012/08/09 06:52:14 jdc Exp $ #- # Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. @@ -61,6 +61,7 @@ define FRAME_MCSR offsetof(struct ktrapf define FRAME_MCAR offsetof(struct ktrapframe, ktf_tf.tf_mcar) define FRAME_SPRG1 offsetof(struct ktrapframe, ktf_tf.tf_sprg1) define FRAME_SPEFSCR offsetof(struct ktrapframe, ktf_tf.tf_spefscr) +define FRAME_CFRAME_LR offsetof(struct ktrapframe, ktf_cframe_lr) define CI_SAVELIFO offsetof(struct cpu_info, ci_savearea[0]) define CI_PMAP_SEGTAB offsetof(struct cpu_info, ci_pmap_segtabs[0]) Index: src/sys/arch/powerpc/booke/trap_subr.S diff -u src/sys/arch/powerpc/booke/trap_subr.S:1.6 src/sys/arch/powerpc/booke/trap_subr.S:1.6.8.1 --- src/sys/arch/powerpc/booke/trap_subr.S:1.6 Tue Jun 21 05:33:04 2011 +++ src/sys/arch/powerpc/booke/trap_subr.S Thu Aug 9 06:52:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: trap_subr.S,v 1.6 2011/06/21 05:33:04 matt Exp $ */ +/* $NetBSD: trap_subr.S,v 1.6.8.1 2012/08/09 06:52:14 jdc Exp $ */ /*- * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. * All rights reserved. @@ -34,7 +34,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -RCSID("$NetBSD: trap_subr.S,v 1.6 2011/06/21 05:33:04 matt Exp $") +RCSID("$NetBSD: trap_subr.S,v 1.6.8.1 2012/08/09 06:52:14 jdc Exp $") .globl _C_LABEL(sctrapexit), _C_LABEL(trapexit), _C_LABEL(intrcall) @@ -137,14 +137,24 @@ RCSID("$NetBSD: trap_subr.S,v 1.6 2011/0 /* * DDB expects to fetch the LR from the previous frame. But it also * expects to be pointing at the instruction after the branch link. Since - * we didn't branch, we need to advance it by to fake out DDB. + * we didn't branch, we need to advance it by to fake out DDB. But there's + * problem. If the routine is in either its first or last two instructions + * (before or after its adjusted its stack pointer), we could possibly + * overwrite stored return address. So that stored return address needs to + * saved and restored. */ -#ifdef DDB +#if defined(DDB) #define FRAME_SAVE_SRR0_FOR_DDB \ - addi %r30, %r30, 4; /* ddb thinks its the next insn */ \ - stw %r30, FRAMELEN+SZREG(%r1); /* appease ddb stacktrace */ + lwz %r29, FRAMELEN+CFRAME_LR(%r1); /* fetch old return address */\ + stw %r29, FRAME_CFRAME_LR(%r1); /* save it */ \ + addi %r30, %r30, 4; /* point to s the next insn */ \ + stw %r30, FRAMELEN+CFRAME_LR(%r1) /* appease ddb stacktrace */ +#define FRAME_RESTORE_RETURN_ADDRESS \ + lwz %r3, FRAME_CFRAME_LR(%r1); /* fetch old return address */ \ + stw %r3, FRAMELEN+CFRAME_LR(%r1) /* restore it */ #else #define FRAME_SAVE_SRR0_FOR_DDB +#define FRAME_RESTORE_RETURN_ADDRESS #endif #ifdef PPC_HAVE_SPE @@ -175,7 +185,6 @@ RCSID("$NetBSD: trap_subr.S,v 1.6 2011/0 addi %r1, %r2, USPACE-CALLFRAMELEN; \ /* start stack at top of it */ \ 1: \ - stw %r30, CFRAME_LR(%r1); /* save in previous callframe */ \ stwu %r31, -FRAMELEN(%r1); /* get space for trapframe */ \ stw %r0, FRAME_R0(%r1); /* save r0 */ \ stw %r31, FRAME_R1(%r1); /* save (saved) r1 */ \ @@ -203,6 +212,7 @@ RCSID("$NetBSD: trap_subr.S,v 1.6 2011/0 addi tf, %r1, FRAME_TF /* get address of trap frame */ #define FRAME_EXC_EXIT(rfi, srr) \ + FRAME_RESTORE_RETURN_ADDRESS; /* restore return address */ \ lmw %r26, FRAME_LR(%r1); /* get LR CR XER CTR SRR0/1 */ \ oris %r31,%r31,PSL_CE@h; \ mtspr SPR_##srr##1, %r31; /* restore SRR1 */ \ @@ -262,7 +272,6 @@ RCSID("$NetBSD: trap_subr.S,v 1.6 2011/0 mtcr %r31; /* user mode exception? */ \ mr %r31, %r1; /* save SP (SRR1 is safe in CR) */ \ get_intr_sp; /* get kernel stack pointer */ \ - stw %r30, CFRAME_LR(%r1); /* save in .. */ \ stwu %r31, -FRAMELEN(%r1); /* get space for trapframe */ \ stw %r0, FRAME_R0(%r1); /* save r0 */ \ stw %r31, FRAME_R1(%r1); /* save (saved) r1 */ \ @@ -294,6 +303,7 @@ RCSID("$NetBSD: trap_subr.S,v 1.6 2011/0 addi %r3, %r1, FRAME_TF /* only argument is trapframe */ #define FRAME_INTR_XEXIT(rfi, srr) \ + FRAME_RESTORE_RETURN_ADDRESS; /* restore return address */ \ lwz %r8, FRAME_LR(%r1); /* get LR */ \ lwz %r9, FRAME_CR(%r1); /* get CR */ \ lwz %r10, FRAME_XER(%r1); /* get XER */ \ Index: src/sys/arch/powerpc/include/frame.h diff -u src/sys/arch/powerpc/include/frame.h:1.23 src/sys/arch/powerpc/include/frame.h:1.23.8.1 --- src/sys/arch/powerpc/include/frame.h:1.23 Mon Jun 20 07:31:18 2011 +++ src/sys/arch/powerpc/include/frame.h Thu Aug 9 06:52:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: frame.h,v 1.23 2011/06/20 07:31:18 matt Exp $ */ +/* $NetBSD: frame.h,v 1.23.8.1 2012/08/09 06:52:14 jdc Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -113,6 +113,7 @@ struct ktrapframe { register_t ktf_sp; register_t ktf_lr; struct trapframe ktf_tf; + register_t ktf_cframe_lr; /* for DDB */ }; #if defined(_KERNEL) || defined(_LKM)