> Date: Sun, 29 Mar 2020 19:59:02 -0400
> From: George Koehler <kern...@gmail.com>
> 
> Here is a new diff for macppc's ofw_stack() problem, without using
> __attribute__((noinline)).  I use this diff to build and run a macppc
> kernel with clang.  It also works with gcc.
> 
> The kernel did 3 steps to prepare an Open Firmware call:
>   1. turn off interrupts (EE and RI in msr)
>   2. move the stack pointer %r1 to firmstk
>   3. switch to Open Firmware's pmap?
> 
> I don't understand these steps, but I tried to preserve all 3 steps as
> I shuffled the code.  The diff doesn't touch step 3.
> 
> The problem was at step 2: ofw_stack() copied the caller's stack frame
> to firmstk, and changed the caller's return address to ofw_back (which
> will restore the old %r1 and msr).  If clang inlines the caller into
> another function, then ofw_back would run too late.  I move step 2
> into openfirmware(), so there is no more copying a stack frame nor
> hijacking a return address.   (I claim that firmstk+NBPG-16 is a
> multiple of 16; that mtctr,bctrl is more idiomatic than mtlr,blrl.)
> 
> ofw_stack() becomes s = ofw_msr() and only does step 1, turning off EE
> and RI in msr.  ppc_mtmsr(s) restores the saved msr.  I don't use
> intr_disable() because it turns off only EE, not RI.  I changed
> OF_call_method*() to turn off EE (external interrupts) before they
> touch their static args.  Some functions, like OF_boot() and
> OF_quiesce(), seem unused, so I can't know if my changes are correct.
> 
> To build a kernel with clang, I do
> # make CC=clang COMPILER_VERSION=clang
> 
> Is this OK to commit?  Would it be better to use intr_disable() in
> OF_*() and turn off RI in ofwreal.S fwentry?

I think we could actually do everything in openfirm().  But lets worry
about that later.  This works and gets us moving forward.

ok kettenis@

P.S. Userland seems to be in good shape as well.  I built and rebuilt
     the world with clang.  That was on a kernel built with gcc, so
     I'm repeating that now with a kernel built with clang.

> Index: ofw_machdep.h
> ===================================================================
> RCS file: /cvs/src/sys/arch/macppc/macppc/ofw_machdep.h,v
> retrieving revision 1.9
> diff -u -p -r1.9 ofw_machdep.h
> --- ofw_machdep.h     7 Apr 2015 14:36:34 -0000       1.9
> +++ ofw_machdep.h     29 Mar 2020 16:16:27 -0000
> @@ -26,6 +26,9 @@
>   *
>   */
>  
> +#include <machine/cpu.h>
> +#include <machine/psl.h>
> +
>  extern int cons_backlight_available;
>  
>  void ofwconprobe(void);
> @@ -49,3 +52,12 @@ void of_setbrightness(int);
>  void of_setcolors(const uint8_t *, unsigned int, unsigned int);
>  
>  void OF_quiesce(void);
> +
> +static inline uint32_t
> +ofw_msr(void)
> +{
> +     uint32_t s = ppc_mfmsr();
> +
> +     ppc_mtmsr(s & ~(PSL_EE|PSL_RI)); /* turn off interrupts */
> +     return s;
> +}
> Index: ofwreal.S
> ===================================================================
> RCS file: /cvs/src/sys/arch/macppc/macppc/ofwreal.S,v
> retrieving revision 1.5
> diff -u -p -r1.5 ofwreal.S
> --- ofwreal.S 3 Sep 2019 14:37:22 -0000       1.5
> +++ ofwreal.S 29 Mar 2020 16:16:27 -0000
> @@ -355,96 +355,32 @@ _ENTRY(_C_LABEL(fwentry))
>       addi    %r1,%r1,16
>       blr
>  
> +.lcomm       firmstk,NBPG,16
> +.comm        _C_LABEL(OF_buf),NBPG
> +
>  /*
>   * OpenFirmware entry point
> + *
> + * Note: caller has to set the machine state register (msr)
> + * to be correct for OpenFirmware.
>   */
>  _ENTRY(_C_LABEL(openfirmware))
> -     stwu    %r1,-16(%r1)
> -     mflr    %r0                     /* save return address */
> -     stw     %r0,20(%r1)
> +     mflr    %r0
> +     stw     %r0,4(%r1)              /* save return address */
> +
> +     /* switch to OpenFirmware real mode stack */
> +     lis     %r7,firmstk+NBPG-16@ha
> +     addi    %r7,%r7,firmstk+NBPG-16@l
> +     stw     %r1,0(%r7)
> +     mr      %r1,%r7
>  
>       lis     %r4,fwcall@ha
>       lwz     %r4,fwcall@l(%r4)
>  
> -     mtlr    %r4
> -     blrl
> -
> -     lwz     %r0,20(%r1)
> -     mtlr    %r0
> -     lwz     %r1,0(%r1)
> -     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;
> - * }
> - */
> -.lcomm       firmstk,NBPG,16
> -.comm        _C_LABEL(OF_buf),NBPG
> -
> -_ENTRY(_C_LABEL(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
> -     li      %r6,0xf
> -     andc    %r7,%r7,%r6
> -     lis     %r6,ofw_back@ha
> -     addi    %r6,%r6,ofw_back@l
> -     subf    %r4,%r5,%r7             /* make room for stack frame on new 
> stack */
> -     stwu    %r1,-16(%r7)
> -     stw     %r6,4(%r7)              /* setup return pointer */
> +     mtctr   %r4
> +     bctrl
>  
> -     stw     %r7,-16(%r4)
> -
> -     addi    %r3,%r1,%r8
> -     addi    %r1,%r4,-16
> -     subi    %r5,%r5,%r8
> -     subi    %r4,%r4,%r8
> -
> -     b       _C_LABEL(ofbcopy)       /* and copy it */
> -
> -     .type ofw_back,@function
> -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
> -
> Index: opendev.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/macppc/macppc/opendev.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 opendev.c
> --- opendev.c 9 Mar 2006 23:06:19 -0000       1.9
> +++ opendev.c 29 Mar 2020 16:16:27 -0000
> @@ -34,11 +34,12 @@
>  #include <sys/param.h>
>  #include <sys/systm.h>
>  #include <sys/stdarg.h>
> +#include <machine/cpu.h>
>  #include <machine/psl.h>
>  
>  #include <dev/ofw/openfirm.h>
> +#include "ofw_machdep.h"
>  
> -extern void ofw_stack(void);
>  extern void ofbcopy(const void *, void *, size_t);
>  
>  int
> @@ -55,12 +56,17 @@ OF_instance_to_package(int ihandle)
>               1,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.ihandle = ihandle;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     return args.phandle;
> +             ret = -1;
> +     else
> +             ret = args.phandle;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -79,18 +85,24 @@ OF_package_to_path(int phandle, char *bu
>               3,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
>       if (buflen > PAGE_SIZE)
>               return -1;
> +     s = ofw_msr();
>       args.phandle = phandle;
>       args.buf = OF_buf;
>       args.buflen = buflen;
>       if (openfirmware(&args) < 0)
> -             return -1;
> -     if (args.length > 0)
> -             ofbcopy(OF_buf, buf, args.length);
> -     return args.length;
> +             ret = -1;
> +     else {
> +             if (args.length > 0)
> +                     ofbcopy(OF_buf, buf, args.length);
> +             ret = args.length;
> +     }
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  
> @@ -110,10 +122,12 @@ OF_call_method(char *method, int ihandle
>               2,
>               1,
>       };
> -     int *ip, n;
> +     uint32_t s;
> +     int *ip, n, ret;
>  
>       if (nargs > 6)
>               return -1;
> +     s = ofw_msr();
>       args.nargs = nargs + 2;
>       args.nreturns = nreturns + 1;
>       args.method = method;
> @@ -121,19 +135,19 @@ OF_call_method(char *method, int ihandle
>       va_start(ap, nreturns);
>       for (ip = args.args_n_results + (n = nargs); --n >= 0;)
>               *--ip = va_arg(ap, int);
> -     ofw_stack();
> -     if (openfirmware(&args) == -1) {
> -             va_end(ap);
> -             return -1;
> -     }
> -     if (args.args_n_results[nargs]) {
> -             va_end(ap);
> -             return args.args_n_results[nargs];
> +     if (openfirmware(&args) == -1)
> +             ret = -1;
> +     else if (args.args_n_results[nargs])
> +             ret = args.args_n_results[nargs];
> +     else {
> +             for (ip = args.args_n_results + nargs + (n = args.nreturns);
> +                 --n > 0;)
> +                     *va_arg(ap, int *) = *--ip;
> +             ret = 0;
>       }
> -     for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
> -             *va_arg(ap, int *) = *--ip;
>       va_end(ap);
> -     return 0;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  int
>  OF_call_method_1(char *method, int ihandle, int nargs, ...)
> @@ -151,10 +165,12 @@ OF_call_method_1(char *method, int ihand
>               2,
>               2,
>       };
> -     int *ip, n;
> +     uint32_t s;
> +     int *ip, n, ret;
>  
>       if (nargs > 6)
>               return -1;
> +     s = ofw_msr();
>       args.nargs = nargs + 2;
>       args.method = method;
>       args.ihandle = ihandle;
> @@ -162,12 +178,14 @@ OF_call_method_1(char *method, int ihand
>       for (ip = args.args_n_results + (n = nargs); --n >= 0;)
>               *--ip = va_arg(ap, int);
>       va_end(ap);
> -     ofw_stack();
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     if (args.args_n_results[nargs])
> -             return -1;
> -     return args.args_n_results[nargs + 1];
> +             ret = -1;
> +     else if (args.args_n_results[nargs])
> +             ret = -1;
> +     else
> +             ret = args.args_n_results[nargs + 1];
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -184,16 +202,20 @@ OF_open(char *dname)
>               1,
>               1,
>       };
> -     int l;
> +     uint32_t s;
> +     int l, ret;
>  
> -     ofw_stack();
>       if ((l = strlen(dname)) >= PAGE_SIZE)
>               return -1;
> +     s = ofw_msr();
>       ofbcopy(dname, OF_buf, l + 1);
>       args.dname = OF_buf;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     return args.handle;
> +             ret = -1;
> +     else
> +             ret = args.handle;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  void
> @@ -209,10 +231,12 @@ OF_close(int handle)
>               1,
>               0,
>       };
> +     uint32_t s;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.handle = handle;
>       openfirmware(&args);
> +     ppc_mtmsr(s);
>  }
>  
>  /*
> @@ -234,28 +258,35 @@ OF_read(int handle, void *addr, int len)
>               3,
>               1,
>       };
> -     int l, act = 0;
> +     uint32_t s;
> +     int act = 0, l, ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.ihandle = handle;
>       args.addr = OF_buf;
>       for (; len > 0; len -= l, addr += l) {
>               l = min(PAGE_SIZE, len);
>               args.len = l;
> -             if (openfirmware(&args) == -1)
> -                     return -1;
> +             if (openfirmware(&args) == -1) {
> +                     ret = -1;
> +                     goto out;
> +             }
>               if (args.actual > 0) {
>                       ofbcopy(OF_buf, addr, args.actual);
>                       act += args.actual;
>               }
>               if (args.actual < l) {
>                       if (act)
> -                             return act;
> +                             ret = act;
>                       else
> -                             return args.actual;
> +                             ret = args.actual;
> +                     goto out;
>               }
>       }
> -     return act;
> +     ret = act;
> +out:
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -274,21 +305,27 @@ OF_write(int handle, void *addr, int len
>               3,
>               1,
>       };
> -     int l, act = 0;
> +     uint32_t s;
> +     int act = 0, l, ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.ihandle = handle;
>       args.addr = OF_buf;
>       for (; len > 0; len -= l, addr += l) {
>               l = min(PAGE_SIZE, len);
>               ofbcopy(addr, OF_buf, l);
>               args.len = l;
> -             if (openfirmware(&args) == -1)
> -                     return -1;
> +             if (openfirmware(&args) == -1) {
> +                     ret = -1;
> +                     goto out;
> +             }
>               l = args.actual;
>               act += l;
>       }
> -     return act;
> +     ret = act;
> +out:
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -307,12 +344,17 @@ OF_seek(int handle, u_quad_t pos)
>               3,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.handle = handle;
>       args.poshi = (int)(pos >> 32);
>       args.poslo = (int)pos;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     return args.status;
> +             ret = -1;
> +     else
> +             ret = args.status;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
> Index: openfirm.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/macppc/macppc/openfirm.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 openfirm.c
> --- openfirm.c        3 Sep 2019 17:51:52 -0000       1.12
> +++ openfirm.c        29 Mar 2020 16:16:27 -0000
> @@ -34,11 +34,12 @@
>  #include <sys/param.h>
>  #include <sys/systm.h>
>  #include <sys/stdarg.h>
> +#include <machine/cpu.h>
>  #include <machine/psl.h>
>  
>  #include <dev/ofw/openfirm.h>
> +#include "ofw_machdep.h"
>  
> -extern void ofw_stack(void);
>  extern void ofbcopy(const void *, void *, size_t);
>  
>  int
> @@ -55,12 +56,17 @@ OF_peer(int phandle)
>               1,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.phandle = phandle;
>       if (openfirmware(&args) == -1)
> -             return 0;
> -     return args.sibling;
> +             ret = 0;
> +     else
> +             ret = args.sibling;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -77,12 +83,17 @@ OF_child(int phandle)
>               1,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.phandle = phandle;
>       if (openfirmware(&args) == -1)
> -             return 0;
> -     return args.child;
> +             ret = 0;
> +     else
> +             ret = args.child;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -99,12 +110,17 @@ OF_parent(int phandle)
>               1,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.phandle = phandle;
>       if (openfirmware(&args) == -1)
> -             return 0;
> -     return args.parent;
> +             ret = 0;
> +     else
> +             ret = args.parent;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -122,13 +138,18 @@ OF_getproplen(int handle, char *prop)
>               2,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.phandle = handle;
>       args.prop = prop;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     return args.size;
> +             ret = -1;
> +     else
> +             ret = args.size;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -148,19 +169,25 @@ OF_getprop(int handle, char *prop, void 
>               4,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
>       if (buflen > NBPG)
>               return -1;
> +     s = ofw_msr();
>       args.phandle = handle;
>       args.prop = prop;
>       args.buf = OF_buf;
>       args.buflen = buflen;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     if (args.size > 0)
> -             ofbcopy(OF_buf, buf, args.size);
> -     return args.size;
> +             ret = -1;
> +     else {
> +             if (args.size > 0)
> +                     ofbcopy(OF_buf, buf, args.size);
> +             ret = args.size;
> +     }
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -180,18 +207,23 @@ OF_setprop(int handle, char *prop, const
>               4,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>       
> -     ofw_stack();
>       if (buflen > NBPG)
>               return -1;
> +     s = ofw_msr();
>       args.phandle = handle;
>       args.prop = prop;
>       ofbcopy(buf, OF_buf, buflen);
>       args.buf = OF_buf;
>       args.buflen = buflen;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     return args.size;
> +             ret = -1;
> +     else
> +             ret = args.size;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
> @@ -210,22 +242,27 @@ OF_nextprop(int handle, char *prop, void
>               3,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.phandle = handle;
>       args.prop = prop;
>       args.buf = OF_buf;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     strlcpy(nextprop, OF_buf, 32);
> -     return args.flag;
> +             ret = -1;
> +     else {
> +             strlcpy(nextprop, OF_buf, 32);
> +             ret = args.flag;
> +     }
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  int
>  OF_interpret(char *cmd, int nreturns, ...)
>  {
>       va_list ap;
> -     int i;
>       static struct {
>               char *name;
>               int nargs;
> @@ -238,23 +275,29 @@ OF_interpret(char *cmd, int nreturns, ..
>               1,
>               2,
>       };
> +     uint32_t s;
> +     int i, ret;
>  
> -     ofw_stack();
>       if (nreturns > 8)
>               return -1;
>       if ((i = strlen(cmd)) >= NBPG)
>               return -1;
> +     s = ofw_msr();
>       ofbcopy(cmd, OF_buf, i + 1);
>       args.cmd = OF_buf;
>       args.nargs = 1;
>       args.nreturns = nreturns + 1;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     va_start(ap, nreturns);
> -     for (i = 0; i < nreturns; i++)
> -             *va_arg(ap, int *) = args.results[i];
> -     va_end(ap);
> -     return args.status;
> +             ret = -1;
> +     else {
> +             va_start(ap, nreturns);
> +             for (i = 0; i < nreturns; i++)
> +                     *va_arg(ap, int *) = args.results[i];
> +             va_end(ap);
> +             ret = args.status;
> +     }
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  
>  
> @@ -272,12 +315,17 @@ OF_finddevice(char *name)
>               1,
>               1,
>       };
> +     uint32_t s;
> +     int ret;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       args.device = name;
>       if (openfirmware(&args) == -1)
> -             return -1;
> -     return args.phandle;
> +             ret = -1;
> +     else
> +             ret = args.phandle;
> +     ppc_mtmsr(s);
> +     return ret;
>  }
>  static void OF_rboot(char *bootspec);
>  
> @@ -293,12 +341,14 @@ OF_rboot(char *bootspec)
>               0,
>               0,
>       };
> +     uint32_t s;
>       int l;
>  
>       if ((l = strlen(bootspec)) >= NBPG)
>               panic("OF_boot");
> -     ofw_stack();
> +     s = ofw_msr();
>       openfirmware(&args);
> +     ppc_mtmsr(s);
>       /* will attempt exit in OF_boot */
>  }
>  
> @@ -325,7 +375,7 @@ OF_exit(void)
>               0,
>       };
>  
> -     ofw_stack();
> +     ofw_msr();
>       openfirmware(&args);
>       panic ("OF_exit returned!");            /* just in case */
>       while (1);
> @@ -343,9 +393,11 @@ OF_quiesce(void)
>               0,
>               0,
>       };
> +     uint32_t s;
>  
> -     ofw_stack();
> +     s = ofw_msr();
>       openfirmware(&args);
> +     ppc_mtmsr(s);
>  }
>  
>  /* XXX What is the reason to have this instead of bcopy/memcpy? */
> 

Reply via email to