aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/misc.S
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2005-10-27 02:27:25 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-27 06:48:50 -0400
commit25c8a78b1e00ac0cc640677eda78b462c2cd4c6e (patch)
treea0044f8b2b557799a8cb3346b590fcd3a8507ed7 /arch/ppc64/kernel/misc.S
parentfda262b8978d0089758ef9444508434c74113a61 (diff)
[PATCH] powerpc: Fix handling of fpscr on 64-bit
The recent merge of fpu.S broken the handling of fpscr for ARCH=powerpc and CONFIG_PPC64=y. FP registers could be corrupted, leading to strange random application crashes. The confusion arises, because the thread_struct has (and requires) a 64-bit area to save the fpscr, because we use load/store double instructions to get it in to/out of the FPU. However, only the low 32-bits are actually used, so we want to treat it as a 32-bit quantity when manipulating its bits to avoid extra load/stores on 32-bit. This patch replaces the current definition with a structure of two 32-bit quantities (pad and val), to clarify things as much as is possible. The 'val' field is used when manipulating bits, the structure itself is used when obtaining the address for loading/unloading the value from the FPU. While we're at it, consolidate the 4 (!) almost identical versions of cvt_fd() and cvt_df() (arch/ppc/kernel/misc.S, arch/ppc64/kernel/misc.S, arch/powerpc/kernel/misc_32.S, arch/powerpc/kernel/misc_64.S) into a single version in fpu.S. The new version takes a pointer to thread_struct and applies the correct offset itself, rather than a pointer to the fpscr field itself, again to avoid confusion as to which is the correct field to use. Finally, this patch makes ARCH=ppc64 also use the consolidated fpu.S code, which it previously did not. Built for G5 (ARCH=ppc64 and ARCH=powerpc), 32-bit powermac (ARCH=ppc and ARCH=powerpc) and Walnut (ARCH=ppc, CONFIG_MATH_EMULATION=y). Booted on G5 (ARCH=powerpc) and things which previously fell over no longer do. Signed-off-by: David Gibson <dwg@au1.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64/kernel/misc.S')
-rw-r--r--arch/ppc64/kernel/misc.S51
1 files changed, 0 insertions, 51 deletions
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index a33448c2bd91..9cae3d5c40e6 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -451,25 +451,6 @@ _GLOBAL(_outsl_ns)
451 sync 451 sync
452 blr 452 blr
453 453
454
455_GLOBAL(cvt_fd)
456 lfd 0,0(r5) /* load up fpscr value */
457 mtfsf 0xff,0
458 lfs 0,0(r3)
459 stfd 0,0(r4)
460 mffs 0 /* save new fpscr value */
461 stfd 0,0(r5)
462 blr
463
464_GLOBAL(cvt_df)
465 lfd 0,0(r5) /* load up fpscr value */
466 mtfsf 0xff,0
467 lfd 0,0(r3)
468 stfs 0,0(r4)
469 mffs 0 /* save new fpscr value */
470 stfd 0,0(r5)
471 blr
472
473/* 454/*
474 * identify_cpu and calls setup_cpu 455 * identify_cpu and calls setup_cpu
475 * In: r3 = base of the cpu_specs array 456 * In: r3 = base of the cpu_specs array
@@ -655,38 +636,6 @@ _GLOBAL(disable_kernel_fp)
655 isync 636 isync
656 blr 637 blr
657 638
658/*
659 * giveup_fpu(tsk)
660 * Disable FP for the task given as the argument,
661 * and save the floating-point registers in its thread_struct.
662 * Enables the FPU for use in the kernel on return.
663 */
664_GLOBAL(giveup_fpu)
665 mfmsr r5
666 ori r5,r5,MSR_FP
667 mtmsrd r5 /* enable use of fpu now */
668 isync
669 cmpdi 0,r3,0
670 beqlr- /* if no previous owner, done */
671 addi r3,r3,THREAD /* want THREAD of task */
672 ld r5,PT_REGS(r3)
673 cmpdi 0,r5,0
674 SAVE_32FPRS(0, r3)
675 mffs fr0
676 stfd fr0,THREAD_FPSCR(r3)
677 beq 1f
678 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
679 li r3,MSR_FP|MSR_FE0|MSR_FE1
680 andc r4,r4,r3 /* disable FP for previous task */
681 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
6821:
683#ifndef CONFIG_SMP
684 li r5,0
685 ld r4,last_task_used_math@got(r2)
686 std r5,0(r4)
687#endif /* CONFIG_SMP */
688 blr
689
690#ifdef CONFIG_ALTIVEC 639#ifdef CONFIG_ALTIVEC
691 640
692#if 0 /* this has no callers for now */ 641#if 0 /* this has no callers for now */