* [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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox