aboutsummaryrefslogtreecommitdiffstats
path: root/arch/hexagon/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/hexagon/kernel/signal.c')
-rw-r--r--arch/hexagon/kernel/signal.c57
1 files changed, 20 insertions, 37 deletions
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index d7c73874b515..eadd70e47e7e 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -36,18 +36,10 @@ struct rt_sigframe {
36 struct ucontext uc; 36 struct ucontext uc;
37}; 37};
38 38
39static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, 39static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
40 size_t frame_size) 40 size_t frame_size)
41{ 41{
42 unsigned long sp = regs->r29; 42 unsigned long sp = sigsp(regs->r29, ksig);
43
44 /* check if we would overflow the alt stack */
45 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
46 return (void __user __force *)-1UL;
47
48 /* Switch to signal stack if appropriate */
49 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
50 sp = current->sas_ss_sp + current->sas_ss_size;
51 43
52 return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1)); 44 return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
53} 45}
@@ -112,20 +104,20 @@ static int restore_sigcontext(struct pt_regs *regs,
112/* 104/*
113 * Setup signal stack frame with siginfo structure 105 * Setup signal stack frame with siginfo structure
114 */ 106 */
115static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, 107static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
116 sigset_t *set, struct pt_regs *regs) 108 struct pt_regs *regs)
117{ 109{
118 int err = 0; 110 int err = 0;
119 struct rt_sigframe __user *frame; 111 struct rt_sigframe __user *frame;
120 struct hexagon_vdso *vdso = current->mm->context.vdso; 112 struct hexagon_vdso *vdso = current->mm->context.vdso;
121 113
122 frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe)); 114 frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
123 115
124 if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe))) 116 if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
125 goto sigsegv; 117 return -EFAULT;
126 118
127 if (copy_siginfo_to_user(&frame->info, info)) 119 if (copy_siginfo_to_user(&frame->info, &ksig->info))
128 goto sigsegv; 120 return -EFAULT;
129 121
130 /* The on-stack signal trampoline is no longer executed; 122 /* The on-stack signal trampoline is no longer executed;
131 * however, the libgcc signal frame unwinding code checks for 123 * however, the libgcc signal frame unwinding code checks for
@@ -137,29 +129,26 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
137 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 129 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
138 err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs)); 130 err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
139 if (err) 131 if (err)
140 goto sigsegv; 132 return -EFAULT;
141 133
142 /* Load r0/r1 pair with signumber/siginfo pointer... */ 134 /* Load r0/r1 pair with signumber/siginfo pointer... */
143 regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32) 135 regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
144 | (unsigned long long)signr; 136 | (unsigned long long)ksig->sig;
145 regs->r02 = (unsigned long) &frame->uc; 137 regs->r02 = (unsigned long) &frame->uc;
146 regs->r31 = (unsigned long) vdso->rt_signal_trampoline; 138 regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
147 pt_psp(regs) = (unsigned long) frame; 139 pt_psp(regs) = (unsigned long) frame;
148 pt_set_elr(regs, (unsigned long)ka->sa.sa_handler); 140 pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
149 141
150 return 0; 142 return 0;
151
152sigsegv:
153 force_sigsegv(signr, current);
154 return -EFAULT;
155} 143}
156 144
157/* 145/*
158 * Setup invocation of signal handler 146 * Setup invocation of signal handler
159 */ 147 */
160static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, 148static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
161 struct pt_regs *regs)
162{ 149{
150 int ret;
151
163 /* 152 /*
164 * If we're handling a signal that aborted a system call, 153 * If we're handling a signal that aborted a system call,
165 * set up the error return value before adding the signal 154 * set up the error return value before adding the signal
@@ -173,7 +162,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
173 regs->r00 = -EINTR; 162 regs->r00 = -EINTR;
174 break; 163 break;
175 case -ERESTARTSYS: 164 case -ERESTARTSYS:
176 if (!(ka->sa.sa_flags & SA_RESTART)) { 165 if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
177 regs->r00 = -EINTR; 166 regs->r00 = -EINTR;
178 break; 167 break;
179 } 168 }
@@ -193,11 +182,9 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
193 * only set up the rt_frame flavor. 182 * only set up the rt_frame flavor.
194 */ 183 */
195 /* If there was an error on setup, no signal was delivered. */ 184 /* If there was an error on setup, no signal was delivered. */
196 if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) 185 ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
197 return;
198 186
199 signal_delivered(sig, info, ka, regs, 187 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
200 test_thread_flag(TIF_SINGLESTEP));
201} 188}
202 189
203/* 190/*
@@ -205,17 +192,13 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
205 */ 192 */
206void do_signal(struct pt_regs *regs) 193void do_signal(struct pt_regs *regs)
207{ 194{
208 struct k_sigaction sigact; 195 struct ksignal ksig;
209 siginfo_t info;
210 int signo;
211 196
212 if (!user_mode(regs)) 197 if (!user_mode(regs))
213 return; 198 return;
214 199
215 signo = get_signal_to_deliver(&info, &sigact, regs, NULL); 200 if (get_signal(&ksig)) {
216 201 handle_signal(&ksig, regs);
217 if (signo > 0) {
218 handle_signal(signo, &info, &sigact, regs);
219 return; 202 return;
220 } 203 }
221 204