patch-2.3.99-pre6 linux/arch/sh/kernel/fpu.c
Next file: linux/arch/sh/kernel/head.S
Previous file: linux/arch/sh/kernel/entry.S
Back to the patch index
Back to the overall index
- Lines: 118
- Date:
Mon Apr 24 13:54:17 2000
- Orig file:
v2.3.99-pre5/linux/arch/sh/kernel/fpu.c
- Orig date:
Tue Apr 11 15:09:14 2000
diff -u --recursive --new-file v2.3.99-pre5/linux/arch/sh/kernel/fpu.c linux/arch/sh/kernel/fpu.c
@@ -23,6 +23,7 @@
{
asm volatile("sts.l $fpul, @-%0\n\t"
"sts.l $fpscr, @-%0\n\t"
+ "lds %1, $fpscr\n\t"
"frchg\n\t"
"fmov.s $fr15, @-%0\n\t"
"fmov.s $fr14, @-%0\n\t"
@@ -58,7 +59,8 @@
"fmov.s $fr1, @-%0\n\t"
"fmov.s $fr0, @-%0"
: /* no output */
- : "r" ((char *)(&tsk->thread.fpu.hard.status))
+ : "r" ((char *)(&tsk->thread.fpu.hard.status)),
+ "r" (FPSCR_INIT)
: "memory");
tsk->flags &= ~PF_USEDFPU;
@@ -68,7 +70,8 @@
static void
restore_fpu(struct task_struct *tsk)
{
- asm volatile("fmov.s @%0+, $fr0\n\t"
+ asm volatile("lds %1, $fpscr\n\t"
+ "fmov.s @%0+, $fr0\n\t"
"fmov.s @%0+, $fr1\n\t"
"fmov.s @%0+, $fr2\n\t"
"fmov.s @%0+, $fr3\n\t"
@@ -105,7 +108,7 @@
"lds.l @%0+, $fpscr\n\t"
"lds.l @%0+, $fpul\n\t"
: /* no output */
- : "r" (&tsk->thread.fpu)
+ : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT)
: "memory");
}
@@ -163,7 +166,6 @@
{
struct task_struct *tsk = current;
- regs.syscall_nr = -1;
regs.pc += 2;
grab_fpu();
@@ -179,15 +181,34 @@
{
struct task_struct *tsk = current;
- regs.syscall_nr = -1;
-
if (!user_mode(®s)) {
if (tsk != &init_task) {
unlazy_fpu(tsk);
}
tsk = &init_task;
- if (tsk->flags & PF_USEDFPU)
- BUG();
+ if (tsk->flags & PF_USEDFPU) {
+ /*
+ * This weird situation can be occurred.
+ *
+ * There's race condition in __cli:
+ *
+ * (1) $SR --> register
+ * (2) Set IMASK of register
+ * (3) $SR <-- register
+ *
+ * Between (1) and (2), or (2) and (3) getting
+ * interrupt, and interrupt handler (or
+ * softirq) may use FPU.
+ *
+ * Then, SR.FD is overwritten by (3).
+ *
+ * This results init_task.PF_USEDFPU is on,
+ * with SR.FD == 1.
+ *
+ */
+ release_fpu();
+ return;
+ }
}
grab_fpu();
@@ -216,8 +237,8 @@
grab_fpu();
else {
if (!(sr & SR_FD)) {
- release_fpu();
BUG();
+ release_fpu();
}
}
return;
@@ -228,16 +249,20 @@
grab_fpu();
else {
if (init_task.flags & PF_USEDFPU) {
- init_task.flags &= ~PF_USEDFPU;
- BUG();
+ /*
+ * This weird situation can be occurred.
+ * See the comment in do_fpu_state_restore.
+ */
+ grab_fpu();
+ save_fpu(&init_task);
}
}
} else {
if (init_task.flags & PF_USEDFPU)
save_fpu(&init_task);
else {
- release_fpu();
BUG();
+ release_fpu();
}
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)