]>
git.ipfire.org Git - thirdparty/kernel/stable.git/blob - arch/loongarch/kernel/signal.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Author: Hanlu Li <lihanlu@loongson.cn>
4 * Huacai Chen <chenhuacai@loongson.cn>
5 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
8 * Copyright (C) 1991, 1992 Linus Torvalds
9 * Copyright (C) 1994 - 2000 Ralf Baechle
10 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
11 * Copyright (C) 2014, Imagination Technologies Ltd.
13 #include <linux/audit.h>
14 #include <linux/cache.h>
15 #include <linux/context_tracking.h>
16 #include <linux/entry-common.h>
17 #include <linux/irqflags.h>
18 #include <linux/sched.h>
20 #include <linux/personality.h>
21 #include <linux/smp.h>
22 #include <linux/kernel.h>
23 #include <linux/signal.h>
24 #include <linux/errno.h>
25 #include <linux/wait.h>
26 #include <linux/ptrace.h>
27 #include <linux/unistd.h>
28 #include <linux/compiler.h>
29 #include <linux/syscalls.h>
30 #include <linux/uaccess.h>
33 #include <asm/cacheflush.h>
34 #include <asm/cpu-features.h>
37 #include <asm/ucontext.h>
41 # define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
43 # define DEBUGP(fmt, args...)
46 /* Make sure we will not lose FPU ownership */
47 #define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
48 #define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
49 /* Make sure we will not lose LBT ownership */
50 #define lock_lbt_owner() ({ preempt_disable(); pagefault_disable(); })
51 #define unlock_lbt_owner() ({ pagefault_enable(); preempt_enable(); })
53 /* Assembly functions to move context to/from the FPU */
55 _save_fp_context(void __user
*fpregs
, void __user
*fcc
, void __user
*csr
);
57 _restore_fp_context(void __user
*fpregs
, void __user
*fcc
, void __user
*csr
);
59 _save_lsx_context(void __user
*fpregs
, void __user
*fcc
, void __user
*fcsr
);
61 _restore_lsx_context(void __user
*fpregs
, void __user
*fcc
, void __user
*fcsr
);
63 _save_lasx_context(void __user
*fpregs
, void __user
*fcc
, void __user
*fcsr
);
65 _restore_lasx_context(void __user
*fpregs
, void __user
*fcc
, void __user
*fcsr
);
67 #ifdef CONFIG_CPU_HAS_LBT
68 extern asmlinkage
int _save_lbt_context(void __user
*regs
, void __user
*eflags
);
69 extern asmlinkage
int _restore_lbt_context(void __user
*regs
, void __user
*eflags
);
70 extern asmlinkage
int _save_ftop_context(void __user
*ftop
);
71 extern asmlinkage
int _restore_ftop_context(void __user
*ftop
);
75 struct siginfo rs_info
;
76 struct ucontext rs_uctx
;
80 struct sctx_info
*addr
;
84 struct extctx_layout
{
87 struct _ctx_layout fpu
;
88 struct _ctx_layout lsx
;
89 struct _ctx_layout lasx
;
90 struct _ctx_layout lbt
;
91 struct _ctx_layout end
;
94 static void __user
*get_ctx_through_ctxinfo(struct sctx_info
*info
)
96 return (void __user
*)((char *)info
+ sizeof(struct sctx_info
));
100 * Thread saved context copy to/from a signal context presumed to be on the
101 * user stack, and therefore accessed with appropriate macros from uaccess.h.
103 static int copy_fpu_to_sigcontext(struct fpu_context __user
*ctx
)
107 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
108 uint64_t __user
*fcc
= &ctx
->fcc
;
109 uint32_t __user
*fcsr
= &ctx
->fcsr
;
111 for (i
= 0; i
< NUM_FPU_REGS
; i
++) {
113 __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 0),
116 err
|= __put_user(current
->thread
.fpu
.fcc
, fcc
);
117 err
|= __put_user(current
->thread
.fpu
.fcsr
, fcsr
);
122 static int copy_fpu_from_sigcontext(struct fpu_context __user
*ctx
)
127 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
128 uint64_t __user
*fcc
= &ctx
->fcc
;
129 uint32_t __user
*fcsr
= &ctx
->fcsr
;
131 for (i
= 0; i
< NUM_FPU_REGS
; i
++) {
132 err
|= __get_user(fpr_val
, ®s
[i
]);
133 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 0, fpr_val
);
135 err
|= __get_user(current
->thread
.fpu
.fcc
, fcc
);
136 err
|= __get_user(current
->thread
.fpu
.fcsr
, fcsr
);
141 static int copy_lsx_to_sigcontext(struct lsx_context __user
*ctx
)
145 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
146 uint64_t __user
*fcc
= &ctx
->fcc
;
147 uint32_t __user
*fcsr
= &ctx
->fcsr
;
149 for (i
= 0; i
< NUM_FPU_REGS
; i
++) {
150 err
|= __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 0),
152 err
|= __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 1),
155 err
|= __put_user(current
->thread
.fpu
.fcc
, fcc
);
156 err
|= __put_user(current
->thread
.fpu
.fcsr
, fcsr
);
161 static int copy_lsx_from_sigcontext(struct lsx_context __user
*ctx
)
166 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
167 uint64_t __user
*fcc
= &ctx
->fcc
;
168 uint32_t __user
*fcsr
= &ctx
->fcsr
;
170 for (i
= 0; i
< NUM_FPU_REGS
; i
++) {
171 err
|= __get_user(fpr_val
, ®s
[2*i
]);
172 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 0, fpr_val
);
173 err
|= __get_user(fpr_val
, ®s
[2*i
+1]);
174 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 1, fpr_val
);
176 err
|= __get_user(current
->thread
.fpu
.fcc
, fcc
);
177 err
|= __get_user(current
->thread
.fpu
.fcsr
, fcsr
);
182 static int copy_lasx_to_sigcontext(struct lasx_context __user
*ctx
)
186 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
187 uint64_t __user
*fcc
= &ctx
->fcc
;
188 uint32_t __user
*fcsr
= &ctx
->fcsr
;
190 for (i
= 0; i
< NUM_FPU_REGS
; i
++) {
191 err
|= __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 0),
193 err
|= __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 1),
195 err
|= __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 2),
197 err
|= __put_user(get_fpr64(¤t
->thread
.fpu
.fpr
[i
], 3),
200 err
|= __put_user(current
->thread
.fpu
.fcc
, fcc
);
201 err
|= __put_user(current
->thread
.fpu
.fcsr
, fcsr
);
206 static int copy_lasx_from_sigcontext(struct lasx_context __user
*ctx
)
211 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
212 uint64_t __user
*fcc
= &ctx
->fcc
;
213 uint32_t __user
*fcsr
= &ctx
->fcsr
;
215 for (i
= 0; i
< NUM_FPU_REGS
; i
++) {
216 err
|= __get_user(fpr_val
, ®s
[4*i
]);
217 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 0, fpr_val
);
218 err
|= __get_user(fpr_val
, ®s
[4*i
+1]);
219 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 1, fpr_val
);
220 err
|= __get_user(fpr_val
, ®s
[4*i
+2]);
221 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 2, fpr_val
);
222 err
|= __get_user(fpr_val
, ®s
[4*i
+3]);
223 set_fpr64(¤t
->thread
.fpu
.fpr
[i
], 3, fpr_val
);
225 err
|= __get_user(current
->thread
.fpu
.fcc
, fcc
);
226 err
|= __get_user(current
->thread
.fpu
.fcsr
, fcsr
);
231 #ifdef CONFIG_CPU_HAS_LBT
232 static int copy_lbt_to_sigcontext(struct lbt_context __user
*ctx
)
235 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
236 uint32_t __user
*eflags
= (uint32_t *)&ctx
->eflags
;
238 err
|= __put_user(current
->thread
.lbt
.scr0
, ®s
[0]);
239 err
|= __put_user(current
->thread
.lbt
.scr1
, ®s
[1]);
240 err
|= __put_user(current
->thread
.lbt
.scr2
, ®s
[2]);
241 err
|= __put_user(current
->thread
.lbt
.scr3
, ®s
[3]);
242 err
|= __put_user(current
->thread
.lbt
.eflags
, eflags
);
247 static int copy_lbt_from_sigcontext(struct lbt_context __user
*ctx
)
250 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
251 uint32_t __user
*eflags
= (uint32_t *)&ctx
->eflags
;
253 err
|= __get_user(current
->thread
.lbt
.scr0
, ®s
[0]);
254 err
|= __get_user(current
->thread
.lbt
.scr1
, ®s
[1]);
255 err
|= __get_user(current
->thread
.lbt
.scr2
, ®s
[2]);
256 err
|= __get_user(current
->thread
.lbt
.scr3
, ®s
[3]);
257 err
|= __get_user(current
->thread
.lbt
.eflags
, eflags
);
262 static int copy_ftop_to_sigcontext(struct lbt_context __user
*ctx
)
264 uint32_t __user
*ftop
= &ctx
->ftop
;
266 return __put_user(current
->thread
.fpu
.ftop
, ftop
);
269 static int copy_ftop_from_sigcontext(struct lbt_context __user
*ctx
)
271 uint32_t __user
*ftop
= &ctx
->ftop
;
273 return __get_user(current
->thread
.fpu
.ftop
, ftop
);
278 * Wrappers for the assembly _{save,restore}_fp_context functions.
280 static int save_hw_fpu_context(struct fpu_context __user
*ctx
)
282 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
283 uint64_t __user
*fcc
= &ctx
->fcc
;
284 uint32_t __user
*fcsr
= &ctx
->fcsr
;
286 return _save_fp_context(regs
, fcc
, fcsr
);
289 static int restore_hw_fpu_context(struct fpu_context __user
*ctx
)
291 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
292 uint64_t __user
*fcc
= &ctx
->fcc
;
293 uint32_t __user
*fcsr
= &ctx
->fcsr
;
295 return _restore_fp_context(regs
, fcc
, fcsr
);
298 static int save_hw_lsx_context(struct lsx_context __user
*ctx
)
300 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
301 uint64_t __user
*fcc
= &ctx
->fcc
;
302 uint32_t __user
*fcsr
= &ctx
->fcsr
;
304 return _save_lsx_context(regs
, fcc
, fcsr
);
307 static int restore_hw_lsx_context(struct lsx_context __user
*ctx
)
309 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
310 uint64_t __user
*fcc
= &ctx
->fcc
;
311 uint32_t __user
*fcsr
= &ctx
->fcsr
;
313 return _restore_lsx_context(regs
, fcc
, fcsr
);
316 static int save_hw_lasx_context(struct lasx_context __user
*ctx
)
318 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
319 uint64_t __user
*fcc
= &ctx
->fcc
;
320 uint32_t __user
*fcsr
= &ctx
->fcsr
;
322 return _save_lasx_context(regs
, fcc
, fcsr
);
325 static int restore_hw_lasx_context(struct lasx_context __user
*ctx
)
327 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
328 uint64_t __user
*fcc
= &ctx
->fcc
;
329 uint32_t __user
*fcsr
= &ctx
->fcsr
;
331 return _restore_lasx_context(regs
, fcc
, fcsr
);
335 * Wrappers for the assembly _{save,restore}_lbt_context functions.
337 #ifdef CONFIG_CPU_HAS_LBT
338 static int save_hw_lbt_context(struct lbt_context __user
*ctx
)
340 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
341 uint32_t __user
*eflags
= (uint32_t *)&ctx
->eflags
;
343 return _save_lbt_context(regs
, eflags
);
346 static int restore_hw_lbt_context(struct lbt_context __user
*ctx
)
348 uint64_t __user
*regs
= (uint64_t *)&ctx
->regs
;
349 uint32_t __user
*eflags
= (uint32_t *)&ctx
->eflags
;
351 return _restore_lbt_context(regs
, eflags
);
354 static int save_hw_ftop_context(struct lbt_context __user
*ctx
)
356 uint32_t __user
*ftop
= &ctx
->ftop
;
358 return _save_ftop_context(ftop
);
361 static int restore_hw_ftop_context(struct lbt_context __user
*ctx
)
363 uint32_t __user
*ftop
= &ctx
->ftop
;
365 return _restore_ftop_context(ftop
);
369 static int fcsr_pending(unsigned int __user
*fcsr
)
372 unsigned int csr
, enabled
;
374 err
= __get_user(csr
, fcsr
);
375 enabled
= ((csr
& FPU_CSR_ALL_E
) << 24);
377 * If the signal handler set some FPU exceptions, clear it and
382 err
|= __put_user(csr
, fcsr
);
391 static int protected_save_fpu_context(struct extctx_layout
*extctx
)
394 struct sctx_info __user
*info
= extctx
->fpu
.addr
;
395 struct fpu_context __user
*fpu_ctx
= (struct fpu_context
*)get_ctx_through_ctxinfo(info
);
396 uint64_t __user
*regs
= (uint64_t *)&fpu_ctx
->regs
;
397 uint64_t __user
*fcc
= &fpu_ctx
->fcc
;
398 uint32_t __user
*fcsr
= &fpu_ctx
->fcsr
;
403 err
= save_hw_fpu_context(fpu_ctx
);
405 err
= copy_fpu_to_sigcontext(fpu_ctx
);
408 err
|= __put_user(FPU_CTX_MAGIC
, &info
->magic
);
409 err
|= __put_user(extctx
->fpu
.size
, &info
->size
);
413 /* Touch the FPU context and try again */
414 err
= __put_user(0, ®s
[0]) |
415 __put_user(0, ®s
[31]) |
419 return err
; /* really bad sigcontext */
425 static int protected_restore_fpu_context(struct extctx_layout
*extctx
)
427 int err
= 0, sig
= 0, tmp __maybe_unused
;
428 struct sctx_info __user
*info
= extctx
->fpu
.addr
;
429 struct fpu_context __user
*fpu_ctx
= (struct fpu_context
*)get_ctx_through_ctxinfo(info
);
430 uint64_t __user
*regs
= (uint64_t *)&fpu_ctx
->regs
;
431 uint64_t __user
*fcc
= &fpu_ctx
->fcc
;
432 uint32_t __user
*fcsr
= &fpu_ctx
->fcsr
;
434 err
= sig
= fcsr_pending(fcsr
);
441 err
= restore_hw_fpu_context(fpu_ctx
);
443 err
= copy_fpu_from_sigcontext(fpu_ctx
);
448 /* Touch the FPU context and try again */
449 err
= __get_user(tmp
, ®s
[0]) |
450 __get_user(tmp
, ®s
[31]) |
451 __get_user(tmp
, fcc
) |
452 __get_user(tmp
, fcsr
);
454 break; /* really bad sigcontext */
460 static int protected_save_lsx_context(struct extctx_layout
*extctx
)
463 struct sctx_info __user
*info
= extctx
->lsx
.addr
;
464 struct lsx_context __user
*lsx_ctx
= (struct lsx_context
*)get_ctx_through_ctxinfo(info
);
465 uint64_t __user
*regs
= (uint64_t *)&lsx_ctx
->regs
;
466 uint64_t __user
*fcc
= &lsx_ctx
->fcc
;
467 uint32_t __user
*fcsr
= &lsx_ctx
->fcsr
;
471 if (is_lsx_enabled())
472 err
= save_hw_lsx_context(lsx_ctx
);
476 err
= copy_lsx_to_sigcontext(lsx_ctx
);
480 err
|= __put_user(LSX_CTX_MAGIC
, &info
->magic
);
481 err
|= __put_user(extctx
->lsx
.size
, &info
->size
);
485 /* Touch the LSX context and try again */
486 err
= __put_user(0, ®s
[0]) |
487 __put_user(0, ®s
[32*2-1]) |
491 return err
; /* really bad sigcontext */
497 static int protected_restore_lsx_context(struct extctx_layout
*extctx
)
499 int err
= 0, sig
= 0, tmp __maybe_unused
;
500 struct sctx_info __user
*info
= extctx
->lsx
.addr
;
501 struct lsx_context __user
*lsx_ctx
= (struct lsx_context
*)get_ctx_through_ctxinfo(info
);
502 uint64_t __user
*regs
= (uint64_t *)&lsx_ctx
->regs
;
503 uint64_t __user
*fcc
= &lsx_ctx
->fcc
;
504 uint32_t __user
*fcsr
= &lsx_ctx
->fcsr
;
506 err
= sig
= fcsr_pending(fcsr
);
512 if (is_lsx_enabled())
513 err
= restore_hw_lsx_context(lsx_ctx
);
515 err
= copy_lsx_from_sigcontext(lsx_ctx
);
523 /* Touch the LSX context and try again */
524 err
= __get_user(tmp
, ®s
[0]) |
525 __get_user(tmp
, ®s
[32*2-1]) |
526 __get_user(tmp
, fcc
) |
527 __get_user(tmp
, fcsr
);
529 break; /* really bad sigcontext */
535 static int protected_save_lasx_context(struct extctx_layout
*extctx
)
538 struct sctx_info __user
*info
= extctx
->lasx
.addr
;
539 struct lasx_context __user
*lasx_ctx
=
540 (struct lasx_context
*)get_ctx_through_ctxinfo(info
);
541 uint64_t __user
*regs
= (uint64_t *)&lasx_ctx
->regs
;
542 uint64_t __user
*fcc
= &lasx_ctx
->fcc
;
543 uint32_t __user
*fcsr
= &lasx_ctx
->fcsr
;
547 if (is_lasx_enabled())
548 err
= save_hw_lasx_context(lasx_ctx
);
550 if (is_lsx_enabled())
552 else if (is_fpu_owner())
554 err
= copy_lasx_to_sigcontext(lasx_ctx
);
558 err
|= __put_user(LASX_CTX_MAGIC
, &info
->magic
);
559 err
|= __put_user(extctx
->lasx
.size
, &info
->size
);
563 /* Touch the LASX context and try again */
564 err
= __put_user(0, ®s
[0]) |
565 __put_user(0, ®s
[32*4-1]) |
569 return err
; /* really bad sigcontext */
575 static int protected_restore_lasx_context(struct extctx_layout
*extctx
)
577 int err
= 0, sig
= 0, tmp __maybe_unused
;
578 struct sctx_info __user
*info
= extctx
->lasx
.addr
;
579 struct lasx_context __user
*lasx_ctx
=
580 (struct lasx_context
*)get_ctx_through_ctxinfo(info
);
581 uint64_t __user
*regs
= (uint64_t *)&lasx_ctx
->regs
;
582 uint64_t __user
*fcc
= &lasx_ctx
->fcc
;
583 uint32_t __user
*fcsr
= &lasx_ctx
->fcsr
;
585 err
= sig
= fcsr_pending(fcsr
);
591 if (is_lasx_enabled())
592 err
= restore_hw_lasx_context(lasx_ctx
);
594 err
= copy_lasx_from_sigcontext(lasx_ctx
);
595 if (is_lsx_enabled())
596 restore_lsx(current
);
597 else if (is_fpu_owner())
604 /* Touch the LASX context and try again */
605 err
= __get_user(tmp
, ®s
[0]) |
606 __get_user(tmp
, ®s
[32*4-1]) |
607 __get_user(tmp
, fcc
) |
608 __get_user(tmp
, fcsr
);
610 break; /* really bad sigcontext */
616 #ifdef CONFIG_CPU_HAS_LBT
617 static int protected_save_lbt_context(struct extctx_layout
*extctx
)
620 struct sctx_info __user
*info
= extctx
->lbt
.addr
;
621 struct lbt_context __user
*lbt_ctx
=
622 (struct lbt_context
*)get_ctx_through_ctxinfo(info
);
623 uint64_t __user
*regs
= (uint64_t *)&lbt_ctx
->regs
;
624 uint32_t __user
*eflags
= (uint32_t *)&lbt_ctx
->eflags
;
629 err
|= save_hw_lbt_context(lbt_ctx
);
631 err
|= copy_lbt_to_sigcontext(lbt_ctx
);
633 err
|= save_hw_ftop_context(lbt_ctx
);
635 err
|= copy_ftop_to_sigcontext(lbt_ctx
);
638 err
|= __put_user(LBT_CTX_MAGIC
, &info
->magic
);
639 err
|= __put_user(extctx
->lbt
.size
, &info
->size
);
643 /* Touch the LBT context and try again */
644 err
= __put_user(0, ®s
[0]) | __put_user(0, eflags
);
653 static int protected_restore_lbt_context(struct extctx_layout
*extctx
)
655 int err
= 0, tmp __maybe_unused
;
656 struct sctx_info __user
*info
= extctx
->lbt
.addr
;
657 struct lbt_context __user
*lbt_ctx
=
658 (struct lbt_context
*)get_ctx_through_ctxinfo(info
);
659 uint64_t __user
*regs
= (uint64_t *)&lbt_ctx
->regs
;
660 uint32_t __user
*eflags
= (uint32_t *)&lbt_ctx
->eflags
;
665 err
|= restore_hw_lbt_context(lbt_ctx
);
667 err
|= copy_lbt_from_sigcontext(lbt_ctx
);
669 err
|= restore_hw_ftop_context(lbt_ctx
);
671 err
|= copy_ftop_from_sigcontext(lbt_ctx
);
676 /* Touch the LBT context and try again */
677 err
= __get_user(tmp
, ®s
[0]) | __get_user(tmp
, eflags
);
687 static int setup_sigcontext(struct pt_regs
*regs
, struct sigcontext __user
*sc
,
688 struct extctx_layout
*extctx
)
691 struct sctx_info __user
*info
;
693 err
|= __put_user(regs
->csr_era
, &sc
->sc_pc
);
694 err
|= __put_user(extctx
->flags
, &sc
->sc_flags
);
696 err
|= __put_user(0, &sc
->sc_regs
[0]);
697 for (i
= 1; i
< 32; i
++)
698 err
|= __put_user(regs
->regs
[i
], &sc
->sc_regs
[i
]);
700 if (extctx
->lasx
.addr
)
701 err
|= protected_save_lasx_context(extctx
);
702 else if (extctx
->lsx
.addr
)
703 err
|= protected_save_lsx_context(extctx
);
704 else if (extctx
->fpu
.addr
)
705 err
|= protected_save_fpu_context(extctx
);
707 #ifdef CONFIG_CPU_HAS_LBT
708 if (extctx
->lbt
.addr
)
709 err
|= protected_save_lbt_context(extctx
);
712 /* Set the "end" magic */
713 info
= (struct sctx_info
*)extctx
->end
.addr
;
714 err
|= __put_user(0, &info
->magic
);
715 err
|= __put_user(0, &info
->size
);
720 static int parse_extcontext(struct sigcontext __user
*sc
, struct extctx_layout
*extctx
)
723 unsigned int magic
, size
;
724 struct sctx_info __user
*info
= (struct sctx_info __user
*)&sc
->sc_extcontext
;
727 err
|= __get_user(magic
, &info
->magic
);
728 err
|= __get_user(size
, &info
->size
);
737 if (size
< (sizeof(struct sctx_info
) +
738 sizeof(struct fpu_context
)))
740 extctx
->fpu
.addr
= info
;
744 if (size
< (sizeof(struct sctx_info
) +
745 sizeof(struct lsx_context
)))
747 extctx
->lsx
.addr
= info
;
751 if (size
< (sizeof(struct sctx_info
) +
752 sizeof(struct lasx_context
)))
754 extctx
->lasx
.addr
= info
;
758 if (size
< (sizeof(struct sctx_info
) +
759 sizeof(struct lbt_context
)))
761 extctx
->lbt
.addr
= info
;
768 info
= (struct sctx_info
*)((char *)info
+ size
);
778 static int restore_sigcontext(struct pt_regs
*regs
, struct sigcontext __user
*sc
)
781 struct extctx_layout extctx
;
783 memset(&extctx
, 0, sizeof(struct extctx_layout
));
785 err
= __get_user(extctx
.flags
, &sc
->sc_flags
);
789 err
= parse_extcontext(sc
, &extctx
);
793 conditional_used_math(extctx
.flags
& SC_USED_FP
);
796 * The signal handler may have used FPU; give it up if the program
797 * doesn't want it following sigreturn.
799 if (!(extctx
.flags
& SC_USED_FP
))
802 /* Always make any pending restarted system calls return -EINTR */
803 current
->restart_block
.fn
= do_no_restart_syscall
;
805 err
|= __get_user(regs
->csr_era
, &sc
->sc_pc
);
806 for (i
= 1; i
< 32; i
++)
807 err
|= __get_user(regs
->regs
[i
], &sc
->sc_regs
[i
]);
809 if (extctx
.lasx
.addr
)
810 err
|= protected_restore_lasx_context(&extctx
);
811 else if (extctx
.lsx
.addr
)
812 err
|= protected_restore_lsx_context(&extctx
);
813 else if (extctx
.fpu
.addr
)
814 err
|= protected_restore_fpu_context(&extctx
);
816 #ifdef CONFIG_CPU_HAS_LBT
818 err
|= protected_restore_lbt_context(&extctx
);
825 static unsigned int handle_flags(void)
827 unsigned int flags
= 0;
829 flags
= used_math() ? SC_USED_FP
: 0;
831 switch (current
->thread
.error_code
) {
833 flags
|= SC_ADDRERR_RD
;
836 flags
|= SC_ADDRERR_WR
;
843 static unsigned long extframe_alloc(struct extctx_layout
*extctx
,
844 struct _ctx_layout
*layout
,
845 size_t size
, unsigned int align
, unsigned long base
)
847 unsigned long new_base
= base
- size
;
849 new_base
= round_down(new_base
, (align
< 16 ? 16 : align
));
850 new_base
-= sizeof(struct sctx_info
);
852 layout
->addr
= (void *)new_base
;
853 layout
->size
= (unsigned int)(base
- new_base
);
854 extctx
->size
+= layout
->size
;
859 static unsigned long setup_extcontext(struct extctx_layout
*extctx
, unsigned long sp
)
861 unsigned long new_sp
= sp
;
863 memset(extctx
, 0, sizeof(struct extctx_layout
));
865 extctx
->flags
= handle_flags();
867 /* Grow down, alloc "end" context info first. */
868 new_sp
-= sizeof(struct sctx_info
);
869 extctx
->end
.addr
= (void *)new_sp
;
870 extctx
->end
.size
= (unsigned int)sizeof(struct sctx_info
);
871 extctx
->size
+= extctx
->end
.size
;
873 if (extctx
->flags
& SC_USED_FP
) {
874 if (cpu_has_lasx
&& thread_lasx_context_live())
875 new_sp
= extframe_alloc(extctx
, &extctx
->lasx
,
876 sizeof(struct lasx_context
), LASX_CTX_ALIGN
, new_sp
);
877 else if (cpu_has_lsx
&& thread_lsx_context_live())
878 new_sp
= extframe_alloc(extctx
, &extctx
->lsx
,
879 sizeof(struct lsx_context
), LSX_CTX_ALIGN
, new_sp
);
880 else if (cpu_has_fpu
)
881 new_sp
= extframe_alloc(extctx
, &extctx
->fpu
,
882 sizeof(struct fpu_context
), FPU_CTX_ALIGN
, new_sp
);
885 #ifdef CONFIG_CPU_HAS_LBT
886 if (cpu_has_lbt
&& thread_lbt_context_live()) {
887 new_sp
= extframe_alloc(extctx
, &extctx
->lbt
,
888 sizeof(struct lbt_context
), LBT_CTX_ALIGN
, new_sp
);
895 static void __user
*get_sigframe(struct ksignal
*ksig
, struct pt_regs
*regs
,
896 struct extctx_layout
*extctx
)
900 /* Default to using normal stack */
904 * If we are on the alternate signal stack and would overflow it, don't.
905 * Return an always-bogus address instead so we will die with SIGSEGV.
907 if (on_sig_stack(sp
) &&
908 !likely(on_sig_stack(sp
- sizeof(struct rt_sigframe
))))
909 return (void __user __force
*)(-1UL);
911 sp
= sigsp(sp
, ksig
);
912 sp
= round_down(sp
, 16);
913 sp
= setup_extcontext(extctx
, sp
);
914 sp
-= sizeof(struct rt_sigframe
);
916 if (!IS_ALIGNED(sp
, 16))
919 return (void __user
*)sp
;
923 * Atomically swap in the new signal mask, and wait for a signal.
926 SYSCALL_DEFINE0(rt_sigreturn
)
930 struct pt_regs
*regs
;
931 struct rt_sigframe __user
*frame
;
933 regs
= current_pt_regs();
934 frame
= (struct rt_sigframe __user
*)regs
->regs
[3];
935 if (!access_ok(frame
, sizeof(*frame
)))
937 if (__copy_from_user(&set
, &frame
->rs_uctx
.uc_sigmask
, sizeof(set
)))
940 set_current_blocked(&set
);
942 sig
= restore_sigcontext(regs
, &frame
->rs_uctx
.uc_mcontext
);
948 regs
->regs
[0] = 0; /* No syscall restarting */
949 if (restore_altstack(&frame
->rs_uctx
.uc_stack
))
952 return regs
->regs
[4];
959 static int setup_rt_frame(void *sig_return
, struct ksignal
*ksig
,
960 struct pt_regs
*regs
, sigset_t
*set
)
963 struct extctx_layout extctx
;
964 struct rt_sigframe __user
*frame
;
966 frame
= get_sigframe(ksig
, regs
, &extctx
);
967 if (!access_ok(frame
, sizeof(*frame
) + extctx
.size
))
970 /* Create siginfo. */
971 err
|= copy_siginfo_to_user(&frame
->rs_info
, &ksig
->info
);
973 /* Create the ucontext. */
974 err
|= __put_user(0, &frame
->rs_uctx
.uc_flags
);
975 err
|= __put_user(NULL
, &frame
->rs_uctx
.uc_link
);
976 err
|= __save_altstack(&frame
->rs_uctx
.uc_stack
, regs
->regs
[3]);
977 err
|= setup_sigcontext(regs
, &frame
->rs_uctx
.uc_mcontext
, &extctx
);
978 err
|= __copy_to_user(&frame
->rs_uctx
.uc_sigmask
, set
, sizeof(*set
));
984 * Arguments to signal handler:
987 * a1 = pointer to siginfo
988 * a2 = pointer to ucontext
990 * c0_era point to the signal handler, $r3 (sp) points to
991 * the struct rt_sigframe.
993 regs
->regs
[4] = ksig
->sig
;
994 regs
->regs
[5] = (unsigned long) &frame
->rs_info
;
995 regs
->regs
[6] = (unsigned long) &frame
->rs_uctx
;
996 regs
->regs
[3] = (unsigned long) frame
;
997 regs
->regs
[1] = (unsigned long) sig_return
;
998 regs
->csr_era
= (unsigned long) ksig
->ka
.sa
.sa_handler
;
1000 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
1001 current
->comm
, current
->pid
,
1002 frame
, regs
->csr_era
, regs
->regs
[1]);
1007 static void handle_signal(struct ksignal
*ksig
, struct pt_regs
*regs
)
1010 sigset_t
*oldset
= sigmask_to_save();
1011 void *vdso
= current
->mm
->context
.vdso
;
1013 /* Are we from a system call? */
1014 if (regs
->regs
[0]) {
1015 switch (regs
->regs
[4]) {
1016 case -ERESTART_RESTARTBLOCK
:
1017 case -ERESTARTNOHAND
:
1018 regs
->regs
[4] = -EINTR
;
1021 if (!(ksig
->ka
.sa
.sa_flags
& SA_RESTART
)) {
1022 regs
->regs
[4] = -EINTR
;
1026 case -ERESTARTNOINTR
:
1027 regs
->regs
[4] = regs
->orig_a0
;
1031 regs
->regs
[0] = 0; /* Don't deal with this again. */
1034 rseq_signal_deliver(ksig
, regs
);
1036 ret
= setup_rt_frame(vdso
+ current
->thread
.vdso
->offset_sigreturn
, ksig
, regs
, oldset
);
1038 signal_setup_done(ret
, ksig
, 0);
1041 void arch_do_signal_or_restart(struct pt_regs
*regs
)
1043 struct ksignal ksig
;
1045 if (get_signal(&ksig
)) {
1046 /* Whee! Actually deliver the signal. */
1047 handle_signal(&ksig
, regs
);
1051 /* Are we from a system call? */
1052 if (regs
->regs
[0]) {
1053 switch (regs
->regs
[4]) {
1054 case -ERESTARTNOHAND
:
1056 case -ERESTARTNOINTR
:
1057 regs
->regs
[4] = regs
->orig_a0
;
1061 case -ERESTART_RESTARTBLOCK
:
1062 regs
->regs
[4] = regs
->orig_a0
;
1063 regs
->regs
[11] = __NR_restart_syscall
;
1067 regs
->regs
[0] = 0; /* Don't deal with this again. */
1071 * If there's no signal to deliver, we just put the saved sigmask
1074 restore_saved_sigmask();