Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 76072
b: refs/heads/master
c: 13b54a5
h: refs/heads/master
v: v3
  • Loading branch information
Haavard Skinnemoen committed Jan 25, 2008
1 parent a0e6aa2 commit d664360
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6ea6dd93c9454cc9521134f907bc970d09f460e4
refs/heads/master: 13b54a50525a9685065684e1e11258d27dd27bdf
2 changes: 1 addition & 1 deletion trunk/arch/avr32/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds

obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
obj-y += syscall_table.o syscall-stubs.o irq.o
obj-y += setup.o traps.o semaphore.o ptrace.o
obj-y += setup.o traps.o semaphore.o ocd.o ptrace.o
obj-y += signal.o sys_avr32.o process.o time.o
obj-y += init_task.o switch_to.o cpu.o
obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
Expand Down
5 changes: 2 additions & 3 deletions trunk/arch/avr32/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
pr_debug("arming kprobe at %p\n", p->addr);
ocd_enable(NULL);
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range((unsigned long)p->addr,
(unsigned long)p->addr + sizeof(kprobe_opcode_t));
Expand All @@ -56,6 +57,7 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
pr_debug("disarming kprobe at %p\n", p->addr);
ocd_disable(NULL);
*p->addr = p->opcode;
flush_icache_range((unsigned long)p->addr,
(unsigned long)p->addr + sizeof(kprobe_opcode_t));
Expand Down Expand Up @@ -260,9 +262,6 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)

int __init arch_init_kprobes(void)
{
printk("KPROBES: Enabling monitor mode (MM|DBE)...\n");
ocd_write(DC, (1 << OCD_DC_MM_BIT) | (1 << OCD_DC_DBE_BIT));

/* TODO: Register kretprobe trampoline */
return 0;
}
163 changes: 163 additions & 0 deletions trunk/arch/avr32/kernel/ocd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Copyright (C) 2007 Atmel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/spinlock.h>

#include <asm/ocd.h>

static long ocd_count;
static spinlock_t ocd_lock;

/**
* ocd_enable - enable on-chip debugging
* @child: task to be debugged
*
* If @child is non-NULL, ocd_enable() first checks if debugging has
* already been enabled for @child, and if it has, does nothing.
*
* If @child is NULL (e.g. when debugging the kernel), or debugging
* has not already been enabled for it, ocd_enable() increments the
* reference count and enables the debugging hardware.
*/
void ocd_enable(struct task_struct *child)
{
u32 dc;

if (child)
pr_debug("ocd_enable: child=%s [%u]\n",
child->comm, child->pid);
else
pr_debug("ocd_enable (no child)\n");

if (!child || !test_and_set_tsk_thread_flag(child, TIF_DEBUG)) {
spin_lock(&ocd_lock);
ocd_count++;
dc = ocd_read(DC);
dc |= (1 << OCD_DC_MM_BIT) | (1 << OCD_DC_DBE_BIT);
ocd_write(DC, dc);
spin_unlock(&ocd_lock);
}
}

/**
* ocd_disable - disable on-chip debugging
* @child: task that was being debugged, but isn't anymore
*
* If @child is non-NULL, ocd_disable() checks if debugging is enabled
* for @child, and if it isn't, does nothing.
*
* If @child is NULL (e.g. when debugging the kernel), or debugging is
* enabled, ocd_disable() decrements the reference count, and if it
* reaches zero, disables the debugging hardware.
*/
void ocd_disable(struct task_struct *child)
{
u32 dc;

if (!child)
pr_debug("ocd_disable (no child)\n");
else if (test_tsk_thread_flag(child, TIF_DEBUG))
pr_debug("ocd_disable: child=%s [%u]\n",
child->comm, child->pid);

if (!child || test_and_clear_tsk_thread_flag(child, TIF_DEBUG)) {
spin_lock(&ocd_lock);
ocd_count--;

WARN_ON(ocd_count < 0);

if (ocd_count <= 0) {
dc = ocd_read(DC);
dc &= ~((1 << OCD_DC_MM_BIT) | (1 << OCD_DC_DBE_BIT));
ocd_write(DC, dc);
}
spin_unlock(&ocd_lock);
}
}

#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/module.h>

static struct dentry *ocd_debugfs_root;
static struct dentry *ocd_debugfs_DC;
static struct dentry *ocd_debugfs_DS;
static struct dentry *ocd_debugfs_count;

static u64 ocd_DC_get(void *data)
{
return ocd_read(DC);
}
static void ocd_DC_set(void *data, u64 val)
{
ocd_write(DC, val);
}
DEFINE_SIMPLE_ATTRIBUTE(fops_DC, ocd_DC_get, ocd_DC_set, "0x%08llx\n");

static u64 ocd_DS_get(void *data)
{
return ocd_read(DS);
}
DEFINE_SIMPLE_ATTRIBUTE(fops_DS, ocd_DS_get, NULL, "0x%08llx\n");

static u64 ocd_count_get(void *data)
{
return ocd_count;
}
DEFINE_SIMPLE_ATTRIBUTE(fops_count, ocd_count_get, NULL, "%lld\n");

static void ocd_debugfs_init(void)
{
struct dentry *root;

root = debugfs_create_dir("ocd", NULL);
if (IS_ERR(root) || !root)
goto err_root;
ocd_debugfs_root = root;

ocd_debugfs_DC = debugfs_create_file("DC", S_IRUSR | S_IWUSR,
root, NULL, &fops_DC);
if (!ocd_debugfs_DC)
goto err_DC;

ocd_debugfs_DS = debugfs_create_file("DS", S_IRUSR, root,
NULL, &fops_DS);
if (!ocd_debugfs_DS)
goto err_DS;

ocd_debugfs_count = debugfs_create_file("count", S_IRUSR, root,
NULL, &fops_count);
if (!ocd_debugfs_count)
goto err_count;

return;

err_count:
debugfs_remove(ocd_debugfs_DS);
err_DS:
debugfs_remove(ocd_debugfs_DC);
err_DC:
debugfs_remove(ocd_debugfs_root);
err_root:
printk(KERN_WARNING "OCD: Failed to create debugfs entries\n");
}
#else
static inline void ocd_debugfs_init(void)
{

}
#endif

static int __init ocd_init(void)
{
spin_lock_init(&ocd_lock);
ocd_debugfs_init();
return 0;
}
arch_initcall(ocd_init);
5 changes: 4 additions & 1 deletion trunk/arch/avr32/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ EXPORT_SYMBOL(kernel_thread);
*/
void exit_thread(void)
{
/* nothing to do */
ocd_disable(current);
}

void flush_thread(void)
Expand Down Expand Up @@ -345,6 +345,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
p->thread.cpu_context.ksp = (unsigned long)childregs;
p->thread.cpu_context.pc = (unsigned long)ret_from_fork;

if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG))
ocd_enable(p);

return 0;
}

Expand Down
5 changes: 1 addition & 4 deletions trunk/arch/avr32/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ void ptrace_disable(struct task_struct *child)
{
clear_tsk_thread_flag(child, TIF_SINGLE_STEP);
clear_tsk_thread_flag(child, TIF_BREAKPOINT);
ocd_disable(child);
}

/*
Expand Down Expand Up @@ -144,10 +145,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret;

pr_debug("ptrace: Enabling monitor mode...\n");
ocd_write(DC, ocd_read(DC) | (1 << OCD_DC_MM_BIT)
| (1 << OCD_DC_DBE_BIT));

switch (request) {
/* Read the word at location addr in the child process */
case PTRACE_PEEKTEXT:
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/asm-avr32/ocd.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,11 @@ static inline void __ocd_write(unsigned int reg, unsigned long value)
#define ocd_read(reg) __ocd_read(OCD_##reg)
#define ocd_write(reg, value) __ocd_write(OCD_##reg, value)

struct task_struct;

void ocd_enable(struct task_struct *child);
void ocd_disable(struct task_struct *child);

#endif /* !__ASSEMBLER__ */

#endif /* __ASM_AVR32_OCD_H */
13 changes: 9 additions & 4 deletions trunk/include/asm-avr32/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,15 @@ struct pt_regs {
};

#ifdef __KERNEL__
# define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER)

#include <asm/ocd.h>

#define arch_ptrace_attach(child) ocd_enable(child)

#define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER)
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)

extern void show_regs (struct pt_regs *);

static __inline__ int valid_user_regs(struct pt_regs *regs)
Expand All @@ -141,9 +149,6 @@ static __inline__ int valid_user_regs(struct pt_regs *regs)
return 0;
}

#define instruction_pointer(regs) ((regs)->pc)

#define profile_pc(regs) instruction_pointer(regs)

#endif /* __KERNEL__ */

Expand Down
1 change: 1 addition & 0 deletions trunk/include/asm-avr32/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_MEMDIE 6
#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal */
#define TIF_CPU_GOING_TO_SLEEP 8 /* CPU is entering sleep 0 mode */
#define TIF_DEBUG 30 /* debugging enabled */
#define TIF_USERSPACE 31 /* true if FS sets userspace */

#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
Expand Down

0 comments on commit d664360

Please sign in to comment.