LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 08/11] perf report: Enable hazard mode
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	Madhavan Srinivasan, adrian.hunter, acme, alexander.shishkin,
	yao.jin, mingo, paulus, eranian, robert.richter, namhyung,
	kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

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

Introduce --hazard with perf report to show perf report with hazard
data. Hazard mode columns are Instruction Type, Hazard Stage, Hazard
Reason, Stall Stage, Stall Reason and Icache access. Default sort
order is sym, dso, inst type, hazard stage, hazard reason, stall
stage, stall reason, inst cache.

Sample o/p on IBM PowerPC machine:

  Overhead  Symbol          Shared  Instruction Type  Hazard Stage   Hazard Reason         Stall Stage   Stall Reason  ICache access
    36.58%  [.] thread_run  ebizzy  Load              LSU            Mispredict            LSU           Load fin      L1 hit
     9.46%  [.] thread_run  ebizzy  Load              LSU            Mispredict            LSU           Dcache_miss   L1 hit
     1.76%  [.] thread_run  ebizzy  Fixed point       -              -                     -             -             L1 hit
     1.31%  [.] thread_run  ebizzy  Load              LSU            ERAT Miss             LSU           Load fin      L1 hit
     1.27%  [.] thread_run  ebizzy  Load              LSU            Mispredict            -             -             L1 hit
     1.16%  [.] thread_run  ebizzy  Fixed point       -              -                     FXU           Fixed cycle   L1 hit
     0.50%  [.] thread_run  ebizzy  Fixed point       ISU            Source Unavailable    FXU           Fixed cycle   L1 hit
     0.30%  [.] thread_run  ebizzy  Load              LSU            LMQ Full, DERAT Miss  LSU           Load fin      L1 hit
     0.24%  [.] thread_run  ebizzy  Load              LSU            ERAT Miss             -             -             L1 hit
     0.08%  [.] thread_run  ebizzy  -                 -              -                     BRU           Fixed cycle   L1 hit
     0.05%  [.] thread_run  ebizzy  Branch            -              -                     BRU           Fixed cycle   L1 hit
     0.04%  [.] thread_run  ebizzy  Fixed point       ISU            Source Unavailable    -             -             L1 hit

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 tools/perf/builtin-report.c |  28 +++++
 tools/perf/util/hist.c      |  77 ++++++++++++
 tools/perf/util/hist.h      |   7 ++
 tools/perf/util/sort.c      | 230 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/sort.h      |  22 ++++
 5 files changed, 364 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 72a12b69f120..a47542a12da1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -77,6 +77,7 @@ struct report {
 	bool			show_threads;
 	bool			inverted_callchain;
 	bool			mem_mode;
+	bool			hazard;
 	bool			stats_mode;
 	bool			tasks_mode;
 	bool			mmaps_mode;
@@ -285,6 +286,8 @@ static int process_sample_event(struct perf_tool *tool,
 		iter.ops = &hist_iter_branch;
 	} else if (rep->mem_mode) {
 		iter.ops = &hist_iter_mem;
+	} else if (rep->hazard) {
+		iter.ops = &hist_iter_haz;
 	} else if (symbol_conf.cumulate_callchain) {
 		iter.ops = &hist_iter_cumulative;
 	} else {
@@ -396,6 +399,14 @@ static int report__setup_sample_type(struct report *rep)
 		}
 	}
 
+	if (sort__mode == SORT_MODE__HAZARD) {
+		if (!is_pipe && !(sample_type & PERF_SAMPLE_PIPELINE_HAZ)) {
+			ui__error("Selected --hazard but no hazard data. "
+				  "Did you call perf record without --hazard?\n");
+			return -1;
+		}
+	}
+
 	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
 		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
 		    (sample_type & PERF_SAMPLE_STACK_USER)) {
@@ -484,6 +495,9 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
 	if (rep->mem_mode) {
 		ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
 		ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
+	} else if (rep->hazard) {
+		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
+		ret += fprintf(fp, "\n# Sort order: %s", sort_order ? : default_haz_sort_order);
 	} else
 		ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
 
@@ -1228,6 +1242,7 @@ int cmd_report(int argc, const char **argv)
 	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 		    "Enable kernel symbol demangling"),
 	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
+	OPT_BOOLEAN(0, "hazard", &report.hazard, "Processor pipeline hazard and stalls"),
 	OPT_INTEGER(0, "samples", &symbol_conf.res_sample,
 		    "Number of samples to save per histogram entry for individual browsing"),
 	OPT_CALLBACK(0, "percent-limit", &report, "percent",
@@ -1394,6 +1409,19 @@ int cmd_report(int argc, const char **argv)
 		symbol_conf.cumulate_callchain = false;
 	}
 
+	if (report.hazard) {
+		if (sort__mode == SORT_MODE__BRANCH) {
+			pr_err("branch and hazard incompatible\n");
+			goto error;
+		}
+		if (sort__mode == SORT_MODE__MEMORY) {
+			pr_err("mem-mode and hazard incompatible\n");
+			goto error;
+		}
+		sort__mode = SORT_MODE__HAZARD;
+		symbol_conf.cumulate_callchain = false;
+	}
+
 	if (symbol_conf.report_hierarchy) {
 		/* disable incompatible options */
 		symbol_conf.cumulate_callchain = false;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6d23efaa52c8..d690d08b0f64 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -203,6 +203,12 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
 	hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
 	hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
 	hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
+	hists__new_col_len(hists, HISTC_HAZ_ITYPE, 31);
+	hists__new_col_len(hists, HISTC_HAZ_ICACHE, 14);
+	hists__new_col_len(hists, HISTC_HAZ_HSTAGE, 13);
+	hists__new_col_len(hists, HISTC_HAZ_HREASON, 27);
+	hists__new_col_len(hists, HISTC_HAZ_SSTAGE, 12);
+	hists__new_col_len(hists, HISTC_HAZ_SREASON, 22);
 	if (symbol_conf.nanosecs)
 		hists__new_col_len(hists, HISTC_TIME, 16);
 	else
@@ -864,6 +870,69 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
 	return err;
 }
 
+static int iter_prepare_haz_entry(struct hist_entry_iter *iter,
+				  struct addr_location *al __maybe_unused)
+{
+	struct perf_sample *sample = iter->sample;
+	struct perf_pipeline_haz_data *haz_data;
+
+	if (!sample->pipeline_haz) {
+		iter->priv = NULL;
+		return 0;
+	}
+
+	haz_data = zalloc(sizeof(*haz_data));
+	if (!haz_data)
+		return -ENOMEM;
+
+	memcpy(haz_data, sample->pipeline_haz, sizeof(*haz_data));
+	iter->priv = haz_data;
+	return 0;
+}
+
+static int iter_add_single_haz_entry(struct hist_entry_iter *iter,
+				     struct addr_location *al __maybe_unused)
+{
+	struct perf_pipeline_haz_data *haz_data = iter->priv;
+	struct hists *hists = evsel__hists(iter->evsel);
+	struct perf_sample *sample = iter->sample;
+	struct hist_entry *he;
+
+	he = hists__add_entry(hists, al, iter->parent, NULL, NULL, haz_data,
+			      sample, true);
+	if (!he)
+		return -ENOMEM;
+
+	iter->he = he;
+	return 0;
+}
+
+static int iter_finish_haz_entry(struct hist_entry_iter *iter,
+				 struct addr_location *al __maybe_unused)
+{
+	struct evsel *evsel = iter->evsel;
+	struct hists *hists = evsel__hists(evsel);
+	struct hist_entry *he = iter->he;
+	int err = -EINVAL;
+
+	if (he == NULL)
+		goto out;
+
+	hists__inc_nr_samples(hists, he->filtered);
+
+	err = hist_entry__append_callchain(he, iter->sample);
+
+out:
+	/*
+	 * We don't need to free iter->priv (perf_pipeline_haz_data) here since
+	 * the hazard info was either already freed in hists__findnew_entry() or
+	 * passed to a new hist entry by hist_entry__new().
+	 */
+	iter->priv = NULL;
+	iter->he = NULL;
+	return err;
+}
+
 static int
 iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al)
 {
@@ -1128,6 +1197,14 @@ iter_finish_cumulative_entry(struct hist_entry_iter *iter,
 	return 0;
 }
 
+const struct hist_iter_ops hist_iter_haz = {
+	.prepare_entry		= iter_prepare_haz_entry,
+	.add_single_entry	= iter_add_single_haz_entry,
+	.next_entry		= iter_next_nop_entry,
+	.add_next_entry		= iter_add_next_nop_entry,
+	.finish_entry		= iter_finish_haz_entry,
+};
+
 const struct hist_iter_ops hist_iter_mem = {
 	.prepare_entry 		= iter_prepare_mem_entry,
 	.add_single_entry 	= iter_add_single_mem_entry,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a4d12a503126..063d65985a11 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -69,6 +69,12 @@ enum hist_column {
 	HISTC_SYM_SIZE,
 	HISTC_DSO_SIZE,
 	HISTC_SYMBOL_IPC,
+	HISTC_HAZ_ITYPE,
+	HISTC_HAZ_ICACHE,
+	HISTC_HAZ_HSTAGE,
+	HISTC_HAZ_HREASON,
+	HISTC_HAZ_SSTAGE,
+	HISTC_HAZ_SREASON,
 	HISTC_NR_COLS, /* Last entry */
 };
 
@@ -132,6 +138,7 @@ struct hist_entry_iter {
 extern const struct hist_iter_ops hist_iter_normal;
 extern const struct hist_iter_ops hist_iter_branch;
 extern const struct hist_iter_ops hist_iter_mem;
+extern const struct hist_iter_ops hist_iter_haz;
 extern const struct hist_iter_ops hist_iter_cumulative;
 
 struct hist_entry *hists__add_entry(struct hists *hists,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index ab0cfd790ad0..b6d47e7160af 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -23,6 +23,7 @@
 #include "strbuf.h"
 #include <traceevent/event-parse.h>
 #include "mem-events.h"
+#include "hazard.h"
 #include "annotate.h"
 #include "time-utils.h"
 #include <linux/kernel.h>
@@ -34,6 +35,7 @@ const char	*parent_pattern = default_parent_pattern;
 const char	*default_sort_order = "comm,dso,symbol";
 const char	default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
 const char	default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
+const char	default_haz_sort_order[] = "sym,dso,itype,hstage,hreason,sstage,sreason,icache";
 const char	default_top_sort_order[] = "dso,symbol";
 const char	default_diff_sort_order[] = "dso,symbol";
 const char	default_tracepoint_sort_order[] = "trace";
@@ -1377,6 +1379,190 @@ struct sort_entry sort_mem_dcacheline = {
 	.se_width_idx	= HISTC_MEM_DCACHELINE,
 };
 
+static int64_t sort__itype_cmp(struct hist_entry *l, struct hist_entry *r)
+{
+	u8 itype_l, itype_r;
+
+	itype_l = l->haz_data ? l->haz_data->itype : PERF_HAZ__ITYPE_NA;
+	itype_r = r->haz_data ? r->haz_data->itype : PERF_HAZ__ITYPE_NA;
+
+	return (int64_t)(itype_r - itype_l);
+}
+
+static int hist_entry__itype_snprintf(struct hist_entry *he, char *bf,
+				       size_t size, unsigned int width)
+{
+	const char *arch;
+	const char *itype = "-";
+
+	arch = hist_entry__get_arch(he);
+	if (he->haz_data)
+		itype = perf_haz__itype_str(he->haz_data->itype, arch);
+
+	return repsep_snprintf(bf, size, "%-*s", width, itype);
+}
+
+struct sort_entry sort_haz_inst_type = {
+	.se_header	= "Instruction Type",
+	.se_cmp		= sort__itype_cmp,
+	.se_snprintf	= hist_entry__itype_snprintf,
+	.se_width_idx	= HISTC_HAZ_ITYPE,
+};
+
+static int64_t sort__icache_cmp(struct hist_entry *l, struct hist_entry *r)
+{
+	u8 icache_l, icache_r;
+
+	icache_l = l->haz_data ? l->haz_data->icache : PERF_HAZ__ICACHE_NA;
+	icache_r = r->haz_data ? r->haz_data->icache : PERF_HAZ__ICACHE_NA;
+
+	return (int64_t)(icache_r - icache_l);
+}
+
+static int hist_entry__icache_snprintf(struct hist_entry *he, char *bf,
+					size_t size, unsigned int width)
+{
+	const char *arch;
+	const char *icache = "-";
+
+	arch = hist_entry__get_arch(he);
+	if (he->haz_data)
+		icache = perf_haz__icache_str(he->haz_data->icache, arch);
+
+	return repsep_snprintf(bf, size, "%-*s", width, icache);
+}
+
+struct sort_entry sort_haz_inst_cache = {
+	.se_header      = "ICache access",
+	.se_cmp         = sort__icache_cmp,
+	.se_snprintf    = hist_entry__icache_snprintf,
+	.se_width_idx   = HISTC_HAZ_ICACHE,
+};
+
+static int64_t sort__hstage_cmp(struct hist_entry *l, struct hist_entry *r)
+{
+	u8 hstage_l, hstage_r;
+
+	hstage_l = l->haz_data ? l->haz_data->hazard_stage : PERF_HAZ__PIPE_STAGE_NA;
+	hstage_r = r->haz_data ? r->haz_data->hazard_stage : PERF_HAZ__PIPE_STAGE_NA;
+
+	return (int64_t)(hstage_r - hstage_l);
+}
+
+static int hist_entry__hstage_snprintf(struct hist_entry *he, char *bf,
+					size_t size, unsigned int width)
+{
+	const char *arch;
+	const char *hstage = "-";
+
+	arch = hist_entry__get_arch(he);
+	if (he->haz_data)
+		hstage = perf_haz__hstage_str(he->haz_data->hazard_stage, arch);
+
+	return repsep_snprintf(bf, size, "%-*s", width, hstage);
+}
+
+struct sort_entry sort_haz_hazard_stage = {
+	.se_header      = "Hazard Stage",
+	.se_cmp         = sort__hstage_cmp,
+	.se_snprintf    = hist_entry__hstage_snprintf,
+	.se_width_idx   = HISTC_HAZ_HSTAGE,
+};
+
+static int64_t sort__hreason_cmp(struct hist_entry *l, struct hist_entry *r)
+{
+	u8 hreason_l, hreason_r;
+
+	hreason_l = l->haz_data ? l->haz_data->hazard_reason : PERF_HAZ__HREASON_NA;
+	hreason_r = r->haz_data ? r->haz_data->hazard_reason : PERF_HAZ__HREASON_NA;
+
+	return (int64_t)(hreason_r - hreason_l);
+}
+
+static int hist_entry__hreason_snprintf(struct hist_entry *he, char *bf,
+					 size_t size, unsigned int width)
+{
+	const char *arch;
+	const char *hreason = "-";
+
+	arch = hist_entry__get_arch(he);
+	if (he->haz_data) {
+		hreason = perf_haz__hreason_str(he->haz_data->hazard_stage,
+					he->haz_data->hazard_reason, arch);
+	}
+
+	return repsep_snprintf(bf, size, "%-*s", width, hreason);
+}
+
+struct sort_entry sort_haz_hazard_reason = {
+	.se_header      = "Hazard Reason",
+	.se_cmp         = sort__hreason_cmp,
+	.se_snprintf    = hist_entry__hreason_snprintf,
+	.se_width_idx   = HISTC_HAZ_HREASON,
+};
+
+static int64_t sort__sstage_cmp(struct hist_entry *l, struct hist_entry *r)
+{
+	u8 sstage_l, sstage_r;
+
+	sstage_l = l->haz_data ? l->haz_data->stall_stage : PERF_HAZ__PIPE_STAGE_NA;
+	sstage_r = r->haz_data ? r->haz_data->stall_stage : PERF_HAZ__PIPE_STAGE_NA;
+
+	return (int64_t)(sstage_r - sstage_l);
+}
+
+static int hist_entry__sstage_snprintf(struct hist_entry *he, char *bf,
+					size_t size, unsigned int width)
+{
+	const char *arch;
+	const char *sstage = "-";
+
+	arch = hist_entry__get_arch(he);
+	if (he->haz_data)
+		sstage = perf_haz__sstage_str(he->haz_data->stall_stage, arch);
+
+	return repsep_snprintf(bf, size, "%-*s", width, sstage);
+}
+
+struct sort_entry sort_haz_stall_stage = {
+	.se_header      = "Stall Stage",
+	.se_cmp         = sort__sstage_cmp,
+	.se_snprintf    = hist_entry__sstage_snprintf,
+	.se_width_idx   = HISTC_HAZ_SSTAGE,
+};
+
+static int64_t sort__sreason_cmp(struct hist_entry *l, struct hist_entry *r)
+{
+	u8 sreason_l, sreason_r;
+
+	sreason_l = l->haz_data ? l->haz_data->stall_reason : PERF_HAZ__SREASON_NA;
+	sreason_r = r->haz_data ? r->haz_data->stall_reason : PERF_HAZ__SREASON_NA;
+
+	return (int64_t)(sreason_r - sreason_l);
+}
+
+static int hist_entry__sreason_snprintf(struct hist_entry *he, char *bf,
+					     size_t size, unsigned int width)
+{
+	const char *arch;
+	const char *sreason = "-";
+
+	arch = hist_entry__get_arch(he);
+	if (he->haz_data) {
+		sreason = perf_haz__sreason_str(he->haz_data->stall_stage,
+					he->haz_data->stall_reason, arch);
+	}
+
+	return repsep_snprintf(bf, size, "%-*s", width, sreason);
+}
+
+struct sort_entry sort_haz_stall_reason = {
+	.se_header      = "Stall Reason",
+	.se_cmp         = sort__sreason_cmp,
+	.se_snprintf    = hist_entry__sreason_snprintf,
+	.se_width_idx   = HISTC_HAZ_SREASON,
+};
+
 static int64_t
 sort__phys_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -1699,6 +1885,19 @@ static struct sort_dimension memory_sort_dimensions[] = {
 
 #undef DIM
 
+#define DIM(d, n, func) [d - __SORT_HAZARD_MODE] = { .name = n, .entry = &(func) }
+
+static struct sort_dimension hazard_sort_dimensions[] = {
+       DIM(SORT_HAZ_ITYPE, "itype", sort_haz_inst_type),
+       DIM(SORT_HAZ_ICACHE, "icache", sort_haz_inst_cache),
+       DIM(SORT_HAZ_HSTAGE, "hstage", sort_haz_hazard_stage),
+       DIM(SORT_HAZ_HREASON, "hreason", sort_haz_hazard_reason),
+       DIM(SORT_HAZ_SSTAGE, "sstage", sort_haz_stall_stage),
+       DIM(SORT_HAZ_SREASON, "sreason", sort_haz_stall_reason),
+};
+
+#undef DIM
+
 struct hpp_dimension {
 	const char		*name;
 	struct perf_hpp_fmt	*fmt;
@@ -2643,6 +2842,19 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
 		return 0;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(hazard_sort_dimensions); i++) {
+		struct sort_dimension *sd = &hazard_sort_dimensions[i];
+
+		if (strncasecmp(tok, sd->name, strlen(tok)))
+			continue;
+
+		if (sort__mode != SORT_MODE__HAZARD)
+			return -EINVAL;
+
+		__sort_dimension__add(sd, list, level);
+		return 0;
+	}
+
 	if (!add_dynamic_entry(evlist, tok, level))
 		return 0;
 
@@ -2705,6 +2917,7 @@ static const char *get_default_sort_order(struct evlist *evlist)
 		default_top_sort_order,
 		default_diff_sort_order,
 		default_tracepoint_sort_order,
+		default_haz_sort_order,
 	};
 	bool use_trace = true;
 	struct evsel *evsel;
@@ -2976,6 +3189,18 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
 		return __sort_dimension__add_output(list, sd);
 	}
 
+	for (i = 0; i < ARRAY_SIZE(hazard_sort_dimensions); i++) {
+		struct sort_dimension *sd = &hazard_sort_dimensions[i];
+
+		if (strncasecmp(tok, sd->name, strlen(tok)))
+			continue;
+
+		if (sort__mode != SORT_MODE__HAZARD)
+			return -EINVAL;
+
+		return __sort_dimension__add_output(list, sd);
+	}
+
 	return -ESRCH;
 }
 
@@ -3014,6 +3239,9 @@ void reset_dimensions(void)
 
 	for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++)
 		memory_sort_dimensions[i].taken = 0;
+
+	for (i = 0; i < ARRAY_SIZE(hazard_sort_dimensions); i++)
+		hazard_sort_dimensions[i].taken = 0;
 }
 
 bool is_strict_order(const char *order)
@@ -3148,6 +3376,8 @@ const char *sort_help(const char *prefix)
 			    ARRAY_SIZE(bstack_sort_dimensions), &len);
 	add_sort_string(&sb, memory_sort_dimensions,
 			    ARRAY_SIZE(memory_sort_dimensions), &len);
+	add_sort_string(&sb, hazard_sort_dimensions,
+			    ARRAY_SIZE(hazard_sort_dimensions), &len);
 	s = strbuf_detach(&sb, NULL);
 	strbuf_release(&sb);
 	return s;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 55eb65fd593f..3c18ece0aa4f 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -12,6 +12,7 @@
 #include "hist.h"
 #include "stat.h"
 #include "spark.h"
+#include "env.h"
 
 struct option;
 struct thread;
@@ -36,6 +37,7 @@ extern struct sort_entry sort_sym_to;
 extern struct sort_entry sort_srcline;
 extern enum sort_type sort__first_dimension;
 extern const char default_mem_sort_order[];
+extern const char default_haz_sort_order[];
 
 struct res_sample {
 	u64 time;
@@ -199,6 +201,16 @@ static inline float hist_entry__get_percent_limit(struct hist_entry *he)
 	return period * 100.0 / total_period;
 }
 
+static inline struct perf_env *hist_entry__env(struct hist_entry *he)
+{
+	return perf_evsel__env(hists_to_evsel(he->hists));
+}
+
+static inline const char *hist_entry__get_arch(struct hist_entry *he)
+{
+	return perf_env__arch(hist_entry__env(he));
+}
+
 enum sort_mode {
 	SORT_MODE__NORMAL,
 	SORT_MODE__BRANCH,
@@ -206,6 +218,7 @@ enum sort_mode {
 	SORT_MODE__TOP,
 	SORT_MODE__DIFF,
 	SORT_MODE__TRACEPOINT,
+	SORT_MODE__HAZARD,
 };
 
 enum sort_type {
@@ -254,6 +267,15 @@ enum sort_type {
 	SORT_MEM_DCACHELINE,
 	SORT_MEM_IADDR_SYMBOL,
 	SORT_MEM_PHYS_DADDR,
+
+	/* hazard mode specific sort keys */
+	__SORT_HAZARD_MODE,
+	SORT_HAZ_ITYPE = __SORT_HAZARD_MODE,
+	SORT_HAZ_ICACHE,
+	SORT_HAZ_HSTAGE,
+	SORT_HAZ_HREASON,
+	SORT_HAZ_SSTAGE,
+	SORT_HAZ_SREASON,
 };
 
 /*
-- 
2.21.1


^ permalink raw reply related

* [RFC 07/11] perf hazard: Functions to convert generic hazard data to arch specific string
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	Madhavan Srinivasan, adrian.hunter, acme, alexander.shishkin,
	yao.jin, mingo, paulus, eranian, robert.richter, namhyung,
	kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

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

Kernel provides pipeline hazard data in struct perf_pipeline_haz_data
format. Add code to convert this data into meaningful string which can
be shown in perf report (followup patch).

Introduce tools/perf/utils/hazard directory which will contains arch
specific directories. Under arch specific directory, add arch specific
logic that will be called by generic code. This directory structure is
introduced to enable cross-arch reporting.

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 tools/perf/util/Build                         |   2 +
 tools/perf/util/hazard.c                      |  51 +++++++
 tools/perf/util/hazard.h                      |  14 ++
 tools/perf/util/hazard/Build                  |   1 +
 .../util/hazard/powerpc/perf_pipeline_haz.h   |  80 ++++++++++
 .../perf/util/hazard/powerpc/powerpc_hazard.c | 142 ++++++++++++++++++
 .../perf/util/hazard/powerpc/powerpc_hazard.h |  14 ++
 7 files changed, 304 insertions(+)
 create mode 100644 tools/perf/util/hazard.c
 create mode 100644 tools/perf/util/hazard.h
 create mode 100644 tools/perf/util/hazard/Build
 create mode 100644 tools/perf/util/hazard/powerpc/perf_pipeline_haz.h
 create mode 100644 tools/perf/util/hazard/powerpc/powerpc_hazard.c
 create mode 100644 tools/perf/util/hazard/powerpc/powerpc_hazard.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 07da6c790b63..f5e1b7d79b6d 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -118,6 +118,7 @@ perf-y += parse-regs-options.o
 perf-y += term.o
 perf-y += help-unknown-cmd.o
 perf-y += mem-events.o
+perf-y += hazard.o
 perf-y += vsprintf.o
 perf-y += units.o
 perf-y += time-utils.o
@@ -153,6 +154,7 @@ perf-$(CONFIG_LIBUNWIND_AARCH64)  += libunwind/arm64.o
 perf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
 
 perf-y += scripting-engines/
+perf-y += hazard/
 
 perf-$(CONFIG_ZLIB) += zlib.o
 perf-$(CONFIG_LZMA) += lzma.o
diff --git a/tools/perf/util/hazard.c b/tools/perf/util/hazard.c
new file mode 100644
index 000000000000..db235b26b266
--- /dev/null
+++ b/tools/perf/util/hazard.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
+#include "hazard/powerpc/powerpc_hazard.h"
+
+const char *perf_haz__itype_str(u8 itype, const char *arch)
+{
+	if (!strncmp(arch, "powerpc", strlen("powerpc")))
+		return powerpc__haz__itype_str(itype);
+
+	return "-";
+}
+
+const char *perf_haz__icache_str(u8 icache, const char *arch)
+{
+	if (!strncmp(arch, "powerpc", strlen("powerpc")))
+		return powerpc__haz__icache_str(icache);
+
+	return "-";
+}
+
+const char *perf_haz__hstage_str(u8 hstage, const char *arch)
+{
+	if (!strncmp(arch, "powerpc", strlen("powerpc")))
+		return powerpc__haz__hstage_str(hstage);
+
+	return "-";
+}
+
+const char *perf_haz__hreason_str(u8 hstage, u8 hreason, const char *arch)
+{
+	if (!strncmp(arch, "powerpc", strlen("powerpc")))
+		return powerpc__haz__hreason_str(hstage, hreason);
+
+	return "-";
+}
+
+const char *perf_haz__sstage_str(u8 sstage, const char *arch)
+{
+	if (!strncmp(arch, "powerpc", strlen("powerpc")))
+		return powerpc__haz__sstage_str(sstage);
+
+	return "-";
+}
+
+const char *perf_haz__sreason_str(u8 sstage, u8 sreason, const char *arch)
+{
+	if (!strncmp(arch, "powerpc", strlen("powerpc")))
+		return powerpc__haz__sreason_str(sstage, sreason);
+
+	return "-";
+}
diff --git a/tools/perf/util/hazard.h b/tools/perf/util/hazard.h
new file mode 100644
index 000000000000..eab4190e056a
--- /dev/null
+++ b/tools/perf/util/hazard.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_HAZARD_H
+#define __PERF_HAZARD_H
+
+#include "sort.h"
+
+const char *perf_haz__itype_str(u8 itype, const char *arch);
+const char *perf_haz__icache_str(u8 icache, const char *arch);
+const char *perf_haz__hstage_str(u8 hstage, const char *arch);
+const char *perf_haz__hreason_str(u8 hstage, u8 hreason, const char *arch);
+const char *perf_haz__sstage_str(u8 sstage, const char *arch);
+const char *perf_haz__sreason_str(u8 sstage, u8 sreason, const char *arch);
+
+#endif /* __PERF_HAZARD_H */
diff --git a/tools/perf/util/hazard/Build b/tools/perf/util/hazard/Build
new file mode 100644
index 000000000000..314c5e316383
--- /dev/null
+++ b/tools/perf/util/hazard/Build
@@ -0,0 +1 @@
+perf-y += powerpc/powerpc_hazard.o
diff --git a/tools/perf/util/hazard/powerpc/perf_pipeline_haz.h b/tools/perf/util/hazard/powerpc/perf_pipeline_haz.h
new file mode 100644
index 000000000000..de8857ec31dd
--- /dev/null
+++ b/tools/perf/util/hazard/powerpc/perf_pipeline_haz.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_ASM_POWERPC_PERF_PIPELINE_HAZ_H
+#define _UAPI_ASM_POWERPC_PERF_PIPELINE_HAZ_H
+
+enum perf_inst_type {
+	PERF_HAZ__ITYPE_LOAD = 1,
+	PERF_HAZ__ITYPE_STORE,
+	PERF_HAZ__ITYPE_BRANCH,
+	PERF_HAZ__ITYPE_FP,
+	PERF_HAZ__ITYPE_FX,
+	PERF_HAZ__ITYPE_CR_OR_SC,
+};
+
+enum perf_inst_cache {
+	PERF_HAZ__ICACHE_L1_HIT = 1,
+	PERF_HAZ__ICACHE_L2_HIT,
+	PERF_HAZ__ICACHE_L3_HIT,
+	PERF_HAZ__ICACHE_L3_MISS,
+};
+
+enum perf_pipeline_stage {
+	PERF_HAZ__PIPE_STAGE_IFU = 1,
+	PERF_HAZ__PIPE_STAGE_IDU,
+	PERF_HAZ__PIPE_STAGE_ISU,
+	PERF_HAZ__PIPE_STAGE_LSU,
+	PERF_HAZ__PIPE_STAGE_BRU,
+	PERF_HAZ__PIPE_STAGE_FXU,
+	PERF_HAZ__PIPE_STAGE_FPU,
+	PERF_HAZ__PIPE_STAGE_VSU,
+	PERF_HAZ__PIPE_STAGE_OTHER,
+};
+
+enum perf_haz_bru_reason {
+	PERF_HAZ__HAZ_BRU_MPRED_DIR = 1,
+	PERF_HAZ__HAZ_BRU_MPRED_TA,
+};
+
+enum perf_haz_isu_reason {
+	PERF_HAZ__HAZ_ISU_SRC = 1,
+	PERF_HAZ__HAZ_ISU_COL = 1,
+};
+
+enum perf_haz_lsu_reason {
+	PERF_HAZ__HAZ_LSU_ERAT_MISS = 1,
+	PERF_HAZ__HAZ_LSU_LMQ,
+	PERF_HAZ__HAZ_LSU_LHS,
+	PERF_HAZ__HAZ_LSU_MPRED,
+	PERF_HAZ__HAZ_DERAT_MISS,
+	PERF_HAZ__HAZ_LSU_LMQ_DERAT_MISS,
+	PERF_HAZ__HAZ_LSU_LHS_DERAT_MISS,
+	PERF_HAZ__HAZ_LSU_MPRED_DERAT_MISS,
+};
+
+enum perf_stall_lsu_reason {
+	PERF_HAZ__STALL_LSU_DCACHE_MISS = 1,
+	PERF_HAZ__STALL_LSU_LD_FIN,
+	PERF_HAZ__STALL_LSU_ST_FWD,
+	PERF_HAZ__STALL_LSU_ST,
+};
+
+enum perf_stall_fxu_reason {
+	PERF_HAZ__STALL_FXU_MC = 1,
+	PERF_HAZ__STALL_FXU_FC,
+};
+
+enum perf_stall_bru_reason {
+	PERF_HAZ__STALL_BRU_FIN_MPRED = 1,
+	PERF_HAZ__STALL_BRU_FC,
+};
+
+enum perf_stall_vsu_reason {
+	PERF_HAZ__STALL_VSU_MC = 1,
+	PERF_HAZ__STALL_VSU_FC,
+};
+
+enum perf_stall_other_reason {
+	PERF_HAZ__STALL_NTC,
+};
+
+#endif /* _UAPI_ASM_POWERPC_PERF_PIPELINE_HAZ_H */
diff --git a/tools/perf/util/hazard/powerpc/powerpc_hazard.c b/tools/perf/util/hazard/powerpc/powerpc_hazard.c
new file mode 100644
index 000000000000..dcb95b769367
--- /dev/null
+++ b/tools/perf/util/hazard/powerpc/powerpc_hazard.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stddef.h>
+#include "hazard.h"
+#include "powerpc_hazard.h"
+#include "perf_pipeline_haz.h"
+
+static const char *haz_inst_type[] = {
+	"-",
+	"Load",
+	"Store",
+	"Branch",
+	"Floating Point",
+	"Fixed point",
+	"Condition Register/System Call",
+};
+
+const char *powerpc__haz__itype_str(u8 itype)
+{
+	return haz_inst_type[itype];
+}
+
+static const char *haz_inst_cache[] = {
+	"-",
+	"L1 hit",
+	"L2 hit",
+	"L3 hit",
+	"L3 Miss"
+};
+
+const char *powerpc__haz__icache_str(u8 icache)
+{
+	return haz_inst_cache[icache];
+}
+
+static const char *pipeline_stages[] = {
+	"-",
+	"IFU",
+	"IDU",
+	"ISU",
+	"LSU",
+	"BRU",
+	"FXU",
+	"FPU",
+	"VSU",
+};
+
+const char *powerpc__haz__hstage_str(u8 hstage)
+{
+	return pipeline_stages[hstage];
+}
+
+static const char *haz_bru_reason[] = {
+	"-",
+	"Direction",
+	"Target Address",
+};
+
+static const char *haz_isu_reason[] = {
+	"-",
+	"Source Unavailable",
+	"Resource Collision",
+};
+
+static const char *haz_lsu_reason[] = {
+	"-",
+	"ERAT Miss",
+	"LMQ Full",
+	"Load Hit Store",
+	"Mispredict",
+	"DERAT Miss",
+	"LMQ Full, DERAT Miss",
+	"Load Hit Store, DERAT Miss",
+	"Mispredict, DERAT Miss",
+};
+
+const char *powerpc__haz__hreason_str(u8 hstage, u8 hreason)
+{
+	switch (hstage) {
+	case PERF_HAZ__PIPE_STAGE_BRU:
+		return haz_bru_reason[hreason];
+	case PERF_HAZ__PIPE_STAGE_LSU:
+		return haz_lsu_reason[hreason];
+	case PERF_HAZ__PIPE_STAGE_ISU:
+		return haz_isu_reason[hreason];
+	default:
+		return "-";
+	}
+}
+
+const char *powerpc__haz__sstage_str(u8 sstage)
+{
+	return pipeline_stages[sstage];
+}
+
+static const char *stall_lsu_reason[] = {
+	"-",
+	"Dcache_miss",
+	"Load fin",
+	"Store fwd",
+	"Store",
+};
+
+static const char *stall_fxu_reason[] = {
+	"-",
+	"Multi cycle",
+	"Fixed cycle",
+};
+
+static const char *stall_bru_reason[] = {
+	"-",
+	"Finish Mispredict",
+	"Fixed cycle",
+};
+
+static const char *stall_vsu_reason[] = {
+	"-",
+	"Multi cycle",
+	"Fixed cycle",
+};
+
+static const char *stall_other_reason[] = {
+	"-",
+	"Marked fin before NTC",
+};
+
+const char *powerpc__haz__sreason_str(u8 sstage, u8 sreason)
+{
+	switch (sstage) {
+	case PERF_HAZ__PIPE_STAGE_LSU:
+		return stall_lsu_reason[sreason];
+	case PERF_HAZ__PIPE_STAGE_FXU:
+		return stall_fxu_reason[sreason];
+	case PERF_HAZ__PIPE_STAGE_BRU:
+		return stall_bru_reason[sreason];
+	case PERF_HAZ__PIPE_STAGE_VSU:
+		return stall_vsu_reason[sreason];
+	case PERF_HAZ__PIPE_STAGE_OTHER:
+		return stall_other_reason[sreason];
+	default:
+		return "-";
+	}
+}
diff --git a/tools/perf/util/hazard/powerpc/powerpc_hazard.h b/tools/perf/util/hazard/powerpc/powerpc_hazard.h
new file mode 100644
index 000000000000..f13f8f3cd10d
--- /dev/null
+++ b/tools/perf/util/hazard/powerpc/powerpc_hazard.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_POWERPC_HAZARD_H
+#define __PERF_POWERPC_HAZARD_H
+
+#include "hazard.h"
+
+const char *powerpc__haz__itype_str(u8 itype);
+const char *powerpc__haz__icache_str(u8 icache);
+const char *powerpc__haz__hstage_str(u8 hstage);
+const char *powerpc__haz__hreason_str(u8 hstage, u8 hreason);
+const char *powerpc__haz__sstage_str(u8 sstage);
+const char *powerpc__haz__sreason_str(u8 sstage, u8 sreason);
+
+#endif /* __PERF_POWERPC_HAZARD_H */
-- 
2.21.1


^ permalink raw reply related

* [RFC 06/11] perf hists: Make a room for hazard info in struct hist_entry
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	Madhavan Srinivasan, adrian.hunter, acme, alexander.shishkin,
	yao.jin, mingo, paulus, eranian, robert.richter, namhyung,
	kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

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

To enable hazard mode with perf report (followup patch) we need to
have cpu pipeline hazard data available in hist_entry. Add hazard
info into struct hist_entry. Also add hazard_info as parameter to
hists__add_entry().

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 tools/perf/builtin-annotate.c |  2 +-
 tools/perf/builtin-c2c.c      |  4 ++--
 tools/perf/builtin-diff.c     |  6 +++---
 tools/perf/tests/hists_link.c |  4 ++--
 tools/perf/util/hist.c        | 22 +++++++++++++++-------
 tools/perf/util/hist.h        |  2 ++
 tools/perf/util/sort.h        |  1 +
 7 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6c0a0412502e..78552a9428a6 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -249,7 +249,7 @@ static int perf_evsel__add_sample(struct evsel *evsel,
 	if (ann->has_br_stack && has_annotation(ann))
 		return process_branch_callback(evsel, sample, al, ann, machine);
 
-	he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
+	he = hists__add_entry(hists, al, NULL, NULL, NULL, NULL, sample, true);
 	if (he == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 246ac0b4d54f..2a1cb5cda6d9 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -292,7 +292,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 	c2c_decode_stats(&stats, mi);
 
 	he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
-				  &al, NULL, NULL, mi,
+				  &al, NULL, NULL, mi, NULL,
 				  sample, true);
 	if (he == NULL)
 		goto free_mi;
@@ -326,7 +326,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 			goto free_mi;
 
 		he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
-					  &al, NULL, NULL, mi,
+					  &al, NULL, NULL, mi, NULL,
 					  sample, true);
 		if (he == NULL)
 			goto free_mi;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index f8b6ae557d8b..e32e91f89a18 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -412,15 +412,15 @@ static int diff__process_sample_event(struct perf_tool *tool,
 	}
 
 	if (compute != COMPUTE_CYCLES) {
-		if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample,
-				      true)) {
+		if (!hists__add_entry(hists, &al, NULL, NULL, NULL, NULL,
+				      sample, true)) {
 			pr_warning("problem incrementing symbol period, "
 				   "skipping event\n");
 			goto out_put;
 		}
 	} else {
 		if (!hists__add_entry_ops(hists, &block_hist_ops, &al, NULL,
-					  NULL, NULL, sample, true)) {
+					  NULL, NULL, NULL, sample, true)) {
 			pr_warning("problem incrementing symbol period, "
 				   "skipping event\n");
 			goto out_put;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index a024d3f3a412..112a90818d2e 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -86,7 +86,7 @@ static int add_hist_entries(struct evlist *evlist, struct machine *machine)
 			if (machine__resolve(machine, &al, &sample) < 0)
 				goto out;
 
-			he = hists__add_entry(hists, &al, NULL,
+			he = hists__add_entry(hists, &al, NULL, NULL,
 						NULL, NULL, &sample, true);
 			if (he == NULL) {
 				addr_location__put(&al);
@@ -105,7 +105,7 @@ static int add_hist_entries(struct evlist *evlist, struct machine *machine)
 			if (machine__resolve(machine, &al, &sample) < 0)
 				goto out;
 
-			he = hists__add_entry(hists, &al, NULL,
+			he = hists__add_entry(hists, &al, NULL, NULL,
 						NULL, NULL, &sample, true);
 			if (he == NULL) {
 				addr_location__put(&al);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index ca5a8f4d007e..6d23efaa52c8 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -604,6 +604,7 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
 			 * and will not be used anymore.
 			 */
 			mem_info__zput(entry->mem_info);
+			zfree(&entry->haz_data);
 
 			block_info__zput(entry->block_info);
 
@@ -678,6 +679,7 @@ __hists__add_entry(struct hists *hists,
 		   struct symbol *sym_parent,
 		   struct branch_info *bi,
 		   struct mem_info *mi,
+		   struct perf_pipeline_haz_data *haz_data,
 		   struct block_info *block_info,
 		   struct perf_sample *sample,
 		   bool sample_self,
@@ -712,6 +714,7 @@ __hists__add_entry(struct hists *hists,
 		.hists	= hists,
 		.branch_info = bi,
 		.mem_info = mi,
+		.haz_data = haz_data,
 		.block_info = block_info,
 		.transaction = sample->transaction,
 		.raw_data = sample->raw_data,
@@ -732,10 +735,11 @@ struct hist_entry *hists__add_entry(struct hists *hists,
 				    struct symbol *sym_parent,
 				    struct branch_info *bi,
 				    struct mem_info *mi,
+				    struct perf_pipeline_haz_data *haz_data,
 				    struct perf_sample *sample,
 				    bool sample_self)
 {
-	return __hists__add_entry(hists, al, sym_parent, bi, mi, NULL,
+	return __hists__add_entry(hists, al, sym_parent, bi, mi, haz_data, NULL,
 				  sample, sample_self, NULL);
 }
 
@@ -745,10 +749,11 @@ struct hist_entry *hists__add_entry_ops(struct hists *hists,
 					struct symbol *sym_parent,
 					struct branch_info *bi,
 					struct mem_info *mi,
+					struct perf_pipeline_haz_data *haz_data,
 					struct perf_sample *sample,
 					bool sample_self)
 {
-	return __hists__add_entry(hists, al, sym_parent, bi, mi, NULL,
+	return __hists__add_entry(hists, al, sym_parent, bi, mi, haz_data, NULL,
 				  sample, sample_self, ops);
 }
 
@@ -823,7 +828,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
 	sample->period = cost;
 
 	he = hists__add_entry(hists, al, iter->parent, NULL, mi,
-			      sample, true);
+			      NULL, sample, true);
 	if (!he)
 		return -ENOMEM;
 
@@ -926,7 +931,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
 	sample->weight = bi->flags.cycles ? bi->flags.cycles : 1;
 
 	he = hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
-			      sample, true);
+			      NULL, sample, true);
 	if (he == NULL)
 		return -ENOMEM;
 
@@ -963,7 +968,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
 	struct hist_entry *he;
 
 	he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
-			      sample, true);
+			      NULL, sample, true);
 	if (he == NULL)
 		return -ENOMEM;
 
@@ -1024,7 +1029,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
 	int err = 0;
 
 	he = hists__add_entry(hists, al, iter->parent, NULL, NULL,
-			      sample, true);
+			      NULL, sample, true);
 	if (he == NULL)
 		return -ENOMEM;
 
@@ -1101,7 +1106,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
 	}
 
 	he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
-			      sample, false);
+			      NULL, sample, false);
 	if (he == NULL)
 		return -ENOMEM;
 
@@ -1268,6 +1273,9 @@ void hist_entry__delete(struct hist_entry *he)
 		mem_info__zput(he->mem_info);
 	}
 
+	if (he->haz_data)
+		zfree(&he->haz_data);
+
 	if (he->block_info)
 		block_info__zput(he->block_info);
 
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 0aa63aeb58ec..a4d12a503126 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -139,6 +139,7 @@ struct hist_entry *hists__add_entry(struct hists *hists,
 				    struct symbol *parent,
 				    struct branch_info *bi,
 				    struct mem_info *mi,
+				    struct perf_pipeline_haz_data *haz_data,
 				    struct perf_sample *sample,
 				    bool sample_self);
 
@@ -148,6 +149,7 @@ struct hist_entry *hists__add_entry_ops(struct hists *hists,
 					struct symbol *sym_parent,
 					struct branch_info *bi,
 					struct mem_info *mi,
+					struct perf_pipeline_haz_data *haz_data,
 					struct perf_sample *sample,
 					bool sample_self);
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 6c862d62d052..55eb65fd593f 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -139,6 +139,7 @@ struct hist_entry {
 	long			time;
 	struct hists		*hists;
 	struct mem_info		*mem_info;
+	struct perf_pipeline_haz_data *haz_data;
 	struct block_info	*block_info;
 	void			*raw_data;
 	u32			raw_size;
-- 
2.21.1


^ permalink raw reply related

* [RFC 03/11] powerpc/perf: Arch specific definitions for pipeline
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	Madhavan Srinivasan, adrian.hunter, acme, alexander.shishkin,
	yao.jin, mingo, paulus, eranian, robert.richter, namhyung,
	kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

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

Create powerpc specific definitions for pipeline hazard and stalls.
This information is available in SIER register on powerpc. Current
definitions are based on IBM PowerPC SIER specification available
in ISA[1] and Performance Monitor Unit User’s Guide[2].

[1]: Book III, Section 9.4.10:
     https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0
[2]: https://wiki.raptorcs.com/w/images/6/6b/POWER9_PMU_UG_v12_28NOV2018_pub.pdf#G9.1106986

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 .../include/uapi/asm/perf_pipeline_haz.h      | 80 +++++++++++++++++++
 1 file changed, 80 insertions(+)
 create mode 100644 arch/powerpc/include/uapi/asm/perf_pipeline_haz.h

diff --git a/arch/powerpc/include/uapi/asm/perf_pipeline_haz.h b/arch/powerpc/include/uapi/asm/perf_pipeline_haz.h
new file mode 100644
index 000000000000..de8857ec31dd
--- /dev/null
+++ b/arch/powerpc/include/uapi/asm/perf_pipeline_haz.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_ASM_POWERPC_PERF_PIPELINE_HAZ_H
+#define _UAPI_ASM_POWERPC_PERF_PIPELINE_HAZ_H
+
+enum perf_inst_type {
+	PERF_HAZ__ITYPE_LOAD = 1,
+	PERF_HAZ__ITYPE_STORE,
+	PERF_HAZ__ITYPE_BRANCH,
+	PERF_HAZ__ITYPE_FP,
+	PERF_HAZ__ITYPE_FX,
+	PERF_HAZ__ITYPE_CR_OR_SC,
+};
+
+enum perf_inst_cache {
+	PERF_HAZ__ICACHE_L1_HIT = 1,
+	PERF_HAZ__ICACHE_L2_HIT,
+	PERF_HAZ__ICACHE_L3_HIT,
+	PERF_HAZ__ICACHE_L3_MISS,
+};
+
+enum perf_pipeline_stage {
+	PERF_HAZ__PIPE_STAGE_IFU = 1,
+	PERF_HAZ__PIPE_STAGE_IDU,
+	PERF_HAZ__PIPE_STAGE_ISU,
+	PERF_HAZ__PIPE_STAGE_LSU,
+	PERF_HAZ__PIPE_STAGE_BRU,
+	PERF_HAZ__PIPE_STAGE_FXU,
+	PERF_HAZ__PIPE_STAGE_FPU,
+	PERF_HAZ__PIPE_STAGE_VSU,
+	PERF_HAZ__PIPE_STAGE_OTHER,
+};
+
+enum perf_haz_bru_reason {
+	PERF_HAZ__HAZ_BRU_MPRED_DIR = 1,
+	PERF_HAZ__HAZ_BRU_MPRED_TA,
+};
+
+enum perf_haz_isu_reason {
+	PERF_HAZ__HAZ_ISU_SRC = 1,
+	PERF_HAZ__HAZ_ISU_COL = 1,
+};
+
+enum perf_haz_lsu_reason {
+	PERF_HAZ__HAZ_LSU_ERAT_MISS = 1,
+	PERF_HAZ__HAZ_LSU_LMQ,
+	PERF_HAZ__HAZ_LSU_LHS,
+	PERF_HAZ__HAZ_LSU_MPRED,
+	PERF_HAZ__HAZ_DERAT_MISS,
+	PERF_HAZ__HAZ_LSU_LMQ_DERAT_MISS,
+	PERF_HAZ__HAZ_LSU_LHS_DERAT_MISS,
+	PERF_HAZ__HAZ_LSU_MPRED_DERAT_MISS,
+};
+
+enum perf_stall_lsu_reason {
+	PERF_HAZ__STALL_LSU_DCACHE_MISS = 1,
+	PERF_HAZ__STALL_LSU_LD_FIN,
+	PERF_HAZ__STALL_LSU_ST_FWD,
+	PERF_HAZ__STALL_LSU_ST,
+};
+
+enum perf_stall_fxu_reason {
+	PERF_HAZ__STALL_FXU_MC = 1,
+	PERF_HAZ__STALL_FXU_FC,
+};
+
+enum perf_stall_bru_reason {
+	PERF_HAZ__STALL_BRU_FIN_MPRED = 1,
+	PERF_HAZ__STALL_BRU_FC,
+};
+
+enum perf_stall_vsu_reason {
+	PERF_HAZ__STALL_VSU_MC = 1,
+	PERF_HAZ__STALL_VSU_FC,
+};
+
+enum perf_stall_other_reason {
+	PERF_HAZ__STALL_NTC,
+};
+
+#endif /* _UAPI_ASM_POWERPC_PERF_PIPELINE_HAZ_H */
-- 
2.21.1


^ permalink raw reply related

* [RFC 04/11] powerpc/perf: Arch support to expose Hazard data
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	Madhavan Srinivasan, adrian.hunter, acme, alexander.shishkin,
	yao.jin, mingo, paulus, eranian, robert.richter, namhyung,
	kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

From: Madhavan Srinivasan <maddy@linux.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@linux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.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


^ permalink raw reply related

* [RFC 02/11] perf/core: Data structure to present hazard data
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	Madhavan Srinivasan, adrian.hunter, acme, alexander.shishkin,
	yao.jin, mingo, paulus, eranian, robert.richter, namhyung,
	kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

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

Introduce new perf sample_type PERF_SAMPLE_PIPELINE_HAZ to request kernel
to provide cpu pipeline hazard data. Also, introduce arch independent
structure 'perf_pipeline_haz_data' to pass hazard data to userspace. This
is generic structure and arch specific data needs to be converted to this
format.

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 include/linux/perf_event.h            |  7 ++++++
 include/uapi/linux/perf_event.h       | 32 ++++++++++++++++++++++++++-
 kernel/events/core.c                  |  6 +++++
 tools/include/uapi/linux/perf_event.h | 32 ++++++++++++++++++++++++++-
 4 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 547773f5894e..d5b606e3c57d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1001,6 +1001,7 @@ struct perf_sample_data {
 	u64				stack_user_size;
 
 	u64				phys_addr;
+	struct perf_pipeline_haz_data	pipeline_haz;
 } ____cacheline_aligned;
 
 /* default value for data source */
@@ -1021,6 +1022,12 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
 	data->weight = 0;
 	data->data_src.val = PERF_MEM_NA;
 	data->txn = 0;
+	data->pipeline_haz.itype = PERF_HAZ__ITYPE_NA;
+	data->pipeline_haz.icache = PERF_HAZ__ICACHE_NA;
+	data->pipeline_haz.hazard_stage = PERF_HAZ__PIPE_STAGE_NA;
+	data->pipeline_haz.hazard_reason = PERF_HAZ__HREASON_NA;
+	data->pipeline_haz.stall_stage = PERF_HAZ__PIPE_STAGE_NA;
+	data->pipeline_haz.stall_reason = PERF_HAZ__SREASON_NA;
 }
 
 extern void perf_output_sample(struct perf_output_handle *handle,
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 377d794d3105..ff252618ca93 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -142,8 +142,9 @@ enum perf_event_sample_format {
 	PERF_SAMPLE_REGS_INTR			= 1U << 18,
 	PERF_SAMPLE_PHYS_ADDR			= 1U << 19,
 	PERF_SAMPLE_AUX				= 1U << 20,
+	PERF_SAMPLE_PIPELINE_HAZ		= 1U << 21,
 
-	PERF_SAMPLE_MAX = 1U << 21,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 22,		/* non-ABI */
 
 	__PERF_SAMPLE_CALLCHAIN_EARLY		= 1ULL << 63, /* non-ABI; internal use */
 };
@@ -870,6 +871,13 @@ enum perf_event_type {
 	 *	{ u64			phys_addr;} && PERF_SAMPLE_PHYS_ADDR
 	 *	{ u64			size;
 	 *	  char			data[size]; } && PERF_SAMPLE_AUX
+	 *	{ u8			itype;
+	 *	  u8			icache;
+	 *	  u8			hazard_stage;
+	 *	  u8			hazard_reason;
+	 *	  u8			stall_stage;
+	 *	  u8			stall_reason;
+	 *	  u16			pad;} && PERF_SAMPLE_PIPELINE_HAZ
 	 * };
 	 */
 	PERF_RECORD_SAMPLE			= 9,
@@ -1185,4 +1193,26 @@ struct perf_branch_entry {
 		reserved:40;
 };
 
+struct perf_pipeline_haz_data {
+	/* Instruction/Opcode type: Load, Store, Branch .... */
+	__u8	itype;
+	/* Instruction Cache source */
+	__u8	icache;
+	/* Instruction suffered hazard in pipeline stage */
+	__u8	hazard_stage;
+	/* Hazard reason */
+	__u8	hazard_reason;
+	/* Instruction suffered stall in pipeline stage */
+	__u8	stall_stage;
+	/* Stall reason */
+	__u8	stall_reason;
+	__u16	pad;
+};
+
+#define PERF_HAZ__ITYPE_NA	0x0
+#define PERF_HAZ__ICACHE_NA	0x0
+#define PERF_HAZ__PIPE_STAGE_NA	0x0
+#define PERF_HAZ__HREASON_NA	0x0
+#define PERF_HAZ__SREASON_NA	0x0
+
 #endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index e453589da97c..d00037c77ccf 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1754,6 +1754,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
 	if (sample_type & PERF_SAMPLE_PHYS_ADDR)
 		size += sizeof(data->phys_addr);
 
+	if (sample_type & PERF_SAMPLE_PIPELINE_HAZ)
+		size += sizeof(data->pipeline_haz);
+
 	event->header_size = size;
 }
 
@@ -6712,6 +6715,9 @@ void perf_output_sample(struct perf_output_handle *handle,
 			perf_aux_sample_output(event, handle, data);
 	}
 
+	if (sample_type & PERF_SAMPLE_PIPELINE_HAZ)
+		perf_output_put(handle, data->pipeline_haz);
+
 	if (!event->attr.watermark) {
 		int wakeup_events = event->attr.wakeup_events;
 
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 377d794d3105..ff252618ca93 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -142,8 +142,9 @@ enum perf_event_sample_format {
 	PERF_SAMPLE_REGS_INTR			= 1U << 18,
 	PERF_SAMPLE_PHYS_ADDR			= 1U << 19,
 	PERF_SAMPLE_AUX				= 1U << 20,
+	PERF_SAMPLE_PIPELINE_HAZ		= 1U << 21,
 
-	PERF_SAMPLE_MAX = 1U << 21,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 22,		/* non-ABI */
 
 	__PERF_SAMPLE_CALLCHAIN_EARLY		= 1ULL << 63, /* non-ABI; internal use */
 };
@@ -870,6 +871,13 @@ enum perf_event_type {
 	 *	{ u64			phys_addr;} && PERF_SAMPLE_PHYS_ADDR
 	 *	{ u64			size;
 	 *	  char			data[size]; } && PERF_SAMPLE_AUX
+	 *	{ u8			itype;
+	 *	  u8			icache;
+	 *	  u8			hazard_stage;
+	 *	  u8			hazard_reason;
+	 *	  u8			stall_stage;
+	 *	  u8			stall_reason;
+	 *	  u16			pad;} && PERF_SAMPLE_PIPELINE_HAZ
 	 * };
 	 */
 	PERF_RECORD_SAMPLE			= 9,
@@ -1185,4 +1193,26 @@ struct perf_branch_entry {
 		reserved:40;
 };
 
+struct perf_pipeline_haz_data {
+	/* Instruction/Opcode type: Load, Store, Branch .... */
+	__u8	itype;
+	/* Instruction Cache source */
+	__u8	icache;
+	/* Instruction suffered hazard in pipeline stage */
+	__u8	hazard_stage;
+	/* Hazard reason */
+	__u8	hazard_reason;
+	/* Instruction suffered stall in pipeline stage */
+	__u8	stall_stage;
+	/* Stall reason */
+	__u8	stall_reason;
+	__u16	pad;
+};
+
+#define PERF_HAZ__ITYPE_NA	0x0
+#define PERF_HAZ__ICACHE_NA	0x0
+#define PERF_HAZ__PIPE_STAGE_NA	0x0
+#define PERF_HAZ__HREASON_NA	0x0
+#define PERF_HAZ__SREASON_NA	0x0
+
 #endif /* _UAPI_LINUX_PERF_EVENT_H */
-- 
2.21.1


^ permalink raw reply related

* [RFC 01/11] powerpc/perf: Simplify ISA207_SIER macros
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	adrian.hunter, acme, alexander.shishkin, yao.jin, mingo, paulus,
	eranian, robert.richter, namhyung, kim.phillips, jolsa, kan.liang
In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com>

Instead of having separate macros for MASK and SHIFT, and using
them to derive the bits, let's have simple macro to do the job.
Also, remove ISA207_ prefix because some of the SIER bits which
are extracted with these macros are not defined in ISA, example
DATA_SRC bits.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 arch/powerpc/perf/isa207-common.c |  8 ++++----
 arch/powerpc/perf/isa207-common.h | 11 +++--------
 2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c
index 4c86da5eb28a..07026bbd292b 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -215,10 +215,10 @@ void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
 	}
 
 	sier = mfspr(SPRN_SIER);
-	val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+	val = SIER_TYPE(sier);
 	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;
+		idx = SIER_LDST(sier);
+		sub_idx = SIER_DATA_SRC(sier);
 
 		dsrc->val = isa207_find_source(idx, sub_idx);
 		dsrc->val |= (val == 1) ? P(OP, LOAD) : P(OP, STORE);
@@ -231,7 +231,7 @@ void isa207_get_mem_weight(u64 *weight)
 	u64 exp = MMCRA_THR_CTR_EXP(mmcra);
 	u64 mantissa = MMCRA_THR_CTR_MANT(mmcra);
 	u64 sier = mfspr(SPRN_SIER);
-	u64 val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+	u64 val = SIER_TYPE(sier);
 
 	if (val == 0 || val == 7)
 		*weight = 0;
diff --git a/arch/powerpc/perf/isa207-common.h b/arch/powerpc/perf/isa207-common.h
index 63fd4f3f6013..7027eb9f3e40 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -202,14 +202,9 @@
 #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 SIER_DATA_SRC(sier)		(((sier) >> (63 - 10)) & 0x7ull)
+#define SIER_TYPE(sier)			(((sier) >> (63 - 48)) & 0x7ull)
+#define SIER_LDST(sier)			(((sier) >> (63 - 62)) & 0x7ull)
 
 #define P(a, b)				PERF_MEM_S(a, b)
 #define PH(a, b)			(P(LVL, HIT) | P(a, b))
-- 
2.21.1


^ permalink raw reply related

* [RFC 00/11] perf: Enhancing perf to export processor hazard information
From: Ravi Bangoria @ 2020-03-02  5:23 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: mark.rutland, ravi.bangoria, ak, maddy, peterz, alexey.budankov,
	adrian.hunter, acme, alexander.shishkin, yao.jin, mingo, paulus,
	eranian, robert.richter, namhyung, kim.phillips, jolsa, kan.liang

Most modern microprocessors employ complex instruction execution
pipelines such that many instructions can be 'in flight' at any
given point in time. Various factors affect this pipeline and
hazards are the primary among them. Different types of hazards
exist - Data hazards, Structural hazards and Control hazards.
Data hazard is the case where data dependencies exist between
instructions in different stages in the pipeline. Structural
hazard is when the same processor hardware is needed by more
than one instruction in flight at the same time. Control hazards
are more the branch misprediction kinds. 

Information about these hazards are critical towards analyzing
performance issues and also to tune software to overcome such
issues. Modern processors export such hazard data in Performance
Monitoring Unit (PMU) registers. Ex, 'Sampled Instruction Event
Register' on IBM PowerPC[1][2] and 'Instruction-Based Sampling' on
AMD[3] provides similar information.

Implementation detail:

A new sample_type called PERF_SAMPLE_PIPELINE_HAZ is introduced.
If it's set, kernel converts arch specific hazard information
into generic format:

  struct perf_pipeline_haz_data {
         /* Instruction/Opcode type: Load, Store, Branch .... */
         __u8    itype;
         /* Instruction Cache source */
         __u8    icache;
         /* Instruction suffered hazard in pipeline stage */
         __u8    hazard_stage;
         /* Hazard reason */
         __u8    hazard_reason;
         /* Instruction suffered stall in pipeline stage */
         __u8    stall_stage;
         /* Stall reason */
         __u8    stall_reason;
         __u16   pad;
  };

... which can be read by user from mmap() ring buffer. With this
approach, sample perf report in hazard mode looks like (On IBM
PowerPC):

  # ./perf record --hazard ./ebizzy
  # ./perf report --hazard
  Overhead  Symbol          Shared  Instruction Type  Hazard Stage   Hazard Reason         Stall Stage   Stall Reason  ICache access
    36.58%  [.] thread_run  ebizzy  Load              LSU            Mispredict            LSU           Load fin      L1 hit
     9.46%  [.] thread_run  ebizzy  Load              LSU            Mispredict            LSU           Dcache_miss   L1 hit
     1.76%  [.] thread_run  ebizzy  Fixed point       -              -                     -             -             L1 hit
     1.31%  [.] thread_run  ebizzy  Load              LSU            ERAT Miss             LSU           Load fin      L1 hit
     1.27%  [.] thread_run  ebizzy  Load              LSU            Mispredict            -             -             L1 hit
     1.16%  [.] thread_run  ebizzy  Fixed point       -              -                     FXU           Fixed cycle   L1 hit
     0.50%  [.] thread_run  ebizzy  Fixed point       ISU            Source Unavailable    FXU           Fixed cycle   L1 hit
     0.30%  [.] thread_run  ebizzy  Load              LSU            LMQ Full, DERAT Miss  LSU           Load fin      L1 hit
     0.24%  [.] thread_run  ebizzy  Load              LSU            ERAT Miss             -             -             L1 hit
     0.08%  [.] thread_run  ebizzy  -                 -              -                     BRU           Fixed cycle   L1 hit
     0.05%  [.] thread_run  ebizzy  Branch            -              -                     BRU           Fixed cycle   L1 hit
     0.04%  [.] thread_run  ebizzy  Fixed point       ISU            Source Unavailable    -             -             L1 hit

Also perf annotate with hazard data:

         │    Disassembly of section .text:
         │
         │    0000000010001cf8 <compare>:
         │    compare():
         │    return NULL;
         │    }
         │
         │    static int
         │    compare(const void *p1, const void *p2)
         │    {
   33.23 │      std    r31,-8(r1)
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}
         │       {haz_stage: LSU, haz_reason: Load Hit Store, stall_stage: LSU, stall_reason: -, icache: L3 hit}
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: -, stall_reason: -, icache: L1 hit}
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}
    0.84 │      stdu   r1,-64(r1)
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: -, stall_reason: -, icache: L1 hit}
    0.24 │      mr     r31,r1
         │       {haz_stage: -, haz_reason: -, stall_stage: -, stall_reason: -, icache: L1 hit}
   21.18 │      std    r3,32(r31)
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}
         │       {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit}


Patches:
 - Patch #1 is a simple cleanup patch
 - Patch #2, #3, #4 implements generic and arch specific kernel
   infrastructure
 - Patch #5 enables perf record and script with hazard mode
 - Patch #6, #7, #8 enables perf report with hazard mode
 - Patch #9, #10, #11 enables perf annotate with hazard mode

Note:
 - This series is based on the talk by Madhavan in LPC 2018[4]. This is
   just an early RFC to get comments about the approach and not intended
   to be merged yet.
 - I've prepared the series base on v5.6-rc3. But it depends on generic
   perf annotate fixes [5][6] which are already merged by Arnaldo in
   perf/urgent and perf/core.

[1]: Book III, Section 9.4.10:
     https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0 
[2]: https://wiki.raptorcs.com/w/images/6/6b/POWER9_PMU_UG_v12_28NOV2018_pub.pdf#G9.1106986
[3]: https://www.amd.com/system/files/TechDocs/24593.pdf#G19.1089550
[4]: https://linuxplumbersconf.org/event/2/contributions/76/
[5]: http://lore.kernel.org/r/20200204045233.474937-1-ravi.bangoria@linux.ibm.com
[6]: http://lore.kernel.org/r/20200213064306.160480-1-ravi.bangoria@linux.ibm.com


Madhavan Srinivasan (7):
  perf/core: Data structure to present hazard data
  powerpc/perf: Arch specific definitions for pipeline
  powerpc/perf: Arch support to expose Hazard data
  perf tools: Enable record and script to record and show hazard data
  perf hists: Make a room for hazard info in struct hist_entry
  perf hazard: Functions to convert generic hazard data to arch specific
    string
  perf report: Enable hazard mode

Ravi Bangoria (4):
  powerpc/perf: Simplify ISA207_SIER macros
  perf annotate: Introduce type for annotation_line
  perf annotate: Preparation for hazard
  perf annotate: Show hazard data in tui mode

 arch/powerpc/include/asm/perf_event_server.h  |   2 +
 .../include/uapi/asm/perf_pipeline_haz.h      |  80 ++++++
 arch/powerpc/perf/core-book3s.c               |   4 +
 arch/powerpc/perf/isa207-common.c             | 165 ++++++++++++-
 arch/powerpc/perf/isa207-common.h             |  23 +-
 arch/powerpc/perf/power8-pmu.c                |   1 +
 arch/powerpc/perf/power9-pmu.c                |   1 +
 include/linux/perf_event.h                    |   7 +
 include/uapi/linux/perf_event.h               |  32 ++-
 kernel/events/core.c                          |   6 +
 tools/include/uapi/linux/perf_event.h         |  32 ++-
 tools/perf/Documentation/perf-record.txt      |   3 +
 tools/perf/builtin-annotate.c                 |   7 +-
 tools/perf/builtin-c2c.c                      |   4 +-
 tools/perf/builtin-diff.c                     |   6 +-
 tools/perf/builtin-record.c                   |   1 +
 tools/perf/builtin-report.c                   |  29 +++
 tools/perf/tests/hists_link.c                 |   4 +-
 tools/perf/ui/browsers/annotate.c             | 128 ++++++++--
 tools/perf/ui/gtk/annotate.c                  |   6 +-
 tools/perf/util/Build                         |   2 +
 tools/perf/util/annotate.c                    | 153 +++++++++++-
 tools/perf/util/annotate.h                    |  38 ++-
 tools/perf/util/event.h                       |   1 +
 tools/perf/util/evsel.c                       |  10 +
 tools/perf/util/hazard.c                      |  51 ++++
 tools/perf/util/hazard.h                      |  14 ++
 tools/perf/util/hazard/Build                  |   1 +
 .../util/hazard/powerpc/perf_pipeline_haz.h   |  80 ++++++
 .../perf/util/hazard/powerpc/powerpc_hazard.c | 142 +++++++++++
 .../perf/util/hazard/powerpc/powerpc_hazard.h |  14 ++
 tools/perf/util/hist.c                        | 112 ++++++++-
 tools/perf/util/hist.h                        |  13 +
 tools/perf/util/machine.c                     |   6 +
 tools/perf/util/machine.h                     |   3 +
 tools/perf/util/perf_event_attr_fprintf.c     |   1 +
 tools/perf/util/record.h                      |   1 +
 tools/perf/util/session.c                     |  16 ++
 tools/perf/util/sort.c                        | 230 ++++++++++++++++++
 tools/perf/util/sort.h                        |  23 ++
 40 files changed, 1387 insertions(+), 65 deletions(-)
 create mode 100644 arch/powerpc/include/uapi/asm/perf_pipeline_haz.h
 create mode 100644 tools/perf/util/hazard.c
 create mode 100644 tools/perf/util/hazard.h
 create mode 100644 tools/perf/util/hazard/Build
 create mode 100644 tools/perf/util/hazard/powerpc/perf_pipeline_haz.h
 create mode 100644 tools/perf/util/hazard/powerpc/powerpc_hazard.c
 create mode 100644 tools/perf/util/hazard/powerpc/powerpc_hazard.h

-- 
2.21.1


^ permalink raw reply

* [RFC PATCH] powerpc/64s: CONFIG_PPC_HASH_MMU
From: Nicholas Piggin @ 2020-03-02  4:49 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin

This allows the 64s hash MMU code to be compiled out if radix is
selected. This saves about 128kB kernel image size (90kB text) on
powernv_defconfig minus KVM, 40kB on a tiny config.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/Kconfig                          |  1 +
 arch/powerpc/include/asm/book3s/64/mmu.h      | 20 ++++++++++++++++-
 arch/powerpc/include/asm/book3s/64/pgtable.h  |  6 +++++
 .../include/asm/book3s/64/tlbflush-hash.h     | 10 +++++++--
 arch/powerpc/include/asm/book3s/64/tlbflush.h |  4 ----
 arch/powerpc/include/asm/book3s/pgtable.h     |  4 ++++
 arch/powerpc/include/asm/mmu.h                | 14 ++++++++++--
 arch/powerpc/include/asm/mmu_context.h        |  2 ++
 arch/powerpc/include/asm/paca.h               |  9 ++++++++
 arch/powerpc/include/asm/sparsemem.h          |  2 +-
 arch/powerpc/kernel/asm-offsets.c             |  4 ++++
 arch/powerpc/kernel/dt_cpu_ftrs.c             | 10 ++++++++-
 arch/powerpc/kernel/entry_64.S                |  4 ++--
 arch/powerpc/kernel/exceptions-64s.S          | 22 ++++++++++++++++---
 arch/powerpc/kernel/mce.c                     |  2 +-
 arch/powerpc/kernel/mce_power.c               | 10 ++++++---
 arch/powerpc/kernel/paca.c                    | 18 ++++++---------
 arch/powerpc/kernel/process.c                 | 13 ++++++-----
 arch/powerpc/kernel/prom.c                    |  2 ++
 arch/powerpc/kernel/setup_64.c                |  4 ++++
 arch/powerpc/kexec/core_64.c                  |  4 ++--
 arch/powerpc/kvm/Kconfig                      |  1 +
 arch/powerpc/mm/book3s64/Makefile             | 17 ++++++++------
 arch/powerpc/mm/book3s64/hash_pgtable.c       |  1 -
 arch/powerpc/mm/book3s64/hash_utils.c         |  9 --------
 .../{hash_hugetlbpage.c => hugetlbpage.c}     |  2 ++
 arch/powerpc/mm/book3s64/mmu_context.c        | 18 +++++++++++++--
 arch/powerpc/mm/book3s64/pgtable.c            | 22 +++++++++++++++++--
 arch/powerpc/mm/book3s64/radix_pgtable.c      |  5 +++++
 arch/powerpc/mm/book3s64/slb.c                | 14 ------------
 arch/powerpc/mm/copro_fault.c                 |  2 ++
 arch/powerpc/mm/fault.c                       | 20 +++++++++++++++++
 arch/powerpc/platforms/Kconfig.cputype        | 20 ++++++++++++++++-
 arch/powerpc/platforms/powernv/idle.c         |  2 ++
 arch/powerpc/platforms/powernv/setup.c        |  2 ++
 arch/powerpc/xmon/xmon.c                      |  8 +++++--
 36 files changed, 231 insertions(+), 77 deletions(-)
 rename arch/powerpc/mm/book3s64/{hash_hugetlbpage.c => hugetlbpage.c} (99%)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 497b7d0b2d7e..50c361b8b7fd 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -963,6 +963,7 @@ config PPC_MEM_KEYS
 	prompt "PowerPC Memory Protection Keys"
 	def_bool y
 	depends on PPC_BOOK3S_64
+	depends on PPC_HASH_MMU
 	select ARCH_USES_HIGH_VMA_FLAGS
 	select ARCH_HAS_PKEYS
 	help
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index bb3deb76c951..fca69dd23e25 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -107,7 +107,9 @@ typedef struct {
 		 * from EA and new context ids to build the new VAs.
 		 */
 		mm_context_id_t id;
+#ifdef CONFIG_PPC_HASH_MMU
 		mm_context_id_t extended_id[TASK_SIZE_USER64/TASK_CONTEXT_SIZE];
+#endif
 	};
 
 	/* Number of bits in the mm_cpumask */
@@ -116,7 +118,9 @@ typedef struct {
 	/* Number of users of the external (Nest) MMU */
 	atomic_t copros;
 
+#ifdef CONFIG_PPC_HASH_MMU
 	struct hash_mm_context *hash_context;
+#endif
 
 	unsigned long vdso_base;
 	/*
@@ -139,6 +143,7 @@ typedef struct {
 #endif
 } mm_context_t;
 
+#ifdef CONFIG_PPC_HASH_MMU
 static inline u16 mm_ctx_user_psize(mm_context_t *ctx)
 {
 	return ctx->hash_context->user_psize;
@@ -193,11 +198,22 @@ static inline struct subpage_prot_table *mm_ctx_subpage_prot(mm_context_t *ctx)
 }
 #endif
 
+#endif
+
 /*
  * The current system page and segment sizes
  */
-extern int mmu_linear_psize;
+#if defined(CONFIG_PPC_RADIX_MMU) && !defined(CONFIG_PPC_HASH_MMU)
+#ifdef CONFIG_PPC_64K_PAGES
+#define mmu_virtual_psize MMU_PAGE_64K
+#else
+#define mmu_virtual_psize MMU_PAGE_4K
+#endif
+#else
 extern int mmu_virtual_psize;
+#endif
+
+extern int mmu_linear_psize;
 extern int mmu_vmalloc_psize;
 extern int mmu_vmemmap_psize;
 extern int mmu_io_psize;
@@ -243,6 +259,7 @@ extern void radix_init_pseries(void);
 static inline void radix_init_pseries(void) { };
 #endif
 
+#ifdef CONFIG_PPC_HASH_MMU
 static inline int get_user_context(mm_context_t *ctx, unsigned long ea)
 {
 	int index = ea >> MAX_EA_BITS_PER_CONTEXT;
@@ -262,6 +279,7 @@ static inline unsigned long get_user_vsid(mm_context_t *ctx,
 
 	return get_vsid(context, ea, ssize);
 }
+#endif
 
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index 201a69e6a355..0d0b5dcadd16 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -1139,8 +1139,14 @@ extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot);
 extern pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot);
 extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 		       pmd_t *pmdp, pmd_t pmd);
+#ifdef CONFIG_PPC_HASH_MMU
 extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
 				 pmd_t *pmd);
+#else
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd)
+{
+}
+#endif
 extern int hash__has_transparent_hugepage(void);
 static inline int has_transparent_hugepage(void)
 {
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
index 64d02a704bcb..bb8a22ee9668 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
@@ -112,9 +112,15 @@ static inline void hash__flush_tlb_kernel_range(unsigned long start,
 
 struct mmu_gather;
 extern void hash__tlb_flush(struct mmu_gather *tlb);
+extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd,
+				unsigned long addr);
+
+#ifdef CONFIG_PPC_HASH_MMU
 /* Private function for use by PCI IO mapping code */
 extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
 				     unsigned long end);
-extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd,
-				unsigned long addr);
+#else
+static inline void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+				     unsigned long end) { }
+#endif
 #endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H */
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h
index dcb5c3839d2f..d2e80f178b6d 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h
@@ -14,7 +14,6 @@ enum {
 	TLB_INVAL_SCOPE_LPID = 1,	/* invalidate TLBs for current LPID */
 };
 
-#ifdef CONFIG_PPC_NATIVE
 static inline void tlbiel_all(void)
 {
 	/*
@@ -30,9 +29,6 @@ static inline void tlbiel_all(void)
 	else
 		hash__tlbiel_all(TLB_INVAL_SCOPE_GLOBAL);
 }
-#else
-static inline void tlbiel_all(void) { BUG(); };
-#endif
 
 static inline void tlbiel_all_lpid(bool radix)
 {
diff --git a/arch/powerpc/include/asm/book3s/pgtable.h b/arch/powerpc/include/asm/book3s/pgtable.h
index 0e1263455d73..cb85da522d0c 100644
--- a/arch/powerpc/include/asm/book3s/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/pgtable.h
@@ -26,6 +26,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 				     unsigned long size, pgprot_t vma_prot);
 #define __HAVE_PHYS_MEM_ACCESS_PROT
 
+#ifdef CONFIG_PPC_HASH_MMU
 /*
  * This gets called at the end of handling a page fault, when
  * the kernel has put a new PTE into the page table for the process.
@@ -36,6 +37,9 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
  * waiting for the inevitable extra hash-table miss exception.
  */
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep);
+#else
+static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) {}
+#endif
 
 #endif /* __ASSEMBLY__ */
 #endif
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 0699cfeeb8c9..9ff4b99cd0d3 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -269,7 +269,7 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 }
 #endif /* !CONFIG_DEBUG_VM */
 
-#ifdef CONFIG_PPC_RADIX_MMU
+#if defined(CONFIG_PPC_RADIX_MMU) && defined(CONFIG_PPC_HASH_MMU)
 static inline bool radix_enabled(void)
 {
 	return mmu_has_feature(MMU_FTR_TYPE_RADIX);
@@ -279,7 +279,7 @@ static inline bool early_radix_enabled(void)
 {
 	return early_mmu_has_feature(MMU_FTR_TYPE_RADIX);
 }
-#else
+#elif defined(CONFIG_PPC_HASH_MMU)
 static inline bool radix_enabled(void)
 {
 	return false;
@@ -289,6 +289,16 @@ static inline bool early_radix_enabled(void)
 {
 	return false;
 }
+#else
+static inline bool radix_enabled(void)
+{
+	return true;
+}
+
+static inline bool early_radix_enabled(void)
+{
+	return true;
+}
 #endif
 
 #ifdef CONFIG_PPC_MEM_KEYS
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index 360367c579de..6a0fafbef119 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -74,6 +74,7 @@ extern void hash__reserve_context_id(int id);
 extern void __destroy_context(int context_id);
 static inline void mmu_context_init(void) { }
 
+#ifdef CONFIG_PPC_HASH_MMU
 static inline int alloc_extended_context(struct mm_struct *mm,
 					 unsigned long ea)
 {
@@ -99,6 +100,7 @@ static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea)
 		return true;
 	return false;
 }
+#endif
 
 #else
 extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index e3cc9eb9204d..6b365cffaee9 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -95,7 +95,9 @@ struct paca_struct {
 					/* this becomes non-zero. */
 	u8 kexec_state;		/* set when kexec down has irqs off */
 #ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	struct slb_shadow *slb_shadow_ptr;
+#endif
 	struct dtl_entry *dispatch_log;
 	struct dtl_entry *dispatch_log_end;
 #endif
@@ -109,6 +111,8 @@ struct paca_struct {
 	u64 exgen[EX_SIZE] __attribute__((aligned(0x80)));
 	u64 exslb[EX_SIZE];	/* used for SLB/segment table misses
  				 * on the linear mapping */
+
+#ifdef CONFIG_PPC_HASH_MMU
 	/* SLB related definitions */
 	u16 vmalloc_sllp;
 	u8 slb_cache_ptr;
@@ -119,6 +123,7 @@ struct paca_struct {
 	u32 slb_used_bitmap;		/* Bitmaps for first 32 SLB entries. */
 	u32 slb_kern_bitmap;
 	u32 slb_cache[SLB_CACHE_ENTRIES];
+#endif
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
 #ifdef CONFIG_PPC_BOOK3E
@@ -149,6 +154,7 @@ struct paca_struct {
 
 #ifdef CONFIG_PPC_BOOK3S
 	mm_context_id_t mm_ctx_id;
+#ifdef CONFIG_PPC_HASH_MMU
 #ifdef CONFIG_PPC_MM_SLICES
 	unsigned char mm_ctx_low_slices_psize[BITS_PER_LONG / BITS_PER_BYTE];
 	unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE];
@@ -157,6 +163,7 @@ struct paca_struct {
 	u16 mm_ctx_user_psize;
 	u16 mm_ctx_sllp;
 #endif
+#endif
 #endif
 
 	/*
@@ -260,9 +267,11 @@ struct paca_struct {
 #endif /* CONFIG_PPC_PSERIES */
 
 #ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	/* Capture SLB related old contents in MCE handler. */
 	struct slb_entry *mce_faulty_slbs;
 	u16 slb_save_cache_ptr;
+#endif
 #endif /* CONFIG_PPC_BOOK3S_64 */
 #ifdef CONFIG_STACKPROTECTOR
 	unsigned long canary;
diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h
index 3192d454a733..958fed1f052e 100644
--- a/arch/powerpc/include/asm/sparsemem.h
+++ b/arch/powerpc/include/asm/sparsemem.h
@@ -16,7 +16,7 @@
 extern int create_section_mapping(unsigned long start, unsigned long end, int nid);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 extern int resize_hpt_for_hotplug(unsigned long new_mem_size);
 #else
 static inline int resize_hpt_for_hotplug(unsigned long new_mem_size) { return 0; }
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index fcf24a365fc0..c4a8a070eab0 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -238,6 +238,7 @@ int main(void)
 #endif /* CONFIG_PPC_BOOK3E */
 
 #ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	OFFSET(PACASLBCACHE, paca_struct, slb_cache);
 	OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr);
 	OFFSET(PACASTABRR, paca_struct, stab_rr);
@@ -246,6 +247,7 @@ int main(void)
 	OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp);
 #else
 	OFFSET(PACACONTEXTSLLP, paca_struct, mm_ctx_sllp);
+#endif
 #endif /* CONFIG_PPC_MM_SLICES */
 	OFFSET(PACA_EXGEN, paca_struct, exgen);
 	OFFSET(PACA_EXMC, paca_struct, exmc);
@@ -254,10 +256,12 @@ int main(void)
 #ifdef CONFIG_PPC_PSERIES
 	OFFSET(PACALPPACAPTR, paca_struct, lppaca_ptr);
 #endif
+#ifdef CONFIG_PPC_HASH_MMU
 	OFFSET(PACA_SLBSHADOWPTR, paca_struct, slb_shadow_ptr);
 	OFFSET(SLBSHADOW_STACKVSID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid);
 	OFFSET(SLBSHADOW_STACKESID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid);
 	OFFSET(SLBSHADOW_SAVEAREA, slb_shadow, save_area);
+#endif
 	OFFSET(LPPACA_PMCINUSE, lppaca, pmcregs_in_use);
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 	OFFSET(PACA_PMCINUSE, paca_struct, pmcregs_in_use);
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 182b4047c1ef..36385eb87d36 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -298,6 +298,7 @@ static int __init feat_enable_idle_stop(struct dt_cpu_feature *f)
 
 static int __init feat_enable_mmu_hash(struct dt_cpu_feature *f)
 {
+#ifdef CONFIG_PPC_HASH_MMU
 	u64 lpcr;
 
 	lpcr = mfspr(SPRN_LPCR);
@@ -313,10 +314,13 @@ static int __init feat_enable_mmu_hash(struct dt_cpu_feature *f)
 	cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
 
 	return 1;
+#endif
+	return 0;
 }
 
 static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f)
 {
+#ifdef CONFIG_PPC_HASH_MMU
 	u64 lpcr;
 
 	system_registers.lpcr_clear |= (LPCR_ISL | LPCR_UPRT | LPCR_HR);
@@ -328,14 +332,18 @@ static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f)
 	cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
 
 	return 1;
+#endif
+	return 0;
 }
 
 
 static int __init feat_enable_mmu_radix(struct dt_cpu_feature *f)
 {
+#ifdef CONFIG_PPC_HASH_MMU
+	cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;
+#endif
 #ifdef CONFIG_PPC_RADIX_MMU
 	cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX;
-	cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;
 	cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
 
 	return 1;
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 6ba675b0cf7d..5f40fe4ec6ba 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -646,7 +646,7 @@ _GLOBAL(_switch)
 #endif
 
 	ld	r8,KSP(r4)	/* new stack pointer */
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 BEGIN_MMU_FTR_SECTION
 	b	2f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
@@ -698,7 +698,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	slbmte	r7,r0
 	isync
 2:
-#endif /* CONFIG_PPC_BOOK3S_64 */
+#endif /* CONFIG_PPC_HASH_MMU */
 
 	clrrdi	r7, r8, THREAD_SHIFT	/* base of new stack */
 	/* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index ffc15f4f079d..b94874c2f7ab 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1161,6 +1161,7 @@ EXC_COMMON_BEGIN(data_access_common)
 	INT_COMMON 0x300, PACA_EXGEN, 1, 1, 1, 1, 1
 	ld	r4,_DAR(r1)
 	ld	r5,_DSISR(r1)
+#ifdef CONFIG_PPC_HASH_MMU
 BEGIN_MMU_FTR_SECTION
 	ld	r6,_MSR(r1)
 	li	r3,0x300
@@ -1168,6 +1169,9 @@ BEGIN_MMU_FTR_SECTION
 MMU_FTR_SECTION_ELSE
 	b	handle_page_fault
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
+#else
+	b	handle_page_fault
+#endif
 
 
 EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
@@ -1181,6 +1185,7 @@ EXC_COMMON_BEGIN(data_access_slb_common)
 	INT_COMMON 0x380, PACA_EXSLB, 1, 1, 0, 1, 0
 	ld	r4,_DAR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_PPC_HASH_MMU
 BEGIN_MMU_FTR_SECTION
 	/* HPT case, do SLB fault */
 	bl	do_slb_fault
@@ -1192,6 +1197,9 @@ MMU_FTR_SECTION_ELSE
 	/* Radix case, access is outside page table range */
 	li	r3,-EFAULT
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
+#else
+	li	r3,-EFAULT
+#endif
 	std	r3,RESULT(r1)
 	bl	save_nvgprs
 	RECONCILE_IRQ_STATE(r10, r11)
@@ -1213,6 +1221,7 @@ EXC_COMMON_BEGIN(instruction_access_common)
 	INT_COMMON 0x400, PACA_EXGEN, 1, 1, 1, 2, 2
 	ld	r4,_DAR(r1)
 	ld	r5,_DSISR(r1)
+#ifdef CONFIG_PPC_HASH_MMU
 BEGIN_MMU_FTR_SECTION
 	ld      r6,_MSR(r1)
 	li	r3,0x400
@@ -1220,6 +1229,9 @@ BEGIN_MMU_FTR_SECTION
 MMU_FTR_SECTION_ELSE
 	b	handle_page_fault
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
+#else
+	b	handle_page_fault
+#endif
 
 
 EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
@@ -1233,6 +1245,7 @@ EXC_COMMON_BEGIN(instruction_access_slb_common)
 	INT_COMMON 0x480, PACA_EXSLB, 1, 1, 0, 2, 0
 	ld	r4,_DAR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_PPC_HASH_MMU
 BEGIN_MMU_FTR_SECTION
 	/* HPT case, do SLB fault */
 	bl	do_slb_fault
@@ -1244,6 +1257,9 @@ MMU_FTR_SECTION_ELSE
 	/* Radix case, access is outside page table range */
 	li	r3,-EFAULT
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
+#else
+	li	r3,-EFAULT
+#endif
 	std	r3,RESULT(r1)
 	bl	save_nvgprs
 	RECONCILE_IRQ_STATE(r10, r11)
@@ -2252,8 +2268,8 @@ disable_machine_check:
  * Hash table stuff
  */
 	.balign	IFETCH_ALIGN_BYTES
+#ifdef CONFIG_PPC_HASH_MMU
 do_hash_page:
-#ifdef CONFIG_PPC_BOOK3S_64
 	lis	r0,(DSISR_BAD_FAULT_64S | DSISR_DABRMATCH | DSISR_KEYFAULT)@h
 	ori	r0,r0,DSISR_BAD_FAULT_64S@l
 	and.	r0,r5,r0		/* weird error? */
@@ -2283,7 +2299,7 @@ do_hash_page:
 	/* Reload DAR/DSISR into r4/r5 for the DABR check below */
 	ld	r4,_DAR(r1)
 	ld      r5,_DSISR(r1)
-#endif /* CONFIG_PPC_BOOK3S_64 */
+#endif /* CONFIG_PPC_HASH_MMU */
 
 /* Here we have a page fault that hash_page can't handle. */
 handle_page_fault:
@@ -2315,7 +2331,7 @@ handle_dabr_fault:
 	b       ret_from_except
 
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 /* We have a page fault that hash_page could handle but HV refused
  * the PTE insertion
  */
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index 34c1001e9e8b..c8ff446acec0 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -544,7 +544,7 @@ void machine_check_print_event_info(struct machine_check_event *evt,
 		mc_error_class[evt->error_class] : "Unknown";
 	printk("%sMCE: CPU%d: %s\n", level, evt->cpu, subtype);
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	/* Display faulty slb contents for SLB errors. */
 	if (evt->error_type == MCE_ERROR_TYPE_SLB)
 		slb_dump_contents(local_paca->mce_faulty_slbs);
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 1cbf7f1a4e3d..fd03ac9d7f7b 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -58,7 +58,7 @@ unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
 }
 
 /* flush SLBs and reload */
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 void flush_and_reload_slb(void)
 {
 	/* Invalidate all SLBs */
@@ -88,7 +88,7 @@ void flush_and_reload_slb(void)
 
 static void flush_erat(void)
 {
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
 		flush_and_reload_slb();
 		return;
@@ -103,7 +103,7 @@ static void flush_erat(void)
 
 static int mce_flush(int what)
 {
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	if (what == MCE_FLUSH_SLB) {
 		flush_and_reload_slb();
 		return 1;
@@ -409,8 +409,10 @@ static int mce_handle_ierror(struct pt_regs *regs,
 		/* attempt to correct the error */
 		switch (table[i].error_type) {
 		case MCE_ERROR_TYPE_SLB:
+#ifdef CONFIG_PPC_HASH_MMU
 			if (local_paca->in_mce == 1)
 				slb_save_contents(local_paca->mce_faulty_slbs);
+#endif
 			handled = mce_flush(MCE_FLUSH_SLB);
 			break;
 		case MCE_ERROR_TYPE_ERAT:
@@ -496,8 +498,10 @@ static int mce_handle_derror(struct pt_regs *regs,
 		/* attempt to correct the error */
 		switch (table[i].error_type) {
 		case MCE_ERROR_TYPE_SLB:
+#ifdef CONFIG_PPC_HASH_MMU
 			if (local_paca->in_mce == 1)
 				slb_save_contents(local_paca->mce_faulty_slbs);
+#endif
 			if (mce_flush(MCE_FLUSH_SLB))
 				handled = 1;
 			break;
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 949eceb254d8..415bdd687900 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -131,8 +131,7 @@ static struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
 }
 #endif /* CONFIG_PPC_PSERIES */
 
-#ifdef CONFIG_PPC_BOOK3S_64
-
+#ifdef CONFIG_PPC_HASH_MMU
 /*
  * 3 persistent SLBs are allocated here.  The buffer will be zero
  * initially, hence will all be invaild until we actually write them.
@@ -161,8 +160,7 @@ static struct slb_shadow * __init new_slb_shadow(int cpu, unsigned long limit)
 
 	return s;
 }
-
-#endif /* CONFIG_PPC_BOOK3S_64 */
+#endif /* CONFIG_PPC_HASH_MMU */
 
 /* The Paca is an array with one entry per processor.  Each contains an
  * lppaca, which contains the information shared between the
@@ -194,7 +192,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 	new_paca->kexec_state = KEXEC_STATE_NONE;
 	new_paca->__current = &init_task;
 	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	new_paca->slb_shadow_ptr = NULL;
 #endif
 
@@ -267,7 +265,7 @@ void __init allocate_paca(int cpu)
 #ifdef CONFIG_PPC_PSERIES
 	paca->lppaca_ptr = new_lppaca(cpu, limit);
 #endif
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
 #endif
 	paca_struct_size += sizeof(struct paca_struct);
@@ -285,7 +283,7 @@ void __init free_unused_pacas(void)
 	paca_nr_cpu_ids = nr_cpu_ids;
 	paca_ptrs_size = new_ptrs_size;
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	if (early_radix_enabled()) {
 		/* Ugly fixup, see new_slb_shadow() */
 		memblock_free(__pa(paca_ptrs[boot_cpuid]->slb_shadow_ptr),
@@ -298,9 +296,9 @@ void __init free_unused_pacas(void)
 			paca_ptrs_size + paca_struct_size, nr_cpu_ids);
 }
 
+#ifdef CONFIG_PPC_HASH_MMU
 void copy_mm_to_paca(struct mm_struct *mm)
 {
-#ifdef CONFIG_PPC_BOOK3S
 	mm_context_t *context = &mm->context;
 
 	get_paca()->mm_ctx_id = context->id;
@@ -315,7 +313,5 @@ void copy_mm_to_paca(struct mm_struct *mm)
 	get_paca()->mm_ctx_user_psize = context->user_psize;
 	get_paca()->mm_ctx_sllp = context->sllp;
 #endif
-#else /* !CONFIG_PPC_BOOK3S */
-	return;
-#endif
 }
+#endif /* CONFIG_PPC_HASH_MMU */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index fad50db9dcf2..c2e8eb100a89 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1140,7 +1140,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 {
 	struct thread_struct *new_thread, *old_thread;
 	struct task_struct *last;
-#ifdef CONFIG_PPC_BOOK3S_64
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_HASH_MMU)
 	struct ppc64_tlb_batch *batch;
 #endif
 
@@ -1149,7 +1149,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
 	WARN_ON(!irqs_disabled());
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_HASH_MMU)
 	batch = this_cpu_ptr(&ppc64_tlb_batch);
 	if (batch->active) {
 		current_thread_info()->local_flags |= _TLF_LAZY_MMU;
@@ -1204,11 +1204,13 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	last = _switch(old_thread, new_thread);
 
 #ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	if (current_thread_info()->local_flags & _TLF_LAZY_MMU) {
 		current_thread_info()->local_flags &= ~_TLF_LAZY_MMU;
 		batch = this_cpu_ptr(&ppc64_tlb_batch);
 		batch->active = 1;
 	}
+#endif
 
 	if (current->thread.regs) {
 		restore_math(current->thread.regs);
@@ -1568,7 +1570,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 
 static void setup_ksp_vsid(struct task_struct *p, unsigned long sp)
 {
-#ifdef CONFIG_PPC_BOOK3S_64
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_HASH_MMU)
 	unsigned long sp_vsid;
 	unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
 
@@ -2179,10 +2181,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 	 * the heap, we can put it above 1TB so it is backed by a 1TB
 	 * segment. Otherwise the heap will be in the bottom 1TB
 	 * which always uses 256MB segments and this may result in a
-	 * performance penalty. We don't need to worry about radix. For
-	 * radix, mmu_highuser_ssize remains unchanged from 256MB.
+	 * performance penalty.
 	 */
-	if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
+	if (!radix_enabled() && !is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
 		base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
 #endif
 
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6620f37abe73..f372340cbcd6 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -232,6 +232,7 @@ static void __init check_cpu_pa_features(unsigned long node)
 #ifdef CONFIG_PPC_BOOK3S_64
 static void __init init_mmu_slb_size(unsigned long node)
 {
+#ifdef CONFIG_PPC_HASH_MMU
 	const __be32 *slb_size_ptr;
 
 	slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL) ? :
@@ -239,6 +240,7 @@ static void __init init_mmu_slb_size(unsigned long node)
 
 	if (slb_size_ptr)
 		mmu_slb_size = be32_to_cpup(slb_size_ptr);
+#endif
 }
 #else
 #define init_mmu_slb_size(node) do { } while(0)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e05e6dd67ae6..70f2db84f5f4 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -758,6 +758,7 @@ void __init setup_per_cpu_areas(void)
 	unsigned int cpu;
 	int rc;
 
+#ifdef CONFIG_PPC_HASH_MMU
 	/*
 	 * Linear mapping is one of 4K, 1M and 16M.  For 4K, no need
 	 * to group units.  For larger mappings, use 1M atom which
@@ -767,6 +768,9 @@ void __init setup_per_cpu_areas(void)
 		atom_size = PAGE_SIZE;
 	else
 		atom_size = 1 << 20;
+#else
+	atom_size = PAGE_SIZE;
+#endif
 
 	rc = pcpu_embed_first_chunk(0, dyn_size, atom_size, pcpu_cpu_distance,
 				    pcpu_fc_alloc, pcpu_fc_free);
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index 04a7cba58eff..97b580b0a766 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -372,7 +372,7 @@ void default_machine_kexec(struct kimage *image)
 	/* NOTREACHED */
 }
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 /* Values we need to export to the second kernel via the device tree. */
 static unsigned long htab_base;
 static unsigned long htab_size;
@@ -414,4 +414,4 @@ static int __init export_htab_values(void)
 	return 0;
 }
 late_initcall(export_htab_values);
-#endif /* CONFIG_PPC_BOOK3S_64 */
+#endif /* CONFIG_PPC_HASH_MMU */
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 711fca9bc6f0..1693f1eebea8 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -70,6 +70,7 @@ config KVM_BOOK3S_64
 	select KVM
 	select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE
 	select SPAPR_TCE_IOMMU if IOMMU_SUPPORT && (PPC_PSERIES || PPC_POWERNV)
+	select PPC_HASH_MMU
 	---help---
 	  Support running unmodified book3s_64 and book3s_32 guest kernels
 	  in virtual machines on book3s_64 host processors.
diff --git a/arch/powerpc/mm/book3s64/Makefile b/arch/powerpc/mm/book3s64/Makefile
index fd393b8be14f..5376e11ec85f 100644
--- a/arch/powerpc/mm/book3s64/Makefile
+++ b/arch/powerpc/mm/book3s64/Makefile
@@ -2,20 +2,23 @@
 
 ccflags-y	:= $(NO_MINIMAL_TOC)
 
+obj-y				+= mmu_context.o pgtable.o
+ifdef CONFIG_PPC_HASH_MMU
 CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE)
-
-obj-y				+= hash_pgtable.o hash_utils.o slb.o \
-				   mmu_context.o pgtable.o hash_tlb.o
+obj-y				+= hash_pgtable.o hash_utils.o hash_tlb.o slb.o
 obj-$(CONFIG_PPC_NATIVE)	+= hash_native.o
-obj-$(CONFIG_PPC_RADIX_MMU)	+= radix_pgtable.o radix_tlb.o
 obj-$(CONFIG_PPC_4K_PAGES)	+= hash_4k.o
 obj-$(CONFIG_PPC_64K_PAGES)	+= hash_64k.o
-obj-$(CONFIG_HUGETLB_PAGE)	+= hash_hugetlbpage.o
+obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += hash_hugepage.o
+obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage_prot.o
+endif
+
+obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
+
+obj-$(CONFIG_PPC_RADIX_MMU)	+= radix_pgtable.o radix_tlb.o
 ifdef CONFIG_HUGETLB_PAGE
 obj-$(CONFIG_PPC_RADIX_MMU)	+= radix_hugetlbpage.o
 endif
-obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += hash_hugepage.o
-obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage_prot.o
 obj-$(CONFIG_SPAPR_TCE_IOMMU)	+= iommu_api.o
 obj-$(CONFIG_PPC_MEM_KEYS)	+= pkeys.o
 
diff --git a/arch/powerpc/mm/book3s64/hash_pgtable.c b/arch/powerpc/mm/book3s64/hash_pgtable.c
index 64733b9cb20a..637f90452657 100644
--- a/arch/powerpc/mm/book3s64/hash_pgtable.c
+++ b/arch/powerpc/mm/book3s64/hash_pgtable.c
@@ -17,7 +17,6 @@
 
 #include <mm/mmu_decl.h>
 
-#define CREATE_TRACE_POINTS
 #include <trace/events/thp.h>
 
 #if H_PGTABLE_RANGE > (USER_VSID_RANGE * (TASK_SIZE_USER64 / TASK_CONTEXT_SIZE))
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
index 523d4d39d11e..44ade204d050 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -95,8 +95,6 @@
  */
 
 static unsigned long _SDR1;
-struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
-EXPORT_SYMBOL_GPL(mmu_psize_defs);
 
 u8 hpte_page_sizes[1 << LP_BITS];
 EXPORT_SYMBOL_GPL(hpte_page_sizes);
@@ -105,14 +103,7 @@ struct hash_pte *htab_address;
 unsigned long htab_size_bytes;
 unsigned long htab_hash_mask;
 EXPORT_SYMBOL_GPL(htab_hash_mask);
-int mmu_linear_psize = MMU_PAGE_4K;
-EXPORT_SYMBOL_GPL(mmu_linear_psize);
 int mmu_virtual_psize = MMU_PAGE_4K;
-int mmu_vmalloc_psize = MMU_PAGE_4K;
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-int mmu_vmemmap_psize = MMU_PAGE_4K;
-#endif
-int mmu_io_psize = MMU_PAGE_4K;
 int mmu_kernel_ssize = MMU_SEGSIZE_256M;
 EXPORT_SYMBOL_GPL(mmu_kernel_ssize);
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
diff --git a/arch/powerpc/mm/book3s64/hash_hugetlbpage.c b/arch/powerpc/mm/book3s64/hugetlbpage.c
similarity index 99%
rename from arch/powerpc/mm/book3s64/hash_hugetlbpage.c
rename to arch/powerpc/mm/book3s64/hugetlbpage.c
index eefa89c6117b..e4df7016e0fb 100644
--- a/arch/powerpc/mm/book3s64/hash_hugetlbpage.c
+++ b/arch/powerpc/mm/book3s64/hugetlbpage.c
@@ -18,6 +18,7 @@
 unsigned int hpage_shift;
 EXPORT_SYMBOL(hpage_shift);
 
+#ifdef CONFIG_PPC_HASH_MMU
 extern long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
 				  unsigned long pa, unsigned long rlags,
 				  unsigned long vflags, int psize, int ssize);
@@ -128,6 +129,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
 	*ptep = __pte(new_pte & ~H_PAGE_BUSY);
 	return 0;
 }
+#endif
 
 pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma,
 				  unsigned long addr, pte_t *ptep)
diff --git a/arch/powerpc/mm/book3s64/mmu_context.c b/arch/powerpc/mm/book3s64/mmu_context.c
index 0ba30b8b935b..660941edd550 100644
--- a/arch/powerpc/mm/book3s64/mmu_context.c
+++ b/arch/powerpc/mm/book3s64/mmu_context.c
@@ -28,6 +28,7 @@ static int alloc_context_id(int min_id, int max_id)
 	return ida_alloc_range(&mmu_context_ida, min_id, max_id, GFP_KERNEL);
 }
 
+#ifdef CONFIG_PPC_HASH_MMU
 void hash__reserve_context_id(int id)
 {
 	int result = ida_alloc_range(&mmu_context_ida, id, id, GFP_KERNEL);
@@ -47,9 +48,9 @@ int hash__alloc_context_id(void)
 	return alloc_context_id(MIN_USER_CONTEXT, max);
 }
 EXPORT_SYMBOL_GPL(hash__alloc_context_id);
+#endif
 
-void slb_setup_new_exec(void);
-
+#ifdef CONFIG_PPC_HASH_MMU
 static int realloc_context_ids(mm_context_t *ctx)
 {
 	int i, id;
@@ -143,12 +144,15 @@ static int hash__init_new_context(struct mm_struct *mm)
 	return index;
 }
 
+void slb_setup_new_exec(void);
+
 void hash__setup_new_exec(void)
 {
 	slice_setup_new_exec();
 
 	slb_setup_new_exec();
 }
+#endif
 
 static int radix__init_new_context(struct mm_struct *mm)
 {
@@ -174,7 +178,9 @@ static int radix__init_new_context(struct mm_struct *mm)
 	 */
 	asm volatile("ptesync;isync" : : : "memory");
 
+#ifdef CONFIG_PPC_HASH_MMU
 	mm->context.hash_context = NULL;
+#endif
 
 	return index;
 }
@@ -185,8 +191,10 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 
 	if (radix_enabled())
 		index = radix__init_new_context(mm);
+#ifdef CONFIG_PPC_HASH_MMU
 	else
 		index = hash__init_new_context(mm);
+#endif
 
 	if (index < 0)
 		return index;
@@ -210,6 +218,7 @@ void __destroy_context(int context_id)
 }
 EXPORT_SYMBOL_GPL(__destroy_context);
 
+#ifdef CONFIG_PPC_HASH_MMU
 static void destroy_contexts(mm_context_t *ctx)
 {
 	int index, context_id;
@@ -221,6 +230,7 @@ static void destroy_contexts(mm_context_t *ctx)
 	}
 	kfree(ctx->hash_context);
 }
+#endif
 
 static void pmd_frag_destroy(void *pmd_frag)
 {
@@ -273,7 +283,11 @@ void destroy_context(struct mm_struct *mm)
 		process_tb[mm->context.id].prtb0 = 0;
 	else
 		subpage_prot_free(mm);
+#ifdef CONFIG_PPC_HASH_MMU
 	destroy_contexts(&mm->context);
+#else
+	ida_free(&mmu_context_ida, mm->context.id);
+#endif
 	mm->context.id = MMU_NO_CONTEXT;
 }
 
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
index 2bf7e1b4fd82..2f308d21700e 100644
--- a/arch/powerpc/mm/book3s64/pgtable.c
+++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -11,14 +11,25 @@
 #include <asm/debugfs.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
-#include <asm/trace.h>
 #include <asm/powernv.h>
 #include <asm/firmware.h>
 #include <asm/ultravisor.h>
 
 #include <mm/mmu_decl.h>
+#define CREATE_TRACE_POINTS
 #include <trace/events/thp.h>
 
+struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+EXPORT_SYMBOL_GPL(mmu_psize_defs);
+
+int mmu_linear_psize = MMU_PAGE_4K;
+EXPORT_SYMBOL_GPL(mmu_linear_psize);
+int mmu_vmalloc_psize = MMU_PAGE_4K;
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+int mmu_vmemmap_psize = MMU_PAGE_4K;
+#endif
+int mmu_io_psize = MMU_PAGE_4K;
+
 unsigned long __pmd_frag_nr;
 EXPORT_SYMBOL(__pmd_frag_nr);
 unsigned long __pmd_frag_size_shift;
@@ -147,6 +158,7 @@ pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 	return pmd_set_protbits(__pmd(pmdv), newprot);
 }
 
+#ifdef CONFIG_PPC_HASH_MMU
 /*
  * This is called at the end of handling a user page fault, when the
  * fault has been handled by updating a HUGE PMD entry in the linux page tables.
@@ -159,6 +171,7 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
 	if (radix_enabled())
 		prefetch((void *)addr);
 }
+#endif
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 /* For use by kexec */
@@ -220,7 +233,12 @@ static void flush_partition(unsigned int lpid, bool radix)
 			     "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
 		/* do we need fixup here ?*/
 		asm volatile("eieio; tlbsync; ptesync" : : : "memory");
-		trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0);
+		/*
+		 * XXX: Can't use this tracepoint
+		 * because this file defines the  THP tracepoints
+		 * trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0);
+		 * KVM tlbie tracing has much larger deficiencies though.
+		 */
 	}
 }
 
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index 2a9a0cd79490..cd22557bb512 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -315,8 +315,11 @@ static void __init radix_init_pgtable(void)
 	unsigned long rts_field;
 	struct memblock_region *reg;
 
+#ifdef CONFIG_PPC_HASH_MMU
 	/* We don't support slb for radix */
 	mmu_slb_size = 0;
+#endif
+
 	/*
 	 * Create the linear mapping, using standard page size for now
 	 */
@@ -548,6 +551,7 @@ void __init radix__early_init_mmu(void)
 {
 	unsigned long lpcr;
 
+#ifdef CONFIG_PPC_HASH_MMU
 #ifdef CONFIG_PPC_64K_PAGES
 	/* PAGE_SIZE mappings */
 	mmu_virtual_psize = MMU_PAGE_64K;
@@ -564,6 +568,7 @@ void __init radix__early_init_mmu(void)
 		mmu_vmemmap_psize = MMU_PAGE_2M;
 	} else
 		mmu_vmemmap_psize = mmu_virtual_psize;
+#endif
 #endif
 	/*
 	 * initialize page table size
diff --git a/arch/powerpc/mm/book3s64/slb.c b/arch/powerpc/mm/book3s64/slb.c
index 716204aee3da..f216bbe58d15 100644
--- a/arch/powerpc/mm/book3s64/slb.c
+++ b/arch/powerpc/mm/book3s64/slb.c
@@ -812,17 +812,3 @@ long do_slb_fault(struct pt_regs *regs, unsigned long ea)
 		return err;
 	}
 }
-
-void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err)
-{
-	if (err == -EFAULT) {
-		if (user_mode(regs))
-			_exception(SIGSEGV, regs, SEGV_BNDERR, ea);
-		else
-			bad_page_fault(regs, ea, SIGSEGV);
-	} else if (err == -EINVAL) {
-		unrecoverable_exception(regs);
-	} else {
-		BUG();
-	}
-}
diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c
index beb060b96632..9fdef2216800 100644
--- a/arch/powerpc/mm/copro_fault.c
+++ b/arch/powerpc/mm/copro_fault.c
@@ -87,6 +87,7 @@ int copro_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
 }
 EXPORT_SYMBOL_GPL(copro_handle_mm_fault);
 
+#ifdef CONFIG_PPC_HASH_MMU
 int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
 {
 	u64 vsid, vsidkey;
@@ -151,3 +152,4 @@ void copro_flush_all_slbs(struct mm_struct *mm)
 	cxl_slbia(mm);
 }
 EXPORT_SYMBOL_GPL(copro_flush_all_slbs);
+#endif
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 8db0507619e2..02095e1d8e62 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -33,6 +33,7 @@
 #include <linux/hugetlb.h>
 #include <linux/uaccess.h>
 
+#include <asm/asm-prototypes.h>
 #include <asm/firmware.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -685,3 +686,22 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 
 	die("Kernel access of bad area", regs, sig);
 }
+
+#ifdef CONFIG_PPC_BOOK3S_64
+/*
+ * Radix takes bad slb (segment) faults as well.
+ */
+void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err)
+{
+	if (err == -EFAULT) {
+		if (user_mode(regs))
+			_exception(SIGSEGV, regs, SEGV_BNDERR, ea);
+		else
+			bad_page_fault(regs, ea, SIGSEGV);
+	} else if (err == -EINVAL) {
+		unrecoverable_exception(regs);
+	} else {
+		BUG();
+	}
+}
+#endif
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 6caedc88474f..a700deae0dcc 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -98,7 +98,6 @@ config PPC_BOOK3S_64
 	select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
 	select ARCH_SUPPORTS_NUMA_BALANCING
 	select IRQ_WORK
-	select PPC_MM_SLICES
 
 config PPC_BOOK3E_64
 	bool "Embedded processors"
@@ -120,11 +119,13 @@ choice
 config GENERIC_CPU
 	bool "Generic (POWER4 and above)"
 	depends on PPC64 && !CPU_LITTLE_ENDIAN
+	select PPC_HASH_MMU
 
 config GENERIC_CPU
 	bool "Generic (POWER8 and above)"
 	depends on PPC64 && CPU_LITTLE_ENDIAN
 	select ARCH_HAS_FAST_MULTIPLIER
+	select PPC_HASH_MMU
 
 config GENERIC_CPU
 	bool "Generic 32 bits powerpc"
@@ -133,24 +134,29 @@ config GENERIC_CPU
 config CELL_CPU
 	bool "Cell Broadband Engine"
 	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
+	select PPC_HASH_MMU
 
 config POWER5_CPU
 	bool "POWER5"
 	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
+	select PPC_HASH_MMU
 
 config POWER6_CPU
 	bool "POWER6"
 	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
+	select PPC_HASH_MMU
 
 config POWER7_CPU
 	bool "POWER7"
 	depends on PPC_BOOK3S_64
 	select ARCH_HAS_FAST_MULTIPLIER
+	select PPC_HASH_MMU
 
 config POWER8_CPU
 	bool "POWER8"
 	depends on PPC_BOOK3S_64
 	select ARCH_HAS_FAST_MULTIPLIER
+	select PPC_HASH_MMU
 
 config POWER9_CPU
 	bool "POWER9"
@@ -358,9 +364,21 @@ config PPC_RADIX_MMU
 	  is only implemented by IBM Power9 CPUs, if you don't have one of them
 	  you can probably disable this.
 
+config PPC_HASH_MMU
+	bool "Hash MMU Support"
+	depends on PPC_BOOK3S_64
+	default y
+	select PPC_MM_SLICES
+	help
+	  Enable support for the Power ISA Hash style MMU. This is implemented
+          by all IBM Power and other Book3S CPUs.
+
+	  If you're unsure, say Y.
+
 config PPC_RADIX_MMU_DEFAULT
 	bool "Default to using the Radix MMU when possible"
 	depends on PPC_RADIX_MMU
+	depends on PPC_HASH_MMU
 	default y
 	help
 	  When the hardware supports the Radix MMU, default to using it unless
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 78599bca66c2..3f2633b46ca3 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -491,12 +491,14 @@ static unsigned long power7_idle_insn(unsigned long type)
 
 	mtspr(SPRN_SPRG3,	local_paca->sprg_vdso);
 
+#ifdef CONFIG_PPC_HASH_MMU
 	/*
 	 * The SLB has to be restored here, but it sometimes still
 	 * contains entries, so the __ variant must be used to prevent
 	 * multi hits.
 	 */
 	__slb_restore_bolted_realmode();
+#endif
 
 	return srr1;
 }
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 11fdae81b5dd..fb7061ca63d0 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -168,6 +168,7 @@ static void __init pnv_init(void)
 #endif
 		add_preferred_console("hvc", 0, NULL);
 
+#ifdef CONFIG_PPC_HASH_MMU
 	if (!radix_enabled()) {
 		int i;
 
@@ -175,6 +176,7 @@ static void __init pnv_init(void)
 		for_each_possible_cpu(i)
 			paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
 	}
+#endif
 }
 
 static void __init pnv_init_IRQ(void)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 0ec9640335bb..0146bfb9ee2a 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -1119,9 +1119,11 @@ cmds(struct pt_regs *excp)
 			show_tasks();
 			break;
 #ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_PPC_HASH_MMU
 		case 'u':
 			dump_segments();
 			break;
+#endif
 #elif defined(CONFIG_44x)
 		case 'u':
 			dump_tlb_44x();
@@ -2419,7 +2421,7 @@ static void dump_tracing(void)
 static void dump_one_paca(int cpu)
 {
 	struct paca_struct *p;
-#ifdef CONFIG_PPC_BOOK3S_64
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_HASH_MMU)
 	int i = 0;
 #endif
 
@@ -2461,6 +2463,7 @@ static void dump_one_paca(int cpu)
 	DUMP(p, cpu_start, "%#-*x");
 	DUMP(p, kexec_state, "%#-*x");
 #ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_HASH_MMU
 	if (!early_radix_enabled()) {
 		for (i = 0; i < SLB_NUM_BOLTED; i++) {
 			u64 esid, vsid;
@@ -2488,6 +2491,7 @@ static void dump_one_paca(int cpu)
 				       22, "slb_cache", i, p->slb_cache[i]);
 		}
 	}
+#endif
 
 	DUMP(p, rfi_flush_fallback_area, "%-*px");
 #endif
@@ -3570,7 +3574,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
 	printf("%s", after);
 }
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_HASH_MMU)
 void dump_segments(void)
 {
 	int i;
-- 
2.23.0


^ permalink raw reply related

* Re: [PATCH] powerpc/Kconfig: Make FSL_85XX_CACHE_SRAM configurable
From: 王文虎 @ 2020-03-02  4:42 UTC (permalink / raw)
  To: Scott Wood
  Cc: Rai Harninder, trivial, linux-kernel, wangwenhu, Paul Mackerras,
	linuxppc-dev
In-Reply-To: <a8134f2ece5059bbf078e8369a485857ff4d6590.camel@buserror.net>

发件人:Scott Wood <oss@buserror.net>
发送日期:2020-03-01 07:12:58
收件人:"王文虎" <wenhu.wang@vivo.com>
抄送人:wangwenhu <wenhu.pku@gmail.com>,Kumar Gala <galak@kernel.crashing.org>,Benjamin Herrenschmidt <benh@kernel.crashing.org>,Paul Mackerras <paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,linuxppc-dev@lists.ozlabs.org,linux-kernel@vger.kernel.org,trivial@kernel.org,Rai Harninder <harninder.rai@nxp.com>
主题:Re: Re: [PATCH] powerpc/Kconfig: Make FSL_85XX_CACHE_SRAM configurable>On Tue, 2020-01-21 at 14:38 +0800, 王文虎 wrote:
>> 发件人:Scott Wood <oss@buserror.net>
>> 发送日期:2020-01-21 13:49:59
>> 收件人:"王文虎" <wenhu.wang@vivo.com>
>> 抄送人:wangwenhu <wenhu.pku@gmail.com>,Kumar Gala <galak@kernel.crashing.org>,B
>> enjamin Herrenschmidt <benh@kernel.crashing.org>,Paul Mackerras <
>> paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,
>> linuxppc-dev@lists.ozlabs.org,linux-kernel@vger.kernel.org,
>> trivial@kernel.org,Rai Harninder <harninder.rai@nxp.com>
>> 主题:Re: [PATCH] powerpc/Kconfig: Make FSL_85XX_CACHE_SRAM configurable>On
>> Tue, 2020-01-21 at 13:20 +0800, 王文虎 wrote:
>> > > From: Scott Wood <oss@buserror.net>
>> > > Date: 2020-01-21 11:25:25
>> > > To:  wangwenhu <wenhu.pku@gmail.com>,Kumar Gala <
>> > > galak@kernel.crashing.org>,
>> > > Benjamin Herrenschmidt <benh@kernel.crashing.org>,Paul Mackerras <
>> > > paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,
>> > > linuxppc-dev@lists.ozlabs.org,linux-kernel@vger.kernel.org
>> > > Cc:  trivial@kernel.org,wenhu.wang@vivo.com,Rai Harninder <
>> > > harninder.rai@nxp.com>
>> > > Subject: Re: [PATCH] powerpc/Kconfig: Make FSL_85XX_CACHE_SRAM
>> > > configurable>On Mon, 2020-01-20 at 06:43 -0800, wangwenhu wrote:
>> > > > > From: wangwenhu <wenhu.wang@vivo.com>
>> > > > > 
>> > > > > When generating .config file with menuconfig on Freescale BOOKE
>> > > > > SOC, FSL_85XX_CACHE_SRAM is not configurable for the lack of
>> > > > > description in the Kconfig field, which makes it impossible
>> > > > > to support L2Cache-Sram driver. Add a description to make it
>> > > > > configurable.
>> > > > > 
>> > > > > Signed-off-by: wangwenhu <wenhu.wang@vivo.com>
>> > > > 
>> > > > The intent was that drivers using the SRAM API would select the
>> > > > symbol.  What
>> > > > is the use case for selecting it manually?
>> > > > 
>> > > 
>> > > With a repository of multiple products(meaning different defconfigs) and
>> > > multiple
>> > > developers, the Kconfigs of the Kernel Source Tree change frequently. So
>> > > the
>> > > "make menuconfig"
>> > > process is needed for defconfigs' re-generating or updating for the
>> > > complexity of dependencies
>> > > between different features defined in the Kconfigs.
>> > 
>> > That doesn't answer my question of how the SRAM code would be useful other
>> > than to some other driver that uses the API (which would use
>> > "select").  There
>> > is no userspace API.  You could use the kernel command line to configure
>> > the
>> > SRAM but you need to get the address of it for it to be useful.
>> > 
>> 
>> Like you've asked below, via /dev/mem or direct calling within the Kernel.
>> And they are not submitted yes, under development.
>
>If they are calling within the kernel, then whatever driver that is should
>select FSL_85XX_CACHE_SRAM.  Directly accessing /dev/mem without any way for
>the kernel to advertise where it is or which parts of SRAM are available for
>use sounds like a bad idea.

>
Yes, definitely. So like we enable the moulde which should selet 
FSL_85XX_CACHE_SRAM to build vmlinux, FSL_85XX_CACHE_SRAM 
could not be seleted because of the Kconfig definition problem 
which I am trying to fix now.  So would you please merge the patch 
for the convenience of later works depending on the driver.

Wenhu

>-Scott
>
>



^ permalink raw reply

* Re: [PATCH v3 0/6] implement KASLR for powerpc/fsl_booke/64
From: Scott Wood @ 2020-03-02  3:24 UTC (permalink / raw)
  To: Jason Yan, Daniel Axtens, mpe, linuxppc-dev, diana.craciun,
	christophe.leroy, benh, paulus, npiggin, keescook,
	kernel-hardening, me
  Cc: linux-kernel, zhaohongjiang
In-Reply-To: <35e6c660-3896-bdb8-45f3-c1504aa2171f@huawei.com>

On Mon, 2020-03-02 at 10:17 +0800, Jason Yan wrote:
> 
> 在 2020/3/1 6:54, Scott Wood 写道:
> > On Sat, 2020-02-29 at 15:27 +0800, Jason Yan wrote:
> > > 
> > > Turnning to %p may not be a good idea in this situation. So
> > > for the REG logs printed when dumping stack, we can disable it when
> > > KASLR is open. For the REG logs in other places like show_regs(), only
> > > privileged can trigger it, and they are not combind with a symbol, so
> > > I think it's ok to keep them.
> > > 
> > > diff --git a/arch/powerpc/kernel/process.c
> > > b/arch/powerpc/kernel/process.c
> > > index fad50db9dcf2..659c51f0739a 100644
> > > --- a/arch/powerpc/kernel/process.c
> > > +++ b/arch/powerpc/kernel/process.c
> > > @@ -2068,7 +2068,10 @@ void show_stack(struct task_struct *tsk, unsigned
> > > long *stack)
> > >                   newsp = stack[0];
> > >                   ip = stack[STACK_FRAME_LR_SAVE];
> > >                   if (!firstframe || ip != lr) {
> > > -                       printk("["REG"] ["REG"] %pS", sp, ip, (void
> > > *)ip);
> > > +                       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
> > > +                               printk("%pS", (void *)ip);
> > > +                       else
> > > +                               printk("["REG"] ["REG"] %pS", sp, ip,
> > > (void *)ip);
> > 
> > This doesn't deal with "nokaslr" on the kernel command line.  It also
> > doesn't
> > seem like something that every callsite should have to opencode, versus
> > having
> > an appropriate format specifier behaves as I described above (and I still
> > don't see why that format specifier should not be "%p").
> > 
> 
> Actually I still do not understand why we should print the raw value 
> here. When KALLSYMS is enabled we have symbol name  and  offset like 
> put_cred_rcu+0x108/0x110, and when KALLSYMS is disabled we have the raw 
> address.

I'm more concerned about the stack address for wading through a raw stack dump
(to find function call arguments, etc).  The return address does help confirm
that I'm on the right stack frame though, and also makes looking up a line
number slightly easier than having to look up a symbol address and then add
the offset (at least for non-module addresses).

As a random aside, the mismatch between Linux printing a hex offset and GDB
using decimal in disassembly is annoying...

-Scott



^ permalink raw reply

* Re: [PATCH] mm/debug: Add tests validating arch page table helpers for core features
From: Anshuman Khandual @ 2020-03-02  3:22 UTC (permalink / raw)
  To: Christophe Leroy, linux-mm
  Cc: Catalin Marinas, Heiko Carstens, Paul Mackerras, H. Peter Anvin,
	linux-riscv, Will Deacon, linux-arch, linux-s390, x86,
	Mike Rapoport, Christian Borntraeger, Ingo Molnar, linux-snps-arc,
	Vasily Gorbik, Borislav Petkov, Paul Walmsley,
	Kirill A . Shutemov, Thomas Gleixner, linux-arm-kernel,
	Vineet Gupta, linux-kernel, Palmer Dabbelt, Andrew Morton,
	linuxppc-dev
In-Reply-To: <2be41c29-500c-50af-f915-1493846ae9e5@c-s.fr>

On 02/27/2020 04:59 PM, Christophe Leroy wrote:
> 
> 
> Le 27/02/2020 à 11:33, Anshuman Khandual a écrit :
>> This adds new tests validating arch page table helpers for these following
>> core memory features. These tests create and test specific mapping types at
>> various page table levels.
>>
>> * SPECIAL mapping
>> * PROTNONE mapping
>> * DEVMAP mapping
>> * SOFTDIRTY mapping
>> * SWAP mapping
>> * MIGRATION mapping
>> * HUGETLB mapping
>> * THP mapping
>>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Mike Rapoport <rppt@linux.ibm.com>
>> Cc: Vineet Gupta <vgupta@synopsys.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will@kernel.org>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
>> Cc: Vasily Gorbik <gor@linux.ibm.com>
>> Cc: Christian Borntraeger <borntraeger@de.ibm.com>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Ingo Molnar <mingo@redhat.com>
>> Cc: Borislav Petkov <bp@alien8.de>
>> Cc: "H. Peter Anvin" <hpa@zytor.com>
>> Cc: Kirill A. Shutemov <kirill@shutemov.name>
>> Cc: Paul Walmsley <paul.walmsley@sifive.com>
>> Cc: Palmer Dabbelt <palmer@dabbelt.com>
>> Cc: linux-snps-arc@lists.infradead.org
>> Cc: linux-arm-kernel@lists.infradead.org
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Cc: linux-s390@vger.kernel.org
>> Cc: linux-riscv@lists.infradead.org
>> Cc: x86@kernel.org
>> Cc: linux-arch@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
>> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
>> ---
>> Tested on arm64 and x86 platforms without any test failures. But this has
>> only been built tested on several other platforms. Individual tests need
>> to be verified on all current enabling platforms for the test i.e s390,
>> ppc32, arc etc.
>>
>> This patch must be applied on v5.6-rc3 after these patches
>>
>> 1. https://patchwork.kernel.org/patch/11385057/
>> 2. https://patchwork.kernel.org/patch/11407715/
>>
>> OR
>>
>> This patch must be applied on linux-next (next-20200227) after this patch
>>
>> 2. https://patchwork.kernel.org/patch/11407715/
>>
>>   mm/debug_vm_pgtable.c | 310 +++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 309 insertions(+), 1 deletion(-)
>>
>> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
>> index 96dd7d574cef..3fb90d5b604e 100644
>> --- a/mm/debug_vm_pgtable.c
>> +++ b/mm/debug_vm_pgtable.c
>> @@ -41,6 +41,44 @@
>>    * wrprotect(entry)        = A write protected and not a write entry
>>    * pxx_bad(entry)        = A mapped and non-table entry
>>    * pxx_same(entry1, entry2)    = Both entries hold the exact same value
>> + *
>> + * Specific feature operations
>> + *
>> + * pte_mkspecial(entry)        = Creates a special entry at PTE level
>> + * pte_special(entry)        = Tests a special entry at PTE level
>> + *
>> + * pte_protnone(entry)        = Tests a no access entry at PTE level
>> + * pmd_protnone(entry)        = Tests a no access entry at PMD level
>> + *
>> + * pte_mkdevmap(entry)        = Creates a device entry at PTE level
>> + * pmd_mkdevmap(entry)        = Creates a device entry at PMD level
>> + * pud_mkdevmap(entry)        = Creates a device entry at PUD level
>> + * pte_devmap(entry)        = Tests a device entry at PTE level
>> + * pmd_devmap(entry)        = Tests a device entry at PMD level
>> + * pud_devmap(entry)        = Tests a device entry at PUD level
>> + *
>> + * pte_mksoft_dirty(entry)    = Creates a soft dirty entry at PTE level
>> + * pmd_mksoft_dirty(entry)    = Creates a soft dirty entry at PMD level
>> + * pte_swp_mksoft_dirty(entry)    = Creates a soft dirty swap entry at PTE level
>> + * pmd_swp_mksoft_dirty(entry)    = Creates a soft dirty swap entry at PMD level
>> + * pte_soft_dirty(entry)    = Tests a soft dirty entry at PTE level
>> + * pmd_soft_dirty(entry)    = Tests a soft dirty entry at PMD level
>> + * pte_swp_soft_dirty(entry)    = Tests a soft dirty swap entry at PTE level
>> + * pmd_swp_soft_dirty(entry)    = Tests a soft dirty swap entry at PMD level
>> + * pte_clear_soft_dirty(entry)       = Clears a soft dirty entry at PTE level
>> + * pmd_clear_soft_dirty(entry)       = Clears a soft dirty entry at PMD level
>> + * pte_swp_clear_soft_dirty(entry) = Clears a soft dirty swap entry at PTE level
>> + * pmd_swp_clear_soft_dirty(entry) = Clears a soft dirty swap entry at PMD level
>> + *
>> + * pte_mkhuge(entry)        = Creates a HugeTLB entry at given level
>> + * pte_huge(entry)        = Tests a HugeTLB entry at given level
>> + *
>> + * pmd_trans_huge(entry)    = Tests a trans huge page at PMD level
>> + * pud_trans_huge(entry)    = Tests a trans huge page at PUD level
>> + * pmd_present(entry)        = Tests an entry points to memory at PMD level
>> + * pud_present(entry)        = Tests an entry points to memory at PUD level
>> + * pmd_mknotpresent(entry)    = Invalidates an PMD entry for MMU
>> + * pud_mknotpresent(entry)    = Invalidates an PUD entry for MMU
>>    */
>>   #define VMFLAGS    (VM_READ|VM_WRITE|VM_EXEC)
>>   @@ -287,6 +325,233 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>       WARN_ON(pmd_bad(pmd));
>>   }
>>   +#ifdef CONFIG_ARCH_HAS_PTE_SPECIAL
> 
> Can we avoid ifdefs unless necessary ?
> 
> In mm/memory.c I see things like the following, it means pte_special() always exist and a #ifdef is not necessary.

True, #ifdef here can be dropped here, done.

> 
>     if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL)) {
>         if (likely(!pte_special(pte)))
>             goto check_pfn;
>         if (vma->vm_ops && vma->vm_ops->find_special_page)
>             return vma->vm_ops->find_special_page(vma, addr);
>         if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
>             return NULL;
>         if (is_zero_pfn(pfn))
>             return NULL;
>         if (pte_devmap(pte))
>             return NULL;
> 
>         print_bad_pte(vma, addr, pte, NULL);
>         return NULL;
>     }
> 
>> +static void __init pte_special_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pte_t pte = pfn_pte(pfn, prot);
>> +
>> +    WARN_ON(!pte_special(pte_mkspecial(pte)));
>> +}
>> +#else
>> +static void __init pte_special_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +
>> +#ifdef CONFIG_NUMA_BALANCING
> 
> Same here, this ifdef shouldn't be necessary because in /include/asm-generic/pgtable.h we have the following, so a if (IS_ENABLED()) should be enough.
> 
> #ifndef CONFIG_NUMA_BALANCING
> /*
>  * Technically a PTE can be PROTNONE even when not doing NUMA balancing but
>  * the only case the kernel cares is for NUMA balancing and is only ever set
>  * when the VMA is accessible. For PROT_NONE VMAs, the PTEs are not marked
>  * _PAGE_PROTNONE so by by default, implement the helper as "always no". It
>  * is the responsibility of the caller to distinguish between PROT_NONE
>  * protections and NUMA hinting fault protections.
>  */
> static inline int pte_protnone(pte_t pte)
> {
>     return 0;
> }
> 
> static inline int pmd_protnone(pmd_t pmd)
> {
>     return 0;
> }
> #endif /* CONFIG_NUMA_BALANCING */

True,  #ifdef here can be dropped, done. There is something I had missed
before, pfn_pmd() requires #ifdef CONFIG_TRANSPARENT_HUGEPAGE instead. We
need a pmd_t here with given prot. We cannot go via pfn_pte() followed by
pte_pmd(), as the later is platform specific and not available in general.

> 
>> +static void __init pte_protnone_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pte_t pte = pfn_pte(pfn, prot);
>> +
>> +    WARN_ON(!pte_protnone(pte));
>> +    WARN_ON(!pte_present(pte));
>> +}
>> +
>> +static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pmd_t pmd = pfn_pmd(pfn, prot);
>> +
>> +    WARN_ON(!pmd_protnone(pmd));
>> +    WARN_ON(!pmd_present(pmd));
>> +}
>> +#else
>> +static void __init pte_protnone_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +
>> +#ifdef CONFIG_ARCH_HAS_PTE_DEVMAP
> 
> Same here, in include/linux/mm.h we have:
> 
> #ifndef CONFIG_ARCH_HAS_PTE_DEVMAP
> static inline int pte_devmap(pte_t pte)
> {
>     return 0;
> }
> #endif
> 
> 
>> +static void __init pte_devmap_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pte_t pte = pfn_pte(pfn, prot);
>> +
>> +    WARN_ON(!pte_devmap(pte_mkdevmap(pte)));
>> +}
>> +
>> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> 
> Same. In inlude/asm-generic/pgtables.h you have:
> 
> #if !defined(CONFIG_ARCH_HAS_PTE_DEVMAP) || !defined(CONFIG_TRANSPARENT_HUGEPAGE)
> static inline int pmd_devmap(pmd_t pmd)
> {
>     return 0;
> }
> static inline int pud_devmap(pud_t pud)
> {
>     return 0;
> }
> static inline int pgd_devmap(pgd_t pgd)
> {
>     return 0;
> }
> #endif
> 
>> +static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pmd_t pmd = pfn_pmd(pfn, prot);
>> +
>> +    WARN_ON(!pmd_devmap(pmd_mkdevmap(pmd)));
>> +}
>> +
>> +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
> 
> Same, see above

Even though pxx_devmap() fallback definitions are present, pxx_mkdevmap()
ones are still missing. We will have to add them first as a pre-requisite
patch (which might not be popular without any non-debug use case) in order
to drop these #ifdefs here.

> 
>> +static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pud_t pud = pfn_pud(pfn, prot);
>> +
>> +    WARN_ON(!pud_devmap(pud_mkdevmap(pud)));
>> +}
>> +#else
>> +static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +#else
>> +static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +#else
>> +static void __init pte_devmap_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +
>> +#ifdef CONFIG_MEM_SOFT_DIRTY
> 
> Same, they always exist, see include/asm-generic/pgtable.h

Yeah, this can be dropped. Though will have to again add TRANSPARENT_HUGEPAGE
to protect pfn_pmd() as explained before.

> 
>> +static void __init pte_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pte_t pte = pfn_pte(pfn, prot);
>> +
>> +    WARN_ON(!pte_soft_dirty(pte_mksoft_dirty(pte)));
>> +    WARN_ON(pte_soft_dirty(pte_clear_soft_dirty(pte)));
>> +}
>> +
>> +static void __init pte_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pte_t pte = pfn_pte(pfn, prot);
>> +
>> +    WARN_ON(!pte_swp_soft_dirty(pte_swp_mksoft_dirty(pte)));
>> +    WARN_ON(pte_swp_soft_dirty(pte_swp_clear_soft_dirty(pte)));
>> +}
>> +
>> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> 
> Same

True, #ifdef here can be dropped, done.

> 
>> +static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pmd_t pmd = pfn_pmd(pfn, prot);
>> +
>> +    WARN_ON(!pmd_soft_dirty(pmd_mksoft_dirty(pmd)));
>> +    WARN_ON(pmd_soft_dirty(pmd_clear_soft_dirty(pmd)));
>> +}
>> +
>> +static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pmd_t pmd = pfn_pmd(pfn, prot);
>> +
>> +    WARN_ON(!pmd_swp_soft_dirty(pmd_swp_mksoft_dirty(pmd)));
>> +    WARN_ON(pmd_swp_soft_dirty(pmd_swp_clear_soft_dirty(pmd)));
>> +}
>> +#else
>> +static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +}
>> +#endif
>> +#else
>> +static void __init pte_soft_dirty_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pte_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +}
>> +static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +}
>> +#endif
>> +
>> +static void __init pte_swap_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    swp_entry_t swp;
>> +    pte_t pte;
>> +
>> +    pte = pfn_pte(pfn, prot);
>> +    swp = __pte_to_swp_entry(pte);
>> +    WARN_ON(!pte_same(pte, __swp_entry_to_pte(swp)));
>> +}
>> +
>> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
>> +static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    swp_entry_t swp;
>> +    pmd_t pmd;
>> +
>> +    pmd = pfn_pmd(pfn, prot);
>> +    swp = __pmd_to_swp_entry(pmd);
>> +    WARN_ON(!pmd_same(pmd, __swp_entry_to_pmd(swp)));
>> +}
>> +#else
>> +static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +
>> +#ifdef CONFIG_MIGRATION
> 
> Same. See include/linux/swapops.h

True, #ifdef here can be dropped, done. Though will have to again add
back TRANSPARENT_HUGEPAGE to protect pfn_pmd() as explained before.

> 
>> +static void __init swap_migration_tests(struct page *page)
>> +{
>> +    swp_entry_t swp;
>> +
>> +    /*
>> +     * make_migration_entry() expects given page to be
>> +     * locked, otherwise it stumbles upon a BUG_ON().
>> +     */
>> +    __SetPageLocked(page);
>> +    swp = make_migration_entry(page, 1);
>> +    WARN_ON(!is_migration_entry(swp));
>> +    WARN_ON(!is_write_migration_entry(swp));
>> +
>> +    make_migration_entry_read(&swp);
>> +    WARN_ON(!is_migration_entry(swp));
>> +    WARN_ON(is_write_migration_entry(swp));
>> +
>> +    swp = make_migration_entry(page, 0);
>> +    WARN_ON(!is_migration_entry(swp));
>> +    WARN_ON(is_write_migration_entry(swp));
>> +    __ClearPageLocked(page);
>> +}
>> +#else
>> +static void __init swap_migration_tests(struct page *page) { }
>> +#endif
>> +
>> +#ifdef CONFIG_HUGETLB_PAGE
>> +static void __init hugetlb_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +#ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB
>> +    pte_t pte = pfn_pte(pfn, prot);
>> +
>> +    WARN_ON(!pte_huge(pte_mkhuge(pte)));
> 
> We also need tests on hugepd stuff

Sure, but lets discuss this on the other thread.

> 
>> +#endif
>> +}
>> +#else
>> +static void __init hugetlb_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +
>> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> 
> Same, see include/asm-generic/pgtable.h

This is required to protect pxx_mknotpresent() which does not have a
fall back and pfn_pmd()/pfn_pud() helpers have similar situation as
well.

> 
>> +static void __init pmd_thp_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pmd_t pmd;
>> +
>> +    /*
>> +     * pmd_trans_huge() and pmd_present() must return negative
>> +     * after MMU invalidation with pmd_mknotpresent().
>> +     */
>> +    pmd = pfn_pmd(pfn, prot);
>> +    WARN_ON(!pmd_trans_huge(pmd_mkhuge(pmd)));
>> +
>> +    /*
>> +     * Though platform specific test exclusions are not ideal,
>> +     * in this case S390 does not define pmd_mknotpresent()
>> +     * which should be tested on other platforms enabling THP.
>> +     */
>> +#ifndef CONFIG_S390
>> +    WARN_ON(pmd_trans_huge(pmd_mknotpresent(pmd)));
>> +    WARN_ON(pmd_present(pmd_mknotpresent(pmd)));
>> +#endif
> 
> Can we add a stub on S390 instead ?

Actually we dont have to. pmd_mknotpresent() is required for platforms
that do not have __HAVE_ARCH_PMDP_INVALIDATE. Hence can wrap this code
with !__HAVE_ARCH_PMDP_INVALIDATE to prevent build failures on such
platforms like s390.

> 
>> +}
>> +
>> +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
> 
> Same ?

The problem is, neither pud_mknotpresent() nor pfn_pud() have a generic
fallback definition. So will have to keep this #ifdef.

> 
>> +static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot)
>> +{
>> +    pud_t pud;
>> +
>> +    /*
>> +     * pud_trans_huge() and pud_present() must return negative
>> +     * after MMU invalidation with pud_mknotpresent().
>> +     */
>> +    pud = pfn_pud(pfn, prot);
>> +    WARN_ON(!pud_trans_huge(pud_mkhuge(pud)));
>> +    WARN_ON(pud_trans_huge(pud_mknotpresent(pud)));
>> +    WARN_ON(pud_present(pud_mknotpresent(pud)));
>> +}
>> +#else
>> +static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +#else
>> +static void __init pmd_thp_tests(unsigned long pfn, pgprot_t prot) { }
>> +static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot) { }
>> +#endif
>> +
>>   static unsigned long __init get_random_vaddr(void)
>>   {
>>       unsigned long random_vaddr, random_pages, total_user_pages;
>> @@ -302,13 +567,14 @@ static unsigned long __init get_random_vaddr(void)
>>   void __init debug_vm_pgtable(void)
>>   {
>>       struct mm_struct *mm;
>> +    struct page *page;
>>       pgd_t *pgdp;
>>       p4d_t *p4dp, *saved_p4dp;
>>       pud_t *pudp, *saved_pudp;
>>       pmd_t *pmdp, *saved_pmdp, pmd;
>>       pte_t *ptep;
>>       pgtable_t saved_ptep;
>> -    pgprot_t prot;
>> +    pgprot_t prot, protnone;
>>       phys_addr_t paddr;
>>       unsigned long vaddr, pte_aligned, pmd_aligned;
>>       unsigned long pud_aligned, p4d_aligned, pgd_aligned;
>> @@ -322,6 +588,25 @@ void __init debug_vm_pgtable(void)
>>           return;
>>       }
>>   +    /*
>> +     * swap_migration_tests() requires a dedicated page as it needs to
>> +     * be locked before creating a migration entry from it. Locking the
>> +     * page that actually maps kernel text ('start_kernel') can be real
>> +     * problematic. Lets allocate a dedicated page explicitly for this
>> +     * purpose that will be freed later.
>> +     */
>> +    page = alloc_page(GFP_KERNEL);
> 
> Can we do the page allocation and freeing in swap_migration_tests() instead ?

Although all the resources used in the helpers have been allocated in the main
function itself before being passed down and later freed. But may be just an
exception could be made for swap_migration_tests() function as the allocated
page is being exclusively used here. Later on if we need this page for some
other future tests, then will have to move it back to debug_vm_pgtable().

^ permalink raw reply

* Re: [GIT PULL] Second batch of KVM changes for Linux 5.6-rc4 (or rc5)
From: Paolo Bonzini @ 2020-03-01 23:04 UTC (permalink / raw)
  To: Linus Torvalds, Michael Ellerman
  Cc: linuxppc-dev, Linux Kernel Mailing List, KVM list
In-Reply-To: <CAHk-=wiin_LkqP2Cm5iPc5snUXYqZVoMFawZ-rjhZnawven8SA@mail.gmail.com>

On 01/03/20 22:33, Linus Torvalds wrote:
> On Sun, Mar 1, 2020 at 1:03 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>>
>> Paolo Bonzini (4):
>>       KVM: allow disabling -Werror
> 
> Honestly, this is just badly done.
> 
> You've basically made it enable -Werror only for very random
> configurations - and apparently the one you test.
> Doing things like COMPILE_TEST disables it, but so does not having
> EXPERT enabled.

Yes, I took this from the i915 Kconfig.  It's temporary, in 5.7 I am
planning to get it to just !KASAN, but for 5.6 I wanted to avoid more
breakage so I added the other restrictions.  The difference between
x86-64 and i386 is really just the frame size warnings, which Christoph
triggered because of a higher CONFIG_NR_CPUS.

(BTW, perhaps it makes sense for Sparse to have something like __nostack
for structs that contain potentially large arrays).

> I've merged this, but I wonder why you couldn't just do what I
> suggested originally?  Seriously, if you script your build tests,
> and don't even look at the results, then you might as well use
> 
>    make KCFLAGS=-Werror

I did that and I'm also adding W=1; and I threw in a smaller than
default frame size warning option too because I don't want cpumasks on
the stack anyway.  However, that wouldn't help contributors.  I'm okay
if I get W=1 or frame size warnings from patches from other
contributors, but I think it's a disservice to them that they have to
set KCFLAGS in order to avoid warnings.

> the "now it causes problems for
> random compiler versions" is a real issue again - but at least it
> wouldn't be a random kernel subsystem that happens to trigger it, it
> would be a _generic_ issue, and we'd have everybody involved when a
> compiler change introduces a new warning.

Yes, and GCC prereleases are tested with Linux, for example by doing
full Rawhide rebuilds.  If we started using -Werror by default
(including allyesconfig), they would probably report warnings early.
Same for clang.

I hope that Linux can have -Werror everywhere, or at least a
CONFIG_WERROR option that does it even if it defaults to n for a release
or more.  But I don't think we can get there without first seeing what
issues pop up in a few subsystems or arches---even before considering
new compilers---so I decided I would just try.

Paolo

> Adding the powerpc people, since they have more history with their
> somewhat less hacky one. Except that one automatically gets disabled
> by "make allmodconfig" and friends, which is also kind of pointless.

> Michael, what tends to be the triggers for people using
> PPC_DISABLE_WERROR? Do you have reports for it? Could we have a
> _generic_ option that just gets enabled by default, except it gets
> disabled by _known_ issues (like KASAN).
> 
> Being disabled for "make allmodconfig" is kind of against one of the
> _points_ of "the build should be warning-free".


^ permalink raw reply

* Re: [PATCH net-next 00/23] Clean driver, module and FW versions
From: David Miller @ 2020-03-02  3:02 UTC (permalink / raw)
  To: leon
  Cc: ajit.khaparde, madalin.bucur, kda, prashant, _govind,
	somnath.kotur, vishal, GR-everest-linux-l2, leedom, opendmb,
	bcm-kernel-feedback-list, kuba, linus.walleij, sgoutham, pkaustub,
	aelior, ulli.kroll, sburla, fmanlunas, leonro, claudiu.manoil,
	f.fainelli, sathya.perla, michael.chan, linux-arm-kernel,
	rvatsavayi, GR-Linux-NIC-Dev, fugang.duan, sriharsha.basavapatna,
	linux-parisc, siva.kallam, rmody, netdev, linux-kernel,
	leoyang.li, hsweeten, rrichter, dchickles, linuxppc-dev, skalluru,
	benve
In-Reply-To: <20200301144457.119795-1-leon@kernel.org>

From: Leon Romanovsky <leon@kernel.org>
Date: Sun,  1 Mar 2020 16:44:33 +0200

> This is second batch of the series which removes various static versions
> in favour of globaly defined Linux kernel version.

This generally looks fine to me but I'll let it sit for a few days so that
others can review.


^ permalink raw reply

* Re: [PATCH v3 0/6] implement KASLR for powerpc/fsl_booke/64
From: Jason Yan @ 2020-03-02  2:17 UTC (permalink / raw)
  To: Scott Wood, Daniel Axtens, mpe, linuxppc-dev, diana.craciun,
	christophe.leroy, benh, paulus, npiggin, keescook,
	kernel-hardening, me
  Cc: linux-kernel, zhaohongjiang
In-Reply-To: <530c49dfd97c811dc53ffc78c594d7133f7eb1e9.camel@buserror.net>



在 2020/3/1 6:54, Scott Wood 写道:
> On Sat, 2020-02-29 at 15:27 +0800, Jason Yan wrote:
>>
>> 在 2020/2/29 12:28, Scott Wood 写道:
>>> On Fri, 2020-02-28 at 14:47 +0800, Jason Yan wrote:
>>>>
>>>> 在 2020/2/28 13:53, Scott Wood 写道:
>>>>>
>>>>> I don't see any debug setting for %pK (or %p) to always print the
>>>>> actual
>>>>> address (closest is kptr_restrict=1 but that only works in certain
>>>>> contexts)... from looking at the code it seems it hashes even if kaslr
>>>>> is
>>>>> entirely disabled?  Or am I missing something?
>>>>>
>>>>
>>>> Yes, %pK (or %p) always hashes whether kaslr is disabled or not. So if
>>>> we want the real value of the address, we cannot use it. But if you only
>>>> want to distinguish if two pointers are the same, it's ok.
>>>
>>> Am I the only one that finds this a bit crazy?  If you want to lock a
>>> system
>>> down then fine, but why wage war on debugging even when there's no
>>> randomization going on?  Comparing two pointers for equality is not always
>>> adequate.
>>>
>>
>> AFAIK, %p hashing is only exist because of many legacy address printings
>> and force who really want the raw values to switch to %px or even %lx.
>> It's not the opposite of debugging. Raw address printing is not
>> forbidden, only people need to estimate the risk of adrdress leaks.
> 
> Yes, but I don't see any format specifier to switch to that will hash in a
> randomized production environment, but not in a debug or other non-randomized
> environment which seems like the ideal default for most debug output.
> 

Sorry I have no idea why there is no format specifier considered for 
switching of randomized or non-randomized environment. May they think 
that raw address should not leak in non-randomized environment too. May 
be Kees or Tobin can answer this question.

Kees? Tobin?

>>
>> Turnning to %p may not be a good idea in this situation. So
>> for the REG logs printed when dumping stack, we can disable it when
>> KASLR is open. For the REG logs in other places like show_regs(), only
>> privileged can trigger it, and they are not combind with a symbol, so
>> I think it's ok to keep them.
>>
>> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
>> index fad50db9dcf2..659c51f0739a 100644
>> --- a/arch/powerpc/kernel/process.c
>> +++ b/arch/powerpc/kernel/process.c
>> @@ -2068,7 +2068,10 @@ void show_stack(struct task_struct *tsk, unsigned
>> long *stack)
>>                   newsp = stack[0];
>>                   ip = stack[STACK_FRAME_LR_SAVE];
>>                   if (!firstframe || ip != lr) {
>> -                       printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
>> +                       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
>> +                               printk("%pS", (void *)ip);
>> +                       else
>> +                               printk("["REG"] ["REG"] %pS", sp, ip,
>> (void *)ip);
> 
> This doesn't deal with "nokaslr" on the kernel command line.  It also doesn't
> seem like something that every callsite should have to opencode, versus having
> an appropriate format specifier behaves as I described above (and I still
> don't see why that format specifier should not be "%p").
> 

Actually I still do not understand why we should print the raw value 
here. When KALLSYMS is enabled we have symbol name  and  offset like 
put_cred_rcu+0x108/0x110, and when KALLSYMS is disabled we have the raw 
address.

> -Scott
> 
> 
> 
> .
> 


^ permalink raw reply

* [PATCH] powerpc/64s/radix: Fix !SMP build
From: Nicholas Piggin @ 2020-03-02  1:04 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/mm/book3s64/radix_pgtable.c | 1 +
 arch/powerpc/mm/book3s64/radix_tlb.c     | 7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index dd1bea45325c..2a9a0cd79490 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -26,6 +26,7 @@
 #include <asm/firmware.h>
 #include <asm/powernv.h>
 #include <asm/sections.h>
+#include <asm/smp.h>
 #include <asm/trace.h>
 #include <asm/uaccess.h>
 #include <asm/ultravisor.h>
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index 03f43c924e00..758ade2c2b6e 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -587,6 +587,11 @@ void radix__local_flush_all_mm(struct mm_struct *mm)
 	preempt_enable();
 }
 EXPORT_SYMBOL(radix__local_flush_all_mm);
+
+static void __flush_all_mm(struct mm_struct *mm, bool fullmm)
+{
+	radix__local_flush_all_mm(mm);
+}
 #endif /* CONFIG_SMP */
 
 void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
@@ -777,7 +782,7 @@ void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 EXPORT_SYMBOL(radix__flush_tlb_page);
 
 #else /* CONFIG_SMP */
-#define radix__flush_all_mm radix__local_flush_all_mm
+static inline void exit_flush_lazy_tlbs(struct mm_struct *mm) { }
 #endif /* CONFIG_SMP */
 
 static void do_tlbiel_kernel(void *info)
-- 
2.23.0


^ permalink raw reply related

* Re: [Intel-gfx] [PATCH v7 00/12] Introduce CAP_PERFMON to secure system performance monitoring and observability
From: Serge Hallyn @ 2020-03-02  0:19 UTC (permalink / raw)
  To: Alexey Budankov
  Cc: linux-man, linux-doc@vger.kernel.org, Peter Zijlstra,
	joonas.lahtinen@linux.intel.com, Alexei Starovoitov,
	Stephane Eranian, Paul Mackerras, Will Deacon, Ingo Molnar,
	Andi Kleen, Jiri Olsa, Helge Deller, Igor Lubashev, James Morris,
	oprofile-list, Stephen Smalley, selinux@vger.kernel.org,
	intel-gfx@lists.freedesktop.org, Arnaldo Carvalho de Melo,
	Thomas Gleixner, linux-arm-kernel, linux-parisc@vger.kernel.org,
	linux-kernel, linux-security-module@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <3ae0bed5-204e-de81-7647-5f0d8106cd67@linux.intel.com>

Thanks, this looks good to me, in keeping with the CAP_SYSLOG break.

Acked-by: Serge E. Hallyn <serge@hallyn.com>

for the set.

James/Ingo/Peter, if noone has remaining objections, whose branch
should these go in through?

thanks,
-serge

On Tue, Feb 25, 2020 at 12:55:54PM +0300, Alexey Budankov wrote:
> 
> Hi,
> 
> Is there anything else I could do in order to move the changes forward
> or is something still missing from this patch set?
> Could you please share you mind?
> 
> Thanks,
> Alexey
> 
> On 17.02.2020 11:02, Alexey Budankov wrote:
> > 
> > Currently access to perf_events, i915_perf and other performance
> > monitoring and observability subsystems of the kernel is open only for
> > a privileged process [1] with CAP_SYS_ADMIN capability enabled in the
> > process effective set [2].
> > 
> > This patch set introduces CAP_PERFMON capability designed to secure
> > system performance monitoring and observability operations so that
> > CAP_PERFMON would assist CAP_SYS_ADMIN capability in its governing role
> > for performance monitoring and observability subsystems of the kernel.
> > 
> > CAP_PERFMON intends to harden system security and integrity during
> > performance monitoring and observability operations by decreasing attack
> > surface that is available to a CAP_SYS_ADMIN privileged process [2].
> > Providing the access to performance monitoring and observability
> > operations under CAP_PERFMON capability singly, without the rest of
> > CAP_SYS_ADMIN credentials, excludes chances to misuse the credentials
> > and makes the operation more secure. Thus, CAP_PERFMON implements the
> > principal of least privilege for performance monitoring and
> > observability operations (POSIX IEEE 1003.1e: 2.2.2.39 principle of
> > least privilege: A security design principle that states that a process
> > or program be granted only those privileges (e.g., capabilities)
> > necessary to accomplish its legitimate function, and only for the time
> > that such privileges are actually required)
> > 
> > CAP_PERFMON intends to meet the demand to secure system performance
> > monitoring and observability operations for adoption in security
> > sensitive, restricted, multiuser production environments (e.g. HPC
> > clusters, cloud and virtual compute environments), where root or
> > CAP_SYS_ADMIN credentials are not available to mass users of a system,
> > and securely unblock accessibility of system performance monitoring and
> > observability operations beyond root and CAP_SYS_ADMIN use cases.
> > 
> > CAP_PERFMON intends to take over CAP_SYS_ADMIN credentials related to
> > system performance monitoring and observability operations and balance
> > amount of CAP_SYS_ADMIN credentials following the recommendations in
> > the capabilities man page [2] for CAP_SYS_ADMIN: "Note: this capability
> > is overloaded; see Notes to kernel developers, below." For backward
> > compatibility reasons access to system performance monitoring and
> > observability subsystems of the kernel remains open for CAP_SYS_ADMIN
> > privileged processes but CAP_SYS_ADMIN capability usage for secure
> > system performance monitoring and observability operations is
> > discouraged with respect to the designed CAP_PERFMON capability.
> > 
> > Possible alternative solution to this system security hardening,
> > capabilities balancing task of making performance monitoring and
> > observability operations more secure and accessible could be to use
> > the existing CAP_SYS_PTRACE capability to govern system performance
> > monitoring and observability subsystems. However CAP_SYS_PTRACE
> > capability still provides users with more credentials than are
> > required for secure performance monitoring and observability
> > operations and this excess is avoided by the designed CAP_PERFMON.
> > 
> > Although software running under CAP_PERFMON can not ensure avoidance of
> > related hardware issues, the software can still mitigate those issues
> > following the official hardware issues mitigation procedure [3]. The
> > bugs in the software itself can be fixed following the standard kernel
> > development process [4] to maintain and harden security of system
> > performance monitoring and observability operations. Finally, the patch
> > set is shaped in the way that simplifies backtracking procedure of
> > possible induced issues [5] as much as possible.
> > 
> > The patch set is for tip perf/core repository:
> > git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip perf/core
> > sha1: fdb64822443ec9fb8c3a74b598a74790ae8d2e22
> > 
> > ---
> > Changes in v7:
> > - updated and extended kernel.rst and perf-security.rst documentation 
> >   files with the information about CAP_PERFMON capability and its use cases
> > - documented the case of double audit logging of CAP_PERFMON and CAP_SYS_ADMIN
> >   capabilities on a SELinux enabled system
> > Changes in v6:
> > - avoided noaudit checks in perfmon_capable() to explicitly advertise
> >   CAP_PERFMON usage thru audit logs to secure system performance
> >   monitoring and observability
> > Changes in v5:
> > - renamed CAP_SYS_PERFMON to CAP_PERFMON
> > - extended perfmon_capable() with noaudit checks
> > Changes in v4:
> > - converted perfmon_capable() into an inline function
> > - made perf_events kprobes, uprobes, hw breakpoints and namespaces data
> >   available to CAP_SYS_PERFMON privileged processes
> > - applied perfmon_capable() to drivers/perf and drivers/oprofile
> > - extended __cmd_ftrace() with support of CAP_SYS_PERFMON
> > Changes in v3:
> > - implemented perfmon_capable() macros aggregating required capabilities
> >   checks
> > Changes in v2:
> > - made perf_events trace points available to CAP_SYS_PERFMON privileged
> >   processes
> > - made perf_event_paranoid_check() treat CAP_SYS_PERFMON equally to
> >   CAP_SYS_ADMIN
> > - applied CAP_SYS_PERFMON to i915_perf, bpf_trace, powerpc and parisc
> >   system performance monitoring and observability related subsystems
> > 
> > ---
> > Alexey Budankov (12):
> >   capabilities: introduce CAP_PERFMON to kernel and user space
> >   perf/core: open access to the core for CAP_PERFMON privileged process
> >   perf/core: open access to probes for CAP_PERFMON privileged process
> >   perf tool: extend Perf tool with CAP_PERFMON capability support
> >   drm/i915/perf: open access for CAP_PERFMON privileged process
> >   trace/bpf_trace: open access for CAP_PERFMON privileged process
> >   powerpc/perf: open access for CAP_PERFMON privileged process
> >   parisc/perf: open access for CAP_PERFMON privileged process
> >   drivers/perf: open access for CAP_PERFMON privileged process
> >   drivers/oprofile: open access for CAP_PERFMON privileged process
> >   doc/admin-guide: update perf-security.rst with CAP_PERFMON information
> >   doc/admin-guide: update kernel.rst with CAP_PERFMON information
> > 
> >  Documentation/admin-guide/perf-security.rst | 65 +++++++++++++--------
> >  Documentation/admin-guide/sysctl/kernel.rst | 16 +++--
> >  arch/parisc/kernel/perf.c                   |  2 +-
> >  arch/powerpc/perf/imc-pmu.c                 |  4 +-
> >  drivers/gpu/drm/i915/i915_perf.c            | 13 ++---
> >  drivers/oprofile/event_buffer.c             |  2 +-
> >  drivers/perf/arm_spe_pmu.c                  |  4 +-
> >  include/linux/capability.h                  |  4 ++
> >  include/linux/perf_event.h                  |  6 +-
> >  include/uapi/linux/capability.h             |  8 ++-
> >  kernel/events/core.c                        |  6 +-
> >  kernel/trace/bpf_trace.c                    |  2 +-
> >  security/selinux/include/classmap.h         |  4 +-
> >  tools/perf/builtin-ftrace.c                 |  5 +-
> >  tools/perf/design.txt                       |  3 +-
> >  tools/perf/util/cap.h                       |  4 ++
> >  tools/perf/util/evsel.c                     | 10 ++--
> >  tools/perf/util/util.c                      |  1 +
> >  18 files changed, 98 insertions(+), 61 deletions(-)
> > 
> > ---
> > Validation (Intel Skylake, 8 cores, Fedora 29, 5.5.0-rc3+, x86_64):
> > 
> > libcap library [6], [7], [8] and Perf tool can be used to apply
> > CAP_PERFMON capability for secure system performance monitoring and
> > observability beyond the scope permitted by the system wide
> > perf_event_paranoid kernel setting [9] and below are the steps for
> > evaluation:
> > 
> >   - patch, build and boot the kernel
> >   - patch, build Perf tool e.g. to /home/user/perf
> >   ...
> >   # git clone git://git.kernel.org/pub/scm/libs/libcap/libcap.git libcap
> >   # pushd libcap
> >   # patch libcap/include/uapi/linux/capabilities.h with [PATCH 1]
> >   # make
> >   # pushd progs
> >   # ./setcap "cap_perfmon,cap_sys_ptrace,cap_syslog=ep" /home/user/perf
> >   # ./setcap -v "cap_perfmon,cap_sys_ptrace,cap_syslog=ep" /home/user/perf
> >   /home/user/perf: OK
> >   # ./getcap /home/user/perf
> >   /home/user/perf = cap_sys_ptrace,cap_syslog,cap_perfmon+ep
> >   # echo 2 > /proc/sys/kernel/perf_event_paranoid
> >   # cat /proc/sys/kernel/perf_event_paranoid 
> >   2
> >   ...
> >   $ /home/user/perf top
> >     ... works as expected ...
> >   $ cat /proc/`pidof perf`/status
> >   Name:	perf
> >   Umask:	0002
> >   State:	S (sleeping)
> >   Tgid:	2958
> >   Ngid:	0
> >   Pid:	2958
> >   PPid:	9847
> >   TracerPid:	0
> >   Uid:	500	500	500	500
> >   Gid:	500	500	500	500
> >   FDSize:	256
> >   ...
> >   CapInh:	0000000000000000
> >   CapPrm:	0000004400080000
> >   CapEff:	0000004400080000 => 01000100 00000000 00001000 00000000 00000000
> >                                      cap_perfmon,cap_sys_ptrace,cap_syslog
> >   CapBnd:	0000007fffffffff
> >   CapAmb:	0000000000000000
> >   NoNewPrivs:	0
> >   Seccomp:	0
> >   Speculation_Store_Bypass:	thread vulnerable
> >   Cpus_allowed:	ff
> >   Cpus_allowed_list:	0-7
> >   ...
> > 
> > Usage of cap_perfmon effectively avoids unused credentials excess:
> > 
> > - with cap_sys_admin:
> >   CapEff:	0000007fffffffff => 01111111 11111111 11111111 11111111 11111111
> > 
> > - with cap_perfmon:
> >   CapEff:	0000004400080000 => 01000100 00000000 00001000 00000000 00000000
> >                                     38   34               19
> >                                perfmon   syslog           sys_ptrace
> > 
> > ---
> > [1] https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html
> > [2] http://man7.org/linux/man-pages/man7/capabilities.7.html
> > [3] https://www.kernel.org/doc/html/latest/process/embargoed-hardware-issues.html
> > [4] https://www.kernel.org/doc/html/latest/admin-guide/security-bugs.html
> > [5] https://www.kernel.org/doc/html/latest/process/management-style.html#decisions
> > [6] http://man7.org/linux/man-pages/man8/setcap.8.html
> > [7] https://git.kernel.org/pub/scm/libs/libcap/libcap.git
> > [8] https://sites.google.com/site/fullycapable/, posix_1003.1e-990310.pdf
> > [9] http://man7.org/linux/man-pages/man2/perf_event_open.2.html
> > 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* RE: [PATCH v3 25/27] powerpc/powernv/pmem: Expose the serial number in sysfs
From: Alastair D'Silva @ 2020-03-01 23:42 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Donnellan
  Cc: Madhavan Srinivasan, Alexey Kardashevskiy, Masahiro Yamada,
	Oliver O'Halloran, Mauro Carvalho Chehab, Ira Weiny,
	Thomas Gleixner, Rob Herring, Dave Jiang, linux-nvdimm,
	Aneesh Kumar K . V, Krzysztof Kozlowski, Anju T Sudhakar,
	Mahesh Salgaonkar, Arnd Bergmann, Greg Kurz, Nicholas Piggin,
	Cédric Le Goater, Dan Williams, Hari Bathini, linux-mm,
	linux-kernel, Vishal Verma, Frederic Barrat, Paul Mackerras,
	Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200228071520.GA2897773@kroah.com>

On Fri, 2020-02-28 at 08:15 +0100, Greg Kroah-Hartman wrote:
> On Fri, Feb 28, 2020 at 05:25:31PM +1100, Andrew Donnellan wrote:
> > On 21/2/20 2:27 pm, Alastair D'Silva wrote:
> > > +int ocxlpmem_sysfs_add(struct ocxlpmem *ocxlpmem)
> > > +{
> > > +	int i, rc;
> > > +
> > > +	for (i = 0; i < ARRAY_SIZE(attrs); i++) {
> > > +		rc = device_create_file(&ocxlpmem->dev, &attrs[i]);
> > > +		if (rc) {
> > > +			for (; --i >= 0;)
> > > +				device_remove_file(&ocxlpmem->dev,
> > > &attrs[i]);
> > 
> > I'd rather avoid weird for loop constructs if possible.
> > 
> > Is it actually dangerous to call device_remove_file() on an attr
> > that hasn't
> > been added? If not then I'd rather define an err: label and loop
> > over the
> > whole array there.
> 
> None of this should be used at all, just use attribute groups
> properly
> and the driver core will handle this all for you.
> 
> device_create/remove_file should never be called by anyone anymore if
> at all
> possible.
> 
> thanks,
> 
> greg k-h


Thanks, I'll rework it to use the .groups member of struct pci_driver.

-- 
Alastair D'Silva
Open Source Developer
Linux Technology Centre, IBM Australia
mob: 0423 762 819


^ permalink raw reply

* Re: [GIT PULL] Second batch of KVM changes for Linux 5.6-rc4 (or rc5)
From: Linus Torvalds @ 2020-03-01 21:33 UTC (permalink / raw)
  To: Paolo Bonzini, Michael Ellerman
  Cc: linuxppc-dev, Linux Kernel Mailing List, KVM list
In-Reply-To: <1583089390-36084-1-git-send-email-pbonzini@redhat.com>

On Sun, Mar 1, 2020 at 1:03 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> Paolo Bonzini (4):
>       KVM: allow disabling -Werror

Honestly, this is just badly done.

You've basically made it enable -Werror only for very random
configurations - and apparently the one you test.

Doing things like COMPILE_TEST disables it, but so does not having
EXPERT enabled.

So it looks entirely ad-hoc and makes very little sense. At least the
"with KASAN, disable this" part makes sense, since that's a known
source or warnings. But everything else looks very random.

I've merged this, but I wonder why you couldn't just do what I
suggested originally?

Seriously, if you script your build tests, and don't even look at the
results, then you might as well use

   make KCFLAGS=-Werror

instead of having this kind of completely random option that has
almost no logic to it at all.

And if you depend entirely on random build infrastructure like the
0day bot etc, this likely _is_ going to break when it starts using a
new gcc version, or when it starts testing using clang, or whatever.
So then we end up with another odd random situation where now kvm (and
only kvm) will fail those builds just because they are automated.

Yes, as I said in that original thread, I'd love to do -Werror in
general, at which point it wouldn't be some random ad-hoc kvm special
case for some random option. But the "now it causes problems for
random compiler versions" is a real issue again - but at least it
wouldn't be a random kernel subsystem that happens to trigger it, it
would be a _generic_ issue, and we'd have everybody involved when a
compiler change introduces a new warning.

I've pulled this for now, but I really think it's a horrible hack, and
it's just done entirely wrong.

Adding the powerpc people, since they have more history with their
somewhat less hacky one. Except that one automatically gets disabled
by "make allmodconfig" and friends, which is also kind of pointless.

Michael, what tends to be the triggers for people using
PPC_DISABLE_WERROR? Do you have reports for it? Could we have a
_generic_ option that just gets enabled by default, except it gets
disabled by _known_ issues (like KASAN).

Being disabled for "make allmodconfig" is kind of against one of the
_points_ of "the build should be warning-free".

               Linus

^ permalink raw reply

* [Bug 199471] [Bisected][Regression] windfarm_pm* no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set
From: bugzilla-daemon @ 2020-03-01 20:10 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=199471

Erhard F. (erhard_f@mailbox.org) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
 Attachment #275509|0                           |1
        is obsolete|                            |

--- Comment #14 from Erhard F. (erhard_f@mailbox.org) ---
Created attachment 287749
  --> https://bugzilla.kernel.org/attachment.cgi?id=287749&action=edit
dmesg (kernel 4.17, PowerMac G5 11,2)

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* [Bug 199471] [Bisected][Regression] windfarm_pm* no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set
From: bugzilla-daemon @ 2020-03-01 20:10 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=199471

--- Comment #13 from Erhard F. (erhard_f@mailbox.org) ---
Created attachment 287747
  --> https://bugzilla.kernel.org/attachment.cgi?id=287747&action=edit
kernel .config (kernel 4.17, PowerMac G5 11,2)

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* [Bug 199471] [Bisected][Regression] windfarm_pm* no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set
From: bugzilla-daemon @ 2020-03-01 20:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=199471

Erhard F. (erhard_f@mailbox.org) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
 Attachment #275507|0                           |1
        is obsolete|                            |

--- Comment #12 from Erhard F. (erhard_f@mailbox.org) ---
Created attachment 287745
  --> https://bugzilla.kernel.org/attachment.cgi?id=287745&action=edit
dmesg (kernel 4.16.18, PowerMac G5 11,2)

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* [Bug 199471] [Bisected][Regression] windfarm_pm* no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set
From: bugzilla-daemon @ 2020-03-01 19:46 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=199471

--- Comment #11 from Erhard F. (erhard_f@mailbox.org) ---
(In reply to Wolfram Sang from comment #8)
> "This has been quite nice since 4.?.x up to 4.16.x as you only need
> CONFIG_I2C_POWERMAC=y which selects the proper windfarm_pmXX at boot time."
> 
> I can't find that in the code. Are you sure i2c-powermac requested that
> module?
I guess so 'cause if I build i2c_powermac as a module and manually modprobe it,
all the relevant windfarm modules get pulled in. But not before.

 # modprobe -v i2c_powermac
insmod
/lib/modules/4.16.18-PowerMacG5+/kernel/drivers/i2c/busses/i2c-powermac.ko 
 # dmesg | tail
[  150.181478]  11
[  150.182851]  0
[  150.184220]  0

[  150.626685] windfarm: Backside control loop started.
[  150.690132] windfarm: Slots control loop started.
[  150.794843] i2c i2c-0: master_xfer[0] W, addr=0x50, len=1
[  150.796467] i2c i2c-0: master_xfer[1] R, addr=0x50, len=8
[  150.801851] i2c i2c-0: NAK from device addr 0x50 msg #0
[  150.807758] windfarm: Drive bay control loop started.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* [Bug 199471] windfarm_pm72 no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set (regression)
From: bugzilla-daemon @ 2020-03-01 19:17 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=199471

--- Comment #10 from Erhard F. (erhard_f@mailbox.org) ---
Created attachment 287743
  --> https://bugzilla.kernel.org/attachment.cgi?id=287743&action=edit
bisect.log

Finally checked on that bug again and bisected it. The offending commit is:

# git bisect bad | tee -a ~/bisect02.log 
af503716ac1444db61d80cb6d17cfe62929c21df is the first bad commit
commit af503716ac1444db61d80cb6d17cfe62929c21df
Author: Javier Martinez Canillas <javierm@redhat.com>
Date:   Sun Dec 3 22:40:50 2017 +0100

    i2c: core: report OF style module alias for devices registered via OF

    The buses should honor the firmware interface used to register the device,
    but the I2C core reports a MODALIAS of the form i2c:<device> even for I2C
    devices registered via OF.

    This means that user-space will never get an OF stype uevent MODALIAS even
    when the drivers modules contain aliases exported from both the I2C and OF
    device ID tables. For example, an Atmel maXTouch Touchscreen registered by
    a DT node with compatible "atmel,maxtouch" has the following module alias:

    $ cat /sys/class/i2c-adapter/i2c-8/8-004b/modalias
    i2c:maxtouch

    So udev won't be able to auto-load a module for an OF-only device driver.
    Many OF-only drivers duplicate the OF device ID table entries in an I2C ID
    table only has a workaround for how the I2C core reports the module alias.

    This patch changes the I2C core to report an OF related MODALIAS uevent if
    the device was registered via OF. So for the previous example, after this
    patch, the reported MODALIAS for the Atmel maXTouch will be the following:

    $ cat /sys/class/i2c-adapter/i2c-8/8-004b/modalias
    of:NtrackpadT<NULL>Catmel,maxtouch

    NOTE: This patch may break out-of-tree drivers that were relying on this
          behavior, and only had an I2C device ID table even when the device
          was registered via OF. There are no remaining drivers in mainline
          that do this, but out-of-tree drivers have to be fixed and define
          a proper OF device ID table to have module auto-loading working.

    Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
    Tested-by: Dmitry Mastykin <mastichi@gmail.com>
    Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

 drivers/i2c/i2c-core-base.c | 8 ++++++++
 1 file changed, 8 insertions(+)

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* [Bug 199471] windfarm_pm72 no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set (regression)
From: bugzilla-daemon @ 2020-03-01 19:14 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=199471

Erhard F. (erhard_f@mailbox.org) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
 Attachment #275503|0                           |1
        is obsolete|                            |
 Attachment #275505|0                           |1
        is obsolete|                            |

--- Comment #9 from Erhard F. (erhard_f@mailbox.org) ---
Created attachment 287741
  --> https://bugzilla.kernel.org/attachment.cgi?id=287741&action=edit
kernel .config (kernel 4.16, PowerMac G5 11,2)

With the attached kernel .config the G5 7,3 and the G5 11,2 automatically load
the suitable windfarm module on kernel <4.17. Starting from kernel 4.17
windfarm core needs to be CONFIG_WINDFARM=y to automacitally load the suitable
windfarm module, CONFIG_WINDFARM=m is no longer sufficient.

Needed for 4.16.x to automatically load the suitable windfarm module:
# grep -i wind .config
CONFIG_WINDFARM=m
CONFIG_WINDFARM_PM81=m
CONFIG_WINDFARM_PM72=m
CONFIG_WINDFARM_RM31=m
CONFIG_WINDFARM_PM91=m
CONFIG_WINDFARM_PM112=m
CONFIG_WINDFARM_PM121=m

Needed for >=4.17.x to automatically load the suitable windfarm module:
# grep -i wind .config
CONFIG_WINDFARM=y
CONFIG_WINDFARM_PM81=m
CONFIG_WINDFARM_PM72=m
CONFIG_WINDFARM_RM31=m
CONFIG_WINDFARM_PM91=m
CONFIG_WINDFARM_PM112=m
CONFIG_WINDFARM_PM121=m

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox