internal.h 15.3 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3 4 5 6 7 8 9 10
/*
 * Copyright (C) 1994 Linus Torvalds
 *
 * Pentium III FXSR, SSE support
 * General FPU state handling cleanups
 *	Gareth Hughes <gareth@valinux.com>, May 2000
 * x86-64 work by Andi Kleen 2002
 */

11 12
#ifndef _ASM_X86_FPU_INTERNAL_H
#define _ASM_X86_FPU_INTERNAL_H
13

14
#include <linux/compat.h>
15
#include <linux/sched.h>
16
#include <linux/slab.h>
R
Rik van Riel 已提交
17
#include <linux/mm.h>
18

19
#include <asm/user.h>
20
#include <asm/fpu/api.h>
21
#include <asm/fpu/xstate.h>
22
#include <asm/cpufeature.h>
23
#include <asm/trace/fpu.h>
24

25 26 27
/*
 * High level FPU state handling functions:
 */
28 29
extern void fpu__prepare_read(struct fpu *fpu);
extern void fpu__prepare_write(struct fpu *fpu);
30
extern void fpu__save(struct fpu *fpu);
31
extern int  fpu__restore_sig(void __user *buf, int ia32_frame);
32 33
extern void fpu__drop(struct fpu *fpu);
extern int  fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu);
34
extern void fpu__clear(struct fpu *fpu);
I
Ingo Molnar 已提交
35 36
extern int  fpu__exception_code(struct fpu *fpu, int trap_nr);
extern int  dump_fpu(struct pt_regs *ptregs, struct user_i387_struct *fpstate);
37

I
Ingo Molnar 已提交
38 39 40 41 42 43 44
/*
 * Boot time FPU initialization functions:
 */
extern void fpu__init_cpu(void);
extern void fpu__init_system_xstate(void);
extern void fpu__init_cpu_xstate(void);
extern void fpu__init_system(struct cpuinfo_x86 *c);
45 46
extern void fpu__init_check_bugs(void);
extern void fpu__resume_cpu(void);
47
extern u64 fpu__get_supported_xfeatures_mask(void);
48

49 50 51 52 53 54
/*
 * Debugging facility:
 */
#ifdef CONFIG_X86_DEBUG_FPU
# define WARN_ON_FPU(x) WARN_ON_ONCE(x)
#else
55
# define WARN_ON_FPU(x) ({ (void)(x); 0; })
56 57
#endif

58
/*
I
Ingo Molnar 已提交
59
 * FPU related CPU feature flag helper routines:
60
 */
61 62
static __always_inline __pure bool use_xsaveopt(void)
{
63
	return static_cpu_has(X86_FEATURE_XSAVEOPT);
64 65 66 67
}

static __always_inline __pure bool use_xsave(void)
{
68
	return static_cpu_has(X86_FEATURE_XSAVE);
69 70 71 72
}

static __always_inline __pure bool use_fxsr(void)
{
73
	return static_cpu_has(X86_FEATURE_FXSR);
74 75
}

I
Ingo Molnar 已提交
76 77 78 79 80 81 82 83 84 85 86 87
/*
 * fpstate handling functions:
 */

extern union fpregs_state init_fpstate;

extern void fpstate_init(union fpregs_state *state);
#ifdef CONFIG_MATH_EMULATION
extern void fpstate_init_soft(struct swregs_state *soft);
#else
static inline void fpstate_init_soft(struct swregs_state *soft) {}
#endif
88 89 90 91 92 93 94 95 96 97

static inline void fpstate_init_xstate(struct xregs_state *xsave)
{
	/*
	 * XRSTORS requires these bits set in xcomp_bv, or it will
	 * trigger #GP:
	 */
	xsave->header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT | xfeatures_mask;
}

I
Ingo Molnar 已提交
98 99 100 101 102
static inline void fpstate_init_fxstate(struct fxregs_state *fx)
{
	fx->cwd = 0x37f;
	fx->mxcsr = MXCSR_DEFAULT;
}
103
extern void fpstate_sanitize_xstate(struct fpu *fpu);
104

105 106 107
#define user_insn(insn, output, input...)				\
({									\
	int err;							\
108 109 110
									\
	might_fault();							\
									\
111 112 113 114 115 116 117 118 119 120 121 122 123
	asm volatile(ASM_STAC "\n"					\
		     "1:" #insn "\n\t"					\
		     "2: " ASM_CLAC "\n"				\
		     ".section .fixup,\"ax\"\n"				\
		     "3:  movl $-1,%[err]\n"				\
		     "    jmp  2b\n"					\
		     ".previous\n"					\
		     _ASM_EXTABLE(1b, 3b)				\
		     : [err] "=r" (err), output				\
		     : "0"(0), input);					\
	err;								\
})

124
#define kernel_insn(insn, output, input...)				\
125 126
	asm volatile("1:" #insn "\n\t"					\
		     "2:\n"						\
127 128
		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_fprestore)	\
		     : output : input)
129

130
static inline int copy_fregs_to_user(struct fregs_state __user *fx)
131
{
132
	return user_insn(fnsave %[fx]; fwait,  [fx] "=m" (*fx), "m" (*fx));
133 134
}

135
static inline int copy_fxregs_to_user(struct fxregs_state __user *fx)
136
{
137
	if (IS_ENABLED(CONFIG_X86_32))
138
		return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
139
	else
140
		return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
141 142 143

}

144
static inline void copy_kernel_to_fxregs(struct fxregs_state *fx)
145
{
146
	if (IS_ENABLED(CONFIG_X86_32))
147
		kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
148 149
	else
		kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
150 151
}

152
static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
153
{
154
	if (IS_ENABLED(CONFIG_X86_32))
155
		return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
156
	else
157 158 159
		return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
}

160
static inline void copy_kernel_to_fregs(struct fregs_state *fx)
161
{
162
	kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
163 164
}

165
static inline int copy_user_to_fregs(struct fregs_state __user *fx)
166 167
{
	return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
168 169
}

170
static inline void copy_fxregs_to_kernel(struct fpu *fpu)
171
{
172
	if (IS_ENABLED(CONFIG_X86_32))
173
		asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state.fxsave));
174
	else
175
		asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave));
176 177
}

178 179 180 181 182 183 184
/* These macros all use (%edi)/(%rdi) as the single memory argument. */
#define XSAVE		".byte " REX_PREFIX "0x0f,0xae,0x27"
#define XSAVEOPT	".byte " REX_PREFIX "0x0f,0xae,0x37"
#define XSAVES		".byte " REX_PREFIX "0x0f,0xc7,0x2f"
#define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f"
#define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f"

185 186 187 188 189 190 191 192
#define XSTATE_OP(op, st, lmask, hmask, err)				\
	asm volatile("1:" op "\n\t"					\
		     "xor %[err], %[err]\n"				\
		     "2:\n\t"						\
		     ".pushsection .fixup,\"ax\"\n\t"			\
		     "3: movl $-2,%[err]\n\t"				\
		     "jmp 2b\n\t"					\
		     ".popsection\n\t"					\
193
		     _ASM_EXTABLE(1b, 3b)				\
194 195 196 197
		     : [err] "=r" (err)					\
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "memory")

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
/*
 * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact
 * format and supervisor states in addition to modified optimization in
 * XSAVEOPT.
 *
 * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
 * supports modified optimization which is not supported by XSAVE.
 *
 * We use XSAVE as a fallback.
 *
 * The 661 label is defined in the ALTERNATIVE* macros as the address of the
 * original instruction which gets replaced. We need to use it here as the
 * address of the instruction where we might get an exception at.
 */
#define XSTATE_XSAVE(st, lmask, hmask, err)				\
	asm volatile(ALTERNATIVE_2(XSAVE,				\
				   XSAVEOPT, X86_FEATURE_XSAVEOPT,	\
				   XSAVES,   X86_FEATURE_XSAVES)	\
		     "\n"						\
		     "xor %[err], %[err]\n"				\
		     "3:\n"						\
		     ".pushsection .fixup,\"ax\"\n"			\
		     "4: movl $-2, %[err]\n"				\
		     "jmp 3b\n"						\
		     ".popsection\n"					\
		     _ASM_EXTABLE(661b, 4b)				\
		     : [err] "=r" (err)					\
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "memory")

/*
 * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact
 * XSAVE area format.
 */
232
#define XSTATE_XRESTORE(st, lmask, hmask)				\
233 234 235 236
	asm volatile(ALTERNATIVE(XRSTOR,				\
				 XRSTORS, X86_FEATURE_XSAVES)		\
		     "\n"						\
		     "3:\n"						\
237 238
		     _ASM_EXTABLE_HANDLE(661b, 3b, ex_handler_fprestore)\
		     :							\
239 240
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "memory")
241

242 243 244 245
/*
 * This function is called only during boot time when x86 caps are not set
 * up and alternative can not be used yet.
 */
246
static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)
247 248 249 250
{
	u64 mask = -1;
	u32 lmask = mask;
	u32 hmask = mask >> 32;
251
	int err;
252 253 254

	WARN_ON(system_state != SYSTEM_BOOTING);

255
	if (static_cpu_has(X86_FEATURE_XSAVES))
256
		XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
257
	else
258
		XSTATE_OP(XSAVE, xstate, lmask, hmask, err);
259 260 261

	/* We should never fault when copying to a kernel buffer: */
	WARN_ON_FPU(err);
262 263 264 265 266 267
}

/*
 * This function is called only during boot time when x86 caps are not set
 * up and alternative can not be used yet.
 */
268
static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)
269
{
270
	u64 mask = -1;
271 272
	u32 lmask = mask;
	u32 hmask = mask >> 32;
273
	int err;
274 275 276

	WARN_ON(system_state != SYSTEM_BOOTING);

277
	if (static_cpu_has(X86_FEATURE_XSAVES))
278
		XSTATE_OP(XRSTORS, xstate, lmask, hmask, err);
279
	else
280
		XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
281

282 283 284 285
	/*
	 * We should never fault when copying from a kernel buffer, and the FPU
	 * state we set at boot time should be valid.
	 */
286
	WARN_ON_FPU(err);
287 288 289 290 291
}

/*
 * Save processor xstate to xsave area.
 */
292
static inline void copy_xregs_to_kernel(struct xregs_state *xstate)
293 294 295 296
{
	u64 mask = -1;
	u32 lmask = mask;
	u32 hmask = mask >> 32;
297
	int err;
298

299
	WARN_ON_FPU(!alternatives_patched);
300

301
	XSTATE_XSAVE(xstate, lmask, hmask, err);
302

303 304
	/* We should never fault when copying to a kernel buffer: */
	WARN_ON_FPU(err);
305 306 307 308 309
}

/*
 * Restore processor xstate from xsave area.
 */
310
static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask)
311 312 313 314
{
	u32 lmask = mask;
	u32 hmask = mask >> 32;

315
	XSTATE_XRESTORE(xstate, lmask, hmask);
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
}

/*
 * Save xstate to user space xsave area.
 *
 * We don't use modified optimization because xrstor/xrstors might track
 * a different application.
 *
 * We don't use compacted format xsave area for
 * backward compatibility for old applications which don't understand
 * compacted format of xsave area.
 */
static inline int copy_xregs_to_user(struct xregs_state __user *buf)
{
	int err;

	/*
	 * Clear the xsave header first, so that reserved fields are
	 * initialized to zero.
	 */
	err = __clear_user(&buf->header, sizeof(buf->header));
	if (unlikely(err))
		return -EFAULT;

340 341 342 343
	stac();
	XSTATE_OP(XSAVE, buf, -1, -1, err);
	clac();

344 345 346 347 348 349 350 351 352 353 354
	return err;
}

/*
 * Restore xstate from user space xsave area.
 */
static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask)
{
	struct xregs_state *xstate = ((__force struct xregs_state *)buf);
	u32 lmask = mask;
	u32 hmask = mask >> 32;
355 356 357 358 359
	int err;

	stac();
	XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
	clac();
360 361 362 363

	return err;
}

364 365
/*
 * These must be called with preempt disabled. Returns
366 367 368 369 370 371
 * 'true' if the FPU state is still intact and we can
 * keep registers active.
 *
 * The legacy FNSAVE instruction cleared all FPU state
 * unconditionally, so registers are essentially destroyed.
 * Modern FPU state can be kept in registers, if there are
372
 * no pending FP exceptions.
373
 */
374
static inline int copy_fpregs_to_fpstate(struct fpu *fpu)
375
{
376
	if (likely(use_xsave())) {
377
		copy_xregs_to_kernel(&fpu->state.xsave);
378 379 380 381 382 383 384

		/*
		 * AVX512 state is tracked here because its use is
		 * known to slow the max clock speed of the core.
		 */
		if (fpu->state.xsave.header.xfeatures & XFEATURE_MASK_AVX512)
			fpu->avx512_timestamp = jiffies;
385 386
		return 1;
	}
387

388
	if (likely(use_fxsr())) {
389
		copy_fxregs_to_kernel(fpu);
390
		return 1;
391 392 393
	}

	/*
394 395
	 * Legacy FPU register saving, FNSAVE always clears FPU registers,
	 * so we have to mark them inactive:
396
	 */
397
	asm volatile("fnsave %[fp]; fwait" : [fp] "=m" (fpu->state.fsave));
398 399

	return 0;
400 401
}

402
static inline void __copy_kernel_to_fpregs(union fpregs_state *fpstate, u64 mask)
403
{
404
	if (use_xsave()) {
405
		copy_kernel_to_xregs(&fpstate->xsave, mask);
406 407
	} else {
		if (use_fxsr())
408
			copy_kernel_to_fxregs(&fpstate->fxsave);
409
		else
410
			copy_kernel_to_fregs(&fpstate->fsave);
411
	}
412 413
}

414
static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)
415
{
416 417 418 419 420
	/*
	 * AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is
	 * pending. Clear the x87 state here by setting it to fixed values.
	 * "m" is a random variable that should be in L1.
	 */
421
	if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) {
422 423 424 425
		asm volatile(
			"fnclex\n\t"
			"emms\n\t"
			"fildl %P[addr]"	/* set F?P to defined value */
426
			: : [addr] "m" (fpstate));
427
	}
428

429
	__copy_kernel_to_fpregs(fpstate, -1);
430 431
}

432
extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size);
I
Ingo Molnar 已提交
433 434 435 436 437 438 439 440

/*
 * FPU context switch related helper methods:
 */

DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);

/*
441 442 443 444 445 446 447 448 449
 * The in-register FPU state for an FPU context on a CPU is assumed to be
 * valid if the fpu->last_cpu matches the CPU, and the fpu_fpregs_owner_ctx
 * matches the FPU.
 *
 * If the FPU register state is valid, the kernel can skip restoring the
 * FPU state from memory.
 *
 * Any code that clobbers the FPU registers or updates the in-memory
 * FPU state for a task MUST let the rest of the kernel know that the
450
 * FPU registers are no longer valid for this task.
451
 *
452 453 454 455
 * Either one of these invalidation functions is enough. Invalidate
 * a resource you control: CPU if using the CPU for something else
 * (with preemption disabled), FPU for the current task, or a task that
 * is prevented from running by the current task.
I
Ingo Molnar 已提交
456
 */
457
static inline void __cpu_invalidate_fpregs_state(void)
I
Ingo Molnar 已提交
458
{
459
	__this_cpu_write(fpu_fpregs_owner_ctx, NULL);
I
Ingo Molnar 已提交
460 461
}

462 463 464 465 466 467
static inline void __fpu_invalidate_fpregs_state(struct fpu *fpu)
{
	fpu->last_cpu = -1;
}

static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu)
I
Ingo Molnar 已提交
468 469 470 471
{
	return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
}

472 473 474 475 476
/*
 * These generally need preemption protection to work,
 * do try to avoid using these on their own:
 */
static inline void fpregs_deactivate(struct fpu *fpu)
477
{
478
	this_cpu_write(fpu_fpregs_owner_ctx, NULL);
479
	trace_x86_fpu_regs_deactivated(fpu);
480 481
}

482
static inline void fpregs_activate(struct fpu *fpu)
483
{
484
	this_cpu_write(fpu_fpregs_owner_ctx, fpu);
485
	trace_x86_fpu_regs_activated(fpu);
486 487
}

488 489 490 491 492 493 494 495 496 497 498 499
/*
 * Internal helper, do not use directly. Use switch_fpu_return() instead.
 */
static inline void __fpregs_load_activate(struct fpu *fpu, int cpu)
{
	if (!fpregs_state_valid(fpu, cpu)) {
		if (current->mm)
			copy_kernel_to_fpregs(&fpu->state);
		fpregs_activate(fpu);
	}
}

500 501 502 503 504
/*
 * FPU state switching for scheduling.
 *
 * This is a two-stage process:
 *
505 506
 *  - switch_fpu_prepare() saves the old state.
 *    This is done within the context of the old process.
507 508 509
 *
 *  - switch_fpu_finish() restores the new state as
 *    necessary.
510
 *
511 512 513 514 515 516 517 518
 * If TIF_NEED_FPU_LOAD is cleared then the CPU's FPU registers
 * are saved in the current thread's FPU register state.
 *
 * If TIF_NEED_FPU_LOAD is set then CPU's FPU registers may not
 * hold current()'s FPU registers. It is required to load the
 * registers before returning to userland or using the content
 * otherwise.
 *
519 520
 * The FPU context is only stored/restored for a user task and
 * ->mm is used to distinguish between kernel and user threads.
521
 */
522 523
static inline void
switch_fpu_prepare(struct fpu *old_fpu, int cpu)
524
{
525
	if (static_cpu_has(X86_FEATURE_FPU) && current->mm) {
526
		if (!copy_fpregs_to_fpstate(old_fpu))
527
			old_fpu->last_cpu = -1;
528
		else
529
			old_fpu->last_cpu = cpu;
530

531
		/* But leave fpu_fpregs_owner_ctx! */
532
		trace_x86_fpu_regs_deactivated(old_fpu);
533
	}
534 535
}

I
Ingo Molnar 已提交
536 537 538 539
/*
 * Misc helper functions:
 */

540
/*
541 542
 * Set up the userspace FPU context for the new task, if the task
 * has used the FPU.
543
 */
544
static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu)
545
{
R
Rik van Riel 已提交
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
	u32 pkru_val = init_pkru_value;
	struct pkru_state *pk;

	if (!static_cpu_has(X86_FEATURE_FPU))
		return;

	__fpregs_load_activate(new_fpu, cpu);

	if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
		return;

	/*
	 * PKRU state is switched eagerly because it needs to be valid before we
	 * return to userland e.g. for a copy_to_user() operation.
	 */
	if (current->mm) {
		pk = get_xsave_addr(&new_fpu->state.xsave, XFEATURE_PKRU);
		if (pk)
			pkru_val = pk->pkru;
	}
	__write_pkru(pkru_val);
567 568
}

I
Ingo Molnar 已提交
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
/*
 * MXCSR and XCR definitions:
 */

extern unsigned int mxcsr_feature_mask;

#define XCR_XFEATURE_ENABLED_MASK	0x00000000

static inline u64 xgetbv(u32 index)
{
	u32 eax, edx;

	asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
		     : "=a" (eax), "=d" (edx)
		     : "c" (index));
	return eax + ((u64)edx << 32);
}

static inline void xsetbv(u32 index, u64 value)
{
	u32 eax = value;
	u32 edx = value >> 32;

	asm volatile(".byte 0x0f,0x01,0xd1" /* xsetbv */
		     : : "a" (eax), "d" (edx), "c" (index));
}

596
#endif /* _ASM_X86_FPU_INTERNAL_H */