Skip to content

Commit

Permalink
Merge branch 'x86/xsave' into x86/core
Browse files Browse the repository at this point in the history
  • Loading branch information
Ingo Molnar committed Sep 5, 2008
2 parents ebd60cd + fe47784 commit accf0fa
Show file tree
Hide file tree
Showing 21 changed files with 899 additions and 184 deletions.
51 changes: 24 additions & 27 deletions arch/x86/ia32/ia32_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,10 @@ struct sigframe
u32 pretcode;
int sig;
struct sigcontext_ia32 sc;
struct _fpstate_ia32 fpstate;
struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */
unsigned int extramask[_COMPAT_NSIG_WORDS-1];
char retcode[8];
/* fp state follows here */
};

struct rt_sigframe
Expand All @@ -192,8 +193,8 @@ struct rt_sigframe
u32 puc;
compat_siginfo_t info;
struct ucontext_ia32 uc;
struct _fpstate_ia32 fpstate;
char retcode[8];
/* fp state follows here */
};

#define COPY(x) { \
Expand All @@ -215,7 +216,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
unsigned int *peax)
{
unsigned int tmpflags, gs, oldgs, err = 0;
struct _fpstate_ia32 __user *buf;
void __user *buf;
u32 tmp;

/* Always make any pending restarted system calls return -EINTR */
Expand Down Expand Up @@ -259,26 +260,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,

err |= __get_user(tmp, &sc->fpstate);
buf = compat_ptr(tmp);
if (buf) {
if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387_ia32(buf);
} else {
struct task_struct *me = current;

if (used_math()) {
clear_fpu(me);
clear_used_math();
}
}
err |= restore_i387_xstate_ia32(buf);

err |= __get_user(tmp, &sc->ax);
*peax = tmp;

return err;

badframe:
return 1;
}

asmlinkage long sys32_sigreturn(struct pt_regs *regs)
Expand Down Expand Up @@ -350,7 +337,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
*/

static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
struct _fpstate_ia32 __user *fpstate,
void __user *fpstate,
struct pt_regs *regs, unsigned int mask)
{
int tmp, err = 0;
Expand Down Expand Up @@ -381,7 +368,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
err |= __put_user((u32)regs->flags, &sc->flags);
err |= __put_user((u32)regs->sp, &sc->sp_at_signal);

tmp = save_i387_ia32(fpstate);
tmp = save_i387_xstate_ia32(fpstate);
if (tmp < 0)
err = -EFAULT;
else {
Expand All @@ -402,7 +389,8 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
* Determine which stack to use..
*/
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size)
size_t frame_size,
void **fpstate)
{
unsigned long sp;

Expand All @@ -421,6 +409,11 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
ka->sa.sa_restorer)
sp = (unsigned long) ka->sa.sa_restorer;

if (used_math()) {
sp = sp - sig_xstate_ia32_size;
*fpstate = (struct _fpstate_ia32 *) sp;
}

sp -= frame_size;
/* Align the stack pointer according to the i386 ABI,
* i.e. so that on function entry ((sp + 4) & 15) == 0. */
Expand All @@ -434,6 +427,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
struct sigframe __user *frame;
void __user *restorer;
int err = 0;
void __user *fpstate = NULL;

/* copy_to_user optimizes that into a single 8 byte store */
static const struct {
Expand All @@ -448,7 +442,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
0,
};

frame = get_sigframe(ka, regs, sizeof(*frame));
frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
Expand All @@ -457,8 +451,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
if (err)
goto give_sigsegv;

err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs,
set->sig[0]);
err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]);
if (err)
goto give_sigsegv;

Expand Down Expand Up @@ -522,6 +515,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
struct rt_sigframe __user *frame;
void __user *restorer;
int err = 0;
void __user *fpstate = NULL;

/* __copy_to_user optimizes that into a single 8 byte store */
static const struct {
Expand All @@ -537,7 +531,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
0,
};

frame = get_sigframe(ka, regs, sizeof(*frame));
frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
Expand All @@ -550,13 +544,16 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;

/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
if (cpu_has_xsave)
err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
else
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->sp),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ obj-y += tsc.o io_delay.o rtc.o

obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-y += process.o
obj-y += i387.o
obj-y += i387.o xsave.o
obj-y += ptrace.o
obj-y += ds.o
obj-$(CONFIG_X86_32) += tls.o
Expand Down
13 changes: 12 additions & 1 deletion arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,9 +739,20 @@ void __cpuinit cpu_init(void)
/*
* Force FPU initialization:
*/
current_thread_info()->status = 0;
if (cpu_has_xsave)
current_thread_info()->status = TS_XSAVE;
else
current_thread_info()->status = 0;
clear_used_math();
mxcsr_feature_mask_init();

/*
* Boot processor to setup the FP and extended state context info.
*/
if (!smp_processor_id())
init_thread_xstate();

xsave_init();
}

#ifdef CONFIG_HOTPLUG_CPU
Expand Down
Loading

0 comments on commit accf0fa

Please sign in to comment.