summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/include/uapi/linux/perf_event.h4
-rw-r--r--tools/pci/pcitest.c1
-rw-r--r--tools/perf/Documentation/intel-pt.txt2
-rw-r--r--tools/perf/Documentation/perf-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt5
-rw-r--r--tools/perf/Documentation/perf-report.txt1
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/builtin-mem.c97
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-script.c15
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-trace.c39
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/frontend.json7
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json120
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pipeline.json7
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pmc.json7
-rw-r--r--tools/perf/tests/code-reading.c5
-rw-r--r--tools/perf/tests/sample-parsing.c6
-rw-r--r--tools/perf/ui/browsers/annotate.c3
-rw-r--r--tools/perf/ui/browsers/hists.c8
-rw-r--r--tools/perf/ui/stdio/hist.c10
-rw-r--r--tools/perf/util/callchain.c49
-rw-r--r--tools/perf/util/callchain.h9
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evsel.c19
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/hist.c4
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/machine.c96
-rw-r--r--tools/perf/util/parse-events.c24
-rw-r--r--tools/perf/util/session.c3
-rw-r--r--tools/perf/util/sort.c42
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/syscalltbl.c33
-rw-r--r--tools/perf/util/syscalltbl.h3
-rw-r--r--tools/testing/nvdimm/test/nfit.c4
-rw-r--r--tools/testing/selftests/bpf/test_maps.c51
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test.c4
-rw-r--r--tools/testing/selftests/capabilities/test_execve.c193
-rw-r--r--tools/testing/selftests/capabilities/validate_cap.c24
-rwxr-xr-xtools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh14
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest51
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi.c8
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c3
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c5
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c6
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_timeout.c5
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c3
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_wouldblock.c3
-rw-r--r--tools/testing/selftests/futex/include/logging.h20
-rw-r--r--tools/testing/selftests/kcmp/kcmp_test.c60
-rw-r--r--tools/testing/selftests/kselftest.h30
-rw-r--r--tools/testing/selftests/kselftest_harness.h39
-rw-r--r--tools/testing/selftests/lib.mk17
-rw-r--r--tools/testing/selftests/memfd/Makefile2
-rw-r--r--tools/testing/selftests/memfd/fuse_test.c2
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c372
-rw-r--r--tools/testing/selftests/memfd/run_tests.sh69
-rw-r--r--tools/testing/selftests/nsfs/config3
-rw-r--r--tools/testing/selftests/powerpc/ptrace/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S2
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c12
-rw-r--r--tools/testing/selftests/pstore/.gitignore2
-rw-r--r--tools/testing/selftests/ptp/Makefile1
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c2
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c53
-rw-r--r--tools/testing/selftests/splice/.gitignore1
-rw-r--r--tools/testing/selftests/splice/Makefile5
-rw-r--r--tools/testing/selftests/sync/sync_test.c71
-rw-r--r--tools/testing/selftests/sync/synctest.h3
-rw-r--r--tools/testing/selftests/timers/Makefile23
-rw-r--r--tools/testing/selftests/timers/adjtick.c11
-rw-r--r--tools/testing/selftests/timers/alarmtimer-suspend.c11
-rw-r--r--tools/testing/selftests/timers/change_skew.c11
-rw-r--r--tools/testing/selftests/timers/clocksource-switch.c13
-rw-r--r--tools/testing/selftests/timers/inconsistency-check.c11
-rw-r--r--tools/testing/selftests/timers/leap-a-day.c28
-rw-r--r--tools/testing/selftests/timers/leapcrash.c13
-rw-r--r--tools/testing/selftests/timers/mqueue-lat.c11
-rw-r--r--tools/testing/selftests/timers/nanosleep.c11
-rw-r--r--tools/testing/selftests/timers/nsleep-lat.c11
-rw-r--r--tools/testing/selftests/timers/raw_skew.c12
-rw-r--r--tools/testing/selftests/timers/rtctest.c7
-rw-r--r--tools/testing/selftests/timers/set-2038.c11
-rw-r--r--tools/testing/selftests/timers/set-tai.c11
-rw-r--r--tools/testing/selftests/timers/set-timer-lat.c11
-rw-r--r--tools/testing/selftests/timers/set-tz.c11
-rw-r--r--tools/testing/selftests/timers/skew_consistency.c11
-rw-r--r--tools/testing/selftests/timers/threadtest.c12
-rw-r--r--tools/testing/selftests/timers/valid-adjtimex.c11
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c279
-rw-r--r--tools/testing/selftests/watchdog/watchdog-test.c190
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c3
-rw-r--r--tools/testing/selftests/x86/protection_keys.c13
98 files changed, 1639 insertions, 877 deletions
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 2a37ae925d85..140ae638cfd6 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -139,8 +139,9 @@ enum perf_event_sample_format {
PERF_SAMPLE_IDENTIFIER = 1U << 16,
PERF_SAMPLE_TRANSACTION = 1U << 17,
PERF_SAMPLE_REGS_INTR = 1U << 18,
+ PERF_SAMPLE_PHYS_ADDR = 1U << 19,
- PERF_SAMPLE_MAX = 1U << 19, /* non-ABI */
+ PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
};
/*
@@ -814,6 +815,7 @@ enum perf_event_type {
* { u64 transaction; } && PERF_SAMPLE_TRANSACTION
* { u64 abi; # enum perf_sample_regs_abi
* u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
+ * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
* };
*/
PERF_RECORD_SAMPLE = 9,
diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c
index ad54a58d7dda..9074b477bff0 100644
--- a/tools/pci/pcitest.c
+++ b/tools/pci/pcitest.c
@@ -173,6 +173,7 @@ usage:
"\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n"
"\t-b <bar num> BAR test (bar number between 0..5)\n"
"\t-m <msi num> MSI test (msi number between 1..32)\n"
+ "\t-l Legacy IRQ test\n"
"\t-r Read buffer test\n"
"\t-w Write buffer test\n"
"\t-c Copy buffer test\n"
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index ab1b0825130a..76971d2e4164 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -873,7 +873,7 @@ amended to take the number of elements as a parameter.
$ cat ~/.perfconfig
[intel-pt]
- mispred-all
+ mispred-all = on
$ perf record -e intel_pt//u ./sort 3000
Bubble sorting array of 3000 elements
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 73496320fca3..4be08a1e3f8d 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -59,6 +59,10 @@ OPTIONS
--ldload::
Specify desired latency for loads event.
+-p::
+--phys-data::
+ Record/Report sample physical addresses
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 9bdea047c5db..e397453e5a46 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -249,7 +249,10 @@ OPTIONS
-d::
--data::
- Record the sample addresses.
+ Record the sample virtual addresses.
+
+--phys-data::
+ Record the sample physical addresses.
-T::
--timestamp::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9fa84617181e..383a98d992ed 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -137,6 +137,7 @@ OPTIONS
- mem: type of memory access for the data at the time of the sample
- snoop: type of snoop (if any) for the data at the time of the sample
- dcacheline: the cacheline the data address is on at the time of the sample
+ - phys_daddr: physical address of data being executed on at the time of sample
And the default sort keys are changed to local_weight, mem, sym, dso,
symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 5ee8796be96e..18dfcfa38454 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff,
- callindent, insn, insnlen, synth.
+ callindent, insn, insnlen, synth, phys_addr.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index c1e3288a2dfb..d53bea6bd571 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -37,7 +37,7 @@ OPTIONS
--expr::
--event::
List of syscalls and other perf events (tracepoints, HW cache events,
- etc) to show.
+ etc) to show. Globbing is supported, e.g.: "epoll_*", "*msg*", etc.
See 'perf list' for a complete list of events.
Prefixing with ! shows all syscalls but the ones specified. You may
need to escape it.
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index e001c0290793..0f15634ef82c 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -23,6 +23,7 @@ struct perf_mem {
bool hide_unresolved;
bool dump_raw;
bool force;
+ bool phys_addr;
int operation;
const char *cpu_list;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -101,6 +102,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
rec_argv[i++] = "-d";
+ if (mem->phys_addr)
+ rec_argv[i++] = "--phys-data";
+
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
if (!perf_mem_events[j].record)
continue;
@@ -161,30 +165,60 @@ dump_raw_samples(struct perf_tool *tool,
if (al.map != NULL)
al.map->dso->hit = 1;
- if (symbol_conf.field_sep) {
- fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64
- "%s0x%"PRIx64"%s%s:%s\n";
+ if (mem->phys_addr) {
+ if (symbol_conf.field_sep) {
+ fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s0x%016"PRIx64
+ "%s%"PRIu64"%s0x%"PRIx64"%s%s:%s\n";
+ } else {
+ fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
+ "%s0x%016"PRIx64"%s%5"PRIu64"%s0x%06"PRIx64
+ "%s%s:%s\n";
+ symbol_conf.field_sep = " ";
+ }
+
+ printf(fmt,
+ sample->pid,
+ symbol_conf.field_sep,
+ sample->tid,
+ symbol_conf.field_sep,
+ sample->ip,
+ symbol_conf.field_sep,
+ sample->addr,
+ symbol_conf.field_sep,
+ sample->phys_addr,
+ symbol_conf.field_sep,
+ sample->weight,
+ symbol_conf.field_sep,
+ sample->data_src,
+ symbol_conf.field_sep,
+ al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
+ al.sym ? al.sym->name : "???");
} else {
- fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
- "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
- symbol_conf.field_sep = " ";
- }
+ if (symbol_conf.field_sep) {
+ fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64
+ "%s0x%"PRIx64"%s%s:%s\n";
+ } else {
+ fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
+ "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
+ symbol_conf.field_sep = " ";
+ }
- printf(fmt,
- sample->pid,
- symbol_conf.field_sep,
- sample->tid,
- symbol_conf.field_sep,
- sample->ip,
- symbol_conf.field_sep,
- sample->addr,
- symbol_conf.field_sep,
- sample->weight,
- symbol_conf.field_sep,
- sample->data_src,
- symbol_conf.field_sep,
- al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
- al.sym ? al.sym->name : "???");
+ printf(fmt,
+ sample->pid,
+ symbol_conf.field_sep,
+ sample->tid,
+ symbol_conf.field_sep,
+ sample->ip,
+ symbol_conf.field_sep,
+ sample->addr,
+ symbol_conf.field_sep,
+ sample->weight,
+ symbol_conf.field_sep,
+ sample->data_src,
+ symbol_conf.field_sep,
+ al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
+ al.sym ? al.sym->name : "???");
+ }
out_put:
addr_location__put(&al);
return 0;
@@ -224,7 +258,10 @@ static int report_raw_events(struct perf_mem *mem)
if (ret < 0)
goto out_delete;
- printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
+ if (mem->phys_addr)
+ printf("# PID, TID, IP, ADDR, PHYS ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
+ else
+ printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
ret = perf_session__process_events(session);
@@ -254,9 +291,16 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
* there is no weight (cost) associated with stores, so don't print
* the column
*/
- if (!(mem->operation & MEM_OPERATION_LOAD))
- rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
- "dso_daddr,tlb,locked";
+ if (!(mem->operation & MEM_OPERATION_LOAD)) {
+ if (mem->phys_addr)
+ rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
+ "dso_daddr,tlb,locked,phys_daddr";
+ else
+ rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
+ "dso_daddr,tlb,locked";
+ } else if (mem->phys_addr)
+ rep_argv[i++] = "--sort=local_weight,mem,sym,dso,symbol_daddr,"
+ "dso_daddr,snoop,tlb,locked,phys_daddr";
for (j = 1; j < argc; j++, i++)
rep_argv[i] = argv[j];
@@ -373,6 +417,7 @@ int cmd_mem(int argc, const char **argv)
"separator for columns, no spaces will be added"
" between columns '.' is reserved."),
OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
+ OPT_BOOLEAN('p', "phys-data", &mem.phys_addr, "Record/Report sample physical addresses"),
OPT_END()
};
const char *const mem_subcommands[] = { "record", "report", NULL };
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 36d7117a7562..56f8142ff97f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1604,6 +1604,8 @@ static struct option __record_options[] = {
OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
"per thread counts"),
OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
+ OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
+ "Record the sample physical addresses"),
OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
&record.opts.sample_time_set,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 378f76cdf923..3d4c3b5e1868 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -87,6 +87,7 @@ enum perf_output_field {
PERF_OUTPUT_BRSTACKINSN = 1U << 23,
PERF_OUTPUT_BRSTACKOFF = 1U << 24,
PERF_OUTPUT_SYNTH = 1U << 25,
+ PERF_OUTPUT_PHYS_ADDR = 1U << 26,
};
struct output_option {
@@ -119,6 +120,7 @@ struct output_option {
{.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
{.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
{.str = "synth", .field = PERF_OUTPUT_SYNTH},
+ {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
};
enum {
@@ -175,7 +177,8 @@ static struct {
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
- PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT,
+ PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT |
+ PERF_OUTPUT_PHYS_ADDR,
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
},
@@ -382,6 +385,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
PERF_OUTPUT_IREGS))
return -EINVAL;
+ if (PRINT_FIELD(PHYS_ADDR) &&
+ perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
+ PERF_OUTPUT_PHYS_ADDR))
+ return -EINVAL;
+
return 0;
}
@@ -1446,6 +1454,9 @@ static void process_event(struct perf_script *script,
if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
print_sample_bpf_output(sample);
print_insn(sample, attr, thread, machine);
+
+ if (PRINT_FIELD(PHYS_ADDR))
+ printf("%16" PRIx64, sample->phys_addr);
printf("\n");
}
@@ -2729,7 +2740,7 @@ int cmd_script(int argc, const char **argv)
"Valid types: hw,sw,trace,raw,synth. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags,"
- "bpf-output,callindent,insn,insnlen,brstackinsn,synth",
+ "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr",
parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 866da7aa54bf..85e992d9215b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1257,7 +1257,7 @@ static bool collect_data(struct perf_evsel *counter,
if (counter->merged_stat)
return false;
cb(counter, data, true);
- if (!no_merge)
+ if (!no_merge && counter->auto_merge_stats)
collect_all_aliases(counter, cb, data);
return true;
}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d59cdadf3a79..771ddab94bb0 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1261,6 +1261,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
static int trace__validate_ev_qualifier(struct trace *trace)
{
int err = 0, i;
+ size_t nr_allocated;
struct str_node *pos;
trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
@@ -1274,13 +1275,18 @@ static int trace__validate_ev_qualifier(struct trace *trace)
goto out;
}
+ nr_allocated = trace->ev_qualifier_ids.nr;
i = 0;
strlist__for_each_entry(pos, trace->ev_qualifier) {
const char *sc = pos->s;
- int id = syscalltbl__id(trace->sctbl, sc);
+ int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
if (id < 0) {
+ id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
+ if (id >= 0)
+ goto matches;
+
if (err == 0) {
fputs("Error:\tInvalid syscall ", trace->output);
err = -EINVAL;
@@ -1290,13 +1296,37 @@ static int trace__validate_ev_qualifier(struct trace *trace)
fputs(sc, trace->output);
}
-
+matches:
trace->ev_qualifier_ids.entries[i++] = id;
+ if (match_next == -1)
+ continue;
+
+ while (1) {
+ id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
+ if (id < 0)
+ break;
+ if (nr_allocated == trace->ev_qualifier_ids.nr) {
+ void *entries;
+
+ nr_allocated += 8;
+ entries = realloc(trace->ev_qualifier_ids.entries,
+ nr_allocated * sizeof(trace->ev_qualifier_ids.entries[0]));
+ if (entries == NULL) {
+ err = -ENOMEM;
+ fputs("\nError:\t Not enough memory for parsing\n", trace->output);
+ goto out_free;
+ }
+ trace->ev_qualifier_ids.entries = entries;
+ }
+ trace->ev_qualifier_ids.nr++;
+ trace->ev_qualifier_ids.entries[i++] = id;
+ }
}
if (err < 0) {
fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
"\nHint:\tand: 'man syscalls'\n", trace->output);
+out_free:
zfree(&trace->ev_qualifier_ids.entries);
trace->ev_qualifier_ids.nr = 0;
}
@@ -2814,7 +2844,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
struct trace *trace = (struct trace *)opt->value;
const char *s = str;
char *sep = NULL, *lists[2] = { NULL, NULL, };
- int len = strlen(str) + 1, err = -1, list;
+ int len = strlen(str) + 1, err = -1, list, idx;
char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
char group_name[PATH_MAX];
@@ -2831,7 +2861,8 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
*sep = '\0';
list = 0;
- if (syscalltbl__id(trace->sctbl, s) >= 0) {
+ if (syscalltbl__id(trace->sctbl, s) >= 0 ||
+ syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
list = 1;
} else {
path__join(group_name, sizeof(group_name), strace_groups_dir, s);
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 2c010dd6a79d..dc442ba21bf6 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -43,6 +43,7 @@ struct record_opts {
bool no_samples;
bool raw_samples;
bool sample_address;
+ bool sample_phys_addr;
bool sample_weight;
bool sample_time;
bool sample_time_set;
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
index 7e62c46d7a20..c63a919eda98 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
@@ -80,11 +80,6 @@
"BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
},
{,
- "EventCode": "0x400F0",
- "EventName": "PM_LD_MISS_L1",
- "BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
- },
- {,
"EventCode": "0x2E01A",
"EventName": "PM_CMPLU_STALL_LSU_FLUSH_NEXT",
"BriefDescription": "Completion stall of one cycle because the LSU requested to flush the next iop in the sequence. It takes 1 cycle for the ISU to process this request before the LSU instruction is allowed to complete"
@@ -374,4 +369,4 @@
"EventName": "PM_IPTEG_FROM_L31_ECO_MOD",
"BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request"
}
-] \ No newline at end of file
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
index 00f3d2a21f31..54cc3be00fc2 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -605,11 +605,6 @@
"BriefDescription": "RC retries on PB for any load from core (excludes DCBFs)"
},
{,
- "EventCode": "0x3689E",
- "EventName": "PM_L2_RTY_LD",
- "BriefDescription": "RC retries on PB for any load from core (excludes DCBFs)"
- },
- {,
"EventCode": "0xE08C",
"EventName": "PM_LSU0_ERAT_HIT",
"BriefDescription": "Primary ERAT hit. There is no secondary ERAT"
@@ -715,11 +710,6 @@
"BriefDescription": "Lifetime, sample of RD machine 0 valid"
},
{,
- "EventCode": "0x468B4",
- "EventName": "PM_L3_RD0_BUSY",
- "BriefDescription": "Lifetime, sample of RD machine 0 valid"
- },
- {,
"EventCode": "0x46080",
"EventName": "PM_L2_DISP_ALL_L2MISS",
"BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)"
@@ -850,21 +840,11 @@
"BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC lifetime (mach0 used as sample point)"
},
{,
- "EventCode": "0x2608C",
- "EventName": "PM_RC0_BUSY",
- "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC lifetime (mach0 used as sample point)"
- },
- {,
"EventCode": "0x36082",
"EventName": "PM_L2_LD_DISP",
"BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)."
},
{,
- "EventCode": "0x1609E",
- "EventName": "PM_L2_LD_DISP",
- "BriefDescription": "All successful D side load dispatches for this thread (L2 miss + L2 hits)"
- },
- {,
"EventCode": "0xF8B0",
"EventName": "PM_L3_SW_PREF",
"BriefDescription": "L3 load prefetch, sourced from a software prefetch stream, was sent to the nest"
@@ -1040,11 +1020,6 @@
"BriefDescription": "L3 castouts in Mepf state for this thread"
},
{,
- "EventCode": "0x168A0",
- "EventName": "PM_L3_CO_MEPF",
- "BriefDescription": "L3 CO of line in Mep state (includes casthrough to memory). The Mepf state indicates that a line was brought in to satisfy an L3 prefetch request"
- },
- {,
"EventCode": "0x460A2",
"EventName": "PM_L3_LAT_CI_HIT",
"BriefDescription": "L3 Lateral Castins Hit"
@@ -1150,11 +1125,6 @@
"BriefDescription": "RC retries on PB for any store from core (excludes DCBFs)"
},
{,
- "EventCode": "0x4689E",
- "EventName": "PM_L2_RTY_ST",
- "BriefDescription": "RC retries on PB for any store from core (excludes DCBFs)"
- },
- {,
"EventCode": "0x24040",
"EventName": "PM_INST_FROM_L2_MEPF",
"BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to an instruction fetch (not prefetch)"
@@ -1255,11 +1225,6 @@
"BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave CO lifetime (mach0 used as sample point)"
},
{,
- "EventCode": "0x4608C",
- "EventName": "PM_CO0_BUSY",
- "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave CO lifetime (mach0 used as sample point)"
- },
- {,
"EventCode": "0x2C122",
"EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT_CYC",
"BriefDescription": "Duration in cycles to reload from local core's L3 with dispatch conflict due to a marked load"
@@ -1395,11 +1360,6 @@
"BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a instruction side request"
},
{,
- "EventCode": "0x40006",
- "EventName": "PM_ISLB_MISS",
- "BriefDescription": "Number of ISLB misses for this thread"
- },
- {,
"EventCode": "0xD8A8",
"EventName": "PM_ISLB_MISS",
"BriefDescription": "Instruction SLB miss - Total of all segment sizes"
@@ -1515,11 +1475,6 @@
"BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)."
},
{,
- "EventCode": "0x3609E",
- "EventName": "PM_L2_INST",
- "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
- },
- {,
"EventCode": "0x3504C",
"EventName": "PM_IPTEG_FROM_DL4",
"BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a instruction side request"
@@ -1690,11 +1645,6 @@
"BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)"
},
{,
- "EventCode": "0x2609E",
- "EventName": "PM_L2_LD_HIT",
- "BriefDescription": "All successful D side load dispatches for this thread that were L2 hits for this thread"
- },
- {,
"EventCode": "0x168AC",
"EventName": "PM_L3_CI_USAGE",
"BriefDescription": "Rotating sample of 16 CI or CO actives"
@@ -1795,21 +1745,11 @@
"BriefDescription": "Rotating sample of 8 WI valid"
},
{,
- "EventCode": "0x260B6",
- "EventName": "PM_L3_WI0_BUSY",
- "BriefDescription": "Rotating sample of 8 WI valid (duplicate)"
- },
- {,
"EventCode": "0x368AC",
"EventName": "PM_L3_CO0_BUSY",
"BriefDescription": "Lifetime, sample of CO machine 0 valid"
},
{,
- "EventCode": "0x468AC",
- "EventName": "PM_L3_CO0_BUSY",
- "BriefDescription": "Lifetime, sample of CO machine 0 valid"
- },
- {,
"EventCode": "0x2E040",
"EventName": "PM_DPTEG_FROM_L2_MEPF",
"BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -1840,11 +1780,6 @@
"BriefDescription": "L3 PF received retry port 0, every retry counted"
},
{,
- "EventCode": "0x260AE",
- "EventName": "PM_L3_P0_PF_RTY",
- "BriefDescription": "L3 PF received retry port 0, every retry counted"
- },
- {,
"EventCode": "0x268B2",
"EventName": "PM_L3_LOC_GUESS_WRONG",
"BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low"
@@ -1895,11 +1830,6 @@
"BriefDescription": "Lifetime, sample of snooper machine 0 valid"
},
{,
- "EventCode": "0x460AC",
- "EventName": "PM_L3_SN0_BUSY",
- "BriefDescription": "Lifetime, sample of snooper machine 0 valid"
- },
- {,
"EventCode": "0x3005C",
"EventName": "PM_BFU_BUSY",
"BriefDescription": "Cycles in which all 4 Binary Floating Point units are busy. The BFU is running at capacity"
@@ -1935,11 +1865,6 @@
"BriefDescription": "Lifetime, sample of PF machine 0 valid"
},
{,
- "EventCode": "0x460B4",
- "EventName": "PM_L3_PF0_BUSY",
- "BriefDescription": "Lifetime, sample of PF machine 0 valid"
- },
- {,
"EventCode": "0xC0B0",
"EventName": "PM_LSU_FLUSH_UE",
"BriefDescription": "Correctable ECC error on reload data, reported at critical data forward time"
@@ -2085,11 +2010,6 @@
"BriefDescription": "L3 CO received retry port 1 (memory only), every retry counted"
},
{,
- "EventCode": "0x468AE",
- "EventName": "PM_L3_P1_CO_RTY",
- "BriefDescription": "L3 CO received retry port 3 (memory only), every retry counted"
- },
- {,
"EventCode": "0xC0AC",
"EventName": "PM_LSU_FLUSH_EMSH",
"BriefDescription": "An ERAT miss was detected after a set-p hit. Erat tracker indicates fail due to tlbmiss and the instruction gets flushed because the instruction was working on the wrong address"
@@ -2195,11 +2115,6 @@
"BriefDescription": "SNP dispatched for a write and was M (true M); for DMA cacheinj this will pulse if rty/push is required (won't pulse if cacheinj is accepted)"
},
{,
- "EventCode": "0x46886",
- "EventName": "PM_L2_SN_M_WR_DONE",
- "BriefDescription": "SNP dispatched for a write and was M (true M); for DMA cacheinj this will pulse if rty/push is required (won't pulse if cacheinj is accepted)"
- },
- {,
"EventCode": "0x489C",
"EventName": "PM_BR_CORECT_PRED_TAKEN_CMPL",
"BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time"
@@ -2290,21 +2205,11 @@
"BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave SN lifetime (mach0 used as sample point)"
},
{,
- "EventCode": "0x26090",
- "EventName": "PM_SN0_BUSY",
- "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave SN lifetime (mach0 used as sample point)"
- },
- {,
"EventCode": "0x360AE",
"EventName": "PM_L3_P0_CO_RTY",
"BriefDescription": "L3 CO received retry port 0 (memory only), every retry counted"
},
{,
- "EventCode": "0x460AE",
- "EventName": "PM_L3_P0_CO_RTY",
- "BriefDescription": "L3 CO received retry port 0 (memory only), every retry counted"
- },
- {,
"EventCode": "0x168A8",
"EventName": "PM_L3_WI_USAGE",
"BriefDescription": "Lifetime, sample of Write Inject machine 0 valid"
@@ -2340,26 +2245,11 @@
"BriefDescription": "L3 PF received retry port 1, every retry counted"
},
{,
- "EventCode": "0x268AE",
- "EventName": "PM_L3_P1_PF_RTY",
- "BriefDescription": "L3 PF received retry port 3, every retry counted"
- },
- {,
"EventCode": "0x46082",
"EventName": "PM_L2_ST_DISP",
"BriefDescription": "All successful D-side store dispatches for this thread "
},
{,
- "EventCode": "0x1689E",
- "EventName": "PM_L2_ST_DISP",
- "BriefDescription": "All successful D-side store dispatches for this thread (L2 miss + L2 hits)"
- },
- {,
- "EventCode": "0x36880",
- "EventName": "PM_L2_INST_MISS",
- "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
- },
- {,
"EventCode": "0x4609E",
"EventName": "PM_L2_INST_MISS",
"BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
@@ -2430,11 +2320,6 @@
"BriefDescription": "# PPC Dispatched"
},
{,
- "EventCode": "0x300F2",
- "EventName": "PM_INST_DISP",
- "BriefDescription": "# PPC Dispatched"
- },
- {,
"EventCode": "0x4E05E",
"EventName": "PM_TM_OUTER_TBEGIN_DISP",
"BriefDescription": "Number of outer tbegin instructions dispatched. The dispatch unit determines whether the tbegin instruction is outer or nested. This is a speculative count, which includes flushed instructions"
@@ -2460,11 +2345,6 @@
"BriefDescription": "All successful D-side store dispatches for this thread that were L2 hits"
},
{,
- "EventCode": "0x2689E",
- "EventName": "PM_L2_ST_HIT",
- "BriefDescription": "All successful D-side store dispatches that were L2 hits for this thread"
- },
- {,
"EventCode": "0x360A8",
"EventName": "PM_L3_CO",
"BriefDescription": "L3 castout occurring (does not include casthrough or log writes (cinj/dmaw))"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
index 47a82568a8df..bc2db636dabf 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
@@ -420,11 +420,6 @@
"BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch"
},
{,
- "EventCode": "0x10016",
- "EventName": "PM_DSLB_MISS",
- "BriefDescription": "Data SLB Miss - Total of all segment sizes"
- },
- {,
"EventCode": "0xD0A8",
"EventName": "PM_DSLB_MISS",
"BriefDescription": "Data SLB Miss - Total of all segment sizes"
@@ -554,4 +549,4 @@
"EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC",
"BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load"
}
-] \ No newline at end of file
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
index a2c95a99e168..3ef8a10aac86 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
@@ -5,11 +5,6 @@
"BriefDescription": "Branches that are not strongly biased"
},
{,
- "EventCode": "0x40036",
- "EventName": "PM_BR_2PATH",
- "BriefDescription": "Branches that are not strongly biased"
- },
- {,
"EventCode": "0x40056",
"EventName": "PM_MEM_LOC_THRESH_LSU_HIGH",
"BriefDescription": "Local memory above threshold for LSU medium"
@@ -124,4 +119,4 @@
"EventName": "PM_1FLOP_CMPL",
"BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation completed"
}
-] \ No newline at end of file
+]
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 761c5a448c56..466a462b26d1 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -237,6 +237,11 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
if (!al.map || !al.map->dso) {
+ if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
+ pr_debug("Hypervisor address can not be resolved - skipping\n");
+ return 0;
+ }
+
pr_debug("thread__find_addr_map failed\n");
return -1;
}
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 6d028f42b3cf..c3858487159d 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -141,6 +141,9 @@ static bool samples_same(const struct perf_sample *s1,
}
}
+ if (type & PERF_SAMPLE_PHYS_ADDR)
+ COMP(phys_addr);
+
return true;
}
@@ -206,6 +209,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
.mask = sample_regs,
.regs = regs,
},
+ .phys_addr = 113,
};
struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
struct perf_sample sample_out;
@@ -305,7 +309,7 @@ int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_u
* were added. Please actually update the test rather than just change
* the condition below.
*/
- if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) {
+ if (PERF_SAMPLE_MAX > PERF_SAMPLE_PHYS_ADDR << 1) {
pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
return -1;
}
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index ba0aee576a2b..786fecaf578e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -829,7 +829,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
"q/ESC/CTRL+C Exit\n\n"
"ENTER Go to target\n"
"ESC Exit\n"
- "H Cycle thru hottest instructions\n"
+ "H Go to hottest instruction\n"
+ "TAB/shift+TAB Cycle thru hottest instructions\n"
"j Toggle showing jump to target arrows\n"
"J Toggle showing number of jump sources on targets\n"
"n Search next string\n"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index f4bc2462bc2c..13dfb0a0bdeb 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -931,12 +931,8 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
browser->show_dso);
if (symbol_conf.show_branchflag_count) {
- if (need_percent)
- callchain_list_counts__printf_value(node, chain, NULL,
- buf, sizeof(buf));
- else
- callchain_list_counts__printf_value(NULL, chain, NULL,
- buf, sizeof(buf));
+ callchain_list_counts__printf_value(chain, NULL,
+ buf, sizeof(buf));
if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
str = "Not enough memory!";
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 5c95b8301c67..8bdb7a500181 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -124,12 +124,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
if (symbol_conf.show_branchflag_count) {
- if (!period)
- callchain_list_counts__printf_value(node, chain, NULL,
- buf, sizeof(buf));
- else
- callchain_list_counts__printf_value(NULL, chain, NULL,
- buf, sizeof(buf));
+ callchain_list_counts__printf_value(chain, NULL,
+ buf, sizeof(buf));
if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
str = "Not enough memory!";
@@ -313,7 +309,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
if (symbol_conf.show_branchflag_count)
ret += callchain_list_counts__printf_value(
- NULL, chain, fp, NULL, 0);
+ chain, fp, NULL, 0);
ret += fprintf(fp, "\n");
if (++entries_printed == callchain_param.print_limit)
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index f320b0777e0d..510b513e0f01 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -588,7 +588,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
call->cycles_count =
cursor_node->branch_flags.cycles;
call->iter_count = cursor_node->nr_loop_iter;
- call->samples_count = cursor_node->samples;
+ call->iter_cycles = cursor_node->iter_cycles;
}
}
@@ -722,7 +722,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
cnode->cycles_count +=
node->branch_flags.cycles;
cnode->iter_count += node->nr_loop_iter;
- cnode->samples_count += node->samples;
+ cnode->iter_cycles += node->iter_cycles;
}
}
@@ -998,7 +998,7 @@ int callchain_merge(struct callchain_cursor *cursor,
int callchain_cursor_append(struct callchain_cursor *cursor,
u64 ip, struct map *map, struct symbol *sym,
bool branch, struct branch_flags *flags,
- int nr_loop_iter, int samples, u64 branch_from)
+ int nr_loop_iter, u64 iter_cycles, u64 branch_from)
{
struct callchain_cursor_node *node = *cursor->last;
@@ -1016,7 +1016,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
node->sym = sym;
node->branch = branch;
node->nr_loop_iter = nr_loop_iter;
- node->samples = samples;
+ node->iter_cycles = iter_cycles;
if (flags)
memcpy(&node->branch_flags, flags,
@@ -1306,7 +1306,7 @@ static int branch_to_str(char *bf, int bfsize,
static int branch_from_str(char *bf, int bfsize,
u64 branch_count,
u64 cycles_count, u64 iter_count,
- u64 samples_count)
+ u64 iter_cycles)
{
int printed = 0, i = 0;
u64 cycles;
@@ -1318,9 +1318,13 @@ static int branch_from_str(char *bf, int bfsize,
bf + printed, bfsize - printed);
}
- if (iter_count && samples_count) {
- printed += count_pri64_printf(i++, "iterations",
- iter_count / samples_count,
+ if (iter_count) {
+ printed += count_pri64_printf(i++, "iter",
+ iter_count,
+ bf + printed, bfsize - printed);
+
+ printed += count_pri64_printf(i++, "avg_cycles",
+ iter_cycles / iter_count,
bf + printed, bfsize - printed);
}
@@ -1333,7 +1337,7 @@ static int branch_from_str(char *bf, int bfsize,
static int counts_str_build(char *bf, int bfsize,
u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count,
- u64 iter_count, u64 samples_count,
+ u64 iter_count, u64 iter_cycles,
struct branch_type_stat *brtype_stat)
{
int printed;
@@ -1346,7 +1350,7 @@ static int counts_str_build(char *bf, int bfsize,
predicted_count, abort_count, brtype_stat);
} else {
printed = branch_from_str(bf, bfsize, branch_count,
- cycles_count, iter_count, samples_count);
+ cycles_count, iter_count, iter_cycles);
}
if (!printed)
@@ -1358,14 +1362,14 @@ static int counts_str_build(char *bf, int bfsize,
static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count,
- u64 iter_count, u64 samples_count,
+ u64 iter_count, u64 iter_cycles,
struct branch_type_stat *brtype_stat)
{
char str[256];
counts_str_build(str, sizeof(str), branch_count,
predicted_count, abort_count, cycles_count,
- iter_count, samples_count, brtype_stat);
+ iter_count, iter_cycles, brtype_stat);
if (fp)
return fprintf(fp, "%s", str);
@@ -1373,31 +1377,23 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
return scnprintf(bf, bfsize, "%s", str);
}
-int callchain_list_counts__printf_value(struct callchain_node *node,
- struct callchain_list *clist,
+int callchain_list_counts__printf_value(struct callchain_list *clist,
FILE *fp, char *bf, int bfsize)
{
u64 branch_count, predicted_count;
u64 abort_count, cycles_count;
- u64 iter_count = 0, samples_count = 0;
+ u64 iter_count, iter_cycles;
branch_count = clist->branch_count;
predicted_count = clist->predicted_count;
abort_count = clist->abort_count;
cycles_count = clist->cycles_count;
-
- if (node) {
- struct callchain_list *call;
-
- list_for_each_entry(call, &node->val, list) {
- iter_count += call->iter_count;
- samples_count += call->samples_count;
- }
- }
+ iter_count = clist->iter_count;
+ iter_cycles = clist->iter_cycles;
return callchain_counts_printf(fp, bf, bfsize, branch_count,
predicted_count, abort_count,
- cycles_count, iter_count, samples_count,
+ cycles_count, iter_count, iter_cycles,
&clist->brtype_stat);
}
@@ -1523,7 +1519,8 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
node->branch, &node->branch_flags,
- node->nr_loop_iter, node->samples,
+ node->nr_loop_iter,
+ node->iter_cycles,
node->branch_from);
if (rc)
break;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 97738201464a..1ed6fc61d0a5 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -119,7 +119,7 @@ struct callchain_list {
u64 abort_count;
u64 cycles_count;
u64 iter_count;
- u64 samples_count;
+ u64 iter_cycles;
struct branch_type_stat brtype_stat;
char *srcline;
struct list_head list;
@@ -139,7 +139,7 @@ struct callchain_cursor_node {
struct branch_flags branch_flags;
u64 branch_from;
int nr_loop_iter;
- int samples;
+ u64 iter_cycles;
struct callchain_cursor_node *next;
};
@@ -201,7 +201,7 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
struct map *map, struct symbol *sym,
bool branch, struct branch_flags *flags,
- int nr_loop_iter, int samples, u64 branch_from);
+ int nr_loop_iter, u64 iter_cycles, u64 branch_from);
/* Close a cursor writing session. Initialize for the reader */
static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
@@ -282,8 +282,7 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
int callchain_node__fprintf_value(struct callchain_node *node,
FILE *fp, u64 total);
-int callchain_list_counts__printf_value(struct callchain_node *node,
- struct callchain_list *clist,
+int callchain_list_counts__printf_value(struct callchain_list *clist,
FILE *fp, char *bf, int bfsize);
void free_callchain(struct callchain_root *root);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 423ac82605f3..ee7bcc898d35 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -200,6 +200,7 @@ struct perf_sample {
u32 cpu;
u32 raw_size;
u64 data_src;
+ u64 phys_addr;
u32 flags;
u16 insn_len;
u8 cpumode;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d9bd632ed7db..4bb89373eb52 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -955,6 +955,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
if (opts->sample_address)
perf_evsel__set_sample_bit(evsel, DATA_SRC);
+ if (opts->sample_phys_addr)
+ perf_evsel__set_sample_bit(evsel, PHYS_ADDR);
+
if (opts->no_buffering) {
attr->watermark = 0;
attr->wakeup_events = 1;
@@ -1464,7 +1467,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
- bit_name(WEIGHT),
+ bit_name(WEIGHT), bit_name(PHYS_ADDR),
{ .name = NULL, }
};
#undef bit_name
@@ -2206,6 +2209,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
}
}
+ data->phys_addr = 0;
+ if (type & PERF_SAMPLE_PHYS_ADDR) {
+ data->phys_addr = *array;
+ array++;
+ }
+
return 0;
}
@@ -2311,6 +2320,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
}
}
+ if (type & PERF_SAMPLE_PHYS_ADDR)
+ result += sizeof(u64);
+
return result;
}
@@ -2500,6 +2512,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
}
}
+ if (type & PERF_SAMPLE_PHYS_ADDR) {
+ *array = sample->phys_addr;
+ array++;
+ }
+
return 0;
}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 351d3b2d8887..dd2c4b5112a5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -131,6 +131,7 @@ struct perf_evsel {
bool cmdline_group_boundary;
struct list_head config_terms;
int bpf_fd;
+ bool auto_merge_stats;
bool merged_stat;
const char * metric_expr;
const char * metric_name;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9453b2e27015..e60d8d8ea4c2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -167,6 +167,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
symlen = unresolved_col_width + 4 + 2;
hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
}
+
+ hists__new_col_len(hists, HISTC_MEM_PHYS_DADDR,
+ unresolved_col_width + 4 + 2);
+
} else {
symlen = unresolved_col_width + 4 + 2;
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ee3670a388df..e60dda26a920 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -47,6 +47,7 @@ enum hist_column {
HISTC_GLOBAL_WEIGHT,
HISTC_MEM_DADDR_SYMBOL,
HISTC_MEM_DADDR_DSO,
+ HISTC_MEM_PHYS_DADDR,
HISTC_MEM_LOCKED,
HISTC_MEM_TLB,
HISTC_MEM_LVL,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 5c8eacaca4f4..df709363ef69 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1635,10 +1635,12 @@ static void ip__resolve_ams(struct thread *thread,
ams->al_addr = al.addr;
ams->sym = al.sym;
ams->map = al.map;
+ ams->phys_addr = 0;
}
static void ip__resolve_data(struct thread *thread,
- u8 m, struct addr_map_symbol *ams, u64 addr)
+ u8 m, struct addr_map_symbol *ams,
+ u64 addr, u64 phys_addr)
{
struct addr_location al;
@@ -1658,6 +1660,7 @@ static void ip__resolve_data(struct thread *thread,
ams->al_addr = al.addr;
ams->sym = al.sym;
ams->map = al.map;
+ ams->phys_addr = phys_addr;
}
struct mem_info *sample__resolve_mem(struct perf_sample *sample,
@@ -1669,12 +1672,18 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
return NULL;
ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
- ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr);
+ ip__resolve_data(al->thread, al->cpumode, &mi->daddr,
+ sample->addr, sample->phys_addr);
mi->data_src.val = sample->data_src;
return mi;
}
+struct iterations {
+ int nr_loop_iter;
+ u64 cycles;
+};
+
static int add_callchain_ip(struct thread *thread,
struct callchain_cursor *cursor,
struct symbol **parent,
@@ -1683,11 +1692,12 @@ static int add_callchain_ip(struct thread *thread,
u64 ip,
bool branch,
struct branch_flags *flags,
- int nr_loop_iter,
- int samples,
+ struct iterations *iter,
u64 branch_from)
{
struct addr_location al;
+ int nr_loop_iter = 0;
+ u64 iter_cycles = 0;
al.filtered = 0;
al.sym = NULL;
@@ -1737,9 +1747,15 @@ static int add_callchain_ip(struct thread *thread,
if (symbol_conf.hide_unresolved && al.sym == NULL)
return 0;
+
+ if (iter) {
+ nr_loop_iter = iter->nr_loop_iter;
+ iter_cycles = iter->cycles;
+ }
+
return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
- branch, flags, nr_loop_iter, samples,
- branch_from);
+ branch, flags, nr_loop_iter,
+ iter_cycles, branch_from);
}
struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1760,6 +1776,18 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
return bi;
}
+static void save_iterations(struct iterations *iter,
+ struct branch_entry *be, int nr)
+{
+ int i;
+
+ iter->nr_loop_iter = nr;
+ iter->cycles = 0;
+
+ for (i = 0; i < nr; i++)
+ iter->cycles += be[i].flags.cycles;
+}
+
#define CHASHSZ 127
#define CHASHBITS 7
#define NO_ENTRY 0xff
@@ -1767,7 +1795,8 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
#define PERF_MAX_BRANCH_DEPTH 127
/* Remove loops. */
-static int remove_loops(struct branch_entry *l, int nr)
+static int remove_loops(struct branch_entry *l, int nr,
+ struct iterations *iter)
{
int i, j, off;
unsigned char chash[CHASHSZ];
@@ -1792,8 +1821,18 @@ static int remove_loops(struct branch_entry *l, int nr)
break;
}
if (is_loop) {
- memmove(l + i, l + i + off,
- (nr - (i + off)) * sizeof(*l));
+ j = nr - (i + off);
+ if (j > 0) {
+ save_iterations(iter + i + off,
+ l + i, off);
+
+ memmove(iter + i, iter + i + off,
+ j * sizeof(*iter));
+
+ memmove(l + i, l + i + off,
+ j * sizeof(*l));
+ }
+
nr -= off;
}
}
@@ -1883,7 +1922,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
- branch, flags, 0, 0,
+ branch, flags, NULL,
branch_from);
if (err)
return (err < 0) ? err : 0;
@@ -1909,7 +1948,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
int i, j, err, nr_entries;
int skip_idx = -1;
int first_call = 0;
- int nr_loop_iter;
if (chain)
chain_nr = chain->nr;
@@ -1942,6 +1980,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
if (branch && callchain_param.branch_callstack) {
int nr = min(max_stack, (int)branch->nr);
struct branch_entry be[nr];
+ struct iterations iter[nr];
if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
pr_warning("corrupted branch chain. skipping...\n");
@@ -1972,38 +2011,21 @@ static int thread__resolve_callchain_sample(struct thread *thread,
be[i] = branch->entries[branch->nr - i - 1];
}
- nr_loop_iter = nr;
- nr = remove_loops(be, nr);
-
- /*
- * Get the number of iterations.
- * It's only approximation, but good enough in practice.
- */
- if (nr_loop_iter > nr)
- nr_loop_iter = nr_loop_iter - nr + 1;
- else
- nr_loop_iter = 0;
+ memset(iter, 0, sizeof(struct iterations) * nr);
+ nr = remove_loops(be, nr, iter);
for (i = 0; i < nr; i++) {
- if (i == nr - 1)
- err = add_callchain_ip(thread, cursor, parent,
- root_al,
- NULL, be[i].to,
- true, &be[i].flags,
- nr_loop_iter, 1,
- be[i].from);
- else
- err = add_callchain_ip(thread, cursor, parent,
- root_al,
- NULL, be[i].to,
- true, &be[i].flags,
- 0, 0, be[i].from);
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al,
+ NULL, be[i].to,
+ true, &be[i].flags,
+ NULL, be[i].from);
if (!err)
err = add_callchain_ip(thread, cursor, parent, root_al,
NULL, be[i].from,
true, &be[i].flags,
- 0, 0, 0);
+ &iter[i], 0);
if (err == -EINVAL)
break;
if (err)
@@ -2037,7 +2059,7 @@ check_calls:
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
- false, NULL, 0, 0, 0);
+ false, NULL, NULL, 0);
if (err)
return (err < 0) ? err : 0;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f44aeba51d1f..f6257fb4f08c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -310,7 +310,7 @@ static struct perf_evsel *
__add_event(struct list_head *list, int *idx,
struct perf_event_attr *attr,
char *name, struct cpu_map *cpus,
- struct list_head *config_terms)
+ struct list_head *config_terms, bool auto_merge_stats)
{
struct perf_evsel *evsel;
@@ -324,6 +324,7 @@ __add_event(struct list_head *list, int *idx,
evsel->cpus = cpu_map__get(cpus);
evsel->own_cpus = cpu_map__get(cpus);
evsel->system_wide = !!cpus;
+ evsel->auto_merge_stats = auto_merge_stats;
if (name)
evsel->name = strdup(name);
@@ -339,7 +340,7 @@ static int add_event(struct list_head *list, int *idx,
struct perf_event_attr *attr, char *name,
struct list_head *config_terms)
{
- return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM;
+ return __add_event(list, idx, attr, name, NULL, config_terms, false) ? 0 : -ENOMEM;
}
static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -1209,9 +1210,9 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
get_config_name(head_config), &config_terms);
}
-int parse_events_add_pmu(struct parse_events_state *parse_state,
+static int __parse_events_add_pmu(struct parse_events_state *parse_state,
struct list_head *list, char *name,
- struct list_head *head_config)
+ struct list_head *head_config, bool auto_merge_stats)
{
struct perf_event_attr attr;
struct perf_pmu_info info;
@@ -1232,7 +1233,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
if (!head_config) {
attr.type = pmu->type;
- evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL);
+ evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL, auto_merge_stats);
return evsel ? 0 : -ENOMEM;
}
@@ -1254,7 +1255,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
evsel = __add_event(list, &parse_state->idx, &attr,
get_config_name(head_config), pmu->cpus,
- &config_terms);
+ &config_terms, auto_merge_stats);
if (evsel) {
evsel->unit = info.unit;
evsel->scale = info.scale;
@@ -1267,6 +1268,13 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
return evsel ? 0 : -ENOMEM;
}
+int parse_events_add_pmu(struct parse_events_state *parse_state,
+ struct list_head *list, char *name,
+ struct list_head *head_config)
+{
+ return __parse_events_add_pmu(parse_state, list, name, head_config, false);
+}
+
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
char *str, struct list_head **listp)
{
@@ -1296,8 +1304,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
return -1;
list_add_tail(&term->list, head);
- if (!parse_events_add_pmu(parse_state, list,
- pmu->name, head)) {
+ if (!__parse_events_add_pmu(parse_state, list,
+ pmu->name, head, true)) {
pr_debug("%s -> %s/%s/\n", str,
pmu->name, alias->str);
ok++;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ac863691605f..a7ebd9fe8e40 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1120,6 +1120,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
if (sample_type & PERF_SAMPLE_DATA_SRC)
printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
+ if (sample_type & PERF_SAMPLE_PHYS_ADDR)
+ printf(" .. phys_addr: 0x%"PRIx64"\n", sample->phys_addr);
+
if (sample_type & PERF_SAMPLE_TRANSACTION)
printf("... transaction: %" PRIx64 "\n", sample->transaction);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 12359bd986db..eb3ab902a1c0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1316,6 +1316,47 @@ struct sort_entry sort_mem_dcacheline = {
};
static int64_t
+sort__phys_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ uint64_t l = 0, r = 0;
+
+ if (left->mem_info)
+ l = left->mem_info->daddr.phys_addr;
+ if (right->mem_info)
+ r = right->mem_info->daddr.phys_addr;
+
+ return (int64_t)(r - l);
+}
+
+static int hist_entry__phys_daddr_snprintf(struct hist_entry *he, char *bf,
+ size_t size, unsigned int width)
+{
+ uint64_t addr = 0;
+ size_t ret = 0;
+ size_t len = BITS_PER_LONG / 4;
+
+ addr = he->mem_info->daddr.phys_addr;
+
+ ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", he->level);
+
+ ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", len, addr);
+
+ ret += repsep_snprintf(bf + ret, size - ret, "%-*s", width - ret, "");
+
+ if (ret > width)
+ bf[width] = '\0';
+
+ return width;
+}
+
+struct sort_entry sort_mem_phys_daddr = {
+ .se_header = "Data Physical Address",
+ .se_cmp = sort__phys_daddr_cmp,
+ .se_snprintf = hist_entry__phys_daddr_snprintf,
+ .se_width_idx = HISTC_MEM_PHYS_DADDR,
+};
+
+static int64_t
sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
{
if (!left->branch_info || !right->branch_info)
@@ -1547,6 +1588,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
+ DIM(SORT_MEM_PHYS_DADDR, "phys_daddr", sort_mem_phys_daddr),
};
#undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index b7c75597e18f..f36dc4980a6c 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -245,6 +245,7 @@ enum sort_type {
SORT_MEM_SNOOP,
SORT_MEM_DCACHELINE,
SORT_MEM_IADDR_SYMBOL,
+ SORT_MEM_PHYS_DADDR,
};
/*
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d00a012cfdfb..2bd6a1f01a1c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -186,6 +186,7 @@ struct addr_map_symbol {
struct symbol *sym;
u64 addr;
u64 al_addr;
+ u64 phys_addr;
};
struct branch_info {
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index bbb4c1957578..19e5db90394c 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -19,6 +19,7 @@
#ifdef HAVE_SYSCALL_TABLE
#include <linux/compiler.h>
#include <string.h>
+#include "string2.h"
#include "util.h"
#if defined(__x86_64__)
@@ -105,6 +106,27 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name)
return sc ? sc->id : -1;
}
+int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+{
+ int i;
+ struct syscall *syscalls = tbl->syscalls.entries;
+
+ for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
+ if (strglobmatch(syscalls[i].name, syscall_glob)) {
+ *idx = i;
+ return syscalls[i].id;
+ }
+ }
+
+ return -1;
+}
+
+int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+{
+ *idx = -1;
+ return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
+}
+
#else /* HAVE_SYSCALL_TABLE */
#include <libaudit.h>
@@ -131,4 +153,15 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name)
{
return audit_name_to_syscall(name, tbl->audit_machine);
}
+
+int syscalltbl__strglobmatch_next(struct syscalltbl *tbl __maybe_unused,
+ const char *syscall_glob __maybe_unused, int *idx __maybe_unused)
+{
+ return -1;
+}
+
+int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+{
+ return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
+}
#endif /* HAVE_SYSCALL_TABLE */
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index e2951510484f..e9fb8786da7c 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -17,4 +17,7 @@ void syscalltbl__delete(struct syscalltbl *tbl);
const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
int syscalltbl__id(struct syscalltbl *tbl, const char *name);
+int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
+
#endif /* __PERF_SYSCALLTBL_H */
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 4c2fa98ef39d..d20791c3f499 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1546,8 +1546,8 @@ static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
else {
memcpy(iobuf, mmio->addr.base + dpa, len);
- /* give us some some coverage of the mmio_flush_range() API */
- mmio_flush_range(mmio->addr.base + dpa, len);
+ /* give us some some coverage of the arch_invalidate_pmem() API */
+ arch_invalidate_pmem(mmio->addr.base + dpa, len);
}
nd_region_release_lane(nd_region, lane);
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 4acc772a28c0..fe3a443a1102 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -558,7 +558,7 @@ static void test_sockmap(int tasks, void *data)
}
}
- /* Test attaching bad fds */
+ /* Test attaching/detaching bad fds */
err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
if (!err) {
printf("Failed invalid parser prog attach\n");
@@ -571,6 +571,30 @@ static void test_sockmap(int tasks, void *data)
goto out_sockmap;
}
+ err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
+ if (!err) {
+ printf("Failed unknown prog attach\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
+ if (err) {
+ printf("Failed empty parser prog detach\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
+ if (err) {
+ printf("Failed empty verdict prog detach\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
+ if (!err) {
+ printf("Detach invalid prog successful\n");
+ goto out_sockmap;
+ }
+
/* Load SK_SKB program and Attach */
err = bpf_prog_load(SOCKMAP_PARSE_PROG,
BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
@@ -643,6 +667,13 @@ static void test_sockmap(int tasks, void *data)
goto out_sockmap;
}
+ err = bpf_prog_attach(verdict_prog, map_fd_rx,
+ __MAX_BPF_ATTACH_TYPE, 0);
+ if (!err) {
+ printf("Attached unknown bpf prog\n");
+ goto out_sockmap;
+ }
+
/* Test map update elem afterwards fd lives in fd and map_fd */
for (i = 0; i < 6; i++) {
err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
@@ -809,6 +840,24 @@ static void test_sockmap(int tasks, void *data)
assert(status == 0);
}
+ err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
+ if (!err) {
+ printf("Detached an invalid prog type.\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
+ if (err) {
+ printf("Failed parser prog detach\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
+ if (err) {
+ printf("Failed parser prog detach\n");
+ goto out_sockmap;
+ }
+
/* Test map close sockets */
for (i = 0; i < 6; i++)
close(sfd[i]);
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c
index f63356151ad4..901b85ea6a59 100644
--- a/tools/testing/selftests/breakpoints/breakpoint_test.c
+++ b/tools/testing/selftests/breakpoints/breakpoint_test.c
@@ -367,11 +367,11 @@ static void launch_tests(void)
/* Icebp traps */
ptrace(PTRACE_CONT, child_pid, NULL, 0);
- check_success("Test icebp");
+ check_success("Test icebp\n");
/* Int 3 traps */
ptrace(PTRACE_CONT, child_pid, NULL, 0);
- check_success("Test int 3 trap");
+ check_success("Test int 3 trap\n");
ptrace(PTRACE_CONT, child_pid, NULL, 0);
}
diff --git a/tools/testing/selftests/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c
index 763f37fecfb8..cf6778441381 100644
--- a/tools/testing/selftests/capabilities/test_execve.c
+++ b/tools/testing/selftests/capabilities/test_execve.c
@@ -1,7 +1,6 @@
#define _GNU_SOURCE
#include <cap-ng.h>
-#include <err.h>
#include <linux/capability.h>
#include <stdbool.h>
#include <string.h>
@@ -18,6 +17,8 @@
#include <sys/prctl.h>
#include <sys/stat.h>
+#include "../kselftest.h"
+
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
# define PR_CAP_AMBIENT_IS_SET 1
@@ -27,6 +28,7 @@
#endif
static int nerrs;
+static pid_t mpid; /* main() pid is used to avoid duplicate test counts */
static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
{
@@ -36,29 +38,32 @@ static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list
int buf_len;
buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
- if (buf_len < 0) {
- err(1, "vsnprintf failed");
- }
- if (buf_len >= sizeof(buf)) {
- errx(1, "vsnprintf output truncated");
- }
+ if (buf_len < 0)
+ ksft_exit_fail_msg("vsnprintf failed - %s\n", strerror(errno));
+
+ if (buf_len >= sizeof(buf))
+ ksft_exit_fail_msg("vsnprintf output truncated\n");
+
fd = open(filename, O_WRONLY);
if (fd < 0) {
if ((errno == ENOENT) && enoent_ok)
return;
- err(1, "open of %s failed", filename);
+ ksft_exit_fail_msg("open of %s failed - %s\n",
+ filename, strerror(errno));
}
written = write(fd, buf, buf_len);
if (written != buf_len) {
if (written >= 0) {
- errx(1, "short write to %s", filename);
+ ksft_exit_fail_msg("short write to %s\n", filename);
} else {
- err(1, "write to %s failed", filename);
+ ksft_exit_fail_msg("write to %s failed - %s\n",
+ filename, strerror(errno));
}
}
if (close(fd) != 0) {
- err(1, "close of %s failed", filename);
+ ksft_exit_fail_msg("close of %s failed - %s\n",
+ filename, strerror(errno));
}
}
@@ -95,11 +100,12 @@ static bool create_and_enter_ns(uid_t inner_uid)
*/
if (unshare(CLONE_NEWNS) == 0) {
- printf("[NOTE]\tUsing global UIDs for tests\n");
+ ksft_print_msg("[NOTE]\tUsing global UIDs for tests\n");
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)
- err(1, "PR_SET_KEEPCAPS");
+ ksft_exit_fail_msg("PR_SET_KEEPCAPS - %s\n",
+ strerror(errno));
if (setresuid(inner_uid, inner_uid, -1) != 0)
- err(1, "setresuid");
+ ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
// Re-enable effective caps
capng_get_caps_process();
@@ -107,22 +113,24 @@ static bool create_and_enter_ns(uid_t inner_uid)
if (capng_have_capability(CAPNG_PERMITTED, i))
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
- err(1, "capng_apply");
+ ksft_exit_fail_msg(
+ "capng_apply - %s\n", strerror(errno));
have_outer_privilege = true;
} else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) {
- printf("[NOTE]\tUsing a user namespace for tests\n");
+ ksft_print_msg("[NOTE]\tUsing a user namespace for tests\n");
maybe_write_file("/proc/self/setgroups", "deny");
write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid);
write_file("/proc/self/gid_map", "0 %d 1", outer_gid);
have_outer_privilege = false;
} else {
- errx(1, "must be root or be able to create a userns");
+ ksft_exit_skip("must be root or be able to create a userns\n");
}
if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
- err(1, "remount everything private");
+ ksft_exit_fail_msg("remount everything private - %s\n",
+ strerror(errno));
return have_outer_privilege;
}
@@ -131,20 +139,22 @@ static void chdir_to_tmpfs(void)
{
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) != cwd)
- err(1, "getcwd");
+ ksft_exit_fail_msg("getcwd - %s\n", strerror(errno));
if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0)
- err(1, "mount private tmpfs");
+ ksft_exit_fail_msg("mount private tmpfs - %s\n",
+ strerror(errno));
if (chdir(cwd) != 0)
- err(1, "chdir to private tmpfs");
+ ksft_exit_fail_msg("chdir to private tmpfs - %s\n",
+ strerror(errno));
}
static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
{
int from = openat(fromfd, fromname, O_RDONLY);
if (from == -1)
- err(1, "open copy source");
+ ksft_exit_fail_msg("open copy source - %s\n", strerror(errno));
int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700);
@@ -154,10 +164,11 @@ static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
if (sz == 0)
break;
if (sz < 0)
- err(1, "read");
+ ksft_exit_fail_msg("read - %s\n", strerror(errno));
if (write(to, buf, sz) != sz)
- err(1, "write"); /* no short writes on tmpfs */
+ /* no short writes on tmpfs */
+ ksft_exit_fail_msg("write - %s\n", strerror(errno));
}
close(from);
@@ -174,18 +185,20 @@ static bool fork_wait(void)
int status;
if (waitpid(child, &status, 0) != child ||
!WIFEXITED(status)) {
- printf("[FAIL]\tChild died\n");
+ ksft_print_msg("Child died\n");
nerrs++;
} else if (WEXITSTATUS(status) != 0) {
- printf("[FAIL]\tChild failed\n");
+ ksft_print_msg("Child failed\n");
nerrs++;
} else {
- printf("[OK]\tChild succeeded\n");
+ /* don't print this message for mpid */
+ if (getpid() != mpid)
+ ksft_test_result_pass("Passed\n");
}
-
return false;
} else {
- err(1, "fork");
+ ksft_exit_fail_msg("fork - %s\n", strerror(errno));
+ return false;
}
}
@@ -195,7 +208,7 @@ static void exec_other_validate_cap(const char *name,
execl(name, name, (eff ? "1" : "0"),
(perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"),
NULL);
- err(1, "execl");
+ ksft_exit_fail_msg("execl - %s\n", strerror(errno));
}
static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient)
@@ -209,7 +222,8 @@ static int do_tests(int uid, const char *our_path)
int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
if (ourpath_fd == -1)
- err(1, "open '%s'", our_path);
+ ksft_exit_fail_msg("open '%s' - %s\n",
+ our_path, strerror(errno));
chdir_to_tmpfs();
@@ -221,30 +235,30 @@ static int do_tests(int uid, const char *our_path)
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_suidroot");
if (chown("validate_cap_suidroot", 0, -1) != 0)
- err(1, "chown");
+ ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0)
- err(1, "chmod");
+ ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_suidnonroot");
if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0)
- err(1, "chown");
+ ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0)
- err(1, "chmod");
+ ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_sgidroot");
if (chown("validate_cap_sgidroot", -1, 0) != 0)
- err(1, "chown");
+ ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0)
- err(1, "chmod");
+ ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_sgidnonroot");
if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0)
- err(1, "chown");
+ ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
- err(1, "chmod");
+ ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
}
capng_get_caps_process();
@@ -252,147 +266,162 @@ static int do_tests(int uid, const char *our_path)
/* Make sure that i starts out clear */
capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
- err(1, "capng_apply");
+ ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (uid == 0) {
- printf("[RUN]\tRoot => ep\n");
+ ksft_print_msg("[RUN]\tRoot => ep\n");
if (fork_wait())
exec_validate_cap(true, true, false, false);
} else {
- printf("[RUN]\tNon-root => no caps\n");
+ ksft_print_msg("[RUN]\tNon-root => no caps\n");
if (fork_wait())
exec_validate_cap(false, false, false, false);
}
- printf("[OK]\tCheck cap_ambient manipulation rules\n");
+ ksft_print_msg("Check cap_ambient manipulation rules\n");
/* We should not be able to add ambient caps yet. */
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) {
if (errno == EINVAL)
- printf("[FAIL]\tPR_CAP_AMBIENT_RAISE isn't supported\n");
+ ksft_test_result_fail(
+ "PR_CAP_AMBIENT_RAISE isn't supported\n");
else
- printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
+ ksft_test_result_fail(
+ "PR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
return 1;
}
- printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
+ ksft_test_result_pass(
+ "PR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW);
capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW);
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
- err(1, "capng_apply");
+ ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0, 0) != -1 || errno != EPERM) {
- printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
+ ksft_test_result_fail(
+ "PR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
return 1;
}
- printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
+ ksft_test_result_pass(
+ "PR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
- err(1, "capng_apply");
+ ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
- printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have succeeded\n");
+ ksft_test_result_fail(
+ "PR_CAP_AMBIENT_RAISE should have succeeded\n");
return 1;
}
- printf("[OK]\tPR_CAP_AMBIENT_RAISE worked\n");
+ ksft_test_result_pass("PR_CAP_AMBIENT_RAISE worked\n");
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) {
- printf("[FAIL]\tPR_CAP_AMBIENT_IS_SET is broken\n");
+ ksft_test_result_fail("PR_CAP_AMBIENT_IS_SET is broken\n");
return 1;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0)
- err(1, "PR_CAP_AMBIENT_CLEAR_ALL");
+ ksft_exit_fail_msg("PR_CAP_AMBIENT_CLEAR_ALL - %s\n",
+ strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
- printf("[FAIL]\tPR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
+ ksft_test_result_fail(
+ "PR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
return 1;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
- err(1, "PR_CAP_AMBIENT_RAISE");
+ ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
+ strerror(errno));
capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
- err(1, "capng_apply");
+ ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
- printf("[FAIL]\tDropping I should have dropped A\n");
+ ksft_test_result_fail("Dropping I should have dropped A\n");
return 1;
}
- printf("[OK]\tBasic manipulation appears to work\n");
+ ksft_test_result_pass("Basic manipulation appears to work\n");
capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
- err(1, "capng_apply");
+ ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (uid == 0) {
- printf("[RUN]\tRoot +i => eip\n");
+ ksft_print_msg("[RUN]\tRoot +i => eip\n");
if (fork_wait())
exec_validate_cap(true, true, true, false);
} else {
- printf("[RUN]\tNon-root +i => i\n");
+ ksft_print_msg("[RUN]\tNon-root +i => i\n");
if (fork_wait())
exec_validate_cap(false, false, true, false);
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
- err(1, "PR_CAP_AMBIENT_RAISE");
+ ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
+ strerror(errno));
- printf("[RUN]\tUID %d +ia => eipa\n", uid);
+ ksft_print_msg("[RUN]\tUID %d +ia => eipa\n", uid);
if (fork_wait())
exec_validate_cap(true, true, true, true);
/* The remaining tests need real privilege */
if (!have_outer_privilege) {
- printf("[SKIP]\tSUID/SGID tests (needs privilege)\n");
+ ksft_test_result_skip("SUID/SGID tests (needs privilege)\n");
goto done;
}
if (uid == 0) {
- printf("[RUN]\tRoot +ia, suidroot => eipa\n");
+ ksft_print_msg("[RUN]\tRoot +ia, suidroot => eipa\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_suidroot",
true, true, true, true);
- printf("[RUN]\tRoot +ia, suidnonroot => ip\n");
+ ksft_print_msg("[RUN]\tRoot +ia, suidnonroot => ip\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_suidnonroot",
false, true, true, false);
- printf("[RUN]\tRoot +ia, sgidroot => eipa\n");
+ ksft_print_msg("[RUN]\tRoot +ia, sgidroot => eipa\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_sgidroot",
true, true, true, true);
if (fork_wait()) {
- printf("[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
+ ksft_print_msg(
+ "[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
if (setresgid(1, 1, 1) != 0)
- err(1, "setresgid");
+ ksft_exit_fail_msg("setresgid - %s\n",
+ strerror(errno));
exec_other_validate_cap("./validate_cap_sgidroot",
true, true, true, false);
}
- printf("[RUN]\tRoot +ia, sgidnonroot => eip\n");
+ ksft_print_msg("[RUN]\tRoot +ia, sgidnonroot => eip\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_sgidnonroot",
true, true, true, false);
} else {
- printf("[RUN]\tNon-root +ia, sgidnonroot => i\n");
- exec_other_validate_cap("./validate_cap_sgidnonroot",
+ ksft_print_msg("[RUN]\tNon-root +ia, sgidnonroot => i\n");
+ if (fork_wait())
+ exec_other_validate_cap("./validate_cap_sgidnonroot",
false, false, true, false);
if (fork_wait()) {
- printf("[RUN]\tNon-root +ia, sgidroot => i\n");
+ ksft_print_msg("[RUN]\tNon-root +ia, sgidroot => i\n");
if (setresgid(1, 1, 1) != 0)
- err(1, "setresgid");
+ ksft_exit_fail_msg("setresgid - %s\n",
+ strerror(errno));
exec_other_validate_cap("./validate_cap_sgidroot",
false, false, true, false);
}
}
done:
+ ksft_print_cnts();
return nerrs ? 1 : 0;
}
@@ -400,23 +429,29 @@ int main(int argc, char **argv)
{
char *tmp1, *tmp2, *our_path;
+ ksft_print_header();
+
/* Find our path */
tmp1 = strdup(argv[0]);
if (!tmp1)
- err(1, "strdup");
+ ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
tmp2 = dirname(tmp1);
our_path = strdup(tmp2);
if (!our_path)
- err(1, "strdup");
+ ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
free(tmp1);
+ mpid = getpid();
+
if (fork_wait()) {
- printf("[RUN]\t+++ Tests with uid == 0 +++\n");
+ ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n");
return do_tests(0, our_path);
}
+ ksft_print_msg("==================================================\n");
+
if (fork_wait()) {
- printf("[RUN]\t+++ Tests with uid != 0 +++\n");
+ ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n");
return do_tests(1, our_path);
}
diff --git a/tools/testing/selftests/capabilities/validate_cap.c b/tools/testing/selftests/capabilities/validate_cap.c
index dd3c45f7b23c..694cd73d4493 100644
--- a/tools/testing/selftests/capabilities/validate_cap.c
+++ b/tools/testing/selftests/capabilities/validate_cap.c
@@ -1,5 +1,4 @@
#include <cap-ng.h>
-#include <err.h>
#include <linux/capability.h>
#include <stdbool.h>
#include <string.h>
@@ -7,6 +6,8 @@
#include <sys/prctl.h>
#include <sys/auxv.h>
+#include "../kselftest.h"
+
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
# define PR_CAP_AMBIENT_IS_SET 1
@@ -25,8 +26,10 @@ static bool bool_arg(char **argv, int i)
return false;
else if (!strcmp(argv[i], "1"))
return true;
- else
- errx(1, "wrong argv[%d]", i);
+ else {
+ ksft_exit_fail_msg("wrong argv[%d]\n", i);
+ return false;
+ }
}
int main(int argc, char **argv)
@@ -39,7 +42,7 @@ int main(int argc, char **argv)
*/
if (argc != 5)
- errx(1, "wrong argc");
+ ksft_exit_fail_msg("wrong argc\n");
#ifdef HAVE_GETAUXVAL
if (getauxval(AT_SECURE))
@@ -51,23 +54,26 @@ int main(int argc, char **argv)
capng_get_caps_process();
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
- printf("[FAIL]\tWrong effective state%s\n", atsec);
+ ksft_print_msg("Wrong effective state%s\n", atsec);
return 1;
}
+
if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) {
- printf("[FAIL]\tWrong permitted state%s\n", atsec);
+ ksft_print_msg("Wrong permitted state%s\n", atsec);
return 1;
}
+
if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) {
- printf("[FAIL]\tWrong inheritable state%s\n", atsec);
+ ksft_print_msg("Wrong inheritable state%s\n", atsec);
return 1;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) {
- printf("[FAIL]\tWrong ambient state%s\n", atsec);
+ ksft_print_msg("Wrong ambient state%s\n", atsec);
return 1;
}
- printf("[OK]\tCapabilities after execve were correct\n");
+ ksft_print_msg("%s: Capabilities after execve were correct\n",
+ "validate_cap:");
return 0;
}
diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
index 98b1d6565f2c..b18b253d7bfb 100755
--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
+++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
@@ -28,6 +28,12 @@ prerequisite()
echo "CPU online/offline summary:"
online_cpus=`cat $SYSFS/devices/system/cpu/online`
online_max=${online_cpus##*-}
+
+ if [[ "$online_cpus" = "$online_max" ]]; then
+ echo "$msg: since there is only one cpu: $online_cpus"
+ exit 0
+ fi
+
echo -e "\t Cpus in online state: $online_cpus"
offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -89,8 +95,10 @@ online_cpu_expect_success()
if ! online_cpu $cpu; then
echo $FUNCNAME $cpu: unexpected fail >&2
+ exit 1
elif ! cpu_is_online $cpu; then
echo $FUNCNAME $cpu: unexpected offline >&2
+ exit 1
fi
}
@@ -100,8 +108,10 @@ online_cpu_expect_fail()
if online_cpu $cpu 2> /dev/null; then
echo $FUNCNAME $cpu: unexpected success >&2
+ exit 1
elif ! cpu_is_offline $cpu; then
echo $FUNCNAME $cpu: unexpected online >&2
+ exit 1
fi
}
@@ -111,8 +121,10 @@ offline_cpu_expect_success()
if ! offline_cpu $cpu; then
echo $FUNCNAME $cpu: unexpected fail >&2
+ exit 1
elif ! cpu_is_offline $cpu; then
echo $FUNCNAME $cpu: unexpected offline >&2
+ exit 1
fi
}
@@ -122,8 +134,10 @@ offline_cpu_expect_fail()
if offline_cpu $cpu 2> /dev/null; then
echo $FUNCNAME $cpu: unexpected success >&2
+ exit 1
elif ! cpu_is_online $cpu; then
echo $FUNCNAME $cpu: unexpected offline >&2
+ exit 1
fi
}
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 14a03ea1e21d..abc706cf7702 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -8,15 +8,18 @@
# Released under the terms of the GPL v2.
usage() { # errno [message]
-[ "$2" ] && echo $2
+[ ! -z "$2" ] && echo $2
echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
echo " Options:"
echo " -h|--help Show help message"
echo " -k|--keep Keep passed test logs"
echo " -v|--verbose Increase verbosity of test messages"
echo " -vv Alias of -v -v (Show all results in stdout)"
+echo " -vvv Alias of -v -v -v (Show all commands immediately)"
+echo " --fail-unsupported Treat UNSUPPORTED as a failure"
echo " -d|--debug Debug mode (trace all shell commands)"
echo " -l|--logdir <dir> Save logs on the <dir>"
+echo " If <dir> is -, all logs output in console only"
exit $1
}
@@ -47,7 +50,7 @@ parse_opts() { # opts
local OPT_TEST_CASES=
local OPT_TEST_DIR=
- while [ "$1" ]; do
+ while [ ! -z "$1" ]; do
case "$1" in
--help|-h)
usage 0
@@ -56,15 +59,20 @@ parse_opts() { # opts
KEEP_LOG=1
shift 1
;;
- --verbose|-v|-vv)
+ --verbose|-v|-vv|-vvv)
VERBOSE=$((VERBOSE + 1))
[ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
+ [ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2))
shift 1
;;
--debug|-d)
DEBUG=1
shift 1
;;
+ --fail-unsupported)
+ UNSUPPORTED_RESULT=1
+ shift 1
+ ;;
--logdir|-l)
LOG_DIR=$2
shift 2
@@ -88,7 +96,7 @@ parse_opts() { # opts
;;
esac
done
- if [ "$OPT_TEST_CASES" ]; then
+ if [ ! -z "$OPT_TEST_CASES" ]; then
TEST_CASES=$OPT_TEST_CASES
fi
}
@@ -108,6 +116,7 @@ LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
KEEP_LOG=0
DEBUG=0
VERBOSE=0
+UNSUPPORTED_RESULT=0
# Parse command-line options
parse_opts $*
@@ -119,14 +128,20 @@ if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
fi
# Preparing logs
-LOG_FILE=$LOG_DIR/ftracetest.log
-mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
-date > $LOG_FILE
+if [ "x$LOG_DIR" = "x-" ]; then
+ LOG_FILE=
+ date
+else
+ LOG_FILE=$LOG_DIR/ftracetest.log
+ mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
+ date > $LOG_FILE
+fi
+
prlog() { # messages
- echo "$@" | tee -a $LOG_FILE
+ [ -z "$LOG_FILE" ] && echo "$@" || echo "$@" | tee -a $LOG_FILE
}
catlog() { #file
- cat $1 | tee -a $LOG_FILE
+ [ -z "$LOG_FILE" ] && cat $1 || cat $1 | tee -a $LOG_FILE
}
prlog "=== Ftrace unit tests ==="
@@ -187,7 +202,7 @@ eval_result() { # sigval
$UNSUPPORTED)
prlog " [UNSUPPORTED]"
UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
- return 1 # this is not a bug, but the result should be reported.
+ return $UNSUPPORTED_RESULT # depends on use case
;;
$XFAIL)
prlog " [XFAIL]"
@@ -247,12 +262,20 @@ __run_test() { # testfile
# Run one test case
run_test() { # testfile
local testname=`basename $1`
- local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
+ if [ ! -z "$LOG_FILE" ] ; then
+ local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
+ else
+ local testlog=/proc/self/fd/1
+ fi
export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
testcase $1
echo "execute$INSTANCE: "$1 > $testlog
SIG_RESULT=0
- if [ $VERBOSE -ge 2 ]; then
+ if [ -z "$LOG_FILE" ]; then
+ __run_test $1 2>&1
+ elif [ $VERBOSE -ge 3 ]; then
+ __run_test $1 | tee -a $testlog 2>&1
+ elif [ $VERBOSE -eq 2 ]; then
__run_test $1 2>> $testlog | tee -a $testlog
else
__run_test $1 >> $testlog 2>&1
@@ -260,9 +283,9 @@ run_test() { # testfile
eval_result $SIG_RESULT
if [ $? -eq 0 ]; then
# Remove test log if the test was done as it was expected.
- [ $KEEP_LOG -eq 0 ] && rm $testlog
+ [ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog
else
- [ $VERBOSE -ge 1 ] && catlog $testlog
+ [ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog
TOTAL_RESULT=1
fi
rm -rf $TMPDIR
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi.c b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
index d24ab7421e73..54cd5c414e82 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
@@ -394,9 +394,11 @@ int main(int argc, char *argv[])
}
}
- printf("%s: Test requeue functionality\n", basename(argv[0]));
- printf("\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
- broadcast, locked, owner, timeout_ns);
+ ksft_print_header();
+ ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0]));
+ ksft_print_msg(
+ "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
+ broadcast, locked, owner, timeout_ns);
/*
* FIXME: unit_test is obsolete now that we parse options and the
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
index e0a798ad0d21..08187a16507f 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
@@ -78,7 +78,8 @@ int main(int argc, char *argv[])
}
}
- printf("%s: Detect mismatched requeue_pi operations\n",
+ ksft_print_header();
+ ksft_print_msg("%s: Detect mismatched requeue_pi operations\n",
basename(argv[0]));
if (pthread_create(&child, NULL, blocking_child, NULL)) {
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
index 982f83577501..f0542a344d95 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
@@ -143,9 +143,10 @@ int main(int argc, char *argv[])
}
}
- printf("%s: Test signal handling during requeue_pi\n",
+ ksft_print_header();
+ ksft_print_msg("%s: Test signal handling during requeue_pi\n",
basename(argv[0]));
- printf("\tArguments: <none>\n");
+ ksft_print_msg("\tArguments: <none>\n");
sa.sa_handler = handle_signal;
sigemptyset(&sa.sa_mask);
diff --git a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
index bdc48dc047e5..6216de828093 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
@@ -97,8 +97,10 @@ int main(int argc, char **argv)
}
}
- printf("%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
- basename(argv[0]));
+ ksft_print_header();
+ ksft_print_msg(
+ "%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
+ basename(argv[0]));
ret = pthread_create(&thr, NULL, thr_futex_wait, NULL);
if (ret < 0) {
diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
index 6aadd560366e..bab3dfe1787f 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
@@ -68,9 +68,10 @@ int main(int argc, char *argv[])
}
}
- printf("%s: Block on a futex and wait for timeout\n",
+ ksft_print_header();
+ ksft_print_msg("%s: Block on a futex and wait for timeout\n",
basename(argv[0]));
- printf("\tArguments: timeout=%ldns\n", timeout_ns);
+ ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
/* initialize timeout */
to.tv_sec = 0;
diff --git a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
index d237a8b702f0..26975322545b 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
@@ -99,7 +99,8 @@ int main(int argc, char **argv)
exit(1);
}
- printf("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
+ ksft_print_header();
+ ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
basename(argv[0]));
diff --git a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
index 9a2c56fa7305..da15a63269b4 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
@@ -64,7 +64,8 @@ int main(int argc, char *argv[])
}
}
- printf("%s: Test the unexpected futex value in FUTEX_WAIT\n",
+ ksft_print_header();
+ ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n",
basename(argv[0]));
info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1);
diff --git a/tools/testing/selftests/futex/include/logging.h b/tools/testing/selftests/futex/include/logging.h
index 4e7944984fbb..01989644e50a 100644
--- a/tools/testing/selftests/futex/include/logging.h
+++ b/tools/testing/selftests/futex/include/logging.h
@@ -109,22 +109,20 @@ void log_verbosity(int level)
*/
void print_result(const char *test_name, int ret)
{
- const char *result = "Unknown return code";
-
switch (ret) {
case RET_PASS:
- ksft_inc_pass_cnt();
- result = PASS;
- break;
+ ksft_test_result_pass("%s\n", test_name);
+ ksft_print_cnts();
+ return;
case RET_ERROR:
- result = ERROR;
- break;
+ ksft_test_result_error("%s\n", test_name);
+ ksft_print_cnts();
+ return;
case RET_FAIL:
- ksft_inc_fail_cnt();
- result = FAIL;
- break;
+ ksft_test_result_fail("%s\n", test_name);
+ ksft_print_cnts();
+ return;
}
- printf("selftests: %s [%s]\n", test_name, result);
}
/* log level macros */
diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c
index a5a4da856dfe..73684c4a1ed6 100644
--- a/tools/testing/selftests/kcmp/kcmp_test.c
+++ b/tools/testing/selftests/kcmp/kcmp_test.c
@@ -8,7 +8,6 @@
#include <errno.h>
#include <string.h>
#include <fcntl.h>
-
#include <linux/unistd.h>
#include <linux/kcmp.h>
@@ -16,20 +15,28 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <sys/epoll.h>
#include "../kselftest.h"
-static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2)
+static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
{
return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
}
+static const unsigned int duped_num = 64;
+
int main(int argc, char **argv)
{
const char kpath[] = "kcmp-test-file";
+ struct kcmp_epoll_slot epoll_slot;
+ struct epoll_event ev;
int pid1, pid2;
+ int pipefd[2];
int fd1, fd2;
+ int epollfd;
int status;
+ int fddup;
fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
pid1 = getpid();
@@ -39,6 +46,37 @@ int main(int argc, char **argv)
ksft_exit_fail();
}
+ if (pipe(pipefd)) {
+ perror("Can't create pipe");
+ ksft_exit_fail();
+ }
+
+ epollfd = epoll_create1(0);
+ if (epollfd < 0) {
+ perror("epoll_create1 failed");
+ ksft_exit_fail();
+ }
+
+ memset(&ev, 0xff, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLOUT;
+
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
+ perror("epoll_ctl failed");
+ ksft_exit_fail();
+ }
+
+ fddup = dup2(pipefd[1], duped_num);
+ if (fddup < 0) {
+ perror("dup2 failed");
+ ksft_exit_fail();
+ }
+
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
+ perror("epoll_ctl failed");
+ ksft_exit_fail();
+ }
+ close(fddup);
+
pid2 = fork();
if (pid2 < 0) {
perror("fork failed");
@@ -95,6 +133,24 @@ int main(int argc, char **argv)
ksft_inc_pass_cnt();
}
+ /* Compare epoll target */
+ epoll_slot = (struct kcmp_epoll_slot) {
+ .efd = epollfd,
+ .tfd = duped_num,
+ .toff = 0,
+ };
+ ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
+ (unsigned long)(void *)&epoll_slot);
+ if (ret) {
+ printf("FAIL: 0 expected but %d returned (%s)\n",
+ ret, strerror(errno));
+ ksft_inc_fail_cnt();
+ ret = -1;
+ } else {
+ printf("PASS: 0 returned as expected\n");
+ ksft_inc_pass_cnt();
+ }
+
ksft_print_cnts();
if (ret)
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 08e90c2cc5cb..1ae565ed9bf0 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -19,7 +19,8 @@
#define KSFT_FAIL 1
#define KSFT_XFAIL 2
#define KSFT_XPASS 3
-#define KSFT_SKIP 4
+/* Treat skip as pass */
+#define KSFT_SKIP KSFT_PASS
/* counters */
struct ksft_count {
@@ -28,6 +29,7 @@ struct ksft_count {
unsigned int ksft_xfail;
unsigned int ksft_xpass;
unsigned int ksft_xskip;
+ unsigned int ksft_error;
};
static struct ksft_count ksft_cnt;
@@ -36,7 +38,7 @@ static inline int ksft_test_num(void)
{
return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
- ksft_cnt.ksft_xskip;
+ ksft_cnt.ksft_xskip + ksft_cnt.ksft_error;
}
static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
@@ -44,6 +46,14 @@ static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
+static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; }
+
+static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; }
+static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; }
+static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; }
+static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; }
+static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; }
+static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
static inline void ksft_print_header(void)
{
@@ -52,6 +62,10 @@ static inline void ksft_print_header(void)
static inline void ksft_print_cnts(void)
{
+ printf("Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n",
+ ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
+ ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
+ ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
printf("1..%d\n", ksft_test_num());
}
@@ -101,6 +115,18 @@ static inline void ksft_test_result_skip(const char *msg, ...)
va_end(args);
}
+static inline void ksft_test_result_error(const char *msg, ...)
+{
+ va_list args;
+
+ ksft_cnt.ksft_error++;
+
+ va_start(args, msg);
+ printf("not ok %d # error ", ksft_test_num());
+ vprintf(msg, args);
+ va_end(args);
+}
+
static inline int ksft_exit_pass(void)
{
ksft_print_cnts();
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index c56f72e07cd7..e81bd28bdd89 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -51,6 +51,9 @@
#define __KSELFTEST_HARNESS_H
#define _GNU_SOURCE
+#include <asm/types.h>
+#include <errno.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -84,6 +87,14 @@
* E.g., #define TH_LOG_ENABLED 1
*
* If no definition is provided, logging is enabled by default.
+ *
+ * If there is no way to print an error message for the process running the
+ * test (e.g. not allowed to write to stderr), it is still possible to get the
+ * ASSERT_* number for which the test failed. This behavior can be enabled by
+ * writing `_metadata->no_print = true;` before the check sequence that is
+ * unable to print. When an error occur, instead of printing an error message
+ * and calling `abort(3)`, the test process call `_exit(2)` with the assert
+ * number as argument, which is then printed by the parent process.
*/
#define TH_LOG(fmt, ...) do { \
if (TH_LOG_ENABLED) \
@@ -555,12 +566,18 @@
* return while still providing an optional block to the API consumer.
*/
#define OPTIONAL_HANDLER(_assert) \
- for (; _metadata->trigger; _metadata->trigger = __bail(_assert))
+ for (; _metadata->trigger; _metadata->trigger = \
+ __bail(_assert, _metadata->no_print, _metadata->step))
+
+#define __INC_STEP(_metadata) \
+ if (_metadata->passed && _metadata->step < 255) \
+ _metadata->step++;
#define __EXPECT(_expected, _seen, _t, _assert) do { \
/* Avoid multiple evaluation of the cases */ \
__typeof__(_expected) __exp = (_expected); \
__typeof__(_seen) __seen = (_seen); \
+ if (_assert) __INC_STEP(_metadata); \
if (!(__exp _t __seen)) { \
unsigned long long __exp_print = (uintptr_t)__exp; \
unsigned long long __seen_print = (uintptr_t)__seen; \
@@ -576,6 +593,7 @@
#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
const char *__exp = (_expected); \
const char *__seen = (_seen); \
+ if (_assert) __INC_STEP(_metadata); \
if (!(strcmp(__exp, __seen) _t 0)) { \
__TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
_metadata->passed = 0; \
@@ -590,6 +608,8 @@ struct __test_metadata {
int termsig;
int passed;
int trigger; /* extra handler after the evaluation */
+ __u8 step;
+ bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
struct __test_metadata *prev, *next;
};
@@ -634,10 +654,13 @@ static inline void __register_test(struct __test_metadata *t)
}
}
-static inline int __bail(int for_realz)
+static inline int __bail(int for_realz, bool no_print, __u8 step)
{
- if (for_realz)
+ if (for_realz) {
+ if (no_print)
+ _exit(step);
abort();
+ }
return 0;
}
@@ -655,18 +678,24 @@ void __run_test(struct __test_metadata *t)
t->passed = 0;
} else if (child_pid == 0) {
t->fn(t);
- _exit(t->passed);
+ /* return the step that failed or 0 */
+ _exit(t->passed ? 0 : t->step);
} else {
/* TODO(wad) add timeout support. */
waitpid(child_pid, &status, 0);
if (WIFEXITED(status)) {
- t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0;
+ t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
if (t->termsig != -1) {
fprintf(TH_LOG_STREAM,
"%s: Test exited normally "
"instead of by signal (code: %d)\n",
t->name,
WEXITSTATUS(status));
+ } else if (!t->passed) {
+ fprintf(TH_LOG_STREAM,
+ "%s: Test failed at step #%d\n",
+ t->name,
+ WEXITSTATUS(status));
}
} else if (WIFSIGNALED(status)) {
t->passed = 0;
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
index 959273c3a52e..693616651da5 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -11,15 +11,26 @@ TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
+.ONESHELL:
define RUN_TESTS
- @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \
+ @test_num=`echo 0`;
+ @echo "TAP version 13";
+ @for TEST in $(1); do \
BASENAME_TEST=`basename $$TEST`; \
- cd `dirname $$TEST`; (./$$BASENAME_TEST && echo "selftests: $$BASENAME_TEST [PASS]") || echo "selftests: $$BASENAME_TEST [FAIL]"; cd -;\
+ test_num=`echo $$test_num+1 | bc`; \
+ echo "selftests: $$BASENAME_TEST"; \
+ echo "========================================"; \
+ if [ ! -x $$BASENAME_TEST ]; then \
+ echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
+ echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
+ else \
+ cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
+ fi; \
done;
endef
run_tests: all
- $(RUN_TESTS)
+ $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_PROGS))
define INSTALL_RULE
@if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index ad8a0897e47f..bc9d02d615da 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I../../../../include/uapi/
CFLAGS += -I../../../../include/
CFLAGS += -I../../../../usr/include/
-TEST_PROGS := run_fuse_test.sh
+TEST_PROGS := run_tests.sh
TEST_GEN_FILES := memfd_test fuse_mnt fuse_test
fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c
index 67908b18f035..7f3617274bf5 100644
--- a/tools/testing/selftests/memfd/fuse_test.c
+++ b/tools/testing/selftests/memfd/fuse_test.c
@@ -33,7 +33,7 @@
#include <unistd.h>
#define MFD_DEF_SIZE 8192
-#define STACK_SIZE 65535
+#define STACK_SIZE 65536
static int sys_memfd_create(const char *name,
unsigned int flags)
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
index 26546892cd54..f94c6d1fb46f 100644
--- a/tools/testing/selftests/memfd/memfd_test.c
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -18,12 +18,48 @@
#include <sys/wait.h>
#include <unistd.h>
+#define MEMFD_STR "memfd:"
+#define SHARED_FT_STR "(shared file-table)"
+
#define MFD_DEF_SIZE 8192
#define STACK_SIZE 65536
+/*
+ * Default is not to test hugetlbfs
+ */
+static int hugetlbfs_test;
+static size_t mfd_def_size = MFD_DEF_SIZE;
+
+/*
+ * Copied from mlock2-tests.c
+ */
+static unsigned long default_huge_page_size(void)
+{
+ unsigned long hps = 0;
+ char *line = NULL;
+ size_t linelen = 0;
+ FILE *f = fopen("/proc/meminfo", "r");
+
+ if (!f)
+ return 0;
+ while (getline(&line, &linelen, f) > 0) {
+ if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
+ hps <<= 10;
+ break;
+ }
+ }
+
+ free(line);
+ fclose(f);
+ return hps;
+}
+
static int sys_memfd_create(const char *name,
unsigned int flags)
{
+ if (hugetlbfs_test)
+ flags |= MFD_HUGETLB;
+
return syscall(__NR_memfd_create, name, flags);
}
@@ -150,7 +186,7 @@ static void *mfd_assert_mmap_shared(int fd)
void *p;
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
@@ -168,7 +204,7 @@ static void *mfd_assert_mmap_private(int fd)
void *p;
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ,
MAP_PRIVATE,
fd,
@@ -223,7 +259,7 @@ static void mfd_assert_read(int fd)
/* verify PROT_READ *is* allowed */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ,
MAP_PRIVATE,
fd,
@@ -232,11 +268,11 @@ static void mfd_assert_read(int fd)
printf("mmap() failed: %m\n");
abort();
}
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
/* verify MAP_PRIVATE is *always* allowed (even writable) */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE,
fd,
@@ -245,7 +281,7 @@ static void mfd_assert_read(int fd)
printf("mmap() failed: %m\n");
abort();
}
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
}
static void mfd_assert_write(int fd)
@@ -254,16 +290,22 @@ static void mfd_assert_write(int fd)
void *p;
int r;
- /* verify write() succeeds */
- l = write(fd, "\0\0\0\0", 4);
- if (l != 4) {
- printf("write() failed: %m\n");
- abort();
+ /*
+ * huegtlbfs does not support write, but we want to
+ * verify everything else here.
+ */
+ if (!hugetlbfs_test) {
+ /* verify write() succeeds */
+ l = write(fd, "\0\0\0\0", 4);
+ if (l != 4) {
+ printf("write() failed: %m\n");
+ abort();
+ }
}
/* verify PROT_READ | PROT_WRITE is allowed */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
@@ -273,11 +315,11 @@ static void mfd_assert_write(int fd)
abort();
}
*(char *)p = 0;
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
/* verify PROT_WRITE is allowed */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_WRITE,
MAP_SHARED,
fd,
@@ -287,12 +329,12 @@ static void mfd_assert_write(int fd)
abort();
}
*(char *)p = 0;
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
/* verify PROT_READ with MAP_SHARED is allowed and a following
* mprotect(PROT_WRITE) allows writing */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ,
MAP_SHARED,
fd,
@@ -302,20 +344,20 @@ static void mfd_assert_write(int fd)
abort();
}
- r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
+ r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
if (r < 0) {
printf("mprotect() failed: %m\n");
abort();
}
*(char *)p = 0;
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
/* verify PUNCH_HOLE works */
r = fallocate(fd,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0,
- MFD_DEF_SIZE);
+ mfd_def_size);
if (r < 0) {
printf("fallocate(PUNCH_HOLE) failed: %m\n");
abort();
@@ -337,7 +379,7 @@ static void mfd_fail_write(int fd)
/* verify PROT_READ | PROT_WRITE is not allowed */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
@@ -349,7 +391,7 @@ static void mfd_fail_write(int fd)
/* verify PROT_WRITE is not allowed */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_WRITE,
MAP_SHARED,
fd,
@@ -362,13 +404,13 @@ static void mfd_fail_write(int fd)
/* Verify PROT_READ with MAP_SHARED with a following mprotect is not
* allowed. Note that for r/w the kernel already prevents the mmap. */
p = mmap(NULL,
- MFD_DEF_SIZE,
+ mfd_def_size,
PROT_READ,
MAP_SHARED,
fd,
0);
if (p != MAP_FAILED) {
- r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
+ r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
if (r >= 0) {
printf("mmap()+mprotect() didn't fail as expected\n");
abort();
@@ -379,7 +421,7 @@ static void mfd_fail_write(int fd)
r = fallocate(fd,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0,
- MFD_DEF_SIZE);
+ mfd_def_size);
if (r >= 0) {
printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
abort();
@@ -390,13 +432,13 @@ static void mfd_assert_shrink(int fd)
{
int r, fd2;
- r = ftruncate(fd, MFD_DEF_SIZE / 2);
+ r = ftruncate(fd, mfd_def_size / 2);
if (r < 0) {
printf("ftruncate(SHRINK) failed: %m\n");
abort();
}
- mfd_assert_size(fd, MFD_DEF_SIZE / 2);
+ mfd_assert_size(fd, mfd_def_size / 2);
fd2 = mfd_assert_open(fd,
O_RDWR | O_CREAT | O_TRUNC,
@@ -410,7 +452,7 @@ static void mfd_fail_shrink(int fd)
{
int r;
- r = ftruncate(fd, MFD_DEF_SIZE / 2);
+ r = ftruncate(fd, mfd_def_size / 2);
if (r >= 0) {
printf("ftruncate(SHRINK) didn't fail as expected\n");
abort();
@@ -425,31 +467,31 @@ static void mfd_assert_grow(int fd)
{
int r;
- r = ftruncate(fd, MFD_DEF_SIZE * 2);
+ r = ftruncate(fd, mfd_def_size * 2);
if (r < 0) {
printf("ftruncate(GROW) failed: %m\n");
abort();
}
- mfd_assert_size(fd, MFD_DEF_SIZE * 2);
+ mfd_assert_size(fd, mfd_def_size * 2);
r = fallocate(fd,
0,
0,
- MFD_DEF_SIZE * 4);
+ mfd_def_size * 4);
if (r < 0) {
printf("fallocate(ALLOC) failed: %m\n");
abort();
}
- mfd_assert_size(fd, MFD_DEF_SIZE * 4);
+ mfd_assert_size(fd, mfd_def_size * 4);
}
static void mfd_fail_grow(int fd)
{
int r;
- r = ftruncate(fd, MFD_DEF_SIZE * 2);
+ r = ftruncate(fd, mfd_def_size * 2);
if (r >= 0) {
printf("ftruncate(GROW) didn't fail as expected\n");
abort();
@@ -458,7 +500,7 @@ static void mfd_fail_grow(int fd)
r = fallocate(fd,
0,
0,
- MFD_DEF_SIZE * 4);
+ mfd_def_size * 4);
if (r >= 0) {
printf("fallocate(ALLOC) didn't fail as expected\n");
abort();
@@ -467,25 +509,37 @@ static void mfd_fail_grow(int fd)
static void mfd_assert_grow_write(int fd)
{
- static char buf[MFD_DEF_SIZE * 8];
+ static char *buf;
ssize_t l;
- l = pwrite(fd, buf, sizeof(buf), 0);
- if (l != sizeof(buf)) {
+ buf = malloc(mfd_def_size * 8);
+ if (!buf) {
+ printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
+ abort();
+ }
+
+ l = pwrite(fd, buf, mfd_def_size * 8, 0);
+ if (l != (mfd_def_size * 8)) {
printf("pwrite() failed: %m\n");
abort();
}
- mfd_assert_size(fd, MFD_DEF_SIZE * 8);
+ mfd_assert_size(fd, mfd_def_size * 8);
}
static void mfd_fail_grow_write(int fd)
{
- static char buf[MFD_DEF_SIZE * 8];
+ static char *buf;
ssize_t l;
- l = pwrite(fd, buf, sizeof(buf), 0);
- if (l == sizeof(buf)) {
+ buf = malloc(mfd_def_size * 8);
+ if (!buf) {
+ printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
+ abort();
+ }
+
+ l = pwrite(fd, buf, mfd_def_size * 8, 0);
+ if (l == (mfd_def_size * 8)) {
printf("pwrite() didn't fail as expected\n");
abort();
}
@@ -543,6 +597,8 @@ static void test_create(void)
char buf[2048];
int fd;
+ printf("%s CREATE\n", MEMFD_STR);
+
/* test NULL name */
mfd_fail_new(NULL, 0);
@@ -570,13 +626,18 @@ static void test_create(void)
fd = mfd_assert_new("", 0, MFD_CLOEXEC);
close(fd);
- /* verify MFD_ALLOW_SEALING is allowed */
- fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
- close(fd);
-
- /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
- fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
- close(fd);
+ if (!hugetlbfs_test) {
+ /* verify MFD_ALLOW_SEALING is allowed */
+ fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
+ close(fd);
+
+ /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
+ fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
+ close(fd);
+ } else {
+ /* sealing is not supported on hugetlbfs */
+ mfd_fail_new("", MFD_ALLOW_SEALING);
+ }
}
/*
@@ -587,8 +648,14 @@ static void test_basic(void)
{
int fd;
+ /* hugetlbfs does not contain sealing support */
+ if (hugetlbfs_test)
+ return;
+
+ printf("%s BASIC\n", MEMFD_STR);
+
fd = mfd_assert_new("kern_memfd_basic",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
/* add basic seals */
@@ -619,7 +686,7 @@ static void test_basic(void)
/* verify sealing does not work without MFD_ALLOW_SEALING */
fd = mfd_assert_new("kern_memfd_basic",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC);
mfd_assert_has_seals(fd, F_SEAL_SEAL);
mfd_fail_add_seals(fd, F_SEAL_SHRINK |
@@ -630,6 +697,28 @@ static void test_basic(void)
}
/*
+ * hugetlbfs doesn't support seals or write, so just verify grow and shrink
+ * on a hugetlbfs file created via memfd_create.
+ */
+static void test_hugetlbfs_grow_shrink(void)
+{
+ int fd;
+
+ printf("%s HUGETLBFS-GROW-SHRINK\n", MEMFD_STR);
+
+ fd = mfd_assert_new("kern_memfd_seal_write",
+ mfd_def_size,
+ MFD_CLOEXEC);
+
+ mfd_assert_read(fd);
+ mfd_assert_write(fd);
+ mfd_assert_shrink(fd);
+ mfd_assert_grow(fd);
+
+ close(fd);
+}
+
+/*
* Test SEAL_WRITE
* Test whether SEAL_WRITE actually prevents modifications.
*/
@@ -637,8 +726,17 @@ static void test_seal_write(void)
{
int fd;
+ /*
+ * hugetlbfs does not contain sealing or write support. Just test
+ * basic grow and shrink via test_hugetlbfs_grow_shrink.
+ */
+ if (hugetlbfs_test)
+ return test_hugetlbfs_grow_shrink();
+
+ printf("%s SEAL-WRITE\n", MEMFD_STR);
+
fd = mfd_assert_new("kern_memfd_seal_write",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
mfd_assert_add_seals(fd, F_SEAL_WRITE);
@@ -661,8 +759,14 @@ static void test_seal_shrink(void)
{
int fd;
+ /* hugetlbfs does not contain sealing support */
+ if (hugetlbfs_test)
+ return;
+
+ printf("%s SEAL-SHRINK\n", MEMFD_STR);
+
fd = mfd_assert_new("kern_memfd_seal_shrink",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
mfd_assert_add_seals(fd, F_SEAL_SHRINK);
@@ -685,8 +789,14 @@ static void test_seal_grow(void)
{
int fd;
+ /* hugetlbfs does not contain sealing support */
+ if (hugetlbfs_test)
+ return;
+
+ printf("%s SEAL-GROW\n", MEMFD_STR);
+
fd = mfd_assert_new("kern_memfd_seal_grow",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
mfd_assert_add_seals(fd, F_SEAL_GROW);
@@ -709,8 +819,14 @@ static void test_seal_resize(void)
{
int fd;
+ /* hugetlbfs does not contain sealing support */
+ if (hugetlbfs_test)
+ return;
+
+ printf("%s SEAL-RESIZE\n", MEMFD_STR);
+
fd = mfd_assert_new("kern_memfd_seal_resize",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
@@ -726,15 +842,52 @@ static void test_seal_resize(void)
}
/*
+ * hugetlbfs does not support seals. Basic test to dup the memfd created
+ * fd and perform some basic operations on it.
+ */
+static void hugetlbfs_dup(char *b_suffix)
+{
+ int fd, fd2;
+
+ printf("%s HUGETLBFS-DUP %s\n", MEMFD_STR, b_suffix);
+
+ fd = mfd_assert_new("kern_memfd_share_dup",
+ mfd_def_size,
+ MFD_CLOEXEC);
+
+ fd2 = mfd_assert_dup(fd);
+
+ mfd_assert_read(fd);
+ mfd_assert_write(fd);
+
+ mfd_assert_shrink(fd2);
+ mfd_assert_grow(fd2);
+
+ close(fd2);
+ close(fd);
+}
+
+/*
* Test sharing via dup()
* Test that seals are shared between dupped FDs and they're all equal.
*/
-static void test_share_dup(void)
+static void test_share_dup(char *banner, char *b_suffix)
{
int fd, fd2;
+ /*
+ * hugetlbfs does not contain sealing support. Perform some
+ * basic testing on dup'ed fd instead via hugetlbfs_dup.
+ */
+ if (hugetlbfs_test) {
+ hugetlbfs_dup(b_suffix);
+ return;
+ }
+
+ printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
+
fd = mfd_assert_new("kern_memfd_share_dup",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
@@ -768,13 +921,19 @@ static void test_share_dup(void)
* Test sealing with active mmap()s
* Modifying seals is only allowed if no other mmap() refs exist.
*/
-static void test_share_mmap(void)
+static void test_share_mmap(char *banner, char *b_suffix)
{
int fd;
void *p;
+ /* hugetlbfs does not contain sealing support */
+ if (hugetlbfs_test)
+ return;
+
+ printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
+
fd = mfd_assert_new("kern_memfd_share_mmap",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
@@ -784,14 +943,40 @@ static void test_share_mmap(void)
mfd_assert_has_seals(fd, 0);
mfd_assert_add_seals(fd, F_SEAL_SHRINK);
mfd_assert_has_seals(fd, F_SEAL_SHRINK);
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
/* readable ref allows sealing */
p = mfd_assert_mmap_private(fd);
mfd_assert_add_seals(fd, F_SEAL_WRITE);
mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
- munmap(p, MFD_DEF_SIZE);
+ munmap(p, mfd_def_size);
+
+ close(fd);
+}
+
+/*
+ * Basic test to make sure we can open the hugetlbfs fd via /proc and
+ * perform some simple operations on it.
+ */
+static void hugetlbfs_proc_open(char *b_suffix)
+{
+ int fd, fd2;
+
+ printf("%s HUGETLBFS-PROC-OPEN %s\n", MEMFD_STR, b_suffix);
+ fd = mfd_assert_new("kern_memfd_share_open",
+ mfd_def_size,
+ MFD_CLOEXEC);
+
+ fd2 = mfd_assert_open(fd, O_RDWR, 0);
+
+ mfd_assert_read(fd);
+ mfd_assert_write(fd);
+
+ mfd_assert_shrink(fd2);
+ mfd_assert_grow(fd2);
+
+ close(fd2);
close(fd);
}
@@ -801,12 +986,23 @@ static void test_share_mmap(void)
* This is *not* like dup(), but like a real separate open(). Make sure the
* semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
*/
-static void test_share_open(void)
+static void test_share_open(char *banner, char *b_suffix)
{
int fd, fd2;
+ /*
+ * hugetlbfs does not contain sealing support. So test basic
+ * functionality of using /proc fd via hugetlbfs_proc_open
+ */
+ if (hugetlbfs_test) {
+ hugetlbfs_proc_open(b_suffix);
+ return;
+ }
+
+ printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
+
fd = mfd_assert_new("kern_memfd_share_open",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
@@ -841,13 +1037,19 @@ static void test_share_open(void)
* Test sharing via fork()
* Test whether seal-modifications work as expected with forked childs.
*/
-static void test_share_fork(void)
+static void test_share_fork(char *banner, char *b_suffix)
{
int fd;
pid_t pid;
+ /* hugetlbfs does not contain sealing support */
+ if (hugetlbfs_test)
+ return;
+
+ printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
+
fd = mfd_assert_new("kern_memfd_share_fork",
- MFD_DEF_SIZE,
+ mfd_def_size,
MFD_CLOEXEC | MFD_ALLOW_SEALING);
mfd_assert_has_seals(fd, 0);
@@ -870,40 +1072,40 @@ int main(int argc, char **argv)
{
pid_t pid;
- printf("memfd: CREATE\n");
+ if (argc == 2) {
+ if (!strcmp(argv[1], "hugetlbfs")) {
+ unsigned long hpage_size = default_huge_page_size();
+
+ if (!hpage_size) {
+ printf("Unable to determine huge page size\n");
+ abort();
+ }
+
+ hugetlbfs_test = 1;
+ mfd_def_size = hpage_size * 2;
+ }
+ }
+
test_create();
- printf("memfd: BASIC\n");
test_basic();
- printf("memfd: SEAL-WRITE\n");
test_seal_write();
- printf("memfd: SEAL-SHRINK\n");
test_seal_shrink();
- printf("memfd: SEAL-GROW\n");
test_seal_grow();
- printf("memfd: SEAL-RESIZE\n");
test_seal_resize();
- printf("memfd: SHARE-DUP\n");
- test_share_dup();
- printf("memfd: SHARE-MMAP\n");
- test_share_mmap();
- printf("memfd: SHARE-OPEN\n");
- test_share_open();
- printf("memfd: SHARE-FORK\n");
- test_share_fork();
+ test_share_dup("SHARE-DUP", "");
+ test_share_mmap("SHARE-MMAP", "");
+ test_share_open("SHARE-OPEN", "");
+ test_share_fork("SHARE-FORK", "");
/* Run test-suite in a multi-threaded environment with a shared
* file-table. */
pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
- printf("memfd: SHARE-DUP (shared file-table)\n");
- test_share_dup();
- printf("memfd: SHARE-MMAP (shared file-table)\n");
- test_share_mmap();
- printf("memfd: SHARE-OPEN (shared file-table)\n");
- test_share_open();
- printf("memfd: SHARE-FORK (shared file-table)\n");
- test_share_fork();
+ test_share_dup("SHARE-DUP", SHARED_FT_STR);
+ test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
+ test_share_open("SHARE-OPEN", SHARED_FT_STR);
+ test_share_fork("SHARE-FORK", SHARED_FT_STR);
join_idle_thread(pid);
printf("memfd: DONE\n");
diff --git a/tools/testing/selftests/memfd/run_tests.sh b/tools/testing/selftests/memfd/run_tests.sh
new file mode 100644
index 000000000000..daabb350697c
--- /dev/null
+++ b/tools/testing/selftests/memfd/run_tests.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+# please run as root
+
+#
+# Normal tests requiring no special resources
+#
+./run_fuse_test.sh
+./memfd_test
+
+#
+# To test memfd_create with hugetlbfs, there needs to be hpages_test
+# huge pages free. Attempt to allocate enough pages to test.
+#
+hpages_test=8
+
+#
+# Get count of free huge pages from /proc/meminfo
+#
+while read name size unit; do
+ if [ "$name" = "HugePages_Free:" ]; then
+ freepgs=$size
+ fi
+done < /proc/meminfo
+
+#
+# If not enough free huge pages for test, attempt to increase
+#
+if [ -n "$freepgs" ] && [ $freepgs -lt $hpages_test ]; then
+ nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
+ hpages_needed=`expr $hpages_test - $freepgs`
+
+ echo 3 > /proc/sys/vm/drop_caches
+ echo $(( $hpages_needed + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
+ if [ $? -ne 0 ]; then
+ echo "Please run this test as root"
+ exit 1
+ fi
+ while read name size unit; do
+ if [ "$name" = "HugePages_Free:" ]; then
+ freepgs=$size
+ fi
+ done < /proc/meminfo
+fi
+
+#
+# If still not enough huge pages available, exit. But, give back any huge
+# pages potentially allocated above.
+#
+if [ $freepgs -lt $hpages_test ]; then
+ # nr_hugepgs non-zero only if we attempted to increase
+ if [ -n "$nr_hugepgs" ]; then
+ echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
+ fi
+ printf "Not enough huge pages available (%d < %d)\n" \
+ $freepgs $needpgs
+ exit 1
+fi
+
+#
+# Run the hugetlbfs test
+#
+./memfd_test hugetlbfs
+
+#
+# Give back any huge pages allocated for the test
+#
+if [ -n "$nr_hugepgs" ]; then
+ echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
+fi
diff --git a/tools/testing/selftests/nsfs/config b/tools/testing/selftests/nsfs/config
new file mode 100644
index 000000000000..598d0a225fc9
--- /dev/null
+++ b/tools/testing/selftests/nsfs/config
@@ -0,0 +1,3 @@
+CONFIG_USER_NS=y
+CONFIG_UTS_NS=y
+CONFIG_PID_NS=y
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index fe6bc60dfc60..8932263e5a74 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -6,7 +6,7 @@ include ../../lib.mk
all: $(TEST_PROGS)
-CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm
+CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
diff --git a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
index ef7c971abb67..bceb53f57573 100644
--- a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
+++ b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
@@ -8,7 +8,7 @@ message:
.section ".toc"
.balign 8
pattern:
- .llong 0x5555AAAA5555AAAA
+ .8byte 0x5555AAAA5555AAAA
.text
FUNC_START(_start)
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 958c11c14acd..7bfcd454fb2a 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -15,6 +15,7 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S
$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
+$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o
SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index e79ccd6aada1..a7ac2e4c60d9 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -30,6 +30,7 @@
#include "utils.h"
#include "tm.h"
+#include "../pmu/lib.h"
#define SPRN_DSCR 0x03
@@ -75,8 +76,6 @@ int test_body(void)
);
assert(rv); /* make sure the transaction aborted */
if ((texasr >> 56) != TM_CAUSE_RESCHED) {
- putchar('.');
- fflush(stdout);
continue;
}
if (dscr2 != dscr1) {
@@ -89,7 +88,12 @@ int test_body(void)
}
}
-int main(void)
+static int tm_resched_dscr(void)
{
- return test_harness(test_body, "tm_resched_dscr");
+ return eat_cpu(test_body);
+}
+
+int main(int argc, const char *argv[])
+{
+ return test_harness(tm_resched_dscr, "tm_resched_dscr");
}
diff --git a/tools/testing/selftests/pstore/.gitignore b/tools/testing/selftests/pstore/.gitignore
new file mode 100644
index 000000000000..5a4a26e5464b
--- /dev/null
+++ b/tools/testing/selftests/pstore/.gitignore
@@ -0,0 +1,2 @@
+logs
+*uuid
diff --git a/tools/testing/selftests/ptp/Makefile b/tools/testing/selftests/ptp/Makefile
index 83dd42b2129e..d4064c742c26 100644
--- a/tools/testing/selftests/ptp/Makefile
+++ b/tools/testing/selftests/ptp/Makefile
@@ -1,3 +1,4 @@
+CFLAGS += -I../../../../usr/include/
TEST_PROGS := testptp
LDLIBS += -lrt
all: $(TEST_PROGS)
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 73f5ea6778ce..4d6f92a9df6b 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -107,7 +107,7 @@ TEST(mode_strict_support)
ASSERT_EQ(0, ret) {
TH_LOG("Kernel does not support CONFIG_SECCOMP");
}
- syscall(__NR_exit, 1);
+ syscall(__NR_exit, 0);
}
TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
index ccd07343d418..7d406c3973ba 100644
--- a/tools/testing/selftests/sigaltstack/sas.c
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -17,6 +17,8 @@
#include <assert.h>
#include <errno.h>
+#include "../kselftest.h"
+
#ifndef SS_AUTODISARM
#define SS_AUTODISARM (1U << 31)
#endif
@@ -41,8 +43,7 @@ void my_usr1(int sig, siginfo_t *si, void *u)
if (sp < (unsigned long)sstack ||
sp >= (unsigned long)sstack + SIGSTKSZ) {
- printf("[FAIL]\tSP is not on sigaltstack\n");
- exit(EXIT_FAILURE);
+ ksft_exit_fail_msg("SP is not on sigaltstack\n");
}
/* put some data on stack. other sighandler will try to overwrite it */
aa = alloca(1024);
@@ -50,21 +51,22 @@ void my_usr1(int sig, siginfo_t *si, void *u)
p = (struct stk_data *)(aa + 512);
strcpy(p->msg, msg);
p->flag = 1;
- printf("[RUN]\tsignal USR1\n");
+ ksft_print_msg("[RUN]\tsignal USR1\n");
err = sigaltstack(NULL, &stk);
if (err) {
- perror("[FAIL]\tsigaltstack()");
+ ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (stk.ss_flags != SS_DISABLE)
- printf("[FAIL]\tss_flags=%x, should be SS_DISABLE\n",
+ ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",
stk.ss_flags);
else
- printf("[OK]\tsigaltstack is disabled in sighandler\n");
+ ksft_test_result_pass(
+ "sigaltstack is disabled in sighandler\n");
swapcontext(&sc, &uc);
- printf("%s\n", p->msg);
+ ksft_print_msg("%s\n", p->msg);
if (!p->flag) {
- printf("[RUN]\tAborting\n");
+ ksft_exit_skip("[RUN]\tAborting\n");
exit(EXIT_FAILURE);
}
}
@@ -74,13 +76,13 @@ void my_usr2(int sig, siginfo_t *si, void *u)
char *aa;
struct stk_data *p;
- printf("[RUN]\tsignal USR2\n");
+ ksft_print_msg("[RUN]\tsignal USR2\n");
aa = alloca(1024);
/* dont run valgrind on this */
/* try to find the data stored by previous sighandler */
p = memmem(aa, 1024, msg, strlen(msg));
if (p) {
- printf("[FAIL]\tsigaltstack re-used\n");
+ ksft_test_result_fail("sigaltstack re-used\n");
/* corrupt the data */
strcpy(p->msg, msg2);
/* tell other sighandler that his data is corrupted */
@@ -90,7 +92,7 @@ void my_usr2(int sig, siginfo_t *si, void *u)
static void switch_fn(void)
{
- printf("[RUN]\tswitched to user ctx\n");
+ ksft_print_msg("[RUN]\tswitched to user ctx\n");
raise(SIGUSR2);
setcontext(&sc);
}
@@ -101,6 +103,8 @@ int main(void)
stack_t stk;
int err;
+ ksft_print_header();
+
sigemptyset(&act.sa_mask);
act.sa_flags = SA_ONSTACK | SA_SIGINFO;
act.sa_sigaction = my_usr1;
@@ -110,19 +114,20 @@ int main(void)
sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (sstack == MAP_FAILED) {
- perror("mmap()");
+ ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
return EXIT_FAILURE;
}
err = sigaltstack(NULL, &stk);
if (err) {
- perror("[FAIL]\tsigaltstack()");
+ ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (stk.ss_flags == SS_DISABLE) {
- printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n");
+ ksft_test_result_pass(
+ "Initial sigaltstack state was SS_DISABLE\n");
} else {
- printf("[FAIL]\tInitial sigaltstack state was %x; "
+ ksft_exit_fail_msg("Initial sigaltstack state was %x; "
"should have been SS_DISABLE\n", stk.ss_flags);
return EXIT_FAILURE;
}
@@ -133,7 +138,8 @@ int main(void)
err = sigaltstack(&stk, NULL);
if (err) {
if (errno == EINVAL) {
- printf("[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
+ ksft_exit_skip(
+ "[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
/*
* If test cases for the !SS_AUTODISARM variant were
* added, we could still run them. We don't have any
@@ -142,7 +148,9 @@ int main(void)
*/
return 0;
} else {
- perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)");
+ ksft_exit_fail_msg(
+ "sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n",
+ strerror(errno));
return EXIT_FAILURE;
}
}
@@ -150,7 +158,7 @@ int main(void)
ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (ustack == MAP_FAILED) {
- perror("mmap()");
+ ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
return EXIT_FAILURE;
}
getcontext(&uc);
@@ -162,16 +170,17 @@ int main(void)
err = sigaltstack(NULL, &stk);
if (err) {
- perror("[FAIL]\tsigaltstack()");
+ ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (stk.ss_flags != SS_AUTODISARM) {
- printf("[FAIL]\tss_flags=%x, should be SS_AUTODISARM\n",
+ ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",
stk.ss_flags);
exit(EXIT_FAILURE);
}
- printf("[OK]\tsigaltstack is still SS_AUTODISARM after signal\n");
+ ksft_test_result_pass(
+ "sigaltstack is still SS_AUTODISARM after signal\n");
- printf("[OK]\tTest passed\n");
+ ksft_exit_pass();
return 0;
}
diff --git a/tools/testing/selftests/splice/.gitignore b/tools/testing/selftests/splice/.gitignore
new file mode 100644
index 000000000000..1e23fefd68e8
--- /dev/null
+++ b/tools/testing/selftests/splice/.gitignore
@@ -0,0 +1 @@
+default_file_splice_read
diff --git a/tools/testing/selftests/splice/Makefile b/tools/testing/selftests/splice/Makefile
index 9fc78e5e5451..7e1187e007fa 100644
--- a/tools/testing/selftests/splice/Makefile
+++ b/tools/testing/selftests/splice/Makefile
@@ -1,7 +1,4 @@
TEST_PROGS := default_file_splice_read.sh
-EXTRA := default_file_splice_read
-all: $(TEST_PROGS) $(EXTRA)
+TEST_GEN_PROGS_EXTENDED := default_file_splice_read
include ../lib.mk
-
-EXTRA_CLEAN := $(EXTRA)
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index 62fa666e501a..7f7938263c5c 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -31,62 +31,83 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <errno.h>
+#include <string.h>
+#include "../kselftest.h"
#include "synctest.h"
static int run_test(int (*test)(void), char *name)
{
int result;
pid_t childpid;
+ int ret;
fflush(stdout);
childpid = fork();
if (childpid) {
waitpid(childpid, &result, 0);
- if (WIFEXITED(result))
- return WEXITSTATUS(result);
+ if (WIFEXITED(result)) {
+ ret = WEXITSTATUS(result);
+ if (!ret)
+ ksft_test_result_pass("[RUN]\t%s\n", name);
+ else
+ ksft_test_result_fail("[RUN]\t%s\n", name);
+ return ret;
+ }
return 1;
}
- printf("[RUN]\tExecuting %s\n", name);
exit(test());
}
-static int sync_api_supported(void)
+static void sync_api_supported(void)
{
struct stat sbuf;
+ int ret;
- return 0 == stat("/sys/kernel/debug/sync/sw_sync", &sbuf);
+ ret = stat("/sys/kernel/debug/sync/sw_sync", &sbuf);
+ if (!ret)
+ return;
+
+ if (errno == ENOENT)
+ ksft_exit_skip("Sync framework not supported by kernel\n");
+
+ if (errno == EACCES)
+ ksft_exit_skip("Run Sync test as root.\n");
+
+ ksft_exit_fail_msg("stat failed on /sys/kernel/debug/sync/sw_sync: %s",
+ strerror(errno));
}
int main(void)
{
- int err = 0;
+ int err;
- if (!sync_api_supported()) {
- printf("SKIP: Sync framework not supported by kernel\n");
- return 0;
- }
+ ksft_print_header();
+
+ sync_api_supported();
- printf("[RUN]\tTesting sync framework\n");
+ ksft_print_msg("[RUN]\tTesting sync framework\n");
- err += RUN_TEST(test_alloc_timeline);
- err += RUN_TEST(test_alloc_fence);
- err += RUN_TEST(test_alloc_fence_negative);
+ RUN_TEST(test_alloc_timeline);
+ RUN_TEST(test_alloc_fence);
+ RUN_TEST(test_alloc_fence_negative);
- err += RUN_TEST(test_fence_one_timeline_wait);
- err += RUN_TEST(test_fence_one_timeline_merge);
- err += RUN_TEST(test_fence_merge_same_fence);
- err += RUN_TEST(test_fence_multi_timeline_wait);
- err += RUN_TEST(test_stress_two_threads_shared_timeline);
- err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
- err += RUN_TEST(test_merge_stress_random_merge);
+ RUN_TEST(test_fence_one_timeline_wait);
+ RUN_TEST(test_fence_one_timeline_merge);
+ RUN_TEST(test_fence_merge_same_fence);
+ RUN_TEST(test_fence_multi_timeline_wait);
+ RUN_TEST(test_stress_two_threads_shared_timeline);
+ RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
+ RUN_TEST(test_merge_stress_random_merge);
+ err = ksft_get_fail_cnt();
if (err)
- printf("[FAIL]\tsync errors: %d\n", err);
- else
- printf("[OK]\tsync\n");
+ ksft_exit_fail_msg("%d out of %d sync tests failed\n",
+ err, ksft_test_num());
- return !!err;
+ /* need this return to keep gcc happy */
+ return ksft_exit_pass();
}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index e7d1d57dba7a..90a8e5369914 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -29,10 +29,11 @@
#define SELFTESTS_SYNCTEST_H
#include <stdio.h>
+#include "../kselftest.h"
#define ASSERT(cond, msg) do { \
if (!(cond)) { \
- printf("[ERROR]\t%s", (msg)); \
+ ksft_print_msg("[ERROR]\t%s", (msg)); \
return 1; \
} \
} while (0)
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index a9b86133b9b3..ae4593115408 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,5 +1,4 @@
-BUILD_FLAGS = -DKTEST
-CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
+CFLAGS += -O3 -Wl,-no-as-needed -Wall
LDFLAGS += -lrt -lpthread -lm
# these are all "safe" tests that don't modify
@@ -7,9 +6,11 @@ LDFLAGS += -lrt -lpthread -lm
TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
inconsistency-check raw_skew threadtest rtctest
-TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \
+DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
skew_consistency clocksource-switch freq-step leap-a-day \
- leapcrash set-tai set-2038 set-tz rtctest_setdate
+ leapcrash set-tai set-2038 set-tz
+
+TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS) rtctest_setdate
include ../lib.mk
@@ -18,16 +19,4 @@ include ../lib.mk
# and may modify the system time or trigger
# other behavior like suspend
run_destructive_tests: run_tests
- ./alarmtimer-suspend
- ./valid-adjtimex
- ./adjtick
- ./change_skew
- ./skew_consistency
- ./clocksource-switch
- ./freq-step
- ./leap-a-day -s -i 10
- ./leapcrash
- ./set-tz
- ./set-tai
- ./set-2038
-
+ $(call RUN_TESTS, $(DESTRUCTIVE_TESTS))
diff --git a/tools/testing/selftests/timers/adjtick.c b/tools/testing/selftests/timers/adjtick.c
index 9887fd538fec..0caca3a06bd2 100644
--- a/tools/testing/selftests/timers/adjtick.c
+++ b/tools/testing/selftests/timers/adjtick.c
@@ -23,18 +23,7 @@
#include <sys/timex.h>
#include <time.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define CLOCK_MONOTONIC_RAW 4
diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/testing/selftests/timers/alarmtimer-suspend.c
index 2b361b830395..4da09dbf83ba 100644
--- a/tools/testing/selftests/timers/alarmtimer-suspend.c
+++ b/tools/testing/selftests/timers/alarmtimer-suspend.c
@@ -28,18 +28,7 @@
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
diff --git a/tools/testing/selftests/timers/change_skew.c b/tools/testing/selftests/timers/change_skew.c
index cb1968977c04..c4eab7124990 100644
--- a/tools/testing/selftests/timers/change_skew.c
+++ b/tools/testing/selftests/timers/change_skew.c
@@ -28,18 +28,7 @@
#include <sys/time.h>
#include <sys/timex.h>
#include <time.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000LL
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c
index 5ff165373f8b..bfc974b4572d 100644
--- a/tools/testing/selftests/timers/clocksource-switch.c
+++ b/tools/testing/selftests/timers/clocksource-switch.c
@@ -34,18 +34,7 @@
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
int get_clocksources(char list[][30])
@@ -61,7 +50,7 @@ int get_clocksources(char list[][30])
close(fd);
- for (i = 0; i < 30; i++)
+ for (i = 0; i < 10; i++)
list[i][0] = '\0';
head = buf;
diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c
index 74c60e8759a0..022d3ffe3fbf 100644
--- a/tools/testing/selftests/timers/inconsistency-check.c
+++ b/tools/testing/selftests/timers/inconsistency-check.c
@@ -28,18 +28,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define CALLS_PER_LOOP 64
#define NSEC_PER_SEC 1000000000ULL
diff --git a/tools/testing/selftests/timers/leap-a-day.c b/tools/testing/selftests/timers/leap-a-day.c
index fb46ad6ac92c..19e46ed5dfb5 100644
--- a/tools/testing/selftests/timers/leap-a-day.c
+++ b/tools/testing/selftests/timers/leap-a-day.c
@@ -48,18 +48,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000ULL
#define CLOCK_TAI 11
@@ -190,18 +179,18 @@ int main(int argc, char **argv)
struct sigevent se;
struct sigaction act;
int signum = SIGRTMAX;
- int settime = 0;
+ int settime = 1;
int tai_time = 0;
int insert = 1;
- int iterations = -1;
+ int iterations = 10;
int opt;
/* Process arguments */
while ((opt = getopt(argc, argv, "sti:")) != -1) {
switch (opt) {
- case 's':
- printf("Setting time to speed up testing\n");
- settime = 1;
+ case 'w':
+ printf("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n");
+ settime = 0;
break;
case 'i':
iterations = atoi(optarg);
@@ -210,9 +199,10 @@ int main(int argc, char **argv)
tai_time = 1;
break;
default:
- printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]);
- printf(" -s: Set time to right before leap second each iteration\n");
- printf(" -i: Number of iterations\n");
+ printf("Usage: %s [-w] [-i <iterations>]\n", argv[0]);
+ printf(" -w: Set flag and wait for leap second each iteration");
+ printf(" (default sets time to right before leapsecond)\n");
+ printf(" -i: Number of iterations (-1 = infinite, default is 10)\n");
printf(" -t: Print TAI time\n");
exit(-1);
}
diff --git a/tools/testing/selftests/timers/leapcrash.c b/tools/testing/selftests/timers/leapcrash.c
index a1071bdbdeb7..830c462f605d 100644
--- a/tools/testing/selftests/timers/leapcrash.c
+++ b/tools/testing/selftests/timers/leapcrash.c
@@ -22,20 +22,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
-
-
/* clear NTP time_status & time_state */
int clear_time_state(void)
diff --git a/tools/testing/selftests/timers/mqueue-lat.c b/tools/testing/selftests/timers/mqueue-lat.c
index a2a3924d0b41..1867db5d6f5e 100644
--- a/tools/testing/selftests/timers/mqueue-lat.c
+++ b/tools/testing/selftests/timers/mqueue-lat.c
@@ -29,18 +29,7 @@
#include <signal.h>
#include <errno.h>
#include <mqueue.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000ULL
diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/selftests/timers/nanosleep.c
index ff942ff7c9b3..8adb0bb51d4d 100644
--- a/tools/testing/selftests/timers/nanosleep.c
+++ b/tools/testing/selftests/timers/nanosleep.c
@@ -27,18 +27,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000ULL
diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c
index 2d7898fda0f1..c3c3dc10db17 100644
--- a/tools/testing/selftests/timers/nsleep-lat.c
+++ b/tools/testing/selftests/timers/nsleep-lat.c
@@ -24,18 +24,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000ULL
diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c
index 30906bfd9c1b..ca6cd146aafe 100644
--- a/tools/testing/selftests/timers/raw_skew.c
+++ b/tools/testing/selftests/timers/raw_skew.c
@@ -25,19 +25,7 @@
#include <sys/time.h>
#include <sys/timex.h>
#include <time.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
-
#define CLOCK_MONOTONIC_RAW 4
#define NSEC_PER_SEC 1000000000LL
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index f61170f7b024..411eff625e66 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -221,6 +221,11 @@ test_READ:
/* Read the current alarm settings */
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
if (retval == -1) {
+ if (errno == EINVAL) {
+ fprintf(stderr,
+ "\n...EINVAL reading current alarm setting.\n");
+ goto test_PIE;
+ }
perror("RTC_ALM_READ ioctl");
exit(errno);
}
@@ -231,7 +236,7 @@ test_READ:
/* Enable alarm interrupts */
retval = ioctl(fd, RTC_AIE_ON, 0);
if (retval == -1) {
- if (errno == EINVAL) {
+ if (errno == EINVAL || errno == EIO) {
fprintf(stderr,
"\n...Alarm IRQs not supported.\n");
goto test_PIE;
diff --git a/tools/testing/selftests/timers/set-2038.c b/tools/testing/selftests/timers/set-2038.c
index c8a7e14446b1..688cfd81b531 100644
--- a/tools/testing/selftests/timers/set-2038.c
+++ b/tools/testing/selftests/timers/set-2038.c
@@ -27,18 +27,7 @@
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000LL
diff --git a/tools/testing/selftests/timers/set-tai.c b/tools/testing/selftests/timers/set-tai.c
index dc88dbc8831f..70fed27d8fd3 100644
--- a/tools/testing/selftests/timers/set-tai.c
+++ b/tools/testing/selftests/timers/set-tai.c
@@ -23,18 +23,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
int set_tai(int offset)
{
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c
index 15434da23b04..9c92b7bd5641 100644
--- a/tools/testing/selftests/timers/set-timer-lat.c
+++ b/tools/testing/selftests/timers/set-timer-lat.c
@@ -28,18 +28,7 @@
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
diff --git a/tools/testing/selftests/timers/set-tz.c b/tools/testing/selftests/timers/set-tz.c
index f4184928b16b..877fd5532fee 100644
--- a/tools/testing/selftests/timers/set-tz.c
+++ b/tools/testing/selftests/timers/set-tz.c
@@ -23,18 +23,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
int set_tz(int min, int dst)
{
diff --git a/tools/testing/selftests/timers/skew_consistency.c b/tools/testing/selftests/timers/skew_consistency.c
index 2a996e072259..022b711c78ee 100644
--- a/tools/testing/selftests/timers/skew_consistency.c
+++ b/tools/testing/selftests/timers/skew_consistency.c
@@ -35,18 +35,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000LL
diff --git a/tools/testing/selftests/timers/threadtest.c b/tools/testing/selftests/timers/threadtest.c
index e632e116f05e..759c9c06f1a0 100644
--- a/tools/testing/selftests/timers/threadtest.c
+++ b/tools/testing/selftests/timers/threadtest.c
@@ -21,19 +21,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
-
/* serializes shared list access */
pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
index 60fe3c569bd9..d9d3ab93b31a 100644
--- a/tools/testing/selftests/timers/valid-adjtimex.c
+++ b/tools/testing/selftests/timers/valid-adjtimex.c
@@ -32,18 +32,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
-#ifdef KTEST
#include "../kselftest.h"
-#else
-static inline int ksft_exit_pass(void)
-{
- exit(0);
-}
-static inline int ksft_exit_fail(void)
-{
- exit(1);
-}
-#endif
#define NSEC_PER_SEC 1000000000LL
#define USEC_PER_SEC 1000000LL
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 1eae79ae5b4e..a2c53a3d223d 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -66,6 +66,8 @@
#include <sys/wait.h>
#include <pthread.h>
#include <linux/userfaultfd.h>
+#include <setjmp.h>
+#include <stdbool.h>
#ifdef __NR_userfaultfd
@@ -82,11 +84,17 @@ static int bounces;
#define TEST_SHMEM 3
static int test_type;
+/* exercise the test_uffdio_*_eexist every ALARM_INTERVAL_SECS */
+#define ALARM_INTERVAL_SECS 10
+static volatile bool test_uffdio_copy_eexist = true;
+static volatile bool test_uffdio_zeropage_eexist = true;
+
+static bool map_shared;
static int huge_fd;
static char *huge_fd_off0;
static unsigned long long *count_verify;
static int uffd, uffd_flags, finished, *pipefd;
-static char *area_src, *area_dst;
+static char *area_src, *area_src_alias, *area_dst, *area_dst_alias;
static char *zeropage;
pthread_attr_t attr;
@@ -125,6 +133,9 @@ static void anon_allocate_area(void **alloc_area)
}
}
+static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
+{
+}
/* HugeTLB memory */
static int hugetlb_release_pages(char *rel_area)
@@ -145,17 +156,51 @@ static int hugetlb_release_pages(char *rel_area)
static void hugetlb_allocate_area(void **alloc_area)
{
+ void *area_alias = NULL;
+ char **alloc_area_alias;
*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_HUGETLB, huge_fd,
- *alloc_area == area_src ? 0 :
- nr_pages * page_size);
+ (map_shared ? MAP_SHARED : MAP_PRIVATE) |
+ MAP_HUGETLB,
+ huge_fd, *alloc_area == area_src ? 0 :
+ nr_pages * page_size);
if (*alloc_area == MAP_FAILED) {
fprintf(stderr, "mmap of hugetlbfs file failed\n");
*alloc_area = NULL;
}
- if (*alloc_area == area_src)
+ if (map_shared) {
+ area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_HUGETLB,
+ huge_fd, *alloc_area == area_src ? 0 :
+ nr_pages * page_size);
+ if (area_alias == MAP_FAILED) {
+ if (munmap(*alloc_area, nr_pages * page_size) < 0)
+ perror("hugetlb munmap"), exit(1);
+ *alloc_area = NULL;
+ return;
+ }
+ }
+ if (*alloc_area == area_src) {
huge_fd_off0 = *alloc_area;
+ alloc_area_alias = &area_src_alias;
+ } else {
+ alloc_area_alias = &area_dst_alias;
+ }
+ if (area_alias)
+ *alloc_area_alias = area_alias;
+}
+
+static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset)
+{
+ if (!map_shared)
+ return;
+ /*
+ * We can't zap just the pagetable with hugetlbfs because
+ * MADV_DONTEED won't work. So exercise -EEXIST on a alias
+ * mapping where the pagetables are not established initially,
+ * this way we'll exercise the -EEXEC at the fs level.
+ */
+ *start = (unsigned long) area_dst_alias + offset;
}
/* Shared memory */
@@ -185,6 +230,7 @@ struct uffd_test_ops {
unsigned long expected_ioctls;
void (*allocate_area)(void **alloc_area);
int (*release_pages)(char *rel_area);
+ void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset);
};
#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
@@ -195,18 +241,21 @@ static struct uffd_test_ops anon_uffd_test_ops = {
.expected_ioctls = ANON_EXPECTED_IOCTLS,
.allocate_area = anon_allocate_area,
.release_pages = anon_release_pages,
+ .alias_mapping = noop_alias_mapping,
};
static struct uffd_test_ops shmem_uffd_test_ops = {
- .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
+ .expected_ioctls = ANON_EXPECTED_IOCTLS,
.allocate_area = shmem_allocate_area,
.release_pages = shmem_release_pages,
+ .alias_mapping = noop_alias_mapping,
};
static struct uffd_test_ops hugetlb_uffd_test_ops = {
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
.allocate_area = hugetlb_allocate_area,
.release_pages = hugetlb_release_pages,
+ .alias_mapping = hugetlb_alias_mapping,
};
static struct uffd_test_ops *uffd_test_ops;
@@ -331,6 +380,23 @@ static void *locking_thread(void *arg)
return NULL;
}
+static void retry_copy_page(int ufd, struct uffdio_copy *uffdio_copy,
+ unsigned long offset)
+{
+ uffd_test_ops->alias_mapping(&uffdio_copy->dst,
+ uffdio_copy->len,
+ offset);
+ if (ioctl(ufd, UFFDIO_COPY, uffdio_copy)) {
+ /* real retval in ufdio_copy.copy */
+ if (uffdio_copy->copy != -EEXIST)
+ fprintf(stderr, "UFFDIO_COPY retry error %Ld\n",
+ uffdio_copy->copy), exit(1);
+ } else {
+ fprintf(stderr, "UFFDIO_COPY retry unexpected %Ld\n",
+ uffdio_copy->copy), exit(1);
+ }
+}
+
static int copy_page(int ufd, unsigned long offset)
{
struct uffdio_copy uffdio_copy;
@@ -351,8 +417,13 @@ static int copy_page(int ufd, unsigned long offset)
} else if (uffdio_copy.copy != page_size) {
fprintf(stderr, "UFFDIO_COPY unexpected copy %Ld\n",
uffdio_copy.copy), exit(1);
- } else
+ } else {
+ if (test_uffdio_copy_eexist) {
+ test_uffdio_copy_eexist = false;
+ retry_copy_page(ufd, &uffdio_copy, offset);
+ }
return 1;
+ }
return 0;
}
@@ -408,6 +479,7 @@ static void *uffd_poll_thread(void *arg)
userfaults++;
break;
case UFFD_EVENT_FORK:
+ close(uffd);
uffd = msg.arg.fork.ufd;
pollfd[0].fd = uffd;
break;
@@ -572,6 +644,17 @@ static int userfaultfd_open(int features)
return 0;
}
+sigjmp_buf jbuf, *sigbuf;
+
+static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
+{
+ if (sig == SIGBUS) {
+ if (sigbuf)
+ siglongjmp(*sigbuf, 1);
+ abort();
+ }
+}
+
/*
* For non-cooperative userfaultfd test we fork() a process that will
* generate pagefaults, will mremap the area monitored by the
@@ -585,19 +668,59 @@ static int userfaultfd_open(int features)
* The release of the pages currently generates event for shmem and
* anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
* for hugetlb.
+ * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register
+ * monitored area, generate pagefaults and test that signal is delivered.
+ * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2
+ * test robustness use case - we release monitored area, fork a process
+ * that will generate pagefaults and verify signal is generated.
+ * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
+ * feature. Using monitor thread, verify no userfault events are generated.
*/
-static int faulting_process(void)
+static int faulting_process(int signal_test)
{
unsigned long nr;
unsigned long long count;
unsigned long split_nr_pages;
+ unsigned long lastnr;
+ struct sigaction act;
+ unsigned long signalled = 0;
if (test_type != TEST_HUGETLB)
split_nr_pages = (nr_pages + 1) / 2;
else
split_nr_pages = nr_pages;
+ if (signal_test) {
+ sigbuf = &jbuf;
+ memset(&act, 0, sizeof(act));
+ act.sa_sigaction = sighndl;
+ act.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGBUS, &act, 0)) {
+ perror("sigaction");
+ return 1;
+ }
+ lastnr = (unsigned long)-1;
+ }
+
for (nr = 0; nr < split_nr_pages; nr++) {
+ if (signal_test) {
+ if (sigsetjmp(*sigbuf, 1) != 0) {
+ if (nr == lastnr) {
+ fprintf(stderr, "Signal repeated\n");
+ return 1;
+ }
+
+ lastnr = nr;
+ if (signal_test == 1) {
+ if (copy_page(uffd, nr * page_size))
+ signalled++;
+ } else {
+ signalled++;
+ continue;
+ }
+ }
+ }
+
count = *area_count(area_dst, nr);
if (count != count_verify[nr]) {
fprintf(stderr,
@@ -607,6 +730,9 @@ static int faulting_process(void)
}
}
+ if (signal_test)
+ return signalled != split_nr_pages;
+
if (test_type == TEST_HUGETLB)
return 0;
@@ -636,6 +762,23 @@ static int faulting_process(void)
return 0;
}
+static void retry_uffdio_zeropage(int ufd,
+ struct uffdio_zeropage *uffdio_zeropage,
+ unsigned long offset)
+{
+ uffd_test_ops->alias_mapping(&uffdio_zeropage->range.start,
+ uffdio_zeropage->range.len,
+ offset);
+ if (ioctl(ufd, UFFDIO_ZEROPAGE, uffdio_zeropage)) {
+ if (uffdio_zeropage->zeropage != -EEXIST)
+ fprintf(stderr, "UFFDIO_ZEROPAGE retry error %Ld\n",
+ uffdio_zeropage->zeropage), exit(1);
+ } else {
+ fprintf(stderr, "UFFDIO_ZEROPAGE retry unexpected %Ld\n",
+ uffdio_zeropage->zeropage), exit(1);
+ }
+}
+
static int uffdio_zeropage(int ufd, unsigned long offset)
{
struct uffdio_zeropage uffdio_zeropage;
@@ -670,8 +813,14 @@ static int uffdio_zeropage(int ufd, unsigned long offset)
if (uffdio_zeropage.zeropage != page_size) {
fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n",
uffdio_zeropage.zeropage), exit(1);
- } else
+ } else {
+ if (test_uffdio_zeropage_eexist) {
+ test_uffdio_zeropage_eexist = false;
+ retry_uffdio_zeropage(ufd, &uffdio_zeropage,
+ offset);
+ }
return 1;
+ }
} else {
fprintf(stderr,
"UFFDIO_ZEROPAGE succeeded %Ld\n",
@@ -761,7 +910,7 @@ static int userfaultfd_events_test(void)
perror("fork"), exit(1);
if (!pid)
- return faulting_process();
+ return faulting_process(0);
waitpid(pid, &err, 0);
if (err)
@@ -778,6 +927,72 @@ static int userfaultfd_events_test(void)
return userfaults != nr_pages;
}
+static int userfaultfd_sig_test(void)
+{
+ struct uffdio_register uffdio_register;
+ unsigned long expected_ioctls;
+ unsigned long userfaults;
+ pthread_t uffd_mon;
+ int err, features;
+ pid_t pid;
+ char c;
+
+ printf("testing signal delivery: ");
+ fflush(stdout);
+
+ if (uffd_test_ops->release_pages(area_dst))
+ return 1;
+
+ features = UFFD_FEATURE_EVENT_FORK|UFFD_FEATURE_SIGBUS;
+ if (userfaultfd_open(features) < 0)
+ return 1;
+ fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
+
+ uffdio_register.range.start = (unsigned long) area_dst;
+ uffdio_register.range.len = nr_pages * page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+ if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
+ fprintf(stderr, "register failure\n"), exit(1);
+
+ expected_ioctls = uffd_test_ops->expected_ioctls;
+ if ((uffdio_register.ioctls & expected_ioctls) !=
+ expected_ioctls)
+ fprintf(stderr,
+ "unexpected missing ioctl for anon memory\n"),
+ exit(1);
+
+ if (faulting_process(1))
+ fprintf(stderr, "faulting process failed\n"), exit(1);
+
+ if (uffd_test_ops->release_pages(area_dst))
+ return 1;
+
+ if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
+ perror("uffd_poll_thread create"), exit(1);
+
+ pid = fork();
+ if (pid < 0)
+ perror("fork"), exit(1);
+
+ if (!pid)
+ exit(faulting_process(2));
+
+ waitpid(pid, &err, 0);
+ if (err)
+ fprintf(stderr, "faulting process failed\n"), exit(1);
+
+ if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
+ perror("pipe write"), exit(1);
+ if (pthread_join(uffd_mon, (void **)&userfaults))
+ return 1;
+
+ printf("done.\n");
+ if (userfaults)
+ fprintf(stderr, "Signal test failed, userfaults: %ld\n",
+ userfaults);
+ close(uffd);
+ return userfaults != 0;
+}
static int userfaultfd_stress(void)
{
void *area;
@@ -879,6 +1094,15 @@ static int userfaultfd_stress(void)
return 1;
}
+ if (area_dst_alias) {
+ uffdio_register.range.start = (unsigned long)
+ area_dst_alias;
+ if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) {
+ fprintf(stderr, "register failure alias\n");
+ return 1;
+ }
+ }
+
/*
* The madvise done previously isn't enough: some
* uffd_thread could have read userfaults (one of
@@ -912,9 +1136,17 @@ static int userfaultfd_stress(void)
/* unregister */
if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) {
- fprintf(stderr, "register failure\n");
+ fprintf(stderr, "unregister failure\n");
return 1;
}
+ if (area_dst_alias) {
+ uffdio_register.range.start = (unsigned long) area_dst;
+ if (ioctl(uffd, UFFDIO_UNREGISTER,
+ &uffdio_register.range)) {
+ fprintf(stderr, "unregister failure alias\n");
+ return 1;
+ }
+ }
/* verification */
if (bounces & BOUNCE_VERIFY) {
@@ -936,6 +1168,10 @@ static int userfaultfd_stress(void)
area_src = area_dst;
area_dst = tmp_area;
+ tmp_area = area_src_alias;
+ area_src_alias = area_dst_alias;
+ area_dst_alias = tmp_area;
+
printf("userfaults:");
for (cpu = 0; cpu < nr_cpus; cpu++)
printf(" %lu", userfaults[cpu]);
@@ -946,7 +1182,8 @@ static int userfaultfd_stress(void)
return err;
close(uffd);
- return userfaultfd_zeropage_test() || userfaultfd_events_test();
+ return userfaultfd_zeropage_test() || userfaultfd_sig_test()
+ || userfaultfd_events_test();
}
/*
@@ -981,7 +1218,12 @@ static void set_test_type(const char *type)
} else if (!strcmp(type, "hugetlb")) {
test_type = TEST_HUGETLB;
uffd_test_ops = &hugetlb_uffd_test_ops;
+ } else if (!strcmp(type, "hugetlb_shared")) {
+ map_shared = true;
+ test_type = TEST_HUGETLB;
+ uffd_test_ops = &hugetlb_uffd_test_ops;
} else if (!strcmp(type, "shmem")) {
+ map_shared = true;
test_type = TEST_SHMEM;
uffd_test_ops = &shmem_uffd_test_ops;
} else {
@@ -1001,12 +1243,25 @@ static void set_test_type(const char *type)
fprintf(stderr, "Impossible to run this test\n"), exit(2);
}
+static void sigalrm(int sig)
+{
+ if (sig != SIGALRM)
+ abort();
+ test_uffdio_copy_eexist = true;
+ test_uffdio_zeropage_eexist = true;
+ alarm(ALARM_INTERVAL_SECS);
+}
+
int main(int argc, char **argv)
{
if (argc < 4)
fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"),
exit(1);
+ if (signal(SIGALRM, sigalrm) == SIG_ERR)
+ fprintf(stderr, "failed to arm SIGALRM"), exit(1);
+ alarm(ALARM_INTERVAL_SECS);
+
set_test_type(argv[1]);
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
diff --git a/tools/testing/selftests/watchdog/watchdog-test.c b/tools/testing/selftests/watchdog/watchdog-test.c
index a74c9d739d07..a1391be2dc1e 100644
--- a/tools/testing/selftests/watchdog/watchdog-test.c
+++ b/tools/testing/selftests/watchdog/watchdog-test.c
@@ -9,12 +9,25 @@
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
+#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/watchdog.h>
+#define DEFAULT_PING_RATE 1
+
int fd;
const char v = 'V';
+static const char sopts[] = "bdehp:t:";
+static const struct option lopts[] = {
+ {"bootstatus", no_argument, NULL, 'b'},
+ {"disable", no_argument, NULL, 'd'},
+ {"enable", no_argument, NULL, 'e'},
+ {"help", no_argument, NULL, 'h'},
+ {"pingrate", required_argument, NULL, 'p'},
+ {"timeout", required_argument, NULL, 't'},
+ {NULL, no_argument, NULL, 0x0}
+};
/*
* This function simply sends an IOCTL to the driver, which in turn ticks
@@ -23,12 +36,12 @@ const char v = 'V';
*/
static void keep_alive(void)
{
- int dummy;
- int ret;
+ int dummy;
+ int ret;
- ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
- if (!ret)
- printf(".");
+ ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
+ if (!ret)
+ printf(".");
}
/*
@@ -38,75 +51,110 @@ static void keep_alive(void)
static void term(int sig)
{
- int ret = write(fd, &v, 1);
-
- close(fd);
- if (ret < 0)
- printf("\nStopping watchdog ticks failed (%d)...\n", errno);
- else
- printf("\nStopping watchdog ticks...\n");
- exit(0);
+ int ret = write(fd, &v, 1);
+
+ close(fd);
+ if (ret < 0)
+ printf("\nStopping watchdog ticks failed (%d)...\n", errno);
+ else
+ printf("\nStopping watchdog ticks...\n");
+ exit(0);
+}
+
+static void usage(char *progname)
+{
+ printf("Usage: %s [options]\n", progname);
+ printf(" -b, --bootstatus Get last boot status (Watchdog/POR)\n");
+ printf(" -d, --disable Turn off the watchdog timer\n");
+ printf(" -e, --enable Turn on the watchdog timer\n");
+ printf(" -h, --help Print the help message\n");
+ printf(" -p, --pingrate=P Set ping rate to P seconds (default %d)\n", DEFAULT_PING_RATE);
+ printf(" -t, --timeout=T Set timeout to T seconds\n");
+ printf("\n");
+ printf("Parameters are parsed left-to-right in real-time.\n");
+ printf("Example: %s -d -t 10 -p 5 -e\n", progname);
}
int main(int argc, char *argv[])
{
- int flags;
- unsigned int ping_rate = 1;
- int ret;
- int i;
-
- setbuf(stdout, NULL);
-
- fd = open("/dev/watchdog", O_WRONLY);
-
- if (fd == -1) {
- printf("Watchdog device not enabled.\n");
- exit(-1);
- }
-
- for (i = 1; i < argc; i++) {
- if (!strncasecmp(argv[i], "-d", 2)) {
- flags = WDIOS_DISABLECARD;
- ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
- if (!ret)
- printf("Watchdog card disabled.\n");
- } else if (!strncasecmp(argv[i], "-e", 2)) {
- flags = WDIOS_ENABLECARD;
- ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
- if (!ret)
- printf("Watchdog card enabled.\n");
- } else if (!strncasecmp(argv[i], "-t", 2) && argv[2]) {
- flags = atoi(argv[i + 1]);
- ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
- if (!ret)
- printf("Watchdog timeout set to %u seconds.\n", flags);
- i++;
- } else if (!strncasecmp(argv[i], "-p", 2) && argv[2]) {
- ping_rate = strtoul(argv[i + 1], NULL, 0);
- printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
- i++;
- } else {
- printf("-d to disable, -e to enable, -t <n> to set "
- "the timeout,\n-p <n> to set the ping rate, and ");
- printf("run by itself to tick the card.\n");
- printf("Parameters are parsed left-to-right in real-time.\n");
- printf("Example: %s -d -t 10 -p 5 -e\n", argv[0]);
- goto end;
- }
- }
-
- printf("Watchdog Ticking Away!\n");
-
- signal(SIGINT, term);
-
- while(1) {
- keep_alive();
- sleep(ping_rate);
- }
+ int flags;
+ unsigned int ping_rate = DEFAULT_PING_RATE;
+ int ret;
+ int c;
+ int oneshot = 0;
+
+ setbuf(stdout, NULL);
+
+ fd = open("/dev/watchdog", O_WRONLY);
+
+ if (fd == -1) {
+ printf("Watchdog device not enabled.\n");
+ exit(-1);
+ }
+
+ while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
+ switch (c) {
+ case 'b':
+ flags = 0;
+ oneshot = 1;
+ ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
+ if (!ret)
+ printf("Last boot is caused by: %s.\n", (flags != 0) ?
+ "Watchdog" : "Power-On-Reset");
+ else
+ printf("WDIOC_GETBOOTSTATUS errno '%s'\n", strerror(errno));
+ break;
+ case 'd':
+ flags = WDIOS_DISABLECARD;
+ ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
+ if (!ret)
+ printf("Watchdog card disabled.\n");
+ else
+ printf("WDIOS_DISABLECARD errno '%s'\n", strerror(errno));
+ break;
+ case 'e':
+ flags = WDIOS_ENABLECARD;
+ ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
+ if (!ret)
+ printf("Watchdog card enabled.\n");
+ else
+ printf("WDIOS_ENABLECARD errno '%s'\n", strerror(errno));
+ break;
+ case 'p':
+ ping_rate = strtoul(optarg, NULL, 0);
+ if (!ping_rate)
+ ping_rate = DEFAULT_PING_RATE;
+ printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
+ break;
+ case 't':
+ flags = strtoul(optarg, NULL, 0);
+ ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
+ if (!ret)
+ printf("Watchdog timeout set to %u seconds.\n", flags);
+ else
+ printf("WDIOC_SETTIMEOUT errno '%s'\n", strerror(errno));
+ break;
+ default:
+ usage(argv[0]);
+ goto end;
+ }
+ }
+
+ if (oneshot)
+ goto end;
+
+ printf("Watchdog Ticking Away!\n");
+
+ signal(SIGINT, term);
+
+ while (1) {
+ keep_alive();
+ sleep(ping_rate);
+ }
end:
- ret = write(fd, &v, 1);
- if (ret < 0)
- printf("Stopping watchdog ticks failed (%d)...\n", errno);
- close(fd);
- return 0;
+ ret = write(fd, &v, 1);
+ if (ret < 0)
+ printf("Stopping watchdog ticks failed (%d)...\n", errno);
+ close(fd);
+ return 0;
}
diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c
index a8df159a8924..ec0f6b45ce8b 100644
--- a/tools/testing/selftests/x86/mpx-mini-test.c
+++ b/tools/testing/selftests/x86/mpx-mini-test.c
@@ -391,8 +391,7 @@ void handler(int signum, siginfo_t *si, void *vucontext)
br_count++;
dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
-#define __SI_FAULT (3 << 16)
-#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */
+#define SEGV_BNDERR 3 /* failed address bound checks */
dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
status, ip, br_reason);
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index 3237bc010e1c..23927845518d 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -212,19 +212,18 @@ void dump_mem(void *dumpme, int len_bytes)
}
}
-#define __SI_FAULT (3 << 16)
-#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */
-#define SEGV_PKUERR (__SI_FAULT|4)
+#define SEGV_BNDERR 3 /* failed address bound checks */
+#define SEGV_PKUERR 4
static char *si_code_str(int si_code)
{
- if (si_code & SEGV_MAPERR)
+ if (si_code == SEGV_MAPERR)
return "SEGV_MAPERR";
- if (si_code & SEGV_ACCERR)
+ if (si_code == SEGV_ACCERR)
return "SEGV_ACCERR";
- if (si_code & SEGV_BNDERR)
+ if (si_code == SEGV_BNDERR)
return "SEGV_BNDERR";
- if (si_code & SEGV_PKUERR)
+ if (si_code == SEGV_PKUERR)
return "SEGV_PKUERR";
return "UNKNOWN";
}