1
0
mirror of https://github.com/openbsd/src.git synced 2026-05-01 17:46:35 +00:00

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@
This commit is contained in:
gkoehler
2020-04-02 19:27:51 +00:00
parent 1045da1136
commit dcf4ae464a
4 changed files with 212 additions and 170 deletions

View File

@@ -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;
}

View File

@@ -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
mtctr %r4
bctrl
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 */
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

View File

@@ -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 (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;
}
if (args.args_n_results[nargs]) {
va_end(ap);
return args.args_n_results[nargs];
}
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;
}

View File

@@ -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? */