diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-06 06:27:45 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-15 16:39:53 -0500 |
commit | 54cb3dbb4a1cccd6b1bffc169ff638f8e74daf44 (patch) | |
tree | 454b05810dc96b288eabcc4e11046adb0bc8b8ec /arch/arm/vfp | |
parent | 462f39a8c7496c95f4de91ef46d875f46e0fa271 (diff) |
ARM: vfp: fix vfp_sync_state()
The more I look at vfp_sync_state(), the more I believe it's trying
to do its job in a really obscure way.
Essentially, last_VFP_context[] tracks who owns the state in the VFP
hardware. If last_VFP_context[] is the context for the thread which
we're interested in, then the VFP hardware has context which is not
saved in the software state - so we need to bring the software state
up to date.
If last_VFP_context[] is for some other thread, we really don't care
what state the VFP hardware is in; it doesn't contain any information
pertinent to the thread we're trying to deal with - so don't touch
the hardware.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r-- | arch/arm/vfp/vfpmodule.c | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index f60a5400a25b..86a57aeeda4a 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -444,32 +444,28 @@ void vfp_sync_state(struct thread_info *thread) | |||
444 | void vfp_sync_state(struct thread_info *thread) | 444 | void vfp_sync_state(struct thread_info *thread) |
445 | { | 445 | { |
446 | unsigned int cpu = get_cpu(); | 446 | unsigned int cpu = get_cpu(); |
447 | u32 fpexc = fmrx(FPEXC); | ||
448 | 447 | ||
449 | /* | 448 | /* |
450 | * If VFP is enabled, the previous state was already saved and | 449 | * If the thread we're interested in is the current owner of the |
451 | * last_VFP_context updated. | 450 | * hardware VFP state, then we need to save its state. |
452 | */ | 451 | */ |
453 | if (fpexc & FPEXC_EN) | 452 | if (last_VFP_context[cpu] == &thread->vfpstate) { |
454 | goto out; | 453 | u32 fpexc = fmrx(FPEXC); |
455 | |||
456 | if (!last_VFP_context[cpu]) | ||
457 | goto out; | ||
458 | 454 | ||
459 | /* | 455 | /* |
460 | * Save the last VFP state on this CPU. | 456 | * Save the last VFP state on this CPU. |
461 | */ | 457 | */ |
462 | fmxr(FPEXC, fpexc | FPEXC_EN); | 458 | fmxr(FPEXC, fpexc | FPEXC_EN); |
463 | vfp_save_state(last_VFP_context[cpu], fpexc); | 459 | vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); |
464 | fmxr(FPEXC, fpexc); | 460 | fmxr(FPEXC, fpexc & ~FPEXC_EN); |
465 | 461 | ||
466 | /* | 462 | /* |
467 | * Set the context to NULL to force a reload the next time the thread | 463 | * Set the context to NULL to force a reload the next time |
468 | * uses the VFP. | 464 | * the thread uses the VFP. |
469 | */ | 465 | */ |
470 | last_VFP_context[cpu] = NULL; | 466 | last_VFP_context[cpu] = NULL; |
467 | } | ||
471 | 468 | ||
472 | out: | ||
473 | put_cpu(); | 469 | put_cpu(); |
474 | } | 470 | } |
475 | #endif | 471 | #endif |