|
@@ -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
|
|
@@ -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) { \
|
|
@@ -402,7 +403,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,
|
|
|
+ struct _fpstate_ia32 **fpstate)
|
|
|
{
|
|
|
unsigned long sp;
|
|
|
|
|
@@ -421,6 +423,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. */
|
|
@@ -434,6 +441,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
|
|
struct sigframe __user *frame;
|
|
|
void __user *restorer;
|
|
|
int err = 0;
|
|
|
+ struct _fpstate_ia32 __user *fpstate = NULL;
|
|
|
|
|
|
/* copy_to_user optimizes that into a single 8 byte store */
|
|
|
static const struct {
|
|
@@ -448,7 +456,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;
|
|
@@ -457,8 +465,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;
|
|
|
|
|
@@ -522,6 +529,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;
|
|
|
+ struct _fpstate_ia32 __user *fpstate = NULL;
|
|
|
|
|
|
/* __copy_to_user optimizes that into a single 8 byte store */
|
|
|
static const struct {
|
|
@@ -537,7 +545,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;
|
|
@@ -556,7 +564,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|
|
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)
|