Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/kernel/fpu.S
26439 views
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 ([email protected])
7
* Copyright (C) 1996 Cort Dougan <[email protected]>
8
* Copyright (C) 1996 Paul Mackerras.
9
* Copyright (C) 1997 Dan Malek ([email protected]).
10
*/
11
12
#include <linux/export.h>
13
#include <asm/reg.h>
14
#include <asm/page.h>
15
#include <asm/mmu.h>
16
#include <asm/cputable.h>
17
#include <asm/cache.h>
18
#include <asm/thread_info.h>
19
#include <asm/ppc_asm.h>
20
#include <asm/asm-offsets.h>
21
#include <asm/ptrace.h>
22
#include <asm/asm-compat.h>
23
#include <asm/feature-fixups.h>
24
25
#ifdef CONFIG_VSX
26
#define __REST_1FPVSR(n,c,base) \
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
#define __REST_32FPVSRS(n,c,base) \
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
#define __SAVE_32FPVSRS(n,c,base) \
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
#else
53
#define __REST_1FPVSR(n,b,base) REST_FPR(n, base)
54
#define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base)
55
#define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base)
56
#endif
57
#define REST_1FPVSR(n,c,base) __REST_1FPVSR(n,__REG_##c,__REG_##base)
58
#define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
59
#define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
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
#else
100
ori r5,r5,MSR_FP
101
#endif
102
#ifdef CONFIG_VSX
103
BEGIN_FTR_SECTION
104
oris r5,r5,MSR_VSX@h
105
END_FTR_SECTION_IFSET(CPU_FTR_VSX)
106
#endif
107
MTMSRD(r5) /* enable use of fpu now */
108
isync
109
/* enable use of FP after return */
110
#ifdef CONFIG_PPC32
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
#else
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
#ifdef CONFIG_PPC_BOOK3S_64
123
li r4,0
124
stb r4,PACASRR_VALID(r13)
125
#endif
126
#endif
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
155
156