diff options
Diffstat (limited to 'arch/arm/vfp/vfpmodule.c')
-rw-r--r-- | arch/arm/vfp/vfpmodule.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index f60a5400a25b..def19f83d812 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -430,7 +430,11 @@ static inline void vfp_pm_init(void) { } | |||
430 | * saved one. This function is used by the ptrace mechanism. | 430 | * saved one. This function is used by the ptrace mechanism. |
431 | */ | 431 | */ |
432 | #ifdef CONFIG_SMP | 432 | #ifdef CONFIG_SMP |
433 | void vfp_sync_state(struct thread_info *thread) | 433 | void vfp_sync_hwstate(struct thread_info *thread) |
434 | { | ||
435 | } | ||
436 | |||
437 | void vfp_flush_hwstate(struct thread_info *thread) | ||
434 | { | 438 | { |
435 | /* | 439 | /* |
436 | * On SMP systems, the VFP state is automatically saved at every | 440 | * On SMP systems, the VFP state is automatically saved at every |
@@ -441,35 +445,48 @@ void vfp_sync_state(struct thread_info *thread) | |||
441 | thread->vfpstate.hard.cpu = NR_CPUS; | 445 | thread->vfpstate.hard.cpu = NR_CPUS; |
442 | } | 446 | } |
443 | #else | 447 | #else |
444 | void vfp_sync_state(struct thread_info *thread) | 448 | void vfp_sync_hwstate(struct thread_info *thread) |
445 | { | 449 | { |
446 | unsigned int cpu = get_cpu(); | 450 | unsigned int cpu = get_cpu(); |
447 | u32 fpexc = fmrx(FPEXC); | ||
448 | 451 | ||
449 | /* | 452 | /* |
450 | * If VFP is enabled, the previous state was already saved and | 453 | * If the thread we're interested in is the current owner of the |
451 | * last_VFP_context updated. | 454 | * hardware VFP state, then we need to save its state. |
452 | */ | 455 | */ |
453 | if (fpexc & FPEXC_EN) | 456 | if (last_VFP_context[cpu] == &thread->vfpstate) { |
454 | goto out; | 457 | u32 fpexc = fmrx(FPEXC); |
455 | 458 | ||
456 | if (!last_VFP_context[cpu]) | 459 | /* |
457 | goto out; | 460 | * Save the last VFP state on this CPU. |
461 | */ | ||
462 | fmxr(FPEXC, fpexc | FPEXC_EN); | ||
463 | vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); | ||
464 | fmxr(FPEXC, fpexc); | ||
465 | } | ||
458 | 466 | ||
459 | /* | 467 | put_cpu(); |
460 | * Save the last VFP state on this CPU. | 468 | } |
461 | */ | 469 | |
462 | fmxr(FPEXC, fpexc | FPEXC_EN); | 470 | void vfp_flush_hwstate(struct thread_info *thread) |
463 | vfp_save_state(last_VFP_context[cpu], fpexc); | 471 | { |
464 | fmxr(FPEXC, fpexc); | 472 | unsigned int cpu = get_cpu(); |
465 | 473 | ||
466 | /* | 474 | /* |
467 | * Set the context to NULL to force a reload the next time the thread | 475 | * If the thread we're interested in is the current owner of the |
468 | * uses the VFP. | 476 | * hardware VFP state, then we need to save its state. |
469 | */ | 477 | */ |
470 | last_VFP_context[cpu] = NULL; | 478 | if (last_VFP_context[cpu] == &thread->vfpstate) { |
479 | u32 fpexc = fmrx(FPEXC); | ||
480 | |||
481 | fmxr(FPEXC, fpexc & ~FPEXC_EN); | ||
482 | |||
483 | /* | ||
484 | * Set the context to NULL to force a reload the next time | ||
485 | * the thread uses the VFP. | ||
486 | */ | ||
487 | last_VFP_context[cpu] = NULL; | ||
488 | } | ||
471 | 489 | ||
472 | out: | ||
473 | put_cpu(); | 490 | put_cpu(); |
474 | } | 491 | } |
475 | #endif | 492 | #endif |