root/arch/sparc/kernel/sigutil_32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. save_fpu_state
  2. restore_fpu_state
  3. save_rwin_state
  4. restore_rwin_state

   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 
  15 int 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 
  49 int 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 
  83 int 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 
 100 int 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 }

/* [<][>][^][v][top][bottom][index][help] */