From nobody Mon Jun 8 08:28:15 2026 Received: from mail-oa1-f74.google.com (mail-oa1-f74.google.com [209.85.160.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 605533BB137 for ; Thu, 4 Jun 2026 16:56:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592170; cv=none; b=oyYSqqznQDTKvdllET13nIBpRbEBpUClFPAq22GXjHr5BNCoV2XsKERgSsfkixS2NYgVyhSxnS4EgTlL3BYNAVCbcrzmWCARExL1pnWoesevZD71r0sOEbjFC8OCR46CYboopu/ZjqOyAQc4/2g7lrkimcBmIRTMCiI+nrTE7+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592170; c=relaxed/simple; bh=zuGm+jxkgkHLeYqh7Gpp9Ch3gQZ2CrWlMTyi/nk7w3A=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=j/cF9cbQlYT3gII+viqnLamZ56mXHZ0LFM6+jxgA77SR9pUp0kWnfNTY/FFKUjuXfwqKb2tiojOUtPAbtiEpHsPTUvynfdZg7eoI9+C4BisQKyjK921HfvbbEesLcCX4nqOP3rt411hpJnBE7zwn9h+U+ma85H/kMNcLIv4saU4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=lWmNtRPP; arc=none smtp.client-ip=209.85.160.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lWmNtRPP" Received: by mail-oa1-f74.google.com with SMTP id 586e51a60fabf-43b7d6f0d56so1673588fac.1 for ; Thu, 04 Jun 2026 09:56:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780592168; x=1781196968; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=oSTVTd68WYWQa6bAmVGofgnqCH1CzDL35zyzdNCR4wA=; b=lWmNtRPPDkAv/u9oXiSkGTAu965S+TCwJawXvzAN64aityXnIdfGcJBru+kAEMI94n eG3D5jaoWlJt9zq5qOFZKcWe9WLI+Xg/VmWLjtLYJOA/YiBac4Ecv0DQ6IqA1PLeAR0a 5jR+JXAjgJYfMxPejpaa/THZiz4ieezyL5NulZFUOwcuTqzU2L8KGe/Jui8uIl1icu72 LuJc99eUoD1567vFZQthp/I/l1cuoyxf8ct5jIY7q07dABNQhApVMw/XaMLocyXBmzNn tzS4ebmvE4wV7tEBcEyotK701vBBETrzPeNa8x56gu+D4ph3kout8yAypjXgkPsqL6DM Svzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780592168; x=1781196968; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=oSTVTd68WYWQa6bAmVGofgnqCH1CzDL35zyzdNCR4wA=; b=Ayeg2giC3hxT4JPJzYJbqvn+w/NaBQJkoVT4sivQlYxk1ujmDilRj9epuzSuddqT7f kp0JqlXGvrIfSLq25iZA4pgqokEJVkID4DPwptmR8weigRuvmKZlSfDrbkXW4Wz6mFch rypQ0/jOWXzE75qounAxbxT69CkygGc/mwrYq/c5ES9KOKUG29TJuDU7hA2eKD/plGGu 6CAEV0//zYrsgOjoaqXIAZ0kWQ5/e7VQOhgEUq4SvU8ePxyLqdxzD4I3C5csjQMxEP0M vX7dydzX3AKZvqWVf9SfgEhSFilaen5OxIS3+1/jIrs1MLSdzrnVzmqtFqmsTDVVjoK8 D1NQ== X-Gm-Message-State: AOJu0Yzfg9MaL4vLdJD59m803GJ3Wqlba88eeLzBgWkmRLR8S4H2LjJ4 IgRmfPQ4ocMc+gEvKh2Pxke00CDOz09H5riKZqbUe+WXif90U6S8eFXoBAId+TfTYUppKTeIZad MF5uRrg== X-Received: from jalt16.prod.google.com ([2002:a05:6638:3490:b0:5e2:99fa:da7b]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a4a:dd05:0:b0:69d:a652:216b with SMTP id 006d021491bc7-69e480dad68mr3571037eaf.60.1780592168106; Thu, 04 Jun 2026 09:56:08 -0700 (PDT) Date: Thu, 4 Jun 2026 16:56:01 +0000 In-Reply-To: <20260604165604.1195243-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260604165604.1195243-1-avagin@google.com> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog Message-ID: <20260604165604.1195243-2-avagin@google.com> Subject: [PATCH 1/4] x86/fpu: Document signal frame portability From: Andrei Vagin To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , "Chang S. Bae" Cc: linux-kernel@vger.kernel.org, criu@lists.linux.dev, Dave Hansen , x86@kernel.org, Andrei Vagin , "H. Peter Anvin" Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The x86 signal frame is designed to be self-describing, with the 'xstate_size' field in the software-reserved bytes indicating the actual size of the context. This design is required for portability, allowing a signal frame created on a system with a specific set of xstate features to be restored on a machine with a different (larger) set of features. Document this contract in the uabi headers and Documentation/. This requirement is critical for checkpoint/restore tools like CRIU, which should be able to migrate processes across machines with heterogeneous FPU capabilities. Note that portability is generally limited to CPUs from the same vendor (e.g., Intel vs. AMD) due to potential differences in xstate layouts. Signed-off-by: Andrei Vagin --- Documentation/arch/x86/xstate.rst | 14 ++++++++++++-- arch/x86/include/uapi/asm/sigcontext.h | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Documentation/arch/x86/xstate.rst b/Documentation/arch/x86/xst= ate.rst index cec05ac464c1..e27e779bae44 100644 --- a/Documentation/arch/x86/xstate.rst +++ b/Documentation/arch/x86/xstate.rst @@ -170,5 +170,15 @@ are extended to control the guest permission: is going to be rejected. So, the permission has to be requested before the first VCPU creation. =20 -Note that some VMMs may have already established a set of supported state -components. These options are not presumed to support any particular VMM. +Signal Frame Portability +------------------------ + +The signal frame is designed to be self-describing and portable. This is +especially important for checkpoint/restore tools like CRIU, which may res= tore +a process on a different host than where it was checkpointed. A signal fra= me +created on a machine with fewer CPU features can be successfully restored = on a +machine with more CPU features. + +Note that signal frame portability is generally guaranteed only between CP= Us +from the same vendor. Different vendors may use different offsets for the = same +xstate features in the xsave area, making frames incompatible between them. diff --git a/arch/x86/include/uapi/asm/sigcontext.h b/arch/x86/include/uapi= /asm/sigcontext.h index d0d9b331d3a1..3ea63c29c3d7 100644 --- a/arch/x86/include/uapi/asm/sigcontext.h +++ b/arch/x86/include/uapi/asm/sigcontext.h @@ -34,6 +34,16 @@ * fpstate+extended_size-FP_XSTATE_MAGIC2_SIZE address) is set to * FP_XSTATE_MAGIC2 so that you can sanity check your size calculations.) * + * The xstate_size field indicates the actual size of the xstate context + * (including the fxregs_state and xstate_header). This size is used in + * conjunction with the fpstate pointer to locate FP_XSTATE_MAGIC2. This = makes + * the signal frame self-describing and portable: a signal frame created o= n a + * machine with a certain set of xstate features can be restored on a mach= ine + * with a different (larger) set of features, as long as the latter suppor= ts + * all features present in the frame. Note that this portability is genera= lly + * limited to CPUs of the same vendor, as different vendors may use differ= ent + * xstate layouts. + * * This extended area typically grows with newer CPUs that have larger and * larger XSAVE areas. */ --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 08:28:15 2026 Received: from mail-oi1-f201.google.com (mail-oi1-f201.google.com [209.85.167.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 741C84949E4 for ; Thu, 4 Jun 2026 16:56:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592173; cv=none; b=k4gSxSCJTz9a+y4Oxyjk70gdGDGrePjF02hMNv4ZW5clC1C8yL1cU+olZIdv5pyjaLT/rPYpOqxVGFWe0JW14xAFqsUNMBO6uVP0TQj9hw1dhKgDl3muAhDZtR3I8fMTFP/oyp/ubkW5MGoJJiJYPLpRp8NiknM/BzZuPjOfNYM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592173; c=relaxed/simple; bh=ekigQyV/jQI92pR236pyinuAEASB8wnGlmIyLrBVUmg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=qSQnYSj5LY7Q3GuI/ma6rfXzjEAT/P7U9NlvIEQBSOq5XO1EWyPZl5996AMutNcI+QP1ShaR4xlf+u062H+6HWWuvAUcW7ZIV3sKWTlj4ND8ZsjSDS0o/Qnq8o7q2eOzv8YfBobwtFDqG4cNQ27DKzAbtnHYapp3aBWsIjfvcLc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=QapgBZmu; arc=none smtp.client-ip=209.85.167.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="QapgBZmu" Received: by mail-oi1-f201.google.com with SMTP id 5614622812f47-48687e7f161so603092b6e.2 for ; Thu, 04 Jun 2026 09:56:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780592169; x=1781196969; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KPEnqE/zE0ic5HdWxS6IoJSQzA2QtUrz99Wvcf3heHQ=; b=QapgBZmuAcN8k5aAC3SgJPmoiaexIq8VOnJYYjtE/W25ke+YCv6LYDXZKTnT+6QqCb iXtEPnH9OCoapXQ27algJcOBvyEsUZQw1gocSJZuyKDDc+JxahQ/a48LPL5GhKDsyyd0 FOEPrWXuc3Zivor2RAd1pPyRigvAuHNJ7W/x2hAASXG1TvL10Ay69/BLWG6jXY7X91pe 5MOac4GHdD7Isco1J1HNwIF2hdhEiZYJPltxhjBi6mznAgB+tpsglUkZ1YRn4m10wlQh 4PlNQHH+m0kIAo9sz5VNaUzTfKTS3IX319e2xh+ehAqIuvB8Ylapcy//KDoZM8NcjGFa QHhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780592169; x=1781196969; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KPEnqE/zE0ic5HdWxS6IoJSQzA2QtUrz99Wvcf3heHQ=; b=h3BOkbmxKRsKeXRCZ/6t6fLhLDp9KJ0CD3+VZE2Yx8r53Je+7Kh+FGS2J1Xwddmjbe XYQNcXbOn+Y1O/AziGVekV771H7SH1tzSySBF68XG20CnNWEjqhssqRJ/xI5y7N+6Gs0 mMRrmqK33xGWpucuF3ihzreL7m8CU0LSB68lJWxhAPnTdqc8YzOMBwTw9SBUGWEKR0gx kT+ck93jXmwBVJ/2x4CExx+vwb55bE405DbM7ZQ+VBmXnbsamIhrtwfR57bX5p5UVf4d 4zEHOMQAoluE14J2wkNgXtGocfk4Ugy2Pelq/MG/ciWM1PCj5zz18cJ7gLcVgBISZN3v pDCw== X-Gm-Message-State: AOJu0YwFs5Qg1HGew4ogg+EQwxf47ARyfUfMS4hqDZoq9MIgWih1bBje 1lkab7uFNjXuBNUY9kElDtGUobVSGEm5HiDfDCcmRgrjO/3N0ahvXPsNP2U6SZRW9FlApxsD9DR S/7jD3w== X-Received: from iodf20.prod.google.com ([2002:a05:6602:62d4:b0:963:c1c8:da0e]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a4a:d017:0:b0:694:8c67:5cb6 with SMTP id 006d021491bc7-69e48093670mr4111052eaf.41.1780592169187; Thu, 04 Jun 2026 09:56:09 -0700 (PDT) Date: Thu, 4 Jun 2026 16:56:02 +0000 In-Reply-To: <20260604165604.1195243-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260604165604.1195243-1-avagin@google.com> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog Message-ID: <20260604165604.1195243-3-avagin@google.com> Subject: [PATCH 2/4] selftests/x86: Add a test for signal frame portability From: Andrei Vagin To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , "Chang S. Bae" Cc: linux-kernel@vger.kernel.org, criu@lists.linux.dev, Dave Hansen , x86@kernel.org, Andrei Vagin , "H. Peter Anvin" Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new selftest tools/testing/selftests/x86/sigframe_portability.c that verifies that the kernel correctly restores the xstate context even if the frame size has been manually reduced, as long as the FP_XSTATE_MAGIC2 marker is correctly placed at the end of the specified xstate_size. This test simulates a scenario where a signal frame is created on a system with fewer xstate features and restored on a system with more features. Signed-off-by: Andrei Vagin --- tools/testing/selftests/x86/Makefile | 5 +- .../selftests/x86/sigframe_portability.c | 156 ++++++++++++++++++ tools/testing/selftests/x86/xstate.c | 5 - tools/testing/selftests/x86/xstate.h | 12 ++ 4 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 tools/testing/selftests/x86/sigframe_portability.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests= /x86/Makefile index 434065215d12..bd59ee3df61d 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -19,7 +19,8 @@ TARGETS_C_32BIT_ONLY :=3D entry_from_vm86 test_syscall_vd= so unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer TARGETS_C_64BIT_ONLY :=3D fsgsbase sysret_rip syscall_numbering \ - corrupt_xstate_header amx lam test_shadow_stack avx apx + corrupt_xstate_header amx lam test_shadow_stack avx apx \ + sigframe_portability # Some selftests require 32bit support enabled also on 64bit systems TARGETS_C_32BIT_NEEDED :=3D ldt_gdt ptrace_syscall =20 @@ -138,3 +139,5 @@ $(OUTPUT)/avx_64: CFLAGS +=3D -mno-avx -mno-avx512f $(OUTPUT)/amx_64: EXTRA_FILES +=3D xstate.c $(OUTPUT)/avx_64: EXTRA_FILES +=3D xstate.c $(OUTPUT)/apx_64: EXTRA_FILES +=3D xstate.c + +$(OUTPUT)/sigframe_portability_64: CFLAGS +=3D -mno-avx -mno-avx512f diff --git a/tools/testing/selftests/x86/sigframe_portability.c b/tools/tes= ting/selftests/x86/sigframe_portability.c new file mode 100644 index 000000000000..54ba182a792f --- /dev/null +++ b/tools/testing/selftests/x86/sigframe_portability.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0-only +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "xstate.h" + +/* + * This test verifies the portability of the signal frame. + * It simulates a scenario where a signal frame is created on a system with + * fewer xstate features and restored on a system with more features. + */ + +#define SIGFRAME_XSTATE_HDR_OFFSET 512 + +#define XSTATE_SSE_ONLY_SIZE (SIGFRAME_XSTATE_HDR_OFFSET + XSAVE_HDR_SIZE) +#define XFEATURE_MASK_FPSSE ((1 << XFEATURE_FP) | (1 << XFEATURE_SSE)) + +static uint32_t ymm_offset; +static uint32_t xstate_size_ymm; + +/* + * Avoid using printf() in signal handlers as it is not + * async-signal-safe. + */ +#define SIGNAL_BUF_LEN 1024 +static char sig_err_buf[SIGNAL_BUF_LEN]; + +static void sig_print(const char *msg) +{ + int left =3D SIGNAL_BUF_LEN - strlen(sig_err_buf) - 1; + + strncat(sig_err_buf, msg, left); +} + +static void check_avx_support(void) +{ + struct xstate_info xstate; + unsigned long features; + long rc; + + /* + * Check if the kernel supports AVX (XFEATURE_YMM). + * This also confirms that the OS has enabled XSAVE. + */ + rc =3D syscall(SYS_arch_prctl, ARCH_GET_XCOMP_SUPP, &features); + if (rc !=3D 0) + ksft_exit_skip("ARCH_GET_XCOMP_SUPP not supported\n"); + + if (!(features & (1 << XFEATURE_YMM))) + ksft_exit_skip("AVX not supported by kernel/hardware\n"); + + xstate =3D get_xstate_info(XFEATURE_YMM); + if (!xstate.size) + ksft_exit_skip("AVX not supported by hardware\n"); + + ymm_offset =3D xstate.xbuf_offset; + xstate_size_ymm =3D xstate.xbuf_offset + xstate.size; +} + +#define TEST_YMMH_VAL (0x5656565656565656UL) + +__attribute__((target("avx"))) +static void read_ymm0(uint64_t *v) +{ + asm volatile ("vmovdqu %%ymm0, %0" : "=3Dm" (*(char (*)[32])v)); +} + +__attribute__((target("avx"))) +static void write_ymm0(uint64_t *v) +{ + asm volatile ("vmovdqu %0, %%ymm0" : : "m" (*(char (*)[32])v)); +} + + +static void handle_signal(int sig, siginfo_t *si, void *ucp) +{ + ucontext_t *uc =3D ucp; + void *fp =3D uc->uc_mcontext.fpregs; + struct _fpx_sw_bytes *sw =3D get_fpx_sw_bytes(fp); + struct xsave_buffer *xbuf; + uint64_t xfeatures, *ymmh_p; + + if (sw->magic1 !=3D FP_XSTATE_MAGIC1) { + sig_print("magic1 is not valid\n"); + return; + } + + xbuf =3D (struct xsave_buffer *)fp; + + /* Shrink the frame to just YMM size */ + sw->xstate_size =3D xstate_size_ymm; + + xfeatures =3D get_xstatebv(xbuf); + xfeatures &=3D XFEATURE_MASK_FPSSE | (1 << XFEATURE_YMM); + set_xstatebv(xbuf, xfeatures); + /* Also update sw->xfeatures as the kernel relies on it */ + set_fpx_sw_bytes_features(fp, xfeatures); + + *(uint32_t *)(fp + sw->xstate_size) =3D FP_XSTATE_MAGIC2; + + ymmh_p =3D (uint64_t *)(fp + ymm_offset); + ymmh_p[0] =3D TEST_YMMH_VAL; + ymmh_p[1] =3D TEST_YMMH_VAL+1; + + /* clear everything after MAGIC2. */ + if (sw->xstate_size + 4 < sw->extended_size) + memset(fp + sw->xstate_size + 4, 0, sw->extended_size - sw->xstate_size = - 4); +} + +int main(void) +{ + uint64_t v[4] =3D {0, 0, 0, 0}; + + ksft_print_header(); + ksft_set_plan(1); + + check_avx_support(); + + sethandler(SIGUSR1, handle_signal, 0); + + v[0] =3D 0x1111111111111111ULL; + v[1] =3D 0x2222222222222222ULL; + v[2] =3D 0x3333333333333333ULL; + v[3] =3D 0x4444444444444444ULL; + write_ymm0(v); + + raise(SIGUSR1); + v[0] =3D v[1] =3D v[2] =3D v[3] =3D 0; + read_ymm0(v); + + if (sig_err_buf[0]) + ksft_test_result_fail("%s\n", sig_err_buf); + else if (v[2] =3D=3D TEST_YMMH_VAL && v[3] =3D=3D (TEST_YMMH_VAL + 1)) + ksft_test_result_pass("YMM state restored correctly\n"); + else + ksft_test_result_fail( + "Got upper bits: 0x%lx 0x%lx (expected %lx %lx)\n", + v[2], v[3], TEST_YMMH_VAL, TEST_YMMH_VAL + 1); + + clearhandler(SIGUSR1); + + ksft_finished(); + return 0; +} diff --git a/tools/testing/selftests/x86/xstate.c b/tools/testing/selftests= /x86/xstate.c index 97fe4bd8bc77..40062b28c001 100644 --- a/tools/testing/selftests/x86/xstate.c +++ b/tools/testing/selftests/x86/xstate.c @@ -42,11 +42,6 @@ static inline uint64_t xgetbv(uint32_t index) return eax + ((uint64_t)edx << 32); } =20 -static inline uint64_t get_xstatebv(struct xsave_buffer *xbuf) -{ - return *(uint64_t *)(&xbuf->header); -} - static struct xstate_info xstate; =20 struct futex_info { diff --git a/tools/testing/selftests/x86/xstate.h b/tools/testing/selftests= /x86/xstate.h index 6ee816e7625a..c531667b66ad 100644 --- a/tools/testing/selftests/x86/xstate.h +++ b/tools/testing/selftests/x86/xstate.h @@ -3,6 +3,8 @@ #define __SELFTESTS_X86_XSTATE_H =20 #include +#include +#include =20 #include "kselftest.h" =20 @@ -160,6 +162,11 @@ static inline void set_xstatebv(struct xsave_buffer *x= buf, uint64_t bv) *(uint64_t *)(&xbuf->header) =3D bv; } =20 +static inline uint64_t get_xstatebv(struct xsave_buffer *xbuf) +{ + return *(uint64_t *)(&xbuf->header); +} + /* See 'struct _fpx_sw_bytes' at sigcontext.h */ #define SW_BYTES_OFFSET 464 /* N.B. The struct's field name varies so read from the offset. */ @@ -175,6 +182,11 @@ static inline uint64_t get_fpx_sw_bytes_features(void = *buffer) return *(uint64_t *)(buffer + SW_BYTES_BV_OFFSET); } =20 +static inline void set_fpx_sw_bytes_features(void *buffer, uint64_t featur= es) +{ + *(uint64_t *)(buffer + SW_BYTES_BV_OFFSET) =3D features; +} + static inline void set_rand_data(struct xstate_info *xstate, struct xsave_= buffer *xbuf) { int *ptr =3D (int *)&xbuf->bytes[xstate->xbuf_offset]; --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 08:28:15 2026 Received: from mail-oa1-f73.google.com (mail-oa1-f73.google.com [209.85.160.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 853882F7EED for ; Thu, 4 Jun 2026 16:56:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592174; cv=none; b=popFT6zUnbdYeBdDecKDIFF/NP4+6eI7ZbZBCiDFEFTeIjp2XbRnM0uf+YkZKCu0T4t5vhO3wcu4daOu92aJJ7R35SwFBom95y3q7gMRB+ITh7OyIYgnxllW8Vwr/wkj5A2MMq887LFW1MfYutSuIiHodLspFOKpE1qdbZGasKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592174; c=relaxed/simple; bh=MmaRtMh4aAZDZABUEveV0hMpZAGs5+4JaHSHcIufLYc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KuH1ocADnuC8ppdpTiCnghE8UOYfjQgTKVwSrlT7hkE0E42GTqhKMzNYHkOnx4EUAg43X5sxImZUWh2JfwtB7rihrVV5tRrT052ciGb+pA5u4dSTv0plfiAwIgRzt/q5gO/YNsoFgGkFIxol0+EkZjWPZEymmmDsG2PKIdKyBUQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gnL1elbv; arc=none smtp.client-ip=209.85.160.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gnL1elbv" Received: by mail-oa1-f73.google.com with SMTP id 586e51a60fabf-440d5e1d5e4so3082510fac.1 for ; Thu, 04 Jun 2026 09:56:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780592170; x=1781196970; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=IN2xvXf7IGO5GKcsJztFH/iiFPbGNA4GZJ2tZsr3Zhw=; b=gnL1elbvi0rhR6kXlLLrocmlft14zJH0S0tbvbgO5nG3kHupAL42ZdChNr6maiPpVb JXjEq453BKqIk42nAS3IS0dxivwJrg2bIkiEF1n3NrVw7RLOx28kksSqQ9500IUhKS2u ciJ6zP6M4oJFDnQNFxDYAK0mctUIQbtYjG21dVYWVLjo9zSLVAvFV5Fg/TSvyT9uBXl6 RB+k1+cfoVWLnERMQZui2y1F40Zw+VwomlyiciO+3g0OQHcwbSJvDd83gKbn2SQo9Lsl q1pTmsdRDK1QfCm8jCkzXxAM0agfRhy3+7LIEkFScnDPym3YQtisnCQJlVksbL6XkAOu lSdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780592170; x=1781196970; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IN2xvXf7IGO5GKcsJztFH/iiFPbGNA4GZJ2tZsr3Zhw=; b=TEEXPMc4265WP2EpVc2HKI4l3B1sE44OKGticvp5mkZIqNs8uOxBTgT7l98Ioqd3YS WmJ7qqS6VsQx20TuHegX2gGAt8C5MSAa0TfsD1ZSGQ62Mo/kqOF9pNVD0gbEo5vU+cxK 3rV2AiD8sUZGcAm3HGUSjEfJ3urpqeORcCo75QMnJM4w5lM4HHhQQhywpuSJZoxTkKt/ iyZa1iA7hIIJVXAJS41CQN1c3kfZJYPe3Mc61WmJcqzPrlfyD0d4lGcCfjwXT0JJRM3b rMiGyugvFZdtZVP6Hi1xdkwgn5fV9hMvsbRUHd6Blo6MJc3fYwJFxFqXiM/jHyTEWjTz Q+Ow== X-Gm-Message-State: AOJu0YwaDlYvKAiwDbx9DV0V/LiPNuhAIYMPfGZ5+VCpPsrVufMeuuPa 6YX6r3kWOciV0f/5fzuZ6kz/cuL2ttan8dSmGq6Y4+jMK5grFo9i4+BTkZTax0WKk6HdTNUrdat uBf6cng== X-Received: from ilbep8-n2.prod.google.com ([2002:a05:6e02:2a08:20b0:500:b03a:fa93]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6820:20a:b0:69e:3868:a737 with SMTP id 006d021491bc7-69e58f81a68mr2176761eaf.4.1780592170266; Thu, 04 Jun 2026 09:56:10 -0700 (PDT) Date: Thu, 4 Jun 2026 16:56:03 +0000 In-Reply-To: <20260604165604.1195243-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260604165604.1195243-1-avagin@google.com> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog Message-ID: <20260604165604.1195243-4-avagin@google.com> Subject: [PATCH 3/4] x86/fpu: Add consistency check between xstate_size and xfeatures From: Andrei Vagin To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , "Chang S. Bae" Cc: linux-kernel@vger.kernel.org, criu@lists.linux.dev, Dave Hansen , x86@kernel.org, Andrei Vagin , "H. Peter Anvin" Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The signal frame is designed to be self-describing, where xstate_size indicates the actual size of the xstate context. The kernel previously lacked a check to ensure that the provided xstate_size was sufficient for the features enabled in the xfeatures mask. Additionally, restore_fpregs_from_user() always used the default xstate_size to fault in the xstate user buffer. These consistency checks have been added: * Validate that xfeatures is a subset of the features enabled for the task. * Calculate the required size for the validated xfeatures mask. * Ensure the provided xstate_size is sufficient. These checks prevent the kernel from attempting to fault in memory past the end of a frame. Signed-off-by: Andrei Vagin --- arch/x86/kernel/fpu/signal.c | 29 +++++++++++++++++++++++------ arch/x86/kernel/fpu/xstate.c | 2 +- arch/x86/kernel/fpu/xstate.h | 2 ++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 20b638c507ca..4ddfa59a2851 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -29,16 +29,21 @@ static inline bool check_xstate_in_sigframe(struct fxre= gs_state __user *fxbuf, { int min_xstate_size =3D sizeof(struct fxregs_state) + sizeof(struct xstate_header); - void __user *fpstate =3D fxbuf; + struct fpstate *fpstate =3D x86_task_fpu(current)->fpstate; + void __user *sig_fpstate =3D fxbuf; unsigned int magic2; =20 if (__copy_from_user(fx_sw, &fxbuf->sw_reserved[0], sizeof(*fx_sw))) return false; =20 + /* Enforce XFEATURE_MASK_FPSSE when XSAVE is enabled */ + fx_sw->xfeatures |=3D XFEATURE_MASK_FPSSE; + /* Check for the first magic field and other error scenarios. */ if (fx_sw->magic1 !=3D FP_XSTATE_MAGIC1 || + (fx_sw->xfeatures & ~fpstate->user_xfeatures) || fx_sw->xstate_size < min_xstate_size || - fx_sw->xstate_size > x86_task_fpu(current)->fpstate->user_size || + fx_sw->xstate_size > fpstate->user_size || fx_sw->xstate_size > fx_sw->extended_size) goto setfx; =20 @@ -48,9 +53,17 @@ static inline bool check_xstate_in_sigframe(struct fxreg= s_state __user *fxbuf, * fpstate layout with out copying the extended state information * in the memory layout. */ - if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))) + if (__get_user(magic2, (__u32 __user *)(sig_fpstate + fx_sw->xstate_size)= )) return false; =20 + if (fx_sw->xstate_size !=3D fpstate->user_size) { + unsigned int calculated_size; + + calculated_size =3D xstate_calculate_size(fx_sw->xfeatures, false); + if (fx_sw->xstate_size < calculated_size) + goto setfx; + } + if (likely(magic2 =3D=3D FP_XSTATE_MAGIC2)) return true; setfx: @@ -266,7 +279,8 @@ static int __restore_fpregs_from_user(void __user *buf,= u64 ufeatures, * Attempt to restore the FPU registers directly from user memory. * Pagefaults are handled and any errors returned are fatal. */ -static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, bool = fx_only) +static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, + bool fx_only, size_t xstate_size) { struct fpu *fpu =3D x86_task_fpu(current); int ret; @@ -302,7 +316,7 @@ static bool restore_fpregs_from_user(void __user *buf, = u64 xrestore, bool fx_onl if (ret !=3D X86_TRAP_PF) return false; =20 - if (!fault_in_readable(buf, fpu->fpstate->user_size)) + if (!fault_in_readable(buf, xstate_size)) goto retry; return false; } @@ -333,6 +347,7 @@ static bool __fpu_restore_sig(void __user *buf, void __= user *buf_fx, bool success, fx_only =3D false; union fpregs_state *fpregs; u64 user_xfeatures =3D 0; + size_t xstate_size; =20 if (use_xsave()) { struct _fpx_sw_bytes fx_sw_user; @@ -342,13 +357,15 @@ static bool __fpu_restore_sig(void __user *buf, void = __user *buf_fx, =20 fx_only =3D !fx_sw_user.magic1; user_xfeatures =3D fx_sw_user.xfeatures; + xstate_size =3D fx_sw_user.xstate_size; } else { user_xfeatures =3D XFEATURE_MASK_FPSSE; + xstate_size =3D sizeof(struct fxregs_state); } =20 if (likely(!ia32_fxstate)) { /* Restore the FPU registers directly from user memory. */ - return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only); + return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only, xstate_= size); } =20 /* diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index a7b6524a9dea..371a3a4a4b4e 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -587,7 +587,7 @@ static bool __init check_xstate_against_struct(int nr) return true; } =20 -static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted) +unsigned int xstate_calculate_size(u64 xfeatures, bool compacted) { unsigned int topmost =3D fls64(xfeatures) - 1; unsigned int offset, i; diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h index 38a2862f09d3..c73cf2444de6 100644 --- a/arch/x86/kernel/fpu/xstate.h +++ b/arch/x86/kernel/fpu/xstate.h @@ -55,6 +55,8 @@ extern int copy_sigframe_from_user_to_xstate(struct task_= struct *tsk, const void extern void fpu__init_cpu_xstate(void); extern void fpu__init_system_xstate(unsigned int legacy_size); =20 +extern unsigned int xstate_calculate_size(u64 xfeatures, bool compacted); + extern void __user *get_xsave_addr_user(struct xregs_state __user *xsave, = int xfeature_nr); =20 static inline u64 xfeatures_mask_supervisor(void) --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 08:28:15 2026 Received: from mail-ot1-f74.google.com (mail-ot1-f74.google.com [209.85.210.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3EBA494A19 for ; Thu, 4 Jun 2026 16:56:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592175; cv=none; b=VZ4ltjrzTgGzYKh68jzmu3ufoA/Wyzfvxr83+xd93/sU0R2BZvFGGgLUkpxcR+KTgKhZtR+pMRiVn7wspBz3N6mF0upD/Xy+9uKcimFVkB5KA/mT6ICUhugXQC0y2L7xig7Rz5hsJsWfs46SRdJ56XQhN6NPJYNb+w76wSy0sRI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780592175; c=relaxed/simple; bh=89gFSp3LYbN1yDbqPUvEu3alJDQfZzbkenkTFIOVnVM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=VcNMDloBZmwgQkr6OUeJMgLFTtpbNqguAjlhTQOuijgnTerFAuwe8snI2aUGHV35uRTuc1oLHj8SUYofbJlaDnLtk4ayN8Dij3Vgs16QtsmsvJxrVBw39VykG2/FI3sgCOcC4h8/DiXSUMhzI7SNUoWQ16O/IquNQaoZbPs2S1o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=YcTzRFde; arc=none smtp.client-ip=209.85.210.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="YcTzRFde" Received: by mail-ot1-f74.google.com with SMTP id 46e09a7af769-7e6cea6ada5so2352616a34.1 for ; Thu, 04 Jun 2026 09:56:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780592171; x=1781196971; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=WaIxq3w6aYgqO9bRvTJvHh7gA/sJPH3yio3cl316AWk=; b=YcTzRFdep7FBtbGNkpIDSF3DaJoQqy+VCV8vkWBQIcHlpxiFM9Hf3Dflb3qRNvpqlT JXno6iIXaEd/eEeTyHklGUZxCKlx9+csOW5OaB6uHURk3DvIxRx9OMtuo26d8MCZF5a2 CVg4E4f5BdrO6tbI32qBmUy2zqpBO10C/GvMIsWNvVSzi5hm7AAz9XHwePmiXZhCxRLw VtbSs67qgqRII8VbqSIBc/LsqbtpPNMv8jgPo7V+oyiwlAQ7y7w4cW2HoQZfMgPVksei fsJ9xmzcr0sUB84qoNrV+sYPJLamRm+/aEN3JKIbuF/VctuITmZBJso0/I06oSe31N2U DBZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780592171; x=1781196971; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WaIxq3w6aYgqO9bRvTJvHh7gA/sJPH3yio3cl316AWk=; b=eX1GFvlAUxJtYCJGfvvAcvhmrxmUAaB0Fukqv34pxeZg4rwsswTgNUsQnI86cSyuSb KkQyPGj0lksctOdjTmuZ2hFw1JWjEiAUb/Kq7GJTf4zwGXIa/tdE8gURQBs74l463wOp jyfXe5p1qDnkYnJ/Wj0Pyw07kK08P1ctwvoQq1RZbpQGXB8Z1dwCPenVCS9aJLImDX6w mYg5P62vzRd2bf0KfJWcXEyZxkoJhdgs/ORQ/AJz3HWOEfTiQHG18NtcdJ55D5tK5YNB 9EKnIvm6azPGBQ9cKTemc8a7nTNRN2fgGR08BSsFbWXbH1kToZPdXsSz7e9p/WLUtzpY toEg== X-Gm-Message-State: AOJu0YwEjbNgrYyUr3VZSJPRtiqQlvvJmYiuJgsXEvhxJ51RXDJTbbor QcIsS5uFzoYyTMOd8URwH6X/FXu+sPCXAxfyxivO3im+zJtN/H1Fk5OtKO04vs9htAmLZuCg2Am Gw2mlFw== X-Received: from ioo22-n1.prod.google.com ([2002:a05:6602:8656:10b0:994:c1d4:29a9]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6820:2201:b0:69d:e235:8868 with SMTP id 006d021491bc7-69e4807c400mr4963336eaf.36.1780592171361; Thu, 04 Jun 2026 09:56:11 -0700 (PDT) Date: Thu, 4 Jun 2026 16:56:04 +0000 In-Reply-To: <20260604165604.1195243-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260604165604.1195243-1-avagin@google.com> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog Message-ID: <20260604165604.1195243-5-avagin@google.com> Subject: [PATCH 4/4] selftests/x86: Add a consistency test for signal frames From: Andrei Vagin To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , "Chang S. Bae" Cc: linux-kernel@vger.kernel.org, criu@lists.linux.dev, Dave Hansen , x86@kernel.org, Andrei Vagin , "H. Peter Anvin" Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend sigframe_portability test to include a consistency check. Verify that the kernel correctly rejects signal frames where the xstate_size is too small for the enabled features in the xfeatures mask. Signed-off-by: Andrei Vagin --- .../selftests/x86/sigframe_portability.c | 77 +++++++++++++++---- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/tools/testing/selftests/x86/sigframe_portability.c b/tools/tes= ting/selftests/x86/sigframe_portability.c index 54ba182a792f..04685a1c3aaa 100644 --- a/tools/testing/selftests/x86/sigframe_portability.c +++ b/tools/testing/selftests/x86/sigframe_portability.c @@ -17,13 +17,14 @@ #include "xstate.h" =20 /* - * This test verifies the portability of the signal frame. - * It simulates a scenario where a signal frame is created on a system with - * fewer xstate features and restored on a system with more features. + * This test verifies the portability and consistency of the signal frame. + * Portability: A frame created on a system with fewer features can be + * restored on a system with more features. + * Consistency: The kernel rejects frames where xstate_size is insufficient + * for the features enabled in xfeatures. */ =20 #define SIGFRAME_XSTATE_HDR_OFFSET 512 - #define XSTATE_SSE_ONLY_SIZE (SIGFRAME_XSTATE_HDR_OFFSET + XSAVE_HDR_SIZE) #define XFEATURE_MASK_FPSSE ((1 << XFEATURE_FP) | (1 << XFEATURE_SSE)) =20 @@ -83,8 +84,7 @@ static void write_ymm0(uint64_t *v) asm volatile ("vmovdqu %0, %%ymm0" : : "m" (*(char (*)[32])v)); } =20 - -static void handle_signal(int sig, siginfo_t *si, void *ucp) +static void handle_portability(int sig, siginfo_t *si, void *ucp) { ucontext_t *uc =3D ucp; void *fp =3D uc->uc_mcontext.fpregs; @@ -119,16 +119,12 @@ static void handle_signal(int sig, siginfo_t *si, voi= d *ucp) memset(fp + sw->xstate_size + 4, 0, sw->extended_size - sw->xstate_size = - 4); } =20 -int main(void) +static void test_portability(void) { uint64_t v[4] =3D {0, 0, 0, 0}; =20 - ksft_print_header(); - ksft_set_plan(1); - - check_avx_support(); - - sethandler(SIGUSR1, handle_signal, 0); + sig_err_buf[0] =3D 0; + sethandler(SIGUSR1, handle_portability, 0); =20 v[0] =3D 0x1111111111111111ULL; v[1] =3D 0x2222222222222222ULL; @@ -143,13 +139,66 @@ int main(void) if (sig_err_buf[0]) ksft_test_result_fail("%s\n", sig_err_buf); else if (v[2] =3D=3D TEST_YMMH_VAL && v[3] =3D=3D (TEST_YMMH_VAL + 1)) - ksft_test_result_pass("YMM state restored correctly\n"); + ksft_test_result_pass("YMM state restored correctly from shrunk frame\n"= ); else ksft_test_result_fail( "Got upper bits: 0x%lx 0x%lx (expected %lx %lx)\n", v[2], v[3], TEST_YMMH_VAL, TEST_YMMH_VAL + 1); =20 clearhandler(SIGUSR1); +} + +static void handle_consistency(int sig, siginfo_t *si, void *ucp) +{ + ucontext_t *uc =3D ucp; + void *fp =3D uc->uc_mcontext.fpregs; + struct _fpx_sw_bytes *sw =3D get_fpx_sw_bytes(fp); + + /* The origin frame contains an AVX state. */ + sw->xstate_size =3D XSTATE_SSE_ONLY_SIZE; + + *(uint32_t *)(fp + sw->xstate_size) =3D FP_XSTATE_MAGIC2; +} + +static void test_consistency(void) +{ + uint64_t v[4] =3D {0, 0, 0, 0}; + + sig_err_buf[0] =3D 0; + sethandler(SIGUSR2, handle_consistency, 0); + + v[0] =3D 0x1111111111111111ULL; + v[1] =3D 0x2222222222222222ULL; + v[2] =3D 0x3333333333333333ULL; + v[3] =3D 0x4444444444444444ULL; + write_ymm0(v); + + raise(SIGUSR2); + v[0] =3D v[1] =3D v[2] =3D v[3] =3D 0; + read_ymm0(v); + + /* + * When inconsistent, the kernel should have fallen back to + * FX-only mode, so YMM upper bits should be zero (init state). + */ + if (v[2] =3D=3D 0 && v[3] =3D=3D 0) + ksft_test_result_pass("Inconsistent size correctly rejected\n"); + else + ksft_test_result_fail("Inconsistent size was NOT rejected: 0x%lx 0x%lx\n= ", + v[2], v[3]); + + clearhandler(SIGUSR2); +} + +int main(void) +{ + ksft_print_header(); + ksft_set_plan(2); + + check_avx_support(); + + test_portability(); + test_consistency(); =20 ksft_finished(); return 0; --=20 2.54.0.1032.g2f8565e1d1-goog