mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
bdbd3acb33
The anonymous union within struct fpu contains a floating point register array and a vector register array. Given that the vector register is always present remove the floating point register array. For configurations without vector registers save the floating point register contents within their corresponding vector register location. This allows to remove the union, and also to simplify ptrace and perf code. Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
67 lines
1.4 KiB
C
67 lines
1.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/perf_event.h>
|
|
#include <linux/perf_regs.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/bug.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/fpu.h>
|
|
|
|
u64 perf_reg_value(struct pt_regs *regs, int idx)
|
|
{
|
|
freg_t fp;
|
|
|
|
if (idx >= PERF_REG_S390_R0 && idx <= PERF_REG_S390_R15)
|
|
return regs->gprs[idx];
|
|
|
|
if (idx >= PERF_REG_S390_FP0 && idx <= PERF_REG_S390_FP15) {
|
|
if (!user_mode(regs))
|
|
return 0;
|
|
|
|
idx -= PERF_REG_S390_FP0;
|
|
fp = *(freg_t *)(current->thread.ufpu.vxrs + idx);
|
|
return fp.ui;
|
|
}
|
|
|
|
if (idx == PERF_REG_S390_MASK)
|
|
return regs->psw.mask;
|
|
if (idx == PERF_REG_S390_PC)
|
|
return regs->psw.addr;
|
|
|
|
WARN_ON_ONCE((u32)idx >= PERF_REG_S390_MAX);
|
|
return 0;
|
|
}
|
|
|
|
#define REG_RESERVED (~((1UL << PERF_REG_S390_MAX) - 1))
|
|
|
|
int perf_reg_validate(u64 mask)
|
|
{
|
|
if (!mask || mask & REG_RESERVED)
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
u64 perf_reg_abi(struct task_struct *task)
|
|
{
|
|
if (test_tsk_thread_flag(task, TIF_31BIT))
|
|
return PERF_SAMPLE_REGS_ABI_32;
|
|
|
|
return PERF_SAMPLE_REGS_ABI_64;
|
|
}
|
|
|
|
void perf_get_regs_user(struct perf_regs *regs_user,
|
|
struct pt_regs *regs)
|
|
{
|
|
/*
|
|
* Use the regs from the first interruption and let
|
|
* perf_sample_regs_intr() handle interrupts (regs == get_irq_regs()).
|
|
*
|
|
* Also save FPU registers for user-space tasks only.
|
|
*/
|
|
regs_user->regs = task_pt_regs(current);
|
|
if (user_mode(regs_user->regs))
|
|
save_user_fpu_regs();
|
|
regs_user->abi = perf_reg_abi(current);
|
|
}
|