Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Define 32/64 bit asm macros and use them in fpu.S

These macros help in writing assembly code that works for both ppc32
and ppc64. With this we now have a common fpu.S. This takes out
load_up_fpu from head_64.S.

Signed-off-by: Paul Mackerras <paulus@samba.org>

+53 -105
+29 -43
arch/powerpc/kernel/fpu.S
··· 27 27 * Load up this task's FP registers from its thread_struct, 28 28 * enable the FPU for the current task and return to the task. 29 29 */ 30 - .globl load_up_fpu 31 - load_up_fpu: 30 + _GLOBAL(load_up_fpu) 32 31 mfmsr r5 33 32 ori r5,r5,MSR_FP 34 - #ifdef CONFIG_PPC64BRIDGE 35 - clrldi r5,r5,1 /* turn off 64-bit mode */ 36 - #endif /* CONFIG_PPC64BRIDGE */ 37 33 SYNC 38 34 MTMSRD(r5) /* enable use of fpu now */ 39 35 isync ··· 39 43 * to another. Instead we call giveup_fpu in switch_to. 40 44 */ 41 45 #ifndef CONFIG_SMP 42 - tophys(r6,0) /* get __pa constant */ 43 - addis r3,r6,last_task_used_math@ha 44 - lwz r4,last_task_used_math@l(r3) 45 - cmpwi 0,r4,0 46 + LOADBASE(r3, last_task_used_math) 47 + tophys(r3,r3) 48 + LDL r4,OFF(last_task_used_math)(r3) 49 + CMPI 0,r4,0 46 50 beq 1f 47 - add r4,r4,r6 51 + tophys(r4,r4) 48 52 addi r4,r4,THREAD /* want last_task_used_math->thread */ 49 53 SAVE_32FPRS(0, r4) 50 54 mffs fr0 51 55 stfd fr0,THREAD_FPSCR-4(r4) 52 - lwz r5,PT_REGS(r4) 53 - add r5,r5,r6 54 - lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) 56 + LDL r5,PT_REGS(r4) 57 + tophys(r5,r5) 58 + LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 55 59 li r10,MSR_FP|MSR_FE0|MSR_FE1 56 60 andc r4,r4,r10 /* disable FP for previous task */ 57 - stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 61 + STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 58 62 1: 59 63 #endif /* CONFIG_SMP */ 60 64 /* enable use of FP after return */ 65 + #ifdef CONFIG_PPC32 61 66 mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ 62 67 lwz r4,THREAD_FPEXC_MODE(r5) 63 68 ori r9,r9,MSR_FP /* enable FP for current */ 64 69 or r9,r9,r4 70 + #else 71 + ld r4,PACACURRENT(r13) 72 + addi r5,r4,THREAD /* Get THREAD */ 73 + ld r4,THREAD_FPEXC_MODE(r5) 74 + ori r12,r12,MSR_FP 75 + or r12,r12,r4 76 + std r12,_MSR(r1) 77 + #endif 65 78 lfd fr0,THREAD_FPSCR-4(r5) 66 79 mtfsf 0xff,fr0 67 80 REST_32FPRS(0, r5) 68 81 #ifndef CONFIG_SMP 69 82 subi r4,r5,THREAD 70 - sub r4,r4,r6 71 - stw r4,last_task_used_math@l(r3) 83 + tovirt(r4,r4) 84 + STL r4,OFF(last_task_used_math)(r3) 72 85 #endif /* CONFIG_SMP */ 73 86 /* restore registers and return */ 74 87 /* we haven't used ctr or xer or lr */ 75 88 b fast_exception_return 76 - 77 - /* 78 - * FP unavailable trap from kernel - print a message, but let 79 - * the task use FP in the kernel until it returns to user mode. 80 - */ 81 - .globl KernelFP 82 - KernelFP: 83 - lwz r3,_MSR(r1) 84 - ori r3,r3,MSR_FP 85 - stw r3,_MSR(r1) /* enable use of FP after return */ 86 - lis r3,86f@h 87 - ori r3,r3,86f@l 88 - mr r4,r2 /* current */ 89 - lwz r5,_NIP(r1) 90 - bl printk 91 - b ret_from_except 92 - 86: .string "floating point used in kernel (task=%p, pc=%x)\n" 93 - .align 4,0 94 89 95 90 /* 96 91 * giveup_fpu(tsk) ··· 89 102 * and save the floating-point registers in its thread_struct. 90 103 * Enables the FPU for use in the kernel on return. 91 104 */ 92 - .globl giveup_fpu 93 - giveup_fpu: 105 + _GLOBAL(giveup_fpu) 94 106 mfmsr r5 95 107 ori r5,r5,MSR_FP 96 108 SYNC_601 ··· 97 111 MTMSRD(r5) /* enable use of fpu now */ 98 112 SYNC_601 99 113 isync 100 - cmpwi 0,r3,0 114 + CMPI 0,r3,0 101 115 beqlr- /* if no previous owner, done */ 102 116 addi r3,r3,THREAD /* want THREAD of task */ 103 - lwz r5,PT_REGS(r3) 104 - cmpwi 0,r5,0 117 + LDL r5,PT_REGS(r3) 118 + CMPI 0,r5,0 105 119 SAVE_32FPRS(0, r3) 106 120 mffs fr0 107 121 stfd fr0,THREAD_FPSCR-4(r3) 108 122 beq 1f 109 - lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) 123 + LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 110 124 li r3,MSR_FP|MSR_FE0|MSR_FE1 111 125 andc r4,r4,r3 /* disable FP for previous task */ 112 - stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 126 + STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 113 127 1: 114 128 #ifndef CONFIG_SMP 115 129 li r5,0 116 - lis r4,last_task_used_math@ha 117 - stw r5,last_task_used_math@l(r4) 130 + LOADBASE(r4,last_task_used_math) 131 + STL r5,OFF(last_task_used_math)(r4) 118 132 #endif /* CONFIG_SMP */ 119 133 blr
+1 -57
arch/powerpc/kernel/head_64.S
··· 80 80 _GLOBAL(__start) 81 81 /* NOP this out unconditionally */ 82 82 BEGIN_FTR_SECTION 83 - b .__start_initialization_multiplatform 83 + b .__start_initialization_multiplatform 84 84 END_FTR_SECTION(0, 1) 85 85 #endif /* CONFIG_PPC_MULTIPLATFORM */ 86 86 ··· 856 856 ENABLE_INTS 857 857 bl .kernel_fp_unavailable_exception 858 858 BUG_OPCODE 859 - 860 - /* 861 - * load_up_fpu(unused, unused, tsk) 862 - * Disable FP for the task which had the FPU previously, 863 - * and save its floating-point registers in its thread_struct. 864 - * Enables the FPU for use in the kernel on return. 865 - * On SMP we know the fpu is free, since we give it up every 866 - * switch (ie, no lazy save of the FP registers). 867 - * On entry: r13 == 'current' && last_task_used_math != 'current' 868 - */ 869 - _STATIC(load_up_fpu) 870 - mfmsr r5 /* grab the current MSR */ 871 - ori r5,r5,MSR_FP 872 - mtmsrd r5 /* enable use of fpu now */ 873 - isync 874 - /* 875 - * For SMP, we don't do lazy FPU switching because it just gets too 876 - * horrendously complex, especially when a task switches from one CPU 877 - * to another. Instead we call giveup_fpu in switch_to. 878 - * 879 - */ 880 - #ifndef CONFIG_SMP 881 - ld r3,last_task_used_math@got(r2) 882 - ld r4,0(r3) 883 - cmpdi 0,r4,0 884 - beq 1f 885 - /* Save FP state to last_task_used_math's THREAD struct */ 886 - addi r4,r4,THREAD 887 - SAVE_32FPRS(0, r4) 888 - mffs fr0 889 - stfd fr0,THREAD_FPSCR(r4) 890 - /* Disable FP for last_task_used_math */ 891 - ld r5,PT_REGS(r4) 892 - ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) 893 - li r6,MSR_FP|MSR_FE0|MSR_FE1 894 - andc r4,r4,r6 895 - std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 896 - 1: 897 - #endif /* CONFIG_SMP */ 898 - /* enable use of FP after return */ 899 - ld r4,PACACURRENT(r13) 900 - addi r5,r4,THREAD /* Get THREAD */ 901 - ld r4,THREAD_FPEXC_MODE(r5) 902 - ori r12,r12,MSR_FP 903 - or r12,r12,r4 904 - std r12,_MSR(r1) 905 - lfd fr0,THREAD_FPSCR(r5) 906 - mtfsf 0xff,fr0 907 - REST_32FPRS(0, r5) 908 - #ifndef CONFIG_SMP 909 - /* Update last_task_used_math to 'current' */ 910 - subi r4,r5,THREAD /* Back to 'current' */ 911 - std r4,0(r3) 912 - #endif /* CONFIG_SMP */ 913 - /* restore registers and return */ 914 - b fast_exception_return 915 859 916 860 .align 7 917 861 .globl altivec_unavailable_common
+23 -5
include/asm-powerpc/ppc_asm.h
··· 103 103 oris rn,rn,name##@h; \ 104 104 ori rn,rn,name##@l 105 105 106 - #define LOADBASE(rn,name) \ 107 - lis rn,name@highest; \ 108 - ori rn,rn,name@higher; \ 109 - rldicr rn,rn,32,31; \ 110 - oris rn,rn,name@ha 106 + #define LOADBASE(rn,name) \ 107 + .section .toc,"aw"; \ 108 + 1: .tc name[TC],name; \ 109 + .previous; \ 110 + ld rn,1b@toc(r2) 111 111 112 + #define OFF(name) 0 112 113 113 114 #define SET_REG_TO_CONST(reg, value) \ 114 115 lis reg,(((value)>>48)&0xFFFF); \ ··· 124 123 rldicr reg,reg,32,31; \ 125 124 oris reg,reg,(label)@h; \ 126 125 ori reg,reg,(label)@l; 126 + 127 + /* operations for longs and pointers */ 128 + #define LDL ld 129 + #define STL std 130 + #define CMPI cmpdi 131 + 132 + #else /* 32-bit */ 133 + #define LOADBASE(rn,name) \ 134 + lis rn,name@ha 135 + 136 + #define OFF(name) name@l 137 + 138 + /* operations for longs and pointers */ 139 + #define LDL lwz 140 + #define STL stw 141 + #define CMPI cmpwi 142 + 127 143 #endif 128 144 129 145 /* various errata or part fixups */