diff options
author | Paul Mundt <lethal@linux-sh.org> | 2006-10-19 03:20:25 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-10-19 03:30:32 -0400 |
commit | 1f666587dbf6bc660b23d8dd8abb6c572ce3eae5 (patch) | |
tree | 5fe9fc801e01a2feed7d1b7e65cafe6d4f23df84 | |
parent | 082c44d20eb4c6c4aa60ae7429ea184854cb0610 (diff) |
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>
-rw-r--r-- | arch/sh/kernel/cpu/sh3/ex.S | 9 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/ex.S | 9 | ||||
-rw-r--r-- | arch/sh/kernel/traps.c | 43 | ||||
-rw-r--r-- | include/asm-sh/system.h | 7 |
4 files changed, 44 insertions, 24 deletions
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index 6be46f0686b7..ba3082d640b5 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S | |||
@@ -4,7 +4,7 @@ | |||
4 | * The SH-3 exception vector table. | 4 | * The SH-3 exception vector table. |
5 | 5 | ||
6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
7 | * Copyright (C) 2003 Paul Mundt | 7 | * Copyright (C) 2003 - 2006 Paul Mundt |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
10 | * License. See the file "COPYING" in the main directory of this archive | 10 | * License. See the file "COPYING" in the main directory of this archive |
@@ -49,3 +49,10 @@ ENTRY(nmi_slot) | |||
49 | #endif | 49 | #endif |
50 | ENTRY(user_break_point_trap) | 50 | ENTRY(user_break_point_trap) |
51 | .long break_point_trap /* 1E0 */ | 51 | .long break_point_trap /* 1E0 */ |
52 | |||
53 | /* | ||
54 | * Pad the remainder of the table out, exceptions residing in far | ||
55 | * away offsets can be manually inserted in to their appropriate | ||
56 | * location via set_exception_table_{evt,vec}(). | ||
57 | */ | ||
58 | .balign 4096,0,4096 | ||
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S index 3f4cd043e900..ac8ab57413cc 100644 --- a/arch/sh/kernel/cpu/sh4/ex.S +++ b/arch/sh/kernel/cpu/sh4/ex.S | |||
@@ -4,7 +4,7 @@ | |||
4 | * The SH-4 exception vector table. | 4 | * The SH-4 exception vector table. |
5 | 5 | ||
6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 6 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
7 | * Copyright (C) 2003 Paul Mundt | 7 | * Copyright (C) 2003 - 2006 Paul Mundt |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
10 | * License. See the file "COPYING" in the main directory of this archive | 10 | * License. See the file "COPYING" in the main directory of this archive |
@@ -53,3 +53,10 @@ ENTRY(nmi_slot) | |||
53 | #endif | 53 | #endif |
54 | ENTRY(user_break_point_trap) | 54 | ENTRY(user_break_point_trap) |
55 | .long break_point_trap /* 1E0 */ | 55 | .long break_point_trap /* 1E0 */ |
56 | |||
57 | /* | ||
58 | * Pad the remainder of the table out, exceptions residing in far | ||
59 | * away offsets can be manually inserted in to their appropriate | ||
60 | * location via set_exception_table_{evt,vec}(). | ||
61 | */ | ||
62 | .balign 4096,0,4096 | ||
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index ffe127f09f3e..53dfa55f3156 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -11,27 +11,15 @@ | |||
11 | * License. See the file "COPYING" in the main directory of this archive | 11 | * License. See the file "COPYING" in the main directory of this archive |
12 | * for more details. | 12 | * for more details. |
13 | */ | 13 | */ |
14 | #include <linux/sched.h> | ||
15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
16 | #include <linux/string.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/ptrace.h> | 15 | #include <linux/ptrace.h> |
19 | #include <linux/timer.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/init.h> | 16 | #include <linux/init.h> |
24 | #include <linux/delay.h> | ||
25 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
26 | #include <linux/module.h> | 18 | #include <linux/module.h> |
27 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
28 | 20 | #include <linux/io.h> | |
29 | #include <asm/system.h> | 21 | #include <asm/system.h> |
30 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
31 | #include <asm/io.h> | ||
32 | #include <asm/atomic.h> | ||
33 | #include <asm/processor.h> | ||
34 | #include <asm/sections.h> | ||
35 | 23 | ||
36 | #ifdef CONFIG_SH_KGDB | 24 | #ifdef CONFIG_SH_KGDB |
37 | #include <asm/kgdb.h> | 25 | #include <asm/kgdb.h> |
@@ -581,7 +569,10 @@ int is_dsp_inst(struct pt_regs *regs) | |||
581 | #define is_dsp_inst(regs) (0) | 569 | #define is_dsp_inst(regs) (0) |
582 | #endif /* CONFIG_SH_DSP */ | 570 | #endif /* CONFIG_SH_DSP */ |
583 | 571 | ||
584 | extern int do_fpu_inst(unsigned short, struct pt_regs*); | 572 | /* arch/sh/kernel/cpu/sh4/fpu.c */ |
573 | extern int do_fpu_inst(unsigned short, struct pt_regs *); | ||
574 | extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, | ||
575 | unsigned long r6, unsigned long r7, struct pt_regs regs); | ||
585 | 576 | ||
586 | asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, | 577 | asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, |
587 | unsigned long r6, unsigned long r7, | 578 | unsigned long r6, unsigned long r7, |
@@ -740,14 +731,20 @@ void __init per_cpu_trap_init(void) | |||
740 | : "memory"); | 731 | : "memory"); |
741 | } | 732 | } |
742 | 733 | ||
743 | void __init trap_init(void) | 734 | void *set_exception_table_vec(unsigned int vec, void *handler) |
744 | { | 735 | { |
745 | extern void *exception_handling_table[]; | 736 | extern void *exception_handling_table[]; |
737 | void *old_handler; | ||
738 | |||
739 | old_handler = exception_handling_table[vec]; | ||
740 | exception_handling_table[vec] = handler; | ||
741 | return old_handler; | ||
742 | } | ||
746 | 743 | ||
747 | exception_handling_table[TRAP_RESERVED_INST] | 744 | void __init trap_init(void) |
748 | = (void *)do_reserved_inst; | 745 | { |
749 | exception_handling_table[TRAP_ILLEGAL_SLOT_INST] | 746 | set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); |
750 | = (void *)do_illegal_slot_inst; | 747 | set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst); |
751 | 748 | ||
752 | #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ | 749 | #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ |
753 | defined(CONFIG_SH_FPU_EMU) | 750 | defined(CONFIG_SH_FPU_EMU) |
@@ -756,9 +753,11 @@ void __init trap_init(void) | |||
756 | * reserved. They'll be handled in the math-emu case, or faulted on | 753 | * reserved. They'll be handled in the math-emu case, or faulted on |
757 | * otherwise. | 754 | * otherwise. |
758 | */ | 755 | */ |
759 | /* entry 64 corresponds to EXPEVT=0x800 */ | 756 | set_exception_table_evt(0x800, do_reserved_inst); |
760 | exception_handling_table[64] = (void *)do_reserved_inst; | 757 | set_exception_table_evt(0x820, do_illegal_slot_inst); |
761 | exception_handling_table[65] = (void *)do_illegal_slot_inst; | 758 | #elif defined(CONFIG_SH_FPU) |
759 | set_exception_table_evt(0x800, do_fpu_state_restore); | ||
760 | set_exception_table_evt(0x820, do_fpu_state_restore); | ||
762 | #endif | 761 | #endif |
763 | 762 | ||
764 | /* Setup VBR for boot cpu */ | 763 | /* Setup VBR for boot cpu */ |
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 6c1f8fde5ac4..3340126f4e0f 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h | |||
@@ -353,6 +353,13 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, | |||
353 | (unsigned long)_n_, sizeof(*(ptr))); \ | 353 | (unsigned long)_n_, sizeof(*(ptr))); \ |
354 | }) | 354 | }) |
355 | 355 | ||
356 | extern void *set_exception_table_vec(unsigned int vec, void *handler); | ||
357 | |||
358 | static inline void *set_exception_table_evt(unsigned int evt, void *handler) | ||
359 | { | ||
360 | return set_exception_table_vec(evt >> 5, handler); | ||
361 | } | ||
362 | |||
356 | /* XXX | 363 | /* XXX |
357 | * disable hlt during certain critical i/o operations | 364 | * disable hlt during certain critical i/o operations |
358 | */ | 365 | */ |