Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323994
b: refs/heads/master
c: 72a671c
h: refs/heads/master
v: v3
  • Loading branch information
Suresh Siddha authored and H. Peter Anvin committed Sep 18, 2012
1 parent d1355ee commit de864b7
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 485 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0ca5bd0d886578ad0afeceaa83458c0f35cb3c6b
refs/heads/master: 72a671ced66db6d1c2bfff1c930a101ac8d08204
9 changes: 6 additions & 3 deletions trunk/arch/x86/ia32/ia32_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,

get_user_ex(tmp, &sc->fpstate);
buf = compat_ptr(tmp);
err |= restore_i387_xstate_ia32(buf);
err |= restore_xstate_sig(buf, 1);

get_user_ex(*pax, &sc->ax);
} get_user_catch(err);
Expand Down Expand Up @@ -382,9 +382,12 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
sp = (unsigned long) ka->sa.sa_restorer;

if (used_math()) {
sp = sp - sig_xstate_ia32_size;
unsigned long fx_aligned, math_size;

sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size);
*fpstate = (struct _fpstate_ia32 __user *) sp;
if (save_i387_xstate_ia32(*fpstate) < 0)
if (save_xstate_sig(*fpstate, (void __user *)fx_aligned,
math_size) < 0)
return (void __user *) -1L;
}

Expand Down
111 changes: 71 additions & 40 deletions trunk/arch/x86/include/asm/fpu-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,30 @@
#include <asm/uaccess.h>
#include <asm/xsave.h>

extern unsigned int sig_xstate_size;
#ifdef CONFIG_X86_64
# include <asm/sigcontext32.h>
# include <asm/user32.h>
int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
compat_sigset_t *set, struct pt_regs *regs);
int ia32_setup_frame(int sig, struct k_sigaction *ka,
compat_sigset_t *set, struct pt_regs *regs);
#else
# define user_i387_ia32_struct user_i387_struct
# define user32_fxsr_struct user_fxsr_struct
# define ia32_setup_frame __setup_frame
# define ia32_setup_rt_frame __setup_rt_frame
#endif

extern unsigned int mxcsr_feature_mask;
extern void fpu_init(void);

DECLARE_PER_CPU(struct task_struct *, fpu_owner_task);

extern void convert_from_fxsr(struct user_i387_ia32_struct *env,
struct task_struct *tsk);
extern void convert_to_fxsr(struct task_struct *tsk,
const struct user_i387_ia32_struct *env);

extern user_regset_active_fn fpregs_active, xfpregs_active;
extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get,
xstateregs_get;
Expand All @@ -39,19 +58,11 @@ extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
*/
#define xstateregs_active fpregs_active

extern struct _fpx_sw_bytes fx_sw_reserved;
#ifdef CONFIG_IA32_EMULATION
extern unsigned int sig_xstate_ia32_size;
extern struct _fpx_sw_bytes fx_sw_reserved_ia32;
struct _fpstate_ia32;
struct _xstate_ia32;
extern int save_i387_xstate_ia32(void __user *buf);
extern int restore_i387_xstate_ia32(void __user *buf);
#endif

#ifdef CONFIG_MATH_EMULATION
# define HAVE_HWFP (boot_cpu_data.hard_math)
extern void finit_soft_fpu(struct i387_soft_struct *soft);
#else
# define HAVE_HWFP 1
static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
#endif

Expand Down Expand Up @@ -119,17 +130,6 @@ static inline int fsave_user(struct i387_fsave_struct __user *fx)

static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
{
int err;

/*
* Clear the bytes not touched by the fxsave and reserved
* for the SW usage.
*/
err = __clear_user(&fx->sw_reserved,
sizeof(struct _fpx_sw_bytes));
if (unlikely(err))
return -EFAULT;

if (config_enabled(CONFIG_X86_32))
return check_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
else if (config_enabled(CONFIG_AS_FXSAVEQ))
Expand Down Expand Up @@ -189,19 +189,6 @@ static inline void fpu_fxsave(struct fpu *fpu)
: [fx] "R" (&fpu->state->fxsave));
}
}
#ifdef CONFIG_X86_64

int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
compat_sigset_t *set, struct pt_regs *regs);
int ia32_setup_frame(int sig, struct k_sigaction *ka,
compat_sigset_t *set, struct pt_regs *regs);

#else /* CONFIG_X86_32 */

#define ia32_setup_frame __setup_frame
#define ia32_setup_rt_frame __setup_rt_frame

#endif /* CONFIG_X86_64 */

/*
* These must be called with preempt disabled. Returns
Expand Down Expand Up @@ -392,10 +379,28 @@ static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu)
/*
* Signal frame handlers...
*/
extern int save_i387_xstate(void __user *buf);
extern int restore_i387_xstate(void __user *buf);
extern int save_xstate_sig(void __user *buf, void __user *fx, int size);
extern int __restore_xstate_sig(void __user *buf, void __user *fx, int size);

static inline int xstate_sigframe_size(void)
{
return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size;
}

static inline int restore_xstate_sig(void __user *buf, int ia32_frame)
{
void __user *buf_fx = buf;
int size = xstate_sigframe_size();

if (ia32_frame && use_fxsr()) {
buf_fx = buf + sizeof(struct i387_fsave_struct);
size += sizeof(struct i387_fsave_struct);
}

return __restore_xstate_sig(buf, buf_fx, size);
}

static inline void __clear_fpu(struct task_struct *tsk)
static inline void __drop_fpu(struct task_struct *tsk)
{
if (__thread_has_fpu(tsk)) {
/* Ignore delayed exceptions from user space */
Expand Down Expand Up @@ -443,11 +448,21 @@ static inline void save_init_fpu(struct task_struct *tsk)
preempt_enable();
}

static inline void clear_fpu(struct task_struct *tsk)
static inline void stop_fpu_preload(struct task_struct *tsk)
{
tsk->fpu_counter = 0;
}

static inline void drop_fpu(struct task_struct *tsk)
{
/*
* Forget coprocessor state..
*/
stop_fpu_preload(tsk);
preempt_disable();
__clear_fpu(tsk);
__drop_fpu(tsk);
preempt_enable();
clear_used_math();
}

/*
Expand Down Expand Up @@ -511,4 +526,20 @@ static inline void fpu_copy(struct fpu *dst, struct fpu *src)

extern void fpu_finit(struct fpu *fpu);

static inline unsigned long
alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long *buf_fx,
unsigned long *size)
{
unsigned long frame_size = xstate_sigframe_size();

*buf_fx = sp = round_down(sp - frame_size, 64);
if (ia32_frame && use_fxsr()) {
frame_size += sizeof(struct i387_fsave_struct);
sp -= sizeof(struct i387_fsave_struct);
}

*size = frame_size;
return sp;
}

#endif
6 changes: 1 addition & 5 deletions trunk/arch/x86/include/asm/xsave.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
extern void xsave_init(void);
extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
extern int init_fpu(struct task_struct *child);
extern int check_for_xstate(struct i387_fxsave_struct __user *buf,
void __user *fpstate,
struct _fpx_sw_bytes *sw);

static inline int fpu_xrstor_checking(struct xsave_struct *fx)
{
Expand Down Expand Up @@ -68,8 +65,7 @@ static inline int xsave_user(struct xsave_struct __user *buf)
* Clear the xsave header first, so that reserved fields are
* initialized to zero.
*/
err = __clear_user(&buf->xsave_hdr,
sizeof(struct xsave_hdr_struct));
err = __clear_user(&buf->xsave_hdr, sizeof(buf->xsave_hdr));
if (unlikely(err))
return -EFAULT;

Expand Down
Loading

0 comments on commit de864b7

Please sign in to comment.