diff options
author | Alan Kao <alankao@andestech.com> | 2018-10-08 22:18:31 -0400 |
---|---|---|
committer | Palmer Dabbelt <palmer@sifive.com> | 2018-10-22 20:02:23 -0400 |
commit | 007f5c35895786fdc797f13313b9493fe5d5e655 (patch) | |
tree | 37ed6cf8decee06defddd93eccc31096f32458ad | |
parent | e68ad867f77e1a839ad496ffcbd88b9c96769b5b (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.c | 68 |
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 | ||
40 | static long restore_d_state(struct pt_regs *regs, | 40 | static 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(¤t->thread.fstate, state, sizeof(*state)); | 47 | err = __copy_from_user(¤t->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 | ||
50 | static long save_d_state(struct pt_regs *regs, | 67 | static 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, ¤t->thread.fstate, sizeof(*state)); | 75 | err = __copy_to_user(state, ¤t->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 | ||
57 | static long restore_sigcontext(struct pt_regs *regs, | 89 | static 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 | ||