diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-02-22 14:17:23 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-02-22 14:17:23 +0000 |
commit | a9f2786d08ce019d0969b21bb7470742b5e5bad5 (patch) | |
tree | c27f698d92061bb3a404250dfa135b059266be48 | |
parent | 69414838331fba17e430ba1b57b262f7eab2bf22 (diff) | |
download | FreeBSD-src-a9f2786d08ce019d0969b21bb7470742b5e5bad5.zip FreeBSD-src-a9f2786d08ce019d0969b21bb7470742b5e5bad5.tar.gz |
Allow user programs to execute mfpvr instructions. Linux allows this, and
some math-related software like GMP expects to be able to use it to pick
a target appropriately.
MFC after: 1 week
-rw-r--r-- | sys/powerpc/aim/trap.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 943e3c6..35f4147 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -82,6 +82,7 @@ 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); @@ -209,7 +210,9 @@ trap(struct trapframe *frame) /* Identify the trap reason */ if (frame->srr1 & EXC_PGM_TRAP) sig = SIGTRAP; - else + else if (ppc_instr_emulate(frame) == 0) + frame->srr0 += 4; + else sig = SIGILL; break; @@ -615,3 +618,21 @@ 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); +} + |