Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *    Common helper functions for kprobes and uprobes
0004  *
0005  *    Copyright IBM Corp. 2014
0006  */
0007 
0008 #include <linux/errno.h>
0009 #include <asm/kprobes.h>
0010 #include <asm/dis.h>
0011 
0012 int probe_is_prohibited_opcode(u16 *insn)
0013 {
0014     if (!is_known_insn((unsigned char *)insn))
0015         return -EINVAL;
0016     switch (insn[0] >> 8) {
0017     case 0x0c:  /* bassm */
0018     case 0x0b:  /* bsm   */
0019     case 0x83:  /* diag  */
0020     case 0x44:  /* ex    */
0021     case 0xac:  /* stnsm */
0022     case 0xad:  /* stosm */
0023         return -EINVAL;
0024     case 0xc6:
0025         switch (insn[0] & 0x0f) {
0026         case 0x00: /* exrl   */
0027             return -EINVAL;
0028         }
0029     }
0030     switch (insn[0]) {
0031     case 0x0101:    /* pr    */
0032     case 0xb25a:    /* bsa   */
0033     case 0xb240:    /* bakr  */
0034     case 0xb258:    /* bsg   */
0035     case 0xb218:    /* pc    */
0036     case 0xb228:    /* pt    */
0037     case 0xb98d:    /* epsw  */
0038     case 0xe560:    /* tbegin */
0039     case 0xe561:    /* tbeginc */
0040     case 0xb2f8:    /* tend  */
0041         return -EINVAL;
0042     }
0043     return 0;
0044 }
0045 
0046 int probe_get_fixup_type(u16 *insn)
0047 {
0048     /* default fixup method */
0049     int fixup = FIXUP_PSW_NORMAL;
0050 
0051     switch (insn[0] >> 8) {
0052     case 0x05:  /* balr */
0053     case 0x0d:  /* basr */
0054         fixup = FIXUP_RETURN_REGISTER;
0055         /* if r2 = 0, no branch will be taken */
0056         if ((insn[0] & 0x0f) == 0)
0057             fixup |= FIXUP_BRANCH_NOT_TAKEN;
0058         break;
0059     case 0x06:  /* bctr */
0060     case 0x07:  /* bcr  */
0061         fixup = FIXUP_BRANCH_NOT_TAKEN;
0062         break;
0063     case 0x45:  /* bal  */
0064     case 0x4d:  /* bas  */
0065         fixup = FIXUP_RETURN_REGISTER;
0066         break;
0067     case 0x47:  /* bc   */
0068     case 0x46:  /* bct  */
0069     case 0x86:  /* bxh  */
0070     case 0x87:  /* bxle */
0071         fixup = FIXUP_BRANCH_NOT_TAKEN;
0072         break;
0073     case 0x82:  /* lpsw */
0074         fixup = FIXUP_NOT_REQUIRED;
0075         break;
0076     case 0xb2:  /* lpswe */
0077         if ((insn[0] & 0xff) == 0xb2)
0078             fixup = FIXUP_NOT_REQUIRED;
0079         break;
0080     case 0xa7:  /* bras */
0081         if ((insn[0] & 0x0f) == 0x05)
0082             fixup |= FIXUP_RETURN_REGISTER;
0083         break;
0084     case 0xc0:
0085         if ((insn[0] & 0x0f) == 0x05)   /* brasl */
0086             fixup |= FIXUP_RETURN_REGISTER;
0087         break;
0088     case 0xeb:
0089         switch (insn[2] & 0xff) {
0090         case 0x44: /* bxhg  */
0091         case 0x45: /* bxleg */
0092             fixup = FIXUP_BRANCH_NOT_TAKEN;
0093             break;
0094         }
0095         break;
0096     case 0xe3:  /* bctg */
0097         if ((insn[2] & 0xff) == 0x46)
0098             fixup = FIXUP_BRANCH_NOT_TAKEN;
0099         break;
0100     case 0xec:
0101         switch (insn[2] & 0xff) {
0102         case 0xe5: /* clgrb */
0103         case 0xe6: /* cgrb  */
0104         case 0xf6: /* crb   */
0105         case 0xf7: /* clrb  */
0106         case 0xfc: /* cgib  */
0107         case 0xfd: /* cglib */
0108         case 0xfe: /* cib   */
0109         case 0xff: /* clib  */
0110             fixup = FIXUP_BRANCH_NOT_TAKEN;
0111             break;
0112         }
0113         break;
0114     }
0115     return fixup;
0116 }
0117 
0118 int probe_is_insn_relative_long(u16 *insn)
0119 {
0120     /* Check if we have a RIL-b or RIL-c format instruction which
0121      * we need to modify in order to avoid instruction emulation. */
0122     switch (insn[0] >> 8) {
0123     case 0xc0:
0124         if ((insn[0] & 0x0f) == 0x00) /* larl */
0125             return true;
0126         break;
0127     case 0xc4:
0128         switch (insn[0] & 0x0f) {
0129         case 0x02: /* llhrl  */
0130         case 0x04: /* lghrl  */
0131         case 0x05: /* lhrl   */
0132         case 0x06: /* llghrl */
0133         case 0x07: /* sthrl  */
0134         case 0x08: /* lgrl   */
0135         case 0x0b: /* stgrl  */
0136         case 0x0c: /* lgfrl  */
0137         case 0x0d: /* lrl    */
0138         case 0x0e: /* llgfrl */
0139         case 0x0f: /* strl   */
0140             return true;
0141         }
0142         break;
0143     case 0xc6:
0144         switch (insn[0] & 0x0f) {
0145         case 0x02: /* pfdrl  */
0146         case 0x04: /* cghrl  */
0147         case 0x05: /* chrl   */
0148         case 0x06: /* clghrl */
0149         case 0x07: /* clhrl  */
0150         case 0x08: /* cgrl   */
0151         case 0x0a: /* clgrl  */
0152         case 0x0c: /* cgfrl  */
0153         case 0x0d: /* crl    */
0154         case 0x0e: /* clgfrl */
0155         case 0x0f: /* clrl   */
0156             return true;
0157         }
0158         break;
0159     }
0160     return false;
0161 }