Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/linux/linux_sysvec.c
Show First 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | linux_fxrstor(struct thread *td, mcontext_t *mcp, struct l_sigcontext *sc) | ||||
error = copyin(PTRIN(sc->sc_fpstate), fp, sizeof(mcp->mc_fpstate)); | error = copyin(PTRIN(sc->sc_fpstate), fp, sizeof(mcp->mc_fpstate)); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
bzero(&fp->sv_pad[0], sizeof(fp->sv_pad)); | bzero(&fp->sv_pad[0], sizeof(fp->sv_pad)); | ||||
return (set_fpcontext(td, mcp, NULL, 0)); | return (set_fpcontext(td, mcp, NULL, 0)); | ||||
} | } | ||||
static int | static int | ||||
linux_xrstor(struct thread *td, mcontext_t *mcp, struct l_sigcontext *sc) | |||||
{ | |||||
struct savefpu *fp = (struct savefpu *)&mcp->mc_fpstate[0]; | |||||
char *xfpustate; | |||||
struct proc *p; | |||||
uint32_t magic2; | |||||
int error; | |||||
p = td->td_proc; | |||||
mcp->mc_xfpustate_len = cpu_max_ext_state_size - sizeof(struct savefpu); | |||||
/* Legacy region of an xsave area. */ | |||||
error = copyin(PTRIN(sc->sc_fpstate), fp, sizeof(mcp->mc_fpstate)); | |||||
if (error != 0) | |||||
return (error); | |||||
bzero(&fp->sv_pad[0], sizeof(fp->sv_pad)); | |||||
/* Extended region of an xsave area. */ | |||||
sc->sc_fpstate += sizeof(mcp->mc_fpstate); | |||||
xfpustate = (char *)fpu_save_area_alloc(); | |||||
error = copyin(PTRIN(sc->sc_fpstate), xfpustate, mcp->mc_xfpustate_len); | |||||
if (error != 0) { | |||||
fpu_save_area_free((struct savefpu *)xfpustate); | |||||
uprintf("pid %d (%s): linux xrstor failed\n", p->p_pid, | |||||
td->td_name); | |||||
return (error); | |||||
} | |||||
/* Linux specific end of xsave area marker. */ | |||||
sc->sc_fpstate += mcp->mc_xfpustate_len; | |||||
error = copyin(PTRIN(sc->sc_fpstate), &magic2, LINUX_FP_XSTATE_MAGIC2_SIZE); | |||||
kib: Is it more correct to check magic before copying xfpustate? | |||||
Done Inline ActionsI've been thinking about it, and leaved as is, as caller will be killed on error or if magic/stack is trashed, and this path is not common. If you insist I’ll fix that, however it does not more sense in my pov dchagin: I've been thinking about it, and leaved as is, as caller will be killed on error or if… | |||||
if (error != 0 || magic2 != LINUX_FP_XSTATE_MAGIC2) { | |||||
fpu_save_area_free((struct savefpu *)xfpustate); | |||||
uprintf("pid %d (%s): sigreturn magic2 0x%x error %d\n", | |||||
p->p_pid, td->td_name, magic2, error); | |||||
return (error); | |||||
} | |||||
error = set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len); | |||||
fpu_save_area_free((struct savefpu *)xfpustate); | |||||
if (error != 0) { | |||||
uprintf("pid %d (%s): sigreturn set_fpcontext error %d\n", | |||||
p->p_pid, td->td_name, error); | |||||
} | |||||
return (error); | |||||
} | |||||
static int | |||||
linux_copyin_fpstate(struct thread *td, struct l_ucontext *uc) | linux_copyin_fpstate(struct thread *td, struct l_ucontext *uc) | ||||
{ | { | ||||
mcontext_t mc; | mcontext_t mc; | ||||
bzero(&mc, sizeof(mc)); | bzero(&mc, sizeof(mc)); | ||||
mc.mc_ownedfp = _MC_FPOWNED_FPU; | mc.mc_ownedfp = _MC_FPOWNED_FPU; | ||||
mc.mc_fpformat = _MC_FPFMT_XMM; | mc.mc_fpformat = _MC_FPFMT_XMM; | ||||
if ((uc->uc_flags & LINUX_UC_FP_XSTATE) != 0) | |||||
return (linux_xrstor(td, &mc, &uc->uc_mcontext)); | |||||
else | |||||
return (linux_fxrstor(td, &mc, &uc->uc_mcontext)); | return (linux_fxrstor(td, &mc, &uc->uc_mcontext)); | ||||
} | } | ||||
/* | /* | ||||
* Copied from amd64/amd64/machdep.c | * Copied from amd64/amd64/machdep.c | ||||
*/ | */ | ||||
int | int | ||||
linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) | linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct l_fpstate *fx = (struct l_fpstate *)&mcp->mc_fpstate[0]; | struct l_fpstate *fx = (struct l_fpstate *)&mcp->mc_fpstate[0]; | ||||
bzero(&fx->reserved2[0], sizeof(fx->reserved2)); | bzero(&fx->reserved2[0], sizeof(fx->reserved2)); | ||||
return (copyout(fx, ufp, sizeof(*fx))); | return (copyout(fx, ufp, sizeof(*fx))); | ||||
} | } | ||||
static int | static int | ||||
linux_xsave(mcontext_t *mcp, char *xfpusave, char *ufp) | |||||
{ | |||||
struct l_fpstate *fx = (struct l_fpstate *)&mcp->mc_fpstate[0]; | |||||
uint32_t magic2; | |||||
int error; | |||||
/* Legacy region of an xsave area. */ | |||||
fx->sw_reserved.magic1 = LINUX_FP_XSTATE_MAGIC1; | |||||
fx->sw_reserved.xstate_size = mcp->mc_xfpustate_len + sizeof(*fx); | |||||
fx->sw_reserved.extended_size = fx->sw_reserved.xstate_size + | |||||
LINUX_FP_XSTATE_MAGIC2_SIZE; | |||||
fx->sw_reserved.xfeatures = xsave_mask; | |||||
error = copyout(fx, ufp, sizeof(*fx)); | |||||
if (error != 0) | |||||
return (error); | |||||
ufp += sizeof(*fx); | |||||
/* Extended region of an xsave area. */ | |||||
error = copyout(xfpusave, ufp, mcp->mc_xfpustate_len); | |||||
if (error != 0) | |||||
return (error); | |||||
/* Linux specific end of xsave area marker. */ | |||||
ufp += mcp->mc_xfpustate_len; | |||||
magic2 = LINUX_FP_XSTATE_MAGIC2; | |||||
return (copyout(&magic2, ufp, LINUX_FP_XSTATE_MAGIC2_SIZE)); | |||||
} | |||||
static int | |||||
linux_copyout_fpstate(struct thread *td, struct l_ucontext *uc, char **sp) | linux_copyout_fpstate(struct thread *td, struct l_ucontext *uc, char **sp) | ||||
{ | { | ||||
size_t xfpusave_len; | |||||
char *xfpusave; | |||||
mcontext_t mc; | mcontext_t mc; | ||||
char *ufp = *sp; | char *ufp = *sp; | ||||
get_fpcontext(td, &mc, NULL, NULL); | get_fpcontext(td, &mc, &xfpusave, &xfpusave_len); | ||||
KASSERT(mc.mc_fpformat != _MC_FPFMT_NODEV, ("fpu not present")); | KASSERT(mc.mc_fpformat != _MC_FPFMT_NODEV, ("fpu not present")); | ||||
/* fxsave area */ | /* Room for fxsave area. */ | ||||
ufp -= sizeof(struct l_fpstate); | ufp -= sizeof(struct l_fpstate); | ||||
if (xfpusave != NULL) { | |||||
/* Room for xsave area. */ | |||||
ufp -= (xfpusave_len + LINUX_FP_XSTATE_MAGIC2_SIZE); | |||||
uc->uc_flags |= LINUX_UC_FP_XSTATE; | |||||
} | |||||
*sp = ufp = (char *)((unsigned long)ufp & ~0x3Ful); | *sp = ufp = (char *)((unsigned long)ufp & ~0x3Ful); | ||||
if (xfpusave != NULL) | |||||
return (linux_xsave(&mc, xfpusave, ufp)); | |||||
else | |||||
return (linux_fxsave(&mc, ufp)); | return (linux_fxsave(&mc, ufp)); | ||||
} | } | ||||
/* | /* | ||||
* copied from amd64/amd64/machdep.c | * copied from amd64/amd64/machdep.c | ||||
* | * | ||||
* Send an interrupt to process. | * Send an interrupt to process. | ||||
*/ | */ | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 448 Lines • Show Last 20 Lines |
Is it more correct to check magic before copying xfpustate?