sh: Fix exception_handling_table alignment.
With the recent change ripping out interrupt_table, explicit padding of the table was missing, causing bad things to happen when manually inserting handlers in to the table. This problem particularly showed up in relation to do_fpu_state_restore() which was inserted quite deeply in to the table and ended up scribbling over a slab object. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
* The SH-3 exception vector table.
|
* The SH-3 exception vector table.
|
||||||
|
|
||||||
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
||||||
* Copyright (C) 2003 Paul Mundt
|
* Copyright (C) 2003 - 2006 Paul Mundt
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* 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
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
@@ -49,3 +49,10 @@ ENTRY(nmi_slot)
|
|||||||
#endif
|
#endif
|
||||||
ENTRY(user_break_point_trap)
|
ENTRY(user_break_point_trap)
|
||||||
.long break_point_trap /* 1E0 */
|
.long break_point_trap /* 1E0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pad the remainder of the table out, exceptions residing in far
|
||||||
|
* away offsets can be manually inserted in to their appropriate
|
||||||
|
* location via set_exception_table_{evt,vec}().
|
||||||
|
*/
|
||||||
|
.balign 4096,0,4096
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
* The SH-4 exception vector table.
|
* The SH-4 exception vector table.
|
||||||
|
|
||||||
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
||||||
* Copyright (C) 2003 Paul Mundt
|
* Copyright (C) 2003 - 2006 Paul Mundt
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* 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
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
@@ -53,3 +53,10 @@ ENTRY(nmi_slot)
|
|||||||
#endif
|
#endif
|
||||||
ENTRY(user_break_point_trap)
|
ENTRY(user_break_point_trap)
|
||||||
.long break_point_trap /* 1E0 */
|
.long break_point_trap /* 1E0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pad the remainder of the table out, exceptions residing in far
|
||||||
|
* away offsets can be manually inserted in to their appropriate
|
||||||
|
* location via set_exception_table_{evt,vec}().
|
||||||
|
*/
|
||||||
|
.balign 4096,0,4096
|
||||||
|
@@ -11,27 +11,15 @@
|
|||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/string.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/smp.h>
|
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/io.h>
|
|
||||||
#include <asm/atomic.h>
|
|
||||||
#include <asm/processor.h>
|
|
||||||
#include <asm/sections.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_SH_KGDB
|
#ifdef CONFIG_SH_KGDB
|
||||||
#include <asm/kgdb.h>
|
#include <asm/kgdb.h>
|
||||||
@@ -581,7 +569,10 @@ int is_dsp_inst(struct pt_regs *regs)
|
|||||||
#define is_dsp_inst(regs) (0)
|
#define is_dsp_inst(regs) (0)
|
||||||
#endif /* CONFIG_SH_DSP */
|
#endif /* CONFIG_SH_DSP */
|
||||||
|
|
||||||
extern int do_fpu_inst(unsigned short, struct pt_regs*);
|
/* arch/sh/kernel/cpu/sh4/fpu.c */
|
||||||
|
extern int do_fpu_inst(unsigned short, struct pt_regs *);
|
||||||
|
extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
|
||||||
|
unsigned long r6, unsigned long r7, struct pt_regs regs);
|
||||||
|
|
||||||
asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
|
asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
|
||||||
unsigned long r6, unsigned long r7,
|
unsigned long r6, unsigned long r7,
|
||||||
@@ -740,14 +731,20 @@ void __init per_cpu_trap_init(void)
|
|||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init trap_init(void)
|
void *set_exception_table_vec(unsigned int vec, void *handler)
|
||||||
{
|
{
|
||||||
extern void *exception_handling_table[];
|
extern void *exception_handling_table[];
|
||||||
|
void *old_handler;
|
||||||
|
|
||||||
|
old_handler = exception_handling_table[vec];
|
||||||
|
exception_handling_table[vec] = handler;
|
||||||
|
return old_handler;
|
||||||
|
}
|
||||||
|
|
||||||
exception_handling_table[TRAP_RESERVED_INST]
|
void __init trap_init(void)
|
||||||
= (void *)do_reserved_inst;
|
{
|
||||||
exception_handling_table[TRAP_ILLEGAL_SLOT_INST]
|
set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
|
||||||
= (void *)do_illegal_slot_inst;
|
set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst);
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
|
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
|
||||||
defined(CONFIG_SH_FPU_EMU)
|
defined(CONFIG_SH_FPU_EMU)
|
||||||
@@ -756,9 +753,11 @@ void __init trap_init(void)
|
|||||||
* reserved. They'll be handled in the math-emu case, or faulted on
|
* reserved. They'll be handled in the math-emu case, or faulted on
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
/* entry 64 corresponds to EXPEVT=0x800 */
|
set_exception_table_evt(0x800, do_reserved_inst);
|
||||||
exception_handling_table[64] = (void *)do_reserved_inst;
|
set_exception_table_evt(0x820, do_illegal_slot_inst);
|
||||||
exception_handling_table[65] = (void *)do_illegal_slot_inst;
|
#elif defined(CONFIG_SH_FPU)
|
||||||
|
set_exception_table_evt(0x800, do_fpu_state_restore);
|
||||||
|
set_exception_table_evt(0x820, do_fpu_state_restore);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Setup VBR for boot cpu */
|
/* Setup VBR for boot cpu */
|
||||||
|
@@ -353,6 +353,13 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
|
|||||||
(unsigned long)_n_, sizeof(*(ptr))); \
|
(unsigned long)_n_, sizeof(*(ptr))); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
extern void *set_exception_table_vec(unsigned int vec, void *handler);
|
||||||
|
|
||||||
|
static inline void *set_exception_table_evt(unsigned int evt, void *handler)
|
||||||
|
{
|
||||||
|
return set_exception_table_vec(evt >> 5, handler);
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX
|
/* XXX
|
||||||
* disable hlt during certain critical i/o operations
|
* disable hlt during certain critical i/o operations
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user