1 // SPDX-License-Identifier: GPL-2.0-only
3 * Ptrace support for Hexagon
5 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/sched/task_stack.h>
12 #include <linux/smp.h>
13 #include <linux/errno.h>
14 #include <linux/ptrace.h>
15 #include <linux/regset.h>
16 #include <linux/user.h>
17 #include <linux/elf.h>
21 #if arch_has_single_step()
22 /* Both called from ptrace_resume */
23 void user_enable_single_step(struct task_struct
*child
)
25 pt_set_singlestep(task_pt_regs(child
));
26 set_tsk_thread_flag(child
, TIF_SINGLESTEP
);
29 void user_disable_single_step(struct task_struct
*child
)
31 pt_clr_singlestep(task_pt_regs(child
));
32 clear_tsk_thread_flag(child
, TIF_SINGLESTEP
);
36 static int genregs_get(struct task_struct
*target
,
37 const struct user_regset
*regset
,
40 struct pt_regs
*regs
= task_pt_regs(target
);
42 /* The general idea here is that the copyout must happen in
43 * exactly the same order in which the userspace expects these
44 * regs. Now, the sequence in userspace does not match the
45 * sequence in the kernel, so everything past the 32 gprs
46 * happens one at a time.
48 membuf_write(&to
, ®s
->r00
, 32*sizeof(unsigned long));
49 /* Must be exactly same sequence as struct user_regs_struct */
50 membuf_store(&to
, regs
->sa0
);
51 membuf_store(&to
, regs
->lc0
);
52 membuf_store(&to
, regs
->sa1
);
53 membuf_store(&to
, regs
->lc1
);
54 membuf_store(&to
, regs
->m0
);
55 membuf_store(&to
, regs
->m1
);
56 membuf_store(&to
, regs
->usr
);
57 membuf_store(&to
, regs
->p3_0
);
58 membuf_store(&to
, regs
->gp
);
59 membuf_store(&to
, regs
->ugp
);
60 membuf_store(&to
, pt_elr(regs
)); // pc
61 membuf_store(&to
, (unsigned long)pt_cause(regs
)); // cause
62 membuf_store(&to
, pt_badva(regs
)); // badva
63 #if CONFIG_HEXAGON_ARCH_VERSION >=4
64 membuf_store(&to
, regs
->cs0
);
65 membuf_store(&to
, regs
->cs1
);
66 return membuf_zero(&to
, sizeof(unsigned long));
68 return membuf_zero(&to
, 3 * sizeof(unsigned long));
72 static int genregs_set(struct task_struct
*target
,
73 const struct user_regset
*regset
,
74 unsigned int pos
, unsigned int count
,
75 const void *kbuf
, const void __user
*ubuf
)
79 struct pt_regs
*regs
= task_pt_regs(target
);
84 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
85 ®s
->r00
, 0, 32*sizeof(unsigned long));
87 #define INEXT(KPT_REG, USR_REG) \
89 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
90 KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
91 offsetof(struct user_regs_struct, USR_REG) + \
92 sizeof(unsigned long));
94 /* Must be exactly same sequence as struct user_regs_struct */
95 INEXT(®s
->sa0
, sa0
);
96 INEXT(®s
->lc0
, lc0
);
97 INEXT(®s
->sa1
, sa1
);
98 INEXT(®s
->lc1
, lc1
);
100 INEXT(®s
->m1
, m1
);
101 INEXT(®s
->usr
, usr
);
102 INEXT(®s
->preds
, p3_0
);
103 INEXT(®s
->gp
, gp
);
104 INEXT(®s
->ugp
, ugp
);
105 INEXT(&pt_elr(regs
), pc
);
107 /* CAUSE and BADVA aren't writeable. */
108 INEXT(&bucket
, cause
);
109 INEXT(&bucket
, badva
);
111 #if CONFIG_HEXAGON_ARCH_VERSION >=4
112 INEXT(®s
->cs0
, cs0
);
113 INEXT(®s
->cs1
, cs1
);
116 /* Ignore the rest, if needed */
118 ret
= user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
119 offsetof(struct user_regs_struct
, pad1
), -1);
125 * This is special; SP is actually restored by the VM via the
126 * special event record which is set by the special trap.
128 regs
->hvmer
.vmpsp
= regs
->r29
;
132 enum hexagon_regset
{
136 static const struct user_regset hexagon_regsets
[] = {
138 .core_note_type
= NT_PRSTATUS
,
140 .size
= sizeof(unsigned long),
141 .align
= sizeof(unsigned long),
142 .regset_get
= genregs_get
,
147 static const struct user_regset_view hexagon_user_view
= {
149 .e_machine
= ELF_ARCH
,
150 .ei_osabi
= ELF_OSABI
,
151 .regsets
= hexagon_regsets
,
152 .e_flags
= ELF_CORE_EFLAGS
,
153 .n
= ARRAY_SIZE(hexagon_regsets
)
156 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
158 return &hexagon_user_view
;
161 void ptrace_disable(struct task_struct
*child
)
163 /* Boilerplate - resolves to null inline if no HW single-step */
164 user_disable_single_step(child
);
167 long arch_ptrace(struct task_struct
*child
, long request
,
168 unsigned long addr
, unsigned long data
)
170 return ptrace_request(child
, request
, addr
, data
);