diff options
Diffstat (limited to 'arch/mips/kernel/elf.c')
-rw-r--r-- | arch/mips/kernel/elf.c | 303 |
1 files changed, 188 insertions, 115 deletions
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c index c92b15df6893..d2c09f6475c5 100644 --- a/arch/mips/kernel/elf.c +++ b/arch/mips/kernel/elf.c | |||
@@ -11,29 +11,112 @@ | |||
11 | #include <linux/elf.h> | 11 | #include <linux/elf.h> |
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | 13 | ||
14 | /* FPU modes */ | ||
14 | enum { | 15 | enum { |
15 | FP_ERROR = -1, | 16 | FP_FRE, |
16 | FP_DOUBLE_64A = -2, | 17 | FP_FR0, |
18 | FP_FR1, | ||
17 | }; | 19 | }; |
18 | 20 | ||
21 | /** | ||
22 | * struct mode_req - ABI FPU mode requirements | ||
23 | * @single: The program being loaded needs an FPU but it will only issue | ||
24 | * single precision instructions meaning that it can execute in | ||
25 | * either FR0 or FR1. | ||
26 | * @soft: The soft(-float) requirement means that the program being | ||
27 | * loaded needs has no FPU dependency at all (i.e. it has no | ||
28 | * FPU instructions). | ||
29 | * @fr1: The program being loaded depends on FPU being in FR=1 mode. | ||
30 | * @frdefault: The program being loaded depends on the default FPU mode. | ||
31 | * That is FR0 for O32 and FR1 for N32/N64. | ||
32 | * @fre: The program being loaded depends on FPU with FRE=1. This mode is | ||
33 | * a bridge which uses FR=1 whilst still being able to maintain | ||
34 | * full compatibility with pre-existing code using the O32 FP32 | ||
35 | * ABI. | ||
36 | * | ||
37 | * More information about the FP ABIs can be found here: | ||
38 | * | ||
39 | * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up | ||
40 | * | ||
41 | */ | ||
42 | |||
43 | struct mode_req { | ||
44 | bool single; | ||
45 | bool soft; | ||
46 | bool fr1; | ||
47 | bool frdefault; | ||
48 | bool fre; | ||
49 | }; | ||
50 | |||
51 | static const struct mode_req fpu_reqs[] = { | ||
52 | [MIPS_ABI_FP_ANY] = { true, true, true, true, true }, | ||
53 | [MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true }, | ||
54 | [MIPS_ABI_FP_SINGLE] = { true, false, false, false, false }, | ||
55 | [MIPS_ABI_FP_SOFT] = { false, true, false, false, false }, | ||
56 | [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false }, | ||
57 | [MIPS_ABI_FP_XX] = { false, false, true, true, true }, | ||
58 | [MIPS_ABI_FP_64] = { false, false, true, false, false }, | ||
59 | [MIPS_ABI_FP_64A] = { false, false, true, false, true } | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * Mode requirements when .MIPS.abiflags is not present in the ELF. | ||
64 | * Not present means that everything is acceptable except FR1. | ||
65 | */ | ||
66 | static struct mode_req none_req = { true, true, false, true, true }; | ||
67 | |||
19 | int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, | 68 | int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, |
20 | bool is_interp, struct arch_elf_state *state) | 69 | bool is_interp, struct arch_elf_state *state) |
21 | { | 70 | { |
22 | struct elfhdr *ehdr = _ehdr; | 71 | struct elf32_hdr *ehdr32 = _ehdr; |
23 | struct elf_phdr *phdr = _phdr; | 72 | struct elf32_phdr *phdr32 = _phdr; |
73 | struct elf64_phdr *phdr64 = _phdr; | ||
24 | struct mips_elf_abiflags_v0 abiflags; | 74 | struct mips_elf_abiflags_v0 abiflags; |
25 | int ret; | 75 | int ret; |
26 | 76 | ||
27 | if (config_enabled(CONFIG_64BIT) && | 77 | /* Lets see if this is an O32 ELF */ |
28 | (ehdr->e_ident[EI_CLASS] != ELFCLASS32)) | 78 | if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) { |
29 | return 0; | 79 | /* FR = 1 for N32 */ |
30 | if (phdr->p_type != PT_MIPS_ABIFLAGS) | 80 | if (ehdr32->e_flags & EF_MIPS_ABI2) |
31 | return 0; | 81 | state->overall_fp_mode = FP_FR1; |
32 | if (phdr->p_filesz < sizeof(abiflags)) | 82 | else |
33 | return -EINVAL; | 83 | /* Set a good default FPU mode for O32 */ |
84 | state->overall_fp_mode = cpu_has_mips_r6 ? | ||
85 | FP_FRE : FP_FR0; | ||
86 | |||
87 | if (ehdr32->e_flags & EF_MIPS_FP64) { | ||
88 | /* | ||
89 | * Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it | ||
90 | * later if needed | ||
91 | */ | ||
92 | if (is_interp) | ||
93 | state->interp_fp_abi = MIPS_ABI_FP_OLD_64; | ||
94 | else | ||
95 | state->fp_abi = MIPS_ABI_FP_OLD_64; | ||
96 | } | ||
97 | if (phdr32->p_type != PT_MIPS_ABIFLAGS) | ||
98 | return 0; | ||
99 | |||
100 | if (phdr32->p_filesz < sizeof(abiflags)) | ||
101 | return -EINVAL; | ||
102 | |||
103 | ret = kernel_read(elf, phdr32->p_offset, | ||
104 | (char *)&abiflags, | ||
105 | sizeof(abiflags)); | ||
106 | } else { | ||
107 | /* FR=1 is really the only option for 64-bit */ | ||
108 | state->overall_fp_mode = FP_FR1; | ||
109 | |||
110 | if (phdr64->p_type != PT_MIPS_ABIFLAGS) | ||
111 | return 0; | ||
112 | if (phdr64->p_filesz < sizeof(abiflags)) | ||
113 | return -EINVAL; | ||
114 | |||
115 | ret = kernel_read(elf, phdr64->p_offset, | ||
116 | (char *)&abiflags, | ||
117 | sizeof(abiflags)); | ||
118 | } | ||
34 | 119 | ||
35 | ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags, | ||
36 | sizeof(abiflags)); | ||
37 | if (ret < 0) | 120 | if (ret < 0) |
38 | return ret; | 121 | return ret; |
39 | if (ret != sizeof(abiflags)) | 122 | if (ret != sizeof(abiflags)) |
@@ -48,35 +131,30 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, | |||
48 | return 0; | 131 | return 0; |
49 | } | 132 | } |
50 | 133 | ||
51 | static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi) | 134 | static inline unsigned get_fp_abi(int in_abi) |
52 | { | 135 | { |
53 | /* If the ABI requirement is provided, simply return that */ | 136 | /* If the ABI requirement is provided, simply return that */ |
54 | if (in_abi != -1) | 137 | if (in_abi != MIPS_ABI_FP_UNKNOWN) |
55 | return in_abi; | 138 | return in_abi; |
56 | 139 | ||
57 | /* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */ | 140 | /* Unknown ABI */ |
58 | if (ehdr->e_flags & EF_MIPS_FP64) | 141 | return MIPS_ABI_FP_UNKNOWN; |
59 | return MIPS_ABI_FP_64; | ||
60 | |||
61 | /* Default to MIPS_ABI_FP_DOUBLE */ | ||
62 | return MIPS_ABI_FP_DOUBLE; | ||
63 | } | 142 | } |
64 | 143 | ||
65 | int arch_check_elf(void *_ehdr, bool has_interpreter, | 144 | int arch_check_elf(void *_ehdr, bool has_interpreter, |
66 | struct arch_elf_state *state) | 145 | struct arch_elf_state *state) |
67 | { | 146 | { |
68 | struct elfhdr *ehdr = _ehdr; | 147 | struct elf32_hdr *ehdr = _ehdr; |
69 | unsigned fp_abi, interp_fp_abi, abi0, abi1; | 148 | struct mode_req prog_req, interp_req; |
149 | int fp_abi, interp_fp_abi, abi0, abi1, max_abi; | ||
70 | 150 | ||
71 | /* Ignore non-O32 binaries */ | 151 | if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) |
72 | if (config_enabled(CONFIG_64BIT) && | ||
73 | (ehdr->e_ident[EI_CLASS] != ELFCLASS32)) | ||
74 | return 0; | 152 | return 0; |
75 | 153 | ||
76 | fp_abi = get_fp_abi(ehdr, state->fp_abi); | 154 | fp_abi = get_fp_abi(state->fp_abi); |
77 | 155 | ||
78 | if (has_interpreter) { | 156 | if (has_interpreter) { |
79 | interp_fp_abi = get_fp_abi(ehdr, state->interp_fp_abi); | 157 | interp_fp_abi = get_fp_abi(state->interp_fp_abi); |
80 | 158 | ||
81 | abi0 = min(fp_abi, interp_fp_abi); | 159 | abi0 = min(fp_abi, interp_fp_abi); |
82 | abi1 = max(fp_abi, interp_fp_abi); | 160 | abi1 = max(fp_abi, interp_fp_abi); |
@@ -84,108 +162,103 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, | |||
84 | abi0 = abi1 = fp_abi; | 162 | abi0 = abi1 = fp_abi; |
85 | } | 163 | } |
86 | 164 | ||
87 | state->overall_abi = FP_ERROR; | 165 | /* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */ |
88 | 166 | max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) && | |
89 | if (abi0 == abi1) { | 167 | (!(ehdr->e_flags & EF_MIPS_ABI2))) ? |
90 | state->overall_abi = abi0; | 168 | MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT; |
91 | } else if (abi0 == MIPS_ABI_FP_ANY) { | ||
92 | state->overall_abi = abi1; | ||
93 | } else if (abi0 == MIPS_ABI_FP_DOUBLE) { | ||
94 | switch (abi1) { | ||
95 | case MIPS_ABI_FP_XX: | ||
96 | state->overall_abi = MIPS_ABI_FP_DOUBLE; | ||
97 | break; | ||
98 | |||
99 | case MIPS_ABI_FP_64A: | ||
100 | state->overall_abi = FP_DOUBLE_64A; | ||
101 | break; | ||
102 | } | ||
103 | } else if (abi0 == MIPS_ABI_FP_SINGLE || | ||
104 | abi0 == MIPS_ABI_FP_SOFT) { | ||
105 | /* Cannot link with other ABIs */ | ||
106 | } else if (abi0 == MIPS_ABI_FP_OLD_64) { | ||
107 | switch (abi1) { | ||
108 | case MIPS_ABI_FP_XX: | ||
109 | case MIPS_ABI_FP_64: | ||
110 | case MIPS_ABI_FP_64A: | ||
111 | state->overall_abi = MIPS_ABI_FP_64; | ||
112 | break; | ||
113 | } | ||
114 | } else if (abi0 == MIPS_ABI_FP_XX || | ||
115 | abi0 == MIPS_ABI_FP_64 || | ||
116 | abi0 == MIPS_ABI_FP_64A) { | ||
117 | state->overall_abi = MIPS_ABI_FP_64; | ||
118 | } | ||
119 | 169 | ||
120 | switch (state->overall_abi) { | 170 | if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) || |
121 | case MIPS_ABI_FP_64: | 171 | (abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN)) |
122 | case MIPS_ABI_FP_64A: | 172 | return -ELIBBAD; |
123 | case FP_DOUBLE_64A: | 173 | |
124 | if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) | 174 | /* It's time to determine the FPU mode requirements */ |
125 | return -ELIBBAD; | 175 | prog_req = (abi0 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi0]; |
126 | break; | 176 | interp_req = (abi1 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi1]; |
127 | 177 | ||
128 | case FP_ERROR: | 178 | /* |
179 | * Check whether the program's and interp's ABIs have a matching FPU | ||
180 | * mode requirement. | ||
181 | */ | ||
182 | prog_req.single = interp_req.single && prog_req.single; | ||
183 | prog_req.soft = interp_req.soft && prog_req.soft; | ||
184 | prog_req.fr1 = interp_req.fr1 && prog_req.fr1; | ||
185 | prog_req.frdefault = interp_req.frdefault && prog_req.frdefault; | ||
186 | prog_req.fre = interp_req.fre && prog_req.fre; | ||
187 | |||
188 | /* | ||
189 | * Determine the desired FPU mode | ||
190 | * | ||
191 | * Decision making: | ||
192 | * | ||
193 | * - We want FR_FRE if FRE=1 and both FR=1 and FR=0 are false. This | ||
194 | * means that we have a combination of program and interpreter | ||
195 | * that inherently require the hybrid FP mode. | ||
196 | * - If FR1 and FRDEFAULT is true, that means we hit the any-abi or | ||
197 | * fpxx case. This is because, in any-ABI (or no-ABI) we have no FPU | ||
198 | * instructions so we don't care about the mode. We will simply use | ||
199 | * the one preferred by the hardware. In fpxx case, that ABI can | ||
200 | * handle both FR=1 and FR=0, so, again, we simply choose the one | ||
201 | * preferred by the hardware. Next, if we only use single-precision | ||
202 | * FPU instructions, and the default ABI FPU mode is not good | ||
203 | * (ie single + any ABI combination), we set again the FPU mode to the | ||
204 | * one is preferred by the hardware. Next, if we know that the code | ||
205 | * will only use single-precision instructions, shown by single being | ||
206 | * true but frdefault being false, then we again set the FPU mode to | ||
207 | * the one that is preferred by the hardware. | ||
208 | * - We want FP_FR1 if that's the only matching mode and the default one | ||
209 | * is not good. | ||
210 | * - Return with -ELIBADD if we can't find a matching FPU mode. | ||
211 | */ | ||
212 | if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) | ||
213 | state->overall_fp_mode = FP_FRE; | ||
214 | else if ((prog_req.fr1 && prog_req.frdefault) || | ||
215 | (prog_req.single && !prog_req.frdefault)) | ||
216 | /* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */ | ||
217 | state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) && | ||
218 | cpu_has_mips_r2_r6) ? | ||
219 | FP_FR1 : FP_FR0; | ||
220 | else if (prog_req.fr1) | ||
221 | state->overall_fp_mode = FP_FR1; | ||
222 | else if (!prog_req.fre && !prog_req.frdefault && | ||
223 | !prog_req.fr1 && !prog_req.single && !prog_req.soft) | ||
129 | return -ELIBBAD; | 224 | return -ELIBBAD; |
130 | } | ||
131 | 225 | ||
132 | return 0; | 226 | return 0; |
133 | } | 227 | } |
134 | 228 | ||
135 | void mips_set_personality_fp(struct arch_elf_state *state) | 229 | static inline void set_thread_fp_mode(int hybrid, int regs32) |
136 | { | 230 | { |
137 | if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) { | 231 | if (hybrid) |
138 | /* | 232 | set_thread_flag(TIF_HYBRID_FPREGS); |
139 | * Use hybrid FPRs for all code which can correctly execute | 233 | else |
140 | * with that mode. | ||
141 | */ | ||
142 | switch (state->overall_abi) { | ||
143 | case MIPS_ABI_FP_DOUBLE: | ||
144 | case MIPS_ABI_FP_SINGLE: | ||
145 | case MIPS_ABI_FP_SOFT: | ||
146 | case MIPS_ABI_FP_XX: | ||
147 | case MIPS_ABI_FP_ANY: | ||
148 | /* FR=1, FRE=1 */ | ||
149 | clear_thread_flag(TIF_32BIT_FPREGS); | ||
150 | set_thread_flag(TIF_HYBRID_FPREGS); | ||
151 | return; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | switch (state->overall_abi) { | ||
156 | case MIPS_ABI_FP_DOUBLE: | ||
157 | case MIPS_ABI_FP_SINGLE: | ||
158 | case MIPS_ABI_FP_SOFT: | ||
159 | /* FR=0 */ | ||
160 | set_thread_flag(TIF_32BIT_FPREGS); | ||
161 | clear_thread_flag(TIF_HYBRID_FPREGS); | 234 | clear_thread_flag(TIF_HYBRID_FPREGS); |
162 | break; | 235 | if (regs32) |
163 | 236 | set_thread_flag(TIF_32BIT_FPREGS); | |
164 | case FP_DOUBLE_64A: | 237 | else |
165 | /* FR=1, FRE=1 */ | ||
166 | clear_thread_flag(TIF_32BIT_FPREGS); | 238 | clear_thread_flag(TIF_32BIT_FPREGS); |
167 | set_thread_flag(TIF_HYBRID_FPREGS); | 239 | } |
168 | break; | ||
169 | 240 | ||
170 | case MIPS_ABI_FP_64: | 241 | void mips_set_personality_fp(struct arch_elf_state *state) |
171 | case MIPS_ABI_FP_64A: | 242 | { |
172 | /* FR=1, FRE=0 */ | 243 | /* |
173 | clear_thread_flag(TIF_32BIT_FPREGS); | 244 | * This function is only ever called for O32 ELFs so we should |
174 | clear_thread_flag(TIF_HYBRID_FPREGS); | 245 | * not be worried about N32/N64 binaries. |
175 | break; | 246 | */ |
176 | 247 | ||
177 | case MIPS_ABI_FP_XX: | 248 | if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) |
178 | case MIPS_ABI_FP_ANY: | 249 | return; |
179 | if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) | ||
180 | set_thread_flag(TIF_32BIT_FPREGS); | ||
181 | else | ||
182 | clear_thread_flag(TIF_32BIT_FPREGS); | ||
183 | 250 | ||
184 | clear_thread_flag(TIF_HYBRID_FPREGS); | 251 | switch (state->overall_fp_mode) { |
252 | case FP_FRE: | ||
253 | set_thread_fp_mode(1, 0); | ||
254 | break; | ||
255 | case FP_FR0: | ||
256 | set_thread_fp_mode(0, 1); | ||
257 | break; | ||
258 | case FP_FR1: | ||
259 | set_thread_fp_mode(0, 0); | ||
185 | break; | 260 | break; |
186 | |||
187 | default: | 261 | default: |
188 | case FP_ERROR: | ||
189 | BUG(); | 262 | BUG(); |
190 | } | 263 | } |
191 | } | 264 | } |