svn commit: r339803 - in stable/12/sys/powerpc: booke include powerpc
Justin Hibbits
jhibbits at FreeBSD.org
Sat Oct 27 03:16:34 UTC 2018
Author: jhibbits
Date: Sat Oct 27 03:16:32 2018
New Revision: 339803
URL: https://svnweb.freebsd.org/changeset/base/339803
Log:
MFC r339514:
powerpcspe: Implement SPE exception handling
The Signal Processing Engine (SPE) found in Freescale e500 cores (and
others) offloads IEEE-754 compliance (NaN, Inf handling, overflow,
underflow) to software, most likely as a means of simplifying the APU
silicon. Some software, like AbiWord, needs full IEEE-754 compliance,
including NaN handling. Implement the necessary bits to enable it.
Approved by: re(kib)
Modified:
stable/12/sys/powerpc/booke/booke_machdep.c
stable/12/sys/powerpc/booke/spe.c
stable/12/sys/powerpc/booke/trap_subr.S
stable/12/sys/powerpc/include/spr.h
stable/12/sys/powerpc/include/trap.h
stable/12/sys/powerpc/powerpc/exec_machdep.c
stable/12/sys/powerpc/powerpc/swtch32.S
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/powerpc/booke/booke_machdep.c
==============================================================================
--- stable/12/sys/powerpc/booke/booke_machdep.c Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/booke/booke_machdep.c Sat Oct 27 03:16:32 2018 (r339803)
@@ -189,6 +189,10 @@ extern void *int_debug;
extern void *int_debug_ed;
extern void *int_vec;
extern void *int_vecast;
+#ifdef __SPE__
+extern void *int_spe_fpdata;
+extern void *int_spe_fpround;
+#endif
#ifdef HWPMC_HOOKS
extern void *int_performance_counter;
#endif
@@ -258,6 +262,10 @@ ivor_setup(void)
case FSL_E500v1:
case FSL_E500v2:
SET_TRAP(SPR_IVOR32, int_vec);
+#ifdef __SPE__
+ SET_TRAP(SPR_IVOR33, int_spe_fpdata);
+ SET_TRAP(SPR_IVOR34, int_spe_fpround);
+#endif
break;
}
Modified: stable/12/sys/powerpc/booke/spe.c
==============================================================================
--- stable/12/sys/powerpc/booke/spe.c Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/booke/spe.c Sat Oct 27 03:16:32 2018 (r339803)
@@ -40,9 +40,19 @@ __FBSDID("$FreeBSD$");
#include <sys/limits.h>
#include <machine/altivec.h>
+#include <machine/fpu.h>
+#include <machine/ieeefp.h>
#include <machine/pcb.h>
#include <machine/psl.h>
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+#include <powerpc/fpu/fpu_extern.h>
+
+void spe_handle_fpdata(struct trapframe *);
+void spe_handle_fpround(struct trapframe *);
+static int spe_emu_instr(uint32_t, struct fpemu *, struct fpn **, uint32_t *);
+
static void
save_vec_int(struct thread *td)
{
@@ -75,7 +85,7 @@ save_vec_int(struct thread *td)
__asm ( "evxor 0,0,0\n"
"evaddumiaaw 0,0\n"
- "evstdd 0,0(%0)" :: "b"(&pcb->pcb_vec.vr[17][0]));
+ "evstdd 0,0(%0)" :: "b"(&pcb->pcb_vec.spare[0]));
pcb->pcb_vec.vscr = mfspr(SPR_SPEFSCR);
/*
@@ -113,6 +123,7 @@ enable_vec(struct thread *td)
if (!(pcb->pcb_flags & PCB_VEC)) {
memset(&pcb->pcb_vec, 0, sizeof pcb->pcb_vec);
pcb->pcb_flags |= PCB_VEC;
+ pcb->pcb_vec.vscr = mfspr(SPR_SPEFSCR);
}
/*
@@ -121,12 +132,11 @@ enable_vec(struct thread *td)
*/
msr = mfmsr();
mtmsr(msr | PSL_VEC);
- isync();
/* Restore SPEFSCR and ACC. Use %r0 as the scratch for ACC. */
mtspr(SPR_SPEFSCR, pcb->pcb_vec.vscr);
__asm __volatile("evldd 0, 0(%0); evmra 0,0\n"
- :: "b"(&pcb->pcb_vec.vr[17][0]));
+ :: "b"(&pcb->pcb_vec.spare[0]));
/*
* The lower half of each register will be restored on trap return. Use
@@ -180,4 +190,445 @@ save_vec_nodrop(struct thread *td)
}
save_vec_int(td);
+}
+
+
+#define SPE_INST_MASK 0x31f
+#define EADD 0x200
+#define ESUB 0x201
+#define EABS 0x204
+#define ENABS 0x205
+#define ENEG 0x206
+#define EMUL 0x208
+#define EDIV 0x209
+#define ECMPGT 0x20c
+#define ECMPLT 0x20d
+#define ECMPEQ 0x20e
+#define ECFUI 0x210
+#define ECFSI 0x211
+#define ECTUI 0x214
+#define ECTSI 0x215
+#define ECTUF 0x216
+#define ECTSF 0x217
+#define ECTUIZ 0x218
+#define ECTSIZ 0x21a
+
+#define SPE 0x4
+#define SPFP 0x6
+#define DPFP 0x7
+
+#define SPE_OPC 4
+#define OPC_SHIFT 26
+
+#define EVFSADD 0x280
+#define EVFSSUB 0x281
+#define EVFSABS 0x284
+#define EVFSNABS 0x285
+#define EVFSNEG 0x286
+#define EVFSMUL 0x288
+#define EVFSDIV 0x289
+#define EVFSCMPGT 0x28c
+#define EVFSCMPLT 0x28d
+#define EVFSCMPEQ 0x28e
+#define EVFSCFUI 0x290
+#define EVFSCFSI 0x291
+#define EVFSCTUI 0x294
+#define EVFSCTSI 0x295
+#define EVFSCTUF 0x296
+#define EVFSCTSF 0x297
+#define EVFSCTUIZ 0x298
+#define EVFSCTSIZ 0x29a
+
+#define EFSADD 0x2c0
+#define EFSSUB 0x2c1
+#define EFSABS 0x2c4
+#define EFSNABS 0x2c5
+#define EFSNEG 0x2c6
+#define EFSMUL 0x2c8
+#define EFSDIV 0x2c9
+#define EFSCMPGT 0x2cc
+#define EFSCMPLT 0x2cd
+#define EFSCMPEQ 0x2ce
+#define EFSCFD 0x2cf
+#define EFSCFUI 0x2d0
+#define EFSCFSI 0x2d1
+#define EFSCTUI 0x2d4
+#define EFSCTSI 0x2d5
+#define EFSCTUF 0x2d6
+#define EFSCTSF 0x2d7
+#define EFSCTUIZ 0x2d8
+#define EFSCTSIZ 0x2da
+
+#define EFDADD 0x2e0
+#define EFDSUB 0x2e1
+#define EFDABS 0x2e4
+#define EFDNABS 0x2e5
+#define EFDNEG 0x2e6
+#define EFDMUL 0x2e8
+#define EFDDIV 0x2e9
+#define EFDCMPGT 0x2ec
+#define EFDCMPLT 0x2ed
+#define EFDCMPEQ 0x2ee
+#define EFDCFS 0x2ef
+#define EFDCFUI 0x2f0
+#define EFDCFSI 0x2f1
+#define EFDCTUI 0x2f4
+#define EFDCTSI 0x2f5
+#define EFDCTUF 0x2f6
+#define EFDCTSF 0x2f7
+#define EFDCTUIZ 0x2f8
+#define EFDCTSIZ 0x2fa
+
+enum {
+ NONE,
+ SINGLE,
+ DOUBLE,
+ VECTOR,
+};
+
+static uint32_t fpscr_to_spefscr(uint32_t fpscr)
+{
+ uint32_t spefscr;
+
+ spefscr = 0;
+
+ if (fpscr & FPSCR_VX)
+ spefscr |= SPEFSCR_FINV;
+ if (fpscr & FPSCR_OX)
+ spefscr |= SPEFSCR_FOVF;
+ if (fpscr & FPSCR_UX)
+ spefscr |= SPEFSCR_FUNF;
+ if (fpscr & FPSCR_ZX)
+ spefscr |= SPEFSCR_FDBZ;
+ if (fpscr & FPSCR_XX)
+ spefscr |= SPEFSCR_FX;
+
+ return (spefscr);
+}
+
+/* Sign is 0 for unsigned, 1 for signed. */
+static int
+spe_to_int(struct fpemu *fpemu, struct fpn *fpn, uint32_t *val, int sign)
+{
+ uint32_t res[2];
+
+ res[0] = fpu_ftox(fpemu, fpn, res);
+ if (res[0] != UINT_MAX && res[0] != 0)
+ fpemu->fe_cx |= FPSCR_OX;
+ else if (sign == 0 && res[0] != 0)
+ fpemu->fe_cx |= FPSCR_UX;
+ else
+ *val = res[1];
+
+ return (0);
+}
+
+/* Masked instruction */
+/*
+ * For compare instructions, returns 1 if success, 0 if not. For all others,
+ * returns -1, or -2 if no result needs recorded.
+ */
+static int
+spe_emu_instr(uint32_t instr, struct fpemu *fpemu,
+ struct fpn **result, uint32_t *iresult)
+{
+ switch (instr & SPE_INST_MASK) {
+ case EABS:
+ case ENABS:
+ case ENEG:
+ /* Taken care of elsewhere. */
+ break;
+ case ECTUIZ:
+ fpemu->fe_cx &= ~FPSCR_RN;
+ fpemu->fe_cx |= FP_RZ;
+ case ECTUI:
+ spe_to_int(fpemu, &fpemu->fe_f2, iresult, 0);
+ return (-1);
+ case ECTSIZ:
+ fpemu->fe_cx &= ~FPSCR_RN;
+ fpemu->fe_cx |= FP_RZ;
+ case ECTSI:
+ spe_to_int(fpemu, &fpemu->fe_f2, iresult, 1);
+ return (-1);
+ case EADD:
+ *result = fpu_add(fpemu);
+ break;
+ case ESUB:
+ *result = fpu_sub(fpemu);
+ break;
+ case EMUL:
+ *result = fpu_mul(fpemu);
+ break;
+ case EDIV:
+ *result = fpu_div(fpemu);
+ break;
+ case ECMPGT:
+ fpu_compare(fpemu, 0);
+ if (fpemu->fe_cx & FPSCR_FG)
+ return (1);
+ return (0);
+ case ECMPLT:
+ fpu_compare(fpemu, 0);
+ if (fpemu->fe_cx & FPSCR_FL)
+ return (1);
+ return (0);
+ case ECMPEQ:
+ fpu_compare(fpemu, 0);
+ if (fpemu->fe_cx & FPSCR_FE)
+ return (1);
+ return (0);
+ default:
+ printf("Unknown instruction %x\n", instr);
+ }
+
+ return (-1);
+}
+
+static int
+spe_explode(struct fpemu *fe, struct fpn *fp, uint32_t type,
+ uint32_t hi, uint32_t lo)
+{
+ uint32_t s;
+
+ fp->fp_sign = hi >> 31;
+ fp->fp_sticky = 0;
+ switch (type) {
+ case SINGLE:
+ s = fpu_stof(fp, hi);
+ break;
+
+ case DOUBLE:
+ s = fpu_dtof(fp, hi, lo);
+ break;
+ }
+
+ if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
+ /*
+ * Input is a signalling NaN. All operations that return
+ * an input NaN operand put it through a ``NaN conversion'',
+ * which basically just means ``turn on the quiet bit''.
+ * We do this here so that all NaNs internally look quiet
+ * (we can tell signalling ones by their class).
+ */
+ fp->fp_mant[0] |= FP_QUIETBIT;
+ fe->fe_cx = FPSCR_VXSNAN; /* assert invalid operand */
+ s = FPC_SNAN;
+ }
+ fp->fp_class = s;
+
+ return (0);
+}
+
+void
+spe_handle_fpdata(struct trapframe *frame)
+{
+ struct fpemu fpemu;
+ struct fpn *result;
+ uint32_t instr, instr_sec_op;
+ uint32_t cr_shift, ra, rb, rd, src;
+ uint32_t high, low, res; /* For vector operations. */
+ uint32_t spefscr = 0;
+ uint32_t ftod_res[2];
+ int width; /* Single, Double, Vector, Integer */
+ int err;
+
+ err = fueword32((void *)frame->srr0, &instr);
+
+ if (err != 0)
+ return;
+ /* Fault. */;
+
+ if ((instr >> OPC_SHIFT) != SPE_OPC)
+ return;
+
+ /*
+ * 'cr' field is the upper 3 bits of rd. Magically, since a) rd is 5
+ * bits, b) each 'cr' field is 4 bits, and c) Only the 'GT' bit is
+ * modified for most compare operations, the full value of rd can be
+ * used as a shift value.
+ */
+ rd = (instr >> 21) & 0x1f;
+ ra = (instr >> 16) & 0x1f;
+ rb = (instr >> 11) & 0x1f;
+ src = (instr >> 5) & 0x7;
+ cr_shift = 28 - (rd & 0x1f);
+
+ instr_sec_op = (instr & 0x7ff);
+
+ memset(&fpemu, 0, sizeof(fpemu));
+
+ width = NONE;
+ switch (src) {
+ case SPE:
+ save_vec_nodrop(curthread);
+ switch (instr_sec_op) {
+ case EVFSABS:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ curthread->td_pcb->pcb_vec.vr[ra][0] & ~(1U << 31);
+ frame->fixreg[rd] = frame->fixreg[ra] & ~(1U << 31);
+ break;
+ case EVFSNABS:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ curthread->td_pcb->pcb_vec.vr[ra][0] | (1U << 31);
+ frame->fixreg[rd] = frame->fixreg[ra] | (1U << 31);
+ break;
+ case EVFSNEG:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ curthread->td_pcb->pcb_vec.vr[ra][0] ^ (1U << 31);
+ frame->fixreg[rd] = frame->fixreg[ra] ^ (1U << 31);
+ break;
+ default:
+ /* High word */
+ spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
+ curthread->td_pcb->pcb_vec.vr[ra][0], 0);
+ spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
+ curthread->td_pcb->pcb_vec.vr[rb][0], 0);
+ high = spe_emu_instr(instr_sec_op, &fpemu, &result,
+ &curthread->td_pcb->pcb_vec.vr[rd][0]);
+
+ spefscr = fpscr_to_spefscr(fpemu.fe_cx) << 16;
+ /* Clear the fpemu to start over on the lower bits. */
+ memset(&fpemu, 0, sizeof(fpemu));
+
+ /* Now low word */
+ spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
+ frame->fixreg[ra], 0);
+ spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
+ frame->fixreg[rb], 0);
+ spefscr |= fpscr_to_spefscr(fpemu.fe_cx);
+ low = spe_emu_instr(instr_sec_op, &fpemu, &result,
+ &frame->fixreg[rd]);
+ if (instr_sec_op == EVFSCMPEQ ||
+ instr_sec_op == EVFSCMPGT ||
+ instr_sec_op == EVFSCMPLT) {
+ res = (high << 3) | (low << 2) |
+ ((high | low) << 1) | (high & low);
+ width = NONE;
+ } else
+ width = VECTOR;
+ break;
+ }
+ enable_vec(curthread);
+ goto end;
+
+ case SPFP:
+ switch (instr_sec_op) {
+ case EFSABS:
+ frame->fixreg[rd] = frame->fixreg[ra] & ~(1U << 31);
+ break;
+ case EFSNABS:
+ frame->fixreg[rd] = frame->fixreg[ra] | (1U << 31);
+ break;
+ case EFSNEG:
+ frame->fixreg[rd] = frame->fixreg[ra] ^ (1U << 31);
+ break;
+ case EFSCFD:
+ spe_explode(&fpemu, &fpemu.fe_f3, DOUBLE,
+ curthread->td_pcb->pcb_vec.vr[rb][0],
+ frame->fixreg[rb]);
+ result = &fpemu.fe_f3;
+ width = SINGLE;
+ break;
+ default:
+ spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
+ frame->fixreg[ra], 0);
+ spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
+ frame->fixreg[rb], 0);
+ width = SINGLE;
+ }
+ break;
+ case DPFP:
+ save_vec_nodrop(curthread);
+ switch (instr_sec_op) {
+ case EFDABS:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ curthread->td_pcb->pcb_vec.vr[ra][0] & ~(1U << 31);
+ break;
+ case EFDNABS:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ curthread->td_pcb->pcb_vec.vr[ra][0] | (1U << 31);
+ break;
+ case EFDNEG:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ curthread->td_pcb->pcb_vec.vr[ra][0] ^ (1U << 31);
+ break;
+ case EFDCFS:
+ spe_explode(&fpemu, &fpemu.fe_f3, SINGLE,
+ frame->fixreg[rb], 0);
+ result = &fpemu.fe_f3;
+ width = DOUBLE;
+ break;
+ default:
+ spe_explode(&fpemu, &fpemu.fe_f1, DOUBLE,
+ curthread->td_pcb->pcb_vec.vr[ra][0],
+ frame->fixreg[ra]);
+ spe_explode(&fpemu, &fpemu.fe_f2, DOUBLE,
+ curthread->td_pcb->pcb_vec.vr[rb][0],
+ frame->fixreg[rb]);
+ width = DOUBLE;
+ }
+ break;
+ }
+ switch (instr_sec_op) {
+ case EFDCFS:
+ case EFSCFD:
+ /* Already handled. */
+ break;
+ default:
+ res = spe_emu_instr(instr_sec_op, &fpemu, &result,
+ &frame->fixreg[rd]);
+ if (res != -1)
+ res <<= 2;
+ break;
+ }
+
+ switch (instr_sec_op & SPE_INST_MASK) {
+ case ECMPEQ:
+ case ECMPGT:
+ case ECMPLT:
+ frame->cr &= ~(0xf << cr_shift);
+ frame->cr |= (res << cr_shift);
+ break;
+ case ECTUI:
+ case ECTUIZ:
+ case ECTSI:
+ case ECTSIZ:
+ break;
+ default:
+ switch (width) {
+ case NONE:
+ case VECTOR:
+ break;
+ case SINGLE:
+ frame->fixreg[rd] = fpu_ftos(&fpemu, result);
+ break;
+ case DOUBLE:
+ curthread->td_pcb->pcb_vec.vr[rd][0] =
+ fpu_ftod(&fpemu, result, ftod_res);
+ frame->fixreg[rd] = ftod_res[1];
+ enable_vec(curthread);
+ break;
+ default:
+ panic("Unknown storage width %d", width);
+ break;
+ }
+ }
+
+end:
+ spefscr |= (mfspr(SPR_SPEFSCR) & ~SPEFSCR_FINVS);
+ mtspr(SPR_SPEFSCR, spefscr);
+ frame->srr0 += 4;
+
+ return;
+}
+
+void
+spe_handle_fpround(struct trapframe *frame)
+{
+
+ /*
+ * Punt fpround exceptions for now. This leaves the truncated result in
+ * the register. We'll deal with overflow/underflow later.
+ */
+ return;
}
Modified: stable/12/sys/powerpc/booke/trap_subr.S
==============================================================================
--- stable/12/sys/powerpc/booke/trap_subr.S Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/booke/trap_subr.S Sat Oct 27 03:16:32 2018 (r339803)
@@ -638,6 +638,28 @@ INTERRUPT(int_vecast)
b trap_common
+#ifdef __SPE__
+/*****************************************************************************
+ * Floating point Assist interrupt
+ ****************************************************************************/
+INTERRUPT(int_spe_fpdata)
+ STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+ FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPD)
+ addi %r3, %r1, CALLSIZE
+ bl spe_handle_fpdata
+ FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
+ rfi
+
+INTERRUPT(int_spe_fpround)
+ STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+ FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPR)
+ addi %r3, %r1, CALLSIZE
+ bl spe_handle_fpround
+ FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
+ rfi
+#endif
+
+
#ifdef HWPMC_HOOKS
/*****************************************************************************
* PMC Interrupt
Modified: stable/12/sys/powerpc/include/spr.h
==============================================================================
--- stable/12/sys/powerpc/include/spr.h Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/include/spr.h Sat Oct 27 03:16:32 2018 (r339803)
@@ -245,6 +245,33 @@
#define SPR_PTCR 0x1d0 /* Partition Table Control Register */
#define SPR_SPEFSCR 0x200 /* ..8 Signal Processing Engine FSCR. */
+#define SPEFSCR_SOVH 0x80000000
+#define SPEFSCR_OVH 0x40000000
+#define SPEFSCR_FGH 0x20000000
+#define SPEFSCR_FXH 0x10000000
+#define SPEFSCR_FINVH 0x08000000
+#define SPEFSCR_FDBZH 0x04000000
+#define SPEFSCR_FUNFH 0x02000000
+#define SPEFSCR_FOVFH 0x01000000
+#define SPEFSCR_FINXS 0x00200000
+#define SPEFSCR_FINVS 0x00100000
+#define SPEFSCR_FDBZS 0x00080000
+#define SPEFSCR_FUNFS 0x00040000
+#define SPEFSCR_FOVFS 0x00020000
+#define SPEFSCR_SOV 0x00008000
+#define SPEFSCR_OV 0x00004000
+#define SPEFSCR_FG 0x00002000
+#define SPEFSCR_FX 0x00001000
+#define SPEFSCR_FINV 0x00000800
+#define SPEFSCR_FDBZ 0x00000400
+#define SPEFSCR_FUNF 0x00000200
+#define SPEFSCR_FOVF 0x00000100
+#define SPEFSCR_FINXE 0x00000040
+#define SPEFSCR_FINVE 0x00000020
+#define SPEFSCR_FDBZE 0x00000010
+#define SPEFSCR_FUNFE 0x00000008
+#define SPEFSCR_FOVFE 0x00000004
+#define SPEFSCR_FRMC_M 0x00000003
#define SPR_IBAT0U 0x210 /* .6. Instruction BAT Reg 0 Upper */
#define SPR_IBAT0L 0x211 /* .6. Instruction BAT Reg 0 Lower */
#define SPR_IBAT1U 0x212 /* .6. Instruction BAT Reg 1 Upper */
Modified: stable/12/sys/powerpc/include/trap.h
==============================================================================
--- stable/12/sys/powerpc/include/trap.h Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/include/trap.h Sat Oct 27 03:16:32 2018 (r339803)
@@ -100,6 +100,8 @@
#define EXC_APU 0x1300 /* Auxiliary Processing Unit */
#define EXC_DEBUG 0x2f10 /* Debug trap */
#define EXC_VECAST_E 0x2f20 /* Altivec Assist (Book-E) */
+#define EXC_SPFPD 0x2f30 /* SPE Floating-point Data */
+#define EXC_SPFPR 0x2f40 /* SPE Floating-point Round */
#define EXC_LAST 0x2f00 /* Last possible exception vector */
Modified: stable/12/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- stable/12/sys/powerpc/powerpc/exec_machdep.c Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/powerpc/exec_machdep.c Sat Oct 27 03:16:32 2018 (r339803)
@@ -971,6 +971,10 @@ cpu_copy_thread(struct thread *td, struct thread *td0)
pcb2->pcb_context[0] = pcb2->pcb_lr;
#endif
pcb2->pcb_cpu.aim.usr_vsid = 0;
+#ifdef __SPE__
+ pcb2->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE |
+ SPEFSCR_FUNFE | SPEFSCR_FOVFE;
+#endif
/* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1;
@@ -1016,6 +1020,10 @@ cpu_set_upcall(struct thread *td, void (*entry)(void *
}
td->td_pcb->pcb_flags = 0;
+#ifdef __SPE__
+ td->td_pcb->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE |
+ SPEFSCR_FUNFE | SPEFSCR_FOVFE;
+#endif
td->td_retval[0] = (register_t)entry;
td->td_retval[1] = 0;
Modified: stable/12/sys/powerpc/powerpc/swtch32.S
==============================================================================
--- stable/12/sys/powerpc/powerpc/swtch32.S Fri Oct 26 23:44:50 2018 (r339802)
+++ stable/12/sys/powerpc/powerpc/swtch32.S Sat Oct 27 03:16:32 2018 (r339803)
@@ -212,4 +212,8 @@ ENTRY(fork_trampoline)
trapframe to simulate FRAME_SETUP
does when allocating space for
a frame pointer/saved LR */
+#ifdef __SPE__
+ li %r3,SPEFSCR_FINVE|SPEFSCR_FDBZE|SPEFSCR_FUNFE|SPEFSCR_FOVFE
+ mtspr SPR_SPEFSCR, %r3
+#endif
b trapexit
More information about the svn-src-stable
mailing list