linux-user/i386: Fix allocation and alignment of fp state

For modern cpus, the kernel uses xsave to store all extra
cpu state across the signal handler.  For xsave/xrstor to
work, the pointer must be 64 byte aligned.  Moreover, the
regular part of the signal frame must be 16 byte aligned.

Attempt to mirror the kernel code as much as possible.
Use enum FPStateKind instead of use_xsave() and use_fxsr().

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1648
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2024-05-26 15:45:23 -07:00
parent 9e9b7d4c15
commit a7365e984d
3 changed files with 377 additions and 215 deletions
+343 -215
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -13,6 +13,7 @@ X86_64_TESTS += vsyscall
X86_64_TESTS += noexec
X86_64_TESTS += cmpxchg
X86_64_TESTS += adox
X86_64_TESTS += test-1648
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
else
TESTS=$(MULTIARCH_TESTS)
+33
View File
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* See https://gitlab.com/qemu-project/qemu/-/issues/1648 */
#include <signal.h>
__attribute__((noinline))
void bar(void)
{
/* Success! Continue through sigreturn. */
}
/*
* Because of the change of ABI between foo and bar, the compiler is
* required to save XMM6-XMM15. The compiler will use MOVAPS or MOVDQA,
* which will trap if the stack frame is not 16 byte aligned.
*/
__attribute__((noinline, ms_abi))
void foo(void)
{
bar();
}
void sighandler(int num)
{
foo();
}
int main(void)
{
signal(SIGUSR1, sighandler);
raise(SIGUSR1);
return 0;
}