1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
6 #include <linux/ptrace.h>
7 #include <linux/sched/task_stack.h>
8 #include <linux/regset.h>
9 #include <linux/unistd.h>
10 #include <linux/elf.h>
12 #define CREATE_TRACE_POINTS
13 #include <trace/events/syscalls.h>
15 struct pt_regs_offset
{
20 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
21 #define REG_OFFSET_END {.name = NULL, .offset = 0}
23 #ifdef CONFIG_ISA_ARCOMPACT
24 static const struct pt_regs_offset regoffset_table
[] = {
26 REG_OFFSET_NAME(lp_start
),
27 REG_OFFSET_NAME(lp_end
),
28 REG_OFFSET_NAME(lp_count
),
29 REG_OFFSET_NAME(status32
),
31 REG_OFFSET_NAME(blink
),
48 REG_OFFSET_NAME(orig_r0
),
55 static const struct pt_regs_offset regoffset_table
[] = {
56 REG_OFFSET_NAME(orig_r0
),
64 #ifdef CONFIG_ARC_HAS_ACCL_REGS
68 #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
69 REG_OFFSET_NAME(DSP_CTRL
),
83 REG_OFFSET_NAME(blink
),
84 REG_OFFSET_NAME(lp_end
),
85 REG_OFFSET_NAME(lp_start
),
86 REG_OFFSET_NAME(lp_count
),
91 REG_OFFSET_NAME(status32
),
96 static struct callee_regs
*task_callee_regs(struct task_struct
*tsk
)
98 struct callee_regs
*tmp
= (struct callee_regs
*)tsk
->thread
.callee_reg
;
102 static int genregs_get(struct task_struct
*target
,
103 const struct user_regset
*regset
,
106 const struct pt_regs
*ptregs
= task_pt_regs(target
);
107 const struct callee_regs
*cregs
= task_callee_regs(target
);
108 unsigned int stop_pc_val
;
110 membuf_zero(&to
, 4); // pad
111 membuf_store(&to
, ptregs
->bta
);
112 membuf_store(&to
, ptregs
->lp_start
);
113 membuf_store(&to
, ptregs
->lp_end
);
114 membuf_store(&to
, ptregs
->lp_count
);
115 membuf_store(&to
, ptregs
->status32
);
116 membuf_store(&to
, ptregs
->ret
);
117 membuf_store(&to
, ptregs
->blink
);
118 membuf_store(&to
, ptregs
->fp
);
119 membuf_store(&to
, ptregs
->r26
); // gp
120 membuf_store(&to
, ptregs
->r12
);
121 membuf_store(&to
, ptregs
->r11
);
122 membuf_store(&to
, ptregs
->r10
);
123 membuf_store(&to
, ptregs
->r9
);
124 membuf_store(&to
, ptregs
->r8
);
125 membuf_store(&to
, ptregs
->r7
);
126 membuf_store(&to
, ptregs
->r6
);
127 membuf_store(&to
, ptregs
->r5
);
128 membuf_store(&to
, ptregs
->r4
);
129 membuf_store(&to
, ptregs
->r3
);
130 membuf_store(&to
, ptregs
->r2
);
131 membuf_store(&to
, ptregs
->r1
);
132 membuf_store(&to
, ptregs
->r0
);
133 membuf_store(&to
, ptregs
->sp
);
134 membuf_zero(&to
, 4); // pad2
135 membuf_store(&to
, cregs
->r25
);
136 membuf_store(&to
, cregs
->r24
);
137 membuf_store(&to
, cregs
->r23
);
138 membuf_store(&to
, cregs
->r22
);
139 membuf_store(&to
, cregs
->r21
);
140 membuf_store(&to
, cregs
->r20
);
141 membuf_store(&to
, cregs
->r19
);
142 membuf_store(&to
, cregs
->r18
);
143 membuf_store(&to
, cregs
->r17
);
144 membuf_store(&to
, cregs
->r16
);
145 membuf_store(&to
, cregs
->r15
);
146 membuf_store(&to
, cregs
->r14
);
147 membuf_store(&to
, cregs
->r13
);
148 membuf_store(&to
, target
->thread
.fault_address
); // efa
150 if (in_brkpt_trap(ptregs
)) {
151 stop_pc_val
= target
->thread
.fault_address
;
152 pr_debug("\t\tstop_pc (brk-pt)\n");
154 stop_pc_val
= ptregs
->ret
;
155 pr_debug("\t\tstop_pc (others)\n");
158 return membuf_store(&to
, stop_pc_val
); // stop_pc
161 static int genregs_set(struct task_struct
*target
,
162 const struct user_regset
*regset
,
163 unsigned int pos
, unsigned int count
,
164 const void *kbuf
, const void __user
*ubuf
)
166 const struct pt_regs
*ptregs
= task_pt_regs(target
);
167 const struct callee_regs
*cregs
= task_callee_regs(target
);
170 #define REG_IN_CHUNK(FIRST, NEXT, PTR) \
172 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
174 offsetof(struct user_regs_struct, FIRST), \
175 offsetof(struct user_regs_struct, NEXT));
177 #define REG_IN_ONE(LOC, PTR) \
179 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
181 offsetof(struct user_regs_struct, LOC), \
182 offsetof(struct user_regs_struct, LOC) + 4);
184 #define REG_IGNORE_ONE(LOC) \
186 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
187 offsetof(struct user_regs_struct, LOC), \
188 offsetof(struct user_regs_struct, LOC) + 4);
192 REG_IN_ONE(scratch
.bta
, &ptregs
->bta
);
193 REG_IN_ONE(scratch
.lp_start
, &ptregs
->lp_start
);
194 REG_IN_ONE(scratch
.lp_end
, &ptregs
->lp_end
);
195 REG_IN_ONE(scratch
.lp_count
, &ptregs
->lp_count
);
197 REG_IGNORE_ONE(scratch
.status32
);
199 REG_IN_ONE(scratch
.ret
, &ptregs
->ret
);
200 REG_IN_ONE(scratch
.blink
, &ptregs
->blink
);
201 REG_IN_ONE(scratch
.fp
, &ptregs
->fp
);
202 REG_IN_ONE(scratch
.gp
, &ptregs
->r26
);
203 REG_IN_ONE(scratch
.r12
, &ptregs
->r12
);
204 REG_IN_ONE(scratch
.r11
, &ptregs
->r11
);
205 REG_IN_ONE(scratch
.r10
, &ptregs
->r10
);
206 REG_IN_ONE(scratch
.r9
, &ptregs
->r9
);
207 REG_IN_ONE(scratch
.r8
, &ptregs
->r8
);
208 REG_IN_ONE(scratch
.r7
, &ptregs
->r7
);
209 REG_IN_ONE(scratch
.r6
, &ptregs
->r6
);
210 REG_IN_ONE(scratch
.r5
, &ptregs
->r5
);
211 REG_IN_ONE(scratch
.r4
, &ptregs
->r4
);
212 REG_IN_ONE(scratch
.r3
, &ptregs
->r3
);
213 REG_IN_ONE(scratch
.r2
, &ptregs
->r2
);
214 REG_IN_ONE(scratch
.r1
, &ptregs
->r1
);
215 REG_IN_ONE(scratch
.r0
, &ptregs
->r0
);
216 REG_IN_ONE(scratch
.sp
, &ptregs
->sp
);
218 REG_IGNORE_ONE(pad2
);
220 REG_IN_ONE(callee
.r25
, &cregs
->r25
);
221 REG_IN_ONE(callee
.r24
, &cregs
->r24
);
222 REG_IN_ONE(callee
.r23
, &cregs
->r23
);
223 REG_IN_ONE(callee
.r22
, &cregs
->r22
);
224 REG_IN_ONE(callee
.r21
, &cregs
->r21
);
225 REG_IN_ONE(callee
.r20
, &cregs
->r20
);
226 REG_IN_ONE(callee
.r19
, &cregs
->r19
);
227 REG_IN_ONE(callee
.r18
, &cregs
->r18
);
228 REG_IN_ONE(callee
.r17
, &cregs
->r17
);
229 REG_IN_ONE(callee
.r16
, &cregs
->r16
);
230 REG_IN_ONE(callee
.r15
, &cregs
->r15
);
231 REG_IN_ONE(callee
.r14
, &cregs
->r14
);
232 REG_IN_ONE(callee
.r13
, &cregs
->r13
);
234 REG_IGNORE_ONE(efa
); /* efa update invalid */
235 REG_IGNORE_ONE(stop_pc
); /* PC updated via @ret */
240 #ifdef CONFIG_ISA_ARCV2
241 static int arcv2regs_get(struct task_struct
*target
,
242 const struct user_regset
*regset
,
245 const struct pt_regs
*regs
= task_pt_regs(target
);
247 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS
))
249 * itemized copy not needed like above as layout of regs (r30,r58,r59)
250 * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
252 return membuf_write(&to
, ®s
->r30
, sizeof(struct user_regs_arcv2
));
255 membuf_write(&to
, ®s
->r30
, 4); /* r30 only */
256 return membuf_zero(&to
, sizeof(struct user_regs_arcv2
) - 4);
259 static int arcv2regs_set(struct task_struct
*target
,
260 const struct user_regset
*regset
,
261 unsigned int pos
, unsigned int count
,
262 const void *kbuf
, const void __user
*ubuf
)
264 const struct pt_regs
*regs
= task_pt_regs(target
);
267 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS
))
268 copy_sz
= sizeof(struct user_regs_arcv2
);
270 copy_sz
= 4; /* r30 only */
272 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, (void *)®s
->r30
,
285 static const struct user_regset arc_regsets
[] = {
287 .core_note_type
= NT_PRSTATUS
,
289 .size
= sizeof(unsigned long),
290 .align
= sizeof(unsigned long),
291 .regset_get
= genregs_get
,
294 #ifdef CONFIG_ISA_ARCV2
296 .core_note_type
= NT_ARC_V2
,
298 .size
= sizeof(unsigned long),
299 .align
= sizeof(unsigned long),
300 .regset_get
= arcv2regs_get
,
301 .set
= arcv2regs_set
,
306 static const struct user_regset_view user_arc_view
= {
308 .e_machine
= EM_ARC_INUSE
,
309 .regsets
= arc_regsets
,
310 .n
= ARRAY_SIZE(arc_regsets
)
313 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
315 return &user_arc_view
;
318 void ptrace_disable(struct task_struct
*child
)
322 long arch_ptrace(struct task_struct
*child
, long request
,
323 unsigned long addr
, unsigned long data
)
327 pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request
, addr
, data
);
330 case PTRACE_GET_THREAD_AREA
:
331 ret
= put_user(task_thread_info(child
)->thr_ptr
,
332 (unsigned long __user
*)data
);
335 ret
= ptrace_request(child
, request
, addr
, data
);
342 asmlinkage
int syscall_trace_enter(struct pt_regs
*regs
)
344 if (test_thread_flag(TIF_SYSCALL_TRACE
))
345 if (ptrace_report_syscall_entry(regs
))
348 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
349 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT
))
350 trace_sys_enter(regs
, syscall_get_nr(current
, regs
));
356 asmlinkage
void syscall_trace_exit(struct pt_regs
*regs
)
358 if (test_thread_flag(TIF_SYSCALL_TRACE
))
359 ptrace_report_syscall_exit(regs
, 0);
361 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
362 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT
))
363 trace_sys_exit(regs
, regs_return_value(regs
));
367 int regs_query_register_offset(const char *name
)
369 const struct pt_regs_offset
*roff
;
371 for (roff
= regoffset_table
; roff
->name
!= NULL
; roff
++)
372 if (!strcmp(roff
->name
, name
))
377 const char *regs_query_register_name(unsigned int offset
)
379 const struct pt_regs_offset
*roff
;
380 for (roff
= regoffset_table
; roff
->name
!= NULL
; roff
++)
381 if (roff
->offset
== offset
)
386 bool regs_within_kernel_stack(struct pt_regs
*regs
, unsigned long addr
)
388 return (addr
& ~(THREAD_SIZE
- 1)) ==
389 (kernel_stack_pointer(regs
) & ~(THREAD_SIZE
- 1));
392 unsigned long regs_get_kernel_stack_nth(struct pt_regs
*regs
, unsigned int n
)
394 unsigned long *addr
= (unsigned long *)kernel_stack_pointer(regs
);
397 if (regs_within_kernel_stack(regs
, (unsigned long)addr
))