typedef u32 kprobe_opcode_t;
+#define __ARCH_WANT_KPROBES_INSN_SLOT
#define BREAKPOINT_INSTRUCTION 0x91d02070 /* ta 0x70 */
#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
#define MAX_INSN_SIZE 2
#define kretprobe_blacklist_size 0
-#define arch_remove_kprobe(p) do {} while (0)
-
#define flush_insn_slot(p) \
do { flushi(&(p)->ainsn.insn[0]); \
flushi(&(p)->ainsn.insn[1]); \
void kretprobe_trampoline(void);
+struct kprobe;
+void __kprobes arch_remove_kprobe(struct kprobe *p);
+
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
/* copy of the original instruction */
- kprobe_opcode_t insn[MAX_INSN_SIZE];
+ kprobe_opcode_t *insn;
};
struct prev_kprobe {
#include <linux/threads.h>
#include <asm/switch_to.h>
+unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n);
+
static inline int pt_regs_trap_type(struct pt_regs *regs)
{
return regs->magic & 0x1ff;
#include <asm/signal.h>
#include <asm/cacheflush.h>
#include <asm/uaccess.h>
+#include <asm/stacktrace.h>
/* We do not have hardware single-stepping on sparc64.
* So we implement software single-stepping with breakpoint
if ((unsigned long) p->addr & 0x3UL)
return -EILSEQ;
+ p->ainsn.insn = get_insn_slot();
+ if (!p->ainsn.insn)
+ return -ENOMEM;
+
p->ainsn.insn[0] = *p->addr;
flushi(&p->ainsn.insn[0]);
return 0;
}
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+ if (p->ainsn.insn) {
+ free_insn_slot(p->ainsn.insn, 0);
+ p->ainsn.insn = NULL;
+ }
+}
+
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
*p->addr = BREAKPOINT_INSTRUCTION;
return 0;
}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @n: stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
+{
+ unsigned long ksp, nth_entry_addr;
+
+ stack_trace_flush();
+
+ ksp = kernel_stack_pointer(regs);
+ ksp += STACK_BIAS;
+ nth_entry_addr = ksp + (n * sizeof(unsigned long));
+
+ if (object_is_on_stack((void *)nth_entry_addr))
+ return *(unsigned long *)nth_entry_addr;
+ else
+ return 0;
+}
+