cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sigutil_64.c (2706B)


      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/errno.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	unsigned long *fpregs = current_thread_info()->fpregs;
     18	unsigned long fprs;
     19	int err = 0;
     20	
     21	fprs = current_thread_info()->fpsaved[0];
     22	if (fprs & FPRS_DL)
     23		err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
     24				    (sizeof(unsigned int) * 32));
     25	if (fprs & FPRS_DU)
     26		err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
     27				    (sizeof(unsigned int) * 32));
     28	err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
     29	err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
     30	err |= __put_user(fprs, &fpu->si_fprs);
     31
     32	return err;
     33}
     34
     35int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
     36{
     37	unsigned long *fpregs = current_thread_info()->fpregs;
     38	unsigned long fprs;
     39	int err;
     40
     41	if (((unsigned long) fpu) & 7)
     42		return -EFAULT;
     43
     44	err = get_user(fprs, &fpu->si_fprs);
     45	fprs_write(0);
     46	regs->tstate &= ~TSTATE_PEF;
     47	if (fprs & FPRS_DL)
     48		err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
     49		       	       (sizeof(unsigned int) * 32));
     50	if (fprs & FPRS_DU)
     51		err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
     52		       	       (sizeof(unsigned int) * 32));
     53	err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
     54	err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
     55	current_thread_info()->fpsaved[0] |= fprs;
     56	return err;
     57}
     58
     59int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
     60{
     61	int i, err = __put_user(wsaved, &rwin->wsaved);
     62
     63	for (i = 0; i < wsaved; i++) {
     64		struct reg_window *rp = &current_thread_info()->reg_window[i];
     65		unsigned long fp = current_thread_info()->rwbuf_stkptrs[i];
     66
     67		err |= copy_to_user(&rwin->reg_window[i], rp,
     68				    sizeof(struct reg_window));
     69		err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
     70	}
     71	return err;
     72}
     73
     74int restore_rwin_state(__siginfo_rwin_t __user *rp)
     75{
     76	struct thread_info *t = current_thread_info();
     77	int i, wsaved, err;
     78
     79	if (((unsigned long) rp) & 7)
     80		return -EFAULT;
     81
     82	get_user(wsaved, &rp->wsaved);
     83	if (wsaved > NSWINS)
     84		return -EFAULT;
     85
     86	err = 0;
     87	for (i = 0; i < wsaved; i++) {
     88		err |= copy_from_user(&t->reg_window[i],
     89				      &rp->reg_window[i],
     90				      sizeof(struct reg_window));
     91		err |= __get_user(t->rwbuf_stkptrs[i],
     92				  &rp->rwbuf_stkptrs[i]);
     93	}
     94	if (err)
     95		return err;
     96
     97	set_thread_wsaved(wsaved);
     98	synchronize_user_stack();
     99	if (get_thread_wsaved())
    100		return -EFAULT;
    101	return 0;
    102}