2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3 * Copyright 2015 Regents of the University of California
4 * Copyright 2017 SiFive
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * Copied from arch/tile/kernel/ptrace.c
18 #include <asm/ptrace.h>
19 #include <asm/syscall.h>
20 #include <asm/thread_info.h>
21 #include <linux/audit.h>
22 #include <linux/ptrace.h>
23 #include <linux/elf.h>
24 #include <linux/regset.h>
25 #include <linux/sched.h>
26 #include <linux/sched/task_stack.h>
27 #include <linux/tracehook.h>
29 #define CREATE_TRACE_POINTS
30 #include <trace/events/syscalls.h>
39 static int riscv_gpr_get(struct task_struct
*target
,
40 const struct user_regset
*regset
,
41 unsigned int pos
, unsigned int count
,
42 void *kbuf
, void __user
*ubuf
)
46 regs
= task_pt_regs(target
);
47 return user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, regs
, 0, -1);
50 static int riscv_gpr_set(struct task_struct
*target
,
51 const struct user_regset
*regset
,
52 unsigned int pos
, unsigned int count
,
53 const void *kbuf
, const void __user
*ubuf
)
58 regs
= task_pt_regs(target
);
59 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, regs
, 0, -1);
64 static int riscv_fpr_get(struct task_struct
*target
,
65 const struct user_regset
*regset
,
66 unsigned int pos
, unsigned int count
,
67 void *kbuf
, void __user
*ubuf
)
70 struct __riscv_d_ext_state
*fstate
= &target
->thread
.fstate
;
72 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
73 offsetof(struct __riscv_d_ext_state
, fcsr
));
75 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
76 offsetof(struct __riscv_d_ext_state
, fcsr
) +
77 sizeof(fstate
->fcsr
));
83 static int riscv_fpr_set(struct task_struct
*target
,
84 const struct user_regset
*regset
,
85 unsigned int pos
, unsigned int count
,
86 const void *kbuf
, const void __user
*ubuf
)
89 struct __riscv_d_ext_state
*fstate
= &target
->thread
.fstate
;
91 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
92 offsetof(struct __riscv_d_ext_state
, fcsr
));
94 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
95 offsetof(struct __riscv_d_ext_state
, fcsr
) +
96 sizeof(fstate
->fcsr
));
103 static const struct user_regset riscv_user_regset
[] = {
105 .core_note_type
= NT_PRSTATUS
,
107 .size
= sizeof(elf_greg_t
),
108 .align
= sizeof(elf_greg_t
),
109 .get
= &riscv_gpr_get
,
110 .set
= &riscv_gpr_set
,
114 .core_note_type
= NT_PRFPREG
,
116 .size
= sizeof(elf_fpreg_t
),
117 .align
= sizeof(elf_fpreg_t
),
118 .get
= &riscv_fpr_get
,
119 .set
= &riscv_fpr_set
,
124 static const struct user_regset_view riscv_user_native_view
= {
126 .e_machine
= EM_RISCV
,
127 .regsets
= riscv_user_regset
,
128 .n
= ARRAY_SIZE(riscv_user_regset
),
131 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
133 return &riscv_user_native_view
;
136 void ptrace_disable(struct task_struct
*child
)
138 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
141 long arch_ptrace(struct task_struct
*child
, long request
,
142 unsigned long addr
, unsigned long data
)
148 ret
= ptrace_request(child
, request
, addr
, data
);
156 * Allows PTRACE_SYSCALL to work. These are called from entry.S in
157 * {handle,ret_from}_syscall.
159 void do_syscall_trace_enter(struct pt_regs
*regs
)
161 if (test_thread_flag(TIF_SYSCALL_TRACE
))
162 if (tracehook_report_syscall_entry(regs
))
163 syscall_set_nr(current
, regs
, -1);
165 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
166 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT
))
167 trace_sys_enter(regs
, syscall_get_nr(current
, regs
));
170 audit_syscall_entry(regs
->a7
, regs
->a0
, regs
->a1
, regs
->a2
, regs
->a3
);
173 void do_syscall_trace_exit(struct pt_regs
*regs
)
175 audit_syscall_exit(regs
);
177 if (test_thread_flag(TIF_SYSCALL_TRACE
))
178 tracehook_report_syscall_exit(regs
, 0);
180 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
181 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT
))
182 trace_sys_exit(regs
, regs_return_value(regs
));