Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 #include <linux/regset.h>
0004 #include <linux/elf.h>
0005 
0006 #include <asm/switch_to.h>
0007 
0008 #include "ptrace-decl.h"
0009 
0010 /*
0011  * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
0012  * The transfer totals 34 quadword.  Quadwords 0-31 contain the
0013  * corresponding vector registers.  Quadword 32 contains the vscr as the
0014  * last word (offset 12) within that quadword.  Quadword 33 contains the
0015  * vrsave as the first word (offset 0) within the quadword.
0016  *
0017  * This definition of the VMX state is compatible with the current PPC32
0018  * ptrace interface.  This allows signal handling and ptrace to use the
0019  * same structures.  This also simplifies the implementation of a bi-arch
0020  * (combined (32- and 64-bit) gdb.
0021  */
0022 
0023 int vr_active(struct task_struct *target, const struct user_regset *regset)
0024 {
0025     flush_altivec_to_thread(target);
0026     return target->thread.used_vr ? regset->n : 0;
0027 }
0028 
0029 /*
0030  * Regardless of transactions, 'vr_state' holds the current running
0031  * value of all the VMX registers and 'ckvr_state' holds the last
0032  * checkpointed value of all the VMX registers for the current
0033  * transaction to fall back on in case it aborts.
0034  *
0035  * Userspace interface buffer layout:
0036  *
0037  * struct data {
0038  *  vector128   vr[32];
0039  *  vector128   vscr;
0040  *  vector128   vrsave;
0041  * };
0042  */
0043 int vr_get(struct task_struct *target, const struct user_regset *regset,
0044        struct membuf to)
0045 {
0046     union {
0047         elf_vrreg_t reg;
0048         u32 word;
0049     } vrsave;
0050 
0051     flush_altivec_to_thread(target);
0052 
0053     BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
0054              offsetof(struct thread_vr_state, vr[32]));
0055 
0056     membuf_write(&to, &target->thread.vr_state, 33 * sizeof(vector128));
0057     /*
0058      * Copy out only the low-order word of vrsave.
0059      */
0060     memset(&vrsave, 0, sizeof(vrsave));
0061     vrsave.word = target->thread.vrsave;
0062     return membuf_write(&to, &vrsave, sizeof(vrsave));
0063 }
0064 
0065 /*
0066  * Regardless of transactions, 'vr_state' holds the current running
0067  * value of all the VMX registers and 'ckvr_state' holds the last
0068  * checkpointed value of all the VMX registers for the current
0069  * transaction to fall back on in case it aborts.
0070  *
0071  * Userspace interface buffer layout:
0072  *
0073  * struct data {
0074  *  vector128   vr[32];
0075  *  vector128   vscr;
0076  *  vector128   vrsave;
0077  * };
0078  */
0079 int vr_set(struct task_struct *target, const struct user_regset *regset,
0080        unsigned int pos, unsigned int count,
0081        const void *kbuf, const void __user *ubuf)
0082 {
0083     int ret;
0084 
0085     flush_altivec_to_thread(target);
0086 
0087     BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
0088              offsetof(struct thread_vr_state, vr[32]));
0089 
0090     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0091                  &target->thread.vr_state, 0,
0092                  33 * sizeof(vector128));
0093     if (!ret && count > 0) {
0094         /*
0095          * We use only the first word of vrsave.
0096          */
0097         int start, end;
0098         union {
0099             elf_vrreg_t reg;
0100             u32 word;
0101         } vrsave;
0102         memset(&vrsave, 0, sizeof(vrsave));
0103 
0104         vrsave.word = target->thread.vrsave;
0105 
0106         start = 33 * sizeof(vector128);
0107         end = start + sizeof(vrsave);
0108         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
0109                      start, end);
0110         if (!ret)
0111             target->thread.vrsave = vrsave.word;
0112     }
0113 
0114     return ret;
0115 }