Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-6]: src/sys/arch/powerpc Pull up revisions:



details:   https://anonhg.NetBSD.org/src/rev/898bae1bc5dd
branches:  netbsd-6
changeset: 774397:898bae1bc5dd
user:      jdc <jdc%NetBSD.org@localhost>
date:      Thu Aug 09 06:52:14 2012 +0000

description:
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.

diffstat:

 sys/arch/powerpc/booke/genassym.cf |   3 ++-
 sys/arch/powerpc/booke/trap_subr.S |  26 ++++++++++++++++++--------
 sys/arch/powerpc/include/frame.h   |   3 ++-
 3 files changed, 22 insertions(+), 10 deletions(-)

diffs (113 lines):

diff -r 4b56d09307e6 -r 898bae1bc5dd sys/arch/powerpc/booke/genassym.cf
--- a/sys/arch/powerpc/booke/genassym.cf        Thu Aug 09 06:49:23 2012 +0000
+++ b/sys/arch/powerpc/booke/genassym.cf        Thu Aug 09 06:52:14 2012 +0000
@@ -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_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])
diff -r 4b56d09307e6 -r 898bae1bc5dd sys/arch/powerpc/booke/trap_subr.S
--- a/sys/arch/powerpc/booke/trap_subr.S        Thu Aug 09 06:49:23 2012 +0000
+++ b/sys/arch/powerpc/booke/trap_subr.S        Thu Aug 09 06:52:14 2012 +0000
@@ -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 @@
 /*
  * 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 @@
        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 @@
        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 @@
        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 @@
        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 */                   \
diff -r 4b56d09307e6 -r 898bae1bc5dd sys/arch/powerpc/include/frame.h
--- a/sys/arch/powerpc/include/frame.h  Thu Aug 09 06:49:23 2012 +0000
+++ b/sys/arch/powerpc/include/frame.h  Thu Aug 09 06:52:14 2012 +0000
@@ -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 @@
        register_t ktf_sp;
        register_t ktf_lr;
        struct trapframe ktf_tf;
+       register_t ktf_cframe_lr;       /* for DDB */
 };
 
 #if defined(_KERNEL) || defined(_LKM)



Home | Main Index | Thread Index | Old Index