1 // SPDX-License-Identifier: GPL-2.0
2 /* ptrace.c: Sparc process tracing support.
4 * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
9 * Added Linux support -miguel (weird, eh?, the original code was meant
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
16 #include <linux/errno.h>
17 #include <linux/ptrace.h>
18 #include <linux/user.h>
19 #include <linux/smp.h>
20 #include <linux/security.h>
21 #include <linux/signal.h>
22 #include <linux/regset.h>
23 #include <linux/elf.h>
25 #include <linux/uaccess.h>
26 #include <asm/cacheflush.h>
30 /* #define ALLOW_INIT_TRACING */
33 * Called by kernel/ptrace.c when detaching..
35 * Make sure single step bits etc are not set.
37 void ptrace_disable(struct task_struct
*child
)
47 static int regwindow32_get(struct task_struct
*target
,
48 const struct pt_regs
*regs
,
51 unsigned long reg_window
= regs
->u_regs
[UREG_I6
];
52 int size
= 16 * sizeof(u32
);
54 if (target
== current
) {
55 if (copy_from_user(uregs
, (void __user
*)reg_window
, size
))
58 if (access_process_vm(target
, reg_window
, uregs
, size
,
65 static int regwindow32_set(struct task_struct
*target
,
66 const struct pt_regs
*regs
,
69 unsigned long reg_window
= regs
->u_regs
[UREG_I6
];
70 int size
= 16 * sizeof(u32
);
72 if (target
== current
) {
73 if (copy_to_user((void __user
*)reg_window
, uregs
, size
))
76 if (access_process_vm(target
, reg_window
, uregs
, size
,
77 FOLL_FORCE
| FOLL_WRITE
) != size
)
83 static int genregs32_get(struct task_struct
*target
,
84 const struct user_regset
*regset
,
87 const struct pt_regs
*regs
= target
->thread
.kregs
;
90 if (target
== current
)
93 membuf_write(&to
, regs
->u_regs
, 16 * sizeof(u32
));
96 if (regwindow32_get(target
, regs
, uregs
))
98 membuf_write(&to
, uregs
, 16 * sizeof(u32
));
99 membuf_store(&to
, regs
->psr
);
100 membuf_store(&to
, regs
->pc
);
101 membuf_store(&to
, regs
->npc
);
102 membuf_store(&to
, regs
->y
);
103 return membuf_zero(&to
, 2 * sizeof(u32
));
106 static int genregs32_set(struct task_struct
*target
,
107 const struct user_regset
*regset
,
108 unsigned int pos
, unsigned int count
,
109 const void *kbuf
, const void __user
*ubuf
)
111 struct pt_regs
*regs
= target
->thread
.kregs
;
116 if (target
== current
)
117 flush_user_windows();
119 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
121 0, 16 * sizeof(u32
));
125 if (regwindow32_get(target
, regs
, uregs
))
127 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
129 16 * sizeof(u32
), 32 * sizeof(u32
));
132 if (regwindow32_set(target
, regs
, uregs
))
137 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
139 32 * sizeof(u32
), 33 * sizeof(u32
));
142 regs
->psr
= (regs
->psr
& ~(PSR_ICC
| PSR_SYSCALL
)) |
143 (psr
& (PSR_ICC
| PSR_SYSCALL
));
146 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
148 33 * sizeof(u32
), 34 * sizeof(u32
));
151 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
153 34 * sizeof(u32
), 35 * sizeof(u32
));
156 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
158 35 * sizeof(u32
), 36 * sizeof(u32
));
161 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
, 36 * sizeof(u32
),
166 static int fpregs32_get(struct task_struct
*target
,
167 const struct user_regset
*regset
,
171 if (target
== current
)
172 save_and_clear_fpu();
175 membuf_write(&to
, target
->thread
.float_regs
, 32 * sizeof(u32
));
176 membuf_zero(&to
, sizeof(u32
));
177 membuf_write(&to
, &target
->thread
.fsr
, sizeof(u32
));
178 membuf_store(&to
, (u32
)((1 << 8) | (8 << 16)));
179 return membuf_zero(&to
, 64 * sizeof(u32
));
182 static int fpregs32_set(struct task_struct
*target
,
183 const struct user_regset
*regset
,
184 unsigned int pos
, unsigned int count
,
185 const void *kbuf
, const void __user
*ubuf
)
187 unsigned long *fpregs
= target
->thread
.float_regs
;
191 if (target
== current
)
192 save_and_clear_fpu();
194 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
196 0, 32 * sizeof(u32
));
198 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
202 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
207 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
208 34 * sizeof(u32
), -1);
212 static const struct user_regset sparc32_regsets
[] = {
218 * PSR, PC, nPC, Y, WIM, TBR
221 .core_note_type
= NT_PRSTATUS
,
223 .size
= sizeof(u32
), .align
= sizeof(u32
),
224 .regset_get
= genregs32_get
, .set
= genregs32_set
230 * FPU QUEUE COUNT (8-bit char)
231 * FPU QUEUE ENTRYSIZE (8-bit char)
232 * FPU ENABLED (8-bit char)
234 * FPU QUEUE (64 32-bit ints)
237 .core_note_type
= NT_PRFPREG
,
239 .size
= sizeof(u32
), .align
= sizeof(u32
),
240 .regset_get
= fpregs32_get
, .set
= fpregs32_set
244 static int getregs_get(struct task_struct
*target
,
245 const struct user_regset
*regset
,
248 const struct pt_regs
*regs
= target
->thread
.kregs
;
250 if (target
== current
)
251 flush_user_windows();
253 membuf_store(&to
, regs
->psr
);
254 membuf_store(&to
, regs
->pc
);
255 membuf_store(&to
, regs
->npc
);
256 membuf_store(&to
, regs
->y
);
257 return membuf_write(&to
, regs
->u_regs
+ 1, 15 * sizeof(u32
));
260 static int setregs_set(struct task_struct
*target
,
261 const struct user_regset
*regset
,
262 unsigned int pos
, unsigned int count
,
263 const void *kbuf
, const void __user
*ubuf
)
265 struct pt_regs
*regs
= target
->thread
.kregs
;
269 if (target
== current
)
270 flush_user_windows();
272 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
277 regs
->psr
= (regs
->psr
& ~(PSR_ICC
| PSR_SYSCALL
)) |
278 (v
[0] & (PSR_ICC
| PSR_SYSCALL
));
282 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
284 4 * sizeof(u32
) , 19 * sizeof(u32
));
287 static int getfpregs_get(struct task_struct
*target
,
288 const struct user_regset
*regset
,
292 if (target
== current
)
293 save_and_clear_fpu();
295 membuf_write(&to
, &target
->thread
.float_regs
, 32 * sizeof(u32
));
296 membuf_write(&to
, &target
->thread
.fsr
, sizeof(u32
));
297 return membuf_zero(&to
, 35 * sizeof(u32
));
300 static int setfpregs_set(struct task_struct
*target
,
301 const struct user_regset
*regset
,
302 unsigned int pos
, unsigned int count
,
303 const void *kbuf
, const void __user
*ubuf
)
305 unsigned long *fpregs
= target
->thread
.float_regs
;
309 if (target
== current
)
310 save_and_clear_fpu();
312 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
314 0, 32 * sizeof(u32
));
317 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
323 static const struct user_regset ptrace32_regsets
[] = {
325 .n
= 19, .size
= sizeof(u32
),
326 .regset_get
= getregs_get
, .set
= setregs_set
,
329 .n
= 68, .size
= sizeof(u32
),
330 .regset_get
= getfpregs_get
, .set
= setfpregs_set
,
334 static const struct user_regset_view ptrace32_view
= {
335 .regsets
= ptrace32_regsets
, .n
= ARRAY_SIZE(ptrace32_regsets
)
338 static const struct user_regset_view user_sparc32_view
= {
339 .name
= "sparc", .e_machine
= EM_SPARC
,
340 .regsets
= sparc32_regsets
, .n
= ARRAY_SIZE(sparc32_regsets
)
343 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
345 return &user_sparc32_view
;
349 unsigned long regs
[32];
355 unsigned long *insnaddr
;
360 long arch_ptrace(struct task_struct
*child
, long request
,
361 unsigned long addr
, unsigned long data
)
363 unsigned long addr2
= current
->thread
.kregs
->u_regs
[UREG_I4
];
365 struct pt_regs __user
*pregs
;
366 struct fps __user
*fps
;
369 addr2p
= (void __user
*) addr2
;
370 pregs
= (struct pt_regs __user
*) addr
;
371 fps
= (struct fps __user
*) addr
;
374 case PTRACE_GETREGS
: {
375 ret
= copy_regset_to_user(child
, &ptrace32_view
,
382 case PTRACE_SETREGS
: {
383 ret
= copy_regset_from_user(child
, &ptrace32_view
,
390 case PTRACE_GETFPREGS
: {
391 ret
= copy_regset_to_user(child
, &ptrace32_view
,
398 case PTRACE_SETFPREGS
: {
399 ret
= copy_regset_from_user(child
, &ptrace32_view
,
406 case PTRACE_READTEXT
:
407 case PTRACE_READDATA
:
408 ret
= ptrace_readdata(child
, addr
, addr2p
, data
);
416 case PTRACE_WRITETEXT
:
417 case PTRACE_WRITEDATA
:
418 ret
= ptrace_writedata(child
, addr2p
, addr
, data
);
427 if (request
== PTRACE_SPARC_DETACH
)
428 request
= PTRACE_DETACH
;
429 ret
= ptrace_request(child
, request
, addr
, data
);
436 asmlinkage
int syscall_trace(struct pt_regs
*regs
, int syscall_exit_p
)
440 if (test_thread_flag(TIF_SYSCALL_TRACE
)) {
442 ptrace_report_syscall_exit(regs
, 0);
444 ret
= ptrace_report_syscall_entry(regs
);