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> Signed-off-by: Vineet Gupta <vgupta@kernel.org>
This commit is contained in:
Родитель
af2d861d4c
Коммит
b3bbf6a70b
|
@ -36,6 +36,7 @@ config ARC
|
|||
select HAVE_KERNEL_LZMA
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_PERF_EVENTS
|
||||
select IRQ_DOMAIN
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define __ASM_ARC_PTRACE_H
|
||||
|
||||
#include <uapi/asm/ptrace.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -54,6 +55,9 @@ struct pt_regs {
|
|||
|
||||
unsigned long user_r25;
|
||||
};
|
||||
|
||||
#define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25)
|
||||
|
||||
#else
|
||||
|
||||
struct pt_regs {
|
||||
|
@ -102,6 +106,8 @@ struct pt_regs {
|
|||
unsigned long status32;
|
||||
};
|
||||
|
||||
#define MAX_REG_OFFSET offsetof(struct pt_regs, status32)
|
||||
|
||||
#endif
|
||||
|
||||
/* Callee saved registers - need to be saved only when you are scheduled out */
|
||||
|
@ -154,6 +160,27 @@ static inline void instruction_pointer_set(struct pt_regs *regs,
|
|||
{
|
||||
instruction_pointer(regs) = val;
|
||||
}
|
||||
|
||||
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
|
||||
{
|
||||
return regs->sp;
|
||||
}
|
||||
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
extern const char *regs_query_register_name(unsigned int offset);
|
||||
extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr);
|
||||
extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
|
||||
unsigned int n);
|
||||
|
||||
static inline unsigned long regs_get_register(struct pt_regs *regs,
|
||||
unsigned int offset)
|
||||
{
|
||||
if (unlikely(offset > MAX_REG_OFFSET))
|
||||
return 0;
|
||||
|
||||
return *(unsigned long *)((unsigned long)regs + offset);
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_PTRACE_H */
|
||||
|
|
|
@ -9,6 +9,89 @@
|
|||
#include <linux/unistd.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
struct pt_regs_offset {
|
||||
const char *name;
|
||||
int offset;
|
||||
};
|
||||
|
||||
#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
|
||||
#define REG_OFFSET_END {.name = NULL, .offset = 0}
|
||||
|
||||
#ifdef CONFIG_ISA_ARCOMPACT
|
||||
static const struct pt_regs_offset regoffset_table[] = {
|
||||
REG_OFFSET_NAME(bta),
|
||||
REG_OFFSET_NAME(lp_start),
|
||||
REG_OFFSET_NAME(lp_end),
|
||||
REG_OFFSET_NAME(lp_count),
|
||||
REG_OFFSET_NAME(status32),
|
||||
REG_OFFSET_NAME(ret),
|
||||
REG_OFFSET_NAME(blink),
|
||||
REG_OFFSET_NAME(fp),
|
||||
REG_OFFSET_NAME(r26),
|
||||
REG_OFFSET_NAME(r12),
|
||||
REG_OFFSET_NAME(r11),
|
||||
REG_OFFSET_NAME(r10),
|
||||
REG_OFFSET_NAME(r9),
|
||||
REG_OFFSET_NAME(r8),
|
||||
REG_OFFSET_NAME(r7),
|
||||
REG_OFFSET_NAME(r6),
|
||||
REG_OFFSET_NAME(r5),
|
||||
REG_OFFSET_NAME(r4),
|
||||
REG_OFFSET_NAME(r3),
|
||||
REG_OFFSET_NAME(r2),
|
||||
REG_OFFSET_NAME(r1),
|
||||
REG_OFFSET_NAME(r0),
|
||||
REG_OFFSET_NAME(sp),
|
||||
REG_OFFSET_NAME(orig_r0),
|
||||
REG_OFFSET_NAME(event),
|
||||
REG_OFFSET_NAME(user_r25),
|
||||
REG_OFFSET_END,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static const struct pt_regs_offset regoffset_table[] = {
|
||||
REG_OFFSET_NAME(orig_r0),
|
||||
REG_OFFSET_NAME(event),
|
||||
REG_OFFSET_NAME(bta),
|
||||
REG_OFFSET_NAME(user_r25),
|
||||
REG_OFFSET_NAME(r26),
|
||||
REG_OFFSET_NAME(fp),
|
||||
REG_OFFSET_NAME(sp),
|
||||
REG_OFFSET_NAME(r12),
|
||||
REG_OFFSET_NAME(r30),
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
REG_OFFSET_NAME(r58),
|
||||
REG_OFFSET_NAME(r59),
|
||||
#endif
|
||||
#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
|
||||
REG_OFFSET_NAME(DSP_CTRL),
|
||||
#endif
|
||||
REG_OFFSET_NAME(r0),
|
||||
REG_OFFSET_NAME(r1),
|
||||
REG_OFFSET_NAME(r2),
|
||||
REG_OFFSET_NAME(r3),
|
||||
REG_OFFSET_NAME(r4),
|
||||
REG_OFFSET_NAME(r5),
|
||||
REG_OFFSET_NAME(r6),
|
||||
REG_OFFSET_NAME(r7),
|
||||
REG_OFFSET_NAME(r8),
|
||||
REG_OFFSET_NAME(r9),
|
||||
REG_OFFSET_NAME(r10),
|
||||
REG_OFFSET_NAME(r11),
|
||||
REG_OFFSET_NAME(blink),
|
||||
REG_OFFSET_NAME(lp_end),
|
||||
REG_OFFSET_NAME(lp_start),
|
||||
REG_OFFSET_NAME(lp_count),
|
||||
REG_OFFSET_NAME(ei),
|
||||
REG_OFFSET_NAME(ldi),
|
||||
REG_OFFSET_NAME(jli),
|
||||
REG_OFFSET_NAME(ret),
|
||||
REG_OFFSET_NAME(status32),
|
||||
REG_OFFSET_END,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct callee_regs *task_callee_regs(struct task_struct *tsk)
|
||||
{
|
||||
struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg;
|
||||
|
@ -267,3 +350,39 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
|
|||
{
|
||||
ptrace_report_syscall_exit(regs, 0);
|
||||
}
|
||||
|
||||
int regs_query_register_offset(const char *name)
|
||||
{
|
||||
const struct pt_regs_offset *roff;
|
||||
|
||||
for (roff = regoffset_table; roff->name != NULL; roff++)
|
||||
if (!strcmp(roff->name, name))
|
||||
return roff->offset;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const char *regs_query_register_name(unsigned int offset)
|
||||
{
|
||||
const struct pt_regs_offset *roff;
|
||||
for (roff = regoffset_table; roff->name != NULL; roff++)
|
||||
if (roff->offset == offset)
|
||||
return roff->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
|
||||
{
|
||||
return (addr & ~(THREAD_SIZE - 1)) ==
|
||||
(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
|
||||
}
|
||||
|
||||
unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
|
||||
{
|
||||
unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
|
||||
|
||||
addr += n;
|
||||
if (regs_within_kernel_stack(regs, (unsigned long)addr))
|
||||
return *addr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче