linux/arch/sparc/kernel/sigutil_32.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/kernel.h>
   3#include <linux/types.h>
   4#include <linux/thread_info.h>
   5#include <linux/uaccess.h>
   6#include <linux/sched.h>
   7
   8#include <asm/sigcontext.h>
   9#include <asm/fpumacro.h>
  10#include <asm/ptrace.h>
  11#include <asm/switch_to.h>
  12
  13#include "sigutil.h"
  14
  15int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
  16{
  17        int err = 0;
  18#ifdef CONFIG_SMP
  19        if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
  20                put_psr(get_psr() | PSR_EF);
  21                fpsave(&current->thread.float_regs[0], &current->thread.fsr,
  22                       &current->thread.fpqueue[0], &current->thread.fpqdepth);
  23                regs->psr &= ~(PSR_EF);
  24                clear_tsk_thread_flag(current, TIF_USEDFPU);
  25        }
  26#else
  27        if (current == last_task_used_math) {
  28                put_psr(get_psr() | PSR_EF);
  29                fpsave(&current->thread.float_regs[0], &current->thread.fsr,
  30                       &current->thread.fpqueue[0], &current->thread.fpqdepth);
  31                last_task_used_math = NULL;
  32                regs->psr &= ~(PSR_EF);
  33        }
  34#endif
  35        err |= __copy_to_user(&fpu->si_float_regs[0],
  36                              &current->thread.float_regs[0],
  37                              (sizeof(unsigned long) * 32));
  38        err |= __put_user(current->thread.fsr, &fpu->si_fsr);
  39        err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
  40        if (current->thread.fpqdepth != 0)
  41                err |= __copy_to_user(&fpu->si_fpqueue[0],
  42                                      &current->thread.fpqueue[0],
  43                                      ((sizeof(unsigned long) +
  44                                      (sizeof(unsigned long *)))*16));
  45        clear_used_math();
  46        return err;
  47}
  48
  49int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
  50{
  51        int err;
  52
  53        if (((unsigned long) fpu) & 3)
  54                return -EFAULT;
  55
  56#ifdef CONFIG_SMP
  57        if (test_tsk_thread_flag(current, TIF_USEDFPU))
  58                regs->psr &= ~PSR_EF;
  59#else
  60        if (current == last_task_used_math) {
  61                last_task_used_math = NULL;
  62                regs->psr &= ~PSR_EF;
  63        }
  64#endif
  65        set_used_math();
  66        clear_tsk_thread_flag(current, TIF_USEDFPU);
  67
  68        if (!access_ok(fpu, sizeof(*fpu)))
  69                return -EFAULT;
  70
  71        err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
  72                               (sizeof(unsigned long) * 32));
  73        err |= __get_user(current->thread.fsr, &fpu->si_fsr);
  74        err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
  75        if (current->thread.fpqdepth != 0)
  76                err |= __copy_from_user(&current->thread.fpqueue[0],
  77                                        &fpu->si_fpqueue[0],
  78                                        ((sizeof(unsigned long) +
  79                                        (sizeof(unsigned long *)))*16));
  80        return err;
  81}
  82
  83int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
  84{
  85        int i, err = __put_user(wsaved, &rwin->wsaved);
  86
  87        for (i = 0; i < wsaved; i++) {
  88                struct reg_window32 *rp;
  89                unsigned long fp;
  90
  91                rp = &current_thread_info()->reg_window[i];
  92                fp = current_thread_info()->rwbuf_stkptrs[i];
  93                err |= copy_to_user(&rwin->reg_window[i], rp,
  94                                    sizeof(struct reg_window32));
  95                err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
  96        }
  97        return err;
  98}
  99
 100int restore_rwin_state(__siginfo_rwin_t __user *rp)
 101{
 102        struct thread_info *t = current_thread_info();
 103        int i, wsaved, err;
 104
 105        if (((unsigned long) rp) & 3)
 106                return -EFAULT;
 107
 108        get_user(wsaved, &rp->wsaved);
 109        if (wsaved > NSWINS)
 110                return -EFAULT;
 111
 112        err = 0;
 113        for (i = 0; i < wsaved; i++) {
 114                err |= copy_from_user(&t->reg_window[i],
 115                                      &rp->reg_window[i],
 116                                      sizeof(struct reg_window32));
 117                err |= __get_user(t->rwbuf_stkptrs[i],
 118                                  &rp->rwbuf_stkptrs[i]);
 119        }
 120        if (err)
 121                return err;
 122
 123        t->w_saved = wsaved;
 124        synchronize_user_stack();
 125        if (t->w_saved)
 126                return -EFAULT;
 127        return 0;
 128
 129}
 130