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