linux/arch/powerpc/kernel/ptrace/ptrace-vsx.c
<<
>>
Prefs
   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}
 149