diff options
author | gkoehler <gkoehler@cvs.openbsd.org> | 2020-04-02 19:27:52 +0000 |
---|---|---|
committer | gkoehler <gkoehler@cvs.openbsd.org> | 2020-04-02 19:27:52 +0000 |
commit | e938cf4d986f5223c38e7a0b1277de3cbecf3510 (patch) | |
tree | a72ea3555a46a33a4feec2db52afcec08c5bc6e2 /sys/arch | |
parent | edc1550759d95ccd1f83f7790a8946d0eacc8456 (diff) |
Make the OpenFirmware functions work with clang.
ofw_stack() was changing its caller's stack frame, but this stops
working when clang inlines the caller into another function. Move the
stack-switching logic into openfirmware(). Now ofw_stack() becomes
ofw_msr() and only sets the msr.
ok deraadt@ kettenis@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/macppc/macppc/ofw_machdep.h | 14 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/ofwreal.S | 98 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/opendev.c | 138 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/openfirm.c | 132 |
4 files changed, 212 insertions, 170 deletions
diff --git a/sys/arch/macppc/macppc/ofw_machdep.h b/sys/arch/macppc/macppc/ofw_machdep.h index 270aed5a525..1a62f71470c 100644 --- a/sys/arch/macppc/macppc/ofw_machdep.h +++ b/sys/arch/macppc/macppc/ofw_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ofw_machdep.h,v 1.9 2015/04/07 14:36:34 mpi Exp $ */ +/* $OpenBSD: ofw_machdep.h,v 1.10 2020/04/02 19:27:51 gkoehler Exp $ */ /* * Copyright (c) 2002, Miodrag Vallat. @@ -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; +} diff --git a/sys/arch/macppc/macppc/ofwreal.S b/sys/arch/macppc/macppc/ofwreal.S index 72418c797d0..61d703b23c3 100644 --- a/sys/arch/macppc/macppc/ofwreal.S +++ b/sys/arch/macppc/macppc/ofwreal.S @@ -1,4 +1,4 @@ -/* $OpenBSD: ofwreal.S,v 1.5 2019/09/03 14:37:22 deraadt Exp $ */ +/* $OpenBSD: ofwreal.S,v 1.6 2020/04/02 19:27:51 gkoehler Exp $ */ /* $NetBSD: ofwreal.S,v 1.1 1996/09/30 16:34:51 ws Exp $ */ /* @@ -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 - diff --git a/sys/arch/macppc/macppc/opendev.c b/sys/arch/macppc/macppc/opendev.c index 9394ac2fd12..f05aa76580e 100644 --- a/sys/arch/macppc/macppc/opendev.c +++ b/sys/arch/macppc/macppc/opendev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: opendev.c,v 1.9 2006/03/09 23:06:19 miod Exp $ */ +/* $OpenBSD: opendev.c,v 1.10 2020/04/02 19:27:51 gkoehler Exp $ */ /* $NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $ */ /* @@ -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 *buf, int buflen) 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, int nargs, int nreturns, ...) 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, int nargs, int nreturns, ...) 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 ihandle, int nargs, ...) 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 ihandle, int nargs, ...) 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; } diff --git a/sys/arch/macppc/macppc/openfirm.c b/sys/arch/macppc/macppc/openfirm.c index f891aa4c10a..c78aad87ca6 100644 --- a/sys/arch/macppc/macppc/openfirm.c +++ b/sys/arch/macppc/macppc/openfirm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: openfirm.c,v 1.12 2019/09/03 17:51:52 deraadt Exp $ */ +/* $OpenBSD: openfirm.c,v 1.13 2020/04/02 19:27:51 gkoehler Exp $ */ /* $NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $ */ /* @@ -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 *buf, int buflen) 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 void *buf, int buflen) 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 *nextprop) 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? */ |