.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * 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. |
---|
8 | 4 | */ |
---|
9 | 5 | |
---|
10 | 6 | #include <linux/errno.h> |
---|
.. | .. |
---|
17 | 13 | #include <asm/ptrace.h> |
---|
18 | 14 | #include <asm/perf_regs.h> |
---|
19 | 15 | |
---|
| 16 | +u64 PERF_REG_EXTENDED_MASK; |
---|
| 17 | + |
---|
20 | 18 | #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) |
---|
21 | 19 | |
---|
22 | | -#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1)) |
---|
| 20 | +#define REG_RESERVED (~(PERF_REG_EXTENDED_MASK | PERF_REG_PMU_MASK)) |
---|
23 | 21 | |
---|
24 | 22 | static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { |
---|
25 | 23 | PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]), |
---|
.. | .. |
---|
69 | 67 | PT_REGS_OFFSET(PERF_REG_POWERPC_TRAP, trap), |
---|
70 | 68 | PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar), |
---|
71 | 69 | 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), |
---|
72 | 72 | }; |
---|
| 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 | +} |
---|
73 | 95 | |
---|
74 | 96 | u64 perf_reg_value(struct pt_regs *regs, int idx) |
---|
75 | 97 | { |
---|
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)) |
---|
77 | 124 | return 0; |
---|
78 | 125 | |
---|
79 | 126 | return regs_get_register(regs, pt_regs_offset[idx]); |
---|
.. | .. |
---|
97 | 144 | } |
---|
98 | 145 | |
---|
99 | 146 | 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) |
---|
102 | 148 | { |
---|
103 | 149 | regs_user->regs = task_pt_regs(current); |
---|
104 | 150 | regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) : |
---|