1 /* 2 * FPU register's regset abstraction, for ptrace, core dumps, etc. 3 */ 4 #include <asm/fpu/internal.h> 5 #include <asm/fpu/signal.h> 6 #include <asm/fpu/regset.h> 7 #include <asm/fpu/xstate.h> 8 #include <linux/sched/task_stack.h> 9 10 /* 11 * The xstateregs_active() routine is the same as the regset_fpregs_active() routine, 12 * as the "regset->n" for the xstate regset will be updated based on the feature 13 * capabilities supported by the xsave. 14 */ 15 int regset_fpregs_active(struct task_struct *target, const struct user_regset *regset) 16 { 17 struct fpu *target_fpu = &target->thread.fpu; 18 19 return target_fpu->initialized ? regset->n : 0; 20 } 21 22 int regset_xregset_fpregs_active(struct task_struct *target, const struct user_regset *regset) 23 { 24 struct fpu *target_fpu = &target->thread.fpu; 25 26 if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->initialized) 27 return regset->n; 28 else 29 return 0; 30 } 31 32 int xfpregs_get(struct task_struct *target, const struct user_regset *regset, 33 unsigned int pos, unsigned int count, 34 void *kbuf, void __user *ubuf) 35 { 36 struct fpu *fpu = &target->thread.fpu; 37 38 if (!boot_cpu_has(X86_FEATURE_FXSR)) 39 return -ENODEV; 40 41 fpu__prepare_read(fpu); 42 fpstate_sanitize_xstate(fpu); 43 44 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 45 &fpu->state.fxsave, 0, -1); 46 } 47 48 int xfpregs_set(struct task_struct *target, const struct user_regset *regset, 49 unsigned int pos, unsigned int count, 50 const void *kbuf, const void __user *ubuf) 51 { 52 struct fpu *fpu = &target->thread.fpu; 53 int ret; 54 55 if (!boot_cpu_has(X86_FEATURE_FXSR)) 56 return -ENODEV; 57 58 fpu__prepare_write(fpu); 59 fpstate_sanitize_xstate(fpu); 60 61 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 62 &fpu->state.fxsave, 0, -1); 63 64 /* 65 * mxcsr reserved bits must be masked to zero for security reasons. 66 */ 67 fpu->state.fxsave.mxcsr &= mxcsr_feature_mask; 68 69 /* 70 * update the header bits in the xsave header, indicating the 71 * presence of FP and SSE state. 72 */ 73 if (boot_cpu_has(X86_FEATURE_XSAVE)) 74 fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FPSSE; 75 76 return ret; 77 } 78 79 int xstateregs_get(struct task_struct *target, const struct user_regset *regset, 80 unsigned int pos, unsigned int count, 81 void *kbuf, void __user *ubuf) 82 { 83 struct fpu *fpu = &target->thread.fpu; 84 struct xregs_state *xsave; 85 int ret; 86 87 if (!boot_cpu_has(X86_FEATURE_XSAVE)) 88 return -ENODEV; 89 90 xsave = &fpu->state.xsave; 91 92 fpu__prepare_read(fpu); 93 94 if (using_compacted_format()) { 95 if (kbuf) 96 ret = copy_xstate_to_kernel(kbuf, xsave, pos, count); 97 else 98 ret = copy_xstate_to_user(ubuf, xsave, pos, count); 99 } else { 100 fpstate_sanitize_xstate(fpu); 101 /* 102 * Copy the 48 bytes defined by the software into the xsave 103 * area in the thread struct, so that we can copy the whole 104 * area to user using one user_regset_copyout(). 105 */ 106 memcpy(&xsave->i387.sw_reserved, xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes)); 107 108 /* 109 * Copy the xstate memory layout. 110 */ 111 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); 112 } 113 return ret; 114 } 115 116 int xstateregs_set(struct task_struct *target, const struct user_regset *regset, 117 unsigned int pos, unsigned int count, 118 const void *kbuf, const void __user *ubuf) 119 { 120 struct fpu *fpu = &target->thread.fpu; 121 struct xregs_state *xsave; 122 int ret; 123 124 if (!boot_cpu_has(X86_FEATURE_XSAVE)) 125 return -ENODEV; 126 127 /* 128 * A whole standard-format XSAVE buffer is needed: 129 */ 130 if ((pos != 0) || (count < fpu_user_xstate_size)) 131 return -EFAULT; 132 133 xsave = &fpu->state.xsave; 134 135 fpu__prepare_write(fpu); 136 137 if (using_compacted_format()) { 138 if (kbuf) 139 ret = copy_kernel_to_xstate(xsave, kbuf); 140 else 141 ret = copy_user_to_xstate(xsave, ubuf); 142 } else { 143 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); 144 if (!ret) 145 ret = validate_xstate_header(&xsave->header); 146 } 147 148 /* 149 * mxcsr reserved bits must be masked to zero for security reasons. 150 */ 151 xsave->i387.mxcsr &= mxcsr_feature_mask; 152 153 /* 154 * In case of failure, mark all states as init: 155 */ 156 if (ret) 157 fpstate_init(&fpu->state); 158 159 return ret; 160 } 161 162 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION 163 164 /* 165 * FPU tag word conversions. 166 */ 167 168 static inline unsigned short twd_i387_to_fxsr(unsigned short twd) 169 { 170 unsigned int tmp; /* to avoid 16 bit prefixes in the code */ 171 172 /* Transform each pair of bits into 01 (valid) or 00 (empty) */ 173 tmp = ~twd; 174 tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ 175 /* and move the valid bits to the lower byte. */ 176 tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ 177 tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ 178 tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ 179 180 return tmp; 181 } 182 183 #define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16) 184 #define FP_EXP_TAG_VALID 0 185 #define FP_EXP_TAG_ZERO 1 186 #define FP_EXP_TAG_SPECIAL 2 187 #define FP_EXP_TAG_EMPTY 3 188 189 static inline u32 twd_fxsr_to_i387(struct fxregs_state *fxsave) 190 { 191 struct _fpxreg *st; 192 u32 tos = (fxsave->swd >> 11) & 7; 193 u32 twd = (unsigned long) fxsave->twd; 194 u32 tag; 195 u32 ret = 0xffff0000u; 196 int i; 197 198 for (i = 0; i < 8; i++, twd >>= 1) { 199 if (twd & 0x1) { 200 st = FPREG_ADDR(fxsave, (i - tos) & 7); 201 202 switch (st->exponent & 0x7fff) { 203 case 0x7fff: 204 tag = FP_EXP_TAG_SPECIAL; 205 break; 206 case 0x0000: 207 if (!st->significand[0] && 208 !st->significand[1] && 209 !st->significand[2] && 210 !st->significand[3]) 211 tag = FP_EXP_TAG_ZERO; 212 else 213 tag = FP_EXP_TAG_SPECIAL; 214 break; 215 default: 216 if (st->significand[3] & 0x8000) 217 tag = FP_EXP_TAG_VALID; 218 else 219 tag = FP_EXP_TAG_SPECIAL; 220 break; 221 } 222 } else { 223 tag = FP_EXP_TAG_EMPTY; 224 } 225 ret |= tag << (2 * i); 226 } 227 return ret; 228 } 229 230 /* 231 * FXSR floating point environment conversions. 232 */ 233 234 void 235 convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) 236 { 237 struct fxregs_state *fxsave = &tsk->thread.fpu.state.fxsave; 238 struct _fpreg *to = (struct _fpreg *) &env->st_space[0]; 239 struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0]; 240 int i; 241 242 env->cwd = fxsave->cwd | 0xffff0000u; 243 env->swd = fxsave->swd | 0xffff0000u; 244 env->twd = twd_fxsr_to_i387(fxsave); 245 246 #ifdef CONFIG_X86_64 247 env->fip = fxsave->rip; 248 env->foo = fxsave->rdp; 249 /* 250 * should be actually ds/cs at fpu exception time, but 251 * that information is not available in 64bit mode. 252 */ 253 env->fcs = task_pt_regs(tsk)->cs; 254 if (tsk == current) { 255 savesegment(ds, env->fos); 256 } else { 257 env->fos = tsk->thread.ds; 258 } 259 env->fos |= 0xffff0000; 260 #else 261 env->fip = fxsave->fip; 262 env->fcs = (u16) fxsave->fcs | ((u32) fxsave->fop << 16); 263 env->foo = fxsave->foo; 264 env->fos = fxsave->fos; 265 #endif 266 267 for (i = 0; i < 8; ++i) 268 memcpy(&to[i], &from[i], sizeof(to[0])); 269 } 270 271 void convert_to_fxsr(struct task_struct *tsk, 272 const struct user_i387_ia32_struct *env) 273 274 { 275 struct fxregs_state *fxsave = &tsk->thread.fpu.state.fxsave; 276 struct _fpreg *from = (struct _fpreg *) &env->st_space[0]; 277 struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0]; 278 int i; 279 280 fxsave->cwd = env->cwd; 281 fxsave->swd = env->swd; 282 fxsave->twd = twd_i387_to_fxsr(env->twd); 283 fxsave->fop = (u16) ((u32) env->fcs >> 16); 284 #ifdef CONFIG_X86_64 285 fxsave->rip = env->fip; 286 fxsave->rdp = env->foo; 287 /* cs and ds ignored */ 288 #else 289 fxsave->fip = env->fip; 290 fxsave->fcs = (env->fcs & 0xffff); 291 fxsave->foo = env->foo; 292 fxsave->fos = env->fos; 293 #endif 294 295 for (i = 0; i < 8; ++i) 296 memcpy(&to[i], &from[i], sizeof(from[0])); 297 } 298 299 int fpregs_get(struct task_struct *target, const struct user_regset *regset, 300 unsigned int pos, unsigned int count, 301 void *kbuf, void __user *ubuf) 302 { 303 struct fpu *fpu = &target->thread.fpu; 304 struct user_i387_ia32_struct env; 305 306 fpu__prepare_read(fpu); 307 308 if (!boot_cpu_has(X86_FEATURE_FPU)) 309 return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf); 310 311 if (!boot_cpu_has(X86_FEATURE_FXSR)) 312 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 313 &fpu->state.fsave, 0, 314 -1); 315 316 fpstate_sanitize_xstate(fpu); 317 318 if (kbuf && pos == 0 && count == sizeof(env)) { 319 convert_from_fxsr(kbuf, target); 320 return 0; 321 } 322 323 convert_from_fxsr(&env, target); 324 325 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &env, 0, -1); 326 } 327 328 int fpregs_set(struct task_struct *target, const struct user_regset *regset, 329 unsigned int pos, unsigned int count, 330 const void *kbuf, const void __user *ubuf) 331 { 332 struct fpu *fpu = &target->thread.fpu; 333 struct user_i387_ia32_struct env; 334 int ret; 335 336 fpu__prepare_write(fpu); 337 fpstate_sanitize_xstate(fpu); 338 339 if (!boot_cpu_has(X86_FEATURE_FPU)) 340 return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf); 341 342 if (!boot_cpu_has(X86_FEATURE_FXSR)) 343 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 344 &fpu->state.fsave, 0, 345 -1); 346 347 if (pos > 0 || count < sizeof(env)) 348 convert_from_fxsr(&env, target); 349 350 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &env, 0, -1); 351 if (!ret) 352 convert_to_fxsr(target, &env); 353 354 /* 355 * update the header bit in the xsave header, indicating the 356 * presence of FP. 357 */ 358 if (boot_cpu_has(X86_FEATURE_XSAVE)) 359 fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FP; 360 return ret; 361 } 362 363 /* 364 * FPU state for core dumps. 365 * This is only used for a.out dumps now. 366 * It is declared generically using elf_fpregset_t (which is 367 * struct user_i387_struct) but is in fact only used for 32-bit 368 * dumps, so on 64-bit it is really struct user_i387_ia32_struct. 369 */ 370 int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu) 371 { 372 struct task_struct *tsk = current; 373 struct fpu *fpu = &tsk->thread.fpu; 374 int fpvalid; 375 376 fpvalid = fpu->initialized; 377 if (fpvalid) 378 fpvalid = !fpregs_get(tsk, NULL, 379 0, sizeof(struct user_i387_ia32_struct), 380 ufpu, NULL); 381 382 return fpvalid; 383 } 384 EXPORT_SYMBOL(dump_fpu); 385 386 #endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */ 387