1070 if (rd)
1071 inst &= ~(0x1f << 25);
1072 if (i == 0 && ignor)
1073 inst &= ~(0xff << 5);
1074 break;
1075 default:
1076 if (optype == OP_V8_LDSTR && !IS_LDST_ALT(op3) &&
1077 i == 0 && ignor)
1078 inst &= ~(0xff << 5);
1079 else
1080 return (SIMU_ILLEGAL);
1081 break;
1082 }
1083 break;
1084 default:
1085 return (SIMU_ILLEGAL);
1086 }
1087
1088 as = p->p_as;
1089
1090 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
1091 mapseg = as_findseg(as, (caddr_t)rp->r_pc, 0);
1092 ASSERT(mapseg != NULL);
1093 svd = (struct segvn_data *)mapseg->s_data;
1094
1095 /*
1096 * We only create COW page for MAP_PRIVATE mappings.
1097 */
1098 SEGVN_LOCK_ENTER(as, &svd->lock, RW_READER);
1099 if ((svd->type & MAP_TYPE) & MAP_SHARED) {
1100 SEGVN_LOCK_EXIT(as, &svd->lock);
1101 AS_LOCK_EXIT(as, &as->a_lock);
1102 return (SIMU_ILLEGAL);
1103 }
1104 SEGVN_LOCK_EXIT(as, &svd->lock);
1105 AS_LOCK_EXIT(as, &as->a_lock);
1106
1107 /*
1108 * A "flush" instruction using the user PC's vaddr will not work
1109 * here, at least on Spitfire. Instead we create a temporary kernel
1110 * mapping to the user's text page, then modify and flush that.
1111 * Break COW by locking user page.
1112 */
1113 if (as_fault(as->a_hat, as, (caddr_t)(rp->r_pc & PAGEMASK), PAGESIZE,
1114 F_SOFTLOCK, S_READ))
1115 return (SIMU_FAULT);
1116
1117 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
1118 pfnum = hat_getpfnum(as->a_hat, (caddr_t)rp->r_pc);
1119 AS_LOCK_EXIT(as, &as->a_lock);
1120 if (pf_is_memory(pfnum)) {
1121 pp = page_numtopp_nolock(pfnum);
1122 ASSERT(pp == NULL || PAGE_LOCKED(pp));
1123 } else {
1124 (void) as_fault(as->a_hat, as, (caddr_t)(rp->r_pc & PAGEMASK),
1125 PAGESIZE, F_SOFTUNLOCK, S_READ);
1126 return (SIMU_FAULT);
1127 }
1128
1129 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
1130 ka = ppmapin(pp, PROT_READ|PROT_WRITE, (caddr_t)rp->r_pc);
1131 *(uint_t *)(ka + (uintptr_t)(rp->r_pc % PAGESIZE)) = inst;
1132 doflush(ka + (uintptr_t)(rp->r_pc % PAGESIZE));
1133 ppmapout(ka);
1134 AS_LOCK_EXIT(as, &as->a_lock);
1135
1136 (void) as_fault(as->a_hat, as, (caddr_t)(rp->r_pc & PAGEMASK),
1137 PAGESIZE, F_SOFTUNLOCK, S_READ);
1138 return (SIMU_RETRY);
1139 }
1140
1141 /*
1142 * Simulate a "rd %tick" or "rd %stick" (%asr24) instruction.
1143 */
1144 int
1145 simulate_rdtick(struct regs *rp)
1146 {
1147 uint_t inst, op, op3, rd, rs1, i;
1148 caddr_t badaddr;
1149
1150 inst = fetch_user_instr((caddr_t)rp->r_pc);
1151 op = (inst >> 30) & 0x3;
1152 rd = (inst >> 25) & 0x1F;
1153 op3 = (inst >> 19) & 0x3F;
1154 i = (inst >> 13) & 0x1;
|
1070 if (rd)
1071 inst &= ~(0x1f << 25);
1072 if (i == 0 && ignor)
1073 inst &= ~(0xff << 5);
1074 break;
1075 default:
1076 if (optype == OP_V8_LDSTR && !IS_LDST_ALT(op3) &&
1077 i == 0 && ignor)
1078 inst &= ~(0xff << 5);
1079 else
1080 return (SIMU_ILLEGAL);
1081 break;
1082 }
1083 break;
1084 default:
1085 return (SIMU_ILLEGAL);
1086 }
1087
1088 as = p->p_as;
1089
1090 AS_LOCK_ENTER(as, RW_READER);
1091 mapseg = as_findseg(as, (caddr_t)rp->r_pc, 0);
1092 ASSERT(mapseg != NULL);
1093 svd = (struct segvn_data *)mapseg->s_data;
1094
1095 /*
1096 * We only create COW page for MAP_PRIVATE mappings.
1097 */
1098 SEGVN_LOCK_ENTER(as, &svd->lock, RW_READER);
1099 if ((svd->type & MAP_TYPE) & MAP_SHARED) {
1100 SEGVN_LOCK_EXIT(as, &svd->lock);
1101 AS_LOCK_EXIT(as);
1102 return (SIMU_ILLEGAL);
1103 }
1104 SEGVN_LOCK_EXIT(as, &svd->lock);
1105 AS_LOCK_EXIT(as);
1106
1107 /*
1108 * A "flush" instruction using the user PC's vaddr will not work
1109 * here, at least on Spitfire. Instead we create a temporary kernel
1110 * mapping to the user's text page, then modify and flush that.
1111 * Break COW by locking user page.
1112 */
1113 if (as_fault(as->a_hat, as, (caddr_t)(rp->r_pc & PAGEMASK), PAGESIZE,
1114 F_SOFTLOCK, S_READ))
1115 return (SIMU_FAULT);
1116
1117 AS_LOCK_ENTER(as, RW_READER);
1118 pfnum = hat_getpfnum(as->a_hat, (caddr_t)rp->r_pc);
1119 AS_LOCK_EXIT(as);
1120 if (pf_is_memory(pfnum)) {
1121 pp = page_numtopp_nolock(pfnum);
1122 ASSERT(pp == NULL || PAGE_LOCKED(pp));
1123 } else {
1124 (void) as_fault(as->a_hat, as, (caddr_t)(rp->r_pc & PAGEMASK),
1125 PAGESIZE, F_SOFTUNLOCK, S_READ);
1126 return (SIMU_FAULT);
1127 }
1128
1129 AS_LOCK_ENTER(as, RW_READER);
1130 ka = ppmapin(pp, PROT_READ|PROT_WRITE, (caddr_t)rp->r_pc);
1131 *(uint_t *)(ka + (uintptr_t)(rp->r_pc % PAGESIZE)) = inst;
1132 doflush(ka + (uintptr_t)(rp->r_pc % PAGESIZE));
1133 ppmapout(ka);
1134 AS_LOCK_EXIT(as);
1135
1136 (void) as_fault(as->a_hat, as, (caddr_t)(rp->r_pc & PAGEMASK),
1137 PAGESIZE, F_SOFTUNLOCK, S_READ);
1138 return (SIMU_RETRY);
1139 }
1140
1141 /*
1142 * Simulate a "rd %tick" or "rd %stick" (%asr24) instruction.
1143 */
1144 int
1145 simulate_rdtick(struct regs *rp)
1146 {
1147 uint_t inst, op, op3, rd, rs1, i;
1148 caddr_t badaddr;
1149
1150 inst = fetch_user_instr((caddr_t)rp->r_pc);
1151 op = (inst >> 30) & 0x3;
1152 rd = (inst >> 25) & 0x1F;
1153 op3 = (inst >> 19) & 0x3F;
1154 i = (inst >> 13) & 0x1;
|