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/ptrace.h>
22 #include <linux/elf.h>
23 #include <linux/regset.h>
24 #include <linux/sched.h>
25 #include <linux/sched/task_stack.h>
26 #include <linux/tracehook.h>
27 #include <trace/events/syscalls.h>
36 static int riscv_gpr_get(struct task_struct
*target
,
37 const struct user_regset
*regset
,
38 unsigned int pos
, unsigned int count
,
39 void *kbuf
, void __user
*ubuf
)
43 regs
= task_pt_regs(target
);
44 return user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, regs
, 0, -1);
47 static int riscv_gpr_set(struct task_struct
*target
,
48 const struct user_regset
*regset
,
49 unsigned int pos
, unsigned int count
,
50 const void *kbuf
, const void __user
*ubuf
)
55 regs
= task_pt_regs(target
);
56 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, regs
, 0, -1);
61 static int riscv_fpr_get(struct task_struct
*target
,
62 const struct user_regset
*regset
,
63 unsigned int pos
, unsigned int count
,
64 void *kbuf
, void __user
*ubuf
)
67 struct __riscv_d_ext_state
*fstate
= &target
->thread
.fstate
;
69 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
70 offsetof(struct __riscv_d_ext_state
, fcsr
));
72 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
73 offsetof(struct __riscv_d_ext_state
, fcsr
) +
74 sizeof(fstate
->fcsr
));
80 static int riscv_fpr_set(struct task_struct
*target
,
81 const struct user_regset
*regset
,
82 unsigned int pos
, unsigned int count
,
83 const void *kbuf
, const void __user
*ubuf
)
86 struct __riscv_d_ext_state
*fstate
= &target
->thread
.fstate
;
88 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
89 offsetof(struct __riscv_d_ext_state
, fcsr
));
91 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, fstate
, 0,
92 offsetof(struct __riscv_d_ext_state
, fcsr
) +
93 sizeof(fstate
->fcsr
));
100 static const struct user_regset riscv_user_regset
[] = {
102 .core_note_type
= NT_PRSTATUS
,
104 .size
= sizeof(elf_greg_t
),
105 .align
= sizeof(elf_greg_t
),
106 .get
= &riscv_gpr_get
,
107 .set
= &riscv_gpr_set
,
111 .core_note_type
= NT_PRFPREG
,
113 .size
= sizeof(elf_fpreg_t
),
114 .align
= sizeof(elf_fpreg_t
),
115 .get
= &riscv_fpr_get
,
116 .set
= &riscv_fpr_set
,
121 static const struct user_regset_view riscv_user_native_view
= {
123 .e_machine
= EM_RISCV
,
124 .regsets
= riscv_user_regset
,
125 .n
= ARRAY_SIZE(riscv_user_regset
),
128 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
130 return &riscv_user_native_view
;
133 void ptrace_disable(struct task_struct
*child
)
135 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
138 long arch_ptrace(struct task_struct
*child
, long request
,
139 unsigned long addr
, unsigned long data
)
145 ret
= ptrace_request(child
, request
, addr
, data
);
153 * Allows PTRACE_SYSCALL to work. These are called from entry.S in
154 * {handle,ret_from}_syscall.
156 void do_syscall_trace_enter(struct pt_regs
*regs
)
158 if (test_thread_flag(TIF_SYSCALL_TRACE
))
159 if (tracehook_report_syscall_entry(regs
))
160 syscall_set_nr(current
, regs
, -1);
162 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
163 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT
))
164 trace_sys_enter(regs
, syscall_get_nr(current
, regs
));
168 void do_syscall_trace_exit(struct pt_regs
*regs
)
170 if (test_thread_flag(TIF_SYSCALL_TRACE
))
171 tracehook_report_syscall_exit(regs
, 0);
173 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
174 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT
))
175 trace_sys_exit(regs
, regs
->regs
[0]);