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.

Merge tag 'x86-fpu-2025-03-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86/fpu updates from Ingo Molnar:

- Improve crypto performance by making kernel-mode FPU reliably usable
in softirqs ((Eric Biggers)

- Fully optimize out WARN_ON_FPU() (Eric Biggers)

- Initial steps to support Support Intel APX (Advanced Performance
Extensions) (Chang S. Bae)

- Fix KASAN for arch_dup_task_struct() (Benjamin Berg)

- Refine and simplify the FPU magic number check during signal return
(Chang S. Bae)

- Fix inconsistencies in guest FPU xfeatures (Chao Gao, Stanislav
Spassov)

- selftests/x86/xstate: Introduce common code for testing extended
states (Chang S. Bae)

- Misc fixes and cleanups (Borislav Petkov, Colin Ian King, Uros
Bizjak)

* tag 'x86-fpu-2025-03-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/fpu/xstate: Fix inconsistencies in guest FPU xfeatures
x86/fpu: Clarify the "xa" symbolic name used in the XSTATE* macros
x86/fpu: Use XSAVE{,OPT,C,S} and XRSTOR{,S} mnemonics in xstate.h
x86/fpu: Improve crypto performance by making kernel-mode FPU reliably usable in softirqs
x86/fpu/xstate: Simplify print_xstate_features()
x86/fpu: Refine and simplify the magic number check during signal return
selftests/x86/xstate: Fix spelling mistake "hader" -> "header"
x86/fpu: Avoid copying dynamic FP state from init_task in arch_dup_task_struct()
vmlinux.lds.h: Remove entry to place init_task onto init_stack
selftests/x86/avx: Add AVX tests
selftests/x86/xstate: Clarify supported xstates
selftests/x86/xstate: Consolidate test invocations into a single entry
selftests/x86/xstate: Introduce signal ABI test
selftests/x86/xstate: Refactor ptrace ABI test
selftests/x86/xstate: Refactor context switching test
selftests/x86/xstate: Enumerate and name xstate components
selftests/x86/xstate: Refactor XSAVE helpers for general use
selftests/x86: Consolidate redundant signal helper functions
x86/fpu: Fix guest FPU state buffer allocation size
x86/fpu: Fully optimize out WARN_ON_FPU()

+812 -783
+7 -10
arch/x86/include/asm/fpu/api.h
··· 16 16 17 17 /* 18 18 * Use kernel_fpu_begin/end() if you intend to use FPU in kernel context. It 19 - * disables preemption so be careful if you intend to use it for long periods 20 - * of time. 21 - * If you intend to use the FPU in irq/softirq you need to check first with 22 - * irq_fpu_usable() if it is possible. 19 + * disables preemption and softirq processing, so be careful if you intend to 20 + * use it for long periods of time. Kernel-mode FPU cannot be used in all 21 + * contexts -- see irq_fpu_usable() for details. 23 22 */ 24 23 25 24 /* Kernel FPU states to initialize in kernel_fpu_begin_mask() */ ··· 49 50 } 50 51 51 52 /* 52 - * Use fpregs_lock() while editing CPU's FPU registers or fpu->fpstate. 53 - * A context switch will (and softirq might) save CPU's FPU registers to 54 - * fpu->fpstate.regs and set TIF_NEED_FPU_LOAD leaving CPU's FPU registers in 55 - * a random state. 53 + * Use fpregs_lock() while editing CPU's FPU registers or fpu->fpstate, or while 54 + * using the FPU in kernel mode. A context switch will (and softirq might) save 55 + * CPU's FPU registers to fpu->fpstate.regs and set TIF_NEED_FPU_LOAD leaving 56 + * CPU's FPU registers in a random state. 56 57 * 57 58 * local_bh_disable() protects against both preemption and soft interrupts 58 59 * on !RT kernels. ··· 62 63 * preemptible. Disabling preemption is the right choice here as bottom 63 64 * half processing is always in thread context on RT kernels so it 64 65 * implicitly prevents bottom half processing as well. 65 - * 66 - * Disabling preemption also serializes against kernel_fpu_begin(). 67 66 */ 68 67 static inline void fpregs_lock(void) 69 68 {
+16 -7
arch/x86/kernel/fpu/core.c
··· 60 60 if (WARN_ON_ONCE(in_nmi())) 61 61 return false; 62 62 63 - /* In kernel FPU usage already active? */ 64 - if (this_cpu_read(in_kernel_fpu)) 63 + /* 64 + * In kernel FPU usage already active? This detects any explicitly 65 + * nested usage in task or softirq context, which is unsupported. It 66 + * also detects attempted usage in a hardirq that has interrupted a 67 + * kernel-mode FPU section. 68 + */ 69 + if (this_cpu_read(in_kernel_fpu)) { 70 + WARN_ON_FPU(!in_hardirq()); 65 71 return false; 72 + } 66 73 67 74 /* 68 75 * When not in NMI or hard interrupt context, FPU can be used in: ··· 227 220 struct fpstate *fpstate; 228 221 unsigned int size; 229 222 230 - size = fpu_user_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64); 223 + size = fpu_kernel_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64); 231 224 fpstate = vzalloc(size); 232 225 if (!fpstate) 233 226 return false; ··· 239 232 fpstate->is_guest = true; 240 233 241 234 gfpu->fpstate = fpstate; 242 - gfpu->xfeatures = fpu_user_cfg.default_features; 243 - gfpu->perm = fpu_user_cfg.default_features; 235 + gfpu->xfeatures = fpu_kernel_cfg.default_features; 236 + gfpu->perm = fpu_kernel_cfg.default_features; 244 237 245 238 /* 246 239 * KVM sets the FP+SSE bits in the XSAVE header when copying FPU state ··· 427 420 428 421 void kernel_fpu_begin_mask(unsigned int kfpu_mask) 429 422 { 430 - preempt_disable(); 423 + if (!irqs_disabled()) 424 + fpregs_lock(); 431 425 432 426 WARN_ON_FPU(!irq_fpu_usable()); 433 427 WARN_ON_FPU(this_cpu_read(in_kernel_fpu)); ··· 456 448 WARN_ON_FPU(!this_cpu_read(in_kernel_fpu)); 457 449 458 450 this_cpu_write(in_kernel_fpu, false); 459 - preempt_enable(); 451 + if (!irqs_disabled()) 452 + fpregs_unlock(); 460 453 } 461 454 EXPORT_SYMBOL_GPL(kernel_fpu_end); 462 455
+1 -1
arch/x86/kernel/fpu/internal.h
··· 18 18 #ifdef CONFIG_X86_DEBUG_FPU 19 19 # define WARN_ON_FPU(x) WARN_ON_ONCE(x) 20 20 #else 21 - # define WARN_ON_FPU(x) ({ (void)(x); 0; }) 21 + # define WARN_ON_FPU(x) ({ BUILD_BUG_ON_INVALID(x); 0; }) 22 22 #endif 23 23 24 24 /* Used in init.c */
+3 -8
arch/x86/kernel/fpu/signal.c
··· 27 27 static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf, 28 28 struct _fpx_sw_bytes *fx_sw) 29 29 { 30 - int min_xstate_size = sizeof(struct fxregs_state) + 31 - sizeof(struct xstate_header); 32 30 void __user *fpstate = fxbuf; 33 31 unsigned int magic2; 34 32 35 33 if (__copy_from_user(fx_sw, &fxbuf->sw_reserved[0], sizeof(*fx_sw))) 36 34 return false; 37 35 38 - /* Check for the first magic field and other error scenarios. */ 39 - if (fx_sw->magic1 != FP_XSTATE_MAGIC1 || 40 - fx_sw->xstate_size < min_xstate_size || 41 - fx_sw->xstate_size > current->thread.fpu.fpstate->user_size || 42 - fx_sw->xstate_size > fx_sw->extended_size) 36 + /* Check for the first magic field */ 37 + if (fx_sw->magic1 != FP_XSTATE_MAGIC1) 43 38 goto setfx; 44 39 45 40 /* ··· 43 48 * fpstate layout with out copying the extended state information 44 49 * in the memory layout. 45 50 */ 46 - if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))) 51 + if (__get_user(magic2, (__u32 __user *)(fpstate + current->thread.fpu.fpstate->user_size))) 47 52 return false; 48 53 49 54 if (likely(magic2 == FP_XSTATE_MAGIC2))
+9 -21
arch/x86/kernel/fpu/xstate.c
··· 259 259 } 260 260 } 261 261 262 - static void __init print_xstate_feature(u64 xstate_mask) 263 - { 264 - const char *feature_name; 265 - 266 - if (cpu_has_xfeatures(xstate_mask, &feature_name)) 267 - pr_info("x86/fpu: Supporting XSAVE feature 0x%03Lx: '%s'\n", xstate_mask, feature_name); 268 - } 269 - 270 262 /* 271 263 * Print out all the supported xstate features: 272 264 */ 273 265 static void __init print_xstate_features(void) 274 266 { 275 - print_xstate_feature(XFEATURE_MASK_FP); 276 - print_xstate_feature(XFEATURE_MASK_SSE); 277 - print_xstate_feature(XFEATURE_MASK_YMM); 278 - print_xstate_feature(XFEATURE_MASK_BNDREGS); 279 - print_xstate_feature(XFEATURE_MASK_BNDCSR); 280 - print_xstate_feature(XFEATURE_MASK_OPMASK); 281 - print_xstate_feature(XFEATURE_MASK_ZMM_Hi256); 282 - print_xstate_feature(XFEATURE_MASK_Hi16_ZMM); 283 - print_xstate_feature(XFEATURE_MASK_PKRU); 284 - print_xstate_feature(XFEATURE_MASK_PASID); 285 - print_xstate_feature(XFEATURE_MASK_CET_USER); 286 - print_xstate_feature(XFEATURE_MASK_XTILE_CFG); 287 - print_xstate_feature(XFEATURE_MASK_XTILE_DATA); 267 + int i; 268 + 269 + for (i = 0; i < XFEATURE_MAX; i++) { 270 + u64 mask = BIT_ULL(i); 271 + const char *name; 272 + 273 + if (cpu_has_xfeatures(mask, &name)) 274 + pr_info("x86/fpu: Supporting XSAVE feature 0x%03Lx: '%s'\n", mask, name); 275 + } 288 276 } 289 277 290 278 /*
+17 -14
arch/x86/kernel/fpu/xstate.h
··· 94 94 /* XSAVE/XRSTOR wrapper functions */ 95 95 96 96 #ifdef CONFIG_X86_64 97 - #define REX_PREFIX "0x48, " 97 + #define REX_SUFFIX "64" 98 98 #else 99 - #define REX_PREFIX 99 + #define REX_SUFFIX 100 100 #endif 101 101 102 - /* These macros all use (%edi)/(%rdi) as the single memory argument. */ 103 - #define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27" 104 - #define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37" 105 - #define XSAVEC ".byte " REX_PREFIX "0x0f,0xc7,0x27" 106 - #define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f" 107 - #define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f" 108 - #define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f" 102 + #define XSAVE "xsave" REX_SUFFIX " %[xa]" 103 + #define XSAVEOPT "xsaveopt" REX_SUFFIX " %[xa]" 104 + #define XSAVEC "xsavec" REX_SUFFIX " %[xa]" 105 + #define XSAVES "xsaves" REX_SUFFIX " %[xa]" 106 + #define XRSTOR "xrstor" REX_SUFFIX " %[xa]" 107 + #define XRSTORS "xrstors" REX_SUFFIX " %[xa]" 109 108 110 109 /* 111 110 * After this @err contains 0 on success or the trap number when the 112 111 * operation raises an exception. 112 + * 113 + * The [xa] input parameter below represents the struct xregs_state pointer 114 + * and the asm symbolic name for the argument used in the XSAVE/XRSTOR insns 115 + * above. 113 116 */ 114 117 #define XSTATE_OP(op, st, lmask, hmask, err) \ 115 118 asm volatile("1:" op "\n\t" \ 116 119 "xor %[err], %[err]\n" \ 117 - "2:\n\t" \ 120 + "2:\n" \ 118 121 _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_MCE_SAFE) \ 119 122 : [err] "=a" (err) \ 120 - : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ 123 + : [xa] "m" (*(st)), "a" (lmask), "d" (hmask) \ 121 124 : "memory") 122 125 123 126 /* ··· 140 137 XSAVEOPT, X86_FEATURE_XSAVEOPT, \ 141 138 XSAVEC, X86_FEATURE_XSAVEC, \ 142 139 XSAVES, X86_FEATURE_XSAVES) \ 143 - "\n" \ 140 + "\n\t" \ 144 141 "xor %[err], %[err]\n" \ 145 142 "3:\n" \ 146 143 _ASM_EXTABLE_TYPE_REG(1b, 3b, EX_TYPE_EFAULT_REG, %[err]) \ 147 144 : [err] "=r" (err) \ 148 - : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ 145 + : [xa] "m" (*(st)), "a" (lmask), "d" (hmask) \ 149 146 : "memory") 150 147 151 148 /* ··· 159 156 "3:\n" \ 160 157 _ASM_EXTABLE_TYPE(1b, 3b, EX_TYPE_FPU_RESTORE) \ 161 158 : \ 162 - : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ 159 + : [xa] "m" (*(st)), "a" (lmask), "d" (hmask) \ 163 160 : "memory") 164 161 165 162 #if defined(CONFIG_X86_64) && defined(CONFIG_X86_DEBUG_FPU)
+6 -1
arch/x86/kernel/process.c
··· 93 93 */ 94 94 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 95 95 { 96 - memcpy(dst, src, arch_task_struct_size); 96 + /* init_task is not dynamically sized (incomplete FPU state) */ 97 + if (unlikely(src == &init_task)) 98 + memcpy_and_pad(dst, arch_task_struct_size, src, sizeof(init_task), 0); 99 + else 100 + memcpy(dst, src, arch_task_struct_size); 101 + 97 102 #ifdef CONFIG_VM86 98 103 dst->thread.vm86 = NULL; 99 104 #endif
-1
include/asm-generic/vmlinux.lds.h
··· 409 409 __start_init_stack = .; \ 410 410 init_thread_union = .; \ 411 411 init_stack = .; \ 412 - KEEP(*(.data..init_task)) \ 413 412 KEEP(*(.data..init_thread_info)) \ 414 413 . = __start_init_stack + THREAD_SIZE; \ 415 414 __end_init_stack = .;
+5 -1
tools/testing/selftests/x86/Makefile
··· 19 19 test_FCMOV test_FCOMI test_FISTTP \ 20 20 vdso_restorer 21 21 TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip syscall_numbering \ 22 - corrupt_xstate_header amx lam test_shadow_stack 22 + corrupt_xstate_header amx lam test_shadow_stack avx 23 23 # Some selftests require 32bit support enabled also on 64bit systems 24 24 TARGETS_C_32BIT_NEEDED := ldt_gdt ptrace_syscall 25 25 ··· 132 132 133 133 $(OUTPUT)/nx_stack_32: CFLAGS += -Wl,-z,noexecstack 134 134 $(OUTPUT)/nx_stack_64: CFLAGS += -Wl,-z,noexecstack 135 + 136 + $(OUTPUT)/avx_64: CFLAGS += -mno-avx -mno-avx512f 137 + $(OUTPUT)/amx_64: EXTRA_FILES += xstate.c 138 + $(OUTPUT)/avx_64: EXTRA_FILES += xstate.c
+14 -428
tools/testing/selftests/x86/amx.c
··· 3 3 #define _GNU_SOURCE 4 4 #include <err.h> 5 5 #include <errno.h> 6 - #include <pthread.h> 7 6 #include <setjmp.h> 8 7 #include <stdio.h> 9 8 #include <string.h> ··· 13 14 #include <sys/auxv.h> 14 15 #include <sys/mman.h> 15 16 #include <sys/shm.h> 16 - #include <sys/ptrace.h> 17 17 #include <sys/syscall.h> 18 18 #include <sys/wait.h> 19 - #include <sys/uio.h> 20 19 21 - #include "../kselftest.h" /* For __cpuid_count() */ 20 + #include "helpers.h" 21 + #include "xstate.h" 22 22 23 23 #ifndef __x86_64__ 24 24 # error This test is 64-bit only 25 25 #endif 26 26 27 - #define XSAVE_HDR_OFFSET 512 28 - #define XSAVE_HDR_SIZE 64 29 - 30 - struct xsave_buffer { 31 - union { 32 - struct { 33 - char legacy[XSAVE_HDR_OFFSET]; 34 - char header[XSAVE_HDR_SIZE]; 35 - char extended[0]; 36 - }; 37 - char bytes[0]; 38 - }; 39 - }; 40 - 41 - static inline void xsave(struct xsave_buffer *xbuf, uint64_t rfbm) 42 - { 43 - uint32_t rfbm_lo = rfbm; 44 - uint32_t rfbm_hi = rfbm >> 32; 45 - 46 - asm volatile("xsave (%%rdi)" 47 - : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi) 48 - : "memory"); 49 - } 50 - 51 - static inline void xrstor(struct xsave_buffer *xbuf, uint64_t rfbm) 52 - { 53 - uint32_t rfbm_lo = rfbm; 54 - uint32_t rfbm_hi = rfbm >> 32; 55 - 56 - asm volatile("xrstor (%%rdi)" 57 - : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi)); 58 - } 59 - 60 27 /* err() exits and will not return */ 61 28 #define fatal_error(msg, ...) err(1, "[FAIL]\t" msg, ##__VA_ARGS__) 62 29 63 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 64 - int flags) 65 - { 66 - struct sigaction sa; 67 - 68 - memset(&sa, 0, sizeof(sa)); 69 - sa.sa_sigaction = handler; 70 - sa.sa_flags = SA_SIGINFO | flags; 71 - sigemptyset(&sa.sa_mask); 72 - if (sigaction(sig, &sa, 0)) 73 - fatal_error("sigaction"); 74 - } 75 - 76 - static void clearhandler(int sig) 77 - { 78 - struct sigaction sa; 79 - 80 - memset(&sa, 0, sizeof(sa)); 81 - sa.sa_handler = SIG_DFL; 82 - sigemptyset(&sa.sa_mask); 83 - if (sigaction(sig, &sa, 0)) 84 - fatal_error("sigaction"); 85 - } 86 - 87 - #define XFEATURE_XTILECFG 17 88 - #define XFEATURE_XTILEDATA 18 89 30 #define XFEATURE_MASK_XTILECFG (1 << XFEATURE_XTILECFG) 90 31 #define XFEATURE_MASK_XTILEDATA (1 << XFEATURE_XTILEDATA) 91 32 #define XFEATURE_MASK_XTILE (XFEATURE_MASK_XTILECFG | XFEATURE_MASK_XTILEDATA) 92 33 93 - #define CPUID_LEAF1_ECX_XSAVE_MASK (1 << 26) 94 - #define CPUID_LEAF1_ECX_OSXSAVE_MASK (1 << 27) 95 - 96 - static uint32_t xbuf_size; 97 - 98 - static struct { 99 - uint32_t xbuf_offset; 100 - uint32_t size; 101 - } xtiledata; 102 - 103 - #define CPUID_LEAF_XSTATE 0xd 104 - #define CPUID_SUBLEAF_XSTATE_USER 0x0 105 - #define TILE_CPUID 0x1d 106 - #define TILE_PALETTE_ID 0x1 107 - 108 - static void check_cpuid_xtiledata(void) 109 - { 110 - uint32_t eax, ebx, ecx, edx; 111 - 112 - __cpuid_count(CPUID_LEAF_XSTATE, CPUID_SUBLEAF_XSTATE_USER, 113 - eax, ebx, ecx, edx); 114 - 115 - /* 116 - * EBX enumerates the size (in bytes) required by the XSAVE 117 - * instruction for an XSAVE area containing all the user state 118 - * components corresponding to bits currently set in XCR0. 119 - * 120 - * Stash that off so it can be used to allocate buffers later. 121 - */ 122 - xbuf_size = ebx; 123 - 124 - __cpuid_count(CPUID_LEAF_XSTATE, XFEATURE_XTILEDATA, 125 - eax, ebx, ecx, edx); 126 - /* 127 - * eax: XTILEDATA state component size 128 - * ebx: XTILEDATA state component offset in user buffer 129 - */ 130 - if (!eax || !ebx) 131 - fatal_error("xstate cpuid: invalid tile data size/offset: %d/%d", 132 - eax, ebx); 133 - 134 - xtiledata.size = eax; 135 - xtiledata.xbuf_offset = ebx; 136 - } 34 + struct xstate_info xtiledata; 137 35 138 36 /* The helpers for managing XSAVE buffer and tile states: */ 139 - 140 - struct xsave_buffer *alloc_xbuf(void) 141 - { 142 - struct xsave_buffer *xbuf; 143 - 144 - /* XSAVE buffer should be 64B-aligned. */ 145 - xbuf = aligned_alloc(64, xbuf_size); 146 - if (!xbuf) 147 - fatal_error("aligned_alloc()"); 148 - return xbuf; 149 - } 150 - 151 - static inline void clear_xstate_header(struct xsave_buffer *buffer) 152 - { 153 - memset(&buffer->header, 0, sizeof(buffer->header)); 154 - } 155 - 156 - static inline void set_xstatebv(struct xsave_buffer *buffer, uint64_t bv) 157 - { 158 - /* XSTATE_BV is at the beginning of the header: */ 159 - *(uint64_t *)(&buffer->header) = bv; 160 - } 161 - 162 - static void set_rand_tiledata(struct xsave_buffer *xbuf) 163 - { 164 - int *ptr = (int *)&xbuf->bytes[xtiledata.xbuf_offset]; 165 - int data; 166 - int i; 167 - 168 - /* 169 - * Ensure that 'data' is never 0. This ensures that 170 - * the registers are never in their initial configuration 171 - * and thus never tracked as being in the init state. 172 - */ 173 - data = rand() | 1; 174 - 175 - for (i = 0; i < xtiledata.size / sizeof(int); i++, ptr++) 176 - *ptr = data; 177 - } 178 37 179 38 struct xsave_buffer *stashed_xsave; 180 39 ··· 47 190 static void free_stashed_xsave(void) 48 191 { 49 192 free(stashed_xsave); 50 - } 51 - 52 - /* See 'struct _fpx_sw_bytes' at sigcontext.h */ 53 - #define SW_BYTES_OFFSET 464 54 - /* N.B. The struct's field name varies so read from the offset. */ 55 - #define SW_BYTES_BV_OFFSET (SW_BYTES_OFFSET + 8) 56 - 57 - static inline struct _fpx_sw_bytes *get_fpx_sw_bytes(void *buffer) 58 - { 59 - return (struct _fpx_sw_bytes *)(buffer + SW_BYTES_OFFSET); 60 - } 61 - 62 - static inline uint64_t get_fpx_sw_bytes_features(void *buffer) 63 - { 64 - return *(uint64_t *)(buffer + SW_BYTES_BV_OFFSET); 65 193 } 66 194 67 195 /* Work around printf() being unsafe in signals: */ ··· 146 304 { 147 305 clear_xstate_header(xbuf); 148 306 set_xstatebv(xbuf, XFEATURE_MASK_XTILEDATA); 149 - set_rand_tiledata(xbuf); 307 + set_rand_data(&xtiledata, xbuf); 150 308 return xrstor_safe(xbuf, XFEATURE_MASK_XTILEDATA); 151 - } 152 - 153 - /* Return XTILEDATA to its initial configuration. */ 154 - static inline void init_xtiledata(void) 155 - { 156 - clear_xstate_header(stashed_xsave); 157 - xrstor_safe(stashed_xsave, XFEATURE_MASK_XTILEDATA); 158 309 } 159 310 160 311 enum expected_result { FAIL_EXPECTED, SUCCESS_EXPECTED }; ··· 422 587 return true; 423 588 } 424 589 425 - static inline void validate_tiledata_regs_same(struct xsave_buffer *xbuf) 426 - { 427 - int ret = __validate_tiledata_regs(xbuf); 428 - 429 - if (ret != 0) 430 - fatal_error("TILEDATA registers changed"); 431 - } 432 - 433 590 static inline void validate_tiledata_regs_changed(struct xsave_buffer *xbuf) 434 591 { 435 592 int ret = __validate_tiledata_regs(xbuf); ··· 478 651 _exit(0); 479 652 } 480 653 481 - /* Context switching test */ 482 - 483 - static struct _ctxtswtest_cfg { 484 - unsigned int iterations; 485 - unsigned int num_threads; 486 - } ctxtswtest_config; 487 - 488 - struct futex_info { 489 - pthread_t thread; 490 - int nr; 491 - pthread_mutex_t mutex; 492 - struct futex_info *next; 493 - }; 494 - 495 - static void *check_tiledata(void *info) 496 - { 497 - struct futex_info *finfo = (struct futex_info *)info; 498 - struct xsave_buffer *xbuf; 499 - int i; 500 - 501 - xbuf = alloc_xbuf(); 502 - if (!xbuf) 503 - fatal_error("unable to allocate XSAVE buffer"); 504 - 505 - /* 506 - * Load random data into 'xbuf' and then restore 507 - * it to the tile registers themselves. 508 - */ 509 - load_rand_tiledata(xbuf); 510 - for (i = 0; i < ctxtswtest_config.iterations; i++) { 511 - pthread_mutex_lock(&finfo->mutex); 512 - 513 - /* 514 - * Ensure the register values have not 515 - * diverged from those recorded in 'xbuf'. 516 - */ 517 - validate_tiledata_regs_same(xbuf); 518 - 519 - /* Load new, random values into xbuf and registers */ 520 - load_rand_tiledata(xbuf); 521 - 522 - /* 523 - * The last thread's last unlock will be for 524 - * thread 0's mutex. However, thread 0 will 525 - * have already exited the loop and the mutex 526 - * will already be unlocked. 527 - * 528 - * Because this is not an ERRORCHECK mutex, 529 - * that inconsistency will be silently ignored. 530 - */ 531 - pthread_mutex_unlock(&finfo->next->mutex); 532 - } 533 - 534 - free(xbuf); 535 - /* 536 - * Return this thread's finfo, which is 537 - * a unique value for this thread. 538 - */ 539 - return finfo; 540 - } 541 - 542 - static int create_threads(int num, struct futex_info *finfo) 543 - { 544 - int i; 545 - 546 - for (i = 0; i < num; i++) { 547 - int next_nr; 548 - 549 - finfo[i].nr = i; 550 - /* 551 - * Thread 'i' will wait on this mutex to 552 - * be unlocked. Lock it immediately after 553 - * initialization: 554 - */ 555 - pthread_mutex_init(&finfo[i].mutex, NULL); 556 - pthread_mutex_lock(&finfo[i].mutex); 557 - 558 - next_nr = (i + 1) % num; 559 - finfo[i].next = &finfo[next_nr]; 560 - 561 - if (pthread_create(&finfo[i].thread, NULL, check_tiledata, &finfo[i])) 562 - fatal_error("pthread_create()"); 563 - } 564 - return 0; 565 - } 566 - 567 - static void affinitize_cpu0(void) 568 - { 569 - cpu_set_t cpuset; 570 - 571 - CPU_ZERO(&cpuset); 572 - CPU_SET(0, &cpuset); 573 - 574 - if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) 575 - fatal_error("sched_setaffinity to CPU 0"); 576 - } 577 - 578 - static void test_context_switch(void) 579 - { 580 - struct futex_info *finfo; 581 - int i; 582 - 583 - /* Affinitize to one CPU to force context switches */ 584 - affinitize_cpu0(); 585 - 586 - req_xtiledata_perm(); 587 - 588 - printf("[RUN]\tCheck tiledata context switches, %d iterations, %d threads.\n", 589 - ctxtswtest_config.iterations, 590 - ctxtswtest_config.num_threads); 591 - 592 - 593 - finfo = malloc(sizeof(*finfo) * ctxtswtest_config.num_threads); 594 - if (!finfo) 595 - fatal_error("malloc()"); 596 - 597 - create_threads(ctxtswtest_config.num_threads, finfo); 598 - 599 - /* 600 - * This thread wakes up thread 0 601 - * Thread 0 will wake up 1 602 - * Thread 1 will wake up 2 603 - * ... 604 - * the last thread will wake up 0 605 - * 606 - * ... this will repeat for the configured 607 - * number of iterations. 608 - */ 609 - pthread_mutex_unlock(&finfo[0].mutex); 610 - 611 - /* Wait for all the threads to finish: */ 612 - for (i = 0; i < ctxtswtest_config.num_threads; i++) { 613 - void *thread_retval; 614 - int rc; 615 - 616 - rc = pthread_join(finfo[i].thread, &thread_retval); 617 - 618 - if (rc) 619 - fatal_error("pthread_join() failed for thread %d err: %d\n", 620 - i, rc); 621 - 622 - if (thread_retval != &finfo[i]) 623 - fatal_error("unexpected thread retval for thread %d: %p\n", 624 - i, thread_retval); 625 - 626 - } 627 - 628 - printf("[OK]\tNo incorrect case was found.\n"); 629 - 630 - free(finfo); 631 - } 632 - 633 - /* Ptrace test */ 634 - 635 - /* 636 - * Make sure the ptracee has the expanded kernel buffer on the first 637 - * use. Then, initialize the state before performing the state 638 - * injection from the ptracer. 639 - */ 640 - static inline void ptracee_firstuse_tiledata(void) 641 - { 642 - load_rand_tiledata(stashed_xsave); 643 - init_xtiledata(); 644 - } 645 - 646 - /* 647 - * Ptracer injects the randomized tile data state. It also reads 648 - * before and after that, which will execute the kernel's state copy 649 - * functions. So, the tester is advised to double-check any emitted 650 - * kernel messages. 651 - */ 652 - static void ptracer_inject_tiledata(pid_t target) 653 - { 654 - struct xsave_buffer *xbuf; 655 - struct iovec iov; 656 - 657 - xbuf = alloc_xbuf(); 658 - if (!xbuf) 659 - fatal_error("unable to allocate XSAVE buffer"); 660 - 661 - printf("\tRead the init'ed tiledata via ptrace().\n"); 662 - 663 - iov.iov_base = xbuf; 664 - iov.iov_len = xbuf_size; 665 - 666 - memset(stashed_xsave, 0, xbuf_size); 667 - 668 - if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 669 - fatal_error("PTRACE_GETREGSET"); 670 - 671 - if (!__compare_tiledata_state(stashed_xsave, xbuf)) 672 - printf("[OK]\tThe init'ed tiledata was read from ptracee.\n"); 673 - else 674 - printf("[FAIL]\tThe init'ed tiledata was not read from ptracee.\n"); 675 - 676 - printf("\tInject tiledata via ptrace().\n"); 677 - 678 - load_rand_tiledata(xbuf); 679 - 680 - memcpy(&stashed_xsave->bytes[xtiledata.xbuf_offset], 681 - &xbuf->bytes[xtiledata.xbuf_offset], 682 - xtiledata.size); 683 - 684 - if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 685 - fatal_error("PTRACE_SETREGSET"); 686 - 687 - if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 688 - fatal_error("PTRACE_GETREGSET"); 689 - 690 - if (!__compare_tiledata_state(stashed_xsave, xbuf)) 691 - printf("[OK]\tTiledata was correctly written to ptracee.\n"); 692 - else 693 - printf("[FAIL]\tTiledata was not correctly written to ptracee.\n"); 694 - } 695 - 696 - static void test_ptrace(void) 697 - { 698 - pid_t child; 699 - int status; 700 - 701 - child = fork(); 702 - if (child < 0) { 703 - err(1, "fork"); 704 - } else if (!child) { 705 - if (ptrace(PTRACE_TRACEME, 0, NULL, NULL)) 706 - err(1, "PTRACE_TRACEME"); 707 - 708 - ptracee_firstuse_tiledata(); 709 - 710 - raise(SIGTRAP); 711 - _exit(0); 712 - } 713 - 714 - do { 715 - wait(&status); 716 - } while (WSTOPSIG(status) != SIGTRAP); 717 - 718 - ptracer_inject_tiledata(child); 719 - 720 - ptrace(PTRACE_DETACH, child, NULL, NULL); 721 - wait(&status); 722 - if (!WIFEXITED(status) || WEXITSTATUS(status)) 723 - err(1, "ptrace test"); 724 - } 725 - 726 654 int main(void) 727 655 { 728 656 unsigned long features; ··· 489 907 return KSFT_SKIP; 490 908 } 491 909 492 - check_cpuid_xtiledata(); 910 + xtiledata = get_xstate_info(XFEATURE_XTILEDATA); 911 + if (!xtiledata.size || !xtiledata.xbuf_offset) { 912 + fatal_error("xstate cpuid: invalid tile data size/offset: %d/%d", 913 + xtiledata.size, xtiledata.xbuf_offset); 914 + } 493 915 494 916 init_stashed_xsave(); 495 917 sethandler(SIGILL, handle_noperm, 0); ··· 505 919 506 920 test_fork(); 507 921 508 - ctxtswtest_config.iterations = 10; 509 - ctxtswtest_config.num_threads = 5; 510 - test_context_switch(); 511 - 512 - test_ptrace(); 922 + /* 923 + * Perform generic xstate tests for context switching, ptrace, 924 + * and signal. 925 + */ 926 + test_xstate(XFEATURE_XTILEDATA); 513 927 514 928 clearhandler(SIGILL); 515 929 free_stashed_xsave();
+12
tools/testing/selftests/x86/avx.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #define _GNU_SOURCE /* Required for inline xstate helpers */ 4 + #include "xstate.h" 5 + 6 + int main(void) 7 + { 8 + test_xstate(XFEATURE_YMM); 9 + test_xstate(XFEATURE_OPMASK); 10 + test_xstate(XFEATURE_ZMM_Hi256); 11 + test_xstate(XFEATURE_Hi16_ZMM); 12 + }
+1 -13
tools/testing/selftests/x86/corrupt_xstate_header.c
··· 18 18 #include <sys/wait.h> 19 19 20 20 #include "../kselftest.h" /* For __cpuid_count() */ 21 + #include "helpers.h" 21 22 22 23 static inline int xsave_enabled(void) 23 24 { ··· 28 27 29 28 /* Is CR4.OSXSAVE enabled ? */ 30 29 return ecx & (1U << 27); 31 - } 32 - 33 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 34 - int flags) 35 - { 36 - struct sigaction sa; 37 - 38 - memset(&sa, 0, sizeof(sa)); 39 - sa.sa_sigaction = handler; 40 - sa.sa_flags = SA_SIGINFO | flags; 41 - sigemptyset(&sa.sa_mask); 42 - if (sigaction(sig, &sa, 0)) 43 - err(1, "sigaction"); 44 30 } 45 31 46 32 static void sigusr1(int sig, siginfo_t *info, void *uc_void)
+2 -22
tools/testing/selftests/x86/entry_from_vm86.c
··· 24 24 #include <errno.h> 25 25 #include <sys/vm86.h> 26 26 27 + #include "helpers.h" 28 + 27 29 static unsigned long load_addr = 0x10000; 28 30 static int nerrs = 0; 29 - 30 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 31 - int flags) 32 - { 33 - struct sigaction sa; 34 - memset(&sa, 0, sizeof(sa)); 35 - sa.sa_sigaction = handler; 36 - sa.sa_flags = SA_SIGINFO | flags; 37 - sigemptyset(&sa.sa_mask); 38 - if (sigaction(sig, &sa, 0)) 39 - err(1, "sigaction"); 40 - } 41 - 42 - static void clearhandler(int sig) 43 - { 44 - struct sigaction sa; 45 - memset(&sa, 0, sizeof(sa)); 46 - sa.sa_handler = SIG_DFL; 47 - sigemptyset(&sa.sa_mask); 48 - if (sigaction(sig, &sa, 0)) 49 - err(1, "sigaction"); 50 - } 51 31 52 32 static sig_atomic_t got_signal; 53 33
+2 -22
tools/testing/selftests/x86/fsgsbase.c
··· 28 28 #include <sys/wait.h> 29 29 #include <setjmp.h> 30 30 31 + #include "helpers.h" 32 + 31 33 #ifndef __x86_64__ 32 34 # error This test is 64-bit only 33 35 #endif ··· 40 38 static unsigned short *shared_scratch; 41 39 42 40 static int nerrs; 43 - 44 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 45 - int flags) 46 - { 47 - struct sigaction sa; 48 - memset(&sa, 0, sizeof(sa)); 49 - sa.sa_sigaction = handler; 50 - sa.sa_flags = SA_SIGINFO | flags; 51 - sigemptyset(&sa.sa_mask); 52 - if (sigaction(sig, &sa, 0)) 53 - err(1, "sigaction"); 54 - } 55 - 56 - static void clearhandler(int sig) 57 - { 58 - struct sigaction sa; 59 - memset(&sa, 0, sizeof(sa)); 60 - sa.sa_handler = SIG_DFL; 61 - sigemptyset(&sa.sa_mask); 62 - if (sigaction(sig, &sa, 0)) 63 - err(1, "sigaction"); 64 - } 65 41 66 42 static void sigsegv(int sig, siginfo_t *si, void *ctx_void) 67 43 {
+28
tools/testing/selftests/x86/helpers.h
··· 2 2 #ifndef __SELFTESTS_X86_HELPERS_H 3 3 #define __SELFTESTS_X86_HELPERS_H 4 4 5 + #include <signal.h> 6 + #include <string.h> 7 + 5 8 #include <asm/processor-flags.h> 9 + 10 + #include "../kselftest.h" 6 11 7 12 static inline unsigned long get_eflags(void) 8 13 { ··· 25 20 #else 26 21 __builtin_ia32_writeeflags_u32(eflags); 27 22 #endif 23 + } 24 + 25 + static inline void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), int flags) 26 + { 27 + struct sigaction sa; 28 + 29 + memset(&sa, 0, sizeof(sa)); 30 + sa.sa_sigaction = handler; 31 + sa.sa_flags = SA_SIGINFO | flags; 32 + sigemptyset(&sa.sa_mask); 33 + if (sigaction(sig, &sa, 0)) 34 + ksft_exit_fail_msg("sigaction failed"); 35 + } 36 + 37 + static inline void clearhandler(int sig) 38 + { 39 + struct sigaction sa; 40 + 41 + memset(&sa, 0, sizeof(sa)); 42 + sa.sa_handler = SIG_DFL; 43 + sigemptyset(&sa.sa_mask); 44 + if (sigaction(sig, &sa, 0)) 45 + ksft_exit_fail_msg("sigaction failed"); 28 46 } 29 47 30 48 #endif /* __SELFTESTS_X86_HELPERS_H */
+2 -23
tools/testing/selftests/x86/ioperm.c
··· 20 20 #include <sched.h> 21 21 #include <sys/io.h> 22 22 23 + #include "helpers.h" 24 + 23 25 static int nerrs = 0; 24 - 25 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 26 - int flags) 27 - { 28 - struct sigaction sa; 29 - memset(&sa, 0, sizeof(sa)); 30 - sa.sa_sigaction = handler; 31 - sa.sa_flags = SA_SIGINFO | flags; 32 - sigemptyset(&sa.sa_mask); 33 - if (sigaction(sig, &sa, 0)) 34 - err(1, "sigaction"); 35 - 36 - } 37 - 38 - static void clearhandler(int sig) 39 - { 40 - struct sigaction sa; 41 - memset(&sa, 0, sizeof(sa)); 42 - sa.sa_handler = SIG_DFL; 43 - sigemptyset(&sa.sa_mask); 44 - if (sigaction(sig, &sa, 0)) 45 - err(1, "sigaction"); 46 - } 47 26 48 27 static jmp_buf jmpbuf; 49 28
+2 -23
tools/testing/selftests/x86/iopl.c
··· 20 20 #include <sched.h> 21 21 #include <sys/io.h> 22 22 23 + #include "helpers.h" 24 + 23 25 static int nerrs = 0; 24 - 25 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 26 - int flags) 27 - { 28 - struct sigaction sa; 29 - memset(&sa, 0, sizeof(sa)); 30 - sa.sa_sigaction = handler; 31 - sa.sa_flags = SA_SIGINFO | flags; 32 - sigemptyset(&sa.sa_mask); 33 - if (sigaction(sig, &sa, 0)) 34 - err(1, "sigaction"); 35 - 36 - } 37 - 38 - static void clearhandler(int sig) 39 - { 40 - struct sigaction sa; 41 - memset(&sa, 0, sizeof(sa)); 42 - sa.sa_handler = SIG_DFL; 43 - sigemptyset(&sa.sa_mask); 44 - if (sigaction(sig, &sa, 0)) 45 - err(1, "sigaction"); 46 - } 47 26 48 27 static jmp_buf jmpbuf; 49 28
+4 -14
tools/testing/selftests/x86/ldt_gdt.c
··· 26 26 #include <asm/prctl.h> 27 27 #include <sys/prctl.h> 28 28 29 + #include "helpers.h" 30 + 29 31 #define AR_ACCESSED (1<<8) 30 32 31 33 #define AR_TYPE_RODATA (0 * (1<<9)) ··· 508 506 } 509 507 #endif 510 508 511 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 512 - int flags) 513 - { 514 - struct sigaction sa; 515 - memset(&sa, 0, sizeof(sa)); 516 - sa.sa_sigaction = handler; 517 - sa.sa_flags = SA_SIGINFO | flags; 518 - sigemptyset(&sa.sa_mask); 519 - if (sigaction(sig, &sa, 0)) 520 - err(1, "sigaction"); 521 - 522 - fix_sa_restorer(sig); 523 - } 524 - 525 509 static jmp_buf jmpbuf; 526 510 527 511 static void sigsegv(int sig, siginfo_t *info, void *ctx_void) ··· 537 549 } 538 550 539 551 sethandler(SIGSEGV, sigsegv, 0); 552 + fix_sa_restorer(SIGSEGV); 540 553 #ifdef __i386__ 541 554 /* True 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */ 542 555 sethandler(SIGILL, sigsegv, 0); 556 + fix_sa_restorer(SIGILL); 543 557 #endif 544 558 545 559 printf("[RUN]\tCross-CPU LDT invalidation\n");
+1 -13
tools/testing/selftests/x86/mov_ss_trap.c
··· 36 36 #include <setjmp.h> 37 37 #include <sys/prctl.h> 38 38 39 - #define X86_EFLAGS_RF (1UL << 16) 39 + #include "helpers.h" 40 40 41 41 #if __x86_64__ 42 42 # define REG_IP REG_RIP ··· 92 92 93 93 exit(0); 94 94 } 95 - } 96 - 97 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 98 - int flags) 99 - { 100 - struct sigaction sa; 101 - memset(&sa, 0, sizeof(sa)); 102 - sa.sa_sigaction = handler; 103 - sa.sa_flags = SA_SIGINFO | flags; 104 - sigemptyset(&sa.sa_mask); 105 - if (sigaction(sig, &sa, 0)) 106 - err(1, "sigaction"); 107 95 } 108 96 109 97 static char const * const signames[] = {
+2 -22
tools/testing/selftests/x86/ptrace_syscall.c
··· 15 15 #include <asm/ptrace-abi.h> 16 16 #include <sys/auxv.h> 17 17 18 + #include "helpers.h" 19 + 18 20 /* Bitness-agnostic defines for user_regs_struct fields. */ 19 21 #ifdef __x86_64__ 20 22 # define user_syscall_nr orig_rax ··· 95 93 return si; 96 94 } 97 95 98 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 99 - int flags) 100 - { 101 - struct sigaction sa; 102 - memset(&sa, 0, sizeof(sa)); 103 - sa.sa_sigaction = handler; 104 - sa.sa_flags = SA_SIGINFO | flags; 105 - sigemptyset(&sa.sa_mask); 106 - if (sigaction(sig, &sa, 0)) 107 - err(1, "sigaction"); 108 - } 109 - 110 96 static void setsigign(int sig, int flags) 111 97 { 112 98 struct sigaction sa; 113 99 memset(&sa, 0, sizeof(sa)); 114 100 sa.sa_sigaction = (void *)SIG_IGN; 115 101 sa.sa_flags = flags; 116 - sigemptyset(&sa.sa_mask); 117 - if (sigaction(sig, &sa, 0)) 118 - err(1, "sigaction"); 119 - } 120 - 121 - static void clearhandler(int sig) 122 - { 123 - struct sigaction sa; 124 - memset(&sa, 0, sizeof(sa)); 125 - sa.sa_handler = SIG_DFL; 126 102 sigemptyset(&sa.sa_mask); 127 103 if (sigaction(sig, &sa, 0)) 128 104 err(1, "sigaction");
+2 -24
tools/testing/selftests/x86/sigaltstack.c
··· 14 14 #include <sys/resource.h> 15 15 #include <setjmp.h> 16 16 17 + #include "helpers.h" 18 + 17 19 /* sigaltstack()-enforced minimum stack */ 18 20 #define ENFORCED_MINSIGSTKSZ 2048 19 21 ··· 28 26 static bool sigalrm_expected; 29 27 30 28 static unsigned long at_minstack_size; 31 - 32 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 33 - int flags) 34 - { 35 - struct sigaction sa; 36 - 37 - memset(&sa, 0, sizeof(sa)); 38 - sa.sa_sigaction = handler; 39 - sa.sa_flags = SA_SIGINFO | flags; 40 - sigemptyset(&sa.sa_mask); 41 - if (sigaction(sig, &sa, 0)) 42 - err(1, "sigaction"); 43 - } 44 - 45 - static void clearhandler(int sig) 46 - { 47 - struct sigaction sa; 48 - 49 - memset(&sa, 0, sizeof(sa)); 50 - sa.sa_handler = SIG_DFL; 51 - sigemptyset(&sa.sa_mask); 52 - if (sigaction(sig, &sa, 0)) 53 - err(1, "sigaction"); 54 - } 55 29 56 30 static int setup_altstack(void *start, unsigned long size) 57 31 {
+2 -22
tools/testing/selftests/x86/sigreturn.c
··· 46 46 #include <sys/ptrace.h> 47 47 #include <sys/user.h> 48 48 49 + #include "helpers.h" 50 + 49 51 /* Pull in AR_xyz defines. */ 50 52 typedef unsigned int u32; 51 53 typedef unsigned short u16; ··· 138 136 static unsigned short LDT3(int idx) 139 137 { 140 138 return (idx << 3) | 7; 141 - } 142 - 143 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 144 - int flags) 145 - { 146 - struct sigaction sa; 147 - memset(&sa, 0, sizeof(sa)); 148 - sa.sa_sigaction = handler; 149 - sa.sa_flags = SA_SIGINFO | flags; 150 - sigemptyset(&sa.sa_mask); 151 - if (sigaction(sig, &sa, 0)) 152 - err(1, "sigaction"); 153 - } 154 - 155 - static void clearhandler(int sig) 156 - { 157 - struct sigaction sa; 158 - memset(&sa, 0, sizeof(sa)); 159 - sa.sa_handler = SIG_DFL; 160 - sigemptyset(&sa.sa_mask); 161 - if (sigaction(sig, &sa, 0)) 162 - err(1, "sigaction"); 163 139 } 164 140 165 141 static void add_ldt(const struct user_desc *desc, unsigned short *var,
-22
tools/testing/selftests/x86/single_step_syscall.c
··· 33 33 34 34 #include "helpers.h" 35 35 36 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 37 - int flags) 38 - { 39 - struct sigaction sa; 40 - memset(&sa, 0, sizeof(sa)); 41 - sa.sa_sigaction = handler; 42 - sa.sa_flags = SA_SIGINFO | flags; 43 - sigemptyset(&sa.sa_mask); 44 - if (sigaction(sig, &sa, 0)) 45 - err(1, "sigaction"); 46 - } 47 - 48 - static void clearhandler(int sig) 49 - { 50 - struct sigaction sa; 51 - memset(&sa, 0, sizeof(sa)); 52 - sa.sa_handler = SIG_DFL; 53 - sigemptyset(&sa.sa_mask); 54 - if (sigaction(sig, &sa, 0)) 55 - err(1, "sigaction"); 56 - } 57 - 58 36 static volatile sig_atomic_t sig_traps, sig_eflags; 59 37 sigjmp_buf jmpbuf; 60 38
-12
tools/testing/selftests/x86/syscall_arg_fault.c
··· 17 17 18 18 #include "helpers.h" 19 19 20 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 21 - int flags) 22 - { 23 - struct sigaction sa; 24 - memset(&sa, 0, sizeof(sa)); 25 - sa.sa_sigaction = handler; 26 - sa.sa_flags = SA_SIGINFO | flags; 27 - sigemptyset(&sa.sa_mask); 28 - if (sigaction(sig, &sa, 0)) 29 - err(1, "sigaction"); 30 - } 31 - 32 20 static sigjmp_buf jmpbuf; 33 21 34 22 static volatile sig_atomic_t n_errs;
-12
tools/testing/selftests/x86/syscall_nt.c
··· 18 18 19 19 static unsigned int nerrs; 20 20 21 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 22 - int flags) 23 - { 24 - struct sigaction sa; 25 - memset(&sa, 0, sizeof(sa)); 26 - sa.sa_sigaction = handler; 27 - sa.sa_flags = SA_SIGINFO | flags; 28 - sigemptyset(&sa.sa_mask); 29 - if (sigaction(sig, &sa, 0)) 30 - err(1, "sigaction"); 31 - } 32 - 33 21 static void sigtrap(int sig, siginfo_t *si, void *ctx_void) 34 22 { 35 23 }
+2 -22
tools/testing/selftests/x86/sysret_rip.c
··· 22 22 #include <sys/mman.h> 23 23 #include <assert.h> 24 24 25 + #include "helpers.h" 26 + 25 27 /* 26 28 * These items are in clang_helpers_64.S, in order to avoid clang inline asm 27 29 * limitations: ··· 32 30 extern const char test_page[]; 33 31 34 32 static void const *current_test_page_addr = test_page; 35 - 36 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 37 - int flags) 38 - { 39 - struct sigaction sa; 40 - memset(&sa, 0, sizeof(sa)); 41 - sa.sa_sigaction = handler; 42 - sa.sa_flags = SA_SIGINFO | flags; 43 - sigemptyset(&sa.sa_mask); 44 - if (sigaction(sig, &sa, 0)) 45 - err(1, "sigaction"); 46 - } 47 - 48 - static void clearhandler(int sig) 49 - { 50 - struct sigaction sa; 51 - memset(&sa, 0, sizeof(sa)); 52 - sa.sa_handler = SIG_DFL; 53 - sigemptyset(&sa.sa_mask); 54 - if (sigaction(sig, &sa, 0)) 55 - err(1, "sigaction"); 56 - } 57 33 58 34 /* State used by our signal handlers. */ 59 35 static gregset_t initial_regs;
-13
tools/testing/selftests/x86/test_vsyscall.c
··· 310 310 static jmp_buf jmpbuf; 311 311 static volatile unsigned long segv_err; 312 312 313 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 314 - int flags) 315 - { 316 - struct sigaction sa; 317 - 318 - memset(&sa, 0, sizeof(sa)); 319 - sa.sa_sigaction = handler; 320 - sa.sa_flags = SA_SIGINFO | flags; 321 - sigemptyset(&sa.sa_mask); 322 - if (sigaction(sig, &sa, 0)) 323 - ksft_exit_fail_msg("sigaction failed\n"); 324 - } 325 - 326 313 static void sigsegv(int sig, siginfo_t *info, void *ctx_void) 327 314 { 328 315 ucontext_t *ctx = (ucontext_t *)ctx_void;
-12
tools/testing/selftests/x86/unwind_vdso.c
··· 43 43 #include <dlfcn.h> 44 44 #include <unwind.h> 45 45 46 - static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 47 - int flags) 48 - { 49 - struct sigaction sa; 50 - memset(&sa, 0, sizeof(sa)); 51 - sa.sa_sigaction = handler; 52 - sa.sa_flags = SA_SIGINFO | flags; 53 - sigemptyset(&sa.sa_mask); 54 - if (sigaction(sig, &sa, 0)) 55 - err(1, "sigaction"); 56 - } 57 - 58 46 static volatile sig_atomic_t nerrs; 59 47 static unsigned long sysinfo; 60 48 static bool got_sysinfo = false;
+477
tools/testing/selftests/x86/xstate.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #define _GNU_SOURCE 4 + 5 + #include <elf.h> 6 + #include <pthread.h> 7 + #include <stdbool.h> 8 + 9 + #include <asm/prctl.h> 10 + #include <sys/ptrace.h> 11 + #include <sys/syscall.h> 12 + #include <sys/uio.h> 13 + #include <sys/wait.h> 14 + 15 + #include "helpers.h" 16 + #include "xstate.h" 17 + 18 + /* 19 + * The userspace xstate test suite is designed to be generic and operates 20 + * with randomized xstate data. However, some states require special handling: 21 + * 22 + * - PKRU and XTILECFG need specific adjustments, such as modifying 23 + * randomization behavior or using fixed values. 24 + * - But, PKRU already has a dedicated test suite in /tools/selftests/mm. 25 + * - Legacy states (FP and SSE) are excluded, as they are not considered 26 + * part of extended states (xstates) and their usage is already deeply 27 + * integrated into user-space libraries. 28 + */ 29 + #define XFEATURE_MASK_TEST_SUPPORTED \ 30 + ((1 << XFEATURE_YMM) | \ 31 + (1 << XFEATURE_OPMASK) | \ 32 + (1 << XFEATURE_ZMM_Hi256) | \ 33 + (1 << XFEATURE_Hi16_ZMM) | \ 34 + (1 << XFEATURE_XTILEDATA)) 35 + 36 + static inline uint64_t xgetbv(uint32_t index) 37 + { 38 + uint32_t eax, edx; 39 + 40 + asm volatile("xgetbv" : "=a" (eax), "=d" (edx) : "c" (index)); 41 + return eax + ((uint64_t)edx << 32); 42 + } 43 + 44 + static inline uint64_t get_xstatebv(struct xsave_buffer *xbuf) 45 + { 46 + return *(uint64_t *)(&xbuf->header); 47 + } 48 + 49 + static struct xstate_info xstate; 50 + 51 + struct futex_info { 52 + unsigned int iterations; 53 + struct futex_info *next; 54 + pthread_mutex_t mutex; 55 + pthread_t thread; 56 + bool valid; 57 + int nr; 58 + }; 59 + 60 + static inline void load_rand_xstate(struct xstate_info *xstate, struct xsave_buffer *xbuf) 61 + { 62 + clear_xstate_header(xbuf); 63 + set_xstatebv(xbuf, xstate->mask); 64 + set_rand_data(xstate, xbuf); 65 + xrstor(xbuf, xstate->mask); 66 + } 67 + 68 + static inline void load_init_xstate(struct xstate_info *xstate, struct xsave_buffer *xbuf) 69 + { 70 + clear_xstate_header(xbuf); 71 + xrstor(xbuf, xstate->mask); 72 + } 73 + 74 + static inline void copy_xstate(struct xsave_buffer *xbuf_dst, struct xsave_buffer *xbuf_src) 75 + { 76 + memcpy(&xbuf_dst->bytes[xstate.xbuf_offset], 77 + &xbuf_src->bytes[xstate.xbuf_offset], 78 + xstate.size); 79 + } 80 + 81 + static inline bool validate_xstate_same(struct xsave_buffer *xbuf1, struct xsave_buffer *xbuf2) 82 + { 83 + int ret; 84 + 85 + ret = memcmp(&xbuf1->bytes[xstate.xbuf_offset], 86 + &xbuf2->bytes[xstate.xbuf_offset], 87 + xstate.size); 88 + return ret == 0; 89 + } 90 + 91 + static inline bool validate_xregs_same(struct xsave_buffer *xbuf1) 92 + { 93 + struct xsave_buffer *xbuf2; 94 + bool ret; 95 + 96 + xbuf2 = alloc_xbuf(); 97 + if (!xbuf2) 98 + ksft_exit_fail_msg("failed to allocate XSAVE buffer\n"); 99 + 100 + xsave(xbuf2, xstate.mask); 101 + ret = validate_xstate_same(xbuf1, xbuf2); 102 + 103 + free(xbuf2); 104 + return ret; 105 + } 106 + 107 + /* Context switching test */ 108 + 109 + static void *check_xstate(void *info) 110 + { 111 + struct futex_info *finfo = (struct futex_info *)info; 112 + struct xsave_buffer *xbuf; 113 + int i; 114 + 115 + xbuf = alloc_xbuf(); 116 + if (!xbuf) 117 + ksft_exit_fail_msg("unable to allocate XSAVE buffer\n"); 118 + 119 + /* 120 + * Load random data into 'xbuf' and then restore it to the xstate 121 + * registers. 122 + */ 123 + load_rand_xstate(&xstate, xbuf); 124 + finfo->valid = true; 125 + 126 + for (i = 0; i < finfo->iterations; i++) { 127 + pthread_mutex_lock(&finfo->mutex); 128 + 129 + /* 130 + * Ensure the register values have not diverged from the 131 + * record. Then reload a new random value. If it failed 132 + * ever before, skip it. 133 + */ 134 + if (finfo->valid) { 135 + finfo->valid = validate_xregs_same(xbuf); 136 + load_rand_xstate(&xstate, xbuf); 137 + } 138 + 139 + /* 140 + * The last thread's last unlock will be for thread 0's 141 + * mutex. However, thread 0 will have already exited the 142 + * loop and the mutex will already be unlocked. 143 + * 144 + * Because this is not an ERRORCHECK mutex, that 145 + * inconsistency will be silently ignored. 146 + */ 147 + pthread_mutex_unlock(&finfo->next->mutex); 148 + } 149 + 150 + free(xbuf); 151 + return finfo; 152 + } 153 + 154 + static void create_threads(uint32_t num_threads, uint32_t iterations, struct futex_info *finfo) 155 + { 156 + int i; 157 + 158 + for (i = 0; i < num_threads; i++) { 159 + int next_nr; 160 + 161 + finfo[i].nr = i; 162 + finfo[i].iterations = iterations; 163 + 164 + /* 165 + * Thread 'i' will wait on this mutex to be unlocked. 166 + * Lock it immediately after initialization: 167 + */ 168 + pthread_mutex_init(&finfo[i].mutex, NULL); 169 + pthread_mutex_lock(&finfo[i].mutex); 170 + 171 + next_nr = (i + 1) % num_threads; 172 + finfo[i].next = &finfo[next_nr]; 173 + 174 + if (pthread_create(&finfo[i].thread, NULL, check_xstate, &finfo[i])) 175 + ksft_exit_fail_msg("pthread_create() failed\n"); 176 + } 177 + } 178 + 179 + static bool checkout_threads(uint32_t num_threads, struct futex_info *finfo) 180 + { 181 + void *thread_retval; 182 + bool valid = true; 183 + int err, i; 184 + 185 + for (i = 0; i < num_threads; i++) { 186 + err = pthread_join(finfo[i].thread, &thread_retval); 187 + if (err) 188 + ksft_exit_fail_msg("pthread_join() failed for thread %d err: %d\n", i, err); 189 + 190 + if (thread_retval != &finfo[i]) { 191 + ksft_exit_fail_msg("unexpected thread retval for thread %d: %p\n", 192 + i, thread_retval); 193 + } 194 + 195 + valid &= finfo[i].valid; 196 + } 197 + 198 + return valid; 199 + } 200 + 201 + static void affinitize_cpu0(void) 202 + { 203 + cpu_set_t cpuset; 204 + 205 + CPU_ZERO(&cpuset); 206 + CPU_SET(0, &cpuset); 207 + 208 + if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) 209 + ksft_exit_fail_msg("sched_setaffinity to CPU 0 failed\n"); 210 + } 211 + 212 + static void test_context_switch(uint32_t num_threads, uint32_t iterations) 213 + { 214 + struct futex_info *finfo; 215 + 216 + /* Affinitize to one CPU to force context switches */ 217 + affinitize_cpu0(); 218 + 219 + printf("[RUN]\t%s: check context switches, %d iterations, %d threads.\n", 220 + xstate.name, iterations, num_threads); 221 + 222 + finfo = malloc(sizeof(*finfo) * num_threads); 223 + if (!finfo) 224 + ksft_exit_fail_msg("unable allocate memory\n"); 225 + 226 + create_threads(num_threads, iterations, finfo); 227 + 228 + /* 229 + * This thread wakes up thread 0 230 + * Thread 0 will wake up 1 231 + * Thread 1 will wake up 2 232 + * ... 233 + * The last thread will wake up 0 234 + * 235 + * This will repeat for the configured 236 + * number of iterations. 237 + */ 238 + pthread_mutex_unlock(&finfo[0].mutex); 239 + 240 + /* Wait for all the threads to finish: */ 241 + if (checkout_threads(num_threads, finfo)) 242 + printf("[OK]\tNo incorrect case was found.\n"); 243 + else 244 + printf("[FAIL]\tFailed with context switching test.\n"); 245 + 246 + free(finfo); 247 + } 248 + 249 + /* 250 + * Ptrace test for the ABI format as described in arch/x86/include/asm/user.h 251 + */ 252 + 253 + /* 254 + * Make sure the ptracee has the expanded kernel buffer on the first use. 255 + * Then, initialize the state before performing the state injection from 256 + * the ptracer. For non-dynamic states, this is benign. 257 + */ 258 + static inline void ptracee_touch_xstate(void) 259 + { 260 + struct xsave_buffer *xbuf; 261 + 262 + xbuf = alloc_xbuf(); 263 + 264 + load_rand_xstate(&xstate, xbuf); 265 + load_init_xstate(&xstate, xbuf); 266 + 267 + free(xbuf); 268 + } 269 + 270 + /* 271 + * Ptracer injects the randomized xstate data. It also reads before and 272 + * after that, which will execute the kernel's state copy functions. 273 + */ 274 + static void ptracer_inject_xstate(pid_t target) 275 + { 276 + uint32_t xbuf_size = get_xbuf_size(); 277 + struct xsave_buffer *xbuf1, *xbuf2; 278 + struct iovec iov; 279 + 280 + /* 281 + * Allocate buffers to keep data while ptracer can write the 282 + * other buffer 283 + */ 284 + xbuf1 = alloc_xbuf(); 285 + xbuf2 = alloc_xbuf(); 286 + if (!xbuf1 || !xbuf2) 287 + ksft_exit_fail_msg("unable to allocate XSAVE buffer\n"); 288 + 289 + iov.iov_base = xbuf1; 290 + iov.iov_len = xbuf_size; 291 + 292 + if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 293 + ksft_exit_fail_msg("PTRACE_GETREGSET failed\n"); 294 + 295 + printf("[RUN]\t%s: inject xstate via ptrace().\n", xstate.name); 296 + 297 + load_rand_xstate(&xstate, xbuf1); 298 + copy_xstate(xbuf2, xbuf1); 299 + 300 + if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 301 + ksft_exit_fail_msg("PTRACE_SETREGSET failed\n"); 302 + 303 + if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 304 + ksft_exit_fail_msg("PTRACE_GETREGSET failed\n"); 305 + 306 + if (*(uint64_t *)get_fpx_sw_bytes(xbuf1) == xgetbv(0)) 307 + printf("[OK]\t'xfeatures' in SW reserved area was correctly written\n"); 308 + else 309 + printf("[FAIL]\t'xfeatures' in SW reserved area was not correctly written\n"); 310 + 311 + if (validate_xstate_same(xbuf2, xbuf1)) 312 + printf("[OK]\txstate was correctly updated.\n"); 313 + else 314 + printf("[FAIL]\txstate was not correctly updated.\n"); 315 + 316 + free(xbuf1); 317 + free(xbuf2); 318 + } 319 + 320 + static void test_ptrace(void) 321 + { 322 + pid_t child; 323 + int status; 324 + 325 + child = fork(); 326 + if (child < 0) { 327 + ksft_exit_fail_msg("fork() failed\n"); 328 + } else if (!child) { 329 + if (ptrace(PTRACE_TRACEME, 0, NULL, NULL)) 330 + ksft_exit_fail_msg("PTRACE_TRACEME failed\n"); 331 + 332 + ptracee_touch_xstate(); 333 + 334 + raise(SIGTRAP); 335 + _exit(0); 336 + } 337 + 338 + do { 339 + wait(&status); 340 + } while (WSTOPSIG(status) != SIGTRAP); 341 + 342 + ptracer_inject_xstate(child); 343 + 344 + ptrace(PTRACE_DETACH, child, NULL, NULL); 345 + wait(&status); 346 + if (!WIFEXITED(status) || WEXITSTATUS(status)) 347 + ksft_exit_fail_msg("ptracee exit error\n"); 348 + } 349 + 350 + /* 351 + * Test signal delivery for the ABI compatibility. 352 + * See the ABI format: arch/x86/include/uapi/asm/sigcontext.h 353 + */ 354 + 355 + /* 356 + * Avoid using printf() in signal handlers as it is not 357 + * async-signal-safe. 358 + */ 359 + #define SIGNAL_BUF_LEN 1000 360 + static char signal_message_buffer[SIGNAL_BUF_LEN]; 361 + static void sig_print(char *msg) 362 + { 363 + int left = SIGNAL_BUF_LEN - strlen(signal_message_buffer) - 1; 364 + 365 + strncat(signal_message_buffer, msg, left); 366 + } 367 + 368 + static struct xsave_buffer *stashed_xbuf; 369 + 370 + static void validate_sigfpstate(int sig, siginfo_t *si, void *ctx_void) 371 + { 372 + ucontext_t *ctx = (ucontext_t *)ctx_void; 373 + void *xbuf = ctx->uc_mcontext.fpregs; 374 + struct _fpx_sw_bytes *sw_bytes; 375 + uint32_t magic2; 376 + 377 + /* Reset the signal message buffer: */ 378 + signal_message_buffer[0] = '\0'; 379 + 380 + sw_bytes = get_fpx_sw_bytes(xbuf); 381 + if (sw_bytes->magic1 == FP_XSTATE_MAGIC1) 382 + sig_print("[OK]\t'magic1' is valid\n"); 383 + else 384 + sig_print("[FAIL]\t'magic1' is not valid\n"); 385 + 386 + if (get_fpx_sw_bytes_features(xbuf) & xstate.mask) 387 + sig_print("[OK]\t'xfeatures' in SW reserved area is valid\n"); 388 + else 389 + sig_print("[FAIL]\t'xfeatures' in SW reserved area is not valid\n"); 390 + 391 + if (get_xstatebv(xbuf) & xstate.mask) 392 + sig_print("[OK]\t'xfeatures' in XSAVE header is valid\n"); 393 + else 394 + sig_print("[FAIL]\t'xfeatures' in XSAVE header is not valid\n"); 395 + 396 + if (validate_xstate_same(stashed_xbuf, xbuf)) 397 + sig_print("[OK]\txstate delivery was successful\n"); 398 + else 399 + sig_print("[FAIL]\txstate delivery was not successful\n"); 400 + 401 + magic2 = *(uint32_t *)(xbuf + sw_bytes->xstate_size); 402 + if (magic2 == FP_XSTATE_MAGIC2) 403 + sig_print("[OK]\t'magic2' is valid\n"); 404 + else 405 + sig_print("[FAIL]\t'magic2' is not valid\n"); 406 + 407 + set_rand_data(&xstate, xbuf); 408 + copy_xstate(stashed_xbuf, xbuf); 409 + } 410 + 411 + static void test_signal(void) 412 + { 413 + bool valid_xstate; 414 + 415 + /* 416 + * The signal handler will access this to verify xstate context 417 + * preservation. 418 + */ 419 + stashed_xbuf = alloc_xbuf(); 420 + if (!stashed_xbuf) 421 + ksft_exit_fail_msg("unable to allocate XSAVE buffer\n"); 422 + 423 + printf("[RUN]\t%s: load xstate and raise SIGUSR1\n", xstate.name); 424 + 425 + sethandler(SIGUSR1, validate_sigfpstate, 0); 426 + 427 + load_rand_xstate(&xstate, stashed_xbuf); 428 + 429 + raise(SIGUSR1); 430 + 431 + /* 432 + * Immediately record the test result, deferring printf() to 433 + * prevent unintended state contamination by that. 434 + */ 435 + valid_xstate = validate_xregs_same(stashed_xbuf); 436 + printf("%s", signal_message_buffer); 437 + 438 + printf("[RUN]\t%s: load new xstate from sighandler and check it after sigreturn\n", 439 + xstate.name); 440 + 441 + if (valid_xstate) 442 + printf("[OK]\txstate was restored correctly\n"); 443 + else 444 + printf("[FAIL]\txstate restoration failed\n"); 445 + 446 + clearhandler(SIGUSR1); 447 + free(stashed_xbuf); 448 + } 449 + 450 + void test_xstate(uint32_t feature_num) 451 + { 452 + const unsigned int ctxtsw_num_threads = 5, ctxtsw_iterations = 10; 453 + unsigned long features; 454 + long rc; 455 + 456 + if (!(XFEATURE_MASK_TEST_SUPPORTED & (1 << feature_num))) { 457 + ksft_print_msg("The xstate test does not fully support the component %u, yet.\n", 458 + feature_num); 459 + return; 460 + } 461 + 462 + rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_SUPP, &features); 463 + if (rc || !(features & (1 << feature_num))) { 464 + ksft_print_msg("The kernel does not support feature number: %u\n", feature_num); 465 + return; 466 + } 467 + 468 + xstate = get_xstate_info(feature_num); 469 + if (!xstate.size || !xstate.xbuf_offset) { 470 + ksft_exit_fail_msg("invalid state size/offset (%d/%d)\n", 471 + xstate.size, xstate.xbuf_offset); 472 + } 473 + 474 + test_context_switch(ctxtsw_num_threads, ctxtsw_iterations); 475 + test_ptrace(); 476 + test_signal(); 477 + }
+195
tools/testing/selftests/x86/xstate.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #ifndef __SELFTESTS_X86_XSTATE_H 3 + #define __SELFTESTS_X86_XSTATE_H 4 + 5 + #include <stdint.h> 6 + 7 + #include "../kselftest.h" 8 + 9 + #define XSAVE_HDR_OFFSET 512 10 + #define XSAVE_HDR_SIZE 64 11 + 12 + /* 13 + * List of XSAVE features Linux knows about. Copied from 14 + * arch/x86/include/asm/fpu/types.h 15 + */ 16 + enum xfeature { 17 + XFEATURE_FP, 18 + XFEATURE_SSE, 19 + XFEATURE_YMM, 20 + XFEATURE_BNDREGS, 21 + XFEATURE_BNDCSR, 22 + XFEATURE_OPMASK, 23 + XFEATURE_ZMM_Hi256, 24 + XFEATURE_Hi16_ZMM, 25 + XFEATURE_PT_UNIMPLEMENTED_SO_FAR, 26 + XFEATURE_PKRU, 27 + XFEATURE_PASID, 28 + XFEATURE_CET_USER, 29 + XFEATURE_CET_KERNEL_UNUSED, 30 + XFEATURE_RSRVD_COMP_13, 31 + XFEATURE_RSRVD_COMP_14, 32 + XFEATURE_LBR, 33 + XFEATURE_RSRVD_COMP_16, 34 + XFEATURE_XTILECFG, 35 + XFEATURE_XTILEDATA, 36 + 37 + XFEATURE_MAX, 38 + }; 39 + 40 + /* Copied from arch/x86/kernel/fpu/xstate.c */ 41 + static const char *xfeature_names[] = 42 + { 43 + "x87 floating point registers", 44 + "SSE registers", 45 + "AVX registers", 46 + "MPX bounds registers", 47 + "MPX CSR", 48 + "AVX-512 opmask", 49 + "AVX-512 Hi256", 50 + "AVX-512 ZMM_Hi256", 51 + "Processor Trace (unused)", 52 + "Protection Keys User registers", 53 + "PASID state", 54 + "Control-flow User registers", 55 + "Control-flow Kernel registers (unused)", 56 + "unknown xstate feature", 57 + "unknown xstate feature", 58 + "unknown xstate feature", 59 + "unknown xstate feature", 60 + "AMX Tile config", 61 + "AMX Tile data", 62 + "unknown xstate feature", 63 + }; 64 + 65 + struct xsave_buffer { 66 + union { 67 + struct { 68 + char legacy[XSAVE_HDR_OFFSET]; 69 + char header[XSAVE_HDR_SIZE]; 70 + char extended[0]; 71 + }; 72 + char bytes[0]; 73 + }; 74 + }; 75 + 76 + static inline void xsave(struct xsave_buffer *xbuf, uint64_t rfbm) 77 + { 78 + uint32_t rfbm_hi = rfbm >> 32; 79 + uint32_t rfbm_lo = rfbm; 80 + 81 + asm volatile("xsave (%%rdi)" 82 + : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi) 83 + : "memory"); 84 + } 85 + 86 + static inline void xrstor(struct xsave_buffer *xbuf, uint64_t rfbm) 87 + { 88 + uint32_t rfbm_hi = rfbm >> 32; 89 + uint32_t rfbm_lo = rfbm; 90 + 91 + asm volatile("xrstor (%%rdi)" 92 + : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi)); 93 + } 94 + 95 + #define CPUID_LEAF_XSTATE 0xd 96 + #define CPUID_SUBLEAF_XSTATE_USER 0x0 97 + 98 + static inline uint32_t get_xbuf_size(void) 99 + { 100 + uint32_t eax, ebx, ecx, edx; 101 + 102 + __cpuid_count(CPUID_LEAF_XSTATE, CPUID_SUBLEAF_XSTATE_USER, 103 + eax, ebx, ecx, edx); 104 + 105 + /* 106 + * EBX enumerates the size (in bytes) required by the XSAVE 107 + * instruction for an XSAVE area containing all the user state 108 + * components corresponding to bits currently set in XCR0. 109 + */ 110 + return ebx; 111 + } 112 + 113 + struct xstate_info { 114 + const char *name; 115 + uint32_t num; 116 + uint32_t mask; 117 + uint32_t xbuf_offset; 118 + uint32_t size; 119 + }; 120 + 121 + static inline struct xstate_info get_xstate_info(uint32_t xfeature_num) 122 + { 123 + struct xstate_info xstate = { }; 124 + uint32_t eax, ebx, ecx, edx; 125 + 126 + if (xfeature_num >= XFEATURE_MAX) { 127 + ksft_print_msg("unknown state\n"); 128 + return xstate; 129 + } 130 + 131 + xstate.name = xfeature_names[xfeature_num]; 132 + xstate.num = xfeature_num; 133 + xstate.mask = 1 << xfeature_num; 134 + 135 + __cpuid_count(CPUID_LEAF_XSTATE, xfeature_num, 136 + eax, ebx, ecx, edx); 137 + xstate.size = eax; 138 + xstate.xbuf_offset = ebx; 139 + return xstate; 140 + } 141 + 142 + static inline struct xsave_buffer *alloc_xbuf(void) 143 + { 144 + uint32_t xbuf_size = get_xbuf_size(); 145 + 146 + /* XSAVE buffer should be 64B-aligned. */ 147 + return aligned_alloc(64, xbuf_size); 148 + } 149 + 150 + static inline void clear_xstate_header(struct xsave_buffer *xbuf) 151 + { 152 + memset(&xbuf->header, 0, sizeof(xbuf->header)); 153 + } 154 + 155 + static inline void set_xstatebv(struct xsave_buffer *xbuf, uint64_t bv) 156 + { 157 + /* XSTATE_BV is at the beginning of the header: */ 158 + *(uint64_t *)(&xbuf->header) = bv; 159 + } 160 + 161 + /* See 'struct _fpx_sw_bytes' at sigcontext.h */ 162 + #define SW_BYTES_OFFSET 464 163 + /* N.B. The struct's field name varies so read from the offset. */ 164 + #define SW_BYTES_BV_OFFSET (SW_BYTES_OFFSET + 8) 165 + 166 + static inline struct _fpx_sw_bytes *get_fpx_sw_bytes(void *xbuf) 167 + { 168 + return xbuf + SW_BYTES_OFFSET; 169 + } 170 + 171 + static inline uint64_t get_fpx_sw_bytes_features(void *buffer) 172 + { 173 + return *(uint64_t *)(buffer + SW_BYTES_BV_OFFSET); 174 + } 175 + 176 + static inline void set_rand_data(struct xstate_info *xstate, struct xsave_buffer *xbuf) 177 + { 178 + int *ptr = (int *)&xbuf->bytes[xstate->xbuf_offset]; 179 + int data, i; 180 + 181 + /* 182 + * Ensure that 'data' is never 0. This ensures that 183 + * the registers are never in their initial configuration 184 + * and thus never tracked as being in the init state. 185 + */ 186 + data = rand() | 1; 187 + 188 + for (i = 0; i < xstate->size / sizeof(int); i++, ptr++) 189 + *ptr = data; 190 + } 191 + 192 + /* Testing kernel's context switching and ABI support for the xstate. */ 193 + void test_xstate(uint32_t feature_num); 194 + 195 + #endif /* __SELFTESTS_X86_XSTATE_H */