linux/arch/s390/lib/probes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *    Common helper functions for kprobes and uprobes
   4 *
   5 *    Copyright IBM Corp. 2014
   6 */
   7
   8#include <linux/errno.h>
   9#include <asm/kprobes.h>
  10#include <asm/dis.h>
  11
  12int probe_is_prohibited_opcode(u16 *insn)
  13{
  14        if (!is_known_insn((unsigned char *)insn))
  15                return -EINVAL;
  16        switch (insn[0] >> 8) {
  17        case 0x0c:      /* bassm */
  18        case 0x0b:      /* bsm   */
  19        case 0x83:      /* diag  */
  20        case 0x44:      /* ex    */
  21        case 0xac:      /* stnsm */
  22        case 0xad:      /* stosm */
  23                return -EINVAL;
  24        case 0xc6:
  25                switch (insn[0] & 0x0f) {
  26                case 0x00: /* exrl   */
  27                        return -EINVAL;
  28                }
  29        }
  30        switch (insn[0]) {
  31        case 0x0101:    /* pr    */
  32        case 0xb25a:    /* bsa   */
  33        case 0xb240:    /* bakr  */
  34        case 0xb258:    /* bsg   */
  35        case 0xb218:    /* pc    */
  36        case 0xb228:    /* pt    */
  37        case 0xb98d:    /* epsw  */
  38        case 0xe560:    /* tbegin */
  39        case 0xe561:    /* tbeginc */
  40        case 0xb2f8:    /* tend  */
  41                return -EINVAL;
  42        }
  43        return 0;
  44}
  45
  46int probe_get_fixup_type(u16 *insn)
  47{
  48        /* default fixup method */
  49        int fixup = FIXUP_PSW_NORMAL;
  50
  51        switch (insn[0] >> 8) {
  52        case 0x05:      /* balr */
  53        case 0x0d:      /* basr */
  54                fixup = FIXUP_RETURN_REGISTER;
  55                /* if r2 = 0, no branch will be taken */
  56                if ((insn[0] & 0x0f) == 0)
  57                        fixup |= FIXUP_BRANCH_NOT_TAKEN;
  58                break;
  59        case 0x06:      /* bctr */
  60        case 0x07:      /* bcr  */
  61                fixup = FIXUP_BRANCH_NOT_TAKEN;
  62                break;
  63        case 0x45:      /* bal  */
  64        case 0x4d:      /* bas  */
  65                fixup = FIXUP_RETURN_REGISTER;
  66                break;
  67        case 0x47:      /* bc   */
  68        case 0x46:      /* bct  */
  69        case 0x86:      /* bxh  */
  70        case 0x87:      /* bxle */
  71                fixup = FIXUP_BRANCH_NOT_TAKEN;
  72                break;
  73        case 0x82:      /* lpsw */
  74                fixup = FIXUP_NOT_REQUIRED;
  75                break;
  76        case 0xb2:      /* lpswe */
  77                if ((insn[0] & 0xff) == 0xb2)
  78                        fixup = FIXUP_NOT_REQUIRED;
  79                break;
  80        case 0xa7:      /* bras */
  81                if ((insn[0] & 0x0f) == 0x05)
  82                        fixup |= FIXUP_RETURN_REGISTER;
  83                break;
  84        case 0xc0:
  85                if ((insn[0] & 0x0f) == 0x05)   /* brasl */
  86                        fixup |= FIXUP_RETURN_REGISTER;
  87                break;
  88        case 0xeb:
  89                switch (insn[2] & 0xff) {
  90                case 0x44: /* bxhg  */
  91                case 0x45: /* bxleg */
  92                        fixup = FIXUP_BRANCH_NOT_TAKEN;
  93                        break;
  94                }
  95                break;
  96        case 0xe3:      /* bctg */
  97                if ((insn[2] & 0xff) == 0x46)
  98                        fixup = FIXUP_BRANCH_NOT_TAKEN;
  99                break;
 100        case 0xec:
 101                switch (insn[2] & 0xff) {
 102                case 0xe5: /* clgrb */
 103                case 0xe6: /* cgrb  */
 104                case 0xf6: /* crb   */
 105                case 0xf7: /* clrb  */
 106                case 0xfc: /* cgib  */
 107                case 0xfd: /* cglib */
 108                case 0xfe: /* cib   */
 109                case 0xff: /* clib  */
 110                        fixup = FIXUP_BRANCH_NOT_TAKEN;
 111                        break;
 112                }
 113                break;
 114        }
 115        return fixup;
 116}
 117
 118int probe_is_insn_relative_long(u16 *insn)
 119{
 120        /* Check if we have a RIL-b or RIL-c format instruction which
 121         * we need to modify in order to avoid instruction emulation. */
 122        switch (insn[0] >> 8) {
 123        case 0xc0:
 124                if ((insn[0] & 0x0f) == 0x00) /* larl */
 125                        return true;
 126                break;
 127        case 0xc4:
 128                switch (insn[0] & 0x0f) {
 129                case 0x02: /* llhrl  */
 130                case 0x04: /* lghrl  */
 131                case 0x05: /* lhrl   */
 132                case 0x06: /* llghrl */
 133                case 0x07: /* sthrl  */
 134                case 0x08: /* lgrl   */
 135                case 0x0b: /* stgrl  */
 136                case 0x0c: /* lgfrl  */
 137                case 0x0d: /* lrl    */
 138                case 0x0e: /* llgfrl */
 139                case 0x0f: /* strl   */
 140                        return true;
 141                }
 142                break;
 143        case 0xc6:
 144                switch (insn[0] & 0x0f) {
 145                case 0x02: /* pfdrl  */
 146                case 0x04: /* cghrl  */
 147                case 0x05: /* chrl   */
 148                case 0x06: /* clghrl */
 149                case 0x07: /* clhrl  */
 150                case 0x08: /* cgrl   */
 151                case 0x0a: /* clgrl  */
 152                case 0x0c: /* cgfrl  */
 153                case 0x0d: /* crl    */
 154                case 0x0e: /* clgfrl */
 155                case 0x0f: /* clrl   */
 156                        return true;
 157                }
 158                break;
 159        }
 160        return false;
 161}
 162