forked from Minki/linux
powerpc/ptrace: split out ALTIVEC related functions.
Move CONFIG_ALTIVEC functions out of ptrace.c, into ptrace-altivec.c Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/35dae891d01c817fca0fd6ab406a3a2c7bf07f60.1582848567.git.christophe.leroy@c-s.fr
This commit is contained in:
parent
7b99ed4e8e
commit
1b20773b00
@ -11,3 +11,4 @@ obj-$(CONFIG_VSX) += ptrace-vsx.o
|
||||
ifneq ($(CONFIG_VSX),y)
|
||||
obj-y += ptrace-novsx.o
|
||||
endif
|
||||
obj-$(CONFIG_ALTIVEC) += ptrace-altivec.o
|
||||
|
128
arch/powerpc/kernel/ptrace/ptrace-altivec.c
Normal file
128
arch/powerpc/kernel/ptrace/ptrace-altivec.c
Normal file
@ -0,0 +1,128 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <linux/regset.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include <asm/switch_to.h>
|
||||
|
||||
#include "ptrace-decl.h"
|
||||
|
||||
/*
|
||||
* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
|
||||
* The transfer totals 34 quadword. Quadwords 0-31 contain the
|
||||
* corresponding vector registers. Quadword 32 contains the vscr as the
|
||||
* last word (offset 12) within that quadword. Quadword 33 contains the
|
||||
* vrsave as the first word (offset 0) within the quadword.
|
||||
*
|
||||
* This definition of the VMX state is compatible with the current PPC32
|
||||
* ptrace interface. This allows signal handling and ptrace to use the
|
||||
* same structures. This also simplifies the implementation of a bi-arch
|
||||
* (combined (32- and 64-bit) gdb.
|
||||
*/
|
||||
|
||||
int vr_active(struct task_struct *target, const struct user_regset *regset)
|
||||
{
|
||||
flush_altivec_to_thread(target);
|
||||
return target->thread.used_vr ? regset->n : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regardless of transactions, 'vr_state' holds the current running
|
||||
* value of all the VMX registers and 'ckvr_state' holds the last
|
||||
* checkpointed value of all the VMX registers for the current
|
||||
* transaction to fall back on in case it aborts.
|
||||
*
|
||||
* Userspace interface buffer layout:
|
||||
*
|
||||
* struct data {
|
||||
* vector128 vr[32];
|
||||
* vector128 vscr;
|
||||
* vector128 vrsave;
|
||||
* };
|
||||
*/
|
||||
int vr_get(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
flush_altivec_to_thread(target);
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
|
||||
offsetof(struct thread_vr_state, vr[32]));
|
||||
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.vr_state, 0,
|
||||
33 * sizeof(vector128));
|
||||
if (!ret) {
|
||||
/*
|
||||
* Copy out only the low-order word of vrsave.
|
||||
*/
|
||||
int start, end;
|
||||
union {
|
||||
elf_vrreg_t reg;
|
||||
u32 word;
|
||||
} vrsave;
|
||||
memset(&vrsave, 0, sizeof(vrsave));
|
||||
|
||||
vrsave.word = target->thread.vrsave;
|
||||
|
||||
start = 33 * sizeof(vector128);
|
||||
end = start + sizeof(vrsave);
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
|
||||
start, end);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regardless of transactions, 'vr_state' holds the current running
|
||||
* value of all the VMX registers and 'ckvr_state' holds the last
|
||||
* checkpointed value of all the VMX registers for the current
|
||||
* transaction to fall back on in case it aborts.
|
||||
*
|
||||
* Userspace interface buffer layout:
|
||||
*
|
||||
* struct data {
|
||||
* vector128 vr[32];
|
||||
* vector128 vscr;
|
||||
* vector128 vrsave;
|
||||
* };
|
||||
*/
|
||||
int vr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
flush_altivec_to_thread(target);
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
|
||||
offsetof(struct thread_vr_state, vr[32]));
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.vr_state, 0,
|
||||
33 * sizeof(vector128));
|
||||
if (!ret && count > 0) {
|
||||
/*
|
||||
* We use only the first word of vrsave.
|
||||
*/
|
||||
int start, end;
|
||||
union {
|
||||
elf_vrreg_t reg;
|
||||
u32 word;
|
||||
} vrsave;
|
||||
memset(&vrsave, 0, sizeof(vrsave));
|
||||
|
||||
vrsave.word = target->thread.vrsave;
|
||||
|
||||
start = 33 * sizeof(vector128);
|
||||
end = start + sizeof(vrsave);
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
|
||||
start, end);
|
||||
if (!ret)
|
||||
target->thread.vrsave = vrsave.word;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -17,6 +17,15 @@ int vsr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf);
|
||||
|
||||
/* ptrace-altivec */
|
||||
|
||||
int vr_active(struct task_struct *target, const struct user_regset *regset);
|
||||
int vr_get(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
|
||||
int vr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf);
|
||||
|
||||
/* ptrace */
|
||||
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
|
@ -403,130 +403,6 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
/*
|
||||
* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
|
||||
* The transfer totals 34 quadword. Quadwords 0-31 contain the
|
||||
* corresponding vector registers. Quadword 32 contains the vscr as the
|
||||
* last word (offset 12) within that quadword. Quadword 33 contains the
|
||||
* vrsave as the first word (offset 0) within the quadword.
|
||||
*
|
||||
* This definition of the VMX state is compatible with the current PPC32
|
||||
* ptrace interface. This allows signal handling and ptrace to use the
|
||||
* same structures. This also simplifies the implementation of a bi-arch
|
||||
* (combined (32- and 64-bit) gdb.
|
||||
*/
|
||||
|
||||
static int vr_active(struct task_struct *target,
|
||||
const struct user_regset *regset)
|
||||
{
|
||||
flush_altivec_to_thread(target);
|
||||
return target->thread.used_vr ? regset->n : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regardless of transactions, 'vr_state' holds the current running
|
||||
* value of all the VMX registers and 'ckvr_state' holds the last
|
||||
* checkpointed value of all the VMX registers for the current
|
||||
* transaction to fall back on in case it aborts.
|
||||
*
|
||||
* Userspace interface buffer layout:
|
||||
*
|
||||
* struct data {
|
||||
* vector128 vr[32];
|
||||
* vector128 vscr;
|
||||
* vector128 vrsave;
|
||||
* };
|
||||
*/
|
||||
static int vr_get(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
flush_altivec_to_thread(target);
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
|
||||
offsetof(struct thread_vr_state, vr[32]));
|
||||
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.vr_state, 0,
|
||||
33 * sizeof(vector128));
|
||||
if (!ret) {
|
||||
/*
|
||||
* Copy out only the low-order word of vrsave.
|
||||
*/
|
||||
int start, end;
|
||||
union {
|
||||
elf_vrreg_t reg;
|
||||
u32 word;
|
||||
} vrsave;
|
||||
memset(&vrsave, 0, sizeof(vrsave));
|
||||
|
||||
vrsave.word = target->thread.vrsave;
|
||||
|
||||
start = 33 * sizeof(vector128);
|
||||
end = start + sizeof(vrsave);
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
|
||||
start, end);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regardless of transactions, 'vr_state' holds the current running
|
||||
* value of all the VMX registers and 'ckvr_state' holds the last
|
||||
* checkpointed value of all the VMX registers for the current
|
||||
* transaction to fall back on in case it aborts.
|
||||
*
|
||||
* Userspace interface buffer layout:
|
||||
*
|
||||
* struct data {
|
||||
* vector128 vr[32];
|
||||
* vector128 vscr;
|
||||
* vector128 vrsave;
|
||||
* };
|
||||
*/
|
||||
static int vr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
flush_altivec_to_thread(target);
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
|
||||
offsetof(struct thread_vr_state, vr[32]));
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.vr_state, 0,
|
||||
33 * sizeof(vector128));
|
||||
if (!ret && count > 0) {
|
||||
/*
|
||||
* We use only the first word of vrsave.
|
||||
*/
|
||||
int start, end;
|
||||
union {
|
||||
elf_vrreg_t reg;
|
||||
u32 word;
|
||||
} vrsave;
|
||||
memset(&vrsave, 0, sizeof(vrsave));
|
||||
|
||||
vrsave.word = target->thread.vrsave;
|
||||
|
||||
start = 33 * sizeof(vector128);
|
||||
end = start + sizeof(vrsave);
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
|
||||
start, end);
|
||||
if (!ret)
|
||||
target->thread.vrsave = vrsave.word;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
|
||||
#ifdef CONFIG_SPE
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user