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

ptrace-vsx.c (3608B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2
      3#include <linux/regset.h>
      4
      5#include <asm/switch_to.h>
      6
      7#include "ptrace-decl.h"
      8
      9/*
     10 * Regardless of transactions, 'fp_state' holds the current running
     11 * value of all FPR registers and 'ckfp_state' holds the last checkpointed
     12 * value of all FPR registers for the current transaction.
     13 *
     14 * Userspace interface buffer layout:
     15 *
     16 * struct data {
     17 *	u64	fpr[32];
     18 *	u64	fpscr;
     19 * };
     20 */
     21int fpr_get(struct task_struct *target, const struct user_regset *regset,
     22	    struct membuf to)
     23{
     24	u64 buf[33];
     25	int i;
     26
     27	flush_fp_to_thread(target);
     28
     29	/* copy to local buffer then write that out */
     30	for (i = 0; i < 32 ; i++)
     31		buf[i] = target->thread.TS_FPR(i);
     32	buf[32] = target->thread.fp_state.fpscr;
     33	return membuf_write(&to, buf, 33 * sizeof(u64));
     34}
     35
     36/*
     37 * Regardless of transactions, 'fp_state' holds the current running
     38 * value of all FPR registers and 'ckfp_state' holds the last checkpointed
     39 * value of all FPR registers for the current transaction.
     40 *
     41 * Userspace interface buffer layout:
     42 *
     43 * struct data {
     44 *	u64	fpr[32];
     45 *	u64	fpscr;
     46 * };
     47 *
     48 */
     49int fpr_set(struct task_struct *target, const struct user_regset *regset,
     50	    unsigned int pos, unsigned int count,
     51	    const void *kbuf, const void __user *ubuf)
     52{
     53	u64 buf[33];
     54	int i;
     55
     56	flush_fp_to_thread(target);
     57
     58	for (i = 0; i < 32 ; i++)
     59		buf[i] = target->thread.TS_FPR(i);
     60	buf[32] = target->thread.fp_state.fpscr;
     61
     62	/* copy to local buffer then write that out */
     63	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
     64	if (i)
     65		return i;
     66
     67	for (i = 0; i < 32 ; i++)
     68		target->thread.TS_FPR(i) = buf[i];
     69	target->thread.fp_state.fpscr = buf[32];
     70	return 0;
     71}
     72
     73/*
     74 * Currently to set and and get all the vsx state, you need to call
     75 * the fp and VMX calls as well.  This only get/sets the lower 32
     76 * 128bit VSX registers.
     77 */
     78
     79int vsr_active(struct task_struct *target, const struct user_regset *regset)
     80{
     81	flush_vsx_to_thread(target);
     82	return target->thread.used_vsr ? regset->n : 0;
     83}
     84
     85/*
     86 * Regardless of transactions, 'fp_state' holds the current running
     87 * value of all FPR registers and 'ckfp_state' holds the last
     88 * checkpointed value of all FPR registers for the current
     89 * transaction.
     90 *
     91 * Userspace interface buffer layout:
     92 *
     93 * struct data {
     94 *	u64	vsx[32];
     95 * };
     96 */
     97int vsr_get(struct task_struct *target, const struct user_regset *regset,
     98	    struct membuf to)
     99{
    100	u64 buf[32];
    101	int i;
    102
    103	flush_tmregs_to_thread(target);
    104	flush_fp_to_thread(target);
    105	flush_altivec_to_thread(target);
    106	flush_vsx_to_thread(target);
    107
    108	for (i = 0; i < 32 ; i++)
    109		buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
    110
    111	return membuf_write(&to, buf, 32 * sizeof(double));
    112}
    113
    114/*
    115 * Regardless of transactions, 'fp_state' holds the current running
    116 * value of all FPR registers and 'ckfp_state' holds the last
    117 * checkpointed value of all FPR registers for the current
    118 * transaction.
    119 *
    120 * Userspace interface buffer layout:
    121 *
    122 * struct data {
    123 *	u64	vsx[32];
    124 * };
    125 */
    126int vsr_set(struct task_struct *target, const struct user_regset *regset,
    127	    unsigned int pos, unsigned int count,
    128	    const void *kbuf, const void __user *ubuf)
    129{
    130	u64 buf[32];
    131	int ret, i;
    132
    133	flush_tmregs_to_thread(target);
    134	flush_fp_to_thread(target);
    135	flush_altivec_to_thread(target);
    136	flush_vsx_to_thread(target);
    137
    138	for (i = 0; i < 32 ; i++)
    139		buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
    140
    141	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    142				 buf, 0, 32 * sizeof(double));
    143	if (!ret)
    144		for (i = 0; i < 32 ; i++)
    145			target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
    146
    147	return ret;
    148}