18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __ASM_X86_XSAVE_H 38c2ecf20Sopenharmony_ci#define __ASM_X86_XSAVE_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 68c2ecf20Sopenharmony_ci#include <linux/types.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm/processor.h> 98c2ecf20Sopenharmony_ci#include <asm/user.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* Bit 63 of XCR0 is reserved for future expansion */ 128c2ecf20Sopenharmony_ci#define XFEATURE_MASK_EXTEND (~(XFEATURE_MASK_FPSSE | (1ULL << 63))) 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define XSTATE_CPUID 0x0000000d 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define FXSAVE_SIZE 512 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define XSAVE_HDR_SIZE 64 198c2ecf20Sopenharmony_ci#define XSAVE_HDR_OFFSET FXSAVE_SIZE 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define XSAVE_YMM_SIZE 256 228c2ecf20Sopenharmony_ci#define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define XSAVE_ALIGNMENT 64 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* All currently supported user features */ 278c2ecf20Sopenharmony_ci#define XFEATURE_MASK_USER_SUPPORTED (XFEATURE_MASK_FP | \ 288c2ecf20Sopenharmony_ci XFEATURE_MASK_SSE | \ 298c2ecf20Sopenharmony_ci XFEATURE_MASK_YMM | \ 308c2ecf20Sopenharmony_ci XFEATURE_MASK_OPMASK | \ 318c2ecf20Sopenharmony_ci XFEATURE_MASK_ZMM_Hi256 | \ 328c2ecf20Sopenharmony_ci XFEATURE_MASK_Hi16_ZMM | \ 338c2ecf20Sopenharmony_ci XFEATURE_MASK_PKRU | \ 348c2ecf20Sopenharmony_ci XFEATURE_MASK_BNDREGS | \ 358c2ecf20Sopenharmony_ci XFEATURE_MASK_BNDCSR) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* All currently supported supervisor features */ 388c2ecf20Sopenharmony_ci#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (XFEATURE_MASK_PASID) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * A supervisor state component may not always contain valuable information, 428c2ecf20Sopenharmony_ci * and its size may be huge. Saving/restoring such supervisor state components 438c2ecf20Sopenharmony_ci * at each context switch can cause high CPU and space overhead, which should 448c2ecf20Sopenharmony_ci * be avoided. Such supervisor state components should only be saved/restored 458c2ecf20Sopenharmony_ci * on demand. The on-demand dynamic supervisor features are set in this mask. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * Unlike the existing supported supervisor features, a dynamic supervisor 488c2ecf20Sopenharmony_ci * feature does not allocate a buffer in task->fpu, and the corresponding 498c2ecf20Sopenharmony_ci * supervisor state component cannot be saved/restored at each context switch. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * To support a dynamic supervisor feature, a developer should follow the 528c2ecf20Sopenharmony_ci * dos and don'ts as below: 538c2ecf20Sopenharmony_ci * - Do dynamically allocate a buffer for the supervisor state component. 548c2ecf20Sopenharmony_ci * - Do manually invoke the XSAVES/XRSTORS instruction to save/restore the 558c2ecf20Sopenharmony_ci * state component to/from the buffer. 568c2ecf20Sopenharmony_ci * - Don't set the bit corresponding to the dynamic supervisor feature in 578c2ecf20Sopenharmony_ci * IA32_XSS at run time, since it has been set at boot time. 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ci#define XFEATURE_MASK_DYNAMIC (XFEATURE_MASK_LBR) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * Unsupported supervisor features. When a supervisor feature in this mask is 638c2ecf20Sopenharmony_ci * supported in the future, move it to the supported supervisor feature mask. 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_ci#define XFEATURE_MASK_SUPERVISOR_UNSUPPORTED (XFEATURE_MASK_PT) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* All supervisor states including supported and unsupported states. */ 688c2ecf20Sopenharmony_ci#define XFEATURE_MASK_SUPERVISOR_ALL (XFEATURE_MASK_SUPERVISOR_SUPPORTED | \ 698c2ecf20Sopenharmony_ci XFEATURE_MASK_DYNAMIC | \ 708c2ecf20Sopenharmony_ci XFEATURE_MASK_SUPERVISOR_UNSUPPORTED) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 738c2ecf20Sopenharmony_ci#define REX_PREFIX "0x48, " 748c2ecf20Sopenharmony_ci#else 758c2ecf20Sopenharmony_ci#define REX_PREFIX 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciextern u64 xfeatures_mask_all; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic inline u64 xfeatures_mask_supervisor(void) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci return xfeatures_mask_all & XFEATURE_MASK_SUPERVISOR_SUPPORTED; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic inline u64 xfeatures_mask_user(void) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci return xfeatures_mask_all & XFEATURE_MASK_USER_SUPPORTED; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic inline u64 xfeatures_mask_dynamic(void) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci if (!boot_cpu_has(X86_FEATURE_ARCH_LBR)) 938c2ecf20Sopenharmony_ci return XFEATURE_MASK_DYNAMIC & ~XFEATURE_MASK_LBR; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return XFEATURE_MASK_DYNAMIC; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciextern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciextern void __init update_regset_xstate_info(unsigned int size, 1018c2ecf20Sopenharmony_ci u64 xstate_mask); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_civoid *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr); 1048c2ecf20Sopenharmony_ciconst void *get_xsave_field_ptr(int xfeature_nr); 1058c2ecf20Sopenharmony_ciint using_compacted_format(void); 1068c2ecf20Sopenharmony_ciint xfeature_size(int xfeature_nr); 1078c2ecf20Sopenharmony_cistruct membuf; 1088c2ecf20Sopenharmony_civoid copy_xstate_to_kernel(struct membuf to, struct xregs_state *xsave); 1098c2ecf20Sopenharmony_ciint copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf); 1108c2ecf20Sopenharmony_ciint copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf); 1118c2ecf20Sopenharmony_civoid copy_supervisor_to_kernel(struct xregs_state *xsave); 1128c2ecf20Sopenharmony_civoid copy_dynamic_supervisor_to_kernel(struct xregs_state *xstate, u64 mask); 1138c2ecf20Sopenharmony_civoid copy_kernel_to_dynamic_supervisor(struct xregs_state *xstate, u64 mask); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */ 1178c2ecf20Sopenharmony_ciint validate_user_xstate_header(const struct xstate_header *hdr); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#endif 120