[IA64] kprobe clears qp bits for special instructions

On IA64 there exists some special instructions which
always need to be executed regradless of qp bits, such
as com.crel.unc, tbit.trel.unc etc.
This patch clears qp bits when inserting kprobe trap code
and disables probepoint on slot 1 for these special
instructions.

Signed-off-by: bibo,mao <bibo.mao@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by bibo,mao and committed by Tony Luck df3e0d1c 08ed38b6

+122 -53
+122 -53
arch/ia64/kernel/kprobes.c
··· 130 130 131 131 /* 132 132 * In this function we check to see if the instruction 133 - * on which we are inserting kprobe is supported. 134 - * Returns 0 if supported 135 - * Returns -EINVAL if unsupported 136 - */ 137 - static int __kprobes unsupported_inst(uint template, uint slot, 138 - uint major_opcode, 139 - unsigned long kprobe_inst, 140 - unsigned long addr) 141 - { 142 - if (bundle_encoding[template][slot] == I) { 143 - switch (major_opcode) { 144 - case 0x0: //I_UNIT_MISC_OPCODE: 145 - /* 146 - * Check for Integer speculation instruction 147 - * - Bit 33-35 to be equal to 0x1 148 - */ 149 - if (((kprobe_inst >> 33) & 0x7) == 1) { 150 - printk(KERN_WARNING 151 - "Kprobes on speculation inst at <0x%lx> not supported\n", 152 - addr); 153 - return -EINVAL; 154 - } 155 - 156 - /* 157 - * IP relative mov instruction 158 - * - Bit 27-35 to be equal to 0x30 159 - */ 160 - if (((kprobe_inst >> 27) & 0x1FF) == 0x30) { 161 - printk(KERN_WARNING 162 - "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n", 163 - addr); 164 - return -EINVAL; 165 - 166 - } 167 - } 168 - } 169 - return 0; 170 - } 171 - 172 - 173 - /* 174 - * In this function we check to see if the instruction 175 133 * (qp) cmpx.crel.ctype p1,p2=r2,r3 176 134 * on which we are inserting kprobe is cmp instruction 177 135 * with ctype as unc. ··· 165 207 } 166 208 167 209 /* 210 + * In this function we check to see if the instruction 211 + * on which we are inserting kprobe is supported. 212 + * Returns qp value if supported 213 + * Returns -EINVAL if unsupported 214 + */ 215 + static int __kprobes unsupported_inst(uint template, uint slot, 216 + uint major_opcode, 217 + unsigned long kprobe_inst, 218 + unsigned long addr) 219 + { 220 + int qp; 221 + 222 + qp = kprobe_inst & 0x3f; 223 + if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) { 224 + if (slot == 1 && qp) { 225 + printk(KERN_WARNING "Kprobes on cmp unc" 226 + "instruction on slot 1 at <0x%lx>" 227 + "is not supported\n", addr); 228 + return -EINVAL; 229 + 230 + } 231 + qp = 0; 232 + } 233 + else if (bundle_encoding[template][slot] == I) { 234 + if (major_opcode == 0) { 235 + /* 236 + * Check for Integer speculation instruction 237 + * - Bit 33-35 to be equal to 0x1 238 + */ 239 + if (((kprobe_inst >> 33) & 0x7) == 1) { 240 + printk(KERN_WARNING 241 + "Kprobes on speculation inst at <0x%lx> not supported\n", 242 + addr); 243 + return -EINVAL; 244 + } 245 + /* 246 + * IP relative mov instruction 247 + * - Bit 27-35 to be equal to 0x30 248 + */ 249 + if (((kprobe_inst >> 27) & 0x1FF) == 0x30) { 250 + printk(KERN_WARNING 251 + "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n", 252 + addr); 253 + return -EINVAL; 254 + 255 + } 256 + } 257 + else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) && 258 + (kprobe_inst & (0x1UL << 12))) { 259 + /* test bit instructions, tbit,tnat,tf 260 + * bit 33-36 to be equal to 0 261 + * bit 12 to be equal to 1 262 + */ 263 + if (slot == 1 && qp) { 264 + printk(KERN_WARNING "Kprobes on test bit" 265 + "instruction on slot at <0x%lx>" 266 + "is not supported\n", addr); 267 + return -EINVAL; 268 + } 269 + qp = 0; 270 + } 271 + } 272 + else if (bundle_encoding[template][slot] == B) { 273 + if (major_opcode == 7) { 274 + /* IP-Relative Predict major code is 7 */ 275 + printk(KERN_WARNING "Kprobes on IP-Relative" 276 + "Predict is not supported\n"); 277 + return -EINVAL; 278 + } 279 + else if (major_opcode == 2) { 280 + /* Indirect Predict, major code is 2 281 + * bit 27-32 to be equal to 10 or 11 282 + */ 283 + int x6=(kprobe_inst >> 27) & 0x3F; 284 + if ((x6 == 0x10) || (x6 == 0x11)) { 285 + printk(KERN_WARNING "Kprobes on" 286 + "Indirect Predict is not supported\n"); 287 + return -EINVAL; 288 + } 289 + } 290 + } 291 + /* kernel does not use float instruction, here for safety kprobe 292 + * will judge whether it is fcmp/flass/float approximation instruction 293 + */ 294 + else if (unlikely(bundle_encoding[template][slot] == F)) { 295 + if ((major_opcode == 4 || major_opcode == 5) && 296 + (kprobe_inst & (0x1 << 12))) { 297 + /* fcmp/fclass unc instruction */ 298 + if (slot == 1 && qp) { 299 + printk(KERN_WARNING "Kprobes on fcmp/fclass " 300 + "instruction on slot at <0x%lx> " 301 + "is not supported\n", addr); 302 + return -EINVAL; 303 + 304 + } 305 + qp = 0; 306 + } 307 + if ((major_opcode == 0 || major_opcode == 1) && 308 + (kprobe_inst & (0x1UL << 33))) { 309 + /* float Approximation instruction */ 310 + if (slot == 1 && qp) { 311 + printk(KERN_WARNING "Kprobes on float Approx " 312 + "instr at <0x%lx> is not supported\n", 313 + addr); 314 + return -EINVAL; 315 + } 316 + qp = 0; 317 + } 318 + } 319 + return qp; 320 + } 321 + 322 + /* 168 323 * In this function we override the bundle with 169 324 * the break instruction at the given slot. 170 325 */ 171 326 static void __kprobes prepare_break_inst(uint template, uint slot, 172 327 uint major_opcode, 173 328 unsigned long kprobe_inst, 174 - struct kprobe *p) 329 + struct kprobe *p, 330 + int qp) 175 331 { 176 332 unsigned long break_inst = BREAK_INST; 177 333 bundle_t *bundle = &p->opcode.bundle; 178 334 179 335 /* 180 336 * Copy the original kprobe_inst qualifying predicate(qp) 181 - * to the break instruction iff !is_cmp_ctype_unc_inst 182 - * because for cmp instruction with ctype equal to unc, 183 - * which is a special instruction always needs to be 184 - * executed regradless of qp 337 + * to the break instruction 185 338 */ 186 - if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) 187 - break_inst |= (0x3f & kprobe_inst); 339 + break_inst |= qp; 188 340 189 341 switch (slot) { 190 342 case 0: ··· 490 422 unsigned long kprobe_inst=0; 491 423 unsigned int slot = addr & 0xf, template, major_opcode = 0; 492 424 bundle_t *bundle; 425 + int qp; 493 426 494 427 bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle; 495 428 template = bundle->quad0.template; ··· 505 436 /* Get kprobe_inst and major_opcode from the bundle */ 506 437 get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode); 507 438 508 - if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr)) 509 - return -EINVAL; 510 - 439 + qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr); 440 + if (qp < 0) 441 + return -EINVAL; 511 442 512 443 p->ainsn.insn = get_insn_slot(); 513 444 if (!p->ainsn.insn) ··· 515 446 memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t)); 516 447 memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t)); 517 448 518 - prepare_break_inst(template, slot, major_opcode, kprobe_inst, p); 449 + prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp); 519 450 520 451 return 0; 521 452 }