hugetlb: introduce generic version of hugetlb_free_pgd_range
[linux/fpc-iii.git] / arch / riscv / kernel / ptrace.c
blob60f1e02eed360780c93f25b70a2a4d484f983d9b
1 /*
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>
29 enum riscv_regset {
30 REGSET_X,
31 #ifdef CONFIG_FPU
32 REGSET_F,
33 #endif
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)
41 struct pt_regs *regs;
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)
52 int ret;
53 struct pt_regs *regs;
55 regs = task_pt_regs(target);
56 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
57 return ret;
60 #ifdef CONFIG_FPU
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)
66 int ret;
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));
71 if (!ret) {
72 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0,
73 offsetof(struct __riscv_d_ext_state, fcsr) +
74 sizeof(fstate->fcsr));
77 return ret;
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)
85 int ret;
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));
90 if (!ret) {
91 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
92 offsetof(struct __riscv_d_ext_state, fcsr) +
93 sizeof(fstate->fcsr));
96 return ret;
98 #endif
100 static const struct user_regset riscv_user_regset[] = {
101 [REGSET_X] = {
102 .core_note_type = NT_PRSTATUS,
103 .n = ELF_NGREG,
104 .size = sizeof(elf_greg_t),
105 .align = sizeof(elf_greg_t),
106 .get = &riscv_gpr_get,
107 .set = &riscv_gpr_set,
109 #ifdef CONFIG_FPU
110 [REGSET_F] = {
111 .core_note_type = NT_PRFPREG,
112 .n = ELF_NFPREG,
113 .size = sizeof(elf_fpreg_t),
114 .align = sizeof(elf_fpreg_t),
115 .get = &riscv_fpr_get,
116 .set = &riscv_fpr_set,
118 #endif
121 static const struct user_regset_view riscv_user_native_view = {
122 .name = "riscv",
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)
141 long ret = -EIO;
143 switch (request) {
144 default:
145 ret = ptrace_request(child, request, addr, data);
146 break;
149 return ret;
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));
165 #endif
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]);
176 #endif