linux/arch/powerpc/kernel/ptrace/ptrace-altivec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2
   3#include <linux/regset.h>
   4#include <linux/elf.h>
   5
   6#include <asm/switch_to.h>
   7
   8#include "ptrace-decl.h"
   9
  10/*
  11 * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
  12 * The transfer totals 34 quadword.  Quadwords 0-31 contain the
  13 * corresponding vector registers.  Quadword 32 contains the vscr as the
  14 * last word (offset 12) within that quadword.  Quadword 33 contains the
  15 * vrsave as the first word (offset 0) within the quadword.
  16 *
  17 * This definition of the VMX state is compatible with the current PPC32
  18 * ptrace interface.  This allows signal handling and ptrace to use the
  19 * same structures.  This also simplifies the implementation of a bi-arch
  20 * (combined (32- and 64-bit) gdb.
  21 */
  22
  23int vr_active(struct task_struct *target, const struct user_regset *regset)
  24{
  25        flush_altivec_to_thread(target);
  26        return target->thread.used_vr ? regset->n : 0;
  27}
  28
  29/*
  30 * Regardless of transactions, 'vr_state' holds the current running
  31 * value of all the VMX registers and 'ckvr_state' holds the last
  32 * checkpointed value of all the VMX registers for the current
  33 * transaction to fall back on in case it aborts.
  34 *
  35 * Userspace interface buffer layout:
  36 *
  37 * struct data {
  38 *      vector128       vr[32];
  39 *      vector128       vscr;
  40 *      vector128       vrsave;
  41 * };
  42 */
  43int vr_get(struct task_struct *target, const struct user_regset *regset,
  44           struct membuf to)
  45{
  46        union {
  47                elf_vrreg_t reg;
  48                u32 word;
  49        } vrsave;
  50
  51        flush_altivec_to_thread(target);
  52
  53        BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
  54                     offsetof(struct thread_vr_state, vr[32]));
  55
  56        membuf_write(&to, &target->thread.vr_state, 33 * sizeof(vector128));
  57        /*
  58         * Copy out only the low-order word of vrsave.
  59         */
  60        memset(&vrsave, 0, sizeof(vrsave));
  61        vrsave.word = target->thread.vrsave;
  62        return membuf_write(&to, &vrsave, sizeof(vrsave));
  63}
  64
  65/*
  66 * Regardless of transactions, 'vr_state' holds the current running
  67 * value of all the VMX registers and 'ckvr_state' holds the last
  68 * checkpointed value of all the VMX registers for the current
  69 * transaction to fall back on in case it aborts.
  70 *
  71 * Userspace interface buffer layout:
  72 *
  73 * struct data {
  74 *      vector128       vr[32];
  75 *      vector128       vscr;
  76 *      vector128       vrsave;
  77 * };
  78 */
  79int vr_set(struct task_struct *target, const struct user_regset *regset,
  80           unsigned int pos, unsigned int count,
  81           const void *kbuf, const void __user *ubuf)
  82{
  83        int ret;
  84
  85        flush_altivec_to_thread(target);
  86
  87        BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
  88                     offsetof(struct thread_vr_state, vr[32]));
  89
  90        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  91                                 &target->thread.vr_state, 0,
  92                                 33 * sizeof(vector128));
  93        if (!ret && count > 0) {
  94                /*
  95                 * We use only the first word of vrsave.
  96                 */
  97                int start, end;
  98                union {
  99                        elf_vrreg_t reg;
 100                        u32 word;
 101                } vrsave;
 102                memset(&vrsave, 0, sizeof(vrsave));
 103
 104                vrsave.word = target->thread.vrsave;
 105
 106                start = 33 * sizeof(vector128);
 107                end = start + sizeof(vrsave);
 108                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
 109                                         start, end);
 110                if (!ret)
 111                        target->thread.vrsave = vrsave.word;
 112        }
 113
 114        return ret;
 115}
 116