Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a2e117e authored by Paul Mundt's avatar Paul Mundt Committed by Paul Mundt
Browse files

sh: Add die chain notifiers.



Add the atomic die chains in, kprobes needs these.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 3dde7a3c
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -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>
@@ -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);
+17 −2
Original line number Diff line number Diff line
@@ -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)
{
+37 −2
Original line number Diff line number Diff line
@@ -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(&notify_page_fault_chain, nb);
}

int unregister_page_fault_notifier(struct notifier_block *nb)
{
	return atomic_notifier_chain_unregister(&notify_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(&notify_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 −0
Original line number Diff line number Diff line
#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 */
+3 −0
Original line number Diff line number Diff line
@@ -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)