162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_X86_XSAVE_H
362306a36Sopenharmony_ci#define __ASM_X86_XSAVE_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/uaccess.h>
662306a36Sopenharmony_ci#include <linux/types.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <asm/processor.h>
962306a36Sopenharmony_ci#include <asm/fpu/api.h>
1062306a36Sopenharmony_ci#include <asm/user.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* Bit 63 of XCR0 is reserved for future expansion */
1362306a36Sopenharmony_ci#define XFEATURE_MASK_EXTEND	(~(XFEATURE_MASK_FPSSE | (1ULL << 63)))
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define XSTATE_CPUID		0x0000000d
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define TILE_CPUID		0x0000001d
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define FXSAVE_SIZE	512
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define XSAVE_HDR_SIZE	    64
2262306a36Sopenharmony_ci#define XSAVE_HDR_OFFSET    FXSAVE_SIZE
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define XSAVE_YMM_SIZE	    256
2562306a36Sopenharmony_ci#define XSAVE_YMM_OFFSET    (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define XSAVE_ALIGNMENT     64
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/* All currently supported user features */
3062306a36Sopenharmony_ci#define XFEATURE_MASK_USER_SUPPORTED (XFEATURE_MASK_FP | \
3162306a36Sopenharmony_ci				      XFEATURE_MASK_SSE | \
3262306a36Sopenharmony_ci				      XFEATURE_MASK_YMM | \
3362306a36Sopenharmony_ci				      XFEATURE_MASK_OPMASK | \
3462306a36Sopenharmony_ci				      XFEATURE_MASK_ZMM_Hi256 | \
3562306a36Sopenharmony_ci				      XFEATURE_MASK_Hi16_ZMM	 | \
3662306a36Sopenharmony_ci				      XFEATURE_MASK_PKRU | \
3762306a36Sopenharmony_ci				      XFEATURE_MASK_BNDREGS | \
3862306a36Sopenharmony_ci				      XFEATURE_MASK_BNDCSR | \
3962306a36Sopenharmony_ci				      XFEATURE_MASK_XTILE)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * Features which are restored when returning to user space.
4362306a36Sopenharmony_ci * PKRU is not restored on return to user space because PKRU
4462306a36Sopenharmony_ci * is switched eagerly in switch_to() and flush_thread()
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_ci#define XFEATURE_MASK_USER_RESTORE	\
4762306a36Sopenharmony_ci	(XFEATURE_MASK_USER_SUPPORTED & ~XFEATURE_MASK_PKRU)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Features which are dynamically enabled for a process on request */
5062306a36Sopenharmony_ci#define XFEATURE_MASK_USER_DYNAMIC	XFEATURE_MASK_XTILE_DATA
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* All currently supported supervisor features */
5362306a36Sopenharmony_ci#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (XFEATURE_MASK_PASID | \
5462306a36Sopenharmony_ci					    XFEATURE_MASK_CET_USER)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*
5762306a36Sopenharmony_ci * A supervisor state component may not always contain valuable information,
5862306a36Sopenharmony_ci * and its size may be huge. Saving/restoring such supervisor state components
5962306a36Sopenharmony_ci * at each context switch can cause high CPU and space overhead, which should
6062306a36Sopenharmony_ci * be avoided. Such supervisor state components should only be saved/restored
6162306a36Sopenharmony_ci * on demand. The on-demand supervisor features are set in this mask.
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * Unlike the existing supported supervisor features, an independent supervisor
6462306a36Sopenharmony_ci * feature does not allocate a buffer in task->fpu, and the corresponding
6562306a36Sopenharmony_ci * supervisor state component cannot be saved/restored at each context switch.
6662306a36Sopenharmony_ci *
6762306a36Sopenharmony_ci * To support an independent supervisor feature, a developer should follow the
6862306a36Sopenharmony_ci * dos and don'ts as below:
6962306a36Sopenharmony_ci * - Do dynamically allocate a buffer for the supervisor state component.
7062306a36Sopenharmony_ci * - Do manually invoke the XSAVES/XRSTORS instruction to save/restore the
7162306a36Sopenharmony_ci *   state component to/from the buffer.
7262306a36Sopenharmony_ci * - Don't set the bit corresponding to the independent supervisor feature in
7362306a36Sopenharmony_ci *   IA32_XSS at run time, since it has been set at boot time.
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_ci#define XFEATURE_MASK_INDEPENDENT (XFEATURE_MASK_LBR)
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/*
7862306a36Sopenharmony_ci * Unsupported supervisor features. When a supervisor feature in this mask is
7962306a36Sopenharmony_ci * supported in the future, move it to the supported supervisor feature mask.
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_ci#define XFEATURE_MASK_SUPERVISOR_UNSUPPORTED (XFEATURE_MASK_PT | \
8262306a36Sopenharmony_ci					      XFEATURE_MASK_CET_KERNEL)
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci/* All supervisor states including supported and unsupported states. */
8562306a36Sopenharmony_ci#define XFEATURE_MASK_SUPERVISOR_ALL (XFEATURE_MASK_SUPERVISOR_SUPPORTED | \
8662306a36Sopenharmony_ci				      XFEATURE_MASK_INDEPENDENT | \
8762306a36Sopenharmony_ci				      XFEATURE_MASK_SUPERVISOR_UNSUPPORTED)
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/*
9062306a36Sopenharmony_ci * The feature mask required to restore FPU state:
9162306a36Sopenharmony_ci * - All user states which are not eagerly switched in switch_to()/exec()
9262306a36Sopenharmony_ci * - The suporvisor states
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_ci#define XFEATURE_MASK_FPSTATE	(XFEATURE_MASK_USER_RESTORE | \
9562306a36Sopenharmony_ci				 XFEATURE_MASK_SUPERVISOR_SUPPORTED)
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/*
9862306a36Sopenharmony_ci * Features in this mask have space allocated in the signal frame, but may not
9962306a36Sopenharmony_ci * have that space initialized when the feature is in its init state.
10062306a36Sopenharmony_ci */
10162306a36Sopenharmony_ci#define XFEATURE_MASK_SIGFRAME_INITOPT	(XFEATURE_MASK_XTILE | \
10262306a36Sopenharmony_ci					 XFEATURE_MASK_USER_DYNAMIC)
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciextern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ciextern void __init update_regset_xstate_info(unsigned int size,
10762306a36Sopenharmony_ci					     u64 xstate_mask);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ciint xfeature_size(int xfeature_nr);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_civoid xsaves(struct xregs_state *xsave, u64 mask);
11262306a36Sopenharmony_civoid xrstors(struct xregs_state *xsave, u64 mask);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ciint xfd_enable_feature(u64 xfd_err);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci#ifdef CONFIG_X86_64
11762306a36Sopenharmony_ciDECLARE_STATIC_KEY_FALSE(__fpu_state_size_dynamic);
11862306a36Sopenharmony_ci#endif
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#ifdef CONFIG_X86_64
12162306a36Sopenharmony_ciDECLARE_STATIC_KEY_FALSE(__fpu_state_size_dynamic);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic __always_inline __pure bool fpu_state_size_dynamic(void)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	return static_branch_unlikely(&__fpu_state_size_dynamic);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci#else
12862306a36Sopenharmony_cistatic __always_inline __pure bool fpu_state_size_dynamic(void)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	return false;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci#endif
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#endif
135