hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/arch/powerpc/perf/perf_regs.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright 2016 Anju T, IBM Corporation.
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License
6
- * as published by the Free Software Foundation; either version
7
- * 2 of the License, or (at your option) any later version.
84 */
95
106 #include <linux/errno.h>
....@@ -17,9 +13,11 @@
1713 #include <asm/ptrace.h>
1814 #include <asm/perf_regs.h>
1915
16
+u64 PERF_REG_EXTENDED_MASK;
17
+
2018 #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)
2119
22
-#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1))
20
+#define REG_RESERVED (~(PERF_REG_EXTENDED_MASK | PERF_REG_PMU_MASK))
2321
2422 static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
2523 PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]),
....@@ -69,11 +67,60 @@
6967 PT_REGS_OFFSET(PERF_REG_POWERPC_TRAP, trap),
7068 PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
7169 PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
70
+ PT_REGS_OFFSET(PERF_REG_POWERPC_SIER, dar),
71
+ PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr),
7272 };
73
+
74
+/* Function to return the extended register values */
75
+static u64 get_ext_regs_value(int idx)
76
+{
77
+ switch (idx) {
78
+ case PERF_REG_POWERPC_MMCR0:
79
+ return mfspr(SPRN_MMCR0);
80
+ case PERF_REG_POWERPC_MMCR1:
81
+ return mfspr(SPRN_MMCR1);
82
+ case PERF_REG_POWERPC_MMCR2:
83
+ return mfspr(SPRN_MMCR2);
84
+#ifdef CONFIG_PPC64
85
+ case PERF_REG_POWERPC_MMCR3:
86
+ return mfspr(SPRN_MMCR3);
87
+ case PERF_REG_POWERPC_SIER2:
88
+ return mfspr(SPRN_SIER2);
89
+ case PERF_REG_POWERPC_SIER3:
90
+ return mfspr(SPRN_SIER3);
91
+#endif
92
+ default: return 0;
93
+ }
94
+}
7395
7496 u64 perf_reg_value(struct pt_regs *regs, int idx)
7597 {
76
- if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX))
98
+ u64 perf_reg_extended_max = PERF_REG_POWERPC_MAX;
99
+
100
+ if (cpu_has_feature(CPU_FTR_ARCH_31))
101
+ perf_reg_extended_max = PERF_REG_MAX_ISA_31;
102
+ else if (cpu_has_feature(CPU_FTR_ARCH_300))
103
+ perf_reg_extended_max = PERF_REG_MAX_ISA_300;
104
+
105
+ if (idx == PERF_REG_POWERPC_SIER &&
106
+ (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
107
+ IS_ENABLED(CONFIG_PPC32) ||
108
+ !is_sier_available()))
109
+ return 0;
110
+
111
+ if (idx == PERF_REG_POWERPC_MMCRA &&
112
+ (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
113
+ IS_ENABLED(CONFIG_PPC32)))
114
+ return 0;
115
+
116
+ if (idx >= PERF_REG_POWERPC_MAX && idx < perf_reg_extended_max)
117
+ return get_ext_regs_value(idx);
118
+
119
+ /*
120
+ * If the idx is referring to value beyond the
121
+ * supported registers, return 0 with a warning
122
+ */
123
+ if (WARN_ON_ONCE(idx >= perf_reg_extended_max))
77124 return 0;
78125
79126 return regs_get_register(regs, pt_regs_offset[idx]);
....@@ -97,8 +144,7 @@
97144 }
98145
99146 void perf_get_regs_user(struct perf_regs *regs_user,
100
- struct pt_regs *regs,
101
- struct pt_regs *regs_user_copy)
147
+ struct pt_regs *regs)
102148 {
103149 regs_user->regs = task_pt_regs(current);
104150 regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :