aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/kernel
diff options
context:
space:
mode:
authorAkira Takeuchi <takeuchi.akr@jp.panasonic.com>2010-10-27 12:28:52 -0400
committerDavid Howells <dhowells@redhat.com>2010-10-27 12:28:52 -0400
commit278d91c4609d55202c1e63d5fc5f01466cc7bbab (patch)
tree8b0c863837508959430c1741e2e5a2d37d2890d4 /arch/mn10300/kernel
parent965ea4bbb9ae926358273368144ba838c561bc38 (diff)
MN10300: Make the FPU operate in non-lazy mode under SMP
Make the FPU operate in non-lazy mode under SMP so that when the process that is currently using the FPU migrates to a different CPU, we don't have to ping its previous CPU to flush the FPU context. Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com> Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'arch/mn10300/kernel')
-rw-r--r--arch/mn10300/kernel/Makefile8
-rw-r--r--arch/mn10300/kernel/asm-offsets.c9
-rw-r--r--arch/mn10300/kernel/fpu-low.S265
-rw-r--r--arch/mn10300/kernel/fpu-nofpu-low.S39
-rw-r--r--arch/mn10300/kernel/fpu-nofpu.c30
-rw-r--r--arch/mn10300/kernel/fpu.c141
-rw-r--r--arch/mn10300/kernel/traps.c2
7 files changed, 302 insertions, 192 deletions
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index c4289e388071..99022351717a 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -3,13 +3,15 @@
3# 3#
4extra-y := head.o init_task.o vmlinux.lds 4extra-y := head.o init_task.o vmlinux.lds
5 5
6obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \ 6fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
7fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
8
9obj-y := process.o signal.o entry.o traps.o irq.o \
7 ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ 10 ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
8 switch_to.o mn10300_ksyms.o kernel_execve.o 11 switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
9 12
10obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o 13obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
11 14
12obj-$(CONFIG_FPU) += fpu-low.o
13 15
14obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \ 16obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
15 mn10300-debug.o 17 mn10300-debug.o
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
index 02dc7e461fef..78e290e342fc 100644
--- a/arch/mn10300/kernel/asm-offsets.c
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -67,6 +67,15 @@ void foo(void)
67 OFFSET(THREAD_A3, thread_struct, a3); 67 OFFSET(THREAD_A3, thread_struct, a3);
68 OFFSET(THREAD_USP, thread_struct, usp); 68 OFFSET(THREAD_USP, thread_struct, usp);
69 OFFSET(THREAD_FRAME, thread_struct, __frame); 69 OFFSET(THREAD_FRAME, thread_struct, __frame);
70#ifdef CONFIG_FPU
71 OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags);
72 OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state);
73 DEFINE(__THREAD_USING_FPU, THREAD_USING_FPU);
74 DEFINE(__THREAD_HAS_FPU, THREAD_HAS_FPU);
75#endif /* CONFIG_FPU */
76 BLANK();
77
78 OFFSET(TASK_THREAD, task_struct, thread);
70 BLANK(); 79 BLANK();
71 80
72 DEFINE(CLONE_VM_asm, CLONE_VM); 81 DEFINE(CLONE_VM_asm, CLONE_VM);
diff --git a/arch/mn10300/kernel/fpu-low.S b/arch/mn10300/kernel/fpu-low.S
index 96cfd47e68d5..78df25cfae29 100644
--- a/arch/mn10300/kernel/fpu-low.S
+++ b/arch/mn10300/kernel/fpu-low.S
@@ -8,25 +8,14 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11#include <linux/linkage.h>
11#include <asm/cpu-regs.h> 12#include <asm/cpu-regs.h>
13#include <asm/smp.h>
14#include <asm/thread_info.h>
15#include <asm/asm-offsets.h>
16#include <asm/frame.inc>
12 17
13############################################################################### 18.macro FPU_INIT_STATE_ALL
14#
15# void fpu_init_state(void)
16# - initialise the FPU
17#
18###############################################################################
19 .globl fpu_init_state
20 .type fpu_init_state,@function
21fpu_init_state:
22 mov epsw,d0
23 or EPSW_FE,epsw
24
25#ifdef CONFIG_MN10300_PROC_MN103E010
26 nop
27 nop
28 nop
29#endif
30 fmov 0,fs0 19 fmov 0,fs0
31 fmov fs0,fs1 20 fmov fs0,fs1
32 fmov fs0,fs2 21 fmov fs0,fs2
@@ -60,7 +49,100 @@ fpu_init_state:
60 fmov fs0,fs30 49 fmov fs0,fs30
61 fmov fs0,fs31 50 fmov fs0,fs31
62 fmov FPCR_INIT,fpcr 51 fmov FPCR_INIT,fpcr
52.endm
53
54.macro FPU_SAVE_ALL areg,dreg
55 fmov fs0,(\areg+)
56 fmov fs1,(\areg+)
57 fmov fs2,(\areg+)
58 fmov fs3,(\areg+)
59 fmov fs4,(\areg+)
60 fmov fs5,(\areg+)
61 fmov fs6,(\areg+)
62 fmov fs7,(\areg+)
63 fmov fs8,(\areg+)
64 fmov fs9,(\areg+)
65 fmov fs10,(\areg+)
66 fmov fs11,(\areg+)
67 fmov fs12,(\areg+)
68 fmov fs13,(\areg+)
69 fmov fs14,(\areg+)
70 fmov fs15,(\areg+)
71 fmov fs16,(\areg+)
72 fmov fs17,(\areg+)
73 fmov fs18,(\areg+)
74 fmov fs19,(\areg+)
75 fmov fs20,(\areg+)
76 fmov fs21,(\areg+)
77 fmov fs22,(\areg+)
78 fmov fs23,(\areg+)
79 fmov fs24,(\areg+)
80 fmov fs25,(\areg+)
81 fmov fs26,(\areg+)
82 fmov fs27,(\areg+)
83 fmov fs28,(\areg+)
84 fmov fs29,(\areg+)
85 fmov fs30,(\areg+)
86 fmov fs31,(\areg+)
87 fmov fpcr,\dreg
88 mov \dreg,(\areg)
89.endm
90
91.macro FPU_RESTORE_ALL areg,dreg
92 fmov (\areg+),fs0
93 fmov (\areg+),fs1
94 fmov (\areg+),fs2
95 fmov (\areg+),fs3
96 fmov (\areg+),fs4
97 fmov (\areg+),fs5
98 fmov (\areg+),fs6
99 fmov (\areg+),fs7
100 fmov (\areg+),fs8
101 fmov (\areg+),fs9
102 fmov (\areg+),fs10
103 fmov (\areg+),fs11
104 fmov (\areg+),fs12
105 fmov (\areg+),fs13
106 fmov (\areg+),fs14
107 fmov (\areg+),fs15
108 fmov (\areg+),fs16
109 fmov (\areg+),fs17
110 fmov (\areg+),fs18
111 fmov (\areg+),fs19
112 fmov (\areg+),fs20
113 fmov (\areg+),fs21
114 fmov (\areg+),fs22
115 fmov (\areg+),fs23
116 fmov (\areg+),fs24
117 fmov (\areg+),fs25
118 fmov (\areg+),fs26
119 fmov (\areg+),fs27
120 fmov (\areg+),fs28
121 fmov (\areg+),fs29
122 fmov (\areg+),fs30
123 fmov (\areg+),fs31
124 mov (\areg),\dreg
125 fmov \dreg,fpcr
126.endm
63 127
128###############################################################################
129#
130# void fpu_init_state(void)
131# - initialise the FPU
132#
133###############################################################################
134 .globl fpu_init_state
135 .type fpu_init_state,@function
136fpu_init_state:
137 mov epsw,d0
138 or EPSW_FE,epsw
139
140#ifdef CONFIG_MN10300_PROC_MN103E010
141 nop
142 nop
143 nop
144#endif
145 FPU_INIT_STATE_ALL
64#ifdef CONFIG_MN10300_PROC_MN103E010 146#ifdef CONFIG_MN10300_PROC_MN103E010
65 nop 147 nop
66 nop 148 nop
@@ -89,40 +171,7 @@ fpu_save:
89 nop 171 nop
90#endif 172#endif
91 mov d0,a0 173 mov d0,a0
92 fmov fs0,(a0+) 174 FPU_SAVE_ALL a0,d0
93 fmov fs1,(a0+)
94 fmov fs2,(a0+)
95 fmov fs3,(a0+)
96 fmov fs4,(a0+)
97 fmov fs5,(a0+)
98 fmov fs6,(a0+)
99 fmov fs7,(a0+)
100 fmov fs8,(a0+)
101 fmov fs9,(a0+)
102 fmov fs10,(a0+)
103 fmov fs11,(a0+)
104 fmov fs12,(a0+)
105 fmov fs13,(a0+)
106 fmov fs14,(a0+)
107 fmov fs15,(a0+)
108 fmov fs16,(a0+)
109 fmov fs17,(a0+)
110 fmov fs18,(a0+)
111 fmov fs19,(a0+)
112 fmov fs20,(a0+)
113 fmov fs21,(a0+)
114 fmov fs22,(a0+)
115 fmov fs23,(a0+)
116 fmov fs24,(a0+)
117 fmov fs25,(a0+)
118 fmov fs26,(a0+)
119 fmov fs27,(a0+)
120 fmov fs28,(a0+)
121 fmov fs29,(a0+)
122 fmov fs30,(a0+)
123 fmov fs31,(a0+)
124 fmov fpcr,d0
125 mov d0,(a0)
126#ifdef CONFIG_MN10300_PROC_MN103E010 175#ifdef CONFIG_MN10300_PROC_MN103E010
127 nop 176 nop
128 nop 177 nop
@@ -135,63 +184,75 @@ fpu_save:
135 184
136############################################################################### 185###############################################################################
137# 186#
138# void fpu_restore(struct fpu_state_struct *) 187# void fpu_disabled(void)
139# - restore the fpu state 188# - handle an exception due to the FPU being disabled
140# - note that an FPU Operational exception might occur during this process 189# when CONFIG_FPU is enabled
141# 190#
142############################################################################### 191###############################################################################
143 .globl fpu_restore 192 .type fpu_disabled,@function
144 .type fpu_restore,@function 193 .globl fpu_disabled
145fpu_restore: 194fpu_disabled:
146 mov epsw,d1 195 or EPSW_nAR|EPSW_FE,epsw
147 or EPSW_FE,epsw /* enable the FPU so we can access it */
148
149#ifdef CONFIG_MN10300_PROC_MN103E010
150 nop 196 nop
151 nop 197 nop
152#endif
153 mov d0,a0
154 fmov (a0+),fs0
155 fmov (a0+),fs1
156 fmov (a0+),fs2
157 fmov (a0+),fs3
158 fmov (a0+),fs4
159 fmov (a0+),fs5
160 fmov (a0+),fs6
161 fmov (a0+),fs7
162 fmov (a0+),fs8
163 fmov (a0+),fs9
164 fmov (a0+),fs10
165 fmov (a0+),fs11
166 fmov (a0+),fs12
167 fmov (a0+),fs13
168 fmov (a0+),fs14
169 fmov (a0+),fs15
170 fmov (a0+),fs16
171 fmov (a0+),fs17
172 fmov (a0+),fs18
173 fmov (a0+),fs19
174 fmov (a0+),fs20
175 fmov (a0+),fs21
176 fmov (a0+),fs22
177 fmov (a0+),fs23
178 fmov (a0+),fs24
179 fmov (a0+),fs25
180 fmov (a0+),fs26
181 fmov (a0+),fs27
182 fmov (a0+),fs28
183 fmov (a0+),fs29
184 fmov (a0+),fs30
185 fmov (a0+),fs31
186 mov (a0),d0
187 fmov d0,fpcr
188#ifdef CONFIG_MN10300_PROC_MN103E010
189 nop 198 nop
199
200 mov sp,a1
201 mov (a1),d1 /* get epsw of user context */
202 and ~(THREAD_SIZE-1),a1 /* a1: (thread_info *ti) */
203 mov (TI_task,a1),a2 /* a2: (task_struct *tsk) */
204 btst EPSW_nSL,d1
205 beq fpu_used_in_kernel
206
207 or EPSW_FE,d1
208 mov d1,(sp)
209 mov (TASK_THREAD+THREAD_FPU_FLAGS,a2),d1
210#ifndef CONFIG_LAZY_SAVE_FPU
211 or __THREAD_HAS_FPU,d1
212 mov d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2)
213#else /* !CONFIG_LAZY_SAVE_FPU */
214 mov (fpu_state_owner),a0
215 cmp 0,a0
216 beq fpu_regs_save_end
217
218 mov (TASK_THREAD+THREAD_UREGS,a0),a1
219 add TASK_THREAD+THREAD_FPU_STATE,a0
220 FPU_SAVE_ALL a0,d0
221
222 mov (REG_EPSW,a1),d0
223 and ~EPSW_FE,d0
224 mov d0,(REG_EPSW,a1)
225
226fpu_regs_save_end:
227 mov a2,(fpu_state_owner)
228#endif /* !CONFIG_LAZY_SAVE_FPU */
229
230 btst __THREAD_USING_FPU,d1
231 beq fpu_regs_init
232 add TASK_THREAD+THREAD_FPU_STATE,a2
233 FPU_RESTORE_ALL a2,d0
234 rti
235
236fpu_regs_init:
237 FPU_INIT_STATE_ALL
238 add TASK_THREAD+THREAD_FPU_FLAGS,a2
239 bset __THREAD_USING_FPU,(0,a2)
240 rti
241
242fpu_used_in_kernel:
243 and ~(EPSW_nAR|EPSW_FE),epsw
190 nop 244 nop
191 nop 245 nop
192#endif
193 246
194 mov d1,epsw 247 add -4,sp
195 ret [],0 248 SAVE_ALL
249 mov -1,d0
250 mov d0,(REG_ORIG_D0,fp)
251
252 and ~EPSW_NMID,epsw
253
254 mov fp,d0
255 call fpu_disabled_in_kernel[],0
256 jmp ret_from_exception
196 257
197 .size fpu_restore,.-fpu_restore 258 .size fpu_disabled,.-fpu_disabled
diff --git a/arch/mn10300/kernel/fpu-nofpu-low.S b/arch/mn10300/kernel/fpu-nofpu-low.S
new file mode 100644
index 000000000000..7ea087a549f4
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-nofpu-low.S
@@ -0,0 +1,39 @@
1/* MN10300 Low level FPU management operations
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/linkage.h>
12#include <asm/cpu-regs.h>
13#include <asm/smp.h>
14#include <asm/thread_info.h>
15#include <asm/asm-offsets.h>
16#include <asm/frame.inc>
17
18###############################################################################
19#
20# void fpu_disabled(void)
21# - handle an exception due to the FPU being disabled
22# when CONFIG_FPU is disabled
23#
24###############################################################################
25 .type fpu_disabled,@function
26 .globl fpu_disabled
27fpu_disabled:
28 add -4,sp
29 SAVE_ALL
30 mov -1,d0
31 mov d0,(REG_ORIG_D0,fp)
32
33 and ~EPSW_NMID,epsw
34
35 mov fp,d0
36 call unexpected_fpu_exception[],0
37 jmp ret_from_exception
38
39 .size fpu_disabled,.-fpu_disabled
diff --git a/arch/mn10300/kernel/fpu-nofpu.c b/arch/mn10300/kernel/fpu-nofpu.c
new file mode 100644
index 000000000000..31c765b92c5d
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-nofpu.c
@@ -0,0 +1,30 @@
1/* MN10300 FPU management
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/fpu.h>
12
13/*
14 * handle an FPU operational exception
15 * - there's a possibility that if the FPU is asynchronous, the signal might
16 * be meant for a process other than the current one
17 */
18asmlinkage
19void unexpected_fpu_exception(struct pt_regs *regs, enum exception_code code)
20{
21 panic("An FPU exception was received, but there's no FPU enabled.");
22}
23
24/*
25 * fill in the FPU structure for a core dump
26 */
27int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
28{
29 return 0; /* not valid */
30}
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
index e705f25ad5ff..5f9c3fa19a85 100644
--- a/arch/mn10300/kernel/fpu.c
+++ b/arch/mn10300/kernel/fpu.c
@@ -12,56 +12,19 @@
12#include <asm/fpu.h> 12#include <asm/fpu.h>
13#include <asm/elf.h> 13#include <asm/elf.h>
14#include <asm/exceptions.h> 14#include <asm/exceptions.h>
15#include <asm/system.h>
15 16
17#ifdef CONFIG_LAZY_SAVE_FPU
16struct task_struct *fpu_state_owner; 18struct task_struct *fpu_state_owner;
19#endif
17 20
18/* 21/*
19 * handle an exception due to the FPU being disabled 22 * error functions in FPU disabled exception
20 */ 23 */
21asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code) 24asmlinkage void fpu_disabled_in_kernel(struct pt_regs *regs)
22{ 25{
23 struct task_struct *tsk = current; 26 die_if_no_fixup("An FPU Disabled exception happened in kernel space\n",
24 27 regs, EXCEP_FPU_DISABLED);
25 if (!user_mode(regs))
26 die_if_no_fixup("An FPU Disabled exception happened in"
27 " kernel space\n",
28 regs, code);
29
30#ifdef CONFIG_FPU
31 preempt_disable();
32
33 /* transfer the last process's FPU state to memory */
34 if (fpu_state_owner) {
35 fpu_save(&fpu_state_owner->thread.fpu_state);
36 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
37 }
38
39 /* the current process now owns the FPU state */
40 fpu_state_owner = tsk;
41 regs->epsw |= EPSW_FE;
42
43 /* load the FPU with the current process's FPU state or invent a new
44 * clean one if the process doesn't have one */
45 if (is_using_fpu(tsk)) {
46 fpu_restore(&tsk->thread.fpu_state);
47 } else {
48 fpu_init_state();
49 set_using_fpu(tsk);
50 }
51
52 preempt_enable();
53#else
54 {
55 siginfo_t info;
56
57 info.si_signo = SIGFPE;
58 info.si_errno = 0;
59 info.si_addr = (void *) tsk->thread.uregs->pc;
60 info.si_code = FPE_FLTINV;
61
62 force_sig_info(SIGFPE, &info, tsk);
63 }
64#endif /* CONFIG_FPU */
65} 28}
66 29
67/* 30/*
@@ -71,15 +34,16 @@ asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
71 */ 34 */
72asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code) 35asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
73{ 36{
74 struct task_struct *tsk = fpu_state_owner; 37 struct task_struct *tsk = current;
75 siginfo_t info; 38 siginfo_t info;
39 u32 fpcr;
76 40
77 if (!user_mode(regs)) 41 if (!user_mode(regs))
78 die_if_no_fixup("An FPU Operation exception happened in" 42 die_if_no_fixup("An FPU Operation exception happened in"
79 " kernel space\n", 43 " kernel space\n",
80 regs, code); 44 regs, code);
81 45
82 if (!tsk) 46 if (!is_using_fpu(tsk))
83 die_if_no_fixup("An FPU Operation exception happened," 47 die_if_no_fixup("An FPU Operation exception happened,"
84 " but the FPU is not in use", 48 " but the FPU is not in use",
85 regs, code); 49 regs, code);
@@ -89,48 +53,45 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
89 info.si_addr = (void *) tsk->thread.uregs->pc; 53 info.si_addr = (void *) tsk->thread.uregs->pc;
90 info.si_code = FPE_FLTINV; 54 info.si_code = FPE_FLTINV;
91 55
92#ifdef CONFIG_FPU 56 unlazy_fpu(tsk);
93 {
94 u32 fpcr;
95 57
96 /* get FPCR (we need to enable the FPU whilst we do this) */ 58 fpcr = tsk->thread.fpu_state.fpcr;
97 asm volatile(" or %1,epsw \n" 59
98#ifdef CONFIG_MN10300_PROC_MN103E010 60 if (fpcr & FPCR_EC_Z)
99 " nop \n" 61 info.si_code = FPE_FLTDIV;
100 " nop \n" 62 else if (fpcr & FPCR_EC_O)
101 " nop \n" 63 info.si_code = FPE_FLTOVF;
102#endif 64 else if (fpcr & FPCR_EC_U)
103 " fmov fpcr,%0 \n" 65 info.si_code = FPE_FLTUND;
104#ifdef CONFIG_MN10300_PROC_MN103E010 66 else if (fpcr & FPCR_EC_I)
105 " nop \n" 67 info.si_code = FPE_FLTRES;
106 " nop \n"
107 " nop \n"
108#endif
109 " and %2,epsw \n"
110 : "=&d"(fpcr)
111 : "i"(EPSW_FE), "i"(~EPSW_FE)
112 );
113
114 if (fpcr & FPCR_EC_Z)
115 info.si_code = FPE_FLTDIV;
116 else if (fpcr & FPCR_EC_O)
117 info.si_code = FPE_FLTOVF;
118 else if (fpcr & FPCR_EC_U)
119 info.si_code = FPE_FLTUND;
120 else if (fpcr & FPCR_EC_I)
121 info.si_code = FPE_FLTRES;
122 }
123#endif
124 68
125 force_sig_info(SIGFPE, &info, tsk); 69 force_sig_info(SIGFPE, &info, tsk);
126} 70}
127 71
128/* 72/*
73 * handle an FPU invalid_op exception
74 * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
75 */
76asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code)
77{
78 siginfo_t info;
79
80 if (!user_mode(regs))
81 die_if_no_fixup("FPU invalid opcode", regs, code);
82
83 info.si_signo = SIGILL;
84 info.si_errno = 0;
85 info.si_code = ILL_COPROC;
86 info.si_addr = (void *) regs->pc;
87 force_sig_info(info.si_signo, &info, current);
88}
89
90/*
129 * save the FPU state to a signal context 91 * save the FPU state to a signal context
130 */ 92 */
131int fpu_setup_sigcontext(struct fpucontext *fpucontext) 93int fpu_setup_sigcontext(struct fpucontext *fpucontext)
132{ 94{
133#ifdef CONFIG_FPU
134 struct task_struct *tsk = current; 95 struct task_struct *tsk = current;
135 96
136 if (!is_using_fpu(tsk)) 97 if (!is_using_fpu(tsk))
@@ -142,11 +103,19 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
142 */ 103 */
143 preempt_disable(); 104 preempt_disable();
144 105
106#ifndef CONFIG_LAZY_SAVE_FPU
107 if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
108 fpu_save(&tsk->thread.fpu_state);
109 tsk->thread.uregs->epsw &= ~EPSW_FE;
110 tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
111 }
112#else /* !CONFIG_LAZY_SAVE_FPU */
145 if (fpu_state_owner == tsk) { 113 if (fpu_state_owner == tsk) {
146 fpu_save(&tsk->thread.fpu_state); 114 fpu_save(&tsk->thread.fpu_state);
147 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; 115 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
148 fpu_state_owner = NULL; 116 fpu_state_owner = NULL;
149 } 117 }
118#endif /* !CONFIG_LAZY_SAVE_FPU */
150 119
151 preempt_enable(); 120 preempt_enable();
152 121
@@ -161,9 +130,6 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
161 return -1; 130 return -1;
162 131
163 return 1; 132 return 1;
164#else
165 return 0;
166#endif
167} 133}
168 134
169/* 135/*
@@ -171,17 +137,23 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
171 */ 137 */
172void fpu_kill_state(struct task_struct *tsk) 138void fpu_kill_state(struct task_struct *tsk)
173{ 139{
174#ifdef CONFIG_FPU
175 /* disown anything left in the FPU */ 140 /* disown anything left in the FPU */
176 preempt_disable(); 141 preempt_disable();
177 142
143#ifndef CONFIG_LAZY_SAVE_FPU
144 if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
145 tsk->thread.uregs->epsw &= ~EPSW_FE;
146 tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
147 }
148#else /* !CONFIG_LAZY_SAVE_FPU */
178 if (fpu_state_owner == tsk) { 149 if (fpu_state_owner == tsk) {
179 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE; 150 fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
180 fpu_state_owner = NULL; 151 fpu_state_owner = NULL;
181 } 152 }
153#endif /* !CONFIG_LAZY_SAVE_FPU */
182 154
183 preempt_enable(); 155 preempt_enable();
184#endif 156
185 /* we no longer have a valid current FPU state */ 157 /* we no longer have a valid current FPU state */
186 clear_using_fpu(tsk); 158 clear_using_fpu(tsk);
187} 159}
@@ -195,8 +167,7 @@ int fpu_restore_sigcontext(struct fpucontext *fpucontext)
195 int ret; 167 int ret;
196 168
197 /* load up the old FPU state */ 169 /* load up the old FPU state */
198 ret = copy_from_user(&tsk->thread.fpu_state, 170 ret = copy_from_user(&tsk->thread.fpu_state, fpucontext,
199 fpucontext,
200 min(sizeof(struct fpu_state_struct), 171 min(sizeof(struct fpu_state_struct),
201 sizeof(struct fpucontext))); 172 sizeof(struct fpucontext)));
202 if (!ret) 173 if (!ret)
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index c7257a1304a9..716a221df2f9 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -101,7 +101,6 @@ DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC);
101DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); 101DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
102DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); 102DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
103DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); 103DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
104DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC);
105 104
106DO_ERROR(SIGTRAP, 105DO_ERROR(SIGTRAP,
107#ifndef CONFIG_MN10300_USING_JTAG 106#ifndef CONFIG_MN10300_USING_JTAG
@@ -561,7 +560,6 @@ void __init trap_init(void)
561 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); 560 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
562 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); 561 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
563 set_excp_vector(EXCEP_DATINSACC, insn_acc_error); 562 set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
564 set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled);
565 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); 563 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
566 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); 564 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
567 565