Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109892145
D38302.id116148.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D38302.id116148.diff
View Options
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -319,21 +319,22 @@
linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
{
struct proc *p;
- struct l_ucontext uc;
+ struct l_rt_sigframe sf;
struct l_sigcontext *context;
struct trapframe *regs;
+ mcontext_t mc;
unsigned long rflags;
sigset_t bmask;
- int error;
+ int error, i;
ksiginfo_t ksi;
regs = td->td_frame;
- error = copyin((void *)regs->tf_rbx, &uc, sizeof(uc));
+ error = copyin((void *)regs->tf_rbx, &sf, sizeof(sf));
if (error != 0)
return (error);
p = td->td_proc;
- context = &uc.uc_mcontext;
+ context = &sf.sf_uc.uc_mcontext;
rflags = context->sc_rflags;
/*
@@ -372,7 +373,7 @@
return (EINVAL);
}
- linux_to_bsd_sigset(&uc.uc_sigmask, &bmask);
+ linux_to_bsd_sigset(&sf.sf_uc.uc_sigmask, &bmask);
kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0);
regs->tf_rdi = context->sc_rdi;
@@ -396,6 +397,40 @@
regs->tf_err = context->sc_err;
regs->tf_rflags = rflags;
+ if (sf.sf_uc.uc_mcontext.sc_fpstate != NULL) {
+ struct savefpu *svfp = (struct savefpu *) mc.mc_fpstate;
+
+ bzero(&mc, sizeof(mc));
+ mc.mc_ownedfp = _MC_FPOWNED_FPU;
+ mc.mc_fpformat = _MC_FPFMT_XMM;
+ mc.mc_flags |= _MC_HASFPXSTATE;
+
+ svfp->sv_env.en_cw = sf.sf_fs.cwd;
+ svfp->sv_env.en_sw = sf.sf_fs.swd;
+ svfp->sv_env.en_tw = sf.sf_fs.twd;
+ svfp->sv_env.en_opcode = sf.sf_fs.fop;
+ svfp->sv_env.en_rip = sf.sf_fs.rip;
+ svfp->sv_env.en_rdp = sf.sf_fs.rdp;
+ svfp->sv_env.en_mxcsr = sf.sf_fs.mxcsr;
+ svfp->sv_env.en_mxcsr_mask = sf.sf_fs.mxcsr_mask;
+ /* FPU registers */
+ for (i = 0; i < sizeof(svfp->sv_fp) / sizeof(svfp->sv_fp[0]);
+ ++i)
+ bcopy(&sf.sf_fs.st[i], svfp->sv_fp[i].fp_acc.fp_bytes,
+ sizeof(svfp->sv_fp[i].fp_acc.fp_bytes));
+ /* SSE registers */
+ for (i = 0; i < sizeof(svfp->sv_xmm) / sizeof(svfp->sv_xmm[0]);
+ ++i)
+ bcopy(&sf.sf_fs.xmm[i], svfp->sv_xmm[i].xmm_bytes,
+ sizeof(svfp->sv_xmm[i].xmm_bytes));
+ error = set_fpcontext(td, &mc, NULL, 0);
+ if (error != 0) {
+ uprintf("pid %d comm %s linux can't restore fpu state %d\n",
+ p->p_pid, p->p_comm, error);
+ return (error);
+ }
+ }
+
set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
return (EJUSTRETURN);
}
@@ -414,8 +449,9 @@
struct sigacts *psp;
caddr_t sp;
struct trapframe *regs;
+ mcontext_t mc;
int sig, code;
- int oonstack, issiginfo;
+ int oonstack, issiginfo, i;
td = curthread;
p = td->td_proc;
@@ -474,6 +510,32 @@
/* Align to 16 bytes. */
sfp = (struct l_rt_sigframe *)((unsigned long)sp & ~0xFul);
+ get_fpcontext(td, &mc, NULL, NULL);
+ if (mc.mc_fpformat != _MC_FPFMT_NODEV) {
+ struct savefpu *svfp = (struct savefpu *) mc.mc_fpstate;
+
+ sf.sf_fs.cwd = svfp->sv_env.en_cw;
+ sf.sf_fs.swd = svfp->sv_env.en_sw;
+ sf.sf_fs.twd = svfp->sv_env.en_tw;
+ sf.sf_fs.fop = svfp->sv_env.en_opcode;
+ sf.sf_fs.rip = svfp->sv_env.en_rip;
+ sf.sf_fs.rdp = svfp->sv_env.en_rdp;
+ sf.sf_fs.mxcsr = svfp->sv_env.en_mxcsr;
+ sf.sf_fs.mxcsr_mask = svfp->sv_env.en_mxcsr_mask;
+ /* FPU registers */
+ for (i = 0; i < sizeof(svfp->sv_fp) / sizeof(svfp->sv_fp[0]);
+ ++i)
+ bcopy(svfp->sv_fp[i].fp_acc.fp_bytes, &sf.sf_fs.st[i],
+ sizeof(svfp->sv_fp[i].fp_acc.fp_bytes));
+ /* SSE registers */
+ for (i = 0; i < sizeof(svfp->sv_xmm) / sizeof(svfp->sv_xmm[0]);
+ ++i)
+ bcopy(svfp->sv_xmm[i].xmm_bytes, &sf.sf_fs.xmm[i],
+ sizeof(svfp->sv_xmm[i].xmm_bytes));
+ sf.sf_uc.uc_mcontext.sc_fpstate = (void *)((char *)sfp +
+ offsetof(struct l_rt_sigframe, sf_fs));
+ }
+
mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
@@ -490,6 +552,7 @@
sigexit(td, SIGILL);
}
+ fpstate_drop(td);
/* Build the argument list for the signal handler. */
regs->tf_rdi = sig; /* arg 1 in %rdi */
regs->tf_rax = 0;
diff --git a/sys/x86/linux/linux_x86_sigframe.h b/sys/x86/linux/linux_x86_sigframe.h
--- a/sys/x86/linux/linux_x86_sigframe.h
+++ b/sys/x86/linux/linux_x86_sigframe.h
@@ -138,10 +138,10 @@
u_int64_t rdp;
u_int32_t mxcsr;
u_int32_t mxcsr_mask;
- u_int32_t st_space[32];
- u_int32_t xmm_space[64];
+ u_int8_t st[8][16];
+ u_int8_t xmm[16][16];
u_int32_t reserved2[24];
-};
+} __aligned(16);
struct l_sigcontext {
l_ulong sc_r8;
@@ -189,6 +189,7 @@
struct l_rt_sigframe {
struct l_ucontext sf_uc;
struct l_siginfo sf_si;
+ struct l_fpstate sf_fs;
};
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 11, 8:53 PM (15 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16600980
Default Alt Text
D38302.id116148.diff (4 KB)
Attached To
Mode
D38302: linux(4): Preserve fpu fxsave state across signal delivery on amd64.
Attached
Detach File
Event Timeline
Log In to Comment