summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2017-11-08 07:30:15 +0100
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-11-16 15:06:14 +0100
commit0da0017f72554c005c1a04c3adc5da9eb64fa7e5 (patch)
treecaca91b7cc8c47786c3c617c7a311c7e4f4bd1a0 /arch
parenta9fc2db0a8abf51c81122799c5ae4808f2324b6d (diff)
downloadop-kernel-dev-0da0017f72554c005c1a04c3adc5da9eb64fa7e5.zip
op-kernel-dev-0da0017f72554c005c1a04c3adc5da9eb64fa7e5.tar.gz
s390/perf: extend perf_regs support to include floating-point registers
Extend the perf register support to also export floating-point register contents for user space tasks. Floating-point registers might be used in leaf functions to contain the return address. Hence, they are required for proper DWARF unwinding. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Reviewed-and-tested-by: Thomas Richter <tmricht@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/uapi/asm/perf_regs.h16
-rw-r--r--arch/s390/kernel/perf_regs.c21
2 files changed, 37 insertions, 0 deletions
diff --git a/arch/s390/include/uapi/asm/perf_regs.h b/arch/s390/include/uapi/asm/perf_regs.h
index f84ea6a..7c8564f 100644
--- a/arch/s390/include/uapi/asm/perf_regs.h
+++ b/arch/s390/include/uapi/asm/perf_regs.h
@@ -18,6 +18,22 @@ enum perf_event_s390_regs {
PERF_REG_S390_R13,
PERF_REG_S390_R14,
PERF_REG_S390_R15,
+ PERF_REG_S390_FP0,
+ PERF_REG_S390_FP1,
+ PERF_REG_S390_FP2,
+ PERF_REG_S390_FP3,
+ PERF_REG_S390_FP4,
+ PERF_REG_S390_FP5,
+ PERF_REG_S390_FP6,
+ PERF_REG_S390_FP7,
+ PERF_REG_S390_FP8,
+ PERF_REG_S390_FP9,
+ PERF_REG_S390_FP10,
+ PERF_REG_S390_FP11,
+ PERF_REG_S390_FP12,
+ PERF_REG_S390_FP13,
+ PERF_REG_S390_FP14,
+ PERF_REG_S390_FP15,
PERF_REG_S390_MASK,
PERF_REG_S390_PC,
diff --git a/arch/s390/kernel/perf_regs.c b/arch/s390/kernel/perf_regs.c
index e883e6a..f8603eb 100644
--- a/arch/s390/kernel/perf_regs.c
+++ b/arch/s390/kernel/perf_regs.c
@@ -4,12 +4,29 @@
#include <linux/errno.h>
#include <linux/bug.h>
#include <asm/ptrace.h>
+#include <asm/fpu/api.h>
+#include <asm/fpu/types.h>
u64 perf_reg_value(struct pt_regs *regs, int idx)
{
+ freg_t fp;
+
if (WARN_ON_ONCE((u32)idx >= PERF_REG_S390_MAX))
return 0;
+ 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 = MACHINE_HAS_VX ? *(freg_t *)(current->thread.fpu.vxrs + idx)
+ : current->thread.fpu.fprs[idx];
+ return fp.ui;
+ }
+
if (idx == PERF_REG_S390_MASK)
return regs->psw.mask;
if (idx == PERF_REG_S390_PC)
@@ -43,7 +60,11 @@ void perf_get_regs_user(struct perf_regs *regs_user,
/*
* 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_fpu_regs();
regs_user->abi = perf_reg_abi(current);
}
OpenPOWER on IntegriCloud