changeset 7:420a1f4ae7e6

6283388 VIS emulation code incorrectly accesses kernel pstate and ccr registers
author df157793
date Wed, 15 Jun 2005 08:22:03 -0700
parents 9049f50e2cc0
children 076213c6325f
files usr/src/uts/sparc/fpu/fpu_simulator.c usr/src/uts/sparc/sys/fpu/fpu_simulator.h usr/src/uts/sparc/sys/fpu/fpusystm.h usr/src/uts/sparc/v9/sys/privregs.h usr/src/uts/sun4/ml/subr_asm.s usr/src/uts/sun4/os/visinstr.c
diffstat 6 files changed, 64 insertions(+), 323 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sparc/fpu/fpu_simulator.c	Wed Jun 15 08:20:19 2005 -0700
+++ b/usr/src/uts/sparc/fpu/fpu_simulator.c	Wed Jun 15 08:22:03 2005 -0700
@@ -41,7 +41,6 @@
 #include <sys/privregs.h>
 #include <sys/vis_simulator.h>
 
-
 #define	FPUINFO_KSTAT(opcode)	{					\
 	extern void __dtrace_probe___fpuinfo_##opcode(uint64_t *);	\
 	uint64_t *stataddr = &fpuinfo.opcode.value.ui64;		\
@@ -479,25 +478,16 @@
 		pfpsd->fp_current_write_freg = _fp_write_pfreg;
 		pfpsd->fp_current_read_dreg = _fp_read_pdreg;
 		pfpsd->fp_current_write_dreg = _fp_write_pdreg;
-		pfpsd->get_gsr = get_phys_gsr;
-		pfpsd->set_gsr = set_phys_gsr;
-		pfpsd->get_ccr = get_ccr;
-		pfpsd->set_ccr = set_ccr;
-		pfpsd->get_pstate = get_pstate;
+		pfpsd->fp_current_read_gsr = _fp_read_pgsr;
+		pfpsd->fp_current_write_gsr = _fp_write_pgsr;
 	} else {
 		pfpsd->fp_current_pfregs = pfp;
 		pfpsd->fp_current_read_freg = _fp_read_vfreg;
 		pfpsd->fp_current_write_freg = _fp_write_vfreg;
 		pfpsd->fp_current_read_dreg = _fp_read_vdreg;
 		pfpsd->fp_current_write_dreg = _fp_write_vdreg;
-		pfpsd->get_gsr = get_gsr;
-		pfpsd->set_gsr = set_gsr;
-
-		/* There are no virtual routines */
-		/* for getting/setting ccr and pstate */
-		pfpsd->get_ccr = get_ccr;
-		pfpsd->set_ccr = set_ccr;
-		pfpsd->get_pstate = get_pstate;
+		pfpsd->fp_current_read_gsr = get_gsr;
+		pfpsd->fp_current_write_gsr = set_gsr;
 	}
 
 	if ((fp.inst.hibits == 2) && (fp.inst.op3 == 0x36)) {
@@ -542,11 +532,8 @@
 	pfpsd->fp_current_write_freg = _fp_write_pfreg;
 	pfpsd->fp_current_read_dreg = _fp_read_pdreg;
 	pfpsd->fp_current_write_dreg = _fp_write_pdreg;
-	pfpsd->get_gsr = get_phys_gsr;
-	pfpsd->set_gsr = set_phys_gsr;
-	pfpsd->get_ccr = get_ccr;
-	pfpsd->set_ccr = set_ccr;
-	pfpsd->get_pstate = get_pstate;
+	pfpsd->fp_current_read_gsr = _fp_read_pgsr;
+	pfpsd->fp_current_write_gsr = _fp_write_pgsr;
 	return (_fp_fpu_simulator(pfpsd, fp.inst, pfsr, gsr));
 }
 
@@ -578,14 +565,8 @@
 	pfpsd->fp_current_write_freg = _fp_write_vfreg;
 	pfpsd->fp_current_read_dreg = _fp_read_vdreg;
 	pfpsd->fp_current_write_dreg = _fp_write_vdreg;
-	pfpsd->get_gsr = get_gsr;
-	pfpsd->set_gsr = set_gsr;
-
-	/* There are no virtual routines */
-	/* for getting/setting ccr and pstate */
-	pfpsd->get_ccr = get_ccr;
-	pfpsd->set_ccr = set_ccr;
-	pfpsd->get_pstate = get_pstate;
+	pfpsd->fp_current_read_gsr = get_gsr;
+	pfpsd->fp_current_write_gsr = set_gsr;
 	pfpsd->fp_trapaddr = (caddr_t)pinst; /* bad inst addr in case we trap */
 	ftt = _fp_read_inst((uint32_t *)pinst, &(fp.i), pfpsd);
 	if (ftt != ftt_none)
--- a/usr/src/uts/sparc/sys/fpu/fpu_simulator.h	Wed Jun 15 08:20:19 2005 -0700
+++ b/usr/src/uts/sparc/sys/fpu/fpu_simulator.h	Wed Jun 15 08:22:03 2005 -0700
@@ -241,11 +241,8 @@
 	void			(*fp_current_write_freg) ();
 	void			(*fp_current_read_dreg) ();
 	void			(*fp_current_write_dreg) ();
-	uint64_t		(*get_gsr) (kfpu_t *);
-	uint_t			(*get_ccr) ();
-	uint_t			(*get_pstate) ();
-	void			(*set_gsr) (uint64_t, kfpu_t *);
-	void			(*set_ccr) (uint_t);
+	uint64_t		(*fp_current_read_gsr) (kfpu_t *);
+	void			(*fp_current_write_gsr) (uint64_t, kfpu_t *);
 	int			fp_trapcode;
 	char			*fp_trapaddr;
 	struct	regs		*fp_traprp;
--- a/usr/src/uts/sparc/sys/fpu/fpusystm.h	Wed Jun 15 08:20:19 2005 -0700
+++ b/usr/src/uts/sparc/sys/fpu/fpusystm.h	Wed Jun 15 08:22:03 2005 -0700
@@ -79,11 +79,8 @@
 extern void restore_gsr(kfpu_t *);
 extern uint64_t get_gsr(kfpu_t *);
 extern void set_gsr(uint64_t, kfpu_t *);
-extern uint64_t get_phys_gsr(kfpu_t *);
-extern void set_phys_gsr(uint64_t, kfpu_t *);
-extern uint_t get_pstate();
-extern uint_t get_ccr();
-extern void set_ccr(uint_t);
+extern uint64_t _fp_read_pgsr(kfpu_t *);
+extern void _fp_write_pgsr(uint64_t, kfpu_t *);
 extern void _fp_read_pdreg(uint64_t *, uint_t);
 extern void _fp_write_pdreg(uint64_t *, uint_t);
 
--- a/usr/src/uts/sparc/v9/sys/privregs.h	Wed Jun 15 08:20:19 2005 -0700
+++ b/usr/src/uts/sparc/v9/sys/privregs.h	Wed Jun 15 08:22:03 2005 -0700
@@ -490,9 +490,13 @@
 #ifndef _ASM
 #define	TSTATE_ICC	((long long)CCR_ICC << TSTATE_CCR_SHIFT)
 #define	TSTATE_IC	((long long)CCR_IC << TSTATE_CCR_SHIFT)
+#define	TSTATE_IV	((long long)CCR_IV << TSTATE_CCR_SHIFT)
+#define	TSTATE_XV	((long long)CCR_XV << TSTATE_CCR_SHIFT)
 #else
 #define	TSTATE_ICC	(CCR_ICC << TSTATE_CCR_SHIFT)
 #define	TSTATE_IC	(CCR_IC << TSTATE_CCR_SHIFT)
+#define	TSTATE_IV	(CCR_IV << TSTATE_CCR_SHIFT)
+#define	TSTATE_XV	(CCR_XV << TSTATE_CCR_SHIFT)
 #endif
 #define	TSTATE_V8_UBITS (TSTATE_ICC | TSTATE_PEF)
 
--- a/usr/src/uts/sun4/ml/subr_asm.s	Wed Jun 15 08:20:19 2005 -0700
+++ b/usr/src/uts/sun4/ml/subr_asm.s	Wed Jun 15 08:22:03 2005 -0700
@@ -343,7 +343,7 @@
 
 /*
  * uint64_t
- * get_phys_gsr()
+ * _fp_read_pgsr()
  * Get the graphics status register info from fp and return it
  */
 
@@ -351,15 +351,15 @@
 
 /* ARGSUSED */
 uint64_t
-get_phys_gsr(kfpu_t *fp)
+_fp_read_pgsr(kfpu_t *fp)
 { return 0; }
 
 #else	/* lint */
 
-	ENTRY_NP(get_phys_gsr)
+	ENTRY_NP(_fp_read_pgsr)
 	retl
 	rd	%gsr, %o0
-	SET_SIZE(get_phys_gsr)
+	SET_SIZE(_fp_read_pgsr)
 
 #endif	/* lint */
 
@@ -387,7 +387,7 @@
 #endif
 
 /*
- * set_phys_gsr(uint64_t *buf, kfpu_t *fp)
+ * _fp_write_pgsr(uint64_t *buf, kfpu_t *fp)
  * Set the graphics status register info to fp from buf
  */
 
@@ -395,15 +395,15 @@
 
 /* ARGSUSED */
 void
-set_phys_gsr(uint64_t buf, kfpu_t *fp)
+_fp_write_pgsr(uint64_t buf, kfpu_t *fp)
 {}
 
 #else	/* lint */
 
-	ENTRY_NP(set_phys_gsr)
+	ENTRY_NP(_fp_write_pgsr)
 	retl
 	mov	%o0, %gsr
-	SET_SIZE(set_phys_gsr)
+	SET_SIZE(_fp_write_pgsr)
 
 #endif	/* lint */
 
@@ -427,67 +427,6 @@
 	SET_SIZE(set_gsr)
 
 #endif	/* lint */
-/*
- * Routine to get the pstate reg - used by vis emulation code
- * to test whether the AM bit for 32 bit instructions
- * has been set.
- */
-#if defined(lint) || defined(__lint)
-
-/* ARGSUSED */
-uint_t
-get_pstate(void)
-{ return 0; }
-#else	/* lint */
-
-	ENTRY_NP(get_pstate)
-	retl
-	rdpr	%pstate, %o0
-	SET_SIZE(get_pstate)
-
-#endif	/* lint */
-/*
- * Routine to get the ccr bits - used by vis emulation code
- * to get the ccr bits before an edge instruction is performed
- *
- */
-
-#if defined(lint) || defined(__lint)
-
-/* ARGSUSED */
-
-uint_t
-get_ccr()
-{ return 0; }
-#else	/* lint */
-
-	ENTRY_NP(get_ccr)
-	retl
-	rd	%ccr, %o0
-	SET_SIZE(get_ccr)
-
-#endif
-
-/*
- * Routine to set the ccr bits - used by vis emulation code
- * to set the ccr bits after an edge instruction is performed
- *
- */
-#if defined(lint) || defined(__lint)
-
-/* ARGSUSED */
-		
-void
-set_ccr(uint_t buf)
-{}
-#else	/* lint */
-
-	ENTRY_NP(set_ccr)
-	retl
-	mov	%o0, %ccr
-	SET_SIZE(set_ccr)
-
-#endif	/* lint */
 
 #if defined(lint) || defined(__lint)
 void
--- a/usr/src/uts/sun4/os/visinstr.c	Wed Jun 15 08:20:19 2005 -0700
+++ b/usr/src/uts/sun4/os/visinstr.c	Wed Jun 15 08:22:03 2005 -0700
@@ -381,7 +381,6 @@
 	uint64_t ah61l, ah61r;		/* Higher 61 bits of address */
 	int al3l, al3r;			/* Lower 3 bits of address */
 	int am32;			/* Whether PSTATE.AM == 1 */
-	uint_t ccr;
 
 	nrs1 = inst.rs1;
 	nrs2 = inst.rs2;
@@ -395,10 +394,10 @@
 		return (ftt);
 
 	/* Get PSTATE.AM to determine 32-bit vs 64-bit addressing */
-	am32 =  get_pstate() & 0x8;
+	am32 =  pregs->r_tstate & TSTATE_AM;
 	if (am32 == 1) {
-		ah61l = addrl & ~0x7 & 0xffffffff;
-		ah61r = addrr & ~0x7 & 0xffffffff;
+		ah61l = addrl & 0xffffffff8;
+		ah61r = addrr & 0xffffffff8;
 	} else {
 		ah61l = addrl & ~0x7;
 		ah61r = addrr & ~0x7;
@@ -419,61 +418,10 @@
 			} else {
 				VISINFO_KSTAT(vis_edge8n);
 			}
-			switch (al3l) {
-			case 0:
-				mask = 0xff;
-				break;
-			case 1:
-				mask = 0x7f;
-				break;
-			case 2:
-				mask = 0x3f;
-				break;
-			case 3:
-				mask = 0x1f;
-				break;
-			case 4:
-				mask = 0x0f;
-				break;
-			case 5:
-				mask = 0x07;
-				break;
-			case 6:
-				mask = 0x03;
-				break;
-			case 7:
-				mask = 0x01;
-				break;
-			}
+			mask = 0xff >> al3l;
 			if (ah61l == ah61r) {
 				al3r = addrr & 0x7;
-				switch (al3r) {
-
-				case 0:
-					mask &= 0x80;
-					break;
-				case 1:
-					mask &= 0xc0;
-					break;
-				case 2:
-					mask &= 0xe0;
-					break;
-				case 3:
-					mask &= 0xf0;
-					break;
-				case 4:
-					mask &= 0xf8;
-					break;
-				case 5:
-					mask &= 0xfc;
-					break;
-				case 6:
-					mask &= 0xfe;
-					break;
-				case 7:
-					mask &= 0xff;
-					break;
-				}
+				mask &= (0xff << (0x7 - al3r)) & 0xff;
 			}
 			break;
 		case edge8l:
@@ -483,61 +431,10 @@
 			} else {
 				VISINFO_KSTAT(vis_edge8ln);
 			}
-
-			switch (al3l) {
-			case 0:
-				mask = 0xff;
-				break;
-			case 1:
-				mask = 0xfe;
-				break;
-			case 2:
-				mask = 0xfc;
-				break;
-			case 3:
-				mask = 0xf8;
-				break;
-			case 4:
-				mask = 0xf0;
-				break;
-			case 5:
-				mask = 0xe0;
-				break;
-			case 6:
-				mask = 0xc0;
-				break;
-			case 7:
-				mask = 0x80;
-				break;
-			}
+			mask = (0xff << al3l) & 0xff;
 			if (ah61l == ah61r) {
 				al3r = addrr & 0x7;
-				switch (al3r) {
-				case 0:
-					mask &= 0x01;
-					break;
-				case 1:
-					mask &= 0x03;
-					break;
-				case 2:
-					mask &= 0x07;
-					break;
-				case 3:
-					mask &= 0x0f;
-					break;
-				case 4:
-					mask &= 0x1f;
-					break;
-				case 5:
-					mask &= 0x3f;
-					break;
-				case 6:
-					mask &= 0x7f;
-					break;
-				case 7:
-					mask &= 0xff;
-					break;
-				}
+				mask &= 0xff >> (0x7 - al3r);
 			}
 			break;
 		}
@@ -547,6 +444,7 @@
 	case edge16n:
 	case edge16ln:
 		al3l = addrl & 0x6;
+		al3l >>= 0x1;
 		switch (inst.opf) {
 		case edge16:
 		case edge16n:
@@ -556,35 +454,11 @@
 			} else {
 				VISINFO_KSTAT(vis_edge16n);
 			}
-			switch (al3l) {
-			case 0:
-				mask = 0xf;
-				break;
-			case 2:
-				mask = 0x7;
-				break;
-			case 4:
-				mask = 0x3;
-				break;
-			case 6:
-				mask = 0x1;
-				break;
-			}
+			mask = 0xf >> al3l;
 			if (ah61l == ah61r) {
 				al3r = addrr & 0x6;
-				switch (al3r) {
-				case 0:
-					mask &= 0x8;
-					break;
-				case 2:
-					mask &= 0xc;
-					break;
-				case 4:
-					mask &= 0xe;
-					break;
-				case 6:
-					mask &= 0xf;
-				}
+				al3r >>= 0x1;
+				mask &= (0xf << (0x3 - al3r)) & 0xf;
 			}
 			break;
 		case edge16l:
@@ -595,36 +469,12 @@
 			} else {
 				VISINFO_KSTAT(vis_edge16ln);
 			}
-			switch (al3l) {
-			case 0:
-				mask = 0xf;
-				break;
-			case 2:
-				mask = 0xe;
-				break;
-			case 4:
-				mask = 0xc;
-				break;
-			case 6:
-				mask = 0x8;
-				break;
-			}
+
+			mask = (0xf << al3l) & 0xf;
 			if (ah61l == ah61r) {
 				al3r = addrr & 0x6;
-				switch (al3r) {
-				case 0:
-					mask &= 0x1;
-					break;
-				case 2:
-					mask &= 0x3;
-					break;
-				case 4:
-					mask &= 0x7;
-					break;
-				case 6:
-					mask &= 0xf;
-					break;
-				}
+				al3r >>= 0x1;
+				mask &= 0xf >> (0x3 - al3r);
 			}
 			break;
 		}
@@ -634,6 +484,8 @@
 	case edge32n:
 	case edge32ln:
 		al3l = addrl & 0x4;
+		al3l >>= 0x2;
+
 		switch (inst.opf) {
 		case edge32:
 		case edge32n:
@@ -643,24 +495,11 @@
 			} else {
 				VISINFO_KSTAT(vis_edge32n);
 			}
-			switch (al3l) {
-			case 0:
-				mask = 0x3;
-				break;
-			case 4:
-				mask = 0x1;
-				break;
-			}
+			mask = 0x3 >> al3l;
 			if (ah61l == ah61r) {
 				al3r = addrr & 0x4;
-				switch (al3r) {
-				case 0:
-					mask &= 0x2;
-					break;
-				case 4:
-					mask &= 0x3;
-					break;
-				}
+				al3r >>= 0x2;
+				mask &= (0x3 << (0x1 - al3r)) & 0x3;
 			}
 			break;
 		case edge32l:
@@ -671,29 +510,17 @@
 			} else {
 				VISINFO_KSTAT(vis_edge32ln);
 			}
-			switch (al3l) {
-			case 0:
-				mask = 0x3;
-				break;
-			case 4:
-				mask = 0x2;
-				break;
-			}
+			mask = (0x3 << al3l) & 0x3;
 			if (ah61l == ah61r) {
 				al3r = addrr & 0x4;
-				switch (al3r) {
-				case 0:
-					mask &= 0x1;
-					break;
-				case 4:
-					mask &= 0x3;
-					break;
+				al3r >>= 0x2;
+				mask &= 0x3 >> (0x1 - al3r);
 			}
 			break;
 		}
 		break;
-		}
 	}
+
 	ftt = write_iureg(pfpsd, nrd, pregs, prw, &mask);
 
 	switch (inst.opf) {
@@ -707,20 +534,17 @@
 		/* We need to set the CCR if we have a carry overflow */
 		/* If this is a 64 bit app, we need to CCR.xcc.v */
 		/* This is the same as the SUBcc instruction */
-		ccr = get_ccr();
 		if (addrl > addrr) {
 			if (am32 == 1) {
-				ccr |= 0x2;
-				set_ccr(ccr);
+				pregs->r_tstate |= TSTATE_IV;
 			} else {
-			    ccr |= 0x20;
-				set_ccr(ccr);
+				pregs->r_tstate |= TSTATE_XV;
 			}
 		}
 		break;
 	}
 	return (ftt);
-}
+	}
 /*
  * Simulator for three dimentional array addressing instructions.
  */
@@ -817,7 +641,7 @@
 	ftt = write_iureg(pfpsd, nrd, pregs, prw, &r);
 
 
-	g = pfpsd->get_gsr(fp);
+	g = pfpsd->fp_current_read_gsr(fp);
 	g &= ~(GSR_ALIGN_MASK);		/* zero the align offset */
 	r = ea & 0x7;
 	if (inst.opf == alignaddrl) {
@@ -828,7 +652,7 @@
 			r = (uint64_t)(s & 0x7);
 	}
 	g |= (r << GSR_ALIGN_SHIFT) & GSR_ALIGN_MASK;
-	pfpsd->set_gsr(g, fp);
+	pfpsd->fp_current_write_gsr(g, fp);
 
 	return (ftt);
 }
@@ -862,12 +686,12 @@
 	ea += tea;
 	ftt = write_iureg(pfpsd, nrd, pregs, prw, &ea);
 
-	g = pfpsd->get_gsr(fp);
+	g = pfpsd->fp_current_read_gsr(fp);
 	g &= ~(GSR_MASK_MASK);		/* zero the mask offset */
 
 	/* Put the least significant 32 bits of ea in GSR.mask */
 	g |= (ea << GSR_MASK_SHIFT) & GSR_MASK_MASK;
-	pfpsd->set_gsr(g, fp);
+	pfpsd->fp_current_write_gsr(g, fp);
 	return (ftt);
 }
 
@@ -1268,7 +1092,7 @@
 		if ((nrs2 & 1) == 1) 	/* fix register encoding */
 			nrs2 = (nrs2 & 0x1e) | 0x20;
 		_fp_unpack_extword(pfpsd, &lrs2.ll, nrs2);
-		r = pfpsd->get_gsr(fp);
+		r = pfpsd->fp_current_read_gsr(fp);
 		/* fpack16 ignores GSR.scale msb */
 		sf = (int)(GSR_SCALE(r) & 0xf);
 		for (i = 0; i <= 3; i++) {
@@ -1295,7 +1119,7 @@
 			nrs2 = (nrs2 & 0x1e) | 0x20;
 		_fp_unpack_extword(pfpsd, &lrs2.ll, nrs2);
 
-		r = pfpsd->get_gsr(fp);
+		r = pfpsd->fp_current_read_gsr(fp);
 		sf = (int)GSR_SCALE(r);
 		lrd.ll = lrs1.ll << 8;
 		for (i = 0, k = 3; i <= 1; i++, k += 4) {
@@ -1319,7 +1143,7 @@
 			nrs2 = (nrs2 & 0x1e) | 0x20;
 		_fp_unpack_extword(pfpsd, &lrs2.ll, nrs2);
 
-		r = pfpsd->get_gsr(fp);
+		r = pfpsd->fp_current_read_gsr(fp);
 		sf = (int)GSR_SCALE(r);
 		for (i = 0; i <= 1; i++) {
 			j = (int)lrs2.i[i];	/* preserve the sign */
@@ -1431,7 +1255,7 @@
 	_fp_unpack_extword(pfpsd, &lrs1.ll, nrs1);
 	_fp_unpack_extword(pfpsd, &lrs2.ll, nrs2);
 
-	r = pfpsd->get_gsr(fp);
+	r = pfpsd->fp_current_read_gsr(fp);
 	ao = (int)GSR_ALIGN(r);
 
 	for (i = 0, j = ao, k = 0; i <= 7; i++)
@@ -1476,8 +1300,7 @@
 	_fp_unpack_extword(pfpsd, &lrs1.ll, nrs1);
 	_fp_unpack_extword(pfpsd, &lrs2.ll, nrs2);
 
-	/* r = get_gsr(fp); */
-	r = pfpsd->get_gsr(fp);
+	r = pfpsd->fp_current_read_gsr(fp);
 	ao = (int)GSR_MASK(r);
 
 	/*
@@ -1521,11 +1344,11 @@
 	uint64_t g, r;
 	nrs2 = inst.rs2;
 
-	g = pfpsd->get_gsr(fp);
+	g = pfpsd->fp_current_read_gsr(fp);
 	g &= ~(GSR_IM_IRND_MASK);	/* zero the IM and IRND fields */
 	r = nrs2 & 0x7;			/* get mode(3 bit) */
 	g |= (r << GSR_IRND_SHIFT);
-	pfpsd->set_gsr(g, fp);
+	pfpsd->fp_current_write_gsr(g, fp);
 	return (ftt_none);
 }
 
@@ -1997,7 +1820,7 @@
 
 	nrd = pinst.rd;
 
-	r = pfpsd->get_gsr(fp);
+	r = pfpsd->fp_current_read_gsr(fp);
 	ftt = write_iureg(pfpsd, nrd, pregs, prw, &r);
 	pregs->r_pc = pregs->r_npc;	/* Do not retry emulated instruction. */
 	pregs->r_npc += 4;
@@ -2040,7 +1863,7 @@
 		r2 = (fp.i << 19) >> 19;
 	}
 	r = r1 ^ r2;
-	pfpsd->set_gsr(r, fp);
+	pfpsd->fp_current_write_gsr(r, fp);
 	pregs->r_pc = pregs->r_npc;	/* Do not retry emulated instruction. */
 	pregs->r_npc += 4;
 	return (ftt);