[v3 04/15] powerpc/perf: Add support for ISA3.1 PMU SPRs
Athira Rajeev
atrajeev at linux.vnet.ibm.com
Wed Jul 22 18:07:23 AEST 2020
> On 22-Jul-2020, at 9:48 AM, Jordan Niethe <jniethe5 at gmail.com> wrote:
>
> On Sat, Jul 18, 2020 at 1:02 AM Athira Rajeev
> <atrajeev at linux.vnet.ibm.com <mailto:atrajeev at linux.vnet.ibm.com>> wrote:
>>
>> From: Madhavan Srinivasan <maddy at linux.ibm.com>
>>
>> PowerISA v3.1 includes new performance monitoring unit(PMU)
>> special purpose registers (SPRs). They are
>>
>> Monitor Mode Control Register 3 (MMCR3)
>> Sampled Instruction Event Register 2 (SIER2)
>> Sampled Instruction Event Register 3 (SIER3)
>>
>> MMCR3 is added for further sampling related configuration
>> control. SIER2/SIER3 are added to provide additional
>> information about the sampled instruction.
>>
>> Patch adds new PPMU flag called "PPMU_ARCH_310S" to support
>> handling of these new SPRs, updates the struct thread_struct
>> to include these new SPRs, include MMCR3 in struct mmcr_regs.
>> This is needed to support programming of MMCR3 SPR during
>> event_[enable/disable]. Patch also adds the sysfs support
>> for the MMCR3 SPR along with SPRN_ macros for these new pmu sprs.
>>
>> Signed-off-by: Madhavan Srinivasan <maddy at linux.ibm.com>
>> ---
>> arch/powerpc/include/asm/perf_event_server.h | 2 ++
>> arch/powerpc/include/asm/processor.h | 4 ++++
>> arch/powerpc/include/asm/reg.h | 6 ++++++
>> arch/powerpc/kernel/sysfs.c | 8 ++++++++
>> arch/powerpc/perf/core-book3s.c | 29 ++++++++++++++++++++++++++++
>> 5 files changed, 49 insertions(+)
>>
>> diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
>> index 14b8dc1..832450a 100644
>> --- a/arch/powerpc/include/asm/perf_event_server.h
>> +++ b/arch/powerpc/include/asm/perf_event_server.h
>> @@ -22,6 +22,7 @@ struct mmcr_regs {
>> unsigned long mmcr1;
>> unsigned long mmcr2;
>> unsigned long mmcra;
>> + unsigned long mmcr3;
>> };
>> /*
>> * This struct provides the constants and functions needed to
>> @@ -75,6 +76,7 @@ struct power_pmu {
>> #define PPMU_HAS_SIER 0x00000040 /* Has SIER */
>> #define PPMU_ARCH_207S 0x00000080 /* PMC is architecture v2.07S */
>> #define PPMU_NO_SIAR 0x00000100 /* Do not use SIAR */
>> +#define PPMU_ARCH_310S 0x00000200 /* Has MMCR3, SIER2 and SIER3 */
> We elsewhere have CPU_FTR_ARCH_31, so should this be PPMU_ARCH_31S to
> be consistent.
>>
Ok,
This change will need to be done in all places which are currently using PPMU_ARCH_310S
>> /*
>> * Values for flags to get_alternatives()
>> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
>> index 52a6783..a466e94 100644
>> --- a/arch/powerpc/include/asm/processor.h
>> +++ b/arch/powerpc/include/asm/processor.h
>> @@ -272,6 +272,10 @@ struct thread_struct {
>> unsigned mmcr0;
>>
>> unsigned used_ebb;
>> + unsigned long mmcr3;
>> + unsigned long sier2;
>> + unsigned long sier3;
>> +
>> #endif
>> };
>>
>> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
>> index 88e6c78..21a1b2d 100644
>> --- a/arch/powerpc/include/asm/reg.h
>> +++ b/arch/powerpc/include/asm/reg.h
>> @@ -876,7 +876,9 @@
>> #define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
>> #define SPRN_MMCR1 798
>> #define SPRN_MMCR2 785
>> +#define SPRN_MMCR3 754
>> #define SPRN_UMMCR2 769
>> +#define SPRN_UMMCR3 738
>> #define SPRN_MMCRA 0x312
>> #define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
>> #define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
>> @@ -918,6 +920,10 @@
>> #define SIER_SIHV 0x1000000 /* Sampled MSR_HV */
>> #define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */
>> #define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */
>> +#define SPRN_SIER2 752
>> +#define SPRN_SIER3 753
>> +#define SPRN_USIER2 736
>> +#define SPRN_USIER3 737
>> #define SPRN_SIAR 796
>> #define SPRN_SDAR 797
>> #define SPRN_TACR 888
>> diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
>> index 571b325..46b4ebc 100644
>> --- a/arch/powerpc/kernel/sysfs.c
>> +++ b/arch/powerpc/kernel/sysfs.c
>> @@ -622,8 +622,10 @@ void ppc_enable_pmcs(void)
>> SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
>>
>> SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
>> +SYSFS_PMCSETUP(mmcr3, SPRN_MMCR3);
>>
>> static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
>> +static DEVICE_ATTR(mmcr3, 0600, show_mmcr3, store_mmcr3);
>> #endif /* HAS_PPC_PMC56 */
>>
>>
>> @@ -886,6 +888,9 @@ static int register_cpu_online(unsigned int cpu)
>> #ifdef CONFIG_PMU_SYSFS
>> if (cpu_has_feature(CPU_FTR_MMCRA))
>> device_create_file(s, &dev_attr_mmcra);
>> +
>> + if (cpu_has_feature(CPU_FTR_ARCH_31))
>> + device_create_file(s, &dev_attr_mmcr3);
>> #endif /* CONFIG_PMU_SYSFS */
>>
>> if (cpu_has_feature(CPU_FTR_PURR)) {
>> @@ -980,6 +985,9 @@ static int unregister_cpu_online(unsigned int cpu)
>> #ifdef CONFIG_PMU_SYSFS
>> if (cpu_has_feature(CPU_FTR_MMCRA))
>> device_remove_file(s, &dev_attr_mmcra);
>> +
>> + if (cpu_has_feature(CPU_FTR_ARCH_31))
>> + device_remove_file(s, &dev_attr_mmcr3);
>> #endif /* CONFIG_PMU_SYSFS */
>>
>> if (cpu_has_feature(CPU_FTR_PURR)) {
>> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
>> index f4d07b5..ca32fc0 100644
>> --- a/arch/powerpc/perf/core-book3s.c
>> +++ b/arch/powerpc/perf/core-book3s.c
>> @@ -72,6 +72,11 @@ struct cpu_hw_events {
>> /*
>> * 32-bit doesn't have MMCRA but does have an MMCR2,
>> * and a few other names are different.
>> + * Also 32-bit doesn't have MMCR3, SIER2 and SIER3.
>> + * Define them as zero knowing that any code path accessing
>> + * these registers (via mtspr/mfspr) are done under ppmu flag
>> + * check for PPMU_ARCH_310S and we will not enter that code path
>> + * for 32-bit.
>> */
>> #ifdef CONFIG_PPC32
>>
>> @@ -85,6 +90,9 @@ struct cpu_hw_events {
>> #define MMCR0_PMCC_U6 0
>>
>> #define SPRN_MMCRA SPRN_MMCR2
>> +#define SPRN_MMCR3 0
>> +#define SPRN_SIER2 0
>> +#define SPRN_SIER3 0
>> #define MMCRA_SAMPLE_ENABLE 0
>>
>> static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
>> @@ -581,6 +589,11 @@ static void ebb_switch_out(unsigned long mmcr0)
>> current->thread.sdar = mfspr(SPRN_SDAR);
>> current->thread.mmcr0 = mmcr0 & MMCR0_USER_MASK;
>> current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK;
>> + if (ppmu->flags & PPMU_ARCH_310S) {
>> + current->thread.mmcr3 = mfspr(SPRN_MMCR3);
> Like MMCR0_USER_MASK and MMCR2_USER_MASK do we need a MMCR3_USER_MASK
> here, or is there no need?
Jordan
We don’t need user mask for MMCR3 and other new SPRs ( SIER2/3) . Incase of MMCR3, we dont have any Freeze control bits and incase of SIER2/3, it is similar to SIER (where HW handles the masking of the bits), hence we didn't add any user_mask for these SPRs
Thanks
Athira
>> + current->thread.sier2 = mfspr(SPRN_SIER2);
>> + current->thread.sier3 = mfspr(SPRN_SIER3);
>> + }
>> }
>>
>> static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
>> @@ -620,6 +633,12 @@ static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
>> * instead manage the MMCR2 entirely by itself.
>> */
>> mtspr(SPRN_MMCR2, cpuhw->mmcr.mmcr2 | current->thread.mmcr2);
>> +
>> + if (ppmu->flags & PPMU_ARCH_310S) {
>> + mtspr(SPRN_MMCR3, current->thread.mmcr3);
>> + mtspr(SPRN_SIER2, current->thread.sier2);
>> + mtspr(SPRN_SIER3, current->thread.sier3);
>> + }
>> out:
>> return mmcr0;
>> }
>> @@ -840,6 +859,11 @@ void perf_event_print_debug(void)
>> pr_info("EBBRR: %016lx BESCR: %016lx\n",
>> mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
>> }
>> +
>> + if (ppmu->flags & PPMU_ARCH_310S) {
>> + pr_info("MMCR3: %016lx SIER2: %016lx SIER3: %016lx\n",
>> + mfspr(SPRN_MMCR3), mfspr(SPRN_SIER2), mfspr(SPRN_SIER3));
>> + }
>> #endif
>> pr_info("SIAR: %016lx SDAR: %016lx SIER: %016lx\n",
>> mfspr(SPRN_SIAR), sdar, sier);
>> @@ -1305,6 +1329,8 @@ static void power_pmu_enable(struct pmu *pmu)
>> if (!cpuhw->n_added) {
>> mtspr(SPRN_MMCRA, cpuhw->mmcr.mmcra & ~MMCRA_SAMPLE_ENABLE);
>> mtspr(SPRN_MMCR1, cpuhw->mmcr.mmcr1);
>> + if (ppmu->flags & PPMU_ARCH_310S)
>> + mtspr(SPRN_MMCR3, cpuhw->mmcr.mmcr3);
>> goto out_enable;
>> }
>>
>> @@ -1348,6 +1374,9 @@ static void power_pmu_enable(struct pmu *pmu)
>> if (ppmu->flags & PPMU_ARCH_207S)
>> mtspr(SPRN_MMCR2, cpuhw->mmcr.mmcr2);
>>
>> + if (ppmu->flags & PPMU_ARCH_310S)
>> + mtspr(SPRN_MMCR3, cpuhw->mmcr.mmcr3);
>> +
>> /*
>> * Read off any pre-existing events that need to move
>> * to another PMC.
>> --
>> 1.8.3.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20200722/5a9b72d5/attachment-0001.htm>
More information about the Linuxppc-dev
mailing list