lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200302052355.36365-5-ravi.bangoria@linux.ibm.com>
Date:   Mon,  2 Mar 2020 10:53:48 +0530
From:   Ravi Bangoria <ravi.bangoria@...ux.ibm.com>
To:     linuxppc-dev@...ts.ozlabs.org, linux-kernel@...r.kernel.org
Cc:     eranian@...gle.com, peterz@...radead.org, mpe@...erman.id.au,
        paulus@...ba.org, mingo@...hat.com, acme@...nel.org,
        mark.rutland@....com, alexander.shishkin@...ux.intel.com,
        jolsa@...hat.com, namhyung@...nel.org, adrian.hunter@...el.com,
        ak@...ux.intel.com, kan.liang@...ux.intel.com,
        alexey.budankov@...ux.intel.com, yao.jin@...ux.intel.com,
        robert.richter@....com, kim.phillips@....com, maddy@...ux.ibm.com,
        ravi.bangoria@...ux.ibm.com,
        Madhavan Srinivasan <maddy@...ux.vnet.ibm.com>
Subject: [RFC 04/11] powerpc/perf: Arch support to expose Hazard data

From: Madhavan Srinivasan <maddy@...ux.vnet.ibm.com>

SIER register on PowerPC hw pmu provides cpu pipeline hazard information.
Add logic to convert this arch specific data into perf_pipeline_haz_data
structure.

Signed-off-by: Madhavan Srinivasan <maddy@...ux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@...ux.ibm.com>
---
 arch/powerpc/include/asm/perf_event_server.h |   2 +
 arch/powerpc/perf/core-book3s.c              |   4 +
 arch/powerpc/perf/isa207-common.c            | 157 +++++++++++++++++++
 arch/powerpc/perf/isa207-common.h            |  12 ++
 arch/powerpc/perf/power8-pmu.c               |   1 +
 arch/powerpc/perf/power9-pmu.c               |   1 +
 6 files changed, 177 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 3e9703f44c7c..9b8f90439ff2 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -37,6 +37,8 @@ struct power_pmu {
 	void		(*get_mem_data_src)(union perf_mem_data_src *dsrc,
 				u32 flags, struct pt_regs *regs);
 	void		(*get_mem_weight)(u64 *weight);
+	void		(*get_phazard_data)(struct perf_pipeline_haz_data *phaz,
+				u32 flags, struct pt_regs *regs);
 	unsigned long	group_constraint_mask;
 	unsigned long	group_constraint_val;
 	u64             (*bhrb_filter_map)(u64 branch_sample_type);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 3086055bf681..fcbb4acc3a03 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2096,6 +2096,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 						ppmu->get_mem_weight)
 			ppmu->get_mem_weight(&data.weight);
 
+		if (event->attr.sample_type & PERF_SAMPLE_PIPELINE_HAZ &&
+						ppmu->get_phazard_data)
+			ppmu->get_phazard_data(&data.pipeline_haz, ppmu->flags, regs);
+
 		if (perf_event_overflow(event, &data, regs))
 			power_pmu_stop(event, 0);
 	}
diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c
index 07026bbd292b..03dafde7cace 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -239,6 +239,163 @@ void isa207_get_mem_weight(u64 *weight)
 		*weight = mantissa << (2 * exp);
 }
 
+static __u8 get_inst_type(u64 sier)
+{
+	switch (SIER_TYPE(sier)) {
+	case 1:
+		return PERF_HAZ__ITYPE_LOAD;
+	case 2:
+		return PERF_HAZ__ITYPE_STORE;
+	case 3:
+		return PERF_HAZ__ITYPE_BRANCH;
+	case 4:
+		return PERF_HAZ__ITYPE_FP;
+	case 5:
+		return PERF_HAZ__ITYPE_FX;
+	case 6:
+		return PERF_HAZ__ITYPE_CR_OR_SC;
+	}
+	return PERF_HAZ__ITYPE_NA;
+}
+
+static __u8 get_inst_cache(u64 sier)
+{
+	switch (SIER_ICACHE(sier)) {
+	case 1:
+		return PERF_HAZ__ICACHE_L1_HIT;
+	case 2:
+		return PERF_HAZ__ICACHE_L2_HIT;
+	case 3:
+		return PERF_HAZ__ICACHE_L3_HIT;
+	case 4:
+		return PERF_HAZ__ICACHE_L3_MISS;
+	}
+	return PERF_HAZ__ICACHE_NA;
+}
+
+static void get_hazard_data(u64 sier, struct perf_pipeline_haz_data *haz)
+{
+	if (SIER_MPRED(sier)) {
+		haz->hazard_stage = PERF_HAZ__PIPE_STAGE_BRU;
+
+		switch (SIER_MPRED_TYPE(sier)) {
+		case 1:
+			haz->hazard_reason = PERF_HAZ__HAZ_BRU_MPRED_DIR;
+			return;
+		case 2:
+			haz->hazard_reason = PERF_HAZ__HAZ_BRU_MPRED_TA;
+			return;
+		}
+	}
+
+	if (cpu_has_feature(CPU_FTR_ARCH_300) &&
+	    (SIER_TYPE(sier) == 1 || SIER_TYPE(sier) == 2)) {
+		haz->hazard_stage = PERF_HAZ__PIPE_STAGE_LSU;
+		haz->hazard_reason = PERF_HAZ__HAZ_DERAT_MISS;
+		return;
+	}
+
+	if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
+	    (SIER_TYPE(sier) == 1 || SIER_TYPE(sier) == 2)) {
+		int derat_miss = SIER_DERAT_MISS(sier);
+
+		haz->hazard_stage = PERF_HAZ__PIPE_STAGE_LSU;
+
+		switch (p8_SIER_REJ_LSU_REASON(sier)) {
+		case 0:
+			haz->hazard_reason = PERF_HAZ__HAZ_LSU_ERAT_MISS;
+			return;
+		case 1:
+			haz->hazard_reason = (derat_miss) ?
+					     PERF_HAZ__HAZ_LSU_LMQ_DERAT_MISS :
+					     PERF_HAZ__HAZ_LSU_LMQ;
+			return;
+		case 2:
+			haz->hazard_reason = (derat_miss) ?
+					     PERF_HAZ__HAZ_LSU_LHS_DERAT_MISS :
+					     PERF_HAZ__HAZ_LSU_LHS;
+			return;
+		case 3:
+			haz->hazard_reason = (derat_miss) ?
+					     PERF_HAZ__HAZ_LSU_MPRED_DERAT_MISS :
+					     PERF_HAZ__HAZ_LSU_MPRED;
+			return;
+		}
+
+		if (derat_miss)
+			haz->hazard_reason = PERF_HAZ__HAZ_DERAT_MISS;
+	}
+
+	if (cpu_has_feature(CPU_FTR_ARCH_207S) && p8_SIER_REJ_ISU(sier)) {
+		haz->hazard_stage = PERF_HAZ__PIPE_STAGE_ISU;
+
+		if (p8_SIER_REJ_ISU_SRC(sier))
+			haz->hazard_reason = PERF_HAZ__HAZ_ISU_SRC;
+		if (p8_SIER_REJ_ISU_COL(sier))
+			haz->hazard_reason = PERF_HAZ__HAZ_ISU_COL;
+	}
+}
+
+static void get_stall_data(u64 sier, struct perf_pipeline_haz_data *haz)
+{
+	switch (SIER_FIN_STALL_REASON(sier)) {
+	case 1:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_OTHER;
+		haz->stall_reason = PERF_HAZ__STALL_NTC;
+		break;
+	case 4:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_LSU;
+		haz->stall_reason = PERF_HAZ__STALL_LSU_DCACHE_MISS;
+		break;
+	case 5:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_LSU;
+		haz->stall_reason = PERF_HAZ__STALL_LSU_LD_FIN;
+		break;
+	case 6:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_LSU;
+		haz->stall_reason = PERF_HAZ__STALL_LSU_ST_FWD;
+		break;
+	case 7:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_LSU;
+		haz->stall_reason = PERF_HAZ__STALL_LSU_ST;
+		break;
+	case 8:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_FXU;
+		haz->stall_reason = PERF_HAZ__STALL_FXU_MC;
+		break;
+	case 9:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_BRU;
+		haz->stall_reason = PERF_HAZ__STALL_BRU_FIN_MPRED;
+		break;
+	case 10:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_VSU;
+		haz->stall_reason = PERF_HAZ__STALL_VSU_MC;
+		break;
+	case 12:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_FXU;
+		haz->stall_reason = PERF_HAZ__STALL_FXU_FC;
+		break;
+	case 13:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_VSU;
+		haz->stall_reason = PERF_HAZ__STALL_VSU_FC;
+		break;
+	case 14:
+		haz->stall_stage = PERF_HAZ__PIPE_STAGE_BRU;
+		haz->stall_reason = PERF_HAZ__STALL_BRU_FC;
+	}
+}
+
+void isa207_get_phazard_data(struct perf_pipeline_haz_data *haz, u32 flags,
+			     struct pt_regs *regs)
+{
+	u64 sier = mfspr(SPRN_SIER);
+
+	haz->itype = get_inst_type(sier);
+	haz->icache = get_inst_cache(sier);
+	get_hazard_data(sier, haz);
+	get_stall_data(sier, haz);
+}
+
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
 	unsigned int unit, pmc, cache, ebb;
diff --git a/arch/powerpc/perf/isa207-common.h b/arch/powerpc/perf/isa207-common.h
index 7027eb9f3e40..125e0e44aeea 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -12,6 +12,7 @@
 #include <linux/perf_event.h>
 #include <asm/firmware.h>
 #include <asm/cputable.h>
+#include <asm/perf_pipeline_haz.h>
 
 #define EVENT_EBB_MASK		1ull
 #define EVENT_EBB_SHIFT		PERF_EVENT_CONFIG_EBB_SHIFT
@@ -202,8 +203,17 @@
 #define MAX_ALT				2
 #define MAX_PMU_COUNTERS		6
 
+#define SIER_FIN_STALL_REASON(sier)	(((sier) >> (63 -  6)) & 0xfull)
 #define SIER_DATA_SRC(sier)		(((sier) >> (63 - 10)) & 0x7ull)
+#define p8_SIER_REJ_ISU_SRC(sier)	(((sier) >> (63 - 32)) & 0x1ull)
+#define p8_SIER_REJ_ISU_COL(sier)	(((sier) >> (63 - 33)) & 0x1ull)
+#define p8_SIER_REJ_ISU(sier)		(((sier) >> (63 - 33)) & 0x3ull)
+#define p8_SIER_REJ_LSU_REASON(sier)	(((sier) >> (63 - 36)) & 0x3ull)
 #define SIER_TYPE(sier)			(((sier) >> (63 - 48)) & 0x7ull)
+#define SIER_ICACHE(sier)		(((sier) >> (63 - 51)) & 0x7ull)
+#define SIER_MPRED(sier)		(((sier) >> (63 - 53)) & 0x1ull)
+#define SIER_MPRED_TYPE(sier)		(((sier) >> (63 - 55)) & 0x3ull)
+#define SIER_DERAT_MISS(sier)		(((sier) >> (63 - 56)) & 0x1ull)
 #define SIER_LDST(sier)			(((sier) >> (63 - 62)) & 0x7ull)
 
 #define P(a, b)				PERF_MEM_S(a, b)
@@ -220,5 +230,7 @@ int isa207_get_alternatives(u64 event, u64 alt[], int size, unsigned int flags,
 void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
 							struct pt_regs *regs);
 void isa207_get_mem_weight(u64 *weight);
+void isa207_get_phazard_data(struct perf_pipeline_haz_data *haz, u32 flags,
+			     struct pt_regs *regs);
 
 #endif
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 3a5fcc20ff31..dc407329ba94 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -370,6 +370,7 @@ static struct power_pmu power8_pmu = {
 	.get_mem_data_src	= isa207_get_mem_data_src,
 	.get_mem_weight		= isa207_get_mem_weight,
 	.disable_pmc		= isa207_disable_pmc,
+	.get_phazard_data	= isa207_get_phazard_data,
 	.flags			= PPMU_HAS_SIER | PPMU_ARCH_207S,
 	.n_generic		= ARRAY_SIZE(power8_generic_events),
 	.generic_events		= power8_generic_events,
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 08c3ef796198..84f663d8df13 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -428,6 +428,7 @@ static struct power_pmu power9_pmu = {
 	.get_mem_data_src	= isa207_get_mem_data_src,
 	.get_mem_weight		= isa207_get_mem_weight,
 	.disable_pmc		= isa207_disable_pmc,
+	.get_phazard_data	= isa207_get_phazard_data,
 	.flags			= PPMU_HAS_SIER | PPMU_ARCH_207S,
 	.n_generic		= ARRAY_SIZE(power9_generic_events),
 	.generic_events		= power9_generic_events,
-- 
2.21.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ