svn commit: r347496 - in stable/12/sys/powerpc: fpu include powerpc

Justin Hibbits jhibbits at FreeBSD.org
Sat May 11 18:31:07 UTC 2019


Author: jhibbits
Date: Sat May 11 18:31:05 2019
New Revision: 347496
URL: https://svnweb.freebsd.org/changeset/base/347496

Log:
  MFC r345829, r345831
  
  r345829:
  powerpc: Apply r178139 from sparc64 to powerpc's fpu_sqrt
  
  This fix was committed less than 2 months after the code was forked into the
  powerpc kernel.  Though powerpc doesn't use quad-precision floating point,
  or need it for emulation, the changes do look like correctness fixes
  overall.
  
  This was found while trying to get fsqrt emulation working on e5500, which
  does have a real FPU, but lacks the fsqrt instruction.  This is not the
  complete fix, the rest is to be committed separately.
  
  r345831:
  powerpc: Allow emulating optional FPU instructions on CPUs with an FPU
  
  The e5500 has an FPU, but lacks the optional fsqrt instruction.  This
  instruction gets emulated in the kernel, but the emulation uses stale data,
  from the last switch out, and does not return the result of the operation
  immediately.  Fix both of these conditions by saving and restoring the FPRs
  around the emulation point.

Modified:
  stable/12/sys/powerpc/fpu/fpu_sqrt.c
  stable/12/sys/powerpc/include/trap.h
  stable/12/sys/powerpc/powerpc/exec_machdep.c
  stable/12/sys/powerpc/powerpc/trap.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/powerpc/fpu/fpu_sqrt.c
==============================================================================
--- stable/12/sys/powerpc/fpu/fpu_sqrt.c	Sat May 11 18:25:15 2019	(r347495)
+++ stable/12/sys/powerpc/fpu/fpu_sqrt.c	Sat May 11 18:31:05 2019	(r347496)
@@ -353,7 +353,7 @@ fpu_sqrt(struct fpemu *fe)
 	FPU_SUBC(d0, x0, t0);
 	if ((int)d0 >= 0) {
 		x0 = d0, x1 = d1, x2 = d2;
-		q |= bit;
+		q = bit;
 		y1 |= 1;		/* now t1, y1 are set in concrete */
 	}
 	ODD_DOUBLE;
@@ -385,12 +385,12 @@ fpu_sqrt(struct fpemu *fe)
 	FPU_SUBCS(d2, x2, t2);
 	FPU_SUBCS(d1, x1, t1);
 	FPU_SUBC(d0, x0, t0);
-	ODD_DOUBLE;
 	if ((int)d0 >= 0) {
-		x0 = d0, x1 = d1, x2 = d2;
-		q |= bit;
+		x0 = d0, x1 = d1, x2 = d2; x3 = d3;
+		q = bit;
 		y2 |= 1;
 	}
+	ODD_DOUBLE;
 	while ((bit >>= 1) != 0) {
 		EVEN_DOUBLE;
 		t3 = y3 | bit;
@@ -399,7 +399,7 @@ fpu_sqrt(struct fpemu *fe)
 		FPU_SUBCS(d1, x1, t1);
 		FPU_SUBC(d0, x0, t0);
 		if ((int)d0 >= 0) {
-			x0 = d0, x1 = d1, x2 = d2;
+			x0 = d0, x1 = d1, x2 = d2; x3 = d3;
 			q |= bit;
 			y3 |= bit << 1;
 		}

Modified: stable/12/sys/powerpc/include/trap.h
==============================================================================
--- stable/12/sys/powerpc/include/trap.h	Sat May 11 18:25:15 2019	(r347495)
+++ stable/12/sys/powerpc/include/trap.h	Sat May 11 18:31:05 2019	(r347496)
@@ -149,10 +149,10 @@
 
 #ifndef LOCORE
 struct	trapframe;
-struct	pcb;
+struct	thread;
 extern int	(*hmi_handler)(struct trapframe *);
 void    trap(struct trapframe *);
-int	ppc_instr_emulate(struct trapframe *, struct pcb *);
+int	ppc_instr_emulate(struct trapframe *, struct thread *);
 #endif
 
 #endif	/* _POWERPC_TRAP_H_ */

Modified: stable/12/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- stable/12/sys/powerpc/powerpc/exec_machdep.c	Sat May 11 18:25:15 2019	(r347495)
+++ stable/12/sys/powerpc/powerpc/exec_machdep.c	Sat May 11 18:31:05 2019	(r347496)
@@ -1066,8 +1066,9 @@ emulate_mtspr(int spr, int reg, struct trapframe *fram
 
 #define XFX 0xFC0007FF
 int
-ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
+ppc_instr_emulate(struct trapframe *frame, struct thread *td)
 {
+	struct pcb *pcb;
 	uint32_t instr;
 	int reg, sig;
 	int rs, spr;
@@ -1094,12 +1095,16 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb 
 		return (0);
 	}
 
+	pcb = td->td_pcb;
 #ifdef FPU_EMU
 	if (!(pcb->pcb_flags & PCB_FPREGS)) {
 		bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
 		pcb->pcb_flags |= PCB_FPREGS;
-	}
+	} else if (pcb->pcb_flags & PCB_FPU)
+		save_fpu(td);
 	sig = fpu_emulate(frame, &pcb->pcb_fpu);
+	if ((sig == 0 || sig == SIGFPE) && pcb->pcb_flags & PCB_FPU)
+		enable_fpu(td);
 #endif
 
 	return (sig);

Modified: stable/12/sys/powerpc/powerpc/trap.c
==============================================================================
--- stable/12/sys/powerpc/powerpc/trap.c	Sat May 11 18:25:15 2019	(r347495)
+++ stable/12/sys/powerpc/powerpc/trap.c	Sat May 11 18:31:05 2019	(r347496)
@@ -361,7 +361,7 @@ trap(struct trapframe *frame)
  				sig = SIGTRAP;
 				ucode = TRAP_BRKPT;
 			} else {
-				sig = ppc_instr_emulate(frame, td->td_pcb);
+				sig = ppc_instr_emulate(frame, td);
 				if (sig == SIGILL) {
 					if (frame->srr1 & EXC_PGM_PRIV)
 						ucode = ILL_PRVOPC;


More information about the svn-src-all mailing list