Commit fd10141d authored by David S. Miller's avatar David S. Miller

[SPARC64]: Save/restore %asi properly in signal handling.

Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 9f2390ee
......@@ -84,8 +84,8 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
regs->tnpc = npc;
err |= __get_user(regs->y, &((*grp)[MC_Y]));
err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
......@@ -408,9 +408,9 @@ void do_rt_sigreturn(struct pt_regs *regs)
err |= __get_user(tstate, &sf->regs.tstate);
err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs));
/* User can only change condition codes in %tstate. */
regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
/* User can only change condition codes and %asi in %tstate. */
regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
err |= __get_user(fpu_save, &sf->fpu_save);
if (fpu_save)
......
......@@ -59,6 +59,16 @@ struct signal_sframe32 {
unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
};
/* This magic should be in g_upper[0] for all upper parts
* to be valid.
*/
#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269
typedef struct {
unsigned int g_upper[8];
unsigned int o_upper[8];
unsigned int asi;
} siginfo_extra_v8plus_t;
/*
* And the new one, intended to be used for Linux applications only
* (we have enough in there to work with clone).
......@@ -299,8 +309,13 @@ void do_new_sigreturn32(struct pt_regs *regs)
if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
err |= __get_user(i, &sf->v8plus.g_upper[0]);
if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
unsigned long asi;
for (i = UREG_G1; i <= UREG_I7; i++)
err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
err |= __get_user(asi, &sf->v8plus.asi);
regs->tstate &= ~TSTATE_ASI;
regs->tstate |= ((asi & 0xffUL) << 24UL);
}
}
......@@ -447,8 +462,13 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
err |= __get_user(i, &sf->v8plus.g_upper[0]);
if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
unsigned long asi;
for (i = UREG_G1; i <= UREG_I7; i++)
err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
err |= __get_user(asi, &sf->v8plus.asi);
regs->tstate &= ~TSTATE_ASI;
regs->tstate |= ((asi & 0xffUL) << 24UL);
}
}
......@@ -715,7 +735,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
for (i = 1; i < 16; i++)
err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
err |= __put_user(((u32 *)regs->u_regs)[2*i],
&sf->v8plus.g_upper[i]);
err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
&sf->v8plus.asi);
if (psr & PSR_EF) {
err |= save_fpu_state32(regs, &sf->fpu_state);
......@@ -1120,6 +1143,8 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
for (i = 1; i < 16; i++)
err |= __put_user(((u32 *)regs->u_regs)[2*i],
&sf->v8plus.g_upper[i]);
err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
&sf->v8plus.asi);
if (psr & PSR_EF) {
err |= save_fpu_state32(regs, &sf->fpu_state);
......
......@@ -57,20 +57,6 @@ typedef struct {
} si_fpqueue [16];
} __siginfo_fpu_t;
#ifdef __KERNEL__
/* This magic should be in g_upper[0] for all upper parts
to be valid.
This is generated by sparc64 only, but for 32bit processes,
so we define it here as well. */
#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269
typedef struct {
unsigned int g_upper[8];
unsigned int o_upper[8];
} siginfo_extra_v8plus_t;
#endif
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC_SIGCONTEXT_H) */
......@@ -83,18 +83,6 @@ struct sigcontext {
unsigned long sigc_mask;
};
#ifdef __KERNEL__
/* This magic should be in g_upper[0] for all upper parts
to be valid. */
#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269
typedef struct {
unsigned int g_upper[8];
unsigned int o_upper[8];
} siginfo_extra_v8plus_t;
#endif
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC64_SIGCONTEXT_H) */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment