Refactor FPU code in signal setup/return procedures
FPU-related logic is separated from normal signal handling path in this patch. Kernel can easily be configured to exclude those procedures for no-FPU systems. Signed-off-by: Alan Kao <alankao@andestech.com> Cc: Greentime Hu <greentime@andestech.com> Cc: Vincent Chen <vincentc@andestech.com> Cc: Zong Li <zong@andestech.com> Cc: Nick Hu <nickhu@andestech.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
parent
e68ad867f7
commit
007f5c3589
|
@ -37,45 +37,63 @@ struct rt_sigframe {
|
||||||
struct ucontext uc;
|
struct ucontext uc;
|
||||||
};
|
};
|
||||||
|
|
||||||
static long restore_d_state(struct pt_regs *regs,
|
static long restore_fp_state(struct pt_regs *regs,
|
||||||
struct __riscv_d_ext_state __user *state)
|
union __riscv_fp_state *sc_fpregs)
|
||||||
{
|
{
|
||||||
long err;
|
long err;
|
||||||
|
struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state));
|
err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state));
|
||||||
if (likely(!err))
|
if (unlikely(err))
|
||||||
fstate_restore(current, regs);
|
return err;
|
||||||
|
|
||||||
|
fstate_restore(current, regs);
|
||||||
|
|
||||||
|
/* We support no other extension state at this time. */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
err = __get_user(value, &sc_fpregs->q.reserved[i]);
|
||||||
|
if (unlikely(err))
|
||||||
|
break;
|
||||||
|
if (value != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long save_d_state(struct pt_regs *regs,
|
static long save_fp_state(struct pt_regs *regs,
|
||||||
struct __riscv_d_ext_state __user *state)
|
union __riscv_fp_state *sc_fpregs)
|
||||||
{
|
{
|
||||||
|
long err;
|
||||||
|
struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
fstate_save(current, regs);
|
fstate_save(current, regs);
|
||||||
return __copy_to_user(state, ¤t->thread.fstate, sizeof(*state));
|
err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state));
|
||||||
|
if (unlikely(err))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* We support no other extension state at this time. */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
|
||||||
|
err = __put_user(0, &sc_fpregs->q.reserved[i]);
|
||||||
|
if (unlikely(err))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long restore_sigcontext(struct pt_regs *regs,
|
static long restore_sigcontext(struct pt_regs *regs,
|
||||||
struct sigcontext __user *sc)
|
struct sigcontext __user *sc)
|
||||||
{
|
{
|
||||||
long err;
|
long err;
|
||||||
size_t i;
|
|
||||||
/* sc_regs is structured the same as the start of pt_regs */
|
/* sc_regs is structured the same as the start of pt_regs */
|
||||||
err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
|
err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
|
||||||
if (unlikely(err))
|
|
||||||
return err;
|
|
||||||
/* Restore the floating-point state. */
|
/* Restore the floating-point state. */
|
||||||
err = restore_d_state(regs, &sc->sc_fpregs.d);
|
err |= restore_fp_state(regs, &sc->sc_fpregs);
|
||||||
if (unlikely(err))
|
|
||||||
return err;
|
|
||||||
/* We support no other extension state at this time. */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
|
|
||||||
u32 value;
|
|
||||||
err = __get_user(value, &sc->sc_fpregs.q.reserved[i]);
|
|
||||||
if (unlikely(err))
|
|
||||||
break;
|
|
||||||
if (value != 0)
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
|
||||||
{
|
{
|
||||||
struct sigcontext __user *sc = &frame->uc.uc_mcontext;
|
struct sigcontext __user *sc = &frame->uc.uc_mcontext;
|
||||||
long err;
|
long err;
|
||||||
size_t i;
|
|
||||||
/* sc_regs is structured the same as the start of pt_regs */
|
/* sc_regs is structured the same as the start of pt_regs */
|
||||||
err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
|
err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
|
||||||
/* Save the floating-point state. */
|
/* Save the floating-point state. */
|
||||||
err |= save_d_state(regs, &sc->sc_fpregs.d);
|
err |= save_fp_state(regs, &sc->sc_fpregs);
|
||||||
/* We support no other extension state at this time. */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
|
|
||||||
err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue