Mercurial > illumos > illumos-gate
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);