Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.13-rc5 652 lines 18 kB view raw
1/* 2 * Copyright (C) 1994 Linus Torvalds 3 * 4 * Pentium III FXSR, SSE support 5 * General FPU state handling cleanups 6 * Gareth Hughes <gareth@valinux.com>, May 2000 7 * x86-64 work by Andi Kleen 2002 8 */ 9 10#ifndef _ASM_X86_FPU_INTERNAL_H 11#define _ASM_X86_FPU_INTERNAL_H 12 13#include <linux/compat.h> 14#include <linux/sched.h> 15#include <linux/slab.h> 16 17#include <asm/user.h> 18#include <asm/fpu/api.h> 19#include <asm/fpu/xstate.h> 20#include <asm/cpufeature.h> 21#include <asm/trace/fpu.h> 22 23/* 24 * High level FPU state handling functions: 25 */ 26extern void fpu__activate_curr(struct fpu *fpu); 27extern void fpu__activate_fpstate_read(struct fpu *fpu); 28extern void fpu__activate_fpstate_write(struct fpu *fpu); 29extern void fpu__current_fpstate_write_begin(void); 30extern void fpu__current_fpstate_write_end(void); 31extern void fpu__save(struct fpu *fpu); 32extern void fpu__restore(struct fpu *fpu); 33extern int fpu__restore_sig(void __user *buf, int ia32_frame); 34extern void fpu__drop(struct fpu *fpu); 35extern int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu); 36extern void fpu__clear(struct fpu *fpu); 37extern int fpu__exception_code(struct fpu *fpu, int trap_nr); 38extern int dump_fpu(struct pt_regs *ptregs, struct user_i387_struct *fpstate); 39 40/* 41 * Boot time FPU initialization functions: 42 */ 43extern void fpu__init_cpu(void); 44extern void fpu__init_system_xstate(void); 45extern void fpu__init_cpu_xstate(void); 46extern void fpu__init_system(struct cpuinfo_x86 *c); 47extern void fpu__init_check_bugs(void); 48extern void fpu__resume_cpu(void); 49extern u64 fpu__get_supported_xfeatures_mask(void); 50 51/* 52 * Debugging facility: 53 */ 54#ifdef CONFIG_X86_DEBUG_FPU 55# define WARN_ON_FPU(x) WARN_ON_ONCE(x) 56#else 57# define WARN_ON_FPU(x) ({ (void)(x); 0; }) 58#endif 59 60/* 61 * FPU related CPU feature flag helper routines: 62 */ 63static __always_inline __pure bool use_xsaveopt(void) 64{ 65 return static_cpu_has(X86_FEATURE_XSAVEOPT); 66} 67 68static __always_inline __pure bool use_xsave(void) 69{ 70 return static_cpu_has(X86_FEATURE_XSAVE); 71} 72 73static __always_inline __pure bool use_fxsr(void) 74{ 75 return static_cpu_has(X86_FEATURE_FXSR); 76} 77 78/* 79 * fpstate handling functions: 80 */ 81 82extern union fpregs_state init_fpstate; 83 84extern void fpstate_init(union fpregs_state *state); 85#ifdef CONFIG_MATH_EMULATION 86extern void fpstate_init_soft(struct swregs_state *soft); 87#else 88static inline void fpstate_init_soft(struct swregs_state *soft) {} 89#endif 90 91static inline void fpstate_init_xstate(struct xregs_state *xsave) 92{ 93 /* 94 * XRSTORS requires these bits set in xcomp_bv, or it will 95 * trigger #GP: 96 */ 97 xsave->header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT | xfeatures_mask; 98} 99 100static inline void fpstate_init_fxstate(struct fxregs_state *fx) 101{ 102 fx->cwd = 0x37f; 103 fx->mxcsr = MXCSR_DEFAULT; 104} 105extern void fpstate_sanitize_xstate(struct fpu *fpu); 106 107#define user_insn(insn, output, input...) \ 108({ \ 109 int err; \ 110 asm volatile(ASM_STAC "\n" \ 111 "1:" #insn "\n\t" \ 112 "2: " ASM_CLAC "\n" \ 113 ".section .fixup,\"ax\"\n" \ 114 "3: movl $-1,%[err]\n" \ 115 " jmp 2b\n" \ 116 ".previous\n" \ 117 _ASM_EXTABLE(1b, 3b) \ 118 : [err] "=r" (err), output \ 119 : "0"(0), input); \ 120 err; \ 121}) 122 123#define check_insn(insn, output, input...) \ 124({ \ 125 int err; \ 126 asm volatile("1:" #insn "\n\t" \ 127 "2:\n" \ 128 ".section .fixup,\"ax\"\n" \ 129 "3: movl $-1,%[err]\n" \ 130 " jmp 2b\n" \ 131 ".previous\n" \ 132 _ASM_EXTABLE(1b, 3b) \ 133 : [err] "=r" (err), output \ 134 : "0"(0), input); \ 135 err; \ 136}) 137 138static inline int copy_fregs_to_user(struct fregs_state __user *fx) 139{ 140 return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx)); 141} 142 143static inline int copy_fxregs_to_user(struct fxregs_state __user *fx) 144{ 145 if (IS_ENABLED(CONFIG_X86_32)) 146 return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx)); 147 else if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) 148 return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx)); 149 150 /* See comment in copy_fxregs_to_kernel() below. */ 151 return user_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx)); 152} 153 154static inline void copy_kernel_to_fxregs(struct fxregs_state *fx) 155{ 156 int err; 157 158 if (IS_ENABLED(CONFIG_X86_32)) { 159 err = check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 160 } else { 161 if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) { 162 err = check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx)); 163 } else { 164 /* See comment in copy_fxregs_to_kernel() below. */ 165 err = check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), "m" (*fx)); 166 } 167 } 168 /* Copying from a kernel buffer to FPU registers should never fail: */ 169 WARN_ON_FPU(err); 170} 171 172static inline int copy_user_to_fxregs(struct fxregs_state __user *fx) 173{ 174 if (IS_ENABLED(CONFIG_X86_32)) 175 return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 176 else if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) 177 return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx)); 178 179 /* See comment in copy_fxregs_to_kernel() below. */ 180 return user_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), 181 "m" (*fx)); 182} 183 184static inline void copy_kernel_to_fregs(struct fregs_state *fx) 185{ 186 int err = check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 187 188 WARN_ON_FPU(err); 189} 190 191static inline int copy_user_to_fregs(struct fregs_state __user *fx) 192{ 193 return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 194} 195 196static inline void copy_fxregs_to_kernel(struct fpu *fpu) 197{ 198 if (IS_ENABLED(CONFIG_X86_32)) 199 asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state.fxsave)); 200 else if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) 201 asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave)); 202 else { 203 /* Using "rex64; fxsave %0" is broken because, if the memory 204 * operand uses any extended registers for addressing, a second 205 * REX prefix will be generated (to the assembler, rex64 206 * followed by semicolon is a separate instruction), and hence 207 * the 64-bitness is lost. 208 * 209 * Using "fxsaveq %0" would be the ideal choice, but is only 210 * supported starting with gas 2.16. 211 * 212 * Using, as a workaround, the properly prefixed form below 213 * isn't accepted by any binutils version so far released, 214 * complaining that the same type of prefix is used twice if 215 * an extended register is needed for addressing (fix submitted 216 * to mainline 2005-11-21). 217 * 218 * asm volatile("rex64/fxsave %0" : "=m" (fpu->state.fxsave)); 219 * 220 * This, however, we can work around by forcing the compiler to 221 * select an addressing mode that doesn't require extended 222 * registers. 223 */ 224 asm volatile( "rex64/fxsave (%[fx])" 225 : "=m" (fpu->state.fxsave) 226 : [fx] "R" (&fpu->state.fxsave)); 227 } 228} 229 230/* These macros all use (%edi)/(%rdi) as the single memory argument. */ 231#define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27" 232#define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37" 233#define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f" 234#define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f" 235#define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f" 236 237#define XSTATE_OP(op, st, lmask, hmask, err) \ 238 asm volatile("1:" op "\n\t" \ 239 "xor %[err], %[err]\n" \ 240 "2:\n\t" \ 241 ".pushsection .fixup,\"ax\"\n\t" \ 242 "3: movl $-2,%[err]\n\t" \ 243 "jmp 2b\n\t" \ 244 ".popsection\n\t" \ 245 _ASM_EXTABLE(1b, 3b) \ 246 : [err] "=r" (err) \ 247 : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ 248 : "memory") 249 250/* 251 * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact 252 * format and supervisor states in addition to modified optimization in 253 * XSAVEOPT. 254 * 255 * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT 256 * supports modified optimization which is not supported by XSAVE. 257 * 258 * We use XSAVE as a fallback. 259 * 260 * The 661 label is defined in the ALTERNATIVE* macros as the address of the 261 * original instruction which gets replaced. We need to use it here as the 262 * address of the instruction where we might get an exception at. 263 */ 264#define XSTATE_XSAVE(st, lmask, hmask, err) \ 265 asm volatile(ALTERNATIVE_2(XSAVE, \ 266 XSAVEOPT, X86_FEATURE_XSAVEOPT, \ 267 XSAVES, X86_FEATURE_XSAVES) \ 268 "\n" \ 269 "xor %[err], %[err]\n" \ 270 "3:\n" \ 271 ".pushsection .fixup,\"ax\"\n" \ 272 "4: movl $-2, %[err]\n" \ 273 "jmp 3b\n" \ 274 ".popsection\n" \ 275 _ASM_EXTABLE(661b, 4b) \ 276 : [err] "=r" (err) \ 277 : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ 278 : "memory") 279 280/* 281 * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact 282 * XSAVE area format. 283 */ 284#define XSTATE_XRESTORE(st, lmask, hmask, err) \ 285 asm volatile(ALTERNATIVE(XRSTOR, \ 286 XRSTORS, X86_FEATURE_XSAVES) \ 287 "\n" \ 288 "xor %[err], %[err]\n" \ 289 "3:\n" \ 290 ".pushsection .fixup,\"ax\"\n" \ 291 "4: movl $-2, %[err]\n" \ 292 "jmp 3b\n" \ 293 ".popsection\n" \ 294 _ASM_EXTABLE(661b, 4b) \ 295 : [err] "=r" (err) \ 296 : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ 297 : "memory") 298 299/* 300 * This function is called only during boot time when x86 caps are not set 301 * up and alternative can not be used yet. 302 */ 303static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) 304{ 305 u64 mask = -1; 306 u32 lmask = mask; 307 u32 hmask = mask >> 32; 308 int err; 309 310 WARN_ON(system_state != SYSTEM_BOOTING); 311 312 if (static_cpu_has(X86_FEATURE_XSAVES)) 313 XSTATE_OP(XSAVES, xstate, lmask, hmask, err); 314 else 315 XSTATE_OP(XSAVE, xstate, lmask, hmask, err); 316 317 /* We should never fault when copying to a kernel buffer: */ 318 WARN_ON_FPU(err); 319} 320 321/* 322 * This function is called only during boot time when x86 caps are not set 323 * up and alternative can not be used yet. 324 */ 325static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate) 326{ 327 u64 mask = -1; 328 u32 lmask = mask; 329 u32 hmask = mask >> 32; 330 int err; 331 332 WARN_ON(system_state != SYSTEM_BOOTING); 333 334 if (static_cpu_has(X86_FEATURE_XSAVES)) 335 XSTATE_OP(XRSTORS, xstate, lmask, hmask, err); 336 else 337 XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); 338 339 /* We should never fault when copying from a kernel buffer: */ 340 WARN_ON_FPU(err); 341} 342 343/* 344 * Save processor xstate to xsave area. 345 */ 346static inline void copy_xregs_to_kernel(struct xregs_state *xstate) 347{ 348 u64 mask = -1; 349 u32 lmask = mask; 350 u32 hmask = mask >> 32; 351 int err; 352 353 WARN_ON(!alternatives_patched); 354 355 XSTATE_XSAVE(xstate, lmask, hmask, err); 356 357 /* We should never fault when copying to a kernel buffer: */ 358 WARN_ON_FPU(err); 359} 360 361/* 362 * Restore processor xstate from xsave area. 363 */ 364static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask) 365{ 366 u32 lmask = mask; 367 u32 hmask = mask >> 32; 368 int err; 369 370 XSTATE_XRESTORE(xstate, lmask, hmask, err); 371 372 /* We should never fault when copying from a kernel buffer: */ 373 WARN_ON_FPU(err); 374} 375 376/* 377 * Save xstate to user space xsave area. 378 * 379 * We don't use modified optimization because xrstor/xrstors might track 380 * a different application. 381 * 382 * We don't use compacted format xsave area for 383 * backward compatibility for old applications which don't understand 384 * compacted format of xsave area. 385 */ 386static inline int copy_xregs_to_user(struct xregs_state __user *buf) 387{ 388 int err; 389 390 /* 391 * Clear the xsave header first, so that reserved fields are 392 * initialized to zero. 393 */ 394 err = __clear_user(&buf->header, sizeof(buf->header)); 395 if (unlikely(err)) 396 return -EFAULT; 397 398 stac(); 399 XSTATE_OP(XSAVE, buf, -1, -1, err); 400 clac(); 401 402 return err; 403} 404 405/* 406 * Restore xstate from user space xsave area. 407 */ 408static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask) 409{ 410 struct xregs_state *xstate = ((__force struct xregs_state *)buf); 411 u32 lmask = mask; 412 u32 hmask = mask >> 32; 413 int err; 414 415 stac(); 416 XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); 417 clac(); 418 419 return err; 420} 421 422/* 423 * These must be called with preempt disabled. Returns 424 * 'true' if the FPU state is still intact and we can 425 * keep registers active. 426 * 427 * The legacy FNSAVE instruction cleared all FPU state 428 * unconditionally, so registers are essentially destroyed. 429 * Modern FPU state can be kept in registers, if there are 430 * no pending FP exceptions. 431 */ 432static inline int copy_fpregs_to_fpstate(struct fpu *fpu) 433{ 434 if (likely(use_xsave())) { 435 copy_xregs_to_kernel(&fpu->state.xsave); 436 return 1; 437 } 438 439 if (likely(use_fxsr())) { 440 copy_fxregs_to_kernel(fpu); 441 return 1; 442 } 443 444 /* 445 * Legacy FPU register saving, FNSAVE always clears FPU registers, 446 * so we have to mark them inactive: 447 */ 448 asm volatile("fnsave %[fp]; fwait" : [fp] "=m" (fpu->state.fsave)); 449 450 return 0; 451} 452 453static inline void __copy_kernel_to_fpregs(union fpregs_state *fpstate) 454{ 455 if (use_xsave()) { 456 copy_kernel_to_xregs(&fpstate->xsave, -1); 457 } else { 458 if (use_fxsr()) 459 copy_kernel_to_fxregs(&fpstate->fxsave); 460 else 461 copy_kernel_to_fregs(&fpstate->fsave); 462 } 463} 464 465static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate) 466{ 467 /* 468 * AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is 469 * pending. Clear the x87 state here by setting it to fixed values. 470 * "m" is a random variable that should be in L1. 471 */ 472 if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) { 473 asm volatile( 474 "fnclex\n\t" 475 "emms\n\t" 476 "fildl %P[addr]" /* set F?P to defined value */ 477 : : [addr] "m" (fpstate)); 478 } 479 480 __copy_kernel_to_fpregs(fpstate); 481} 482 483extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size); 484 485/* 486 * FPU context switch related helper methods: 487 */ 488 489DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx); 490 491/* 492 * The in-register FPU state for an FPU context on a CPU is assumed to be 493 * valid if the fpu->last_cpu matches the CPU, and the fpu_fpregs_owner_ctx 494 * matches the FPU. 495 * 496 * If the FPU register state is valid, the kernel can skip restoring the 497 * FPU state from memory. 498 * 499 * Any code that clobbers the FPU registers or updates the in-memory 500 * FPU state for a task MUST let the rest of the kernel know that the 501 * FPU registers are no longer valid for this task. 502 * 503 * Either one of these invalidation functions is enough. Invalidate 504 * a resource you control: CPU if using the CPU for something else 505 * (with preemption disabled), FPU for the current task, or a task that 506 * is prevented from running by the current task. 507 */ 508static inline void __cpu_invalidate_fpregs_state(void) 509{ 510 __this_cpu_write(fpu_fpregs_owner_ctx, NULL); 511} 512 513static inline void __fpu_invalidate_fpregs_state(struct fpu *fpu) 514{ 515 fpu->last_cpu = -1; 516} 517 518static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu) 519{ 520 return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; 521} 522 523/* 524 * These generally need preemption protection to work, 525 * do try to avoid using these on their own: 526 */ 527static inline void fpregs_deactivate(struct fpu *fpu) 528{ 529 WARN_ON_FPU(!fpu->fpregs_active); 530 531 fpu->fpregs_active = 0; 532 this_cpu_write(fpu_fpregs_owner_ctx, NULL); 533 trace_x86_fpu_regs_deactivated(fpu); 534} 535 536static inline void fpregs_activate(struct fpu *fpu) 537{ 538 WARN_ON_FPU(fpu->fpregs_active); 539 540 fpu->fpregs_active = 1; 541 this_cpu_write(fpu_fpregs_owner_ctx, fpu); 542 trace_x86_fpu_regs_activated(fpu); 543} 544 545/* 546 * The question "does this thread have fpu access?" 547 * is slightly racy, since preemption could come in 548 * and revoke it immediately after the test. 549 * 550 * However, even in that very unlikely scenario, 551 * we can just assume we have FPU access - typically 552 * to save the FP state - we'll just take a #NM 553 * fault and get the FPU access back. 554 */ 555static inline int fpregs_active(void) 556{ 557 return current->thread.fpu.fpregs_active; 558} 559 560/* 561 * FPU state switching for scheduling. 562 * 563 * This is a two-stage process: 564 * 565 * - switch_fpu_prepare() saves the old state. 566 * This is done within the context of the old process. 567 * 568 * - switch_fpu_finish() restores the new state as 569 * necessary. 570 */ 571static inline void 572switch_fpu_prepare(struct fpu *old_fpu, int cpu) 573{ 574 if (old_fpu->fpregs_active) { 575 if (!copy_fpregs_to_fpstate(old_fpu)) 576 old_fpu->last_cpu = -1; 577 else 578 old_fpu->last_cpu = cpu; 579 580 /* But leave fpu_fpregs_owner_ctx! */ 581 old_fpu->fpregs_active = 0; 582 trace_x86_fpu_regs_deactivated(old_fpu); 583 } else 584 old_fpu->last_cpu = -1; 585} 586 587/* 588 * Misc helper functions: 589 */ 590 591/* 592 * Set up the userspace FPU context for the new task, if the task 593 * has used the FPU. 594 */ 595static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu) 596{ 597 bool preload = static_cpu_has(X86_FEATURE_FPU) && 598 new_fpu->fpstate_active; 599 600 if (preload) { 601 if (!fpregs_state_valid(new_fpu, cpu)) 602 copy_kernel_to_fpregs(&new_fpu->state); 603 fpregs_activate(new_fpu); 604 } 605} 606 607/* 608 * Needs to be preemption-safe. 609 * 610 * NOTE! user_fpu_begin() must be used only immediately before restoring 611 * the save state. It does not do any saving/restoring on its own. In 612 * lazy FPU mode, it is just an optimization to avoid a #NM exception, 613 * the task can lose the FPU right after preempt_enable(). 614 */ 615static inline void user_fpu_begin(void) 616{ 617 struct fpu *fpu = &current->thread.fpu; 618 619 preempt_disable(); 620 if (!fpregs_active()) 621 fpregs_activate(fpu); 622 preempt_enable(); 623} 624 625/* 626 * MXCSR and XCR definitions: 627 */ 628 629extern unsigned int mxcsr_feature_mask; 630 631#define XCR_XFEATURE_ENABLED_MASK 0x00000000 632 633static inline u64 xgetbv(u32 index) 634{ 635 u32 eax, edx; 636 637 asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */ 638 : "=a" (eax), "=d" (edx) 639 : "c" (index)); 640 return eax + ((u64)edx << 32); 641} 642 643static inline void xsetbv(u32 index, u64 value) 644{ 645 u32 eax = value; 646 u32 edx = value >> 32; 647 648 asm volatile(".byte 0x0f,0x01,0xd1" /* xsetbv */ 649 : : "a" (eax), "d" (edx), "c" (index)); 650} 651 652#endif /* _ASM_X86_FPU_INTERNAL_H */