sh: Add die chain notifiers.
Add the atomic die chains in, kprobes needs these. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
3dde7a3c74
commit
3a2e117e22
5 changed files with 104 additions and 7 deletions
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
|
||||
* Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
|
||||
* Copyright (C) 2002 - 2006 Paul Mundt
|
||||
* Copyright (C) 2002 - 2007 Paul Mundt
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
|
@ -15,6 +15,7 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/ubc.h>
|
||||
|
@ -299,8 +300,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
|
|||
ctrl_outl(0, UBC_BAMRA);
|
||||
|
||||
if (current_cpu_data.type == CPU_SH7729 ||
|
||||
current_cpu_data.type == CPU_SH7710 ||
|
||||
current_cpu_data.type == CPU_SH7712 ) {
|
||||
current_cpu_data.type == CPU_SH7710 ||
|
||||
current_cpu_data.type == CPU_SH7712) {
|
||||
ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
|
||||
ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
|
||||
} else {
|
||||
|
@ -496,6 +497,10 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
|
|||
/* Rewind */
|
||||
regs->pc -= 2;
|
||||
|
||||
if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
force_sig(SIGTRAP, current);
|
||||
}
|
||||
|
||||
|
@ -511,6 +516,10 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
|
|||
/* Rewind */
|
||||
regs->pc -= 2;
|
||||
|
||||
if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
if (__kernel_text_address(instruction_pointer(regs))) {
|
||||
u16 insn = *(u16 *)instruction_pointer(regs);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* SuperH version: Copyright (C) 1999 Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf
|
||||
* Copyright (C) 2000 David Howells
|
||||
* Copyright (C) 2002 - 2006 Paul Mundt
|
||||
* Copyright (C) 2002 - 2007 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -23,6 +23,7 @@
|
|||
#include <linux/limits.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/kdebug.h>
|
||||
|
||||
#ifdef CONFIG_SH_KGDB
|
||||
#include <asm/kgdb.h>
|
||||
|
@ -75,7 +76,21 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_SPINLOCK(die_lock);
|
||||
ATOMIC_NOTIFIER_HEAD(shdie_chain);
|
||||
|
||||
int register_die_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(&shdie_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(register_die_notifier);
|
||||
|
||||
int unregister_die_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_unregister(&shdie_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(unregister_die_notifier);
|
||||
|
||||
static DEFINE_SPINLOCK(die_lock);
|
||||
|
||||
void die(const char * str, struct pt_regs * regs, long err)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Page fault handler for SH with an MMU.
|
||||
*
|
||||
* Copyright (C) 1999 Niibe Yutaka
|
||||
* Copyright (C) 2003 Paul Mundt
|
||||
* Copyright (C) 2003 - 2007 Paul Mundt
|
||||
*
|
||||
* Based on linux/arch/i386/mm/fault.c:
|
||||
* Copyright (C) 1995 Linus Torvalds
|
||||
|
@ -15,12 +15,42 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/kgdb.h>
|
||||
|
||||
extern void die(const char *,struct pt_regs *,long);
|
||||
#ifdef CONFIG_KPROBES
|
||||
ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
|
||||
|
||||
/* Hook to register for page fault notifications */
|
||||
int register_page_fault_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(¬ify_page_fault_chain, nb);
|
||||
}
|
||||
|
||||
int unregister_page_fault_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb);
|
||||
}
|
||||
|
||||
static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
|
||||
int trap, int sig)
|
||||
{
|
||||
struct die_args args = {
|
||||
.regs = regs,
|
||||
.trapnr = trap,
|
||||
};
|
||||
return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args);
|
||||
}
|
||||
#else
|
||||
static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
|
||||
int trap, int sig)
|
||||
{
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine handles page faults. It determines the address,
|
||||
|
@ -39,6 +69,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
siginfo_t info;
|
||||
|
||||
trace_hardirqs_on();
|
||||
|
||||
if (notify_page_fault(DIE_PAGE_FAULT, regs,
|
||||
writeaccess, SIGSEGV) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
#ifdef CONFIG_SH_KGDB
|
||||
|
|
35
include/asm-sh/kdebug.h
Normal file
35
include/asm-sh/kdebug.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef __ASM_SH_KDEBUG_H
|
||||
#define __ASM_SH_KDEBUG_H
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
struct die_args {
|
||||
struct pt_regs *regs;
|
||||
int trapnr;
|
||||
};
|
||||
|
||||
int register_die_notifier(struct notifier_block *nb);
|
||||
int unregister_die_notifier(struct notifier_block *nb);
|
||||
int register_page_fault_notifier(struct notifier_block *nb);
|
||||
int unregister_page_fault_notifier(struct notifier_block *nb);
|
||||
extern struct atomic_notifier_head shdie_chain;
|
||||
|
||||
/* Grossly misnamed. */
|
||||
enum die_val {
|
||||
DIE_TRAP,
|
||||
DIE_PAGE_FAULT,
|
||||
};
|
||||
|
||||
static inline int notify_die(enum die_val val, struct pt_regs *regs,
|
||||
int trap, int sig)
|
||||
{
|
||||
struct die_args args = {
|
||||
.regs = regs,
|
||||
.trapnr = trap,
|
||||
};
|
||||
|
||||
return atomic_notifier_call_chain(&shdie_chain, val, &args);
|
||||
}
|
||||
#endif /* __ASM_SH_KDEBUG_H */
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/irqflags.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
/*
|
||||
* switch_to() should switch tasks to task nr n, first
|
||||
|
@ -255,6 +256,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
|
|||
(unsigned long)_n_, sizeof(*(ptr))); \
|
||||
})
|
||||
|
||||
extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
|
||||
|
||||
extern void *set_exception_table_vec(unsigned int vec, void *handler);
|
||||
|
||||
static inline void *set_exception_table_evt(unsigned int evt, void *handler)
|
||||
|
|
Loading…
Reference in a new issue