aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Kao <alankao@andestech.com>2018-10-08 22:18:31 -0400
committerPalmer Dabbelt <palmer@sifive.com>2018-10-22 20:02:23 -0400
commit007f5c35895786fdc797f13313b9493fe5d5e655 (patch)
tree37ed6cf8decee06defddd93eccc31096f32458ad
parente68ad867f77e1a839ad496ffcbd88b9c96769b5b (diff)
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>
-rw-r--r--arch/riscv/kernel/signal.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
37 struct ucontext uc; 37 struct ucontext uc;
38}; 38};
39 39
40static long restore_d_state(struct pt_regs *regs, 40static long restore_fp_state(struct pt_regs *regs,
41 struct __riscv_d_ext_state __user *state) 41 union __riscv_fp_state *sc_fpregs)
42{ 42{
43 long err; 43 long err;
44 struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
45 size_t i;
46
44 err = __copy_from_user(&current->thread.fstate, state, sizeof(*state)); 47 err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
45 if (likely(!err)) 48 if (unlikely(err))
46 fstate_restore(current, regs); 49 return err;
50
51 fstate_restore(current, regs);
52
53 /* We support no other extension state at this time. */
54 for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
55 u32 value;
56
57 err = __get_user(value, &sc_fpregs->q.reserved[i]);
58 if (unlikely(err))
59 break;
60 if (value != 0)
61 return -EINVAL;
62 }
63
47 return err; 64 return err;
48} 65}
49 66
50static long save_d_state(struct pt_regs *regs, 67static long save_fp_state(struct pt_regs *regs,
51 struct __riscv_d_ext_state __user *state) 68 union __riscv_fp_state *sc_fpregs)
52{ 69{
70 long err;
71 struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
72 size_t i;
73
53 fstate_save(current, regs); 74 fstate_save(current, regs);
54 return __copy_to_user(state, &current->thread.fstate, sizeof(*state)); 75 err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
76 if (unlikely(err))
77 return err;
78
79 /* We support no other extension state at this time. */
80 for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
81 err = __put_user(0, &sc_fpregs->q.reserved[i]);
82 if (unlikely(err))
83 break;
84 }
85
86 return err;
55} 87}
56 88
57static long restore_sigcontext(struct pt_regs *regs, 89static long restore_sigcontext(struct pt_regs *regs,
58 struct sigcontext __user *sc) 90 struct sigcontext __user *sc)
59{ 91{
60 long err; 92 long err;
61 size_t i;
62 /* sc_regs is structured the same as the start of pt_regs */ 93 /* sc_regs is structured the same as the start of pt_regs */
63 err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); 94 err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
64 if (unlikely(err))
65 return err;
66 /* Restore the floating-point state. */ 95 /* Restore the floating-point state. */
67 err = restore_d_state(regs, &sc->sc_fpregs.d); 96 err |= restore_fp_state(regs, &sc->sc_fpregs);
68 if (unlikely(err))
69 return err;
70 /* We support no other extension state at this time. */
71 for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
72 u32 value;
73 err = __get_user(value, &sc->sc_fpregs.q.reserved[i]);
74 if (unlikely(err))
75 break;
76 if (value != 0)
77 return -EINVAL;
78 }
79 return err; 97 return err;
80} 98}
81 99
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
124{ 142{
125 struct sigcontext __user *sc = &frame->uc.uc_mcontext; 143 struct sigcontext __user *sc = &frame->uc.uc_mcontext;
126 long err; 144 long err;
127 size_t i;
128 /* sc_regs is structured the same as the start of pt_regs */ 145 /* sc_regs is structured the same as the start of pt_regs */
129 err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); 146 err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
130 /* Save the floating-point state. */ 147 /* Save the floating-point state. */
131 err |= save_d_state(regs, &sc->sc_fpregs.d); 148 err |= save_fp_state(regs, &sc->sc_fpregs);
132 /* We support no other extension state at this time. */
133 for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
134 err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]);
135 return err; 149 return err;
136} 150}
137 151