| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */
|
| 2 | /*
|
| 3 | * FPU support code, moved here from head.S so that it can be used
|
| 4 | * by chips which use other head-whatever.S files.
|
| 5 | *
|
| 6 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
| 7 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
|
| 8 | * Copyright (C) 1996 Paul Mackerras.
|
| 9 | * Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
|
| 10 | */
|
| 11 |
|
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 |
|
| 25 | |
| 26 | |
| 27 | BEGIN_FTR_SECTION \
|
| 28 | b 2f; \
|
| 29 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
| 30 | REST_FPR(n,base); \
|
| 31 | b 3f; \
|
| 32 | 2: REST_VSR(n,c,base); \
|
| 33 | 3:
|
| 34 |
|
| 35 | |
| 36 | BEGIN_FTR_SECTION \
|
| 37 | b 2f; \
|
| 38 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
| 39 | REST_32FPRS(n,base); \
|
| 40 | b 3f; \
|
| 41 | 2: REST_32VSRS(n,c,base); \
|
| 42 | 3:
|
| 43 |
|
| 44 | |
| 45 | BEGIN_FTR_SECTION \
|
| 46 | b 2f; \
|
| 47 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
| 48 | SAVE_32FPRS(n,base); \
|
| 49 | b 3f; \
|
| 50 | 2: SAVE_32VSRS(n,c,base); \
|
| 51 | 3:
|
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 |
|
| 61 | /*
|
| 62 | * Load state from memory into FP registers including FPSCR.
|
| 63 | * Assumes the caller has enabled FP in the MSR.
|
| 64 | */
|
| 65 | _GLOBAL(load_fp_state)
|
| 66 | lfd fr0,FPSTATE_FPSCR(r3)
|
| 67 | MTFSF_L(fr0)
|
| 68 | REST_32FPVSRS(0, R4, R3)
|
| 69 | blr
|
| 70 | EXPORT_SYMBOL(load_fp_state)
|
| 71 | _ASM_NOKPROBE_SYMBOL(load_fp_state); /* used by restore_math */
|
| 72 |
|
| 73 | /*
|
| 74 | * Store FP state into memory, including FPSCR
|
| 75 | * Assumes the caller has enabled FP in the MSR.
|
| 76 | */
|
| 77 | _GLOBAL(store_fp_state)
|
| 78 | SAVE_32FPVSRS(0, R4, R3)
|
| 79 | mffs fr0
|
| 80 | stfd fr0,FPSTATE_FPSCR(r3)
|
| 81 | REST_1FPVSR(0, R4, R3)
|
| 82 | blr
|
| 83 | EXPORT_SYMBOL(store_fp_state)
|
| 84 |
|
| 85 | /*
|
| 86 | * This task wants to use the FPU now.
|
| 87 | * On UP, disable FP for the task which had the FPU previously,
|
| 88 | * and save its floating-point registers in its thread_struct.
|
| 89 | * Load up this task's FP registers from its thread_struct,
|
| 90 | * enable the FPU for the current task and return to the task.
|
| 91 | * Note that on 32-bit this can only use registers that will be
|
| 92 | * restored by fast_exception_return, i.e. r3 - r6, r10 and r11.
|
| 93 | */
|
| 94 | _GLOBAL(load_up_fpu)
|
| 95 | mfmsr r5
|
| 96 | #ifdef CONFIG_PPC_BOOK3S_64
|
| 97 | /* interrupt doesn't set MSR[RI] and HPT can fault on current access */
|
| 98 | ori r5,r5,MSR_FP|MSR_RI
|
| 99 | |
| 100 | ori r5,r5,MSR_FP
|
| 101 | |
| 102 | |
| 103 | BEGIN_FTR_SECTION
|
| 104 | oris r5,r5,MSR_VSX@h
|
| 105 | END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
| 106 | |
| 107 | MTMSRD(r5) /* enable use of fpu now */
|
| 108 | isync
|
| 109 | /* enable use of FP after return */
|
| 110 | |
| 111 | addi r5,r2,THREAD
|
| 112 | lwz r4,THREAD_FPEXC_MODE(r5)
|
| 113 | ori r9,r9,MSR_FP /* enable FP for current */
|
| 114 | or r9,r9,r4
|
| 115 | |
| 116 | ld r4,PACACURRENT(r13)
|
| 117 | addi r5,r4,THREAD /* Get THREAD */
|
| 118 | lwz r4,THREAD_FPEXC_MODE(r5)
|
| 119 | ori r12,r12,MSR_FP
|
| 120 | or r12,r12,r4
|
| 121 | std r12,_MSR(r1)
|
| 122 | |
| 123 | li r4,0
|
| 124 | stb r4,PACASRR_VALID(r13)
|
| 125 | |
| 126 | |
| 127 | li r4,1
|
| 128 | stb r4,THREAD_LOAD_FP(r5)
|
| 129 | addi r10,r5,THREAD_FPSTATE
|
| 130 | lfd fr0,FPSTATE_FPSCR(r10)
|
| 131 | MTFSF_L(fr0)
|
| 132 | REST_32FPVSRS(0, R4, R10)
|
| 133 | /* restore registers and return */
|
| 134 | /* we haven't used ctr or xer or lr */
|
| 135 | blr
|
| 136 | _ASM_NOKPROBE_SYMBOL(load_up_fpu)
|
| 137 |
|
| 138 | /*
|
| 139 | * save_fpu(tsk)
|
| 140 | * Save the floating-point registers in its thread_struct.
|
| 141 | * Enables the FPU for use in the kernel on return.
|
| 142 | */
|
| 143 | _GLOBAL(save_fpu)
|
| 144 | addi r3,r3,THREAD /* want THREAD of task */
|
| 145 | PPC_LL r6,THREAD_FPSAVEAREA(r3)
|
| 146 | PPC_LL r5,PT_REGS(r3)
|
| 147 | PPC_LCMPI 0,r6,0
|
| 148 | bne 2f
|
| 149 | addi r6,r3,THREAD_FPSTATE
|
| 150 | 2: SAVE_32FPVSRS(0, R4, R6)
|
| 151 | mffs fr0
|
| 152 | stfd fr0,FPSTATE_FPSCR(r6)
|
| 153 | REST_1FPVSR(0, R4, R6)
|
| 154 | blr
|