Commit c718547e authored by Madhavan Srinivasan's avatar Madhavan Srinivasan Committed by Michael Ellerman
Browse files

powerpc/perf: Add support for ISA3.1 PMU SPRs



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_31" 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: default avatarMadhavan Srinivasan <maddy@linux.ibm.com>
[mpe: Rename to PPMU_ARCH_31 as noted by jpn]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/1594996707-3727-5-git-send-email-atrajeev@linux.vnet.ibm.com
parent 9d4fc86d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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_31		0x00000200 /* Has MMCR3, SIER2 and SIER3 */

/*
 * Values for flags to get_alternatives()
+4 −0
Original line number Diff line number Diff line
@@ -271,6 +271,10 @@ struct thread_struct {
	unsigned 	mmcr0;

	unsigned 	used_ebb;
	unsigned long   mmcr3;
	unsigned long   sier2;
	unsigned long   sier3;

#endif
};

+6 −0
Original line number Diff line number Diff line
@@ -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
+8 −0
Original line number Diff line number Diff line
@@ -622,8 +622,10 @@ SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
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)) {
+29 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
/*
 * 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_31 and we will not enter that code path
 * for 32-bit.
 */
#ifdef CONFIG_PPC32

@@ -85,6 +90,9 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
#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_31) {
		current->thread.mmcr3 = mfspr(SPRN_MMCR3);
		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_31) {
		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_31) {
		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_31)
			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_31)
		mtspr(SPRN_MMCR3, cpuhw->mmcr.mmcr3);

	/*
	 * Read off any pre-existing events that need to move
	 * to another PMC.