aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/Kconfig7
-rw-r--r--arch/sh/boards/mach-se/7343/irq.c35
-rw-r--r--arch/sh/boards/mach-se/7343/setup.c16
-rw-r--r--arch/sh/include/asm/Kbuild4
-rw-r--r--arch/sh/include/asm/alignment.h21
-rw-r--r--arch/sh/include/asm/atomic-grb.h46
-rw-r--r--arch/sh/include/asm/atomic-llsc.h27
-rw-r--r--arch/sh/include/asm/atomic.h73
-rw-r--r--arch/sh/include/asm/fpu.h35
-rw-r--r--arch/sh/include/asm/hw_breakpoint.h67
-rw-r--r--arch/sh/include/asm/kdebug.h2
-rw-r--r--arch/sh/include/asm/pgalloc.h32
-rw-r--r--arch/sh/include/asm/pgtable.h26
-rw-r--r--arch/sh/include/asm/pgtable_64.h11
-rw-r--r--arch/sh/include/asm/pgtable_nopmd.h22
-rw-r--r--arch/sh/include/asm/pgtable_pmd.h55
-rw-r--r--arch/sh/include/asm/processor_32.h37
-rw-r--r--arch/sh/include/asm/ptrace.h6
-rw-r--r--arch/sh/include/asm/setup.h1
-rw-r--r--arch/sh/include/asm/sh_bios.h15
-rw-r--r--arch/sh/include/asm/system.h4
-rw-r--r--arch/sh/include/asm/thread_info.h10
-rw-r--r--arch/sh/include/asm/ubc.h64
-rw-r--r--arch/sh/include/cpu-sh2/cpu/ubc.h32
-rw-r--r--arch/sh/include/cpu-sh3/cpu/ubc.h42
-rw-r--r--arch/sh/include/cpu-sh4/cpu/ubc.h64
-rw-r--r--arch/sh/include/mach-se/mach/se7343.h52
-rw-r--r--arch/sh/kernel/Makefile7
-rw-r--r--arch/sh/kernel/cpu/Makefile2
-rw-r--r--arch/sh/kernel/cpu/fpu.c82
-rw-r--r--arch/sh/kernel/cpu/init.c98
-rw-r--r--arch/sh/kernel/cpu/sh2a/fpu.c111
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S2
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c159
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile9
-rw-r--r--arch/sh/kernel/cpu/sh4a/ubc.c133
-rw-r--r--arch/sh/kernel/debugtraps.S1
-rw-r--r--arch/sh/kernel/early_printk.c85
-rw-r--r--arch/sh/kernel/head_64.S2
-rw-r--r--arch/sh/kernel/hw_breakpoint.c463
-rw-r--r--arch/sh/kernel/kgdb.c46
-rw-r--r--arch/sh/kernel/machine_kexec.c8
-rw-r--r--arch/sh/kernel/process.c100
-rw-r--r--arch/sh/kernel/process_32.c114
-rw-r--r--arch/sh/kernel/ptrace_32.c82
-rw-r--r--arch/sh/kernel/sh_bios.c129
-rw-r--r--arch/sh/kernel/signal_32.c4
-rw-r--r--arch/sh/kernel/traps_32.c182
-rw-r--r--arch/sh/math-emu/math.c12
-rw-r--r--arch/sh/mm/Kconfig20
-rw-r--r--arch/sh/mm/Makefile4
-rw-r--r--arch/sh/mm/alignment.c159
-rw-r--r--arch/sh/mm/cache-sh4.c13
-rw-r--r--arch/sh/mm/fault_32.c3
-rw-r--r--arch/sh/mm/init.c35
-rw-r--r--arch/sh/mm/nommu.c4
-rw-r--r--arch/sh/mm/pgtable.c57
57 files changed, 1761 insertions, 1171 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 2121fbb2ff4c..4eaf3401a15e 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -42,6 +42,8 @@ config SUPERH32
42 select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE 42 select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
43 select HAVE_FUNCTION_GRAPH_TRACER 43 select HAVE_FUNCTION_GRAPH_TRACER
44 select HAVE_ARCH_KGDB 44 select HAVE_ARCH_KGDB
45 select HAVE_HW_BREAKPOINT
46 select PERF_EVENTS if HAVE_HW_BREAKPOINT
45 select ARCH_HIBERNATION_POSSIBLE if MMU 47 select ARCH_HIBERNATION_POSSIBLE if MMU
46 48
47config SUPERH64 49config SUPERH64
@@ -726,8 +728,9 @@ config GUSA_RB
726 disabling interrupts around the atomic sequence. 728 disabling interrupts around the atomic sequence.
727 729
728config SPARSE_IRQ 730config SPARSE_IRQ
729 bool "Support sparse irq numbering" 731 def_bool y
730 depends on EXPERIMENTAL 732 depends on SUPERH32 && !SH_DREAMCAST && !SH_HIGHLANDER && \
733 !SH_RTS7751R2D && !HD64461 && !SH_7724_SOLUTION_ENGINE
731 help 734 help
732 This enables support for sparse irqs. This is useful in general 735 This enables support for sparse irqs. This is useful in general
733 as most CPUs have a fairly sparse array of IRQ vectors, which 736 as most CPUs have a fairly sparse array of IRQ vectors, which
diff --git a/arch/sh/boards/mach-se/7343/irq.c b/arch/sh/boards/mach-se/7343/irq.c
index 051c29d4eae0..c60fd13608d0 100644
--- a/arch/sh/boards/mach-se/7343/irq.c
+++ b/arch/sh/boards/mach-se/7343/irq.c
@@ -16,15 +16,17 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <mach-se/mach/se7343.h> 17#include <mach-se/mach/se7343.h>
18 18
19unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, };
20
19static void disable_se7343_irq(unsigned int irq) 21static void disable_se7343_irq(unsigned int irq)
20{ 22{
21 unsigned int bit = irq - SE7343_FPGA_IRQ_BASE; 23 unsigned int bit = (unsigned int)get_irq_chip_data(irq);
22 ctrl_outw(ctrl_inw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK); 24 ctrl_outw(ctrl_inw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK);
23} 25}
24 26
25static void enable_se7343_irq(unsigned int irq) 27static void enable_se7343_irq(unsigned int irq)
26{ 28{
27 unsigned int bit = irq - SE7343_FPGA_IRQ_BASE; 29 unsigned int bit = (unsigned int)get_irq_chip_data(irq);
28 ctrl_outw(ctrl_inw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK); 30 ctrl_outw(ctrl_inw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK);
29} 31}
30 32
@@ -38,18 +40,15 @@ static struct irq_chip se7343_irq_chip __read_mostly = {
38static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) 40static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
39{ 41{
40 unsigned short intv = ctrl_inw(PA_CPLD_ST); 42 unsigned short intv = ctrl_inw(PA_CPLD_ST);
41 struct irq_desc *ext_desc; 43 unsigned int ext_irq = 0;
42 unsigned int ext_irq = SE7343_FPGA_IRQ_BASE;
43 44
44 intv &= (1 << SE7343_FPGA_IRQ_NR) - 1; 45 intv &= (1 << SE7343_FPGA_IRQ_NR) - 1;
45 46
46 while (intv) { 47 for (; intv; intv >>= 1, ext_irq++) {
47 if (intv & 1) { 48 if (!(intv & 1))
48 ext_desc = irq_desc + ext_irq; 49 continue;
49 handle_level_irq(ext_irq, ext_desc); 50
50 } 51 generic_handle_irq(se7343_fpga_irq[ext_irq]);
51 intv >>= 1;
52 ext_irq++;
53 } 52 }
54} 53}
55 54
@@ -58,16 +57,24 @@ static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
58 */ 57 */
59void __init init_7343se_IRQ(void) 58void __init init_7343se_IRQ(void)
60{ 59{
61 int i; 60 int i, irq;
62 61
63 ctrl_outw(0, PA_CPLD_IMSK); /* disable all irqs */ 62 ctrl_outw(0, PA_CPLD_IMSK); /* disable all irqs */
64 ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */ 63 ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */
65 64
66 for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) 65 for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) {
67 set_irq_chip_and_handler_name(SE7343_FPGA_IRQ_BASE + i, 66 irq = create_irq();
67 if (irq < 0)
68 return;
69 se7343_fpga_irq[i] = irq;
70
71 set_irq_chip_and_handler_name(se7343_fpga_irq[i],
68 &se7343_irq_chip, 72 &se7343_irq_chip,
69 handle_level_irq, "level"); 73 handle_level_irq, "level");
70 74
75 set_irq_chip_data(se7343_fpga_irq[i], (void *)i);
76 }
77
71 set_irq_chained_handler(IRQ0_IRQ, se7343_irq_demux); 78 set_irq_chained_handler(IRQ0_IRQ, se7343_irq_demux);
72 set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); 79 set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
73 set_irq_chained_handler(IRQ1_IRQ, se7343_irq_demux); 80 set_irq_chained_handler(IRQ1_IRQ, se7343_irq_demux);
diff --git a/arch/sh/boards/mach-se/7343/setup.c b/arch/sh/boards/mach-se/7343/setup.c
index 4de56f35f419..292cc47d853f 100644
--- a/arch/sh/boards/mach-se/7343/setup.c
+++ b/arch/sh/boards/mach-se/7343/setup.c
@@ -82,7 +82,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
82 .mapbase = 0x16000000, 82 .mapbase = 0x16000000,
83 .regshift = 1, 83 .regshift = 1,
84 .flags = ST16C2550C_FLAGS, 84 .flags = ST16C2550C_FLAGS,
85 .irq = UARTA_IRQ,
86 .uartclk = 7372800, 85 .uartclk = 7372800,
87 }, 86 },
88 [1] = { 87 [1] = {
@@ -90,7 +89,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
90 .mapbase = 0x17000000, 89 .mapbase = 0x17000000,
91 .regshift = 1, 90 .regshift = 1,
92 .flags = ST16C2550C_FLAGS, 91 .flags = ST16C2550C_FLAGS,
93 .irq = UARTB_IRQ,
94 .uartclk = 7372800, 92 .uartclk = 7372800,
95 }, 93 },
96 { }, 94 { },
@@ -121,7 +119,7 @@ static struct resource usb_resources[] = {
121 .flags = IORESOURCE_MEM, 119 .flags = IORESOURCE_MEM,
122 }, 120 },
123 [2] = { 121 [2] = {
124 .start = USB_IRQ, 122 /* Filled in later */
125 .flags = IORESOURCE_IRQ, 123 .flags = IORESOURCE_IRQ,
126 }, 124 },
127}; 125};
@@ -138,8 +136,8 @@ static struct isp116x_platform_data usb_platform_data = {
138static struct platform_device usb_device = { 136static struct platform_device usb_device = {
139 .name = "isp116x-hcd", 137 .name = "isp116x-hcd",
140 .id = -1, 138 .id = -1,
141 .num_resources = ARRAY_SIZE(usb_resources), 139 .num_resources = ARRAY_SIZE(usb_resources),
142 .resource = usb_resources, 140 .resource = usb_resources,
143 .dev = { 141 .dev = {
144 .platform_data = &usb_platform_data, 142 .platform_data = &usb_platform_data,
145 }, 143 },
@@ -155,6 +153,13 @@ static struct platform_device *sh7343se_platform_devices[] __initdata = {
155 153
156static int __init sh7343se_devices_setup(void) 154static int __init sh7343se_devices_setup(void)
157{ 155{
156 /* Wire-up dynamic vectors */
157 serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA];
158 serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB];
159
160 usb_resources[2].start = usb_resources[2].end =
161 se7343_fpga_irq[SE7343_FPGA_IRQ_USB];
162
158 return platform_add_devices(sh7343se_platform_devices, 163 return platform_add_devices(sh7343se_platform_devices,
159 ARRAY_SIZE(sh7343se_platform_devices)); 164 ARRAY_SIZE(sh7343se_platform_devices));
160} 165}
@@ -179,6 +184,5 @@ static void __init sh7343se_setup(char **cmdline_p)
179static struct sh_machine_vector mv_7343se __initmv = { 184static struct sh_machine_vector mv_7343se __initmv = {
180 .mv_name = "SolutionEngine 7343", 185 .mv_name = "SolutionEngine 7343",
181 .mv_setup = sh7343se_setup, 186 .mv_setup = sh7343se_setup,
182 .mv_nr_irqs = SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_NR,
183 .mv_init_irq = init_7343se_IRQ, 187 .mv_init_irq = init_7343se_IRQ,
184}; 188};
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index e121c30f797d..46cb93477bcb 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -1,6 +1,8 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3header-y += cachectl.h cpu-features.h 3header-y += cachectl.h
4header-y += cpu-features.h
5header-y += hw_breakpoint.h
4 6
5unifdef-y += unistd_32.h 7unifdef-y += unistd_32.h
6unifdef-y += unistd_64.h 8unifdef-y += unistd_64.h
diff --git a/arch/sh/include/asm/alignment.h b/arch/sh/include/asm/alignment.h
new file mode 100644
index 000000000000..b12efecf5294
--- /dev/null
+++ b/arch/sh/include/asm/alignment.h
@@ -0,0 +1,21 @@
1#ifndef __ASM_SH_ALIGNMENT_H
2#define __ASM_SH_ALIGNMENT_H
3
4#include <linux/types.h>
5
6extern void inc_unaligned_byte_access(void);
7extern void inc_unaligned_word_access(void);
8extern void inc_unaligned_dword_access(void);
9extern void inc_unaligned_multi_access(void);
10extern void inc_unaligned_user_access(void);
11extern void inc_unaligned_kernel_access(void);
12
13#define UM_WARN (1 << 0)
14#define UM_FIXUP (1 << 1)
15#define UM_SIGNAL (1 << 2)
16
17extern unsigned int unaligned_user_action(void);
18
19extern void unaligned_fixups_notify(struct task_struct *, insn_size_t, struct pt_regs *);
20
21#endif /* __ASM_SH_ALIGNMENT_H */
diff --git a/arch/sh/include/asm/atomic-grb.h b/arch/sh/include/asm/atomic-grb.h
index 4c5b7dbfcedb..a273c88578fc 100644
--- a/arch/sh/include/asm/atomic-grb.h
+++ b/arch/sh/include/asm/atomic-grb.h
@@ -120,50 +120,4 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
120 : "memory" , "r0", "r1"); 120 : "memory" , "r0", "r1");
121} 121}
122 122
123static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
124{
125 int ret;
126
127 __asm__ __volatile__ (
128 " .align 2 \n\t"
129 " mova 1f, r0 \n\t"
130 " nop \n\t"
131 " mov r15, r1 \n\t"
132 " mov #-8, r15 \n\t"
133 " mov.l @%1, %0 \n\t"
134 " cmp/eq %2, %0 \n\t"
135 " bf 1f \n\t"
136 " mov.l %3, @%1 \n\t"
137 "1: mov r1, r15 \n\t"
138 : "=&r" (ret)
139 : "r" (v), "r" (old), "r" (new)
140 : "memory" , "r0", "r1" , "t");
141
142 return ret;
143}
144
145static inline int atomic_add_unless(atomic_t *v, int a, int u)
146{
147 int ret;
148 unsigned long tmp;
149
150 __asm__ __volatile__ (
151 " .align 2 \n\t"
152 " mova 1f, r0 \n\t"
153 " nop \n\t"
154 " mov r15, r1 \n\t"
155 " mov #-12, r15 \n\t"
156 " mov.l @%2, %1 \n\t"
157 " mov %1, %0 \n\t"
158 " cmp/eq %4, %0 \n\t"
159 " bt/s 1f \n\t"
160 " add %3, %1 \n\t"
161 " mov.l %1, @%2 \n\t"
162 "1: mov r1, r15 \n\t"
163 : "=&r" (ret), "=&r" (tmp)
164 : "r" (v), "r" (a), "r" (u)
165 : "memory" , "r0", "r1" , "t");
166
167 return ret != u;
168}
169#endif /* __ASM_SH_ATOMIC_GRB_H */ 123#endif /* __ASM_SH_ATOMIC_GRB_H */
diff --git a/arch/sh/include/asm/atomic-llsc.h b/arch/sh/include/asm/atomic-llsc.h
index b040e1e08610..4b00b78e3f4f 100644
--- a/arch/sh/include/asm/atomic-llsc.h
+++ b/arch/sh/include/asm/atomic-llsc.h
@@ -104,31 +104,4 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
104 : "t"); 104 : "t");
105} 105}
106 106
107#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
108
109/**
110 * atomic_add_unless - add unless the number is a given value
111 * @v: pointer of type atomic_t
112 * @a: the amount to add to v...
113 * @u: ...unless v is equal to u.
114 *
115 * Atomically adds @a to @v, so long as it was not @u.
116 * Returns non-zero if @v was not @u, and zero otherwise.
117 */
118static inline int atomic_add_unless(atomic_t *v, int a, int u)
119{
120 int c, old;
121 c = atomic_read(v);
122 for (;;) {
123 if (unlikely(c == (u)))
124 break;
125 old = atomic_cmpxchg((v), c, c + (a));
126 if (likely(old == c))
127 break;
128 c = old;
129 }
130
131 return c != (u);
132}
133
134#endif /* __ASM_SH_ATOMIC_LLSC_H */ 107#endif /* __ASM_SH_ATOMIC_LLSC_H */
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index b16388d71954..275a448ae8c2 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -25,58 +25,43 @@
25#endif 25#endif
26 26
27#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) 27#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
28#define atomic_dec_return(v) atomic_sub_return(1, (v))
29#define atomic_inc_return(v) atomic_add_return(1, (v))
30#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
31#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
32#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
33#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
28 34
29#define atomic_dec_return(v) atomic_sub_return(1,(v)) 35#define atomic_inc(v) atomic_add(1, (v))
30#define atomic_inc_return(v) atomic_add_return(1,(v)) 36#define atomic_dec(v) atomic_sub(1, (v))
31 37
32/* 38#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
33 * atomic_inc_and_test - increment and test 39#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
40
41/**
42 * atomic_add_unless - add unless the number is a given value
34 * @v: pointer of type atomic_t 43 * @v: pointer of type atomic_t
44 * @a: the amount to add to v...
45 * @u: ...unless v is equal to u.
35 * 46 *
36 * Atomically increments @v by 1 47 * Atomically adds @a to @v, so long as it was not @u.
37 * and returns true if the result is zero, or false for all 48 * Returns non-zero if @v was not @u, and zero otherwise.
38 * other cases.
39 */ 49 */
40#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
41
42#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
43#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
44
45#define atomic_inc(v) atomic_add(1,(v))
46#define atomic_dec(v) atomic_sub(1,(v))
47
48#if !defined(CONFIG_GUSA_RB) && !defined(CONFIG_CPU_SH4A)
49static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
50{
51 int ret;
52 unsigned long flags;
53
54 local_irq_save(flags);
55 ret = v->counter;
56 if (likely(ret == old))
57 v->counter = new;
58 local_irq_restore(flags);
59
60 return ret;
61}
62
63static inline int atomic_add_unless(atomic_t *v, int a, int u) 50static inline int atomic_add_unless(atomic_t *v, int a, int u)
64{ 51{
65 int ret; 52 int c, old;
66 unsigned long flags; 53 c = atomic_read(v);
67 54 for (;;) {
68 local_irq_save(flags); 55 if (unlikely(c == (u)))
69 ret = v->counter; 56 break;
70 if (ret != u) 57 old = atomic_cmpxchg((v), c, c + (a));
71 v->counter += a; 58 if (likely(old == c))
72 local_irq_restore(flags); 59 break;
73 60 c = old;
74 return ret != u; 61 }
62
63 return c != (u);
75} 64}
76#endif /* !CONFIG_GUSA_RB && !CONFIG_CPU_SH4A */
77
78#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
79#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
80 65
81#define smp_mb__before_atomic_dec() smp_mb() 66#define smp_mb__before_atomic_dec() smp_mb()
82#define smp_mb__after_atomic_dec() smp_mb() 67#define smp_mb__after_atomic_dec() smp_mb()
diff --git a/arch/sh/include/asm/fpu.h b/arch/sh/include/asm/fpu.h
index fb6bbb9b1cc8..06c4281aab65 100644
--- a/arch/sh/include/asm/fpu.h
+++ b/arch/sh/include/asm/fpu.h
@@ -2,8 +2,8 @@
2#define __ASM_SH_FPU_H 2#define __ASM_SH_FPU_H
3 3
4#ifndef __ASSEMBLY__ 4#ifndef __ASSEMBLY__
5#include <linux/preempt.h> 5
6#include <asm/ptrace.h> 6struct task_struct;
7 7
8#ifdef CONFIG_SH_FPU 8#ifdef CONFIG_SH_FPU
9static inline void release_fpu(struct pt_regs *regs) 9static inline void release_fpu(struct pt_regs *regs)
@@ -16,22 +16,23 @@ static inline void grab_fpu(struct pt_regs *regs)
16 regs->sr &= ~SR_FD; 16 regs->sr &= ~SR_FD;
17} 17}
18 18
19struct task_struct;
20
21extern void save_fpu(struct task_struct *__tsk); 19extern void save_fpu(struct task_struct *__tsk);
22void fpu_state_restore(struct pt_regs *regs); 20extern void restore_fpu(struct task_struct *__tsk);
21extern void fpu_state_restore(struct pt_regs *regs);
22extern void __fpu_state_restore(void);
23#else 23#else
24 24#define save_fpu(tsk) do { } while (0)
25#define save_fpu(tsk) do { } while (0) 25#define restore_fpu(tsk) do { } while (0)
26#define release_fpu(regs) do { } while (0) 26#define release_fpu(regs) do { } while (0)
27#define grab_fpu(regs) do { } while (0) 27#define grab_fpu(regs) do { } while (0)
28#define fpu_state_restore(regs) do { } while (0) 28#define fpu_state_restore(regs) do { } while (0)
29 29#define __fpu_state_restore(regs) do { } while (0)
30#endif 30#endif
31 31
32struct user_regset; 32struct user_regset;
33 33
34extern int do_fpu_inst(unsigned short, struct pt_regs *); 34extern int do_fpu_inst(unsigned short, struct pt_regs *);
35extern int init_fpu(struct task_struct *);
35 36
36extern int fpregs_get(struct task_struct *target, 37extern int fpregs_get(struct task_struct *target,
37 const struct user_regset *regset, 38 const struct user_regset *regset,
@@ -65,18 +66,6 @@ static inline void clear_fpu(struct task_struct *tsk, struct pt_regs *regs)
65 preempt_enable(); 66 preempt_enable();
66} 67}
67 68
68static inline int init_fpu(struct task_struct *tsk)
69{
70 if (tsk_used_math(tsk)) {
71 if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
72 unlazy_fpu(tsk, task_pt_regs(tsk));
73 return 0;
74 }
75
76 set_stopped_child_used_math(tsk);
77 return 0;
78}
79
80#endif /* __ASSEMBLY__ */ 69#endif /* __ASSEMBLY__ */
81 70
82#endif /* __ASM_SH_FPU_H */ 71#endif /* __ASM_SH_FPU_H */
diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h
new file mode 100644
index 000000000000..7295d6290249
--- /dev/null
+++ b/arch/sh/include/asm/hw_breakpoint.h
@@ -0,0 +1,67 @@
1#ifndef __ASM_SH_HW_BREAKPOINT_H
2#define __ASM_SH_HW_BREAKPOINT_H
3
4#include <linux/kdebug.h>
5#include <linux/types.h>
6
7#ifdef __KERNEL__
8#define __ARCH_HW_BREAKPOINT_H
9
10struct arch_hw_breakpoint {
11 char *name; /* Contains name of the symbol to set bkpt */
12 unsigned long address;
13 u16 len;
14 u16 type;
15};
16
17enum {
18 SH_BREAKPOINT_READ = (1 << 1),
19 SH_BREAKPOINT_WRITE = (1 << 2),
20 SH_BREAKPOINT_RW = SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
21
22 SH_BREAKPOINT_LEN_1 = (1 << 12),
23 SH_BREAKPOINT_LEN_2 = (1 << 13),
24 SH_BREAKPOINT_LEN_4 = SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
25 SH_BREAKPOINT_LEN_8 = (1 << 14),
26};
27
28struct sh_ubc {
29 const char *name;
30 unsigned int num_events;
31 unsigned int trap_nr;
32 void (*enable)(struct arch_hw_breakpoint *, int);
33 void (*disable)(struct arch_hw_breakpoint *, int);
34 void (*enable_all)(unsigned long);
35 void (*disable_all)(void);
36 unsigned long (*active_mask)(void);
37 unsigned long (*triggered_mask)(void);
38 void (*clear_triggered_mask)(unsigned long);
39 struct clk *clk; /* optional interface clock / MSTP bit */
40};
41
42struct perf_event;
43struct task_struct;
44struct pmu;
45
46/* Maximum number of UBC channels */
47#define HBP_NUM 2
48
49/* arch/sh/kernel/hw_breakpoint.c */
50extern int arch_check_va_in_userspace(unsigned long va, u16 hbp_len);
51extern int arch_validate_hwbkpt_settings(struct perf_event *bp,
52 struct task_struct *tsk);
53extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
54 unsigned long val, void *data);
55
56int arch_install_hw_breakpoint(struct perf_event *bp);
57void arch_uninstall_hw_breakpoint(struct perf_event *bp);
58void hw_breakpoint_pmu_read(struct perf_event *bp);
59void hw_breakpoint_pmu_unthrottle(struct perf_event *bp);
60
61extern void arch_fill_perf_breakpoint(struct perf_event *bp);
62extern int register_sh_ubc(struct sh_ubc *);
63
64extern struct pmu perf_ops_bp;
65
66#endif /* __KERNEL__ */
67#endif /* __ASM_SH_HW_BREAKPOINT_H */
diff --git a/arch/sh/include/asm/kdebug.h b/arch/sh/include/asm/kdebug.h
index 985219f9759e..5f6d2e9ccb7c 100644
--- a/arch/sh/include/asm/kdebug.h
+++ b/arch/sh/include/asm/kdebug.h
@@ -6,6 +6,8 @@ enum die_val {
6 DIE_TRAP, 6 DIE_TRAP,
7 DIE_NMI, 7 DIE_NMI,
8 DIE_OOPS, 8 DIE_OOPS,
9 DIE_BREAKPOINT,
10 DIE_SSTEP,
9}; 11};
10 12
11#endif /* __ASM_SH_KDEBUG_H */ 13#endif /* __ASM_SH_KDEBUG_H */
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h
index 63ca37bd9a95..f8982f4e0405 100644
--- a/arch/sh/include/asm/pgalloc.h
+++ b/arch/sh/include/asm/pgalloc.h
@@ -4,8 +4,16 @@
4#include <linux/quicklist.h> 4#include <linux/quicklist.h>
5#include <asm/page.h> 5#include <asm/page.h>
6 6
7#define QUICK_PGD 0 /* We preserve special mappings over free */ 7#define QUICK_PT 0 /* Other page table pages that are zero on free */
8#define QUICK_PT 1 /* Other page table pages that are zero on free */ 8
9extern pgd_t *pgd_alloc(struct mm_struct *);
10extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
11
12#ifdef CONFIG_PGTABLE_LEVELS_3
13extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
14extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
15extern void pmd_free(struct mm_struct *mm, pmd_t *pmd);
16#endif
9 17
10static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, 18static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
11 pte_t *pte) 19 pte_t *pte)
@@ -20,28 +28,9 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
20} 28}
21#define pmd_pgtable(pmd) pmd_page(pmd) 29#define pmd_pgtable(pmd) pmd_page(pmd)
22 30
23static inline void pgd_ctor(void *x)
24{
25 pgd_t *pgd = x;
26
27 memcpy(pgd + USER_PTRS_PER_PGD,
28 swapper_pg_dir + USER_PTRS_PER_PGD,
29 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
30}
31
32/* 31/*
33 * Allocate and free page tables. 32 * Allocate and free page tables.
34 */ 33 */
35static inline pgd_t *pgd_alloc(struct mm_struct *mm)
36{
37 return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
38}
39
40static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
41{
42 quicklist_free(QUICK_PGD, NULL, pgd);
43}
44
45static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 34static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
46 unsigned long address) 35 unsigned long address)
47{ 36{
@@ -81,7 +70,6 @@ do { \
81 70
82static inline void check_pgt_cache(void) 71static inline void check_pgt_cache(void)
83{ 72{
84 quicklist_trim(QUICK_PGD, NULL, 25, 16);
85 quicklist_trim(QUICK_PT, NULL, 25, 16); 73 quicklist_trim(QUICK_PT, NULL, 25, 16);
86} 74}
87 75
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index ba3046e4f06f..78598ec33d0a 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -12,7 +12,11 @@
12#ifndef __ASM_SH_PGTABLE_H 12#ifndef __ASM_SH_PGTABLE_H
13#define __ASM_SH_PGTABLE_H 13#define __ASM_SH_PGTABLE_H
14 14
15#include <asm-generic/pgtable-nopmd.h> 15#ifdef CONFIG_PGTABLE_LEVELS_3
16#include <asm/pgtable_pmd.h>
17#else
18#include <asm/pgtable_nopmd.h>
19#endif
16#include <asm/page.h> 20#include <asm/page.h>
17 21
18#ifndef __ASSEMBLY__ 22#ifndef __ASSEMBLY__
@@ -51,28 +55,12 @@ static inline unsigned long long neff_sign_extend(unsigned long val)
51#define NPHYS_SIGN (1LL << (NPHYS - 1)) 55#define NPHYS_SIGN (1LL << (NPHYS - 1))
52#define NPHYS_MASK (-1LL << NPHYS) 56#define NPHYS_MASK (-1LL << NPHYS)
53 57
54/*
55 * traditional two-level paging structure
56 */
57/* PTE bits */
58#if defined(CONFIG_X2TLB) || defined(CONFIG_SUPERH64)
59# define PTE_MAGNITUDE 3 /* 64-bit PTEs on extended mode SH-X2 TLB */
60#else
61# define PTE_MAGNITUDE 2 /* 32-bit PTEs */
62#endif
63#define PTE_SHIFT PAGE_SHIFT
64#define PTE_BITS (PTE_SHIFT - PTE_MAGNITUDE)
65
66/* PGD bits */
67#define PGDIR_SHIFT (PTE_SHIFT + PTE_BITS)
68#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 58#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
69#define PGDIR_MASK (~(PGDIR_SIZE-1)) 59#define PGDIR_MASK (~(PGDIR_SIZE-1))
70 60
71/* Entries per level */ 61/* Entries per level */
72#define PTRS_PER_PTE (PAGE_SIZE / (1 << PTE_MAGNITUDE)) 62#define PTRS_PER_PTE (PAGE_SIZE / (1 << PTE_MAGNITUDE))
73#define PTRS_PER_PGD (PAGE_SIZE / sizeof(pgd_t))
74 63
75#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
76#define FIRST_USER_ADDRESS 0 64#define FIRST_USER_ADDRESS 0
77 65
78#define PHYS_ADDR_MASK29 0x1fffffff 66#define PHYS_ADDR_MASK29 0x1fffffff
@@ -153,9 +141,9 @@ typedef pte_t *pte_addr_t;
153#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) 141#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
154 142
155/* 143/*
156 * No page table caches to initialise 144 * Initialise the page table caches
157 */ 145 */
158#define pgtable_cache_init() do { } while (0) 146extern void pgtable_cache_init(void);
159 147
160struct vm_area_struct; 148struct vm_area_struct;
161 149
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h
index 17cdbecc3adc..dd381588c695 100644
--- a/arch/sh/include/asm/pgtable_64.h
+++ b/arch/sh/include/asm/pgtable_64.h
@@ -43,11 +43,6 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
43} 43}
44#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) 44#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
45 45
46static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
47{
48 pmd_val(*pmdp) = (unsigned long) ptep;
49}
50
51/* 46/*
52 * PGD defines. Top level. 47 * PGD defines. Top level.
53 */ 48 */
@@ -203,12 +198,6 @@ static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
203#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) 198#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE)
204 199
205/* 200/*
206 * Handling allocation failures during page table setup.
207 */
208extern void __handle_bad_pmd_kernel(pmd_t * pmd);
209#define __handle_bad_pmd(x) __handle_bad_pmd_kernel(x)
210
211/*
212 * PTE level access routines. 201 * PTE level access routines.
213 * 202 *
214 * Note1: 203 * Note1:
diff --git a/arch/sh/include/asm/pgtable_nopmd.h b/arch/sh/include/asm/pgtable_nopmd.h
new file mode 100644
index 000000000000..f0b525b3cb4a
--- /dev/null
+++ b/arch/sh/include/asm/pgtable_nopmd.h
@@ -0,0 +1,22 @@
1#ifndef __ASM_SH_PGTABLE_NOPMD_H
2#define __ASM_SH_PGTABLE_NOPMD_H
3
4#include <asm-generic/pgtable-nopmd.h>
5
6/*
7 * traditional two-level paging structure
8 */
9
10/* PTE bits */
11#define PTE_MAGNITUDE 2 /* 32-bit PTEs */
12
13#define PTE_SHIFT PAGE_SHIFT
14#define PTE_BITS (PTE_SHIFT - PTE_MAGNITUDE)
15
16/* PGD bits */
17#define PGDIR_SHIFT (PTE_SHIFT + PTE_BITS)
18
19#define PTRS_PER_PGD (PAGE_SIZE / (1 << PTE_MAGNITUDE))
20#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
21
22#endif /* __ASM_SH_PGTABLE_NOPMD_H */
diff --git a/arch/sh/include/asm/pgtable_pmd.h b/arch/sh/include/asm/pgtable_pmd.h
new file mode 100644
index 000000000000..42a180e534a8
--- /dev/null
+++ b/arch/sh/include/asm/pgtable_pmd.h
@@ -0,0 +1,55 @@
1#ifndef __ASM_SH_PGTABLE_PMD_H
2#define __ASM_SH_PGTABLE_PMD_H
3
4#include <asm-generic/pgtable-nopud.h>
5
6/*
7 * Some cores need a 3-level page table layout, for example when using
8 * 64-bit PTEs and 4K pages.
9 */
10
11#define PTE_MAGNITUDE 3 /* 64-bit PTEs on extended mode SH-X2 TLB */
12
13/* PGD bits */
14#define PGDIR_SHIFT 30
15
16#define PTRS_PER_PGD 4
17#define USER_PTRS_PER_PGD 2
18
19/* PMD bits */
20#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTE_MAGNITUDE))
21#define PMD_SIZE (1UL << PMD_SHIFT)
22#define PMD_MASK (~(PMD_SIZE-1))
23
24#define PTRS_PER_PMD ((1 << PGDIR_SHIFT) / PMD_SIZE)
25
26#define pmd_ERROR(e) \
27 printk("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e))
28
29typedef struct { unsigned long long pmd; } pmd_t;
30#define pmd_val(x) ((x).pmd)
31#define __pmd(x) ((pmd_t) { (x) } )
32
33static inline unsigned long pud_page_vaddr(pud_t pud)
34{
35 return pud_val(pud);
36}
37
38#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
39static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
40{
41 return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
42}
43
44#define pud_none(x) (!pud_val(x))
45#define pud_present(x) (pud_val(x))
46#define pud_clear(xp) do { set_pud(xp, __pud(0)); } while (0)
47#define pud_bad(x) (pud_val(x) & ~PAGE_MASK)
48
49/*
50 * (puds are folded into pgds so this doesn't get actually called,
51 * but the define is needed for a generic inline function.)
52 */
53#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while(0)
54
55#endif /* __ASM_SH_PGTABLE_PMD_H */
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index 1f3d6fab660c..5fd83125fb89 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -14,6 +14,7 @@
14#include <asm/page.h> 14#include <asm/page.h>
15#include <asm/types.h> 15#include <asm/types.h>
16#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/hw_breakpoint.h>
17 18
18/* 19/*
19 * Default implementation of macro that returns current 20 * Default implementation of macro that returns current
@@ -90,48 +91,40 @@ struct sh_fpu_soft_struct {
90 unsigned long entry_pc; 91 unsigned long entry_pc;
91}; 92};
92 93
93union sh_fpu_union { 94union thread_xstate {
94 struct sh_fpu_hard_struct hard; 95 struct sh_fpu_hard_struct hardfpu;
95 struct sh_fpu_soft_struct soft; 96 struct sh_fpu_soft_struct softfpu;
96}; 97};
97 98
99extern unsigned int xstate_size;
100extern void free_thread_xstate(struct task_struct *);
101extern struct kmem_cache *task_xstate_cachep;
102
98struct thread_struct { 103struct thread_struct {
99 /* Saved registers when thread is descheduled */ 104 /* Saved registers when thread is descheduled */
100 unsigned long sp; 105 unsigned long sp;
101 unsigned long pc; 106 unsigned long pc;
102 107
103 /* Hardware debugging registers */ 108 /* Save middle states of ptrace breakpoints */
104 unsigned long ubc_pc; 109 struct perf_event *ptrace_bps[HBP_NUM];
105
106 /* floating point info */
107 union sh_fpu_union fpu;
108 110
109#ifdef CONFIG_SH_DSP 111#ifdef CONFIG_SH_DSP
110 /* Dsp status information */ 112 /* Dsp status information */
111 struct sh_dsp_struct dsp_status; 113 struct sh_dsp_struct dsp_status;
112#endif 114#endif
113};
114 115
115/* Count of active tasks with UBC settings */ 116 /* Extended processor state */
116extern int ubc_usercnt; 117 union thread_xstate *xstate;
118};
117 119
118#define INIT_THREAD { \ 120#define INIT_THREAD { \
119 .sp = sizeof(init_stack) + (long) &init_stack, \ 121 .sp = sizeof(init_stack) + (long) &init_stack, \
120} 122}
121 123
122/*
123 * Do necessary setup to start up a newly executed thread.
124 */
125#define start_thread(_regs, new_pc, new_sp) \
126 set_fs(USER_DS); \
127 _regs->pr = 0; \
128 _regs->sr = SR_FD; /* User mode. */ \
129 _regs->pc = new_pc; \
130 _regs->regs[15] = new_sp
131
132/* Forward declaration, a strange C thing */ 124/* Forward declaration, a strange C thing */
133struct task_struct; 125struct task_struct;
134struct mm_struct; 126
127extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp);
135 128
136/* Free all resources held by a thread. */ 129/* Free all resources held by a thread. */
137extern void release_thread(struct task_struct *); 130extern void release_thread(struct task_struct *);
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index 1dc12cb44a2d..201d11ef211f 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -124,6 +124,12 @@ struct task_struct;
124extern void user_enable_single_step(struct task_struct *); 124extern void user_enable_single_step(struct task_struct *);
125extern void user_disable_single_step(struct task_struct *); 125extern void user_disable_single_step(struct task_struct *);
126 126
127struct perf_event;
128struct perf_sample_data;
129
130extern void ptrace_triggered(struct perf_event *bp, int nmi,
131 struct perf_sample_data *data, struct pt_regs *regs);
132
127#define task_pt_regs(task) \ 133#define task_pt_regs(task) \
128 ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1) 134 ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1)
129 135
diff --git a/arch/sh/include/asm/setup.h b/arch/sh/include/asm/setup.h
index ce3743599b27..4758325bb24a 100644
--- a/arch/sh/include/asm/setup.h
+++ b/arch/sh/include/asm/setup.h
@@ -18,7 +18,6 @@
18/* ... */ 18/* ... */
19#define COMMAND_LINE ((char *) (PARAM+0x100)) 19#define COMMAND_LINE ((char *) (PARAM+0x100))
20 20
21int setup_early_printk(char *);
22void sh_mv_setup(void); 21void sh_mv_setup(void);
23 22
24#endif /* __KERNEL__ */ 23#endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/sh_bios.h b/arch/sh/include/asm/sh_bios.h
index d9c96d7cf6c7..95714c28422b 100644
--- a/arch/sh/include/asm/sh_bios.h
+++ b/arch/sh/include/asm/sh_bios.h
@@ -1,18 +1,27 @@
1#ifndef __ASM_SH_BIOS_H 1#ifndef __ASM_SH_BIOS_H
2#define __ASM_SH_BIOS_H 2#define __ASM_SH_BIOS_H
3 3
4#ifdef CONFIG_SH_STANDARD_BIOS
5
4/* 6/*
5 * Copyright (C) 2000 Greg Banks, Mitch Davis 7 * Copyright (C) 2000 Greg Banks, Mitch Davis
6 * C API to interface to the standard LinuxSH BIOS 8 * C API to interface to the standard LinuxSH BIOS
7 * usually from within the early stages of kernel boot. 9 * usually from within the early stages of kernel boot.
8 */ 10 */
9
10
11extern void sh_bios_console_write(const char *buf, unsigned int len); 11extern void sh_bios_console_write(const char *buf, unsigned int len);
12extern void sh_bios_char_out(char ch);
13extern void sh_bios_gdb_detach(void); 12extern void sh_bios_gdb_detach(void);
14 13
15extern void sh_bios_get_node_addr(unsigned char *node_addr); 14extern void sh_bios_get_node_addr(unsigned char *node_addr);
16extern void sh_bios_shutdown(unsigned int how); 15extern void sh_bios_shutdown(unsigned int how);
17 16
17extern void sh_bios_vbr_init(void);
18extern void sh_bios_vbr_reload(void);
19
20#else
21
22static inline void sh_bios_vbr_init(void) { }
23static inline void sh_bios_vbr_reload(void) { }
24
25#endif /* CONFIG_SH_STANDARD_BIOS */
26
18#endif /* __ASM_SH_BIOS_H */ 27#endif /* __ASM_SH_BIOS_H */
diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h
index c15415b4b169..62e4fc1e4409 100644
--- a/arch/sh/include/asm/system.h
+++ b/arch/sh/include/asm/system.h
@@ -32,7 +32,7 @@
32#define mb() __asm__ __volatile__ ("synco": : :"memory") 32#define mb() __asm__ __volatile__ ("synco": : :"memory")
33#define rmb() mb() 33#define rmb() mb()
34#define wmb() __asm__ __volatile__ ("synco": : :"memory") 34#define wmb() __asm__ __volatile__ ("synco": : :"memory")
35#define ctrl_barrier() __icbi(0xa8000000) 35#define ctrl_barrier() __icbi(PAGE_OFFSET)
36#define read_barrier_depends() do { } while(0) 36#define read_barrier_depends() do { } while(0)
37#else 37#else
38#define mb() __asm__ __volatile__ ("": : :"memory") 38#define mb() __asm__ __volatile__ ("": : :"memory")
@@ -144,8 +144,6 @@ void per_cpu_trap_init(void);
144void default_idle(void); 144void default_idle(void);
145void cpu_idle_wait(void); 145void cpu_idle_wait(void);
146 146
147asmlinkage void break_point_trap(void);
148
149#ifdef CONFIG_SUPERH32 147#ifdef CONFIG_SUPERH32
150#define BUILD_TRAP_HANDLER(name) \ 148#define BUILD_TRAP_HANDLER(name) \
151asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5, \ 149asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5, \
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index 1f3d927e2265..55a36fef6875 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -93,14 +93,16 @@ static inline struct thread_info *current_thread_info(void)
93 93
94#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) 94#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
95 95
96#else /* THREAD_SHIFT < PAGE_SHIFT */ 96#endif
97
98#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
99 97
100extern struct thread_info *alloc_thread_info(struct task_struct *tsk); 98extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
101extern void free_thread_info(struct thread_info *ti); 99extern void free_thread_info(struct thread_info *ti);
100extern void arch_task_cache_init(void);
101#define arch_task_cache_init arch_task_cache_init
102extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
103extern void init_thread_xstate(void);
102 104
103#endif /* THREAD_SHIFT < PAGE_SHIFT */ 105#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
104 106
105#endif /* __ASSEMBLY__ */ 107#endif /* __ASSEMBLY__ */
106 108
diff --git a/arch/sh/include/asm/ubc.h b/arch/sh/include/asm/ubc.h
deleted file mode 100644
index 9bf961684431..000000000000
--- a/arch/sh/include/asm/ubc.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * include/asm-sh/ubc.h
3 *
4 * Copyright (C) 1999 Niibe Yutaka
5 * Copyright (C) 2002, 2003 Paul Mundt
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11#ifndef __ASM_SH_UBC_H
12#define __ASM_SH_UBC_H
13#ifdef __KERNEL__
14
15#include <cpu/ubc.h>
16
17/* User Break Controller */
18#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
19#define UBC_TYPE_SH7729 (current_cpu_data.type == CPU_SH7729)
20#else
21#define UBC_TYPE_SH7729 0
22#endif
23
24#define BAMR_ASID (1 << 2)
25#define BAMR_NONE 0
26#define BAMR_10 0x1
27#define BAMR_12 0x2
28#define BAMR_ALL 0x3
29#define BAMR_16 0x8
30#define BAMR_20 0x9
31
32#define BBR_INST (1 << 4)
33#define BBR_DATA (2 << 4)
34#define BBR_READ (1 << 2)
35#define BBR_WRITE (2 << 2)
36#define BBR_BYTE 0x1
37#define BBR_HALF 0x2
38#define BBR_LONG 0x3
39#define BBR_QUAD (1 << 6) /* SH7750 */
40#define BBR_CPU (1 << 6) /* SH7709A,SH7729 */
41#define BBR_DMA (2 << 6) /* SH7709A,SH7729 */
42
43#define BRCR_CMFA (1 << 15)
44#define BRCR_CMFB (1 << 14)
45
46#if defined CONFIG_CPU_SH2A
47#define BRCR_CMFCA (1 << 15)
48#define BRCR_CMFCB (1 << 14)
49#define BRCR_CMFDA (1 << 13)
50#define BRCR_CMFDB (1 << 12)
51#define BRCR_PCBB (1 << 6) /* 1: after execution */
52#define BRCR_PCBA (1 << 5) /* 1: after execution */
53#define BRCR_PCTE 0
54#else
55#define BRCR_PCTE (1 << 11)
56#define BRCR_PCBA (1 << 10) /* 1: after execution */
57#define BRCR_DBEB (1 << 7)
58#define BRCR_PCBB (1 << 6)
59#define BRCR_SEQ (1 << 3)
60#define BRCR_UBDE (1 << 0)
61#endif
62
63#endif /* __KERNEL__ */
64#endif /* __ASM_SH_UBC_H */
diff --git a/arch/sh/include/cpu-sh2/cpu/ubc.h b/arch/sh/include/cpu-sh2/cpu/ubc.h
deleted file mode 100644
index ba0e87f19c7a..000000000000
--- a/arch/sh/include/cpu-sh2/cpu/ubc.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * include/asm-sh/cpu-sh2/ubc.h
3 *
4 * Copyright (C) 2003 Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#ifndef __ASM_CPU_SH2_UBC_H
11#define __ASM_CPU_SH2_UBC_H
12
13#define UBC_BARA 0xffffff40
14#define UBC_BAMRA 0xffffff44
15#define UBC_BBRA 0xffffff48
16#define UBC_BARB 0xffffff60
17#define UBC_BAMRB 0xffffff64
18#define UBC_BBRB 0xffffff68
19#define UBC_BDRB 0xffffff70
20#define UBC_BDMRB 0xffffff74
21#define UBC_BRCR 0xffffff78
22
23/*
24 * We don't have any ASID changes to make in the UBC on the SH-2.
25 *
26 * Make these purposely invalid to track misuse.
27 */
28#define UBC_BASRA 0x00000000
29#define UBC_BASRB 0x00000000
30
31#endif /* __ASM_CPU_SH2_UBC_H */
32
diff --git a/arch/sh/include/cpu-sh3/cpu/ubc.h b/arch/sh/include/cpu-sh3/cpu/ubc.h
deleted file mode 100644
index 4e6381d5ff7a..000000000000
--- a/arch/sh/include/cpu-sh3/cpu/ubc.h
+++ /dev/null
@@ -1,42 +0,0 @@
1/*
2 * include/asm-sh/cpu-sh3/ubc.h
3 *
4 * Copyright (C) 1999 Niibe Yutaka
5 * Copyright (C) 2003 Paul Mundt
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11#ifndef __ASM_CPU_SH3_UBC_H
12#define __ASM_CPU_SH3_UBC_H
13
14#if defined(CONFIG_CPU_SUBTYPE_SH7710) || \
15 defined(CONFIG_CPU_SUBTYPE_SH7720) || \
16 defined(CONFIG_CPU_SUBTYPE_SH7721)
17#define UBC_BARA 0xa4ffffb0
18#define UBC_BAMRA 0xa4ffffb4
19#define UBC_BBRA 0xa4ffffb8
20#define UBC_BASRA 0xffffffe4
21#define UBC_BARB 0xa4ffffa0
22#define UBC_BAMRB 0xa4ffffa4
23#define UBC_BBRB 0xa4ffffa8
24#define UBC_BASRB 0xffffffe8
25#define UBC_BDRB 0xa4ffff90
26#define UBC_BDMRB 0xa4ffff94
27#define UBC_BRCR 0xa4ffff98
28#else
29#define UBC_BARA 0xffffffb0
30#define UBC_BAMRA 0xffffffb4
31#define UBC_BBRA 0xffffffb8
32#define UBC_BASRA 0xffffffe4
33#define UBC_BARB 0xffffffa0
34#define UBC_BAMRB 0xffffffa4
35#define UBC_BBRB 0xffffffa8
36#define UBC_BASRB 0xffffffe8
37#define UBC_BDRB 0xffffff90
38#define UBC_BDMRB 0xffffff94
39#define UBC_BRCR 0xffffff98
40#endif
41
42#endif /* __ASM_CPU_SH3_UBC_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/ubc.h b/arch/sh/include/cpu-sh4/cpu/ubc.h
deleted file mode 100644
index c86e17050935..000000000000
--- a/arch/sh/include/cpu-sh4/cpu/ubc.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * include/asm-sh/cpu-sh4/ubc.h
3 *
4 * Copyright (C) 1999 Niibe Yutaka
5 * Copyright (C) 2003 Paul Mundt
6 * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#ifndef __ASM_CPU_SH4_UBC_H
13#define __ASM_CPU_SH4_UBC_H
14
15#if defined(CONFIG_CPU_SH4A)
16#define UBC_CBR0 0xff200000
17#define UBC_CRR0 0xff200004
18#define UBC_CAR0 0xff200008
19#define UBC_CAMR0 0xff20000c
20#define UBC_CBR1 0xff200020
21#define UBC_CRR1 0xff200024
22#define UBC_CAR1 0xff200028
23#define UBC_CAMR1 0xff20002c
24#define UBC_CDR1 0xff200030
25#define UBC_CDMR1 0xff200034
26#define UBC_CETR1 0xff200038
27#define UBC_CCMFR 0xff200600
28#define UBC_CBCR 0xff200620
29
30/* CBR */
31#define UBC_CBR_AIE (0x01<<30)
32#define UBC_CBR_ID_INST (0x01<<4)
33#define UBC_CBR_RW_READ (0x01<<1)
34#define UBC_CBR_CE (0x01)
35
36#define UBC_CBR_AIV_MASK (0x00FF0000)
37#define UBC_CBR_AIV_SHIFT (16)
38#define UBC_CBR_AIV_SET(asid) (((asid)<<UBC_CBR_AIV_SHIFT) & UBC_CBR_AIV_MASK)
39
40#define UBC_CBR_INIT 0x20000000
41
42/* CRR */
43#define UBC_CRR_RES (0x01<<13)
44#define UBC_CRR_PCB (0x01<<1)
45#define UBC_CRR_BIE (0x01)
46
47#define UBC_CRR_INIT 0x00002000
48
49#else /* CONFIG_CPU_SH4 */
50#define UBC_BARA 0xff200000
51#define UBC_BAMRA 0xff200004
52#define UBC_BBRA 0xff200008
53#define UBC_BASRA 0xff000014
54#define UBC_BARB 0xff20000c
55#define UBC_BAMRB 0xff200010
56#define UBC_BBRB 0xff200014
57#define UBC_BASRB 0xff000018
58#define UBC_BDRB 0xff200018
59#define UBC_BDMRB 0xff20001c
60#define UBC_BRCR 0xff200020
61#endif /* CONFIG_CPU_SH4 */
62
63#endif /* __ASM_CPU_SH4_UBC_H */
64
diff --git a/arch/sh/include/mach-se/mach/se7343.h b/arch/sh/include/mach-se/mach/se7343.h
index 749914b400fb..8d8170d6cc43 100644
--- a/arch/sh/include/mach-se/mach/se7343.h
+++ b/arch/sh/include/mach-se/mach/se7343.h
@@ -94,26 +94,26 @@
94 94
95#define PORT_DRVCR 0xA4050180 95#define PORT_DRVCR 0xA4050180
96 96
97#define PORT_PADR 0xA4050120 97#define PORT_PADR 0xA4050120
98#define PORT_PBDR 0xA4050122 98#define PORT_PBDR 0xA4050122
99#define PORT_PCDR 0xA4050124 99#define PORT_PCDR 0xA4050124
100#define PORT_PDDR 0xA4050126 100#define PORT_PDDR 0xA4050126
101#define PORT_PEDR 0xA4050128 101#define PORT_PEDR 0xA4050128
102#define PORT_PFDR 0xA405012A 102#define PORT_PFDR 0xA405012A
103#define PORT_PGDR 0xA405012C 103#define PORT_PGDR 0xA405012C
104#define PORT_PHDR 0xA405012E 104#define PORT_PHDR 0xA405012E
105#define PORT_PJDR 0xA4050130 105#define PORT_PJDR 0xA4050130
106#define PORT_PKDR 0xA4050132 106#define PORT_PKDR 0xA4050132
107#define PORT_PLDR 0xA4050134 107#define PORT_PLDR 0xA4050134
108#define PORT_PMDR 0xA4050136 108#define PORT_PMDR 0xA4050136
109#define PORT_PNDR 0xA4050138 109#define PORT_PNDR 0xA4050138
110#define PORT_PQDR 0xA405013A 110#define PORT_PQDR 0xA405013A
111#define PORT_PRDR 0xA405013C 111#define PORT_PRDR 0xA405013C
112#define PORT_PTDR 0xA4050160 112#define PORT_PTDR 0xA4050160
113#define PORT_PUDR 0xA4050162 113#define PORT_PUDR 0xA4050162
114#define PORT_PVDR 0xA4050164 114#define PORT_PVDR 0xA4050164
115#define PORT_PWDR 0xA4050166 115#define PORT_PWDR 0xA4050166
116#define PORT_PYDR 0xA4050168 116#define PORT_PYDR 0xA4050168
117 117
118#define FPGA_IN 0xb1400000 118#define FPGA_IN 0xb1400000
119#define FPGA_OUT 0xb1400002 119#define FPGA_OUT 0xb1400002
@@ -133,18 +133,10 @@
133#define SE7343_FPGA_IRQ_UARTB 11 133#define SE7343_FPGA_IRQ_UARTB 11
134 134
135#define SE7343_FPGA_IRQ_NR 12 135#define SE7343_FPGA_IRQ_NR 12
136#define SE7343_FPGA_IRQ_BASE 120
137
138#define MRSHPC_IRQ3 (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC3)
139#define MRSHPC_IRQ2 (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC2)
140#define MRSHPC_IRQ1 (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC1)
141#define MRSHPC_IRQ0 (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC0)
142#define SMC_IRQ (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_SMC)
143#define USB_IRQ (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_USB)
144#define UARTA_IRQ (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_UARTA)
145#define UARTB_IRQ (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_UARTB)
146 136
147/* arch/sh/boards/se/7343/irq.c */ 137/* arch/sh/boards/se/7343/irq.c */
138extern unsigned int se7343_fpga_irq[];
139
148void init_7343se_IRQ(void); 140void init_7343se_IRQ(void);
149 141
150#endif /* __ASM_SH_HITACHI_SE7343_H */ 142#endif /* __ASM_SH_HITACHI_SE7343_H */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 0d587da1ef12..56704a6d723a 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -13,8 +13,8 @@ CFLAGS_REMOVE_return_address.o = -pg
13 13
14obj-y := debugtraps.o dma-nommu.o dumpstack.o \ 14obj-y := debugtraps.o dma-nommu.o dumpstack.o \
15 idle.o io.o io_generic.o irq.o \ 15 idle.o io.o io_generic.o irq.o \
16 irq_$(BITS).o machvec.o nmi_debug.o process_$(BITS).o \ 16 irq_$(BITS).o machvec.o nmi_debug.o process.o \
17 ptrace_$(BITS).o return_address.o \ 17 process_$(BITS).o ptrace_$(BITS).o return_address.o \
18 setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ 18 setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \
19 syscalls_$(BITS).o time.o topology.o traps.o \ 19 syscalls_$(BITS).o time.o topology.o traps.o \
20 traps_$(BITS).o unwinder.o 20 traps_$(BITS).o unwinder.o
@@ -22,7 +22,7 @@ obj-y := debugtraps.o dma-nommu.o dumpstack.o \
22obj-y += cpu/ 22obj-y += cpu/
23obj-$(CONFIG_VSYSCALL) += vsyscall/ 23obj-$(CONFIG_VSYSCALL) += vsyscall/
24obj-$(CONFIG_SMP) += smp.o 24obj-$(CONFIG_SMP) += smp.o
25obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o early_printk.o 25obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
26obj-$(CONFIG_KGDB) += kgdb.o 26obj-$(CONFIG_KGDB) += kgdb.o
27obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o 27obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
28obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o 28obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o
@@ -39,6 +39,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp.o
39obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o 39obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
40obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o 40obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o
41 41
42obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
42obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o 43obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
43 44
44EXTRA_CFLAGS += -Werror 45EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index d97c803719ec..0e48bc61c272 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -17,5 +17,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/
17 17
18obj-$(CONFIG_SH_ADC) += adc.o 18obj-$(CONFIG_SH_ADC) += adc.o
19obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o 19obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
20obj-$(CONFIG_SH_FPU) += fpu.o
21obj-$(CONFIG_SH_FPU_EMU) += fpu.o
20 22
21obj-y += irq/ init.o clock.o hwblk.o 23obj-y += irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c
new file mode 100644
index 000000000000..c23e6727002a
--- /dev/null
+++ b/arch/sh/kernel/cpu/fpu.c
@@ -0,0 +1,82 @@
1#include <linux/sched.h>
2#include <asm/processor.h>
3#include <asm/fpu.h>
4
5int init_fpu(struct task_struct *tsk)
6{
7 if (tsk_used_math(tsk)) {
8 if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
9 unlazy_fpu(tsk, task_pt_regs(tsk));
10 return 0;
11 }
12
13 /*
14 * Memory allocation at the first usage of the FPU and other state.
15 */
16 if (!tsk->thread.xstate) {
17 tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
18 GFP_KERNEL);
19 if (!tsk->thread.xstate)
20 return -ENOMEM;
21 }
22
23 if (boot_cpu_data.flags & CPU_HAS_FPU) {
24 struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu;
25 memset(fp, 0, xstate_size);
26 fp->fpscr = FPSCR_INIT;
27 } else {
28 struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu;
29 memset(fp, 0, xstate_size);
30 fp->fpscr = FPSCR_INIT;
31 }
32
33 set_stopped_child_used_math(tsk);
34 return 0;
35}
36
37#ifdef CONFIG_SH_FPU
38void __fpu_state_restore(void)
39{
40 struct task_struct *tsk = current;
41
42 restore_fpu(tsk);
43
44 task_thread_info(tsk)->status |= TS_USEDFPU;
45 tsk->fpu_counter++;
46}
47
48void fpu_state_restore(struct pt_regs *regs)
49{
50 struct task_struct *tsk = current;
51
52 if (unlikely(!user_mode(regs))) {
53 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
54 BUG();
55 return;
56 }
57
58 if (!tsk_used_math(tsk)) {
59 /*
60 * does a slab alloc which can sleep
61 */
62 if (init_fpu(tsk)) {
63 /*
64 * ran out of memory!
65 */
66 do_group_exit(SIGKILL);
67 return;
68 }
69 }
70
71 grab_fpu(regs);
72
73 __fpu_state_restore();
74}
75
76BUILD_TRAP_HANDLER(fpu_state_restore)
77{
78 TRAP_HANDLER_DECL;
79
80 fpu_state_restore(regs);
81}
82#endif /* CONFIG_SH_FPU */
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 89b4b76c0d76..a5bb0550bbf3 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -24,22 +24,31 @@
24#include <asm/elf.h> 24#include <asm/elf.h>
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/smp.h> 26#include <asm/smp.h>
27#ifdef CONFIG_SUPERH32 27
28#include <asm/ubc.h> 28#ifdef CONFIG_SH_FPU
29#define cpu_has_fpu 1
30#else
31#define cpu_has_fpu 0
32#endif
33
34#ifdef CONFIG_SH_DSP
35#define cpu_has_dsp 1
36#else
37#define cpu_has_dsp 0
29#endif 38#endif
30 39
31/* 40/*
32 * Generic wrapper for command line arguments to disable on-chip 41 * Generic wrapper for command line arguments to disable on-chip
33 * peripherals (nofpu, nodsp, and so forth). 42 * peripherals (nofpu, nodsp, and so forth).
34 */ 43 */
35#define onchip_setup(x) \ 44#define onchip_setup(x) \
36static int x##_disabled __initdata = 0; \ 45static int x##_disabled __initdata = !cpu_has_##x; \
37 \ 46 \
38static int __init x##_setup(char *opts) \ 47static int __init x##_setup(char *opts) \
39{ \ 48{ \
40 x##_disabled = 1; \ 49 x##_disabled = 1; \
41 return 1; \ 50 return 1; \
42} \ 51} \
43__setup("no" __stringify(x), x##_setup); 52__setup("no" __stringify(x), x##_setup);
44 53
45onchip_setup(fpu); 54onchip_setup(fpu);
@@ -207,6 +216,18 @@ static void detect_cache_shape(void)
207 l2_cache_shape = -1; /* No S-cache */ 216 l2_cache_shape = -1; /* No S-cache */
208} 217}
209 218
219static void __init fpu_init(void)
220{
221 /* Disable the FPU */
222 if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) {
223 printk("FPU Disabled\n");
224 current_cpu_data.flags &= ~CPU_HAS_FPU;
225 }
226
227 disable_fpu();
228 clear_used_math();
229}
230
210#ifdef CONFIG_SH_DSP 231#ifdef CONFIG_SH_DSP
211static void __init release_dsp(void) 232static void __init release_dsp(void)
212{ 233{
@@ -244,28 +265,35 @@ static void __init dsp_init(void)
244 if (sr & SR_DSP) 265 if (sr & SR_DSP)
245 current_cpu_data.flags |= CPU_HAS_DSP; 266 current_cpu_data.flags |= CPU_HAS_DSP;
246 267
268 /* Disable the DSP */
269 if (dsp_disabled && (current_cpu_data.flags & CPU_HAS_DSP)) {
270 printk("DSP Disabled\n");
271 current_cpu_data.flags &= ~CPU_HAS_DSP;
272 }
273
247 /* Now that we've determined the DSP status, clear the DSP bit. */ 274 /* Now that we've determined the DSP status, clear the DSP bit. */
248 release_dsp(); 275 release_dsp();
249} 276}
277#else
278static inline void __init dsp_init(void) { }
250#endif /* CONFIG_SH_DSP */ 279#endif /* CONFIG_SH_DSP */
251 280
252/** 281/**
253 * sh_cpu_init 282 * sh_cpu_init
254 * 283 *
255 * This is our initial entry point for each CPU, and is invoked on the boot 284 * This is our initial entry point for each CPU, and is invoked on the
256 * CPU prior to calling start_kernel(). For SMP, a combination of this and 285 * boot CPU prior to calling start_kernel(). For SMP, a combination of
257 * start_secondary() will bring up each processor to a ready state prior 286 * this and start_secondary() will bring up each processor to a ready
258 * to hand forking the idle loop. 287 * state prior to hand forking the idle loop.
259 * 288 *
260 * We do all of the basic processor init here, including setting up the 289 * We do all of the basic processor init here, including setting up
261 * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is 290 * the caches, FPU, DSP, etc. By the time start_kernel() is hit (and
262 * hit (and subsequently platform_setup()) things like determining the 291 * subsequently platform_setup()) things like determining the CPU
263 * CPU subtype and initial configuration will all be done. 292 * subtype and initial configuration will all be done.
264 * 293 *
265 * Each processor family is still responsible for doing its own probing 294 * Each processor family is still responsible for doing its own probing
266 * and cache configuration in detect_cpu_and_cache_system(). 295 * and cache configuration in detect_cpu_and_cache_system().
267 */ 296 */
268
269asmlinkage void __init sh_cpu_init(void) 297asmlinkage void __init sh_cpu_init(void)
270{ 298{
271 current_thread_info()->cpu = hard_smp_processor_id(); 299 current_thread_info()->cpu = hard_smp_processor_id();
@@ -302,18 +330,8 @@ asmlinkage void __init sh_cpu_init(void)
302 detect_cache_shape(); 330 detect_cache_shape();
303 } 331 }
304 332
305 /* Disable the FPU */ 333 fpu_init();
306 if (fpu_disabled) { 334 dsp_init();
307 printk("FPU Disabled\n");
308 current_cpu_data.flags &= ~CPU_HAS_FPU;
309 }
310
311 /* FPU initialization */
312 disable_fpu();
313 if ((current_cpu_data.flags & CPU_HAS_FPU)) {
314 current_thread_info()->status &= ~TS_USEDFPU;
315 clear_used_math();
316 }
317 335
318 /* 336 /*
319 * Initialize the per-CPU ASID cache very early, since the 337 * Initialize the per-CPU ASID cache very early, since the
@@ -321,18 +339,12 @@ asmlinkage void __init sh_cpu_init(void)
321 */ 339 */
322 current_cpu_data.asid_cache = NO_CONTEXT; 340 current_cpu_data.asid_cache = NO_CONTEXT;
323 341
324#ifdef CONFIG_SH_DSP
325 /* Probe for DSP */
326 dsp_init();
327
328 /* Disable the DSP */
329 if (dsp_disabled) {
330 printk("DSP Disabled\n");
331 current_cpu_data.flags &= ~CPU_HAS_DSP;
332 release_dsp();
333 }
334#endif
335
336 speculative_execution_init(); 342 speculative_execution_init();
337 expmask_init(); 343 expmask_init();
344
345 /*
346 * Boot processor to setup the FP and extended state context info.
347 */
348 if (raw_smp_processor_id() == 0)
349 init_thread_xstate();
338} 350}
diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c
index d395ce5740e7..488d24e0cdf0 100644
--- a/arch/sh/kernel/cpu/sh2a/fpu.c
+++ b/arch/sh/kernel/cpu/sh2a/fpu.c
@@ -26,8 +26,7 @@
26/* 26/*
27 * Save FPU registers onto task structure. 27 * Save FPU registers onto task structure.
28 */ 28 */
29void 29void save_fpu(struct task_struct *tsk)
30save_fpu(struct task_struct *tsk)
31{ 30{
32 unsigned long dummy; 31 unsigned long dummy;
33 32
@@ -52,7 +51,7 @@ save_fpu(struct task_struct *tsk)
52 "fmov.s fr0, @-%0\n\t" 51 "fmov.s fr0, @-%0\n\t"
53 "lds %3, fpscr\n\t" 52 "lds %3, fpscr\n\t"
54 : "=r" (dummy) 53 : "=r" (dummy)
55 : "0" ((char *)(&tsk->thread.fpu.hard.status)), 54 : "0" ((char *)(&tsk->thread.xstate->hardfpu.status)),
56 "r" (FPSCR_RCHG), 55 "r" (FPSCR_RCHG),
57 "r" (FPSCR_INIT) 56 "r" (FPSCR_INIT)
58 : "memory"); 57 : "memory");
@@ -60,8 +59,7 @@ save_fpu(struct task_struct *tsk)
60 disable_fpu(); 59 disable_fpu();
61} 60}
62 61
63static void 62void restore_fpu(struct task_struct *tsk)
64restore_fpu(struct task_struct *tsk)
65{ 63{
66 unsigned long dummy; 64 unsigned long dummy;
67 65
@@ -85,45 +83,12 @@ restore_fpu(struct task_struct *tsk)
85 "lds.l @%0+, fpscr\n\t" 83 "lds.l @%0+, fpscr\n\t"
86 "lds.l @%0+, fpul\n\t" 84 "lds.l @%0+, fpul\n\t"
87 : "=r" (dummy) 85 : "=r" (dummy)
88 : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG) 86 : "0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
89 : "memory"); 87 : "memory");
90 disable_fpu(); 88 disable_fpu();
91} 89}
92 90
93/* 91/*
94 * Load the FPU with signalling NANS. This bit pattern we're using
95 * has the property that no matter wether considered as single or as
96 * double precission represents signaling NANS.
97 */
98
99static void
100fpu_init(void)
101{
102 enable_fpu();
103 asm volatile("lds %0, fpul\n\t"
104 "fsts fpul, fr0\n\t"
105 "fsts fpul, fr1\n\t"
106 "fsts fpul, fr2\n\t"
107 "fsts fpul, fr3\n\t"
108 "fsts fpul, fr4\n\t"
109 "fsts fpul, fr5\n\t"
110 "fsts fpul, fr6\n\t"
111 "fsts fpul, fr7\n\t"
112 "fsts fpul, fr8\n\t"
113 "fsts fpul, fr9\n\t"
114 "fsts fpul, fr10\n\t"
115 "fsts fpul, fr11\n\t"
116 "fsts fpul, fr12\n\t"
117 "fsts fpul, fr13\n\t"
118 "fsts fpul, fr14\n\t"
119 "fsts fpul, fr15\n\t"
120 "lds %2, fpscr\n\t"
121 : /* no output */
122 : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT));
123 disable_fpu();
124}
125
126/*
127 * Emulate arithmetic ops on denormalized number for some FPU insns. 92 * Emulate arithmetic ops on denormalized number for some FPU insns.
128 */ 93 */
129 94
@@ -490,9 +455,9 @@ ieee_fpe_handler (struct pt_regs *regs)
490 if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ 455 if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
491 struct task_struct *tsk = current; 456 struct task_struct *tsk = current;
492 457
493 if ((tsk->thread.fpu.hard.fpscr & FPSCR_FPU_ERROR)) { 458 if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_FPU_ERROR)) {
494 /* FPU error */ 459 /* FPU error */
495 denormal_to_double (&tsk->thread.fpu.hard, 460 denormal_to_double (&tsk->thread.xstate->hardfpu,
496 (finsn >> 8) & 0xf); 461 (finsn >> 8) & 0xf);
497 } else 462 } else
498 return 0; 463 return 0;
@@ -507,9 +472,9 @@ ieee_fpe_handler (struct pt_regs *regs)
507 472
508 n = (finsn >> 8) & 0xf; 473 n = (finsn >> 8) & 0xf;
509 m = (finsn >> 4) & 0xf; 474 m = (finsn >> 4) & 0xf;
510 hx = tsk->thread.fpu.hard.fp_regs[n]; 475 hx = tsk->thread.xstate->hardfpu.fp_regs[n];
511 hy = tsk->thread.fpu.hard.fp_regs[m]; 476 hy = tsk->thread.xstate->hardfpu.fp_regs[m];
512 fpscr = tsk->thread.fpu.hard.fpscr; 477 fpscr = tsk->thread.xstate->hardfpu.fpscr;
513 prec = fpscr & (1 << 19); 478 prec = fpscr & (1 << 19);
514 479
515 if ((fpscr & FPSCR_FPU_ERROR) 480 if ((fpscr & FPSCR_FPU_ERROR)
@@ -519,15 +484,15 @@ ieee_fpe_handler (struct pt_regs *regs)
519 484
520 /* FPU error because of denormal */ 485 /* FPU error because of denormal */
521 llx = ((long long) hx << 32) 486 llx = ((long long) hx << 32)
522 | tsk->thread.fpu.hard.fp_regs[n+1]; 487 | tsk->thread.xstate->hardfpu.fp_regs[n+1];
523 lly = ((long long) hy << 32) 488 lly = ((long long) hy << 32)
524 | tsk->thread.fpu.hard.fp_regs[m+1]; 489 | tsk->thread.xstate->hardfpu.fp_regs[m+1];
525 if ((hx & 0x7fffffff) >= 0x00100000) 490 if ((hx & 0x7fffffff) >= 0x00100000)
526 llx = denormal_muld(lly, llx); 491 llx = denormal_muld(lly, llx);
527 else 492 else
528 llx = denormal_muld(llx, lly); 493 llx = denormal_muld(llx, lly);
529 tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; 494 tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
530 tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff; 495 tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
531 } else if ((fpscr & FPSCR_FPU_ERROR) 496 } else if ((fpscr & FPSCR_FPU_ERROR)
532 && (!prec && ((hx & 0x7fffffff) < 0x00800000 497 && (!prec && ((hx & 0x7fffffff) < 0x00800000
533 || (hy & 0x7fffffff) < 0x00800000))) { 498 || (hy & 0x7fffffff) < 0x00800000))) {
@@ -536,7 +501,7 @@ ieee_fpe_handler (struct pt_regs *regs)
536 hx = denormal_mulf(hy, hx); 501 hx = denormal_mulf(hy, hx);
537 else 502 else
538 hx = denormal_mulf(hx, hy); 503 hx = denormal_mulf(hx, hy);
539 tsk->thread.fpu.hard.fp_regs[n] = hx; 504 tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
540 } else 505 } else
541 return 0; 506 return 0;
542 507
@@ -550,9 +515,9 @@ ieee_fpe_handler (struct pt_regs *regs)
550 515
551 n = (finsn >> 8) & 0xf; 516 n = (finsn >> 8) & 0xf;
552 m = (finsn >> 4) & 0xf; 517 m = (finsn >> 4) & 0xf;
553 hx = tsk->thread.fpu.hard.fp_regs[n]; 518 hx = tsk->thread.xstate->hardfpu.fp_regs[n];
554 hy = tsk->thread.fpu.hard.fp_regs[m]; 519 hy = tsk->thread.xstate->hardfpu.fp_regs[m];
555 fpscr = tsk->thread.fpu.hard.fpscr; 520 fpscr = tsk->thread.xstate->hardfpu.fpscr;
556 prec = fpscr & (1 << 19); 521 prec = fpscr & (1 << 19);
557 522
558 if ((fpscr & FPSCR_FPU_ERROR) 523 if ((fpscr & FPSCR_FPU_ERROR)
@@ -562,15 +527,15 @@ ieee_fpe_handler (struct pt_regs *regs)
562 527
563 /* FPU error because of denormal */ 528 /* FPU error because of denormal */
564 llx = ((long long) hx << 32) 529 llx = ((long long) hx << 32)
565 | tsk->thread.fpu.hard.fp_regs[n+1]; 530 | tsk->thread.xstate->hardfpu.fp_regs[n+1];
566 lly = ((long long) hy << 32) 531 lly = ((long long) hy << 32)
567 | tsk->thread.fpu.hard.fp_regs[m+1]; 532 | tsk->thread.xstate->hardfpu.fp_regs[m+1];
568 if ((finsn & 0xf00f) == 0xf000) 533 if ((finsn & 0xf00f) == 0xf000)
569 llx = denormal_addd(llx, lly); 534 llx = denormal_addd(llx, lly);
570 else 535 else
571 llx = denormal_addd(llx, lly ^ (1LL << 63)); 536 llx = denormal_addd(llx, lly ^ (1LL << 63));
572 tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; 537 tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
573 tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff; 538 tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
574 } else if ((fpscr & FPSCR_FPU_ERROR) 539 } else if ((fpscr & FPSCR_FPU_ERROR)
575 && (!prec && ((hx & 0x7fffffff) < 0x00800000 540 && (!prec && ((hx & 0x7fffffff) < 0x00800000
576 || (hy & 0x7fffffff) < 0x00800000))) { 541 || (hy & 0x7fffffff) < 0x00800000))) {
@@ -579,7 +544,7 @@ ieee_fpe_handler (struct pt_regs *regs)
579 hx = denormal_addf(hx, hy); 544 hx = denormal_addf(hx, hy);
580 else 545 else
581 hx = denormal_addf(hx, hy ^ 0x80000000); 546 hx = denormal_addf(hx, hy ^ 0x80000000);
582 tsk->thread.fpu.hard.fp_regs[n] = hx; 547 tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
583 } else 548 } else
584 return 0; 549 return 0;
585 550
@@ -597,7 +562,7 @@ BUILD_TRAP_HANDLER(fpu_error)
597 562
598 __unlazy_fpu(tsk, regs); 563 __unlazy_fpu(tsk, regs);
599 if (ieee_fpe_handler(regs)) { 564 if (ieee_fpe_handler(regs)) {
600 tsk->thread.fpu.hard.fpscr &= 565 tsk->thread.xstate->hardfpu.fpscr &=
601 ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); 566 ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
602 grab_fpu(regs); 567 grab_fpu(regs);
603 restore_fpu(tsk); 568 restore_fpu(tsk);
@@ -607,33 +572,3 @@ BUILD_TRAP_HANDLER(fpu_error)
607 572
608 force_sig(SIGFPE, tsk); 573 force_sig(SIGFPE, tsk);
609} 574}
610
611void fpu_state_restore(struct pt_regs *regs)
612{
613 struct task_struct *tsk = current;
614
615 grab_fpu(regs);
616 if (unlikely(!user_mode(regs))) {
617 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
618 BUG();
619 return;
620 }
621
622 if (likely(used_math())) {
623 /* Using the FPU again. */
624 restore_fpu(tsk);
625 } else {
626 /* First time FPU user. */
627 fpu_init();
628 set_used_math();
629 }
630 task_thread_info(tsk)->status |= TS_USEDFPU;
631 tsk->fpu_counter++;
632}
633
634BUILD_TRAP_HANDLER(fpu_state_restore)
635{
636 TRAP_HANDLER_DECL;
637
638 fpu_state_restore(regs);
639}
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index 46610c35c232..99b4d020179a 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -49,7 +49,7 @@ ENTRY(exception_handling_table)
49 .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ 49 .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
50 .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ 50 .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
51 .long nmi_trap_handler /* 1C0 */ ! Allow trap to debugger 51 .long nmi_trap_handler /* 1C0 */ ! Allow trap to debugger
52 .long break_point_trap /* 1E0 */ 52 .long breakpoint_trap_handler /* 1E0 */
53 53
54 /* 54 /*
55 * Pad the remainder of the table out, exceptions residing in far 55 * Pad the remainder of the table out, exceptions residing in far
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index e97857aec8a0..447482d7f65e 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -85,14 +85,14 @@ void save_fpu(struct task_struct *tsk)
85 "fmov.s fr1, @-%0\n\t" 85 "fmov.s fr1, @-%0\n\t"
86 "fmov.s fr0, @-%0\n\t" 86 "fmov.s fr0, @-%0\n\t"
87 "lds %3, fpscr\n\t":"=r" (dummy) 87 "lds %3, fpscr\n\t":"=r" (dummy)
88 :"0"((char *)(&tsk->thread.fpu.hard.status)), 88 :"0"((char *)(&tsk->thread.xstate->hardfpu.status)),
89 "r"(FPSCR_RCHG), "r"(FPSCR_INIT) 89 "r"(FPSCR_RCHG), "r"(FPSCR_INIT)
90 :"memory"); 90 :"memory");
91 91
92 disable_fpu(); 92 disable_fpu();
93} 93}
94 94
95static void restore_fpu(struct task_struct *tsk) 95void restore_fpu(struct task_struct *tsk)
96{ 96{
97 unsigned long dummy; 97 unsigned long dummy;
98 98
@@ -135,62 +135,11 @@ static void restore_fpu(struct task_struct *tsk)
135 "lds.l @%0+, fpscr\n\t" 135 "lds.l @%0+, fpscr\n\t"
136 "lds.l @%0+, fpul\n\t" 136 "lds.l @%0+, fpul\n\t"
137 :"=r" (dummy) 137 :"=r" (dummy)
138 :"0"(&tsk->thread.fpu), "r"(FPSCR_RCHG) 138 :"0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
139 :"memory"); 139 :"memory");
140 disable_fpu(); 140 disable_fpu();
141} 141}
142 142
143/*
144 * Load the FPU with signalling NANS. This bit pattern we're using
145 * has the property that no matter wether considered as single or as
146 * double precision represents signaling NANS.
147 */
148
149static void fpu_init(void)
150{
151 enable_fpu();
152 asm volatile ( "lds %0, fpul\n\t"
153 "lds %1, fpscr\n\t"
154 "fsts fpul, fr0\n\t"
155 "fsts fpul, fr1\n\t"
156 "fsts fpul, fr2\n\t"
157 "fsts fpul, fr3\n\t"
158 "fsts fpul, fr4\n\t"
159 "fsts fpul, fr5\n\t"
160 "fsts fpul, fr6\n\t"
161 "fsts fpul, fr7\n\t"
162 "fsts fpul, fr8\n\t"
163 "fsts fpul, fr9\n\t"
164 "fsts fpul, fr10\n\t"
165 "fsts fpul, fr11\n\t"
166 "fsts fpul, fr12\n\t"
167 "fsts fpul, fr13\n\t"
168 "fsts fpul, fr14\n\t"
169 "fsts fpul, fr15\n\t"
170 "frchg\n\t"
171 "fsts fpul, fr0\n\t"
172 "fsts fpul, fr1\n\t"
173 "fsts fpul, fr2\n\t"
174 "fsts fpul, fr3\n\t"
175 "fsts fpul, fr4\n\t"
176 "fsts fpul, fr5\n\t"
177 "fsts fpul, fr6\n\t"
178 "fsts fpul, fr7\n\t"
179 "fsts fpul, fr8\n\t"
180 "fsts fpul, fr9\n\t"
181 "fsts fpul, fr10\n\t"
182 "fsts fpul, fr11\n\t"
183 "fsts fpul, fr12\n\t"
184 "fsts fpul, fr13\n\t"
185 "fsts fpul, fr14\n\t"
186 "fsts fpul, fr15\n\t"
187 "frchg\n\t"
188 "lds %2, fpscr\n\t"
189 : /* no output */
190 :"r" (0), "r"(FPSCR_RCHG), "r"(FPSCR_INIT));
191 disable_fpu();
192}
193
194/** 143/**
195 * denormal_to_double - Given denormalized float number, 144 * denormal_to_double - Given denormalized float number,
196 * store double float 145 * store double float
@@ -282,9 +231,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
282 /* fcnvsd */ 231 /* fcnvsd */
283 struct task_struct *tsk = current; 232 struct task_struct *tsk = current;
284 233
285 if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)) 234 if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR))
286 /* FPU error */ 235 /* FPU error */
287 denormal_to_double(&tsk->thread.fpu.hard, 236 denormal_to_double(&tsk->thread.xstate->hardfpu,
288 (finsn >> 8) & 0xf); 237 (finsn >> 8) & 0xf);
289 else 238 else
290 return 0; 239 return 0;
@@ -300,9 +249,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
300 249
301 n = (finsn >> 8) & 0xf; 250 n = (finsn >> 8) & 0xf;
302 m = (finsn >> 4) & 0xf; 251 m = (finsn >> 4) & 0xf;
303 hx = tsk->thread.fpu.hard.fp_regs[n]; 252 hx = tsk->thread.xstate->hardfpu.fp_regs[n];
304 hy = tsk->thread.fpu.hard.fp_regs[m]; 253 hy = tsk->thread.xstate->hardfpu.fp_regs[m];
305 fpscr = tsk->thread.fpu.hard.fpscr; 254 fpscr = tsk->thread.xstate->hardfpu.fpscr;
306 prec = fpscr & FPSCR_DBL_PRECISION; 255 prec = fpscr & FPSCR_DBL_PRECISION;
307 256
308 if ((fpscr & FPSCR_CAUSE_ERROR) 257 if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -312,18 +261,18 @@ static int ieee_fpe_handler(struct pt_regs *regs)
312 261
313 /* FPU error because of denormal (doubles) */ 262 /* FPU error because of denormal (doubles) */
314 llx = ((long long)hx << 32) 263 llx = ((long long)hx << 32)
315 | tsk->thread.fpu.hard.fp_regs[n + 1]; 264 | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
316 lly = ((long long)hy << 32) 265 lly = ((long long)hy << 32)
317 | tsk->thread.fpu.hard.fp_regs[m + 1]; 266 | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
318 llx = float64_mul(llx, lly); 267 llx = float64_mul(llx, lly);
319 tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; 268 tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
320 tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; 269 tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
321 } else if ((fpscr & FPSCR_CAUSE_ERROR) 270 } else if ((fpscr & FPSCR_CAUSE_ERROR)
322 && (!prec && ((hx & 0x7fffffff) < 0x00800000 271 && (!prec && ((hx & 0x7fffffff) < 0x00800000
323 || (hy & 0x7fffffff) < 0x00800000))) { 272 || (hy & 0x7fffffff) < 0x00800000))) {
324 /* FPU error because of denormal (floats) */ 273 /* FPU error because of denormal (floats) */
325 hx = float32_mul(hx, hy); 274 hx = float32_mul(hx, hy);
326 tsk->thread.fpu.hard.fp_regs[n] = hx; 275 tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
327 } else 276 } else
328 return 0; 277 return 0;
329 278
@@ -338,9 +287,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
338 287
339 n = (finsn >> 8) & 0xf; 288 n = (finsn >> 8) & 0xf;
340 m = (finsn >> 4) & 0xf; 289 m = (finsn >> 4) & 0xf;
341 hx = tsk->thread.fpu.hard.fp_regs[n]; 290 hx = tsk->thread.xstate->hardfpu.fp_regs[n];
342 hy = tsk->thread.fpu.hard.fp_regs[m]; 291 hy = tsk->thread.xstate->hardfpu.fp_regs[m];
343 fpscr = tsk->thread.fpu.hard.fpscr; 292 fpscr = tsk->thread.xstate->hardfpu.fpscr;
344 prec = fpscr & FPSCR_DBL_PRECISION; 293 prec = fpscr & FPSCR_DBL_PRECISION;
345 294
346 if ((fpscr & FPSCR_CAUSE_ERROR) 295 if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -350,15 +299,15 @@ static int ieee_fpe_handler(struct pt_regs *regs)
350 299
351 /* FPU error because of denormal (doubles) */ 300 /* FPU error because of denormal (doubles) */
352 llx = ((long long)hx << 32) 301 llx = ((long long)hx << 32)
353 | tsk->thread.fpu.hard.fp_regs[n + 1]; 302 | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
354 lly = ((long long)hy << 32) 303 lly = ((long long)hy << 32)
355 | tsk->thread.fpu.hard.fp_regs[m + 1]; 304 | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
356 if ((finsn & 0xf00f) == 0xf000) 305 if ((finsn & 0xf00f) == 0xf000)
357 llx = float64_add(llx, lly); 306 llx = float64_add(llx, lly);
358 else 307 else
359 llx = float64_sub(llx, lly); 308 llx = float64_sub(llx, lly);
360 tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; 309 tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
361 tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; 310 tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
362 } else if ((fpscr & FPSCR_CAUSE_ERROR) 311 } else if ((fpscr & FPSCR_CAUSE_ERROR)
363 && (!prec && ((hx & 0x7fffffff) < 0x00800000 312 && (!prec && ((hx & 0x7fffffff) < 0x00800000
364 || (hy & 0x7fffffff) < 0x00800000))) { 313 || (hy & 0x7fffffff) < 0x00800000))) {
@@ -367,7 +316,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
367 hx = float32_add(hx, hy); 316 hx = float32_add(hx, hy);
368 else 317 else
369 hx = float32_sub(hx, hy); 318 hx = float32_sub(hx, hy);
370 tsk->thread.fpu.hard.fp_regs[n] = hx; 319 tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
371 } else 320 } else
372 return 0; 321 return 0;
373 322
@@ -382,9 +331,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
382 331
383 n = (finsn >> 8) & 0xf; 332 n = (finsn >> 8) & 0xf;
384 m = (finsn >> 4) & 0xf; 333 m = (finsn >> 4) & 0xf;
385 hx = tsk->thread.fpu.hard.fp_regs[n]; 334 hx = tsk->thread.xstate->hardfpu.fp_regs[n];
386 hy = tsk->thread.fpu.hard.fp_regs[m]; 335 hy = tsk->thread.xstate->hardfpu.fp_regs[m];
387 fpscr = tsk->thread.fpu.hard.fpscr; 336 fpscr = tsk->thread.xstate->hardfpu.fpscr;
388 prec = fpscr & FPSCR_DBL_PRECISION; 337 prec = fpscr & FPSCR_DBL_PRECISION;
389 338
390 if ((fpscr & FPSCR_CAUSE_ERROR) 339 if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -394,20 +343,20 @@ static int ieee_fpe_handler(struct pt_regs *regs)
394 343
395 /* FPU error because of denormal (doubles) */ 344 /* FPU error because of denormal (doubles) */
396 llx = ((long long)hx << 32) 345 llx = ((long long)hx << 32)
397 | tsk->thread.fpu.hard.fp_regs[n + 1]; 346 | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
398 lly = ((long long)hy << 32) 347 lly = ((long long)hy << 32)
399 | tsk->thread.fpu.hard.fp_regs[m + 1]; 348 | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
400 349
401 llx = float64_div(llx, lly); 350 llx = float64_div(llx, lly);
402 351
403 tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; 352 tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
404 tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; 353 tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
405 } else if ((fpscr & FPSCR_CAUSE_ERROR) 354 } else if ((fpscr & FPSCR_CAUSE_ERROR)
406 && (!prec && ((hx & 0x7fffffff) < 0x00800000 355 && (!prec && ((hx & 0x7fffffff) < 0x00800000
407 || (hy & 0x7fffffff) < 0x00800000))) { 356 || (hy & 0x7fffffff) < 0x00800000))) {
408 /* FPU error because of denormal (floats) */ 357 /* FPU error because of denormal (floats) */
409 hx = float32_div(hx, hy); 358 hx = float32_div(hx, hy);
410 tsk->thread.fpu.hard.fp_regs[n] = hx; 359 tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
411 } else 360 } else
412 return 0; 361 return 0;
413 362
@@ -420,17 +369,17 @@ static int ieee_fpe_handler(struct pt_regs *regs)
420 unsigned int hx; 369 unsigned int hx;
421 370
422 m = (finsn >> 8) & 0x7; 371 m = (finsn >> 8) & 0x7;
423 hx = tsk->thread.fpu.hard.fp_regs[m]; 372 hx = tsk->thread.xstate->hardfpu.fp_regs[m];
424 373
425 if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR) 374 if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR)
426 && ((hx & 0x7fffffff) < 0x00100000)) { 375 && ((hx & 0x7fffffff) < 0x00100000)) {
427 /* subnormal double to float conversion */ 376 /* subnormal double to float conversion */
428 long long llx; 377 long long llx;
429 378
430 llx = ((long long)tsk->thread.fpu.hard.fp_regs[m] << 32) 379 llx = ((long long)tsk->thread.xstate->hardfpu.fp_regs[m] << 32)
431 | tsk->thread.fpu.hard.fp_regs[m + 1]; 380 | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
432 381
433 tsk->thread.fpu.hard.fpul = float64_to_float32(llx); 382 tsk->thread.xstate->hardfpu.fpul = float64_to_float32(llx);
434 } else 383 } else
435 return 0; 384 return 0;
436 385
@@ -449,7 +398,7 @@ void float_raise(unsigned int flags)
449int float_rounding_mode(void) 398int float_rounding_mode(void)
450{ 399{
451 struct task_struct *tsk = current; 400 struct task_struct *tsk = current;
452 int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.fpu.hard.fpscr); 401 int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.xstate->hardfpu.fpscr);
453 return roundingMode; 402 return roundingMode;
454} 403}
455 404
@@ -461,16 +410,16 @@ BUILD_TRAP_HANDLER(fpu_error)
461 __unlazy_fpu(tsk, regs); 410 __unlazy_fpu(tsk, regs);
462 fpu_exception_flags = 0; 411 fpu_exception_flags = 0;
463 if (ieee_fpe_handler(regs)) { 412 if (ieee_fpe_handler(regs)) {
464 tsk->thread.fpu.hard.fpscr &= 413 tsk->thread.xstate->hardfpu.fpscr &=
465 ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); 414 ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
466 tsk->thread.fpu.hard.fpscr |= fpu_exception_flags; 415 tsk->thread.xstate->hardfpu.fpscr |= fpu_exception_flags;
467 /* Set the FPSCR flag as well as cause bits - simply 416 /* Set the FPSCR flag as well as cause bits - simply
468 * replicate the cause */ 417 * replicate the cause */
469 tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10); 418 tsk->thread.xstate->hardfpu.fpscr |= (fpu_exception_flags >> 10);
470 grab_fpu(regs); 419 grab_fpu(regs);
471 restore_fpu(tsk); 420 restore_fpu(tsk);
472 task_thread_info(tsk)->status |= TS_USEDFPU; 421 task_thread_info(tsk)->status |= TS_USEDFPU;
473 if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) & 422 if ((((tsk->thread.xstate->hardfpu.fpscr & FPSCR_ENABLE_MASK) >> 7) &
474 (fpu_exception_flags >> 2)) == 0) { 423 (fpu_exception_flags >> 2)) == 0) {
475 return; 424 return;
476 } 425 }
@@ -478,33 +427,3 @@ BUILD_TRAP_HANDLER(fpu_error)
478 427
479 force_sig(SIGFPE, tsk); 428 force_sig(SIGFPE, tsk);
480} 429}
481
482void fpu_state_restore(struct pt_regs *regs)
483{
484 struct task_struct *tsk = current;
485
486 grab_fpu(regs);
487 if (unlikely(!user_mode(regs))) {
488 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
489 BUG();
490 return;
491 }
492
493 if (likely(used_math())) {
494 /* Using the FPU again. */
495 restore_fpu(tsk);
496 } else {
497 /* First time FPU user. */
498 fpu_init();
499 set_used_math();
500 }
501 task_thread_info(tsk)->status |= TS_USEDFPU;
502 tsk->fpu_counter++;
503}
504
505BUILD_TRAP_HANDLER(fpu_state_restore)
506{
507 TRAP_HANDLER_DECL;
508
509 fpu_state_restore(regs);
510}
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 33bab477d2e2..b144e8af89dc 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -41,7 +41,8 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7757) := pinmux-sh7757.o
41pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o 41pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o
42pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o 42pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o
43 43
44obj-y += $(clock-y) 44obj-y += $(clock-y)
45obj-$(CONFIG_SMP) += $(smp-y) 45obj-$(CONFIG_SMP) += $(smp-y)
46obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) 46obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y)
47obj-$(CONFIG_PERF_EVENTS) += perf_event.o 47obj-$(CONFIG_PERF_EVENTS) += perf_event.o
48obj-$(CONFIG_HAVE_HW_BREAKPOINT) += ubc.o
diff --git a/arch/sh/kernel/cpu/sh4a/ubc.c b/arch/sh/kernel/cpu/sh4a/ubc.c
new file mode 100644
index 000000000000..efb2745bcb36
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/ubc.c
@@ -0,0 +1,133 @@
1/*
2 * arch/sh/kernel/cpu/sh4a/ubc.c
3 *
4 * On-chip UBC support for SH-4A CPUs.
5 *
6 * Copyright (C) 2009 - 2010 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/err.h>
14#include <linux/clk.h>
15#include <linux/io.h>
16#include <asm/hw_breakpoint.h>
17
18#define UBC_CBR(idx) (0xff200000 + (0x20 * idx))
19#define UBC_CRR(idx) (0xff200004 + (0x20 * idx))
20#define UBC_CAR(idx) (0xff200008 + (0x20 * idx))
21#define UBC_CAMR(idx) (0xff20000c + (0x20 * idx))
22
23#define UBC_CCMFR 0xff200600
24#define UBC_CBCR 0xff200620
25
26/* CRR */
27#define UBC_CRR_PCB (1 << 1)
28#define UBC_CRR_BIE (1 << 0)
29
30/* CBR */
31#define UBC_CBR_CE (1 << 0)
32
33static struct sh_ubc sh4a_ubc;
34
35static void sh4a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
36{
37 __raw_writel(UBC_CBR_CE | info->len | info->type, UBC_CBR(idx));
38 __raw_writel(info->address, UBC_CAR(idx));
39}
40
41static void sh4a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
42{
43 __raw_writel(0, UBC_CBR(idx));
44 __raw_writel(0, UBC_CAR(idx));
45}
46
47static void sh4a_ubc_enable_all(unsigned long mask)
48{
49 int i;
50
51 for (i = 0; i < sh4a_ubc.num_events; i++)
52 if (mask & (1 << i))
53 __raw_writel(__raw_readl(UBC_CBR(i)) | UBC_CBR_CE,
54 UBC_CBR(i));
55}
56
57static void sh4a_ubc_disable_all(void)
58{
59 int i;
60
61 for (i = 0; i < sh4a_ubc.num_events; i++)
62 __raw_writel(__raw_readl(UBC_CBR(i)) & ~UBC_CBR_CE,
63 UBC_CBR(i));
64}
65
66static unsigned long sh4a_ubc_active_mask(void)
67{
68 unsigned long active = 0;
69 int i;
70
71 for (i = 0; i < sh4a_ubc.num_events; i++)
72 if (__raw_readl(UBC_CBR(i)) & UBC_CBR_CE)
73 active |= (1 << i);
74
75 return active;
76}
77
78static unsigned long sh4a_ubc_triggered_mask(void)
79{
80 return __raw_readl(UBC_CCMFR);
81}
82
83static void sh4a_ubc_clear_triggered_mask(unsigned long mask)
84{
85 __raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR);
86}
87
88static struct sh_ubc sh4a_ubc = {
89 .name = "SH-4A",
90 .num_events = 2,
91 .trap_nr = 0x1e0,
92 .enable = sh4a_ubc_enable,
93 .disable = sh4a_ubc_disable,
94 .enable_all = sh4a_ubc_enable_all,
95 .disable_all = sh4a_ubc_disable_all,
96 .active_mask = sh4a_ubc_active_mask,
97 .triggered_mask = sh4a_ubc_triggered_mask,
98 .clear_triggered_mask = sh4a_ubc_clear_triggered_mask,
99};
100
101static int __init sh4a_ubc_init(void)
102{
103 struct clk *ubc_iclk = clk_get(NULL, "ubc0");
104 int i;
105
106 /*
107 * The UBC MSTP bit is optional, as not all platforms will have
108 * it. Just ignore it if we can't find it.
109 */
110 if (IS_ERR(ubc_iclk))
111 ubc_iclk = NULL;
112
113 clk_enable(ubc_iclk);
114
115 __raw_writel(0, UBC_CBCR);
116
117 for (i = 0; i < sh4a_ubc.num_events; i++) {
118 __raw_writel(0, UBC_CAMR(i));
119 __raw_writel(0, UBC_CBR(i));
120
121 __raw_writel(UBC_CRR_BIE | UBC_CRR_PCB, UBC_CRR(i));
122
123 /* dummy read for write posting */
124 (void)__raw_readl(UBC_CRR(i));
125 }
126
127 clk_disable(ubc_iclk);
128
129 sh4a_ubc.clk = ubc_iclk;
130
131 return register_sh_ubc(&sh4a_ubc);
132}
133arch_initcall(sh4a_ubc_init);
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S
index 591741383ee6..7a1b46fec0f4 100644
--- a/arch/sh/kernel/debugtraps.S
+++ b/arch/sh/kernel/debugtraps.S
@@ -13,7 +13,6 @@
13#include <linux/linkage.h> 13#include <linux/linkage.h>
14 14
15#if !defined(CONFIG_KGDB) 15#if !defined(CONFIG_KGDB)
16#define breakpoint_trap_handler debug_trap_handler
17#define singlestep_trap_handler debug_trap_handler 16#define singlestep_trap_handler debug_trap_handler
18#endif 17#endif
19 18
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
deleted file mode 100644
index f8bb50c6e050..000000000000
--- a/arch/sh/kernel/early_printk.c
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * arch/sh/kernel/early_printk.c
3 *
4 * Copyright (C) 1999, 2000 Niibe Yutaka
5 * Copyright (C) 2002 M. R. Brown
6 * Copyright (C) 2004 - 2007 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/console.h>
13#include <linux/tty.h>
14#include <linux/init.h>
15#include <linux/io.h>
16#include <linux/delay.h>
17
18#include <asm/sh_bios.h>
19
20/*
21 * Print a string through the BIOS
22 */
23static void sh_console_write(struct console *co, const char *s,
24 unsigned count)
25{
26 sh_bios_console_write(s, count);
27}
28
29/*
30 * Setup initial baud/bits/parity. We do two things here:
31 * - construct a cflag setting for the first rs_open()
32 * - initialize the serial port
33 * Return non-zero if we didn't find a serial port.
34 */
35static int __init sh_console_setup(struct console *co, char *options)
36{
37 int cflag = CREAD | HUPCL | CLOCAL;
38
39 /*
40 * Now construct a cflag setting.
41 * TODO: this is a totally bogus cflag, as we have
42 * no idea what serial settings the BIOS is using, or
43 * even if its using the serial port at all.
44 */
45 cflag |= B115200 | CS8 | /*no parity*/0;
46
47 co->cflag = cflag;
48
49 return 0;
50}
51
52static struct console bios_console = {
53 .name = "bios",
54 .write = sh_console_write,
55 .setup = sh_console_setup,
56 .flags = CON_PRINTBUFFER,
57 .index = -1,
58};
59
60static struct console *early_console;
61
62static int __init setup_early_printk(char *buf)
63{
64 int keep_early = 0;
65
66 if (!buf)
67 return 0;
68
69 if (strstr(buf, "keep"))
70 keep_early = 1;
71
72 if (!strncmp(buf, "bios", 4))
73 early_console = &bios_console;
74
75 if (likely(early_console)) {
76 if (keep_early)
77 early_console->flags &= ~CON_BOOT;
78 else
79 early_console->flags |= CON_BOOT;
80 register_console(early_console);
81 }
82
83 return 0;
84}
85early_param("earlyprintk", setup_early_printk);
diff --git a/arch/sh/kernel/head_64.S b/arch/sh/kernel/head_64.S
index 3ea765844c74..defd851abefa 100644
--- a/arch/sh/kernel/head_64.S
+++ b/arch/sh/kernel/head_64.S
@@ -220,7 +220,6 @@ clear_DTLB:
220 add.l r22, r63, r22 /* Sign extend */ 220 add.l r22, r63, r22 /* Sign extend */
221 putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ 221 putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */
222 222
223#ifdef CONFIG_EARLY_PRINTK
224 /* 223 /*
225 * Setup a DTLB translation for SCIF phys. 224 * Setup a DTLB translation for SCIF phys.
226 */ 225 */
@@ -231,7 +230,6 @@ clear_DTLB:
231 movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */ 230 movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */
232 shori 0x0003, r22 231 shori 0x0003, r22
233 putcfg r21, 0, r22 /* PTEH last */ 232 putcfg r21, 0, r22 /* PTEH last */
234#endif
235 233
236 /* 234 /*
237 * Set cache behaviours. 235 * Set cache behaviours.
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
new file mode 100644
index 000000000000..e2f1753d275c
--- /dev/null
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -0,0 +1,463 @@
1/*
2 * arch/sh/kernel/hw_breakpoint.c
3 *
4 * Unified kernel/user-space hardware breakpoint facility for the on-chip UBC.
5 *
6 * Copyright (C) 2009 - 2010 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/perf_event.h>
14#include <linux/hw_breakpoint.h>
15#include <linux/percpu.h>
16#include <linux/kallsyms.h>
17#include <linux/notifier.h>
18#include <linux/kprobes.h>
19#include <linux/kdebug.h>
20#include <linux/io.h>
21#include <linux/clk.h>
22#include <asm/hw_breakpoint.h>
23#include <asm/mmu_context.h>
24#include <asm/ptrace.h>
25
26/*
27 * Stores the breakpoints currently in use on each breakpoint address
28 * register for each cpus
29 */
30static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]);
31
32/*
33 * A dummy placeholder for early accesses until the CPUs get a chance to
34 * register their UBCs later in the boot process.
35 */
36static struct sh_ubc ubc_dummy = { .num_events = 0 };
37
38static struct sh_ubc *sh_ubc __read_mostly = &ubc_dummy;
39
40/*
41 * Install a perf counter breakpoint.
42 *
43 * We seek a free UBC channel and use it for this breakpoint.
44 *
45 * Atomic: we hold the counter->ctx->lock and we only handle variables
46 * and registers local to this cpu.
47 */
48int arch_install_hw_breakpoint(struct perf_event *bp)
49{
50 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
51 int i;
52
53 for (i = 0; i < sh_ubc->num_events; i++) {
54 struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
55
56 if (!*slot) {
57 *slot = bp;
58 break;
59 }
60 }
61
62 if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot"))
63 return -EBUSY;
64
65 clk_enable(sh_ubc->clk);
66 sh_ubc->enable(info, i);
67
68 return 0;
69}
70
71/*
72 * Uninstall the breakpoint contained in the given counter.
73 *
74 * First we search the debug address register it uses and then we disable
75 * it.
76 *
77 * Atomic: we hold the counter->ctx->lock and we only handle variables
78 * and registers local to this cpu.
79 */
80void arch_uninstall_hw_breakpoint(struct perf_event *bp)
81{
82 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
83 int i;
84
85 for (i = 0; i < sh_ubc->num_events; i++) {
86 struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
87
88 if (*slot == bp) {
89 *slot = NULL;
90 break;
91 }
92 }
93
94 if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot"))
95 return;
96
97 sh_ubc->disable(info, i);
98 clk_disable(sh_ubc->clk);
99}
100
101static int get_hbp_len(u16 hbp_len)
102{
103 unsigned int len_in_bytes = 0;
104
105 switch (hbp_len) {
106 case SH_BREAKPOINT_LEN_1:
107 len_in_bytes = 1;
108 break;
109 case SH_BREAKPOINT_LEN_2:
110 len_in_bytes = 2;
111 break;
112 case SH_BREAKPOINT_LEN_4:
113 len_in_bytes = 4;
114 break;
115 case SH_BREAKPOINT_LEN_8:
116 len_in_bytes = 8;
117 break;
118 }
119 return len_in_bytes;
120}
121
122/*
123 * Check for virtual address in user space.
124 */
125int arch_check_va_in_userspace(unsigned long va, u16 hbp_len)
126{
127 unsigned int len;
128
129 len = get_hbp_len(hbp_len);
130
131 return (va <= TASK_SIZE - len);
132}
133
134/*
135 * Check for virtual address in kernel space.
136 */
137static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
138{
139 unsigned int len;
140
141 len = get_hbp_len(hbp_len);
142
143 return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
144}
145
146/*
147 * Store a breakpoint's encoded address, length, and type.
148 */
149static int arch_store_info(struct perf_event *bp)
150{
151 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
152
153 /*
154 * User-space requests will always have the address field populated
155 * For kernel-addresses, either the address or symbol name can be
156 * specified.
157 */
158 if (info->name)
159 info->address = (unsigned long)kallsyms_lookup_name(info->name);
160 if (info->address)
161 return 0;
162
163 return -EINVAL;
164}
165
166int arch_bp_generic_fields(int sh_len, int sh_type,
167 int *gen_len, int *gen_type)
168{
169 /* Len */
170 switch (sh_len) {
171 case SH_BREAKPOINT_LEN_1:
172 *gen_len = HW_BREAKPOINT_LEN_1;
173 break;
174 case SH_BREAKPOINT_LEN_2:
175 *gen_len = HW_BREAKPOINT_LEN_2;
176 break;
177 case SH_BREAKPOINT_LEN_4:
178 *gen_len = HW_BREAKPOINT_LEN_4;
179 break;
180 case SH_BREAKPOINT_LEN_8:
181 *gen_len = HW_BREAKPOINT_LEN_8;
182 break;
183 default:
184 return -EINVAL;
185 }
186
187 /* Type */
188 switch (sh_type) {
189 case SH_BREAKPOINT_READ:
190 *gen_type = HW_BREAKPOINT_R;
191 case SH_BREAKPOINT_WRITE:
192 *gen_type = HW_BREAKPOINT_W;
193 break;
194 case SH_BREAKPOINT_RW:
195 *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
196 break;
197 default:
198 return -EINVAL;
199 }
200
201 return 0;
202}
203
204static int arch_build_bp_info(struct perf_event *bp)
205{
206 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
207
208 info->address = bp->attr.bp_addr;
209
210 /* Len */
211 switch (bp->attr.bp_len) {
212 case HW_BREAKPOINT_LEN_1:
213 info->len = SH_BREAKPOINT_LEN_1;
214 break;
215 case HW_BREAKPOINT_LEN_2:
216 info->len = SH_BREAKPOINT_LEN_2;
217 break;
218 case HW_BREAKPOINT_LEN_4:
219 info->len = SH_BREAKPOINT_LEN_4;
220 break;
221 case HW_BREAKPOINT_LEN_8:
222 info->len = SH_BREAKPOINT_LEN_8;
223 break;
224 default:
225 return -EINVAL;
226 }
227
228 /* Type */
229 switch (bp->attr.bp_type) {
230 case HW_BREAKPOINT_R:
231 info->type = SH_BREAKPOINT_READ;
232 break;
233 case HW_BREAKPOINT_W:
234 info->type = SH_BREAKPOINT_WRITE;
235 break;
236 case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
237 info->type = SH_BREAKPOINT_RW;
238 break;
239 default:
240 return -EINVAL;
241 }
242
243 return 0;
244}
245
246/*
247 * Validate the arch-specific HW Breakpoint register settings
248 */
249int arch_validate_hwbkpt_settings(struct perf_event *bp,
250 struct task_struct *tsk)
251{
252 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
253 unsigned int align;
254 int ret;
255
256 ret = arch_build_bp_info(bp);
257 if (ret)
258 return ret;
259
260 ret = -EINVAL;
261
262 switch (info->len) {
263 case SH_BREAKPOINT_LEN_1:
264 align = 0;
265 break;
266 case SH_BREAKPOINT_LEN_2:
267 align = 1;
268 break;
269 case SH_BREAKPOINT_LEN_4:
270 align = 3;
271 break;
272 case SH_BREAKPOINT_LEN_8:
273 align = 7;
274 break;
275 default:
276 return ret;
277 }
278
279 ret = arch_store_info(bp);
280
281 if (ret < 0)
282 return ret;
283
284 /*
285 * Check that the low-order bits of the address are appropriate
286 * for the alignment implied by len.
287 */
288 if (info->address & align)
289 return -EINVAL;
290
291 /* Check that the virtual address is in the proper range */
292 if (tsk) {
293 if (!arch_check_va_in_userspace(info->address, info->len))
294 return -EFAULT;
295 } else {
296 if (!arch_check_va_in_kernelspace(info->address, info->len))
297 return -EFAULT;
298 }
299
300 return 0;
301}
302
303/*
304 * Release the user breakpoints used by ptrace
305 */
306void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
307{
308 int i;
309 struct thread_struct *t = &tsk->thread;
310
311 for (i = 0; i < sh_ubc->num_events; i++) {
312 unregister_hw_breakpoint(t->ptrace_bps[i]);
313 t->ptrace_bps[i] = NULL;
314 }
315}
316
317static int __kprobes hw_breakpoint_handler(struct die_args *args)
318{
319 int cpu, i, rc = NOTIFY_STOP;
320 struct perf_event *bp;
321 unsigned int cmf, resume_mask;
322
323 /*
324 * Do an early return if none of the channels triggered.
325 */
326 cmf = sh_ubc->triggered_mask();
327 if (unlikely(!cmf))
328 return NOTIFY_DONE;
329
330 /*
331 * By default, resume all of the active channels.
332 */
333 resume_mask = sh_ubc->active_mask();
334
335 /*
336 * Disable breakpoints during exception handling.
337 */
338 sh_ubc->disable_all();
339
340 cpu = get_cpu();
341 for (i = 0; i < sh_ubc->num_events; i++) {
342 unsigned long event_mask = (1 << i);
343
344 if (likely(!(cmf & event_mask)))
345 continue;
346
347 /*
348 * The counter may be concurrently released but that can only
349 * occur from a call_rcu() path. We can then safely fetch
350 * the breakpoint, use its callback, touch its counter
351 * while we are in an rcu_read_lock() path.
352 */
353 rcu_read_lock();
354
355 bp = per_cpu(bp_per_reg[i], cpu);
356 if (bp)
357 rc = NOTIFY_DONE;
358
359 /*
360 * Reset the condition match flag to denote completion of
361 * exception handling.
362 */
363 sh_ubc->clear_triggered_mask(event_mask);
364
365 /*
366 * bp can be NULL due to concurrent perf counter
367 * removing.
368 */
369 if (!bp) {
370 rcu_read_unlock();
371 break;
372 }
373
374 /*
375 * Don't restore the channel if the breakpoint is from
376 * ptrace, as it always operates in one-shot mode.
377 */
378 if (bp->overflow_handler == ptrace_triggered)
379 resume_mask &= ~(1 << i);
380
381 perf_bp_event(bp, args->regs);
382
383 /* Deliver the signal to userspace */
384 if (arch_check_va_in_userspace(bp->attr.bp_addr,
385 bp->attr.bp_len)) {
386 siginfo_t info;
387
388 info.si_signo = args->signr;
389 info.si_errno = notifier_to_errno(rc);
390 info.si_code = TRAP_HWBKPT;
391
392 force_sig_info(args->signr, &info, current);
393 }
394
395 rcu_read_unlock();
396 }
397
398 if (cmf == 0)
399 rc = NOTIFY_DONE;
400
401 sh_ubc->enable_all(resume_mask);
402
403 put_cpu();
404
405 return rc;
406}
407
408BUILD_TRAP_HANDLER(breakpoint)
409{
410 unsigned long ex = lookup_exception_vector();
411 TRAP_HANDLER_DECL;
412
413 notify_die(DIE_BREAKPOINT, "breakpoint", regs, 0, ex, SIGTRAP);
414}
415
416/*
417 * Handle debug exception notifications.
418 */
419int __kprobes hw_breakpoint_exceptions_notify(struct notifier_block *unused,
420 unsigned long val, void *data)
421{
422 struct die_args *args = data;
423
424 if (val != DIE_BREAKPOINT)
425 return NOTIFY_DONE;
426
427 /*
428 * If the breakpoint hasn't been triggered by the UBC, it's
429 * probably from a debugger, so don't do anything more here.
430 *
431 * This also permits the UBC interface clock to remain off for
432 * non-UBC breakpoints, as we don't need to check the triggered
433 * or active channel masks.
434 */
435 if (args->trapnr != sh_ubc->trap_nr)
436 return NOTIFY_DONE;
437
438 return hw_breakpoint_handler(data);
439}
440
441void hw_breakpoint_pmu_read(struct perf_event *bp)
442{
443 /* TODO */
444}
445
446void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
447{
448 /* TODO */
449}
450
451int register_sh_ubc(struct sh_ubc *ubc)
452{
453 /* Bail if it's already assigned */
454 if (sh_ubc != &ubc_dummy)
455 return -EBUSY;
456 sh_ubc = ubc;
457
458 pr_info("HW Breakpoints: %s UBC support registered\n", ubc->name);
459
460 WARN_ON(ubc->num_events > HBP_NUM);
461
462 return 0;
463}
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c
index 3e532d0d4a5c..70c69659b846 100644
--- a/arch/sh/kernel/kgdb.c
+++ b/arch/sh/kernel/kgdb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * SuperH KGDB support 2 * SuperH KGDB support
3 * 3 *
4 * Copyright (C) 2008 Paul Mundt 4 * Copyright (C) 2008 - 2009 Paul Mundt
5 * 5 *
6 * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. 6 * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
7 * 7 *
@@ -251,24 +251,60 @@ BUILD_TRAP_HANDLER(singlestep)
251 local_irq_restore(flags); 251 local_irq_restore(flags);
252} 252}
253 253
254static int __kgdb_notify(struct die_args *args, unsigned long cmd)
255{
256 int ret;
257
258 switch (cmd) {
259 case DIE_BREAKPOINT:
260 /*
261 * This means a user thread is single stepping
262 * a system call which should be ignored
263 */
264 if (test_thread_flag(TIF_SINGLESTEP))
265 return NOTIFY_DONE;
266
267 ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr,
268 args->err, args->regs);
269 if (ret)
270 return NOTIFY_DONE;
271
272 break;
273 }
254 274
255BUILD_TRAP_HANDLER(breakpoint) 275 return NOTIFY_STOP;
276}
277
278static int
279kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
256{ 280{
257 unsigned long flags; 281 unsigned long flags;
258 TRAP_HANDLER_DECL; 282 int ret;
259 283
260 local_irq_save(flags); 284 local_irq_save(flags);
261 kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); 285 ret = __kgdb_notify(ptr, cmd);
262 local_irq_restore(flags); 286 local_irq_restore(flags);
287
288 return ret;
263} 289}
264 290
291static struct notifier_block kgdb_notifier = {
292 .notifier_call = kgdb_notify,
293
294 /*
295 * Lowest-prio notifier priority, we want to be notified last:
296 */
297 .priority = -INT_MAX,
298};
299
265int kgdb_arch_init(void) 300int kgdb_arch_init(void)
266{ 301{
267 return 0; 302 return register_die_notifier(&kgdb_notifier);
268} 303}
269 304
270void kgdb_arch_exit(void) 305void kgdb_arch_exit(void)
271{ 306{
307 unregister_die_notifier(&kgdb_notifier);
272} 308}
273 309
274struct kgdb_arch arch_kgdb_ops = { 310struct kgdb_arch arch_kgdb_ops = {
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 76f280223ebd..f52d8ed69e12 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -21,6 +21,7 @@
21#include <asm/mmu_context.h> 21#include <asm/mmu_context.h>
22#include <asm/io.h> 22#include <asm/io.h>
23#include <asm/cacheflush.h> 23#include <asm/cacheflush.h>
24#include <asm/sh_bios.h>
24 25
25typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, 26typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
26 unsigned long reboot_code_buffer, 27 unsigned long reboot_code_buffer,
@@ -28,7 +29,6 @@ typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
28 29
29extern const unsigned char relocate_new_kernel[]; 30extern const unsigned char relocate_new_kernel[];
30extern const unsigned int relocate_new_kernel_size; 31extern const unsigned int relocate_new_kernel_size;
31extern void *gdb_vbr_vector;
32extern void *vbr_base; 32extern void *vbr_base;
33 33
34void machine_shutdown(void) 34void machine_shutdown(void)
@@ -117,11 +117,7 @@ void machine_kexec(struct kimage *image)
117 kexec_info(image); 117 kexec_info(image);
118 flush_cache_all(); 118 flush_cache_all();
119 119
120#if defined(CONFIG_SH_STANDARD_BIOS) 120 sh_bios_vbr_reload();
121 asm volatile("ldc %0, vbr" :
122 : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
123 : "memory");
124#endif
125 121
126 /* now call it */ 122 /* now call it */
127 rnk = (relocate_new_kernel_t) reboot_code_buffer; 123 rnk = (relocate_new_kernel_t) reboot_code_buffer;
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
new file mode 100644
index 000000000000..81add9b9ea6e
--- /dev/null
+++ b/arch/sh/kernel/process.c
@@ -0,0 +1,100 @@
1#include <linux/mm.h>
2#include <linux/kernel.h>
3#include <linux/sched.h>
4
5struct kmem_cache *task_xstate_cachep = NULL;
6unsigned int xstate_size;
7
8int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
9{
10 *dst = *src;
11
12 if (src->thread.xstate) {
13 dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
14 GFP_KERNEL);
15 if (!dst->thread.xstate)
16 return -ENOMEM;
17 memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
18 }
19
20 return 0;
21}
22
23void free_thread_xstate(struct task_struct *tsk)
24{
25 if (tsk->thread.xstate) {
26 kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
27 tsk->thread.xstate = NULL;
28 }
29}
30
31#if THREAD_SHIFT < PAGE_SHIFT
32static struct kmem_cache *thread_info_cache;
33
34struct thread_info *alloc_thread_info(struct task_struct *tsk)
35{
36 struct thread_info *ti;
37
38 ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
39 if (unlikely(ti == NULL))
40 return NULL;
41#ifdef CONFIG_DEBUG_STACK_USAGE
42 memset(ti, 0, THREAD_SIZE);
43#endif
44 return ti;
45}
46
47void free_thread_info(struct thread_info *ti)
48{
49 free_thread_xstate(ti->task);
50 kmem_cache_free(thread_info_cache, ti);
51}
52
53void thread_info_cache_init(void)
54{
55 thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
56 THREAD_SIZE, SLAB_PANIC, NULL);
57}
58#else
59struct thread_info *alloc_thread_info(struct task_struct *tsk)
60{
61#ifdef CONFIG_DEBUG_STACK_USAGE
62 gfp_t mask = GFP_KERNEL | __GFP_ZERO;
63#else
64 gfp_t mask = GFP_KERNEL;
65#endif
66 return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
67}
68
69void free_thread_info(struct thread_info *ti)
70{
71 free_thread_xstate(ti->task);
72 free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
73}
74#endif /* THREAD_SHIFT < PAGE_SHIFT */
75
76void arch_task_cache_init(void)
77{
78 if (!xstate_size)
79 return;
80
81 task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size,
82 __alignof__(union thread_xstate),
83 SLAB_PANIC | SLAB_NOTRACK, NULL);
84}
85
86#ifdef CONFIG_SH_FPU_EMU
87# define HAVE_SOFTFP 1
88#else
89# define HAVE_SOFTFP 0
90#endif
91
92void init_thread_xstate(void)
93{
94 if (boot_cpu_data.flags & CPU_HAS_FPU)
95 xstate_size = sizeof(struct sh_fpu_hard_struct);
96 else if (HAVE_SOFTFP)
97 xstate_size = sizeof(struct sh_fpu_soft_struct);
98 else
99 xstate_size = 0;
100}
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index d8af889366a4..856010f9ebc9 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -25,17 +25,15 @@
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/ftrace.h> 26#include <linux/ftrace.h>
27#include <linux/preempt.h> 27#include <linux/preempt.h>
28#include <linux/hw_breakpoint.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
29#include <asm/mmu_context.h> 30#include <asm/mmu_context.h>
30#include <asm/pgalloc.h> 31#include <asm/pgalloc.h>
31#include <asm/system.h> 32#include <asm/system.h>
32#include <asm/ubc.h>
33#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/syscalls.h> 34#include <asm/syscalls.h>
35#include <asm/watchdog.h> 35#include <asm/watchdog.h>
36 36
37int ubc_usercnt = 0;
38
39#ifdef CONFIG_32BIT 37#ifdef CONFIG_32BIT
40static void watchdog_trigger_immediate(void) 38static void watchdog_trigger_immediate(void)
41{ 39{
@@ -147,21 +145,34 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
147} 145}
148EXPORT_SYMBOL(kernel_thread); 146EXPORT_SYMBOL(kernel_thread);
149 147
148void start_thread(struct pt_regs *regs, unsigned long new_pc,
149 unsigned long new_sp)
150{
151 set_fs(USER_DS);
152
153 regs->pr = 0;
154 regs->sr = SR_FD;
155 regs->pc = new_pc;
156 regs->regs[15] = new_sp;
157
158 free_thread_xstate(current);
159}
160EXPORT_SYMBOL(start_thread);
161
150/* 162/*
151 * Free current thread data structures etc.. 163 * Free current thread data structures etc..
152 */ 164 */
153void exit_thread(void) 165void exit_thread(void)
154{ 166{
155 if (current->thread.ubc_pc) {
156 current->thread.ubc_pc = 0;
157 ubc_usercnt -= 1;
158 }
159} 167}
160 168
161void flush_thread(void) 169void flush_thread(void)
162{ 170{
163#if defined(CONFIG_SH_FPU)
164 struct task_struct *tsk = current; 171 struct task_struct *tsk = current;
172
173 flush_ptrace_hw_breakpoint(tsk);
174
175#if defined(CONFIG_SH_FPU)
165 /* Forget lazy FPU state */ 176 /* Forget lazy FPU state */
166 clear_fpu(tsk, task_pt_regs(tsk)); 177 clear_fpu(tsk, task_pt_regs(tsk));
167 clear_used_math(); 178 clear_used_math();
@@ -209,11 +220,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
209{ 220{
210 struct thread_info *ti = task_thread_info(p); 221 struct thread_info *ti = task_thread_info(p);
211 struct pt_regs *childregs; 222 struct pt_regs *childregs;
223
212#if defined(CONFIG_SH_DSP) 224#if defined(CONFIG_SH_DSP)
213 struct task_struct *tsk = current; 225 struct task_struct *tsk = current;
214#endif
215 226
216#if defined(CONFIG_SH_DSP)
217 if (is_dsp_enabled(tsk)) { 227 if (is_dsp_enabled(tsk)) {
218 /* We can use the __save_dsp or just copy the struct: 228 /* We can use the __save_dsp or just copy the struct:
219 * __save_dsp(p); 229 * __save_dsp(p);
@@ -244,53 +254,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
244 p->thread.sp = (unsigned long) childregs; 254 p->thread.sp = (unsigned long) childregs;
245 p->thread.pc = (unsigned long) ret_from_fork; 255 p->thread.pc = (unsigned long) ret_from_fork;
246 256
247 p->thread.ubc_pc = 0; 257 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
248 258
249 return 0; 259 return 0;
250} 260}
251 261
252/* Tracing by user break controller. */
253static void ubc_set_tracing(int asid, unsigned long pc)
254{
255#if defined(CONFIG_CPU_SH4A)
256 unsigned long val;
257
258 val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
259 val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
260
261 ctrl_outl(val, UBC_CBR0);
262 ctrl_outl(pc, UBC_CAR0);
263 ctrl_outl(0x0, UBC_CAMR0);
264 ctrl_outl(0x0, UBC_CBCR);
265
266 val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
267 ctrl_outl(val, UBC_CRR0);
268
269 /* Read UBC register that we wrote last, for checking update */
270 val = ctrl_inl(UBC_CRR0);
271
272#else /* CONFIG_CPU_SH4A */
273 ctrl_outl(pc, UBC_BARA);
274
275#ifdef CONFIG_MMU
276 ctrl_outb(asid, UBC_BASRA);
277#endif
278
279 ctrl_outl(0, UBC_BAMRA);
280
281 if (current_cpu_data.type == CPU_SH7729 ||
282 current_cpu_data.type == CPU_SH7710 ||
283 current_cpu_data.type == CPU_SH7712 ||
284 current_cpu_data.type == CPU_SH7203){
285 ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
286 ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
287 } else {
288 ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
289 ctrl_outw(BRCR_PCBA, UBC_BRCR);
290 }
291#endif /* CONFIG_CPU_SH4A */
292}
293
294/* 262/*
295 * switch_to(x,y) should switch tasks from x to y. 263 * switch_to(x,y) should switch tasks from x to y.
296 * 264 *
@@ -304,7 +272,7 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
304 272
305 /* we're going to use this soon, after a few expensive things */ 273 /* we're going to use this soon, after a few expensive things */
306 if (next->fpu_counter > 5) 274 if (next->fpu_counter > 5)
307 prefetch(&next_t->fpu.hard); 275 prefetch(next_t->xstate);
308 276
309#ifdef CONFIG_MMU 277#ifdef CONFIG_MMU
310 /* 278 /*
@@ -316,32 +284,13 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
316 : "r" (task_thread_info(next))); 284 : "r" (task_thread_info(next)));
317#endif 285#endif
318 286
319 /* If no tasks are using the UBC, we're done */
320 if (ubc_usercnt == 0)
321 /* If no tasks are using the UBC, we're done */;
322 else if (next->thread.ubc_pc && next->mm) {
323 int asid = 0;
324#ifdef CONFIG_MMU
325 asid |= cpu_asid(smp_processor_id(), next->mm);
326#endif
327 ubc_set_tracing(asid, next->thread.ubc_pc);
328 } else {
329#if defined(CONFIG_CPU_SH4A)
330 ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
331 ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
332#else
333 ctrl_outw(0, UBC_BBRA);
334 ctrl_outw(0, UBC_BBRB);
335#endif
336 }
337
338 /* 287 /*
339 * If the task has used fpu the last 5 timeslices, just do a full 288 * If the task has used fpu the last 5 timeslices, just do a full
340 * restore of the math state immediately to avoid the trap; the 289 * restore of the math state immediately to avoid the trap; the
341 * chances of needing FPU soon are obviously high now 290 * chances of needing FPU soon are obviously high now
342 */ 291 */
343 if (next->fpu_counter > 5) 292 if (next->fpu_counter > 5)
344 fpu_state_restore(task_pt_regs(next)); 293 __fpu_state_restore();
345 294
346 return prev; 295 return prev;
347} 296}
@@ -434,20 +383,3 @@ unsigned long get_wchan(struct task_struct *p)
434 383
435 return pc; 384 return pc;
436} 385}
437
438asmlinkage void break_point_trap(void)
439{
440 /* Clear tracing. */
441#if defined(CONFIG_CPU_SH4A)
442 ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
443 ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
444#else
445 ctrl_outw(0, UBC_BBRA);
446 ctrl_outw(0, UBC_BBRB);
447 ctrl_outl(0, UBC_BRCR);
448#endif
449 current->thread.ubc_pc = 0;
450 ubc_usercnt -= 1;
451
452 force_sig(SIGTRAP, current);
453}
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 9be35f348093..c625cdab76dd 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -2,7 +2,7 @@
2 * SuperH process tracing 2 * SuperH process tracing
3 * 3 *
4 * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka 4 * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
5 * Copyright (C) 2002 - 2008 Paul Mundt 5 * Copyright (C) 2002 - 2009 Paul Mundt
6 * 6 *
7 * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp> 7 * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp>
8 * 8 *
@@ -26,6 +26,7 @@
26#include <linux/tracehook.h> 26#include <linux/tracehook.h>
27#include <linux/elf.h> 27#include <linux/elf.h>
28#include <linux/regset.h> 28#include <linux/regset.h>
29#include <linux/hw_breakpoint.h>
29#include <asm/uaccess.h> 30#include <asm/uaccess.h>
30#include <asm/pgtable.h> 31#include <asm/pgtable.h>
31#include <asm/system.h> 32#include <asm/system.h>
@@ -63,33 +64,64 @@ static inline int put_stack_long(struct task_struct *task, int offset,
63 return 0; 64 return 0;
64} 65}
65 66
66void user_enable_single_step(struct task_struct *child) 67void ptrace_triggered(struct perf_event *bp, int nmi,
68 struct perf_sample_data *data, struct pt_regs *regs)
67{ 69{
68 /* Next scheduling will set up UBC */ 70 struct perf_event_attr attr;
69 if (child->thread.ubc_pc == 0) 71
70 ubc_usercnt += 1; 72 /*
73 * Disable the breakpoint request here since ptrace has defined a
74 * one-shot behaviour for breakpoint exceptions.
75 */
76 attr = bp->attr;
77 attr.disabled = true;
78 modify_user_hw_breakpoint(bp, &attr);
79}
80
81static int set_single_step(struct task_struct *tsk, unsigned long addr)
82{
83 struct thread_struct *thread = &tsk->thread;
84 struct perf_event *bp;
85 struct perf_event_attr attr;
86
87 bp = thread->ptrace_bps[0];
88 if (!bp) {
89 hw_breakpoint_init(&attr);
90
91 attr.bp_addr = addr;
92 attr.bp_len = HW_BREAKPOINT_LEN_2;
93 attr.bp_type = HW_BREAKPOINT_R;
94
95 bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
96 if (IS_ERR(bp))
97 return PTR_ERR(bp);
98
99 thread->ptrace_bps[0] = bp;
100 } else {
101 int err;
102
103 attr = bp->attr;
104 attr.bp_addr = addr;
105 err = modify_user_hw_breakpoint(bp, &attr);
106 if (unlikely(err))
107 return err;
108 }
109
110 return 0;
111}
71 112
72 child->thread.ubc_pc = get_stack_long(child, 113void user_enable_single_step(struct task_struct *child)
73 offsetof(struct pt_regs, pc)); 114{
115 unsigned long pc = get_stack_long(child, offsetof(struct pt_regs, pc));
74 116
75 set_tsk_thread_flag(child, TIF_SINGLESTEP); 117 set_tsk_thread_flag(child, TIF_SINGLESTEP);
118
119 set_single_step(child, pc);
76} 120}
77 121
78void user_disable_single_step(struct task_struct *child) 122void user_disable_single_step(struct task_struct *child)
79{ 123{
80 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 124 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
81
82 /*
83 * Ensure the UBC is not programmed at the next context switch.
84 *
85 * Normally this is not needed but there are sequences such as
86 * singlestep, signal delivery, and continue that leave the
87 * ubc_pc non-zero leading to spurious SIGTRAPs.
88 */
89 if (child->thread.ubc_pc != 0) {
90 ubc_usercnt -= 1;
91 child->thread.ubc_pc = 0;
92 }
93} 125}
94 126
95/* 127/*
@@ -163,10 +195,10 @@ int fpregs_get(struct task_struct *target,
163 195
164 if ((boot_cpu_data.flags & CPU_HAS_FPU)) 196 if ((boot_cpu_data.flags & CPU_HAS_FPU))
165 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 197 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
166 &target->thread.fpu.hard, 0, -1); 198 &target->thread.xstate->hardfpu, 0, -1);
167 199
168 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 200 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
169 &target->thread.fpu.soft, 0, -1); 201 &target->thread.xstate->softfpu, 0, -1);
170} 202}
171 203
172static int fpregs_set(struct task_struct *target, 204static int fpregs_set(struct task_struct *target,
@@ -184,10 +216,10 @@ static int fpregs_set(struct task_struct *target,
184 216
185 if ((boot_cpu_data.flags & CPU_HAS_FPU)) 217 if ((boot_cpu_data.flags & CPU_HAS_FPU))
186 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 218 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
187 &target->thread.fpu.hard, 0, -1); 219 &target->thread.xstate->hardfpu, 0, -1);
188 220
189 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 221 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
190 &target->thread.fpu.soft, 0, -1); 222 &target->thread.xstate->softfpu, 0, -1);
191} 223}
192 224
193static int fpregs_active(struct task_struct *target, 225static int fpregs_active(struct task_struct *target,
@@ -333,7 +365,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
333 else 365 else
334 tmp = 0; 366 tmp = 0;
335 } else 367 } else
336 tmp = ((long *)&child->thread.fpu) 368 tmp = ((long *)child->thread.xstate)
337 [(addr - (long)&dummy->fpu) >> 2]; 369 [(addr - (long)&dummy->fpu) >> 2];
338 } else if (addr == (long) &dummy->u_fpvalid) 370 } else if (addr == (long) &dummy->u_fpvalid)
339 tmp = !!tsk_used_math(child); 371 tmp = !!tsk_used_math(child);
@@ -362,7 +394,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
362 else if (addr >= (long) &dummy->fpu && 394 else if (addr >= (long) &dummy->fpu &&
363 addr < (long) &dummy->u_fpvalid) { 395 addr < (long) &dummy->u_fpvalid) {
364 set_stopped_child_used_math(child); 396 set_stopped_child_used_math(child);
365 ((long *)&child->thread.fpu) 397 ((long *)child->thread.xstate)
366 [(addr - (long)&dummy->fpu) >> 2] = data; 398 [(addr - (long)&dummy->fpu) >> 2] = data;
367 ret = 0; 399 ret = 0;
368 } else if (addr == (long) &dummy->u_fpvalid) { 400 } else if (addr == (long) &dummy->u_fpvalid) {
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
index c852f7805728..47475cca068a 100644
--- a/arch/sh/kernel/sh_bios.c
+++ b/arch/sh/kernel/sh_bios.c
@@ -1,19 +1,30 @@
1/* 1/*
2 * linux/arch/sh/kernel/sh_bios.c
3 * C interface for trapping into the standard LinuxSH BIOS. 2 * C interface for trapping into the standard LinuxSH BIOS.
4 * 3 *
5 * Copyright (C) 2000 Greg Banks, Mitch Davis 4 * Copyright (C) 2000 Greg Banks, Mitch Davis
5 * Copyright (C) 1999, 2000 Niibe Yutaka
6 * Copyright (C) 2002 M. R. Brown
7 * Copyright (C) 2004 - 2010 Paul Mundt
6 * 8 *
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
11 * for more details.
7 */ 12 */
8#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/console.h>
15#include <linux/tty.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/delay.h>
9#include <asm/sh_bios.h> 19#include <asm/sh_bios.h>
10 20
11#define BIOS_CALL_CONSOLE_WRITE 0 21#define BIOS_CALL_CONSOLE_WRITE 0
12#define BIOS_CALL_ETH_NODE_ADDR 10 22#define BIOS_CALL_ETH_NODE_ADDR 10
13#define BIOS_CALL_SHUTDOWN 11 23#define BIOS_CALL_SHUTDOWN 11
14#define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */
15#define BIOS_CALL_GDB_DETACH 0xff 24#define BIOS_CALL_GDB_DETACH 0xff
16 25
26void *gdb_vbr_vector = NULL;
27
17static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, 28static inline long sh_bios_call(long func, long arg0, long arg1, long arg2,
18 long arg3) 29 long arg3)
19{ 30{
@@ -23,6 +34,9 @@ static inline long sh_bios_call(long func, long arg0, long arg1, long arg2,
23 register long r6 __asm__("r6") = arg2; 34 register long r6 __asm__("r6") = arg2;
24 register long r7 __asm__("r7") = arg3; 35 register long r7 __asm__("r7") = arg3;
25 36
37 if (!gdb_vbr_vector)
38 return -ENOSYS;
39
26 __asm__ __volatile__("trapa #0x3f":"=z"(r0) 40 __asm__ __volatile__("trapa #0x3f":"=z"(r0)
27 :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7) 41 :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
28 :"memory"); 42 :"memory");
@@ -34,11 +48,6 @@ void sh_bios_console_write(const char *buf, unsigned int len)
34 sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); 48 sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0);
35} 49}
36 50
37void sh_bios_char_out(char ch)
38{
39 sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0);
40}
41
42void sh_bios_gdb_detach(void) 51void sh_bios_gdb_detach(void)
43{ 52{
44 sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); 53 sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
@@ -55,3 +64,109 @@ void sh_bios_shutdown(unsigned int how)
55{ 64{
56 sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); 65 sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
57} 66}
67
68/*
69 * Read the old value of the VBR register to initialise the vector
70 * through which debug and BIOS traps are delegated by the Linux trap
71 * handler.
72 */
73void sh_bios_vbr_init(void)
74{
75 unsigned long vbr;
76
77 if (unlikely(gdb_vbr_vector))
78 return;
79
80 __asm__ __volatile__ ("stc vbr, %0" : "=r" (vbr));
81
82 if (vbr) {
83 gdb_vbr_vector = (void *)(vbr + 0x100);
84 printk(KERN_NOTICE "Setting GDB trap vector to %p\n",
85 gdb_vbr_vector);
86 } else
87 printk(KERN_NOTICE "SH-BIOS not detected\n");
88}
89
90/**
91 * sh_bios_vbr_reload - Re-load the system VBR from the BIOS vector.
92 *
93 * This can be used by save/restore code to reinitialize the system VBR
94 * from the fixed BIOS VBR. A no-op if no BIOS VBR is known.
95 */
96void sh_bios_vbr_reload(void)
97{
98 if (gdb_vbr_vector)
99 __asm__ __volatile__ (
100 "ldc %0, vbr"
101 :
102 : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
103 : "memory"
104 );
105}
106
107/*
108 * Print a string through the BIOS
109 */
110static void sh_console_write(struct console *co, const char *s,
111 unsigned count)
112{
113 sh_bios_console_write(s, count);
114}
115
116/*
117 * Setup initial baud/bits/parity. We do two things here:
118 * - construct a cflag setting for the first rs_open()
119 * - initialize the serial port
120 * Return non-zero if we didn't find a serial port.
121 */
122static int __init sh_console_setup(struct console *co, char *options)
123{
124 int cflag = CREAD | HUPCL | CLOCAL;
125
126 /*
127 * Now construct a cflag setting.
128 * TODO: this is a totally bogus cflag, as we have
129 * no idea what serial settings the BIOS is using, or
130 * even if its using the serial port at all.
131 */
132 cflag |= B115200 | CS8 | /*no parity*/0;
133
134 co->cflag = cflag;
135
136 return 0;
137}
138
139static struct console bios_console = {
140 .name = "bios",
141 .write = sh_console_write,
142 .setup = sh_console_setup,
143 .flags = CON_PRINTBUFFER,
144 .index = -1,
145};
146
147static struct console *early_console;
148
149static int __init setup_early_printk(char *buf)
150{
151 int keep_early = 0;
152
153 if (!buf)
154 return 0;
155
156 if (strstr(buf, "keep"))
157 keep_early = 1;
158
159 if (!strncmp(buf, "bios", 4))
160 early_console = &bios_console;
161
162 if (likely(early_console)) {
163 if (keep_early)
164 early_console->flags &= ~CON_BOOT;
165 else
166 early_console->flags |= CON_BOOT;
167 register_console(early_console);
168 }
169
170 return 0;
171}
172early_param("earlyprintk", setup_early_printk);
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 12815ce01ecd..6a7cce79eb4e 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -150,7 +150,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc)
150 return 0; 150 return 0;
151 151
152 set_used_math(); 152 set_used_math();
153 return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], 153 return __copy_from_user(&tsk->thread.xstate->hardfpu, &sc->sc_fpregs[0],
154 sizeof(long)*(16*2+2)); 154 sizeof(long)*(16*2+2));
155} 155}
156 156
@@ -175,7 +175,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
175 clear_used_math(); 175 clear_used_math();
176 176
177 unlazy_fpu(tsk, regs); 177 unlazy_fpu(tsk, regs);
178 return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, 178 return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.xstate->hardfpu,
179 sizeof(long)*(16*2+2)); 179 sizeof(long)*(16*2+2));
180} 180}
181#endif /* CONFIG_SH_FPU */ 181#endif /* CONFIG_SH_FPU */
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 86639beac3a2..9c090cb68878 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -24,13 +24,13 @@
24#include <linux/kdebug.h> 24#include <linux/kdebug.h>
25#include <linux/kexec.h> 25#include <linux/kexec.h>
26#include <linux/limits.h> 26#include <linux/limits.h>
27#include <linux/proc_fs.h>
28#include <linux/seq_file.h>
29#include <linux/sysfs.h> 27#include <linux/sysfs.h>
28#include <linux/uaccess.h>
30#include <asm/system.h> 29#include <asm/system.h>
31#include <asm/uaccess.h> 30#include <asm/alignment.h>
32#include <asm/fpu.h> 31#include <asm/fpu.h>
33#include <asm/kprobes.h> 32#include <asm/kprobes.h>
33#include <asm/sh_bios.h>
34 34
35#ifdef CONFIG_CPU_SH2 35#ifdef CONFIG_CPU_SH2
36# define TRAP_RESERVED_INST 4 36# define TRAP_RESERVED_INST 4
@@ -47,73 +47,6 @@
47#define TRAP_ILLEGAL_SLOT_INST 13 47#define TRAP_ILLEGAL_SLOT_INST 13
48#endif 48#endif
49 49
50static unsigned long se_user;
51static unsigned long se_sys;
52static unsigned long se_half;
53static unsigned long se_word;
54static unsigned long se_dword;
55static unsigned long se_multi;
56/* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
57 valid! */
58static int se_usermode = 3;
59/* 0: no warning 1: print a warning message, disabled by default */
60static int se_kernmode_warn;
61
62#ifdef CONFIG_PROC_FS
63static const char *se_usermode_action[] = {
64 "ignored",
65 "warn",
66 "fixup",
67 "fixup+warn",
68 "signal",
69 "signal+warn"
70};
71
72static int alignment_proc_show(struct seq_file *m, void *v)
73{
74 seq_printf(m, "User:\t\t%lu\n", se_user);
75 seq_printf(m, "System:\t\t%lu\n", se_sys);
76 seq_printf(m, "Half:\t\t%lu\n", se_half);
77 seq_printf(m, "Word:\t\t%lu\n", se_word);
78 seq_printf(m, "DWord:\t\t%lu\n", se_dword);
79 seq_printf(m, "Multi:\t\t%lu\n", se_multi);
80 seq_printf(m, "User faults:\t%i (%s)\n", se_usermode,
81 se_usermode_action[se_usermode]);
82 seq_printf(m, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn,
83 se_kernmode_warn ? "+warn" : "");
84 return 0;
85}
86
87static int alignment_proc_open(struct inode *inode, struct file *file)
88{
89 return single_open(file, alignment_proc_show, NULL);
90}
91
92static ssize_t alignment_proc_write(struct file *file,
93 const char __user *buffer, size_t count, loff_t *pos)
94{
95 int *data = PDE(file->f_path.dentry->d_inode)->data;
96 char mode;
97
98 if (count > 0) {
99 if (get_user(mode, buffer))
100 return -EFAULT;
101 if (mode >= '0' && mode <= '5')
102 *data = mode - '0';
103 }
104 return count;
105}
106
107static const struct file_operations alignment_proc_fops = {
108 .owner = THIS_MODULE,
109 .open = alignment_proc_open,
110 .read = seq_read,
111 .llseek = seq_lseek,
112 .release = single_release,
113 .write = alignment_proc_write,
114};
115#endif
116
117static void dump_mem(const char *str, unsigned long bottom, unsigned long top) 50static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
118{ 51{
119 unsigned long p; 52 unsigned long p;
@@ -265,10 +198,10 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
265 count = 1<<(instruction&3); 198 count = 1<<(instruction&3);
266 199
267 switch (count) { 200 switch (count) {
268 case 1: se_half += 1; break; 201 case 1: inc_unaligned_byte_access(); break;
269 case 2: se_word += 1; break; 202 case 2: inc_unaligned_word_access(); break;
270 case 4: se_dword += 1; break; 203 case 4: inc_unaligned_dword_access(); break;
271 case 8: se_multi += 1; break; /* ??? */ 204 case 8: inc_unaligned_multi_access(); break;
272 } 205 }
273 206
274 ret = -EFAULT; 207 ret = -EFAULT;
@@ -452,18 +385,8 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
452 rm = regs->regs[index]; 385 rm = regs->regs[index];
453 386
454 /* shout about fixups */ 387 /* shout about fixups */
455 if (!expected) { 388 if (!expected)
456 if (user_mode(regs) && (se_usermode & 1) && printk_ratelimit()) 389 unaligned_fixups_notify(current, instruction, regs);
457 pr_notice("Fixing up unaligned userspace access "
458 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
459 current->comm, task_pid_nr(current),
460 (void *)regs->pc, instruction);
461 else if (se_kernmode_warn && printk_ratelimit())
462 pr_notice("Fixing up unaligned kernel access "
463 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
464 current->comm, task_pid_nr(current),
465 (void *)regs->pc, instruction);
466 }
467 390
468 ret = -EFAULT; 391 ret = -EFAULT;
469 switch (instruction&0xF000) { 392 switch (instruction&0xF000) {
@@ -616,10 +539,10 @@ asmlinkage void do_address_error(struct pt_regs *regs,
616 539
617 if (user_mode(regs)) { 540 if (user_mode(regs)) {
618 int si_code = BUS_ADRERR; 541 int si_code = BUS_ADRERR;
542 unsigned int user_action;
619 543
620 local_irq_enable(); 544 local_irq_enable();
621 545 inc_unaligned_user_access();
622 se_user += 1;
623 546
624 set_fs(USER_DS); 547 set_fs(USER_DS);
625 if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1), 548 if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1),
@@ -630,16 +553,12 @@ asmlinkage void do_address_error(struct pt_regs *regs,
630 set_fs(oldfs); 553 set_fs(oldfs);
631 554
632 /* shout about userspace fixups */ 555 /* shout about userspace fixups */
633 if (se_usermode & 1) 556 unaligned_fixups_notify(current, instruction, regs);
634 printk(KERN_NOTICE "Unaligned userspace access "
635 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
636 current->comm, current->pid, (void *)regs->pc,
637 instruction);
638 557
639 if (se_usermode & 2) 558 user_action = unaligned_user_action();
559 if (user_action & UM_FIXUP)
640 goto fixup; 560 goto fixup;
641 561 if (user_action & UM_SIGNAL)
642 if (se_usermode & 4)
643 goto uspace_segv; 562 goto uspace_segv;
644 else { 563 else {
645 /* ignore */ 564 /* ignore */
@@ -659,7 +578,7 @@ fixup:
659 &user_mem_access, 0); 578 &user_mem_access, 0);
660 set_fs(oldfs); 579 set_fs(oldfs);
661 580
662 if (tmp==0) 581 if (tmp == 0)
663 return; /* sorted */ 582 return; /* sorted */
664uspace_segv: 583uspace_segv:
665 printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " 584 printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
@@ -672,7 +591,7 @@ uspace_segv:
672 info.si_addr = (void __user *)address; 591 info.si_addr = (void __user *)address;
673 force_sig_info(SIGBUS, &info, current); 592 force_sig_info(SIGBUS, &info, current);
674 } else { 593 } else {
675 se_sys += 1; 594 inc_unaligned_kernel_access();
676 595
677 if (regs->pc & 1) 596 if (regs->pc & 1)
678 die("unaligned program counter", regs, error_code); 597 die("unaligned program counter", regs, error_code);
@@ -687,11 +606,7 @@ uspace_segv:
687 die("insn faulting in do_address_error", regs, 0); 606 die("insn faulting in do_address_error", regs, 0);
688 } 607 }
689 608
690 if (se_kernmode_warn) 609 unaligned_fixups_notify(current, instruction, regs);
691 printk(KERN_NOTICE "Unaligned kernel access "
692 "on behalf of \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
693 current->comm, current->pid, (void *)regs->pc,
694 instruction);
695 610
696 handle_unaligned_access(instruction, regs, 611 handle_unaligned_access(instruction, regs,
697 &user_mem_access, 0); 612 &user_mem_access, 0);
@@ -876,35 +791,10 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
876 die_if_kernel("exception", regs, ex); 791 die_if_kernel("exception", regs, ex);
877} 792}
878 793
879#if defined(CONFIG_SH_STANDARD_BIOS)
880void *gdb_vbr_vector;
881
882static inline void __init gdb_vbr_init(void)
883{
884 register unsigned long vbr;
885
886 /*
887 * Read the old value of the VBR register to initialise
888 * the vector through which debug and BIOS traps are
889 * delegated by the Linux trap handler.
890 */
891 asm volatile("stc vbr, %0" : "=r" (vbr));
892
893 gdb_vbr_vector = (void *)(vbr + 0x100);
894 printk("Setting GDB trap vector to 0x%08lx\n",
895 (unsigned long)gdb_vbr_vector);
896}
897#endif
898
899void __cpuinit per_cpu_trap_init(void) 794void __cpuinit per_cpu_trap_init(void)
900{ 795{
901 extern void *vbr_base; 796 extern void *vbr_base;
902 797
903#ifdef CONFIG_SH_STANDARD_BIOS
904 if (raw_smp_processor_id() == 0)
905 gdb_vbr_init();
906#endif
907
908 /* NOTE: The VBR value should be at P1 798 /* NOTE: The VBR value should be at P1
909 (or P2, virtural "fixed" address space). 799 (or P2, virtural "fixed" address space).
910 It's definitely should not in physical address. */ 800 It's definitely should not in physical address. */
@@ -956,9 +846,12 @@ void __init trap_init(void)
956#endif 846#endif
957 847
958#ifdef TRAP_UBC 848#ifdef TRAP_UBC
959 set_exception_table_vec(TRAP_UBC, break_point_trap); 849 set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
960#endif 850#endif
961 851
852 /* Save off the BIOS VBR, if there is one */
853 sh_bios_vbr_init();
854
962 /* Setup VBR for boot cpu */ 855 /* Setup VBR for boot cpu */
963 per_cpu_trap_init(); 856 per_cpu_trap_init();
964} 857}
@@ -985,34 +878,3 @@ void dump_stack(void)
985 show_stack(NULL, NULL); 878 show_stack(NULL, NULL);
986} 879}
987EXPORT_SYMBOL(dump_stack); 880EXPORT_SYMBOL(dump_stack);
988
989#ifdef CONFIG_PROC_FS
990/*
991 * This needs to be done after sysctl_init, otherwise sys/ will be
992 * overwritten. Actually, this shouldn't be in sys/ at all since
993 * it isn't a sysctl, and it doesn't contain sysctl information.
994 * We now locate it in /proc/cpu/alignment instead.
995 */
996static int __init alignment_init(void)
997{
998 struct proc_dir_entry *dir, *res;
999
1000 dir = proc_mkdir("cpu", NULL);
1001 if (!dir)
1002 return -ENOMEM;
1003
1004 res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir,
1005 &alignment_proc_fops, &se_usermode);
1006 if (!res)
1007 return -ENOMEM;
1008
1009 res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir,
1010 &alignment_proc_fops, &se_kernmode_warn);
1011 if (!res)
1012 return -ENOMEM;
1013
1014 return 0;
1015}
1016
1017fs_initcall(alignment_init);
1018#endif
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index d6c15cae0912..1fcdb1220975 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -471,10 +471,10 @@ static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_reg
471 * denormal_to_double - Given denormalized float number, 471 * denormal_to_double - Given denormalized float number,
472 * store double float 472 * store double float
473 * 473 *
474 * @fpu: Pointer to sh_fpu_hard structure 474 * @fpu: Pointer to sh_fpu_soft structure
475 * @n: Index to FP register 475 * @n: Index to FP register
476 */ 476 */
477static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n) 477static void denormal_to_double(struct sh_fpu_soft_struct *fpu, int n)
478{ 478{
479 unsigned long du, dl; 479 unsigned long du, dl;
480 unsigned long x = fpu->fpul; 480 unsigned long x = fpu->fpul;
@@ -552,11 +552,11 @@ static int ieee_fpe_handler(struct pt_regs *regs)
552 if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ 552 if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
553 struct task_struct *tsk = current; 553 struct task_struct *tsk = current;
554 554
555 if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) { 555 if ((tsk->thread.xstate->softfpu.fpscr & (1 << 17))) {
556 /* FPU error */ 556 /* FPU error */
557 denormal_to_double (&tsk->thread.fpu.hard, 557 denormal_to_double (&tsk->thread.xstate->softfpu,
558 (finsn >> 8) & 0xf); 558 (finsn >> 8) & 0xf);
559 tsk->thread.fpu.hard.fpscr &= 559 tsk->thread.xstate->softfpu.fpscr &=
560 ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); 560 ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
561 task_thread_info(tsk)->status |= TS_USEDFPU; 561 task_thread_info(tsk)->status |= TS_USEDFPU;
562 } else { 562 } else {
@@ -617,7 +617,7 @@ static void fpu_init(struct sh_fpu_soft_struct *fpu)
617int do_fpu_inst(unsigned short inst, struct pt_regs *regs) 617int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
618{ 618{
619 struct task_struct *tsk = current; 619 struct task_struct *tsk = current;
620 struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft); 620 struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
621 621
622 if (!(task_thread_info(tsk)->status & TS_USEDFPU)) { 622 if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
623 /* initialize once. */ 623 /* initialize once. */
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 986a71b88ca3..358c860aeb9b 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -189,13 +189,31 @@ config ARCH_MEMORY_PROBE
189 depends on MEMORY_HOTPLUG 189 depends on MEMORY_HOTPLUG
190 190
191choice 191choice
192 prompt "Page table layout"
193 default PGTABLE_LEVELS_3 if X2TLB
194 default PGTABLE_LEVELS_2
195
196config PGTABLE_LEVELS_2
197 bool "2 Levels"
198 help
199 This is the default page table layout for all SuperH CPUs.
200
201config PGTABLE_LEVELS_3
202 bool "3 Levels"
203 depends on X2TLB
204 help
205 This enables a 3 level page table structure.
206
207endchoice
208
209choice
192 prompt "Kernel page size" 210 prompt "Kernel page size"
193 default PAGE_SIZE_8KB if X2TLB 211 default PAGE_SIZE_8KB if X2TLB
194 default PAGE_SIZE_4KB 212 default PAGE_SIZE_4KB
195 213
196config PAGE_SIZE_4KB 214config PAGE_SIZE_4KB
197 bool "4kB" 215 bool "4kB"
198 depends on !MMU || !X2TLB 216 depends on !MMU || !X2TLB || PGTABLE_LEVELS_3
199 help 217 help
200 This is the default page size used by all SuperH CPUs. 218 This is the default page size used by all SuperH CPUs.
201 219
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 8a70535fa7ce..9fa11d655044 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the Linux SuperH-specific parts of the memory manager. 2# Makefile for the Linux SuperH-specific parts of the memory manager.
3# 3#
4 4
5obj-y := cache.o init.o consistent.o mmap.o 5obj-y := alignment.o cache.o init.o consistent.o mmap.o
6 6
7cacheops-$(CONFIG_CPU_SH2) := cache-sh2.o 7cacheops-$(CONFIG_CPU_SH2) := cache-sh2.o
8cacheops-$(CONFIG_CPU_SH2A) := cache-sh2a.o 8cacheops-$(CONFIG_CPU_SH2A) := cache-sh2a.o
@@ -15,7 +15,7 @@ obj-y += $(cacheops-y)
15 15
16mmu-y := nommu.o extable_32.o 16mmu-y := nommu.o extable_32.o
17mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \ 17mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \
18 ioremap_$(BITS).o kmap.o tlbflush_$(BITS).o 18 ioremap_$(BITS).o kmap.o pgtable.o tlbflush_$(BITS).o
19 19
20obj-y += $(mmu-y) 20obj-y += $(mmu-y)
21obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o 21obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o
diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c
new file mode 100644
index 000000000000..e615151eac3b
--- /dev/null
+++ b/arch/sh/mm/alignment.c
@@ -0,0 +1,159 @@
1/*
2 * Alignment access counters and corresponding user-space interfaces.
3 *
4 * Copyright (C) 2009 ST Microelectronics
5 * Copyright (C) 2009 - 2010 Paul Mundt
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/seq_file.h>
14#include <linux/proc_fs.h>
15#include <linux/uaccess.h>
16#include <asm/alignment.h>
17
18static unsigned long se_user;
19static unsigned long se_sys;
20static unsigned long se_half;
21static unsigned long se_word;
22static unsigned long se_dword;
23static unsigned long se_multi;
24/* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
25 valid! */
26static int se_usermode = UM_WARN | UM_FIXUP;
27/* 0: no warning 1: print a warning message, disabled by default */
28static int se_kernmode_warn;
29
30void inc_unaligned_byte_access(void)
31{
32 se_half++;
33}
34
35void inc_unaligned_word_access(void)
36{
37 se_word++;
38}
39
40void inc_unaligned_dword_access(void)
41{
42 se_dword++;
43}
44
45void inc_unaligned_multi_access(void)
46{
47 se_multi++;
48}
49
50void inc_unaligned_user_access(void)
51{
52 se_user++;
53}
54
55void inc_unaligned_kernel_access(void)
56{
57 se_sys++;
58}
59
60unsigned int unaligned_user_action(void)
61{
62 return se_usermode;
63}
64
65void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn,
66 struct pt_regs *regs)
67{
68 if (user_mode(regs) && (se_usermode & UM_WARN) && printk_ratelimit())
69 pr_notice("Fixing up unaligned userspace access "
70 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
71 tsk->comm, task_pid_nr(tsk),
72 (void *)regs->pc, insn);
73 else if (se_kernmode_warn && printk_ratelimit())
74 pr_notice("Fixing up unaligned kernel access "
75 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
76 tsk->comm, task_pid_nr(tsk),
77 (void *)regs->pc, insn);
78}
79
80static const char *se_usermode_action[] = {
81 "ignored",
82 "warn",
83 "fixup",
84 "fixup+warn",
85 "signal",
86 "signal+warn"
87};
88
89static int alignment_proc_show(struct seq_file *m, void *v)
90{
91 seq_printf(m, "User:\t\t%lu\n", se_user);
92 seq_printf(m, "System:\t\t%lu\n", se_sys);
93 seq_printf(m, "Half:\t\t%lu\n", se_half);
94 seq_printf(m, "Word:\t\t%lu\n", se_word);
95 seq_printf(m, "DWord:\t\t%lu\n", se_dword);
96 seq_printf(m, "Multi:\t\t%lu\n", se_multi);
97 seq_printf(m, "User faults:\t%i (%s)\n", se_usermode,
98 se_usermode_action[se_usermode]);
99 seq_printf(m, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn,
100 se_kernmode_warn ? "+warn" : "");
101 return 0;
102}
103
104static int alignment_proc_open(struct inode *inode, struct file *file)
105{
106 return single_open(file, alignment_proc_show, NULL);
107}
108
109static ssize_t alignment_proc_write(struct file *file,
110 const char __user *buffer, size_t count, loff_t *pos)
111{
112 int *data = PDE(file->f_path.dentry->d_inode)->data;
113 char mode;
114
115 if (count > 0) {
116 if (get_user(mode, buffer))
117 return -EFAULT;
118 if (mode >= '0' && mode <= '5')
119 *data = mode - '0';
120 }
121 return count;
122}
123
124static const struct file_operations alignment_proc_fops = {
125 .owner = THIS_MODULE,
126 .open = alignment_proc_open,
127 .read = seq_read,
128 .llseek = seq_lseek,
129 .release = single_release,
130 .write = alignment_proc_write,
131};
132
133/*
134 * This needs to be done after sysctl_init, otherwise sys/ will be
135 * overwritten. Actually, this shouldn't be in sys/ at all since
136 * it isn't a sysctl, and it doesn't contain sysctl information.
137 * We now locate it in /proc/cpu/alignment instead.
138 */
139static int __init alignment_init(void)
140{
141 struct proc_dir_entry *dir, *res;
142
143 dir = proc_mkdir("cpu", NULL);
144 if (!dir)
145 return -ENOMEM;
146
147 res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir,
148 &alignment_proc_fops, &se_usermode);
149 if (!res)
150 return -ENOMEM;
151
152 res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir,
153 &alignment_proc_fops, &se_kernmode_warn);
154 if (!res)
155 return -ENOMEM;
156
157 return 0;
158}
159fs_initcall(alignment_init);
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 560ddb6bc8a7..a2301daeefa3 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -109,6 +109,7 @@ static inline void flush_cache_one(unsigned long start, unsigned long phys)
109static void sh4_flush_dcache_page(void *arg) 109static void sh4_flush_dcache_page(void *arg)
110{ 110{
111 struct page *page = arg; 111 struct page *page = arg;
112 unsigned long addr = (unsigned long)page_address(page);
112#ifndef CONFIG_SMP 113#ifndef CONFIG_SMP
113 struct address_space *mapping = page_mapping(page); 114 struct address_space *mapping = page_mapping(page);
114 115
@@ -116,16 +117,8 @@ static void sh4_flush_dcache_page(void *arg)
116 set_bit(PG_dcache_dirty, &page->flags); 117 set_bit(PG_dcache_dirty, &page->flags);
117 else 118 else
118#endif 119#endif
119 { 120 flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
120 unsigned long phys = page_to_phys(page); 121 (addr & shm_align_mask), page_to_phys(page));
121 unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
122 int i, n;
123
124 /* Loop all the D-cache */
125 n = boot_cpu_data.dcache.n_aliases;
126 for (i = 0; i < n; i++, addr += PAGE_SIZE)
127 flush_cache_one(addr, phys);
128 }
129 122
130 wmb(); 123 wmb();
131} 124}
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index 47530104e0ad..28e22839c665 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -53,6 +53,9 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
53 if (!pud_present(*pud_k)) 53 if (!pud_present(*pud_k))
54 return NULL; 54 return NULL;
55 55
56 if (!pud_present(*pud))
57 set_pud(pud, *pud_k);
58
56 pmd = pmd_offset(pud, address); 59 pmd = pmd_offset(pud, address);
57 pmd_k = pmd_offset(pud_k, address); 60 pmd_k = pmd_offset(pud_k, address);
58 if (!pmd_present(*pmd_k)) 61 if (!pmd_present(*pmd_k))
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 432acd07e76a..d5fb014279ad 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -120,7 +120,13 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
120 for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { 120 for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
121 pud = (pud_t *)pgd; 121 pud = (pud_t *)pgd;
122 for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) { 122 for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
123#ifdef __PAGETABLE_PMD_FOLDED
123 pmd = (pmd_t *)pud; 124 pmd = (pmd_t *)pud;
125#else
126 pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
127 pud_populate(&init_mm, pud, pmd);
128 pmd += k;
129#endif
124 for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { 130 for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
125 if (pmd_none(*pmd)) { 131 if (pmd_none(*pmd)) {
126 pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); 132 pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
@@ -277,35 +283,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
277} 283}
278#endif 284#endif
279 285
280#if THREAD_SHIFT < PAGE_SHIFT
281static struct kmem_cache *thread_info_cache;
282
283struct thread_info *alloc_thread_info(struct task_struct *tsk)
284{
285 struct thread_info *ti;
286
287 ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
288 if (unlikely(ti == NULL))
289 return NULL;
290#ifdef CONFIG_DEBUG_STACK_USAGE
291 memset(ti, 0, THREAD_SIZE);
292#endif
293 return ti;
294}
295
296void free_thread_info(struct thread_info *ti)
297{
298 kmem_cache_free(thread_info_cache, ti);
299}
300
301void thread_info_cache_init(void)
302{
303 thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
304 THREAD_SIZE, 0, NULL);
305 BUG_ON(thread_info_cache == NULL);
306}
307#endif /* THREAD_SHIFT < PAGE_SHIFT */
308
309#ifdef CONFIG_MEMORY_HOTPLUG 286#ifdef CONFIG_MEMORY_HOTPLUG
310int arch_add_memory(int nid, u64 start, u64 size) 287int arch_add_memory(int nid, u64 start, u64 size)
311{ 288{
diff --git a/arch/sh/mm/nommu.c b/arch/sh/mm/nommu.c
index ac16c05917ef..7694f50c9034 100644
--- a/arch/sh/mm/nommu.c
+++ b/arch/sh/mm/nommu.c
@@ -94,3 +94,7 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
94void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) 94void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
95{ 95{
96} 96}
97
98void pgtable_cache_init(void)
99{
100}
diff --git a/arch/sh/mm/pgtable.c b/arch/sh/mm/pgtable.c
new file mode 100644
index 000000000000..e1bc5483cc07
--- /dev/null
+++ b/arch/sh/mm/pgtable.c
@@ -0,0 +1,57 @@
1#include <linux/mm.h>
2
3#define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO
4
5static struct kmem_cache *pgd_cachep;
6
7#ifdef CONFIG_PGTABLE_LEVELS_3
8static struct kmem_cache *pmd_cachep;
9#endif
10
11void pgd_ctor(void *x)
12{
13 pgd_t *pgd = x;
14
15 memcpy(pgd + USER_PTRS_PER_PGD,
16 swapper_pg_dir + USER_PTRS_PER_PGD,
17 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
18}
19
20void pgtable_cache_init(void)
21{
22 pgd_cachep = kmem_cache_create("pgd_cache",
23 PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
24 PAGE_SIZE, SLAB_PANIC, pgd_ctor);
25#ifdef CONFIG_PGTABLE_LEVELS_3
26 pmd_cachep = kmem_cache_create("pmd_cache",
27 PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
28 PAGE_SIZE, SLAB_PANIC, NULL);
29#endif
30}
31
32pgd_t *pgd_alloc(struct mm_struct *mm)
33{
34 return kmem_cache_alloc(pgd_cachep, PGALLOC_GFP);
35}
36
37void pgd_free(struct mm_struct *mm, pgd_t *pgd)
38{
39 kmem_cache_free(pgd_cachep, pgd);
40}
41
42#ifdef CONFIG_PGTABLE_LEVELS_3
43void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
44{
45 set_pud(pud, __pud((unsigned long)pmd));
46}
47
48pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
49{
50 return kmem_cache_alloc(pmd_cachep, PGALLOC_GFP);
51}
52
53void pmd_free(struct mm_struct *mm, pmd_t *pmd)
54{
55 kmem_cache_free(pmd_cachep, pmd);
56}
57#endif /* CONFIG_PGTABLE_LEVELS_3 */