summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-14 04:57:55 +0000
committerian <ian@FreeBSD.org>2014-05-14 04:57:55 +0000
commit4a602a895785693d5def6282dbd784066341e805 (patch)
tree93e1dc02422784a7958c97bfd024009d3b8817ff
parent9277bb1a2b74a398eb2fd572785d2d6db451d8c1 (diff)
downloadFreeBSD-src-4a602a895785693d5def6282dbd784066341e805.zip
FreeBSD-src-4a602a895785693d5def6282dbd784066341e805.tar.gz
MFC r258259, r258798, r259010
Unify handling of illegal instruction faults between AIM and Book-E. Make uart_cpu_powerpc work on both FDT and OFW systems. Fix debug printfs in FPU_EMU to compile on powerpc64 and enable it for powerpc64.
-rw-r--r--sys/conf/files.powerpc21
-rw-r--r--sys/dev/uart/uart_cpu_powerpc.c97
-rw-r--r--sys/powerpc/aim/trap.c25
-rw-r--r--sys/powerpc/booke/trap.c17
-rw-r--r--sys/powerpc/fpu/fpu_emu.c21
-rw-r--r--sys/powerpc/include/trap.h2
-rw-r--r--sys/powerpc/powerpc/exec_machdep.c38
7 files changed, 144 insertions, 77 deletions
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 5dc582a..63b70c4 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -65,8 +65,7 @@ dev/syscons/scterm-teken.c optional sc
dev/syscons/scvtb.c optional sc
dev/tsec/if_tsec.c optional tsec
dev/tsec/if_tsec_fdt.c optional tsec fdt
-dev/uart/uart_cpu_fdt.c optional uart fdt
-dev/uart/uart_cpu_powerpc.c optional uart aim
+dev/uart/uart_cpu_powerpc.c optional uart
dev/usb/controller/ehci_fsl.c optional ehci mpc85xx
dev/vt/hw/ofwfb/ofwfb.c optional vt aim
kern/kern_clocksource.c standard
@@ -111,15 +110,15 @@ powerpc/booke/trap.c optional booke
powerpc/cpufreq/dfs.c optional cpufreq
powerpc/cpufreq/pcr.c optional cpufreq aim
powerpc/cpufreq/pmufreq.c optional cpufreq aim pmu
-powerpc/fpu/fpu_add.c optional fpu_emu powerpc
-powerpc/fpu/fpu_compare.c optional fpu_emu powerpc
-powerpc/fpu/fpu_div.c optional fpu_emu powerpc
-powerpc/fpu/fpu_emu.c optional fpu_emu powerpc
-powerpc/fpu/fpu_explode.c optional fpu_emu powerpc
-powerpc/fpu/fpu_implode.c optional fpu_emu powerpc
-powerpc/fpu/fpu_mul.c optional fpu_emu powerpc
-powerpc/fpu/fpu_sqrt.c optional fpu_emu powerpc
-powerpc/fpu/fpu_subr.c optional fpu_emu powerpc
+powerpc/fpu/fpu_add.c optional fpu_emu
+powerpc/fpu/fpu_compare.c optional fpu_emu
+powerpc/fpu/fpu_div.c optional fpu_emu
+powerpc/fpu/fpu_emu.c optional fpu_emu
+powerpc/fpu/fpu_explode.c optional fpu_emu
+powerpc/fpu/fpu_implode.c optional fpu_emu
+powerpc/fpu/fpu_mul.c optional fpu_emu
+powerpc/fpu/fpu_sqrt.c optional fpu_emu
+powerpc/fpu/fpu_subr.c optional fpu_emu
powerpc/mambo/mambocall.S optional mambo
powerpc/mambo/mambo.c optional mambo
powerpc/mambo/mambo_console.c optional mambo
diff --git a/sys/dev/uart/uart_cpu_powerpc.c b/sys/dev/uart/uart_cpu_powerpc.c
index 997bdd8..44f6338 100644
--- a/sys/dev/uart/uart_cpu_powerpc.c
+++ b/sys/dev/uart/uart_cpu_powerpc.c
@@ -61,42 +61,96 @@ ofw_get_uart_console(phandle_t opts, phandle_t *result, const char *inputdev,
input = OF_finddevice(buf);
if (input == -1)
return (ENXIO);
- if (OF_getprop(opts, outputdev, buf, sizeof(buf)) == -1)
- return (ENXIO);
- if (OF_finddevice(buf) != input)
- return (ENXIO);
+
+ if (outputdev != NULL) {
+ if (OF_getprop(opts, outputdev, buf, sizeof(buf)) == -1)
+ return (ENXIO);
+ if (OF_finddevice(buf) != input)
+ return (ENXIO);
+ }
*result = input;
return (0);
}
+static int
+ofw_get_console_phandle_path(phandle_t node, phandle_t *result,
+ const char *prop)
+{
+ union {
+ char buf[64];
+ phandle_t ref;
+ } field;
+ phandle_t output;
+ ssize_t size;
+
+ size = OF_getproplen(node, prop);
+ if (size == -1)
+ return (ENXIO);
+ OF_getprop(node, prop, &field, sizeof(field));
+
+ /* This property might be a phandle or might be a path. Hooray. */
+
+ output = -1;
+ if (field.buf[size - 1] == 0)
+ output = OF_finddevice(field.buf);
+ if (output == -1 && size == 4)
+ output = OF_xref_phandle(field.ref);
+
+ if (output != -1) {
+ *result = output;
+ return (0);
+ }
+
+ return (ENXIO);
+}
+
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
char buf[64];
struct uart_class *class;
- phandle_t input, opts;
+ phandle_t input, opts, chosen;
int error;
class = &uart_z8530_class;
if (class == NULL)
return (ENXIO);
- if ((opts = OF_finddevice("/options")) == -1)
- return (ENXIO);
+ opts = OF_finddevice("/options");
+ chosen = OF_finddevice("/chosen");
switch (devtype) {
case UART_DEV_CONSOLE:
- if (ofw_get_uart_console(opts, &input, "input-device",
- "output-device")) {
- /*
- * At least some G5 Xserves require that we
- * probe input-device-1 as well
- */
-
- if (ofw_get_uart_console(opts, &input, "input-device-1",
- "output-device-1"))
- return (ENXIO);
+ error = ENXIO;
+ if (chosen != -1 && error != 0)
+ error = ofw_get_uart_console(chosen, &input,
+ "stdout-path", NULL);
+ if (chosen != -1 && error != 0)
+ error = ofw_get_uart_console(chosen, &input,
+ "linux,stdout-path", NULL);
+ if (chosen != -1 && error != 0)
+ error = ofw_get_console_phandle_path(chosen, &input,
+ "stdout");
+ if (chosen != -1 && error != 0)
+ error = ofw_get_uart_console(chosen, &input,
+ "stdin-path", NULL);
+ if (chosen != -1 && error != 0)
+ error = ofw_get_console_phandle_path(chosen, &input,
+ "stdin");
+ if (opts != -1 && error != 0)
+ error = ofw_get_uart_console(opts, &input,
+ "input-device", "output-device");
+ if (opts != -1 && error != 0)
+ error = ofw_get_uart_console(opts, &input,
+ "input-device-1", "output-device-1");
+ if (error != 0) {
+ input = OF_finddevice("serial0"); /* Last ditch */
+ if (input == -1)
+ error = (ENXIO);
}
+
+ if (error != 0)
+ return (error);
break;
case UART_DEV_DBGPORT:
if (!getenv_string("hw.uart.dbgport", buf, sizeof(buf)))
@@ -113,14 +167,14 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
return (ENXIO);
if (strcmp(buf, "serial") != 0)
return (ENXIO);
- if (OF_getprop(input, "name", buf, sizeof(buf)) == -1)
+ if (OF_getprop(input, "compatible", buf, sizeof(buf)) == -1)
return (ENXIO);
- if (strcmp(buf, "ch-a") == 0) {
+ if (strncmp(buf, "chrp,es", 7) == 0) {
class = &uart_z8530_class;
di->bas.regshft = 4;
di->bas.chan = 1;
- } else if (strcmp(buf,"serial") == 0) {
+ } else if (strcmp(buf,"ns16550") == 0 || strcmp(buf,"ns8250") == 0) {
class = &uart_ns8250_class;
di->bas.regshft = 0;
di->bas.chan = 0;
@@ -139,9 +193,12 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
if (OF_getprop(input, "current-speed", &di->baudrate,
sizeof(di->baudrate)) == -1)
di->baudrate = 0;
+ OF_getprop(input, "reg-shift", &di->bas.regshft,
+ sizeof(di->bas.regshft));
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
return (0);
}
+
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c
index d234ba2..025b5cf 100644
--- a/sys/powerpc/aim/trap.c
+++ b/sys/powerpc/aim/trap.c
@@ -80,7 +80,6 @@ static void printtrap(u_int vector, struct trapframe *frame, int isfatal,
int user);
static int trap_pfault(struct trapframe *frame, int user);
static int fix_unaligned(struct thread *td, struct trapframe *frame);
-static int ppc_instr_emulate(struct trapframe *frame);
static int handle_onfault(struct trapframe *frame);
static void syscall(struct trapframe *frame);
@@ -292,10 +291,9 @@ trap(struct trapframe *frame)
}
#endif
sig = SIGTRAP;
- } else if (ppc_instr_emulate(frame) == 0)
- frame->srr0 += 4;
- else
- sig = SIGILL;
+ } else {
+ sig = ppc_instr_emulate(frame, td->td_pcb);
+ }
break;
default:
@@ -800,20 +798,3 @@ fix_unaligned(struct thread *td, struct trapframe *frame)
return -1;
}
-static int
-ppc_instr_emulate(struct trapframe *frame)
-{
- uint32_t instr;
- int reg;
-
- instr = fuword32((void *)frame->srr0);
-
- if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */
- reg = (instr & ~0xfc1fffff) >> 21;
- frame->fixreg[reg] = mfpvr();
- return (0);
- }
-
- return (-1);
-}
-
diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c
index 72c4f47..dc84ede 100644
--- a/sys/powerpc/booke/trap.c
+++ b/sys/powerpc/booke/trap.c
@@ -71,10 +71,6 @@ __FBSDID("$FreeBSD$");
#include <machine/trap.h>
#include <machine/spr.h>
-#ifdef FPU_EMU
-#include <powerpc/fpu/fpu_extern.h>
-#endif
-
#define FAULTBUF_LR 0
#define FAULTBUF_R1 1
#define FAULTBUF_R2 2
@@ -193,18 +189,7 @@ trap(struct trapframe *frame)
break;
case EXC_PGM: /* Program exception */
-#ifdef FPU_EMU
- if (!(td->td_pcb->pcb_flags & PCB_FPREGS)) {
- bzero(&td->td_pcb->pcb_fpu,
- sizeof(td->td_pcb->pcb_fpu));
- td->td_pcb->pcb_flags |= PCB_FPREGS;
- }
- sig = fpu_emulate(frame,
- (struct fpreg *)&td->td_pcb->pcb_fpu);
-#else
- /* XXX SIGILL for non-trap instructions. */
- sig = SIGTRAP;
-#endif
+ sig = ppc_instr_emulate(frame, td->td_pcb);
break;
default:
diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c
index 33c1f74..610c0ea 100644
--- a/sys/powerpc/fpu/fpu_emu.c
+++ b/sys/powerpc/fpu/fpu_emu.c
@@ -326,8 +326,10 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* Store as integer */
ra = instr.i_x.i_ra;
rb = instr.i_x.i_rb;
- DPRINTF(FPE_INSN, ("reg %d has %x reg %d has %x\n",
- ra, tf->fixreg[ra], rb, tf->fixreg[rb]));
+ DPRINTF(FPE_INSN,
+ ("reg %d has %jx reg %d has %jx\n",
+ ra, (uintmax_t)tf->fixreg[ra], rb,
+ (uintmax_t)tf->fixreg[rb]));
addr = tf->fixreg[rb];
if (ra != 0)
@@ -356,8 +358,9 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* calculate EA of load/store */
ra = instr.i_x.i_ra;
rb = instr.i_x.i_rb;
- DPRINTF(FPE_INSN, ("reg %d has %x reg %d has %x\n",
- ra, tf->fixreg[ra], rb, tf->fixreg[rb]));
+ DPRINTF(FPE_INSN, ("reg %d has %jx reg %d has %jx\n",
+ ra, (uintmax_t)tf->fixreg[ra], rb,
+ (uintmax_t)tf->fixreg[rb]));
addr = tf->fixreg[rb];
if (ra != 0)
addr += tf->fixreg[ra];
@@ -373,8 +376,9 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* calculate EA of load/store */
ra = instr.i_d.i_ra;
addr = instr.i_d.i_d;
- DPRINTF(FPE_INSN, ("reg %d has %x displ %x\n",
- ra, tf->fixreg[ra], addr));
+ DPRINTF(FPE_INSN, ("reg %d has %jx displ %jx\n",
+ ra, (uintmax_t)tf->fixreg[ra],
+ (uintmax_t)addr));
if (ra != 0)
addr += tf->fixreg[ra];
rt = instr.i_d.i_rt;
@@ -420,7 +424,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
return (0);
#ifdef notyet
} else if (instr.i_any.i_opcd == OPC_load_st_62) {
- /* These are 64-bit extenstions */
+ /* These are 64-bit extensions */
return (NOTFPU);
#endif
} else if (instr.i_any.i_opcd == OPC_sp_fp_59 ||
@@ -784,7 +788,8 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* Move fpu condition codes to cr[1] */
tf->cr &= ~(0xf0000000>>bf);
tf->cr |= (cond>>bf);
- DPRINTF(FPE_INSN, ("fpu_execute: cr[%d] (cr=%x) <= %x\n", bf/4, tf->cr, cond));
+ DPRINTF(FPE_INSN, ("fpu_execute: cr[%d] (cr=%jx) <= %x\n",
+ bf/4, (uintmax_t)tf->cr, cond));
}
((int *)&fs->fpscr)[1] = fsr;
diff --git a/sys/powerpc/include/trap.h b/sys/powerpc/include/trap.h
index d8462cf..89f5966 100644
--- a/sys/powerpc/include/trap.h
+++ b/sys/powerpc/include/trap.h
@@ -122,7 +122,9 @@
#ifndef LOCORE
struct trapframe;
+struct pcb;
void trap(struct trapframe *);
+int ppc_instr_emulate(struct trapframe *, struct pcb *);
#endif
#endif /* _POWERPC_TRAP_H_ */
diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c
index 4b4be6c..acacb3d 100644
--- a/sys/powerpc/powerpc/exec_machdep.c
+++ b/sys/powerpc/powerpc/exec_machdep.c
@@ -58,6 +58,7 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
+#include "opt_fpu_emu.h"
#include <sys/param.h>
#include <sys/proc.h>
@@ -92,6 +93,10 @@ __FBSDID("$FreeBSD$");
#include <machine/trap.h>
#include <machine/vmparam.h>
+#ifdef FPU_EMU
+#include <powerpc/fpu/fpu_extern.h>
+#endif
+
#ifdef COMPAT_FREEBSD32
#include <compat/freebsd32/freebsd32_signal.h>
#include <compat/freebsd32/freebsd32_util.h>
@@ -1038,3 +1043,36 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
td->td_retval[1] = 0;
}
+int
+ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
+{
+ uint32_t instr;
+ int reg, sig;
+
+ instr = fuword32((void *)frame->srr0);
+ sig = SIGILL;
+
+ if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */
+ reg = (instr & ~0xfc1fffff) >> 21;
+ frame->fixreg[reg] = mfpvr();
+ frame->srr0 += 4;
+ return (0);
+ }
+
+ if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */
+ powerpc_sync(); /* Do a heavy-weight sync */
+ frame->srr0 += 4;
+ return (0);
+ }
+
+#ifdef FPU_EMU
+ if (!(pcb->pcb_flags & PCB_FPREGS)) {
+ bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
+ pcb->pcb_flags |= PCB_FPREGS;
+ }
+ sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu);
+#endif
+
+ return (sig);
+}
+
OpenPOWER on IntegriCloud