Author: nwhitehorn
Date: Sun Nov 17 15:12:03 2013
New Revision: 258259
URL: http://svnweb.freebsd.org/changeset/base/258259

Log:
  Unify handling of illegal instruction faults between AIM and Book-E. This
  allows FPU emulation on AIM as well as providing support for the mfpvr
  and lwsync instructions from userland on e500 cores. lwsync, in particular,
  is required for many C++ programs to work correctly.
  
  MFC after:    1 week

Modified:
  head/sys/powerpc/aim/trap.c
  head/sys/powerpc/booke/trap.c
  head/sys/powerpc/include/trap.h
  head/sys/powerpc/powerpc/exec_machdep.c

Modified: head/sys/powerpc/aim/trap.c
==============================================================================
--- head/sys/powerpc/aim/trap.c Sun Nov 17 15:09:39 2013        (r258258)
+++ head/sys/powerpc/aim/trap.c Sun Nov 17 15:12:03 2013        (r258259)
@@ -80,7 +80,6 @@ static void   printtrap(u_int vector, stru
                    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 
        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);
-}
-

Modified: head/sys/powerpc/booke/trap.c
==============================================================================
--- head/sys/powerpc/booke/trap.c       Sun Nov 17 15:09:39 2013        
(r258258)
+++ head/sys/powerpc/booke/trap.c       Sun Nov 17 15:12:03 2013        
(r258259)
@@ -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:

Modified: head/sys/powerpc/include/trap.h
==============================================================================
--- head/sys/powerpc/include/trap.h     Sun Nov 17 15:09:39 2013        
(r258258)
+++ head/sys/powerpc/include/trap.h     Sun Nov 17 15:12:03 2013        
(r258259)
@@ -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_ */

Modified: head/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/exec_machdep.c     Sun Nov 17 15:09:39 2013        
(r258258)
+++ head/sys/powerpc/powerpc/exec_machdep.c     Sun Nov 17 15:12:03 2013        
(r258259)
@@ -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, vo
        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);
+}
+
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to