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

powerpc/perf: Export memory hierarchy info to user space



The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: default avatarMadhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 8c5073db
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ struct power_pmu {
				unsigned long *valp);
	int		(*get_alternatives)(u64 event_id, unsigned int flags,
				u64 alt[]);
	void		(*get_mem_data_src)(union perf_mem_data_src *dsrc,
				u32 flags, struct pt_regs *regs);
	u64             (*bhrb_filter_map)(u64 branch_sample_type);
	void            (*config_bhrb)(u64 pmu_bhrb_filter);
	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
+4 −0
Original line number Diff line number Diff line
@@ -2049,6 +2049,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
			data.br_stack = &cpuhw->bhrb_stack;
		}

		if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
						ppmu->get_mem_data_src)
			ppmu->get_mem_data_src(&data.data_src, ppmu->flags, regs);

		if (perf_event_overflow(event, &data, regs))
			power_pmu_stop(event, 0);
	}
+74 −0
Original line number Diff line number Diff line
@@ -148,6 +148,80 @@ static bool is_thresh_cmp_valid(u64 event)
	return true;
}

static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
{
	u64 ret = PERF_MEM_NA;

	switch(idx) {
	case 0:
		/* Nothing to do */
		break;
	case 1:
		ret = PH(LVL, L1);
		break;
	case 2:
		ret = PH(LVL, L2);
		break;
	case 3:
		ret = PH(LVL, L3);
		break;
	case 4:
		if (sub_idx <= 1)
			ret = PH(LVL, LOC_RAM);
		else if (sub_idx > 1 && sub_idx <= 2)
			ret = PH(LVL, REM_RAM1);
		else
			ret = PH(LVL, REM_RAM2);
		ret |= P(SNOOP, HIT);
		break;
	case 5:
		ret = PH(LVL, REM_CCE1);
		if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
			ret |= P(SNOOP, HIT);
		else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
			ret |= P(SNOOP, HITM);
		break;
	case 6:
		ret = PH(LVL, REM_CCE2);
		if ((sub_idx == 0) || (sub_idx == 2))
			ret |= P(SNOOP, HIT);
		else if ((sub_idx == 1) || (sub_idx == 3))
			ret |= P(SNOOP, HITM);
		break;
	case 7:
		ret = PM(LVL, L1);
		break;
	}

	return ret;
}

void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
							struct pt_regs *regs)
{
	u64 idx;
	u32 sub_idx;
	u64 sier;
	u64 val;

	/* Skip if no SIER support */
	if (!(flags & PPMU_HAS_SIER)) {
		dsrc->val = 0;
		return;
	}

	sier = mfspr(SPRN_SIER);
	val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
	if (val == 1 || val == 2) {
		idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT;
		sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT;

		dsrc->val = isa207_find_source(idx, sub_idx);
		dsrc->val |= (val == 1) ? P(OP, LOAD) : P(OP, STORE);
	}
}


int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
{
	unsigned int unit, pmc, cache, ebb;
+15 −1
Original line number Diff line number Diff line
@@ -260,6 +260,19 @@
#define MAX_ALT				2
#define MAX_PMU_COUNTERS		6

#define ISA207_SIER_TYPE_SHIFT		15
#define ISA207_SIER_TYPE_MASK		(0x7ull << ISA207_SIER_TYPE_SHIFT)

#define ISA207_SIER_LDST_SHIFT		1
#define ISA207_SIER_LDST_MASK		(0x7ull << ISA207_SIER_LDST_SHIFT)

#define ISA207_SIER_DATA_SRC_SHIFT	53
#define ISA207_SIER_DATA_SRC_MASK	(0x7ull << ISA207_SIER_DATA_SRC_SHIFT)

#define P(a, b)				PERF_MEM_S(a, b)
#define PH(a, b)			(P(LVL, HIT) | P(a, b))
#define PM(a, b)			(P(LVL, MISS) | P(a, b))

int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp);
int isa207_compute_mmcr(u64 event[], int n_ev,
				unsigned int hwc[], unsigned long mmcr[],
@@ -267,6 +280,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev,
void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[]);
int isa207_get_alternatives(u64 event, u64 alt[],
				const unsigned int ev_alt[][MAX_ALT], int size);

void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
							struct pt_regs *regs);

#endif