Skip to content

Commit 8f0350a

Browse files
author
Sergey Matyukevich
committed
ARC: enable HAVE_REGS_AND_STACK_ACCESS_API feature
Enable HAVE_REGS_AND_STACK_ACCESS_API feature for ARC architecture, including ARCcompact and ARCv2 flavors. Add supporting functions and defines. Signed-off-by: Sergey Matyukevich <sergey.matyukevich@synopsys.com>
1 parent eacf252 commit 8f0350a

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

arch/arc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ config ARC
3838
select HAVE_KERNEL_LZMA
3939
select HAVE_KPROBES
4040
select HAVE_KRETPROBES
41+
select HAVE_REGS_AND_STACK_ACCESS_API
4142
select HAVE_MOD_ARCH_SPECIFIC
4243
select HAVE_PERF_EVENTS
4344
select IRQ_DOMAIN

arch/arc/include/asm/ptrace.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define __ASM_ARC_PTRACE_H
99

1010
#include <uapi/asm/ptrace.h>
11+
#include <linux/compiler.h>
1112

1213
#ifndef __ASSEMBLY__
1314

@@ -53,6 +54,8 @@ struct pt_regs {
5354
ecr_reg ecr;
5455
};
5556

57+
#define MAX_REG_OFFSET offsetof(struct pt_regs, ecr)
58+
5659
struct callee_regs {
5760
unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
5861
};
@@ -95,6 +98,8 @@ struct pt_regs {
9598
unsigned long status32;
9699
};
97100

101+
#define MAX_REG_OFFSET offsetof(struct pt_regs, status32)
102+
98103
struct callee_regs {
99104
unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
100105
};
@@ -170,6 +175,27 @@ static inline void instruction_pointer_set(struct pt_regs *regs,
170175
{
171176
instruction_pointer(regs) = val;
172177
}
178+
179+
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
180+
{
181+
return regs->sp;
182+
}
183+
184+
extern int regs_query_register_offset(const char *name);
185+
extern const char *regs_query_register_name(unsigned int offset);
186+
extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr);
187+
extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
188+
unsigned int n);
189+
190+
static inline unsigned long regs_get_register(struct pt_regs *regs,
191+
unsigned int offset)
192+
{
193+
if (unlikely(offset > MAX_REG_OFFSET))
194+
return 0;
195+
196+
return *(unsigned long *)((unsigned long)regs + offset);
197+
}
198+
173199
#endif /* !__ASSEMBLY__ */
174200

175201
#endif /* __ASM_PTRACE_H */

arch/arc/kernel/ptrace.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,89 @@
1111
#include <linux/elf.h>
1212
#include <asm/asm-offsets.h>
1313

14+
struct pt_regs_offset {
15+
const char *name;
16+
int offset;
17+
};
18+
19+
#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
20+
#define REG_OFFSET_END {.name = NULL, .offset = 0}
21+
22+
#ifdef CONFIG_ISA_ARCOMPACT
23+
static const struct pt_regs_offset regoffset_table[] = {
24+
REG_OFFSET_NAME(bta),
25+
REG_OFFSET_NAME(lp_start),
26+
REG_OFFSET_NAME(lp_end),
27+
REG_OFFSET_NAME(lp_count),
28+
REG_OFFSET_NAME(status32),
29+
REG_OFFSET_NAME(ret),
30+
REG_OFFSET_NAME(blink),
31+
REG_OFFSET_NAME(fp),
32+
REG_OFFSET_NAME(gp),
33+
REG_OFFSET_NAME(r12),
34+
REG_OFFSET_NAME(r11),
35+
REG_OFFSET_NAME(r10),
36+
REG_OFFSET_NAME(r9),
37+
REG_OFFSET_NAME(r8),
38+
REG_OFFSET_NAME(r7),
39+
REG_OFFSET_NAME(r6),
40+
REG_OFFSET_NAME(r5),
41+
REG_OFFSET_NAME(r4),
42+
REG_OFFSET_NAME(r3),
43+
REG_OFFSET_NAME(r2),
44+
REG_OFFSET_NAME(r1),
45+
REG_OFFSET_NAME(r0),
46+
REG_OFFSET_NAME(sp),
47+
REG_OFFSET_NAME(orig_r0),
48+
REG_OFFSET_NAME(ecr),
49+
REG_OFFSET_END,
50+
};
51+
52+
#else
53+
54+
static const struct pt_regs_offset regoffset_table[] = {
55+
REG_OFFSET_NAME(orig_r0),
56+
REG_OFFSET_NAME(ecr),
57+
REG_OFFSET_NAME(bta),
58+
REG_OFFSET_NAME(fp),
59+
REG_OFFSET_NAME(r30),
60+
REG_OFFSET_NAME(r12),
61+
REG_OFFSET_NAME(gp),
62+
#ifdef CONFIG_ARC_HAS_ACCL_REGS
63+
REG_OFFSET_NAME(r58),
64+
REG_OFFSET_NAME(r59),
65+
#endif
66+
#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
67+
REG_OFFSET_NAME(DSP_CTRL),
68+
#endif
69+
REG_OFFSET_NAME(sp),
70+
REG_OFFSET_NAME(r0),
71+
REG_OFFSET_NAME(r1),
72+
REG_OFFSET_NAME(r2),
73+
REG_OFFSET_NAME(r3),
74+
REG_OFFSET_NAME(r4),
75+
REG_OFFSET_NAME(r5),
76+
REG_OFFSET_NAME(r6),
77+
REG_OFFSET_NAME(r7),
78+
REG_OFFSET_NAME(r8),
79+
REG_OFFSET_NAME(r9),
80+
REG_OFFSET_NAME(r10),
81+
REG_OFFSET_NAME(r11),
82+
REG_OFFSET_NAME(blink),
83+
#ifndef CONFIG_ARC_LACKS_ZOL
84+
REG_OFFSET_NAME(lp_end),
85+
REG_OFFSET_NAME(lp_start),
86+
REG_OFFSET_NAME(lp_count),
87+
#endif
88+
REG_OFFSET_NAME(ei),
89+
REG_OFFSET_NAME(ldi),
90+
REG_OFFSET_NAME(jli),
91+
REG_OFFSET_NAME(ret),
92+
REG_OFFSET_NAME(status32),
93+
REG_OFFSET_END,
94+
};
95+
#endif
96+
1497
static struct callee_regs *task_callee_regs(struct task_struct *tsk)
1598
{
1699
struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg;
@@ -290,3 +373,39 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
290373
{
291374
tracehook_report_syscall_exit(regs, 0);
292375
}
376+
377+
int regs_query_register_offset(const char *name)
378+
{
379+
const struct pt_regs_offset *roff;
380+
381+
for (roff = regoffset_table; roff->name != NULL; roff++)
382+
if (!strcmp(roff->name, name))
383+
return roff->offset;
384+
return -EINVAL;
385+
}
386+
387+
const char *regs_query_register_name(unsigned int offset)
388+
{
389+
const struct pt_regs_offset *roff;
390+
for (roff = regoffset_table; roff->name != NULL; roff++)
391+
if (roff->offset == offset)
392+
return roff->name;
393+
return NULL;
394+
}
395+
396+
bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
397+
{
398+
return (addr & ~(THREAD_SIZE - 1)) ==
399+
(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
400+
}
401+
402+
unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
403+
{
404+
unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
405+
406+
addr += n;
407+
if (regs_within_kernel_stack(regs, (unsigned long)addr))
408+
return *addr;
409+
else
410+
return 0;
411+
}

0 commit comments

Comments
 (0)