aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-06-14 02:16:53 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-06-14 02:16:53 -0400
commiteaaaeef392cb245e415c31d480ed2d5a466fd88f (patch)
tree483761495ceb9cc3a277769f52d0ec8abeed1ac0
parent9973e38575070b70c68bad177fb5056548fea349 (diff)
sh: Add kprobe-based event tracer.
This follows the x86/ppc changes for kprobe-based event tracing on sh. While kprobes is only supported on 32-bit sh, we provide the API for HAVE_REGS_AND_STACK_ACCESS_API for both 32 and 64-bit. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/include/asm/kprobes.h1
-rw-r--r--arch/sh/include/asm/processor_32.h3
-rw-r--r--arch/sh/include/asm/processor_64.h3
-rw-r--r--arch/sh/include/asm/ptrace.h89
-rw-r--r--arch/sh/kernel/Makefile2
-rw-r--r--arch/sh/kernel/ptrace.c33
-rw-r--r--arch/sh/kernel/ptrace_32.c27
-rw-r--r--arch/sh/kernel/ptrace_64.c79
9 files changed, 227 insertions, 11 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 573fca1fbd9..e6b1f207f7a 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -23,6 +23,7 @@ config SUPERH
23 select HAVE_KERNEL_LZMA 23 select HAVE_KERNEL_LZMA
24 select HAVE_KERNEL_LZO 24 select HAVE_KERNEL_LZO
25 select HAVE_SYSCALL_TRACEPOINTS 25 select HAVE_SYSCALL_TRACEPOINTS
26 select HAVE_REGS_AND_STACK_ACCESS_API
26 select RTC_LIB 27 select RTC_LIB
27 select GENERIC_ATOMIC64 28 select GENERIC_ATOMIC64
28 help 29 help
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 036c3311233..134f3980e44 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -16,7 +16,6 @@ typedef insn_size_t kprobe_opcode_t;
16 ? (MAX_STACK_SIZE) \ 16 ? (MAX_STACK_SIZE) \
17 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) 17 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
18 18
19#define regs_return_value(_regs) ((_regs)->regs[0])
20#define flush_insn_slot(p) do { } while (0) 19#define flush_insn_slot(p) do { } while (0)
21#define kretprobe_blacklist_size 0 20#define kretprobe_blacklist_size 0
22 21
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index 61a445d2d02..46d5179c9f4 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -13,7 +13,6 @@
13#include <linux/linkage.h> 13#include <linux/linkage.h>
14#include <asm/page.h> 14#include <asm/page.h>
15#include <asm/types.h> 15#include <asm/types.h>
16#include <asm/ptrace.h>
17#include <asm/hw_breakpoint.h> 16#include <asm/hw_breakpoint.h>
18 17
19/* 18/*
@@ -194,8 +193,6 @@ extern unsigned long get_wchan(struct task_struct *p);
194#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) 193#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
195#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) 194#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15])
196 195
197#define user_stack_pointer(_regs) ((_regs)->regs[15])
198
199#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) 196#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
200#define PREFETCH_STRIDE L1_CACHE_BYTES 197#define PREFETCH_STRIDE L1_CACHE_BYTES
201#define ARCH_HAS_PREFETCH 198#define ARCH_HAS_PREFETCH
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index 621bc4618c6..2a541ddb5a1 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -17,7 +17,6 @@
17#include <linux/compiler.h> 17#include <linux/compiler.h>
18#include <asm/page.h> 18#include <asm/page.h>
19#include <asm/types.h> 19#include <asm/types.h>
20#include <asm/ptrace.h>
21#include <cpu/registers.h> 20#include <cpu/registers.h>
22 21
23/* 22/*
@@ -231,7 +230,5 @@ extern unsigned long get_wchan(struct task_struct *p);
231#define KSTK_EIP(tsk) ((tsk)->thread.pc) 230#define KSTK_EIP(tsk) ((tsk)->thread.pc)
232#define KSTK_ESP(tsk) ((tsk)->thread.sp) 231#define KSTK_ESP(tsk) ((tsk)->thread.sp)
233 232
234#define user_stack_pointer(_regs) ((_regs)->regs[15])
235
236#endif /* __ASSEMBLY__ */ 233#endif /* __ASSEMBLY__ */
237#endif /* __ASM_SH_PROCESSOR_64_H */ 234#endif /* __ASM_SH_PROCESSOR_64_H */
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index 2168fde2561..33b3f37dcdb 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -1,6 +1,8 @@
1#ifndef __ASM_SH_PTRACE_H 1#ifndef __ASM_SH_PTRACE_H
2#define __ASM_SH_PTRACE_H 2#define __ASM_SH_PTRACE_H
3 3
4#include <linux/stringify.h>
5
4/* 6/*
5 * Copyright (C) 1999, 2000 Niibe Yutaka 7 * Copyright (C) 1999, 2000 Niibe Yutaka
6 * 8 *
@@ -14,6 +16,13 @@ struct pt_regs {
14 unsigned long long tregs[8]; 16 unsigned long long tregs[8];
15 unsigned long long pad[2]; 17 unsigned long long pad[2];
16}; 18};
19
20#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7])
21#define regs_return_value(regs) ((regs)->regs[3])
22
23#define TREGS_OFFSET_NAME(num) \
24 {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])}
25
17#else 26#else
18/* 27/*
19 * GCC defines register number like this: 28 * GCC defines register number like this:
@@ -66,6 +75,9 @@ struct pt_regs {
66 long tra; 75 long tra;
67}; 76};
68 77
78#define MAX_REG_OFFSET offsetof(struct pt_regs, tra)
79#define regs_return_value(regs) ((regs)->regs[0])
80
69/* 81/*
70 * This struct defines the way the DSP registers are stored on the 82 * This struct defines the way the DSP registers are stored on the
71 * kernel stack during a system call or other kernel entry. 83 * kernel stack during a system call or other kernel entry.
@@ -113,16 +125,87 @@ struct pt_dspregs {
113#include <asm/system.h> 125#include <asm/system.h>
114 126
115#define user_mode(regs) (((regs)->sr & 0x40000000)==0) 127#define user_mode(regs) (((regs)->sr & 0x40000000)==0)
128#define user_stack_pointer(regs) ((unsigned long)(regs)->regs[15])
129#define kernel_stack_pointer(regs) ((unsigned long)(regs)->regs[15])
116#define instruction_pointer(regs) ((unsigned long)(regs)->pc) 130#define instruction_pointer(regs) ((unsigned long)(regs)->pc)
117 131
118extern void show_regs(struct pt_regs *); 132extern void show_regs(struct pt_regs *);
119 133
134#define arch_has_single_step() (1)
135
120/* 136/*
121 * These are defined as per linux/ptrace.h. 137 * kprobe-based event tracer support
122 */ 138 */
123struct task_struct; 139#include <linux/stddef.h>
140#include <linux/thread_info.h>
124 141
125#define arch_has_single_step() (1) 142struct pt_regs_offset {
143 const char *name;
144 int offset;
145};
146
147#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
148#define REGS_OFFSET_NAME(num) \
149 {.name = __stringify(r##num), .offset = offsetof(struct pt_regs, regs[num])}
150#define REG_OFFSET_END {.name = NULL, .offset = 0}
151
152/* Query offset/name of register from its name/offset */
153extern int regs_query_register_offset(const char *name);
154extern const char *regs_query_register_name(unsigned int offset);
155
156extern const struct pt_regs_offset regoffset_table[];
157
158/**
159 * regs_get_register() - get register value from its offset
160 * @regs: pt_regs from which register value is gotten.
161 * @offset: offset number of the register.
162 *
163 * regs_get_register returns the value of a register. The @offset is the
164 * offset of the register in struct pt_regs address which specified by @regs.
165 * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
166 */
167static inline unsigned long regs_get_register(struct pt_regs *regs,
168 unsigned int offset)
169{
170 if (unlikely(offset > MAX_REG_OFFSET))
171 return 0;
172 return *(unsigned long *)((unsigned long)regs + offset);
173}
174
175/**
176 * regs_within_kernel_stack() - check the address in the stack
177 * @regs: pt_regs which contains kernel stack pointer.
178 * @addr: address which is checked.
179 *
180 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
181 * If @addr is within the kernel stack, it returns true. If not, returns false.
182 */
183static inline int regs_within_kernel_stack(struct pt_regs *regs,
184 unsigned long addr)
185{
186 return ((addr & ~(THREAD_SIZE - 1)) ==
187 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
188}
189
190/**
191 * regs_get_kernel_stack_nth() - get Nth entry of the stack
192 * @regs: pt_regs which contains kernel stack pointer.
193 * @n: stack entry number.
194 *
195 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
196 * is specified by @regs. If the @n th entry is NOT in the kernel stack,
197 * this returns 0.
198 */
199static inline unsigned long