Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/s390/lib/probes.c
26439 views
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
12
int 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
46
int 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
118
int 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
163