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