2 * Copyright (C) 2005-2012 Imagination Technologies Ltd.
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file COPYING in the main directory of
6 * this archive for more details.
9 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/ptrace.h>
13 #include <linux/user.h>
14 #include <linux/regset.h>
15 #include <linux/tracehook.h>
16 #include <linux/elf.h>
17 #include <linux/uaccess.h>
18 #include <trace/syscall.h>
20 #define CREATE_TRACE_POINTS
21 #include <trace/events/syscalls.h>
24 * user_regset definitions.
27 int metag_gp_regs_copyout(const struct pt_regs
*regs
,
28 unsigned int pos
, unsigned int count
,
29 void *kbuf
, void __user
*ubuf
)
36 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
37 regs
->ctx
.DX
, 0, 4*16);
41 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
42 regs
->ctx
.AX
, 4*16, 4*20);
46 if (regs
->ctx
.SaveMask
& TBICTX_XEXT_BIT
)
47 ptr
= regs
->ctx
.Ext
.Ctx
.pExt
;
49 ptr
= ®s
->ctx
.Ext
.AX2
;
50 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
55 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
56 ®s
->ctx
.AX3
, 4*22, 4*24);
60 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
61 ®s
->ctx
.CurrPC
, 4*24, 4*25);
65 data
= (unsigned long)regs
->ctx
.Flags
;
66 if (regs
->ctx
.SaveMask
& TBICTX_CBUF_BIT
)
67 data
|= USER_GP_REGS_STATUS_CATCH_BIT
;
68 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
72 /* TXRPT, TXBPOBITS, TXMODE */
73 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
74 ®s
->ctx
.CurrRPT
, 4*26, 4*29);
78 ret
= user_regset_copyout_zero(&pos
, &count
, &kbuf
, &ubuf
,
84 int metag_gp_regs_copyin(struct pt_regs
*regs
,
85 unsigned int pos
, unsigned int count
,
86 const void *kbuf
, const void __user
*ubuf
)
93 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
94 regs
->ctx
.DX
, 0, 4*16);
98 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
99 regs
->ctx
.AX
, 4*16, 4*20);
103 if (regs
->ctx
.SaveMask
& TBICTX_XEXT_BIT
)
104 ptr
= regs
->ctx
.Ext
.Ctx
.pExt
;
106 ptr
= ®s
->ctx
.Ext
.AX2
;
107 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
112 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
113 ®s
->ctx
.AX3
, 4*22, 4*24);
117 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
118 ®s
->ctx
.CurrPC
, 4*24, 4*25);
122 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
126 regs
->ctx
.Flags
= data
& 0xffff;
127 if (data
& USER_GP_REGS_STATUS_CATCH_BIT
)
128 regs
->ctx
.SaveMask
|= TBICTX_XCBF_BIT
| TBICTX_CBUF_BIT
;
130 regs
->ctx
.SaveMask
&= ~TBICTX_CBUF_BIT
;
131 /* TXRPT, TXBPOBITS, TXMODE */
132 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
133 ®s
->ctx
.CurrRPT
, 4*26, 4*29);
138 static int metag_gp_regs_get(struct task_struct
*target
,
139 const struct user_regset
*regset
,
140 unsigned int pos
, unsigned int count
,
141 void *kbuf
, void __user
*ubuf
)
143 const struct pt_regs
*regs
= task_pt_regs(target
);
144 return metag_gp_regs_copyout(regs
, pos
, count
, kbuf
, ubuf
);
147 static int metag_gp_regs_set(struct task_struct
*target
,
148 const struct user_regset
*regset
,
149 unsigned int pos
, unsigned int count
,
150 const void *kbuf
, const void __user
*ubuf
)
152 struct pt_regs
*regs
= task_pt_regs(target
);
153 return metag_gp_regs_copyin(regs
, pos
, count
, kbuf
, ubuf
);
156 int metag_cb_regs_copyout(const struct pt_regs
*regs
,
157 unsigned int pos
, unsigned int count
,
158 void *kbuf
, void __user
*ubuf
)
163 if (regs
->ctx
.SaveMask
& TBICTX_XCBF_BIT
)
164 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
165 regs
->extcb0
, 0, 4*4);
167 ret
= user_regset_copyout_zero(&pos
, &count
, &kbuf
, &ubuf
,
172 int metag_cb_regs_copyin(struct pt_regs
*regs
,
173 unsigned int pos
, unsigned int count
,
174 const void *kbuf
, const void __user
*ubuf
)
179 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
180 regs
->extcb0
, 0, 4*4);
184 static int metag_cb_regs_get(struct task_struct
*target
,
185 const struct user_regset
*regset
,
186 unsigned int pos
, unsigned int count
,
187 void *kbuf
, void __user
*ubuf
)
189 const struct pt_regs
*regs
= task_pt_regs(target
);
190 return metag_cb_regs_copyout(regs
, pos
, count
, kbuf
, ubuf
);
193 static int metag_cb_regs_set(struct task_struct
*target
,
194 const struct user_regset
*regset
,
195 unsigned int pos
, unsigned int count
,
196 const void *kbuf
, const void __user
*ubuf
)
198 struct pt_regs
*regs
= task_pt_regs(target
);
199 return metag_cb_regs_copyin(regs
, pos
, count
, kbuf
, ubuf
);
202 int metag_rp_state_copyout(const struct pt_regs
*regs
,
203 unsigned int pos
, unsigned int count
,
204 void *kbuf
, void __user
*ubuf
)
210 /* Empty read pipeline */
211 if (!(regs
->ctx
.SaveMask
& TBICTX_CBRP_BIT
)) {
212 ret
= user_regset_copyout_zero(&pos
, &count
, &kbuf
, &ubuf
,
217 mask
= (regs
->ctx
.CurrDIVTIME
& TXDIVTIME_RPMASK_BITS
) >>
220 /* Read pipeline entries */
221 ptr
= (void *)®s
->extcb0
[1];
222 for (i
= 0; i
< 6; ++i
, ++ptr
) {
224 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
225 ptr
, 8*i
, 8*(i
+ 1));
227 ret
= user_regset_copyout_zero(&pos
, &count
, &kbuf
,
228 &ubuf
, 8*i
, 8*(i
+ 1));
232 /* Mask of entries */
233 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
239 int metag_rp_state_copyin(struct pt_regs
*regs
,
240 unsigned int pos
, unsigned int count
,
241 const void *kbuf
, const void __user
*ubuf
)
243 struct user_rp_state rp
;
244 unsigned long long *ptr
;
247 /* Read the entire pipeline before making any changes */
248 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
253 /* Write pipeline entries */
254 ptr
= (void *)®s
->extcb0
[1];
255 for (i
= 0; i
< 6; ++i
, ++ptr
)
256 if (rp
.mask
& (1 << i
))
257 *ptr
= rp
.entries
[i
];
259 /* Update RPMask in TXDIVTIME */
260 regs
->ctx
.CurrDIVTIME
&= ~TXDIVTIME_RPMASK_BITS
;
261 regs
->ctx
.CurrDIVTIME
|= (rp
.mask
<< TXDIVTIME_RPMASK_S
)
262 & TXDIVTIME_RPMASK_BITS
;
264 /* Set/clear flags to indicate catch/read pipeline state */
266 regs
->ctx
.SaveMask
|= TBICTX_XCBF_BIT
| TBICTX_CBRP_BIT
;
268 regs
->ctx
.SaveMask
&= ~TBICTX_CBRP_BIT
;
273 static int metag_rp_state_get(struct task_struct
*target
,
274 const struct user_regset
*regset
,
275 unsigned int pos
, unsigned int count
,
276 void *kbuf
, void __user
*ubuf
)
278 const struct pt_regs
*regs
= task_pt_regs(target
);
279 return metag_rp_state_copyout(regs
, pos
, count
, kbuf
, ubuf
);
282 static int metag_rp_state_set(struct task_struct
*target
,
283 const struct user_regset
*regset
,
284 unsigned int pos
, unsigned int count
,
285 const void *kbuf
, const void __user
*ubuf
)
287 struct pt_regs
*regs
= task_pt_regs(target
);
288 return metag_rp_state_copyin(regs
, pos
, count
, kbuf
, ubuf
);
291 static int metag_tls_get(struct task_struct
*target
,
292 const struct user_regset
*regset
,
293 unsigned int pos
, unsigned int count
,
294 void *kbuf
, void __user
*ubuf
)
296 void __user
*tls
= target
->thread
.tls_ptr
;
297 return user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, &tls
, 0, -1);
300 static int metag_tls_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
)
308 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, &tls
, 0, -1);
312 target
->thread
.tls_ptr
= tls
;
323 static const struct user_regset metag_regsets
[] = {
325 .core_note_type
= NT_PRSTATUS
,
327 .size
= sizeof(long),
328 .align
= sizeof(long long),
329 .get
= metag_gp_regs_get
,
330 .set
= metag_gp_regs_set
,
333 .core_note_type
= NT_METAG_CBUF
,
334 .n
= sizeof(struct user_cb_regs
) / sizeof(long),
335 .size
= sizeof(long),
336 .align
= sizeof(long long),
337 .get
= metag_cb_regs_get
,
338 .set
= metag_cb_regs_set
,
340 [REGSET_READPIPE
] = {
341 .core_note_type
= NT_METAG_RPIPE
,
342 .n
= sizeof(struct user_rp_state
) / sizeof(long),
343 .size
= sizeof(long),
344 .align
= sizeof(long long),
345 .get
= metag_rp_state_get
,
346 .set
= metag_rp_state_set
,
349 .core_note_type
= NT_METAG_TLS
,
351 .size
= sizeof(void *),
352 .align
= sizeof(void *),
353 .get
= metag_tls_get
,
354 .set
= metag_tls_set
,
358 static const struct user_regset_view user_metag_view
= {
360 .e_machine
= EM_METAG
,
361 .regsets
= metag_regsets
,
362 .n
= ARRAY_SIZE(metag_regsets
)
365 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
367 return &user_metag_view
;
371 * Called by kernel/ptrace.c when detaching..
373 * Make sure single step bits etc are not set.
375 void ptrace_disable(struct task_struct
*child
)
377 /* nothing to do.. */
380 long arch_ptrace(struct task_struct
*child
, long request
, unsigned long addr
,
387 ret
= ptrace_request(child
, request
, addr
, data
);
394 int syscall_trace_enter(struct pt_regs
*regs
)
398 if (test_thread_flag(TIF_SYSCALL_TRACE
))
399 ret
= tracehook_report_syscall_entry(regs
);
401 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT
)))
402 trace_sys_enter(regs
, regs
->ctx
.DX
[0].U1
);
404 return ret
? -1 : regs
->ctx
.DX
[0].U1
;
407 void syscall_trace_leave(struct pt_regs
*regs
)
409 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT
)))
410 trace_sys_exit(regs
, regs
->ctx
.DX
[0].U1
);
412 if (test_thread_flag(TIF_SYSCALL_TRACE
))
413 tracehook_report_syscall_exit(regs
, 0);