Index: sys/powerpc/include/fpu.h =================================================================== --- sys/powerpc/include/fpu.h +++ sys/powerpc/include/fpu.h @@ -75,6 +75,7 @@ void enable_fpu(struct thread *); void save_fpu(struct thread *); void save_fpu_nodrop(struct thread *); +u_int get_fpu_exception(struct thread *); #endif /* _KERNEL */ Index: sys/powerpc/include/psl.h =================================================================== --- sys/powerpc/include/psl.h +++ sys/powerpc/include/psl.h @@ -88,7 +88,7 @@ #define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ #define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ #define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ -#define PSL_FE_DFLT PSL_FE_DIS /* default == none */ +#define PSL_FE_DFLT PSL_FE_PREC /* default == precise */ #ifndef LOCORE extern register_t psl_kernset; /* Default MSR values for kernel */ Index: sys/powerpc/powerpc/exec_machdep.c =================================================================== --- sys/powerpc/powerpc/exec_machdep.c +++ sys/powerpc/powerpc/exec_machdep.c @@ -1158,6 +1158,12 @@ sig = fpu_emulate(frame, &pcb->pcb_fpu); if ((sig == 0 || sig == SIGFPE) && pcb->pcb_flags & PCB_FPU) enable_fpu(td); +#else + if ((frame->srr1 & EXC_PGM_FPENABLED) && (pcb->pcb_flags & PCB_FPU)) { + /* Floating-Point Enabled Exception type Program interrupt */ + sig = SIGFPE; + enable_fpu(td); + } #endif if (sig == SIGILL) { if (pcb->pcb_lastill != frame->srr0) { Index: sys/powerpc/powerpc/fpu.c =================================================================== --- sys/powerpc/powerpc/fpu.c +++ sys/powerpc/powerpc/fpu.c @@ -213,3 +213,38 @@ save_fpu_int(td); } + +/* + * Returns the current fp exception + */ +u_int +get_fpu_exception(struct thread *td) +{ + int msr; + u_int ucode; + uint64_t reg; + + if (!(td->td_pcb->pcb_flags & PCB_FPU)) + return 0; + + msr = mfmsr(); + mtmsr(msr | PSL_FP); + __asm __volatile ("mffs 0; stfd 0,0(%0)" + :: "b"(®)); + mtmsr(msr); + + save_fpu(td); + + if (reg & FPSCR_ZX) + ucode = FPE_FLTDIV; + else if (reg & FPSCR_OX) + ucode = FPE_FLTOVF; + else if (reg & FPSCR_UX) + ucode = FPE_FLTUND; + else if (reg & FPSCR_XX) + ucode = FPE_FLTRES; + else + ucode = FPE_FLTINV; + + return ucode; +} Index: sys/powerpc/powerpc/trap.c =================================================================== --- sys/powerpc/powerpc/trap.c +++ sys/powerpc/powerpc/trap.c @@ -398,7 +398,7 @@ else if (frame->srr1 & EXC_PGM_ILLEGAL) ucode = ILL_ILLOPC; } else if (sig == SIGFPE) - ucode = FPE_FLTINV; /* Punt for now, invalid operation. */ + ucode = get_fpu_exception(td); } break;