Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
xenomai
xenomai
Commits
c77076d9
Commit
c77076d9
authored
Sep 13, 2006
by
Gilles Chanteperdrix
Browse files
Fix x86 FPU bug
parent
e533f7cf
Changes
2
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
c77076d9
2006-09-13 Gilles Chanteperdrix <gilles.chanteperdrix@laposte.net>
* include/asm-i386/bits/pod.h (xnarch_*_fpu): Restore root thread
fpu context consistently with ts bit value in cr0, fixes a bug
that occured when Xenomai preempted Linux in the middle of
dup_task_struct().
2006-03-16 Philippe Gerum <rpm@xenomai.org>
* RELEASE: Xenomai 2.0.4 (Slick)
...
...
include/nucleus/asm-i386/system.h
View file @
c77076d9
...
...
@@ -74,6 +74,11 @@ typedef struct xnarchtcb { /* Per-thread arch-dependent block */
unsigned
long
*
eipp
;
/* Pointer to EIP backup area (&eip or &user->thread.eip) */
union
i387_union
*
fpup
;
/* Pointer to the FPU backup area (&fpuenv or &user->thread.i387.f[x]save */
/* FPU context bits for root thread. */
unsigned
is_root
:
1
;
unsigned
cr0_ts
:
1
;
unsigned
ts_usedfpu
:
1
;
}
xnarchtcb_t
;
typedef
struct
xnarch_fltinfo
{
...
...
@@ -160,6 +165,8 @@ static inline void xnarch_leave_root (xnarchtcb_t *rootcb)
__set_bit
(
cpuid
,
&
rthal_cpu_realtime
);
/* Remember the preempted Linux task pointer. */
rootcb
->
user_task
=
rootcb
->
active_task
=
rthal_current_host_task
(
cpuid
);
rootcb
->
cr0_ts
=
(
read_cr0
()
&
8
)
!=
0
;
rootcb
->
ts_usedfpu
=
(
current
->
thread_info
->
status
&
TS_USEDFPU
)
!=
0
;
/* So that xnarch_save_fpu() will operate on the right FPU area. */
rootcb
->
fpup
=
&
rootcb
->
user_task
->
thread
.
i387
;
}
...
...
@@ -336,6 +343,7 @@ static inline void xnarch_init_root_tcb (xnarchtcb_t *tcb,
tcb
->
espp
=
&
tcb
->
esp
;
tcb
->
eipp
=
&
tcb
->
eip
;
tcb
->
fpup
=
NULL
;
tcb
->
is_root
=
1
;
}
asmlinkage
static
void
xnarch_thread_redirect
(
struct
xnthread
*
self
,
...
...
@@ -411,15 +419,28 @@ static inline void xnarch_save_fpu (xnarchtcb_t *tcb)
{
struct
task_struct
*
task
=
tcb
->
user_task
;
if
(
task
)
{
if
(
!
(
task
->
thread_info
->
status
&
TS_USEDFPU
))
return
;
if
(
!
tcb
->
is_root
)
{
if
(
task
)
{
if
(
!
(
task
->
thread_info
->
status
&
TS_USEDFPU
))
return
;
/* Tell Linux that we already saved the state of the FPU
hardware of this task. */
task
->
thread_info
->
status
&=
~
TS_USEDFPU
;
}
}
else
{
/* Do not save root context FPU if cr0 bit ts is armed . */
if
(
tcb
->
cr0_ts
)
return
;
if
(
tcb
->
ts_usedfpu
)
task
->
thread_info
->
status
&=
~
TS_USEDFPU
;
}
/* Tell Linux that we already saved the state of the FPU hardware
of this task. */
task
->
thread_info
->
status
&=
~
TS_USEDFPU
;
}
clts
();
...
...
@@ -434,18 +455,33 @@ static inline void xnarch_restore_fpu (xnarchtcb_t *tcb)
{
struct
task_struct
*
task
=
tcb
->
user_task
;
if
(
task
)
{
if
(
!
xnarch_fpu_init_p
(
task
))
{
stts
();
return
;
/* Uninit fpu area -- do not restore. */
}
/* Tell Linux that this task has altered the state of the FPU
hardware. */
task
->
thread_info
->
status
|=
TS_USEDFPU
;
}
if
(
!
tcb
->
is_root
)
{
if
(
task
)
{
if
(
!
xnarch_fpu_init_p
(
task
))
{
stts
();
return
;
/* Uninit fpu area -- do not restore. */
}
/* Tell Linux that this task has altered the state of
* the FPU hardware. */
task
->
thread_info
->
status
|=
TS_USEDFPU
;
}
}
else
{
/* Restore state of ts bit if armed. */
if
(
tcb
->
cr0_ts
)
{
stts
();
return
;
}
if
(
tcb
->
ts_usedfpu
)
task
->
thread_info
->
status
|=
TS_USEDFPU
;
}
/* Restore the FPU hardware with valid fp registers from a
user-space or kernel thread. */
...
...
@@ -462,8 +498,30 @@ static inline void xnarch_enable_fpu(xnarchtcb_t *tcb)
{
struct
task_struct
*
task
=
tcb
->
user_task
;
if
(
task
&&
!
(
task
->
thread_info
->
status
&
TS_USEDFPU
))
return
;
if
(
!
tcb
->
is_root
)
{
if
(
task
)
{
if
(
!
xnarch_fpu_init_p
(
task
))
return
;
/* If "task" switched while in Linux domain, its FPU
* context may have been overriden, restore it. */
if
(
!
(
task
->
thread_info
->
status
&
TS_USEDFPU
))
{
xnarch_restore_fpu
(
tcb
);
return
;
}
}
}
else
{
if
(
tcb
->
cr0_ts
)
return
;
xnarch_restore_fpu
(
tcb
);
return
;
}
clts
();
...
...
@@ -505,6 +563,7 @@ static inline void xnarch_init_tcb (xnarchtcb_t *tcb)
tcb
->
espp
=
&
tcb
->
esp
;
tcb
->
eipp
=
&
tcb
->
eip
;
tcb
->
fpup
=
&
tcb
->
fpuenv
;
tcb
->
is_root
=
0
;
/* Must be followed by xnarch_init_thread(). */
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment