signal.c (34069d12e239ae8f36dd96c378e4622fb1c42a76) signal.c (bd3c5798484aa9a08302a844d7a75a2ee3b53d05)
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Author: Hanlu Li <lihanlu@loongson.cn>
4 * Huacai Chen <chenhuacai@loongson.cn>
5 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
6 *
7 * Derived from MIPS:
8 * Copyright (C) 1991, 1992 Linus Torvalds

--- 18 unchanged lines hidden (view full) ---

27#include <linux/compiler.h>
28#include <linux/syscalls.h>
29#include <linux/uaccess.h>
30
31#include <asm/asm.h>
32#include <asm/cacheflush.h>
33#include <asm/cpu-features.h>
34#include <asm/fpu.h>
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Author: Hanlu Li <lihanlu@loongson.cn>
4 * Huacai Chen <chenhuacai@loongson.cn>
5 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
6 *
7 * Derived from MIPS:
8 * Copyright (C) 1991, 1992 Linus Torvalds

--- 18 unchanged lines hidden (view full) ---

27#include <linux/compiler.h>
28#include <linux/syscalls.h>
29#include <linux/uaccess.h>
30
31#include <asm/asm.h>
32#include <asm/cacheflush.h>
33#include <asm/cpu-features.h>
34#include <asm/fpu.h>
35#include <asm/lbt.h>
35#include <asm/ucontext.h>
36#include <asm/vdso.h>
37
38#ifdef DEBUG_SIG
39# define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
40#else
41# define DEBUGP(fmt, args...)
42#endif
43
44/* Make sure we will not lose FPU ownership */
45#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
46#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
36#include <asm/ucontext.h>
37#include <asm/vdso.h>
38
39#ifdef DEBUG_SIG
40# define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
41#else
42# define DEBUGP(fmt, args...)
43#endif
44
45/* Make sure we will not lose FPU ownership */
46#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
47#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
48/* Make sure we will not lose LBT ownership */
49#define lock_lbt_owner() ({ preempt_disable(); pagefault_disable(); })
50#define unlock_lbt_owner() ({ pagefault_enable(); preempt_enable(); })
47
48/* Assembly functions to move context to/from the FPU */
49extern asmlinkage int
50_save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
51extern asmlinkage int
52_restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
53extern asmlinkage int
54_save_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
55extern asmlinkage int
56_restore_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
57extern asmlinkage int
58_save_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
59extern asmlinkage int
60_restore_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
61
51
52/* Assembly functions to move context to/from the FPU */
53extern asmlinkage int
54_save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
55extern asmlinkage int
56_restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
57extern asmlinkage int
58_save_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
59extern asmlinkage int
60_restore_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
61extern asmlinkage int
62_save_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
63extern asmlinkage int
64_restore_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
65
66#ifdef CONFIG_CPU_HAS_LBT
67extern asmlinkage int _save_lbt_context(void __user *regs, void __user *eflags);
68extern asmlinkage int _restore_lbt_context(void __user *regs, void __user *eflags);
69extern asmlinkage int _save_ftop_context(void __user *ftop);
70extern asmlinkage int _restore_ftop_context(void __user *ftop);
71#endif
72
62struct rt_sigframe {
63 struct siginfo rs_info;
64 struct ucontext rs_uctx;
65};
66
67struct _ctx_layout {
68 struct sctx_info *addr;
69 unsigned int size;
70};
71
72struct extctx_layout {
73 unsigned long size;
74 unsigned int flags;
75 struct _ctx_layout fpu;
76 struct _ctx_layout lsx;
77 struct _ctx_layout lasx;
73struct rt_sigframe {
74 struct siginfo rs_info;
75 struct ucontext rs_uctx;
76};
77
78struct _ctx_layout {
79 struct sctx_info *addr;
80 unsigned int size;
81};
82
83struct extctx_layout {
84 unsigned long size;
85 unsigned int flags;
86 struct _ctx_layout fpu;
87 struct _ctx_layout lsx;
88 struct _ctx_layout lasx;
89 struct _ctx_layout lbt;
78 struct _ctx_layout end;
79};
80
81static void __user *get_ctx_through_ctxinfo(struct sctx_info *info)
82{
83 return (void __user *)((char *)info + sizeof(struct sctx_info));
84}
85

--- 124 unchanged lines hidden (view full) ---

210 set_fpr64(&current->thread.fpu.fpr[i], 3, fpr_val);
211 }
212 err |= __get_user(current->thread.fpu.fcc, fcc);
213 err |= __get_user(current->thread.fpu.fcsr, fcsr);
214
215 return err;
216}
217
90 struct _ctx_layout end;
91};
92
93static void __user *get_ctx_through_ctxinfo(struct sctx_info *info)
94{
95 return (void __user *)((char *)info + sizeof(struct sctx_info));
96}
97

--- 124 unchanged lines hidden (view full) ---

222 set_fpr64(&current->thread.fpu.fpr[i], 3, fpr_val);
223 }
224 err |= __get_user(current->thread.fpu.fcc, fcc);
225 err |= __get_user(current->thread.fpu.fcsr, fcsr);
226
227 return err;
228}
229
230#ifdef CONFIG_CPU_HAS_LBT
231static int copy_lbt_to_sigcontext(struct lbt_context __user *ctx)
232{
233 int err = 0;
234 uint64_t __user *regs = (uint64_t *)&ctx->regs;
235 uint32_t __user *eflags = (uint32_t *)&ctx->eflags;
236
237 err |= __put_user(current->thread.lbt.scr0, &regs[0]);
238 err |= __put_user(current->thread.lbt.scr1, &regs[1]);
239 err |= __put_user(current->thread.lbt.scr2, &regs[2]);
240 err |= __put_user(current->thread.lbt.scr3, &regs[3]);
241 err |= __put_user(current->thread.lbt.eflags, eflags);
242
243 return err;
244}
245
246static int copy_lbt_from_sigcontext(struct lbt_context __user *ctx)
247{
248 int err = 0;
249 uint64_t __user *regs = (uint64_t *)&ctx->regs;
250 uint32_t __user *eflags = (uint32_t *)&ctx->eflags;
251
252 err |= __get_user(current->thread.lbt.scr0, &regs[0]);
253 err |= __get_user(current->thread.lbt.scr1, &regs[1]);
254 err |= __get_user(current->thread.lbt.scr2, &regs[2]);
255 err |= __get_user(current->thread.lbt.scr3, &regs[3]);
256 err |= __get_user(current->thread.lbt.eflags, eflags);
257
258 return err;
259}
260
261static int copy_ftop_to_sigcontext(struct lbt_context __user *ctx)
262{
263 uint32_t __user *ftop = &ctx->ftop;
264
265 return __put_user(current->thread.fpu.ftop, ftop);
266}
267
268static int copy_ftop_from_sigcontext(struct lbt_context __user *ctx)
269{
270 uint32_t __user *ftop = &ctx->ftop;
271
272 return __get_user(current->thread.fpu.ftop, ftop);
273}
274#endif
275
218/*
219 * Wrappers for the assembly _{save,restore}_fp_context functions.
220 */
221static int save_hw_fpu_context(struct fpu_context __user *ctx)
222{
223 uint64_t __user *regs = (uint64_t *)&ctx->regs;
224 uint64_t __user *fcc = &ctx->fcc;
225 uint32_t __user *fcsr = &ctx->fcsr;

--- 41 unchanged lines hidden (view full) ---

267{
268 uint64_t __user *regs = (uint64_t *)&ctx->regs;
269 uint64_t __user *fcc = &ctx->fcc;
270 uint32_t __user *fcsr = &ctx->fcsr;
271
272 return _restore_lasx_context(regs, fcc, fcsr);
273}
274
276/*
277 * Wrappers for the assembly _{save,restore}_fp_context functions.
278 */
279static int save_hw_fpu_context(struct fpu_context __user *ctx)
280{
281 uint64_t __user *regs = (uint64_t *)&ctx->regs;
282 uint64_t __user *fcc = &ctx->fcc;
283 uint32_t __user *fcsr = &ctx->fcsr;

--- 41 unchanged lines hidden (view full) ---

325{
326 uint64_t __user *regs = (uint64_t *)&ctx->regs;
327 uint64_t __user *fcc = &ctx->fcc;
328 uint32_t __user *fcsr = &ctx->fcsr;
329
330 return _restore_lasx_context(regs, fcc, fcsr);
331}
332
333/*
334 * Wrappers for the assembly _{save,restore}_lbt_context functions.
335 */
336#ifdef CONFIG_CPU_HAS_LBT
337static int save_hw_lbt_context(struct lbt_context __user *ctx)
338{
339 uint64_t __user *regs = (uint64_t *)&ctx->regs;
340 uint32_t __user *eflags = (uint32_t *)&ctx->eflags;
341
342 return _save_lbt_context(regs, eflags);
343}
344
345static int restore_hw_lbt_context(struct lbt_context __user *ctx)
346{
347 uint64_t __user *regs = (uint64_t *)&ctx->regs;
348 uint32_t __user *eflags = (uint32_t *)&ctx->eflags;
349
350 return _restore_lbt_context(regs, eflags);
351}
352
353static int save_hw_ftop_context(struct lbt_context __user *ctx)
354{
355 uint32_t __user *ftop = &ctx->ftop;
356
357 return _save_ftop_context(ftop);
358}
359
360static int restore_hw_ftop_context(struct lbt_context __user *ctx)
361{
362 uint32_t __user *ftop = &ctx->ftop;
363
364 return _restore_ftop_context(ftop);
365}
366#endif
367
275static int fcsr_pending(unsigned int __user *fcsr)
276{
277 int err, sig = 0;
278 unsigned int csr, enabled;
279
280 err = __get_user(csr, fcsr);
281 enabled = ((csr & FPU_CSR_ALL_E) << 24);
282 /*

--- 231 unchanged lines hidden (view full) ---

514 __get_user(tmp, fcsr);
515 if (err)
516 break; /* really bad sigcontext */
517 }
518
519 return err ?: sig;
520}
521
368static int fcsr_pending(unsigned int __user *fcsr)
369{
370 int err, sig = 0;
371 unsigned int csr, enabled;
372
373 err = __get_user(csr, fcsr);
374 enabled = ((csr & FPU_CSR_ALL_E) << 24);
375 /*

--- 231 unchanged lines hidden (view full) ---

607 __get_user(tmp, fcsr);
608 if (err)
609 break; /* really bad sigcontext */
610 }
611
612 return err ?: sig;
613}
614
615#ifdef CONFIG_CPU_HAS_LBT
616static int protected_save_lbt_context(struct extctx_layout *extctx)
617{
618 int err = 0;
619 struct sctx_info __user *info = extctx->lbt.addr;
620 struct lbt_context __user *lbt_ctx =
621 (struct lbt_context *)get_ctx_through_ctxinfo(info);
622 uint64_t __user *regs = (uint64_t *)&lbt_ctx->regs;
623 uint32_t __user *eflags = (uint32_t *)&lbt_ctx->eflags;
624
625 while (1) {
626 lock_lbt_owner();
627 if (is_lbt_owner())
628 err |= save_hw_lbt_context(lbt_ctx);
629 else
630 err |= copy_lbt_to_sigcontext(lbt_ctx);
631 if (is_fpu_owner())
632 err |= save_hw_ftop_context(lbt_ctx);
633 else
634 err |= copy_ftop_to_sigcontext(lbt_ctx);
635 unlock_lbt_owner();
636
637 err |= __put_user(LBT_CTX_MAGIC, &info->magic);
638 err |= __put_user(extctx->lbt.size, &info->size);
639
640 if (likely(!err))
641 break;
642 /* Touch the LBT context and try again */
643 err = __put_user(0, &regs[0]) | __put_user(0, eflags);
644
645 if (err)
646 return err;
647 }
648
649 return err;
650}
651
652static int protected_restore_lbt_context(struct extctx_layout *extctx)
653{
654 int err = 0, tmp __maybe_unused;
655 struct sctx_info __user *info = extctx->lbt.addr;
656 struct lbt_context __user *lbt_ctx =
657 (struct lbt_context *)get_ctx_through_ctxinfo(info);
658 uint64_t __user *regs = (uint64_t *)&lbt_ctx->regs;
659 uint32_t __user *eflags = (uint32_t *)&lbt_ctx->eflags;
660
661 while (1) {
662 lock_lbt_owner();
663 if (is_lbt_owner())
664 err |= restore_hw_lbt_context(lbt_ctx);
665 else
666 err |= copy_lbt_from_sigcontext(lbt_ctx);
667 if (is_fpu_owner())
668 err |= restore_hw_ftop_context(lbt_ctx);
669 else
670 err |= copy_ftop_from_sigcontext(lbt_ctx);
671 unlock_lbt_owner();
672
673 if (likely(!err))
674 break;
675 /* Touch the LBT context and try again */
676 err = __get_user(tmp, &regs[0]) | __get_user(tmp, eflags);
677
678 if (err)
679 return err;
680 }
681
682 return err;
683}
684#endif
685
522static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
523 struct extctx_layout *extctx)
524{
525 int i, err = 0;
526 struct sctx_info __user *info;
527
528 err |= __put_user(regs->csr_era, &sc->sc_pc);
529 err |= __put_user(extctx->flags, &sc->sc_flags);

--- 4 unchanged lines hidden (view full) ---

534
535 if (extctx->lasx.addr)
536 err |= protected_save_lasx_context(extctx);
537 else if (extctx->lsx.addr)
538 err |= protected_save_lsx_context(extctx);
539 else if (extctx->fpu.addr)
540 err |= protected_save_fpu_context(extctx);
541
686static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
687 struct extctx_layout *extctx)
688{
689 int i, err = 0;
690 struct sctx_info __user *info;
691
692 err |= __put_user(regs->csr_era, &sc->sc_pc);
693 err |= __put_user(extctx->flags, &sc->sc_flags);

--- 4 unchanged lines hidden (view full) ---

698
699 if (extctx->lasx.addr)
700 err |= protected_save_lasx_context(extctx);
701 else if (extctx->lsx.addr)
702 err |= protected_save_lsx_context(extctx);
703 else if (extctx->fpu.addr)
704 err |= protected_save_fpu_context(extctx);
705
706#ifdef CONFIG_CPU_HAS_LBT
707 if (extctx->lbt.addr)
708 err |= protected_save_lbt_context(extctx);
709#endif
710
542 /* Set the "end" magic */
543 info = (struct sctx_info *)extctx->end.addr;
544 err |= __put_user(0, &info->magic);
545 err |= __put_user(0, &info->size);
546
547 return err;
548}
549

--- 29 unchanged lines hidden (view full) ---

579
580 case LASX_CTX_MAGIC:
581 if (size < (sizeof(struct sctx_info) +
582 sizeof(struct lasx_context)))
583 goto invalid;
584 extctx->lasx.addr = info;
585 break;
586
711 /* Set the "end" magic */
712 info = (struct sctx_info *)extctx->end.addr;
713 err |= __put_user(0, &info->magic);
714 err |= __put_user(0, &info->size);
715
716 return err;
717}
718

--- 29 unchanged lines hidden (view full) ---

748
749 case LASX_CTX_MAGIC:
750 if (size < (sizeof(struct sctx_info) +
751 sizeof(struct lasx_context)))
752 goto invalid;
753 extctx->lasx.addr = info;
754 break;
755
756 case LBT_CTX_MAGIC:
757 if (size < (sizeof(struct sctx_info) +
758 sizeof(struct lbt_context)))
759 goto invalid;
760 extctx->lbt.addr = info;
761 break;
762
587 default:
588 goto invalid;
589 }
590
591 info = (struct sctx_info *)((char *)info + size);
592 }
593
594done:

--- 36 unchanged lines hidden (view full) ---

631
632 if (extctx.lasx.addr)
633 err |= protected_restore_lasx_context(&extctx);
634 else if (extctx.lsx.addr)
635 err |= protected_restore_lsx_context(&extctx);
636 else if (extctx.fpu.addr)
637 err |= protected_restore_fpu_context(&extctx);
638
763 default:
764 goto invalid;
765 }
766
767 info = (struct sctx_info *)((char *)info + size);
768 }
769
770done:

--- 36 unchanged lines hidden (view full) ---

807
808 if (extctx.lasx.addr)
809 err |= protected_restore_lasx_context(&extctx);
810 else if (extctx.lsx.addr)
811 err |= protected_restore_lsx_context(&extctx);
812 else if (extctx.fpu.addr)
813 err |= protected_restore_fpu_context(&extctx);
814
815#ifdef CONFIG_CPU_HAS_LBT
816 if (extctx.lbt.addr)
817 err |= protected_restore_lbt_context(&extctx);
818#endif
819
639bad:
640 return err;
641}
642
643static unsigned int handle_flags(void)
644{
645 unsigned int flags = 0;
646

--- 48 unchanged lines hidden (view full) ---

695 else if (cpu_has_lsx && thread_lsx_context_live())
696 new_sp = extframe_alloc(extctx, &extctx->lsx,
697 sizeof(struct lsx_context), LSX_CTX_ALIGN, new_sp);
698 else if (cpu_has_fpu)
699 new_sp = extframe_alloc(extctx, &extctx->fpu,
700 sizeof(struct fpu_context), FPU_CTX_ALIGN, new_sp);
701 }
702
820bad:
821 return err;
822}
823
824static unsigned int handle_flags(void)
825{
826 unsigned int flags = 0;
827

--- 48 unchanged lines hidden (view full) ---

876 else if (cpu_has_lsx && thread_lsx_context_live())
877 new_sp = extframe_alloc(extctx, &extctx->lsx,
878 sizeof(struct lsx_context), LSX_CTX_ALIGN, new_sp);
879 else if (cpu_has_fpu)
880 new_sp = extframe_alloc(extctx, &extctx->fpu,
881 sizeof(struct fpu_context), FPU_CTX_ALIGN, new_sp);
882 }
883
884#ifdef CONFIG_CPU_HAS_LBT
885 if (cpu_has_lbt && thread_lbt_context_live()) {
886 new_sp = extframe_alloc(extctx, &extctx->lbt,
887 sizeof(struct lbt_context), LBT_CTX_ALIGN, new_sp);
888 }
889#endif
890
703 return new_sp;
704}
705
706void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
707 struct extctx_layout *extctx)
708{
709 unsigned long sp;
710

--- 176 unchanged lines hidden ---
891 return new_sp;
892}
893
894void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
895 struct extctx_layout *extctx)
896{
897 unsigned long sp;
898

--- 176 unchanged lines hidden ---