Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/powerpc - Don't change to the OFW stack in C code; ...



details:   https://anonhg.NetBSD.org/src/rev/4dbcac687eb7
branches:  trunk
changeset: 952320:4dbcac687eb7
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Feb 13 01:48:33 2021 +0000

description:
- Don't change to the OFW stack in C code; instead, switch to the OFW
  stack in the openfirmware() wrapper itself.  Inspired by a similar
  change in OpenBSD designed to appease clang.
- The OF_*() entry firmware interfaces use several global resources;
  protect those global resources with a __cpu_simple_lock_t.
- Make ofbcopy() static -- it's no longer referenced outside openfirm.c

diffstat:

 sys/arch/powerpc/oea/ofw_subr.S     |   91 +------
 sys/arch/powerpc/powerpc/openfirm.c |  405 ++++++++++++++++++++++++++---------
 2 files changed, 309 insertions(+), 187 deletions(-)

diffs (truncated from 870 to 300 lines):

diff -r f2109d00e4c8 -r 4dbcac687eb7 sys/arch/powerpc/oea/ofw_subr.S
--- a/sys/arch/powerpc/oea/ofw_subr.S   Sat Feb 13 01:11:58 2021 +0000
+++ b/sys/arch/powerpc/oea/ofw_subr.S   Sat Feb 13 01:48:33 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ofw_subr.S,v 1.12 2020/07/06 10:31:23 rin Exp $        */
+/*     $NetBSD: ofw_subr.S,v 1.13 2021/02/13 01:48:33 thorpej Exp $    */
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -103,9 +103,18 @@
  */
        .text
 ENTRY(openfirmware)
-       mflr    %r0                     /* save return address */
-       stw     %r0,4(%r1)
-       stwu    %r1,-32(%r1)            /* setup stack frame */
+       mflr    %r0
+       stw     %r0,4(%r1)              /* save return address */
+
+       /*
+        * Switch to OpenFirmware stack.
+        *
+        * -48 == -16 to stack old SP and align, -32 for save area
+        */
+       lis     %r7,firmstk+NBPG-48@ha
+       addi    %r7,%r7,firmstk+NBPG-48@l
+       stw     %r1,32(%r7)             /* stash away prev stack pointer */
+       mr      %r1,%r7
 
        lis     %r4,openfirmware_entry@ha       /* get firmware entry point */
        lwz     %r4,openfirmware_entry@l(%r4)
@@ -202,77 +211,7 @@
        lwz     %r5,28(%r1)
        mtsprg3 %r5
 
-       lwz     %r1,0(%r1)              /* and return */
-       lwz     %r0,4(%r1)
+       lwz     %r1,32(%r1)             /* restore previous stack pointer */
+       lwz     %r0,4(%r1)              /* return address */
        mtlr    %r0
        blr
-
-/*
- * Switch to/from OpenFirmware real mode stack
- *
- * Note: has to be called as the very first thing in OpenFirmware interface
- * routines.
- * E.g.:
- * int
- * OF_xxx(arg1, arg2)
- * type arg1, arg2;
- * {
- *     static struct {
- *             char *name;
- *             int nargs;
- *             int nreturns;
- *             char *method;
- *             int arg1;
- *             int arg2;
- *             int ret;
- *     } args = {
- *             "xxx",
- *             2,
- *             1,
- *     };
- *
- *     ofw_stack();
- *     args.arg1 = arg1;
- *     args.arg2 = arg2;
- *     if (openfirmware(&args) < 0)
- *             return -1;
- *     return args.ret;
- * }
- */
-
-ENTRY(ofw_stack)
-       mfmsr   %r8                     /* turn off interrupts */
-       andi.   %r0,%r8,~(PSL_EE|PSL_RI)@l
-       mtmsr   %r0
-       stw     %r8,4(%r1)              /* abuse return address slot */
-
-       lwz     %r5,0(%r1)              /* get length of stack frame */
-       subf    %r5,%r1,%r5
-
-       lis     %r7,firmstk+NBPG-8@ha
-       addi    %r7,%r7,firmstk+NBPG-8@l
-       lis     %r6,ofw_back@ha
-       addi    %r6,%r6,ofw_back@l
-       subf    %r4,%r5,%r7             /* make room for stack frame on
-                                          new stack */
-       stw     %r6,-4(%r7)             /* setup return pointer */
-       stwu    %r1,-8(%r7)
-
-       stw     %r7,-8(%r4)
-
-       addi    %r3,%r1,8
-       addi    %r1,%r4,-8
-       subi    %r5,%r5,8
-
-       b       _C_LABEL(ofbcopy)       /* and copy it */
-
-ofw_back:
-       lwz     %r1,0(%r1)              /* get callers original stack pointer */
-
-       lwz     %r0,4(%r1)              /* get saved msr from abused slot */
-       mtmsr   %r0
-
-       lwz     %r1,0(%r1)              /* return */
-       lwz     %r0,4(%r1)
-       mtlr    %r0
-       blr
diff -r f2109d00e4c8 -r 4dbcac687eb7 sys/arch/powerpc/powerpc/openfirm.c
--- a/sys/arch/powerpc/powerpc/openfirm.c       Sat Feb 13 01:11:58 2021 +0000
+++ b/sys/arch/powerpc/powerpc/openfirm.c       Sat Feb 13 01:48:33 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: openfirm.c,v 1.32 2021/02/05 00:06:11 thorpej Exp $    */
+/*     $NetBSD: openfirm.c,v 1.33 2021/02/13 01:48:33 thorpej Exp $    */
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.32 2021/02/05 00:06:11 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.33 2021/02/13 01:48:33 thorpej Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_multiprocessor.h"
@@ -50,11 +50,37 @@
 
 char *OF_buf;
 
-void ofw_stack(void);
-void ofbcopy(const void *, void *, size_t);
+static void ofbcopy(const void *, void *, size_t);
+
 #ifdef MULTIPROCESSOR
 void OF_start_cpu(int, u_int, int);
-#endif
+
+
+static __cpu_simple_lock_t ofw_mutex = __SIMPLELOCK_UNLOCKED;
+#endif /* MULTIPROCESSOR */
+
+static inline register_t
+ofw_lock(void)
+{
+       const register_t s = mfmsr();
+
+       mtmsr(s & ~(PSL_EE|PSL_RI));    /* disable interrupts */
+
+#ifdef MULTIPROCESSOR
+       __cpu_simple_lock(&ofw_mutex);
+#endif /* MULTIPROCESSOR */
+
+       return s;
+}
+
+static inline void
+ofw_unlock(register_t s)
+{
+#ifdef MULTIPROCESSOR
+       __cpu_simple_unlock(&ofw_mutex);
+#endif /* MULTIPROCESSOR */
+       mtmsr(s);
+}
 
 int
 OF_peer(int phandle)
@@ -71,11 +97,17 @@
                1,
        };
 
-       ofw_stack();
+       const register_t s = ofw_lock();
+       int rv;
+
        args.phandle = phandle;
        if (openfirmware(&args) == -1)
-               return 0;
-       return args.sibling;
+               rv = 0;
+       else
+               rv = args.sibling;
+
+       ofw_unlock(s);
+       return rv;
 }
 
 int
@@ -93,11 +125,17 @@
                1,
        };
 
-       ofw_stack();
+       const register_t s = ofw_lock();
+       int rv;
+
        args.phandle = phandle;
        if (openfirmware(&args) == -1)
-               return 0;
-       return args.child;
+               rv = 0;
+       else
+               rv = args.child;
+
+       ofw_unlock(s);
+       return rv;
 }
 
 int
@@ -115,11 +153,17 @@
                1,
        };
 
-       ofw_stack();
+       const register_t s = ofw_lock();
+       int rv;
+
        args.phandle = phandle;
        if (openfirmware(&args) == -1)
-               return 0;
-       return args.parent;
+               rv = 0;
+       else
+               rv = args.parent;
+
+       ofw_unlock(s);
+       return rv;
 }
 
 int
@@ -137,11 +181,17 @@
                1,
        };
 
-       ofw_stack();
+       const register_t s = ofw_lock();
+       int rv;
+
        args.ihandle = ihandle;
        if (openfirmware(&args) == -1)
-               return -1;
-       return args.phandle;
+               rv = -1;
+       else
+               rv = args.phandle;
+
+       ofw_unlock(s);
+       return rv;
 }
 
 int
@@ -160,13 +210,19 @@
                1,
        };
 
-       ofw_stack();
+       const register_t s = ofw_lock();
+       int rv;
+
        strncpy(OF_buf, prop, 32);
        args.phandle = handle;
        args.prop = OF_buf;
        if (openfirmware(&args) == -1)
-               return -1;
-       return args.proplen;
+               rv = -1;
+       else
+               rv = args.proplen;
+
+       ofw_unlock(s);
+       return rv;
 }
 
 int
@@ -187,21 +243,29 @@
                1,
        };
 
-       ofw_stack();
        if (buflen > PAGE_SIZE)
                return -1;
+
+       const register_t s = ofw_lock();
+       int rv;
+
        strncpy(OF_buf, prop, 32);
        args.phandle = handle;
        args.prop = OF_buf;
        args.buf = &OF_buf[33];
        args.buflen = buflen;
        if (openfirmware(&args) == -1)
-               return -1;
-       if (args.size > buflen)
-               args.size = buflen;
-       if (args.size > 0)
-               ofbcopy(&OF_buf[33], buf, args.size);
-       return args.size;



Home | Main Index | Thread Index | Old Index