1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c08098f2SVineet Gupta /*
3c08098f2SVineet Gupta * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4c08098f2SVineet Gupta */
5c08098f2SVineet Gupta
6c08098f2SVineet Gupta #include <linux/ptrace.h>
768db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
8547f1125SVineet Gupta #include <linux/regset.h>
9547f1125SVineet Gupta #include <linux/unistd.h>
10547f1125SVineet Gupta #include <linux/elf.h>
11547f1125SVineet Gupta
12fb0b5490SSergey Matyukevich #define CREATE_TRACE_POINTS
13fb0b5490SSergey Matyukevich #include <trace/events/syscalls.h>
14fb0b5490SSergey Matyukevich
15b3bbf6a7SSergey Matyukevich struct pt_regs_offset {
16b3bbf6a7SSergey Matyukevich const char *name;
17b3bbf6a7SSergey Matyukevich int offset;
18b3bbf6a7SSergey Matyukevich };
19b3bbf6a7SSergey Matyukevich
20b3bbf6a7SSergey Matyukevich #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
21b3bbf6a7SSergey Matyukevich #define REG_OFFSET_END {.name = NULL, .offset = 0}
22b3bbf6a7SSergey Matyukevich
23b3bbf6a7SSergey Matyukevich #ifdef CONFIG_ISA_ARCOMPACT
24b3bbf6a7SSergey Matyukevich static const struct pt_regs_offset regoffset_table[] = {
25b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(bta),
26b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(lp_start),
27b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(lp_end),
28b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(lp_count),
29b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(status32),
30b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(ret),
31b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(blink),
32b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(fp),
33b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r26),
34b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r12),
35b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r11),
36b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r10),
37b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r9),
38b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r8),
39b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r7),
40b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r6),
41b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r5),
42b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r4),
43b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r3),
44b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r2),
45b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r1),
46b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r0),
47b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(sp),
48b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(orig_r0),
49*58d9ceb7SVineet Gupta REG_OFFSET_NAME(ecr),
50b3bbf6a7SSergey Matyukevich REG_OFFSET_END,
51b3bbf6a7SSergey Matyukevich };
52b3bbf6a7SSergey Matyukevich
53b3bbf6a7SSergey Matyukevich #else
54b3bbf6a7SSergey Matyukevich
55b3bbf6a7SSergey Matyukevich static const struct pt_regs_offset regoffset_table[] = {
56b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(orig_r0),
57*58d9ceb7SVineet Gupta REG_OFFSET_NAME(ecr),
58b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(bta),
59b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r26),
60b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(fp),
61b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(sp),
62b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r12),
63b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r30),
64b3bbf6a7SSergey Matyukevich #ifdef CONFIG_ARC_HAS_ACCL_REGS
65b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r58),
66b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r59),
67b3bbf6a7SSergey Matyukevich #endif
68b3bbf6a7SSergey Matyukevich #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
69b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(DSP_CTRL),
70b3bbf6a7SSergey Matyukevich #endif
71b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r0),
72b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r1),
73b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r2),
74b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r3),
75b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r4),
76b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r5),
77b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r6),
78b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r7),
79b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r8),
80b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r9),
81b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r10),
82b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(r11),
83b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(blink),
84b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(lp_end),
85b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(lp_start),
86b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(lp_count),
87b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(ei),
88b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(ldi),
89b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(jli),
90b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(ret),
91b3bbf6a7SSergey Matyukevich REG_OFFSET_NAME(status32),
92b3bbf6a7SSergey Matyukevich REG_OFFSET_END,
93b3bbf6a7SSergey Matyukevich };
94b3bbf6a7SSergey Matyukevich #endif
95b3bbf6a7SSergey Matyukevich
task_callee_regs(struct task_struct * tsk)96547f1125SVineet Gupta static struct callee_regs *task_callee_regs(struct task_struct *tsk)
97547f1125SVineet Gupta {
98547f1125SVineet Gupta struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg;
99547f1125SVineet Gupta return tmp;
100547f1125SVineet Gupta }
101547f1125SVineet Gupta
genregs_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)102547f1125SVineet Gupta static int genregs_get(struct task_struct *target,
103547f1125SVineet Gupta const struct user_regset *regset,
1045a806e0aSAl Viro struct membuf to)
105547f1125SVineet Gupta {
106547f1125SVineet Gupta const struct pt_regs *ptregs = task_pt_regs(target);
107547f1125SVineet Gupta const struct callee_regs *cregs = task_callee_regs(target);
108547f1125SVineet Gupta unsigned int stop_pc_val;
109547f1125SVineet Gupta
1105a806e0aSAl Viro membuf_zero(&to, 4); // pad
1115a806e0aSAl Viro membuf_store(&to, ptregs->bta);
1125a806e0aSAl Viro membuf_store(&to, ptregs->lp_start);
1135a806e0aSAl Viro membuf_store(&to, ptregs->lp_end);
1145a806e0aSAl Viro membuf_store(&to, ptregs->lp_count);
1155a806e0aSAl Viro membuf_store(&to, ptregs->status32);
1165a806e0aSAl Viro membuf_store(&to, ptregs->ret);
1175a806e0aSAl Viro membuf_store(&to, ptregs->blink);
1185a806e0aSAl Viro membuf_store(&to, ptregs->fp);
1195a806e0aSAl Viro membuf_store(&to, ptregs->r26); // gp
1205a806e0aSAl Viro membuf_store(&to, ptregs->r12);
1215a806e0aSAl Viro membuf_store(&to, ptregs->r11);
1225a806e0aSAl Viro membuf_store(&to, ptregs->r10);
1235a806e0aSAl Viro membuf_store(&to, ptregs->r9);
1245a806e0aSAl Viro membuf_store(&to, ptregs->r8);
1255a806e0aSAl Viro membuf_store(&to, ptregs->r7);
1265a806e0aSAl Viro membuf_store(&to, ptregs->r6);
1275a806e0aSAl Viro membuf_store(&to, ptregs->r5);
1285a806e0aSAl Viro membuf_store(&to, ptregs->r4);
1295a806e0aSAl Viro membuf_store(&to, ptregs->r3);
1305a806e0aSAl Viro membuf_store(&to, ptregs->r2);
1315a806e0aSAl Viro membuf_store(&to, ptregs->r1);
1325a806e0aSAl Viro membuf_store(&to, ptregs->r0);
1335a806e0aSAl Viro membuf_store(&to, ptregs->sp);
1345a806e0aSAl Viro membuf_zero(&to, 4); // pad2
1355a806e0aSAl Viro membuf_store(&to, cregs->r25);
1365a806e0aSAl Viro membuf_store(&to, cregs->r24);
1375a806e0aSAl Viro membuf_store(&to, cregs->r23);
1385a806e0aSAl Viro membuf_store(&to, cregs->r22);
1395a806e0aSAl Viro membuf_store(&to, cregs->r21);
1405a806e0aSAl Viro membuf_store(&to, cregs->r20);
1415a806e0aSAl Viro membuf_store(&to, cregs->r19);
1425a806e0aSAl Viro membuf_store(&to, cregs->r18);
1435a806e0aSAl Viro membuf_store(&to, cregs->r17);
1445a806e0aSAl Viro membuf_store(&to, cregs->r16);
1455a806e0aSAl Viro membuf_store(&to, cregs->r15);
1465a806e0aSAl Viro membuf_store(&to, cregs->r14);
1475a806e0aSAl Viro membuf_store(&to, cregs->r13);
1485a806e0aSAl Viro membuf_store(&to, target->thread.fault_address); // efa
149547f1125SVineet Gupta
150547f1125SVineet Gupta if (in_brkpt_trap(ptregs)) {
151547f1125SVineet Gupta stop_pc_val = target->thread.fault_address;
152547f1125SVineet Gupta pr_debug("\t\tstop_pc (brk-pt)\n");
153547f1125SVineet Gupta } else {
154547f1125SVineet Gupta stop_pc_val = ptregs->ret;
155547f1125SVineet Gupta pr_debug("\t\tstop_pc (others)\n");
156547f1125SVineet Gupta }
157547f1125SVineet Gupta
1585a806e0aSAl Viro return membuf_store(&to, stop_pc_val); // stop_pc
159547f1125SVineet Gupta }
160547f1125SVineet Gupta
genregs_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)161547f1125SVineet Gupta static int genregs_set(struct task_struct *target,
162547f1125SVineet Gupta const struct user_regset *regset,
163547f1125SVineet Gupta unsigned int pos, unsigned int count,
164547f1125SVineet Gupta const void *kbuf, const void __user *ubuf)
165547f1125SVineet Gupta {
166547f1125SVineet Gupta const struct pt_regs *ptregs = task_pt_regs(target);
167547f1125SVineet Gupta const struct callee_regs *cregs = task_callee_regs(target);
168547f1125SVineet Gupta int ret = 0;
169547f1125SVineet Gupta
170547f1125SVineet Gupta #define REG_IN_CHUNK(FIRST, NEXT, PTR) \
171547f1125SVineet Gupta if (!ret) \
172547f1125SVineet Gupta ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
173547f1125SVineet Gupta (void *)(PTR), \
174547f1125SVineet Gupta offsetof(struct user_regs_struct, FIRST), \
175547f1125SVineet Gupta offsetof(struct user_regs_struct, NEXT));
176547f1125SVineet Gupta
177547f1125SVineet Gupta #define REG_IN_ONE(LOC, PTR) \
178547f1125SVineet Gupta if (!ret) \
179547f1125SVineet Gupta ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
180547f1125SVineet Gupta (void *)(PTR), \
181547f1125SVineet Gupta offsetof(struct user_regs_struct, LOC), \
182547f1125SVineet Gupta offsetof(struct user_regs_struct, LOC) + 4);
183547f1125SVineet Gupta
184547f1125SVineet Gupta #define REG_IGNORE_ONE(LOC) \
185547f1125SVineet Gupta if (!ret) \
186461cc6e5SSergey Shtylyov user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
187547f1125SVineet Gupta offsetof(struct user_regs_struct, LOC), \
188547f1125SVineet Gupta offsetof(struct user_regs_struct, LOC) + 4);
189547f1125SVineet Gupta
1902fa91904SVineet Gupta REG_IGNORE_ONE(pad);
1916ffb9c8cSVineet Gupta
1926ffb9c8cSVineet Gupta REG_IN_ONE(scratch.bta, &ptregs->bta);
1936ffb9c8cSVineet Gupta REG_IN_ONE(scratch.lp_start, &ptregs->lp_start);
1946ffb9c8cSVineet Gupta REG_IN_ONE(scratch.lp_end, &ptregs->lp_end);
1956ffb9c8cSVineet Gupta REG_IN_ONE(scratch.lp_count, &ptregs->lp_count);
1966ffb9c8cSVineet Gupta
1976ffb9c8cSVineet Gupta REG_IGNORE_ONE(scratch.status32);
1986ffb9c8cSVineet Gupta
1996ffb9c8cSVineet Gupta REG_IN_ONE(scratch.ret, &ptregs->ret);
2006ffb9c8cSVineet Gupta REG_IN_ONE(scratch.blink, &ptregs->blink);
2016ffb9c8cSVineet Gupta REG_IN_ONE(scratch.fp, &ptregs->fp);
2026ffb9c8cSVineet Gupta REG_IN_ONE(scratch.gp, &ptregs->r26);
2036ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r12, &ptregs->r12);
2046ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r11, &ptregs->r11);
2056ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r10, &ptregs->r10);
2066ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r9, &ptregs->r9);
2076ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r8, &ptregs->r8);
2086ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r7, &ptregs->r7);
2096ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r6, &ptregs->r6);
2106ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r5, &ptregs->r5);
2116ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r4, &ptregs->r4);
2126ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r3, &ptregs->r3);
2136ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r2, &ptregs->r2);
2146ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r1, &ptregs->r1);
2156ffb9c8cSVineet Gupta REG_IN_ONE(scratch.r0, &ptregs->r0);
2166ffb9c8cSVineet Gupta REG_IN_ONE(scratch.sp, &ptregs->sp);
2176ffb9c8cSVineet Gupta
21816f9afe6SVineet Gupta REG_IGNORE_ONE(pad2);
2196ffb9c8cSVineet Gupta
2206ffb9c8cSVineet Gupta REG_IN_ONE(callee.r25, &cregs->r25);
2216ffb9c8cSVineet Gupta REG_IN_ONE(callee.r24, &cregs->r24);
2226ffb9c8cSVineet Gupta REG_IN_ONE(callee.r23, &cregs->r23);
2236ffb9c8cSVineet Gupta REG_IN_ONE(callee.r22, &cregs->r22);
2246ffb9c8cSVineet Gupta REG_IN_ONE(callee.r21, &cregs->r21);
2256ffb9c8cSVineet Gupta REG_IN_ONE(callee.r20, &cregs->r20);
2266ffb9c8cSVineet Gupta REG_IN_ONE(callee.r19, &cregs->r19);
2276ffb9c8cSVineet Gupta REG_IN_ONE(callee.r18, &cregs->r18);
2286ffb9c8cSVineet Gupta REG_IN_ONE(callee.r17, &cregs->r17);
2296ffb9c8cSVineet Gupta REG_IN_ONE(callee.r16, &cregs->r16);
2306ffb9c8cSVineet Gupta REG_IN_ONE(callee.r15, &cregs->r15);
2316ffb9c8cSVineet Gupta REG_IN_ONE(callee.r14, &cregs->r14);
2326ffb9c8cSVineet Gupta REG_IN_ONE(callee.r13, &cregs->r13);
2336ffb9c8cSVineet Gupta
234547f1125SVineet Gupta REG_IGNORE_ONE(efa); /* efa update invalid */
2355b242828SVineet Gupta REG_IGNORE_ONE(stop_pc); /* PC updated via @ret */
236547f1125SVineet Gupta
237547f1125SVineet Gupta return ret;
238547f1125SVineet Gupta }
239547f1125SVineet Gupta
24065c02a55SVineet Gupta #ifdef CONFIG_ISA_ARCV2
arcv2regs_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)24165c02a55SVineet Gupta static int arcv2regs_get(struct task_struct *target,
24265c02a55SVineet Gupta const struct user_regset *regset,
2435a806e0aSAl Viro struct membuf to)
24465c02a55SVineet Gupta {
24565c02a55SVineet Gupta const struct pt_regs *regs = task_pt_regs(target);
24665c02a55SVineet Gupta
24765c02a55SVineet Gupta if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
24865c02a55SVineet Gupta /*
24965c02a55SVineet Gupta * itemized copy not needed like above as layout of regs (r30,r58,r59)
25065c02a55SVineet Gupta * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
25165c02a55SVineet Gupta */
2525a806e0aSAl Viro return membuf_write(&to, ®s->r30, sizeof(struct user_regs_arcv2));
25365c02a55SVineet Gupta
2545a806e0aSAl Viro
2555a806e0aSAl Viro membuf_write(&to, ®s->r30, 4); /* r30 only */
2565a806e0aSAl Viro return membuf_zero(&to, sizeof(struct user_regs_arcv2) - 4);
25765c02a55SVineet Gupta }
25865c02a55SVineet Gupta
arcv2regs_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)25965c02a55SVineet Gupta static int arcv2regs_set(struct task_struct *target,
26065c02a55SVineet Gupta const struct user_regset *regset,
26165c02a55SVineet Gupta unsigned int pos, unsigned int count,
26265c02a55SVineet Gupta const void *kbuf, const void __user *ubuf)
26365c02a55SVineet Gupta {
26465c02a55SVineet Gupta const struct pt_regs *regs = task_pt_regs(target);
26565c02a55SVineet Gupta int ret, copy_sz;
26665c02a55SVineet Gupta
26765c02a55SVineet Gupta if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
26865c02a55SVineet Gupta copy_sz = sizeof(struct user_regs_arcv2);
26965c02a55SVineet Gupta else
27065c02a55SVineet Gupta copy_sz = 4; /* r30 only */
27165c02a55SVineet Gupta
27265c02a55SVineet Gupta ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)®s->r30,
27365c02a55SVineet Gupta 0, copy_sz);
27465c02a55SVineet Gupta
27565c02a55SVineet Gupta return ret;
27665c02a55SVineet Gupta }
27765c02a55SVineet Gupta
27865c02a55SVineet Gupta #endif
27965c02a55SVineet Gupta
280547f1125SVineet Gupta enum arc_getset {
28165c02a55SVineet Gupta REGSET_CMN,
28265c02a55SVineet Gupta REGSET_ARCV2,
283547f1125SVineet Gupta };
284547f1125SVineet Gupta
285547f1125SVineet Gupta static const struct user_regset arc_regsets[] = {
28665c02a55SVineet Gupta [REGSET_CMN] = {
287547f1125SVineet Gupta .core_note_type = NT_PRSTATUS,
288547f1125SVineet Gupta .n = ELF_NGREG,
289547f1125SVineet Gupta .size = sizeof(unsigned long),
290547f1125SVineet Gupta .align = sizeof(unsigned long),
2915a806e0aSAl Viro .regset_get = genregs_get,
292547f1125SVineet Gupta .set = genregs_set,
29365c02a55SVineet Gupta },
29465c02a55SVineet Gupta #ifdef CONFIG_ISA_ARCV2
29565c02a55SVineet Gupta [REGSET_ARCV2] = {
29665c02a55SVineet Gupta .core_note_type = NT_ARC_V2,
29765c02a55SVineet Gupta .n = ELF_ARCV2REG,
29865c02a55SVineet Gupta .size = sizeof(unsigned long),
29965c02a55SVineet Gupta .align = sizeof(unsigned long),
3005a806e0aSAl Viro .regset_get = arcv2regs_get,
30165c02a55SVineet Gupta .set = arcv2regs_set,
30265c02a55SVineet Gupta },
30365c02a55SVineet Gupta #endif
304547f1125SVineet Gupta };
305547f1125SVineet Gupta
306547f1125SVineet Gupta static const struct user_regset_view user_arc_view = {
3079eca345cSMasahiro Yamada .name = "arc",
3081f6ccfffSVineet Gupta .e_machine = EM_ARC_INUSE,
309547f1125SVineet Gupta .regsets = arc_regsets,
310547f1125SVineet Gupta .n = ARRAY_SIZE(arc_regsets)
311547f1125SVineet Gupta };
312547f1125SVineet Gupta
task_user_regset_view(struct task_struct * task)313547f1125SVineet Gupta const struct user_regset_view *task_user_regset_view(struct task_struct *task)
314547f1125SVineet Gupta {
315547f1125SVineet Gupta return &user_arc_view;
316547f1125SVineet Gupta }
317c08098f2SVineet Gupta
ptrace_disable(struct task_struct * child)318c08098f2SVineet Gupta void ptrace_disable(struct task_struct *child)
319c08098f2SVineet Gupta {
320c08098f2SVineet Gupta }
321c08098f2SVineet Gupta
arch_ptrace(struct task_struct * child,long request,unsigned long addr,unsigned long data)322c08098f2SVineet Gupta long arch_ptrace(struct task_struct *child, long request,
323c08098f2SVineet Gupta unsigned long addr, unsigned long data)
324c08098f2SVineet Gupta {
325c08098f2SVineet Gupta int ret = -EIO;
326547f1125SVineet Gupta
327547f1125SVineet Gupta pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request, addr, data);
328547f1125SVineet Gupta
329547f1125SVineet Gupta switch (request) {
330a4b6cb73SAnton Kolesov case PTRACE_GET_THREAD_AREA:
331a4b6cb73SAnton Kolesov ret = put_user(task_thread_info(child)->thr_ptr,
332a4b6cb73SAnton Kolesov (unsigned long __user *)data);
333a4b6cb73SAnton Kolesov break;
334547f1125SVineet Gupta default:
335547f1125SVineet Gupta ret = ptrace_request(child, request, addr, data);
336547f1125SVineet Gupta break;
337547f1125SVineet Gupta }
338547f1125SVineet Gupta
339c08098f2SVineet Gupta return ret;
340c08098f2SVineet Gupta }
341c08098f2SVineet Gupta
syscall_trace_enter(struct pt_regs * regs)342c505b0daSVineet Gupta asmlinkage int syscall_trace_enter(struct pt_regs *regs)
343c08098f2SVineet Gupta {
344fb0b5490SSergey Matyukevich if (test_thread_flag(TIF_SYSCALL_TRACE))
345153474baSEric W. Biederman if (ptrace_report_syscall_entry(regs))
346547f1125SVineet Gupta return ULONG_MAX;
347547f1125SVineet Gupta
348fb0b5490SSergey Matyukevich #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
349fb0b5490SSergey Matyukevich if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
350fb0b5490SSergey Matyukevich trace_sys_enter(regs, syscall_get_nr(current, regs));
351fb0b5490SSergey Matyukevich #endif
352fb0b5490SSergey Matyukevich
353547f1125SVineet Gupta return regs->r8;
354547f1125SVineet Gupta }
355547f1125SVineet Gupta
syscall_trace_exit(struct pt_regs * regs)356547f1125SVineet Gupta asmlinkage void syscall_trace_exit(struct pt_regs *regs)
357547f1125SVineet Gupta {
358fb0b5490SSergey Matyukevich if (test_thread_flag(TIF_SYSCALL_TRACE))
359153474baSEric W. Biederman ptrace_report_syscall_exit(regs, 0);
360fb0b5490SSergey Matyukevich
361fb0b5490SSergey Matyukevich #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
362fb0b5490SSergey Matyukevich if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
363fb0b5490SSergey Matyukevich trace_sys_exit(regs, regs_return_value(regs));
364fb0b5490SSergey Matyukevich #endif
365c08098f2SVineet Gupta }
366b3bbf6a7SSergey Matyukevich
regs_query_register_offset(const char * name)367b3bbf6a7SSergey Matyukevich int regs_query_register_offset(const char *name)
368b3bbf6a7SSergey Matyukevich {
369b3bbf6a7SSergey Matyukevich const struct pt_regs_offset *roff;
370b3bbf6a7SSergey Matyukevich
371b3bbf6a7SSergey Matyukevich for (roff = regoffset_table; roff->name != NULL; roff++)
372b3bbf6a7SSergey Matyukevich if (!strcmp(roff->name, name))
373b3bbf6a7SSergey Matyukevich return roff->offset;
374b3bbf6a7SSergey Matyukevich return -EINVAL;
375b3bbf6a7SSergey Matyukevich }
376b3bbf6a7SSergey Matyukevich
regs_query_register_name(unsigned int offset)377b3bbf6a7SSergey Matyukevich const char *regs_query_register_name(unsigned int offset)
378b3bbf6a7SSergey Matyukevich {
379b3bbf6a7SSergey Matyukevich const struct pt_regs_offset *roff;
380b3bbf6a7SSergey Matyukevich for (roff = regoffset_table; roff->name != NULL; roff++)
381b3bbf6a7SSergey Matyukevich if (roff->offset == offset)
382b3bbf6a7SSergey Matyukevich return roff->name;
383b3bbf6a7SSergey Matyukevich return NULL;
384b3bbf6a7SSergey Matyukevich }
385b3bbf6a7SSergey Matyukevich
regs_within_kernel_stack(struct pt_regs * regs,unsigned long addr)386b3bbf6a7SSergey Matyukevich bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
387b3bbf6a7SSergey Matyukevich {
388b3bbf6a7SSergey Matyukevich return (addr & ~(THREAD_SIZE - 1)) ==
389b3bbf6a7SSergey Matyukevich (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
390b3bbf6a7SSergey Matyukevich }
391b3bbf6a7SSergey Matyukevich
regs_get_kernel_stack_nth(struct pt_regs * regs,unsigned int n)392b3bbf6a7SSergey Matyukevich unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
393b3bbf6a7SSergey Matyukevich {
394b3bbf6a7SSergey Matyukevich unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
395b3bbf6a7SSergey Matyukevich
396b3bbf6a7SSergey Matyukevich addr += n;
397b3bbf6a7SSergey Matyukevich if (regs_within_kernel_stack(regs, (unsigned long)addr))
398b3bbf6a7SSergey Matyukevich return *addr;
399b3bbf6a7SSergey Matyukevich else
400b3bbf6a7SSergey Matyukevich return 0;
401b3bbf6a7SSergey Matyukevich }
402