Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  *  FPU support code, moved here from head.S so that it can be used
0004  *  by chips which use other head-whatever.S files.
0005  *
0006  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
0007  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
0008  *    Copyright (C) 1996 Paul Mackerras.
0009  *    Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
0010  */
0011 
0012 #include <asm/reg.h>
0013 #include <asm/page.h>
0014 #include <asm/mmu.h>
0015 #include <asm/cputable.h>
0016 #include <asm/cache.h>
0017 #include <asm/thread_info.h>
0018 #include <asm/ppc_asm.h>
0019 #include <asm/asm-offsets.h>
0020 #include <asm/ptrace.h>
0021 #include <asm/export.h>
0022 #include <asm/asm-compat.h>
0023 #include <asm/feature-fixups.h>
0024 
0025 #ifdef CONFIG_VSX
0026 #define __REST_32FPVSRS(n,c,base)                   \
0027 BEGIN_FTR_SECTION                           \
0028     b   2f;                         \
0029 END_FTR_SECTION_IFSET(CPU_FTR_VSX);                 \
0030     REST_32FPRS(n,base);                        \
0031     b   3f;                         \
0032 2:  REST_32VSRS(n,c,base);                      \
0033 3:
0034 
0035 #define __SAVE_32FPVSRS(n,c,base)                   \
0036 BEGIN_FTR_SECTION                           \
0037     b   2f;                         \
0038 END_FTR_SECTION_IFSET(CPU_FTR_VSX);                 \
0039     SAVE_32FPRS(n,base);                        \
0040     b   3f;                         \
0041 2:  SAVE_32VSRS(n,c,base);                      \
0042 3:
0043 #else
0044 #define __REST_32FPVSRS(n,b,base)   REST_32FPRS(n, base)
0045 #define __SAVE_32FPVSRS(n,b,base)   SAVE_32FPRS(n, base)
0046 #endif
0047 #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
0048 #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
0049 
0050 /*
0051  * Load state from memory into FP registers including FPSCR.
0052  * Assumes the caller has enabled FP in the MSR.
0053  */
0054 _GLOBAL(load_fp_state)
0055     lfd fr0,FPSTATE_FPSCR(r3)
0056     MTFSF_L(fr0)
0057     REST_32FPVSRS(0, R4, R3)
0058     blr
0059 EXPORT_SYMBOL(load_fp_state)
0060 _ASM_NOKPROBE_SYMBOL(load_fp_state); /* used by restore_math */
0061 
0062 /*
0063  * Store FP state into memory, including FPSCR
0064  * Assumes the caller has enabled FP in the MSR.
0065  */
0066 _GLOBAL(store_fp_state)
0067     SAVE_32FPVSRS(0, R4, R3)
0068     mffs    fr0
0069     stfd    fr0,FPSTATE_FPSCR(r3)
0070     blr
0071 EXPORT_SYMBOL(store_fp_state)
0072 
0073 /*
0074  * This task wants to use the FPU now.
0075  * On UP, disable FP for the task which had the FPU previously,
0076  * and save its floating-point registers in its thread_struct.
0077  * Load up this task's FP registers from its thread_struct,
0078  * enable the FPU for the current task and return to the task.
0079  * Note that on 32-bit this can only use registers that will be
0080  * restored by fast_exception_return, i.e. r3 - r6, r10 and r11.
0081  */
0082 _GLOBAL(load_up_fpu)
0083     mfmsr   r5
0084 #ifdef CONFIG_PPC_BOOK3S_64
0085     /* interrupt doesn't set MSR[RI] and HPT can fault on current access */
0086     ori r5,r5,MSR_FP|MSR_RI
0087 #else
0088     ori r5,r5,MSR_FP
0089 #endif
0090 #ifdef CONFIG_VSX
0091 BEGIN_FTR_SECTION
0092     oris    r5,r5,MSR_VSX@h
0093 END_FTR_SECTION_IFSET(CPU_FTR_VSX)
0094 #endif
0095     MTMSRD(r5)          /* enable use of fpu now */
0096     isync
0097     /* enable use of FP after return */
0098 #ifdef CONFIG_PPC32
0099     addi    r5,r2,THREAD
0100     lwz r4,THREAD_FPEXC_MODE(r5)
0101     ori r9,r9,MSR_FP        /* enable FP for current */
0102     or  r9,r9,r4
0103 #else
0104     ld  r4,PACACURRENT(r13)
0105     addi    r5,r4,THREAD        /* Get THREAD */
0106     lwz r4,THREAD_FPEXC_MODE(r5)
0107     ori r12,r12,MSR_FP
0108     or  r12,r12,r4
0109     std r12,_MSR(r1)
0110 #ifdef CONFIG_PPC_BOOK3S_64
0111     li  r4,0
0112     stb r4,PACASRR_VALID(r13)
0113 #endif
0114 #endif
0115     li  r4,1
0116     stb r4,THREAD_LOAD_FP(r5)
0117     addi    r10,r5,THREAD_FPSTATE
0118     lfd fr0,FPSTATE_FPSCR(r10)
0119     MTFSF_L(fr0)
0120     REST_32FPVSRS(0, R4, R10)
0121     /* restore registers and return */
0122     /* we haven't used ctr or xer or lr */
0123     blr
0124 _ASM_NOKPROBE_SYMBOL(load_up_fpu)
0125 
0126 /*
0127  * save_fpu(tsk)
0128  * Save the floating-point registers in its thread_struct.
0129  * Enables the FPU for use in the kernel on return.
0130  */
0131 _GLOBAL(save_fpu)
0132     addi    r3,r3,THREAD            /* want THREAD of task */
0133     PPC_LL  r6,THREAD_FPSAVEAREA(r3)
0134     PPC_LL  r5,PT_REGS(r3)
0135     PPC_LCMPI   0,r6,0
0136     bne 2f
0137     addi    r6,r3,THREAD_FPSTATE
0138 2:  SAVE_32FPVSRS(0, R4, R6)
0139     mffs    fr0
0140     stfd    fr0,FPSTATE_FPSCR(r6)
0141     blr