* [Linux-ia64] High fpu register corruption
@ 2003-05-08 14:16 Andreas Schwab
2003-05-08 16:33 ` Mallick, Asit K
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: Andreas Schwab @ 2003-05-08 14:16 UTC (permalink / raw)
To: linux-ia64
When a process clears the psr.mfh bit after using the high fpu registers
and then starts using them again it can corrupt the fpu state of another
process. In order for this to happen there must be some context switches
inbetween (thanks to Chris Mason for tracking this down):
Processes start with psr.dfh=1, IA64_THREAD_FPH_VALID not set
proc A proc B
------ ------
use fph reg
-> trap, mfh=1, dfh=0
-> fpu_owner = proc A
clear mfh (rum)
context switch
-> no registers saved
-> IA64_THREAD_FPH_VALID not set
start running
use fph reg
-> trap, mfh=1, dfh=0
-> fpu_owner = proc B
context switch
-> save registers, mfh=0
-> set IA64_THREAD_FPH_VALID
continue running
-> IA64_THREAD_FPH_VALID not set
-> dfh not modified
modify fph reg
-> no trap
-> fpu_owner still proc B
clear mfh (rum)
context switch
continue running
-> fpu_owner still proc B
-> dfh=0, mfh=0
At this point proc B uses the fph registers that were modified by proc A.
The problem is that dfh was not set for proc A although
IA64_THREAD_FPH_VALID wasn't set and proc A is not the fpu owner. This
patch fixes the problem:
--- linux-2.4/include/asm-ia64/system.h.~1~ 2003-05-07 15:44:44.000000000 +0200
+++ linux-2.4/include/asm-ia64/system.h 2003-05-07 15:31:47.000000000 +0200
@@ -281,7 +281,8 @@ extern void ia64_load_extra (struct task
} else { \
ia64_psr(ia64_task_regs(next))->dfh = 1; \
} \
- } \
+ } else if (ia64_get_fpu_owner() != next) \
+ ia64_psr(ia64_task_regs(next))->dfh = 1; \
__switch_to(prev,next,last); \
} while (0)
#else
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
@ 2003-05-08 16:33 ` Mallick, Asit K
2003-05-08 16:42 ` Chris Mason
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Mallick, Asit K @ 2003-05-08 16:33 UTC (permalink / raw)
To: linux-ia64
Andreas,
The high FP save and restore in the context switch makes the assumption that user will not be modifying the psr.mfh and it will be only updated by the hardware. Without this assumption we can not optimize the FP save/restore for SMP systems (this patch will not cover all cases). If application wants the current high fpu state to be preserved then it should will not be able to modify the psr.mfh.
What kind of applications are trying to modify the mfh?
Thanks,
Asit
> -----Original Message-----
> From: Andreas Schwab [mailto:schwab@suse.de]
> Sent: Thursday, May 08, 2003 7:16 AM
> To: linux-ia64@linuxia64.org
> Cc: Chris Mason
> Subject: [Linux-ia64] High fpu register corruption
>
> When a process clears the psr.mfh bit after using the high fpu registers
> and then starts using them again it can corrupt the fpu state of another
> process. In order for this to happen there must be some context switches
> inbetween (thanks to Chris Mason for tracking this down):
>
> Processes start with psr.dfh=1, IA64_THREAD_FPH_VALID not set
>
> proc A proc B
> ------ ------
> use fph reg
> -> trap, mfh=1, dfh=0
> -> fpu_owner = proc A
> clear mfh (rum)
>
> context switch
> -> no registers saved
> -> IA64_THREAD_FPH_VALID not set
>
> start running
> use fph reg
> -> trap, mfh=1, dfh=0
> -> fpu_owner = proc B
>
> context switch
> -> save registers, mfh=0
> -> set IA64_THREAD_FPH_VALID
>
> continue running
> -> IA64_THREAD_FPH_VALID not set
> -> dfh not modified
>
> modify fph reg
> -> no trap
> -> fpu_owner still proc B
> clear mfh (rum)
>
> context switch
>
> continue running
> -> fpu_owner still proc B
> -> dfh=0, mfh=0
>
> At this point proc B uses the fph registers that were modified by proc A.
> The problem is that dfh was not set for proc A although
> IA64_THREAD_FPH_VALID wasn't set and proc A is not the fpu owner. This
> patch fixes the problem:
>
> --- linux-2.4/include/asm-ia64/system.h.~1~ 2003-05-07
> 15:44:44.000000000 +0200
> +++ linux-2.4/include/asm-ia64/system.h 2003-05-07 15:31:47.000000000
> +0200
> @@ -281,7 +281,8 @@ extern void ia64_load_extra (struct task
> } else { \
> ia64_psr(ia64_task_regs(next))->dfh = 1; \
> } \
> - } \
> + } else if (ia64_get_fpu_owner() != next) \
> + ia64_psr(ia64_task_regs(next))->dfh = 1; \
> __switch_to(prev,next,last); \
> } while (0)
> #else
>
>
> Andreas.
>
> --
> Andreas Schwab, SuSE Labs, schwab@suse.de
> SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
> Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
> "And now for something completely different."
>
> _______________________________________________
> Linux-IA64 mailing list
> Linux-IA64@linuxia64.org
> http://lists.linuxia64.org/lists/listinfo/linux-ia64
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
2003-05-08 16:33 ` Mallick, Asit K
@ 2003-05-08 16:42 ` Chris Mason
2003-05-08 16:58 ` David Mosberger
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Chris Mason @ 2003-05-08 16:42 UTC (permalink / raw)
To: linux-ia64
On Thu, 2003-05-08 at 12:33, Mallick, Asit K wrote:
> Andreas,
>
> The high FP save and restore in the context switch makes the
> assumption that user will not be modifying the psr.mfh and it will be
> only updated by the hardware. Without this assumption we can not
> optimize the FP save/restore for SMP systems (this patch will not
> cover all cases). If application wants the current high fpu state to
> be preserved then it should will not be able to modify the psr.mfh.
>
> What kind of applications are trying to modify the mfh?
The ia64 ssl source has hand optimized asm that clears mfh, but that
doesn't really matter. What matters is that any application can do it,
so it has security implications.
-chris
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
2003-05-08 16:33 ` Mallick, Asit K
2003-05-08 16:42 ` Chris Mason
@ 2003-05-08 16:58 ` David Mosberger
2003-05-08 17:03 ` David Mosberger
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: David Mosberger @ 2003-05-08 16:58 UTC (permalink / raw)
To: linux-ia64
>>>>> On Thu, 8 May 2003 09:33:55 -0700, "Mallick, Asit K" <asit.k.mallick@intel.com> said:
Asit> Andreas, The high FP save and restore in the context switch
Asit> makes the assumption that user will not be modifying the
Asit> psr.mfh and it will be only updated by the hardware.
Not a chance. We can't rely on the application doing the Right Thing.
In fact, having an application clear psr.mfh makes tons of sense,
when it knows it's done using mfh.
Asit> Without this assumption we can not optimize the FP
Asit> save/restore for SMP systems (this patch will not cover all
Asit> cases). If application wants the current high fpu state to be
Asit> preserved then it should will not be able to modify the
Asit> psr.mfh.
Asit> What kind of applications are trying to modify the mfh?
OpenSSL does (really: some underlying crypto code).
I think you're misunderstanding the problem though: the problem is
that application A clears psr.mfh and application B gets its fph state
corrupted.
So, really, this is just a bug that needs fixing. It won't affect the
rest of the lazy fph save/restore logic.
--david
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Linux-ia64] High fpu register corruption
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (2 preceding siblings ...)
2003-05-08 16:58 ` David Mosberger
@ 2003-05-08 17:03 ` David Mosberger
2003-05-08 17:14 ` Mallick, Asit K
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: David Mosberger @ 2003-05-08 17:03 UTC (permalink / raw)
To: linux-ia64
>>>>> On Thu, 08 May 2003 16:16:13 +0200, Andreas Schwab <schwab@suse.de> said:
Andreas> When a process clears the psr.mfh bit after using the high
Andreas> fpu registers and then starts using them again it can
Andreas> corrupt the fpu state of another process. In order for
Andreas> this to happen there must be some context switches
Andreas> inbetween (thanks to Chris Mason for tracking this down):
Ah, _now_ it makes sense. I got a similar bug report yesterday, but
it claimed the _old_ (2.4.19) context switch was breaking and the
new one (2.4.20) was fine. When I looked at the old code, I couldn't
find anythign wrong with it.
Andreas> + } else if (ia64_get_fpu_owner() != next) \
Andreas> + ia64_psr(ia64_task_regs(next))->dfh = 1; \
I suspect what we really want to do here is something along the lines
of:
Andreas> + ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != next); \
This expresses the invariant we're after: the next thread has DFH set
unless it owns the FPH partition. IIRC, this is what the UP code does
already.
--david
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (3 preceding siblings ...)
2003-05-08 17:03 ` David Mosberger
@ 2003-05-08 17:14 ` Mallick, Asit K
2003-05-08 17:55 ` David Mosberger
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Mallick, Asit K @ 2003-05-08 17:14 UTC (permalink / raw)
To: linux-ia64
David,
The save part in the context switch also needs to be fixed and we will
take a look at this.
Thanks,
Asit
> -----Original Message-----
> From: David Mosberger [mailto:davidm@napali.hpl.hp.com]
> Sent: Thursday, May 08, 2003 10:03 AM
> To: Andreas Schwab
> Cc: linux-ia64@linuxia64.org; Chris Mason
> Subject: Re: [Linux-ia64] High fpu register corruption
>
> >>>>> On Thu, 08 May 2003 16:16:13 +0200, Andreas Schwab
<schwab@suse.de>
> said:
>
> Andreas> When a process clears the psr.mfh bit after using the high
> Andreas> fpu registers and then starts using them again it can
> Andreas> corrupt the fpu state of another process. In order for
> Andreas> this to happen there must be some context switches
> Andreas> inbetween (thanks to Chris Mason for tracking this down):
>
> Ah, _now_ it makes sense. I got a similar bug report yesterday, but
> it claimed the _old_ (2.4.19) context switch was breaking and the
> new one (2.4.20) was fine. When I looked at the old code, I couldn't
> find anythign wrong with it.
>
> Andreas> + } else if (ia64_get_fpu_owner() != next)
\
> Andreas> + ia64_psr(ia64_task_regs(next))->dfh = 1;
\
>
> I suspect what we really want to do here is something along the lines
> of:
>
> Andreas> + ia64_psr(ia64_task_regs(next))->dfh =
> (ia64_get_fpu_owner() != next); \
>
> This expresses the invariant we're after: the next thread has DFH set
> unless it owns the FPH partition. IIRC, this is what the UP code does
> already.
>
> --david
>
> _______________________________________________
> Linux-IA64 mailing list
> Linux-IA64@linuxia64.org
> http://lists.linuxia64.org/lists/listinfo/linux-ia64
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (4 preceding siblings ...)
2003-05-08 17:14 ` Mallick, Asit K
@ 2003-05-08 17:55 ` David Mosberger
2003-05-22 21:55 ` [Linux-ia64] High fpu register corruption (PATCH) Mallick, Asit K
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: David Mosberger @ 2003-05-08 17:55 UTC (permalink / raw)
To: linux-ia64
>>>>> On Thu, 8 May 2003 10:14:20 -0700, "Mallick, Asit K" <asit.k.mallick@intel.com> said:
Asit> David, The save part in the context switch also needs to be
Asit> fixed and we will take a look at this.
Are you sure? It looks fine to me. What's the scenario you're
worried about? Note that if an application clears psr.mfh it says: I
no longer care about the state, next time I touch it, give me whatever
contents you have (either all zeroes or an earlier snapshot of fph;
never the contents of fph from another thread, of course).
Note that the fph registers are all scratch registers. Are you
worried about someone implementing a non-standard calling convention?
Even then I think an application that clears psr.mfh is saying that
the fph contents is no longer relevant, so I think we'd still be OK.
--david
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption (PATCH)
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (5 preceding siblings ...)
2003-05-08 17:55 ` David Mosberger
@ 2003-05-22 21:55 ` Mallick, Asit K
2003-05-29 3:53 ` Bjorn Helgaas
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Mallick, Asit K @ 2003-05-22 21:55 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 2527 bytes --]
Attached is a patch to fix the high FPU corruption (thanks to Andreas
and Chris). This patch also unifies the FPU save/restore for SMP and UP
and also fixes another problem with FPH save/restore path due to an
unaligned fault. Sorry for the delay.
This patch based on 2.4.21-rc2 (latest bktree).
Thanks,
Asit
> From: Mallick, Asit K
> Sent: Thursday, May 08, 2003 10:14 AM
> To: davidm@hpl.hp.com; Andreas Schwab
> Cc: linux-ia64@linuxia64.org; Chris Mason
> Subject: RE: [Linux-ia64] High fpu register corruption
>
> David,
>
> The save part in the context switch also needs to be fixed and we will
> take a look at this.
> Thanks,
> Asit
>
>
> > -----Original Message-----
> > From: David Mosberger [mailto:davidm@napali.hpl.hp.com]
> > Sent: Thursday, May 08, 2003 10:03 AM
> > To: Andreas Schwab
> > Cc: linux-ia64@linuxia64.org; Chris Mason
> > Subject: Re: [Linux-ia64] High fpu register corruption
> >
> > >>>>> On Thu, 08 May 2003 16:16:13 +0200, Andreas Schwab
> <schwab@suse.de>
> > said:
> >
> > Andreas> When a process clears the psr.mfh bit after using the
high
> > Andreas> fpu registers and then starts using them again it can
> > Andreas> corrupt the fpu state of another process. In order for
> > Andreas> this to happen there must be some context switches
> > Andreas> inbetween (thanks to Chris Mason for tracking this down):
> >
> > Ah, _now_ it makes sense. I got a similar bug report yesterday, but
> > it claimed the _old_ (2.4.19) context switch was breaking and the
> > new one (2.4.20) was fine. When I looked at the old code, I
couldn't
> > find anythign wrong with it.
> >
> > Andreas> + } else if (ia64_get_fpu_owner() != next)
> \
> > Andreas> + ia64_psr(ia64_task_regs(next))->dfh = 1;
> \
> >
> > I suspect what we really want to do here is something along the
lines
> > of:
> >
> > Andreas> + ia64_psr(ia64_task_regs(next))->dfh =
> > (ia64_get_fpu_owner() != next); \
> >
> > This expresses the invariant we're after: the next thread has DFH
set
> > unless it owns the FPH partition. IIRC, this is what the UP code
does
> > already.
> >
> > --david
> >
> > _______________________________________________
> > Linux-IA64 mailing list
> > Linux-IA64@linuxia64.org
> > http://lists.linuxia64.org/lists/listinfo/linux-ia64
>
> _______________________________________________
> Linux-IA64 mailing list
> Linux-IA64@linuxia64.org
> http://lists.linuxia64.org/lists/listinfo/linux-ia64
[-- Attachment #2: lazyfp1_7-24.txt --]
[-- Type: text/plain, Size: 9619 bytes --]
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1130 -> 1.1133
# arch/ia64/kernel/setup.c 1.12 -> 1.14
# include/asm-ia64/processor.h 1.19 -> 1.21
# include/asm-ia64/system.h 1.18 -> 1.19
# arch/ia64/kernel/process.c 1.18 -> 1.19
# arch/ia64/kernel/signal.c 1.14 -> 1.15
# arch/ia64/kernel/traps.c 1.13 -> 1.15
# arch/ia64/kernel/ptrace.c 1.17 -> 1.19
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/05/21 adsharma@linux-t08.(none) 1.1131
# lazyfp1.5-24
# --------------------------------------------
# 03/05/21 adsharma@linux-t08.(none) 1.1132
# fph corruption fix
# --------------------------------------------
# 03/05/22 adsharma@linux-t08.(none) 1.1133
# UP fixes
# --------------------------------------------
#
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c Thu May 22 14:25:13 2003
+++ b/arch/ia64/kernel/process.c Thu May 22 14:25:13 2003
@@ -333,6 +333,7 @@
# define THREAD_FLAGS_TO_SET 0
p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
| THREAD_FLAGS_TO_SET);
+ ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
#ifdef CONFIG_IA32_SUPPORT
/*
* If we're cloning an IA32 task then save the IA32 extra
@@ -517,11 +518,7 @@
{
/* drop floating-point and debug-register state if it exists: */
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
-
-#ifndef CONFIG_SMP
- if (ia64_get_fpu_owner() == current)
- ia64_set_fpu_owner(0);
-#endif
+ ia64_drop_fpu(current);
}
#ifdef CONFIG_PERFMON
@@ -559,10 +556,7 @@
void
exit_thread (void)
{
-#ifndef CONFIG_SMP
- if (ia64_get_fpu_owner() == current)
- ia64_set_fpu_owner(0);
-#endif
+ ia64_drop_fpu(current);
#ifdef CONFIG_PERFMON
/* stop monitoring */
if (current->thread.pfm_context)
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c Thu May 22 14:25:13 2003
+++ b/arch/ia64/kernel/ptrace.c Thu May 22 14:25:13 2003
@@ -597,16 +597,11 @@
ia64_flush_fph (struct task_struct *task)
{
struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
-#ifdef CONFIG_SMP
- struct task_struct *fpu_owner = current;
-#else
- struct task_struct *fpu_owner = ia64_get_fpu_owner();
-#endif
- if (task == fpu_owner && psr->mfh) {
+ if (ia64_is_local_fpu_owner(task) && psr->mfh) {
psr->mfh = 0;
- ia64_save_fpu(&task->thread.fph[0]);
task->thread.flags |= IA64_THREAD_FPH_VALID;
+ ia64_save_fpu(&task->thread.fph[0]);
}
}
@@ -628,10 +623,7 @@
task->thread.flags |= IA64_THREAD_FPH_VALID;
memset(&task->thread.fph, 0, sizeof(task->thread.fph));
}
-#ifndef CONFIG_SMP
- if (ia64_get_fpu_owner() == task)
- ia64_set_fpu_owner(0);
-#endif
+ ia64_drop_fpu(task);
psr->dfh = 1;
}
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c Thu May 22 14:25:13 2003
+++ b/arch/ia64/kernel/setup.c Thu May 22 14:25:13 2003
@@ -619,6 +619,8 @@
/* Clear the stack memory reserved for pt_regs: */
memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
+ ia64_set_kr(IA64_KR_FPU_OWNER, 0);
+
/*
* Initialize default control register to defer all speculative faults. The
* kernel MUST NOT depend on a particular setting of these bits (in other words,
@@ -629,10 +631,6 @@
*/
ia64_set_dcr( IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
| IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC);
-#ifndef CONFIG_SMP
- ia64_set_fpu_owner(0);
-#endif
-
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c Thu May 22 14:25:13 2003
+++ b/arch/ia64/kernel/signal.c Thu May 22 14:25:13 2003
@@ -142,8 +142,12 @@
__copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
psr->mfh = 0; /* drop signal handler's fph contents... */
- if (!psr->dfh)
+ if (!psr->dfh) {
__ia64_load_fpu(current->thread.fph);
+ ia64_set_local_fpu_owner(current);
+ } else {
+ ia64_drop_fpu(current);
+ }
}
return err;
}
diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
--- a/arch/ia64/kernel/traps.c Thu May 22 14:25:13 2003
+++ b/arch/ia64/kernel/traps.c Thu May 22 14:25:13 2003
@@ -245,9 +245,9 @@
psr->dfh = 0;
#ifndef CONFIG_SMP
{
- struct task_struct *fpu_owner = ia64_get_fpu_owner();
+ struct task_struct *fpu_owner = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
- if (fpu_owner == current)
+ if (ia64_is_local_fpu_owner(current))
return;
if (fpu_owner)
@@ -255,7 +255,7 @@
}
#endif /* !CONFIG_SMP */
- ia64_set_fpu_owner(current);
+ ia64_set_local_fpu_owner(current);
if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
__ia64_load_fpu(current->thread.fph);
psr->mfh = 0;
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h Thu May 22 14:25:13 2003
+++ b/include/asm-ia64/processor.h Thu May 22 14:25:13 2003
@@ -302,7 +302,8 @@
INIT_THREAD_PM \
{0, }, /* dbr */ \
{0, }, /* ibr */ \
- {{{{0}}}, } /* fph */ \
+ {{{{0}}}, }, /* fph */ \
+ -1 /* last_fph_cpu*/ \
}
#define start_thread(regs,new_ip,new_sp) do { \
@@ -426,17 +427,16 @@
}
}
-static inline struct task_struct *
-ia64_get_fpu_owner (void)
-{
- return (struct task_struct *) ia64_get_kr(IA64_KR_FPU_OWNER);
-}
+#define ia64_is_local_fpu_owner(t) (((t)->thread.last_fph_cpu == smp_processor_id()) && \
+ ((t) == (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER)))
-static inline void
-ia64_set_fpu_owner (struct task_struct *t)
-{
- ia64_set_kr(IA64_KR_FPU_OWNER, (unsigned long) t);
-}
+#define ia64_set_local_fpu_owner(t) do { \
+ t->thread.last_fph_cpu = smp_processor_id(); \
+ ia64_set_kr(IA64_KR_FPU_OWNER, (unsigned long) (t)); \
+} while(0)
+
+/* Mark the fph partition of task T as being invalid on all CPUs. */
+#define ia64_drop_fpu(t) ((t)->thread.last_fph_cpu = -1)
extern void __ia64_init_fpu (void);
extern void __ia64_save_fpu (struct ia64_fpreg *fph);
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h Thu May 22 14:25:13 2003
+++ b/include/asm-ia64/system.h Thu May 22 14:25:13 2003
@@ -244,13 +244,16 @@
# define PERFMON_IS_SYSWIDE() (0)
#endif
+#define IA64_HAS_EXTRA_STATE(t) \
+ ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID) \
+ || IS_IA32_PROCESS(ia64_task_regs(t)) || PERFMON_IS_SYSWIDE())
+
#define __switch_to(prev,next,last) do { \
- if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)) \
- || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE()) \
- ia64_save_extra(prev); \
- if (((next)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)) \
- || IS_IA32_PROCESS(ia64_task_regs(next)) || PERFMON_IS_SYSWIDE()) \
+ if (IA64_HAS_EXTRA_STATE(prev)) \
+ ia64_save_extra(prev); \
+ if (IA64_HAS_EXTRA_STATE(next)) \
ia64_load_extra(next); \
+ ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next); \
(last) = ia64_switch_to((next)); \
} while (0)
@@ -260,35 +263,21 @@
#define arch_consoles_callable() (cpu_online_map & (1UL << smp_processor_id()))
/*
- * In the SMP case, we save the fph state when context-switching
- * away from a thread that modified fph. This way, when the thread
- * gets scheduled on another CPU, the CPU can pick up the state from
- * task->thread.fph, avoiding the complication of having to fetch
- * the latest fph state from another CPU.
+ * In the SMP case, we save the fph state when context-switching away from a thread that
+ * modified fph. This way, when the thread gets scheduled on another CPU, the CPU can
+ * pick up the state from task->thread.fph, avoiding the complication of having to fetch
+ * the latest fph state from another CPU. In other words: eager save, lazy restore.
*/
# define switch_to(prev,next,last) do { \
- if (ia64_psr(ia64_task_regs(prev))->mfh) { \
+ if (ia64_psr(ia64_task_regs(prev))->mfh) { \
ia64_psr(ia64_task_regs(prev))->mfh = 0; \
(prev)->thread.flags |= IA64_THREAD_FPH_VALID; \
__ia64_save_fpu((prev)->thread.fph); \
- (prev)->thread.last_fph_cpu = smp_processor_id(); \
- } \
- if ((next)->thread.flags & IA64_THREAD_FPH_VALID) { \
- if (((next)->thread.last_fph_cpu == smp_processor_id()) \
- && (ia64_get_fpu_owner() == next)) { \
- ia64_psr(ia64_task_regs(next))->dfh = 0; \
- ia64_psr(ia64_task_regs(next))->mfh = 0; \
- } else { \
- ia64_psr(ia64_task_regs(next))->dfh = 1; \
- } \
} \
- __switch_to(prev,next,last); \
+ __switch_to(prev, next, last); \
} while (0)
#else
-# define switch_to(prev,next,last) do { \
- ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next)); \
- __switch_to(prev,next,last); \
-} while (0)
+# define switch_to(prev,next,last) __switch_to(prev,next,last)
#endif
#endif /* __KERNEL__ */
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Linux-ia64] High fpu register corruption (PATCH)
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (6 preceding siblings ...)
2003-05-22 21:55 ` [Linux-ia64] High fpu register corruption (PATCH) Mallick, Asit K
@ 2003-05-29 3:53 ` Bjorn Helgaas
2003-05-29 4:10 ` David Mosberger
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Bjorn Helgaas @ 2003-05-29 3:53 UTC (permalink / raw)
To: linux-ia64
On Thursday 22 May 2003 3:55 pm, Mallick, Asit K wrote:
> Attached is a patch to fix the high FPU corruption (thanks to Andreas
> and Chris). This patch also unifies the FPU save/restore for SMP and UP
> and also fixes another problem with FPH save/restore path due to an
> unaligned fault.
I'm comparing 2.4 (including your patch) and David's current
2.5 BK tree. I'd like to keep them as close as possible, but
I see several clearly gratuitous differences (like whitespace)
and some that aren't obvious to me.
arch/ia64/kernel/ptrace.c:
2.4 calls ia64_drop_fpu() from ia64_sync_fph().
2.5 calls ia64_drop_fpu() from ia64_flush_fph().
Is there a reason for the difference?
arch/ia64/kernel/setup.c:
cpu_init(): 2.4 added ia64_set_kr() and removed
ia64_set_fpu_owner(); 2.5 doesn't have this change.
This looks like at least partly a bug in 2.5 --
ia64_set_fpu_owner is called under "#ifndef CONFIG_SMP"
but not defined anywhere.
arch/ia64/kernel/signal.c:
restore_sigcontext() changes look equivalent, but have
gratuitous differences from 2.5 (reversed sense of test,
comment)
arch/ia64/kernel/traps.c:
disabled_fph_fault(): 2.4 uses ia64_is_local_fpu_owner();
2.5 uses "fpu_owner = current". Is there a reason for
this?
Also gratuitous whitespace differences.
include/asm-ia64/processor.h:
ia64_is_local_fpu_owner(), ia64_set_local_fpu_owner():
these look functionally equivalent in 2.4 and 2.5.
Can they be made identical?
include/asm-ia64/system.h:
IA64_HAS_EXTRA_STATE() and switch_to() appear to be
identical in 2.4 and 2.5 except for whitespace changes.
Can they be made identical?
Any insight would be appreciated!
Bjorn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Linux-ia64] High fpu register corruption (PATCH)
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (7 preceding siblings ...)
2003-05-29 3:53 ` Bjorn Helgaas
@ 2003-05-29 4:10 ` David Mosberger
2003-05-29 4:25 ` Bjorn Helgaas
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: David Mosberger @ 2003-05-29 4:10 UTC (permalink / raw)
To: linux-ia64
>>>>> On Wed, 28 May 2003 21:53:13 -0600, Bjorn Helgaas <bjorn_helgaas@hp.com> said:
Bjorn> I'm comparing 2.4 (including your patch) and David's current
Bjorn> 2.5 BK tree. I'd like to keep them as close as possible, but
Bjorn> I see several clearly gratuitous differences (like
Bjorn> whitespace) and some that aren't obvious to me.
Bjorn> arch/ia64/kernel/ptrace.c: 2.4 calls ia64_drop_fpu() from
Bjorn> ia64_sync_fph(). 2.5 calls ia64_drop_fpu() from
Bjorn> ia64_flush_fph(). Is there a reason for the difference?
Which tree are you looking at? to-linus-2.5 or linux-ia64-2.5? I have
gotten quite lazy in pushing the former, since the only reason now to
do a push there is when I want Linus to do a pull. The latter tree is
much more active.
--david
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Linux-ia64] High fpu register corruption (PATCH)
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (8 preceding siblings ...)
2003-05-29 4:10 ` David Mosberger
@ 2003-05-29 4:25 ` Bjorn Helgaas
2003-05-29 4:40 ` David Mosberger
2003-05-29 5:43 ` Mallick, Asit K
11 siblings, 0 replies; 13+ messages in thread
From: Bjorn Helgaas @ 2003-05-29 4:25 UTC (permalink / raw)
To: linux-ia64
> Which tree are you looking at? to-linus-2.5 or linux-ia64-2.5? I have
> gotten quite lazy in pushing the former, since the only reason now to
> do a push there is when I want Linus to do a pull. The latter tree is
> much more active.
The latter (linux-ia64-2.5). But ... argh! I've been doing "bk changes -R"
to watch for your updates, and saw none. BUT, I just did a "bk pull"
and got a lot of them.
OK, ignore my questions about ptrace.c and setup.c. Questions still
open:
arch/ia64/kernel/signal.c:
restore_sigcontext() changes look equivalent, but have
gratuitous differences from 2.5 (reversed sense of test,
comment)
arch/ia64/kernel/traps.c:
Gratuitous whitespace differences.
include/asm-ia64/processor.h:
ia64_is_local_fpu_owner(), ia64_set_local_fpu_owner():
these look functionally equivalent in 2.4 and 2.5.
Can they be made identical?
include/asm-ia64/system.h:
IA64_HAS_EXTRA_STATE() and switch_to() appear to be
identical in 2.4 and 2.5 except for whitespace changes.
Can they be made identical?
Bjorn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Linux-ia64] High fpu register corruption (PATCH)
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (9 preceding siblings ...)
2003-05-29 4:25 ` Bjorn Helgaas
@ 2003-05-29 4:40 ` David Mosberger
2003-05-29 5:43 ` Mallick, Asit K
11 siblings, 0 replies; 13+ messages in thread
From: David Mosberger @ 2003-05-29 4:40 UTC (permalink / raw)
To: linux-ia64
>>>>> On Wed, 28 May 2003 22:25:37 -0600, Bjorn Helgaas <bjorn_helgaas@hp.com> said:
Bjorn> OK, ignore my questions about ptrace.c and setup.c. Questions still
Bjorn> open:
Bjorn> arch/ia64/kernel/signal.c:
Bjorn> restore_sigcontext() changes look equivalent, but have
Bjorn> gratuitous differences from 2.5 (reversed sense of test,
Bjorn> comment)
Bjorn> arch/ia64/kernel/traps.c:
Bjorn> Gratuitous whitespace differences.
Bjorn> include/asm-ia64/processor.h:
Bjorn> ia64_is_local_fpu_owner(), ia64_set_local_fpu_owner():
Bjorn> these look functionally equivalent in 2.4 and 2.5.
Bjorn> Can they be made identical?
Bjorn> include/asm-ia64/system.h:
Bjorn> IA64_HAS_EXTRA_STATE() and switch_to() appear to be
Bjorn> identical in 2.4 and 2.5 except for whitespace changes.
Bjorn> Can they be made identical?
Not sure if those are intentional. I of course would prefer if 2.5
were followed. ;-) Asit?
--daivd
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [Linux-ia64] High fpu register corruption (PATCH)
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
` (10 preceding siblings ...)
2003-05-29 4:40 ` David Mosberger
@ 2003-05-29 5:43 ` Mallick, Asit K
11 siblings, 0 replies; 13+ messages in thread
From: Mallick, Asit K @ 2003-05-29 5:43 UTC (permalink / raw)
To: linux-ia64
Yes, it can be same as 2.5.
Thanks,
Asit
> -----Original Message-----
> From: David Mosberger [mailto:davidm@napali.hpl.hp.com]
> Sent: Wednesday, May 28, 2003 9:41 PM
> To: Bjorn Helgaas
> Cc: davidm@hpl.hp.com; David Mosberger; Mallick, Asit K;
> linux-ia64@linuxia64.org; Chris Mason; dstownse@us.ibm.com
> Subject: Re: [Linux-ia64] High fpu register corruption (PATCH)
>
>
> >>>>> On Wed, 28 May 2003 22:25:37 -0600, Bjorn Helgaas
> <bjorn_helgaas@hp.com> said:
>
> Bjorn> OK, ignore my questions about ptrace.c and setup.c.
> Questions still
> Bjorn> open:
>
> Bjorn> arch/ia64/kernel/signal.c:
> Bjorn> restore_sigcontext() changes look equivalent, but have
> Bjorn> gratuitous differences from 2.5 (reversed sense of test,
> Bjorn> comment)
>
> Bjorn> arch/ia64/kernel/traps.c:
> Bjorn> Gratuitous whitespace differences.
>
> Bjorn> include/asm-ia64/processor.h:
> Bjorn> ia64_is_local_fpu_owner(), ia64_set_local_fpu_owner():
> Bjorn> these look functionally equivalent in 2.4 and 2.5.
> Bjorn> Can they be made identical?
>
> Bjorn> include/asm-ia64/system.h:
> Bjorn> IA64_HAS_EXTRA_STATE() and switch_to() appear to be
> Bjorn> identical in 2.4 and 2.5 except for whitespace changes.
> Bjorn> Can they be made identical?
>
> Not sure if those are intentional. I of course would prefer if 2.5
> were followed. ;-) Asit?
>
> --daivd
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2003-05-29 5:43 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-08 14:16 [Linux-ia64] High fpu register corruption Andreas Schwab
2003-05-08 16:33 ` Mallick, Asit K
2003-05-08 16:42 ` Chris Mason
2003-05-08 16:58 ` David Mosberger
2003-05-08 17:03 ` David Mosberger
2003-05-08 17:14 ` Mallick, Asit K
2003-05-08 17:55 ` David Mosberger
2003-05-22 21:55 ` [Linux-ia64] High fpu register corruption (PATCH) Mallick, Asit K
2003-05-29 3:53 ` Bjorn Helgaas
2003-05-29 4:10 ` David Mosberger
2003-05-29 4:25 ` Bjorn Helgaas
2003-05-29 4:40 ` David Mosberger
2003-05-29 5:43 ` Mallick, Asit K
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox