| .. | .. |
|---|
| 15 | 15 | */ |
|---|
| 16 | 16 | int regset_fpregs_active(struct task_struct *target, const struct user_regset *regset) |
|---|
| 17 | 17 | { |
|---|
| 18 | | - struct fpu *target_fpu = &target->thread.fpu; |
|---|
| 19 | | - |
|---|
| 20 | | - return target_fpu->initialized ? regset->n : 0; |
|---|
| 18 | + return regset->n; |
|---|
| 21 | 19 | } |
|---|
| 22 | 20 | |
|---|
| 23 | 21 | int regset_xregset_fpregs_active(struct task_struct *target, const struct user_regset *regset) |
|---|
| 24 | 22 | { |
|---|
| 25 | | - struct fpu *target_fpu = &target->thread.fpu; |
|---|
| 26 | | - |
|---|
| 27 | | - if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->initialized) |
|---|
| 23 | + if (boot_cpu_has(X86_FEATURE_FXSR)) |
|---|
| 28 | 24 | return regset->n; |
|---|
| 29 | 25 | else |
|---|
| 30 | 26 | return 0; |
|---|
| 31 | 27 | } |
|---|
| 32 | 28 | |
|---|
| 33 | 29 | int xfpregs_get(struct task_struct *target, const struct user_regset *regset, |
|---|
| 34 | | - unsigned int pos, unsigned int count, |
|---|
| 35 | | - void *kbuf, void __user *ubuf) |
|---|
| 30 | + struct membuf to) |
|---|
| 36 | 31 | { |
|---|
| 37 | 32 | struct fpu *fpu = &target->thread.fpu; |
|---|
| 38 | 33 | |
|---|
| .. | .. |
|---|
| 42 | 37 | fpu__prepare_read(fpu); |
|---|
| 43 | 38 | fpstate_sanitize_xstate(fpu); |
|---|
| 44 | 39 | |
|---|
| 45 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 46 | | - &fpu->state.fxsave, 0, -1); |
|---|
| 40 | + return membuf_write(&to, &fpu->state.fxsave, sizeof(struct fxregs_state)); |
|---|
| 47 | 41 | } |
|---|
| 48 | 42 | |
|---|
| 49 | 43 | int xfpregs_set(struct task_struct *target, const struct user_regset *regset, |
|---|
| .. | .. |
|---|
| 78 | 72 | } |
|---|
| 79 | 73 | |
|---|
| 80 | 74 | int xstateregs_get(struct task_struct *target, const struct user_regset *regset, |
|---|
| 81 | | - unsigned int pos, unsigned int count, |
|---|
| 82 | | - void *kbuf, void __user *ubuf) |
|---|
| 75 | + struct membuf to) |
|---|
| 83 | 76 | { |
|---|
| 84 | 77 | struct fpu *fpu = &target->thread.fpu; |
|---|
| 85 | 78 | struct xregs_state *xsave; |
|---|
| 86 | | - int ret; |
|---|
| 87 | 79 | |
|---|
| 88 | 80 | if (!boot_cpu_has(X86_FEATURE_XSAVE)) |
|---|
| 89 | 81 | return -ENODEV; |
|---|
| .. | .. |
|---|
| 93 | 85 | fpu__prepare_read(fpu); |
|---|
| 94 | 86 | |
|---|
| 95 | 87 | if (using_compacted_format()) { |
|---|
| 96 | | - if (kbuf) |
|---|
| 97 | | - ret = copy_xstate_to_kernel(kbuf, xsave, pos, count); |
|---|
| 98 | | - else |
|---|
| 99 | | - ret = copy_xstate_to_user(ubuf, xsave, pos, count); |
|---|
| 88 | + copy_xstate_to_kernel(to, xsave); |
|---|
| 89 | + return 0; |
|---|
| 100 | 90 | } else { |
|---|
| 101 | 91 | fpstate_sanitize_xstate(fpu); |
|---|
| 102 | 92 | /* |
|---|
| .. | .. |
|---|
| 109 | 99 | /* |
|---|
| 110 | 100 | * Copy the xstate memory layout. |
|---|
| 111 | 101 | */ |
|---|
| 112 | | - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); |
|---|
| 102 | + return membuf_write(&to, xsave, fpu_user_xstate_size); |
|---|
| 113 | 103 | } |
|---|
| 114 | | - return ret; |
|---|
| 115 | 104 | } |
|---|
| 116 | 105 | |
|---|
| 117 | 106 | int xstateregs_set(struct task_struct *target, const struct user_regset *regset, |
|---|
| .. | .. |
|---|
| 143 | 132 | } else { |
|---|
| 144 | 133 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); |
|---|
| 145 | 134 | if (!ret) |
|---|
| 146 | | - ret = validate_xstate_header(&xsave->header); |
|---|
| 135 | + ret = validate_user_xstate_header(&xsave->header); |
|---|
| 147 | 136 | } |
|---|
| 148 | 137 | |
|---|
| 149 | 138 | /* |
|---|
| .. | .. |
|---|
| 269 | 258 | memcpy(&to[i], &from[i], sizeof(to[0])); |
|---|
| 270 | 259 | } |
|---|
| 271 | 260 | |
|---|
| 272 | | -void convert_to_fxsr(struct task_struct *tsk, |
|---|
| 261 | +void convert_to_fxsr(struct fxregs_state *fxsave, |
|---|
| 273 | 262 | const struct user_i387_ia32_struct *env) |
|---|
| 274 | 263 | |
|---|
| 275 | 264 | { |
|---|
| 276 | | - struct fxregs_state *fxsave = &tsk->thread.fpu.state.fxsave; |
|---|
| 277 | 265 | struct _fpreg *from = (struct _fpreg *) &env->st_space[0]; |
|---|
| 278 | 266 | struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0]; |
|---|
| 279 | 267 | int i; |
|---|
| .. | .. |
|---|
| 298 | 286 | } |
|---|
| 299 | 287 | |
|---|
| 300 | 288 | int fpregs_get(struct task_struct *target, const struct user_regset *regset, |
|---|
| 301 | | - unsigned int pos, unsigned int count, |
|---|
| 302 | | - void *kbuf, void __user *ubuf) |
|---|
| 289 | + struct membuf to) |
|---|
| 303 | 290 | { |
|---|
| 304 | 291 | struct fpu *fpu = &target->thread.fpu; |
|---|
| 305 | 292 | struct user_i387_ia32_struct env; |
|---|
| .. | .. |
|---|
| 307 | 294 | fpu__prepare_read(fpu); |
|---|
| 308 | 295 | |
|---|
| 309 | 296 | if (!boot_cpu_has(X86_FEATURE_FPU)) |
|---|
| 310 | | - return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf); |
|---|
| 297 | + return fpregs_soft_get(target, regset, to); |
|---|
| 311 | 298 | |
|---|
| 312 | | - if (!boot_cpu_has(X86_FEATURE_FXSR)) |
|---|
| 313 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 314 | | - &fpu->state.fsave, 0, |
|---|
| 315 | | - -1); |
|---|
| 299 | + if (!boot_cpu_has(X86_FEATURE_FXSR)) { |
|---|
| 300 | + return membuf_write(&to, &fpu->state.fsave, |
|---|
| 301 | + sizeof(struct fregs_state)); |
|---|
| 302 | + } |
|---|
| 316 | 303 | |
|---|
| 317 | 304 | fpstate_sanitize_xstate(fpu); |
|---|
| 318 | 305 | |
|---|
| 319 | | - if (kbuf && pos == 0 && count == sizeof(env)) { |
|---|
| 320 | | - convert_from_fxsr(kbuf, target); |
|---|
| 306 | + if (to.left == sizeof(env)) { |
|---|
| 307 | + convert_from_fxsr(to.p, target); |
|---|
| 321 | 308 | return 0; |
|---|
| 322 | 309 | } |
|---|
| 323 | 310 | |
|---|
| 324 | 311 | convert_from_fxsr(&env, target); |
|---|
| 325 | | - |
|---|
| 326 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &env, 0, -1); |
|---|
| 312 | + return membuf_write(&to, &env, sizeof(env)); |
|---|
| 327 | 313 | } |
|---|
| 328 | 314 | |
|---|
| 329 | 315 | int fpregs_set(struct task_struct *target, const struct user_regset *regset, |
|---|
| .. | .. |
|---|
| 350 | 336 | |
|---|
| 351 | 337 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &env, 0, -1); |
|---|
| 352 | 338 | if (!ret) |
|---|
| 353 | | - convert_to_fxsr(target, &env); |
|---|
| 339 | + convert_to_fxsr(&target->thread.fpu.state.fxsave, &env); |
|---|
| 354 | 340 | |
|---|
| 355 | 341 | /* |
|---|
| 356 | 342 | * update the header bit in the xsave header, indicating the |
|---|
| .. | .. |
|---|
| 360 | 346 | fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FP; |
|---|
| 361 | 347 | return ret; |
|---|
| 362 | 348 | } |
|---|
| 363 | | - |
|---|
| 364 | | -/* |
|---|
| 365 | | - * FPU state for core dumps. |
|---|
| 366 | | - * This is only used for a.out dumps now. |
|---|
| 367 | | - * It is declared generically using elf_fpregset_t (which is |
|---|
| 368 | | - * struct user_i387_struct) but is in fact only used for 32-bit |
|---|
| 369 | | - * dumps, so on 64-bit it is really struct user_i387_ia32_struct. |
|---|
| 370 | | - */ |
|---|
| 371 | | -int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu) |
|---|
| 372 | | -{ |
|---|
| 373 | | - struct task_struct *tsk = current; |
|---|
| 374 | | - struct fpu *fpu = &tsk->thread.fpu; |
|---|
| 375 | | - int fpvalid; |
|---|
| 376 | | - |
|---|
| 377 | | - fpvalid = fpu->initialized; |
|---|
| 378 | | - if (fpvalid) |
|---|
| 379 | | - fpvalid = !fpregs_get(tsk, NULL, |
|---|
| 380 | | - 0, sizeof(struct user_i387_ia32_struct), |
|---|
| 381 | | - ufpu, NULL); |
|---|
| 382 | | - |
|---|
| 383 | | - return fpvalid; |
|---|
| 384 | | -} |
|---|
| 385 | | -EXPORT_SYMBOL(dump_fpu); |
|---|
| 386 | 349 | |
|---|
| 387 | 350 | #endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */ |
|---|