]> sourceware.org Git - systemtap.git/blame - tapset/s390/registers.stp
Fix typo in languange reference
[systemtap.git] / tapset / s390 / registers.stp
CommitLineData
4ff1e447
JK
1/* Dwarfless register access for s390x */
2
ed82a324 3@__private30 global _reg_offsets[22]
4ff1e447 4
eefd579b
DS
5%{
6#include <asm/ptrace.h>
3ecf49ee
WC
7#ifdef STAPCONF_STACKTRACE_H
8#include <asm/stacktrace.h>
9#endif
eefd579b
DS
10
11/*
12 * The following routines help with getting arguments off the s390x
13 * stack. For more details see:
14 *
15 * "S/390 ELF Application Binary Interface Supplement"
16 * <http://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390/x414.html>
17 */
18
19/*
20 * This is a copy of the kernel's kernel_stack_pointer(), which is
21 * only available on newer kernels.
22 */
23static inline unsigned long _stp_kernel_stack_pointer(struct pt_regs *regs)
24{
25 return regs->gprs[15] & PSW_ADDR_INSN;
26}
27
28/*
29 * This is a copy of the kernel's unexported regs_within_kernel_stack().
30 */
31static int
32_stp_regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
33{
34 unsigned long ksp = _stp_kernel_stack_pointer(regs);
35
36 return (addr & ~(THREAD_SIZE - 1)) == (ksp & ~(THREAD_SIZE - 1));
37}
38%}
39
40/*
41 * _stp_get_kernel_stack_param() - get Nth parameter from the stack
42 * n:stack parameter number (starts from 0)
43 *
44 * _stp_get_kernel_stack_param() returns nth parameter from
45 * the kernel stack. If the nth entry is NOT in the kernel stack, this
46 * returns 0.
47 *
48 * This is based on the kernel's (unexported)
49 * regs_get_kernel_stack_nth() function.
50 */
51function _stp_get_kernel_stack_param:long(n:long)
52%{
aeb73b70 53 __label__ deref_fault;
eefd579b
DS
54 unsigned long addr;
55 struct pt_regs *regs;
56
57 regs = CONTEXT->kregs;
58 if (!regs) {
59 CONTEXT->last_error = "No registers available in this context";
60 return;
61 }
62
63 // The parameters start just after the stack frame.
64 addr = (_stp_kernel_stack_pointer(regs) + sizeof(struct stack_frame)
65 + STAP_ARG_n * sizeof(long));
66 if (!_stp_regs_within_kernel_stack(regs, addr)) {
67 STAP_RETVALUE = 0;
68 return;
69 }
70 STAP_RETVALUE = kread((unsigned long *)addr);
71 return;
72
eefd579b 73deref_fault: /* branched to from kread() */
aeb73b70
RH
74 snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
75 "kernel fault at %#lx accessing stack param(%d)",
76 addr, (int)STAP_ARG_n);
77 CONTEXT->last_error = CONTEXT->error_buffer;
eefd579b
DS
78%}
79
6ae3ec1c 80probe init {
4ff1e447
JK
81 /* Same order as pt_regs */
82 _reg_offsets["args"] = 0
83 _reg_offsets["psw.mask"] = 8
84 _reg_offsets["psw.addr"] = 16
85 _reg_offsets["r0"] = 24
86 _reg_offsets["r1"] = 32
87 _reg_offsets["r2"] = 40
88 _reg_offsets["r3"] = 48
89 _reg_offsets["r4"] = 56
90 _reg_offsets["r5"] = 64
91 _reg_offsets["r6"] = 72
92 _reg_offsets["r7"] = 80
93 _reg_offsets["r8"] = 88
94 _reg_offsets["r9"] = 96
95 _reg_offsets["r10"] = 104
96 _reg_offsets["r11"] = 112
97 _reg_offsets["r12"] = 120
98 _reg_offsets["r13"] = 128
99 _reg_offsets["r14"] = 136
100 _reg_offsets["r15"] = 144
101
102 _reg_offsets["orig_gpr2"] = 152
103 _reg_offsets["ilc"] = 160
104 _reg_offsets["trap"] = 162
105
106 /*
107 * If we ever need to support s390 (31-bit arch), we can
108 * get to the register offsets by using just a
109 * reg32_offset = _reg_offsets["reg"]/2
110 * or somesuch
111 */
4ff1e447
JK
112}
113
114
115/*
116 * Though the flag says 31bit, asm-s390/thread_info.h comment
117 * says "32bit process"
118 */
b583125d 119function probing_32bit_app:long() %{ /* pure */
e04b5d74 120 if (CONTEXT->user_mode_p && _stp_is_compat_task())
b7b482fb 121 STAP_RETVALUE = 1;
4ff1e447 122 else
b7b482fb 123 STAP_RETVALUE = 0;
4ff1e447
JK
124%}
125
92c25572
MW
126function _stp_probing_kernel: long () {
127 return !user_mode();
128}
4ff1e447 129
93f70a9a
FL
130function arch_bytes:long() %{ /* pure */
131 STAP_RETVALUE = sizeof(long);
132%}
133
134function uarch_bytes:long() {
247e2766
FL
135 assert(user_mode(), "requires user mode")
136 return probing_32bit_app() ? 4 : 8
93f70a9a
FL
137}
138
4ff1e447
JK
139function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
140 long value;
d9aed31e 141 struct pt_regs *regs;
5409ddea
FCE
142 if (CONTEXT->sregs)
143 regs = CONTEXT->sregs;
144 else
145 regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs);
d9aed31e 146 if (!regs) {
ba4e4ff4
JS
147 CONTEXT->last_error = "No registers available in this context";
148 return;
149 }
b7b482fb 150 if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(unsigned short)) {
ba4e4ff4 151 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
08fcfd65 152 "Bad register offset: %lld",
b7b482fb 153 (long long)STAP_ARG_offset);
ba4e4ff4
JS
154 CONTEXT->last_error = CONTEXT->error_buffer;
155 return;
156 }
4ff1e447 157
b7b482fb
SM
158 if (STAP_ARG_offset < sizeof(struct pt_regs) - 2 * sizeof(unsigned short))
159 memcpy(&value, ((char *)regs) + STAP_ARG_offset,
4ff1e447
JK
160 sizeof(value));
161 else {
162 /* ilc or trap */
163 unsigned short us_value;
b7b482fb 164 memcpy(&us_value, ((char *)regs) + STAP_ARG_offset,
4ff1e447
JK
165 sizeof(us_value));
166 value = us_value; // not sign-extended
167 }
b7b482fb 168 STAP_RETVALUE = value;
4ff1e447
JK
169%}
170
171function _stp_sign_extend32:long (value:long) {
172 if (value & 0x80000000)
173 value |= (0xffffffff << 32)
174 return value
175}
176
177function _stp_register:long (name:string, sign_extend:long) {
5409ddea
FCE
178 # don't assert this: will get *regs state checked in _stp_get_register_by_offset, and better
179 # assert(registers_valid(), "cannot access CPU registers in this context")
4ff1e447 180 offset = _reg_offsets[name]
5409ddea 181 assert(offset != 0 || (name in _reg_offsets), "Unknown register: " . name)
4ff1e447
JK
182 value = _stp_get_register_by_offset(offset)
183 if (probing_32bit_app()) {
184 if (sign_extend)
185 value = _stp_sign_extend32(value)
186 else
187 value &= 0xffffffff
188 }
189 return value
190}
191
192/* Return the named register value as a signed value. */
193function register:long (name:string) {
194 return _stp_register(name, 1)
195}
196
197/*
198 * Return the named register value as an unsigned value. Specifically,
199 * don't sign-extend the register value when promoting it to 64 bits.
200 */
201function u_register:long (name:string) {
202 return _stp_register(name, 0)
203}
204
205/*
206 * Return the value of function arg #argnum (1=first arg).
207 * If truncate=1, mask off the top 32 bits.
208 * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a
209 * 32-bit app), sign-extend the 32-bit value.
7a563a0f 210 * If force64=1, return a 64-bit value even if we're in a 32-bit app.
4ff1e447 211 */
f861d05e 212function _stp_arg:long (argnum:long, sign_extend:long, truncate:long)
7a563a0f
DS
213{
214 return _stp_arg2(argnum, sign_extend, truncate, 0)
215}
216function _stp_arg2:long (argnum:long, sign_extend:long, truncate:long,
217 force64:long)
eefd579b
DS
218{
219 val = 0
247e2766 220 assert(!(argnum < 1 || argnum > 8), sprintf("Cannot access arg(%d)", argnum))
4ff1e447 221
eefd579b
DS
222 /*
223 * Why not use syscall_get_arguments() here? On the s390x,
224 * syscall_get_arguments() is only defined to work on the
225 * pt_regs structure that gets intialized when a context
226 * switch from user space to kernel space happens due to a
227 * system call. This pt_regs structure is returned by
228 * 'task_pt_regs(current)'.
229 *
230 * This function is designed to get the argument of the
231 * current kernel function, which may or may not be a
232 * syscall. So, we have to roll our own.
233 */
f861d05e 234
eefd579b
DS
235 if (argnum == 1)
236 val = u_register("r2")
237 else if (argnum == 2)
238 val = u_register("r3")
239 else if (argnum == 3)
240 val = u_register("r4")
241 else if (argnum == 4)
242 val = u_register("r5")
243 else if (argnum == 5)
244 val = u_register("r6")
5409ddea
FCE
245 else if (argnum == 6 && %{ CONTEXT->sregs != NULL %} ) // linux syscall arg6 goes into r7
246 val = u_register("r7")
eefd579b 247 else if (argnum >= 6)
5409ddea 248 val = _stp_get_kernel_stack_param(argnum - 6);
eefd579b 249
7a563a0f 250 if ((truncate || @__compat_task) && !force64) {
eefd579b
DS
251 /* High bits may be garbage. */
252 val = (val & 0xffffffff)
253 if (sign_extend)
254 val = _stp_sign_extend32(val)
4ff1e447 255 }
eefd579b
DS
256 return val
257}
4ff1e447
JK
258
259/* Return the value of function arg #argnum (1=first arg) as a signed int. */
260function int_arg:long (argnum:long) {
7a563a0f 261 return _stp_arg2(argnum, 1, 1, 0)
4ff1e447
JK
262}
263
264/* Return the value of function arg #argnum (1=first arg) as an unsigned int. */
265function uint_arg:long (argnum:long) {
7a563a0f 266 return _stp_arg2(argnum, 0, 1, 0)
4ff1e447
JK
267}
268
269function long_arg:long (argnum:long) {
7a563a0f 270 return _stp_arg2(argnum, 1, 0, 0)
4ff1e447
JK
271}
272
273function ulong_arg:long (argnum:long) {
7a563a0f 274 return _stp_arg2(argnum, 0, 0, 0)
4ff1e447
JK
275}
276
277function longlong_arg:long (argnum:long) {
278 if (probing_32bit_app()) {
7a563a0f
DS
279 highbits = _stp_arg2(argnum, 0, 1, 0)
280 lowbits = _stp_arg2(argnum+1, 0, 1, 0)
4ff1e447
JK
281 return ((highbits << 32) | lowbits)
282 } else
7a563a0f 283 return _stp_arg2(argnum, 0, 0, 1)
4ff1e447
JK
284}
285
286function ulonglong_arg:long (argnum:long) {
287 return longlong_arg(argnum)
288}
289
290function pointer_arg:long (argnum:long) {
7a563a0f 291 return _stp_arg2(argnum, 0, 0, 0)
4ff1e447
JK
292}
293
294function s32_arg:long (argnum:long) {
295 return int_arg(argnum)
296}
297
298function u32_arg:long (argnum:long) {
299 return uint_arg(argnum)
300}
301
302function s64_arg:long (argnum:long) {
303 return longlong_arg(argnum)
304}
305
306function u64_arg:long (argnum:long) {
307 return ulonglong_arg(argnum)
308}
309
29d0edeb 310function asmlinkage() %{ /* pure */ %}
4ff1e447 311
29d0edeb 312function fastcall() %{ /* pure */ %}
4ff1e447 313
309d67d8 314function regparm(n:long) %{
4ff1e447
JK
315 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
316 "regparm is invalid on s390.");
317 CONTEXT->last_error = CONTEXT->error_buffer;
318%}
This page took 0.265037 seconds and 6 git commands to generate.