mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
systrap: don't copy an FPU state in sighandler
We can set ucontext->uc_mcontext.fpregs to the memory with a target state. PiperOrigin-RevId: 527340901
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <linux/futex.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@@ -196,6 +197,9 @@ struct thread_context *switch_context_amd64(
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void prep_fpstate_for_sigframe(void *buf, uint32_t user_size,
|
||||
bool use_xsave);
|
||||
|
||||
void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
|
||||
ucontext_t *ucontext = _ucontext;
|
||||
void *sp = sysmsg_sp();
|
||||
@@ -335,8 +339,10 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
|
||||
|
||||
if (__export_context_decoupling_exp &&
|
||||
__atomic_load_n(&ctx->fpstate_changed, __ATOMIC_ACQUIRE)) {
|
||||
memcpy((uint8_t *)ucontext->uc_mcontext.fpregs, ctx->fpstate,
|
||||
__export_arch_state.fp_len);
|
||||
prep_fpstate_for_sigframe(
|
||||
ctx->fpstate, __export_arch_state.fp_len,
|
||||
__export_arch_state.xsave_mode != XSAVE_MODE_FXSAVE);
|
||||
ucontext->uc_mcontext.fpregs = (void *)ctx->fpstate;
|
||||
}
|
||||
ptregs_to_gregs(ucontext, &ctx->ptregs);
|
||||
}
|
||||
@@ -453,3 +459,41 @@ void verify_offsets_amd64() {
|
||||
(offsetof(struct user_regs_struct, gs) + PTREGS_OFFSET));
|
||||
#undef PTREGS_OFFSET
|
||||
}
|
||||
|
||||
// asm/sigcontext.h conflicts with signal.h.
|
||||
struct __fpx_sw_bytes {
|
||||
uint32_t magic1;
|
||||
uint32_t extended_size;
|
||||
uint64_t xfeatures;
|
||||
uint32_t xstate_size;
|
||||
uint32_t padding[7];
|
||||
};
|
||||
|
||||
struct __fpstate {
|
||||
uint16_t cwd;
|
||||
uint16_t swd;
|
||||
uint16_t twd;
|
||||
uint16_t fop;
|
||||
uint64_t rip;
|
||||
uint64_t rdp;
|
||||
uint32_t mxcsr;
|
||||
uint32_t mxcsr_mask;
|
||||
uint32_t st_space[32];
|
||||
uint32_t xmm_space[64];
|
||||
uint32_t reserved2[12];
|
||||
struct __fpx_sw_bytes sw_reserved;
|
||||
};
|
||||
|
||||
// The kernel expects to see some additional info in an FPU state. More details
|
||||
// can be found in arch/x86/kernel/fpu/signal.c:check_xstate_in_sigframe.
|
||||
static void prep_fpstate_for_sigframe(void *buf, uint32_t user_size,
|
||||
bool use_xsave) {
|
||||
struct __fpstate *fpstate = buf;
|
||||
struct __fpx_sw_bytes *sw_bytes = &fpstate->sw_reserved;
|
||||
|
||||
sw_bytes->magic1 = FP_XSTATE_MAGIC1;
|
||||
sw_bytes->extended_size = user_size + FP_XSTATE_MAGIC2_SIZE;
|
||||
sw_bytes->xfeatures = ~(0ULL);
|
||||
sw_bytes->xstate_size = user_size;
|
||||
*(uint32_t *)(buf + user_size) = use_xsave ? FP_XSTATE_MAGIC2 : 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user