aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2018-05-24 12:30:15 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2018-05-24 12:30:15 -0400
commit754451342fc5954061ede74b0a8485ec4a4c6eaa (patch)
tree82daccba5779de492631c42e47a614bd9d4cddd2 /tools
parentbf232e460a3530adf17da7d7f1332347b73a3d08 (diff)
parent771c577c23bac90597c685971d7297ea00f99d11 (diff)
Merge tag 'v4.17-rc6' into next
Sync up with mainline to bring in Atmel controller changes for Caroline.
Diffstat (limited to 'tools')
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h15
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h6
-rw-r--r--tools/arch/frv/include/uapi/asm/bitsperlong.h2
-rw-r--r--tools/arch/frv/include/uapi/asm/mman.h7
-rw-r--r--tools/arch/m32r/include/uapi/asm/bitsperlong.h2
-rw-r--r--tools/arch/m32r/include/uapi/asm/mman.h7
-rw-r--r--tools/arch/mn10300/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/mn10300/include/uapi/asm/mman.h7
-rw-r--r--tools/arch/powerpc/include/uapi/asm/unistd.h402
-rw-r--r--tools/arch/score/include/uapi/asm/bitsperlong.h7
-rw-r--r--tools/arch/score/include/uapi/asm/mman.h7
-rw-r--r--tools/arch/tile/include/asm/barrier.h16
-rw-r--r--tools/arch/tile/include/uapi/asm/bitsperlong.h27
-rw-r--r--tools/arch/tile/include/uapi/asm/mman.h16
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h3
-rw-r--r--tools/arch/x86/include/asm/required-features.h8
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h19
-rw-r--r--tools/bpf/Makefile80
-rw-r--r--tools/bpf/bpf_dbg.c7
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-prog.rst18
-rw-r--r--tools/bpf/bpftool/Makefile6
-rw-r--r--tools/bpf/bpftool/bash-completion/bpftool13
-rw-r--r--tools/bpf/bpftool/cfg.c514
-rw-r--r--tools/bpf/bpftool/cfg.h43
-rw-r--r--tools/bpf/bpftool/main.c104
-rw-r--r--tools/bpf/bpftool/map.c2
-rw-r--r--tools/bpf/bpftool/prog.c305
-rw-r--r--tools/bpf/bpftool/xlated_dumper.c338
-rw-r--r--tools/bpf/bpftool/xlated_dumper.h64
-rw-r--r--tools/build/Build.include5
-rw-r--r--tools/build/Makefile.feature6
-rw-r--r--tools/build/feature/Makefile14
-rw-r--r--tools/gpio/gpio-event-mon.c2
-rw-r--r--tools/hv/hv_fcopy_daemon.c4
-rw-r--r--tools/hv/hv_kvp_daemon.c138
-rw-r--r--tools/hv/hv_vss_daemon.c1
-rw-r--r--tools/include/asm-generic/barrier.h2
-rw-r--r--tools/include/linux/bitmap.h2
-rw-r--r--tools/include/linux/compiler.h20
-rw-r--r--tools/include/linux/coresight-pmu.h13
-rw-r--r--tools/include/linux/spinlock.h4
-rw-r--r--tools/include/tools/config.h34
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h3
-rw-r--r--tools/include/uapi/drm/i915_drm.h112
-rw-r--r--tools/include/uapi/linux/bpf.h108
-rw-r--r--tools/include/uapi/linux/if_link.h39
-rw-r--r--tools/include/uapi/linux/kvm.h30
-rw-r--r--tools/include/uapi/linux/perf_event.h45
-rw-r--r--tools/include/uapi/sound/asound.h1
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat11
-rw-r--r--tools/lib/api/fs/fs.c44
-rw-r--r--tools/lib/api/fs/fs.h2
-rw-r--r--tools/lib/bpf/bpf.c55
-rw-r--r--tools/lib/bpf/bpf.h18
-rw-r--r--tools/lib/bpf/libbpf.c114
-rw-r--r--tools/lib/bpf/libbpf.h8
-rw-r--r--tools/lib/str_error_r.c2
-rw-r--r--tools/lib/subcmd/parse-options.c6
-rw-r--r--tools/lib/symbol/kallsyms.c4
-rw-r--r--tools/memory-model/Documentation/cheatsheet.txt29
-rw-r--r--tools/memory-model/Documentation/explanation.txt1845
-rw-r--r--tools/memory-model/Documentation/recipes.txt570
-rw-r--r--tools/memory-model/Documentation/references.txt107
-rw-r--r--tools/memory-model/README206
-rw-r--r--tools/memory-model/linux-kernel.bell52
-rw-r--r--tools/memory-model/linux-kernel.cat121
-rw-r--r--tools/memory-model/linux-kernel.cfg21
-rw-r--r--tools/memory-model/linux-kernel.def106
-rw-r--r--tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus26
-rw-r--r--tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus25
-rw-r--r--tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus25
-rw-r--r--tools/memory-model/litmus-tests/CoWW+poonceonce.litmus18
-rw-r--r--tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus45
-rw-r--r--tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus43
-rw-r--r--tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus41
-rw-r--r--tools/memory-model/litmus-tests/ISA2+poonceonces.litmus37
-rw-r--r--tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus39
-rw-r--r--tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus34
-rw-r--r--tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus29
-rw-r--r--tools/memory-model/litmus-tests/LB+poonceonces.litmus28
-rw-r--r--tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus34
-rw-r--r--tools/memory-model/litmus-tests/MP+polocks.litmus35
-rw-r--r--tools/memory-model/litmus-tests/MP+poonceonces.litmus27
-rw-r--r--tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus28
-rw-r--r--tools/memory-model/litmus-tests/MP+porevlocks.litmus35
-rw-r--r--tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus30
-rw-r--r--tools/memory-model/litmus-tests/R+mbonceonces.litmus30
-rw-r--r--tools/memory-model/litmus-tests/R+poonceonces.litmus27
-rw-r--r--tools/memory-model/litmus-tests/README131
-rw-r--r--tools/memory-model/litmus-tests/S+poonceonces.litmus28
-rw-r--r--tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus27
-rw-r--r--tools/memory-model/litmus-tests/SB+mbonceonces.litmus32
-rw-r--r--tools/memory-model/litmus-tests/SB+poonceonces.litmus29
-rw-r--r--tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus35
-rw-r--r--tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus36
-rw-r--r--tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus42
-rw-r--r--tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus40
-rw-r--r--tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus42
-rw-r--r--tools/memory-model/lock.cat99
-rw-r--r--tools/objtool/Makefile6
-rw-r--r--tools/objtool/arch/x86/include/asm/insn.h18
-rw-r--r--tools/objtool/check.c178
-rw-r--r--tools/objtool/elf.c42
-rw-r--r--tools/objtool/elf.h2
-rw-r--r--tools/perf/Documentation/perf-annotate.txt11
-rw-r--r--tools/perf/Documentation/perf-c2c.txt2
-rw-r--r--tools/perf/Documentation/perf-config.txt5
-rw-r--r--tools/perf/Documentation/perf-data.txt2
-rw-r--r--tools/perf/Documentation/perf-ftrace.txt2
-rw-r--r--tools/perf/Documentation/perf-kallsyms.txt2
-rw-r--r--tools/perf/Documentation/perf-kmem.txt6
-rw-r--r--tools/perf/Documentation/perf-list.txt8
-rw-r--r--tools/perf/Documentation/perf-mem.txt46
-rw-r--r--tools/perf/Documentation/perf-record.txt15
-rw-r--r--tools/perf/Documentation/perf-report.txt9
-rw-r--r--tools/perf/Documentation/perf-sched.txt6
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt20
-rw-r--r--tools/perf/Documentation/perf-stat.txt35
-rw-r--r--tools/perf/Documentation/perf-top.txt7
-rw-r--r--tools/perf/Documentation/perf-trace.txt28
-rw-r--r--tools/perf/Documentation/perf-version.txt24
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt7
-rw-r--r--tools/perf/Makefile.config39
-rw-r--r--tools/perf/Makefile.perf13
-rw-r--r--tools/perf/arch/arm/include/arch-tests.h12
-rw-r--r--tools/perf/arch/arm/tests/Build2
-rw-r--r--tools/perf/arch/arm/tests/arch-tests.c16
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c15
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c64
-rw-r--r--tools/perf/arch/arm/util/cs-etm.h13
-rw-r--r--tools/perf/arch/arm/util/pmu.c13
-rw-r--r--tools/perf/arch/arm64/include/arch-tests.h12
-rw-r--r--tools/perf/arch/arm64/tests/Build2
-rw-r--r--tools/perf/arch/arm64/tests/arch-tests.c16
-rw-r--r--tools/perf/arch/arm64/util/Build1
-rw-r--r--tools/perf/arch/arm64/util/unwind-libdw.c60
-rw-r--r--tools/perf/arch/powerpc/Makefile25
-rwxr-xr-xtools/perf/arch/powerpc/entry/syscalls/mksyscalltbl37
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c144
-rw-r--r--tools/perf/arch/s390/util/auxtrace.c1
-rw-r--r--tools/perf/arch/s390/util/header.c130
-rw-r--r--tools/perf/arch/x86/Makefile2
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c67
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl712
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c10
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c14
-rw-r--r--tools/perf/bench/numa.c2
-rw-r--r--tools/perf/builtin-annotate.c109
-rw-r--r--tools/perf/builtin-c2c.c247
-rw-r--r--tools/perf/builtin-ftrace.c18
-rw-r--r--tools/perf/builtin-help.c2
-rw-r--r--tools/perf/builtin-kvm.c16
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-record.c82
-rw-r--r--tools/perf/builtin-report.c65
-rw-r--r--tools/perf/builtin-sched.c133
-rw-r--r--tools/perf/builtin-script.c48
-rw-r--r--tools/perf/builtin-stat.c156
-rw-r--r--tools/perf/builtin-top.c19
-rw-r--r--tools/perf/builtin-trace.c71
-rw-r--r--tools/perf/builtin-version.c85
-rwxr-xr-xtools/perf/check-headers.sh2
-rw-r--r--tools/perf/perf-sys.h4
-rw-r--r--tools/perf/perf.c10
-rw-r--r--tools/perf/perf.h4
-rw-r--r--tools/perf/pmu-events/Build2
-rw-r--r--tools/perf/pmu-events/README15
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json (renamed from tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json)14
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json8
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json27
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json (renamed from tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json)14
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json28
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json (renamed from tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json)20
-rw-r--r--tools/perf/pmu-events/arch/arm64/armv8-recommended.json452
-rw-r--r--tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json62
-rw-r--r--tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json22
-rw-r--r--tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json27
-rw-r--r--tools/perf/pmu-events/arch/arm64/cortex-a53/other.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json122
-rw-r--r--tools/perf/pmu-events/arch/arm64/mapfile.csv6
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/cache.json25
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/frontend.json10
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/marked.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/memory.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json241
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pipeline.json50
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pmc.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/translation.json10
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/extended.json110
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/extended.json338
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/basic.json50
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/extended.json320
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/extended.json146
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/extended.json212
-rw-r--r--tools/perf/pmu-events/arch/s390/mapfile.csv6
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv1
-rw-r--r--tools/perf/pmu-events/jevents.c291
-rwxr-xr-xtools/perf/python/twatch.py8
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c34
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/attr.c4
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling3
-rw-r--r--tools/perf/tests/backward-ring-buffer.c5
-rw-r--r--tools/perf/tests/bp_account.c193
-rw-r--r--tools/perf/tests/bpf-script-example.c2
-rw-r--r--tools/perf/tests/bpf-script-test-kbuild.c1
-rw-r--r--tools/perf/tests/bpf.c8
-rw-r--r--tools/perf/tests/builtin-test.c9
-rw-r--r--tools/perf/tests/code-reading.c43
-rw-r--r--tools/perf/tests/dwarf-unwind.c46
-rw-r--r--tools/perf/tests/keep-tracking.c9
-rw-r--r--tools/perf/tests/mem.c2
-rw-r--r--tools/perf/tests/mem2node.c75
-rw-r--r--tools/perf/tests/mmap-basic.c13
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c10
-rw-r--r--tools/perf/tests/perf-record.c10
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/shell/lib/probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh (renamed from tools/perf/tests/shell/trace+probe_libc_inet_pton.sh)33
-rw-r--r--tools/perf/tests/sw-clock.c11
-rw-r--r--tools/perf/tests/switch-tracking.c10
-rw-r--r--tools/perf/tests/task-exit.c11
-rw-r--r--tools/perf/tests/tests.h2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c4
-rw-r--r--tools/perf/trace/beauty/mmap.c3
-rw-r--r--tools/perf/ui/browser.c21
-rw-r--r--tools/perf/ui/browser.h5
-rw-r--r--tools/perf/ui/browsers/annotate.c730
-rw-r--r--tools/perf/ui/browsers/hists.c135
-rw-r--r--tools/perf/ui/stdio/hist.c6
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c795
-rw-r--r--tools/perf/util/annotate.h124
-rw-r--r--tools/perf/util/auxtrace.c99
-rw-r--r--tools/perf/util/auxtrace.h2
-rw-r--r--tools/perf/util/build-id.c10
-rw-r--r--tools/perf/util/c++/clang-test.cpp2
-rw-r--r--tools/perf/util/c++/clang.cpp11
-rw-r--r--tools/perf/util/cgroup.c128
-rw-r--r--tools/perf/util/cgroup.h13
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c77
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.h2
-rw-r--r--tools/perf/util/cs-etm.c509
-rw-r--r--tools/perf/util/cs-etm.h13
-rw-r--r--tools/perf/util/debug.c1
-rw-r--r--tools/perf/util/dwarf-aux.c2
-rw-r--r--tools/perf/util/env.c4
-rw-r--r--tools/perf/util/env.h9
-rw-r--r--tools/perf/util/event.c20
-rw-r--r--tools/perf/util/evlist.c54
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c50
-rw-r--r--tools/perf/util/evsel.h7
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh2
-rw-r--r--tools/perf/util/header.c324
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c89
-rw-r--r--tools/perf/util/hist.h8
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c64
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h2
-rw-r--r--tools/perf/util/intel-pt.c110
-rw-r--r--tools/perf/util/llvm-utils.c14
-rw-r--r--tools/perf/util/machine.c157
-rw-r--r--tools/perf/util/machine.h6
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/mem2node.c134
-rw-r--r--tools/perf/util/mem2node.h19
-rw-r--r--tools/perf/util/mmap.c114
-rw-r--r--tools/perf/util/mmap.h16
-rw-r--r--tools/perf/util/parse-events.c27
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-events.y18
-rw-r--r--tools/perf/util/pmu.c75
-rw-r--r--tools/perf/util/probe-finder.c13
-rw-r--r--tools/perf/util/python.c110
-rw-r--r--tools/perf/util/record.c43
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c147
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/perf/util/setup.py8
-rw-r--r--tools/perf/util/sort.c48
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/stat.h4
-rw-r--r--tools/perf/util/symbol.c43
-rw-r--r--tools/perf/util/symbol.h19
-rw-r--r--tools/perf/util/syscalltbl.c14
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/thread_map.c5
-rw-r--r--tools/perf/util/thread_map.h3
-rw-r--r--tools/perf/util/trace-event-scripting.c4
-rw-r--r--tools/perf/util/unwind-libdw.c5
-rw-r--r--tools/perf/util/util.h4
-rw-r--r--tools/power/acpi/Makefile.config1
-rw-r--r--tools/power/acpi/common/cmfsize.c38
-rw-r--r--tools/power/acpi/common/getopt.c38
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c40
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixdir.c40
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixmap.c40
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c40
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.h38
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c40
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c38
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c38
-rw-r--r--tools/power/pm-graph/Makefile29
-rw-r--r--tools/power/pm-graph/bootgraph.818
-rwxr-xr-xtools/power/pm-graph/bootgraph.py (renamed from tools/power/pm-graph/analyze_boot.py)219
-rw-r--r--tools/power/pm-graph/config/cgskip.txt65
-rw-r--r--tools/power/pm-graph/config/custom-timeline-functions.cfg205
-rw-r--r--tools/power/pm-graph/config/example.cfg133
-rw-r--r--tools/power/pm-graph/config/freeze-callgraph.cfg94
-rw-r--r--tools/power/pm-graph/config/freeze-dev.cfg93
-rw-r--r--tools/power/pm-graph/config/freeze.cfg93
-rw-r--r--tools/power/pm-graph/config/standby-callgraph.cfg94
-rw-r--r--tools/power/pm-graph/config/standby-dev.cfg93
-rw-r--r--tools/power/pm-graph/config/standby.cfg93
-rw-r--r--tools/power/pm-graph/config/suspend-callgraph.cfg98
-rw-r--r--tools/power/pm-graph/config/suspend-dev.cfg93
-rw-r--r--tools/power/pm-graph/config/suspend-x2-proc.cfg93
-rw-r--r--tools/power/pm-graph/config/suspend.cfg93
-rw-r--r--tools/power/pm-graph/sleepgraph.847
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py (renamed from tools/power/pm-graph/analyze_suspend.py)1625
-rw-r--r--tools/scripts/Makefile.arch11
-rw-r--r--tools/scripts/Makefile.include2
-rwxr-xr-xtools/testing/ktest/config-bisect.pl770
-rw-r--r--tools/testing/ktest/examples/crosstests.conf31
-rwxr-xr-xtools/testing/ktest/ktest.pl535
-rw-r--r--tools/testing/ktest/sample.conf60
-rw-r--r--tools/testing/nvdimm/test/nfit.c323
-rw-r--r--tools/testing/nvdimm/test/nfit_test.h16
-rw-r--r--tools/testing/radix-tree/Makefile6
-rw-r--r--tools/testing/radix-tree/linux/gfp.h1
-rw-r--r--tools/testing/radix-tree/multiorder.c63
-rw-r--r--tools/testing/radix-tree/test.c19
-rw-r--r--tools/testing/radix-tree/test.h3
-rw-r--r--tools/testing/selftests/Makefile14
-rw-r--r--tools/testing/selftests/android/ion/.gitignore1
-rw-r--r--tools/testing/selftests/android/ion/Makefile5
-rw-r--r--tools/testing/selftests/android/ion/config1
-rw-r--r--tools/testing/selftests/android/ion/ionmap_test.c136
-rw-r--r--tools/testing/selftests/android/ion/ionutils.c6
-rw-r--r--tools/testing/selftests/bpf/.gitignore3
-rw-r--r--tools/testing/selftests/bpf/Makefile25
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h12
-rw-r--r--tools/testing/selftests/bpf/bpf_rlimit.h28
-rw-r--r--tools/testing/selftests/bpf/connect4_prog.c45
-rw-r--r--tools/testing/selftests/bpf/connect6_prog.c61
-rw-r--r--tools/testing/selftests/bpf/sockmap_parse_prog.c15
-rw-r--r--tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c33
-rw-r--r--tools/testing/selftests/bpf/sockmap_verdict_prog.c7
-rw-r--r--tools/testing/selftests/bpf/test_align.c6
-rw-r--r--tools/testing/selftests/bpf/test_dev_cgroup.c6
-rw-r--r--tools/testing/selftests/bpf/test_lpm_map.c14
-rw-r--r--tools/testing/selftests/bpf/test_lru_map.c6
-rw-r--r--tools/testing/selftests/bpf/test_maps.c62
-rw-r--r--tools/testing/selftests/bpf/test_progs.c230
-rw-r--r--tools/testing/selftests/bpf/test_sock.c480
-rw-r--r--tools/testing/selftests/bpf/test_sock_addr.c589
-rwxr-xr-xtools/testing/selftests/bpf/test_sock_addr.sh57
-rw-r--r--tools/testing/selftests/bpf/test_stacktrace_build_id.c60
-rw-r--r--tools/testing/selftests/bpf/test_tag.c4
-rw-r--r--tools/testing/selftests/bpf/test_tcpbpf_user.c2
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c304
-rw-r--r--tools/testing/selftests/bpf/test_verifier_log.c8
-rw-r--r--tools/testing/selftests/bpf/urandom_read.c22
-rw-r--r--tools/testing/selftests/filesystems/.gitignore1
-rw-r--r--tools/testing/selftests/filesystems/Makefile8
-rw-r--r--tools/testing/selftests/filesystems/devpts_pts.c313
-rw-r--r--tools/testing/selftests/firmware/Makefile3
-rw-r--r--tools/testing/selftests/firmware/config4
-rwxr-xr-xtools/testing/selftests/firmware/fw_fallback.sh65
-rwxr-xr-xtools/testing/selftests/firmware/fw_filesystem.sh72
-rwxr-xr-xtools/testing/selftests/firmware/fw_lib.sh196
-rwxr-xr-xtools/testing/selftests/firmware/fw_run_tests.sh70
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions7
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc39
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc54
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc58
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc44
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc50
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc50
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc48
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc54
-rw-r--r--tools/testing/selftests/futex/Makefile4
-rw-r--r--tools/testing/selftests/intel_pstate/Makefile5
-rw-r--r--tools/testing/selftests/kselftest.h3
-rw-r--r--tools/testing/selftests/kselftest_harness.h26
-rw-r--r--tools/testing/selftests/kvm/Makefile40
-rw-r--r--tools/testing/selftests/kvm/include/kvm_util.h145
-rw-r--r--tools/testing/selftests/kvm/include/sparsebit.h75
-rw-r--r--tools/testing/selftests/kvm/include/test_util.h46
-rw-r--r--tools/testing/selftests/kvm/include/vmx.h494
-rw-r--r--tools/testing/selftests/kvm/include/x86.h1043
-rw-r--r--tools/testing/selftests/kvm/lib/assert.c87
-rw-r--r--tools/testing/selftests/kvm/lib/elf.c197
-rw-r--r--tools/testing/selftests/kvm/lib/io.c158
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util.c1486
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util_internal.h67
-rw-r--r--tools/testing/selftests/kvm/lib/sparsebit.c2087
-rw-r--r--tools/testing/selftests/kvm/lib/vmx.c243
-rw-r--r--tools/testing/selftests/kvm/lib/x86.c700
-rw-r--r--tools/testing/selftests/kvm/set_sregs_test.c54
-rw-r--r--tools/testing/selftests/kvm/sync_regs_test.c254
-rw-r--r--tools/testing/selftests/kvm/vmx_tsc_adjust_test.c231
-rw-r--r--tools/testing/selftests/lib.mk7
-rw-r--r--tools/testing/selftests/net/Makefile3
-rw-r--r--tools/testing/selftests/net/config5
-rwxr-xr-xtools/testing/selftests/net/fib-onlink-tests.sh467
-rwxr-xr-xtools/testing/selftests/net/fib_tests.sh664
-rw-r--r--tools/testing/selftests/net/forwarding/.gitignore1
-rw-r--r--tools/testing/selftests/net/forwarding/README56
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_vlan_aware.sh88
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh86
-rw-r--r--tools/testing/selftests/net/forwarding/config12
-rw-r--r--tools/testing/selftests/net/forwarding/forwarding.config.sample35
-rw-r--r--tools/testing/selftests/net/forwarding/lib.sh577
-rwxr-xr-xtools/testing/selftests/net/forwarding/router.sh125
-rwxr-xr-xtools/testing/selftests/net/forwarding/router_multipath.sh376
-rwxr-xr-xtools/testing/selftests/net/forwarding/tc_actions.sh202
-rwxr-xr-xtools/testing/selftests/net/forwarding/tc_chains.sh122
-rw-r--r--tools/testing/selftests/net/forwarding/tc_common.sh25
-rwxr-xr-xtools/testing/selftests/net/forwarding/tc_flower.sh196
-rwxr-xr-xtools/testing/selftests/net/forwarding/tc_shblocks.sh122
-rwxr-xr-xtools/testing/selftests/net/in_netns.sh23
-rw-r--r--tools/testing/selftests/net/msg_zerocopy.c131
-rwxr-xr-xtools/testing/selftests/net/pmtu.sh471
-rw-r--r--tools/testing/selftests/net/psock_fanout.c35
-rwxr-xr-xtools/testing/selftests/net/rtnetlink.sh6
-rwxr-xr-xtools/testing/selftests/net/run_afpackettests4
-rw-r--r--tools/testing/selftests/networking/timestamping/txtimestamp.c21
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/Makefile7
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/exec_target.c13
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/fork.c325
-rw-r--r--tools/testing/selftests/powerpc/copyloops/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-sigreturn.c92
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-unavailable.c24
-rw-r--r--tools/testing/selftests/proc/.gitignore8
-rw-r--r--tools/testing/selftests/proc/Makefile13
-rw-r--r--tools/testing/selftests/proc/config1
-rw-r--r--tools/testing/selftests/proc/proc-loadavg-001.c83
-rw-r--r--tools/testing/selftests/proc/proc-self-map-files-001.c82
-rw-r--r--tools/testing/selftests/proc/proc-self-map-files-002.c85
-rw-r--r--tools/testing/selftests/proc/proc-self-syscall.c60
-rw-r--r--tools/testing/selftests/proc/proc-self-wchan.c40
-rw-r--r--tools/testing/selftests/proc/proc-uptime-001.c45
-rw-r--r--tools/testing/selftests/proc/proc-uptime-002.c79
-rw-r--r--tools/testing/selftests/proc/proc-uptime.h74
-rw-r--r--tools/testing/selftests/proc/read.c147
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh17
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh11
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh4
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS031
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE041
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE071
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh24
-rw-r--r--tools/testing/selftests/rcutorture/doc/rcu-test-image.txt2
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c15
-rw-r--r--tools/testing/selftests/tc-testing/README173
-rw-r--r--tools/testing/selftests/tc-testing/TODO.txt25
-rw-r--r--tools/testing/selftests/tc-testing/TdcPlugin.py74
-rw-r--r--tools/testing/selftests/tc-testing/creating-plugins/AddingPlugins.txt104
-rw-r--r--tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt35
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/README-PLUGINS27
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py141
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/rootPlugin.py19
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/valgrindPlugin.py142
-rw-r--r--tools/testing/selftests/tc-testing/plugins/__init__.py0
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json294
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json291
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/csum.json410
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/gact.json71
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json192
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/police.json144
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json168
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json24
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json410
-rwxr-xr-xtools/testing/selftests/tc-testing/tdc.py576
-rwxr-xr-xtools/testing/selftests/tc-testing/tdc_batch.py8
-rw-r--r--tools/testing/selftests/tc-testing/tdc_helper.py15
-rw-r--r--tools/testing/selftests/x86/Makefile2
-rw-r--r--tools/testing/selftests/x86/mov_ss_trap.c285
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c7
-rw-r--r--tools/testing/selftests/x86/pkey-helpers.h20
-rw-r--r--tools/testing/selftests/x86/protection_keys.c254
-rw-r--r--tools/testing/selftests/x86/test_syscall_vdso.c35
-rw-r--r--tools/thermal/tmon/sysfs.c12
-rw-r--r--tools/thermal/tmon/tmon.c1
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.c23
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h11
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.c5
-rw-r--r--tools/usb/usbip/src/usbip_attach.c10
-rw-r--r--tools/usb/usbip/src/usbip_list.c6
-rw-r--r--tools/usb/usbip/src/usbip_network.c10
-rw-r--r--tools/usb/usbip/src/usbip_network.h6
-rw-r--r--tools/usb/usbip/src/usbipd.c34
-rw-r--r--tools/virtio/ringtest/ptr_ring.c5
512 files changed, 38592 insertions, 5612 deletions
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index 6edd177bb1c7..caae4843cb70 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -135,6 +135,15 @@ struct kvm_arch_memory_slot {
135#define KVM_REG_ARM_CRM_SHIFT 7 135#define KVM_REG_ARM_CRM_SHIFT 7
136#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800 136#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
137#define KVM_REG_ARM_32_CRN_SHIFT 11 137#define KVM_REG_ARM_32_CRN_SHIFT 11
138/*
139 * For KVM currently all guest registers are nonsecure, but we reserve a bit
140 * in the encoding to distinguish secure from nonsecure for AArch32 system
141 * registers that are banked by security. This is 1 for the secure banked
142 * register, and 0 for the nonsecure banked register or if the register is
143 * not banked by security.
144 */
145#define KVM_REG_ARM_SECURE_MASK 0x0000000010000000
146#define KVM_REG_ARM_SECURE_SHIFT 28
138 147
139#define ARM_CP15_REG_SHIFT_MASK(x,n) \ 148#define ARM_CP15_REG_SHIFT_MASK(x,n) \
140 (((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK) 149 (((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK)
@@ -186,6 +195,12 @@ struct kvm_arch_memory_slot {
186#define KVM_REG_ARM_VFP_FPINST 0x1009 195#define KVM_REG_ARM_VFP_FPINST 0x1009
187#define KVM_REG_ARM_VFP_FPINST2 0x100A 196#define KVM_REG_ARM_VFP_FPINST2 0x100A
188 197
198/* KVM-as-firmware specific pseudo-registers */
199#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
200#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
201 KVM_REG_ARM_FW | ((r) & 0xffff))
202#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
203
189/* Device Control API: ARM VGIC */ 204/* Device Control API: ARM VGIC */
190#define KVM_DEV_ARM_VGIC_GRP_ADDR 0 205#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
191#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 206#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index 9abbf3044654..04b3256f8e6d 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -206,6 +206,12 @@ struct kvm_arch_memory_slot {
206#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2) 206#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
207#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2) 207#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
208 208
209/* KVM-as-firmware specific pseudo-registers */
210#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
211#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
212 KVM_REG_ARM_FW | ((r) & 0xffff))
213#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
214
209/* Device Control API: ARM VGIC */ 215/* Device Control API: ARM VGIC */
210#define KVM_DEV_ARM_VGIC_GRP_ADDR 0 216#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
211#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 217#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
diff --git a/tools/arch/frv/include/uapi/asm/bitsperlong.h b/tools/arch/frv/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 76da34b10f59..000000000000
--- a/tools/arch/frv/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1,2 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/frv/include/uapi/asm/mman.h b/tools/arch/frv/include/uapi/asm/mman.h
deleted file mode 100644
index 5bc900b0bc78..000000000000
--- a/tools/arch/frv/include/uapi/asm/mman.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
3#define TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
4#include <uapi/asm-generic/mman.h>
5/* MAP_32BIT is undefined on frv, fix it for perf */
6#define MAP_32BIT 0
7#endif
diff --git a/tools/arch/m32r/include/uapi/asm/bitsperlong.h b/tools/arch/m32r/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 76da34b10f59..000000000000
--- a/tools/arch/m32r/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1,2 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/m32r/include/uapi/asm/mman.h b/tools/arch/m32r/include/uapi/asm/mman.h
deleted file mode 100644
index d19b82c9c290..000000000000
--- a/tools/arch/m32r/include/uapi/asm/mman.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
3#define TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
4#include <uapi/asm-generic/mman.h>
5/* MAP_32BIT is undefined on m32r, fix it for perf */
6#define MAP_32BIT 0
7#endif
diff --git a/tools/arch/mn10300/include/uapi/asm/bitsperlong.h b/tools/arch/mn10300/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0c13b2..000000000000
--- a/tools/arch/mn10300/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/mn10300/include/uapi/asm/mman.h b/tools/arch/mn10300/include/uapi/asm/mman.h
deleted file mode 100644
index b9360639974f..000000000000
--- a/tools/arch/mn10300/include/uapi/asm/mman.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
3#define TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
4#include <uapi/asm-generic/mman.h>
5/* MAP_32BIT is undefined on mn10300, fix it for perf */
6#define MAP_32BIT 0
7#endif
diff --git a/tools/arch/powerpc/include/uapi/asm/unistd.h b/tools/arch/powerpc/include/uapi/asm/unistd.h
new file mode 100644
index 000000000000..389c36fd8299
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/unistd.h
@@ -0,0 +1,402 @@
1/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2/*
3 * This file contains the system call numbers.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10#ifndef _UAPI_ASM_POWERPC_UNISTD_H_
11#define _UAPI_ASM_POWERPC_UNISTD_H_
12
13
14#define __NR_restart_syscall 0
15#define __NR_exit 1
16#define __NR_fork 2
17#define __NR_read 3
18#define __NR_write 4
19#define __NR_open 5
20#define __NR_close 6
21#define __NR_waitpid 7
22#define __NR_creat 8
23#define __NR_link 9
24#define __NR_unlink 10
25#define __NR_execve 11
26#define __NR_chdir 12
27#define __NR_time 13
28#define __NR_mknod 14
29#define __NR_chmod 15
30#define __NR_lchown 16
31#define __NR_break 17
32#define __NR_oldstat 18
33#define __NR_lseek 19
34#define __NR_getpid 20
35#define __NR_mount 21
36#define __NR_umount 22
37#define __NR_setuid 23
38#define __NR_getuid 24
39#define __NR_stime 25
40#define __NR_ptrace 26
41#define __NR_alarm 27
42#define __NR_oldfstat 28
43#define __NR_pause 29
44#define __NR_utime 30
45#define __NR_stty 31
46#define __NR_gtty 32
47#define __NR_access 33
48#define __NR_nice 34
49#define __NR_ftime 35
50#define __NR_sync 36
51#define __NR_kill 37
52#define __NR_rename 38
53#define __NR_mkdir 39
54#define __NR_rmdir 40
55#define __NR_dup 41
56#define __NR_pipe 42
57#define __NR_times 43
58#define __NR_prof 44
59#define __NR_brk 45
60#define __NR_setgid 46
61#define __NR_getgid 47
62#define __NR_signal 48
63#define __NR_geteuid 49
64#define __NR_getegid 50
65#define __NR_acct 51
66#define __NR_umount2 52
67#define __NR_lock 53
68#define __NR_ioctl 54
69#define __NR_fcntl 55
70#define __NR_mpx 56
71#define __NR_setpgid 57
72#define __NR_ulimit 58
73#define __NR_oldolduname 59
74#define __NR_umask 60
75#define __NR_chroot 61
76#define __NR_ustat 62
77#define __NR_dup2 63
78#define __NR_getppid 64
79#define __NR_getpgrp 65
80#define __NR_setsid 66
81#define __NR_sigaction 67
82#define __NR_sgetmask 68
83#define __NR_ssetmask 69
84#define __NR_setreuid 70
85#define __NR_setregid 71
86#define __NR_sigsuspend 72
87#define __NR_sigpending 73
88#define __NR_sethostname 74
89#define __NR_setrlimit 75
90#define __NR_getrlimit 76
91#define __NR_getrusage 77
92#define __NR_gettimeofday 78
93#define __NR_settimeofday 79
94#define __NR_getgroups 80
95#define __NR_setgroups 81
96#define __NR_select 82
97#define __NR_symlink 83
98#define __NR_oldlstat 84
99#define __NR_readlink 85
100#define __NR_uselib 86
101#define __NR_swapon 87
102#define __NR_reboot 88
103#define __NR_readdir 89
104#define __NR_mmap 90
105#define __NR_munmap 91
106#define __NR_truncate 92
107#define __NR_ftruncate 93
108#define __NR_fchmod 94
109#define __NR_fchown 95
110#define __NR_getpriority 96
111#define __NR_setpriority 97
112#define __NR_profil 98
113#define __NR_statfs 99
114#define __NR_fstatfs 100
115#define __NR_ioperm 101
116#define __NR_socketcall 102
117#define __NR_syslog 103
118#define __NR_setitimer 104
119#define __NR_getitimer 105
120#define __NR_stat 106
121#define __NR_lstat 107
122#define __NR_fstat 108
123#define __NR_olduname 109
124#define __NR_iopl 110
125#define __NR_vhangup 111
126#define __NR_idle 112
127#define __NR_vm86 113
128#define __NR_wait4 114
129#define __NR_swapoff 115
130#define __NR_sysinfo 116
131#define __NR_ipc 117
132#define __NR_fsync 118
133#define __NR_sigreturn 119
134#define __NR_clone 120
135#define __NR_setdomainname 121
136#define __NR_uname 122
137#define __NR_modify_ldt 123
138#define __NR_adjtimex 124
139#define __NR_mprotect 125
140#define __NR_sigprocmask 126
141#define __NR_create_module 127
142#define __NR_init_module 128
143#define __NR_delete_module 129
144#define __NR_get_kernel_syms 130
145#define __NR_quotactl 131
146#define __NR_getpgid 132
147#define __NR_fchdir 133
148#define __NR_bdflush 134
149#define __NR_sysfs 135
150#define __NR_personality 136
151#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
152#define __NR_setfsuid 138
153#define __NR_setfsgid 139
154#define __NR__llseek 140
155#define __NR_getdents 141
156#define __NR__newselect 142
157#define __NR_flock 143
158#define __NR_msync 144
159#define __NR_readv 145
160#define __NR_writev 146
161#define __NR_getsid 147
162#define __NR_fdatasync 148
163#define __NR__sysctl 149
164#define __NR_mlock 150
165#define __NR_munlock 151
166#define __NR_mlockall 152
167#define __NR_munlockall 153
168#define __NR_sched_setparam 154
169#define __NR_sched_getparam 155
170#define __NR_sched_setscheduler 156
171#define __NR_sched_getscheduler 157
172#define __NR_sched_yield 158
173#define __NR_sched_get_priority_max 159
174#define __NR_sched_get_priority_min 160
175#define __NR_sched_rr_get_interval 161
176#define __NR_nanosleep 162
177#define __NR_mremap 163
178#define __NR_setresuid 164
179#define __NR_getresuid 165
180#define __NR_query_module 166
181#define __NR_poll 167
182#define __NR_nfsservctl 168
183#define __NR_setresgid 169
184#define __NR_getresgid 170
185#define __NR_prctl 171
186#define __NR_rt_sigreturn 172
187#define __NR_rt_sigaction 173
188#define __NR_rt_sigprocmask 174
189#define __NR_rt_sigpending 175
190#define __NR_rt_sigtimedwait 176
191#define __NR_rt_sigqueueinfo 177
192#define __NR_rt_sigsuspend 178
193#define __NR_pread64 179
194#define __NR_pwrite64 180
195#define __NR_chown 181
196#define __NR_getcwd 182
197#define __NR_capget 183
198#define __NR_capset 184
199#define __NR_sigaltstack 185
200#define __NR_sendfile 186
201#define __NR_getpmsg 187 /* some people actually want streams */
202#define __NR_putpmsg 188 /* some people actually want streams */
203#define __NR_vfork 189
204#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
205#define __NR_readahead 191
206#ifndef __powerpc64__ /* these are 32-bit only */
207#define __NR_mmap2 192
208#define __NR_truncate64 193
209#define __NR_ftruncate64 194
210#define __NR_stat64 195
211#define __NR_lstat64 196
212#define __NR_fstat64 197
213#endif
214#define __NR_pciconfig_read 198
215#define __NR_pciconfig_write 199
216#define __NR_pciconfig_iobase 200
217#define __NR_multiplexer 201
218#define __NR_getdents64 202
219#define __NR_pivot_root 203
220#ifndef __powerpc64__
221#define __NR_fcntl64 204
222#endif
223#define __NR_madvise 205
224#define __NR_mincore 206
225#define __NR_gettid 207
226#define __NR_tkill 208
227#define __NR_setxattr 209
228#define __NR_lsetxattr 210
229#define __NR_fsetxattr 211
230#define __NR_getxattr 212
231#define __NR_lgetxattr 213
232#define __NR_fgetxattr 214
233#define __NR_listxattr 215
234#define __NR_llistxattr 216
235#define __NR_flistxattr 217
236#define __NR_removexattr 218
237#define __NR_lremovexattr 219
238#define __NR_fremovexattr 220
239#define __NR_futex 221
240#define __NR_sched_setaffinity 222
241#define __NR_sched_getaffinity 223
242/* 224 currently unused */
243#define __NR_tuxcall 225
244#ifndef __powerpc64__
245#define __NR_sendfile64 226
246#endif
247#define __NR_io_setup 227
248#define __NR_io_destroy 228
249#define __NR_io_getevents 229
250#define __NR_io_submit 230
251#define __NR_io_cancel 231
252#define __NR_set_tid_address 232
253#define __NR_fadvise64 233
254#define __NR_exit_group 234
255#define __NR_lookup_dcookie 235
256#define __NR_epoll_create 236
257#define __NR_epoll_ctl 237
258#define __NR_epoll_wait 238
259#define __NR_remap_file_pages 239
260#define __NR_timer_create 240
261#define __NR_timer_settime 241
262#define __NR_timer_gettime 242
263#define __NR_timer_getoverrun 243
264#define __NR_timer_delete 244
265#define __NR_clock_settime 245
266#define __NR_clock_gettime 246
267#define __NR_clock_getres 247
268#define __NR_clock_nanosleep 248
269#define __NR_swapcontext 249
270#define __NR_tgkill 250
271#define __NR_utimes 251
272#define __NR_statfs64 252
273#define __NR_fstatfs64 253
274#ifndef __powerpc64__
275#define __NR_fadvise64_64 254
276#endif
277#define __NR_rtas 255
278#define __NR_sys_debug_setcontext 256
279/* Number 257 is reserved for vserver */
280#define __NR_migrate_pages 258
281#define __NR_mbind 259
282#define __NR_get_mempolicy 260
283#define __NR_set_mempolicy 261
284#define __NR_mq_open 262
285#define __NR_mq_unlink 263
286#define __NR_mq_timedsend 264
287#define __NR_mq_timedreceive 265
288#define __NR_mq_notify 266
289#define __NR_mq_getsetattr 267
290#define __NR_kexec_load 268
291#define __NR_add_key 269
292#define __NR_request_key 270
293#define __NR_keyctl 271
294#define __NR_waitid 272
295#define __NR_ioprio_set 273
296#define __NR_ioprio_get 274
297#define __NR_inotify_init 275
298#define __NR_inotify_add_watch 276
299#define __NR_inotify_rm_watch 277
300#define __NR_spu_run 278
301#define __NR_spu_create 279
302#define __NR_pselect6 280
303#define __NR_ppoll 281
304#define __NR_unshare 282
305#define __NR_splice 283
306#define __NR_tee 284
307#define __NR_vmsplice 285
308#define __NR_openat 286
309#define __NR_mkdirat 287
310#define __NR_mknodat 288
311#define __NR_fchownat 289
312#define __NR_futimesat 290
313#ifdef __powerpc64__
314#define __NR_newfstatat 291
315#else
316#define __NR_fstatat64 291
317#endif
318#define __NR_unlinkat 292
319#define __NR_renameat 293
320#define __NR_linkat 294
321#define __NR_symlinkat 295
322#define __NR_readlinkat 296
323#define __NR_fchmodat 297
324#define __NR_faccessat 298
325#define __NR_get_robust_list 299
326#define __NR_set_robust_list 300
327#define __NR_move_pages 301
328#define __NR_getcpu 302
329#define __NR_epoll_pwait 303
330#define __NR_utimensat 304
331#define __NR_signalfd 305
332#define __NR_timerfd_create 306
333#define __NR_eventfd 307
334#define __NR_sync_file_range2 308
335#define __NR_fallocate 309
336#define __NR_subpage_prot 310
337#define __NR_timerfd_settime 311
338#define __NR_timerfd_gettime 312
339#define __NR_signalfd4 313
340#define __NR_eventfd2 314
341#define __NR_epoll_create1 315
342#define __NR_dup3 316
343#define __NR_pipe2 317
344#define __NR_inotify_init1 318
345#define __NR_perf_event_open 319
346#define __NR_preadv 320
347#define __NR_pwritev 321
348#define __NR_rt_tgsigqueueinfo 322
349#define __NR_fanotify_init 323
350#define __NR_fanotify_mark 324
351#define __NR_prlimit64 325
352#define __NR_socket 326
353#define __NR_bind 327
354#define __NR_connect 328
355#define __NR_listen 329
356#define __NR_accept 330
357#define __NR_getsockname 331
358#define __NR_getpeername 332
359#define __NR_socketpair 333
360#define __NR_send 334
361#define __NR_sendto 335
362#define __NR_recv 336
363#define __NR_recvfrom 337
364#define __NR_shutdown 338
365#define __NR_setsockopt 339
366#define __NR_getsockopt 340
367#define __NR_sendmsg 341
368#define __NR_recvmsg 342
369#define __NR_recvmmsg 343
370#define __NR_accept4 344
371#define __NR_name_to_handle_at 345
372#define __NR_open_by_handle_at 346
373#define __NR_clock_adjtime 347
374#define __NR_syncfs 348
375#define __NR_sendmmsg 349
376#define __NR_setns 350
377#define __NR_process_vm_readv 351
378#define __NR_process_vm_writev 352
379#define __NR_finit_module 353
380#define __NR_kcmp 354
381#define __NR_sched_setattr 355
382#define __NR_sched_getattr 356
383#define __NR_renameat2 357
384#define __NR_seccomp 358
385#define __NR_getrandom 359
386#define __NR_memfd_create 360
387#define __NR_bpf 361
388#define __NR_execveat 362
389#define __NR_switch_endian 363
390#define __NR_userfaultfd 364
391#define __NR_membarrier 365
392#define __NR_mlock2 378
393#define __NR_copy_file_range 379
394#define __NR_preadv2 380
395#define __NR_pwritev2 381
396#define __NR_kexec_file_load 382
397#define __NR_statx 383
398#define __NR_pkey_alloc 384
399#define __NR_pkey_free 385
400#define __NR_pkey_mprotect 386
401
402#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/tools/arch/score/include/uapi/asm/bitsperlong.h b/tools/arch/score/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index df48f2717da2..000000000000
--- a/tools/arch/score/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _ASM_SCORE_BITSPERLONG_H
3#define _ASM_SCORE_BITSPERLONG_H
4
5#include <asm-generic/bitsperlong.h>
6
7#endif /* _ASM_SCORE_BITSPERLONG_H */
diff --git a/tools/arch/score/include/uapi/asm/mman.h b/tools/arch/score/include/uapi/asm/mman.h
deleted file mode 100644
index b4bd195a8586..000000000000
--- a/tools/arch/score/include/uapi/asm/mman.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
3#define TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
4#include <uapi/asm-generic/mman.h>
5/* MAP_32BIT is undefined on score, fix it for perf */
6#define MAP_32BIT 0
7#endif
diff --git a/tools/arch/tile/include/asm/barrier.h b/tools/arch/tile/include/asm/barrier.h
deleted file mode 100644
index 7ad02a591b43..000000000000
--- a/tools/arch/tile/include/asm/barrier.h
+++ /dev/null
@@ -1,16 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _TOOLS_LINUX_ASM_TILE_BARRIER_H
3#define _TOOLS_LINUX_ASM_TILE_BARRIER_H
4/*
5 * FIXME: This came from tools/perf/perf-sys.h, where it was first introduced
6 * in 620830b6954913647b7c7f68920cf48eddf6ad92, more work needed to make it
7 * more closely follow the Linux kernel arch/tile/include/asm/barrier.h file.
8 * Probably when we continue work on tools/ Kconfig support to have all the
9 * CONFIG_ needed for properly doing that.
10 */
11
12#define mb() asm volatile ("mf" ::: "memory")
13#define wmb() mb()
14#define rmb() mb()
15
16#endif /* _TOOLS_LINUX_ASM_TILE_BARRIER_H */
diff --git a/tools/arch/tile/include/uapi/asm/bitsperlong.h b/tools/arch/tile/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 57cca78c0fbb..000000000000
--- a/tools/arch/tile/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * Copyright 2010 Tilera Corporation. All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation, version 2.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12 * NON INFRINGEMENT. See the GNU General Public License for
13 * more details.
14 */
15
16#ifndef _ASM_TILE_BITSPERLONG_H
17#define _ASM_TILE_BITSPERLONG_H
18
19#ifdef __LP64__
20# define __BITS_PER_LONG 64
21#else
22# define __BITS_PER_LONG 32
23#endif
24
25#include <asm-generic/bitsperlong.h>
26
27#endif /* _ASM_TILE_BITSPERLONG_H */
diff --git a/tools/arch/tile/include/uapi/asm/mman.h b/tools/arch/tile/include/uapi/asm/mman.h
deleted file mode 100644
index 65ec92925c6c..000000000000
--- a/tools/arch/tile/include/uapi/asm/mman.h
+++ /dev/null
@@ -1,16 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
3#define TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
4#define MAP_DENYWRITE 0x0800
5#define MAP_EXECUTABLE 0x1000
6#define MAP_GROWSDOWN 0x0100
7#define MAP_HUGETLB 0x4000
8#define MAP_LOCKED 0x0200
9#define MAP_NONBLOCK 0x0080
10#define MAP_NORESERVE 0x0400
11#define MAP_POPULATE 0x0040
12#define MAP_STACK MAP_GROWSDOWN
13#include <uapi/asm-generic/mman-common.h>
14/* MAP_32BIT is undefined on tile, fix it for perf */
15#define MAP_32BIT 0
16#endif
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index f41079da38c5..578793e97431 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -316,9 +316,11 @@
316#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ 316#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */
317#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ 317#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */
318#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ 318#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */
319#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */
319#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ 320#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
320#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ 321#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */
321#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ 322#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */
323#define X86_FEATURE_CLDEMOTE (16*32+25) /* CLDEMOTE instruction */
322 324
323/* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */ 325/* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
324#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */ 326#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */
@@ -328,6 +330,7 @@
328/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ 330/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
329#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ 331#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
330#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ 332#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
333#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
331#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ 334#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
332#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ 335#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
333#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ 336#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h
index fb3a6de7440b..6847d85400a8 100644
--- a/tools/arch/x86/include/asm/required-features.h
+++ b/tools/arch/x86/include/asm/required-features.h
@@ -53,12 +53,6 @@
53# define NEED_MOVBE 0 53# define NEED_MOVBE 0
54#endif 54#endif
55 55
56#ifdef CONFIG_X86_5LEVEL
57# define NEED_LA57 (1<<(X86_FEATURE_LA57 & 31))
58#else
59# define NEED_LA57 0
60#endif
61
62#ifdef CONFIG_X86_64 56#ifdef CONFIG_X86_64
63#ifdef CONFIG_PARAVIRT 57#ifdef CONFIG_PARAVIRT
64/* Paravirtualized systems may not have PSE or PGE available */ 58/* Paravirtualized systems may not have PSE or PGE available */
@@ -104,7 +98,7 @@
104#define REQUIRED_MASK13 0 98#define REQUIRED_MASK13 0
105#define REQUIRED_MASK14 0 99#define REQUIRED_MASK14 0
106#define REQUIRED_MASK15 0 100#define REQUIRED_MASK15 0
107#define REQUIRED_MASK16 (NEED_LA57) 101#define REQUIRED_MASK16 0
108#define REQUIRED_MASK17 0 102#define REQUIRED_MASK17 0
109#define REQUIRED_MASK18 0 103#define REQUIRED_MASK18 0
110#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19) 104#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index f3a960488eae..c535c2fdea13 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -354,8 +354,25 @@ struct kvm_xcrs {
354 __u64 padding[16]; 354 __u64 padding[16];
355}; 355};
356 356
357/* definition of registers in kvm_run */ 357#define KVM_SYNC_X86_REGS (1UL << 0)
358#define KVM_SYNC_X86_SREGS (1UL << 1)
359#define KVM_SYNC_X86_EVENTS (1UL << 2)
360
361#define KVM_SYNC_X86_VALID_FIELDS \
362 (KVM_SYNC_X86_REGS| \
363 KVM_SYNC_X86_SREGS| \
364 KVM_SYNC_X86_EVENTS)
365
366/* kvm_sync_regs struct included by kvm_run struct */
358struct kvm_sync_regs { 367struct kvm_sync_regs {
368 /* Members of this structure are potentially malicious.
369 * Care must be taken by code reading, esp. interpreting,
370 * data fields from them inside KVM to prevent TOCTOU and
371 * double-fetch types of vulnerabilities.
372 */
373 struct kvm_regs regs;
374 struct kvm_sregs sregs;
375 struct kvm_vcpu_events events;
359}; 376};
360 377
361#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) 378#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index c8ec0ae16bf0..53b60ad452f5 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -1,19 +1,28 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2prefix = /usr 2include ../scripts/Makefile.include
3
4prefix ?= /usr/local
3 5
4CC = gcc 6CC = gcc
5LEX = flex 7LEX = flex
6YACC = bison 8YACC = bison
7MAKE = make 9MAKE = make
10INSTALL ?= install
8 11
9CFLAGS += -Wall -O2 12CFLAGS += -Wall -O2
10CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 13CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/include/uapi -I$(srctree)/include
11 14
12ifeq ($(srctree),) 15ifeq ($(srctree),)
13srctree := $(patsubst %/,%,$(dir $(CURDIR))) 16srctree := $(patsubst %/,%,$(dir $(CURDIR)))
14srctree := $(patsubst %/,%,$(dir $(srctree))) 17srctree := $(patsubst %/,%,$(dir $(srctree)))
15endif 18endif
16 19
20ifeq ($(V),1)
21 Q =
22else
23 Q = @
24endif
25
17FEATURE_USER = .bpf 26FEATURE_USER = .bpf
18FEATURE_TESTS = libbfd disassembler-four-args 27FEATURE_TESTS = libbfd disassembler-four-args
19FEATURE_DISPLAY = libbfd disassembler-four-args 28FEATURE_DISPLAY = libbfd disassembler-four-args
@@ -38,40 +47,61 @@ ifeq ($(feature-disassembler-four-args), 1)
38CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE 47CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
39endif 48endif
40 49
41%.yacc.c: %.y 50$(OUTPUT)%.yacc.c: $(srctree)/tools/bpf/%.y
42 $(YACC) -o $@ -d $< 51 $(QUIET_BISON)$(YACC) -o $@ -d $<
43 52
44%.lex.c: %.l 53$(OUTPUT)%.lex.c: $(srctree)/tools/bpf/%.l
45 $(LEX) -o $@ $< 54 $(QUIET_FLEX)$(LEX) -o $@ $<
46 55
47all: bpf_jit_disasm bpf_dbg bpf_asm bpftool 56$(OUTPUT)%.o: $(srctree)/tools/bpf/%.c
57 $(QUIET_CC)$(COMPILE.c) -o $@ $<
48 58
49bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm' 59$(OUTPUT)%.yacc.o: $(OUTPUT)%.yacc.c
50bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl 60 $(QUIET_CC)$(COMPILE.c) -o $@ $<
51bpf_jit_disasm : bpf_jit_disasm.o 61$(OUTPUT)%.lex.o: $(OUTPUT)%.lex.c
62 $(QUIET_CC)$(COMPILE.c) -o $@ $<
52 63
53bpf_dbg : LDLIBS = -lreadline 64PROGS = $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm
54bpf_dbg : bpf_dbg.o
55 65
56bpf_asm : LDLIBS = 66all: $(PROGS) bpftool
57bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
58bpf_exp.lex.o : bpf_exp.yacc.c
59 67
60clean: bpftool_clean 68$(OUTPUT)bpf_jit_disasm: CFLAGS += -DPACKAGE='bpf_jit_disasm'
61 rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.* 69$(OUTPUT)bpf_jit_disasm: $(OUTPUT)bpf_jit_disasm.o
70 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ -lopcodes -lbfd -ldl
62 71
63install: bpftool_install 72$(OUTPUT)bpf_dbg: $(OUTPUT)bpf_dbg.o
64 install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm 73 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ -lreadline
65 install bpf_dbg $(prefix)/bin/bpf_dbg 74
66 install bpf_asm $(prefix)/bin/bpf_asm 75$(OUTPUT)bpf_asm: $(OUTPUT)bpf_asm.o $(OUTPUT)bpf_exp.yacc.o $(OUTPUT)bpf_exp.lex.o
76 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^
77
78$(OUTPUT)bpf_exp.lex.c: $(OUTPUT)bpf_exp.yacc.c
79$(OUTPUT)bpf_exp.yacc.o: $(OUTPUT)bpf_exp.yacc.c
80$(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.lex.c
81
82clean: bpftool_clean
83 $(call QUIET_CLEAN, bpf-progs)
84 $(Q)rm -rf $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
85 $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
86 $(call QUIET_CLEAN, core-gen)
87 $(Q)rm -f $(OUTPUT)FEATURE-DUMP.bpf
88
89install: $(PROGS) bpftool_install
90 $(call QUIET_INSTALL, bpf_jit_disasm)
91 $(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
92 $(Q)$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm
93 $(call QUIET_INSTALL, bpf_dbg)
94 $(Q)$(INSTALL) $(OUTPUT)bpf_dbg $(DESTDIR)$(prefix)/bin/bpf_dbg
95 $(call QUIET_INSTALL, bpf_asm)
96 $(Q)$(INSTALL) $(OUTPUT)bpf_asm $(DESTDIR)$(prefix)/bin/bpf_asm
67 97
68bpftool: 98bpftool:
69 $(MAKE) -C bpftool 99 $(call descend,bpftool)
70 100
71bpftool_install: 101bpftool_install:
72 $(MAKE) -C bpftool install 102 $(call descend,bpftool,install)
73 103
74bpftool_clean: 104bpftool_clean:
75 $(MAKE) -C bpftool clean 105 $(call descend,bpftool,clean)
76 106
77.PHONY: bpftool FORCE 107.PHONY: all install clean bpftool bpftool_install bpftool_clean
diff --git a/tools/bpf/bpf_dbg.c b/tools/bpf/bpf_dbg.c
index 4f254bcc4423..61b9aa5d6415 100644
--- a/tools/bpf/bpf_dbg.c
+++ b/tools/bpf/bpf_dbg.c
@@ -1063,7 +1063,7 @@ static int cmd_load_pcap(char *file)
1063 1063
1064static int cmd_load(char *arg) 1064static int cmd_load(char *arg)
1065{ 1065{
1066 char *subcmd, *cont, *tmp = strdup(arg); 1066 char *subcmd, *cont = NULL, *tmp = strdup(arg);
1067 int ret = CMD_OK; 1067 int ret = CMD_OK;
1068 1068
1069 subcmd = strtok_r(tmp, " ", &cont); 1069 subcmd = strtok_r(tmp, " ", &cont);
@@ -1073,7 +1073,10 @@ static int cmd_load(char *arg)
1073 bpf_reset(); 1073 bpf_reset();
1074 bpf_reset_breakpoints(); 1074 bpf_reset_breakpoints();
1075 1075
1076 ret = cmd_load_bpf(cont); 1076 if (!cont)
1077 ret = CMD_ERR;
1078 else
1079 ret = cmd_load_bpf(cont);
1077 } else if (matches(subcmd, "pcap") == 0) { 1080 } else if (matches(subcmd, "pcap") == 0) {
1078 ret = cmd_load_pcap(cont); 1081 ret = cmd_load_pcap(cont);
1079 } else { 1082 } else {
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index e4ceee7f2dff..67ca6c69376c 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -21,7 +21,7 @@ MAP COMMANDS
21============= 21=============
22 22
23| **bpftool** **prog { show | list }** [*PROG*] 23| **bpftool** **prog { show | list }** [*PROG*]
24| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes**}] 24| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}]
25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] 25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
26| **bpftool** **prog pin** *PROG* *FILE* 26| **bpftool** **prog pin** *PROG* *FILE*
27| **bpftool** **prog load** *OBJ* *FILE* 27| **bpftool** **prog load** *OBJ* *FILE*
@@ -39,12 +39,18 @@ DESCRIPTION
39 Output will start with program ID followed by program type and 39 Output will start with program ID followed by program type and
40 zero or more named attributes (depending on kernel version). 40 zero or more named attributes (depending on kernel version).
41 41
42 **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** }] 42 **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** | **visual** }]
43 Dump eBPF instructions of the program from the kernel. 43 Dump eBPF instructions of the program from the kernel. By
44 If *FILE* is specified image will be written to a file, 44 default, eBPF will be disassembled and printed to standard
45 otherwise it will be disassembled and printed to stdout. 45 output in human-readable format. In this case, **opcodes**
46 controls if raw opcodes should be printed as well.
46 47
47 **opcodes** controls if raw opcodes will be printed. 48 If **file** is specified, the binary image will instead be
49 written to *FILE*.
50
51 If **visual** is specified, control flow graph (CFG) will be
52 built instead, and eBPF instructions will be presented with
53 CFG in DOT format, on standard output.
48 54
49 **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** }] 55 **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** }]
50 Dump jited image (host machine code) of the program. 56 Dump jited image (host machine code) of the program.
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 26901ec87361..4e69782c4a79 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -38,7 +38,7 @@ bash_compdir ?= /usr/share/bash-completion/completions
38CC = gcc 38CC = gcc
39 39
40CFLAGS += -O2 40CFLAGS += -O2
41CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow 41CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow -Wno-missing-field-initializers
42CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/ 42CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
43CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"' 43CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"'
44LIBS = -lelf -lbfd -lopcodes $(LIBBPF) 44LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
@@ -70,7 +70,7 @@ ifeq ($(feature-disassembler-four-args), 1)
70CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE 70CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
71endif 71endif
72 72
73include $(wildcard *.d) 73include $(wildcard $(OUTPUT)*.d)
74 74
75all: $(OUTPUT)bpftool 75all: $(OUTPUT)bpftool
76 76
@@ -89,6 +89,8 @@ $(OUTPUT)%.o: %.c
89clean: $(LIBBPF)-clean 89clean: $(LIBBPF)-clean
90 $(call QUIET_CLEAN, bpftool) 90 $(call QUIET_CLEAN, bpftool)
91 $(Q)$(RM) $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d 91 $(Q)$(RM) $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d
92 $(call QUIET_CLEAN, core-gen)
93 $(Q)$(RM) $(OUTPUT)FEATURE-DUMP.bpftool
92 94
93install: $(OUTPUT)bpftool 95install: $(OUTPUT)bpftool
94 $(call QUIET_INSTALL, bpftool) 96 $(call QUIET_INSTALL, bpftool)
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 08719c54a614..490811b45fa7 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -147,7 +147,7 @@ _bpftool()
147 147
148 # Deal with simplest keywords 148 # Deal with simplest keywords
149 case $prev in 149 case $prev in
150 help|key|opcodes) 150 help|key|opcodes|visual)
151 return 0 151 return 0
152 ;; 152 ;;
153 tag) 153 tag)
@@ -223,11 +223,16 @@ _bpftool()
223 return 0 223 return 0
224 ;; 224 ;;
225 *) 225 *)
226 _bpftool_once_attr 'file' 226 _bpftool_once_attr 'file'
227 if _bpftool_search_list 'xlated'; then
228 COMPREPLY+=( $( compgen -W 'opcodes visual' -- \
229 "$cur" ) )
230 else
227 COMPREPLY+=( $( compgen -W 'opcodes' -- \ 231 COMPREPLY+=( $( compgen -W 'opcodes' -- \
228 "$cur" ) ) 232 "$cur" ) )
229 return 0 233 fi
230 ;; 234 return 0
235 ;;
231 esac 236 esac
232 ;; 237 ;;
233 pin) 238 pin)
diff --git a/tools/bpf/bpftool/cfg.c b/tools/bpf/bpftool/cfg.c
new file mode 100644
index 000000000000..f30b3a4a840b
--- /dev/null
+++ b/tools/bpf/bpftool/cfg.c
@@ -0,0 +1,514 @@
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2/*
3 * Copyright (C) 2018 Netronome Systems, Inc.
4 *
5 * This software is dual licensed under the GNU General License Version 2,
6 * June 1991 as shown in the file COPYING in the top-level directory of this
7 * source tree or the BSD 2-Clause License provided below. You have the
8 * option to license this software under the complete terms of either license.
9 *
10 * The BSD 2-Clause License:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/list.h>
39#include <stdlib.h>
40#include <string.h>
41
42#include "cfg.h"
43#include "main.h"
44#include "xlated_dumper.h"
45
46struct cfg {
47 struct list_head funcs;
48 int func_num;
49};
50
51struct func_node {
52 struct list_head l;
53 struct list_head bbs;
54 struct bpf_insn *start;
55 struct bpf_insn *end;
56 int idx;
57 int bb_num;
58};
59
60struct bb_node {
61 struct list_head l;
62 struct list_head e_prevs;
63 struct list_head e_succs;
64 struct bpf_insn *head;
65 struct bpf_insn *tail;
66 int idx;
67};
68
69#define EDGE_FLAG_EMPTY 0x0
70#define EDGE_FLAG_FALLTHROUGH 0x1
71#define EDGE_FLAG_JUMP 0x2
72struct edge_node {
73 struct list_head l;
74 struct bb_node *src;
75 struct bb_node *dst;
76 int flags;
77};
78
79#define ENTRY_BLOCK_INDEX 0
80#define EXIT_BLOCK_INDEX 1
81#define NUM_FIXED_BLOCKS 2
82#define func_prev(func) list_prev_entry(func, l)
83#define func_next(func) list_next_entry(func, l)
84#define bb_prev(bb) list_prev_entry(bb, l)
85#define bb_next(bb) list_next_entry(bb, l)
86#define entry_bb(func) func_first_bb(func)
87#define exit_bb(func) func_last_bb(func)
88#define cfg_first_func(cfg) \
89 list_first_entry(&cfg->funcs, struct func_node, l)
90#define cfg_last_func(cfg) \
91 list_last_entry(&cfg->funcs, struct func_node, l)
92#define func_first_bb(func) \
93 list_first_entry(&func->bbs, struct bb_node, l)
94#define func_last_bb(func) \
95 list_last_entry(&func->bbs, struct bb_node, l)
96
97static struct func_node *cfg_append_func(struct cfg *cfg, struct bpf_insn *insn)
98{
99 struct func_node *new_func, *func;
100
101 list_for_each_entry(func, &cfg->funcs, l) {
102 if (func->start == insn)
103 return func;
104 else if (func->start > insn)
105 break;
106 }
107
108 func = func_prev(func);
109 new_func = calloc(1, sizeof(*new_func));
110 if (!new_func) {
111 p_err("OOM when allocating FUNC node");
112 return NULL;
113 }
114 new_func->start = insn;
115 new_func->idx = cfg->func_num;
116 list_add(&new_func->l, &func->l);
117 cfg->func_num++;
118
119 return new_func;
120}
121
122static struct bb_node *func_append_bb(struct func_node *func,
123 struct bpf_insn *insn)
124{
125 struct bb_node *new_bb, *bb;
126
127 list_for_each_entry(bb, &func->bbs, l) {
128 if (bb->head == insn)
129 return bb;
130 else if (bb->head > insn)
131 break;
132 }
133
134 bb = bb_prev(bb);
135 new_bb = calloc(1, sizeof(*new_bb));
136 if (!new_bb) {
137 p_err("OOM when allocating BB node");
138 return NULL;
139 }
140 new_bb->head = insn;
141 INIT_LIST_HEAD(&new_bb->e_prevs);
142 INIT_LIST_HEAD(&new_bb->e_succs);
143 list_add(&new_bb->l, &bb->l);
144
145 return new_bb;
146}
147
148static struct bb_node *func_insert_dummy_bb(struct list_head *after)
149{
150 struct bb_node *bb;
151
152 bb = calloc(1, sizeof(*bb));
153 if (!bb) {
154 p_err("OOM when allocating BB node");
155 return NULL;
156 }
157
158 INIT_LIST_HEAD(&bb->e_prevs);
159 INIT_LIST_HEAD(&bb->e_succs);
160 list_add(&bb->l, after);
161
162 return bb;
163}
164
165static bool cfg_partition_funcs(struct cfg *cfg, struct bpf_insn *cur,
166 struct bpf_insn *end)
167{
168 struct func_node *func, *last_func;
169
170 func = cfg_append_func(cfg, cur);
171 if (!func)
172 return true;
173
174 for (; cur < end; cur++) {
175 if (cur->code != (BPF_JMP | BPF_CALL))
176 continue;
177 if (cur->src_reg != BPF_PSEUDO_CALL)
178 continue;
179 func = cfg_append_func(cfg, cur + cur->off + 1);
180 if (!func)
181 return true;
182 }
183
184 last_func = cfg_last_func(cfg);
185 last_func->end = end - 1;
186 func = cfg_first_func(cfg);
187 list_for_each_entry_from(func, &last_func->l, l) {
188 func->end = func_next(func)->start - 1;
189 }
190
191 return false;
192}
193
194static bool func_partition_bb_head(struct func_node *func)
195{
196 struct bpf_insn *cur, *end;
197 struct bb_node *bb;
198
199 cur = func->start;
200 end = func->end;
201 INIT_LIST_HEAD(&func->bbs);
202 bb = func_append_bb(func, cur);
203 if (!bb)
204 return true;
205
206 for (; cur <= end; cur++) {
207 if (BPF_CLASS(cur->code) == BPF_JMP) {
208 u8 opcode = BPF_OP(cur->code);
209
210 if (opcode == BPF_EXIT || opcode == BPF_CALL)
211 continue;
212
213 bb = func_append_bb(func, cur + cur->off + 1);
214 if (!bb)
215 return true;
216
217 if (opcode != BPF_JA) {
218 bb = func_append_bb(func, cur + 1);
219 if (!bb)
220 return true;
221 }
222 }
223 }
224
225 return false;
226}
227
228static void func_partition_bb_tail(struct func_node *func)
229{
230 unsigned int bb_idx = NUM_FIXED_BLOCKS;
231 struct bb_node *bb, *last;
232
233 last = func_last_bb(func);
234 last->tail = func->end;
235 bb = func_first_bb(func);
236 list_for_each_entry_from(bb, &last->l, l) {
237 bb->tail = bb_next(bb)->head - 1;
238 bb->idx = bb_idx++;
239 }
240
241 last->idx = bb_idx++;
242 func->bb_num = bb_idx;
243}
244
245static bool func_add_special_bb(struct func_node *func)
246{
247 struct bb_node *bb;
248
249 bb = func_insert_dummy_bb(&func->bbs);
250 if (!bb)
251 return true;
252 bb->idx = ENTRY_BLOCK_INDEX;
253
254 bb = func_insert_dummy_bb(&func_last_bb(func)->l);
255 if (!bb)
256 return true;
257 bb->idx = EXIT_BLOCK_INDEX;
258
259 return false;
260}
261
262static bool func_partition_bb(struct func_node *func)
263{
264 if (func_partition_bb_head(func))
265 return true;
266
267 func_partition_bb_tail(func);
268
269 return false;
270}
271
272static struct bb_node *func_search_bb_with_head(struct func_node *func,
273 struct bpf_insn *insn)
274{
275 struct bb_node *bb;
276
277 list_for_each_entry(bb, &func->bbs, l) {
278 if (bb->head == insn)
279 return bb;
280 }
281
282 return NULL;
283}
284
285static struct edge_node *new_edge(struct bb_node *src, struct bb_node *dst,
286 int flags)
287{
288 struct edge_node *e;
289
290 e = calloc(1, sizeof(*e));
291 if (!e) {
292 p_err("OOM when allocating edge node");
293 return NULL;
294 }
295
296 if (src)
297 e->src = src;
298 if (dst)
299 e->dst = dst;
300
301 e->flags |= flags;
302
303 return e;
304}
305
306static bool func_add_bb_edges(struct func_node *func)
307{
308 struct bpf_insn *insn;
309 struct edge_node *e;
310 struct bb_node *bb;
311
312 bb = entry_bb(func);
313 e = new_edge(bb, bb_next(bb), EDGE_FLAG_FALLTHROUGH);
314 if (!e)
315 return true;
316 list_add_tail(&e->l, &bb->e_succs);
317
318 bb = exit_bb(func);
319 e = new_edge(bb_prev(bb), bb, EDGE_FLAG_FALLTHROUGH);
320 if (!e)
321 return true;
322 list_add_tail(&e->l, &bb->e_prevs);
323
324 bb = entry_bb(func);
325 bb = bb_next(bb);
326 list_for_each_entry_from(bb, &exit_bb(func)->l, l) {
327 e = new_edge(bb, NULL, EDGE_FLAG_EMPTY);
328 if (!e)
329 return true;
330 e->src = bb;
331
332 insn = bb->tail;
333 if (BPF_CLASS(insn->code) != BPF_JMP ||
334 BPF_OP(insn->code) == BPF_EXIT) {
335 e->dst = bb_next(bb);
336 e->flags |= EDGE_FLAG_FALLTHROUGH;
337 list_add_tail(&e->l, &bb->e_succs);
338 continue;
339 } else if (BPF_OP(insn->code) == BPF_JA) {
340 e->dst = func_search_bb_with_head(func,
341 insn + insn->off + 1);
342 e->flags |= EDGE_FLAG_JUMP;
343 list_add_tail(&e->l, &bb->e_succs);
344 continue;
345 }
346
347 e->dst = bb_next(bb);
348 e->flags |= EDGE_FLAG_FALLTHROUGH;
349 list_add_tail(&e->l, &bb->e_succs);
350
351 e = new_edge(bb, NULL, EDGE_FLAG_JUMP);
352 if (!e)
353 return true;
354 e->src = bb;
355 e->dst = func_search_bb_with_head(func, insn + insn->off + 1);
356 list_add_tail(&e->l, &bb->e_succs);
357 }
358
359 return false;
360}
361
362static bool cfg_build(struct cfg *cfg, struct bpf_insn *insn, unsigned int len)
363{
364 int cnt = len / sizeof(*insn);
365 struct func_node *func;
366
367 INIT_LIST_HEAD(&cfg->funcs);
368
369 if (cfg_partition_funcs(cfg, insn, insn + cnt))
370 return true;
371
372 list_for_each_entry(func, &cfg->funcs, l) {
373 if (func_partition_bb(func) || func_add_special_bb(func))
374 return true;
375
376 if (func_add_bb_edges(func))
377 return true;
378 }
379
380 return false;
381}
382
383static void cfg_destroy(struct cfg *cfg)
384{
385 struct func_node *func, *func2;
386
387 list_for_each_entry_safe(func, func2, &cfg->funcs, l) {
388 struct bb_node *bb, *bb2;
389
390 list_for_each_entry_safe(bb, bb2, &func->bbs, l) {
391 struct edge_node *e, *e2;
392
393 list_for_each_entry_safe(e, e2, &bb->e_prevs, l) {
394 list_del(&e->l);
395 free(e);
396 }
397
398 list_for_each_entry_safe(e, e2, &bb->e_succs, l) {
399 list_del(&e->l);
400 free(e);
401 }
402
403 list_del(&bb->l);
404 free(bb);
405 }
406
407 list_del(&func->l);
408 free(func);
409 }
410}
411
412static void draw_bb_node(struct func_node *func, struct bb_node *bb)
413{
414 const char *shape;
415
416 if (bb->idx == ENTRY_BLOCK_INDEX || bb->idx == EXIT_BLOCK_INDEX)
417 shape = "Mdiamond";
418 else
419 shape = "record";
420
421 printf("\tfn_%d_bb_%d [shape=%s,style=filled,label=\"",
422 func->idx, bb->idx, shape);
423
424 if (bb->idx == ENTRY_BLOCK_INDEX) {
425 printf("ENTRY");
426 } else if (bb->idx == EXIT_BLOCK_INDEX) {
427 printf("EXIT");
428 } else {
429 unsigned int start_idx;
430 struct dump_data dd = {};
431
432 printf("{");
433 kernel_syms_load(&dd);
434 start_idx = bb->head - func->start;
435 dump_xlated_for_graph(&dd, bb->head, bb->tail, start_idx);
436 kernel_syms_destroy(&dd);
437 printf("}");
438 }
439
440 printf("\"];\n\n");
441}
442
443static void draw_bb_succ_edges(struct func_node *func, struct bb_node *bb)
444{
445 const char *style = "\"solid,bold\"";
446 const char *color = "black";
447 int func_idx = func->idx;
448 struct edge_node *e;
449 int weight = 10;
450
451 if (list_empty(&bb->e_succs))
452 return;
453
454 list_for_each_entry(e, &bb->e_succs, l) {
455 printf("\tfn_%d_bb_%d:s -> fn_%d_bb_%d:n [style=%s, color=%s, weight=%d, constraint=true",
456 func_idx, e->src->idx, func_idx, e->dst->idx,
457 style, color, weight);
458 printf("];\n");
459 }
460}
461
462static void func_output_bb_def(struct func_node *func)
463{
464 struct bb_node *bb;
465
466 list_for_each_entry(bb, &func->bbs, l) {
467 draw_bb_node(func, bb);
468 }
469}
470
471static void func_output_edges(struct func_node *func)
472{
473 int func_idx = func->idx;
474 struct bb_node *bb;
475
476 list_for_each_entry(bb, &func->bbs, l) {
477 draw_bb_succ_edges(func, bb);
478 }
479
480 /* Add an invisible edge from ENTRY to EXIT, this is to
481 * improve the graph layout.
482 */
483 printf("\tfn_%d_bb_%d:s -> fn_%d_bb_%d:n [style=\"invis\", constraint=true];\n",
484 func_idx, ENTRY_BLOCK_INDEX, func_idx, EXIT_BLOCK_INDEX);
485}
486
487static void cfg_dump(struct cfg *cfg)
488{
489 struct func_node *func;
490
491 printf("digraph \"DOT graph for eBPF program\" {\n");
492 list_for_each_entry(func, &cfg->funcs, l) {
493 printf("subgraph \"cluster_%d\" {\n\tstyle=\"dashed\";\n\tcolor=\"black\";\n\tlabel=\"func_%d ()\";\n",
494 func->idx, func->idx);
495 func_output_bb_def(func);
496 func_output_edges(func);
497 printf("}\n");
498 }
499 printf("}\n");
500}
501
502void dump_xlated_cfg(void *buf, unsigned int len)
503{
504 struct bpf_insn *insn = buf;
505 struct cfg cfg;
506
507 memset(&cfg, 0, sizeof(cfg));
508 if (cfg_build(&cfg, insn, len))
509 return;
510
511 cfg_dump(&cfg);
512
513 cfg_destroy(&cfg);
514}
diff --git a/tools/bpf/bpftool/cfg.h b/tools/bpf/bpftool/cfg.h
new file mode 100644
index 000000000000..2cc9bd990b13
--- /dev/null
+++ b/tools/bpf/bpftool/cfg.h
@@ -0,0 +1,43 @@
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2/*
3 * Copyright (C) 2018 Netronome Systems, Inc.
4 *
5 * This software is dual licensed under the GNU General License Version 2,
6 * June 1991 as shown in the file COPYING in the top-level directory of this
7 * source tree or the BSD 2-Clause License provided below. You have the
8 * option to license this software under the complete terms of either license.
9 *
10 * The BSD 2-Clause License:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef __BPF_TOOL_CFG_H
39#define __BPF_TOOL_CFG_H
40
41void dump_xlated_cfg(void *buf, unsigned int len);
42
43#endif /* __BPF_TOOL_CFG_H */
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 185acfa229b5..1ec852d21d44 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -46,6 +46,9 @@
46 46
47#include "main.h" 47#include "main.h"
48 48
49#define BATCH_LINE_LEN_MAX 65536
50#define BATCH_ARG_NB_MAX 4096
51
49const char *bin_name; 52const char *bin_name;
50static int last_argc; 53static int last_argc;
51static char **last_argv; 54static char **last_argv;
@@ -157,6 +160,54 @@ void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
157 } 160 }
158} 161}
159 162
163/* Split command line into argument vector. */
164static int make_args(char *line, char *n_argv[], int maxargs, int cmd_nb)
165{
166 static const char ws[] = " \t\r\n";
167 char *cp = line;
168 int n_argc = 0;
169
170 while (*cp) {
171 /* Skip leading whitespace. */
172 cp += strspn(cp, ws);
173
174 if (*cp == '\0')
175 break;
176
177 if (n_argc >= (maxargs - 1)) {
178 p_err("too many arguments to command %d", cmd_nb);
179 return -1;
180 }
181
182 /* Word begins with quote. */
183 if (*cp == '\'' || *cp == '"') {
184 char quote = *cp++;
185
186 n_argv[n_argc++] = cp;
187 /* Find ending quote. */
188 cp = strchr(cp, quote);
189 if (!cp) {
190 p_err("unterminated quoted string in command %d",
191 cmd_nb);
192 return -1;
193 }
194 } else {
195 n_argv[n_argc++] = cp;
196
197 /* Find end of word. */
198 cp += strcspn(cp, ws);
199 if (*cp == '\0')
200 break;
201 }
202
203 /* Separate words. */
204 *cp++ = 0;
205 }
206 n_argv[n_argc] = NULL;
207
208 return n_argc;
209}
210
160static int do_batch(int argc, char **argv); 211static int do_batch(int argc, char **argv);
161 212
162static const struct cmd cmds[] = { 213static const struct cmd cmds[] = {
@@ -171,11 +222,12 @@ static const struct cmd cmds[] = {
171 222
172static int do_batch(int argc, char **argv) 223static int do_batch(int argc, char **argv)
173{ 224{
225 char buf[BATCH_LINE_LEN_MAX], contline[BATCH_LINE_LEN_MAX];
226 char *n_argv[BATCH_ARG_NB_MAX];
174 unsigned int lines = 0; 227 unsigned int lines = 0;
175 char *n_argv[4096];
176 char buf[65536];
177 int n_argc; 228 int n_argc;
178 FILE *fp; 229 FILE *fp;
230 char *cp;
179 int err; 231 int err;
180 int i; 232 int i;
181 233
@@ -191,7 +243,10 @@ static int do_batch(int argc, char **argv)
191 } 243 }
192 NEXT_ARG(); 244 NEXT_ARG();
193 245
194 fp = fopen(*argv, "r"); 246 if (!strcmp(*argv, "-"))
247 fp = stdin;
248 else
249 fp = fopen(*argv, "r");
195 if (!fp) { 250 if (!fp) {
196 p_err("Can't open file (%s): %s", *argv, strerror(errno)); 251 p_err("Can't open file (%s): %s", *argv, strerror(errno));
197 return -1; 252 return -1;
@@ -200,27 +255,45 @@ static int do_batch(int argc, char **argv)
200 if (json_output) 255 if (json_output)
201 jsonw_start_array(json_wtr); 256 jsonw_start_array(json_wtr);
202 while (fgets(buf, sizeof(buf), fp)) { 257 while (fgets(buf, sizeof(buf), fp)) {
258 cp = strchr(buf, '#');
259 if (cp)
260 *cp = '\0';
261
203 if (strlen(buf) == sizeof(buf) - 1) { 262 if (strlen(buf) == sizeof(buf) - 1) {
204 errno = E2BIG; 263 errno = E2BIG;
205 break; 264 break;
206 } 265 }
207 266
208 n_argc = 0; 267 /* Append continuation lines if any (coming after a line ending
209 n_argv[n_argc] = strtok(buf, " \t\n"); 268 * with '\' in the batch file).
210 269 */
211 while (n_argv[n_argc]) { 270 while ((cp = strstr(buf, "\\\n")) != NULL) {
212 n_argc++; 271 if (!fgets(contline, sizeof(contline), fp) ||
213 if (n_argc == ARRAY_SIZE(n_argv)) { 272 strlen(contline) == 0) {
214 p_err("line %d has too many arguments, skip", 273 p_err("missing continuation line on command %d",
215 lines); 274 lines);
216 n_argc = 0; 275 err = -1;
217 break; 276 goto err_close;
277 }
278
279 cp = strchr(contline, '#');
280 if (cp)
281 *cp = '\0';
282
283 if (strlen(buf) + strlen(contline) + 1 > sizeof(buf)) {
284 p_err("command %d is too long", lines);
285 err = -1;
286 goto err_close;
218 } 287 }
219 n_argv[n_argc] = strtok(NULL, " \t\n"); 288 buf[strlen(buf) - 2] = '\0';
289 strcat(buf, contline);
220 } 290 }
221 291
292 n_argc = make_args(buf, n_argv, BATCH_ARG_NB_MAX, lines);
222 if (!n_argc) 293 if (!n_argc)
223 continue; 294 continue;
295 if (n_argc < 0)
296 goto err_close;
224 297
225 if (json_output) { 298 if (json_output) {
226 jsonw_start_object(json_wtr); 299 jsonw_start_object(json_wtr);
@@ -247,11 +320,12 @@ static int do_batch(int argc, char **argv)
247 p_err("reading batch file failed: %s", strerror(errno)); 320 p_err("reading batch file failed: %s", strerror(errno));
248 err = -1; 321 err = -1;
249 } else { 322 } else {
250 p_info("processed %d lines", lines); 323 p_info("processed %d commands", lines);
251 err = 0; 324 err = 0;
252 } 325 }
253err_close: 326err_close:
254 fclose(fp); 327 if (fp != stdin)
328 fclose(fp);
255 329
256 if (json_output) 330 if (json_output)
257 jsonw_end_array(json_wtr); 331 jsonw_end_array(json_wtr);
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index f95fa67bb498..f509c86faede 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -428,7 +428,7 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
428 jsonw_string_field(json_wtr, "name", info->name); 428 jsonw_string_field(json_wtr, "name", info->name);
429 429
430 jsonw_name(json_wtr, "flags"); 430 jsonw_name(json_wtr, "flags");
431 jsonw_printf(json_wtr, "%#x", info->map_flags); 431 jsonw_printf(json_wtr, "%d", info->map_flags);
432 432
433 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 433 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
434 434
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index e549e329be82..f7a810897eac 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -47,8 +47,9 @@
47#include <bpf.h> 47#include <bpf.h>
48#include <libbpf.h> 48#include <libbpf.h>
49 49
50#include "cfg.h"
50#include "main.h" 51#include "main.h"
51#include "disasm.h" 52#include "xlated_dumper.h"
52 53
53static const char * const prog_type_name[] = { 54static const char * const prog_type_name[] = {
54 [BPF_PROG_TYPE_UNSPEC] = "unspec", 55 [BPF_PROG_TYPE_UNSPEC] = "unspec",
@@ -407,259 +408,6 @@ static int do_show(int argc, char **argv)
407 return err; 408 return err;
408} 409}
409 410
410#define SYM_MAX_NAME 256
411
412struct kernel_sym {
413 unsigned long address;
414 char name[SYM_MAX_NAME];
415};
416
417struct dump_data {
418 unsigned long address_call_base;
419 struct kernel_sym *sym_mapping;
420 __u32 sym_count;
421 char scratch_buff[SYM_MAX_NAME];
422};
423
424static int kernel_syms_cmp(const void *sym_a, const void *sym_b)
425{
426 return ((struct kernel_sym *)sym_a)->address -
427 ((struct kernel_sym *)sym_b)->address;
428}
429
430static void kernel_syms_load(struct dump_data *dd)
431{
432 struct kernel_sym *sym;
433 char buff[256];
434 void *tmp, *address;
435 FILE *fp;
436
437 fp = fopen("/proc/kallsyms", "r");
438 if (!fp)
439 return;
440
441 while (!feof(fp)) {
442 if (!fgets(buff, sizeof(buff), fp))
443 break;
444 tmp = realloc(dd->sym_mapping,
445 (dd->sym_count + 1) *
446 sizeof(*dd->sym_mapping));
447 if (!tmp) {
448out:
449 free(dd->sym_mapping);
450 dd->sym_mapping = NULL;
451 fclose(fp);
452 return;
453 }
454 dd->sym_mapping = tmp;
455 sym = &dd->sym_mapping[dd->sym_count];
456 if (sscanf(buff, "%p %*c %s", &address, sym->name) != 2)
457 continue;
458 sym->address = (unsigned long)address;
459 if (!strcmp(sym->name, "__bpf_call_base")) {
460 dd->address_call_base = sym->address;
461 /* sysctl kernel.kptr_restrict was set */
462 if (!sym->address)
463 goto out;
464 }
465 if (sym->address)
466 dd->sym_count++;
467 }
468
469 fclose(fp);
470
471 qsort(dd->sym_mapping, dd->sym_count,
472 sizeof(*dd->sym_mapping), kernel_syms_cmp);
473}
474
475static void kernel_syms_destroy(struct dump_data *dd)
476{
477 free(dd->sym_mapping);
478}
479
480static struct kernel_sym *kernel_syms_search(struct dump_data *dd,
481 unsigned long key)
482{
483 struct kernel_sym sym = {
484 .address = key,
485 };
486
487 return dd->sym_mapping ?
488 bsearch(&sym, dd->sym_mapping, dd->sym_count,
489 sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL;
490}
491
492static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
493{
494 va_list args;
495
496 va_start(args, fmt);
497 vprintf(fmt, args);
498 va_end(args);
499}
500
501static const char *print_call_pcrel(struct dump_data *dd,
502 struct kernel_sym *sym,
503 unsigned long address,
504 const struct bpf_insn *insn)
505{
506 if (sym)
507 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
508 "%+d#%s", insn->off, sym->name);
509 else
510 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
511 "%+d#0x%lx", insn->off, address);
512 return dd->scratch_buff;
513}
514
515static const char *print_call_helper(struct dump_data *dd,
516 struct kernel_sym *sym,
517 unsigned long address)
518{
519 if (sym)
520 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
521 "%s", sym->name);
522 else
523 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
524 "0x%lx", address);
525 return dd->scratch_buff;
526}
527
528static const char *print_call(void *private_data,
529 const struct bpf_insn *insn)
530{
531 struct dump_data *dd = private_data;
532 unsigned long address = dd->address_call_base + insn->imm;
533 struct kernel_sym *sym;
534
535 sym = kernel_syms_search(dd, address);
536 if (insn->src_reg == BPF_PSEUDO_CALL)
537 return print_call_pcrel(dd, sym, address, insn);
538 else
539 return print_call_helper(dd, sym, address);
540}
541
542static const char *print_imm(void *private_data,
543 const struct bpf_insn *insn,
544 __u64 full_imm)
545{
546 struct dump_data *dd = private_data;
547
548 if (insn->src_reg == BPF_PSEUDO_MAP_FD)
549 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
550 "map[id:%u]", insn->imm);
551 else
552 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
553 "0x%llx", (unsigned long long)full_imm);
554 return dd->scratch_buff;
555}
556
557static void dump_xlated_plain(struct dump_data *dd, void *buf,
558 unsigned int len, bool opcodes)
559{
560 const struct bpf_insn_cbs cbs = {
561 .cb_print = print_insn,
562 .cb_call = print_call,
563 .cb_imm = print_imm,
564 .private_data = dd,
565 };
566 struct bpf_insn *insn = buf;
567 bool double_insn = false;
568 unsigned int i;
569
570 for (i = 0; i < len / sizeof(*insn); i++) {
571 if (double_insn) {
572 double_insn = false;
573 continue;
574 }
575
576 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
577
578 printf("% 4d: ", i);
579 print_bpf_insn(&cbs, NULL, insn + i, true);
580
581 if (opcodes) {
582 printf(" ");
583 fprint_hex(stdout, insn + i, 8, " ");
584 if (double_insn && i < len - 1) {
585 printf(" ");
586 fprint_hex(stdout, insn + i + 1, 8, " ");
587 }
588 printf("\n");
589 }
590 }
591}
592
593static void print_insn_json(struct bpf_verifier_env *env, const char *fmt, ...)
594{
595 unsigned int l = strlen(fmt);
596 char chomped_fmt[l];
597 va_list args;
598
599 va_start(args, fmt);
600 if (l > 0) {
601 strncpy(chomped_fmt, fmt, l - 1);
602 chomped_fmt[l - 1] = '\0';
603 }
604 jsonw_vprintf_enquote(json_wtr, chomped_fmt, args);
605 va_end(args);
606}
607
608static void dump_xlated_json(struct dump_data *dd, void *buf,
609 unsigned int len, bool opcodes)
610{
611 const struct bpf_insn_cbs cbs = {
612 .cb_print = print_insn_json,
613 .cb_call = print_call,
614 .cb_imm = print_imm,
615 .private_data = dd,
616 };
617 struct bpf_insn *insn = buf;
618 bool double_insn = false;
619 unsigned int i;
620
621 jsonw_start_array(json_wtr);
622 for (i = 0; i < len / sizeof(*insn); i++) {
623 if (double_insn) {
624 double_insn = false;
625 continue;
626 }
627 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
628
629 jsonw_start_object(json_wtr);
630 jsonw_name(json_wtr, "disasm");
631 print_bpf_insn(&cbs, NULL, insn + i, true);
632
633 if (opcodes) {
634 jsonw_name(json_wtr, "opcodes");
635 jsonw_start_object(json_wtr);
636
637 jsonw_name(json_wtr, "code");
638 jsonw_printf(json_wtr, "\"0x%02hhx\"", insn[i].code);
639
640 jsonw_name(json_wtr, "src_reg");
641 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].src_reg);
642
643 jsonw_name(json_wtr, "dst_reg");
644 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].dst_reg);
645
646 jsonw_name(json_wtr, "off");
647 print_hex_data_json((uint8_t *)(&insn[i].off), 2);
648
649 jsonw_name(json_wtr, "imm");
650 if (double_insn && i < len - 1)
651 print_hex_data_json((uint8_t *)(&insn[i].imm),
652 12);
653 else
654 print_hex_data_json((uint8_t *)(&insn[i].imm),
655 4);
656 jsonw_end_object(json_wtr);
657 }
658 jsonw_end_object(json_wtr);
659 }
660 jsonw_end_array(json_wtr);
661}
662
663static int do_dump(int argc, char **argv) 411static int do_dump(int argc, char **argv)
664{ 412{
665 struct bpf_prog_info info = {}; 413 struct bpf_prog_info info = {};
@@ -668,6 +416,7 @@ static int do_dump(int argc, char **argv)
668 unsigned int buf_size; 416 unsigned int buf_size;
669 char *filepath = NULL; 417 char *filepath = NULL;
670 bool opcodes = false; 418 bool opcodes = false;
419 bool visual = false;
671 unsigned char *buf; 420 unsigned char *buf;
672 __u32 *member_len; 421 __u32 *member_len;
673 __u64 *member_ptr; 422 __u64 *member_ptr;
@@ -706,6 +455,9 @@ static int do_dump(int argc, char **argv)
706 } else if (is_prefix(*argv, "opcodes")) { 455 } else if (is_prefix(*argv, "opcodes")) {
707 opcodes = true; 456 opcodes = true;
708 NEXT_ARG(); 457 NEXT_ARG();
458 } else if (is_prefix(*argv, "visual")) {
459 visual = true;
460 NEXT_ARG();
709 } 461 }
710 462
711 if (argc) { 463 if (argc) {
@@ -777,27 +529,30 @@ static int do_dump(int argc, char **argv)
777 529
778 if (json_output) 530 if (json_output)
779 jsonw_null(json_wtr); 531 jsonw_null(json_wtr);
780 } else { 532 } else if (member_len == &info.jited_prog_len) {
781 if (member_len == &info.jited_prog_len) { 533 const char *name = NULL;
782 const char *name = NULL; 534
783 535 if (info.ifindex) {
784 if (info.ifindex) { 536 name = ifindex_to_bfd_name_ns(info.ifindex,
785 name = ifindex_to_bfd_name_ns(info.ifindex, 537 info.netns_dev,
786 info.netns_dev, 538 info.netns_ino);
787 info.netns_ino); 539 if (!name)
788 if (!name) 540 goto err_free;
789 goto err_free;
790 }
791
792 disasm_print_insn(buf, *member_len, opcodes, name);
793 } else {
794 kernel_syms_load(&dd);
795 if (json_output)
796 dump_xlated_json(&dd, buf, *member_len, opcodes);
797 else
798 dump_xlated_plain(&dd, buf, *member_len, opcodes);
799 kernel_syms_destroy(&dd);
800 } 541 }
542
543 disasm_print_insn(buf, *member_len, opcodes, name);
544 } else if (visual) {
545 if (json_output)
546 jsonw_null(json_wtr);
547 else
548 dump_xlated_cfg(buf, *member_len);
549 } else {
550 kernel_syms_load(&dd);
551 if (json_output)
552 dump_xlated_json(&dd, buf, *member_len, opcodes);
553 else
554 dump_xlated_plain(&dd, buf, *member_len, opcodes);
555 kernel_syms_destroy(&dd);
801 } 556 }
802 557
803 free(buf); 558 free(buf);
@@ -851,7 +606,7 @@ static int do_help(int argc, char **argv)
851 606
852 fprintf(stderr, 607 fprintf(stderr,
853 "Usage: %s %s { show | list } [PROG]\n" 608 "Usage: %s %s { show | list } [PROG]\n"
854 " %s %s dump xlated PROG [{ file FILE | opcodes }]\n" 609 " %s %s dump xlated PROG [{ file FILE | opcodes | visual }]\n"
855 " %s %s dump jited PROG [{ file FILE | opcodes }]\n" 610 " %s %s dump jited PROG [{ file FILE | opcodes }]\n"
856 " %s %s pin PROG FILE\n" 611 " %s %s pin PROG FILE\n"
857 " %s %s load OBJ FILE\n" 612 " %s %s load OBJ FILE\n"
diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c
new file mode 100644
index 000000000000..7a3173b76c16
--- /dev/null
+++ b/tools/bpf/bpftool/xlated_dumper.c
@@ -0,0 +1,338 @@
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2/*
3 * Copyright (C) 2018 Netronome Systems, Inc.
4 *
5 * This software is dual licensed under the GNU General License Version 2,
6 * June 1991 as shown in the file COPYING in the top-level directory of this
7 * source tree or the BSD 2-Clause License provided below. You have the
8 * option to license this software under the complete terms of either license.
9 *
10 * The BSD 2-Clause License:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <stdarg.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <sys/types.h>
43
44#include "disasm.h"
45#include "json_writer.h"
46#include "main.h"
47#include "xlated_dumper.h"
48
49static int kernel_syms_cmp(const void *sym_a, const void *sym_b)
50{
51 return ((struct kernel_sym *)sym_a)->address -
52 ((struct kernel_sym *)sym_b)->address;
53}
54
55void kernel_syms_load(struct dump_data *dd)
56{
57 struct kernel_sym *sym;
58 char buff[256];
59 void *tmp, *address;
60 FILE *fp;
61
62 fp = fopen("/proc/kallsyms", "r");
63 if (!fp)
64 return;
65
66 while (!feof(fp)) {
67 if (!fgets(buff, sizeof(buff), fp))
68 break;
69 tmp = realloc(dd->sym_mapping,
70 (dd->sym_count + 1) *
71 sizeof(*dd->sym_mapping));
72 if (!tmp) {
73out:
74 free(dd->sym_mapping);
75 dd->sym_mapping = NULL;
76 fclose(fp);
77 return;
78 }
79 dd->sym_mapping = tmp;
80 sym = &dd->sym_mapping[dd->sym_count];
81 if (sscanf(buff, "%p %*c %s", &address, sym->name) != 2)
82 continue;
83 sym->address = (unsigned long)address;
84 if (!strcmp(sym->name, "__bpf_call_base")) {
85 dd->address_call_base = sym->address;
86 /* sysctl kernel.kptr_restrict was set */
87 if (!sym->address)
88 goto out;
89 }
90 if (sym->address)
91 dd->sym_count++;
92 }
93
94 fclose(fp);
95
96 qsort(dd->sym_mapping, dd->sym_count,
97 sizeof(*dd->sym_mapping), kernel_syms_cmp);
98}
99
100void kernel_syms_destroy(struct dump_data *dd)
101{
102 free(dd->sym_mapping);
103}
104
105static struct kernel_sym *kernel_syms_search(struct dump_data *dd,
106 unsigned long key)
107{
108 struct kernel_sym sym = {
109 .address = key,
110 };
111
112 return dd->sym_mapping ?
113 bsearch(&sym, dd->sym_mapping, dd->sym_count,
114 sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL;
115}
116
117static void print_insn(void *private_data, const char *fmt, ...)
118{
119 va_list args;
120
121 va_start(args, fmt);
122 vprintf(fmt, args);
123 va_end(args);
124}
125
126static void
127print_insn_for_graph(void *private_data, const char *fmt, ...)
128{
129 char buf[64], *p;
130 va_list args;
131
132 va_start(args, fmt);
133 vsnprintf(buf, sizeof(buf), fmt, args);
134 va_end(args);
135
136 p = buf;
137 while (*p != '\0') {
138 if (*p == '\n') {
139 memmove(p + 3, p, strlen(buf) + 1 - (p - buf));
140 /* Align each instruction dump row left. */
141 *p++ = '\\';
142 *p++ = 'l';
143 /* Output multiline concatenation. */
144 *p++ = '\\';
145 } else if (*p == '<' || *p == '>' || *p == '|' || *p == '&') {
146 memmove(p + 1, p, strlen(buf) + 1 - (p - buf));
147 /* Escape special character. */
148 *p++ = '\\';
149 }
150
151 p++;
152 }
153
154 printf("%s", buf);
155}
156
157static void print_insn_json(void *private_data, const char *fmt, ...)
158{
159 unsigned int l = strlen(fmt);
160 char chomped_fmt[l];
161 va_list args;
162
163 va_start(args, fmt);
164 if (l > 0) {
165 strncpy(chomped_fmt, fmt, l - 1);
166 chomped_fmt[l - 1] = '\0';
167 }
168 jsonw_vprintf_enquote(json_wtr, chomped_fmt, args);
169 va_end(args);
170}
171
172static const char *print_call_pcrel(struct dump_data *dd,
173 struct kernel_sym *sym,
174 unsigned long address,
175 const struct bpf_insn *insn)
176{
177 if (sym)
178 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
179 "%+d#%s", insn->off, sym->name);
180 else
181 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
182 "%+d#0x%lx", insn->off, address);
183 return dd->scratch_buff;
184}
185
186static const char *print_call_helper(struct dump_data *dd,
187 struct kernel_sym *sym,
188 unsigned long address)
189{
190 if (sym)
191 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
192 "%s", sym->name);
193 else
194 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
195 "0x%lx", address);
196 return dd->scratch_buff;
197}
198
199static const char *print_call(void *private_data,
200 const struct bpf_insn *insn)
201{
202 struct dump_data *dd = private_data;
203 unsigned long address = dd->address_call_base + insn->imm;
204 struct kernel_sym *sym;
205
206 sym = kernel_syms_search(dd, address);
207 if (insn->src_reg == BPF_PSEUDO_CALL)
208 return print_call_pcrel(dd, sym, address, insn);
209 else
210 return print_call_helper(dd, sym, address);
211}
212
213static const char *print_imm(void *private_data,
214 const struct bpf_insn *insn,
215 __u64 full_imm)
216{
217 struct dump_data *dd = private_data;
218
219 if (insn->src_reg == BPF_PSEUDO_MAP_FD)
220 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
221 "map[id:%u]", insn->imm);
222 else
223 snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
224 "0x%llx", (unsigned long long)full_imm);
225 return dd->scratch_buff;
226}
227
228void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
229 bool opcodes)
230{
231 const struct bpf_insn_cbs cbs = {
232 .cb_print = print_insn_json,
233 .cb_call = print_call,
234 .cb_imm = print_imm,
235 .private_data = dd,
236 };
237 struct bpf_insn *insn = buf;
238 bool double_insn = false;
239 unsigned int i;
240
241 jsonw_start_array(json_wtr);
242 for (i = 0; i < len / sizeof(*insn); i++) {
243 if (double_insn) {
244 double_insn = false;
245 continue;
246 }
247 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
248
249 jsonw_start_object(json_wtr);
250 jsonw_name(json_wtr, "disasm");
251 print_bpf_insn(&cbs, insn + i, true);
252
253 if (opcodes) {
254 jsonw_name(json_wtr, "opcodes");
255 jsonw_start_object(json_wtr);
256
257 jsonw_name(json_wtr, "code");
258 jsonw_printf(json_wtr, "\"0x%02hhx\"", insn[i].code);
259
260 jsonw_name(json_wtr, "src_reg");
261 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].src_reg);
262
263 jsonw_name(json_wtr, "dst_reg");
264 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].dst_reg);
265
266 jsonw_name(json_wtr, "off");
267 print_hex_data_json((uint8_t *)(&insn[i].off), 2);
268
269 jsonw_name(json_wtr, "imm");
270 if (double_insn && i < len - 1)
271 print_hex_data_json((uint8_t *)(&insn[i].imm),
272 12);
273 else
274 print_hex_data_json((uint8_t *)(&insn[i].imm),
275 4);
276 jsonw_end_object(json_wtr);
277 }
278 jsonw_end_object(json_wtr);
279 }
280 jsonw_end_array(json_wtr);
281}
282
283void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
284 bool opcodes)
285{
286 const struct bpf_insn_cbs cbs = {
287 .cb_print = print_insn,
288 .cb_call = print_call,
289 .cb_imm = print_imm,
290 .private_data = dd,
291 };
292 struct bpf_insn *insn = buf;
293 bool double_insn = false;
294 unsigned int i;
295
296 for (i = 0; i < len / sizeof(*insn); i++) {
297 if (double_insn) {
298 double_insn = false;
299 continue;
300 }
301
302 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
303
304 printf("% 4d: ", i);
305 print_bpf_insn(&cbs, insn + i, true);
306
307 if (opcodes) {
308 printf(" ");
309 fprint_hex(stdout, insn + i, 8, " ");
310 if (double_insn && i < len - 1) {
311 printf(" ");
312 fprint_hex(stdout, insn + i + 1, 8, " ");
313 }
314 printf("\n");
315 }
316 }
317}
318
319void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,
320 unsigned int start_idx)
321{
322 const struct bpf_insn_cbs cbs = {
323 .cb_print = print_insn_for_graph,
324 .cb_call = print_call,
325 .cb_imm = print_imm,
326 .private_data = dd,
327 };
328 struct bpf_insn *insn_start = buf_start;
329 struct bpf_insn *insn_end = buf_end;
330 struct bpf_insn *cur = insn_start;
331
332 for (; cur <= insn_end; cur++) {
333 printf("% 4d: ", (int)(cur - insn_start + start_idx));
334 print_bpf_insn(&cbs, cur, true);
335 if (cur != insn_end)
336 printf(" | ");
337 }
338}
diff --git a/tools/bpf/bpftool/xlated_dumper.h b/tools/bpf/bpftool/xlated_dumper.h
new file mode 100644
index 000000000000..b34affa7ef2d
--- /dev/null
+++ b/tools/bpf/bpftool/xlated_dumper.h
@@ -0,0 +1,64 @@
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2/*
3 * Copyright (C) 2018 Netronome Systems, Inc.
4 *
5 * This software is dual licensed under the GNU General License Version 2,
6 * June 1991 as shown in the file COPYING in the top-level directory of this
7 * source tree or the BSD 2-Clause License provided below. You have the
8 * option to license this software under the complete terms of either license.
9 *
10 * The BSD 2-Clause License:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef __BPF_TOOL_XLATED_DUMPER_H
39#define __BPF_TOOL_XLATED_DUMPER_H
40
41#define SYM_MAX_NAME 256
42
43struct kernel_sym {
44 unsigned long address;
45 char name[SYM_MAX_NAME];
46};
47
48struct dump_data {
49 unsigned long address_call_base;
50 struct kernel_sym *sym_mapping;
51 __u32 sym_count;
52 char scratch_buff[SYM_MAX_NAME + 8];
53};
54
55void kernel_syms_load(struct dump_data *dd);
56void kernel_syms_destroy(struct dump_data *dd);
57void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
58 bool opcodes);
59void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
60 bool opcodes);
61void dump_xlated_for_graph(struct dump_data *dd, void *buf, void *buf_end,
62 unsigned int start_index);
63
64#endif
diff --git a/tools/build/Build.include b/tools/build/Build.include
index 418871d02ebf..a4bbb984941d 100644
--- a/tools/build/Build.include
+++ b/tools/build/Build.include
@@ -12,6 +12,7 @@
12# Convenient variables 12# Convenient variables
13comma := , 13comma := ,
14squote := ' 14squote := '
15pound := \#
15 16
16### 17###
17# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o 18# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
@@ -43,11 +44,11 @@ echo-cmd = $(if $($(quiet)cmd_$(1)),\
43### 44###
44# Replace >$< with >$$< to preserve $ when reloading the .cmd file 45# Replace >$< with >$$< to preserve $ when reloading the .cmd file
45# (needed for make) 46# (needed for make)
46# Replace >#< with >\#< to avoid starting a comment in the .cmd file 47# Replace >#< with >$(pound)< to avoid starting a comment in the .cmd file
47# (needed for make) 48# (needed for make)
48# Replace >'< with >'\''< to be able to enclose the whole string in '...' 49# Replace >'< with >'\''< to be able to enclose the whole string in '...'
49# (needed for the shell) 50# (needed for the shell)
50make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1))))) 51make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
51 52
52### 53###
53# Find any prerequisites that is newer than target or that does not exist. 54# Find any prerequisites that is newer than target or that does not exist.
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index c378f003b007..5b6dda3b1ca8 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -82,7 +82,11 @@ FEATURE_TESTS_EXTRA := \
82 liberty-z \ 82 liberty-z \
83 libunwind-debug-frame \ 83 libunwind-debug-frame \
84 libunwind-debug-frame-arm \ 84 libunwind-debug-frame-arm \
85 libunwind-debug-frame-aarch64 85 libunwind-debug-frame-aarch64 \
86 cxx \
87 llvm \
88 llvm-version \
89 clang
86 90
87FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) 91FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
88 92
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 0a490cb15149..dac9563b5470 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -54,7 +54,10 @@ FILES= \
54 test-jvmti.bin \ 54 test-jvmti.bin \
55 test-sched_getcpu.bin \ 55 test-sched_getcpu.bin \
56 test-setns.bin \ 56 test-setns.bin \
57 test-libopencsd.bin 57 test-libopencsd.bin \
58 test-clang.bin \
59 test-llvm.bin \
60 test-llvm-version.bin
58 61
59FILES := $(addprefix $(OUTPUT),$(FILES)) 62FILES := $(addprefix $(OUTPUT),$(FILES))
60 63
@@ -257,11 +260,13 @@ $(OUTPUT)test-llvm.bin:
257 -I$(shell $(LLVM_CONFIG) --includedir) \ 260 -I$(shell $(LLVM_CONFIG) --includedir) \
258 -L$(shell $(LLVM_CONFIG) --libdir) \ 261 -L$(shell $(LLVM_CONFIG) --libdir) \
259 $(shell $(LLVM_CONFIG) --libs Core BPF) \ 262 $(shell $(LLVM_CONFIG) --libs Core BPF) \
260 $(shell $(LLVM_CONFIG) --system-libs) 263 $(shell $(LLVM_CONFIG) --system-libs) \
264 > $(@:.bin=.make.output) 2>&1
261 265
262$(OUTPUT)test-llvm-version.bin: 266$(OUTPUT)test-llvm-version.bin:
263 $(BUILDXX) -std=gnu++11 \ 267 $(BUILDXX) -std=gnu++11 \
264 -I$(shell $(LLVM_CONFIG) --includedir) 268 -I$(shell $(LLVM_CONFIG) --includedir) \
269 > $(@:.bin=.make.output) 2>&1
265 270
266$(OUTPUT)test-clang.bin: 271$(OUTPUT)test-clang.bin:
267 $(BUILDXX) -std=gnu++11 \ 272 $(BUILDXX) -std=gnu++11 \
@@ -271,7 +276,8 @@ $(OUTPUT)test-clang.bin:
271 -lclangFrontend -lclangEdit -lclangLex \ 276 -lclangFrontend -lclangEdit -lclangLex \
272 -lclangAST -Wl,--end-group \ 277 -lclangAST -Wl,--end-group \
273 $(shell $(LLVM_CONFIG) --libs Core option) \ 278 $(shell $(LLVM_CONFIG) --libs Core option) \
274 $(shell $(LLVM_CONFIG) --system-libs) 279 $(shell $(LLVM_CONFIG) --system-libs) \
280 > $(@:.bin=.make.output) 2>&1
275 281
276-include $(OUTPUT)*.d 282-include $(OUTPUT)*.d
277 283
diff --git a/tools/gpio/gpio-event-mon.c b/tools/gpio/gpio-event-mon.c
index dac4d4131d9b..c864544efe05 100644
--- a/tools/gpio/gpio-event-mon.c
+++ b/tools/gpio/gpio-event-mon.c
@@ -99,7 +99,7 @@ int monitor_device(const char *device_name,
99 ret = -EIO; 99 ret = -EIO;
100 break; 100 break;
101 } 101 }
102 fprintf(stdout, "GPIO EVENT %" PRIu64 ": ", event.timestamp); 102 fprintf(stdout, "GPIO EVENT %llu: ", event.timestamp);
103 switch (event.id) { 103 switch (event.id) {
104 case GPIOEVENT_EVENT_RISING_EDGE: 104 case GPIOEVENT_EVENT_RISING_EDGE:
105 fprintf(stdout, "rising edge"); 105 fprintf(stdout, "rising edge");
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 457a1521f32f..d78aed86af09 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -21,15 +21,17 @@
21#include <stdio.h> 21#include <stdio.h>
22#include <stdlib.h> 22#include <stdlib.h>
23#include <unistd.h> 23#include <unistd.h>
24#include <string.h>
24#include <errno.h> 25#include <errno.h>
25#include <linux/hyperv.h> 26#include <linux/hyperv.h>
27#include <linux/limits.h>
26#include <syslog.h> 28#include <syslog.h>
27#include <sys/stat.h> 29#include <sys/stat.h>
28#include <fcntl.h> 30#include <fcntl.h>
29#include <getopt.h> 31#include <getopt.h>
30 32
31static int target_fd; 33static int target_fd;
32static char target_fname[W_MAX_PATH]; 34static char target_fname[PATH_MAX];
33static unsigned long long filesize; 35static unsigned long long filesize;
34 36
35static int hv_start_fcopy(struct hv_start_fcopy *smsg) 37static int hv_start_fcopy(struct hv_start_fcopy *smsg)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 4c99c57736ce..dbf6e8bd98ba 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -634,64 +634,6 @@ static char *kvp_if_name_to_mac(char *if_name)
634 return mac_addr; 634 return mac_addr;
635} 635}
636 636
637
638/*
639 * Retrieve the interface name given tha MAC address.
640 */
641
642static char *kvp_mac_to_if_name(char *mac)
643{
644 DIR *dir;
645 struct dirent *entry;
646 FILE *file;
647 char *p, *x;
648 char *if_name = NULL;
649 char buf[256];
650 char dev_id[PATH_MAX];
651 unsigned int i;
652
653 dir = opendir(KVP_NET_DIR);
654 if (dir == NULL)
655 return NULL;
656
657 while ((entry = readdir(dir)) != NULL) {
658 /*
659 * Set the state for the next pass.
660 */
661 snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
662 entry->d_name);
663
664 file = fopen(dev_id, "r");
665 if (file == NULL)
666 continue;
667
668 p = fgets(buf, sizeof(buf), file);
669 if (p) {
670 x = strchr(p, '\n');
671 if (x)
672 *x = '\0';
673
674 for (i = 0; i < strlen(p); i++)
675 p[i] = toupper(p[i]);
676
677 if (!strcmp(p, mac)) {
678 /*
679 * Found the MAC match; return the interface
680 * name. The caller will free the memory.
681 */
682 if_name = strdup(entry->d_name);
683 fclose(file);
684 break;
685 }
686 }
687 fclose(file);
688 }
689
690 closedir(dir);
691 return if_name;
692}
693
694
695static void kvp_process_ipconfig_file(char *cmd, 637static void kvp_process_ipconfig_file(char *cmd,
696 char *config_buf, unsigned int len, 638 char *config_buf, unsigned int len,
697 int element_size, int offset) 639 int element_size, int offset)
@@ -997,6 +939,70 @@ getaddr_done:
997 return error; 939 return error;
998} 940}
999 941
942/*
943 * Retrieve the IP given the MAC address.
944 */
945static int kvp_mac_to_ip(struct hv_kvp_ipaddr_value *kvp_ip_val)
946{
947 char *mac = (char *)kvp_ip_val->adapter_id;
948 DIR *dir;
949 struct dirent *entry;
950 FILE *file;
951 char *p, *x;
952 char *if_name = NULL;
953 char buf[256];
954 char dev_id[PATH_MAX];
955 unsigned int i;
956 int error = HV_E_FAIL;
957
958 dir = opendir(KVP_NET_DIR);
959 if (dir == NULL)
960 return HV_E_FAIL;
961
962 while ((entry = readdir(dir)) != NULL) {
963 /*
964 * Set the state for the next pass.
965 */
966 snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
967 entry->d_name);
968
969 file = fopen(dev_id, "r");
970 if (file == NULL)
971 continue;
972
973 p = fgets(buf, sizeof(buf), file);
974 fclose(file);
975 if (!p)
976 continue;
977
978 x = strchr(p, '\n');
979 if (x)
980 *x = '\0';
981
982 for (i = 0; i < strlen(p); i++)
983 p[i] = toupper(p[i]);
984
985 if (strcmp(p, mac))
986 continue;
987
988 /*
989 * Found the MAC match.
990 * A NIC (e.g. VF) matching the MAC, but without IP, is skipped.
991 */
992 if_name = entry->d_name;
993 if (!if_name)
994 continue;
995
996 error = kvp_get_ip_info(0, if_name, KVP_OP_GET_IP_INFO,
997 kvp_ip_val, MAX_IP_ADDR_SIZE * 2);
998
999 if (!error && strlen((char *)kvp_ip_val->ip_addr))
1000 break;
1001 }
1002
1003 closedir(dir);
1004 return error;
1005}
1000 1006
1001static int expand_ipv6(char *addr, int type) 1007static int expand_ipv6(char *addr, int type)
1002{ 1008{
@@ -1472,26 +1478,12 @@ int main(int argc, char *argv[])
1472 switch (op) { 1478 switch (op) {
1473 case KVP_OP_GET_IP_INFO: 1479 case KVP_OP_GET_IP_INFO:
1474 kvp_ip_val = &hv_msg->body.kvp_ip_val; 1480 kvp_ip_val = &hv_msg->body.kvp_ip_val;
1475 if_name =
1476 kvp_mac_to_if_name((char *)kvp_ip_val->adapter_id);
1477 1481
1478 if (if_name == NULL) { 1482 error = kvp_mac_to_ip(kvp_ip_val);
1479 /*
1480 * We could not map the mac address to an
1481 * interface name; return error.
1482 */
1483 hv_msg->error = HV_E_FAIL;
1484 break;
1485 }
1486 error = kvp_get_ip_info(
1487 0, if_name, KVP_OP_GET_IP_INFO,
1488 kvp_ip_val,
1489 (MAX_IP_ADDR_SIZE * 2));
1490 1483
1491 if (error) 1484 if (error)
1492 hv_msg->error = error; 1485 hv_msg->error = error;
1493 1486
1494 free(if_name);
1495 break; 1487 break;
1496 1488
1497 case KVP_OP_SET_IP_INFO: 1489 case KVP_OP_SET_IP_INFO:
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index b2b4ebffab8c..34031a297f02 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -22,6 +22,7 @@
22#include <sys/poll.h> 22#include <sys/poll.h>
23#include <sys/ioctl.h> 23#include <sys/ioctl.h>
24#include <sys/stat.h> 24#include <sys/stat.h>
25#include <sys/sysmacros.h>
25#include <fcntl.h> 26#include <fcntl.h>
26#include <stdio.h> 27#include <stdio.h>
27#include <mntent.h> 28#include <mntent.h>
diff --git a/tools/include/asm-generic/barrier.h b/tools/include/asm-generic/barrier.h
index 47b933903eaf..52278d880a61 100644
--- a/tools/include/asm-generic/barrier.h
+++ b/tools/include/asm-generic/barrier.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copied from the kernel sources to tools/perf/: 2 * Copied from the kernel sources to tools/perf/:
3 * 3 *
4 * Generic barrier definitions, originally based on MN10300 definitions. 4 * Generic barrier definitions.
5 * 5 *
6 * It should be possible to use these on really simple architectures, 6 * It should be possible to use these on really simple architectures,
7 * but it serves more as a starting point for new ports. 7 * but it serves more as a starting point for new ports.
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index ca160270fdfa..63440cc8d618 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -98,7 +98,7 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
98 98
99/** 99/**
100 * bitmap_alloc - Allocate bitmap 100 * bitmap_alloc - Allocate bitmap
101 * @nr: Bit to set 101 * @nbits: Number of bits
102 */ 102 */
103static inline unsigned long *bitmap_alloc(int nbits) 103static inline unsigned long *bitmap_alloc(int nbits)
104{ 104{
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 04e32f965ad7..1827c2f973f9 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -151,11 +151,21 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
151 * required ordering. 151 * required ordering.
152 */ 152 */
153 153
154#define READ_ONCE(x) \ 154#define READ_ONCE(x) \
155 ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) 155({ \
156 156 union { typeof(x) __val; char __c[1]; } __u = \
157#define WRITE_ONCE(x, val) \ 157 { .__c = { 0 } }; \
158 ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) 158 __read_once_size(&(x), __u.__c, sizeof(x)); \
159 __u.__val; \
160})
161
162#define WRITE_ONCE(x, val) \
163({ \
164 union { typeof(x) __val; char __c[1]; } __u = \
165 { .__val = (val) }; \
166 __write_once_size(&(x), __u.__c, sizeof(x)); \
167 __u.__val; \
168})
159 169
160 170
161#ifndef __fallthrough 171#ifndef __fallthrough
diff --git a/tools/include/linux/coresight-pmu.h b/tools/include/linux/coresight-pmu.h
index edfeaba95429..a1a959ba24ff 100644
--- a/tools/include/linux/coresight-pmu.h
+++ b/tools/include/linux/coresight-pmu.h
@@ -1,18 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved. 3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 5 */
17 6
18#ifndef _LINUX_CORESIGHT_PMU_H 7#ifndef _LINUX_CORESIGHT_PMU_H
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h
index 4ed569fcb139..1738c0391da4 100644
--- a/tools/include/linux/spinlock.h
+++ b/tools/include/linux/spinlock.h
@@ -6,7 +6,9 @@
6#include <stdbool.h> 6#include <stdbool.h>
7 7
8#define spinlock_t pthread_mutex_t 8#define spinlock_t pthread_mutex_t
9#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; 9#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER
10#define __SPIN_LOCK_UNLOCKED(x) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER
11#define spin_lock_init(x) pthread_mutex_init(x, NULL)
10 12
11#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) 13#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x)
12#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x) 14#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x)
diff --git a/tools/include/tools/config.h b/tools/include/tools/config.h
new file mode 100644
index 000000000000..08ade7df8132
--- /dev/null
+++ b/tools/include/tools/config.h
@@ -0,0 +1,34 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _TOOLS_CONFIG_H
3#define _TOOLS_CONFIG_H
4
5/* Subset of include/linux/kconfig.h */
6
7#define __ARG_PLACEHOLDER_1 0,
8#define __take_second_arg(__ignored, val, ...) val
9
10/*
11 * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
12 * these only work with boolean and tristate options.
13 */
14
15/*
16 * Getting something that works in C and CPP for an arg that may or may
17 * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
18 * we match on the placeholder define, insert the "0," for arg1 and generate
19 * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
20 * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
21 * the last step cherry picks the 2nd arg, we get a zero.
22 */
23#define __is_defined(x) ___is_defined(x)
24#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
25#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
26
27/*
28 * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
29 * otherwise. For boolean options, this is equivalent to
30 * IS_ENABLED(CONFIG_FOO).
31 */
32#define IS_BUILTIN(option) __is_defined(option)
33
34#endif /* _TOOLS_CONFIG_H */
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
index f8b134f5608f..e7ee32861d51 100644
--- a/tools/include/uapi/asm-generic/mman-common.h
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -27,6 +27,9 @@
27# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */ 27# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
28#endif 28#endif
29 29
30/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
31#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
32
30/* 33/*
31 * Flags for mlock 34 * Flags for mlock
32 */ 35 */
diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h
index 536ee4febd74..7f5634ce8e88 100644
--- a/tools/include/uapi/drm/i915_drm.h
+++ b/tools/include/uapi/drm/i915_drm.h
@@ -318,6 +318,7 @@ typedef struct _drm_i915_sarea {
318#define DRM_I915_PERF_OPEN 0x36 318#define DRM_I915_PERF_OPEN 0x36
319#define DRM_I915_PERF_ADD_CONFIG 0x37 319#define DRM_I915_PERF_ADD_CONFIG 0x37
320#define DRM_I915_PERF_REMOVE_CONFIG 0x38 320#define DRM_I915_PERF_REMOVE_CONFIG 0x38
321#define DRM_I915_QUERY 0x39
321 322
322#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 323#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
323#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) 324#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -375,6 +376,7 @@ typedef struct _drm_i915_sarea {
375#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) 376#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
376#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) 377#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
377#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) 378#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
379#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
378 380
379/* Allow drivers to submit batchbuffers directly to hardware, relying 381/* Allow drivers to submit batchbuffers directly to hardware, relying
380 * on the security mechanisms provided by hardware. 382 * on the security mechanisms provided by hardware.
@@ -1358,7 +1360,9 @@ struct drm_intel_overlay_attrs {
1358 * active on a given plane. 1360 * active on a given plane.
1359 */ 1361 */
1360 1362
1361#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ 1363#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set
1364 * flags==0 to disable colorkeying.
1365 */
1362#define I915_SET_COLORKEY_DESTINATION (1<<1) 1366#define I915_SET_COLORKEY_DESTINATION (1<<1)
1363#define I915_SET_COLORKEY_SOURCE (1<<2) 1367#define I915_SET_COLORKEY_SOURCE (1<<2)
1364struct drm_intel_sprite_colorkey { 1368struct drm_intel_sprite_colorkey {
@@ -1604,15 +1608,115 @@ struct drm_i915_perf_oa_config {
1604 __u32 n_flex_regs; 1608 __u32 n_flex_regs;
1605 1609
1606 /* 1610 /*
1607 * These fields are pointers to tuples of u32 values (register 1611 * These fields are pointers to tuples of u32 values (register address,
1608 * address, value). For example the expected length of the buffer 1612 * value). For example the expected length of the buffer pointed by
1609 * pointed by mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). 1613 * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs).
1610 */ 1614 */
1611 __u64 mux_regs_ptr; 1615 __u64 mux_regs_ptr;
1612 __u64 boolean_regs_ptr; 1616 __u64 boolean_regs_ptr;
1613 __u64 flex_regs_ptr; 1617 __u64 flex_regs_ptr;
1614}; 1618};
1615 1619
1620struct drm_i915_query_item {
1621 __u64 query_id;
1622#define DRM_I915_QUERY_TOPOLOGY_INFO 1
1623
1624 /*
1625 * When set to zero by userspace, this is filled with the size of the
1626 * data to be written at the data_ptr pointer. The kernel sets this
1627 * value to a negative value to signal an error on a particular query
1628 * item.
1629 */
1630 __s32 length;
1631
1632 /*
1633 * Unused for now. Must be cleared to zero.
1634 */
1635 __u32 flags;
1636
1637 /*
1638 * Data will be written at the location pointed by data_ptr when the
1639 * value of length matches the length of the data to be written by the
1640 * kernel.
1641 */
1642 __u64 data_ptr;
1643};
1644
1645struct drm_i915_query {
1646 __u32 num_items;
1647
1648 /*
1649 * Unused for now. Must be cleared to zero.
1650 */
1651 __u32 flags;
1652
1653 /*
1654 * This points to an array of num_items drm_i915_query_item structures.
1655 */
1656 __u64 items_ptr;
1657};
1658
1659/*
1660 * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
1661 *
1662 * data: contains the 3 pieces of information :
1663 *
1664 * - the slice mask with one bit per slice telling whether a slice is
1665 * available. The availability of slice X can be queried with the following
1666 * formula :
1667 *
1668 * (data[X / 8] >> (X % 8)) & 1
1669 *
1670 * - the subslice mask for each slice with one bit per subslice telling
1671 * whether a subslice is available. The availability of subslice Y in slice
1672 * X can be queried with the following formula :
1673 *
1674 * (data[subslice_offset +
1675 * X * subslice_stride +
1676 * Y / 8] >> (Y % 8)) & 1
1677 *
1678 * - the EU mask for each subslice in each slice with one bit per EU telling
1679 * whether an EU is available. The availability of EU Z in subslice Y in
1680 * slice X can be queried with the following formula :
1681 *
1682 * (data[eu_offset +
1683 * (X * max_subslices + Y) * eu_stride +
1684 * Z / 8] >> (Z % 8)) & 1
1685 */
1686struct drm_i915_query_topology_info {
1687 /*
1688 * Unused for now. Must be cleared to zero.
1689 */
1690 __u16 flags;
1691
1692 __u16 max_slices;
1693 __u16 max_subslices;
1694 __u16 max_eus_per_subslice;
1695
1696 /*
1697 * Offset in data[] at which the subslice masks are stored.
1698 */
1699 __u16 subslice_offset;
1700
1701 /*
1702 * Stride at which each of the subslice masks for each slice are
1703 * stored.
1704 */
1705 __u16 subslice_stride;
1706
1707 /*
1708 * Offset in data[] at which the EU masks are stored.
1709 */
1710 __u16 eu_offset;
1711
1712 /*
1713 * Stride at which each of the EU masks for each subslice are stored.
1714 */
1715 __u16 eu_stride;
1716
1717 __u8 data[];
1718};
1719
1616#if defined(__cplusplus) 1720#if defined(__cplusplus)
1617} 1721}
1618#endif 1722#endif
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index db6bdc375126..c5ec89732a8d 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -94,6 +94,7 @@ enum bpf_cmd {
94 BPF_MAP_GET_FD_BY_ID, 94 BPF_MAP_GET_FD_BY_ID,
95 BPF_OBJ_GET_INFO_BY_FD, 95 BPF_OBJ_GET_INFO_BY_FD,
96 BPF_PROG_QUERY, 96 BPF_PROG_QUERY,
97 BPF_RAW_TRACEPOINT_OPEN,
97}; 98};
98 99
99enum bpf_map_type { 100enum bpf_map_type {
@@ -133,6 +134,9 @@ enum bpf_prog_type {
133 BPF_PROG_TYPE_SOCK_OPS, 134 BPF_PROG_TYPE_SOCK_OPS,
134 BPF_PROG_TYPE_SK_SKB, 135 BPF_PROG_TYPE_SK_SKB,
135 BPF_PROG_TYPE_CGROUP_DEVICE, 136 BPF_PROG_TYPE_CGROUP_DEVICE,
137 BPF_PROG_TYPE_SK_MSG,
138 BPF_PROG_TYPE_RAW_TRACEPOINT,
139 BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
136}; 140};
137 141
138enum bpf_attach_type { 142enum bpf_attach_type {
@@ -143,6 +147,13 @@ enum bpf_attach_type {
143 BPF_SK_SKB_STREAM_PARSER, 147 BPF_SK_SKB_STREAM_PARSER,
144 BPF_SK_SKB_STREAM_VERDICT, 148 BPF_SK_SKB_STREAM_VERDICT,
145 BPF_CGROUP_DEVICE, 149 BPF_CGROUP_DEVICE,
150 BPF_SK_MSG_VERDICT,
151 BPF_CGROUP_INET4_BIND,
152 BPF_CGROUP_INET6_BIND,
153 BPF_CGROUP_INET4_CONNECT,
154 BPF_CGROUP_INET6_CONNECT,
155 BPF_CGROUP_INET4_POST_BIND,
156 BPF_CGROUP_INET6_POST_BIND,
146 __MAX_BPF_ATTACH_TYPE 157 __MAX_BPF_ATTACH_TYPE
147}; 158};
148 159
@@ -231,6 +242,28 @@ enum bpf_attach_type {
231#define BPF_F_RDONLY (1U << 3) 242#define BPF_F_RDONLY (1U << 3)
232#define BPF_F_WRONLY (1U << 4) 243#define BPF_F_WRONLY (1U << 4)
233 244
245/* Flag for stack_map, store build_id+offset instead of pointer */
246#define BPF_F_STACK_BUILD_ID (1U << 5)
247
248enum bpf_stack_build_id_status {
249 /* user space need an empty entry to identify end of a trace */
250 BPF_STACK_BUILD_ID_EMPTY = 0,
251 /* with valid build_id and offset */
252 BPF_STACK_BUILD_ID_VALID = 1,
253 /* couldn't get build_id, fallback to ip */
254 BPF_STACK_BUILD_ID_IP = 2,
255};
256
257#define BPF_BUILD_ID_SIZE 20
258struct bpf_stack_build_id {
259 __s32 status;
260 unsigned char build_id[BPF_BUILD_ID_SIZE];
261 union {
262 __u64 offset;
263 __u64 ip;
264 };
265};
266
234union bpf_attr { 267union bpf_attr {
235 struct { /* anonymous struct used by BPF_MAP_CREATE command */ 268 struct { /* anonymous struct used by BPF_MAP_CREATE command */
236 __u32 map_type; /* one of enum bpf_map_type */ 269 __u32 map_type; /* one of enum bpf_map_type */
@@ -270,6 +303,11 @@ union bpf_attr {
270 __u32 prog_flags; 303 __u32 prog_flags;
271 char prog_name[BPF_OBJ_NAME_LEN]; 304 char prog_name[BPF_OBJ_NAME_LEN];
272 __u32 prog_ifindex; /* ifindex of netdev to prep for */ 305 __u32 prog_ifindex; /* ifindex of netdev to prep for */
306 /* For some prog types expected attach type must be known at
307 * load time to verify attach type specific parts of prog
308 * (context accesses, allowed helpers, etc).
309 */
310 __u32 expected_attach_type;
273 }; 311 };
274 312
275 struct { /* anonymous struct used by BPF_OBJ_* commands */ 313 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -320,6 +358,11 @@ union bpf_attr {
320 __aligned_u64 prog_ids; 358 __aligned_u64 prog_ids;
321 __u32 prog_cnt; 359 __u32 prog_cnt;
322 } query; 360 } query;
361
362 struct {
363 __u64 name;
364 __u32 prog_fd;
365 } raw_tracepoint;
323} __attribute__((aligned(8))); 366} __attribute__((aligned(8)));
324 367
325/* BPF helper function descriptions: 368/* BPF helper function descriptions:
@@ -696,6 +739,22 @@ union bpf_attr {
696 * int bpf_override_return(pt_regs, rc) 739 * int bpf_override_return(pt_regs, rc)
697 * @pt_regs: pointer to struct pt_regs 740 * @pt_regs: pointer to struct pt_regs
698 * @rc: the return value to set 741 * @rc: the return value to set
742 *
743 * int bpf_msg_redirect_map(map, key, flags)
744 * Redirect msg to a sock in map using key as a lookup key for the
745 * sock in map.
746 * @map: pointer to sockmap
747 * @key: key to lookup sock in map
748 * @flags: reserved for future use
749 * Return: SK_PASS
750 *
751 * int bpf_bind(ctx, addr, addr_len)
752 * Bind socket to address. Only binding to IP is supported, no port can be
753 * set in addr.
754 * @ctx: pointer to context of type bpf_sock_addr
755 * @addr: pointer to struct sockaddr to bind socket to
756 * @addr_len: length of sockaddr structure
757 * Return: 0 on success or negative error code
699 */ 758 */
700#define __BPF_FUNC_MAPPER(FN) \ 759#define __BPF_FUNC_MAPPER(FN) \
701 FN(unspec), \ 760 FN(unspec), \
@@ -757,7 +816,12 @@ union bpf_attr {
757 FN(perf_prog_read_value), \ 816 FN(perf_prog_read_value), \
758 FN(getsockopt), \ 817 FN(getsockopt), \
759 FN(override_return), \ 818 FN(override_return), \
760 FN(sock_ops_cb_flags_set), 819 FN(sock_ops_cb_flags_set), \
820 FN(msg_redirect_map), \
821 FN(msg_apply_bytes), \
822 FN(msg_cork_bytes), \
823 FN(msg_pull_data), \
824 FN(bind),
761 825
762/* integer value in 'imm' field of BPF_CALL instruction selects which helper 826/* integer value in 'imm' field of BPF_CALL instruction selects which helper
763 * function eBPF program intends to call 827 * function eBPF program intends to call
@@ -800,6 +864,7 @@ enum bpf_func_id {
800/* BPF_FUNC_skb_set_tunnel_key flags. */ 864/* BPF_FUNC_skb_set_tunnel_key flags. */
801#define BPF_F_ZERO_CSUM_TX (1ULL << 1) 865#define BPF_F_ZERO_CSUM_TX (1ULL << 1)
802#define BPF_F_DONT_FRAGMENT (1ULL << 2) 866#define BPF_F_DONT_FRAGMENT (1ULL << 2)
867#define BPF_F_SEQ_NUMBER (1ULL << 3)
803 868
804/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and 869/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
805 * BPF_FUNC_perf_event_read_value flags. 870 * BPF_FUNC_perf_event_read_value flags.
@@ -885,6 +950,15 @@ struct bpf_sock {
885 __u32 protocol; 950 __u32 protocol;
886 __u32 mark; 951 __u32 mark;
887 __u32 priority; 952 __u32 priority;
953 __u32 src_ip4; /* Allows 1,2,4-byte read.
954 * Stored in network byte order.
955 */
956 __u32 src_ip6[4]; /* Allows 1,2,4-byte read.
957 * Stored in network byte order.
958 */
959 __u32 src_port; /* Allows 4-byte read.
960 * Stored in host byte order
961 */
888}; 962};
889 963
890#define XDP_PACKET_HEADROOM 256 964#define XDP_PACKET_HEADROOM 256
@@ -919,6 +993,14 @@ enum sk_action {
919 SK_PASS, 993 SK_PASS,
920}; 994};
921 995
996/* user accessible metadata for SK_MSG packet hook, new fields must
997 * be added to the end of this structure
998 */
999struct sk_msg_md {
1000 void *data;
1001 void *data_end;
1002};
1003
922#define BPF_TAG_SIZE 8 1004#define BPF_TAG_SIZE 8
923 1005
924struct bpf_prog_info { 1006struct bpf_prog_info {
@@ -952,6 +1034,26 @@ struct bpf_map_info {
952 __u64 netns_ino; 1034 __u64 netns_ino;
953} __attribute__((aligned(8))); 1035} __attribute__((aligned(8)));
954 1036
1037/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
1038 * by user and intended to be used by socket (e.g. to bind to, depends on
1039 * attach attach type).
1040 */
1041struct bpf_sock_addr {
1042 __u32 user_family; /* Allows 4-byte read, but no write. */
1043 __u32 user_ip4; /* Allows 1,2,4-byte read and 4-byte write.
1044 * Stored in network byte order.
1045 */
1046 __u32 user_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write.
1047 * Stored in network byte order.
1048 */
1049 __u32 user_port; /* Allows 4-byte read and write.
1050 * Stored in network byte order
1051 */
1052 __u32 family; /* Allows 4-byte read, but no write */
1053 __u32 type; /* Allows 4-byte read, but no write */
1054 __u32 protocol; /* Allows 4-byte read, but no write */
1055};
1056
955/* User bpf_sock_ops struct to access socket values and specify request ops 1057/* User bpf_sock_ops struct to access socket values and specify request ops
956 * and their replies. 1058 * and their replies.
957 * Some of this fields are in network (bigendian) byte order and may need 1059 * Some of this fields are in network (bigendian) byte order and may need
@@ -1106,4 +1208,8 @@ struct bpf_cgroup_dev_ctx {
1106 __u32 minor; 1208 __u32 minor;
1107}; 1209};
1108 1210
1211struct bpf_raw_tracepoint_args {
1212 __u64 args[0];
1213};
1214
1109#endif /* _UAPI__LINUX_BPF_H__ */ 1215#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 6d9447700e18..68699f654118 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -941,4 +941,43 @@ enum {
941 IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */ 941 IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */
942}; 942};
943 943
944/* tun section */
945
946enum {
947 IFLA_TUN_UNSPEC,
948 IFLA_TUN_OWNER,
949 IFLA_TUN_GROUP,
950 IFLA_TUN_TYPE,
951 IFLA_TUN_PI,
952 IFLA_TUN_VNET_HDR,
953 IFLA_TUN_PERSIST,
954 IFLA_TUN_MULTI_QUEUE,
955 IFLA_TUN_NUM_QUEUES,
956 IFLA_TUN_NUM_DISABLED_QUEUES,
957 __IFLA_TUN_MAX,
958};
959
960#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1)
961
962/* rmnet section */
963
964#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0)
965#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1)
966#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2)
967#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3)
968
969enum {
970 IFLA_RMNET_UNSPEC,
971 IFLA_RMNET_MUX_ID,
972 IFLA_RMNET_FLAGS,
973 __IFLA_RMNET_MAX,
974};
975
976#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1)
977
978struct ifla_rmnet_flags {
979 __u32 flags;
980 __u32 mask;
981};
982
944#endif /* _UAPI_LINUX_IF_LINK_H */ 983#endif /* _UAPI_LINUX_IF_LINK_H */
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 7b26d4b0b052..b02c41e53d56 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -396,6 +396,10 @@ struct kvm_run {
396 char padding[256]; 396 char padding[256];
397 }; 397 };
398 398
399 /* 2048 is the size of the char array used to bound/pad the size
400 * of the union that holds sync regs.
401 */
402 #define SYNC_REGS_SIZE_BYTES 2048
399 /* 403 /*
400 * shared registers between kvm and userspace. 404 * shared registers between kvm and userspace.
401 * kvm_valid_regs specifies the register classes set by the host 405 * kvm_valid_regs specifies the register classes set by the host
@@ -407,7 +411,7 @@ struct kvm_run {
407 __u64 kvm_dirty_regs; 411 __u64 kvm_dirty_regs;
408 union { 412 union {
409 struct kvm_sync_regs regs; 413 struct kvm_sync_regs regs;
410 char padding[2048]; 414 char padding[SYNC_REGS_SIZE_BYTES];
411 } s; 415 } s;
412}; 416};
413 417
@@ -672,6 +676,13 @@ struct kvm_ioeventfd {
672 __u8 pad[36]; 676 __u8 pad[36];
673}; 677};
674 678
679#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
680#define KVM_X86_DISABLE_EXITS_HTL (1 << 1)
681#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
682#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \
683 KVM_X86_DISABLE_EXITS_HTL | \
684 KVM_X86_DISABLE_EXITS_PAUSE)
685
675/* for KVM_ENABLE_CAP */ 686/* for KVM_ENABLE_CAP */
676struct kvm_enable_cap { 687struct kvm_enable_cap {
677 /* in */ 688 /* in */
@@ -925,7 +936,7 @@ struct kvm_ppc_resize_hpt {
925#define KVM_CAP_S390_GS 140 936#define KVM_CAP_S390_GS 140
926#define KVM_CAP_S390_AIS 141 937#define KVM_CAP_S390_AIS 141
927#define KVM_CAP_SPAPR_TCE_VFIO 142 938#define KVM_CAP_SPAPR_TCE_VFIO 142
928#define KVM_CAP_X86_GUEST_MWAIT 143 939#define KVM_CAP_X86_DISABLE_EXITS 143
929#define KVM_CAP_ARM_USER_IRQ 144 940#define KVM_CAP_ARM_USER_IRQ 144
930#define KVM_CAP_S390_CMMA_MIGRATION 145 941#define KVM_CAP_S390_CMMA_MIGRATION 145
931#define KVM_CAP_PPC_FWNMI 146 942#define KVM_CAP_PPC_FWNMI 146
@@ -936,6 +947,7 @@ struct kvm_ppc_resize_hpt {
936#define KVM_CAP_PPC_GET_CPU_CHAR 151 947#define KVM_CAP_PPC_GET_CPU_CHAR 151
937#define KVM_CAP_S390_BPB 152 948#define KVM_CAP_S390_BPB 152
938#define KVM_CAP_GET_MSR_FEATURES 153 949#define KVM_CAP_GET_MSR_FEATURES 153
950#define KVM_CAP_HYPERV_EVENTFD 154
939 951
940#ifdef KVM_CAP_IRQ_ROUTING 952#ifdef KVM_CAP_IRQ_ROUTING
941 953
@@ -1375,6 +1387,10 @@ struct kvm_enc_region {
1375#define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region) 1387#define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region)
1376#define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region) 1388#define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region)
1377 1389
1390/* Available with KVM_CAP_HYPERV_EVENTFD */
1391#define KVM_HYPERV_EVENTFD _IOW(KVMIO, 0xbd, struct kvm_hyperv_eventfd)
1392
1393
1378/* Secure Encrypted Virtualization command */ 1394/* Secure Encrypted Virtualization command */
1379enum sev_cmd_id { 1395enum sev_cmd_id {
1380 /* Guest initialization commands */ 1396 /* Guest initialization commands */
@@ -1515,4 +1531,14 @@ struct kvm_assigned_msix_entry {
1515#define KVM_ARM_DEV_EL1_PTIMER (1 << 1) 1531#define KVM_ARM_DEV_EL1_PTIMER (1 << 1)
1516#define KVM_ARM_DEV_PMU (1 << 2) 1532#define KVM_ARM_DEV_PMU (1 << 2)
1517 1533
1534struct kvm_hyperv_eventfd {
1535 __u32 conn_id;
1536 __s32 fd;
1537 __u32 flags;
1538 __u32 padding[3];
1539};
1540
1541#define KVM_HYPERV_CONN_ID_MASK 0x00ffffff
1542#define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0)
1543
1518#endif /* __LINUX_KVM_H */ 1544#endif /* __LINUX_KVM_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index e0739a1aa4b2..b8e288a1f740 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -380,10 +380,14 @@ struct perf_event_attr {
380 __u32 bp_type; 380 __u32 bp_type;
381 union { 381 union {
382 __u64 bp_addr; 382 __u64 bp_addr;
383 __u64 kprobe_func; /* for perf_kprobe */
384 __u64 uprobe_path; /* for perf_uprobe */
383 __u64 config1; /* extension of config */ 385 __u64 config1; /* extension of config */
384 }; 386 };
385 union { 387 union {
386 __u64 bp_len; 388 __u64 bp_len;
389 __u64 kprobe_addr; /* when kprobe_func == NULL */
390 __u64 probe_offset; /* for perf_[k,u]probe */
387 __u64 config2; /* extension of config1 */ 391 __u64 config2; /* extension of config1 */
388 }; 392 };
389 __u64 branch_sample_type; /* enum perf_branch_sample_type */ 393 __u64 branch_sample_type; /* enum perf_branch_sample_type */
@@ -444,17 +448,18 @@ struct perf_event_query_bpf {
444/* 448/*
445 * Ioctls that can be done on a perf event fd: 449 * Ioctls that can be done on a perf event fd:
446 */ 450 */
447#define PERF_EVENT_IOC_ENABLE _IO ('$', 0) 451#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
448#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) 452#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
449#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) 453#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
450#define PERF_EVENT_IOC_RESET _IO ('$', 3) 454#define PERF_EVENT_IOC_RESET _IO ('$', 3)
451#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64) 455#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
452#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) 456#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
453#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) 457#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
454#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) 458#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
455#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) 459#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
456#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) 460#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
457#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *) 461#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)
462#define PERF_EVENT_IOC_MODIFY_ATTRIBUTES _IOW('$', 11, struct perf_event_attr *)
458 463
459enum perf_event_ioc_flags { 464enum perf_event_ioc_flags {
460 PERF_IOC_FLAG_GROUP = 1U << 0, 465 PERF_IOC_FLAG_GROUP = 1U << 0,
@@ -645,11 +650,23 @@ struct perf_event_mmap_page {
645#define PERF_RECORD_MISC_COMM_EXEC (1 << 13) 650#define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
646#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) 651#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
647/* 652/*
648 * Indicates that the content of PERF_SAMPLE_IP points to 653 * These PERF_RECORD_MISC_* flags below are safely reused
649 * the actual instruction that triggered the event. See also 654 * for the following events:
650 * perf_event_attr::precise_ip. 655 *
656 * PERF_RECORD_MISC_EXACT_IP - PERF_RECORD_SAMPLE of precise events
657 * PERF_RECORD_MISC_SWITCH_OUT_PREEMPT - PERF_RECORD_SWITCH* events
658 *
659 *
660 * PERF_RECORD_MISC_EXACT_IP:
661 * Indicates that the content of PERF_SAMPLE_IP points to
662 * the actual instruction that triggered the event. See also
663 * perf_event_attr::precise_ip.
664 *
665 * PERF_RECORD_MISC_SWITCH_OUT_PREEMPT:
666 * Indicates that thread was preempted in TASK_RUNNING state.
651 */ 667 */
652#define PERF_RECORD_MISC_EXACT_IP (1 << 14) 668#define PERF_RECORD_MISC_EXACT_IP (1 << 14)
669#define PERF_RECORD_MISC_SWITCH_OUT_PREEMPT (1 << 14)
653/* 670/*
654 * Reserve the last bit to indicate some extended misc field 671 * Reserve the last bit to indicate some extended misc field
655 */ 672 */
diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h
index 07d61583fd02..ed0a120d4f08 100644
--- a/tools/include/uapi/sound/asound.h
+++ b/tools/include/uapi/sound/asound.h
@@ -242,6 +242,7 @@ typedef int __bitwise snd_pcm_format_t;
242#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */ 242#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
243#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */ 243#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
244#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE 244#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE
245#define SNDRV_PCM_FORMAT_FIRST SNDRV_PCM_FORMAT_S8
245 246
246#ifdef SNDRV_LITTLE_ENDIAN 247#ifdef SNDRV_LITTLE_ENDIAN
247#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE 248#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index 5898c22ba310..56c4b3f8a01b 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -1121,9 +1121,6 @@ class Tui(object):
1121 self.screen.refresh() 1121 self.screen.refresh()
1122 1122
1123 def _refresh_body(self, sleeptime): 1123 def _refresh_body(self, sleeptime):
1124 def is_child_field(field):
1125 return field.find('(') != -1
1126
1127 def insert_child(sorted_items, child, values, parent): 1124 def insert_child(sorted_items, child, values, parent):
1128 num = len(sorted_items) 1125 num = len(sorted_items)
1129 for i in range(0, num): 1126 for i in range(0, num):
@@ -1134,12 +1131,14 @@ class Tui(object):
1134 def get_sorted_events(self, stats): 1131 def get_sorted_events(self, stats):
1135 """ separate parent and child events """ 1132 """ separate parent and child events """
1136 if self._sorting == SORT_DEFAULT: 1133 if self._sorting == SORT_DEFAULT:
1137 def sortkey((_k, v)): 1134 def sortkey(pair):
1138 # sort by (delta value, overall value) 1135 # sort by (delta value, overall value)
1136 v = pair[1]
1139 return (v.delta, v.value) 1137 return (v.delta, v.value)
1140 else: 1138 else:
1141 def sortkey((_k, v)): 1139 def sortkey(pair):
1142 # sort by overall value 1140 # sort by overall value
1141 v = pair[1]
1143 return v.value 1142 return v.value
1144 1143
1145 childs = [] 1144 childs = []
@@ -1613,7 +1612,7 @@ def assign_globals():
1613 global PATH_DEBUGFS_TRACING 1612 global PATH_DEBUGFS_TRACING
1614 1613
1615 debugfs = '' 1614 debugfs = ''
1616 for line in file('/proc/mounts'): 1615 for line in open('/proc/mounts'):
1617 if line.split(' ')[0] == 'debugfs': 1616 if line.split(' ')[0] == 'debugfs':
1618 debugfs = line.split(' ')[1] 1617 debugfs = line.split(' ')[1]
1619 break 1618 break
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index b24afc0e6e81..6a12bbf39f7b 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -315,12 +315,8 @@ int filename__read_int(const char *filename, int *value)
315 return err; 315 return err;
316} 316}
317 317
318/* 318static int filename__read_ull_base(const char *filename,
319 * Parses @value out of @filename with strtoull. 319 unsigned long long *value, int base)
320 * By using 0 for base, the strtoull detects the
321 * base automatically (see man strtoull).
322 */
323int filename__read_ull(const char *filename, unsigned long long *value)
324{ 320{
325 char line[64]; 321 char line[64];
326 int fd = open(filename, O_RDONLY), err = -1; 322 int fd = open(filename, O_RDONLY), err = -1;
@@ -329,7 +325,7 @@ int filename__read_ull(const char *filename, unsigned long long *value)
329 return -1; 325 return -1;
330 326
331 if (read(fd, line, sizeof(line)) > 0) { 327 if (read(fd, line, sizeof(line)) > 0) {
332 *value = strtoull(line, NULL, 0); 328 *value = strtoull(line, NULL, base);
333 if (*value != ULLONG_MAX) 329 if (*value != ULLONG_MAX)
334 err = 0; 330 err = 0;
335 } 331 }
@@ -338,6 +334,25 @@ int filename__read_ull(const char *filename, unsigned long long *value)
338 return err; 334 return err;
339} 335}
340 336
337/*
338 * Parses @value out of @filename with strtoull.
339 * By using 16 for base to treat the number as hex.
340 */
341int filename__read_xll(const char *filename, unsigned long long *value)
342{
343 return filename__read_ull_base(filename, value, 16);
344}
345
346/*
347 * Parses @value out of @filename with strtoull.
348 * By using 0 for base, the strtoull detects the
349 * base automatically (see man strtoull).
350 */
351int filename__read_ull(const char *filename, unsigned long long *value)
352{
353 return filename__read_ull_base(filename, value, 0);
354}
355
341#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */ 356#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
342 357
343int filename__read_str(const char *filename, char **buf, size_t *sizep) 358int filename__read_str(const char *filename, char **buf, size_t *sizep)
@@ -417,7 +432,8 @@ int procfs__read_str(const char *entry, char **buf, size_t *sizep)
417 return filename__read_str(path, buf, sizep); 432 return filename__read_str(path, buf, sizep);
418} 433}
419 434
420int sysfs__read_ull(const char *entry, unsigned long long *value) 435static int sysfs__read_ull_base(const char *entry,
436 unsigned long long *value, int base)
421{ 437{
422 char path[PATH_MAX]; 438 char path[PATH_MAX];
423 const char *sysfs = sysfs__mountpoint(); 439 const char *sysfs = sysfs__mountpoint();
@@ -427,7 +443,17 @@ int sysfs__read_ull(const char *entry, unsigned long long *value)
427 443
428 snprintf(path, sizeof(path), "%s/%s", sysfs, entry); 444 snprintf(path, sizeof(path), "%s/%s", sysfs, entry);
429 445
430 return filename__read_ull(path, value); 446 return filename__read_ull_base(path, value, base);
447}
448
449int sysfs__read_xll(const char *entry, unsigned long long *value)
450{
451 return sysfs__read_ull_base(entry, value, 16);
452}
453
454int sysfs__read_ull(const char *entry, unsigned long long *value)
455{
456 return sysfs__read_ull_base(entry, value, 0);
431} 457}
432 458
433int sysfs__read_int(const char *entry, int *value) 459int sysfs__read_int(const char *entry, int *value)
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index dda49deefb52..92d03b8396b1 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -30,6 +30,7 @@ FS(bpf_fs)
30 30
31int filename__read_int(const char *filename, int *value); 31int filename__read_int(const char *filename, int *value);
32int filename__read_ull(const char *filename, unsigned long long *value); 32int filename__read_ull(const char *filename, unsigned long long *value);
33int filename__read_xll(const char *filename, unsigned long long *value);
33int filename__read_str(const char *filename, char **buf, size_t *sizep); 34int filename__read_str(const char *filename, char **buf, size_t *sizep);
34 35
35int filename__write_int(const char *filename, int value); 36int filename__write_int(const char *filename, int value);
@@ -39,6 +40,7 @@ int procfs__read_str(const char *entry, char **buf, size_t *sizep);
39int sysctl__read_int(const char *sysctl, int *value); 40int sysctl__read_int(const char *sysctl, int *value);
40int sysfs__read_int(const char *entry, int *value); 41int sysfs__read_int(const char *entry, int *value);
41int sysfs__read_ull(const char *entry, unsigned long long *value); 42int sysfs__read_ull(const char *entry, unsigned long long *value);
43int sysfs__read_xll(const char *entry, unsigned long long *value);
42int sysfs__read_str(const char *entry, char **buf, size_t *sizep); 44int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
43int sysfs__read_bool(const char *entry, bool *value); 45int sysfs__read_bool(const char *entry, bool *value);
44 46
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 592a58a2b681..acbb3f8b3bec 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -146,26 +146,30 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
146 -1); 146 -1);
147} 147}
148 148
149int bpf_load_program_name(enum bpf_prog_type type, const char *name, 149int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
150 const struct bpf_insn *insns, 150 char *log_buf, size_t log_buf_sz)
151 size_t insns_cnt, const char *license,
152 __u32 kern_version, char *log_buf,
153 size_t log_buf_sz)
154{ 151{
155 int fd;
156 union bpf_attr attr; 152 union bpf_attr attr;
157 __u32 name_len = name ? strlen(name) : 0; 153 __u32 name_len;
154 int fd;
155
156 if (!load_attr)
157 return -EINVAL;
158
159 name_len = load_attr->name ? strlen(load_attr->name) : 0;
158 160
159 bzero(&attr, sizeof(attr)); 161 bzero(&attr, sizeof(attr));
160 attr.prog_type = type; 162 attr.prog_type = load_attr->prog_type;
161 attr.insn_cnt = (__u32)insns_cnt; 163 attr.expected_attach_type = load_attr->expected_attach_type;
162 attr.insns = ptr_to_u64(insns); 164 attr.insn_cnt = (__u32)load_attr->insns_cnt;
163 attr.license = ptr_to_u64(license); 165 attr.insns = ptr_to_u64(load_attr->insns);
166 attr.license = ptr_to_u64(load_attr->license);
164 attr.log_buf = ptr_to_u64(NULL); 167 attr.log_buf = ptr_to_u64(NULL);
165 attr.log_size = 0; 168 attr.log_size = 0;
166 attr.log_level = 0; 169 attr.log_level = 0;
167 attr.kern_version = kern_version; 170 attr.kern_version = load_attr->kern_version;
168 memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); 171 memcpy(attr.prog_name, load_attr->name,
172 min(name_len, BPF_OBJ_NAME_LEN - 1));
169 173
170 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 174 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
171 if (fd >= 0 || !log_buf || !log_buf_sz) 175 if (fd >= 0 || !log_buf || !log_buf_sz)
@@ -184,8 +188,18 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
184 __u32 kern_version, char *log_buf, 188 __u32 kern_version, char *log_buf,
185 size_t log_buf_sz) 189 size_t log_buf_sz)
186{ 190{
187 return bpf_load_program_name(type, NULL, insns, insns_cnt, license, 191 struct bpf_load_program_attr load_attr;
188 kern_version, log_buf, log_buf_sz); 192
193 memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
194 load_attr.prog_type = type;
195 load_attr.expected_attach_type = 0;
196 load_attr.name = NULL;
197 load_attr.insns = insns;
198 load_attr.insns_cnt = insns_cnt;
199 load_attr.license = license;
200 load_attr.kern_version = kern_version;
201
202 return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
189} 203}
190 204
191int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 205int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
@@ -428,6 +442,17 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
428 return err; 442 return err;
429} 443}
430 444
445int bpf_raw_tracepoint_open(const char *name, int prog_fd)
446{
447 union bpf_attr attr;
448
449 bzero(&attr, sizeof(attr));
450 attr.raw_tracepoint.name = ptr_to_u64(name);
451 attr.raw_tracepoint.prog_fd = prog_fd;
452
453 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
454}
455
431int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) 456int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
432{ 457{
433 struct sockaddr_nl sa; 458 struct sockaddr_nl sa;
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 8d18fb73d7fb..39f6a0d64a3b 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -41,13 +41,20 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
41 int key_size, int inner_map_fd, int max_entries, 41 int key_size, int inner_map_fd, int max_entries,
42 __u32 map_flags); 42 __u32 map_flags);
43 43
44struct bpf_load_program_attr {
45 enum bpf_prog_type prog_type;
46 enum bpf_attach_type expected_attach_type;
47 const char *name;
48 const struct bpf_insn *insns;
49 size_t insns_cnt;
50 const char *license;
51 __u32 kern_version;
52};
53
44/* Recommend log buffer size */ 54/* Recommend log buffer size */
45#define BPF_LOG_BUF_SIZE (256 * 1024) 55#define BPF_LOG_BUF_SIZE (256 * 1024)
46int bpf_load_program_name(enum bpf_prog_type type, const char *name, 56int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
47 const struct bpf_insn *insns, 57 char *log_buf, size_t log_buf_sz);
48 size_t insns_cnt, const char *license,
49 __u32 kern_version, char *log_buf,
50 size_t log_buf_sz);
51int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 58int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
52 size_t insns_cnt, const char *license, 59 size_t insns_cnt, const char *license,
53 __u32 kern_version, char *log_buf, 60 __u32 kern_version, char *log_buf,
@@ -79,4 +86,5 @@ int bpf_map_get_fd_by_id(__u32 id);
79int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len); 86int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len);
80int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, 87int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
81 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt); 88 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt);
89int bpf_raw_tracepoint_open(const char *name, int prog_fd);
82#endif 90#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 5bbbf285af74..5922443063f0 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -203,6 +203,8 @@ struct bpf_program {
203 struct bpf_object *obj; 203 struct bpf_object *obj;
204 void *priv; 204 void *priv;
205 bpf_program_clear_priv_t clear_priv; 205 bpf_program_clear_priv_t clear_priv;
206
207 enum bpf_attach_type expected_attach_type;
206}; 208};
207 209
208struct bpf_map { 210struct bpf_map {
@@ -1162,21 +1164,31 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1162} 1164}
1163 1165
1164static int 1166static int
1165load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns, 1167load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type,
1166 int insns_cnt, char *license, u32 kern_version, int *pfd) 1168 const char *name, struct bpf_insn *insns, int insns_cnt,
1169 char *license, u32 kern_version, int *pfd)
1167{ 1170{
1168 int ret; 1171 struct bpf_load_program_attr load_attr;
1169 char *log_buf; 1172 char *log_buf;
1173 int ret;
1170 1174
1171 if (!insns || !insns_cnt) 1175 memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
1176 load_attr.prog_type = type;
1177 load_attr.expected_attach_type = expected_attach_type;
1178 load_attr.name = name;
1179 load_attr.insns = insns;
1180 load_attr.insns_cnt = insns_cnt;
1181 load_attr.license = license;
1182 load_attr.kern_version = kern_version;
1183
1184 if (!load_attr.insns || !load_attr.insns_cnt)
1172 return -EINVAL; 1185 return -EINVAL;
1173 1186
1174 log_buf = malloc(BPF_LOG_BUF_SIZE); 1187 log_buf = malloc(BPF_LOG_BUF_SIZE);
1175 if (!log_buf) 1188 if (!log_buf)
1176 pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); 1189 pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
1177 1190
1178 ret = bpf_load_program_name(type, name, insns, insns_cnt, license, 1191 ret = bpf_load_program_xattr(&load_attr, log_buf, BPF_LOG_BUF_SIZE);
1179 kern_version, log_buf, BPF_LOG_BUF_SIZE);
1180 1192
1181 if (ret >= 0) { 1193 if (ret >= 0) {
1182 *pfd = ret; 1194 *pfd = ret;
@@ -1192,18 +1204,18 @@ load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns,
1192 pr_warning("-- BEGIN DUMP LOG ---\n"); 1204 pr_warning("-- BEGIN DUMP LOG ---\n");
1193 pr_warning("\n%s\n", log_buf); 1205 pr_warning("\n%s\n", log_buf);
1194 pr_warning("-- END LOG --\n"); 1206 pr_warning("-- END LOG --\n");
1195 } else if (insns_cnt >= BPF_MAXINSNS) { 1207 } else if (load_attr.insns_cnt >= BPF_MAXINSNS) {
1196 pr_warning("Program too large (%d insns), at most %d insns\n", 1208 pr_warning("Program too large (%zu insns), at most %d insns\n",
1197 insns_cnt, BPF_MAXINSNS); 1209 load_attr.insns_cnt, BPF_MAXINSNS);
1198 ret = -LIBBPF_ERRNO__PROG2BIG; 1210 ret = -LIBBPF_ERRNO__PROG2BIG;
1199 } else { 1211 } else {
1200 /* Wrong program type? */ 1212 /* Wrong program type? */
1201 if (type != BPF_PROG_TYPE_KPROBE) { 1213 if (load_attr.prog_type != BPF_PROG_TYPE_KPROBE) {
1202 int fd; 1214 int fd;
1203 1215
1204 fd = bpf_load_program_name(BPF_PROG_TYPE_KPROBE, name, 1216 load_attr.prog_type = BPF_PROG_TYPE_KPROBE;
1205 insns, insns_cnt, license, 1217 load_attr.expected_attach_type = 0;
1206 kern_version, NULL, 0); 1218 fd = bpf_load_program_xattr(&load_attr, NULL, 0);
1207 if (fd >= 0) { 1219 if (fd >= 0) {
1208 close(fd); 1220 close(fd);
1209 ret = -LIBBPF_ERRNO__PROGTYPE; 1221 ret = -LIBBPF_ERRNO__PROGTYPE;
@@ -1247,8 +1259,9 @@ bpf_program__load(struct bpf_program *prog,
1247 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", 1259 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
1248 prog->section_name, prog->instances.nr); 1260 prog->section_name, prog->instances.nr);
1249 } 1261 }
1250 err = load_program(prog->type, prog->name, prog->insns, 1262 err = load_program(prog->type, prog->expected_attach_type,
1251 prog->insns_cnt, license, kern_version, &fd); 1263 prog->name, prog->insns, prog->insns_cnt,
1264 license, kern_version, &fd);
1252 if (!err) 1265 if (!err)
1253 prog->instances.fds[0] = fd; 1266 prog->instances.fds[0] = fd;
1254 goto out; 1267 goto out;
@@ -1276,8 +1289,8 @@ bpf_program__load(struct bpf_program *prog,
1276 continue; 1289 continue;
1277 } 1290 }
1278 1291
1279 err = load_program(prog->type, prog->name, 1292 err = load_program(prog->type, prog->expected_attach_type,
1280 result.new_insn_ptr, 1293 prog->name, result.new_insn_ptr,
1281 result.new_insn_cnt, 1294 result.new_insn_cnt,
1282 license, kern_version, &fd); 1295 license, kern_version, &fd);
1283 1296
@@ -1835,11 +1848,25 @@ BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
1835BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); 1848BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
1836BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); 1849BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
1837 1850
1838#define BPF_PROG_SEC(string, type) { string, sizeof(string) - 1, type } 1851static void bpf_program__set_expected_attach_type(struct bpf_program *prog,
1852 enum bpf_attach_type type)
1853{
1854 prog->expected_attach_type = type;
1855}
1856
1857#define BPF_PROG_SEC_FULL(string, ptype, atype) \
1858 { string, sizeof(string) - 1, ptype, atype }
1859
1860#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_FULL(string, ptype, 0)
1861
1862#define BPF_SA_PROG_SEC(string, ptype) \
1863 BPF_PROG_SEC_FULL(string, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, ptype)
1864
1839static const struct { 1865static const struct {
1840 const char *sec; 1866 const char *sec;
1841 size_t len; 1867 size_t len;
1842 enum bpf_prog_type prog_type; 1868 enum bpf_prog_type prog_type;
1869 enum bpf_attach_type expected_attach_type;
1843} section_names[] = { 1870} section_names[] = {
1844 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), 1871 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
1845 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE), 1872 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE),
@@ -1857,10 +1884,18 @@ static const struct {
1857 BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT), 1884 BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT),
1858 BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS), 1885 BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS),
1859 BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), 1886 BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB),
1887 BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG),
1888 BPF_SA_PROG_SEC("cgroup/bind4", BPF_CGROUP_INET4_BIND),
1889 BPF_SA_PROG_SEC("cgroup/bind6", BPF_CGROUP_INET6_BIND),
1890 BPF_SA_PROG_SEC("cgroup/connect4", BPF_CGROUP_INET4_CONNECT),
1891 BPF_SA_PROG_SEC("cgroup/connect6", BPF_CGROUP_INET6_CONNECT),
1860}; 1892};
1893
1861#undef BPF_PROG_SEC 1894#undef BPF_PROG_SEC
1895#undef BPF_PROG_SEC_FULL
1896#undef BPF_SA_PROG_SEC
1862 1897
1863static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog) 1898static int bpf_program__identify_section(struct bpf_program *prog)
1864{ 1899{
1865 int i; 1900 int i;
1866 1901
@@ -1870,13 +1905,13 @@ static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog)
1870 for (i = 0; i < ARRAY_SIZE(section_names); i++) 1905 for (i = 0; i < ARRAY_SIZE(section_names); i++)
1871 if (strncmp(prog->section_name, section_names[i].sec, 1906 if (strncmp(prog->section_name, section_names[i].sec,
1872 section_names[i].len) == 0) 1907 section_names[i].len) == 0)
1873 return section_names[i].prog_type; 1908 return i;
1874 1909
1875err: 1910err:
1876 pr_warning("failed to guess program type based on section name %s\n", 1911 pr_warning("failed to guess program type based on section name %s\n",
1877 prog->section_name); 1912 prog->section_name);
1878 1913
1879 return BPF_PROG_TYPE_UNSPEC; 1914 return -1;
1880} 1915}
1881 1916
1882int bpf_map__fd(struct bpf_map *map) 1917int bpf_map__fd(struct bpf_map *map)
@@ -1976,11 +2011,30 @@ long libbpf_get_error(const void *ptr)
1976int bpf_prog_load(const char *file, enum bpf_prog_type type, 2011int bpf_prog_load(const char *file, enum bpf_prog_type type,
1977 struct bpf_object **pobj, int *prog_fd) 2012 struct bpf_object **pobj, int *prog_fd)
1978{ 2013{
2014 struct bpf_prog_load_attr attr;
2015
2016 memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
2017 attr.file = file;
2018 attr.prog_type = type;
2019 attr.expected_attach_type = 0;
2020
2021 return bpf_prog_load_xattr(&attr, pobj, prog_fd);
2022}
2023
2024int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
2025 struct bpf_object **pobj, int *prog_fd)
2026{
1979 struct bpf_program *prog, *first_prog = NULL; 2027 struct bpf_program *prog, *first_prog = NULL;
2028 enum bpf_attach_type expected_attach_type;
2029 enum bpf_prog_type prog_type;
1980 struct bpf_object *obj; 2030 struct bpf_object *obj;
2031 int section_idx;
1981 int err; 2032 int err;
1982 2033
1983 obj = bpf_object__open(file); 2034 if (!attr)
2035 return -EINVAL;
2036
2037 obj = bpf_object__open(attr->file);
1984 if (IS_ERR(obj)) 2038 if (IS_ERR(obj))
1985 return -ENOENT; 2039 return -ENOENT;
1986 2040
@@ -1989,15 +2043,23 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
1989 * If type is not specified, try to guess it based on 2043 * If type is not specified, try to guess it based on
1990 * section name. 2044 * section name.
1991 */ 2045 */
1992 if (type == BPF_PROG_TYPE_UNSPEC) { 2046 prog_type = attr->prog_type;
1993 type = bpf_program__guess_type(prog); 2047 expected_attach_type = attr->expected_attach_type;
1994 if (type == BPF_PROG_TYPE_UNSPEC) { 2048 if (prog_type == BPF_PROG_TYPE_UNSPEC) {
2049 section_idx = bpf_program__identify_section(prog);
2050 if (section_idx < 0) {
1995 bpf_object__close(obj); 2051 bpf_object__close(obj);
1996 return -EINVAL; 2052 return -EINVAL;
1997 } 2053 }
2054 prog_type = section_names[section_idx].prog_type;
2055 expected_attach_type =
2056 section_names[section_idx].expected_attach_type;
1998 } 2057 }
1999 2058
2000 bpf_program__set_type(prog, type); 2059 bpf_program__set_type(prog, prog_type);
2060 bpf_program__set_expected_attach_type(prog,
2061 expected_attach_type);
2062
2001 if (prog->idx != obj->efile.text_shndx && !first_prog) 2063 if (prog->idx != obj->efile.text_shndx && !first_prog)
2002 first_prog = prog; 2064 first_prog = prog;
2003 } 2065 }
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index f85906533cdd..a3a62a583f27 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -248,6 +248,14 @@ int bpf_map__pin(struct bpf_map *map, const char *path);
248 248
249long libbpf_get_error(const void *ptr); 249long libbpf_get_error(const void *ptr);
250 250
251struct bpf_prog_load_attr {
252 const char *file;
253 enum bpf_prog_type prog_type;
254 enum bpf_attach_type expected_attach_type;
255};
256
257int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
258 struct bpf_object **pobj, int *prog_fd);
251int bpf_prog_load(const char *file, enum bpf_prog_type type, 259int bpf_prog_load(const char *file, enum bpf_prog_type type,
252 struct bpf_object **pobj, int *prog_fd); 260 struct bpf_object **pobj, int *prog_fd);
253 261
diff --git a/tools/lib/str_error_r.c b/tools/lib/str_error_r.c
index d6d65537b0d9..6aad8308a0ac 100644
--- a/tools/lib/str_error_r.c
+++ b/tools/lib/str_error_r.c
@@ -22,6 +22,6 @@ char *str_error_r(int errnum, char *buf, size_t buflen)
22{ 22{
23 int err = strerror_r(errnum, buf, buflen); 23 int err = strerror_r(errnum, buf, buflen);
24 if (err) 24 if (err)
25 snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d", errnum, buf, buflen, err); 25 snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, [buf], %zd)=%d", errnum, buflen, err);
26 return buf; 26 return buf;
27} 27}
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index f6a1babcbac4..cb7154eccbdc 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -433,7 +433,7 @@ match:
433 433
434 if (ambiguous_option) { 434 if (ambiguous_option) {
435 fprintf(stderr, 435 fprintf(stderr,
436 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)", 436 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)\n",
437 arg, 437 arg,
438 (ambiguous_flags & OPT_UNSET) ? "no-" : "", 438 (ambiguous_flags & OPT_UNSET) ? "no-" : "",
439 ambiguous_option->long_name, 439 ambiguous_option->long_name,
@@ -458,7 +458,7 @@ static void check_typos(const char *arg, const struct option *options)
458 return; 458 return;
459 459
460 if (strstarts(arg, "no-")) { 460 if (strstarts(arg, "no-")) {
461 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 461 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)\n", arg);
462 exit(129); 462 exit(129);
463 } 463 }
464 464
@@ -466,7 +466,7 @@ static void check_typos(const char *arg, const struct option *options)
466 if (!options->long_name) 466 if (!options->long_name)
467 continue; 467 continue;
468 if (strstarts(options->long_name, arg)) { 468 if (strstarts(options->long_name, arg)) {
469 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 469 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)\n", arg);
470 exit(129); 470 exit(129);
471 } 471 }
472 } 472 }
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c
index 914cb8e3d40b..689b6a130dd7 100644
--- a/tools/lib/symbol/kallsyms.c
+++ b/tools/lib/symbol/kallsyms.c
@@ -38,6 +38,10 @@ int kallsyms__parse(const char *filename, void *arg,
38 38
39 len = hex2u64(line, &start); 39 len = hex2u64(line, &start);
40 40
41 /* Skip the line if we failed to parse the address. */
42 if (!len)
43 continue;
44
41 len++; 45 len++;
42 if (len + 2 >= line_len) 46 if (len + 2 >= line_len)
43 continue; 47 continue;
diff --git a/tools/memory-model/Documentation/cheatsheet.txt b/tools/memory-model/Documentation/cheatsheet.txt
new file mode 100644
index 000000000000..956b1ae4aafb
--- /dev/null
+++ b/tools/memory-model/Documentation/cheatsheet.txt
@@ -0,0 +1,29 @@
1 Prior Operation Subsequent Operation
2 --------------- ---------------------------
3 C Self R W RWM Self R W DR DW RMW SV
4 -- ---- - - --- ---- - - -- -- --- --
5
6Store, e.g., WRITE_ONCE() Y Y
7Load, e.g., READ_ONCE() Y Y Y Y
8Unsuccessful RMW operation Y Y Y Y
9rcu_dereference() Y Y Y Y
10Successful *_acquire() R Y Y Y Y Y Y
11Successful *_release() C Y Y Y W Y
12smp_rmb() Y R Y Y R
13smp_wmb() Y W Y Y W
14smp_mb() & synchronize_rcu() CP Y Y Y Y Y Y Y Y
15Successful full non-void RMW CP Y Y Y Y Y Y Y Y Y Y Y
16smp_mb__before_atomic() CP Y Y Y a a a a Y
17smp_mb__after_atomic() CP a a Y Y Y Y Y
18
19
20Key: C: Ordering is cumulative
21 P: Ordering propagates
22 R: Read, for example, READ_ONCE(), or read portion of RMW
23 W: Write, for example, WRITE_ONCE(), or write portion of RMW
24 Y: Provides ordering
25 a: Provides ordering given intervening RMW atomic operation
26 DR: Dependent read (address dependency)
27 DW: Dependent write (address, data, or control dependency)
28 RMW: Atomic read-modify-write operation
29 SV Same-variable access
diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
new file mode 100644
index 000000000000..a727c82bd434
--- /dev/null
+++ b/tools/memory-model/Documentation/explanation.txt
@@ -0,0 +1,1845 @@
1Explanation of the Linux-Kernel Memory Consistency Model
2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4:Author: Alan Stern <stern@rowland.harvard.edu>
5:Created: October 2017
6
7.. Contents
8
9 1. INTRODUCTION
10 2. BACKGROUND
11 3. A SIMPLE EXAMPLE
12 4. A SELECTION OF MEMORY MODELS
13 5. ORDERING AND CYCLES
14 6. EVENTS
15 7. THE PROGRAM ORDER RELATION: po AND po-loc
16 8. A WARNING
17 9. DEPENDENCY RELATIONS: data, addr, and ctrl
18 10. THE READS-FROM RELATION: rf, rfi, and rfe
19 11. CACHE COHERENCE AND THE COHERENCE ORDER RELATION: co, coi, and coe
20 12. THE FROM-READS RELATION: fr, fri, and fre
21 13. AN OPERATIONAL MODEL
22 14. PROPAGATION ORDER RELATION: cumul-fence
23 15. DERIVATION OF THE LKMM FROM THE OPERATIONAL MODEL
24 16. SEQUENTIAL CONSISTENCY PER VARIABLE
25 17. ATOMIC UPDATES: rmw
26 18. THE PRESERVED PROGRAM ORDER RELATION: ppo
27 19. AND THEN THERE WAS ALPHA
28 20. THE HAPPENS-BEFORE RELATION: hb
29 21. THE PROPAGATES-BEFORE RELATION: pb
30 22. RCU RELATIONS: link, gp-link, rscs-link, and rcu-path
31 23. ODDS AND ENDS
32
33
34
35INTRODUCTION
36------------
37
38The Linux-kernel memory consistency model (LKMM) is rather complex and
39obscure. This is particularly evident if you read through the
40linux-kernel.bell and linux-kernel.cat files that make up the formal
41version of the model; they are extremely terse and their meanings are
42far from clear.
43
44This document describes the ideas underlying the LKMM. It is meant
45for people who want to understand how the model was designed. It does
46not go into the details of the code in the .bell and .cat files;
47rather, it explains in English what the code expresses symbolically.
48
49Sections 2 (BACKGROUND) through 5 (ORDERING AND CYCLES) are aimed
50toward beginners; they explain what memory consistency models are and
51the basic notions shared by all such models. People already familiar
52with these concepts can skim or skip over them. Sections 6 (EVENTS)
53through 12 (THE FROM_READS RELATION) describe the fundamental
54relations used in many models. Starting in Section 13 (AN OPERATIONAL
55MODEL), the workings of the LKMM itself are covered.
56
57Warning: The code examples in this document are not written in the
58proper format for litmus tests. They don't include a header line, the
59initializations are not enclosed in braces, the global variables are
60not passed by pointers, and they don't have an "exists" clause at the
61end. Converting them to the right format is left as an exercise for
62the reader.
63
64
65BACKGROUND
66----------
67
68A memory consistency model (or just memory model, for short) is
69something which predicts, given a piece of computer code running on a
70particular kind of system, what values may be obtained by the code's
71load instructions. The LKMM makes these predictions for code running
72as part of the Linux kernel.
73
74In practice, people tend to use memory models the other way around.
75That is, given a piece of code and a collection of values specified
76for the loads, the model will predict whether it is possible for the
77code to run in such a way that the loads will indeed obtain the
78specified values. Of course, this is just another way of expressing
79the same idea.
80
81For code running on a uniprocessor system, the predictions are easy:
82Each load instruction must obtain the value written by the most recent
83store instruction accessing the same location (we ignore complicating
84factors such as DMA and mixed-size accesses.) But on multiprocessor
85systems, with multiple CPUs making concurrent accesses to shared
86memory locations, things aren't so simple.
87
88Different architectures have differing memory models, and the Linux
89kernel supports a variety of architectures. The LKMM has to be fairly
90permissive, in the sense that any behavior allowed by one of these
91architectures also has to be allowed by the LKMM.
92
93
94A SIMPLE EXAMPLE
95----------------
96
97Here is a simple example to illustrate the basic concepts. Consider
98some code running as part of a device driver for an input device. The
99driver might contain an interrupt handler which collects data from the
100device, stores it in a buffer, and sets a flag to indicate the buffer
101is full. Running concurrently on a different CPU might be a part of
102the driver code being executed by a process in the midst of a read(2)
103system call. This code tests the flag to see whether the buffer is
104ready, and if it is, copies the data back to userspace. The buffer
105and the flag are memory locations shared between the two CPUs.
106
107We can abstract out the important pieces of the driver code as follows
108(the reason for using WRITE_ONCE() and READ_ONCE() instead of simple
109assignment statements is discussed later):
110
111 int buf = 0, flag = 0;
112
113 P0()
114 {
115 WRITE_ONCE(buf, 1);
116 WRITE_ONCE(flag, 1);
117 }
118
119 P1()
120 {
121 int r1;
122 int r2 = 0;
123
124 r1 = READ_ONCE(flag);
125 if (r1)
126 r2 = READ_ONCE(buf);
127 }
128
129Here the P0() function represents the interrupt handler running on one
130CPU and P1() represents the read() routine running on another. The
131value 1 stored in buf represents input data collected from the device.
132Thus, P0 stores the data in buf and then sets flag. Meanwhile, P1
133reads flag into the private variable r1, and if it is set, reads the
134data from buf into a second private variable r2 for copying to
135userspace. (Presumably if flag is not set then the driver will wait a
136while and try again.)
137
138This pattern of memory accesses, where one CPU stores values to two
139shared memory locations and another CPU loads from those locations in
140the opposite order, is widely known as the "Message Passing" or MP
141pattern. It is typical of memory access patterns in the kernel.
142
143Please note that this example code is a simplified abstraction. Real
144buffers are usually larger than a single integer, real device drivers
145usually use sleep and wakeup mechanisms rather than polling for I/O
146completion, and real code generally doesn't bother to copy values into
147private variables before using them. All that is beside the point;
148the idea here is simply to illustrate the overall pattern of memory
149accesses by the CPUs.
150
151A memory model will predict what values P1 might obtain for its loads
152from flag and buf, or equivalently, what values r1 and r2 might end up
153with after the code has finished running.
154
155Some predictions are trivial. For instance, no sane memory model would
156predict that r1 = 42 or r2 = -7, because neither of those values ever
157gets stored in flag or buf.
158
159Some nontrivial predictions are nonetheless quite simple. For
160instance, P1 might run entirely before P0 begins, in which case r1 and
161r2 will both be 0 at the end. Or P0 might run entirely before P1
162begins, in which case r1 and r2 will both be 1.
163
164The interesting predictions concern what might happen when the two
165routines run concurrently. One possibility is that P1 runs after P0's
166store to buf but before the store to flag. In this case, r1 and r2
167will again both be 0. (If P1 had been designed to read buf
168unconditionally then we would instead have r1 = 0 and r2 = 1.)
169
170However, the most interesting possibility is where r1 = 1 and r2 = 0.
171If this were to occur it would mean the driver contains a bug, because
172incorrect data would get sent to the user: 0 instead of 1. As it
173happens, the LKMM does predict this outcome can occur, and the example
174driver code shown above is indeed buggy.
175
176
177A SELECTION OF MEMORY MODELS
178----------------------------
179
180The first widely cited memory model, and the simplest to understand,
181is Sequential Consistency. According to this model, systems behave as
182if each CPU executed its instructions in order but with unspecified
183timing. In other words, the instructions from the various CPUs get
184interleaved in a nondeterministic way, always according to some single
185global order that agrees with the order of the instructions in the
186program source for each CPU. The model says that the value obtained
187by each load is simply the value written by the most recently executed
188store to the same memory location, from any CPU.
189
190For the MP example code shown above, Sequential Consistency predicts
191that the undesired result r1 = 1, r2 = 0 cannot occur. The reasoning
192goes like this:
193
194 Since r1 = 1, P0 must store 1 to flag before P1 loads 1 from
195 it, as loads can obtain values only from earlier stores.
196
197 P1 loads from flag before loading from buf, since CPUs execute
198 their instructions in order.
199
200 P1 must load 0 from buf before P0 stores 1 to it; otherwise r2
201 would be 1 since a load obtains its value from the most recent
202 store to the same address.
203
204 P0 stores 1 to buf before storing 1 to flag, since it executes
205 its instructions in order.
206
207 Since an instruction (in this case, P1's store to flag) cannot
208 execute before itself, the specified outcome is impossible.
209
210However, real computer hardware almost never follows the Sequential
211Consistency memory model; doing so would rule out too many valuable
212performance optimizations. On ARM and PowerPC architectures, for
213instance, the MP example code really does sometimes yield r1 = 1 and
214r2 = 0.
215
216x86 and SPARC follow yet a different memory model: TSO (Total Store
217Ordering). This model predicts that the undesired outcome for the MP
218pattern cannot occur, but in other respects it differs from Sequential
219Consistency. One example is the Store Buffer (SB) pattern, in which
220each CPU stores to its own shared location and then loads from the
221other CPU's location:
222
223 int x = 0, y = 0;
224
225 P0()
226 {
227 int r0;
228
229 WRITE_ONCE(x, 1);
230 r0 = READ_ONCE(y);
231 }
232
233 P1()
234 {
235 int r1;
236
237 WRITE_ONCE(y, 1);
238 r1 = READ_ONCE(x);
239 }
240
241Sequential Consistency predicts that the outcome r0 = 0, r1 = 0 is
242impossible. (Exercise: Figure out the reasoning.) But TSO allows
243this outcome to occur, and in fact it does sometimes occur on x86 and
244SPARC systems.
245
246The LKMM was inspired by the memory models followed by PowerPC, ARM,
247x86, Alpha, and other architectures. However, it is different in
248detail from each of them.
249
250
251ORDERING AND CYCLES
252-------------------
253
254Memory models are all about ordering. Often this is temporal ordering
255(i.e., the order in which certain events occur) but it doesn't have to
256be; consider for example the order of instructions in a program's
257source code. We saw above that Sequential Consistency makes an
258important assumption that CPUs execute instructions in the same order
259as those instructions occur in the code, and there are many other
260instances of ordering playing central roles in memory models.
261
262The counterpart to ordering is a cycle. Ordering rules out cycles:
263It's not possible to have X ordered before Y, Y ordered before Z, and
264Z ordered before X, because this would mean that X is ordered before
265itself. The analysis of the MP example under Sequential Consistency
266involved just such an impossible cycle:
267
268 W: P0 stores 1 to flag executes before
269 X: P1 loads 1 from flag executes before
270 Y: P1 loads 0 from buf executes before
271 Z: P0 stores 1 to buf executes before
272 W: P0 stores 1 to flag.
273
274In short, if a memory model requires certain accesses to be ordered,
275and a certain outcome for the loads in a piece of code can happen only
276if those accesses would form a cycle, then the memory model predicts
277that outcome cannot occur.
278
279The LKMM is defined largely in terms of cycles, as we will see.
280
281
282EVENTS
283------
284
285The LKMM does not work directly with the C statements that make up
286kernel source code. Instead it considers the effects of those
287statements in a more abstract form, namely, events. The model
288includes three types of events:
289
290 Read events correspond to loads from shared memory, such as
291 calls to READ_ONCE(), smp_load_acquire(), or
292 rcu_dereference().
293
294 Write events correspond to stores to shared memory, such as
295 calls to WRITE_ONCE(), smp_store_release(), or atomic_set().
296
297 Fence events correspond to memory barriers (also known as
298 fences), such as calls to smp_rmb() or rcu_read_lock().
299
300These categories are not exclusive; a read or write event can also be
301a fence. This happens with functions like smp_load_acquire() or
302spin_lock(). However, no single event can be both a read and a write.
303Atomic read-modify-write accesses, such as atomic_inc() or xchg(),
304correspond to a pair of events: a read followed by a write. (The
305write event is omitted for executions where it doesn't occur, such as
306a cmpxchg() where the comparison fails.)
307
308Other parts of the code, those which do not involve interaction with
309shared memory, do not give rise to events. Thus, arithmetic and
310logical computations, control-flow instructions, or accesses to
311private memory or CPU registers are not of central interest to the
312memory model. They only affect the model's predictions indirectly.
313For example, an arithmetic computation might determine the value that
314gets stored to a shared memory location (or in the case of an array
315index, the address where the value gets stored), but the memory model
316is concerned only with the store itself -- its value and its address
317-- not the computation leading up to it.
318
319Events in the LKMM can be linked by various relations, which we will
320describe in the following sections. The memory model requires certain
321of these relations to be orderings, that is, it requires them not to
322have any cycles.
323
324
325THE PROGRAM ORDER RELATION: po AND po-loc
326-----------------------------------------
327
328The most important relation between events is program order (po). You
329can think of it as the order in which statements occur in the source
330code after branches are taken into account and loops have been
331unrolled. A better description might be the order in which
332instructions are presented to a CPU's execution unit. Thus, we say
333that X is po-before Y (written as "X ->po Y" in formulas) if X occurs
334before Y in the instruction stream.
335
336This is inherently a single-CPU relation; two instructions executing
337on different CPUs are never linked by po. Also, it is by definition
338an ordering so it cannot have any cycles.
339
340po-loc is a sub-relation of po. It links two memory accesses when the
341first comes before the second in program order and they access the
342same memory location (the "-loc" suffix).
343
344Although this may seem straightforward, there is one subtle aspect to
345program order we need to explain. The LKMM was inspired by low-level
346architectural memory models which describe the behavior of machine
347code, and it retains their outlook to a considerable extent. The
348read, write, and fence events used by the model are close in spirit to
349individual machine instructions. Nevertheless, the LKMM describes
350kernel code written in C, and the mapping from C to machine code can
351be extremely complex.
352
353Optimizing compilers have great freedom in the way they translate
354source code to object code. They are allowed to apply transformations
355that add memory accesses, eliminate accesses, combine them, split them
356into pieces, or move them around. Faced with all these possibilities,
357the LKMM basically gives up. It insists that the code it analyzes
358must contain no ordinary accesses to shared memory; all accesses must
359be performed using READ_ONCE(), WRITE_ONCE(), or one of the other
360atomic or synchronization primitives. These primitives prevent a
361large number of compiler optimizations. In particular, it is
362guaranteed that the compiler will not remove such accesses from the
363generated code (unless it can prove the accesses will never be
364executed), it will not change the order in which they occur in the
365code (within limits imposed by the C standard), and it will not
366introduce extraneous accesses.
367
368This explains why the MP and SB examples above used READ_ONCE() and
369WRITE_ONCE() rather than ordinary memory accesses. Thanks to this
370usage, we can be certain that in the MP example, P0's write event to
371buf really is po-before its write event to flag, and similarly for the
372other shared memory accesses in the examples.
373
374Private variables are not subject to this restriction. Since they are
375not shared between CPUs, they can be accessed normally without
376READ_ONCE() or WRITE_ONCE(), and there will be no ill effects. In
377fact, they need not even be stored in normal memory at all -- in
378principle a private variable could be stored in a CPU register (hence
379the convention that these variables have names starting with the
380letter 'r').
381
382
383A WARNING
384---------
385
386The protections provided by READ_ONCE(), WRITE_ONCE(), and others are
387not perfect; and under some circumstances it is possible for the
388compiler to undermine the memory model. Here is an example. Suppose
389both branches of an "if" statement store the same value to the same
390location:
391
392 r1 = READ_ONCE(x);
393 if (r1) {
394 WRITE_ONCE(y, 2);
395 ... /* do something */
396 } else {
397 WRITE_ONCE(y, 2);
398 ... /* do something else */
399 }
400
401For this code, the LKMM predicts that the load from x will always be
402executed before either of the stores to y. However, a compiler could
403lift the stores out of the conditional, transforming the code into
404something resembling:
405
406 r1 = READ_ONCE(x);
407 WRITE_ONCE(y, 2);
408 if (r1) {
409 ... /* do something */
410 } else {
411 ... /* do something else */
412 }
413
414Given this version of the code, the LKMM would predict that the load
415from x could be executed after the store to y. Thus, the memory
416model's original prediction could be invalidated by the compiler.
417
418Another issue arises from the fact that in C, arguments to many
419operators and function calls can be evaluated in any order. For
420example:
421
422 r1 = f(5) + g(6);
423
424The object code might call f(5) either before or after g(6); the
425memory model cannot assume there is a fixed program order relation
426between them. (In fact, if the functions are inlined then the
427compiler might even interleave their object code.)
428
429
430DEPENDENCY RELATIONS: data, addr, and ctrl
431------------------------------------------
432
433We say that two events are linked by a dependency relation when the
434execution of the second event depends in some way on a value obtained
435from memory by the first. The first event must be a read, and the
436value it obtains must somehow affect what the second event does.
437There are three kinds of dependencies: data, address (addr), and
438control (ctrl).
439
440A read and a write event are linked by a data dependency if the value
441obtained by the read affects the value stored by the write. As a very
442simple example:
443
444 int x, y;
445
446 r1 = READ_ONCE(x);
447 WRITE_ONCE(y, r1 + 5);
448
449The value stored by the WRITE_ONCE obviously depends on the value
450loaded by the READ_ONCE. Such dependencies can wind through
451arbitrarily complicated computations, and a write can depend on the
452values of multiple reads.
453
454A read event and another memory access event are linked by an address
455dependency if the value obtained by the read affects the location
456accessed by the other event. The second event can be either a read or
457a write. Here's another simple example:
458
459 int a[20];
460 int i;
461
462 r1 = READ_ONCE(i);
463 r2 = READ_ONCE(a[r1]);
464
465Here the location accessed by the second READ_ONCE() depends on the
466index value loaded by the first. Pointer indirection also gives rise
467to address dependencies, since the address of a location accessed
468through a pointer will depend on the value read earlier from that
469pointer.
470
471Finally, a read event and another memory access event are linked by a
472control dependency if the value obtained by the read affects whether
473the second event is executed at all. Simple example:
474
475 int x, y;
476
477 r1 = READ_ONCE(x);
478 if (r1)
479 WRITE_ONCE(y, 1984);
480
481Execution of the WRITE_ONCE() is controlled by a conditional expression
482which depends on the value obtained by the READ_ONCE(); hence there is
483a control dependency from the load to the store.
484
485It should be pretty obvious that events can only depend on reads that
486come earlier in program order. Symbolically, if we have R ->data X,
487R ->addr X, or R ->ctrl X (where R is a read event), then we must also
488have R ->po X. It wouldn't make sense for a computation to depend
489somehow on a value that doesn't get loaded from shared memory until
490later in the code!
491
492
493THE READS-FROM RELATION: rf, rfi, and rfe
494-----------------------------------------
495
496The reads-from relation (rf) links a write event to a read event when
497the value loaded by the read is the value that was stored by the
498write. In colloquial terms, the load "reads from" the store. We
499write W ->rf R to indicate that the load R reads from the store W. We
500further distinguish the cases where the load and the store occur on
501the same CPU (internal reads-from, or rfi) and where they occur on
502different CPUs (external reads-from, or rfe).
503
504For our purposes, a memory location's initial value is treated as
505though it had been written there by an imaginary initial store that
506executes on a separate CPU before the program runs.
507
508Usage of the rf relation implicitly assumes that loads will always
509read from a single store. It doesn't apply properly in the presence
510of load-tearing, where a load obtains some of its bits from one store
511and some of them from another store. Fortunately, use of READ_ONCE()
512and WRITE_ONCE() will prevent load-tearing; it's not possible to have:
513
514 int x = 0;
515
516 P0()
517 {
518 WRITE_ONCE(x, 0x1234);
519 }
520
521 P1()
522 {
523 int r1;
524
525 r1 = READ_ONCE(x);
526 }
527
528and end up with r1 = 0x1200 (partly from x's initial value and partly
529from the value stored by P0).
530
531On the other hand, load-tearing is unavoidable when mixed-size
532accesses are used. Consider this example:
533
534 union {
535 u32 w;
536 u16 h[2];
537 } x;
538
539 P0()
540 {
541 WRITE_ONCE(x.h[0], 0x1234);
542 WRITE_ONCE(x.h[1], 0x5678);
543 }
544
545 P1()
546 {
547 int r1;
548
549 r1 = READ_ONCE(x.w);
550 }
551
552If r1 = 0x56781234 (little-endian!) at the end, then P1 must have read
553from both of P0's stores. It is possible to handle mixed-size and
554unaligned accesses in a memory model, but the LKMM currently does not
555attempt to do so. It requires all accesses to be properly aligned and
556of the location's actual size.
557
558
559CACHE COHERENCE AND THE COHERENCE ORDER RELATION: co, coi, and coe
560------------------------------------------------------------------
561
562Cache coherence is a general principle requiring that in a
563multi-processor system, the CPUs must share a consistent view of the
564memory contents. Specifically, it requires that for each location in
565shared memory, the stores to that location must form a single global
566ordering which all the CPUs agree on (the coherence order), and this
567ordering must be consistent with the program order for accesses to
568that location.
569
570To put it another way, for any variable x, the coherence order (co) of
571the stores to x is simply the order in which the stores overwrite one
572another. The imaginary store which establishes x's initial value
573comes first in the coherence order; the store which directly
574overwrites the initial value comes second; the store which overwrites
575that value comes third, and so on.
576
577You can think of the coherence order as being the order in which the
578stores reach x's location in memory (or if you prefer a more
579hardware-centric view, the order in which the stores get written to
580x's cache line). We write W ->co W' if W comes before W' in the
581coherence order, that is, if the value stored by W gets overwritten,
582directly or indirectly, by the value stored by W'.
583
584Coherence order is required to be consistent with program order. This
585requirement takes the form of four coherency rules:
586
587 Write-write coherence: If W ->po-loc W' (i.e., W comes before
588 W' in program order and they access the same location), where W
589 and W' are two stores, then W ->co W'.
590
591 Write-read coherence: If W ->po-loc R, where W is a store and R
592 is a load, then R must read from W or from some other store
593 which comes after W in the coherence order.
594
595 Read-write coherence: If R ->po-loc W, where R is a load and W
596 is a store, then the store which R reads from must come before
597 W in the coherence order.
598
599 Read-read coherence: If R ->po-loc R', where R and R' are two
600 loads, then either they read from the same store or else the
601 store read by R comes before the store read by R' in the
602 coherence order.
603
604This is sometimes referred to as sequential consistency per variable,
605because it means that the accesses to any single memory location obey
606the rules of the Sequential Consistency memory model. (According to
607Wikipedia, sequential consistency per variable and cache coherence
608mean the same thing except that cache coherence includes an extra
609requirement that every store eventually becomes visible to every CPU.)
610
611Any reasonable memory model will include cache coherence. Indeed, our
612expectation of cache coherence is so deeply ingrained that violations
613of its requirements look more like hardware bugs than programming
614errors:
615
616 int x;
617
618 P0()
619 {
620 WRITE_ONCE(x, 17);
621 WRITE_ONCE(x, 23);
622 }
623
624If the final value stored in x after this code ran was 17, you would
625think your computer was broken. It would be a violation of the
626write-write coherence rule: Since the store of 23 comes later in
627program order, it must also come later in x's coherence order and
628thus must overwrite the store of 17.
629
630 int x = 0;
631
632 P0()
633 {
634 int r1;
635
636 r1 = READ_ONCE(x);
637 WRITE_ONCE(x, 666);
638 }
639
640If r1 = 666 at the end, this would violate the read-write coherence
641rule: The READ_ONCE() load comes before the WRITE_ONCE() store in
642program order, so it must not read from that store but rather from one
643coming earlier in the coherence order (in this case, x's initial
644value).
645
646 int x = 0;
647
648 P0()
649 {
650 WRITE_ONCE(x, 5);
651 }
652
653 P1()
654 {
655 int r1, r2;
656
657 r1 = READ_ONCE(x);
658 r2 = READ_ONCE(x);
659 }
660
661If r1 = 5 (reading from P0's store) and r2 = 0 (reading from the
662imaginary store which establishes x's initial value) at the end, this
663would violate the read-read coherence rule: The r1 load comes before
664the r2 load in program order, so it must not read from a store that
665comes later in the coherence order.
666
667(As a minor curiosity, if this code had used normal loads instead of
668READ_ONCE() in P1, on Itanium it sometimes could end up with r1 = 5
669and r2 = 0! This results from parallel execution of the operations
670encoded in Itanium's Very-Long-Instruction-Word format, and it is yet
671another motivation for using READ_ONCE() when accessing shared memory
672locations.)
673
674Just like the po relation, co is inherently an ordering -- it is not
675possible for a store to directly or indirectly overwrite itself! And
676just like with the rf relation, we distinguish between stores that
677occur on the same CPU (internal coherence order, or coi) and stores
678that occur on different CPUs (external coherence order, or coe).
679
680On the other hand, stores to different memory locations are never
681related by co, just as instructions on different CPUs are never
682related by po. Coherence order is strictly per-location, or if you
683prefer, each location has its own independent coherence order.
684
685
686THE FROM-READS RELATION: fr, fri, and fre
687-----------------------------------------
688
689The from-reads relation (fr) can be a little difficult for people to
690grok. It describes the situation where a load reads a value that gets
691overwritten by a store. In other words, we have R ->fr W when the
692value that R reads is overwritten (directly or indirectly) by W, or
693equivalently, when R reads from a store which comes earlier than W in
694the coherence order.
695
696For example:
697
698 int x = 0;
699
700 P0()
701 {
702 int r1;
703
704 r1 = READ_ONCE(x);
705 WRITE_ONCE(x, 2);
706 }
707
708The value loaded from x will be 0 (assuming cache coherence!), and it
709gets overwritten by the value 2. Thus there is an fr link from the
710READ_ONCE() to the WRITE_ONCE(). If the code contained any later
711stores to x, there would also be fr links from the READ_ONCE() to
712them.
713
714As with rf, rfi, and rfe, we subdivide the fr relation into fri (when
715the load and the store are on the same CPU) and fre (when they are on
716different CPUs).
717
718Note that the fr relation is determined entirely by the rf and co
719relations; it is not independent. Given a read event R and a write
720event W for the same location, we will have R ->fr W if and only if
721the write which R reads from is co-before W. In symbols,
722
723 (R ->fr W) := (there exists W' with W' ->rf R and W' ->co W).
724
725
726AN OPERATIONAL MODEL
727--------------------
728
729The LKMM is based on various operational memory models, meaning that
730the models arise from an abstract view of how a computer system
731operates. Here are the main ideas, as incorporated into the LKMM.
732
733The system as a whole is divided into the CPUs and a memory subsystem.
734The CPUs are responsible for executing instructions (not necessarily
735in program order), and they communicate with the memory subsystem.
736For the most part, executing an instruction requires a CPU to perform
737only internal operations. However, loads, stores, and fences involve
738more.
739
740When CPU C executes a store instruction, it tells the memory subsystem
741to store a certain value at a certain location. The memory subsystem
742propagates the store to all the other CPUs as well as to RAM. (As a
743special case, we say that the store propagates to its own CPU at the
744time it is executed.) The memory subsystem also determines where the
745store falls in the location's coherence order. In particular, it must
746arrange for the store to be co-later than (i.e., to overwrite) any
747other store to the same location which has already propagated to CPU C.
748
749When a CPU executes a load instruction R, it first checks to see
750whether there are any as-yet unexecuted store instructions, for the
751same location, that come before R in program order. If there are, it
752uses the value of the po-latest such store as the value obtained by R,
753and we say that the store's value is forwarded to R. Otherwise, the
754CPU asks the memory subsystem for the value to load and we say that R
755is satisfied from memory. The memory subsystem hands back the value
756of the co-latest store to the location in question which has already
757propagated to that CPU.
758
759(In fact, the picture needs to be a little more complicated than this.
760CPUs have local caches, and propagating a store to a CPU really means
761propagating it to the CPU's local cache. A local cache can take some
762time to process the stores that it receives, and a store can't be used
763to satisfy one of the CPU's loads until it has been processed. On
764most architectures, the local caches process stores in
765First-In-First-Out order, and consequently the processing delay
766doesn't matter for the memory model. But on Alpha, the local caches
767have a partitioned design that results in non-FIFO behavior. We will
768discuss this in more detail later.)
769
770Note that load instructions may be executed speculatively and may be
771restarted under certain circumstances. The memory model ignores these
772premature executions; we simply say that the load executes at the
773final time it is forwarded or satisfied.
774
775Executing a fence (or memory barrier) instruction doesn't require a
776CPU to do anything special other than informing the memory subsystem
777about the fence. However, fences do constrain the way CPUs and the
778memory subsystem handle other instructions, in two respects.
779
780First, a fence forces the CPU to execute various instructions in
781program order. Exactly which instructions are ordered depends on the
782type of fence:
783
784 Strong fences, including smp_mb() and synchronize_rcu(), force
785 the CPU to execute all po-earlier instructions before any
786 po-later instructions;
787
788 smp_rmb() forces the CPU to execute all po-earlier loads
789 before any po-later loads;
790
791 smp_wmb() forces the CPU to execute all po-earlier stores
792 before any po-later stores;
793
794 Acquire fences, such as smp_load_acquire(), force the CPU to
795 execute the load associated with the fence (e.g., the load
796 part of an smp_load_acquire()) before any po-later
797 instructions;
798
799 Release fences, such as smp_store_release(), force the CPU to
800 execute all po-earlier instructions before the store
801 associated with the fence (e.g., the store part of an
802 smp_store_release()).
803
804Second, some types of fence affect the way the memory subsystem
805propagates stores. When a fence instruction is executed on CPU C:
806
807 For each other CPU C', smb_wmb() forces all po-earlier stores
808 on C to propagate to C' before any po-later stores do.
809
810 For each other CPU C', any store which propagates to C before
811 a release fence is executed (including all po-earlier
812 stores executed on C) is forced to propagate to C' before the
813 store associated with the release fence does.
814
815 Any store which propagates to C before a strong fence is
816 executed (including all po-earlier stores on C) is forced to
817 propagate to all other CPUs before any instructions po-after
818 the strong fence are executed on C.
819
820The propagation ordering enforced by release fences and strong fences
821affects stores from other CPUs that propagate to CPU C before the
822fence is executed, as well as stores that are executed on C before the
823fence. We describe this property by saying that release fences and
824strong fences are A-cumulative. By contrast, smp_wmb() fences are not
825A-cumulative; they only affect the propagation of stores that are
826executed on C before the fence (i.e., those which precede the fence in
827program order).
828
829rcu_read_lock(), rcu_read_unlock(), and synchronize_rcu() fences have
830other properties which we discuss later.
831
832
833PROPAGATION ORDER RELATION: cumul-fence
834---------------------------------------
835
836The fences which affect propagation order (i.e., strong, release, and
837smp_wmb() fences) are collectively referred to as cumul-fences, even
838though smp_wmb() isn't A-cumulative. The cumul-fence relation is
839defined to link memory access events E and F whenever:
840
841 E and F are both stores on the same CPU and an smp_wmb() fence
842 event occurs between them in program order; or
843
844 F is a release fence and some X comes before F in program order,
845 where either X = E or else E ->rf X; or
846
847 A strong fence event occurs between some X and F in program
848 order, where either X = E or else E ->rf X.
849
850The operational model requires that whenever W and W' are both stores
851and W ->cumul-fence W', then W must propagate to any given CPU
852before W' does. However, for different CPUs C and C', it does not
853require W to propagate to C before W' propagates to C'.
854
855
856DERIVATION OF THE LKMM FROM THE OPERATIONAL MODEL
857-------------------------------------------------
858
859The LKMM is derived from the restrictions imposed by the design
860outlined above. These restrictions involve the necessity of
861maintaining cache coherence and the fact that a CPU can't operate on a
862value before it knows what that value is, among other things.
863
864The formal version of the LKMM is defined by five requirements, or
865axioms:
866
867 Sequential consistency per variable: This requires that the
868 system obey the four coherency rules.
869
870 Atomicity: This requires that atomic read-modify-write
871 operations really are atomic, that is, no other stores can
872 sneak into the middle of such an update.
873
874 Happens-before: This requires that certain instructions are
875 executed in a specific order.
876
877 Propagation: This requires that certain stores propagate to
878 CPUs and to RAM in a specific order.
879
880 Rcu: This requires that RCU read-side critical sections and
881 grace periods obey the rules of RCU, in particular, the
882 Grace-Period Guarantee.
883
884The first and second are quite common; they can be found in many
885memory models (such as those for C11/C++11). The "happens-before" and
886"propagation" axioms have analogs in other memory models as well. The
887"rcu" axiom is specific to the LKMM.
888
889Each of these axioms is discussed below.
890
891
892SEQUENTIAL CONSISTENCY PER VARIABLE
893-----------------------------------
894
895According to the principle of cache coherence, the stores to any fixed
896shared location in memory form a global ordering. We can imagine
897inserting the loads from that location into this ordering, by placing
898each load between the store that it reads from and the following
899store. This leaves the relative positions of loads that read from the
900same store unspecified; let's say they are inserted in program order,
901first for CPU 0, then CPU 1, etc.
902
903You can check that the four coherency rules imply that the rf, co, fr,
904and po-loc relations agree with this global ordering; in other words,
905whenever we have X ->rf Y or X ->co Y or X ->fr Y or X ->po-loc Y, the
906X event comes before the Y event in the global ordering. The LKMM's
907"coherence" axiom expresses this by requiring the union of these
908relations not to have any cycles. This means it must not be possible
909to find events
910
911 X0 -> X1 -> X2 -> ... -> Xn -> X0,
912
913where each of the links is either rf, co, fr, or po-loc. This has to
914hold if the accesses to the fixed memory location can be ordered as
915cache coherence demands.
916
917Although it is not obvious, it can be shown that the converse is also
918true: This LKMM axiom implies that the four coherency rules are
919obeyed.
920
921
922ATOMIC UPDATES: rmw
923-------------------
924
925What does it mean to say that a read-modify-write (rmw) update, such
926as atomic_inc(&x), is atomic? It means that the memory location (x in
927this case) does not get altered between the read and the write events
928making up the atomic operation. In particular, if two CPUs perform
929atomic_inc(&x) concurrently, it must be guaranteed that the final
930value of x will be the initial value plus two. We should never have
931the following sequence of events:
932
933 CPU 0 loads x obtaining 13;
934 CPU 1 loads x obtaining 13;
935 CPU 0 stores 14 to x;
936 CPU 1 stores 14 to x;
937
938where the final value of x is wrong (14 rather than 15).
939
940In this example, CPU 0's increment effectively gets lost because it
941occurs in between CPU 1's load and store. To put it another way, the
942problem is that the position of CPU 0's store in x's coherence order
943is between the store that CPU 1 reads from and the store that CPU 1
944performs.
945
946The same analysis applies to all atomic update operations. Therefore,
947to enforce atomicity the LKMM requires that atomic updates follow this
948rule: Whenever R and W are the read and write events composing an
949atomic read-modify-write and W' is the write event which R reads from,
950there must not be any stores coming between W' and W in the coherence
951order. Equivalently,
952
953 (R ->rmw W) implies (there is no X with R ->fr X and X ->co W),
954
955where the rmw relation links the read and write events making up each
956atomic update. This is what the LKMM's "atomic" axiom says.
957
958
959THE PRESERVED PROGRAM ORDER RELATION: ppo
960-----------------------------------------
961
962There are many situations where a CPU is obligated to execute two
963instructions in program order. We amalgamate them into the ppo (for
964"preserved program order") relation, which links the po-earlier
965instruction to the po-later instruction and is thus a sub-relation of
966po.
967
968The operational model already includes a description of one such
969situation: Fences are a source of ppo links. Suppose X and Y are
970memory accesses with X ->po Y; then the CPU must execute X before Y if
971any of the following hold:
972
973 A strong (smp_mb() or synchronize_rcu()) fence occurs between
974 X and Y;
975
976 X and Y are both stores and an smp_wmb() fence occurs between
977 them;
978
979 X and Y are both loads and an smp_rmb() fence occurs between
980 them;
981
982 X is also an acquire fence, such as smp_load_acquire();
983
984 Y is also a release fence, such as smp_store_release().
985
986Another possibility, not mentioned earlier but discussed in the next
987section, is:
988
989 X and Y are both loads, X ->addr Y (i.e., there is an address
990 dependency from X to Y), and X is a READ_ONCE() or an atomic
991 access.
992
993Dependencies can also cause instructions to be executed in program
994order. This is uncontroversial when the second instruction is a
995store; either a data, address, or control dependency from a load R to
996a store W will force the CPU to execute R before W. This is very
997simply because the CPU cannot tell the memory subsystem about W's
998store before it knows what value should be stored (in the case of a
999data dependency), what location it should be stored into (in the case
1000of an address dependency), or whether the store should actually take
1001place (in the case of a control dependency).
1002
1003Dependencies to load instructions are more problematic. To begin with,
1004there is no such thing as a data dependency to a load. Next, a CPU
1005has no reason to respect a control dependency to a load, because it
1006can always satisfy the second load speculatively before the first, and
1007then ignore the result if it turns out that the second load shouldn't
1008be executed after all. And lastly, the real difficulties begin when
1009we consider address dependencies to loads.
1010
1011To be fair about it, all Linux-supported architectures do execute
1012loads in program order if there is an address dependency between them.
1013After all, a CPU cannot ask the memory subsystem to load a value from
1014a particular location before it knows what that location is. However,
1015the split-cache design used by Alpha can cause it to behave in a way
1016that looks as if the loads were executed out of order (see the next
1017section for more details). The kernel includes a workaround for this
1018problem when the loads come from READ_ONCE(), and therefore the LKMM
1019includes address dependencies to loads in the ppo relation.
1020
1021On the other hand, dependencies can indirectly affect the ordering of
1022two loads. This happens when there is a dependency from a load to a
1023store and a second, po-later load reads from that store:
1024
1025 R ->dep W ->rfi R',
1026
1027where the dep link can be either an address or a data dependency. In
1028this situation we know it is possible for the CPU to execute R' before
1029W, because it can forward the value that W will store to R'. But it
1030cannot execute R' before R, because it cannot forward the value before
1031it knows what that value is, or that W and R' do access the same
1032location. However, if there is merely a control dependency between R
1033and W then the CPU can speculatively forward W to R' before executing
1034R; if the speculation turns out to be wrong then the CPU merely has to
1035restart or abandon R'.
1036
1037(In theory, a CPU might forward a store to a load when it runs across
1038an address dependency like this:
1039
1040 r1 = READ_ONCE(ptr);
1041 WRITE_ONCE(*r1, 17);
1042 r2 = READ_ONCE(*r1);
1043
1044because it could tell that the store and the second load access the
1045same location even before it knows what the location's address is.
1046However, none of the architectures supported by the Linux kernel do
1047this.)
1048
1049Two memory accesses of the same location must always be executed in
1050program order if the second access is a store. Thus, if we have
1051
1052 R ->po-loc W
1053
1054(the po-loc link says that R comes before W in program order and they
1055access the same location), the CPU is obliged to execute W after R.
1056If it executed W first then the memory subsystem would respond to R's
1057read request with the value stored by W (or an even later store), in
1058violation of the read-write coherence rule. Similarly, if we had
1059
1060 W ->po-loc W'
1061
1062and the CPU executed W' before W, then the memory subsystem would put
1063W' before W in the coherence order. It would effectively cause W to
1064overwrite W', in violation of the write-write coherence rule.
1065(Interestingly, an early ARMv8 memory model, now obsolete, proposed
1066allowing out-of-order writes like this to occur. The model avoided
1067violating the write-write coherence rule by requiring the CPU not to
1068send the W write to the memory subsystem at all!)
1069
1070There is one last example of preserved program order in the LKMM: when
1071a load-acquire reads from an earlier store-release. For example:
1072
1073 smp_store_release(&x, 123);
1074 r1 = smp_load_acquire(&x);
1075
1076If the smp_load_acquire() ends up obtaining the 123 value that was
1077stored by the smp_store_release(), the LKMM says that the load must be
1078executed after the store; the store cannot be forwarded to the load.
1079This requirement does not arise from the operational model, but it
1080yields correct predictions on all architectures supported by the Linux
1081kernel, although for differing reasons.
1082
1083On some architectures, including x86 and ARMv8, it is true that the
1084store cannot be forwarded to the load. On others, including PowerPC
1085and ARMv7, smp_store_release() generates object code that starts with
1086a fence and smp_load_acquire() generates object code that ends with a
1087fence. The upshot is that even though the store may be forwarded to
1088the load, it is still true that any instruction preceding the store
1089will be executed before the load or any following instructions, and
1090the store will be executed before any instruction following the load.
1091
1092
1093AND THEN THERE WAS ALPHA
1094------------------------
1095
1096As mentioned above, the Alpha architecture is unique in that it does
1097not appear to respect address dependencies to loads. This means that
1098code such as the following:
1099
1100 int x = 0;
1101 int y = -1;
1102 int *ptr = &y;
1103
1104 P0()
1105 {
1106 WRITE_ONCE(x, 1);
1107 smp_wmb();
1108 WRITE_ONCE(ptr, &x);
1109 }
1110
1111 P1()
1112 {
1113 int *r1;
1114 int r2;
1115
1116 r1 = ptr;
1117 r2 = READ_ONCE(*r1);
1118 }
1119
1120can malfunction on Alpha systems (notice that P1 uses an ordinary load
1121to read ptr instead of READ_ONCE()). It is quite possible that r1 = &x
1122and r2 = 0 at the end, in spite of the address dependency.
1123
1124At first glance this doesn't seem to make sense. We know that the
1125smp_wmb() forces P0's store to x to propagate to P1 before the store
1126to ptr does. And since P1 can't execute its second load
1127until it knows what location to load from, i.e., after executing its
1128first load, the value x = 1 must have propagated to P1 before the
1129second load executed. So why doesn't r2 end up equal to 1?
1130
1131The answer lies in the Alpha's split local caches. Although the two
1132stores do reach P1's local cache in the proper order, it can happen
1133that the first store is processed by a busy part of the cache while
1134the second store is processed by an idle part. As a result, the x = 1
1135value may not become available for P1's CPU to read until after the
1136ptr = &x value does, leading to the undesirable result above. The
1137final effect is that even though the two loads really are executed in
1138program order, it appears that they aren't.
1139
1140This could not have happened if the local cache had processed the
1141incoming stores in FIFO order. By contrast, other architectures
1142maintain at least the appearance of FIFO order.
1143
1144In practice, this difficulty is solved by inserting a special fence
1145between P1's two loads when the kernel is compiled for the Alpha
1146architecture. In fact, as of version 4.15, the kernel automatically
1147adds this fence (called smp_read_barrier_depends() and defined as
1148nothing at all on non-Alpha builds) after every READ_ONCE() and atomic
1149load. The effect of the fence is to cause the CPU not to execute any
1150po-later instructions until after the local cache has finished
1151processing all the stores it has already received. Thus, if the code
1152was changed to:
1153
1154 P1()
1155 {
1156 int *r1;
1157 int r2;
1158
1159 r1 = READ_ONCE(ptr);
1160 r2 = READ_ONCE(*r1);
1161 }
1162
1163then we would never get r1 = &x and r2 = 0. By the time P1 executed
1164its second load, the x = 1 store would already be fully processed by
1165the local cache and available for satisfying the read request. Thus
1166we have yet another reason why shared data should always be read with
1167READ_ONCE() or another synchronization primitive rather than accessed
1168directly.
1169
1170The LKMM requires that smp_rmb(), acquire fences, and strong fences
1171share this property with smp_read_barrier_depends(): They do not allow
1172the CPU to execute any po-later instructions (or po-later loads in the
1173case of smp_rmb()) until all outstanding stores have been processed by
1174the local cache. In the case of a strong fence, the CPU first has to
1175wait for all of its po-earlier stores to propagate to every other CPU
1176in the system; then it has to wait for the local cache to process all
1177the stores received as of that time -- not just the stores received
1178when the strong fence began.
1179
1180And of course, none of this matters for any architecture other than
1181Alpha.
1182
1183
1184THE HAPPENS-BEFORE RELATION: hb
1185-------------------------------
1186
1187The happens-before relation (hb) links memory accesses that have to
1188execute in a certain order. hb includes the ppo relation and two
1189others, one of which is rfe.
1190
1191W ->rfe R implies that W and R are on different CPUs. It also means
1192that W's store must have propagated to R's CPU before R executed;
1193otherwise R could not have read the value stored by W. Therefore W
1194must have executed before R, and so we have W ->hb R.
1195
1196The equivalent fact need not hold if W ->rfi R (i.e., W and R are on
1197the same CPU). As we have already seen, the operational model allows
1198W's value to be forwarded to R in such cases, meaning that R may well
1199execute before W does.
1200
1201It's important to understand that neither coe nor fre is included in
1202hb, despite their similarities to rfe. For example, suppose we have
1203W ->coe W'. This means that W and W' are stores to the same location,
1204they execute on different CPUs, and W comes before W' in the coherence
1205order (i.e., W' overwrites W). Nevertheless, it is possible for W' to
1206execute before W, because the decision as to which store overwrites
1207the other is made later by the memory subsystem. When the stores are
1208nearly simultaneous, either one can come out on top. Similarly,
1209R ->fre W means that W overwrites the value which R reads, but it
1210doesn't mean that W has to execute after R. All that's necessary is
1211for the memory subsystem not to propagate W to R's CPU until after R
1212has executed, which is possible if W executes shortly before R.
1213
1214The third relation included in hb is like ppo, in that it only links
1215events that are on the same CPU. However it is more difficult to
1216explain, because it arises only indirectly from the requirement of
1217cache coherence. The relation is called prop, and it links two events
1218on CPU C in situations where a store from some other CPU comes after
1219the first event in the coherence order and propagates to C before the
1220second event executes.
1221
1222This is best explained with some examples. The simplest case looks
1223like this:
1224
1225 int x;
1226
1227 P0()
1228 {
1229 int r1;
1230
1231 WRITE_ONCE(x, 1);
1232 r1 = READ_ONCE(x);
1233 }
1234
1235 P1()
1236 {
1237 WRITE_ONCE(x, 8);
1238 }
1239
1240If r1 = 8 at the end then P0's accesses must have executed in program
1241order. We can deduce this from the operational model; if P0's load
1242had executed before its store then the value of the store would have
1243been forwarded to the load, so r1 would have ended up equal to 1, not
12448. In this case there is a prop link from P0's write event to its read
1245event, because P1's store came after P0's store in x's coherence
1246order, and P1's store propagated to P0 before P0's load executed.
1247
1248An equally simple case involves two loads of the same location that
1249read from different stores:
1250
1251 int x = 0;
1252
1253 P0()
1254 {
1255 int r1, r2;
1256
1257 r1 = READ_ONCE(x);
1258 r2 = READ_ONCE(x);
1259 }
1260
1261 P1()
1262 {
1263 WRITE_ONCE(x, 9);
1264 }
1265
1266If r1 = 0 and r2 = 9 at the end then P0's accesses must have executed
1267in program order. If the second load had executed before the first
1268then the x = 9 store must have been propagated to P0 before the first
1269load executed, and so r1 would have been 9 rather than 0. In this
1270case there is a prop link from P0's first read event to its second,
1271because P1's store overwrote the value read by P0's first load, and
1272P1's store propagated to P0 before P0's second load executed.
1273
1274Less trivial examples of prop all involve fences. Unlike the simple
1275examples above, they can require that some instructions are executed
1276out of program order. This next one should look familiar:
1277
1278 int buf = 0, flag = 0;
1279
1280 P0()
1281 {
1282 WRITE_ONCE(buf, 1);
1283 smp_wmb();
1284 WRITE_ONCE(flag, 1);
1285 }
1286
1287 P1()
1288 {
1289 int r1;
1290 int r2;
1291
1292 r1 = READ_ONCE(flag);
1293 r2 = READ_ONCE(buf);
1294 }
1295
1296This is the MP pattern again, with an smp_wmb() fence between the two
1297stores. If r1 = 1 and r2 = 0 at the end then there is a prop link
1298from P1's second load to its first (backwards!). The reason is
1299similar to the previous examples: The value P1 loads from buf gets
1300overwritten by P0's store to buf, the fence guarantees that the store
1301to buf will propagate to P1 before the store to flag does, and the
1302store to flag propagates to P1 before P1 reads flag.
1303
1304The prop link says that in order to obtain the r1 = 1, r2 = 0 result,
1305P1 must execute its second load before the first. Indeed, if the load
1306from flag were executed first, then the buf = 1 store would already
1307have propagated to P1 by the time P1's load from buf executed, so r2
1308would have been 1 at the end, not 0. (The reasoning holds even for
1309Alpha, although the details are more complicated and we will not go
1310into them.)
1311
1312But what if we put an smp_rmb() fence between P1's loads? The fence
1313would force the two loads to be executed in program order, and it
1314would generate a cycle in the hb relation: The fence would create a ppo
1315link (hence an hb link) from the first load to the second, and the
1316prop relation would give an hb link from the second load to the first.
1317Since an instruction can't execute before itself, we are forced to
1318conclude that if an smp_rmb() fence is added, the r1 = 1, r2 = 0
1319outcome is impossible -- as it should be.
1320
1321The formal definition of the prop relation involves a coe or fre link,
1322followed by an arbitrary number of cumul-fence links, ending with an
1323rfe link. You can concoct more exotic examples, containing more than
1324one fence, although this quickly leads to diminishing returns in terms
1325of complexity. For instance, here's an example containing a coe link
1326followed by two fences and an rfe link, utilizing the fact that
1327release fences are A-cumulative:
1328
1329 int x, y, z;
1330
1331 P0()
1332 {
1333 int r0;
1334
1335 WRITE_ONCE(x, 1);
1336 r0 = READ_ONCE(z);
1337 }
1338
1339 P1()
1340 {
1341 WRITE_ONCE(x, 2);
1342 smp_wmb();
1343 WRITE_ONCE(y, 1);
1344 }
1345
1346 P2()
1347 {
1348 int r2;
1349
1350 r2 = READ_ONCE(y);
1351 smp_store_release(&z, 1);
1352 }
1353
1354If x = 2, r0 = 1, and r2 = 1 after this code runs then there is a prop
1355link from P0's store to its load. This is because P0's store gets
1356overwritten by P1's store since x = 2 at the end (a coe link), the
1357smp_wmb() ensures that P1's store to x propagates to P2 before the
1358store to y does (the first fence), the store to y propagates to P2
1359before P2's load and store execute, P2's smp_store_release()
1360guarantees that the stores to x and y both propagate to P0 before the
1361store to z does (the second fence), and P0's load executes after the
1362store to z has propagated to P0 (an rfe link).
1363
1364In summary, the fact that the hb relation links memory access events
1365in the order they execute means that it must not have cycles. This
1366requirement is the content of the LKMM's "happens-before" axiom.
1367
1368The LKMM defines yet another relation connected to times of
1369instruction execution, but it is not included in hb. It relies on the
1370particular properties of strong fences, which we cover in the next
1371section.
1372
1373
1374THE PROPAGATES-BEFORE RELATION: pb
1375----------------------------------
1376
1377The propagates-before (pb) relation capitalizes on the special
1378features of strong fences. It links two events E and F whenever some
1379store is coherence-later than E and propagates to every CPU and to RAM
1380before F executes. The formal definition requires that E be linked to
1381F via a coe or fre link, an arbitrary number of cumul-fences, an
1382optional rfe link, a strong fence, and an arbitrary number of hb
1383links. Let's see how this definition works out.
1384
1385Consider first the case where E is a store (implying that the sequence
1386of links begins with coe). Then there are events W, X, Y, and Z such
1387that:
1388
1389 E ->coe W ->cumul-fence* X ->rfe? Y ->strong-fence Z ->hb* F,
1390
1391where the * suffix indicates an arbitrary number of links of the
1392specified type, and the ? suffix indicates the link is optional (Y may
1393be equal to X). Because of the cumul-fence links, we know that W will
1394propagate to Y's CPU before X does, hence before Y executes and hence
1395before the strong fence executes. Because this fence is strong, we
1396know that W will propagate to every CPU and to RAM before Z executes.
1397And because of the hb links, we know that Z will execute before F.
1398Thus W, which comes later than E in the coherence order, will
1399propagate to every CPU and to RAM before F executes.
1400
1401The case where E is a load is exactly the same, except that the first
1402link in the sequence is fre instead of coe.
1403
1404The existence of a pb link from E to F implies that E must execute
1405before F. To see why, suppose that F executed first. Then W would
1406have propagated to E's CPU before E executed. If E was a store, the
1407memory subsystem would then be forced to make E come after W in the
1408coherence order, contradicting the fact that E ->coe W. If E was a
1409load, the memory subsystem would then be forced to satisfy E's read
1410request with the value stored by W or an even later store,
1411contradicting the fact that E ->fre W.
1412
1413A good example illustrating how pb works is the SB pattern with strong
1414fences:
1415
1416 int x = 0, y = 0;
1417
1418 P0()
1419 {
1420 int r0;
1421
1422 WRITE_ONCE(x, 1);
1423 smp_mb();
1424 r0 = READ_ONCE(y);
1425 }
1426
1427 P1()
1428 {
1429 int r1;
1430
1431 WRITE_ONCE(y, 1);
1432 smp_mb();
1433 r1 = READ_ONCE(x);
1434 }
1435
1436If r0 = 0 at the end then there is a pb link from P0's load to P1's
1437load: an fre link from P0's load to P1's store (which overwrites the
1438value read by P0), and a strong fence between P1's store and its load.
1439In this example, the sequences of cumul-fence and hb links are empty.
1440Note that this pb link is not included in hb as an instance of prop,
1441because it does not start and end on the same CPU.
1442
1443Similarly, if r1 = 0 at the end then there is a pb link from P1's load
1444to P0's. This means that if both r1 and r2 were 0 there would be a
1445cycle in pb, which is not possible since an instruction cannot execute
1446before itself. Thus, adding smp_mb() fences to the SB pattern
1447prevents the r0 = 0, r1 = 0 outcome.
1448
1449In summary, the fact that the pb relation links events in the order
1450they execute means that it cannot have cycles. This requirement is
1451the content of the LKMM's "propagation" axiom.
1452
1453
1454RCU RELATIONS: link, gp-link, rscs-link, and rcu-path
1455-----------------------------------------------------
1456
1457RCU (Read-Copy-Update) is a powerful synchronization mechanism. It
1458rests on two concepts: grace periods and read-side critical sections.
1459
1460A grace period is the span of time occupied by a call to
1461synchronize_rcu(). A read-side critical section (or just critical
1462section, for short) is a region of code delimited by rcu_read_lock()
1463at the start and rcu_read_unlock() at the end. Critical sections can
1464be nested, although we won't make use of this fact.
1465
1466As far as memory models are concerned, RCU's main feature is its
1467Grace-Period Guarantee, which states that a critical section can never
1468span a full grace period. In more detail, the Guarantee says:
1469
1470 If a critical section starts before a grace period then it
1471 must end before the grace period does. In addition, every
1472 store that propagates to the critical section's CPU before the
1473 end of the critical section must propagate to every CPU before
1474 the end of the grace period.
1475
1476 If a critical section ends after a grace period ends then it
1477 must start after the grace period does. In addition, every
1478 store that propagates to the grace period's CPU before the
1479 start of the grace period must propagate to every CPU before
1480 the start of the critical section.
1481
1482Here is a simple example of RCU in action:
1483
1484 int x, y;
1485
1486 P0()
1487 {
1488 rcu_read_lock();
1489 WRITE_ONCE(x, 1);
1490 WRITE_ONCE(y, 1);
1491 rcu_read_unlock();
1492 }
1493
1494 P1()
1495 {
1496 int r1, r2;
1497
1498 r1 = READ_ONCE(x);
1499 synchronize_rcu();
1500 r2 = READ_ONCE(y);
1501 }
1502
1503The Grace Period Guarantee tells us that when this code runs, it will
1504never end with r1 = 1 and r2 = 0. The reasoning is as follows. r1 = 1
1505means that P0's store to x propagated to P1 before P1 called
1506synchronize_rcu(), so P0's critical section must have started before
1507P1's grace period. On the other hand, r2 = 0 means that P0's store to
1508y, which occurs before the end of the critical section, did not
1509propagate to P1 before the end of the grace period, violating the
1510Guarantee.
1511
1512In the kernel's implementations of RCU, the business about stores
1513propagating to every CPU is realized by placing strong fences at
1514suitable places in the RCU-related code. Thus, if a critical section
1515starts before a grace period does then the critical section's CPU will
1516execute an smp_mb() fence after the end of the critical section and
1517some time before the grace period's synchronize_rcu() call returns.
1518And if a critical section ends after a grace period does then the
1519synchronize_rcu() routine will execute an smp_mb() fence at its start
1520and some time before the critical section's opening rcu_read_lock()
1521executes.
1522
1523What exactly do we mean by saying that a critical section "starts
1524before" or "ends after" a grace period? Some aspects of the meaning
1525are pretty obvious, as in the example above, but the details aren't
1526entirely clear. The LKMM formalizes this notion by means of a
1527relation with the unfortunately generic name "link". It is a very
1528general relation; among other things, X ->link Z includes cases where
1529X happens-before or is equal to some event Y which is equal to or
1530comes before Z in the coherence order. Taking Y = Z, this says that
1531X ->rfe Z implies X ->link Z, and taking Y = X, it says that X ->fr Z
1532and X ->co Z each imply X ->link Z.
1533
1534The formal definition of the link relation is more than a little
1535obscure, and we won't give it here. It is closely related to the pb
1536relation, and the details don't matter unless you want to comb through
1537a somewhat lengthy formal proof. Pretty much all you need to know
1538about link is the information in the preceding paragraph.
1539
1540The LKMM goes on to define the gp-link and rscs-link relations. They
1541bring grace periods and read-side critical sections into the picture,
1542in the following way:
1543
1544 E ->gp-link F means there is a synchronize_rcu() fence event S
1545 and an event X such that E ->po S, either S ->po X or S = X,
1546 and X ->link F. In other words, E and F are connected by a
1547 grace period followed by an instance of link.
1548
1549 E ->rscs-link F means there is a critical section delimited by
1550 an rcu_read_lock() fence L and an rcu_read_unlock() fence U,
1551 and an event X such that E ->po U, either L ->po X or L = X,
1552 and X ->link F. Roughly speaking, this says that some event
1553 in the same critical section as E is connected by link to F.
1554
1555If we think of the link relation as standing for an extended "before",
1556then E ->gp-link F says that E executes before a grace period which
1557ends before F executes. (In fact it says more than this, because it
1558includes cases where E executes before a grace period and some store
1559propagates to F's CPU before F executes and doesn't propagate to some
1560other CPU until after the grace period ends.) Similarly,
1561E ->rscs-link F says that E is part of (or before the start of) a
1562critical section which starts before F executes.
1563
1564Putting this all together, the LKMM expresses the Grace Period
1565Guarantee by requiring that there are no cycles consisting of gp-link
1566and rscs-link connections in which the number of gp-link instances is
1567>= the number of rscs-link instances. It does this by defining the
1568rcu-path relation to link events E and F whenever it is possible to
1569pass from E to F by a sequence of gp-link and rscs-link connections
1570with at least as many of the former as the latter. The LKMM's "rcu"
1571axiom then says that there are no events E such that E ->rcu-path E.
1572
1573Justifying this axiom takes some intellectual effort, but it is in
1574fact a valid formalization of the Grace Period Guarantee. We won't
1575attempt to go through the detailed argument, but the following
1576analysis gives a taste of what is involved. Suppose we have a
1577violation of the first part of the Guarantee: A critical section
1578starts before a grace period, and some store propagates to the
1579critical section's CPU before the end of the critical section but
1580doesn't propagate to some other CPU until after the end of the grace
1581period.
1582
1583Putting symbols to these ideas, let L and U be the rcu_read_lock() and
1584rcu_read_unlock() fence events delimiting the critical section in
1585question, and let S be the synchronize_rcu() fence event for the grace
1586period. Saying that the critical section starts before S means there
1587are events E and F where E is po-after L (which marks the start of the
1588critical section), E is "before" F in the sense of the link relation,
1589and F is po-before the grace period S:
1590
1591 L ->po E ->link F ->po S.
1592
1593Let W be the store mentioned above, let Z come before the end of the
1594critical section and witness that W propagates to the critical
1595section's CPU by reading from W, and let Y on some arbitrary CPU be a
1596witness that W has not propagated to that CPU, where Y happens after
1597some event X which is po-after S. Symbolically, this amounts to:
1598
1599 S ->po X ->hb* Y ->fr W ->rf Z ->po U.
1600
1601The fr link from Y to W indicates that W has not propagated to Y's CPU
1602at the time that Y executes. From this, it can be shown (see the
1603discussion of the link relation earlier) that X and Z are connected by
1604link, yielding:
1605
1606 S ->po X ->link Z ->po U.
1607
1608These formulas say that S is po-between F and X, hence F ->gp-link Z
1609via X. They also say that Z comes before the end of the critical
1610section and E comes after its start, hence Z ->rscs-link F via E. But
1611now we have a forbidden cycle: F ->gp-link Z ->rscs-link F. Thus the
1612"rcu" axiom rules out this violation of the Grace Period Guarantee.
1613
1614For something a little more down-to-earth, let's see how the axiom
1615works out in practice. Consider the RCU code example from above, this
1616time with statement labels added to the memory access instructions:
1617
1618 int x, y;
1619
1620 P0()
1621 {
1622 rcu_read_lock();
1623 W: WRITE_ONCE(x, 1);
1624 X: WRITE_ONCE(y, 1);
1625 rcu_read_unlock();
1626 }
1627
1628 P1()
1629 {
1630 int r1, r2;
1631
1632 Y: r1 = READ_ONCE(x);
1633 synchronize_rcu();
1634 Z: r2 = READ_ONCE(y);
1635 }
1636
1637
1638If r2 = 0 at the end then P0's store at X overwrites the value
1639that P1's load at Z reads from, so we have Z ->fre X and thus
1640Z ->link X. In addition, there is a synchronize_rcu() between Y and
1641Z, so therefore we have Y ->gp-link X.
1642
1643If r1 = 1 at the end then P1's load at Y reads from P0's store at W,
1644so we have W ->link Y. In addition, W and X are in the same critical
1645section, so therefore we have X ->rscs-link Y.
1646
1647This gives us a cycle, Y ->gp-link X ->rscs-link Y, with one gp-link
1648and one rscs-link, violating the "rcu" axiom. Hence the outcome is
1649not allowed by the LKMM, as we would expect.
1650
1651For contrast, let's see what can happen in a more complicated example:
1652
1653 int x, y, z;
1654
1655 P0()
1656 {
1657 int r0;
1658
1659 rcu_read_lock();
1660 W: r0 = READ_ONCE(x);
1661 X: WRITE_ONCE(y, 1);
1662 rcu_read_unlock();
1663 }
1664
1665 P1()
1666 {
1667 int r1;
1668
1669 Y: r1 = READ_ONCE(y);
1670 synchronize_rcu();
1671 Z: WRITE_ONCE(z, 1);
1672 }
1673
1674 P2()
1675 {
1676 int r2;
1677
1678 rcu_read_lock();
1679 U: r2 = READ_ONCE(z);
1680 V: WRITE_ONCE(x, 1);
1681 rcu_read_unlock();
1682 }
1683
1684If r0 = r1 = r2 = 1 at the end, then similar reasoning to before shows
1685that W ->rscs-link Y via X, Y ->gp-link U via Z, and U ->rscs-link W
1686via V. And just as before, this gives a cycle:
1687
1688 W ->rscs-link Y ->gp-link U ->rscs-link W.
1689
1690However, this cycle has fewer gp-link instances than rscs-link
1691instances, and consequently the outcome is not forbidden by the LKMM.
1692The following instruction timing diagram shows how it might actually
1693occur:
1694
1695P0 P1 P2
1696-------------------- -------------------- --------------------
1697rcu_read_lock()
1698X: WRITE_ONCE(y, 1)
1699 Y: r1 = READ_ONCE(y)
1700 synchronize_rcu() starts
1701 . rcu_read_lock()
1702 . V: WRITE_ONCE(x, 1)
1703W: r0 = READ_ONCE(x) .
1704rcu_read_unlock() .
1705 synchronize_rcu() ends
1706 Z: WRITE_ONCE(z, 1)
1707 U: r2 = READ_ONCE(z)
1708 rcu_read_unlock()
1709
1710This requires P0 and P2 to execute their loads and stores out of
1711program order, but of course they are allowed to do so. And as you
1712can see, the Grace Period Guarantee is not violated: The critical
1713section in P0 both starts before P1's grace period does and ends
1714before it does, and the critical section in P2 both starts after P1's
1715grace period does and ends after it does.
1716
1717
1718ODDS AND ENDS
1719-------------
1720
1721This section covers material that didn't quite fit anywhere in the
1722earlier sections.
1723
1724The descriptions in this document don't always match the formal
1725version of the LKMM exactly. For example, the actual formal
1726definition of the prop relation makes the initial coe or fre part
1727optional, and it doesn't require the events linked by the relation to
1728be on the same CPU. These differences are very unimportant; indeed,
1729instances where the coe/fre part of prop is missing are of no interest
1730because all the other parts (fences and rfe) are already included in
1731hb anyway, and where the formal model adds prop into hb, it includes
1732an explicit requirement that the events being linked are on the same
1733CPU.
1734
1735Another minor difference has to do with events that are both memory
1736accesses and fences, such as those corresponding to smp_load_acquire()
1737calls. In the formal model, these events aren't actually both reads
1738and fences; rather, they are read events with an annotation marking
1739them as acquires. (Or write events annotated as releases, in the case
1740smp_store_release().) The final effect is the same.
1741
1742Although we didn't mention it above, the instruction execution
1743ordering provided by the smp_rmb() fence doesn't apply to read events
1744that are part of a non-value-returning atomic update. For instance,
1745given:
1746
1747 atomic_inc(&x);
1748 smp_rmb();
1749 r1 = READ_ONCE(y);
1750
1751it is not guaranteed that the load from y will execute after the
1752update to x. This is because the ARMv8 architecture allows
1753non-value-returning atomic operations effectively to be executed off
1754the CPU. Basically, the CPU tells the memory subsystem to increment
1755x, and then the increment is carried out by the memory hardware with
1756no further involvement from the CPU. Since the CPU doesn't ever read
1757the value of x, there is nothing for the smp_rmb() fence to act on.
1758
1759The LKMM defines a few extra synchronization operations in terms of
1760things we have already covered. In particular, rcu_dereference() is
1761treated as READ_ONCE() and rcu_assign_pointer() is treated as
1762smp_store_release() -- which is basically how the Linux kernel treats
1763them.
1764
1765There are a few oddball fences which need special treatment:
1766smp_mb__before_atomic(), smp_mb__after_atomic(), and
1767smp_mb__after_spinlock(). The LKMM uses fence events with special
1768annotations for them; they act as strong fences just like smp_mb()
1769except for the sets of events that they order. Instead of ordering
1770all po-earlier events against all po-later events, as smp_mb() does,
1771they behave as follows:
1772
1773 smp_mb__before_atomic() orders all po-earlier events against
1774 po-later atomic updates and the events following them;
1775
1776 smp_mb__after_atomic() orders po-earlier atomic updates and
1777 the events preceding them against all po-later events;
1778
1779 smp_mb_after_spinlock() orders po-earlier lock acquisition
1780 events and the events preceding them against all po-later
1781 events.
1782
1783The LKMM includes locking. In fact, there is special code for locking
1784in the formal model, added in order to make tools run faster.
1785However, this special code is intended to be exactly equivalent to
1786concepts we have already covered. A spinlock_t variable is treated
1787the same as an int, and spin_lock(&s) is treated the same as:
1788
1789 while (cmpxchg_acquire(&s, 0, 1) != 0)
1790 cpu_relax();
1791
1792which waits until s is equal to 0 and then atomically sets it to 1,
1793and where the read part of the atomic update is also an acquire fence.
1794An alternate way to express the same thing would be:
1795
1796 r = xchg_acquire(&s, 1);
1797
1798along with a requirement that at the end, r = 0. spin_unlock(&s) is
1799treated the same as:
1800
1801 smp_store_release(&s, 0);
1802
1803Interestingly, RCU and locking each introduce the possibility of
1804deadlock. When faced with code sequences such as:
1805
1806 spin_lock(&s);
1807 spin_lock(&s);
1808 spin_unlock(&s);
1809 spin_unlock(&s);
1810
1811or:
1812
1813 rcu_read_lock();
1814 synchronize_rcu();
1815 rcu_read_unlock();
1816
1817what does the LKMM have to say? Answer: It says there are no allowed
1818executions at all, which makes sense. But this can also lead to
1819misleading results, because if a piece of code has multiple possible
1820executions, some of which deadlock, the model will report only on the
1821non-deadlocking executions. For example:
1822
1823 int x, y;
1824
1825 P0()
1826 {
1827 int r0;
1828
1829 WRITE_ONCE(x, 1);
1830 r0 = READ_ONCE(y);
1831 }
1832
1833 P1()
1834 {
1835 rcu_read_lock();
1836 if (READ_ONCE(x) > 0) {
1837 WRITE_ONCE(y, 36);
1838 synchronize_rcu();
1839 }
1840 rcu_read_unlock();
1841 }
1842
1843Is it possible to end up with r0 = 36 at the end? The LKMM will tell
1844you it is not, but the model won't mention that this is because P1
1845will self-deadlock in the executions where it stores 36 in y.
diff --git a/tools/memory-model/Documentation/recipes.txt b/tools/memory-model/Documentation/recipes.txt
new file mode 100644
index 000000000000..ee4309a87fc4
--- /dev/null
+++ b/tools/memory-model/Documentation/recipes.txt
@@ -0,0 +1,570 @@
1This document provides "recipes", that is, litmus tests for commonly
2occurring situations, as well as a few that illustrate subtly broken but
3attractive nuisances. Many of these recipes include example code from
4v4.13 of the Linux kernel.
5
6The first section covers simple special cases, the second section
7takes off the training wheels to cover more involved examples,
8and the third section provides a few rules of thumb.
9
10
11Simple special cases
12====================
13
14This section presents two simple special cases, the first being where
15there is only one CPU or only one memory location is accessed, and the
16second being use of that old concurrency workhorse, locking.
17
18
19Single CPU or single memory location
20------------------------------------
21
22If there is only one CPU on the one hand or only one variable
23on the other, the code will execute in order. There are (as
24usual) some things to be careful of:
25
261. Some aspects of the C language are unordered. For example,
27 in the expression "f(x) + g(y)", the order in which f and g are
28 called is not defined; the object code is allowed to use either
29 order or even to interleave the computations.
30
312. Compilers are permitted to use the "as-if" rule. That is, a
32 compiler can emit whatever code it likes for normal accesses,
33 as long as the results of a single-threaded execution appear
34 just as if the compiler had followed all the relevant rules.
35 To see this, compile with a high level of optimization and run
36 the debugger on the resulting binary.
37
383. If there is only one variable but multiple CPUs, that variable
39 must be properly aligned and all accesses to that variable must
40 be full sized. Variables that straddle cachelines or pages void
41 your full-ordering warranty, as do undersized accesses that load
42 from or store to only part of the variable.
43
444. If there are multiple CPUs, accesses to shared variables should
45 use READ_ONCE() and WRITE_ONCE() or stronger to prevent load/store
46 tearing, load/store fusing, and invented loads and stores.
47 There are exceptions to this rule, including:
48
49 i. When there is no possibility of a given shared variable
50 being updated by some other CPU, for example, while
51 holding the update-side lock, reads from that variable
52 need not use READ_ONCE().
53
54 ii. When there is no possibility of a given shared variable
55 being either read or updated by other CPUs, for example,
56 when running during early boot, reads from that variable
57 need not use READ_ONCE() and writes to that variable
58 need not use WRITE_ONCE().
59
60
61Locking
62-------
63
64Locking is well-known and straightforward, at least if you don't think
65about it too hard. And the basic rule is indeed quite simple: Any CPU that
66has acquired a given lock sees any changes previously seen or made by any
67CPU before it released that same lock. Note that this statement is a bit
68stronger than "Any CPU holding a given lock sees all changes made by any
69CPU during the time that CPU was holding this same lock". For example,
70consider the following pair of code fragments:
71
72 /* See MP+polocks.litmus. */
73 void CPU0(void)
74 {
75 WRITE_ONCE(x, 1);
76 spin_lock(&mylock);
77 WRITE_ONCE(y, 1);
78 spin_unlock(&mylock);
79 }
80
81 void CPU1(void)
82 {
83 spin_lock(&mylock);
84 r0 = READ_ONCE(y);
85 spin_unlock(&mylock);
86 r1 = READ_ONCE(x);
87 }
88
89The basic rule guarantees that if CPU0() acquires mylock before CPU1(),
90then both r0 and r1 must be set to the value 1. This also has the
91consequence that if the final value of r0 is equal to 1, then the final
92value of r1 must also be equal to 1. In contrast, the weaker rule would
93say nothing about the final value of r1.
94
95The converse to the basic rule also holds, as illustrated by the
96following litmus test:
97
98 /* See MP+porevlocks.litmus. */
99 void CPU0(void)
100 {
101 r0 = READ_ONCE(y);
102 spin_lock(&mylock);
103 r1 = READ_ONCE(x);
104 spin_unlock(&mylock);
105 }
106
107 void CPU1(void)
108 {
109 spin_lock(&mylock);
110 WRITE_ONCE(x, 1);
111 spin_unlock(&mylock);
112 WRITE_ONCE(y, 1);
113 }
114
115This converse to the basic rule guarantees that if CPU0() acquires
116mylock before CPU1(), then both r0 and r1 must be set to the value 0.
117This also has the consequence that if the final value of r1 is equal
118to 0, then the final value of r0 must also be equal to 0. In contrast,
119the weaker rule would say nothing about the final value of r0.
120
121These examples show only a single pair of CPUs, but the effects of the
122locking basic rule extend across multiple acquisitions of a given lock
123across multiple CPUs.
124
125However, it is not necessarily the case that accesses ordered by
126locking will be seen as ordered by CPUs not holding that lock.
127Consider this example:
128
129 /* See Z6.0+pooncelock+pooncelock+pombonce.litmus. */
130 void CPU0(void)
131 {
132 spin_lock(&mylock);
133 WRITE_ONCE(x, 1);
134 WRITE_ONCE(y, 1);
135 spin_unlock(&mylock);
136 }
137
138 void CPU1(void)
139 {
140 spin_lock(&mylock);
141 r0 = READ_ONCE(y);
142 WRITE_ONCE(z, 1);
143 spin_unlock(&mylock);
144 }
145
146 void CPU2(void)
147 {
148 WRITE_ONCE(z, 2);
149 smp_mb();
150 r1 = READ_ONCE(x);
151 }
152
153Counter-intuitive though it might be, it is quite possible to have
154the final value of r0 be 1, the final value of z be 2, and the final
155value of r1 be 0. The reason for this surprising outcome is that
156CPU2() never acquired the lock, and thus did not benefit from the
157lock's ordering properties.
158
159Ordering can be extended to CPUs not holding the lock by careful use
160of smp_mb__after_spinlock():
161
162 /* See Z6.0+pooncelock+poonceLock+pombonce.litmus. */
163 void CPU0(void)
164 {
165 spin_lock(&mylock);
166 WRITE_ONCE(x, 1);
167 WRITE_ONCE(y, 1);
168 spin_unlock(&mylock);
169 }
170
171 void CPU1(void)
172 {
173 spin_lock(&mylock);
174 smp_mb__after_spinlock();
175 r0 = READ_ONCE(y);
176 WRITE_ONCE(z, 1);
177 spin_unlock(&mylock);
178 }
179
180 void CPU2(void)
181 {
182 WRITE_ONCE(z, 2);
183 smp_mb();
184 r1 = READ_ONCE(x);
185 }
186
187This addition of smp_mb__after_spinlock() strengthens the lock acquisition
188sufficiently to rule out the counter-intuitive outcome.
189
190
191Taking off the training wheels
192==============================
193
194This section looks at more complex examples, including message passing,
195load buffering, release-acquire chains, store buffering.
196Many classes of litmus tests have abbreviated names, which may be found
197here: https://www.cl.cam.ac.uk/~pes20/ppc-supplemental/test6.pdf
198
199
200Message passing (MP)
201--------------------
202
203The MP pattern has one CPU execute a pair of stores to a pair of variables
204and another CPU execute a pair of loads from this same pair of variables,
205but in the opposite order. The goal is to avoid the counter-intuitive
206outcome in which the first load sees the value written by the second store
207but the second load does not see the value written by the first store.
208In the absence of any ordering, this goal may not be met, as can be seen
209in the MP+poonceonces.litmus litmus test. This section therefore looks at
210a number of ways of meeting this goal.
211
212
213Release and acquire
214~~~~~~~~~~~~~~~~~~~
215
216Use of smp_store_release() and smp_load_acquire() is one way to force
217the desired MP ordering. The general approach is shown below:
218
219 /* See MP+pooncerelease+poacquireonce.litmus. */
220 void CPU0(void)
221 {
222 WRITE_ONCE(x, 1);
223 smp_store_release(&y, 1);
224 }
225
226 void CPU1(void)
227 {
228 r0 = smp_load_acquire(&y);
229 r1 = READ_ONCE(x);
230 }
231
232The smp_store_release() macro orders any prior accesses against the
233store, while the smp_load_acquire macro orders the load against any
234subsequent accesses. Therefore, if the final value of r0 is the value 1,
235the final value of r1 must also be the value 1.
236
237The init_stack_slab() function in lib/stackdepot.c uses release-acquire
238in this way to safely initialize of a slab of the stack. Working out
239the mutual-exclusion design is left as an exercise for the reader.
240
241
242Assign and dereference
243~~~~~~~~~~~~~~~~~~~~~~
244
245Use of rcu_assign_pointer() and rcu_dereference() is quite similar to the
246use of smp_store_release() and smp_load_acquire(), except that both
247rcu_assign_pointer() and rcu_dereference() operate on RCU-protected
248pointers. The general approach is shown below:
249
250 /* See MP+onceassign+derefonce.litmus. */
251 int z;
252 int *y = &z;
253 int x;
254
255 void CPU0(void)
256 {
257 WRITE_ONCE(x, 1);
258 rcu_assign_pointer(y, &x);
259 }
260
261 void CPU1(void)
262 {
263 rcu_read_lock();
264 r0 = rcu_dereference(y);
265 r1 = READ_ONCE(*r0);
266 rcu_read_unlock();
267 }
268
269In this example, if the final value of r0 is &x then the final value of
270r1 must be 1.
271
272The rcu_assign_pointer() macro has the same ordering properties as does
273smp_store_release(), but the rcu_dereference() macro orders the load only
274against later accesses that depend on the value loaded. A dependency
275is present if the value loaded determines the address of a later access
276(address dependency, as shown above), the value written by a later store
277(data dependency), or whether or not a later store is executed in the
278first place (control dependency). Note that the term "data dependency"
279is sometimes casually used to cover both address and data dependencies.
280
281In lib/prime_numbers.c, the expand_to_next_prime() function invokes
282rcu_assign_pointer(), and the next_prime_number() function invokes
283rcu_dereference(). This combination mediates access to a bit vector
284that is expanded as additional primes are needed.
285
286
287Write and read memory barriers
288~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
289
290It is usually better to use smp_store_release() instead of smp_wmb()
291and to use smp_load_acquire() instead of smp_rmb(). However, the older
292smp_wmb() and smp_rmb() APIs are still heavily used, so it is important
293to understand their use cases. The general approach is shown below:
294
295 /* See MP+wmbonceonce+rmbonceonce.litmus. */
296 void CPU0(void)
297 {
298 WRITE_ONCE(x, 1);
299 smp_wmb();
300 WRITE_ONCE(y, 1);
301 }
302
303 void CPU1(void)
304 {
305 r0 = READ_ONCE(y);
306 smp_rmb();
307 r1 = READ_ONCE(x);
308 }
309
310The smp_wmb() macro orders prior stores against later stores, and the
311smp_rmb() macro orders prior loads against later loads. Therefore, if
312the final value of r0 is 1, the final value of r1 must also be 1.
313
314The the xlog_state_switch_iclogs() function in fs/xfs/xfs_log.c contains
315the following write-side code fragment:
316
317 log->l_curr_block -= log->l_logBBsize;
318 ASSERT(log->l_curr_block >= 0);
319 smp_wmb();
320 log->l_curr_cycle++;
321
322And the xlog_valid_lsn() function in fs/xfs/xfs_log_priv.h contains
323the corresponding read-side code fragment:
324
325 cur_cycle = ACCESS_ONCE(log->l_curr_cycle);
326 smp_rmb();
327 cur_block = ACCESS_ONCE(log->l_curr_block);
328
329Alternatively, consider the following comment in function
330perf_output_put_handle() in kernel/events/ring_buffer.c:
331
332 * kernel user
333 *
334 * if (LOAD ->data_tail) { LOAD ->data_head
335 * (A) smp_rmb() (C)
336 * STORE $data LOAD $data
337 * smp_wmb() (B) smp_mb() (D)
338 * STORE ->data_head STORE ->data_tail
339 * }
340
341The B/C pairing is an example of the MP pattern using smp_wmb() on the
342write side and smp_rmb() on the read side.
343
344Of course, given that smp_mb() is strictly stronger than either smp_wmb()
345or smp_rmb(), any code fragment that would work with smp_rmb() and
346smp_wmb() would also work with smp_mb() replacing either or both of the
347weaker barriers.
348
349
350Load buffering (LB)
351-------------------
352
353The LB pattern has one CPU load from one variable and then store to a
354second, while another CPU loads from the second variable and then stores
355to the first. The goal is to avoid the counter-intuitive situation where
356each load reads the value written by the other CPU's store. In the
357absence of any ordering it is quite possible that this may happen, as
358can be seen in the LB+poonceonces.litmus litmus test.
359
360One way of avoiding the counter-intuitive outcome is through the use of a
361control dependency paired with a full memory barrier:
362
363 /* See LB+ctrlonceonce+mbonceonce.litmus. */
364 void CPU0(void)
365 {
366 r0 = READ_ONCE(x);
367 if (r0)
368 WRITE_ONCE(y, 1);
369 }
370
371 void CPU1(void)
372 {
373 r1 = READ_ONCE(y);
374 smp_mb();
375 WRITE_ONCE(x, 1);
376 }
377
378This pairing of a control dependency in CPU0() with a full memory
379barrier in CPU1() prevents r0 and r1 from both ending up equal to 1.
380
381The A/D pairing from the ring-buffer use case shown earlier also
382illustrates LB. Here is a repeat of the comment in
383perf_output_put_handle() in kernel/events/ring_buffer.c, showing a
384control dependency on the kernel side and a full memory barrier on
385the user side:
386
387 * kernel user
388 *
389 * if (LOAD ->data_tail) { LOAD ->data_head
390 * (A) smp_rmb() (C)
391 * STORE $data LOAD $data
392 * smp_wmb() (B) smp_mb() (D)
393 * STORE ->data_head STORE ->data_tail
394 * }
395 *
396 * Where A pairs with D, and B pairs with C.
397
398The kernel's control dependency between the load from ->data_tail
399and the store to data combined with the user's full memory barrier
400between the load from data and the store to ->data_tail prevents
401the counter-intuitive outcome where the kernel overwrites the data
402before the user gets done loading it.
403
404
405Release-acquire chains
406----------------------
407
408Release-acquire chains are a low-overhead, flexible, and easy-to-use
409method of maintaining order. However, they do have some limitations that
410need to be fully understood. Here is an example that maintains order:
411
412 /* See ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus. */
413 void CPU0(void)
414 {
415 WRITE_ONCE(x, 1);
416 smp_store_release(&y, 1);
417 }
418
419 void CPU1(void)
420 {
421 r0 = smp_load_acquire(y);
422 smp_store_release(&z, 1);
423 }
424
425 void CPU2(void)
426 {
427 r1 = smp_load_acquire(z);
428 r2 = READ_ONCE(x);
429 }
430
431In this case, if r0 and r1 both have final values of 1, then r2 must
432also have a final value of 1.
433
434The ordering in this example is stronger than it needs to be. For
435example, ordering would still be preserved if CPU1()'s smp_load_acquire()
436invocation was replaced with READ_ONCE().
437
438It is tempting to assume that CPU0()'s store to x is globally ordered
439before CPU1()'s store to z, but this is not the case:
440
441 /* See Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus. */
442 void CPU0(void)
443 {
444 WRITE_ONCE(x, 1);
445 smp_store_release(&y, 1);
446 }
447
448 void CPU1(void)
449 {
450 r0 = smp_load_acquire(y);
451 smp_store_release(&z, 1);
452 }
453
454 void CPU2(void)
455 {
456 WRITE_ONCE(z, 2);
457 smp_mb();
458 r1 = READ_ONCE(x);
459 }
460
461One might hope that if the final value of r0 is 1 and the final value
462of z is 2, then the final value of r1 must also be 1, but it really is
463possible for r1 to have the final value of 0. The reason, of course,
464is that in this version, CPU2() is not part of the release-acquire chain.
465This situation is accounted for in the rules of thumb below.
466
467Despite this limitation, release-acquire chains are low-overhead as
468well as simple and powerful, at least as memory-ordering mechanisms go.
469
470
471Store buffering
472---------------
473
474Store buffering can be thought of as upside-down load buffering, so
475that one CPU first stores to one variable and then loads from a second,
476while another CPU stores to the second variable and then loads from the
477first. Preserving order requires nothing less than full barriers:
478
479 /* See SB+mbonceonces.litmus. */
480 void CPU0(void)
481 {
482 WRITE_ONCE(x, 1);
483 smp_mb();
484 r0 = READ_ONCE(y);
485 }
486
487 void CPU1(void)
488 {
489 WRITE_ONCE(y, 1);
490 smp_mb();
491 r1 = READ_ONCE(x);
492 }
493
494Omitting either smp_mb() will allow both r0 and r1 to have final
495values of 0, but providing both full barriers as shown above prevents
496this counter-intuitive outcome.
497
498This pattern most famously appears as part of Dekker's locking
499algorithm, but it has a much more practical use within the Linux kernel
500of ordering wakeups. The following comment taken from waitqueue_active()
501in include/linux/wait.h shows the canonical pattern:
502
503 * CPU0 - waker CPU1 - waiter
504 *
505 * for (;;) {
506 * @cond = true; prepare_to_wait(&wq_head, &wait, state);
507 * smp_mb(); // smp_mb() from set_current_state()
508 * if (waitqueue_active(wq_head)) if (@cond)
509 * wake_up(wq_head); break;
510 * schedule();
511 * }
512 * finish_wait(&wq_head, &wait);
513
514On CPU0, the store is to @cond and the load is in waitqueue_active().
515On CPU1, prepare_to_wait() contains both a store to wq_head and a call
516to set_current_state(), which contains an smp_mb() barrier; the load is
517"if (@cond)". The full barriers prevent the undesirable outcome where
518CPU1 puts the waiting task to sleep and CPU0 fails to wake it up.
519
520Note that use of locking can greatly simplify this pattern.
521
522
523Rules of thumb
524==============
525
526There might seem to be no pattern governing what ordering primitives are
527needed in which situations, but this is not the case. There is a pattern
528based on the relation between the accesses linking successive CPUs in a
529given litmus test. There are three types of linkage:
530
5311. Write-to-read, where the next CPU reads the value that the
532 previous CPU wrote. The LB litmus-test patterns contain only
533 this type of relation. In formal memory-modeling texts, this
534 relation is called "reads-from" and is usually abbreviated "rf".
535
5362. Read-to-write, where the next CPU overwrites the value that the
537 previous CPU read. The SB litmus test contains only this type
538 of relation. In formal memory-modeling texts, this relation is
539 often called "from-reads" and is sometimes abbreviated "fr".
540
5413. Write-to-write, where the next CPU overwrites the value written
542 by the previous CPU. The Z6.0 litmus test pattern contains a
543 write-to-write relation between the last access of CPU1() and
544 the first access of CPU2(). In formal memory-modeling texts,
545 this relation is often called "coherence order" and is sometimes
546 abbreviated "co". In the C++ standard, it is instead called
547 "modification order" and often abbreviated "mo".
548
549The strength of memory ordering required for a given litmus test to
550avoid a counter-intuitive outcome depends on the types of relations
551linking the memory accesses for the outcome in question:
552
553o If all links are write-to-read links, then the weakest
554 possible ordering within each CPU suffices. For example, in
555 the LB litmus test, a control dependency was enough to do the
556 job.
557
558o If all but one of the links are write-to-read links, then a
559 release-acquire chain suffices. Both the MP and the ISA2
560 litmus tests illustrate this case.
561
562o If more than one of the links are something other than
563 write-to-read links, then a full memory barrier is required
564 between each successive pair of non-write-to-read links. This
565 case is illustrated by the Z6.0 litmus tests, both in the
566 locking and in the release-acquire sections.
567
568However, if you find yourself having to stretch these rules of thumb
569to fit your situation, you should consider creating a litmus test and
570running it on the model.
diff --git a/tools/memory-model/Documentation/references.txt b/tools/memory-model/Documentation/references.txt
new file mode 100644
index 000000000000..ba2e34c2ec3f
--- /dev/null
+++ b/tools/memory-model/Documentation/references.txt
@@ -0,0 +1,107 @@
1This document provides background reading for memory models and related
2tools. These documents are aimed at kernel hackers who are interested
3in memory models.
4
5
6Hardware manuals and models
7===========================
8
9o SPARC International Inc. (Ed.). 1994. "The SPARC Architecture
10 Reference Manual Version 9". SPARC International Inc.
11
12o Compaq Computer Corporation (Ed.). 2002. "Alpha Architecture
13 Reference Manual". Compaq Computer Corporation.
14
15o Intel Corporation (Ed.). 2002. "A Formal Specification of Intel
16 Itanium Processor Family Memory Ordering". Intel Corporation.
17
18o Intel Corporation (Ed.). 2002. "Intel 64 and IA-32 Architectures
19 Software Developer’s Manual". Intel Corporation.
20
21o Peter Sewell, Susmit Sarkar, Scott Owens, Francesco Zappa Nardelli,
22 and Magnus O. Myreen. 2010. "x86-TSO: A Rigorous and Usable
23 Programmer's Model for x86 Multiprocessors". Commun. ACM 53, 7
24 (July, 2010), 89-97. http://doi.acm.org/10.1145/1785414.1785443
25
26o IBM Corporation (Ed.). 2009. "Power ISA Version 2.06". IBM
27 Corporation.
28
29o ARM Ltd. (Ed.). 2009. "ARM Barrier Litmus Tests and Cookbook".
30 ARM Ltd.
31
32o Susmit Sarkar, Peter Sewell, Jade Alglave, Luc Maranget, and
33 Derek Williams. 2011. "Understanding POWER Multiprocessors". In
34 Proceedings of the 32Nd ACM SIGPLAN Conference on Programming
35 Language Design and Implementation (PLDI ’11). ACM, New York,
36 NY, USA, 175–186.
37
38o Susmit Sarkar, Kayvan Memarian, Scott Owens, Mark Batty,
39 Peter Sewell, Luc Maranget, Jade Alglave, and Derek Williams.
40 2012. "Synchronising C/C++ and POWER". In Proceedings of the 33rd
41 ACM SIGPLAN Conference on Programming Language Design and
42 Implementation (PLDI '12). ACM, New York, NY, USA, 311-322.
43
44o ARM Ltd. (Ed.). 2014. "ARM Architecture Reference Manual (ARMv8,
45 for ARMv8-A architecture profile)". ARM Ltd.
46
47o Imagination Technologies, LTD. 2015. "MIPS(R) Architecture
48 For Programmers, Volume II-A: The MIPS64(R) Instruction,
49 Set Reference Manual". Imagination Technologies,
50 LTD. https://imgtec.com/?do-download=4302.
51
52o Shaked Flur, Kathryn E. Gray, Christopher Pulte, Susmit
53 Sarkar, Ali Sezgin, Luc Maranget, Will Deacon, and Peter
54 Sewell. 2016. "Modelling the ARMv8 Architecture, Operationally:
55 Concurrency and ISA". In Proceedings of the 43rd Annual ACM
56 SIGPLAN-SIGACT Symposium on Principles of Programming Languages
57 (POPL ’16). ACM, New York, NY, USA, 608–621.
58
59o Shaked Flur, Susmit Sarkar, Christopher Pulte, Kyndylan Nienhuis,
60 Luc Maranget, Kathryn E. Gray, Ali Sezgin, Mark Batty, and Peter
61 Sewell. 2017. "Mixed-size Concurrency: ARM, POWER, C/C++11,
62 and SC". In Proceedings of the 44th ACM SIGPLAN Symposium on
63 Principles of Programming Languages (POPL 2017). ACM, New York,
64 NY, USA, 429–442.
65
66
67Linux-kernel memory model
68=========================
69
70o Andrea Parri, Alan Stern, Luc Maranget, Paul E. McKenney,
71 and Jade Alglave. 2017. "A formal model of
72 Linux-kernel memory ordering - companion webpage".
73 http://moscova.inria.fr/∼maranget/cats7/linux/. (2017). [Online;
74 accessed 30-January-2017].
75
76o Jade Alglave, Luc Maranget, Paul E. McKenney, Andrea Parri, and
77 Alan Stern. 2017. "A formal kernel memory-ordering model (part 1)"
78 Linux Weekly News. https://lwn.net/Articles/718628/
79
80o Jade Alglave, Luc Maranget, Paul E. McKenney, Andrea Parri, and
81 Alan Stern. 2017. "A formal kernel memory-ordering model (part 2)"
82 Linux Weekly News. https://lwn.net/Articles/720550/
83
84
85Memory-model tooling
86====================
87
88o Daniel Jackson. 2002. "Alloy: A Lightweight Object Modelling
89 Notation". ACM Trans. Softw. Eng. Methodol. 11, 2 (April 2002),
90 256–290. http://doi.acm.org/10.1145/505145.505149
91
92o Jade Alglave, Luc Maranget, and Michael Tautschnig. 2014. "Herding
93 Cats: Modelling, Simulation, Testing, and Data Mining for Weak
94 Memory". ACM Trans. Program. Lang. Syst. 36, 2, Article 7 (July
95 2014), 7:1–7:74 pages.
96
97o Jade Alglave, Patrick Cousot, and Luc Maranget. 2016. "Syntax and
98 semantics of the weak consistency model specification language
99 cat". CoRR abs/1608.07531 (2016). http://arxiv.org/abs/1608.07531
100
101
102Memory-model comparisons
103========================
104
105o Paul E. McKenney, Ulrich Weigand, Andrea Parri, and Boqun
106 Feng. 2016. "Linux-Kernel Memory Model". (6 June 2016).
107 http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0124r2.html.
diff --git a/tools/memory-model/README b/tools/memory-model/README
new file mode 100644
index 000000000000..0b3a5f3c9ccd
--- /dev/null
+++ b/tools/memory-model/README
@@ -0,0 +1,206 @@
1 =====================================
2 LINUX KERNEL MEMORY CONSISTENCY MODEL
3 =====================================
4
5============
6INTRODUCTION
7============
8
9This directory contains the memory consistency model (memory model, for
10short) of the Linux kernel, written in the "cat" language and executable
11by the externally provided "herd7" simulator, which exhaustively explores
12the state space of small litmus tests.
13
14In addition, the "klitmus7" tool (also externally provided) may be used
15to convert a litmus test to a Linux kernel module, which in turn allows
16that litmus test to be exercised within the Linux kernel.
17
18
19============
20REQUIREMENTS
21============
22
23Version 7.48 of the "herd7" and "klitmus7" tools must be downloaded
24separately:
25
26 https://github.com/herd/herdtools7
27
28See "herdtools7/INSTALL.md" for installation instructions.
29
30
31==================
32BASIC USAGE: HERD7
33==================
34
35The memory model is used, in conjunction with "herd7", to exhaustively
36explore the state space of small litmus tests.
37
38For example, to run SB+mbonceonces.litmus against the memory model:
39
40 $ herd7 -conf linux-kernel.cfg litmus-tests/SB+mbonceonces.litmus
41
42Here is the corresponding output:
43
44 Test SB+mbonceonces Allowed
45 States 3
46 0:r0=0; 1:r0=1;
47 0:r0=1; 1:r0=0;
48 0:r0=1; 1:r0=1;
49 No
50 Witnesses
51 Positive: 0 Negative: 3
52 Condition exists (0:r0=0 /\ 1:r0=0)
53 Observation SB+mbonceonces Never 0 3
54 Time SB+mbonceonces 0.01
55 Hash=d66d99523e2cac6b06e66f4c995ebb48
56
57The "Positive: 0 Negative: 3" and the "Never 0 3" each indicate that
58this litmus test's "exists" clause can not be satisfied.
59
60See "herd7 -help" or "herdtools7/doc/" for more information.
61
62
63=====================
64BASIC USAGE: KLITMUS7
65=====================
66
67The "klitmus7" tool converts a litmus test into a Linux kernel module,
68which may then be loaded and run.
69
70For example, to run SB+mbonceonces.litmus against hardware:
71
72 $ mkdir mymodules
73 $ klitmus7 -o mymodules litmus-tests/SB+mbonceonces.litmus
74 $ cd mymodules ; make
75 $ sudo sh run.sh
76
77The corresponding output includes:
78
79 Test SB+mbonceonces Allowed
80 Histogram (3 states)
81 644580 :>0:r0=1; 1:r0=0;
82 644328 :>0:r0=0; 1:r0=1;
83 711092 :>0:r0=1; 1:r0=1;
84 No
85 Witnesses
86 Positive: 0, Negative: 2000000
87 Condition exists (0:r0=0 /\ 1:r0=0) is NOT validated
88 Hash=d66d99523e2cac6b06e66f4c995ebb48
89 Observation SB+mbonceonces Never 0 2000000
90 Time SB+mbonceonces 0.16
91
92The "Positive: 0 Negative: 2000000" and the "Never 0 2000000" indicate
93that during two million trials, the state specified in this litmus
94test's "exists" clause was not reached.
95
96And, as with "herd7", please see "klitmus7 -help" or "herdtools7/doc/"
97for more information.
98
99
100====================
101DESCRIPTION OF FILES
102====================
103
104Documentation/cheatsheet.txt
105 Quick-reference guide to the Linux-kernel memory model.
106
107Documentation/explanation.txt
108 Describes the memory model in detail.
109
110Documentation/recipes.txt
111 Lists common memory-ordering patterns.
112
113Documentation/references.txt
114 Provides background reading.
115
116linux-kernel.bell
117 Categorizes the relevant instructions, including memory
118 references, memory barriers, atomic read-modify-write operations,
119 lock acquisition/release, and RCU operations.
120
121 More formally, this file (1) lists the subtypes of the various
122 event types used by the memory model and (2) performs RCU
123 read-side critical section nesting analysis.
124
125linux-kernel.cat
126 Specifies what reorderings are forbidden by memory references,
127 memory barriers, atomic read-modify-write operations, and RCU.
128
129 More formally, this file specifies what executions are forbidden
130 by the memory model. Allowed executions are those which
131 satisfy the model's "coherence", "atomic", "happens-before",
132 "propagation", and "rcu" axioms, which are defined in the file.
133
134linux-kernel.cfg
135 Convenience file that gathers the common-case herd7 command-line
136 arguments.
137
138linux-kernel.def
139 Maps from C-like syntax to herd7's internal litmus-test
140 instruction-set architecture.
141
142litmus-tests
143 Directory containing a few representative litmus tests, which
144 are listed in litmus-tests/README. A great deal more litmus
145 tests are available at https://github.com/paulmckrcu/litmus.
146
147lock.cat
148 Provides a front-end analysis of lock acquisition and release,
149 for example, associating a lock acquisition with the preceding
150 and following releases and checking for self-deadlock.
151
152 More formally, this file defines a performance-enhanced scheme
153 for generation of the possible reads-from and coherence order
154 relations on the locking primitives.
155
156README
157 This file.
158
159
160===========
161LIMITATIONS
162===========
163
164The Linux-kernel memory model has the following limitations:
165
1661. Compiler optimizations are not modeled. Of course, the use
167 of READ_ONCE() and WRITE_ONCE() limits the compiler's ability
168 to optimize, but there is Linux-kernel code that uses bare C
169 memory accesses. Handling this code is on the to-do list.
170 For more information, see Documentation/explanation.txt (in
171 particular, the "THE PROGRAM ORDER RELATION: po AND po-loc"
172 and "A WARNING" sections).
173
1742. Multiple access sizes for a single variable are not supported,
175 and neither are misaligned or partially overlapping accesses.
176
1773. Exceptions and interrupts are not modeled. In some cases,
178 this limitation can be overcome by modeling the interrupt or
179 exception with an additional process.
180
1814. I/O such as MMIO or DMA is not supported.
182
1835. Self-modifying code (such as that found in the kernel's
184 alternatives mechanism, function tracer, Berkeley Packet Filter
185 JIT compiler, and module loader) is not supported.
186
1876. Complete modeling of all variants of atomic read-modify-write
188 operations, locking primitives, and RCU is not provided.
189 For example, call_rcu() and rcu_barrier() are not supported.
190 However, a substantial amount of support is provided for these
191 operations, as shown in the linux-kernel.def file.
192
193The "herd7" tool has some additional limitations of its own, apart from
194the memory model:
195
1961. Non-trivial data structures such as arrays or structures are
197 not supported. However, pointers are supported, allowing trivial
198 linked lists to be constructed.
199
2002. Dynamic memory allocation is not supported, although this can
201 be worked around in some cases by supplying multiple statically
202 allocated variables.
203
204Some of these limitations may be overcome in the future, but others are
205more likely to be addressed by incorporating the Linux-kernel memory model
206into other tools.
diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
new file mode 100644
index 000000000000..432c7cf71b23
--- /dev/null
+++ b/tools/memory-model/linux-kernel.bell
@@ -0,0 +1,52 @@
1// SPDX-License-Identifier: GPL-2.0+
2(*
3 * Copyright (C) 2015 Jade Alglave <j.alglave@ucl.ac.uk>,
4 * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
5 * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>,
6 * Andrea Parri <parri.andrea@gmail.com>
7 *
8 * An earlier version of this file appears in the companion webpage for
9 * "Frightening small children and disconcerting grown-ups: Concurrency
10 * in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
11 * which is to appear in ASPLOS 2018.
12 *)
13
14"Linux-kernel memory consistency model"
15
16enum Accesses = 'once (*READ_ONCE,WRITE_ONCE,ACCESS_ONCE*) ||
17 'release (*smp_store_release*) ||
18 'acquire (*smp_load_acquire*) ||
19 'noreturn (* R of non-return RMW *)
20instructions R[{'once,'acquire,'noreturn}]
21instructions W[{'once,'release}]
22instructions RMW[{'once,'acquire,'release}]
23
24enum Barriers = 'wmb (*smp_wmb*) ||
25 'rmb (*smp_rmb*) ||
26 'mb (*smp_mb*) ||
27 'rcu-lock (*rcu_read_lock*) ||
28 'rcu-unlock (*rcu_read_unlock*) ||
29 'sync-rcu (*synchronize_rcu*) ||
30 'before-atomic (*smp_mb__before_atomic*) ||
31 'after-atomic (*smp_mb__after_atomic*) ||
32 'after-spinlock (*smp_mb__after_spinlock*)
33instructions F[Barriers]
34
35(* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
36let matched = let rec
37 unmatched-locks = Rcu-lock \ domain(matched)
38 and unmatched-unlocks = Rcu-unlock \ range(matched)
39 and unmatched = unmatched-locks | unmatched-unlocks
40 and unmatched-po = [unmatched] ; po ; [unmatched]
41 and unmatched-locks-to-unlocks =
42 [unmatched-locks] ; po ; [unmatched-unlocks]
43 and matched = matched | (unmatched-locks-to-unlocks \
44 (unmatched-po ; unmatched-po))
45 in matched
46
47(* Validate nesting *)
48flag ~empty Rcu-lock \ domain(matched) as unbalanced-rcu-locking
49flag ~empty Rcu-unlock \ range(matched) as unbalanced-rcu-locking
50
51(* Outermost level of nesting only *)
52let crit = matched \ (po^-1 ; matched ; po^-1)
diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
new file mode 100644
index 000000000000..df97db03b6c2
--- /dev/null
+++ b/tools/memory-model/linux-kernel.cat
@@ -0,0 +1,121 @@
1// SPDX-License-Identifier: GPL-2.0+
2(*
3 * Copyright (C) 2015 Jade Alglave <j.alglave@ucl.ac.uk>,
4 * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
5 * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>,
6 * Andrea Parri <parri.andrea@gmail.com>
7 *
8 * An earlier version of this file appears in the companion webpage for
9 * "Frightening small children and disconcerting grown-ups: Concurrency
10 * in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
11 * which is to appear in ASPLOS 2018.
12 *)
13
14"Linux-kernel memory consistency model"
15
16(*
17 * File "lock.cat" handles locks and is experimental.
18 * It can be replaced by include "cos.cat" for tests that do not use locks.
19 *)
20
21include "lock.cat"
22
23(*******************)
24(* Basic relations *)
25(*******************)
26
27(* Fences *)
28let rmb = [R \ Noreturn] ; fencerel(Rmb) ; [R \ Noreturn]
29let wmb = [W] ; fencerel(Wmb) ; [W]
30let mb = ([M] ; fencerel(Mb) ; [M]) |
31 ([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) |
32 ([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) |
33 ([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M])
34let gp = po ; [Sync-rcu] ; po?
35
36let strong-fence = mb | gp
37
38(* Release Acquire *)
39let acq-po = [Acquire] ; po ; [M]
40let po-rel = [M] ; po ; [Release]
41let rfi-rel-acq = [Release] ; rfi ; [Acquire]
42
43(**********************************)
44(* Fundamental coherence ordering *)
45(**********************************)
46
47(* Sequential Consistency Per Variable *)
48let com = rf | co | fr
49acyclic po-loc | com as coherence
50
51(* Atomic Read-Modify-Write *)
52empty rmw & (fre ; coe) as atomic
53
54(**********************************)
55(* Instruction execution ordering *)
56(**********************************)
57
58(* Preserved Program Order *)
59let dep = addr | data
60let rwdep = (dep | ctrl) ; [W]
61let overwrite = co | fr
62let to-w = rwdep | (overwrite & int)
63let to-r = addr | (dep ; rfi) | rfi-rel-acq
64let fence = strong-fence | wmb | po-rel | rmb | acq-po
65let ppo = to-r | to-w | fence
66
67(* Propagation: Ordering from release operations and strong fences. *)
68let A-cumul(r) = rfe? ; r
69let cumul-fence = A-cumul(strong-fence | po-rel) | wmb
70let prop = (overwrite & ext)? ; cumul-fence* ; rfe?
71
72(*
73 * Happens Before: Ordering from the passage of time.
74 * No fences needed here for prop because relation confined to one process.
75 *)
76let hb = ppo | rfe | ((prop \ id) & int)
77acyclic hb as happens-before
78
79(****************************************)
80(* Write and fence propagation ordering *)
81(****************************************)
82
83(* Propagation: Each non-rf link needs a strong fence. *)
84let pb = prop ; strong-fence ; hb*
85acyclic pb as propagation
86
87(*******)
88(* RCU *)
89(*******)
90
91(*
92 * Effect of read-side critical section proceeds from the rcu_read_lock()
93 * onward on the one hand and from the rcu_read_unlock() backwards on the
94 * other hand.
95 *)
96let rscs = po ; crit^-1 ; po?
97
98(*
99 * The synchronize_rcu() strong fence is special in that it can order not
100 * one but two non-rf relations, but only in conjunction with an RCU
101 * read-side critical section.
102 *)
103let link = hb* ; pb* ; prop
104
105(* Chains that affect the RCU grace-period guarantee *)
106let gp-link = gp ; link
107let rscs-link = rscs ; link
108
109(*
110 * A cycle containing at least as many grace periods as RCU read-side
111 * critical sections is forbidden.
112 *)
113let rec rcu-path =
114 gp-link |
115 (gp-link ; rscs-link) |
116 (rscs-link ; gp-link) |
117 (rcu-path ; rcu-path) |
118 (gp-link ; rcu-path ; rscs-link) |
119 (rscs-link ; rcu-path ; gp-link)
120
121irreflexive rcu-path as rcu
diff --git a/tools/memory-model/linux-kernel.cfg b/tools/memory-model/linux-kernel.cfg
new file mode 100644
index 000000000000..3c8098e99f41
--- /dev/null
+++ b/tools/memory-model/linux-kernel.cfg
@@ -0,0 +1,21 @@
1macros linux-kernel.def
2bell linux-kernel.bell
3model linux-kernel.cat
4graph columns
5squished true
6showevents noregs
7movelabel true
8fontsize 8
9xscale 2.0
10yscale 1.5
11arrowsize 0.8
12showinitrf false
13showfinalrf false
14showinitwrites false
15splines spline
16pad 0.1
17edgeattr hb,color,indigo
18edgeattr co,color,blue
19edgeattr mb,color,darkgreen
20edgeattr wmb,color,darkgreen
21edgeattr rmb,color,darkgreen
diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
new file mode 100644
index 000000000000..397e4e67e8c8
--- /dev/null
+++ b/tools/memory-model/linux-kernel.def
@@ -0,0 +1,106 @@
1// SPDX-License-Identifier: GPL-2.0+
2//
3// An earlier version of this file appears in the companion webpage for
4// "Frightening small children and disconcerting grown-ups: Concurrency
5// in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
6// which is to appear in ASPLOS 2018.
7
8// ONCE
9READ_ONCE(X) __load{once}(X)
10WRITE_ONCE(X,V) { __store{once}(X,V); }
11
12// Release Acquire and friends
13smp_store_release(X,V) { __store{release}(*X,V); }
14smp_load_acquire(X) __load{acquire}(*X)
15rcu_assign_pointer(X,V) { __store{release}(X,V); }
16rcu_dereference(X) __load{once}(X)
17
18// Fences
19smp_mb() { __fence{mb} ; }
20smp_rmb() { __fence{rmb} ; }
21smp_wmb() { __fence{wmb} ; }
22smp_mb__before_atomic() { __fence{before-atomic} ; }
23smp_mb__after_atomic() { __fence{after-atomic} ; }
24smp_mb__after_spinlock() { __fence{after-spinlock} ; }
25
26// Exchange
27xchg(X,V) __xchg{mb}(X,V)
28xchg_relaxed(X,V) __xchg{once}(X,V)
29xchg_release(X,V) __xchg{release}(X,V)
30xchg_acquire(X,V) __xchg{acquire}(X,V)
31cmpxchg(X,V,W) __cmpxchg{mb}(X,V,W)
32cmpxchg_relaxed(X,V,W) __cmpxchg{once}(X,V,W)
33cmpxchg_acquire(X,V,W) __cmpxchg{acquire}(X,V,W)
34cmpxchg_release(X,V,W) __cmpxchg{release}(X,V,W)
35
36// Spinlocks
37spin_lock(X) { __lock(X) ; }
38spin_unlock(X) { __unlock(X) ; }
39spin_trylock(X) __trylock(X)
40
41// RCU
42rcu_read_lock() { __fence{rcu-lock}; }
43rcu_read_unlock() { __fence{rcu-unlock};}
44synchronize_rcu() { __fence{sync-rcu}; }
45synchronize_rcu_expedited() { __fence{sync-rcu}; }
46
47// Atomic
48atomic_read(X) READ_ONCE(*X)
49atomic_set(X,V) { WRITE_ONCE(*X,V) ; }
50atomic_read_acquire(X) smp_load_acquire(X)
51atomic_set_release(X,V) { smp_store_release(X,V); }
52
53atomic_add(V,X) { __atomic_op(X,+,V) ; }
54atomic_sub(V,X) { __atomic_op(X,-,V) ; }
55atomic_inc(X) { __atomic_op(X,+,1) ; }
56atomic_dec(X) { __atomic_op(X,-,1) ; }
57
58atomic_add_return(V,X) __atomic_op_return{mb}(X,+,V)
59atomic_add_return_relaxed(V,X) __atomic_op_return{once}(X,+,V)
60atomic_add_return_acquire(V,X) __atomic_op_return{acquire}(X,+,V)
61atomic_add_return_release(V,X) __atomic_op_return{release}(X,+,V)
62atomic_fetch_add(V,X) __atomic_fetch_op{mb}(X,+,V)
63atomic_fetch_add_relaxed(V,X) __atomic_fetch_op{once}(X,+,V)
64atomic_fetch_add_acquire(V,X) __atomic_fetch_op{acquire}(X,+,V)
65atomic_fetch_add_release(V,X) __atomic_fetch_op{release}(X,+,V)
66
67atomic_inc_return(X) __atomic_op_return{mb}(X,+,1)
68atomic_inc_return_relaxed(X) __atomic_op_return{once}(X,+,1)
69atomic_inc_return_acquire(X) __atomic_op_return{acquire}(X,+,1)
70atomic_inc_return_release(X) __atomic_op_return{release}(X,+,1)
71atomic_fetch_inc(X) __atomic_fetch_op{mb}(X,+,1)
72atomic_fetch_inc_relaxed(X) __atomic_fetch_op{once}(X,+,1)
73atomic_fetch_inc_acquire(X) __atomic_fetch_op{acquire}(X,+,1)
74atomic_fetch_inc_release(X) __atomic_fetch_op{release}(X,+,1)
75
76atomic_sub_return(V,X) __atomic_op_return{mb}(X,-,V)
77atomic_sub_return_relaxed(V,X) __atomic_op_return{once}(X,-,V)
78atomic_sub_return_acquire(V,X) __atomic_op_return{acquire}(X,-,V)
79atomic_sub_return_release(V,X) __atomic_op_return{release}(X,-,V)
80atomic_fetch_sub(V,X) __atomic_fetch_op{mb}(X,-,V)
81atomic_fetch_sub_relaxed(V,X) __atomic_fetch_op{once}(X,-,V)
82atomic_fetch_sub_acquire(V,X) __atomic_fetch_op{acquire}(X,-,V)
83atomic_fetch_sub_release(V,X) __atomic_fetch_op{release}(X,-,V)
84
85atomic_dec_return(X) __atomic_op_return{mb}(X,-,1)
86atomic_dec_return_relaxed(X) __atomic_op_return{once}(X,-,1)
87atomic_dec_return_acquire(X) __atomic_op_return{acquire}(X,-,1)
88atomic_dec_return_release(X) __atomic_op_return{release}(X,-,1)
89atomic_fetch_dec(X) __atomic_fetch_op{mb}(X,-,1)
90atomic_fetch_dec_relaxed(X) __atomic_fetch_op{once}(X,-,1)
91atomic_fetch_dec_acquire(X) __atomic_fetch_op{acquire}(X,-,1)
92atomic_fetch_dec_release(X) __atomic_fetch_op{release}(X,-,1)
93
94atomic_xchg(X,V) __xchg{mb}(X,V)
95atomic_xchg_relaxed(X,V) __xchg{once}(X,V)
96atomic_xchg_release(X,V) __xchg{release}(X,V)
97atomic_xchg_acquire(X,V) __xchg{acquire}(X,V)
98atomic_cmpxchg(X,V,W) __cmpxchg{mb}(X,V,W)
99atomic_cmpxchg_relaxed(X,V,W) __cmpxchg{once}(X,V,W)
100atomic_cmpxchg_acquire(X,V,W) __cmpxchg{acquire}(X,V,W)
101atomic_cmpxchg_release(X,V,W) __cmpxchg{release}(X,V,W)
102
103atomic_sub_and_test(V,X) __atomic_op_return{mb}(X,-,V) == 0
104atomic_dec_and_test(X) __atomic_op_return{mb}(X,-,1) == 0
105atomic_inc_and_test(X) __atomic_op_return{mb}(X,+,1) == 0
106atomic_add_negative(V,X) __atomic_op_return{mb}(X,+,V) < 0
diff --git a/tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus b/tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus
new file mode 100644
index 000000000000..967f9f2a6226
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus
@@ -0,0 +1,26 @@
1C CoRR+poonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * Test of read-read coherence, that is, whether or not two successive
7 * reads from the same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 WRITE_ONCE(*x, 1);
15}
16
17P1(int *x)
18{
19 int r0;
20 int r1;
21
22 r0 = READ_ONCE(*x);
23 r1 = READ_ONCE(*x);
24}
25
26exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus b/tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus
new file mode 100644
index 000000000000..4635739f3974
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus
@@ -0,0 +1,25 @@
1C CoRW+poonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * Test of read-write coherence, that is, whether or not a read from
7 * a given variable and a later write to that same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 int r0;
15
16 r0 = READ_ONCE(*x);
17 WRITE_ONCE(*x, 1);
18}
19
20P1(int *x)
21{
22 WRITE_ONCE(*x, 2);
23}
24
25exists (x=2 /\ 0:r0=2)
diff --git a/tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus b/tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus
new file mode 100644
index 000000000000..bb068c92d8da
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus
@@ -0,0 +1,25 @@
1C CoWR+poonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * Test of write-read coherence, that is, whether or not a write to a
7 * given variable and a later read from that same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 int r0;
15
16 WRITE_ONCE(*x, 1);
17 r0 = READ_ONCE(*x);
18}
19
20P1(int *x)
21{
22 WRITE_ONCE(*x, 2);
23}
24
25exists (x=1 /\ 0:r0=2)
diff --git a/tools/memory-model/litmus-tests/CoWW+poonceonce.litmus b/tools/memory-model/litmus-tests/CoWW+poonceonce.litmus
new file mode 100644
index 000000000000..0d9f0a958799
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoWW+poonceonce.litmus
@@ -0,0 +1,18 @@
1C CoWW+poonceonce
2
3(*
4 * Result: Never
5 *
6 * Test of write-write coherence, that is, whether or not two successive
7 * writes to the same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 WRITE_ONCE(*x, 1);
15 WRITE_ONCE(*x, 2);
16}
17
18exists (x=1)
diff --git a/tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus b/tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus
new file mode 100644
index 000000000000..50d5db9ea983
--- /dev/null
+++ b/tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus
@@ -0,0 +1,45 @@
1C IRIW+mbonceonces+OnceOnce
2
3(*
4 * Result: Never
5 *
6 * Test of independent reads from independent writes with smp_mb()
7 * between each pairs of reads. In other words, is smp_mb() sufficient to
8 * cause two different reading processes to agree on the order of a pair
9 * of writes, where each write is to a different variable by a different
10 * process?
11 *)
12
13{}
14
15P0(int *x)
16{
17 WRITE_ONCE(*x, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23 int r1;
24
25 r0 = READ_ONCE(*x);
26 smp_mb();
27 r1 = READ_ONCE(*y);
28}
29
30P2(int *y)
31{
32 WRITE_ONCE(*y, 1);
33}
34
35P3(int *x, int *y)
36{
37 int r0;
38 int r1;
39
40 r0 = READ_ONCE(*y);
41 smp_mb();
42 r1 = READ_ONCE(*x);
43}
44
45exists (1:r0=1 /\ 1:r1=0 /\ 3:r0=1 /\ 3:r1=0)
diff --git a/tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus b/tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus
new file mode 100644
index 000000000000..4b54dd6a6cd9
--- /dev/null
+++ b/tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus
@@ -0,0 +1,43 @@
1C IRIW+poonceonces+OnceOnce
2
3(*
4 * Result: Sometimes
5 *
6 * Test of independent reads from independent writes with nothing
7 * between each pairs of reads. In other words, is anything at all
8 * needed to cause two different reading processes to agree on the order
9 * of a pair of writes, where each write is to a different variable by a
10 * different process?
11 *)
12
13{}
14
15P0(int *x)
16{
17 WRITE_ONCE(*x, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23 int r1;
24
25 r0 = READ_ONCE(*x);
26 r1 = READ_ONCE(*y);
27}
28
29P2(int *y)
30{
31 WRITE_ONCE(*y, 1);
32}
33
34P3(int *x, int *y)
35{
36 int r0;
37 int r1;
38
39 r0 = READ_ONCE(*y);
40 r1 = READ_ONCE(*x);
41}
42
43exists (1:r0=1 /\ 1:r1=0 /\ 3:r0=1 /\ 3:r1=0)
diff --git a/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
new file mode 100644
index 000000000000..7a39a0aaa976
--- /dev/null
+++ b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
@@ -0,0 +1,41 @@
1C ISA2+pooncelock+pooncelock+pombonce.litmus
2
3(*
4 * Result: Sometimes
5 *
6 * This test shows that the ordering provided by a lock-protected S
7 * litmus test (P0() and P1()) are not visible to external process P2().
8 * This is likely to change soon.
9 *)
10
11{}
12
13P0(int *x, int *y, spinlock_t *mylock)
14{
15 spin_lock(mylock);
16 WRITE_ONCE(*x, 1);
17 WRITE_ONCE(*y, 1);
18 spin_unlock(mylock);
19}
20
21P1(int *y, int *z, spinlock_t *mylock)
22{
23 int r0;
24
25 spin_lock(mylock);
26 r0 = READ_ONCE(*y);
27 WRITE_ONCE(*z, 1);
28 spin_unlock(mylock);
29}
30
31P2(int *x, int *z)
32{
33 int r1;
34 int r2;
35
36 r2 = READ_ONCE(*z);
37 smp_mb();
38 r1 = READ_ONCE(*x);
39}
40
41exists (1:r0=1 /\ 2:r2=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/ISA2+poonceonces.litmus b/tools/memory-model/litmus-tests/ISA2+poonceonces.litmus
new file mode 100644
index 000000000000..b321aa6f4ea5
--- /dev/null
+++ b/tools/memory-model/litmus-tests/ISA2+poonceonces.litmus
@@ -0,0 +1,37 @@
1C ISA2+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * Given a release-acquire chain ordering the first process's store
7 * against the last process's load, is ordering preserved if all of the
8 * smp_store_release() invocations are replaced by WRITE_ONCE() and all
9 * of the smp_load_acquire() invocations are replaced by READ_ONCE()?
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 WRITE_ONCE(*x, 1);
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *y, int *z)
21{
22 int r0;
23
24 r0 = READ_ONCE(*y);
25 WRITE_ONCE(*z, 1);
26}
27
28P2(int *x, int *z)
29{
30 int r0;
31 int r1;
32
33 r0 = READ_ONCE(*z);
34 r1 = READ_ONCE(*x);
35}
36
37exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus b/tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus
new file mode 100644
index 000000000000..025b0462ec9b
--- /dev/null
+++ b/tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus
@@ -0,0 +1,39 @@
1C ISA2+pooncerelease+poacquirerelease+poacquireonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that a release-acquire chain suffices
7 * to order P0()'s initial write against P2()'s final read. The reason
8 * that the release-acquire chain suffices is because in all but one
9 * case (P2() to P0()), each process reads from the preceding process's
10 * write. In memory-model-speak, there is only one non-reads-from
11 * (AKA non-rf) link, so release-acquire is all that is needed.
12 *)
13
14{}
15
16P0(int *x, int *y)
17{
18 WRITE_ONCE(*x, 1);
19 smp_store_release(y, 1);
20}
21
22P1(int *y, int *z)
23{
24 int r0;
25
26 r0 = smp_load_acquire(y);
27 smp_store_release(z, 1);
28}
29
30P2(int *x, int *z)
31{
32 int r0;
33 int r1;
34
35 r0 = smp_load_acquire(z);
36 r1 = READ_ONCE(*x);
37}
38
39exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus b/tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus
new file mode 100644
index 000000000000..de6708229dd1
--- /dev/null
+++ b/tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus
@@ -0,0 +1,34 @@
1C LB+ctrlonceonce+mbonceonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that lightweight ordering suffices for
7 * the load-buffering pattern, in other words, preventing all processes
8 * reading from the preceding process's write. In this example, the
9 * combination of a control dependency and a full memory barrier are enough
10 * to do the trick. (But the full memory barrier could be replaced with
11 * another control dependency and order would still be maintained.)
12 *)
13
14{}
15
16P0(int *x, int *y)
17{
18 int r0;
19
20 r0 = READ_ONCE(*x);
21 if (r0)
22 WRITE_ONCE(*y, 1);
23}
24
25P1(int *x, int *y)
26{
27 int r0;
28
29 r0 = READ_ONCE(*y);
30 smp_mb();
31 WRITE_ONCE(*x, 1);
32}
33
34exists (0:r0=1 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus b/tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus
new file mode 100644
index 000000000000..07b9904b0e49
--- /dev/null
+++ b/tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus
@@ -0,0 +1,29 @@
1C LB+poacquireonce+pooncerelease
2
3(*
4 * Result: Never
5 *
6 * Does a release-acquire pair suffice for the load-buffering litmus
7 * test, where each process reads from one of two variables then writes
8 * to the other?
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 int r0;
16
17 r0 = READ_ONCE(*x);
18 smp_store_release(y, 1);
19}
20
21P1(int *x, int *y)
22{
23 int r0;
24
25 r0 = smp_load_acquire(y);
26 WRITE_ONCE(*x, 1);
27}
28
29exists (0:r0=1 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/LB+poonceonces.litmus b/tools/memory-model/litmus-tests/LB+poonceonces.litmus
new file mode 100644
index 000000000000..74c49cb3c37b
--- /dev/null
+++ b/tools/memory-model/litmus-tests/LB+poonceonces.litmus
@@ -0,0 +1,28 @@
1C LB+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * Can the counter-intuitive outcome for the load-buffering pattern
7 * be prevented even with no explicit ordering?
8 *)
9
10{}
11
12P0(int *x, int *y)
13{
14 int r0;
15
16 r0 = READ_ONCE(*x);
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23
24 r0 = READ_ONCE(*y);
25 WRITE_ONCE(*x, 1);
26}
27
28exists (0:r0=1 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus b/tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus
new file mode 100644
index 000000000000..97731b4bbdd8
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus
@@ -0,0 +1,34 @@
1C MP+onceassign+derefonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that rcu_assign_pointer() and
7 * rcu_dereference() suffice to ensure that an RCU reader will not see
8 * pre-initialization garbage when it traverses an RCU-protected data
9 * structure containing a newly inserted element.
10 *)
11
12{
13y=z;
14z=0;
15}
16
17P0(int *x, int **y)
18{
19 WRITE_ONCE(*x, 1);
20 rcu_assign_pointer(*y, x);
21}
22
23P1(int *x, int **y)
24{
25 int *r0;
26 int r1;
27
28 rcu_read_lock();
29 r0 = rcu_dereference(*y);
30 r1 = READ_ONCE(*r0);
31 rcu_read_unlock();
32}
33
34exists (1:r0=x /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+polocks.litmus b/tools/memory-model/litmus-tests/MP+polocks.litmus
new file mode 100644
index 000000000000..712a4fcdf6ce
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+polocks.litmus
@@ -0,0 +1,35 @@
1C MP+polocks
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates how lock acquisitions and releases can
7 * stand in for smp_load_acquire() and smp_store_release(), respectively.
8 * In other words, when holding a given lock (or indeed after releasing a
9 * given lock), a CPU is not only guaranteed to see the accesses that other
10 * CPUs made while previously holding that lock, it is also guaranteed
11 * to see all prior accesses by those other CPUs.
12 *)
13
14{}
15
16P0(int *x, int *y, spinlock_t *mylock)
17{
18 WRITE_ONCE(*x, 1);
19 spin_lock(mylock);
20 WRITE_ONCE(*y, 1);
21 spin_unlock(mylock);
22}
23
24P1(int *x, int *y, spinlock_t *mylock)
25{
26 int r0;
27 int r1;
28
29 spin_lock(mylock);
30 r0 = READ_ONCE(*y);
31 spin_unlock(mylock);
32 r1 = READ_ONCE(*x);
33}
34
35exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+poonceonces.litmus b/tools/memory-model/litmus-tests/MP+poonceonces.litmus
new file mode 100644
index 000000000000..b2b60b84fb9d
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+poonceonces.litmus
@@ -0,0 +1,27 @@
1C MP+poonceonces
2
3(*
4 * Result: Maybe
5 *
6 * Can the counter-intuitive message-passing outcome be prevented with
7 * no ordering at all?
8 *)
9
10{}
11
12P0(int *x, int *y)
13{
14 WRITE_ONCE(*x, 1);
15 WRITE_ONCE(*y, 1);
16}
17
18P1(int *x, int *y)
19{
20 int r0;
21 int r1;
22
23 r0 = READ_ONCE(*y);
24 r1 = READ_ONCE(*x);
25}
26
27exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus b/tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus
new file mode 100644
index 000000000000..d52c68429722
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus
@@ -0,0 +1,28 @@
1C MP+pooncerelease+poacquireonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that smp_store_release() and
7 * smp_load_acquire() provide sufficient ordering for the message-passing
8 * pattern.
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 WRITE_ONCE(*x, 1);
16 smp_store_release(y, 1);
17}
18
19P1(int *x, int *y)
20{
21 int r0;
22 int r1;
23
24 r0 = smp_load_acquire(y);
25 r1 = READ_ONCE(*x);
26}
27
28exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+porevlocks.litmus b/tools/memory-model/litmus-tests/MP+porevlocks.litmus
new file mode 100644
index 000000000000..72c9276b363e
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+porevlocks.litmus
@@ -0,0 +1,35 @@
1C MP+porevlocks
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates how lock acquisitions and releases can
7 * stand in for smp_load_acquire() and smp_store_release(), respectively.
8 * In other words, when holding a given lock (or indeed after releasing a
9 * given lock), a CPU is not only guaranteed to see the accesses that other
10 * CPUs made while previously holding that lock, it is also guaranteed to
11 * see all prior accesses by those other CPUs.
12 *)
13
14{}
15
16P0(int *x, int *y, spinlock_t *mylock)
17{
18 int r0;
19 int r1;
20
21 r0 = READ_ONCE(*y);
22 spin_lock(mylock);
23 r1 = READ_ONCE(*x);
24 spin_unlock(mylock);
25}
26
27P1(int *x, int *y, spinlock_t *mylock)
28{
29 spin_lock(mylock);
30 WRITE_ONCE(*x, 1);
31 spin_unlock(mylock);
32 WRITE_ONCE(*y, 1);
33}
34
35exists (0:r0=1 /\ 0:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus b/tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus
new file mode 100644
index 000000000000..c078f38ff27a
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus
@@ -0,0 +1,30 @@
1C MP+wmbonceonce+rmbonceonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that smp_wmb() and smp_rmb() provide
7 * sufficient ordering for the message-passing pattern. However, it
8 * is usually better to use smp_store_release() and smp_load_acquire().
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 WRITE_ONCE(*x, 1);
16 smp_wmb();
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23 int r1;
24
25 r0 = READ_ONCE(*y);
26 smp_rmb();
27 r1 = READ_ONCE(*x);
28}
29
30exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/R+mbonceonces.litmus b/tools/memory-model/litmus-tests/R+mbonceonces.litmus
new file mode 100644
index 000000000000..a0e884ad2132
--- /dev/null
+++ b/tools/memory-model/litmus-tests/R+mbonceonces.litmus
@@ -0,0 +1,30 @@
1C R+mbonceonces
2
3(*
4 * Result: Never
5 *
6 * This is the fully ordered (via smp_mb()) version of one of the classic
7 * counterintuitive litmus tests that illustrates the effects of store
8 * propagation delays. Note that weakening either of the barriers would
9 * cause the resulting test to be allowed.
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 WRITE_ONCE(*x, 1);
17 smp_mb();
18 WRITE_ONCE(*y, 1);
19}
20
21P1(int *x, int *y)
22{
23 int r0;
24
25 WRITE_ONCE(*y, 2);
26 smp_mb();
27 r0 = READ_ONCE(*x);
28}
29
30exists (y=2 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/R+poonceonces.litmus b/tools/memory-model/litmus-tests/R+poonceonces.litmus
new file mode 100644
index 000000000000..5386f128a131
--- /dev/null
+++ b/tools/memory-model/litmus-tests/R+poonceonces.litmus
@@ -0,0 +1,27 @@
1C R+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * This is the unordered (thus lacking smp_mb()) version of one of the
7 * classic counterintuitive litmus tests that illustrates the effects of
8 * store propagation delays.
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 WRITE_ONCE(*x, 1);
16 WRITE_ONCE(*y, 1);
17}
18
19P1(int *x, int *y)
20{
21 int r0;
22
23 WRITE_ONCE(*y, 2);
24 r0 = READ_ONCE(*x);
25}
26
27exists (y=2 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/README b/tools/memory-model/litmus-tests/README
new file mode 100644
index 000000000000..04096fb8b8d9
--- /dev/null
+++ b/tools/memory-model/litmus-tests/README
@@ -0,0 +1,131 @@
1This directory contains the following litmus tests:
2
3CoRR+poonceonce+Once.litmus
4 Test of read-read coherence, that is, whether or not two
5 successive reads from the same variable are ordered.
6
7CoRW+poonceonce+Once.litmus
8 Test of read-write coherence, that is, whether or not a read
9 from a given variable followed by a write to that same variable
10 are ordered.
11
12CoWR+poonceonce+Once.litmus
13 Test of write-read coherence, that is, whether or not a write
14 to a given variable followed by a read from that same variable
15 are ordered.
16
17CoWW+poonceonce.litmus
18 Test of write-write coherence, that is, whether or not two
19 successive writes to the same variable are ordered.
20
21IRIW+mbonceonces+OnceOnce.litmus
22 Test of independent reads from independent writes with smp_mb()
23 between each pairs of reads. In other words, is smp_mb()
24 sufficient to cause two different reading processes to agree on
25 the order of a pair of writes, where each write is to a different
26 variable by a different process?
27
28IRIW+poonceonces+OnceOnce.litmus
29 Test of independent reads from independent writes with nothing
30 between each pairs of reads. In other words, is anything at all
31 needed to cause two different reading processes to agree on the
32 order of a pair of writes, where each write is to a different
33 variable by a different process?
34
35ISA2+pooncelock+pooncelock+pombonce.litmus
36 Tests whether the ordering provided by a lock-protected S
37 litmus test is visible to an external process whose accesses are
38 separated by smp_mb(). This addition of an external process to
39 S is otherwise known as ISA2.
40
41ISA2+poonceonces.litmus
42 As below, but with store-release replaced with WRITE_ONCE()
43 and load-acquire replaced with READ_ONCE().
44
45ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus
46 Can a release-acquire chain order a prior store against
47 a later load?
48
49LB+ctrlonceonce+mbonceonce.litmus
50 Does a control dependency and an smp_mb() suffice for the
51 load-buffering litmus test, where each process reads from one
52 of two variables then writes to the other?
53
54LB+poacquireonce+pooncerelease.litmus
55 Does a release-acquire pair suffice for the load-buffering
56 litmus test, where each process reads from one of two variables then
57 writes to the other?
58
59LB+poonceonces.litmus
60 As above, but with store-release replaced with WRITE_ONCE()
61 and load-acquire replaced with READ_ONCE().
62
63MP+onceassign+derefonce.litmus
64 As below, but with rcu_assign_pointer() and an rcu_dereference().
65
66MP+polocks.litmus
67 As below, but with the second access of the writer process
68 and the first access of reader process protected by a lock.
69
70MP+poonceonces.litmus
71 As below, but without the smp_rmb() and smp_wmb().
72
73MP+pooncerelease+poacquireonce.litmus
74 As below, but with a release-acquire chain.
75
76MP+porevlocks.litmus
77 As below, but with the first access of the writer process
78 and the second access of reader process protected by a lock.
79
80MP+wmbonceonce+rmbonceonce.litmus
81 Does a smp_wmb() (between the stores) and an smp_rmb() (between
82 the loads) suffice for the message-passing litmus test, where one
83 process writes data and then a flag, and the other process reads
84 the flag and then the data. (This is similar to the ISA2 tests,
85 but with two processes instead of three.)
86
87R+mbonceonces.litmus
88 This is the fully ordered (via smp_mb()) version of one of
89 the classic counterintuitive litmus tests that illustrates the
90 effects of store propagation delays.
91
92R+poonceonces.litmus
93 As above, but without the smp_mb() invocations.
94
95SB+mbonceonces.litmus
96 This is the fully ordered (again, via smp_mb() version of store
97 buffering, which forms the core of Dekker's mutual-exclusion
98 algorithm.
99
100SB+poonceonces.litmus
101 As above, but without the smp_mb() invocations.
102
103S+poonceonces.litmus
104 As below, but without the smp_wmb() and acquire load.
105
106S+wmbonceonce+poacquireonce.litmus
107 Can a smp_wmb(), instead of a release, and an acquire order
108 a prior store against a subsequent store?
109
110WRC+poonceonces+Once.litmus
111WRC+pooncerelease+rmbonceonce+Once.litmus
112 These two are members of an extension of the MP litmus-test class
113 in which the first write is moved to a separate process.
114
115Z6.0+pooncelock+pooncelock+pombonce.litmus
116 Is the ordering provided by a spin_unlock() and a subsequent
117 spin_lock() sufficient to make ordering apparent to accesses
118 by a process not holding the lock?
119
120Z6.0+pooncelock+poonceLock+pombonce.litmus
121 As above, but with smp_mb__after_spinlock() immediately
122 following the spin_lock().
123
124Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus
125 Is the ordering provided by a release-acquire chain sufficient
126 to make ordering apparent to accesses by a process that does
127 not participate in that release-acquire chain?
128
129A great many more litmus tests are available here:
130
131 https://github.com/paulmckrcu/litmus
diff --git a/tools/memory-model/litmus-tests/S+poonceonces.litmus b/tools/memory-model/litmus-tests/S+poonceonces.litmus
new file mode 100644
index 000000000000..8c9c2f81a580
--- /dev/null
+++ b/tools/memory-model/litmus-tests/S+poonceonces.litmus
@@ -0,0 +1,28 @@
1C S+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * Starting with a two-process release-acquire chain ordering P0()'s
7 * first store against P1()'s final load, if the smp_store_release()
8 * is replaced by WRITE_ONCE() and the smp_load_acquire() replaced by
9 * READ_ONCE(), is ordering preserved?
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 WRITE_ONCE(*x, 2);
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23
24 r0 = READ_ONCE(*y);
25 WRITE_ONCE(*x, 1);
26}
27
28exists (x=2 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus b/tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus
new file mode 100644
index 000000000000..c53350205d28
--- /dev/null
+++ b/tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus
@@ -0,0 +1,27 @@
1C S+wmbonceonce+poacquireonce
2
3(*
4 * Result: Never
5 *
6 * Can a smp_wmb(), instead of a release, and an acquire order a prior
7 * store against a subsequent store?
8 *)
9
10{}
11
12P0(int *x, int *y)
13{
14 WRITE_ONCE(*x, 2);
15 smp_wmb();
16 WRITE_ONCE(*y, 1);
17}
18
19P1(int *x, int *y)
20{
21 int r0;
22
23 r0 = smp_load_acquire(y);
24 WRITE_ONCE(*x, 1);
25}
26
27exists (x=2 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/SB+mbonceonces.litmus b/tools/memory-model/litmus-tests/SB+mbonceonces.litmus
new file mode 100644
index 000000000000..74b874ffa8da
--- /dev/null
+++ b/tools/memory-model/litmus-tests/SB+mbonceonces.litmus
@@ -0,0 +1,32 @@
1C SB+mbonceonces
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that full memory barriers suffice to
7 * order the store-buffering pattern, where each process writes to the
8 * variable that the preceding process reads. (Locking and RCU can also
9 * suffice, but not much else.)
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 int r0;
17
18 WRITE_ONCE(*x, 1);
19 smp_mb();
20 r0 = READ_ONCE(*y);
21}
22
23P1(int *x, int *y)
24{
25 int r0;
26
27 WRITE_ONCE(*y, 1);
28 smp_mb();
29 r0 = READ_ONCE(*x);
30}
31
32exists (0:r0=0 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/SB+poonceonces.litmus b/tools/memory-model/litmus-tests/SB+poonceonces.litmus
new file mode 100644
index 000000000000..10d550730b25
--- /dev/null
+++ b/tools/memory-model/litmus-tests/SB+poonceonces.litmus
@@ -0,0 +1,29 @@
1C SB+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * This litmus test demonstrates that at least some ordering is required
7 * to order the store-buffering pattern, where each process writes to the
8 * variable that the preceding process reads.
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 int r0;
16
17 WRITE_ONCE(*x, 1);
18 r0 = READ_ONCE(*y);
19}
20
21P1(int *x, int *y)
22{
23 int r0;
24
25 WRITE_ONCE(*y, 1);
26 r0 = READ_ONCE(*x);
27}
28
29exists (0:r0=0 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus b/tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus
new file mode 100644
index 000000000000..6a2bc12a1af1
--- /dev/null
+++ b/tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus
@@ -0,0 +1,35 @@
1C WRC+poonceonces+Once
2
3(*
4 * Result: Sometimes
5 *
6 * This litmus test is an extension of the message-passing pattern,
7 * where the first write is moved to a separate process. Note that this
8 * test has no ordering at all.
9 *)
10
11{}
12
13P0(int *x)
14{
15 WRITE_ONCE(*x, 1);
16}
17
18P1(int *x, int *y)
19{
20 int r0;
21
22 r0 = READ_ONCE(*x);
23 WRITE_ONCE(*y, 1);
24}
25
26P2(int *x, int *y)
27{
28 int r0;
29 int r1;
30
31 r0 = READ_ONCE(*y);
32 r1 = READ_ONCE(*x);
33}
34
35exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus b/tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus
new file mode 100644
index 000000000000..97fcbffde9a0
--- /dev/null
+++ b/tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus
@@ -0,0 +1,36 @@
1C WRC+pooncerelease+rmbonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * This litmus test is an extension of the message-passing pattern, where
7 * the first write is moved to a separate process. Because it features
8 * a release and a read memory barrier, it should be forbidden.
9 *)
10
11{}
12
13P0(int *x)
14{
15 WRITE_ONCE(*x, 1);
16}
17
18P1(int *x, int *y)
19{
20 int r0;
21
22 r0 = READ_ONCE(*x);
23 smp_store_release(y, 1);
24}
25
26P2(int *x, int *y)
27{
28 int r0;
29 int r1;
30
31 r0 = READ_ONCE(*y);
32 smp_rmb();
33 r1 = READ_ONCE(*x);
34}
35
36exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus
new file mode 100644
index 000000000000..415248fb6699
--- /dev/null
+++ b/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus
@@ -0,0 +1,42 @@
1C Z6.0+pooncelock+poonceLock+pombonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates how smp_mb__after_spinlock() may be
7 * used to ensure that accesses in different critical sections for a
8 * given lock running on different CPUs are nevertheless seen in order
9 * by CPUs not holding that lock.
10 *)
11
12{}
13
14P0(int *x, int *y, spinlock_t *mylock)
15{
16 spin_lock(mylock);
17 WRITE_ONCE(*x, 1);
18 WRITE_ONCE(*y, 1);
19 spin_unlock(mylock);
20}
21
22P1(int *y, int *z, spinlock_t *mylock)
23{
24 int r0;
25
26 spin_lock(mylock);
27 smp_mb__after_spinlock();
28 r0 = READ_ONCE(*y);
29 WRITE_ONCE(*z, 1);
30 spin_unlock(mylock);
31}
32
33P2(int *x, int *z)
34{
35 int r1;
36
37 WRITE_ONCE(*z, 2);
38 smp_mb();
39 r1 = READ_ONCE(*x);
40}
41
42exists (1:r0=1 /\ z=2 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus
new file mode 100644
index 000000000000..10a2aa04cd07
--- /dev/null
+++ b/tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus
@@ -0,0 +1,40 @@
1C Z6.0+pooncelock+pooncelock+pombonce
2
3(*
4 * Result: Sometimes
5 *
6 * This example demonstrates that a pair of accesses made by different
7 * processes each while holding a given lock will not necessarily be
8 * seen as ordered by a third process not holding that lock.
9 *)
10
11{}
12
13P0(int *x, int *y, spinlock_t *mylock)
14{
15 spin_lock(mylock);
16 WRITE_ONCE(*x, 1);
17 WRITE_ONCE(*y, 1);
18 spin_unlock(mylock);
19}
20
21P1(int *y, int *z, spinlock_t *mylock)
22{
23 int r0;
24
25 spin_lock(mylock);
26 r0 = READ_ONCE(*y);
27 WRITE_ONCE(*z, 1);
28 spin_unlock(mylock);
29}
30
31P2(int *x, int *z)
32{
33 int r1;
34
35 WRITE_ONCE(*z, 2);
36 smp_mb();
37 r1 = READ_ONCE(*x);
38}
39
40exists (1:r0=1 /\ z=2 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus
new file mode 100644
index 000000000000..a20fc3fafb53
--- /dev/null
+++ b/tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus
@@ -0,0 +1,42 @@
1C Z6.0+pooncerelease+poacquirerelease+mbonceonce
2
3(*
4 * Result: Sometimes
5 *
6 * This litmus test shows that a release-acquire chain, while sufficient
7 * when there is but one non-reads-from (AKA non-rf) link, does not suffice
8 * if there is more than one. Of the three processes, only P1() reads from
9 * P0's write, which means that there are two non-rf links: P1() to P2()
10 * is a write-to-write link (AKA a "coherence" or just "co" link) and P2()
11 * to P0() is a read-to-write link (AKA a "from-reads" or just "fr" link).
12 * When there are two or more non-rf links, you typically will need one
13 * full barrier for each non-rf link. (Exceptions include some cases
14 * involving locking.)
15 *)
16
17{}
18
19P0(int *x, int *y)
20{
21 WRITE_ONCE(*x, 1);
22 smp_store_release(y, 1);
23}
24
25P1(int *y, int *z)
26{
27 int r0;
28
29 r0 = smp_load_acquire(y);
30 smp_store_release(z, 1);
31}
32
33P2(int *x, int *z)
34{
35 int r1;
36
37 WRITE_ONCE(*z, 2);
38 smp_mb();
39 r1 = READ_ONCE(*x);
40}
41
42exists (1:r0=1 /\ z=2 /\ 2:r1=0)
diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
new file mode 100644
index 000000000000..ba4a4ec6d313
--- /dev/null
+++ b/tools/memory-model/lock.cat
@@ -0,0 +1,99 @@
1// SPDX-License-Identifier: GPL-2.0+
2(*
3 * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
4 * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>
5 *)
6
7(* Generate coherence orders and handle lock operations *)
8
9include "cross.cat"
10
11(* From lock reads to their partner lock writes *)
12let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)
13let rmw = rmw | lk-rmw
14
15(*
16 * A paired LKR must always see an unlocked value; spin_lock() calls nested
17 * inside a critical section (for the same lock) always deadlock.
18 *)
19empty ([LKW] ; po-loc ; [domain(lk-rmw)]) \ (po-loc ; [UL] ; po-loc)
20 as lock-nest
21
22(* The litmus test is invalid if an LKW event is not part of an RMW pair *)
23flag ~empty LKW \ range(lk-rmw) as unpaired-LKW
24
25(* This will be allowed if we implement spin_is_locked() *)
26flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
27
28(* There should be no R or W accesses to spinlocks *)
29let ALL-LOCKS = LKR | LKW | UL | LF
30flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
31
32(* The final value of a spinlock should not be tested *)
33flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final
34
35
36(*
37 * Put lock operations in their appropriate classes, but leave UL out of W
38 * until after the co relation has been generated.
39 *)
40let R = R | LKR | LF
41let W = W | LKW
42
43let Release = Release | UL
44let Acquire = Acquire | LKR
45
46
47(* Match LKW events to their corresponding UL events *)
48let critical = ([LKW] ; po-loc ; [UL]) \ (po-loc ; [LKW | UL] ; po-loc)
49
50flag ~empty UL \ range(critical) as unmatched-unlock
51
52(* Allow up to one unmatched LKW per location; more must deadlock *)
53let UNMATCHED-LKW = LKW \ domain(critical)
54empty ([UNMATCHED-LKW] ; loc ; [UNMATCHED-LKW]) \ id as unmatched-locks
55
56
57(* rfi for LF events: link each LKW to the LF events in its critical section *)
58let rfi-lf = ([LKW] ; po-loc ; [LF]) \ ([LKW] ; po-loc ; [UL] ; po-loc)
59
60(* rfe for LF events *)
61let all-possible-rfe-lf =
62 (*
63 * Given an LF event r, compute the possible rfe edges for that event
64 * (all those starting from LKW events in other threads),
65 * and then convert that relation to a set of single-edge relations.
66 *)
67 let possible-rfe-lf r =
68 let pair-to-relation p = p ++ 0
69 in map pair-to-relation ((LKW * {r}) & loc & ext)
70 (* Do this for each LF event r that isn't in rfi-lf *)
71 in map possible-rfe-lf (LF \ range(rfi-lf))
72
73(* Generate all rf relations for LF events *)
74with rfe-lf from cross(all-possible-rfe-lf)
75let rf = rf | rfi-lf | rfe-lf
76
77
78(* Generate all co relations, including LKW events but not UL *)
79let co0 = co0 | ([IW] ; loc ; [LKW]) |
80 (([LKW] ; loc ; [UNMATCHED-LKW]) \ [UNMATCHED-LKW])
81include "cos-opt.cat"
82let W = W | UL
83let M = R | W
84
85(* Merge UL events into co *)
86let co = (co | critical | (critical^-1 ; co))+
87let coe = co & ext
88let coi = co & int
89
90(* Merge LKR events into rf *)
91let rf = rf | ([IW | UL] ; singlestep(co) ; lk-rmw^-1)
92let rfe = rf & ext
93let rfi = rf & int
94
95let fr = rf^-1 ; co
96let fre = fr & ext
97let fri = fr & int
98
99show co,rf,fr
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index e6acc281dd37..f76d9914686a 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -31,11 +31,11 @@ INCLUDES := -I$(srctree)/tools/include \
31 -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \ 31 -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \
32 -I$(srctree)/tools/objtool/arch/$(ARCH)/include 32 -I$(srctree)/tools/objtool/arch/$(ARCH)/include
33WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed 33WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed
34CFLAGS += -Wall -Werror $(WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 34CFLAGS += -Werror $(WARNINGS) $(HOSTCFLAGS) -g $(INCLUDES)
35LDFLAGS += -lelf $(LIBSUBCMD) 35LDFLAGS += -lelf $(LIBSUBCMD) $(HOSTLDFLAGS)
36 36
37# Allow old libelf to be used: 37# Allow old libelf to be used:
38elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr) 38elfshdr := $(shell echo '$(pound)include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)
39CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED) 39CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
40 40
41AWK = awk 41AWK = awk
diff --git a/tools/objtool/arch/x86/include/asm/insn.h b/tools/objtool/arch/x86/include/asm/insn.h
index b3e32b010ab1..c2c01f84df75 100644
--- a/tools/objtool/arch/x86/include/asm/insn.h
+++ b/tools/objtool/arch/x86/include/asm/insn.h
@@ -208,4 +208,22 @@ static inline int insn_offset_immediate(struct insn *insn)
208 return insn_offset_displacement(insn) + insn->displacement.nbytes; 208 return insn_offset_displacement(insn) + insn->displacement.nbytes;
209} 209}
210 210
211#define POP_SS_OPCODE 0x1f
212#define MOV_SREG_OPCODE 0x8e
213
214/*
215 * Intel SDM Vol.3A 6.8.3 states;
216 * "Any single-step trap that would be delivered following the MOV to SS
217 * instruction or POP to SS instruction (because EFLAGS.TF is 1) is
218 * suppressed."
219 * This function returns true if @insn is MOV SS or POP SS. On these
220 * instructions, single stepping is suppressed.
221 */
222static inline int insn_masking_exception(struct insn *insn)
223{
224 return insn->opcode.bytes[0] == POP_SS_OPCODE ||
225 (insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
226 X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
227}
228
211#endif /* _ASM_X86_INSN_H */ 229#endif /* _ASM_X86_INSN_H */
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 92b6a2c21631..3a31b238f885 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -59,6 +59,31 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
59 return next; 59 return next;
60} 60}
61 61
62static struct instruction *next_insn_same_func(struct objtool_file *file,
63 struct instruction *insn)
64{
65 struct instruction *next = list_next_entry(insn, list);
66 struct symbol *func = insn->func;
67
68 if (!func)
69 return NULL;
70
71 if (&next->list != &file->insn_list && next->func == func)
72 return next;
73
74 /* Check if we're already in the subfunction: */
75 if (func == func->cfunc)
76 return NULL;
77
78 /* Move to the subfunction: */
79 return find_insn(file, func->cfunc->sec, func->cfunc->offset);
80}
81
82#define func_for_each_insn_all(file, func, insn) \
83 for (insn = find_insn(file, func->sec, func->offset); \
84 insn; \
85 insn = next_insn_same_func(file, insn))
86
62#define func_for_each_insn(file, func, insn) \ 87#define func_for_each_insn(file, func, insn) \
63 for (insn = find_insn(file, func->sec, func->offset); \ 88 for (insn = find_insn(file, func->sec, func->offset); \
64 insn && &insn->list != &file->insn_list && \ 89 insn && &insn->list != &file->insn_list && \
@@ -149,10 +174,14 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
149 if (!strcmp(func->name, global_noreturns[i])) 174 if (!strcmp(func->name, global_noreturns[i]))
150 return 1; 175 return 1;
151 176
152 if (!func->sec) 177 if (!func->len)
153 return 0; 178 return 0;
154 179
155 func_for_each_insn(file, func, insn) { 180 insn = find_insn(file, func->sec, func->offset);
181 if (!insn->func)
182 return 0;
183
184 func_for_each_insn_all(file, func, insn) {
156 empty = false; 185 empty = false;
157 186
158 if (insn->type == INSN_RETURN) 187 if (insn->type == INSN_RETURN)
@@ -167,35 +196,28 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
167 * case, the function's dead-end status depends on whether the target 196 * case, the function's dead-end status depends on whether the target
168 * of the sibling call returns. 197 * of the sibling call returns.
169 */ 198 */
170 func_for_each_insn(file, func, insn) { 199 func_for_each_insn_all(file, func, insn) {
171 if (insn->sec != func->sec ||
172 insn->offset >= func->offset + func->len)
173 break;
174
175 if (insn->type == INSN_JUMP_UNCONDITIONAL) { 200 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
176 struct instruction *dest = insn->jump_dest; 201 struct instruction *dest = insn->jump_dest;
177 struct symbol *dest_func;
178 202
179 if (!dest) 203 if (!dest)
180 /* sibling call to another file */ 204 /* sibling call to another file */
181 return 0; 205 return 0;
182 206
183 if (dest->sec != func->sec || 207 if (dest->func && dest->func->pfunc != insn->func->pfunc) {
184 dest->offset < func->offset ||
185 dest->offset >= func->offset + func->len) {
186 /* local sibling call */
187 dest_func = find_symbol_by_offset(dest->sec,
188 dest->offset);
189 if (!dest_func)
190 continue;
191 208
209 /* local sibling call */
192 if (recursion == 5) { 210 if (recursion == 5) {
193 WARN_FUNC("infinite recursion (objtool bug!)", 211 /*
194 dest->sec, dest->offset); 212 * Infinite recursion: two functions
195 return -1; 213 * have sibling calls to each other.
214 * This is a very rare case. It means
215 * they aren't dead ends.
216 */
217 return 0;
196 } 218 }
197 219
198 return __dead_end_function(file, dest_func, 220 return __dead_end_function(file, dest->func,
199 recursion + 1); 221 recursion + 1);
200 } 222 }
201 } 223 }
@@ -422,7 +444,7 @@ static void add_ignores(struct objtool_file *file)
422 if (!ignore_func(file, func)) 444 if (!ignore_func(file, func))
423 continue; 445 continue;
424 446
425 func_for_each_insn(file, func, insn) 447 func_for_each_insn_all(file, func, insn)
426 insn->ignore = true; 448 insn->ignore = true;
427 } 449 }
428 } 450 }
@@ -782,30 +804,35 @@ out:
782 return ret; 804 return ret;
783} 805}
784 806
785static int add_switch_table(struct objtool_file *file, struct symbol *func, 807static int add_switch_table(struct objtool_file *file, struct instruction *insn,
786 struct instruction *insn, struct rela *table, 808 struct rela *table, struct rela *next_table)
787 struct rela *next_table)
788{ 809{
789 struct rela *rela = table; 810 struct rela *rela = table;
790 struct instruction *alt_insn; 811 struct instruction *alt_insn;
791 struct alternative *alt; 812 struct alternative *alt;
813 struct symbol *pfunc = insn->func->pfunc;
814 unsigned int prev_offset = 0;
792 815
793 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) { 816 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
794 if (rela == next_table) 817 if (rela == next_table)
795 break; 818 break;
796 819
797 if (rela->sym->sec != insn->sec || 820 /* Make sure the switch table entries are consecutive: */
798 rela->addend <= func->offset || 821 if (prev_offset && rela->offset != prev_offset + 8)
799 rela->addend >= func->offset + func->len)
800 break; 822 break;
801 823
802 alt_insn = find_insn(file, insn->sec, rela->addend); 824 /* Detect function pointers from contiguous objects: */
803 if (!alt_insn) { 825 if (rela->sym->sec == pfunc->sec &&
804 WARN("%s: can't find instruction at %s+0x%x", 826 rela->addend == pfunc->offset)
805 file->rodata->rela->name, insn->sec->name, 827 break;
806 rela->addend); 828
807 return -1; 829 alt_insn = find_insn(file, rela->sym->sec, rela->addend);
808 } 830 if (!alt_insn)
831 break;
832
833 /* Make sure the jmp dest is in the function or subfunction: */
834 if (alt_insn->func->pfunc != pfunc)
835 break;
809 836
810 alt = malloc(sizeof(*alt)); 837 alt = malloc(sizeof(*alt));
811 if (!alt) { 838 if (!alt) {
@@ -815,6 +842,13 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func,
815 842
816 alt->insn = alt_insn; 843 alt->insn = alt_insn;
817 list_add_tail(&alt->list, &insn->alts); 844 list_add_tail(&alt->list, &insn->alts);
845 prev_offset = rela->offset;
846 }
847
848 if (!prev_offset) {
849 WARN_FUNC("can't find switch jump table",
850 insn->sec, insn->offset);
851 return -1;
818 } 852 }
819 853
820 return 0; 854 return 0;
@@ -869,40 +903,21 @@ static struct rela *find_switch_table(struct objtool_file *file,
869{ 903{
870 struct rela *text_rela, *rodata_rela; 904 struct rela *text_rela, *rodata_rela;
871 struct instruction *orig_insn = insn; 905 struct instruction *orig_insn = insn;
906 unsigned long table_offset;
872 907
873 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
874 if (text_rela && text_rela->sym == file->rodata->sym) {
875 /* case 1 */
876 rodata_rela = find_rela_by_dest(file->rodata,
877 text_rela->addend);
878 if (rodata_rela)
879 return rodata_rela;
880
881 /* case 2 */
882 rodata_rela = find_rela_by_dest(file->rodata,
883 text_rela->addend + 4);
884 if (!rodata_rela)
885 return NULL;
886
887 file->ignore_unreachables = true;
888 return rodata_rela;
889 }
890
891 /* case 3 */
892 /* 908 /*
893 * Backward search using the @first_jump_src links, these help avoid 909 * Backward search using the @first_jump_src links, these help avoid
894 * much of the 'in between' code. Which avoids us getting confused by 910 * much of the 'in between' code. Which avoids us getting confused by
895 * it. 911 * it.
896 */ 912 */
897 for (insn = list_prev_entry(insn, list); 913 for (;
898
899 &insn->list != &file->insn_list && 914 &insn->list != &file->insn_list &&
900 insn->sec == func->sec && 915 insn->sec == func->sec &&
901 insn->offset >= func->offset; 916 insn->offset >= func->offset;
902 917
903 insn = insn->first_jump_src ?: list_prev_entry(insn, list)) { 918 insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
904 919
905 if (insn->type == INSN_JUMP_DYNAMIC) 920 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
906 break; 921 break;
907 922
908 /* allow small jumps within the range */ 923 /* allow small jumps within the range */
@@ -918,18 +933,29 @@ static struct rela *find_switch_table(struct objtool_file *file,
918 if (!text_rela || text_rela->sym != file->rodata->sym) 933 if (!text_rela || text_rela->sym != file->rodata->sym)
919 continue; 934 continue;
920 935
936 table_offset = text_rela->addend;
937 if (text_rela->type == R_X86_64_PC32)
938 table_offset += 4;
939
921 /* 940 /*
922 * Make sure the .rodata address isn't associated with a 941 * Make sure the .rodata address isn't associated with a
923 * symbol. gcc jump tables are anonymous data. 942 * symbol. gcc jump tables are anonymous data.
924 */ 943 */
925 if (find_symbol_containing(file->rodata, text_rela->addend)) 944 if (find_symbol_containing(file->rodata, table_offset))
926 continue; 945 continue;
927 946
928 rodata_rela = find_rela_by_dest(file->rodata, text_rela->addend); 947 rodata_rela = find_rela_by_dest(file->rodata, table_offset);
929 if (!rodata_rela) 948 if (rodata_rela) {
930 continue; 949 /*
950 * Use of RIP-relative switch jumps is quite rare, and
951 * indicates a rare GCC quirk/bug which can leave dead
952 * code behind.
953 */
954 if (text_rela->type == R_X86_64_PC32)
955 file->ignore_unreachables = true;
931 956
932 return rodata_rela; 957 return rodata_rela;
958 }
933 } 959 }
934 960
935 return NULL; 961 return NULL;
@@ -943,7 +969,7 @@ static int add_func_switch_tables(struct objtool_file *file,
943 struct rela *rela, *prev_rela = NULL; 969 struct rela *rela, *prev_rela = NULL;
944 int ret; 970 int ret;
945 971
946 func_for_each_insn(file, func, insn) { 972 func_for_each_insn_all(file, func, insn) {
947 if (!last) 973 if (!last)
948 last = insn; 974 last = insn;
949 975
@@ -974,8 +1000,7 @@ static int add_func_switch_tables(struct objtool_file *file,
974 * the beginning of another switch table in the same function. 1000 * the beginning of another switch table in the same function.
975 */ 1001 */
976 if (prev_jump) { 1002 if (prev_jump) {
977 ret = add_switch_table(file, func, prev_jump, prev_rela, 1003 ret = add_switch_table(file, prev_jump, prev_rela, rela);
978 rela);
979 if (ret) 1004 if (ret)
980 return ret; 1005 return ret;
981 } 1006 }
@@ -985,7 +1010,7 @@ static int add_func_switch_tables(struct objtool_file *file,
985 } 1010 }
986 1011
987 if (prev_jump) { 1012 if (prev_jump) {
988 ret = add_switch_table(file, func, prev_jump, prev_rela, NULL); 1013 ret = add_switch_table(file, prev_jump, prev_rela, NULL);
989 if (ret) 1014 if (ret)
990 return ret; 1015 return ret;
991 } 1016 }
@@ -1386,6 +1411,17 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1386 state->vals[op->dest.reg].offset = -state->stack_size; 1411 state->vals[op->dest.reg].offset = -state->stack_size;
1387 } 1412 }
1388 1413
1414 else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
1415 cfa->base == CFI_BP) {
1416
1417 /*
1418 * mov %rbp, %rsp
1419 *
1420 * Restore the original stack pointer (Clang).
1421 */
1422 state->stack_size = -state->regs[CFI_BP].offset;
1423 }
1424
1389 else if (op->dest.reg == cfa->base) { 1425 else if (op->dest.reg == cfa->base) {
1390 1426
1391 /* mov %reg, %rsp */ 1427 /* mov %reg, %rsp */
@@ -1738,15 +1774,13 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1738 while (1) { 1774 while (1) {
1739 next_insn = next_insn_same_sec(file, insn); 1775 next_insn = next_insn_same_sec(file, insn);
1740 1776
1741 1777 if (file->c_file && func && insn->func && func != insn->func->pfunc) {
1742 if (file->c_file && func && insn->func && func != insn->func) {
1743 WARN("%s() falls through to next function %s()", 1778 WARN("%s() falls through to next function %s()",
1744 func->name, insn->func->name); 1779 func->name, insn->func->name);
1745 return 1; 1780 return 1;
1746 } 1781 }
1747 1782
1748 if (insn->func) 1783 func = insn->func ? insn->func->pfunc : NULL;
1749 func = insn->func;
1750 1784
1751 if (func && insn->ignore) { 1785 if (func && insn->ignore) {
1752 WARN_FUNC("BUG: why am I validating an ignored function?", 1786 WARN_FUNC("BUG: why am I validating an ignored function?",
@@ -1767,7 +1801,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1767 1801
1768 i = insn; 1802 i = insn;
1769 save_insn = NULL; 1803 save_insn = NULL;
1770 func_for_each_insn_continue_reverse(file, func, i) { 1804 func_for_each_insn_continue_reverse(file, insn->func, i) {
1771 if (i->save) { 1805 if (i->save) {
1772 save_insn = i; 1806 save_insn = i;
1773 break; 1807 break;
@@ -1854,7 +1888,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1854 case INSN_JUMP_UNCONDITIONAL: 1888 case INSN_JUMP_UNCONDITIONAL:
1855 if (insn->jump_dest && 1889 if (insn->jump_dest &&
1856 (!func || !insn->jump_dest->func || 1890 (!func || !insn->jump_dest->func ||
1857 func == insn->jump_dest->func)) { 1891 insn->jump_dest->func->pfunc == func)) {
1858 ret = validate_branch(file, insn->jump_dest, 1892 ret = validate_branch(file, insn->jump_dest,
1859 state); 1893 state);
1860 if (ret) 1894 if (ret)
@@ -2049,7 +2083,7 @@ static int validate_functions(struct objtool_file *file)
2049 2083
2050 for_each_sec(file, sec) { 2084 for_each_sec(file, sec) {
2051 list_for_each_entry(func, &sec->symbol_list, list) { 2085 list_for_each_entry(func, &sec->symbol_list, list) {
2052 if (func->type != STT_FUNC) 2086 if (func->type != STT_FUNC || func->pfunc != func)
2053 continue; 2087 continue;
2054 2088
2055 insn = find_insn(file, sec, func->offset); 2089 insn = find_insn(file, sec, func->offset);
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index c1c338661699..4e60e105583e 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -79,6 +79,19 @@ struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
79 return NULL; 79 return NULL;
80} 80}
81 81
82struct symbol *find_symbol_by_name(struct elf *elf, const char *name)
83{
84 struct section *sec;
85 struct symbol *sym;
86
87 list_for_each_entry(sec, &elf->sections, list)
88 list_for_each_entry(sym, &sec->symbol_list, list)
89 if (!strcmp(sym->name, name))
90 return sym;
91
92 return NULL;
93}
94
82struct symbol *find_symbol_containing(struct section *sec, unsigned long offset) 95struct symbol *find_symbol_containing(struct section *sec, unsigned long offset)
83{ 96{
84 struct symbol *sym; 97 struct symbol *sym;
@@ -203,10 +216,11 @@ static int read_sections(struct elf *elf)
203 216
204static int read_symbols(struct elf *elf) 217static int read_symbols(struct elf *elf)
205{ 218{
206 struct section *symtab; 219 struct section *symtab, *sec;
207 struct symbol *sym; 220 struct symbol *sym, *pfunc;
208 struct list_head *entry, *tmp; 221 struct list_head *entry, *tmp;
209 int symbols_nr, i; 222 int symbols_nr, i;
223 char *coldstr;
210 224
211 symtab = find_section_by_name(elf, ".symtab"); 225 symtab = find_section_by_name(elf, ".symtab");
212 if (!symtab) { 226 if (!symtab) {
@@ -281,6 +295,30 @@ static int read_symbols(struct elf *elf)
281 hash_add(sym->sec->symbol_hash, &sym->hash, sym->idx); 295 hash_add(sym->sec->symbol_hash, &sym->hash, sym->idx);
282 } 296 }
283 297
298 /* Create parent/child links for any cold subfunctions */
299 list_for_each_entry(sec, &elf->sections, list) {
300 list_for_each_entry(sym, &sec->symbol_list, list) {
301 if (sym->type != STT_FUNC)
302 continue;
303 sym->pfunc = sym->cfunc = sym;
304 coldstr = strstr(sym->name, ".cold.");
305 if (coldstr) {
306 coldstr[0] = '\0';
307 pfunc = find_symbol_by_name(elf, sym->name);
308 coldstr[0] = '.';
309
310 if (!pfunc) {
311 WARN("%s(): can't find parent function",
312 sym->name);
313 goto err;
314 }
315
316 sym->pfunc = pfunc;
317 pfunc->cfunc = sym;
318 }
319 }
320 }
321
284 return 0; 322 return 0;
285 323
286err: 324err:
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index d86e2ff14466..de5cd2ddded9 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -61,6 +61,7 @@ struct symbol {
61 unsigned char bind, type; 61 unsigned char bind, type;
62 unsigned long offset; 62 unsigned long offset;
63 unsigned int len; 63 unsigned int len;
64 struct symbol *pfunc, *cfunc;
64}; 65};
65 66
66struct rela { 67struct rela {
@@ -86,6 +87,7 @@ struct elf {
86struct elf *elf_open(const char *name, int flags); 87struct elf *elf_open(const char *name, int flags);
87struct section *find_section_by_name(struct elf *elf, const char *name); 88struct section *find_section_by_name(struct elf *elf, const char *name);
88struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 89struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
90struct symbol *find_symbol_by_name(struct elf *elf, const char *name);
89struct symbol *find_symbol_containing(struct section *sec, unsigned long offset); 91struct symbol *find_symbol_containing(struct section *sec, unsigned long offset);
90struct rela *find_rela_by_dest(struct section *sec, unsigned long offset); 92struct rela *find_rela_by_dest(struct section *sec, unsigned long offset);
91struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset, 93struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index c635eab6af54..749cc6055dac 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -21,7 +21,7 @@ If there is no debug info in the object, then annotated assembly is displayed.
21OPTIONS 21OPTIONS
22------- 22-------
23-i:: 23-i::
24--input=:: 24--input=<file>::
25 Input file name. (default: perf.data unless stdin is a fifo) 25 Input file name. (default: perf.data unless stdin is a fifo)
26 26
27-d:: 27-d::
@@ -55,6 +55,9 @@ OPTIONS
55--vmlinux=<file>:: 55--vmlinux=<file>::
56 vmlinux pathname. 56 vmlinux pathname.
57 57
58--ignore-vmlinux::
59 Ignore vmlinux files.
60
58-m:: 61-m::
59--modules:: 62--modules::
60 Load module symbols. WARNING: use only with -k and LIVE kernel. 63 Load module symbols. WARNING: use only with -k and LIVE kernel.
@@ -69,7 +72,9 @@ OPTIONS
69 72
70--stdio:: Use the stdio interface. 73--stdio:: Use the stdio interface.
71 74
72--stdio-color:: 75--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
76
77--stdio-color=<mode>::
73 'always', 'never' or 'auto', allowing configuring color output 78 'always', 'never' or 'auto', allowing configuring color output
74 via the command line, in addition to via "color.ui" .perfconfig. 79 via the command line, in addition to via "color.ui" .perfconfig.
75 Use '--stdio-color always' to generate color even when redirecting 80 Use '--stdio-color always' to generate color even when redirecting
@@ -84,7 +89,7 @@ OPTIONS
84--gtk:: Use the GTK interface. 89--gtk:: Use the GTK interface.
85 90
86-C:: 91-C::
87--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 92--cpu=<cpu>:: Only report samples for the list of CPUs provided. Multiple CPUs can
88 be provided as a comma-separated list with no space: 0,1. Ranges of 93 be provided as a comma-separated list with no space: 0,1. Ranges of
89 CPUs are specified with -: 0-2. Default is to report samples on all 94 CPUs are specified with -: 0-2. Default is to report samples on all
90 CPUs. 95 CPUs.
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt
index 822414235170..095aebdc5bb7 100644
--- a/tools/perf/Documentation/perf-c2c.txt
+++ b/tools/perf/Documentation/perf-c2c.txt
@@ -116,7 +116,7 @@ and calls standard perf record command.
116Following perf record options are configured by default: 116Following perf record options are configured by default:
117(check perf record man page for details) 117(check perf record man page for details)
118 118
119 -W,-d,--sample-cpu 119 -W,-d,--phys-data,--sample-cpu
120 120
121Unless specified otherwise with '-e' option, following events are monitored by 121Unless specified otherwise with '-e' option, following events are monitored by
122default: 122default:
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 5b4fff3adc4b..32f4a898e3f2 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -334,6 +334,11 @@ annotate.*::
334 334
335 99.93 │ mov %eax,%eax 335 99.93 │ mov %eax,%eax
336 336
337 annotate.offset_level::
338 Default is '1', meaning just jump targets will have offsets show right beside
339 the instruction. When set to '2' 'call' instructions will also have its offsets
340 shown, 3 or higher will show offsets for all instructions.
341
337hist.*:: 342hist.*::
338 hist.percentage:: 343 hist.percentage::
339 This option control the way to calculate overhead of filtered entries - 344 This option control the way to calculate overhead of filtered entries -
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
index 90bb4aabe4f8..c87180764829 100644
--- a/tools/perf/Documentation/perf-data.txt
+++ b/tools/perf/Documentation/perf-data.txt
@@ -1,5 +1,5 @@
1perf-data(1) 1perf-data(1)
2============== 2============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt
index 721a447f046e..b80c84307dc9 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -1,5 +1,5 @@
1perf-ftrace(1) 1perf-ftrace(1)
2============= 2==============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-kallsyms.txt b/tools/perf/Documentation/perf-kallsyms.txt
index cf9f4040ea5c..f3c620951f6e 100644
--- a/tools/perf/Documentation/perf-kallsyms.txt
+++ b/tools/perf/Documentation/perf-kallsyms.txt
@@ -1,5 +1,5 @@
1perf-kallsyms(1) 1perf-kallsyms(1)
2============== 2================
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 479fc3261a50..85b8ac695c87 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -25,6 +25,10 @@ OPTIONS
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data unless stdin is a fifo) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28-f::
29--force::
30 Don't do ownership validation
31
28-v:: 32-v::
29--verbose:: 33--verbose::
30 Be more verbose. (show symbol address, etc) 34 Be more verbose. (show symbol address, etc)
@@ -61,7 +65,7 @@ OPTIONS
61 default, but this option shows live (currently allocated) pages 65 default, but this option shows live (currently allocated) pages
62 instead. (This option works with --page option only) 66 instead. (This option works with --page option only)
63 67
64--time:: 68--time=<start>,<stop>::
65 Only analyze samples within given time window: <start>,<stop>. Times 69 Only analyze samples within given time window: <start>,<stop>. Times
66 have the format seconds.microseconds. If start is not given (i.e., time 70 have the format seconds.microseconds. If start is not given (i.e., time
67 string is ',x.y') then analysis starts at the beginning of the file. If 71 string is ',x.y') then analysis starts at the beginning of the file. If
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index e2a897ae3596..2549c34a7895 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -141,7 +141,13 @@ on the first memory controller on socket 0 of a Intel Xeon system
141 141
142Each memory controller has its own PMU. Measuring the complete system 142Each memory controller has its own PMU. Measuring the complete system
143bandwidth would require specifying all imc PMUs (see perf list output), 143bandwidth would require specifying all imc PMUs (see perf list output),
144and adding the values together. 144and adding the values together. To simplify creation of multiple events,
145prefix and glob matching is supported in the PMU name, and the prefix
146'uncore_' is also ignored when performing the match. So the command above
147can be expanded to all memory controllers by using the syntaxes:
148
149 perf stat -C 0 -a imc/cas_count_read/,imc/cas_count_write/ -I 1000 ...
150 perf stat -C 0 -a *imc*/cas_count_read/,*imc*/cas_count_write/ -I 1000 ...
145 151
146This example measures the combined core power every second 152This example measures the combined core power every second
147 153
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 4be08a1e3f8d..f8d2167cf3e7 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -28,25 +28,46 @@ OPTIONS
28<command>...:: 28<command>...::
29 Any command you can specify in a shell. 29 Any command you can specify in a shell.
30 30
31-i::
32--input=<file>::
33 Input file name.
34
35-f::
36--force::
37 Don't do ownership validation
38
31-t:: 39-t::
32--type=:: 40--type=<type>::
33 Select the memory operation type: load or store (default: load,store) 41 Select the memory operation type: load or store (default: load,store)
34 42
35-D:: 43-D::
36--dump-raw-samples=:: 44--dump-raw-samples::
37 Dump the raw decoded samples on the screen in a format that is easy to parse with 45 Dump the raw decoded samples on the screen in a format that is easy to parse with
38 one sample per line. 46 one sample per line.
39 47
40-x:: 48-x::
41--field-separator:: 49--field-separator=<separator>::
42 Specify the field separator used when dump raw samples (-D option). By default, 50 Specify the field separator used when dump raw samples (-D option). By default,
43 The separator is the space character. 51 The separator is the space character.
44 52
45-C:: 53-C::
46--cpu-list:: 54--cpu=<cpu>::
47 Restrict dump of raw samples to those provided via this option. Note that the same 55 Monitor only on the list of CPUs provided. Multiple CPUs can be provided as a
48 option can be passed in record mode. It will be interpreted the same way as perf 56 comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. Default
49 record. 57 is to monitor all CPUS.
58-U::
59--hide-unresolved::
60 Only display entries resolved to a symbol.
61
62-p::
63--phys-data::
64 Record/Report sample physical addresses
65
66RECORD OPTIONS
67--------------
68-e::
69--event <event>::
70 Event selector. Use 'perf mem record -e list' to list available events.
50 71
51-K:: 72-K::
52--all-kernel:: 73--all-kernel::
@@ -56,12 +77,15 @@ OPTIONS
56--all-user:: 77--all-user::
57 Configure all used events to run in user space. 78 Configure all used events to run in user space.
58 79
59--ldload:: 80-v::
81--verbose::
82 Be more verbose (show counter open errors, etc)
83
84--ldlat <n>::
60 Specify desired latency for loads event. 85 Specify desired latency for loads event.
61 86
62-p:: 87In addition, for report all perf report options are valid, and for record
63--phys-data:: 88all perf record options.
64 Record/Report sample physical addresses
65 89
66SEE ALSO 90SEE ALSO
67-------- 91--------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 3eea6de35a38..cc37b3a4be76 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -191,9 +191,16 @@ OPTIONS
191-i:: 191-i::
192--no-inherit:: 192--no-inherit::
193 Child tasks do not inherit counters. 193 Child tasks do not inherit counters.
194
194-F:: 195-F::
195--freq=:: 196--freq=::
196 Profile at this frequency. 197 Profile at this frequency. Use 'max' to use the currently maximum
198 allowed frequency, i.e. the value in the kernel.perf_event_max_sample_rate
199 sysctl. Will throttle down to the currently maximum allowed frequency.
200 See --strict-freq.
201
202--strict-freq::
203 Fail if the specified frequency can't be used.
197 204
198-m:: 205-m::
199--mmap-pages=:: 206--mmap-pages=::
@@ -308,7 +315,11 @@ can be provided. Each cgroup is applied to the corresponding event, i.e., first
308to first event, second cgroup to second event and so on. It is possible to provide 315to first event, second cgroup to second event and so on. It is possible to provide
309an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have 316an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
310corresponding events, i.e., they always refer to events defined earlier on the command 317corresponding events, i.e., they always refer to events defined earlier on the command
311line. 318line. If the user wants to track multiple events for a specific cgroup, the user can
319use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
320
321If wanting to monitor, say, 'cycles' for a cgroup and also for system wide, this
322command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
312 323
313-b:: 324-b::
314--branch-any:: 325--branch-any::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 907e505b6309..917e36fde6d8 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -80,6 +80,7 @@ OPTIONS
80 - comm: command (name) of the task which can be read via /proc/<pid>/comm 80 - comm: command (name) of the task which can be read via /proc/<pid>/comm
81 - pid: command and tid of the task 81 - pid: command and tid of the task
82 - dso: name of library or module executed at the time of sample 82 - dso: name of library or module executed at the time of sample
83 - dso_size: size of library or module executed at the time of sample
83 - symbol: name of function executed at the time of sample 84 - symbol: name of function executed at the time of sample
84 - symbol_size: size of function executed at the time of sample 85 - symbol_size: size of function executed at the time of sample
85 - parent: name of function matched to the parent regex filter. Unmatched 86 - parent: name of function matched to the parent regex filter. Unmatched
@@ -296,6 +297,9 @@ OPTIONS
296--vmlinux=<file>:: 297--vmlinux=<file>::
297 vmlinux pathname 298 vmlinux pathname
298 299
300--ignore-vmlinux::
301 Ignore vmlinux files.
302
299--kallsyms=<file>:: 303--kallsyms=<file>::
300 kallsyms pathname 304 kallsyms pathname
301 305
@@ -354,7 +358,8 @@ OPTIONS
354 Path to objdump binary. 358 Path to objdump binary.
355 359
356--group:: 360--group::
357 Show event group information together. 361 Show event group information together. It forces group output also
362 if there are no groups defined in data file.
358 363
359--demangle:: 364--demangle::
360 Demangle symbol names to human readable form. It's enabled by default, 365 Demangle symbol names to human readable form. It's enabled by default,
@@ -367,7 +372,7 @@ OPTIONS
367 Use the data addresses of samples in addition to instruction addresses 372 Use the data addresses of samples in addition to instruction addresses
368 to build the histograms. To generate meaningful output, the perf.data 373 to build the histograms. To generate meaningful output, the perf.data
369 file must have been obtained using perf record -d -W and using a 374 file must have been obtained using perf record -d -W and using a
370 special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See 375 special event -e cpu/mem-loads/p or -e cpu/mem-stores/p. See
371 'perf mem' for simpler access. 376 'perf mem' for simpler access.
372 377
373--percent-limit:: 378--percent-limit::
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index c7e50f263887..63f938b887dd 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -1,5 +1,5 @@
1perf-sched(1) 1perf-sched(1)
2============== 2=============
3 3
4NAME 4NAME
5---- 5----
@@ -104,8 +104,8 @@ OPTIONS for 'perf sched timehist'
104 kallsyms pathname 104 kallsyms pathname
105 105
106-g:: 106-g::
107--no-call-graph:: 107--call-graph::
108 Do not display call chains if present. 108 Display call chains if present (default on).
109 109
110--max-stack:: 110--max-stack::
111 Maximum number of functions to display in backtrace, default 5. 111 Maximum number of functions to display in backtrace, default 5.
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index 142606c0ec9c..5a1f68122f50 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -1,5 +1,5 @@
1perf-script-perl(1) 1perf-script-perl(1)
2================== 2===================
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 7730c1d2b5d3..afdafe2110a1 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -228,14 +228,15 @@ OPTIONS
228 For sample events it's possible to display misc field with -F +misc option, 228 For sample events it's possible to display misc field with -F +misc option,
229 following letters are displayed for each bit: 229 following letters are displayed for each bit:
230 230
231 PERF_RECORD_MISC_KERNEL K 231 PERF_RECORD_MISC_KERNEL K
232 PERF_RECORD_MISC_USER U 232 PERF_RECORD_MISC_USER U
233 PERF_RECORD_MISC_HYPERVISOR H 233 PERF_RECORD_MISC_HYPERVISOR H
234 PERF_RECORD_MISC_GUEST_KERNEL G 234 PERF_RECORD_MISC_GUEST_KERNEL G
235 PERF_RECORD_MISC_GUEST_USER g 235 PERF_RECORD_MISC_GUEST_USER g
236 PERF_RECORD_MISC_MMAP_DATA* M 236 PERF_RECORD_MISC_MMAP_DATA* M
237 PERF_RECORD_MISC_COMM_EXEC E 237 PERF_RECORD_MISC_COMM_EXEC E
238 PERF_RECORD_MISC_SWITCH_OUT S 238 PERF_RECORD_MISC_SWITCH_OUT S
239 PERF_RECORD_MISC_SWITCH_OUT_PREEMPT Sp
239 240
240 $ perf script -F +misc ... 241 $ perf script -F +misc ...
241 sched-messaging 1414 K 28690.636582: 4590 cycles ... 242 sched-messaging 1414 K 28690.636582: 4590 cycles ...
@@ -303,6 +304,9 @@ OPTIONS
303--show-lost-events 304--show-lost-events
304 Display lost events i.e. events of type PERF_RECORD_LOST. 305 Display lost events i.e. events of type PERF_RECORD_LOST.
305 306
307--show-round-events
308 Display finished round events i.e. events of type PERF_RECORD_FINISHED_ROUND.
309
306--demangle:: 310--demangle::
307 Demangle symbol names to human readable form. It's enabled by default, 311 Demangle symbol names to human readable form. It's enabled by default,
308 disable with --no-demangle. 312 disable with --no-demangle.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 823fce7674bb..e6c3b4e555c2 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -49,6 +49,13 @@ report::
49 parameters are defined by corresponding entries in 49 parameters are defined by corresponding entries in
50 /sys/bus/event_source/devices/<pmu>/format/* 50 /sys/bus/event_source/devices/<pmu>/format/*
51 51
52 Note that the last two syntaxes support prefix and glob matching in
53 the PMU name to simplify creation of events accross multiple instances
54 of the same type of PMU in large systems (e.g. memory controller PMUs).
55 Multiple PMU instances are typical for uncore PMUs, so the prefix
56 'uncore_' is also ignored when performing this match.
57
58
52-i:: 59-i::
53--no-inherit:: 60--no-inherit::
54 child tasks do not inherit counters 61 child tasks do not inherit counters
@@ -118,7 +125,11 @@ can be provided. Each cgroup is applied to the corresponding event, i.e., first
118to first event, second cgroup to second event and so on. It is possible to provide 125to first event, second cgroup to second event and so on. It is possible to provide
119an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have 126an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
120corresponding events, i.e., they always refer to events defined earlier on the command 127corresponding events, i.e., they always refer to events defined earlier on the command
121line. 128line. If the user wants to track multiple events for a specific cgroup, the user can
129use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
130
131If wanting to monitor, say, 'cycles' for a cgroup and also for system wide, this
132command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
122 133
123-o file:: 134-o file::
124--output file:: 135--output file::
@@ -142,10 +153,20 @@ perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- m
142 153
143-I msecs:: 154-I msecs::
144--interval-print msecs:: 155--interval-print msecs::
145Print count deltas every N milliseconds (minimum: 10ms) 156Print count deltas every N milliseconds (minimum: 1ms)
146The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution. 157The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution.
147 example: 'perf stat -I 1000 -e cycles -a sleep 5' 158 example: 'perf stat -I 1000 -e cycles -a sleep 5'
148 159
160--interval-count times::
161Print count deltas for fixed number of times.
162This option should be used together with "-I" option.
163 example: 'perf stat -I 1000 --interval-count 2 -e cycles -a'
164
165--timeout msecs::
166Stop the 'perf stat' session and print count deltas after N milliseconds (minimum: 10 ms).
167This option is not supported with the "-I" option.
168 example: 'perf stat --time 2000 -e cycles -a'
169
149--metric-only:: 170--metric-only::
150Only print computed metrics. Print them in a single line. 171Only print computed metrics. Print them in a single line.
151Don't show any raw values. Not supported with --per-thread. 172Don't show any raw values. Not supported with --per-thread.
@@ -246,6 +267,16 @@ taskset.
246--no-merge:: 267--no-merge::
247Do not merge results from same PMUs. 268Do not merge results from same PMUs.
248 269
270When multiple events are created from a single event specification,
271stat will, by default, aggregate the event counts and show the result
272in a single row. This option disables that behavior and shows
273the individual events and counts.
274
275Multiple events are created from a single event specification when:
2761. Prefix or glob matching is used for the PMU name.
2772. Aliases, which are listed immediately after the Kernel PMU events
278 by perf list, are used.
279
249--smi-cost:: 280--smi-cost::
250Measure SMI cost if msr/aperf/ and msr/smi/ events are supported. 281Measure SMI cost if msr/aperf/ and msr/smi/ events are supported.
251 282
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 8a32cc77bead..114fda12aa49 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -55,7 +55,9 @@ Default is to monitor all CPUS.
55 55
56-F <freq>:: 56-F <freq>::
57--freq=<freq>:: 57--freq=<freq>::
58 Profile at this frequency. 58 Profile at this frequency. Use 'max' to use the currently maximum
59 allowed frequency, i.e. the value in the kernel.perf_event_max_sample_rate
60 sysctl.
59 61
60-i:: 62-i::
61--inherit:: 63--inherit::
@@ -65,6 +67,9 @@ Default is to monitor all CPUS.
65--vmlinux=<path>:: 67--vmlinux=<path>::
66 Path to vmlinux. Required for annotation functionality. 68 Path to vmlinux. Required for annotation functionality.
67 69
70--ignore-vmlinux::
71 Ignore vmlinux files.
72
68-m <pages>:: 73-m <pages>::
69--mmap-pages=<pages>:: 74--mmap-pages=<pages>::
70 Number of mmap data pages (must be a power of two) or size 75 Number of mmap data pages (must be a power of two) or size
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 33a88e984e66..115db9e06ecd 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -63,6 +63,31 @@ filter out the startup phase of the program, which is often very different.
63--uid=:: 63--uid=::
64 Record events in threads owned by uid. Name or number. 64 Record events in threads owned by uid. Name or number.
65 65
66-G::
67--cgroup::
68 Record events in threads in a cgroup.
69
70 Look for cgroups to set at the /sys/fs/cgroup/perf_event directory, then
71 remove the /sys/fs/cgroup/perf_event/ part and try:
72
73 perf trace -G A -e sched:*switch
74
75 Will set all raw_syscalls:sys_{enter,exit}, pgfault, vfs_getname, etc
76 _and_ sched:sched_switch to the 'A' cgroup, while:
77
78 perf trace -e sched:*switch -G A
79
80 will only set the sched:sched_switch event to the 'A' cgroup, all the
81 other events (raw_syscalls:sys_{enter,exit}, etc are left "without"
82 a cgroup (on the root cgroup, sys wide, etc).
83
84 Multiple cgroups:
85
86 perf trace -G A -e sched:*switch -G B
87
88 the syscall ones go to the 'A' cgroup, the sched:sched_switch goes
89 to the 'B' cgroup.
90
66--filter-pids=:: 91--filter-pids=::
67 Filter out events for these pids and for 'trace' itself (comma separated list). 92 Filter out events for these pids and for 'trace' itself (comma separated list).
68 93
@@ -92,6 +117,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
92--sched:: 117--sched::
93 Accrue thread runtime and provide a summary at the end of the session. 118 Accrue thread runtime and provide a summary at the end of the session.
94 119
120--failure::
121 Show only syscalls that failed, i.e. that returned < 0.
122
95-i:: 123-i::
96--input:: 124--input::
97 Process events from a given perf data file. 125 Process events from a given perf data file.
diff --git a/tools/perf/Documentation/perf-version.txt b/tools/perf/Documentation/perf-version.txt
new file mode 100644
index 000000000000..e207b7cfca26
--- /dev/null
+++ b/tools/perf/Documentation/perf-version.txt
@@ -0,0 +1,24 @@
1perf-version(1)
2===============
3
4NAME
5----
6perf-version - display the version of perf binary
7
8SYNOPSIS
9--------
10'perf version' [--build-options]
11
12DESCRIPTION
13-----------
14With no options given, the 'perf version' prints the perf version
15on the standard output.
16
17If the option '--build-options' is given, then the status of
18compiled-in libraries are printed on the standard output.
19
20OPTIONS
21-------
22--build-options::
23 Prints the status of compiled-in libraries on the
24 standard output.
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index f7d85e89a98a..d00f0d51cab8 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -485,10 +485,5 @@ in pmu-tools parser. This allows to read perf.data from python and dump it.
485quipper 485quipper
486 486
487The quipper C++ parser is available at 487The quipper C++ parser is available at
488https://chromium.googlesource.com/chromiumos/platform2 488http://github.com/google/perf_data_converter/tree/master/src/quipper
489 489
490It is under the chromiumos-wide-profiling/ subdirectory. This library can
491convert a perf data file to a protobuf and vice versa.
492
493Unfortunately this parser tends to be many versions behind and may not be able
494to parse data files generated by recent perf.
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 0dfdaa9fa81e..ae7dc46e8f8a 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -27,6 +27,8 @@ NO_SYSCALL_TABLE := 1
27# Additional ARCH settings for ppc 27# Additional ARCH settings for ppc
28ifeq ($(SRCARCH),powerpc) 28ifeq ($(SRCARCH),powerpc)
29 NO_PERF_REGS := 0 29 NO_PERF_REGS := 0
30 NO_SYSCALL_TABLE := 0
31 CFLAGS += -I$(OUTPUT)arch/powerpc/include/generated
30 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 32 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
31endif 33endif
32 34
@@ -66,14 +68,14 @@ ifeq ($(NO_PERF_REGS),0)
66endif 68endif
67 69
68ifneq ($(NO_SYSCALL_TABLE),1) 70ifneq ($(NO_SYSCALL_TABLE),1)
69 CFLAGS += -DHAVE_SYSCALL_TABLE 71 CFLAGS += -DHAVE_SYSCALL_TABLE_SUPPORT
70endif 72endif
71 73
72# So far there's only x86 and arm libdw unwind support merged in perf. 74# So far there's only x86 and arm libdw unwind support merged in perf.
73# Disable it on all other architectures in case libdw unwind 75# Disable it on all other architectures in case libdw unwind
74# support is detected in system. Add supported architectures 76# support is detected in system. Add supported architectures
75# to the check. 77# to the check.
76ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc s390)) 78ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390))
77 NO_LIBDW_DWARF_UNWIND := 1 79 NO_LIBDW_DWARF_UNWIND := 1
78endif 80endif
79 81
@@ -344,12 +346,16 @@ else
344 ifneq ($(feature-dwarf_getlocations), 1) 346 ifneq ($(feature-dwarf_getlocations), 1)
345 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); 347 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
346 else 348 else
347 CFLAGS += -DHAVE_DWARF_GETLOCATIONS 349 CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT
348 endif # dwarf_getlocations 350 endif # dwarf_getlocations
349 endif # Dwarf support 351 endif # Dwarf support
350 endif # libelf support 352 endif # libelf support
351endif # NO_LIBELF 353endif # NO_LIBELF
352 354
355ifeq ($(feature-glibc), 1)
356 CFLAGS += -DHAVE_GLIBC_SUPPORT
357endif
358
353ifdef NO_DWARF 359ifdef NO_DWARF
354 NO_LIBDW_DWARF_UNWIND := 1 360 NO_LIBDW_DWARF_UNWIND := 1
355endif 361endif
@@ -633,6 +639,7 @@ else
633 else 639 else
634 LDFLAGS += $(PERL_EMBED_LDFLAGS) 640 LDFLAGS += $(PERL_EMBED_LDFLAGS)
635 EXTLIBS += $(PERL_EMBED_LIBADD) 641 EXTLIBS += $(PERL_EMBED_LIBADD)
642 CFLAGS += -DHAVE_LIBPERL_SUPPORT
636 $(call detected,CONFIG_LIBPERL) 643 $(call detected,CONFIG_LIBPERL)
637 endif 644 endif
638endif 645endif
@@ -666,25 +673,11 @@ else
666 ifneq ($(feature-libpython), 1) 673 ifneq ($(feature-libpython), 1)
667 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) 674 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
668 else 675 else
669 ifneq ($(feature-libpython-version), 1) 676 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
670 $(warning Python 3 is not yet supported; please set) 677 EXTLIBS += $(PYTHON_EMBED_LIBADD)
671 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 678 LANG_BINDINGS += $(obj-perf)python/perf.so
672 $(warning If you also have Python 2 installed, then) 679 CFLAGS += -DHAVE_LIBPYTHON_SUPPORT
673 $(warning try something like:) 680 $(call detected,CONFIG_LIBPYTHON)
674 $(warning $(and ,))
675 $(warning $(and ,) make PYTHON=python2)
676 $(warning $(and ,))
677 $(warning Otherwise, disable Python support entirely:)
678 $(warning $(and ,))
679 $(warning $(and ,) make NO_LIBPYTHON=1)
680 $(warning $(and ,))
681 $(error $(and ,))
682 else
683 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
684 EXTLIBS += $(PYTHON_EMBED_LIBADD)
685 LANG_BINDINGS += $(obj-perf)python/perf.so
686 $(call detected,CONFIG_LIBPYTHON)
687 endif
688 endif 681 endif
689 endif 682 endif
690 endif 683 endif
@@ -854,7 +847,7 @@ ifndef NO_JVMTI
854 ifeq ($(feature-jvmti), 1) 847 ifeq ($(feature-jvmti), 1)
855 $(call detected_var,JDIR) 848 $(call detected_var,JDIR)
856 else 849 else
857 $(warning No openjdk development package found, please install JDK package) 850 $(warning No openjdk development package found, please install JDK package, e.g. openjdk-8-jdk, java-1.8.0-openjdk-devel)
858 NO_JVMTI := 1 851 NO_JVMTI := 1
859 endif 852 endif
860endif 853endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 012328038594..83e453de36f8 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -296,7 +296,7 @@ PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
296PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ 296PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
297export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP 297export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
298 298
299python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 299python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so
300 300
301PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 301PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
302PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 302PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
@@ -364,7 +364,8 @@ LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive
364 364
365ifeq ($(USE_CLANG), 1) 365ifeq ($(USE_CLANG), 1)
366 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization 366 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
367 LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a)) 367 CLANGLIBS_NOEXT_LIST = $(foreach l,$(CLANGLIBS_LIST),$(shell $(LLVM_CONFIG) --libdir)/libclang$(l))
368 LIBCLANG = $(foreach l,$(CLANGLIBS_NOEXT_LIST),$(wildcard $(l).a $(l).so))
368 LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group 369 LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
369endif 370endif
370 371
@@ -473,7 +474,7 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_D
473 $(PYTHON_WORD) util/setup.py \ 474 $(PYTHON_WORD) util/setup.py \
474 --quiet build_ext; \ 475 --quiet build_ext; \
475 mkdir -p $(OUTPUT)python && \ 476 mkdir -p $(OUTPUT)python && \
476 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 477 cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/
477 478
478please_set_SHELL_PATH_to_a_more_modern_shell: 479please_set_SHELL_PATH_to_a_more_modern_shell:
479 $(Q)$$(:) 480 $(Q)$$(:)
@@ -708,15 +709,15 @@ TAG_FILES= ../../include/uapi/linux/perf_event.h
708 709
709TAGS: 710TAGS:
710 $(QUIET_GEN)$(RM) TAGS; \ 711 $(QUIET_GEN)$(RM) TAGS; \
711 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs etags -a $(TAG_FILES) 712 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs etags -a $(TAG_FILES)
712 713
713tags: 714tags:
714 $(QUIET_GEN)$(RM) tags; \ 715 $(QUIET_GEN)$(RM) tags; \
715 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs ctags -a $(TAG_FILES) 716 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs ctags -a $(TAG_FILES)
716 717
717cscope: 718cscope:
718 $(QUIET_GEN)$(RM) cscope*; \ 719 $(QUIET_GEN)$(RM) cscope*; \
719 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) 720 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs cscope -b $(TAG_FILES)
720 721
721### Testing rules 722### Testing rules
722 723
diff --git a/tools/perf/arch/arm/include/arch-tests.h b/tools/perf/arch/arm/include/arch-tests.h
new file mode 100644
index 000000000000..90ec4c8cb880
--- /dev/null
+++ b/tools/perf/arch/arm/include/arch-tests.h
@@ -0,0 +1,12 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef ARCH_TESTS_H
3#define ARCH_TESTS_H
4
5#ifdef HAVE_DWARF_UNWIND_SUPPORT
6struct thread;
7struct perf_sample;
8#endif
9
10extern struct test arch_tests[];
11
12#endif
diff --git a/tools/perf/arch/arm/tests/Build b/tools/perf/arch/arm/tests/Build
index b30eff9bcc83..883c57ff0c08 100644
--- a/tools/perf/arch/arm/tests/Build
+++ b/tools/perf/arch/arm/tests/Build
@@ -1,2 +1,4 @@
1libperf-y += regs_load.o 1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o 2libperf-y += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/arm/tests/arch-tests.c b/tools/perf/arch/arm/tests/arch-tests.c
new file mode 100644
index 000000000000..5b1543c98022
--- /dev/null
+++ b/tools/perf/arch/arm/tests/arch-tests.c
@@ -0,0 +1,16 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <string.h>
3#include "tests/tests.h"
4#include "arch-tests.h"
5
6struct test arch_tests[] = {
7#ifdef HAVE_DWARF_UNWIND_SUPPORT
8 {
9 .desc = "DWARF unwind",
10 .func = test__dwarf_unwind,
11 },
12#endif
13 {
14 .func = NULL,
15 },
16};
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
index 2323581b157d..1ce6bdbda561 100644
--- a/tools/perf/arch/arm/util/auxtrace.c
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -1,18 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved. 3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 5 */
17 6
18#include <stdbool.h> 7#include <stdbool.h>
@@ -68,7 +57,7 @@ struct auxtrace_record
68 bool found_spe = false; 57 bool found_spe = false;
69 static struct perf_pmu **arm_spe_pmus = NULL; 58 static struct perf_pmu **arm_spe_pmus = NULL;
70 static int nr_spes = 0; 59 static int nr_spes = 0;
71 int i; 60 int i = 0;
72 61
73 if (!evlist) 62 if (!evlist)
74 return NULL; 63 return NULL;
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index fbfc055d3f4d..2f595cd73da6 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -1,18 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved. 3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 5 */
17 6
18#include <api/fs/fs.h> 7#include <api/fs/fs.h>
@@ -298,12 +287,17 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
298{ 287{
299 int i; 288 int i;
300 int etmv3 = 0, etmv4 = 0; 289 int etmv3 = 0, etmv4 = 0;
301 const struct cpu_map *cpus = evlist->cpus; 290 struct cpu_map *event_cpus = evlist->cpus;
291 struct cpu_map *online_cpus = cpu_map__new(NULL);
302 292
303 /* cpu map is not empty, we have specific CPUs to work with */ 293 /* cpu map is not empty, we have specific CPUs to work with */
304 if (!cpu_map__empty(cpus)) { 294 if (!cpu_map__empty(event_cpus)) {
305 for (i = 0; i < cpu_map__nr(cpus); i++) { 295 for (i = 0; i < cpu__max_cpu(); i++) {
306 if (cs_etm_is_etmv4(itr, cpus->map[i])) 296 if (!cpu_map__has(event_cpus, i) ||
297 !cpu_map__has(online_cpus, i))
298 continue;
299
300 if (cs_etm_is_etmv4(itr, i))
307 etmv4++; 301 etmv4++;
308 else 302 else
309 etmv3++; 303 etmv3++;
@@ -311,6 +305,9 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
311 } else { 305 } else {
312 /* get configuration for all CPUs in the system */ 306 /* get configuration for all CPUs in the system */
313 for (i = 0; i < cpu__max_cpu(); i++) { 307 for (i = 0; i < cpu__max_cpu(); i++) {
308 if (!cpu_map__has(online_cpus, i))
309 continue;
310
314 if (cs_etm_is_etmv4(itr, i)) 311 if (cs_etm_is_etmv4(itr, i))
315 etmv4++; 312 etmv4++;
316 else 313 else
@@ -318,6 +315,8 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
318 } 315 }
319 } 316 }
320 317
318 cpu_map__put(online_cpus);
319
321 return (CS_ETM_HEADER_SIZE + 320 return (CS_ETM_HEADER_SIZE +
322 (etmv4 * CS_ETMV4_PRIV_SIZE) + 321 (etmv4 * CS_ETMV4_PRIV_SIZE) +
323 (etmv3 * CS_ETMV3_PRIV_SIZE)); 322 (etmv3 * CS_ETMV3_PRIV_SIZE));
@@ -447,7 +446,9 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
447 int i; 446 int i;
448 u32 offset; 447 u32 offset;
449 u64 nr_cpu, type; 448 u64 nr_cpu, type;
450 const struct cpu_map *cpus = session->evlist->cpus; 449 struct cpu_map *cpu_map;
450 struct cpu_map *event_cpus = session->evlist->cpus;
451 struct cpu_map *online_cpus = cpu_map__new(NULL);
451 struct cs_etm_recording *ptr = 452 struct cs_etm_recording *ptr =
452 container_of(itr, struct cs_etm_recording, itr); 453 container_of(itr, struct cs_etm_recording, itr);
453 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 454 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
@@ -458,8 +459,21 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
458 if (!session->evlist->nr_mmaps) 459 if (!session->evlist->nr_mmaps)
459 return -EINVAL; 460 return -EINVAL;
460 461
461 /* If the cpu_map is empty all CPUs are involved */ 462 /* If the cpu_map is empty all online CPUs are involved */
462 nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus); 463 if (cpu_map__empty(event_cpus)) {
464 cpu_map = online_cpus;
465 } else {
466 /* Make sure all specified CPUs are online */
467 for (i = 0; i < cpu_map__nr(event_cpus); i++) {
468 if (cpu_map__has(event_cpus, i) &&
469 !cpu_map__has(online_cpus, i))
470 return -EINVAL;
471 }
472
473 cpu_map = event_cpus;
474 }
475
476 nr_cpu = cpu_map__nr(cpu_map);
463 /* Get PMU type as dynamically assigned by the core */ 477 /* Get PMU type as dynamically assigned by the core */
464 type = cs_etm_pmu->type; 478 type = cs_etm_pmu->type;
465 479
@@ -472,15 +486,11 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
472 486
473 offset = CS_ETM_SNAPSHOT + 1; 487 offset = CS_ETM_SNAPSHOT + 1;
474 488
475 /* cpu map is not empty, we have specific CPUs to work with */ 489 for (i = 0; i < cpu__max_cpu() && offset < priv_size; i++)
476 if (!cpu_map__empty(cpus)) { 490 if (cpu_map__has(cpu_map, i))
477 for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
478 cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
479 } else {
480 /* get configuration for all CPUs in the system */
481 for (i = 0; i < cpu__max_cpu(); i++)
482 cs_etm_get_metadata(i, &offset, itr, info); 491 cs_etm_get_metadata(i, &offset, itr, info);
483 } 492
493 cpu_map__put(online_cpus);
484 494
485 return 0; 495 return 0;
486} 496}
diff --git a/tools/perf/arch/arm/util/cs-etm.h b/tools/perf/arch/arm/util/cs-etm.h
index 5256741be549..1a12e64f5127 100644
--- a/tools/perf/arch/arm/util/cs-etm.h
+++ b/tools/perf/arch/arm/util/cs-etm.h
@@ -1,18 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved. 3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 5 */
17 6
18#ifndef INCLUDE__PERF_CS_ETM_H__ 7#ifndef INCLUDE__PERF_CS_ETM_H__
diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
index ac4dffc807b8..e047571e6080 100644
--- a/tools/perf/arch/arm/util/pmu.c
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -1,18 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved. 3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 5 */
17 6
18#include <string.h> 7#include <string.h>
diff --git a/tools/perf/arch/arm64/include/arch-tests.h b/tools/perf/arch/arm64/include/arch-tests.h
new file mode 100644
index 000000000000..90ec4c8cb880
--- /dev/null
+++ b/tools/perf/arch/arm64/include/arch-tests.h
@@ -0,0 +1,12 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef ARCH_TESTS_H
3#define ARCH_TESTS_H
4
5#ifdef HAVE_DWARF_UNWIND_SUPPORT
6struct thread;
7struct perf_sample;
8#endif
9
10extern struct test arch_tests[];
11
12#endif
diff --git a/tools/perf/arch/arm64/tests/Build b/tools/perf/arch/arm64/tests/Build
index b30eff9bcc83..883c57ff0c08 100644
--- a/tools/perf/arch/arm64/tests/Build
+++ b/tools/perf/arch/arm64/tests/Build
@@ -1,2 +1,4 @@
1libperf-y += regs_load.o 1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o 2libperf-y += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/arm64/tests/arch-tests.c b/tools/perf/arch/arm64/tests/arch-tests.c
new file mode 100644
index 000000000000..5b1543c98022
--- /dev/null
+++ b/tools/perf/arch/arm64/tests/arch-tests.c
@@ -0,0 +1,16 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <string.h>
3#include "tests/tests.h"
4#include "arch-tests.h"
5
6struct test arch_tests[] = {
7#ifdef HAVE_DWARF_UNWIND_SUPPORT
8 {
9 .desc = "DWARF unwind",
10 .func = test__dwarf_unwind,
11 },
12#endif
13 {
14 .func = NULL,
15 },
16};
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index c0b8dfef98ba..68f8a8eb3ad0 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -2,6 +2,7 @@ libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-$(CONFIG_DWARF) += dwarf-regs.o 3libperf-$(CONFIG_DWARF) += dwarf-regs.o
4libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 4libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
5libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
5 6
6libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ 7libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
7 ../../arm/util/auxtrace.o \ 8 ../../arm/util/auxtrace.o \
diff --git a/tools/perf/arch/arm64/util/unwind-libdw.c b/tools/perf/arch/arm64/util/unwind-libdw.c
new file mode 100644
index 000000000000..7623d85e77f3
--- /dev/null
+++ b/tools/perf/arch/arm64/util/unwind-libdw.c
@@ -0,0 +1,60 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <elfutils/libdwfl.h>
3#include "../../util/unwind-libdw.h"
4#include "../../util/perf_regs.h"
5#include "../../util/event.h"
6
7bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
8{
9 struct unwind_info *ui = arg;
10 struct regs_dump *user_regs = &ui->sample->user_regs;
11 Dwarf_Word dwarf_regs[PERF_REG_ARM64_MAX], dwarf_pc;
12
13#define REG(r) ({ \
14 Dwarf_Word val = 0; \
15 perf_reg_value(&val, user_regs, PERF_REG_ARM64_##r); \
16 val; \
17})
18
19 dwarf_regs[0] = REG(X0);
20 dwarf_regs[1] = REG(X1);
21 dwarf_regs[2] = REG(X2);
22 dwarf_regs[3] = REG(X3);
23 dwarf_regs[4] = REG(X4);
24 dwarf_regs[5] = REG(X5);
25 dwarf_regs[6] = REG(X6);
26 dwarf_regs[7] = REG(X7);
27 dwarf_regs[8] = REG(X8);
28 dwarf_regs[9] = REG(X9);
29 dwarf_regs[10] = REG(X10);
30 dwarf_regs[11] = REG(X11);
31 dwarf_regs[12] = REG(X12);
32 dwarf_regs[13] = REG(X13);
33 dwarf_regs[14] = REG(X14);
34 dwarf_regs[15] = REG(X15);
35 dwarf_regs[16] = REG(X16);
36 dwarf_regs[17] = REG(X17);
37 dwarf_regs[18] = REG(X18);
38 dwarf_regs[19] = REG(X19);
39 dwarf_regs[20] = REG(X20);
40 dwarf_regs[21] = REG(X21);
41 dwarf_regs[22] = REG(X22);
42 dwarf_regs[23] = REG(X23);
43 dwarf_regs[24] = REG(X24);
44 dwarf_regs[25] = REG(X25);
45 dwarf_regs[26] = REG(X26);
46 dwarf_regs[27] = REG(X27);
47 dwarf_regs[28] = REG(X28);
48 dwarf_regs[29] = REG(X29);
49 dwarf_regs[30] = REG(LR);
50 dwarf_regs[31] = REG(SP);
51
52 if (!dwfl_thread_state_registers(thread, 0, PERF_REG_ARM64_MAX,
53 dwarf_regs))
54 return false;
55
56 dwarf_pc = REG(PC);
57 dwfl_thread_state_register_pc(thread, dwarf_pc);
58
59 return true;
60}
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 42dab7c8f508..a111239df182 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -6,3 +6,28 @@ endif
6HAVE_KVM_STAT_SUPPORT := 1 6HAVE_KVM_STAT_SUPPORT := 1
7PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 7PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
8PERF_HAVE_JITDUMP := 1 8PERF_HAVE_JITDUMP := 1
9
10#
11# Syscall table generation for perf
12#
13
14out := $(OUTPUT)arch/powerpc/include/generated/asm
15header32 := $(out)/syscalls_32.c
16header64 := $(out)/syscalls_64.c
17sysdef := $(srctree)/tools/arch/powerpc/include/uapi/asm/unistd.h
18sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls/
19systbl := $(sysprf)/mksyscalltbl
20
21# Create output directory if not already present
22_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
23
24$(header64): $(sysdef) $(systbl)
25 $(Q)$(SHELL) '$(systbl)' '64' '$(CC)' $(sysdef) > $@
26
27$(header32): $(sysdef) $(systbl)
28 $(Q)$(SHELL) '$(systbl)' '32' '$(CC)' $(sysdef) > $@
29
30clean::
31 $(call QUIET_CLEAN, powerpc) $(RM) $(header32) $(header64)
32
33archheaders: $(header32) $(header64)
diff --git a/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl b/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
new file mode 100755
index 000000000000..ef52e1dd694b
--- /dev/null
+++ b/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
@@ -0,0 +1,37 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Generate system call table for perf. Derived from
5# s390 script.
6#
7# Copyright IBM Corp. 2017
8# Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
9# Changed by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
10
11wordsize=$1
12gcc=$2
13input=$3
14
15if ! test -r $input; then
16 echo "Could not read input file" >&2
17 exit 1
18fi
19
20create_table()
21{
22 local wordsize=$1
23 local max_nr
24
25 echo "static const char *syscalltbl_powerpc_${wordsize}[] = {"
26 while read sc nr; do
27 printf '\t[%d] = "%s",\n' $nr $sc
28 max_nr=$nr
29 done
30 echo '};'
31 echo "#define SYSCALLTBL_POWERPC_${wordsize}_MAX_ID $max_nr"
32}
33
34$gcc -m${wordsize} -E -dM -x c $input \
35 |sed -ne 's/^#define __NR_//p' \
36 |sort -t' ' -k2 -nu \
37 |create_table ${wordsize}
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 8c72b44444cb..cee4e2f7c057 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -1,6 +1,113 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3 3
4static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
5 struct map_symbol *ms)
6{
7 char *endptr, *tok, *name;
8 struct map *map = ms->map;
9 struct addr_map_symbol target = {
10 .map = map,
11 };
12
13 tok = strchr(ops->raw, ',');
14 if (!tok)
15 return -1;
16
17 ops->target.addr = strtoull(tok + 1, &endptr, 16);
18
19 name = strchr(endptr, '<');
20 if (name == NULL)
21 return -1;
22
23 name++;
24
25 if (arch->objdump.skip_functions_char &&
26 strchr(name, arch->objdump.skip_functions_char))
27 return -1;
28
29 tok = strchr(name, '>');
30 if (tok == NULL)
31 return -1;
32
33 *tok = '\0';
34 ops->target.name = strdup(name);
35 *tok = '>';
36
37 if (ops->target.name == NULL)
38 return -1;
39 target.addr = map__objdump_2mem(map, ops->target.addr);
40
41 if (map_groups__find_ams(&target) == 0 &&
42 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
43 ops->target.sym = target.sym;
44
45 return 0;
46}
47
48static int call__scnprintf(struct ins *ins, char *bf, size_t size,
49 struct ins_operands *ops);
50
51static struct ins_ops s390_call_ops = {
52 .parse = s390_call__parse,
53 .scnprintf = call__scnprintf,
54};
55
56static int s390_mov__parse(struct arch *arch __maybe_unused,
57 struct ins_operands *ops,
58 struct map_symbol *ms __maybe_unused)
59{
60 char *s = strchr(ops->raw, ','), *target, *endptr;
61
62 if (s == NULL)
63 return -1;
64
65 *s = '\0';
66 ops->source.raw = strdup(ops->raw);
67 *s = ',';
68
69 if (ops->source.raw == NULL)
70 return -1;
71
72 target = ++s;
73 ops->target.raw = strdup(target);
74 if (ops->target.raw == NULL)
75 goto out_free_source;
76
77 ops->target.addr = strtoull(target, &endptr, 16);
78 if (endptr == target)
79 goto out_free_target;
80
81 s = strchr(endptr, '<');
82 if (s == NULL)
83 goto out_free_target;
84 endptr = strchr(s + 1, '>');
85 if (endptr == NULL)
86 goto out_free_target;
87
88 *endptr = '\0';
89 ops->target.name = strdup(s + 1);
90 *endptr = '>';
91 if (ops->target.name == NULL)
92 goto out_free_target;
93
94 return 0;
95
96out_free_target:
97 zfree(&ops->target.raw);
98out_free_source:
99 zfree(&ops->source.raw);
100 return -1;
101}
102
103static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
104 struct ins_operands *ops);
105
106static struct ins_ops s390_mov_ops = {
107 .parse = s390_mov__parse,
108 .scnprintf = mov__scnprintf,
109};
110
4static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name) 111static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
5{ 112{
6 struct ins_ops *ops = NULL; 113 struct ins_ops *ops = NULL;
@@ -14,21 +121,54 @@ static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *na
14 if (!strcmp(name, "bras") || 121 if (!strcmp(name, "bras") ||
15 !strcmp(name, "brasl") || 122 !strcmp(name, "brasl") ||
16 !strcmp(name, "basr")) 123 !strcmp(name, "basr"))
17 ops = &call_ops; 124 ops = &s390_call_ops;
18 if (!strcmp(name, "br")) 125 if (!strcmp(name, "br"))
19 ops = &ret_ops; 126 ops = &ret_ops;
127 /* override load/store relative to PC */
128 if (!strcmp(name, "lrl") ||
129 !strcmp(name, "lgrl") ||
130 !strcmp(name, "lgfrl") ||
131 !strcmp(name, "llgfrl") ||
132 !strcmp(name, "strl") ||
133 !strcmp(name, "stgrl"))
134 ops = &s390_mov_ops;
20 135
21 if (ops) 136 if (ops)
22 arch__associate_ins_ops(arch, name, ops); 137 arch__associate_ins_ops(arch, name, ops);
23 return ops; 138 return ops;
24} 139}
25 140
141static int s390__cpuid_parse(struct arch *arch, char *cpuid)
142{
143 unsigned int family;
144 char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
145 int ret;
146
147 /*
148 * cpuid string format:
149 * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
150 */
151 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
152 model, cpumf_v, cpumf_a);
153 if (ret >= 2) {
154 arch->family = family;
155 arch->model = 0;
156 return 0;
157 }
158
159 return -1;
160}
161
26static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused) 162static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
27{ 163{
164 int err = 0;
165
28 if (!arch->initialized) { 166 if (!arch->initialized) {
29 arch->initialized = true; 167 arch->initialized = true;
30 arch->associate_instruction_ops = s390__associate_ins_ops; 168 arch->associate_instruction_ops = s390__associate_ins_ops;
169 if (cpuid)
170 err = s390__cpuid_parse(arch, cpuid);
31 } 171 }
32 172
33 return 0; 173 return err;
34} 174}
diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c
index 6cb48e4cffd9..3afe8256eff2 100644
--- a/tools/perf/arch/s390/util/auxtrace.c
+++ b/tools/perf/arch/s390/util/auxtrace.c
@@ -87,6 +87,7 @@ struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
87 struct perf_evsel *pos; 87 struct perf_evsel *pos;
88 int diagnose = 0; 88 int diagnose = 0;
89 89
90 *err = 0;
90 if (evlist->nr_entries == 0) 91 if (evlist->nr_entries == 0)
91 return NULL; 92 return NULL;
92 93
diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 9fa6c3e5782c..163b92f33998 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * Implementation of get_cpuid(). 2 * Implementation of get_cpuid().
3 * 3 *
4 * Copyright 2014 IBM Corp. 4 * Copyright IBM Corp. 2014, 2018
5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> 5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
6 * Thomas Richter <tmricht@linux.vnet.ibm.com>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only) 9 * it under the terms of the GNU General Public License (version 2 only)
@@ -13,16 +14,135 @@
13#include <unistd.h> 14#include <unistd.h>
14#include <stdio.h> 15#include <stdio.h>
15#include <string.h> 16#include <string.h>
17#include <ctype.h>
16 18
17#include "../../util/header.h" 19#include "../../util/header.h"
20#include "../../util/util.h"
21
22#define SYSINFO_MANU "Manufacturer:"
23#define SYSINFO_TYPE "Type:"
24#define SYSINFO_MODEL "Model:"
25#define SRVLVL_CPUMF "CPU-MF:"
26#define SRVLVL_VERSION "version="
27#define SRVLVL_AUTHORIZATION "authorization="
28#define SYSINFO "/proc/sysinfo"
29#define SRVLVL "/proc/service_levels"
18 30
19int get_cpuid(char *buffer, size_t sz) 31int get_cpuid(char *buffer, size_t sz)
20{ 32{
21 const char *cpuid = "IBM/S390"; 33 char *cp, *line = NULL, *line2;
34 char type[8], model[33], version[8], manufacturer[32], authorization[8];
35 int tpsize = 0, mdsize = 0, vssize = 0, mfsize = 0, atsize = 0;
36 int read;
37 unsigned long line_sz;
38 size_t nbytes;
39 FILE *sysinfo;
40
41 /*
42 * Scan /proc/sysinfo line by line and read out values for
43 * Manufacturer:, Type: and Model:, for example:
44 * Manufacturer: IBM
45 * Type: 2964
46 * Model: 702 N96
47 * The first word is the Model Capacity and the second word is
48 * Model (can be omitted). Both words have a maximum size of 16
49 * bytes.
50 */
51 memset(manufacturer, 0, sizeof(manufacturer));
52 memset(type, 0, sizeof(type));
53 memset(model, 0, sizeof(model));
54 memset(version, 0, sizeof(version));
55 memset(authorization, 0, sizeof(authorization));
56
57 sysinfo = fopen(SYSINFO, "r");
58 if (sysinfo == NULL)
59 return -1;
60
61 while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
62 if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
63 line2 = line + strlen(SYSINFO_MANU);
64
65 while ((cp = strtok_r(line2, "\n ", &line2))) {
66 mfsize += scnprintf(manufacturer + mfsize,
67 sizeof(manufacturer) - mfsize, "%s", cp);
68 }
69 }
70
71 if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
72 line2 = line + strlen(SYSINFO_TYPE);
73
74 while ((cp = strtok_r(line2, "\n ", &line2))) {
75 tpsize += scnprintf(type + tpsize,
76 sizeof(type) - tpsize, "%s", cp);
77 }
78 }
79
80 if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
81 line2 = line + strlen(SYSINFO_MODEL);
82
83 while ((cp = strtok_r(line2, "\n ", &line2))) {
84 mdsize += scnprintf(model + mdsize, sizeof(model) - mdsize,
85 "%s%s", model[0] ? "," : "", cp);
86 }
87 break;
88 }
89 }
90 fclose(sysinfo);
22 91
23 if (strlen(cpuid) + 1 > sz) 92 /* Missing manufacturer, type or model information should not happen */
93 if (!manufacturer[0] || !type[0] || !model[0])
24 return -1; 94 return -1;
25 95
26 strcpy(buffer, cpuid); 96 /*
27 return 0; 97 * Scan /proc/service_levels and return the CPU-MF counter facility
98 * version number and authorization level.
99 * Optional, does not exist on z/VM guests.
100 */
101 sysinfo = fopen(SRVLVL, "r");
102 if (sysinfo == NULL)
103 goto skip_sysinfo;
104 while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
105 if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
106 continue;
107
108 line2 = line + strlen(SRVLVL_CPUMF);
109 while ((cp = strtok_r(line2, "\n ", &line2))) {
110 if (!strncmp(cp, SRVLVL_VERSION,
111 strlen(SRVLVL_VERSION))) {
112 char *sep = strchr(cp, '=');
113
114 vssize += scnprintf(version + vssize,
115 sizeof(version) - vssize, "%s", sep + 1);
116 }
117 if (!strncmp(cp, SRVLVL_AUTHORIZATION,
118 strlen(SRVLVL_AUTHORIZATION))) {
119 char *sep = strchr(cp, '=');
120
121 atsize += scnprintf(authorization + atsize,
122 sizeof(authorization) - atsize, "%s", sep + 1);
123 }
124 }
125 }
126 fclose(sysinfo);
127
128skip_sysinfo:
129 free(line);
130
131 if (version[0] && authorization[0] )
132 nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
133 manufacturer, type, model, version,
134 authorization);
135 else
136 nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
137 model);
138 return (nbytes >= sz) ? -1 : 0;
139}
140
141char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
142{
143 char *buf = malloc(128);
144
145 if (buf && get_cpuid(buf, 128) < 0)
146 zfree(&buf);
147 return buf;
28} 148}
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index d74eaa7aa927..1a38e78117ce 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -21,7 +21,7 @@ _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
21$(header): $(sys)/syscall_64.tbl $(systbl) 21$(header): $(sys)/syscall_64.tbl $(systbl)
22 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \ 22 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
23 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \ 23 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
24 || echo "Warning: Kernel ABI header at 'tools/arch/x86/entry/syscalls/syscall_64.tbl' differs from latest version at 'arch/x86/entry/syscalls/syscall_64.tbl'" >&2 )) || true 24 || echo "Warning: Kernel ABI header at 'tools/perf/arch/x86/entry/syscalls/syscall_64.tbl' differs from latest version at 'arch/x86/entry/syscalls/syscall_64.tbl'" >&2 )) || true
25 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@ 25 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
26 26
27clean:: 27clean::
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index 5bd1ba8c0282..44f5aba78210 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -1,21 +1,43 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2static struct ins x86__instructions[] = { 2static struct ins x86__instructions[] = {
3 { .name = "adc", .ops = &mov_ops, },
4 { .name = "adcb", .ops = &mov_ops, },
5 { .name = "adcl", .ops = &mov_ops, },
3 { .name = "add", .ops = &mov_ops, }, 6 { .name = "add", .ops = &mov_ops, },
4 { .name = "addl", .ops = &mov_ops, }, 7 { .name = "addl", .ops = &mov_ops, },
5 { .name = "addq", .ops = &mov_ops, }, 8 { .name = "addq", .ops = &mov_ops, },
9 { .name = "addsd", .ops = &mov_ops, },
6 { .name = "addw", .ops = &mov_ops, }, 10 { .name = "addw", .ops = &mov_ops, },
7 { .name = "and", .ops = &mov_ops, }, 11 { .name = "and", .ops = &mov_ops, },
12 { .name = "andb", .ops = &mov_ops, },
13 { .name = "andl", .ops = &mov_ops, },
14 { .name = "andpd", .ops = &mov_ops, },
15 { .name = "andps", .ops = &mov_ops, },
16 { .name = "andq", .ops = &mov_ops, },
17 { .name = "andw", .ops = &mov_ops, },
18 { .name = "bsr", .ops = &mov_ops, },
19 { .name = "bt", .ops = &mov_ops, },
20 { .name = "btr", .ops = &mov_ops, },
8 { .name = "bts", .ops = &mov_ops, }, 21 { .name = "bts", .ops = &mov_ops, },
22 { .name = "btsq", .ops = &mov_ops, },
9 { .name = "call", .ops = &call_ops, }, 23 { .name = "call", .ops = &call_ops, },
10 { .name = "callq", .ops = &call_ops, }, 24 { .name = "callq", .ops = &call_ops, },
25 { .name = "cmovbe", .ops = &mov_ops, },
26 { .name = "cmove", .ops = &mov_ops, },
27 { .name = "cmovae", .ops = &mov_ops, },
11 { .name = "cmp", .ops = &mov_ops, }, 28 { .name = "cmp", .ops = &mov_ops, },
12 { .name = "cmpb", .ops = &mov_ops, }, 29 { .name = "cmpb", .ops = &mov_ops, },
13 { .name = "cmpl", .ops = &mov_ops, }, 30 { .name = "cmpl", .ops = &mov_ops, },
14 { .name = "cmpq", .ops = &mov_ops, }, 31 { .name = "cmpq", .ops = &mov_ops, },
15 { .name = "cmpw", .ops = &mov_ops, }, 32 { .name = "cmpw", .ops = &mov_ops, },
16 { .name = "cmpxch", .ops = &mov_ops, }, 33 { .name = "cmpxch", .ops = &mov_ops, },
34 { .name = "cmpxchg", .ops = &mov_ops, },
35 { .name = "cs", .ops = &mov_ops, },
17 { .name = "dec", .ops = &dec_ops, }, 36 { .name = "dec", .ops = &dec_ops, },
18 { .name = "decl", .ops = &dec_ops, }, 37 { .name = "decl", .ops = &dec_ops, },
38 { .name = "divsd", .ops = &mov_ops, },
39 { .name = "divss", .ops = &mov_ops, },
40 { .name = "gs", .ops = &mov_ops, },
19 { .name = "imul", .ops = &mov_ops, }, 41 { .name = "imul", .ops = &mov_ops, },
20 { .name = "inc", .ops = &dec_ops, }, 42 { .name = "inc", .ops = &dec_ops, },
21 { .name = "incl", .ops = &dec_ops, }, 43 { .name = "incl", .ops = &dec_ops, },
@@ -57,25 +79,68 @@ static struct ins x86__instructions[] = {
57 { .name = "lea", .ops = &mov_ops, }, 79 { .name = "lea", .ops = &mov_ops, },
58 { .name = "lock", .ops = &lock_ops, }, 80 { .name = "lock", .ops = &lock_ops, },
59 { .name = "mov", .ops = &mov_ops, }, 81 { .name = "mov", .ops = &mov_ops, },
82 { .name = "movapd", .ops = &mov_ops, },
83 { .name = "movaps", .ops = &mov_ops, },
60 { .name = "movb", .ops = &mov_ops, }, 84 { .name = "movb", .ops = &mov_ops, },
61 { .name = "movdqa", .ops = &mov_ops, }, 85 { .name = "movdqa", .ops = &mov_ops, },
86 { .name = "movdqu", .ops = &mov_ops, },
62 { .name = "movl", .ops = &mov_ops, }, 87 { .name = "movl", .ops = &mov_ops, },
63 { .name = "movq", .ops = &mov_ops, }, 88 { .name = "movq", .ops = &mov_ops, },
89 { .name = "movsd", .ops = &mov_ops, },
64 { .name = "movslq", .ops = &mov_ops, }, 90 { .name = "movslq", .ops = &mov_ops, },
91 { .name = "movss", .ops = &mov_ops, },
92 { .name = "movupd", .ops = &mov_ops, },
93 { .name = "movups", .ops = &mov_ops, },
94 { .name = "movw", .ops = &mov_ops, },
65 { .name = "movzbl", .ops = &mov_ops, }, 95 { .name = "movzbl", .ops = &mov_ops, },
66 { .name = "movzwl", .ops = &mov_ops, }, 96 { .name = "movzwl", .ops = &mov_ops, },
97 { .name = "mulsd", .ops = &mov_ops, },
98 { .name = "mulss", .ops = &mov_ops, },
67 { .name = "nop", .ops = &nop_ops, }, 99 { .name = "nop", .ops = &nop_ops, },
68 { .name = "nopl", .ops = &nop_ops, }, 100 { .name = "nopl", .ops = &nop_ops, },
69 { .name = "nopw", .ops = &nop_ops, }, 101 { .name = "nopw", .ops = &nop_ops, },
70 { .name = "or", .ops = &mov_ops, }, 102 { .name = "or", .ops = &mov_ops, },
103 { .name = "orb", .ops = &mov_ops, },
71 { .name = "orl", .ops = &mov_ops, }, 104 { .name = "orl", .ops = &mov_ops, },
105 { .name = "orps", .ops = &mov_ops, },
106 { .name = "orq", .ops = &mov_ops, },
107 { .name = "pand", .ops = &mov_ops, },
108 { .name = "paddq", .ops = &mov_ops, },
109 { .name = "pcmpeqb", .ops = &mov_ops, },
110 { .name = "por", .ops = &mov_ops, },
111 { .name = "rclb", .ops = &mov_ops, },
112 { .name = "rcll", .ops = &mov_ops, },
113 { .name = "retq", .ops = &ret_ops, },
114 { .name = "sbb", .ops = &mov_ops, },
115 { .name = "sbbl", .ops = &mov_ops, },
116 { .name = "sete", .ops = &mov_ops, },
117 { .name = "sub", .ops = &mov_ops, },
118 { .name = "subl", .ops = &mov_ops, },
119 { .name = "subq", .ops = &mov_ops, },
120 { .name = "subsd", .ops = &mov_ops, },
121 { .name = "subw", .ops = &mov_ops, },
72 { .name = "test", .ops = &mov_ops, }, 122 { .name = "test", .ops = &mov_ops, },
73 { .name = "testb", .ops = &mov_ops, }, 123 { .name = "testb", .ops = &mov_ops, },
74 { .name = "testl", .ops = &mov_ops, }, 124 { .name = "testl", .ops = &mov_ops, },
125 { .name = "ucomisd", .ops = &mov_ops, },
126 { .name = "ucomiss", .ops = &mov_ops, },
127 { .name = "vaddsd", .ops = &mov_ops, },
128 { .name = "vandpd", .ops = &mov_ops, },
129 { .name = "vmovdqa", .ops = &mov_ops, },
130 { .name = "vmovq", .ops = &mov_ops, },
131 { .name = "vmovsd", .ops = &mov_ops, },
132 { .name = "vmulsd", .ops = &mov_ops, },
133 { .name = "vorpd", .ops = &mov_ops, },
134 { .name = "vsubsd", .ops = &mov_ops, },
135 { .name = "vucomisd", .ops = &mov_ops, },
75 { .name = "xadd", .ops = &mov_ops, }, 136 { .name = "xadd", .ops = &mov_ops, },
76 { .name = "xbeginl", .ops = &jump_ops, }, 137 { .name = "xbeginl", .ops = &jump_ops, },
77 { .name = "xbeginq", .ops = &jump_ops, }, 138 { .name = "xbeginq", .ops = &jump_ops, },
78 { .name = "retq", .ops = &ret_ops, }, 139 { .name = "xchg", .ops = &mov_ops, },
140 { .name = "xor", .ops = &mov_ops, },
141 { .name = "xorb", .ops = &mov_ops, },
142 { .name = "xorpd", .ops = &mov_ops, },
143 { .name = "xorps", .ops = &mov_ops, },
79}; 144};
80 145
81static bool x86__ins_is_fused(struct arch *arch, const char *ins1, 146static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index 5aef183e2f85..4dfe42666d0c 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -4,379 +4,383 @@
4# The format is: 4# The format is:
5# <number> <abi> <name> <entry point> 5# <number> <abi> <name> <entry point>
6# 6#
7# The __x64_sys_*() stubs are created on-the-fly for sys_*() system calls
8#
7# The abi is "common", "64" or "x32" for this file. 9# The abi is "common", "64" or "x32" for this file.
8# 10#
90 common read sys_read 110 common read __x64_sys_read
101 common write sys_write 121 common write __x64_sys_write
112 common open sys_open 132 common open __x64_sys_open
123 common close sys_close 143 common close __x64_sys_close
134 common stat sys_newstat 154 common stat __x64_sys_newstat
145 common fstat sys_newfstat 165 common fstat __x64_sys_newfstat
156 common lstat sys_newlstat 176 common lstat __x64_sys_newlstat
167 common poll sys_poll 187 common poll __x64_sys_poll
178 common lseek sys_lseek 198 common lseek __x64_sys_lseek
189 common mmap sys_mmap 209 common mmap __x64_sys_mmap
1910 common mprotect sys_mprotect 2110 common mprotect __x64_sys_mprotect
2011 common munmap sys_munmap 2211 common munmap __x64_sys_munmap
2112 common brk sys_brk 2312 common brk __x64_sys_brk
2213 64 rt_sigaction sys_rt_sigaction 2413 64 rt_sigaction __x64_sys_rt_sigaction
2314 common rt_sigprocmask sys_rt_sigprocmask 2514 common rt_sigprocmask __x64_sys_rt_sigprocmask
2415 64 rt_sigreturn sys_rt_sigreturn/ptregs 2615 64 rt_sigreturn __x64_sys_rt_sigreturn/ptregs
2516 64 ioctl sys_ioctl 2716 64 ioctl __x64_sys_ioctl
2617 common pread64 sys_pread64 2817 common pread64 __x64_sys_pread64
2718 common pwrite64 sys_pwrite64 2918 common pwrite64 __x64_sys_pwrite64
2819 64 readv sys_readv 3019 64 readv __x64_sys_readv
2920 64 writev sys_writev 3120 64 writev __x64_sys_writev
3021 common access sys_access 3221 common access __x64_sys_access
3122 common pipe sys_pipe 3322 common pipe __x64_sys_pipe
3223 common select sys_select 3423 common select __x64_sys_select
3324 common sched_yield sys_sched_yield 3524 common sched_yield __x64_sys_sched_yield
3425 common mremap sys_mremap 3625 common mremap __x64_sys_mremap
3526 common msync sys_msync 3726 common msync __x64_sys_msync
3627 common mincore sys_mincore 3827 common mincore __x64_sys_mincore
3728 common madvise sys_madvise 3928 common madvise __x64_sys_madvise
3829 common shmget sys_shmget 4029 common shmget __x64_sys_shmget
3930 common shmat sys_shmat 4130 common shmat __x64_sys_shmat
4031 common shmctl sys_shmctl 4231 common shmctl __x64_sys_shmctl
4132 common dup sys_dup 4332 common dup __x64_sys_dup
4233 common dup2 sys_dup2 4433 common dup2 __x64_sys_dup2
4334 common pause sys_pause 4534 common pause __x64_sys_pause
4435 common nanosleep sys_nanosleep 4635 common nanosleep __x64_sys_nanosleep
4536 common getitimer sys_getitimer 4736 common getitimer __x64_sys_getitimer
4637 common alarm sys_alarm 4837 common alarm __x64_sys_alarm
4738 common setitimer sys_setitimer 4938 common setitimer __x64_sys_setitimer
4839 common getpid sys_getpid 5039 common getpid __x64_sys_getpid
4940 common sendfile sys_sendfile64 5140 common sendfile __x64_sys_sendfile64
5041 common socket sys_socket 5241 common socket __x64_sys_socket
5142 common connect sys_connect 5342 common connect __x64_sys_connect
5243 common accept sys_accept 5443 common accept __x64_sys_accept
5344 common sendto sys_sendto 5544 common sendto __x64_sys_sendto
5445 64 recvfrom sys_recvfrom 5645 64 recvfrom __x64_sys_recvfrom
5546 64 sendmsg sys_sendmsg 5746 64 sendmsg __x64_sys_sendmsg
5647 64 recvmsg sys_recvmsg 5847 64 recvmsg __x64_sys_recvmsg
5748 common shutdown sys_shutdown 5948 common shutdown __x64_sys_shutdown
5849 common bind sys_bind 6049 common bind __x64_sys_bind
5950 common listen sys_listen 6150 common listen __x64_sys_listen
6051 common getsockname sys_getsockname 6251 common getsockname __x64_sys_getsockname
6152 common getpeername sys_getpeername 6352 common getpeername __x64_sys_getpeername
6253 common socketpair sys_socketpair 6453 common socketpair __x64_sys_socketpair
6354 64 setsockopt sys_setsockopt 6554 64 setsockopt __x64_sys_setsockopt
6455 64 getsockopt sys_getsockopt 6655 64 getsockopt __x64_sys_getsockopt
6556 common clone sys_clone/ptregs 6756 common clone __x64_sys_clone/ptregs
6657 common fork sys_fork/ptregs 6857 common fork __x64_sys_fork/ptregs
6758 common vfork sys_vfork/ptregs 6958 common vfork __x64_sys_vfork/ptregs
6859 64 execve sys_execve/ptregs 7059 64 execve __x64_sys_execve/ptregs
6960 common exit sys_exit 7160 common exit __x64_sys_exit
7061 common wait4 sys_wait4 7261 common wait4 __x64_sys_wait4
7162 common kill sys_kill 7362 common kill __x64_sys_kill
7263 common uname sys_newuname 7463 common uname __x64_sys_newuname
7364 common semget sys_semget 7564 common semget __x64_sys_semget
7465 common semop sys_semop 7665 common semop __x64_sys_semop
7566 common semctl sys_semctl 7766 common semctl __x64_sys_semctl
7667 common shmdt sys_shmdt 7867 common shmdt __x64_sys_shmdt
7768 common msgget sys_msgget 7968 common msgget __x64_sys_msgget
7869 common msgsnd sys_msgsnd 8069 common msgsnd __x64_sys_msgsnd
7970 common msgrcv sys_msgrcv 8170 common msgrcv __x64_sys_msgrcv
8071 common msgctl sys_msgctl 8271 common msgctl __x64_sys_msgctl
8172 common fcntl sys_fcntl 8372 common fcntl __x64_sys_fcntl
8273 common flock sys_flock 8473 common flock __x64_sys_flock
8374 common fsync sys_fsync 8574 common fsync __x64_sys_fsync
8475 common fdatasync sys_fdatasync 8675 common fdatasync __x64_sys_fdatasync
8576 common truncate sys_truncate 8776 common truncate __x64_sys_truncate
8677 common ftruncate sys_ftruncate 8877 common ftruncate __x64_sys_ftruncate
8778 common getdents sys_getdents 8978 common getdents __x64_sys_getdents
8879 common getcwd sys_getcwd 9079 common getcwd __x64_sys_getcwd
8980 common chdir sys_chdir 9180 common chdir __x64_sys_chdir
9081 common fchdir sys_fchdir 9281 common fchdir __x64_sys_fchdir
9182 common rename sys_rename 9382 common rename __x64_sys_rename
9283 common mkdir sys_mkdir 9483 common mkdir __x64_sys_mkdir
9384 common rmdir sys_rmdir 9584 common rmdir __x64_sys_rmdir
9485 common creat sys_creat 9685 common creat __x64_sys_creat
9586 common link sys_link 9786 common link __x64_sys_link
9687 common unlink sys_unlink 9887 common unlink __x64_sys_unlink
9788 common symlink sys_symlink 9988 common symlink __x64_sys_symlink
9889 common readlink sys_readlink 10089 common readlink __x64_sys_readlink
9990 common chmod sys_chmod 10190 common chmod __x64_sys_chmod
10091 common fchmod sys_fchmod 10291 common fchmod __x64_sys_fchmod
10192 common chown sys_chown 10392 common chown __x64_sys_chown
10293 common fchown sys_fchown 10493 common fchown __x64_sys_fchown
10394 common lchown sys_lchown 10594 common lchown __x64_sys_lchown
10495 common umask sys_umask 10695 common umask __x64_sys_umask
10596 common gettimeofday sys_gettimeofday 10796 common gettimeofday __x64_sys_gettimeofday
10697 common getrlimit sys_getrlimit 10897 common getrlimit __x64_sys_getrlimit
10798 common getrusage sys_getrusage 10998 common getrusage __x64_sys_getrusage
10899 common sysinfo sys_sysinfo 11099 common sysinfo __x64_sys_sysinfo
109100 common times sys_times 111100 common times __x64_sys_times
110101 64 ptrace sys_ptrace 112101 64 ptrace __x64_sys_ptrace
111102 common getuid sys_getuid 113102 common getuid __x64_sys_getuid
112103 common syslog sys_syslog 114103 common syslog __x64_sys_syslog
113104 common getgid sys_getgid 115104 common getgid __x64_sys_getgid
114105 common setuid sys_setuid 116105 common setuid __x64_sys_setuid
115106 common setgid sys_setgid 117106 common setgid __x64_sys_setgid
116107 common geteuid sys_geteuid 118107 common geteuid __x64_sys_geteuid
117108 common getegid sys_getegid 119108 common getegid __x64_sys_getegid
118109 common setpgid sys_setpgid 120109 common setpgid __x64_sys_setpgid
119110 common getppid sys_getppid 121110 common getppid __x64_sys_getppid
120111 common getpgrp sys_getpgrp 122111 common getpgrp __x64_sys_getpgrp
121112 common setsid sys_setsid 123112 common setsid __x64_sys_setsid
122113 common setreuid sys_setreuid 124113 common setreuid __x64_sys_setreuid
123114 common setregid sys_setregid 125114 common setregid __x64_sys_setregid
124115 common getgroups sys_getgroups 126115 common getgroups __x64_sys_getgroups
125116 common setgroups sys_setgroups 127116 common setgroups __x64_sys_setgroups
126117 common setresuid sys_setresuid 128117 common setresuid __x64_sys_setresuid
127118 common getresuid sys_getresuid 129118 common getresuid __x64_sys_getresuid
128119 common setresgid sys_setresgid 130119 common setresgid __x64_sys_setresgid
129120 common getresgid sys_getresgid 131120 common getresgid __x64_sys_getresgid
130121 common getpgid sys_getpgid 132121 common getpgid __x64_sys_getpgid
131122 common setfsuid sys_setfsuid 133122 common setfsuid __x64_sys_setfsuid
132123 common setfsgid sys_setfsgid 134123 common setfsgid __x64_sys_setfsgid
133124 common getsid sys_getsid 135124 common getsid __x64_sys_getsid
134125 common capget sys_capget 136125 common capget __x64_sys_capget
135126 common capset sys_capset 137126 common capset __x64_sys_capset
136127 64 rt_sigpending sys_rt_sigpending 138127 64 rt_sigpending __x64_sys_rt_sigpending
137128 64 rt_sigtimedwait sys_rt_sigtimedwait 139128 64 rt_sigtimedwait __x64_sys_rt_sigtimedwait
138129 64 rt_sigqueueinfo sys_rt_sigqueueinfo 140129 64 rt_sigqueueinfo __x64_sys_rt_sigqueueinfo
139130 common rt_sigsuspend sys_rt_sigsuspend 141130 common rt_sigsuspend __x64_sys_rt_sigsuspend
140131 64 sigaltstack sys_sigaltstack 142131 64 sigaltstack __x64_sys_sigaltstack
141132 common utime sys_utime 143132 common utime __x64_sys_utime
142133 common mknod sys_mknod 144133 common mknod __x64_sys_mknod
143134 64 uselib 145134 64 uselib
144135 common personality sys_personality 146135 common personality __x64_sys_personality
145136 common ustat sys_ustat 147136 common ustat __x64_sys_ustat
146137 common statfs sys_statfs 148137 common statfs __x64_sys_statfs
147138 common fstatfs sys_fstatfs 149138 common fstatfs __x64_sys_fstatfs
148139 common sysfs sys_sysfs 150139 common sysfs __x64_sys_sysfs
149140 common getpriority sys_getpriority 151140 common getpriority __x64_sys_getpriority
150141 common setpriority sys_setpriority 152141 common setpriority __x64_sys_setpriority
151142 common sched_setparam sys_sched_setparam 153142 common sched_setparam __x64_sys_sched_setparam
152143 common sched_getparam sys_sched_getparam 154143 common sched_getparam __x64_sys_sched_getparam
153144 common sched_setscheduler sys_sched_setscheduler 155144 common sched_setscheduler __x64_sys_sched_setscheduler
154145 common sched_getscheduler sys_sched_getscheduler 156145 common sched_getscheduler __x64_sys_sched_getscheduler
155146 common sched_get_priority_max sys_sched_get_priority_max 157146 common sched_get_priority_max __x64_sys_sched_get_priority_max
156147 common sched_get_priority_min sys_sched_get_priority_min 158147 common sched_get_priority_min __x64_sys_sched_get_priority_min
157148 common sched_rr_get_interval sys_sched_rr_get_interval 159148 common sched_rr_get_interval __x64_sys_sched_rr_get_interval
158149 common mlock sys_mlock 160149 common mlock __x64_sys_mlock
159150 common munlock sys_munlock 161150 common munlock __x64_sys_munlock
160151 common mlockall sys_mlockall 162151 common mlockall __x64_sys_mlockall
161152 common munlockall sys_munlockall 163152 common munlockall __x64_sys_munlockall
162153 common vhangup sys_vhangup 164153 common vhangup __x64_sys_vhangup
163154 common modify_ldt sys_modify_ldt 165154 common modify_ldt __x64_sys_modify_ldt
164155 common pivot_root sys_pivot_root 166155 common pivot_root __x64_sys_pivot_root
165156 64 _sysctl sys_sysctl 167156 64 _sysctl __x64_sys_sysctl
166157 common prctl sys_prctl 168157 common prctl __x64_sys_prctl
167158 common arch_prctl sys_arch_prctl 169158 common arch_prctl __x64_sys_arch_prctl
168159 common adjtimex sys_adjtimex 170159 common adjtimex __x64_sys_adjtimex
169160 common setrlimit sys_setrlimit 171160 common setrlimit __x64_sys_setrlimit
170161 common chroot sys_chroot 172161 common chroot __x64_sys_chroot
171162 common sync sys_sync 173162 common sync __x64_sys_sync
172163 common acct sys_acct 174163 common acct __x64_sys_acct
173164 common settimeofday sys_settimeofday 175164 common settimeofday __x64_sys_settimeofday
174165 common mount sys_mount 176165 common mount __x64_sys_mount
175166 common umount2 sys_umount 177166 common umount2 __x64_sys_umount
176167 common swapon sys_swapon 178167 common swapon __x64_sys_swapon
177168 common swapoff sys_swapoff 179168 common swapoff __x64_sys_swapoff
178169 common reboot sys_reboot 180169 common reboot __x64_sys_reboot
179170 common sethostname sys_sethostname 181170 common sethostname __x64_sys_sethostname
180171 common setdomainname sys_setdomainname 182171 common setdomainname __x64_sys_setdomainname
181172 common iopl sys_iopl/ptregs 183172 common iopl __x64_sys_iopl/ptregs
182173 common ioperm sys_ioperm 184173 common ioperm __x64_sys_ioperm
183174 64 create_module 185174 64 create_module
184175 common init_module sys_init_module 186175 common init_module __x64_sys_init_module
185176 common delete_module sys_delete_module 187176 common delete_module __x64_sys_delete_module
186177 64 get_kernel_syms 188177 64 get_kernel_syms
187178 64 query_module 189178 64 query_module
188179 common quotactl sys_quotactl 190179 common quotactl __x64_sys_quotactl
189180 64 nfsservctl 191180 64 nfsservctl
190181 common getpmsg 192181 common getpmsg
191182 common putpmsg 193182 common putpmsg
192183 common afs_syscall 194183 common afs_syscall
193184 common tuxcall 195184 common tuxcall
194185 common security 196185 common security
195186 common gettid sys_gettid 197186 common gettid __x64_sys_gettid
196187 common readahead sys_readahead 198187 common readahead __x64_sys_readahead
197188 common setxattr sys_setxattr 199188 common setxattr __x64_sys_setxattr
198189 common lsetxattr sys_lsetxattr 200189 common lsetxattr __x64_sys_lsetxattr
199190 common fsetxattr sys_fsetxattr 201190 common fsetxattr __x64_sys_fsetxattr
200191 common getxattr sys_getxattr 202191 common getxattr __x64_sys_getxattr
201192 common lgetxattr sys_lgetxattr 203192 common lgetxattr __x64_sys_lgetxattr
202193 common fgetxattr sys_fgetxattr 204193 common fgetxattr __x64_sys_fgetxattr
203194 common listxattr sys_listxattr 205194 common listxattr __x64_sys_listxattr
204195 common llistxattr sys_llistxattr 206195 common llistxattr __x64_sys_llistxattr
205196 common flistxattr sys_flistxattr 207196 common flistxattr __x64_sys_flistxattr
206197 common removexattr sys_removexattr 208197 common removexattr __x64_sys_removexattr
207198 common lremovexattr sys_lremovexattr 209198 common lremovexattr __x64_sys_lremovexattr
208199 common fremovexattr sys_fremovexattr 210199 common fremovexattr __x64_sys_fremovexattr
209200 common tkill sys_tkill 211200 common tkill __x64_sys_tkill
210201 common time sys_time 212201 common time __x64_sys_time
211202 common futex sys_futex 213202 common futex __x64_sys_futex
212203 common sched_setaffinity sys_sched_setaffinity 214203 common sched_setaffinity __x64_sys_sched_setaffinity
213204 common sched_getaffinity sys_sched_getaffinity 215204 common sched_getaffinity __x64_sys_sched_getaffinity
214205 64 set_thread_area 216205 64 set_thread_area
215206 64 io_setup sys_io_setup 217206 64 io_setup __x64_sys_io_setup
216207 common io_destroy sys_io_destroy 218207 common io_destroy __x64_sys_io_destroy
217208 common io_getevents sys_io_getevents 219208 common io_getevents __x64_sys_io_getevents
218209 64 io_submit sys_io_submit 220209 64 io_submit __x64_sys_io_submit
219210 common io_cancel sys_io_cancel 221210 common io_cancel __x64_sys_io_cancel
220211 64 get_thread_area 222211 64 get_thread_area
221212 common lookup_dcookie sys_lookup_dcookie 223212 common lookup_dcookie __x64_sys_lookup_dcookie
222213 common epoll_create sys_epoll_create 224213 common epoll_create __x64_sys_epoll_create
223214 64 epoll_ctl_old 225214 64 epoll_ctl_old
224215 64 epoll_wait_old 226215 64 epoll_wait_old
225216 common remap_file_pages sys_remap_file_pages 227216 common remap_file_pages __x64_sys_remap_file_pages
226217 common getdents64 sys_getdents64 228217 common getdents64 __x64_sys_getdents64
227218 common set_tid_address sys_set_tid_address 229218 common set_tid_address __x64_sys_set_tid_address
228219 common restart_syscall sys_restart_syscall 230219 common restart_syscall __x64_sys_restart_syscall
229220 common semtimedop sys_semtimedop 231220 common semtimedop __x64_sys_semtimedop
230221 common fadvise64 sys_fadvise64 232221 common fadvise64 __x64_sys_fadvise64
231222 64 timer_create sys_timer_create 233222 64 timer_create __x64_sys_timer_create
232223 common timer_settime sys_timer_settime 234223 common timer_settime __x64_sys_timer_settime
233224 common timer_gettime sys_timer_gettime 235224 common timer_gettime __x64_sys_timer_gettime
234225 common timer_getoverrun sys_timer_getoverrun 236225 common timer_getoverrun __x64_sys_timer_getoverrun
235226 common timer_delete sys_timer_delete 237226 common timer_delete __x64_sys_timer_delete
236227 common clock_settime sys_clock_settime 238227 common clock_settime __x64_sys_clock_settime
237228 common clock_gettime sys_clock_gettime 239228 common clock_gettime __x64_sys_clock_gettime
238229 common clock_getres sys_clock_getres 240229 common clock_getres __x64_sys_clock_getres
239230 common clock_nanosleep sys_clock_nanosleep 241230 common clock_nanosleep __x64_sys_clock_nanosleep
240231 common exit_group sys_exit_group 242231 common exit_group __x64_sys_exit_group
241232 common epoll_wait sys_epoll_wait 243232 common epoll_wait __x64_sys_epoll_wait
242233 common epoll_ctl sys_epoll_ctl 244233 common epoll_ctl __x64_sys_epoll_ctl
243234 common tgkill sys_tgkill 245234 common tgkill __x64_sys_tgkill
244235 common utimes sys_utimes 246235 common utimes __x64_sys_utimes
245236 64 vserver 247236 64 vserver
246237 common mbind sys_mbind 248237 common mbind __x64_sys_mbind
247238 common set_mempolicy sys_set_mempolicy 249238 common set_mempolicy __x64_sys_set_mempolicy
248239 common get_mempolicy sys_get_mempolicy 250239 common get_mempolicy __x64_sys_get_mempolicy
249240 common mq_open sys_mq_open 251240 common mq_open __x64_sys_mq_open
250241 common mq_unlink sys_mq_unlink 252241 common mq_unlink __x64_sys_mq_unlink
251242 common mq_timedsend sys_mq_timedsend 253242 common mq_timedsend __x64_sys_mq_timedsend
252243 common mq_timedreceive sys_mq_timedreceive 254243 common mq_timedreceive __x64_sys_mq_timedreceive
253244 64 mq_notify sys_mq_notify 255244 64 mq_notify __x64_sys_mq_notify
254245 common mq_getsetattr sys_mq_getsetattr 256245 common mq_getsetattr __x64_sys_mq_getsetattr
255246 64 kexec_load sys_kexec_load 257246 64 kexec_load __x64_sys_kexec_load
256247 64 waitid sys_waitid 258247 64 waitid __x64_sys_waitid
257248 common add_key sys_add_key 259248 common add_key __x64_sys_add_key
258249 common request_key sys_request_key 260249 common request_key __x64_sys_request_key
259250 common keyctl sys_keyctl 261250 common keyctl __x64_sys_keyctl
260251 common ioprio_set sys_ioprio_set 262251 common ioprio_set __x64_sys_ioprio_set
261252 common ioprio_get sys_ioprio_get 263252 common ioprio_get __x64_sys_ioprio_get
262253 common inotify_init sys_inotify_init 264253 common inotify_init __x64_sys_inotify_init
263254 common inotify_add_watch sys_inotify_add_watch 265254 common inotify_add_watch __x64_sys_inotify_add_watch
264255 common inotify_rm_watch sys_inotify_rm_watch 266255 common inotify_rm_watch __x64_sys_inotify_rm_watch
265256 common migrate_pages sys_migrate_pages 267256 common migrate_pages __x64_sys_migrate_pages
266257 common openat sys_openat 268257 common openat __x64_sys_openat
267258 common mkdirat sys_mkdirat 269258 common mkdirat __x64_sys_mkdirat
268259 common mknodat sys_mknodat 270259 common mknodat __x64_sys_mknodat
269260 common fchownat sys_fchownat 271260 common fchownat __x64_sys_fchownat
270261 common futimesat sys_futimesat 272261 common futimesat __x64_sys_futimesat
271262 common newfstatat sys_newfstatat 273262 common newfstatat __x64_sys_newfstatat
272263 common unlinkat sys_unlinkat 274263 common unlinkat __x64_sys_unlinkat
273264 common renameat sys_renameat 275264 common renameat __x64_sys_renameat
274265 common linkat sys_linkat 276265 common linkat __x64_sys_linkat
275266 common symlinkat sys_symlinkat 277266 common symlinkat __x64_sys_symlinkat
276267 common readlinkat sys_readlinkat 278267 common readlinkat __x64_sys_readlinkat
277268 common fchmodat sys_fchmodat 279268 common fchmodat __x64_sys_fchmodat
278269 common faccessat sys_faccessat 280269 common faccessat __x64_sys_faccessat
279270 common pselect6 sys_pselect6 281270 common pselect6 __x64_sys_pselect6
280271 common ppoll sys_ppoll 282271 common ppoll __x64_sys_ppoll
281272 common unshare sys_unshare 283272 common unshare __x64_sys_unshare
282273 64 set_robust_list sys_set_robust_list 284273 64 set_robust_list __x64_sys_set_robust_list
283274 64 get_robust_list sys_get_robust_list 285274 64 get_robust_list __x64_sys_get_robust_list
284275 common splice sys_splice 286275 common splice __x64_sys_splice
285276 common tee sys_tee 287276 common tee __x64_sys_tee
286277 common sync_file_range sys_sync_file_range 288277 common sync_file_range __x64_sys_sync_file_range
287278 64 vmsplice sys_vmsplice 289278 64 vmsplice __x64_sys_vmsplice
288279 64 move_pages sys_move_pages 290279 64 move_pages __x64_sys_move_pages
289280 common utimensat sys_utimensat 291280 common utimensat __x64_sys_utimensat
290281 common epoll_pwait sys_epoll_pwait 292281 common epoll_pwait __x64_sys_epoll_pwait
291282 common signalfd sys_signalfd 293282 common signalfd __x64_sys_signalfd
292283 common timerfd_create sys_timerfd_create 294283 common timerfd_create __x64_sys_timerfd_create
293284 common eventfd sys_eventfd 295284 common eventfd __x64_sys_eventfd
294285 common fallocate sys_fallocate 296285 common fallocate __x64_sys_fallocate
295286 common timerfd_settime sys_timerfd_settime 297286 common timerfd_settime __x64_sys_timerfd_settime
296287 common timerfd_gettime sys_timerfd_gettime 298287 common timerfd_gettime __x64_sys_timerfd_gettime
297288 common accept4 sys_accept4 299288 common accept4 __x64_sys_accept4
298289 common signalfd4 sys_signalfd4 300289 common signalfd4 __x64_sys_signalfd4
299290 common eventfd2 sys_eventfd2 301290 common eventfd2 __x64_sys_eventfd2
300291 common epoll_create1 sys_epoll_create1 302291 common epoll_create1 __x64_sys_epoll_create1
301292 common dup3 sys_dup3 303292 common dup3 __x64_sys_dup3
302293 common pipe2 sys_pipe2 304293 common pipe2 __x64_sys_pipe2
303294 common inotify_init1 sys_inotify_init1 305294 common inotify_init1 __x64_sys_inotify_init1
304295 64 preadv sys_preadv 306295 64 preadv __x64_sys_preadv
305296 64 pwritev sys_pwritev 307296 64 pwritev __x64_sys_pwritev
306297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo 308297 64 rt_tgsigqueueinfo __x64_sys_rt_tgsigqueueinfo
307298 common perf_event_open sys_perf_event_open 309298 common perf_event_open __x64_sys_perf_event_open
308299 64 recvmmsg sys_recvmmsg 310299 64 recvmmsg __x64_sys_recvmmsg
309300 common fanotify_init sys_fanotify_init 311300 common fanotify_init __x64_sys_fanotify_init
310301 common fanotify_mark sys_fanotify_mark 312301 common fanotify_mark __x64_sys_fanotify_mark
311302 common prlimit64 sys_prlimit64 313302 common prlimit64 __x64_sys_prlimit64
312303 common name_to_handle_at sys_name_to_handle_at 314303 common name_to_handle_at __x64_sys_name_to_handle_at
313304 common open_by_handle_at sys_open_by_handle_at 315304 common open_by_handle_at __x64_sys_open_by_handle_at
314305 common clock_adjtime sys_clock_adjtime 316305 common clock_adjtime __x64_sys_clock_adjtime
315306 common syncfs sys_syncfs 317306 common syncfs __x64_sys_syncfs
316307 64 sendmmsg sys_sendmmsg 318307 64 sendmmsg __x64_sys_sendmmsg
317308 common setns sys_setns 319308 common setns __x64_sys_setns
318309 common getcpu sys_getcpu 320309 common getcpu __x64_sys_getcpu
319310 64 process_vm_readv sys_process_vm_readv 321310 64 process_vm_readv __x64_sys_process_vm_readv
320311 64 process_vm_writev sys_process_vm_writev 322311 64 process_vm_writev __x64_sys_process_vm_writev
321312 common kcmp sys_kcmp 323312 common kcmp __x64_sys_kcmp
322313 common finit_module sys_finit_module 324313 common finit_module __x64_sys_finit_module
323314 common sched_setattr sys_sched_setattr 325314 common sched_setattr __x64_sys_sched_setattr
324315 common sched_getattr sys_sched_getattr 326315 common sched_getattr __x64_sys_sched_getattr
325316 common renameat2 sys_renameat2 327316 common renameat2 __x64_sys_renameat2
326317 common seccomp sys_seccomp 328317 common seccomp __x64_sys_seccomp
327318 common getrandom sys_getrandom 329318 common getrandom __x64_sys_getrandom
328319 common memfd_create sys_memfd_create 330319 common memfd_create __x64_sys_memfd_create
329320 common kexec_file_load sys_kexec_file_load 331320 common kexec_file_load __x64_sys_kexec_file_load
330321 common bpf sys_bpf 332321 common bpf __x64_sys_bpf
331322 64 execveat sys_execveat/ptregs 333322 64 execveat __x64_sys_execveat/ptregs
332323 common userfaultfd sys_userfaultfd 334323 common userfaultfd __x64_sys_userfaultfd
333324 common membarrier sys_membarrier 335324 common membarrier __x64_sys_membarrier
334325 common mlock2 sys_mlock2 336325 common mlock2 __x64_sys_mlock2
335326 common copy_file_range sys_copy_file_range 337326 common copy_file_range __x64_sys_copy_file_range
336327 64 preadv2 sys_preadv2 338327 64 preadv2 __x64_sys_preadv2
337328 64 pwritev2 sys_pwritev2 339328 64 pwritev2 __x64_sys_pwritev2
338329 common pkey_mprotect sys_pkey_mprotect 340329 common pkey_mprotect __x64_sys_pkey_mprotect
339330 common pkey_alloc sys_pkey_alloc 341330 common pkey_alloc __x64_sys_pkey_alloc
340331 common pkey_free sys_pkey_free 342331 common pkey_free __x64_sys_pkey_free
341332 common statx sys_statx 343332 common statx __x64_sys_statx
342 344
343# 345#
344# x32-specific system call numbers start at 512 to avoid cache impact 346# x32-specific system call numbers start at 512 to avoid cache impact
345# for native 64-bit operation. 347# for native 64-bit operation. The __x32_compat_sys stubs are created
348# on-the-fly for compat_sys_*() compatibility system calls if X86_X32
349# is defined.
346# 350#
347512 x32 rt_sigaction compat_sys_rt_sigaction 351512 x32 rt_sigaction __x32_compat_sys_rt_sigaction
348513 x32 rt_sigreturn sys32_x32_rt_sigreturn 352513 x32 rt_sigreturn sys32_x32_rt_sigreturn
349514 x32 ioctl compat_sys_ioctl 353514 x32 ioctl __x32_compat_sys_ioctl
350515 x32 readv compat_sys_readv 354515 x32 readv __x32_compat_sys_readv
351516 x32 writev compat_sys_writev 355516 x32 writev __x32_compat_sys_writev
352517 x32 recvfrom compat_sys_recvfrom 356517 x32 recvfrom __x32_compat_sys_recvfrom
353518 x32 sendmsg compat_sys_sendmsg 357518 x32 sendmsg __x32_compat_sys_sendmsg
354519 x32 recvmsg compat_sys_recvmsg 358519 x32 recvmsg __x32_compat_sys_recvmsg
355520 x32 execve compat_sys_execve/ptregs 359520 x32 execve __x32_compat_sys_execve/ptregs
356521 x32 ptrace compat_sys_ptrace 360521 x32 ptrace __x32_compat_sys_ptrace
357522 x32 rt_sigpending compat_sys_rt_sigpending 361522 x32 rt_sigpending __x32_compat_sys_rt_sigpending
358523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait 362523 x32 rt_sigtimedwait __x32_compat_sys_rt_sigtimedwait
359524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo 363524 x32 rt_sigqueueinfo __x32_compat_sys_rt_sigqueueinfo
360525 x32 sigaltstack compat_sys_sigaltstack 364525 x32 sigaltstack __x32_compat_sys_sigaltstack
361526 x32 timer_create compat_sys_timer_create 365526 x32 timer_create __x32_compat_sys_timer_create
362527 x32 mq_notify compat_sys_mq_notify 366527 x32 mq_notify __x32_compat_sys_mq_notify
363528 x32 kexec_load compat_sys_kexec_load 367528 x32 kexec_load __x32_compat_sys_kexec_load
364529 x32 waitid compat_sys_waitid 368529 x32 waitid __x32_compat_sys_waitid
365530 x32 set_robust_list compat_sys_set_robust_list 369530 x32 set_robust_list __x32_compat_sys_set_robust_list
366531 x32 get_robust_list compat_sys_get_robust_list 370531 x32 get_robust_list __x32_compat_sys_get_robust_list
367532 x32 vmsplice compat_sys_vmsplice 371532 x32 vmsplice __x32_compat_sys_vmsplice
368533 x32 move_pages compat_sys_move_pages 372533 x32 move_pages __x32_compat_sys_move_pages
369534 x32 preadv compat_sys_preadv64 373534 x32 preadv __x32_compat_sys_preadv64
370535 x32 pwritev compat_sys_pwritev64 374535 x32 pwritev __x32_compat_sys_pwritev64
371536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo 375536 x32 rt_tgsigqueueinfo __x32_compat_sys_rt_tgsigqueueinfo
372537 x32 recvmmsg compat_sys_recvmmsg 376537 x32 recvmmsg __x32_compat_sys_recvmmsg
373538 x32 sendmmsg compat_sys_sendmmsg 377538 x32 sendmmsg __x32_compat_sys_sendmmsg
374539 x32 process_vm_readv compat_sys_process_vm_readv 378539 x32 process_vm_readv __x32_compat_sys_process_vm_readv
375540 x32 process_vm_writev compat_sys_process_vm_writev 379540 x32 process_vm_writev __x32_compat_sys_process_vm_writev
376541 x32 setsockopt compat_sys_setsockopt 380541 x32 setsockopt __x32_compat_sys_setsockopt
377542 x32 getsockopt compat_sys_getsockopt 381542 x32 getsockopt __x32_compat_sys_getsockopt
378543 x32 io_setup compat_sys_io_setup 382543 x32 io_setup __x32_compat_sys_io_setup
379544 x32 io_submit compat_sys_io_submit 383544 x32 io_submit __x32_compat_sys_io_submit
380545 x32 execveat compat_sys_execveat/ptregs 384545 x32 execveat __x32_compat_sys_execveat/ptregs
381546 x32 preadv2 compat_sys_preadv64v2 385546 x32 preadv2 __x32_compat_sys_preadv64v2
382547 x32 pwritev2 compat_sys_pwritev64v2 386547 x32 pwritev2 __x32_compat_sys_pwritev64v2
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 06abe8108b33..7a7721604b86 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -60,6 +60,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
60 union perf_event *event; 60 union perf_event *event;
61 u64 test_tsc, comm1_tsc, comm2_tsc; 61 u64 test_tsc, comm1_tsc, comm2_tsc;
62 u64 test_time, comm1_time = 0, comm2_time = 0; 62 u64 test_time, comm1_time = 0, comm2_time = 0;
63 struct perf_mmap *md;
63 64
64 threads = thread_map__new(-1, getpid(), UINT_MAX); 65 threads = thread_map__new(-1, getpid(), UINT_MAX);
65 CHECK_NOT_NULL__(threads); 66 CHECK_NOT_NULL__(threads);
@@ -109,7 +110,11 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
109 perf_evlist__disable(evlist); 110 perf_evlist__disable(evlist);
110 111
111 for (i = 0; i < evlist->nr_mmaps; i++) { 112 for (i = 0; i < evlist->nr_mmaps; i++) {
112 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 113 md = &evlist->mmap[i];
114 if (perf_mmap__read_init(md) < 0)
115 continue;
116
117 while ((event = perf_mmap__read_event(md)) != NULL) {
113 struct perf_sample sample; 118 struct perf_sample sample;
114 119
115 if (event->header.type != PERF_RECORD_COMM || 120 if (event->header.type != PERF_RECORD_COMM ||
@@ -128,8 +133,9 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
128 comm2_time = sample.time; 133 comm2_time = sample.time;
129 } 134 }
130next_event: 135next_event:
131 perf_evlist__mmap_consume(evlist, i); 136 perf_mmap__consume(md);
132 } 137 }
138 perf_mmap__read_done(md);
133 } 139 }
134 140
135 if (!comm1_time || !comm2_time) 141 if (!comm1_time || !comm2_time)
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c
index 6aa3f2a38321..b135af62011c 100644
--- a/tools/perf/arch/x86/util/auxtrace.c
+++ b/tools/perf/arch/x86/util/auxtrace.c
@@ -37,15 +37,11 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
37 intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); 37 intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME);
38 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); 38 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
39 39
40 if (evlist) { 40 evlist__for_each_entry(evlist, evsel) {
41 evlist__for_each_entry(evlist, evsel) { 41 if (intel_pt_pmu && evsel->attr.type == intel_pt_pmu->type)
42 if (intel_pt_pmu && 42 found_pt = true;
43 evsel->attr.type == intel_pt_pmu->type) 43 if (intel_bts_pmu && evsel->attr.type == intel_bts_pmu->type)
44 found_pt = true; 44 found_bts = true;
45 if (intel_bts_pmu &&
46 evsel->attr.type == intel_bts_pmu->type)
47 found_bts = true;
48 }
49 } 45 }
50 46
51 if (found_pt && found_bts) { 47 if (found_pt && found_bts) {
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 944070e98a2c..63eb49082774 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -175,7 +175,7 @@ static const struct option options[] = {
175 OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"), 175 OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"),
176 OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), 176 OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"),
177 177
178 OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), 178 OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via reads (can be mixed with -W)"),
179 OPT_BOOLEAN('W', "data_writes" , &p0.data_writes, "access the data via writes (can be mixed with -R)"), 179 OPT_BOOLEAN('W', "data_writes" , &p0.data_writes, "access the data via writes (can be mixed with -R)"),
180 OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards, "access the data backwards as well"), 180 OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards, "access the data backwards as well"),
181 OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"), 181 OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"),
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f15731a3d438..51709a961496 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -40,10 +40,11 @@
40struct perf_annotate { 40struct perf_annotate {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 bool use_tui, use_stdio, use_gtk; 43 bool use_tui, use_stdio, use_stdio2, use_gtk;
44 bool full_paths; 44 bool full_paths;
45 bool print_line; 45 bool print_line;
46 bool skip_missing; 46 bool skip_missing;
47 bool has_br_stack;
47 const char *sym_hist_filter; 48 const char *sym_hist_filter;
48 const char *cpu_list; 49 const char *cpu_list;
49 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 50 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -146,16 +147,78 @@ static void process_branch_stack(struct branch_stack *bs, struct addr_location *
146 free(bi); 147 free(bi);
147} 148}
148 149
150static int hist_iter__branch_callback(struct hist_entry_iter *iter,
151 struct addr_location *al __maybe_unused,
152 bool single __maybe_unused,
153 void *arg __maybe_unused)
154{
155 struct hist_entry *he = iter->he;
156 struct branch_info *bi;
157 struct perf_sample *sample = iter->sample;
158 struct perf_evsel *evsel = iter->evsel;
159 int err;
160
161 hist__account_cycles(sample->branch_stack, al, sample, false);
162
163 bi = he->branch_info;
164 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
165
166 if (err)
167 goto out;
168
169 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
170
171out:
172 return err;
173}
174
175static int process_branch_callback(struct perf_evsel *evsel,
176 struct perf_sample *sample,
177 struct addr_location *al __maybe_unused,
178 struct perf_annotate *ann,
179 struct machine *machine)
180{
181 struct hist_entry_iter iter = {
182 .evsel = evsel,
183 .sample = sample,
184 .add_entry_cb = hist_iter__branch_callback,
185 .hide_unresolved = symbol_conf.hide_unresolved,
186 .ops = &hist_iter_branch,
187 };
188
189 struct addr_location a;
190 int ret;
191
192 if (machine__resolve(machine, &a, sample) < 0)
193 return -1;
194
195 if (a.sym == NULL)
196 return 0;
197
198 if (a.map != NULL)
199 a.map->dso->hit = 1;
200
201 ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
202 return ret;
203}
204
205static bool has_annotation(struct perf_annotate *ann)
206{
207 return ui__has_annotation() || ann->use_stdio2;
208}
209
149static int perf_evsel__add_sample(struct perf_evsel *evsel, 210static int perf_evsel__add_sample(struct perf_evsel *evsel,
150 struct perf_sample *sample, 211 struct perf_sample *sample,
151 struct addr_location *al, 212 struct addr_location *al,
152 struct perf_annotate *ann) 213 struct perf_annotate *ann,
214 struct machine *machine)
153{ 215{
154 struct hists *hists = evsel__hists(evsel); 216 struct hists *hists = evsel__hists(evsel);
155 struct hist_entry *he; 217 struct hist_entry *he;
156 int ret; 218 int ret;
157 219
158 if (ann->sym_hist_filter != NULL && 220 if ((!ann->has_br_stack || !has_annotation(ann)) &&
221 ann->sym_hist_filter != NULL &&
159 (al->sym == NULL || 222 (al->sym == NULL ||
160 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { 223 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
161 /* We're only interested in a symbol named sym_hist_filter */ 224 /* We're only interested in a symbol named sym_hist_filter */
@@ -178,6 +241,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
178 */ 241 */
179 process_branch_stack(sample->branch_stack, al, sample); 242 process_branch_stack(sample->branch_stack, al, sample);
180 243
244 if (ann->has_br_stack && has_annotation(ann))
245 return process_branch_callback(evsel, sample, al, ann, machine);
246
181 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 247 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
182 if (he == NULL) 248 if (he == NULL)
183 return -ENOMEM; 249 return -ENOMEM;
@@ -206,7 +272,8 @@ static int process_sample_event(struct perf_tool *tool,
206 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) 272 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
207 goto out_put; 273 goto out_put;
208 274
209 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { 275 if (!al.filtered &&
276 perf_evsel__add_sample(evsel, sample, &al, ann, machine)) {
210 pr_warning("problem incrementing symbol count, " 277 pr_warning("problem incrementing symbol count, "
211 "skipping event\n"); 278 "skipping event\n");
212 ret = -1; 279 ret = -1;
@@ -220,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
220 struct perf_evsel *evsel, 287 struct perf_evsel *evsel,
221 struct perf_annotate *ann) 288 struct perf_annotate *ann)
222{ 289{
223 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 290 if (!ann->use_stdio2)
224 ann->print_line, ann->full_paths, 0, 0); 291 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
292 ann->print_line, ann->full_paths, 0, 0);
293 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel,
294 ann->print_line, ann->full_paths);
225} 295}
226 296
227static void hists__find_annotations(struct hists *hists, 297static void hists__find_annotations(struct hists *hists,
@@ -238,6 +308,10 @@ static void hists__find_annotations(struct hists *hists,
238 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) 308 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
239 goto find_next; 309 goto find_next;
240 310
311 if (ann->sym_hist_filter &&
312 (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0))
313 goto find_next;
314
241 notes = symbol__annotation(he->ms.sym); 315 notes = symbol__annotation(he->ms.sym);
242 if (notes->src == NULL) { 316 if (notes->src == NULL) {
243find_next: 317find_next:
@@ -269,6 +343,7 @@ find_next:
269 nd = rb_next(nd); 343 nd = rb_next(nd);
270 } else if (use_browser == 1) { 344 } else if (use_browser == 1) {
271 key = hist_entry__tui_annotate(he, evsel, NULL); 345 key = hist_entry__tui_annotate(he, evsel, NULL);
346
272 switch (key) { 347 switch (key) {
273 case -1: 348 case -1:
274 if (!ann->skip_missing) 349 if (!ann->skip_missing)
@@ -420,6 +495,9 @@ int cmd_annotate(int argc, const char **argv)
420 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), 495 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
421 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"), 496 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
422 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"), 497 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
498 OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
499 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
500 "don't load vmlinux even if found"),
423 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 501 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
424 "file", "vmlinux pathname"), 502 "file", "vmlinux pathname"),
425 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 503 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -489,20 +567,22 @@ int cmd_annotate(int argc, const char **argv)
489 if (annotate.session == NULL) 567 if (annotate.session == NULL)
490 return -1; 568 return -1;
491 569
570 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
571 HEADER_BRANCH_STACK);
572
492 ret = symbol__annotation_init(); 573 ret = symbol__annotation_init();
493 if (ret < 0) 574 if (ret < 0)
494 goto out_delete; 575 goto out_delete;
495 576
577 annotation_config__init();
578
496 symbol_conf.try_vmlinux_path = true; 579 symbol_conf.try_vmlinux_path = true;
497 580
498 ret = symbol__init(&annotate.session->header.env); 581 ret = symbol__init(&annotate.session->header.env);
499 if (ret < 0) 582 if (ret < 0)
500 goto out_delete; 583 goto out_delete;
501 584
502 if (setup_sorting(NULL) < 0) 585 if (annotate.use_stdio || annotate.use_stdio2)
503 usage_with_options(annotate_usage, options);
504
505 if (annotate.use_stdio)
506 use_browser = 0; 586 use_browser = 0;
507 else if (annotate.use_tui) 587 else if (annotate.use_tui)
508 use_browser = 1; 588 use_browser = 1;
@@ -511,6 +591,15 @@ int cmd_annotate(int argc, const char **argv)
511 591
512 setup_browser(true); 592 setup_browser(true);
513 593
594 if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
595 sort__mode = SORT_MODE__BRANCH;
596 if (setup_sorting(annotate.session->evlist) < 0)
597 usage_with_options(annotate_usage, options);
598 } else {
599 if (setup_sorting(NULL) < 0)
600 usage_with_options(annotate_usage, options);
601 }
602
514 ret = __cmd_annotate(&annotate); 603 ret = __cmd_annotate(&annotate);
515 604
516out_delete: 605out_delete:
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 539c3d460158..2126bfbcb385 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -32,6 +32,7 @@
32#include "evsel.h" 32#include "evsel.h"
33#include "ui/browsers/hists.h" 33#include "ui/browsers/hists.h"
34#include "thread.h" 34#include "thread.h"
35#include "mem2node.h"
35 36
36struct c2c_hists { 37struct c2c_hists {
37 struct hists hists; 38 struct hists hists;
@@ -49,6 +50,7 @@ struct c2c_hist_entry {
49 struct c2c_hists *hists; 50 struct c2c_hists *hists;
50 struct c2c_stats stats; 51 struct c2c_stats stats;
51 unsigned long *cpuset; 52 unsigned long *cpuset;
53 unsigned long *nodeset;
52 struct c2c_stats *node_stats; 54 struct c2c_stats *node_stats;
53 unsigned int cacheline_idx; 55 unsigned int cacheline_idx;
54 56
@@ -59,6 +61,11 @@ struct c2c_hist_entry {
59 * because of its callchain dynamic entry 61 * because of its callchain dynamic entry
60 */ 62 */
61 struct hist_entry he; 63 struct hist_entry he;
64
65 unsigned long paddr;
66 unsigned long paddr_cnt;
67 bool paddr_zero;
68 char *nodestr;
62}; 69};
63 70
64static char const *coalesce_default = "pid,iaddr"; 71static char const *coalesce_default = "pid,iaddr";
@@ -66,6 +73,7 @@ static char const *coalesce_default = "pid,iaddr";
66struct perf_c2c { 73struct perf_c2c {
67 struct perf_tool tool; 74 struct perf_tool tool;
68 struct c2c_hists hists; 75 struct c2c_hists hists;
76 struct mem2node mem2node;
69 77
70 unsigned long **nodes; 78 unsigned long **nodes;
71 int nodes_cnt; 79 int nodes_cnt;
@@ -123,6 +131,10 @@ static void *c2c_he_zalloc(size_t size)
123 if (!c2c_he->cpuset) 131 if (!c2c_he->cpuset)
124 return NULL; 132 return NULL;
125 133
134 c2c_he->nodeset = bitmap_alloc(c2c.nodes_cnt);
135 if (!c2c_he->nodeset)
136 return NULL;
137
126 c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats)); 138 c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
127 if (!c2c_he->node_stats) 139 if (!c2c_he->node_stats)
128 return NULL; 140 return NULL;
@@ -145,6 +157,8 @@ static void c2c_he_free(void *he)
145 } 157 }
146 158
147 free(c2c_he->cpuset); 159 free(c2c_he->cpuset);
160 free(c2c_he->nodeset);
161 free(c2c_he->nodestr);
148 free(c2c_he->node_stats); 162 free(c2c_he->node_stats);
149 free(c2c_he); 163 free(c2c_he);
150} 164}
@@ -194,6 +208,28 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
194 set_bit(sample->cpu, c2c_he->cpuset); 208 set_bit(sample->cpu, c2c_he->cpuset);
195} 209}
196 210
211static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
212 struct perf_sample *sample)
213{
214 int node;
215
216 if (!sample->phys_addr) {
217 c2c_he->paddr_zero = true;
218 return;
219 }
220
221 node = mem2node__node(&c2c.mem2node, sample->phys_addr);
222 if (WARN_ONCE(node < 0, "WARNING: failed to find node\n"))
223 return;
224
225 set_bit(node, c2c_he->nodeset);
226
227 if (c2c_he->paddr != sample->phys_addr) {
228 c2c_he->paddr_cnt++;
229 c2c_he->paddr = sample->phys_addr;
230 }
231}
232
197static void compute_stats(struct c2c_hist_entry *c2c_he, 233static void compute_stats(struct c2c_hist_entry *c2c_he,
198 struct c2c_stats *stats, 234 struct c2c_stats *stats,
199 u64 weight) 235 u64 weight)
@@ -237,9 +273,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
237 if (mi == NULL) 273 if (mi == NULL)
238 return -ENOMEM; 274 return -ENOMEM;
239 275
240 mi_dup = memdup(mi, sizeof(*mi)); 276 /*
241 if (!mi_dup) 277 * The mi object is released in hists__add_entry_ops,
242 goto free_mi; 278 * if it gets sorted out into existing data, so we need
279 * to take the copy now.
280 */
281 mi_dup = mem_info__get(mi);
243 282
244 c2c_decode_stats(&stats, mi); 283 c2c_decode_stats(&stats, mi);
245 284
@@ -247,13 +286,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
247 &al, NULL, NULL, mi, 286 &al, NULL, NULL, mi,
248 sample, true); 287 sample, true);
249 if (he == NULL) 288 if (he == NULL)
250 goto free_mi_dup; 289 goto free_mi;
251 290
252 c2c_he = container_of(he, struct c2c_hist_entry, he); 291 c2c_he = container_of(he, struct c2c_hist_entry, he);
253 c2c_add_stats(&c2c_he->stats, &stats); 292 c2c_add_stats(&c2c_he->stats, &stats);
254 c2c_add_stats(&c2c_hists->stats, &stats); 293 c2c_add_stats(&c2c_hists->stats, &stats);
255 294
256 c2c_he__set_cpu(c2c_he, sample); 295 c2c_he__set_cpu(c2c_he, sample);
296 c2c_he__set_node(c2c_he, sample);
257 297
258 hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 298 hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
259 ret = hist_entry__append_callchain(he, sample); 299 ret = hist_entry__append_callchain(he, sample);
@@ -272,19 +312,15 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
272 312
273 mi = mi_dup; 313 mi = mi_dup;
274 314
275 mi_dup = memdup(mi, sizeof(*mi));
276 if (!mi_dup)
277 goto free_mi;
278
279 c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2); 315 c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
280 if (!c2c_hists) 316 if (!c2c_hists)
281 goto free_mi_dup; 317 goto free_mi;
282 318
283 he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, 319 he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
284 &al, NULL, NULL, mi, 320 &al, NULL, NULL, mi,
285 sample, true); 321 sample, true);
286 if (he == NULL) 322 if (he == NULL)
287 goto free_mi_dup; 323 goto free_mi;
288 324
289 c2c_he = container_of(he, struct c2c_hist_entry, he); 325 c2c_he = container_of(he, struct c2c_hist_entry, he);
290 c2c_add_stats(&c2c_he->stats, &stats); 326 c2c_add_stats(&c2c_he->stats, &stats);
@@ -294,6 +330,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
294 compute_stats(c2c_he, &stats, sample->weight); 330 compute_stats(c2c_he, &stats, sample->weight);
295 331
296 c2c_he__set_cpu(c2c_he, sample); 332 c2c_he__set_cpu(c2c_he, sample);
333 c2c_he__set_node(c2c_he, sample);
297 334
298 hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 335 hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
299 ret = hist_entry__append_callchain(he, sample); 336 ret = hist_entry__append_callchain(he, sample);
@@ -303,10 +340,9 @@ out:
303 addr_location__put(&al); 340 addr_location__put(&al);
304 return ret; 341 return ret;
305 342
306free_mi_dup:
307 free(mi_dup);
308free_mi: 343free_mi:
309 free(mi); 344 mem_info__put(mi_dup);
345 mem_info__put(mi);
310 ret = -ENOMEM; 346 ret = -ENOMEM;
311 goto out; 347 goto out;
312} 348}
@@ -457,6 +493,31 @@ static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
457 return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr)); 493 return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
458} 494}
459 495
496static int
497dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
498 struct hist_entry *he)
499{
500 struct c2c_hist_entry *c2c_he;
501 int width = c2c_width(fmt, hpp, he->hists);
502
503 c2c_he = container_of(he, struct c2c_hist_entry, he);
504 if (WARN_ON_ONCE(!c2c_he->nodestr))
505 return 0;
506
507 return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr);
508}
509
510static int
511dcacheline_node_count(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
512 struct hist_entry *he)
513{
514 struct c2c_hist_entry *c2c_he;
515 int width = c2c_width(fmt, hpp, he->hists);
516
517 c2c_he = container_of(he, struct c2c_hist_entry, he);
518 return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt);
519}
520
460static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 521static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
461 struct hist_entry *he) 522 struct hist_entry *he)
462{ 523{
@@ -1202,23 +1263,47 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1202 } 1263 }
1203 1264
1204static struct c2c_dimension dim_dcacheline = { 1265static struct c2c_dimension dim_dcacheline = {
1205 .header = HEADER_LOW("Cacheline"), 1266 .header = HEADER_SPAN("--- Cacheline ----", "Address", 2),
1206 .name = "dcacheline", 1267 .name = "dcacheline",
1207 .cmp = dcacheline_cmp, 1268 .cmp = dcacheline_cmp,
1208 .entry = dcacheline_entry, 1269 .entry = dcacheline_entry,
1209 .width = 18, 1270 .width = 18,
1210}; 1271};
1211 1272
1212static struct c2c_header header_offset_tui = HEADER_LOW("Off"); 1273static struct c2c_dimension dim_dcacheline_node = {
1274 .header = HEADER_LOW("Node"),
1275 .name = "dcacheline_node",
1276 .cmp = empty_cmp,
1277 .entry = dcacheline_node_entry,
1278 .width = 4,
1279};
1280
1281static struct c2c_dimension dim_dcacheline_count = {
1282 .header = HEADER_LOW("PA cnt"),
1283 .name = "dcacheline_count",
1284 .cmp = empty_cmp,
1285 .entry = dcacheline_node_count,
1286 .width = 6,
1287};
1288
1289static struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2);
1213 1290
1214static struct c2c_dimension dim_offset = { 1291static struct c2c_dimension dim_offset = {
1215 .header = HEADER_BOTH("Data address", "Offset"), 1292 .header = HEADER_SPAN("--- Data address -", "Offset", 2),
1216 .name = "offset", 1293 .name = "offset",
1217 .cmp = offset_cmp, 1294 .cmp = offset_cmp,
1218 .entry = offset_entry, 1295 .entry = offset_entry,
1219 .width = 18, 1296 .width = 18,
1220}; 1297};
1221 1298
1299static struct c2c_dimension dim_offset_node = {
1300 .header = HEADER_LOW("Node"),
1301 .name = "offset_node",
1302 .cmp = empty_cmp,
1303 .entry = dcacheline_node_entry,
1304 .width = 4,
1305};
1306
1222static struct c2c_dimension dim_iaddr = { 1307static struct c2c_dimension dim_iaddr = {
1223 .header = HEADER_LOW("Code address"), 1308 .header = HEADER_LOW("Code address"),
1224 .name = "iaddr", 1309 .name = "iaddr",
@@ -1538,7 +1623,10 @@ static struct c2c_dimension dim_dcacheline_num_empty = {
1538 1623
1539static struct c2c_dimension *dimensions[] = { 1624static struct c2c_dimension *dimensions[] = {
1540 &dim_dcacheline, 1625 &dim_dcacheline,
1626 &dim_dcacheline_node,
1627 &dim_dcacheline_count,
1541 &dim_offset, 1628 &dim_offset,
1629 &dim_offset_node,
1542 &dim_iaddr, 1630 &dim_iaddr,
1543 &dim_tot_hitm, 1631 &dim_tot_hitm,
1544 &dim_lcl_hitm, 1632 &dim_lcl_hitm,
@@ -1841,20 +1929,56 @@ static inline int valid_hitm_or_store(struct hist_entry *he)
1841 return has_hitm || c2c_he->stats.store; 1929 return has_hitm || c2c_he->stats.store;
1842} 1930}
1843 1931
1844static void calc_width(struct hist_entry *he) 1932static void set_node_width(struct c2c_hist_entry *c2c_he, int len)
1933{
1934 struct c2c_dimension *dim;
1935
1936 dim = &c2c.hists == c2c_he->hists ?
1937 &dim_dcacheline_node : &dim_offset_node;
1938
1939 if (len > dim->width)
1940 dim->width = len;
1941}
1942
1943static int set_nodestr(struct c2c_hist_entry *c2c_he)
1944{
1945 char buf[30];
1946 int len;
1947
1948 if (c2c_he->nodestr)
1949 return 0;
1950
1951 if (bitmap_weight(c2c_he->nodeset, c2c.nodes_cnt)) {
1952 len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt,
1953 buf, sizeof(buf));
1954 } else {
1955 len = scnprintf(buf, sizeof(buf), "N/A");
1956 }
1957
1958 set_node_width(c2c_he, len);
1959 c2c_he->nodestr = strdup(buf);
1960 return c2c_he->nodestr ? 0 : -ENOMEM;
1961}
1962
1963static void calc_width(struct c2c_hist_entry *c2c_he)
1845{ 1964{
1846 struct c2c_hists *c2c_hists; 1965 struct c2c_hists *c2c_hists;
1847 1966
1848 c2c_hists = container_of(he->hists, struct c2c_hists, hists); 1967 c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
1849 hists__calc_col_len(&c2c_hists->hists, he); 1968 hists__calc_col_len(&c2c_hists->hists, &c2c_he->he);
1969 set_nodestr(c2c_he);
1850} 1970}
1851 1971
1852static int filter_cb(struct hist_entry *he) 1972static int filter_cb(struct hist_entry *he)
1853{ 1973{
1974 struct c2c_hist_entry *c2c_he;
1975
1976 c2c_he = container_of(he, struct c2c_hist_entry, he);
1977
1854 if (c2c.show_src && !he->srcline) 1978 if (c2c.show_src && !he->srcline)
1855 he->srcline = hist_entry__get_srcline(he); 1979 he->srcline = hist_entry__get_srcline(he);
1856 1980
1857 calc_width(he); 1981 calc_width(c2c_he);
1858 1982
1859 if (!valid_hitm_or_store(he)) 1983 if (!valid_hitm_or_store(he))
1860 he->filtered = HIST_FILTER__C2C; 1984 he->filtered = HIST_FILTER__C2C;
@@ -1871,12 +1995,11 @@ static int resort_cl_cb(struct hist_entry *he)
1871 c2c_he = container_of(he, struct c2c_hist_entry, he); 1995 c2c_he = container_of(he, struct c2c_hist_entry, he);
1872 c2c_hists = c2c_he->hists; 1996 c2c_hists = c2c_he->hists;
1873 1997
1874 calc_width(he);
1875
1876 if (display && c2c_hists) { 1998 if (display && c2c_hists) {
1877 static unsigned int idx; 1999 static unsigned int idx;
1878 2000
1879 c2c_he->cacheline_idx = idx++; 2001 c2c_he->cacheline_idx = idx++;
2002 calc_width(c2c_he);
1880 2003
1881 c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort); 2004 c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
1882 2005
@@ -2350,14 +2473,66 @@ static void perf_c2c_display(struct perf_session *session)
2350} 2473}
2351#endif /* HAVE_SLANG_SUPPORT */ 2474#endif /* HAVE_SLANG_SUPPORT */
2352 2475
2353static void ui_quirks(void) 2476static char *fill_line(const char *orig, int len)
2477{
2478 int i, j, olen = strlen(orig);
2479 char *buf;
2480
2481 buf = zalloc(len + 1);
2482 if (!buf)
2483 return NULL;
2484
2485 j = len / 2 - olen / 2;
2486
2487 for (i = 0; i < j - 1; i++)
2488 buf[i] = '-';
2489
2490 buf[i++] = ' ';
2491
2492 strcpy(buf + i, orig);
2493
2494 i += olen;
2495
2496 buf[i++] = ' ';
2497
2498 for (; i < len; i++)
2499 buf[i] = '-';
2500
2501 return buf;
2502}
2503
2504static int ui_quirks(void)
2354{ 2505{
2506 const char *nodestr = "Data address";
2507 char *buf;
2508
2355 if (!c2c.use_stdio) { 2509 if (!c2c.use_stdio) {
2356 dim_offset.width = 5; 2510 dim_offset.width = 5;
2357 dim_offset.header = header_offset_tui; 2511 dim_offset.header = header_offset_tui;
2512 nodestr = "CL";
2358 } 2513 }
2359 2514
2360 dim_percent_hitm.header = percent_hitm_header[c2c.display]; 2515 dim_percent_hitm.header = percent_hitm_header[c2c.display];
2516
2517 /* Fix the zero line for dcacheline column. */
2518 buf = fill_line("Cacheline", dim_dcacheline.width +
2519 dim_dcacheline_node.width +
2520 dim_dcacheline_count.width + 4);
2521 if (!buf)
2522 return -ENOMEM;
2523
2524 dim_dcacheline.header.line[0].text = buf;
2525
2526 /* Fix the zero line for offset column. */
2527 buf = fill_line(nodestr, dim_offset.width +
2528 dim_offset_node.width +
2529 dim_dcacheline_count.width + 4);
2530 if (!buf)
2531 return -ENOMEM;
2532
2533 dim_offset.header.line[0].text = buf;
2534
2535 return 0;
2361} 2536}
2362 2537
2363#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" 2538#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
@@ -2473,7 +2648,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
2473 "percent_lcl_hitm," 2648 "percent_lcl_hitm,"
2474 "percent_stores_l1hit," 2649 "percent_stores_l1hit,"
2475 "percent_stores_l1miss," 2650 "percent_stores_l1miss,"
2476 "offset,", 2651 "offset,offset_node,dcacheline_count,",
2477 add_pid ? "pid," : "", 2652 add_pid ? "pid," : "",
2478 add_tid ? "tid," : "", 2653 add_tid ? "tid," : "",
2479 add_iaddr ? "iaddr," : "", 2654 add_iaddr ? "iaddr," : "",
@@ -2602,17 +2777,21 @@ static int perf_c2c__report(int argc, const char **argv)
2602 goto out; 2777 goto out;
2603 } 2778 }
2604 2779
2605 err = setup_callchain(session->evlist); 2780 err = mem2node__init(&c2c.mem2node, &session->header.env);
2606 if (err) 2781 if (err)
2607 goto out_session; 2782 goto out_session;
2608 2783
2784 err = setup_callchain(session->evlist);
2785 if (err)
2786 goto out_mem2node;
2787
2609 if (symbol__init(&session->header.env) < 0) 2788 if (symbol__init(&session->header.env) < 0)
2610 goto out_session; 2789 goto out_mem2node;
2611 2790
2612 /* No pipe support at the moment. */ 2791 /* No pipe support at the moment. */
2613 if (perf_data__is_pipe(session->data)) { 2792 if (perf_data__is_pipe(session->data)) {
2614 pr_debug("No pipe support at the moment.\n"); 2793 pr_debug("No pipe support at the moment.\n");
2615 goto out_session; 2794 goto out_mem2node;
2616 } 2795 }
2617 2796
2618 if (c2c.use_stdio) 2797 if (c2c.use_stdio)
@@ -2625,12 +2804,14 @@ static int perf_c2c__report(int argc, const char **argv)
2625 err = perf_session__process_events(session); 2804 err = perf_session__process_events(session);
2626 if (err) { 2805 if (err) {
2627 pr_err("failed to process sample\n"); 2806 pr_err("failed to process sample\n");
2628 goto out_session; 2807 goto out_mem2node;
2629 } 2808 }
2630 2809
2631 c2c_hists__reinit(&c2c.hists, 2810 c2c_hists__reinit(&c2c.hists,
2632 "cl_idx," 2811 "cl_idx,"
2633 "dcacheline," 2812 "dcacheline,"
2813 "dcacheline_node,"
2814 "dcacheline_count,"
2634 "tot_recs," 2815 "tot_recs,"
2635 "percent_hitm," 2816 "percent_hitm,"
2636 "tot_hitm,lcl_hitm,rmt_hitm," 2817 "tot_hitm,lcl_hitm,rmt_hitm,"
@@ -2652,10 +2833,15 @@ static int perf_c2c__report(int argc, const char **argv)
2652 2833
2653 ui_progress__finish(); 2834 ui_progress__finish();
2654 2835
2655 ui_quirks(); 2836 if (ui_quirks()) {
2837 pr_err("failed to setup UI\n");
2838 goto out_mem2node;
2839 }
2656 2840
2657 perf_c2c_display(session); 2841 perf_c2c_display(session);
2658 2842
2843out_mem2node:
2844 mem2node__exit(&c2c.mem2node);
2659out_session: 2845out_session:
2660 perf_session__delete(session); 2846 perf_session__delete(session);
2661out: 2847out:
@@ -2706,7 +2892,7 @@ static int perf_c2c__record(int argc, const char **argv)
2706 argc = parse_options(argc, argv, options, record_mem_usage, 2892 argc = parse_options(argc, argv, options, record_mem_usage,
2707 PARSE_OPT_KEEP_UNKNOWN); 2893 PARSE_OPT_KEEP_UNKNOWN);
2708 2894
2709 rec_argc = argc + 10; /* max number of arguments */ 2895 rec_argc = argc + 11; /* max number of arguments */
2710 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 2896 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2711 if (!rec_argv) 2897 if (!rec_argv)
2712 return -1; 2898 return -1;
@@ -2722,6 +2908,7 @@ static int perf_c2c__record(int argc, const char **argv)
2722 rec_argv[i++] = "-W"; 2908 rec_argv[i++] = "-W";
2723 2909
2724 rec_argv[i++] = "-d"; 2910 rec_argv[i++] = "-d";
2911 rec_argv[i++] = "--phys-data";
2725 rec_argv[i++] = "--sample-cpu"; 2912 rec_argv[i++] = "--sample-cpu";
2726 2913
2727 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 2914 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 25a42acabee1..f42f228e8899 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -72,6 +72,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
72 ssize_t size = strlen(val); 72 ssize_t size = strlen(val);
73 int flags = O_WRONLY; 73 int flags = O_WRONLY;
74 char errbuf[512]; 74 char errbuf[512];
75 char *val_copy;
75 76
76 file = get_tracing_file(name); 77 file = get_tracing_file(name);
77 if (!file) { 78 if (!file) {
@@ -91,12 +92,23 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
91 goto out; 92 goto out;
92 } 93 }
93 94
94 if (write(fd, val, size) == size) 95 /*
96 * Copy the original value and append a '\n'. Without this,
97 * the kernel can hide possible errors.
98 */
99 val_copy = strdup(val);
100 if (!val_copy)
101 goto out_close;
102 val_copy[size] = '\n';
103
104 if (write(fd, val_copy, size + 1) == size + 1)
95 ret = 0; 105 ret = 0;
96 else 106 else
97 pr_debug("write '%s' to tracing/%s failed: %s\n", 107 pr_debug("write '%s' to tracing/%s failed: %s\n",
98 val, name, str_error_r(errno, errbuf, sizeof(errbuf))); 108 val, name, str_error_r(errno, errbuf, sizeof(errbuf)));
99 109
110 free(val_copy);
111out_close:
100 close(fd); 112 close(fd);
101out: 113out:
102 put_tracing_file(file); 114 put_tracing_file(file);
@@ -280,8 +292,10 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
280 signal(SIGCHLD, sig_handler); 292 signal(SIGCHLD, sig_handler);
281 signal(SIGPIPE, sig_handler); 293 signal(SIGPIPE, sig_handler);
282 294
283 if (reset_tracing_files(ftrace) < 0) 295 if (reset_tracing_files(ftrace) < 0) {
296 pr_err("failed to reset ftrace\n");
284 goto out; 297 goto out;
298 }
285 299
286 /* reset ftrace buffer */ 300 /* reset ftrace buffer */
287 if (write_tracing_file("trace", "0") < 0) 301 if (write_tracing_file("trace", "0") < 0)
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 4aca13f23b9d..1c41b4eaf73c 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -439,7 +439,7 @@ int cmd_help(int argc, const char **argv)
439#ifdef HAVE_LIBELF_SUPPORT 439#ifdef HAVE_LIBELF_SUPPORT
440 "probe", 440 "probe",
441#endif 441#endif
442#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE) 442#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
443 "trace", 443 "trace",
444#endif 444#endif
445 NULL }; 445 NULL };
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 55d919dc5bc6..72e2ca096bf5 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -743,16 +743,23 @@ static bool verify_vcpu(int vcpu)
743static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, 743static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
744 u64 *mmap_time) 744 u64 *mmap_time)
745{ 745{
746 struct perf_evlist *evlist = kvm->evlist;
746 union perf_event *event; 747 union perf_event *event;
748 struct perf_mmap *md;
747 u64 timestamp; 749 u64 timestamp;
748 s64 n = 0; 750 s64 n = 0;
749 int err; 751 int err;
750 752
751 *mmap_time = ULLONG_MAX; 753 *mmap_time = ULLONG_MAX;
752 while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { 754 md = &evlist->mmap[idx];
753 err = perf_evlist__parse_sample_timestamp(kvm->evlist, event, &timestamp); 755 err = perf_mmap__read_init(md);
756 if (err < 0)
757 return (err == -EAGAIN) ? 0 : -1;
758
759 while ((event = perf_mmap__read_event(md)) != NULL) {
760 err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
754 if (err) { 761 if (err) {
755 perf_evlist__mmap_consume(kvm->evlist, idx); 762 perf_mmap__consume(md);
756 pr_err("Failed to parse sample\n"); 763 pr_err("Failed to parse sample\n");
757 return -1; 764 return -1;
758 } 765 }
@@ -762,7 +769,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
762 * FIXME: Here we can't consume the event, as perf_session__queue_event will 769 * FIXME: Here we can't consume the event, as perf_session__queue_event will
763 * point to it, and it'll get possibly overwritten by the kernel. 770 * point to it, and it'll get possibly overwritten by the kernel.
764 */ 771 */
765 perf_evlist__mmap_consume(kvm->evlist, idx); 772 perf_mmap__consume(md);
766 773
767 if (err) { 774 if (err) {
768 pr_err("Failed to enqueue sample: %d\n", err); 775 pr_err("Failed to enqueue sample: %d\n", err);
@@ -779,6 +786,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
779 break; 786 break;
780 } 787 }
781 788
789 perf_mmap__read_done(md);
782 return n; 790 return n;
783} 791}
784 792
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 506564651cda..57393e94d156 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -83,7 +83,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
83 }; 83 };
84 84
85 argc = parse_options(argc, argv, options, record_mem_usage, 85 argc = parse_options(argc, argv, options, record_mem_usage,
86 PARSE_OPT_STOP_AT_NON_OPTION); 86 PARSE_OPT_KEEP_UNKNOWN);
87 87
88 rec_argc = argc + 9; /* max number of arguments */ 88 rec_argc = argc + 9; /* max number of arguments */
89 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 89 rec_argv = calloc(rec_argc + 1, sizeof(char *));
@@ -436,7 +436,7 @@ int cmd_mem(int argc, const char **argv)
436 } 436 }
437 437
438 argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, 438 argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
439 mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); 439 mem_usage, PARSE_OPT_KEEP_UNKNOWN);
440 440
441 if (!argc || !(strncmp(argv[0], "rec", 3) || mem.operation)) 441 if (!argc || !(strncmp(argv[0], "rec", 3) || mem.operation))
442 usage_with_options(mem_usage, mem_options); 442 usage_with_options(mem_usage, mem_options);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a217623fec2e..22ebeb92ac51 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -45,6 +45,7 @@
45 45
46#include <errno.h> 46#include <errno.h>
47#include <inttypes.h> 47#include <inttypes.h>
48#include <locale.h>
48#include <poll.h> 49#include <poll.h>
49#include <unistd.h> 50#include <unistd.h>
50#include <sched.h> 51#include <sched.h>
@@ -70,7 +71,6 @@ struct record {
70 struct auxtrace_record *itr; 71 struct auxtrace_record *itr;
71 struct perf_evlist *evlist; 72 struct perf_evlist *evlist;
72 struct perf_session *session; 73 struct perf_session *session;
73 const char *progname;
74 int realtime_prio; 74 int realtime_prio;
75 bool no_buildid; 75 bool no_buildid;
76 bool no_buildid_set; 76 bool no_buildid_set;
@@ -273,6 +273,24 @@ static void record__read_auxtrace_snapshot(struct record *rec)
273 } 273 }
274} 274}
275 275
276static int record__auxtrace_init(struct record *rec)
277{
278 int err;
279
280 if (!rec->itr) {
281 rec->itr = auxtrace_record__init(rec->evlist, &err);
282 if (err)
283 return err;
284 }
285
286 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
287 rec->opts.auxtrace_snapshot_opts);
288 if (err)
289 return err;
290
291 return auxtrace_parse_filters(rec->evlist);
292}
293
276#else 294#else
277 295
278static inline 296static inline
@@ -293,6 +311,11 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
293 return 0; 311 return 0;
294} 312}
295 313
314static int record__auxtrace_init(struct record *rec __maybe_unused)
315{
316 return 0;
317}
318
296#endif 319#endif
297 320
298static int record__mmap_evlist(struct record *rec, 321static int record__mmap_evlist(struct record *rec,
@@ -509,7 +532,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
509 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 532 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
510 533
511 if (maps[i].base) { 534 if (maps[i].base) {
512 if (perf_mmap__push(&maps[i], overwrite, rec, record__pushfn) != 0) { 535 if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) {
513 rc = -1; 536 rc = -1;
514 goto out; 537 goto out;
515 } 538 }
@@ -731,13 +754,10 @@ static int record__synthesize(struct record *rec, bool tail)
731 return 0; 754 return 0;
732 755
733 if (data->is_pipe) { 756 if (data->is_pipe) {
734 err = perf_event__synthesize_features( 757 /*
735 tool, session, rec->evlist, process_synthesized_event); 758 * We need to synthesize events first, because some
736 if (err < 0) { 759 * features works on top of them (on report side).
737 pr_err("Couldn't synthesize features.\n"); 760 */
738 return err;
739 }
740
741 err = perf_event__synthesize_attrs(tool, session, 761 err = perf_event__synthesize_attrs(tool, session,
742 process_synthesized_event); 762 process_synthesized_event);
743 if (err < 0) { 763 if (err < 0) {
@@ -745,6 +765,13 @@ static int record__synthesize(struct record *rec, bool tail)
745 goto out; 765 goto out;
746 } 766 }
747 767
768 err = perf_event__synthesize_features(tool, session, rec->evlist,
769 process_synthesized_event);
770 if (err < 0) {
771 pr_err("Couldn't synthesize features.\n");
772 return err;
773 }
774
748 if (have_tracepoints(&rec->evlist->entries)) { 775 if (have_tracepoints(&rec->evlist->entries)) {
749 /* 776 /*
750 * FIXME err <= 0 here actually means that 777 * FIXME err <= 0 here actually means that
@@ -830,7 +857,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
830 int status = 0; 857 int status = 0;
831 unsigned long waking = 0; 858 unsigned long waking = 0;
832 const bool forks = argc > 0; 859 const bool forks = argc > 0;
833 struct machine *machine;
834 struct perf_tool *tool = &rec->tool; 860 struct perf_tool *tool = &rec->tool;
835 struct record_opts *opts = &rec->opts; 861 struct record_opts *opts = &rec->opts;
836 struct perf_data *data = &rec->data; 862 struct perf_data *data = &rec->data;
@@ -838,8 +864,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
838 bool disabled = false, draining = false; 864 bool disabled = false, draining = false;
839 int fd; 865 int fd;
840 866
841 rec->progname = argv[0];
842
843 atexit(record__sig_exit); 867 atexit(record__sig_exit);
844 signal(SIGCHLD, sig_handler); 868 signal(SIGCHLD, sig_handler);
845 signal(SIGINT, sig_handler); 869 signal(SIGINT, sig_handler);
@@ -935,8 +959,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
935 goto out_child; 959 goto out_child;
936 } 960 }
937 961
938 machine = &session->machines.host;
939
940 err = record__synthesize(rec, false); 962 err = record__synthesize(rec, false);
941 if (err < 0) 963 if (err < 0)
942 goto out_child; 964 goto out_child;
@@ -964,6 +986,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
964 * Let the child rip 986 * Let the child rip
965 */ 987 */
966 if (forks) { 988 if (forks) {
989 struct machine *machine = &session->machines.host;
967 union perf_event *event; 990 union perf_event *event;
968 pid_t tgid; 991 pid_t tgid;
969 992
@@ -1260,10 +1283,12 @@ static int perf_record_config(const char *var, const char *value, void *cb)
1260 return -1; 1283 return -1;
1261 return 0; 1284 return 0;
1262 } 1285 }
1263 if (!strcmp(var, "record.call-graph")) 1286 if (!strcmp(var, "record.call-graph")) {
1264 var = "call-graph.record-mode"; /* fall-through */ 1287 var = "call-graph.record-mode";
1288 return perf_default_config(var, value, cb);
1289 }
1265 1290
1266 return perf_default_config(var, value, cb); 1291 return 0;
1267} 1292}
1268 1293
1269struct clockid_map { 1294struct clockid_map {
@@ -1551,7 +1576,11 @@ static struct option __record_options[] = {
1551 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 1576 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1552 "synthesize non-sample events at the end of output"), 1577 "synthesize non-sample events at the end of output"),
1553 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1578 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1554 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1579 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1580 "Fail if the specified frequency can't be used"),
1581 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
1582 "profile at this frequency",
1583 record__parse_freq),
1555 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1584 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1556 "number of mmap data pages and AUX area tracing mmap pages", 1585 "number of mmap data pages and AUX area tracing mmap pages",
1557 record__parse_mmap_pages), 1586 record__parse_mmap_pages),
@@ -1660,6 +1689,8 @@ int cmd_record(int argc, const char **argv)
1660 struct record *rec = &record; 1689 struct record *rec = &record;
1661 char errbuf[BUFSIZ]; 1690 char errbuf[BUFSIZ];
1662 1691
1692 setlocale(LC_ALL, "");
1693
1663#ifndef HAVE_LIBBPF_SUPPORT 1694#ifndef HAVE_LIBBPF_SUPPORT
1664# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 1695# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
1665 set_nobuild('\0', "clang-path", true); 1696 set_nobuild('\0', "clang-path", true);
@@ -1720,17 +1751,6 @@ int cmd_record(int argc, const char **argv)
1720 alarm(rec->switch_output.time); 1751 alarm(rec->switch_output.time);
1721 } 1752 }
1722 1753
1723 if (!rec->itr) {
1724 rec->itr = auxtrace_record__init(rec->evlist, &err);
1725 if (err)
1726 goto out;
1727 }
1728
1729 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1730 rec->opts.auxtrace_snapshot_opts);
1731 if (err)
1732 goto out;
1733
1734 /* 1754 /*
1735 * Allow aliases to facilitate the lookup of symbols for address 1755 * Allow aliases to facilitate the lookup of symbols for address
1736 * filters. Refer to auxtrace_parse_filters(). 1756 * filters. Refer to auxtrace_parse_filters().
@@ -1739,7 +1759,7 @@ int cmd_record(int argc, const char **argv)
1739 1759
1740 symbol__init(NULL); 1760 symbol__init(NULL);
1741 1761
1742 err = auxtrace_parse_filters(rec->evlist); 1762 err = record__auxtrace_init(rec);
1743 if (err) 1763 if (err)
1744 goto out; 1764 goto out;
1745 1765
@@ -1812,7 +1832,7 @@ int cmd_record(int argc, const char **argv)
1812 err = target__validate(&rec->opts.target); 1832 err = target__validate(&rec->opts.target);
1813 if (err) { 1833 if (err) {
1814 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 1834 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
1815 ui__warning("%s", errbuf); 1835 ui__warning("%s\n", errbuf);
1816 } 1836 }
1817 1837
1818 err = target__parse_uid(&rec->opts.target); 1838 err = target__parse_uid(&rec->opts.target);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4ad5dc649716..0f198f6d9b77 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -68,6 +68,7 @@ struct report {
68 bool header; 68 bool header;
69 bool header_only; 69 bool header_only;
70 bool nonany_branch_mode; 70 bool nonany_branch_mode;
71 bool group_set;
71 int max_stack; 72 int max_stack;
72 struct perf_read_values show_threads_values; 73 struct perf_read_values show_threads_values;
73 const char *pretty_printing_style; 74 const char *pretty_printing_style;
@@ -193,6 +194,45 @@ out:
193 return err; 194 return err;
194} 195}
195 196
197/*
198 * Events in data file are not collect in groups, but we still want
199 * the group display. Set the artificial group and set the leader's
200 * forced_leader flag to notify the display code.
201 */
202static void setup_forced_leader(struct report *report,
203 struct perf_evlist *evlist)
204{
205 if (report->group_set && !evlist->nr_groups) {
206 struct perf_evsel *leader = perf_evlist__first(evlist);
207
208 perf_evlist__set_leader(evlist);
209 leader->forced_leader = true;
210 }
211}
212
213static int process_feature_event(struct perf_tool *tool,
214 union perf_event *event,
215 struct perf_session *session __maybe_unused)
216{
217 struct report *rep = container_of(tool, struct report, tool);
218
219 if (event->feat.feat_id < HEADER_LAST_FEATURE)
220 return perf_event__process_feature(tool, event, session);
221
222 if (event->feat.feat_id != HEADER_LAST_FEATURE) {
223 pr_err("failed: wrong feature ID: %" PRIu64 "\n",
224 event->feat.feat_id);
225 return -1;
226 }
227
228 /*
229 * All features are received, we can force the
230 * group if needed.
231 */
232 setup_forced_leader(rep, session->evlist);
233 return 0;
234}
235
196static int process_sample_event(struct perf_tool *tool, 236static int process_sample_event(struct perf_tool *tool,
197 union perf_event *event, 237 union perf_event *event,
198 struct perf_sample *sample, 238 struct perf_sample *sample,
@@ -400,8 +440,10 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
400 440
401 nr_samples = convert_unit(nr_samples, &unit); 441 nr_samples = convert_unit(nr_samples, &unit);
402 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit); 442 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
403 if (evname != NULL) 443 if (evname != NULL) {
404 ret += fprintf(fp, " of event '%s'", evname); 444 ret += fprintf(fp, " of event%s '%s'",
445 evsel->nr_members > 1 ? "s" : "", evname);
446 }
405 447
406 if (rep->time_str) 448 if (rep->time_str)
407 ret += fprintf(fp, " (time slices: %s)", rep->time_str); 449 ret += fprintf(fp, " (time slices: %s)", rep->time_str);
@@ -614,6 +656,7 @@ static int stats_print(struct report *rep)
614static void tasks_setup(struct report *rep) 656static void tasks_setup(struct report *rep)
615{ 657{
616 memset(&rep->tool, 0, sizeof(rep->tool)); 658 memset(&rep->tool, 0, sizeof(rep->tool));
659 rep->tool.ordered_events = true;
617 if (rep->mmaps_mode) { 660 if (rep->mmaps_mode) {
618 rep->tool.mmap = perf_event__process_mmap; 661 rep->tool.mmap = perf_event__process_mmap;
619 rep->tool.mmap2 = perf_event__process_mmap2; 662 rep->tool.mmap2 = perf_event__process_mmap2;
@@ -954,7 +997,7 @@ int cmd_report(int argc, const char **argv)
954 .id_index = perf_event__process_id_index, 997 .id_index = perf_event__process_id_index,
955 .auxtrace_info = perf_event__process_auxtrace_info, 998 .auxtrace_info = perf_event__process_auxtrace_info,
956 .auxtrace = perf_event__process_auxtrace, 999 .auxtrace = perf_event__process_auxtrace,
957 .feature = perf_event__process_feature, 1000 .feature = process_feature_event,
958 .ordered_events = true, 1001 .ordered_events = true,
959 .ordering_requires_timestamps = true, 1002 .ordering_requires_timestamps = true,
960 }, 1003 },
@@ -975,6 +1018,8 @@ int cmd_report(int argc, const char **argv)
975 OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"), 1018 OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"),
976 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1019 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
977 "file", "vmlinux pathname"), 1020 "file", "vmlinux pathname"),
1021 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1022 "don't load vmlinux even if found"),
978 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 1023 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
979 "file", "kallsyms pathname"), 1024 "file", "kallsyms pathname"),
980 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 1025 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
@@ -1056,7 +1101,7 @@ int cmd_report(int argc, const char **argv)
1056 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1101 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1057 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1102 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1058 "Show a column with the sum of periods"), 1103 "Show a column with the sum of periods"),
1059 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 1104 OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
1060 "Show event group information together"), 1105 "Show event group information together"),
1061 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", 1106 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
1062 "use branch records for per branch histogram filling", 1107 "use branch records for per branch histogram filling",
@@ -1173,6 +1218,8 @@ repeat:
1173 has_br_stack = perf_header__has_feat(&session->header, 1218 has_br_stack = perf_header__has_feat(&session->header,
1174 HEADER_BRANCH_STACK); 1219 HEADER_BRANCH_STACK);
1175 1220
1221 setup_forced_leader(&report, session->evlist);
1222
1176 if (itrace_synth_opts.last_branch) 1223 if (itrace_synth_opts.last_branch)
1177 has_br_stack = true; 1224 has_br_stack = true;
1178 1225
@@ -1295,6 +1342,7 @@ repeat:
1295 symbol_conf.priv_size += sizeof(u32); 1342 symbol_conf.priv_size += sizeof(u32);
1296 symbol_conf.sort_by_name = true; 1343 symbol_conf.sort_by_name = true;
1297 } 1344 }
1345 annotation_config__init();
1298 } 1346 }
1299 1347
1300 if (symbol__init(&session->header.env) < 0) 1348 if (symbol__init(&session->header.env) < 0)
@@ -1332,6 +1380,15 @@ repeat:
1332 report.range_num = 1; 1380 report.range_num = 1;
1333 } 1381 }
1334 1382
1383 if (session->tevent.pevent &&
1384 pevent_set_function_resolver(session->tevent.pevent,
1385 machine__resolve_kernel_addr,
1386 &session->machines.host) < 0) {
1387 pr_err("%s: failed to set libtraceevent function resolver\n",
1388 __func__);
1389 return -1;
1390 }
1391
1335 sort__setup_elide(stdout); 1392 sort__setup_elide(stdout);
1336 1393
1337 ret = __cmd_report(&report); 1394 ret = __cmd_report(&report);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 83283fedb00f..4dfdee668b0c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -254,6 +254,10 @@ struct thread_runtime {
254 u64 total_delay_time; 254 u64 total_delay_time;
255 255
256 int last_state; 256 int last_state;
257
258 char shortname[3];
259 bool comm_changed;
260
257 u64 migrations; 261 u64 migrations;
258}; 262};
259 263
@@ -897,6 +901,37 @@ struct sort_dimension {
897 struct list_head list; 901 struct list_head list;
898}; 902};
899 903
904/*
905 * handle runtime stats saved per thread
906 */
907static struct thread_runtime *thread__init_runtime(struct thread *thread)
908{
909 struct thread_runtime *r;
910
911 r = zalloc(sizeof(struct thread_runtime));
912 if (!r)
913 return NULL;
914
915 init_stats(&r->run_stats);
916 thread__set_priv(thread, r);
917
918 return r;
919}
920
921static struct thread_runtime *thread__get_runtime(struct thread *thread)
922{
923 struct thread_runtime *tr;
924
925 tr = thread__priv(thread);
926 if (tr == NULL) {
927 tr = thread__init_runtime(thread);
928 if (tr == NULL)
929 pr_debug("Failed to malloc memory for runtime data.\n");
930 }
931
932 return tr;
933}
934
900static int 935static int
901thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r) 936thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r)
902{ 937{
@@ -1480,6 +1515,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1480{ 1515{
1481 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 1516 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
1482 struct thread *sched_in; 1517 struct thread *sched_in;
1518 struct thread_runtime *tr;
1483 int new_shortname; 1519 int new_shortname;
1484 u64 timestamp0, timestamp = sample->time; 1520 u64 timestamp0, timestamp = sample->time;
1485 s64 delta; 1521 s64 delta;
@@ -1519,22 +1555,28 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1519 if (sched_in == NULL) 1555 if (sched_in == NULL)
1520 return -1; 1556 return -1;
1521 1557
1558 tr = thread__get_runtime(sched_in);
1559 if (tr == NULL) {
1560 thread__put(sched_in);
1561 return -1;
1562 }
1563
1522 sched->curr_thread[this_cpu] = thread__get(sched_in); 1564 sched->curr_thread[this_cpu] = thread__get(sched_in);
1523 1565
1524 printf(" "); 1566 printf(" ");
1525 1567
1526 new_shortname = 0; 1568 new_shortname = 0;
1527 if (!sched_in->shortname[0]) { 1569 if (!tr->shortname[0]) {
1528 if (!strcmp(thread__comm_str(sched_in), "swapper")) { 1570 if (!strcmp(thread__comm_str(sched_in), "swapper")) {
1529 /* 1571 /*
1530 * Don't allocate a letter-number for swapper:0 1572 * Don't allocate a letter-number for swapper:0
1531 * as a shortname. Instead, we use '.' for it. 1573 * as a shortname. Instead, we use '.' for it.
1532 */ 1574 */
1533 sched_in->shortname[0] = '.'; 1575 tr->shortname[0] = '.';
1534 sched_in->shortname[1] = ' '; 1576 tr->shortname[1] = ' ';
1535 } else { 1577 } else {
1536 sched_in->shortname[0] = sched->next_shortname1; 1578 tr->shortname[0] = sched->next_shortname1;
1537 sched_in->shortname[1] = sched->next_shortname2; 1579 tr->shortname[1] = sched->next_shortname2;
1538 1580
1539 if (sched->next_shortname1 < 'Z') { 1581 if (sched->next_shortname1 < 'Z') {
1540 sched->next_shortname1++; 1582 sched->next_shortname1++;
@@ -1552,6 +1594,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1552 for (i = 0; i < cpus_nr; i++) { 1594 for (i = 0; i < cpus_nr; i++) {
1553 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; 1595 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;
1554 struct thread *curr_thread = sched->curr_thread[cpu]; 1596 struct thread *curr_thread = sched->curr_thread[cpu];
1597 struct thread_runtime *curr_tr;
1555 const char *pid_color = color; 1598 const char *pid_color = color;
1556 const char *cpu_color = color; 1599 const char *cpu_color = color;
1557 1600
@@ -1569,9 +1612,14 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1569 else 1612 else
1570 color_fprintf(stdout, cpu_color, "*"); 1613 color_fprintf(stdout, cpu_color, "*");
1571 1614
1572 if (sched->curr_thread[cpu]) 1615 if (sched->curr_thread[cpu]) {
1573 color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); 1616 curr_tr = thread__get_runtime(sched->curr_thread[cpu]);
1574 else 1617 if (curr_tr == NULL) {
1618 thread__put(sched_in);
1619 return -1;
1620 }
1621 color_fprintf(stdout, pid_color, "%2s ", curr_tr->shortname);
1622 } else
1575 color_fprintf(stdout, color, " "); 1623 color_fprintf(stdout, color, " ");
1576 } 1624 }
1577 1625
@@ -1580,14 +1628,15 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1580 1628
1581 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp)); 1629 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp));
1582 color_fprintf(stdout, color, " %12s secs ", stimestamp); 1630 color_fprintf(stdout, color, " %12s secs ", stimestamp);
1583 if (new_shortname || (verbose > 0 && sched_in->tid)) { 1631 if (new_shortname || tr->comm_changed || (verbose > 0 && sched_in->tid)) {
1584 const char *pid_color = color; 1632 const char *pid_color = color;
1585 1633
1586 if (thread__has_color(sched_in)) 1634 if (thread__has_color(sched_in))
1587 pid_color = COLOR_PIDS; 1635 pid_color = COLOR_PIDS;
1588 1636
1589 color_fprintf(stdout, pid_color, "%s => %s:%d", 1637 color_fprintf(stdout, pid_color, "%s => %s:%d",
1590 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); 1638 tr->shortname, thread__comm_str(sched_in), sched_in->tid);
1639 tr->comm_changed = false;
1591 } 1640 }
1592 1641
1593 if (sched->map.comp && new_cpu) 1642 if (sched->map.comp && new_cpu)
@@ -1691,6 +1740,37 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1691 return err; 1740 return err;
1692} 1741}
1693 1742
1743static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused,
1744 union perf_event *event,
1745 struct perf_sample *sample,
1746 struct machine *machine)
1747{
1748 struct thread *thread;
1749 struct thread_runtime *tr;
1750 int err;
1751
1752 err = perf_event__process_comm(tool, event, sample, machine);
1753 if (err)
1754 return err;
1755
1756 thread = machine__find_thread(machine, sample->pid, sample->tid);
1757 if (!thread) {
1758 pr_err("Internal error: can't find thread\n");
1759 return -1;
1760 }
1761
1762 tr = thread__get_runtime(thread);
1763 if (tr == NULL) {
1764 thread__put(thread);
1765 return -1;
1766 }
1767
1768 tr->comm_changed = true;
1769 thread__put(thread);
1770
1771 return 0;
1772}
1773
1694static int perf_sched__read_events(struct perf_sched *sched) 1774static int perf_sched__read_events(struct perf_sched *sched)
1695{ 1775{
1696 const struct perf_evsel_str_handler handlers[] = { 1776 const struct perf_evsel_str_handler handlers[] = {
@@ -2200,37 +2280,6 @@ static void save_idle_callchain(struct idle_thread_runtime *itr,
2200 callchain_cursor__copy(&itr->cursor, &callchain_cursor); 2280 callchain_cursor__copy(&itr->cursor, &callchain_cursor);
2201} 2281}
2202 2282
2203/*
2204 * handle runtime stats saved per thread
2205 */
2206static struct thread_runtime *thread__init_runtime(struct thread *thread)
2207{
2208 struct thread_runtime *r;
2209
2210 r = zalloc(sizeof(struct thread_runtime));
2211 if (!r)
2212 return NULL;
2213
2214 init_stats(&r->run_stats);
2215 thread__set_priv(thread, r);
2216
2217 return r;
2218}
2219
2220static struct thread_runtime *thread__get_runtime(struct thread *thread)
2221{
2222 struct thread_runtime *tr;
2223
2224 tr = thread__priv(thread);
2225 if (tr == NULL) {
2226 tr = thread__init_runtime(thread);
2227 if (tr == NULL)
2228 pr_debug("Failed to malloc memory for runtime data.\n");
2229 }
2230
2231 return tr;
2232}
2233
2234static struct thread *timehist_get_thread(struct perf_sched *sched, 2283static struct thread *timehist_get_thread(struct perf_sched *sched,
2235 struct perf_sample *sample, 2284 struct perf_sample *sample,
2236 struct machine *machine, 2285 struct machine *machine,
@@ -3291,7 +3340,7 @@ int cmd_sched(int argc, const char **argv)
3291 struct perf_sched sched = { 3340 struct perf_sched sched = {
3292 .tool = { 3341 .tool = {
3293 .sample = perf_sched__process_tracepoint_sample, 3342 .sample = perf_sched__process_tracepoint_sample,
3294 .comm = perf_event__process_comm, 3343 .comm = perf_sched__process_comm,
3295 .namespaces = perf_event__process_namespaces, 3344 .namespaces = perf_event__process_namespaces,
3296 .lost = perf_event__process_lost, 3345 .lost = perf_event__process_lost,
3297 .fork = perf_sched__process_fork_event, 3346 .fork = perf_sched__process_fork_event,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ab19a6ee4093..e0a9845b6cbc 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -657,8 +657,11 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
657 break; 657 break;
658 case PERF_RECORD_SWITCH: 658 case PERF_RECORD_SWITCH:
659 case PERF_RECORD_SWITCH_CPU_WIDE: 659 case PERF_RECORD_SWITCH_CPU_WIDE:
660 if (has(SWITCH_OUT)) 660 if (has(SWITCH_OUT)) {
661 ret += fprintf(fp, "S"); 661 ret += fprintf(fp, "S");
662 if (sample->misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT)
663 ret += fprintf(fp, "p");
664 }
662 default: 665 default:
663 break; 666 break;
664 } 667 }
@@ -1489,6 +1492,7 @@ struct perf_script {
1489 bool show_switch_events; 1492 bool show_switch_events;
1490 bool show_namespace_events; 1493 bool show_namespace_events;
1491 bool show_lost_events; 1494 bool show_lost_events;
1495 bool show_round_events;
1492 bool allocated; 1496 bool allocated;
1493 bool per_event_dump; 1497 bool per_event_dump;
1494 struct cpu_map *cpus; 1498 struct cpu_map *cpus;
@@ -2104,6 +2108,16 @@ process_lost_event(struct perf_tool *tool,
2104 return 0; 2108 return 0;
2105} 2109}
2106 2110
2111static int
2112process_finished_round_event(struct perf_tool *tool __maybe_unused,
2113 union perf_event *event,
2114 struct ordered_events *oe __maybe_unused)
2115
2116{
2117 perf_event__fprintf(event, stdout);
2118 return 0;
2119}
2120
2107static void sig_handler(int sig __maybe_unused) 2121static void sig_handler(int sig __maybe_unused)
2108{ 2122{
2109 session_done = 1; 2123 session_done = 1;
@@ -2200,6 +2214,10 @@ static int __cmd_script(struct perf_script *script)
2200 script->tool.namespaces = process_namespaces_event; 2214 script->tool.namespaces = process_namespaces_event;
2201 if (script->show_lost_events) 2215 if (script->show_lost_events)
2202 script->tool.lost = process_lost_event; 2216 script->tool.lost = process_lost_event;
2217 if (script->show_round_events) {
2218 script->tool.ordered_events = false;
2219 script->tool.finished_round = process_finished_round_event;
2220 }
2203 2221
2204 if (perf_script__setup_per_event_dump(script)) { 2222 if (perf_script__setup_per_event_dump(script)) {
2205 pr_err("Couldn't create the per event dump files\n"); 2223 pr_err("Couldn't create the per event dump files\n");
@@ -2659,8 +2677,8 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
2659 } 2677 }
2660 2678
2661 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2679 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2662 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 2680 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2663 lang_dirent->d_name); 2681 lang_dirent->d_name);
2664 lang_dir = opendir(lang_path); 2682 lang_dir = opendir(lang_path);
2665 if (!lang_dir) 2683 if (!lang_dir)
2666 continue; 2684 continue;
@@ -2669,8 +2687,8 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
2669 script_root = get_script_root(script_dirent, REPORT_SUFFIX); 2687 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
2670 if (script_root) { 2688 if (script_root) {
2671 desc = script_desc__findnew(script_root); 2689 desc = script_desc__findnew(script_root);
2672 snprintf(script_path, MAXPATHLEN, "%s/%s", 2690 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2673 lang_path, script_dirent->d_name); 2691 lang_path, script_dirent->d_name);
2674 read_script_info(desc, script_path); 2692 read_script_info(desc, script_path);
2675 free(script_root); 2693 free(script_root);
2676 } 2694 }
@@ -2706,7 +2724,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
2706 int match, len; 2724 int match, len;
2707 FILE *fp; 2725 FILE *fp;
2708 2726
2709 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname); 2727 scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);
2710 2728
2711 fp = fopen(filename, "r"); 2729 fp = fopen(filename, "r");
2712 if (!fp) 2730 if (!fp)
@@ -2784,13 +2802,13 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2784 } 2802 }
2785 2803
2786 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2804 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2787 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 2805 scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
2788 lang_dirent->d_name); 2806 lang_dirent->d_name);
2789#ifdef NO_LIBPERL 2807#ifndef HAVE_LIBPERL_SUPPORT
2790 if (strstr(lang_path, "perl")) 2808 if (strstr(lang_path, "perl"))
2791 continue; 2809 continue;
2792#endif 2810#endif
2793#ifdef NO_LIBPYTHON 2811#ifndef HAVE_LIBPYTHON_SUPPORT
2794 if (strstr(lang_path, "python")) 2812 if (strstr(lang_path, "python"))
2795 continue; 2813 continue;
2796#endif 2814#endif
@@ -2840,8 +2858,8 @@ static char *get_script_path(const char *script_root, const char *suffix)
2840 return NULL; 2858 return NULL;
2841 2859
2842 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2860 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2843 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 2861 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2844 lang_dirent->d_name); 2862 lang_dirent->d_name);
2845 lang_dir = opendir(lang_path); 2863 lang_dir = opendir(lang_path);
2846 if (!lang_dir) 2864 if (!lang_dir)
2847 continue; 2865 continue;
@@ -2852,8 +2870,8 @@ static char *get_script_path(const char *script_root, const char *suffix)
2852 free(__script_root); 2870 free(__script_root);
2853 closedir(lang_dir); 2871 closedir(lang_dir);
2854 closedir(scripts_dir); 2872 closedir(scripts_dir);
2855 snprintf(script_path, MAXPATHLEN, "%s/%s", 2873 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2856 lang_path, script_dirent->d_name); 2874 lang_path, script_dirent->d_name);
2857 return strdup(script_path); 2875 return strdup(script_path);
2858 } 2876 }
2859 free(__script_root); 2877 free(__script_root);
@@ -3139,6 +3157,8 @@ int cmd_script(int argc, const char **argv)
3139 "Show namespace events (if recorded)"), 3157 "Show namespace events (if recorded)"),
3140 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events, 3158 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
3141 "Show lost events (if recorded)"), 3159 "Show lost events (if recorded)"),
3160 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
3161 "Show round events (if recorded)"),
3142 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump, 3162 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
3143 "Dump trace output to files named by the monitored events"), 3163 "Dump trace output to files named by the monitored events"),
3144 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 3164 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 54a4c152edb3..f17dc601b0f3 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -168,9 +168,11 @@ static struct timespec ref_time;
168static struct cpu_map *aggr_map; 168static struct cpu_map *aggr_map;
169static aggr_get_id_t aggr_get_id; 169static aggr_get_id_t aggr_get_id;
170static bool append_file; 170static bool append_file;
171static bool interval_count;
171static const char *output_name; 172static const char *output_name;
172static int output_fd; 173static int output_fd;
173static int print_free_counters_hint; 174static int print_free_counters_hint;
175static int print_mixed_hw_group_error;
174 176
175struct perf_stat { 177struct perf_stat {
176 bool record; 178 bool record;
@@ -507,14 +509,13 @@ static int perf_stat_synthesize_config(bool is_pipe)
507 509
508#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 510#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
509 511
510static int __store_counter_ids(struct perf_evsel *counter, 512static int __store_counter_ids(struct perf_evsel *counter)
511 struct cpu_map *cpus,
512 struct thread_map *threads)
513{ 513{
514 int cpu, thread; 514 int cpu, thread;
515 515
516 for (cpu = 0; cpu < cpus->nr; cpu++) { 516 for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
517 for (thread = 0; thread < threads->nr; thread++) { 517 for (thread = 0; thread < xyarray__max_y(counter->fd);
518 thread++) {
518 int fd = FD(counter, cpu, thread); 519 int fd = FD(counter, cpu, thread);
519 520
520 if (perf_evlist__id_add_fd(evsel_list, counter, 521 if (perf_evlist__id_add_fd(evsel_list, counter,
@@ -534,7 +535,7 @@ static int store_counter_ids(struct perf_evsel *counter)
534 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr)) 535 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
535 return -ENOMEM; 536 return -ENOMEM;
536 537
537 return __store_counter_ids(counter, cpus, threads); 538 return __store_counter_ids(counter);
538} 539}
539 540
540static bool perf_evsel__should_store_id(struct perf_evsel *counter) 541static bool perf_evsel__should_store_id(struct perf_evsel *counter)
@@ -571,6 +572,8 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
571static int __run_perf_stat(int argc, const char **argv) 572static int __run_perf_stat(int argc, const char **argv)
572{ 573{
573 int interval = stat_config.interval; 574 int interval = stat_config.interval;
575 int times = stat_config.times;
576 int timeout = stat_config.timeout;
574 char msg[BUFSIZ]; 577 char msg[BUFSIZ];
575 unsigned long long t0, t1; 578 unsigned long long t0, t1;
576 struct perf_evsel *counter; 579 struct perf_evsel *counter;
@@ -584,6 +587,9 @@ static int __run_perf_stat(int argc, const char **argv)
584 if (interval) { 587 if (interval) {
585 ts.tv_sec = interval / USEC_PER_MSEC; 588 ts.tv_sec = interval / USEC_PER_MSEC;
586 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC; 589 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC;
590 } else if (timeout) {
591 ts.tv_sec = timeout / USEC_PER_MSEC;
592 ts.tv_nsec = (timeout % USEC_PER_MSEC) * NSEC_PER_MSEC;
587 } else { 593 } else {
588 ts.tv_sec = 1; 594 ts.tv_sec = 1;
589 ts.tv_nsec = 0; 595 ts.tv_nsec = 0;
@@ -632,7 +638,19 @@ try_again:
632 if (verbose > 0) 638 if (verbose > 0)
633 ui__warning("%s\n", msg); 639 ui__warning("%s\n", msg);
634 goto try_again; 640 goto try_again;
635 } 641 } else if (target__has_per_thread(&target) &&
642 evsel_list->threads &&
643 evsel_list->threads->err_thread != -1) {
644 /*
645 * For global --per-thread case, skip current
646 * error thread.
647 */
648 if (!thread_map__remove(evsel_list->threads,
649 evsel_list->threads->err_thread)) {
650 evsel_list->threads->err_thread = -1;
651 goto try_again;
652 }
653 }
636 654
637 perf_evsel__open_strerror(counter, &target, 655 perf_evsel__open_strerror(counter, &target,
638 errno, msg, sizeof(msg)); 656 errno, msg, sizeof(msg));
@@ -696,10 +714,14 @@ try_again:
696 perf_evlist__start_workload(evsel_list); 714 perf_evlist__start_workload(evsel_list);
697 enable_counters(); 715 enable_counters();
698 716
699 if (interval) { 717 if (interval || timeout) {
700 while (!waitpid(child_pid, &status, WNOHANG)) { 718 while (!waitpid(child_pid, &status, WNOHANG)) {
701 nanosleep(&ts, NULL); 719 nanosleep(&ts, NULL);
720 if (timeout)
721 break;
702 process_interval(); 722 process_interval();
723 if (interval_count && !(--times))
724 break;
703 } 725 }
704 } 726 }
705 waitpid(child_pid, &status, 0); 727 waitpid(child_pid, &status, 0);
@@ -716,8 +738,13 @@ try_again:
716 enable_counters(); 738 enable_counters();
717 while (!done) { 739 while (!done) {
718 nanosleep(&ts, NULL); 740 nanosleep(&ts, NULL);
719 if (interval) 741 if (timeout)
742 break;
743 if (interval) {
720 process_interval(); 744 process_interval();
745 if (interval_count && !(--times))
746 break;
747 }
721 } 748 }
722 } 749 }
723 750
@@ -1100,6 +1127,30 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1100 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 1127 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
1101} 1128}
1102 1129
1130static bool is_mixed_hw_group(struct perf_evsel *counter)
1131{
1132 struct perf_evlist *evlist = counter->evlist;
1133 u32 pmu_type = counter->attr.type;
1134 struct perf_evsel *pos;
1135
1136 if (counter->nr_members < 2)
1137 return false;
1138
1139 evlist__for_each_entry(evlist, pos) {
1140 /* software events can be part of any hardware group */
1141 if (pos->attr.type == PERF_TYPE_SOFTWARE)
1142 continue;
1143 if (pmu_type == PERF_TYPE_SOFTWARE) {
1144 pmu_type = pos->attr.type;
1145 continue;
1146 }
1147 if (pmu_type != pos->attr.type)
1148 return true;
1149 }
1150
1151 return false;
1152}
1153
1103static void printout(int id, int nr, struct perf_evsel *counter, double uval, 1154static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1104 char *prefix, u64 run, u64 ena, double noise, 1155 char *prefix, u64 run, u64 ena, double noise,
1105 struct runtime_stat *st) 1156 struct runtime_stat *st)
@@ -1152,8 +1203,11 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1152 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1203 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1153 csv_sep); 1204 csv_sep);
1154 1205
1155 if (counter->supported) 1206 if (counter->supported) {
1156 print_free_counters_hint = 1; 1207 print_free_counters_hint = 1;
1208 if (is_mixed_hw_group(counter))
1209 print_mixed_hw_group_error = 1;
1210 }
1157 1211
1158 fprintf(stat_config.output, "%-*s%s", 1212 fprintf(stat_config.output, "%-*s%s",
1159 csv_output ? 0 : unit_width, 1213 csv_output ? 0 : unit_width,
@@ -1225,6 +1279,34 @@ static void aggr_update_shadow(void)
1225 } 1279 }
1226} 1280}
1227 1281
1282static void uniquify_event_name(struct perf_evsel *counter)
1283{
1284 char *new_name;
1285 char *config;
1286
1287 if (counter->uniquified_name ||
1288 !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
1289 strlen(counter->pmu_name)))
1290 return;
1291
1292 config = strchr(counter->name, '/');
1293 if (config) {
1294 if (asprintf(&new_name,
1295 "%s%s", counter->pmu_name, config) > 0) {
1296 free(counter->name);
1297 counter->name = new_name;
1298 }
1299 } else {
1300 if (asprintf(&new_name,
1301 "%s [%s]", counter->name, counter->pmu_name) > 0) {
1302 free(counter->name);
1303 counter->name = new_name;
1304 }
1305 }
1306
1307 counter->uniquified_name = true;
1308}
1309
1228static void collect_all_aliases(struct perf_evsel *counter, 1310static void collect_all_aliases(struct perf_evsel *counter,
1229 void (*cb)(struct perf_evsel *counter, void *data, 1311 void (*cb)(struct perf_evsel *counter, void *data,
1230 bool first), 1312 bool first),
@@ -1253,7 +1335,9 @@ static bool collect_data(struct perf_evsel *counter,
1253 if (counter->merged_stat) 1335 if (counter->merged_stat)
1254 return false; 1336 return false;
1255 cb(counter, data, true); 1337 cb(counter, data, true);
1256 if (!no_merge && counter->auto_merge_stats) 1338 if (no_merge)
1339 uniquify_event_name(counter);
1340 else if (counter->auto_merge_stats)
1257 collect_all_aliases(counter, cb, data); 1341 collect_all_aliases(counter, cb, data);
1258 return true; 1342 return true;
1259} 1343}
@@ -1704,6 +1788,11 @@ static void print_footer(void)
1704" echo 0 > /proc/sys/kernel/nmi_watchdog\n" 1788" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1705" perf stat ...\n" 1789" perf stat ...\n"
1706" echo 1 > /proc/sys/kernel/nmi_watchdog\n"); 1790" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1791
1792 if (print_mixed_hw_group_error)
1793 fprintf(output,
1794 "The events in group usually have to be from "
1795 "the same PMU. Try reorganizing the group.\n");
1707} 1796}
1708 1797
1709static void print_counters(struct timespec *ts, int argc, const char **argv) 1798static void print_counters(struct timespec *ts, int argc, const char **argv)
@@ -1890,7 +1979,12 @@ static const struct option stat_options[] = {
1890 OPT_STRING(0, "post", &post_cmd, "command", 1979 OPT_STRING(0, "post", &post_cmd, "command",
1891 "command to run after to the measured command"), 1980 "command to run after to the measured command"),
1892 OPT_UINTEGER('I', "interval-print", &stat_config.interval, 1981 OPT_UINTEGER('I', "interval-print", &stat_config.interval,
1893 "print counts at regular interval in ms (>= 10)"), 1982 "print counts at regular interval in ms "
1983 "(overhead is possible for values <= 100ms)"),
1984 OPT_INTEGER(0, "interval-count", &stat_config.times,
1985 "print counts for fixed number of times"),
1986 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
1987 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
1894 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, 1988 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
1895 "aggregate counts per processor socket", AGGR_SOCKET), 1989 "aggregate counts per processor socket", AGGR_SOCKET),
1896 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, 1990 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
@@ -2274,11 +2368,16 @@ static int add_default_attributes(void)
2274 return 0; 2368 return 0;
2275 2369
2276 if (transaction_run) { 2370 if (transaction_run) {
2371 struct parse_events_error errinfo;
2372
2277 if (pmu_have_event("cpu", "cycles-ct") && 2373 if (pmu_have_event("cpu", "cycles-ct") &&
2278 pmu_have_event("cpu", "el-start")) 2374 pmu_have_event("cpu", "el-start"))
2279 err = parse_events(evsel_list, transaction_attrs, NULL); 2375 err = parse_events(evsel_list, transaction_attrs,
2376 &errinfo);
2280 else 2377 else
2281 err = parse_events(evsel_list, transaction_limited_attrs, NULL); 2378 err = parse_events(evsel_list,
2379 transaction_limited_attrs,
2380 &errinfo);
2282 if (err) { 2381 if (err) {
2283 fprintf(stderr, "Cannot set up transaction events\n"); 2382 fprintf(stderr, "Cannot set up transaction events\n");
2284 return -1; 2383 return -1;
@@ -2688,7 +2787,7 @@ int cmd_stat(int argc, const char **argv)
2688 int status = -EINVAL, run_idx; 2787 int status = -EINVAL, run_idx;
2689 const char *mode; 2788 const char *mode;
2690 FILE *output = stderr; 2789 FILE *output = stderr;
2691 unsigned int interval; 2790 unsigned int interval, timeout;
2692 const char * const stat_subcommands[] = { "record", "report" }; 2791 const char * const stat_subcommands[] = { "record", "report" };
2693 2792
2694 setlocale(LC_ALL, ""); 2793 setlocale(LC_ALL, "");
@@ -2719,6 +2818,7 @@ int cmd_stat(int argc, const char **argv)
2719 return __cmd_report(argc, argv); 2818 return __cmd_report(argc, argv);
2720 2819
2721 interval = stat_config.interval; 2820 interval = stat_config.interval;
2821 timeout = stat_config.timeout;
2722 2822
2723 /* 2823 /*
2724 * For record command the -o is already taken care of. 2824 * For record command the -o is already taken care of.
@@ -2860,16 +2960,32 @@ int cmd_stat(int argc, const char **argv)
2860 } 2960 }
2861 } 2961 }
2862 2962
2863 if (interval && interval < 100) { 2963 if (stat_config.times && interval)
2864 if (interval < 10) { 2964 interval_count = true;
2865 pr_err("print interval must be >= 10ms\n"); 2965 else if (stat_config.times && !interval) {
2866 parse_options_usage(stat_usage, stat_options, "I", 1); 2966 pr_err("interval-count option should be used together with "
2967 "interval-print.\n");
2968 parse_options_usage(stat_usage, stat_options, "interval-count", 0);
2969 parse_options_usage(stat_usage, stat_options, "I", 1);
2970 goto out;
2971 }
2972
2973 if (timeout && timeout < 100) {
2974 if (timeout < 10) {
2975 pr_err("timeout must be >= 10ms.\n");
2976 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2867 goto out; 2977 goto out;
2868 } else 2978 } else
2869 pr_warning("print interval < 100ms. " 2979 pr_warning("timeout < 100ms. "
2870 "The overhead percentage could be high in some cases. " 2980 "The overhead percentage could be high in some cases. "
2871 "Please proceed with caution.\n"); 2981 "Please proceed with caution.\n");
2872 } 2982 }
2983 if (timeout && interval) {
2984 pr_err("timeout option is not supported with interval-print.\n");
2985 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2986 parse_options_usage(stat_usage, stat_options, "I", 1);
2987 goto out;
2988 }
2873 2989
2874 if (perf_evlist__alloc_stats(evsel_list, interval)) 2990 if (perf_evlist__alloc_stats(evsel_list, interval))
2875 goto out; 2991 goto out;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 35ac016fcb98..f39bd60d2708 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -817,14 +817,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
817 struct perf_session *session = top->session; 817 struct perf_session *session = top->session;
818 union perf_event *event; 818 union perf_event *event;
819 struct machine *machine; 819 struct machine *machine;
820 u64 end, start;
821 int ret; 820 int ret;
822 821
823 md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx]; 822 md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx];
824 if (perf_mmap__read_init(md, opts->overwrite, &start, &end) < 0) 823 if (perf_mmap__read_init(md) < 0)
825 return; 824 return;
826 825
827 while ((event = perf_mmap__read_event(md, opts->overwrite, &start, end)) != NULL) { 826 while ((event = perf_mmap__read_event(md)) != NULL) {
828 ret = perf_evlist__parse_sample(evlist, event, &sample); 827 ret = perf_evlist__parse_sample(evlist, event, &sample);
829 if (ret) { 828 if (ret) {
830 pr_err("Can't parse sample, err = %d\n", ret); 829 pr_err("Can't parse sample, err = %d\n", ret);
@@ -879,7 +878,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
879 } else 878 } else
880 ++session->evlist->stats.nr_unknown_events; 879 ++session->evlist->stats.nr_unknown_events;
881next_event: 880next_event:
882 perf_mmap__consume(md, opts->overwrite); 881 perf_mmap__consume(md);
883 } 882 }
884 883
885 perf_mmap__read_done(md); 884 perf_mmap__read_done(md);
@@ -1224,8 +1223,10 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1224 1223
1225static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused) 1224static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused)
1226{ 1225{
1227 if (!strcmp(var, "top.call-graph")) 1226 if (!strcmp(var, "top.call-graph")) {
1228 var = "call-graph.record-mode"; /* fall-through */ 1227 var = "call-graph.record-mode";
1228 return perf_default_config(var, value, cb);
1229 }
1229 if (!strcmp(var, "top.children")) { 1230 if (!strcmp(var, "top.children")) {
1230 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1231 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1231 return 0; 1232 return 0;
@@ -1307,7 +1308,9 @@ int cmd_top(int argc, const char **argv)
1307 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", 1308 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1308 "symbol to annotate"), 1309 "symbol to annotate"),
1309 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"), 1310 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
1310 OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"), 1311 OPT_CALLBACK('F', "freq", &top.record_opts, "freq or 'max'",
1312 "profile at this frequency",
1313 record__parse_freq),
1311 OPT_INTEGER('E', "entries", &top.print_entries, 1314 OPT_INTEGER('E', "entries", &top.print_entries,
1312 "display this many functions"), 1315 "display this many functions"),
1313 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1316 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1490,6 +1493,8 @@ int cmd_top(int argc, const char **argv)
1490 if (status < 0) 1493 if (status < 0)
1491 goto out_delete_evlist; 1494 goto out_delete_evlist;
1492 1495
1496 annotation_config__init();
1497
1493 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1498 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1494 if (symbol__init(NULL) < 0) 1499 if (symbol__init(NULL) < 0)
1495 return -1; 1500 return -1;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e7f1b182fc15..3ad17ee89403 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -19,6 +19,7 @@
19#include <traceevent/event-parse.h> 19#include <traceevent/event-parse.h>
20#include <api/fs/tracing_path.h> 20#include <api/fs/tracing_path.h>
21#include "builtin.h" 21#include "builtin.h"
22#include "util/cgroup.h"
22#include "util/color.h" 23#include "util/color.h"
23#include "util/debug.h" 24#include "util/debug.h"
24#include "util/env.h" 25#include "util/env.h"
@@ -83,6 +84,7 @@ struct trace {
83 struct perf_evlist *evlist; 84 struct perf_evlist *evlist;
84 struct machine *host; 85 struct machine *host;
85 struct thread *current; 86 struct thread *current;
87 struct cgroup *cgroup;
86 u64 base_time; 88 u64 base_time;
87 FILE *output; 89 FILE *output;
88 unsigned long nr_events; 90 unsigned long nr_events;
@@ -110,6 +112,7 @@ struct trace {
110 bool multiple_threads; 112 bool multiple_threads;
111 bool summary; 113 bool summary;
112 bool summary_only; 114 bool summary_only;
115 bool failure_only;
113 bool show_comm; 116 bool show_comm;
114 bool print_sample; 117 bool print_sample;
115 bool show_tool_stats; 118 bool show_tool_stats;
@@ -1563,7 +1566,7 @@ static int trace__printf_interrupted_entry(struct trace *trace)
1563 struct thread_trace *ttrace; 1566 struct thread_trace *ttrace;
1564 size_t printed; 1567 size_t printed;
1565 1568
1566 if (trace->current == NULL) 1569 if (trace->failure_only || trace->current == NULL)
1567 return 0; 1570 return 0;
1568 1571
1569 ttrace = thread__priv(trace->current); 1572 ttrace = thread__priv(trace->current);
@@ -1636,7 +1639,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1636 args, trace, thread); 1639 args, trace, thread);
1637 1640
1638 if (sc->is_exit) { 1641 if (sc->is_exit) {
1639 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { 1642 if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
1640 trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); 1643 trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output);
1641 fprintf(trace->output, "%-70s)\n", ttrace->entry_str); 1644 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
1642 } 1645 }
@@ -1740,7 +1743,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1740 } 1743 }
1741 } 1744 }
1742 1745
1743 if (trace->summary_only) 1746 if (trace->summary_only || (ret >= 0 && trace->failure_only))
1744 goto out; 1747 goto out;
1745 1748
1746 trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); 1749 trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);
@@ -1959,7 +1962,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1959 trace->output); 1962 trace->output);
1960 } 1963 }
1961 1964
1962 fprintf(trace->output, ")\n"); 1965 fprintf(trace->output, "\n");
1963 1966
1964 if (callchain_ret > 0) 1967 if (callchain_ret > 0)
1965 trace__fprintf_callchain(trace, sample); 1968 trace__fprintf_callchain(trace, sample);
@@ -2370,6 +2373,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2370 trace__sched_stat_runtime)) 2373 trace__sched_stat_runtime))
2371 goto out_error_sched_stat_runtime; 2374 goto out_error_sched_stat_runtime;
2372 2375
2376 /*
2377 * If a global cgroup was set, apply it to all the events without an
2378 * explicit cgroup. I.e.:
2379 *
2380 * trace -G A -e sched:*switch
2381 *
2382 * Will set all raw_syscalls:sys_{enter,exit}, pgfault, vfs_getname, etc
2383 * _and_ sched:sched_switch to the 'A' cgroup, while:
2384 *
2385 * trace -e sched:*switch -G A
2386 *
2387 * will only set the sched:sched_switch event to the 'A' cgroup, all the
2388 * other events (raw_syscalls:sys_{enter,exit}, etc are left "without"
2389 * a cgroup (on the root cgroup, sys wide, etc).
2390 *
2391 * Multiple cgroups:
2392 *
2393 * trace -G A -e sched:*switch -G B
2394 *
2395 * the syscall ones go to the 'A' cgroup, the sched:sched_switch goes
2396 * to the 'B' cgroup.
2397 *
2398 * evlist__set_default_cgroup() grabs a reference of the passed cgroup
2399 * only for the evsels still without a cgroup, i.e. evsel->cgroup == NULL.
2400 */
2401 if (trace->cgroup)
2402 evlist__set_default_cgroup(trace->evlist, trace->cgroup);
2403
2373 err = perf_evlist__create_maps(evlist, &trace->opts.target); 2404 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2374 if (err < 0) { 2405 if (err < 0) {
2375 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n"); 2406 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
@@ -2472,8 +2503,13 @@ again:
2472 2503
2473 for (i = 0; i < evlist->nr_mmaps; i++) { 2504 for (i = 0; i < evlist->nr_mmaps; i++) {
2474 union perf_event *event; 2505 union perf_event *event;
2506 struct perf_mmap *md;
2475 2507
2476 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 2508 md = &evlist->mmap[i];
2509 if (perf_mmap__read_init(md) < 0)
2510 continue;
2511
2512 while ((event = perf_mmap__read_event(md)) != NULL) {
2477 struct perf_sample sample; 2513 struct perf_sample sample;
2478 2514
2479 ++trace->nr_events; 2515 ++trace->nr_events;
@@ -2486,7 +2522,7 @@ again:
2486 2522
2487 trace__handle_event(trace, event, &sample); 2523 trace__handle_event(trace, event, &sample);
2488next_event: 2524next_event:
2489 perf_evlist__mmap_consume(evlist, i); 2525 perf_mmap__consume(md);
2490 2526
2491 if (interrupted) 2527 if (interrupted)
2492 goto out_disable; 2528 goto out_disable;
@@ -2496,6 +2532,7 @@ next_event:
2496 draining = true; 2532 draining = true;
2497 } 2533 }
2498 } 2534 }
2535 perf_mmap__read_done(md);
2499 } 2536 }
2500 2537
2501 if (trace->nr_events == before) { 2538 if (trace->nr_events == before) {
@@ -2533,6 +2570,7 @@ out_delete_evlist:
2533 trace__symbols__exit(trace); 2570 trace__symbols__exit(trace);
2534 2571
2535 perf_evlist__delete(evlist); 2572 perf_evlist__delete(evlist);
2573 cgroup__put(trace->cgroup);
2536 trace->evlist = NULL; 2574 trace->evlist = NULL;
2537 trace->live = false; 2575 trace->live = false;
2538 return err; 2576 return err;
@@ -2972,6 +3010,18 @@ out:
2972 return err; 3010 return err;
2973} 3011}
2974 3012
3013static int trace__parse_cgroups(const struct option *opt, const char *str, int unset)
3014{
3015 struct trace *trace = opt->value;
3016
3017 if (!list_empty(&trace->evlist->entries))
3018 return parse_cgroups(opt, str, unset);
3019
3020 trace->cgroup = evlist__findnew_cgroup(trace->evlist, str);
3021
3022 return 0;
3023}
3024
2975int cmd_trace(int argc, const char **argv) 3025int cmd_trace(int argc, const char **argv)
2976{ 3026{
2977 const char *trace_usage[] = { 3027 const char *trace_usage[] = {
@@ -3038,6 +3088,8 @@ int cmd_trace(int argc, const char **argv)
3038 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 3088 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
3039 OPT_BOOLEAN('T', "time", &trace.full_time, 3089 OPT_BOOLEAN('T', "time", &trace.full_time,
3040 "Show full timestamp, not time relative to first start"), 3090 "Show full timestamp, not time relative to first start"),
3091 OPT_BOOLEAN(0, "failure", &trace.failure_only,
3092 "Show only syscalls that failed"),
3041 OPT_BOOLEAN('s', "summary", &trace.summary_only, 3093 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3042 "Show only syscall summary with statistics"), 3094 "Show only syscall summary with statistics"),
3043 OPT_BOOLEAN('S', "with-summary", &trace.summary, 3095 OPT_BOOLEAN('S', "with-summary", &trace.summary,
@@ -3062,6 +3114,8 @@ int cmd_trace(int argc, const char **argv)
3062 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"), 3114 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"),
3063 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 3115 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3064 "per thread proc mmap processing timeout in ms"), 3116 "per thread proc mmap processing timeout in ms"),
3117 OPT_CALLBACK('G', "cgroup", &trace, "name", "monitor event in cgroup name only",
3118 trace__parse_cgroups),
3065 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay, 3119 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
3066 "ms to wait before starting measurement after program " 3120 "ms to wait before starting measurement after program "
3067 "start"), 3121 "start"),
@@ -3088,6 +3142,11 @@ int cmd_trace(int argc, const char **argv)
3088 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, 3142 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3089 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); 3143 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3090 3144
3145 if ((nr_cgroups || trace.cgroup) && !trace.opts.target.system_wide) {
3146 usage_with_options_msg(trace_usage, trace_options,
3147 "cgroup monitoring only available in system-wide mode");
3148 }
3149
3091 err = bpf__setup_stdout(trace.evlist); 3150 err = bpf__setup_stdout(trace.evlist);
3092 if (err) { 3151 if (err) {
3093 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf)); 3152 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c
index 37019c5d675f..50df168be326 100644
--- a/tools/perf/builtin-version.c
+++ b/tools/perf/builtin-version.c
@@ -1,11 +1,94 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include "builtin.h" 2#include "builtin.h"
3#include "perf.h" 3#include "perf.h"
4#include "color.h"
4#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <tools/config.h>
5#include <stdio.h> 7#include <stdio.h>
8#include <string.h>
9#include <subcmd/parse-options.h>
6 10
7int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused) 11int version_verbose;
12
13struct version {
14 bool build_options;
15};
16
17static struct version version;
18
19static struct option version_options[] = {
20 OPT_BOOLEAN(0, "build-options", &version.build_options,
21 "display the build options"),
22};
23
24static const char * const version_usage[] = {
25 "perf version [<options>]",
26 NULL
27};
28
29static void on_off_print(const char *status)
30{
31 printf("[ ");
32
33 if (!strcmp(status, "OFF"))
34 color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status);
35 else
36 color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status);
37
38 printf(" ]");
39}
40
41static void status_print(const char *name, const char *macro,
42 const char *status)
8{ 43{
44 printf("%22s: ", name);
45 on_off_print(status);
46 printf(" # %s\n", macro);
47}
48
49#define STATUS(__d, __m) \
50do { \
51 if (IS_BUILTIN(__d)) \
52 status_print(#__m, #__d, "on"); \
53 else \
54 status_print(#__m, #__d, "OFF"); \
55} while (0)
56
57static void library_status(void)
58{
59 STATUS(HAVE_DWARF_SUPPORT, dwarf);
60 STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations);
61 STATUS(HAVE_GLIBC_SUPPORT, glibc);
62 STATUS(HAVE_GTK2_SUPPORT, gtk2);
63#ifndef HAVE_SYSCALL_TABLE_SUPPORT
64 STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit);
65#endif
66 STATUS(HAVE_SYSCALL_TABLE_SUPPORT, syscall_table);
67 STATUS(HAVE_LIBBFD_SUPPORT, libbfd);
68 STATUS(HAVE_LIBELF_SUPPORT, libelf);
69 STATUS(HAVE_LIBNUMA_SUPPORT, libnuma);
70 STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus);
71 STATUS(HAVE_LIBPERL_SUPPORT, libperl);
72 STATUS(HAVE_LIBPYTHON_SUPPORT, libpython);
73 STATUS(HAVE_SLANG_SUPPORT, libslang);
74 STATUS(HAVE_LIBCRYPTO_SUPPORT, libcrypto);
75 STATUS(HAVE_LIBUNWIND_SUPPORT, libunwind);
76 STATUS(HAVE_DWARF_SUPPORT, libdw-dwarf-unwind);
77 STATUS(HAVE_ZLIB_SUPPORT, zlib);
78 STATUS(HAVE_LZMA_SUPPORT, lzma);
79 STATUS(HAVE_AUXTRACE_SUPPORT, get_cpuid);
80 STATUS(HAVE_LIBBPF_SUPPORT, bpf);
81}
82
83int cmd_version(int argc, const char **argv)
84{
85 argc = parse_options(argc, argv, version_options, version_usage,
86 PARSE_OPT_STOP_AT_NON_OPTION);
87
9 printf("perf version %s\n", perf_version_string); 88 printf("perf version %s\n", perf_version_string);
89
90 if (version.build_options || version_verbose == 1)
91 library_status();
92
10 return 0; 93 return 0;
11} 94}
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 790ec25919a0..9aff89bc7535 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -42,6 +42,7 @@ arch/parisc/include/uapi/asm/errno.h
42arch/powerpc/include/uapi/asm/errno.h 42arch/powerpc/include/uapi/asm/errno.h
43arch/sparc/include/uapi/asm/errno.h 43arch/sparc/include/uapi/asm/errno.h
44arch/x86/include/uapi/asm/errno.h 44arch/x86/include/uapi/asm/errno.h
45arch/powerpc/include/uapi/asm/unistd.h
45include/asm-generic/bitops/arch_hweight.h 46include/asm-generic/bitops/arch_hweight.h
46include/asm-generic/bitops/const_hweight.h 47include/asm-generic/bitops/const_hweight.h
47include/asm-generic/bitops/__fls.h 48include/asm-generic/bitops/__fls.h
@@ -58,6 +59,7 @@ check () {
58 file=$1 59 file=$1
59 60
60 shift 61 shift
62 opts=
61 while [ -n "$*" ]; do 63 while [ -n "$*" ]; do
62 opts="$opts \"$1\"" 64 opts="$opts \"$1\""
63 shift 65 shift
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 36673f98d66b..3eb7a39169f6 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -46,10 +46,6 @@
46#define CPUINFO_PROC {"Processor"} 46#define CPUINFO_PROC {"Processor"}
47#endif 47#endif
48 48
49#ifdef __metag__
50#define CPUINFO_PROC {"CPU"}
51#endif
52
53#ifdef __xtensa__ 49#ifdef __xtensa__
54#define CPUINFO_PROC {"core ID"} 50#define CPUINFO_PROC {"core ID"}
55#endif 51#endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 1b3fc8ec0fa2..20a08cb32332 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -73,7 +73,7 @@ static struct cmd_struct commands[] = {
73 { "lock", cmd_lock, 0 }, 73 { "lock", cmd_lock, 0 },
74 { "kvm", cmd_kvm, 0 }, 74 { "kvm", cmd_kvm, 0 },
75 { "test", cmd_test, 0 }, 75 { "test", cmd_test, 0 },
76#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE) 76#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
77 { "trace", cmd_trace, 0 }, 77 { "trace", cmd_trace, 0 },
78#endif 78#endif
79 { "inject", cmd_inject, 0 }, 79 { "inject", cmd_inject, 0 },
@@ -190,6 +190,12 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
190 break; 190 break;
191 } 191 }
192 192
193 if (!strcmp(cmd, "-vv")) {
194 (*argv)[0] = "version";
195 version_verbose = 1;
196 break;
197 }
198
193 /* 199 /*
194 * Check remaining flags. 200 * Check remaining flags.
195 */ 201 */
@@ -485,7 +491,7 @@ int main(int argc, const char **argv)
485 argv[0] = cmd; 491 argv[0] = cmd;
486 } 492 }
487 if (strstarts(cmd, "trace")) { 493 if (strstarts(cmd, "trace")) {
488#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE) 494#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
489 setup_path(); 495 setup_path();
490 argv[0] = "trace"; 496 argv[0] = "trace";
491 return cmd_trace(argc, argv); 497 return cmd_trace(argc, argv);
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 57b9b342d533..a1a97956136f 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -61,6 +61,7 @@ struct record_opts {
61 bool tail_synthesize; 61 bool tail_synthesize;
62 bool overwrite; 62 bool overwrite;
63 bool ignore_missing_thread; 63 bool ignore_missing_thread;
64 bool strict_freq;
64 bool sample_id; 65 bool sample_id;
65 unsigned int freq; 66 unsigned int freq;
66 unsigned int mmap_pages; 67 unsigned int mmap_pages;
@@ -83,4 +84,7 @@ struct record_opts {
83struct option; 84struct option;
84extern const char * const *record_usage; 85extern const char * const *record_usage;
85extern struct option *record_options; 86extern struct option *record_options;
87extern int version_verbose;
88
89int record__parse_freq(const struct option *opt, const char *str, int unset);
86#endif 90#endif
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 999a4e878162..17783913d330 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -1,10 +1,12 @@
1hostprogs := jevents 1hostprogs := jevents
2 2
3jevents-y += json.o jsmn.o jevents.o 3jevents-y += json.o jsmn.o jevents.o
4CHOSTFLAGS_jevents.o = -I$(srctree)/tools/include
4pmu-events-y += pmu-events.o 5pmu-events-y += pmu-events.o
5JDIR = pmu-events/arch/$(SRCARCH) 6JDIR = pmu-events/arch/$(SRCARCH)
6JSON = $(shell [ -d $(JDIR) ] && \ 7JSON = $(shell [ -d $(JDIR) ] && \
7 find $(JDIR) -name '*.json' -o -name 'mapfile.csv') 8 find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
9
8# 10#
9# Locate/process JSON files in pmu-events/arch/ 11# Locate/process JSON files in pmu-events/arch/
10# directory and create tables in pmu-events.c. 12# directory and create tables in pmu-events.c.
diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
index c2ee3e4417fe..e62b09b6a844 100644
--- a/tools/perf/pmu-events/README
+++ b/tools/perf/pmu-events/README
@@ -11,12 +11,17 @@ tree tools/perf/pmu-events/arch/foo.
11 - Regular files with '.json' extension in the name are assumed to be 11 - Regular files with '.json' extension in the name are assumed to be
12 JSON files, each of which describes a set of PMU events. 12 JSON files, each of which describes a set of PMU events.
13 13
14 - Regular files with basename starting with 'mapfile.csv' are assumed 14 - The CSV file that maps a specific CPU to its set of PMU events is to
15 to be a CSV file that maps a specific CPU to its set of PMU events. 15 be named 'mapfile.csv' (see below for mapfile format).
16 (see below for mapfile format)
17 16
18 - Directories are traversed, but all other files are ignored. 17 - Directories are traversed, but all other files are ignored.
19 18
19 - To reduce JSON event duplication per architecture, platform JSONs may
20 use "ArchStdEvent" keyword to dereference an "Architecture standard
21 events", defined in architecture standard JSONs.
22 Architecture standard JSONs must be located in the architecture root
23 folder. Matching is based on the "EventName" field.
24
20The PMU events supported by a CPU model are expected to grouped into topics 25The PMU events supported by a CPU model are expected to grouped into topics
21such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic 26such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic
22should be placed in a separate JSON file - where the file name identifies 27should be placed in a separate JSON file - where the file name identifies
@@ -29,6 +34,10 @@ sub directory. Thus for the Silvermont X86 CPU:
29 Cache.json Memory.json Virtual-Memory.json 34 Cache.json Memory.json Virtual-Memory.json
30 Frontend.json Pipeline.json 35 Frontend.json Pipeline.json
31 36
37The JSONs folder for a CPU model/family may be placed in the root arch
38folder, or may be placed in a vendor sub-folder under the arch folder
39for instances where the arch and vendor are not the same.
40
32Using the JSON files and the mapfile, 'jevents' generates the C source file, 41Using the JSON files and the mapfile, 'jevents' generates the C source file,
33'pmu-events.c', which encodes the two sets of tables: 42'pmu-events.c', which encodes the two sets of tables:
34 43
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json
index 3b6208763e50..0b0e6b26605b 100644
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json
@@ -1,25 +1,23 @@
1[ 1[
2 {, 2 {
3 "EventCode": "0x7A", 3 "ArchStdEvent": "BR_INDIRECT_SPEC",
4 "EventName": "BR_INDIRECT_SPEC",
5 "BriefDescription": "Branch speculatively executed - Indirect branch"
6 }, 4 },
7 {, 5 {
8 "EventCode": "0xC9", 6 "EventCode": "0xC9",
9 "EventName": "BR_COND", 7 "EventName": "BR_COND",
10 "BriefDescription": "Conditional branch executed" 8 "BriefDescription": "Conditional branch executed"
11 }, 9 },
12 {, 10 {
13 "EventCode": "0xCA", 11 "EventCode": "0xCA",
14 "EventName": "BR_INDIRECT_MISPRED", 12 "EventName": "BR_INDIRECT_MISPRED",
15 "BriefDescription": "Indirect branch mispredicted" 13 "BriefDescription": "Indirect branch mispredicted"
16 }, 14 },
17 {, 15 {
18 "EventCode": "0xCB", 16 "EventCode": "0xCB",
19 "EventName": "BR_INDIRECT_MISPRED_ADDR", 17 "EventName": "BR_INDIRECT_MISPRED_ADDR",
20 "BriefDescription": "Indirect branch mispredicted because of address miscompare" 18 "BriefDescription": "Indirect branch mispredicted because of address miscompare"
21 }, 19 },
22 {, 20 {
23 "EventCode": "0xCC", 21 "EventCode": "0xCC",
24 "EventName": "BR_COND_MISPRED", 22 "EventName": "BR_COND_MISPRED",
25 "BriefDescription": "Conditional branch mispredicted" 23 "BriefDescription": "Conditional branch mispredicted"
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json
new file mode 100644
index 000000000000..ce33b2553277
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json
@@ -0,0 +1,8 @@
1[
2 {
3 "ArchStdEvent": "BUS_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "BUS_ACCESS_WR",
7 }
8]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json
new file mode 100644
index 000000000000..5dfbec43c9f9
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json
@@ -0,0 +1,27 @@
1[
2 {
3 "EventCode": "0xC2",
4 "EventName": "PREFETCH_LINEFILL",
5 "BriefDescription": "Linefill because of prefetch"
6 },
7 {
8 "EventCode": "0xC3",
9 "EventName": "PREFETCH_LINEFILL_DROP",
10 "BriefDescription": "Instruction Cache Throttle occurred"
11 },
12 {
13 "EventCode": "0xC4",
14 "EventName": "READ_ALLOC_ENTER",
15 "BriefDescription": "Entering read allocate mode"
16 },
17 {
18 "EventCode": "0xC5",
19 "EventName": "READ_ALLOC",
20 "BriefDescription": "Read allocate mode"
21 },
22 {
23 "EventCode": "0xC8",
24 "EventName": "EXT_SNOOP",
25 "BriefDescription": "SCU Snooped data from another CPU for this CPU"
26 }
27]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json
index 480d9f7460ab..25ae642ba381 100644
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json
@@ -1,20 +1,10 @@
1[ 1[
2 {, 2 {
3 "EventCode": "0x60",
4 "EventName": "BUS_ACCESS_LD",
5 "BriefDescription": "Bus access - Read"
6 },
7 {,
8 "EventCode": "0x61",
9 "EventName": "BUS_ACCESS_ST",
10 "BriefDescription": "Bus access - Write"
11 },
12 {,
13 "EventCode": "0xC0", 3 "EventCode": "0xC0",
14 "EventName": "EXT_MEM_REQ", 4 "EventName": "EXT_MEM_REQ",
15 "BriefDescription": "External memory request" 5 "BriefDescription": "External memory request"
16 }, 6 },
17 {, 7 {
18 "EventCode": "0xC1", 8 "EventCode": "0xC1",
19 "EventName": "EXT_MEM_REQ_NC", 9 "EventName": "EXT_MEM_REQ_NC",
20 "BriefDescription": "Non-cacheable external memory request" 10 "BriefDescription": "Non-cacheable external memory request"
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json
new file mode 100644
index 000000000000..6cc6cbd7bf0b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json
@@ -0,0 +1,28 @@
1[
2 {
3 "ArchStdEvent": "EXC_IRQ",
4 },
5 {
6 "ArchStdEvent": "EXC_FIQ",
7 },
8 {
9 "EventCode": "0xC6",
10 "EventName": "PRE_DECODE_ERR",
11 "BriefDescription": "Pre-decode error"
12 },
13 {
14 "EventCode": "0xD0",
15 "EventName": "L1I_CACHE_ERR",
16 "BriefDescription": "L1 Instruction Cache (data or tag) memory error"
17 },
18 {
19 "EventCode": "0xD1",
20 "EventName": "L1D_CACHE_ERR",
21 "BriefDescription": "L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"
22 },
23 {
24 "EventCode": "0xD2",
25 "EventName": "TLB_ERR",
26 "BriefDescription": "TLB memory error"
27 }
28]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json
index 3149fb90555a..f45a6b5d0025 100644
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json
@@ -1,50 +1,50 @@
1[ 1[
2 {, 2 {
3 "EventCode": "0xC7", 3 "EventCode": "0xC7",
4 "EventName": "STALL_SB_FULL", 4 "EventName": "STALL_SB_FULL",
5 "BriefDescription": "Data Write operation that stalls the pipeline because the store buffer is full" 5 "BriefDescription": "Data Write operation that stalls the pipeline because the store buffer is full"
6 }, 6 },
7 {, 7 {
8 "EventCode": "0xE0", 8 "EventCode": "0xE0",
9 "EventName": "OTHER_IQ_DEP_STALL", 9 "EventName": "OTHER_IQ_DEP_STALL",
10 "BriefDescription": "Cycles that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error" 10 "BriefDescription": "Cycles that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error"
11 }, 11 },
12 {, 12 {
13 "EventCode": "0xE1", 13 "EventCode": "0xE1",
14 "EventName": "IC_DEP_STALL", 14 "EventName": "IC_DEP_STALL",
15 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction cache miss being processed" 15 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction cache miss being processed"
16 }, 16 },
17 {, 17 {
18 "EventCode": "0xE2", 18 "EventCode": "0xE2",
19 "EventName": "IUTLB_DEP_STALL", 19 "EventName": "IUTLB_DEP_STALL",
20 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction micro-TLB miss being processed" 20 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction micro-TLB miss being processed"
21 }, 21 },
22 {, 22 {
23 "EventCode": "0xE3", 23 "EventCode": "0xE3",
24 "EventName": "DECODE_DEP_STALL", 24 "EventName": "DECODE_DEP_STALL",
25 "BriefDescription": "Cycles the DPU IQ is empty and there is a pre-decode error being processed" 25 "BriefDescription": "Cycles the DPU IQ is empty and there is a pre-decode error being processed"
26 }, 26 },
27 {, 27 {
28 "EventCode": "0xE4", 28 "EventCode": "0xE4",
29 "EventName": "OTHER_INTERLOCK_STALL", 29 "EventName": "OTHER_INTERLOCK_STALL",
30 "BriefDescription": "Cycles there is an interlock other than Advanced SIMD/Floating-point instructions or load/store instruction" 30 "BriefDescription": "Cycles there is an interlock other than Advanced SIMD/Floating-point instructions or load/store instruction"
31 }, 31 },
32 {, 32 {
33 "EventCode": "0xE5", 33 "EventCode": "0xE5",
34 "EventName": "AGU_DEP_STALL", 34 "EventName": "AGU_DEP_STALL",
35 "BriefDescription": "Cycles there is an interlock for a load/store instruction waiting for data to calculate the address in the AGU" 35 "BriefDescription": "Cycles there is an interlock for a load/store instruction waiting for data to calculate the address in the AGU"
36 }, 36 },
37 {, 37 {
38 "EventCode": "0xE6", 38 "EventCode": "0xE6",
39 "EventName": "SIMD_DEP_STALL", 39 "EventName": "SIMD_DEP_STALL",
40 "BriefDescription": "Cycles there is an interlock for an Advanced SIMD/Floating-point operation." 40 "BriefDescription": "Cycles there is an interlock for an Advanced SIMD/Floating-point operation."
41 }, 41 },
42 {, 42 {
43 "EventCode": "0xE7", 43 "EventCode": "0xE7",
44 "EventName": "LD_DEP_STALL", 44 "EventName": "LD_DEP_STALL",
45 "BriefDescription": "Cycles there is a stall in the Wr stage because of a load miss" 45 "BriefDescription": "Cycles there is a stall in the Wr stage because of a load miss"
46 }, 46 },
47 {, 47 {
48 "EventCode": "0xE8", 48 "EventCode": "0xE8",
49 "EventName": "ST_DEP_STALL", 49 "EventName": "ST_DEP_STALL",
50 "BriefDescription": "Cycles there is a stall in the Wr stage because of a store" 50 "BriefDescription": "Cycles there is a stall in the Wr stage because of a store"
diff --git a/tools/perf/pmu-events/arch/arm64/armv8-recommended.json b/tools/perf/pmu-events/arch/arm64/armv8-recommended.json
new file mode 100644
index 000000000000..6328828c018c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/armv8-recommended.json
@@ -0,0 +1,452 @@
1[
2 {
3 "PublicDescription": "Attributable Level 1 data cache access, read",
4 "EventCode": "0x40",
5 "EventName": "L1D_CACHE_RD",
6 "BriefDescription": "L1D cache access, read"
7 },
8 {
9 "PublicDescription": "Attributable Level 1 data cache access, write",
10 "EventCode": "0x41",
11 "EventName": "L1D_CACHE_WR",
12 "BriefDescription": "L1D cache access, write"
13 },
14 {
15 "PublicDescription": "Attributable Level 1 data cache refill, read",
16 "EventCode": "0x42",
17 "EventName": "L1D_CACHE_REFILL_RD",
18 "BriefDescription": "L1D cache refill, read"
19 },
20 {
21 "PublicDescription": "Attributable Level 1 data cache refill, write",
22 "EventCode": "0x43",
23 "EventName": "L1D_CACHE_REFILL_WR",
24 "BriefDescription": "L1D cache refill, write"
25 },
26 {
27 "PublicDescription": "Attributable Level 1 data cache refill, inner",
28 "EventCode": "0x44",
29 "EventName": "L1D_CACHE_REFILL_INNER",
30 "BriefDescription": "L1D cache refill, inner"
31 },
32 {
33 "PublicDescription": "Attributable Level 1 data cache refill, outer",
34 "EventCode": "0x45",
35 "EventName": "L1D_CACHE_REFILL_OUTER",
36 "BriefDescription": "L1D cache refill, outer"
37 },
38 {
39 "PublicDescription": "Attributable Level 1 data cache Write-Back, victim",
40 "EventCode": "0x46",
41 "EventName": "L1D_CACHE_WB_VICTIM",
42 "BriefDescription": "L1D cache Write-Back, victim"
43 },
44 {
45 "PublicDescription": "Level 1 data cache Write-Back, cleaning and coherency",
46 "EventCode": "0x47",
47 "EventName": "L1D_CACHE_WB_CLEAN",
48 "BriefDescription": "L1D cache Write-Back, cleaning and coherency"
49 },
50 {
51 "PublicDescription": "Attributable Level 1 data cache invalidate",
52 "EventCode": "0x48",
53 "EventName": "L1D_CACHE_INVAL",
54 "BriefDescription": "L1D cache invalidate"
55 },
56 {
57 "PublicDescription": "Attributable Level 1 data TLB refill, read",
58 "EventCode": "0x4C",
59 "EventName": "L1D_TLB_REFILL_RD",
60 "BriefDescription": "L1D tlb refill, read"
61 },
62 {
63 "PublicDescription": "Attributable Level 1 data TLB refill, write",
64 "EventCode": "0x4D",
65 "EventName": "L1D_TLB_REFILL_WR",
66 "BriefDescription": "L1D tlb refill, write"
67 },
68 {
69 "PublicDescription": "Attributable Level 1 data or unified TLB access, read",
70 "EventCode": "0x4E",
71 "EventName": "L1D_TLB_RD",
72 "BriefDescription": "L1D tlb access, read"
73 },
74 {
75 "PublicDescription": "Attributable Level 1 data or unified TLB access, write",
76 "EventCode": "0x4F",
77 "EventName": "L1D_TLB_WR",
78 "BriefDescription": "L1D tlb access, write"
79 },
80 {
81 "PublicDescription": "Attributable Level 2 data cache access, read",
82 "EventCode": "0x50",
83 "EventName": "L2D_CACHE_RD",
84 "BriefDescription": "L2D cache access, read"
85 },
86 {
87 "PublicDescription": "Attributable Level 2 data cache access, write",
88 "EventCode": "0x51",
89 "EventName": "L2D_CACHE_WR",
90 "BriefDescription": "L2D cache access, write"
91 },
92 {
93 "PublicDescription": "Attributable Level 2 data cache refill, read",
94 "EventCode": "0x52",
95 "EventName": "L2D_CACHE_REFILL_RD",
96 "BriefDescription": "L2D cache refill, read"
97 },
98 {
99 "PublicDescription": "Attributable Level 2 data cache refill, write",
100 "EventCode": "0x53",
101 "EventName": "L2D_CACHE_REFILL_WR",
102 "BriefDescription": "L2D cache refill, write"
103 },
104 {
105 "PublicDescription": "Attributable Level 2 data cache Write-Back, victim",
106 "EventCode": "0x56",
107 "EventName": "L2D_CACHE_WB_VICTIM",
108 "BriefDescription": "L2D cache Write-Back, victim"
109 },
110 {
111 "PublicDescription": "Level 2 data cache Write-Back, cleaning and coherency",
112 "EventCode": "0x57",
113 "EventName": "L2D_CACHE_WB_CLEAN",
114 "BriefDescription": "L2D cache Write-Back, cleaning and coherency"
115 },
116 {
117 "PublicDescription": "Attributable Level 2 data cache invalidate",
118 "EventCode": "0x58",
119 "EventName": "L2D_CACHE_INVAL",
120 "BriefDescription": "L2D cache invalidate"
121 },
122 {
123 "PublicDescription": "Attributable Level 2 data or unified TLB refill, read",
124 "EventCode": "0x5c",
125 "EventName": "L2D_TLB_REFILL_RD",
126 "BriefDescription": "L2D cache refill, read"
127 },
128 {
129 "PublicDescription": "Attributable Level 2 data or unified TLB refill, write",
130 "EventCode": "0x5d",
131 "EventName": "L2D_TLB_REFILL_WR",
132 "BriefDescription": "L2D cache refill, write"
133 },
134 {
135 "PublicDescription": "Attributable Level 2 data or unified TLB access, read",
136 "EventCode": "0x5e",
137 "EventName": "L2D_TLB_RD",
138 "BriefDescription": "L2D cache access, read"
139 },
140 {
141 "PublicDescription": "Attributable Level 2 data or unified TLB access, write",
142 "EventCode": "0x5f",
143 "EventName": "L2D_TLB_WR",
144 "BriefDescription": "L2D cache access, write"
145 },
146 {
147 "PublicDescription": "Bus access read",
148 "EventCode": "0x60",
149 "EventName": "BUS_ACCESS_RD",
150 "BriefDescription": "Bus access read"
151 },
152 {
153 "PublicDescription": "Bus access write",
154 "EventCode": "0x61",
155 "EventName": "BUS_ACCESS_WR",
156 "BriefDescription": "Bus access write"
157 }
158 {
159 "PublicDescription": "Bus access, Normal, Cacheable, Shareable",
160 "EventCode": "0x62",
161 "EventName": "BUS_ACCESS_SHARED",
162 "BriefDescription": "Bus access, Normal, Cacheable, Shareable"
163 }
164 {
165 "PublicDescription": "Bus access, not Normal, Cacheable, Shareable",
166 "EventCode": "0x63",
167 "EventName": "BUS_ACCESS_NOT_SHARED",
168 "BriefDescription": "Bus access, not Normal, Cacheable, Shareable"
169 }
170 {
171 "PublicDescription": "Bus access, Normal",
172 "EventCode": "0x64",
173 "EventName": "BUS_ACCESS_NORMAL",
174 "BriefDescription": "Bus access, Normal"
175 }
176 {
177 "PublicDescription": "Bus access, peripheral",
178 "EventCode": "0x65",
179 "EventName": "BUS_ACCESS_PERIPH",
180 "BriefDescription": "Bus access, peripheral"
181 }
182 {
183 "PublicDescription": "Data memory access, read",
184 "EventCode": "0x66",
185 "EventName": "MEM_ACCESS_RD",
186 "BriefDescription": "Data memory access, read"
187 }
188 {
189 "PublicDescription": "Data memory access, write",
190 "EventCode": "0x67",
191 "EventName": "MEM_ACCESS_WR",
192 "BriefDescription": "Data memory access, write"
193 }
194 {
195 "PublicDescription": "Unaligned access, read",
196 "EventCode": "0x68",
197 "EventName": "UNALIGNED_LD_SPEC",
198 "BriefDescription": "Unaligned access, read"
199 }
200 {
201 "PublicDescription": "Unaligned access, write",
202 "EventCode": "0x69",
203 "EventName": "UNALIGNED_ST_SPEC",
204 "BriefDescription": "Unaligned access, write"
205 }
206 {
207 "PublicDescription": "Unaligned access",
208 "EventCode": "0x6a",
209 "EventName": "UNALIGNED_LDST_SPEC",
210 "BriefDescription": "Unaligned access"
211 }
212 {
213 "PublicDescription": "Exclusive operation speculatively executed, LDREX or LDX",
214 "EventCode": "0x6c",
215 "EventName": "LDREX_SPEC",
216 "BriefDescription": "Exclusive operation speculatively executed, LDREX or LDX"
217 }
218 {
219 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX pass",
220 "EventCode": "0x6d",
221 "EventName": "STREX_PASS_SPEC",
222 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX pass"
223 }
224 {
225 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX fail",
226 "EventCode": "0x6e",
227 "EventName": "STREX_FAIL_SPEC",
228 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX fail"
229 }
230 {
231 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX",
232 "EventCode": "0x6f",
233 "EventName": "STREX_SPEC",
234 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX"
235 }
236 {
237 "PublicDescription": "Operation speculatively executed, load",
238 "EventCode": "0x70",
239 "EventName": "LD_SPEC",
240 "BriefDescription": "Operation speculatively executed, load"
241 }
242 {
243 "PublicDescription": "Operation speculatively executed, store"
244 "EventCode": "0x71",
245 "EventName": "ST_SPEC",
246 "BriefDescription": "Operation speculatively executed, store"
247 }
248 {
249 "PublicDescription": "Operation speculatively executed, load or store",
250 "EventCode": "0x72",
251 "EventName": "LDST_SPEC",
252 "BriefDescription": "Operation speculatively executed, load or store"
253 }
254 {
255 "PublicDescription": "Operation speculatively executed, integer data processing",
256 "EventCode": "0x73",
257 "EventName": "DP_SPEC",
258 "BriefDescription": "Operation speculatively executed, integer data processing"
259 }
260 {
261 "PublicDescription": "Operation speculatively executed, Advanced SIMD instruction",
262 "EventCode": "0x74",
263 "EventName": "ASE_SPEC",
264 "BriefDescription": "Operation speculatively executed, Advanced SIMD instruction",
265 }
266 {
267 "PublicDescription": "Operation speculatively executed, floating-point instruction",
268 "EventCode": "0x75",
269 "EventName": "VFP_SPEC",
270 "BriefDescription": "Operation speculatively executed, floating-point instruction"
271 }
272 {
273 "PublicDescription": "Operation speculatively executed, software change of the PC",
274 "EventCode": "0x76",
275 "EventName": "PC_WRITE_SPEC",
276 "BriefDescription": "Operation speculatively executed, software change of the PC"
277 }
278 {
279 "PublicDescription": "Operation speculatively executed, Cryptographic instruction",
280 "EventCode": "0x77",
281 "EventName": "CRYPTO_SPEC",
282 "BriefDescription": "Operation speculatively executed, Cryptographic instruction"
283 }
284 {
285 "PublicDescription": "Branch speculatively executed, immediate branch"
286 "EventCode": "0x78",
287 "EventName": "BR_IMMED_SPEC",
288 "BriefDescription": "Branch speculatively executed, immediate branch"
289 }
290 {
291 "PublicDescription": "Branch speculatively executed, procedure return"
292 "EventCode": "0x79",
293 "EventName": "BR_RETURN_SPEC",
294 "BriefDescription": "Branch speculatively executed, procedure return"
295 }
296 {
297 "PublicDescription": "Branch speculatively executed, indirect branch"
298 "EventCode": "0x7a",
299 "EventName": "BR_INDIRECT_SPEC",
300 "BriefDescription": "Branch speculatively executed, indirect branch"
301 }
302 {
303 "PublicDescription": "Barrier speculatively executed, ISB"
304 "EventCode": "0x7c",
305 "EventName": "ISB_SPEC",
306 "BriefDescription": "Barrier speculatively executed, ISB"
307 }
308 {
309 "PublicDescription": "Barrier speculatively executed, DSB"
310 "EventCode": "0x7d",
311 "EventName": "DSB_SPEC",
312 "BriefDescription": "Barrier speculatively executed, DSB"
313 }
314 {
315 "PublicDescription": "Barrier speculatively executed, DMB"
316 "EventCode": "0x7e",
317 "EventName": "DMB_SPEC",
318 "BriefDescription": "Barrier speculatively executed, DMB"
319 }
320 {
321 "PublicDescription": "Exception taken, Other synchronous"
322 "EventCode": "0x81",
323 "EventName": "EXC_UNDEF",
324 "BriefDescription": "Exception taken, Other synchronous"
325 }
326 {
327 "PublicDescription": "Exception taken, Supervisor Call"
328 "EventCode": "0x82",
329 "EventName": "EXC_SVC",
330 "BriefDescription": "Exception taken, Supervisor Call"
331 }
332 {
333 "PublicDescription": "Exception taken, Instruction Abort"
334 "EventCode": "0x83",
335 "EventName": "EXC_PABORT",
336 "BriefDescription": "Exception taken, Instruction Abort"
337 }
338 {
339 "PublicDescription": "Exception taken, Data Abort and SError"
340 "EventCode": "0x84",
341 "EventName": "EXC_DABORT",
342 "BriefDescription": "Exception taken, Data Abort and SError"
343 }
344 {
345 "PublicDescription": "Exception taken, IRQ"
346 "EventCode": "0x86",
347 "EventName": "EXC_IRQ",
348 "BriefDescription": "Exception taken, IRQ"
349 }
350 {
351 "PublicDescription": "Exception taken, FIQ"
352 "EventCode": "0x87",
353 "EventName": "EXC_FIQ",
354 "BriefDescription": "Exception taken, FIQ"
355 }
356 {
357 "PublicDescription": "Exception taken, Secure Monitor Call"
358 "EventCode": "0x88",
359 "EventName": "EXC_SMC",
360 "BriefDescription": "Exception taken, Secure Monitor Call"
361 }
362 {
363 "PublicDescription": "Exception taken, Hypervisor Call"
364 "EventCode": "0x8a",
365 "EventName": "EXC_HVC",
366 "BriefDescription": "Exception taken, Hypervisor Call"
367 }
368 {
369 "PublicDescription": "Exception taken, Instruction Abort not taken locally"
370 "EventCode": "0x8b",
371 "EventName": "EXC_TRAP_PABORT",
372 "BriefDescription": "Exception taken, Instruction Abort not taken locally"
373 }
374 {
375 "PublicDescription": "Exception taken, Data Abort or SError not taken locally"
376 "EventCode": "0x8c",
377 "EventName": "EXC_TRAP_DABORT",
378 "BriefDescription": "Exception taken, Data Abort or SError not taken locally"
379 }
380 {
381 "PublicDescription": "Exception taken, Other traps not taken locally"
382 "EventCode": "0x8d",
383 "EventName": "EXC_TRAP_OTHER",
384 "BriefDescription": "Exception taken, Other traps not taken locally"
385 }
386 {
387 "PublicDescription": "Exception taken, IRQ not taken locally"
388 "EventCode": "0x8e",
389 "EventName": "EXC_TRAP_IRQ",
390 "BriefDescription": "Exception taken, IRQ not taken locally"
391 }
392 {
393 "PublicDescription": "Exception taken, FIQ not taken locally"
394 "EventCode": "0x8f",
395 "EventName": "EXC_TRAP_FIQ",
396 "BriefDescription": "Exception taken, FIQ not taken locally"
397 }
398 {
399 "PublicDescription": "Release consistency operation speculatively executed, Load-Acquire"
400 "EventCode": "0x90",
401 "EventName": "RC_LD_SPEC",
402 "BriefDescription": "Release consistency operation speculatively executed, Load-Acquire"
403 }
404 {
405 "PublicDescription": "Release consistency operation speculatively executed, Store-Release"
406 "EventCode": "0x91",
407 "EventName": "RC_ST_SPEC",
408 "BriefDescription": "Release consistency operation speculatively executed, Store-Release"
409 }
410 {
411 "PublicDescription": "Attributable Level 3 data or unified cache access, read"
412 "EventCode": "0xa0",
413 "EventName": "L3D_CACHE_RD",
414 "BriefDescription": "Attributable Level 3 data or unified cache access, read"
415 }
416 {
417 "PublicDescription": "Attributable Level 3 data or unified cache access, write"
418 "EventCode": "0xa1",
419 "EventName": "L3D_CACHE_WR",
420 "BriefDescription": "Attributable Level 3 data or unified cache access, write"
421 }
422 {
423 "PublicDescription": "Attributable Level 3 data or unified cache refill, read"
424 "EventCode": "0xa2",
425 "EventName": "L3D_CACHE_REFILL_RD",
426 "BriefDescription": "Attributable Level 3 data or unified cache refill, read"
427 }
428 {
429 "PublicDescription": "Attributable Level 3 data or unified cache refill, write"
430 "EventCode": "0xa3",
431 "EventName": "L3D_CACHE_REFILL_WR",
432 "BriefDescription": "Attributable Level 3 data or unified cache refill, write"
433 }
434 {
435 "PublicDescription": "Attributable Level 3 data or unified cache Write-Back, victim"
436 "EventCode": "0xa6",
437 "EventName": "L3D_CACHE_WB_VICTIM",
438 "BriefDescription": "Attributable Level 3 data or unified cache Write-Back, victim"
439 }
440 {
441 "PublicDescription": "Attributable Level 3 data or unified cache Write-Back, cache clean"
442 "EventCode": "0xa7",
443 "EventName": "L3D_CACHE_WB_CLEAN",
444 "BriefDescription": "Attributable Level 3 data or unified cache Write-Back, cache clean"
445 }
446 {
447 "PublicDescription": "Attributable Level 3 data or unified cache access, invalidate"
448 "EventCode": "0xa8",
449 "EventName": "L3D_CACHE_INVAL",
450 "BriefDescription": "Attributable Level 3 data or unified cache access, invalidate"
451 }
452]
diff --git a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json
deleted file mode 100644
index 2db45c40ebc7..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json
+++ /dev/null
@@ -1,62 +0,0 @@
1[
2 {
3 "PublicDescription": "Attributable Level 1 data cache access, read",
4 "EventCode": "0x40",
5 "EventName": "l1d_cache_rd",
6 "BriefDescription": "L1D cache read",
7 },
8 {
9 "PublicDescription": "Attributable Level 1 data cache access, write ",
10 "EventCode": "0x41",
11 "EventName": "l1d_cache_wr",
12 "BriefDescription": "L1D cache write",
13 },
14 {
15 "PublicDescription": "Attributable Level 1 data cache refill, read",
16 "EventCode": "0x42",
17 "EventName": "l1d_cache_refill_rd",
18 "BriefDescription": "L1D cache refill read",
19 },
20 {
21 "PublicDescription": "Attributable Level 1 data cache refill, write",
22 "EventCode": "0x43",
23 "EventName": "l1d_cache_refill_wr",
24 "BriefDescription": "L1D refill write",
25 },
26 {
27 "PublicDescription": "Attributable Level 1 data TLB refill, read",
28 "EventCode": "0x4C",
29 "EventName": "l1d_tlb_refill_rd",
30 "BriefDescription": "L1D tlb refill read",
31 },
32 {
33 "PublicDescription": "Attributable Level 1 data TLB refill, write",
34 "EventCode": "0x4D",
35 "EventName": "l1d_tlb_refill_wr",
36 "BriefDescription": "L1D tlb refill write",
37 },
38 {
39 "PublicDescription": "Attributable Level 1 data or unified TLB access, read",
40 "EventCode": "0x4E",
41 "EventName": "l1d_tlb_rd",
42 "BriefDescription": "L1D tlb read",
43 },
44 {
45 "PublicDescription": "Attributable Level 1 data or unified TLB access, write",
46 "EventCode": "0x4F",
47 "EventName": "l1d_tlb_wr",
48 "BriefDescription": "L1D tlb write",
49 },
50 {
51 "PublicDescription": "Bus access read",
52 "EventCode": "0x60",
53 "EventName": "bus_access_rd",
54 "BriefDescription": "Bus access read",
55 },
56 {
57 "PublicDescription": "Bus access write",
58 "EventCode": "0x61",
59 "EventName": "bus_access_wr",
60 "BriefDescription": "Bus access write",
61 }
62]
diff --git a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json
new file mode 100644
index 000000000000..bc03c06c3918
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json
@@ -0,0 +1,32 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_REFILL_WR",
13 },
14 {
15 "ArchStdEvent": "L1D_TLB_REFILL_RD",
16 },
17 {
18 "ArchStdEvent": "L1D_TLB_REFILL_WR",
19 },
20 {
21 "ArchStdEvent": "L1D_TLB_RD",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_WR",
25 },
26 {
27 "ArchStdEvent": "BUS_ACCESS_RD",
28 },
29 {
30 "ArchStdEvent": "BUS_ACCESS_WR",
31 }
32]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json b/tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json
deleted file mode 100644
index 480d9f7460ab..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json
+++ /dev/null
@@ -1,22 +0,0 @@
1[
2 {,
3 "EventCode": "0x60",
4 "EventName": "BUS_ACCESS_LD",
5 "BriefDescription": "Bus access - Read"
6 },
7 {,
8 "EventCode": "0x61",
9 "EventName": "BUS_ACCESS_ST",
10 "BriefDescription": "Bus access - Write"
11 },
12 {,
13 "EventCode": "0xC0",
14 "EventName": "EXT_MEM_REQ",
15 "BriefDescription": "External memory request"
16 },
17 {,
18 "EventCode": "0xC1",
19 "EventName": "EXT_MEM_REQ_NC",
20 "BriefDescription": "Non-cacheable external memory request"
21 }
22]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json b/tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json
deleted file mode 100644
index 11baad6344b9..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json
+++ /dev/null
@@ -1,27 +0,0 @@
1[
2 {,
3 "EventCode": "0xC2",
4 "EventName": "PREFETCH_LINEFILL",
5 "BriefDescription": "Linefill because of prefetch"
6 },
7 {,
8 "EventCode": "0xC3",
9 "EventName": "PREFETCH_LINEFILL_DROP",
10 "BriefDescription": "Instruction Cache Throttle occurred"
11 },
12 {,
13 "EventCode": "0xC4",
14 "EventName": "READ_ALLOC_ENTER",
15 "BriefDescription": "Entering read allocate mode"
16 },
17 {,
18 "EventCode": "0xC5",
19 "EventName": "READ_ALLOC",
20 "BriefDescription": "Read allocate mode"
21 },
22 {,
23 "EventCode": "0xC8",
24 "EventName": "EXT_SNOOP",
25 "BriefDescription": "SCU Snooped data from another CPU for this CPU"
26 }
27]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/other.json b/tools/perf/pmu-events/arch/arm64/cortex-a53/other.json
deleted file mode 100644
index 73a22402d003..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/other.json
+++ /dev/null
@@ -1,32 +0,0 @@
1[
2 {,
3 "EventCode": "0x86",
4 "EventName": "EXC_IRQ",
5 "BriefDescription": "Exception taken, IRQ"
6 },
7 {,
8 "EventCode": "0x87",
9 "EventName": "EXC_FIQ",
10 "BriefDescription": "Exception taken, FIQ"
11 },
12 {,
13 "EventCode": "0xC6",
14 "EventName": "PRE_DECODE_ERR",
15 "BriefDescription": "Pre-decode error"
16 },
17 {,
18 "EventCode": "0xD0",
19 "EventName": "L1I_CACHE_ERR",
20 "BriefDescription": "L1 Instruction Cache (data or tag) memory error"
21 },
22 {,
23 "EventCode": "0xD1",
24 "EventName": "L1D_CACHE_ERR",
25 "BriefDescription": "L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"
26 },
27 {,
28 "EventCode": "0xD2",
29 "EventName": "TLB_ERR",
30 "BriefDescription": "TLB memory error"
31 }
32]
diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json
new file mode 100644
index 000000000000..9f0f15d15f75
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json
@@ -0,0 +1,122 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_REFILL_WR",
13 },
14 {
15 "ArchStdEvent": "L1D_CACHE_WB_VICTIM",
16 },
17 {
18 "ArchStdEvent": "L1D_CACHE_WB_CLEAN",
19 },
20 {
21 "ArchStdEvent": "L1D_CACHE_INVAL",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_REFILL_RD",
25 },
26 {
27 "ArchStdEvent": "L1D_TLB_REFILL_WR",
28 },
29 {
30 "ArchStdEvent": "L1D_TLB_RD",
31 },
32 {
33 "ArchStdEvent": "L1D_TLB_WR",
34 },
35 {
36 "ArchStdEvent": "L2D_CACHE_RD",
37 },
38 {
39 "ArchStdEvent": "L2D_CACHE_WR",
40 },
41 {
42 "ArchStdEvent": "L2D_CACHE_REFILL_RD",
43 },
44 {
45 "ArchStdEvent": "L2D_CACHE_REFILL_WR",
46 },
47 {
48 "ArchStdEvent": "L2D_CACHE_WB_VICTIM",
49 },
50 {
51 "ArchStdEvent": "L2D_CACHE_WB_CLEAN",
52 },
53 {
54 "ArchStdEvent": "L2D_CACHE_INVAL",
55 },
56 {
57 "PublicDescription": "Level 1 instruction cache prefetch access count",
58 "EventCode": "0x102e",
59 "EventName": "L1I_CACHE_PRF",
60 "BriefDescription": "L1I cache prefetch access count",
61 },
62 {
63 "PublicDescription": "Level 1 instruction cache miss due to prefetch access count",
64 "EventCode": "0x102f",
65 "EventName": "L1I_CACHE_PRF_REFILL",
66 "BriefDescription": "L1I cache miss due to prefetch access count",
67 },
68 {
69 "PublicDescription": "Instruction queue is empty",
70 "EventCode": "0x1043",
71 "EventName": "IQ_IS_EMPTY",
72 "BriefDescription": "Instruction queue is empty",
73 },
74 {
75 "PublicDescription": "Instruction fetch stall cycles",
76 "EventCode": "0x1044",
77 "EventName": "IF_IS_STALL",
78 "BriefDescription": "Instruction fetch stall cycles",
79 },
80 {
81 "PublicDescription": "Instructions can receive, but not send",
82 "EventCode": "0x2014",
83 "EventName": "FETCH_BUBBLE",
84 "BriefDescription": "Instructions can receive, but not send",
85 },
86 {
87 "PublicDescription": "Prefetch request from LSU",
88 "EventCode": "0x6013",
89 "EventName": "PRF_REQ",
90 "BriefDescription": "Prefetch request from LSU",
91 },
92 {
93 "PublicDescription": "Hit on prefetched data",
94 "EventCode": "0x6014",
95 "EventName": "HIT_ON_PRF",
96 "BriefDescription": "Hit on prefetched data",
97 },
98 {
99 "PublicDescription": "Cycles of that the number of issuing micro operations are less than 4",
100 "EventCode": "0x7001",
101 "EventName": "EXE_STALL_CYCLE",
102 "BriefDescription": "Cycles of that the number of issue ups are less than 4",
103 },
104 {
105 "PublicDescription": "No any micro operation is issued and meanwhile any load operation is not resolved",
106 "EventCode": "0x7004",
107 "EventName": "MEM_STALL_ANYLOAD",
108 "BriefDescription": "No any micro operation is issued and meanwhile any load operation is not resolved",
109 },
110 {
111 "PublicDescription": "No any micro operation is issued and meanwhile there is any load operation missing L1 cache and pending data refill",
112 "EventCode": "0x7006",
113 "EventName": "MEM_STALL_L1MISS",
114 "BriefDescription": "No any micro operation is issued and meanwhile there is any load operation missing L1 cache and pending data refill",
115 },
116 {
117 "PublicDescription": "No any micro operation is issued and meanwhile there is any load operation missing both L1 and L2 cache and pending data refill from L3 cache",
118 "EventCode": "0x7007",
119 "EventName": "MEM_STALL_L2MISS",
120 "BriefDescription": "No any micro operation is issued and meanwhile there is any load operation missing both L1 and L2 cache and pending data refill from L3 cache",
121 },
122]
diff --git a/tools/perf/pmu-events/arch/arm64/mapfile.csv b/tools/perf/pmu-events/arch/arm64/mapfile.csv
index e61c9ca6cf9e..f03e26ecb658 100644
--- a/tools/perf/pmu-events/arch/arm64/mapfile.csv
+++ b/tools/perf/pmu-events/arch/arm64/mapfile.csv
@@ -12,5 +12,7 @@
12# 12#
13# 13#
14#Family-model,Version,Filename,EventType 14#Family-model,Version,Filename,EventType
150x00000000420f5160,v1,cavium,core 150x00000000410fd03[[:xdigit:]],v1,arm/cortex-a53,core
160x00000000410fd03[[:xdigit:]],v1,cortex-a53,core 160x00000000420f5160,v1,cavium/thunderx2,core
170x00000000430f0af0,v1,cavium/thunderx2,core
180x00000000480fd010,v1,hisilicon/hip08,core
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/cache.json b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
index 7945c5196c43..851072105054 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/cache.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
@@ -20,11 +20,6 @@
20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes" 20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes"
21 }, 21 },
22 {, 22 {,
23 "EventCode": "0x1D15C",
24 "EventName": "PM_MRK_DTLB_MISS_1G",
25 "BriefDescription": "Marked Data TLB reload (after a miss) page size 2M. Implies radix translation was used"
26 },
27 {,
28 "EventCode": "0x4D12A", 23 "EventCode": "0x4D12A",
29 "EventName": "PM_MRK_DATA_FROM_RL4_CYC", 24 "EventName": "PM_MRK_DATA_FROM_RL4_CYC",
30 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load" 25 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load"
@@ -80,21 +75,6 @@
80 "BriefDescription": "Threshold counter exceed a count of 4096" 75 "BriefDescription": "Threshold counter exceed a count of 4096"
81 }, 76 },
82 {, 77 {,
83 "EventCode": "0x3D156",
84 "EventName": "PM_MRK_DTLB_MISS_64K",
85 "BriefDescription": "Marked Data TLB Miss page size 64K"
86 },
87 {,
88 "EventCode": "0x4C15E",
89 "EventName": "PM_MRK_DTLB_MISS_16M",
90 "BriefDescription": "Marked Data TLB Miss page size 16M"
91 },
92 {,
93 "EventCode": "0x2D15E",
94 "EventName": "PM_MRK_DTLB_MISS_16G",
95 "BriefDescription": "Marked Data TLB Miss page size 16G"
96 },
97 {,
98 "EventCode": "0x3F14A", 78 "EventCode": "0x3F14A",
99 "EventName": "PM_MRK_DPTEG_FROM_RMEM", 79 "EventName": "PM_MRK_DPTEG_FROM_RMEM",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 80 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -123,10 +103,5 @@
123 "EventCode": "0x1002A", 103 "EventCode": "0x1002A",
124 "EventName": "PM_CMPLU_STALL_LARX", 104 "EventName": "PM_CMPLU_STALL_LARX",
125 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied" 105 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied"
126 },
127 {,
128 "EventCode": "0x1C058",
129 "EventName": "PM_DTLB_MISS_16G",
130 "BriefDescription": "Data TLB Miss page size 16G"
131 } 106 }
132] \ No newline at end of file 107] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
index bd8361b5fd6a..f9fa84b16fb5 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
@@ -155,11 +155,6 @@
155 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load" 155 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
156 }, 156 },
157 {, 157 {,
158 "EventCode": "0x3C056",
159 "EventName": "PM_DTLB_MISS_64K",
160 "BriefDescription": "Data TLB Miss page size 64K"
161 },
162 {,
163 "EventCode": "0x30060", 158 "EventCode": "0x30060",
164 "EventName": "PM_TM_TRANS_RUN_INST", 159 "EventName": "PM_TM_TRANS_RUN_INST",
165 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)" 160 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)"
@@ -345,11 +340,6 @@
345 "BriefDescription": "Larx finished" 340 "BriefDescription": "Larx finished"
346 }, 341 },
347 {, 342 {,
348 "EventCode": "0x4C056",
349 "EventName": "PM_DTLB_MISS_16M",
350 "BriefDescription": "Data TLB Miss page size 16M"
351 },
352 {,
353 "EventCode": "0x1003A", 343 "EventCode": "0x1003A",
354 "EventName": "PM_CMPLU_STALL_LSU_FIN", 344 "EventName": "PM_CMPLU_STALL_LSU_FIN",
355 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish" 345 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/marked.json b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
index 22f9f32060a8..b1954c38bab1 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/marked.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
@@ -530,11 +530,6 @@
530 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch" 530 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch"
531 }, 531 },
532 {, 532 {,
533 "EventCode": "0x4003C",
534 "EventName": "PM_DISP_HELD_SYNC_HOLD",
535 "BriefDescription": "Cycles in which dispatch is held because of a synchronizing instruction in the pipeline"
536 },
537 {,
538 "EventCode": "0x3003C", 533 "EventCode": "0x3003C",
539 "EventName": "PM_CMPLU_STALL_NESTED_TEND", 534 "EventName": "PM_CMPLU_STALL_NESTED_TEND",
540 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay" 535 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/memory.json b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
index 9960d1c0dd44..2e2ebc700c74 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/memory.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
@@ -45,11 +45,6 @@
45 "BriefDescription": "count of Loads completed" 45 "BriefDescription": "count of Loads completed"
46 }, 46 },
47 {, 47 {,
48 "EventCode": "0x2D156",
49 "EventName": "PM_MRK_DTLB_MISS_4K",
50 "BriefDescription": "Marked Data TLB Miss page size 4k"
51 },
52 {,
53 "EventCode": "0x4C042", 48 "EventCode": "0x4C042",
54 "EventName": "PM_DATA_FROM_L3", 49 "EventName": "PM_DATA_FROM_L3",
55 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load" 50 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
index 5ce312973f1e..48cf4f920b3f 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -70,6 +70,11 @@
70 "BriefDescription": "Cycles thread running at priority level 0 or 1" 70 "BriefDescription": "Cycles thread running at priority level 0 or 1"
71 }, 71 },
72 {, 72 {,
73 "EventCode": "0x4C054",
74 "EventName": "PM_DERAT_MISS_16G_1G",
75 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G (hpt mode) or 1G (radix mode)"
76 },
77 {,
73 "EventCode": "0x2084", 78 "EventCode": "0x2084",
74 "EventName": "PM_FLUSH_HB_RESTORE_CYC", 79 "EventName": "PM_FLUSH_HB_RESTORE_CYC",
75 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery" 80 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery"
@@ -107,12 +112,12 @@
107 {, 112 {,
108 "EventCode": "0x360B2", 113 "EventCode": "0x360B2",
109 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW", 114 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW",
110 "BriefDescription": "Initial scope=group (GS or NNS) but data from outside group (far or rem). Prediction too Low" 115 "BriefDescription": "Prefetch scope predictor selected GS or NNS, but was wrong because scope was LNS"
111 }, 116 },
112 {, 117 {,
113 "EventCode": "0x168A6", 118 "EventCode": "0x168A6",
114 "EventName": "PM_TM_CAM_OVERFLOW", 119 "EventName": "PM_TM_CAM_OVERFLOW",
115 "BriefDescription": "L3 TM cam overflow during L2 co of SC" 120 "BriefDescription": "L3 TM CAM is full when a L2 castout of TM_SC line occurs. Line is pushed to memory"
116 }, 121 },
117 {, 122 {,
118 "EventCode": "0xE8B0", 123 "EventCode": "0xE8B0",
@@ -150,11 +155,6 @@
150 "BriefDescription": "All ISU rejects" 155 "BriefDescription": "All ISU rejects"
151 }, 156 },
152 {, 157 {,
153 "EventCode": "0x460A6",
154 "EventName": "PM_RD_FORMING_SC",
155 "BriefDescription": "Read forming SC"
156 },
157 {,
158 "EventCode": "0x468A0", 158 "EventCode": "0x468A0",
159 "EventName": "PM_L3_PF_OFF_CHIP_MEM", 159 "EventName": "PM_L3_PF_OFF_CHIP_MEM",
160 "BriefDescription": "L3 PF from Off chip memory" 160 "BriefDescription": "L3 PF from Off chip memory"
@@ -187,7 +187,7 @@
187 {, 187 {,
188 "EventCode": "0x368A6", 188 "EventCode": "0x368A6",
189 "EventName": "PM_SNP_TM_HIT_T", 189 "EventName": "PM_SNP_TM_HIT_T",
190 "BriefDescription": "Snp TM sthit T/Tn/Te" 190 "BriefDescription": "TM snoop that is a store hits line in L3 in T, Tn or Te state (shared modified)"
191 }, 191 },
192 {, 192 {,
193 "EventCode": "0x3001A", 193 "EventCode": "0x3001A",
@@ -205,6 +205,11 @@
205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load" 205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load"
206 }, 206 },
207 {, 207 {,
208 "EventCode": "0xF0B4",
209 "EventName": "PM_DC_PREF_CONS_ALLOC",
210 "BriefDescription": "Prefetch stream allocated in the conservative phase by either the hardware prefetch mechanism or software prefetch. The sum of this pair subtracted from the total number of allocs will give the total allocs in normal phase"
211 },
212 {,
208 "EventCode": "0xF894", 213 "EventCode": "0xF894",
209 "EventName": "PM_LSU3_L1_CAM_CANCEL", 214 "EventName": "PM_LSU3_L1_CAM_CANCEL",
210 "BriefDescription": "ls3 l1 tm cam cancel" 215 "BriefDescription": "ls3 l1 tm cam cancel"
@@ -227,7 +232,12 @@
227 {, 232 {,
228 "EventCode": "0x468A6", 233 "EventCode": "0x468A6",
229 "EventName": "PM_RD_CLEARING_SC", 234 "EventName": "PM_RD_CLEARING_SC",
230 "BriefDescription": "Read clearing SC" 235 "BriefDescription": "Core TM load hits line in L3 in TM_SC state and causes it to be invalidated"
236 },
237 {,
238 "EventCode": "0xD0B0",
239 "EventName": "PM_HWSYNC",
240 "BriefDescription": ""
231 }, 241 },
232 {, 242 {,
233 "EventCode": "0x168B0", 243 "EventCode": "0x168B0",
@@ -265,6 +275,11 @@
265 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism" 275 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism"
266 }, 276 },
267 {, 277 {,
278 "EventCode": "0xF0BC",
279 "EventName": "PM_LS2_UNALIGNED_ST",
280 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
281 },
282 {,
268 "EventCode": "0xD0AC", 283 "EventCode": "0xD0AC",
269 "EventName": "PM_SRQ_SYNC_CYC", 284 "EventName": "PM_SRQ_SYNC_CYC",
270 "BriefDescription": "A sync is in the S2Q (edge detect to count)" 285 "BriefDescription": "A sync is in the S2Q (edge detect to count)"
@@ -275,6 +290,11 @@
275 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet" 290 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet"
276 }, 291 },
277 {, 292 {,
293 "EventCode": "0x58A8",
294 "EventName": "PM_DECODE_HOLD_ICT_FULL",
295 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
296 },
297 {,
278 "EventCode": "0x26082", 298 "EventCode": "0x26082",
279 "EventName": "PM_L2_IC_INV", 299 "EventName": "PM_L2_IC_INV",
280 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core" 300 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core"
@@ -365,6 +385,16 @@
365 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load" 385 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load"
366 }, 386 },
367 {, 387 {,
388 "EventCode": "0xF888",
389 "EventName": "PM_LSU1_STORE_REJECT",
390 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
391 },
392 {,
393 "EventCode": "0xC098",
394 "EventName": "PM_LS2_UNALIGNED_LD",
395 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
396 },
397 {,
368 "EventCode": "0x20058", 398 "EventCode": "0x20058",
369 "EventName": "PM_DARQ1_10_12_ENTRIES", 399 "EventName": "PM_DARQ1_10_12_ENTRIES",
370 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use" 400 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use"
@@ -372,7 +402,7 @@
372 {, 402 {,
373 "EventCode": "0x360A6", 403 "EventCode": "0x360A6",
374 "EventName": "PM_SNP_TM_HIT_M", 404 "EventName": "PM_SNP_TM_HIT_M",
375 "BriefDescription": "Snp TM st hit M/Mu" 405 "BriefDescription": "TM snoop that is a store hits line in L3 in M or Mu state (exclusive modified)"
376 }, 406 },
377 {, 407 {,
378 "EventCode": "0x5898", 408 "EventCode": "0x5898",
@@ -395,9 +425,9 @@
395 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch" 425 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch"
396 }, 426 },
397 {, 427 {,
398 "EventCode": "0xF888", 428 "EventCode": "0x2608E",
399 "EventName": "PM_LSU1_STORE_REJECT", 429 "EventName": "PM_TM_LD_CONF",
400 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met" 430 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
401 }, 431 },
402 {, 432 {,
403 "EventCode": "0x1D144", 433 "EventCode": "0x1D144",
@@ -422,7 +452,7 @@
422 {, 452 {,
423 "EventCode": "0x26884", 453 "EventCode": "0x26884",
424 "EventName": "PM_DSIDE_MRU_TOUCH", 454 "EventName": "PM_DSIDE_MRU_TOUCH",
425 "BriefDescription": "D-side L2 MRU touch sent to L2" 455 "BriefDescription": "D-side L2 MRU touch commands sent to the L2"
426 }, 456 },
427 {, 457 {,
428 "EventCode": "0x30134", 458 "EventCode": "0x30134",
@@ -440,6 +470,16 @@
440 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued" 470 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued"
441 }, 471 },
442 {, 472 {,
473 "EventCode": "0xC094",
474 "EventName": "PM_LS0_UNALIGNED_LD",
475 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
476 },
477 {,
478 "EventCode": "0xF8BC",
479 "EventName": "PM_LS3_UNALIGNED_ST",
480 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
481 },
482 {,
443 "EventCode": "0x460AE", 483 "EventCode": "0x460AE",
444 "EventName": "PM_L3_P2_CO_RTY", 484 "EventName": "PM_L3_P2_CO_RTY",
445 "BriefDescription": "L3 CO received retry port 2 (memory only), every retry counted" 485 "BriefDescription": "L3 CO received retry port 2 (memory only), every retry counted"
@@ -492,7 +532,7 @@
492 {, 532 {,
493 "EventCode": "0xC880", 533 "EventCode": "0xC880",
494 "EventName": "PM_LS1_LD_VECTOR_FIN", 534 "EventName": "PM_LS1_LD_VECTOR_FIN",
495 "BriefDescription": "" 535 "BriefDescription": "LS1 finished load vector op"
496 }, 536 },
497 {, 537 {,
498 "EventCode": "0x2894", 538 "EventCode": "0x2894",
@@ -515,6 +555,11 @@
515 "BriefDescription": "Marked derat reload (miss) for any page size" 555 "BriefDescription": "Marked derat reload (miss) for any page size"
516 }, 556 },
517 {, 557 {,
558 "EventCode": "0x160A0",
559 "EventName": "PM_L3_PF_MISS_L3",
560 "BriefDescription": "L3 PF missed in L3"
561 },
562 {,
518 "EventCode": "0x1C04A", 563 "EventCode": "0x1C04A",
519 "EventName": "PM_DATA_FROM_RL2L3_SHR", 564 "EventName": "PM_DATA_FROM_RL2L3_SHR",
520 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load" 565 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
@@ -565,11 +610,21 @@
565 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)" 610 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)"
566 }, 611 },
567 {, 612 {,
613 "EventCode": "0xC888",
614 "EventName": "PM_LSU_DTLB_MISS_64K",
615 "BriefDescription": "Data TLB Miss page size 64K"
616 },
617 {,
568 "EventCode": "0xE0A4", 618 "EventCode": "0xE0A4",
569 "EventName": "PM_TMA_REQ_L2", 619 "EventName": "PM_TMA_REQ_L2",
570 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding" 620 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding"
571 }, 621 },
572 {, 622 {,
623 "EventCode": "0xC088",
624 "EventName": "PM_LSU_DTLB_MISS_4K",
625 "BriefDescription": "Data TLB Miss page size 4K"
626 },
627 {,
573 "EventCode": "0x3C042", 628 "EventCode": "0x3C042",
574 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT", 629 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT",
575 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load" 630 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load"
@@ -602,7 +657,7 @@
602 {, 657 {,
603 "EventCode": "0x26084", 658 "EventCode": "0x26084",
604 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER", 659 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER",
605 "BriefDescription": "All I-or-D side load dispatch attempts for this thread that failed due to reason other than address collision (excludes i_l2mru_tch_reqs)" 660 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread that failed due to reasons other than an address collision conflicts with an L2 machines (e.g. Read-Claim/Snoop machine not available)"
606 }, 661 },
607 {, 662 {,
608 "EventCode": "0x101E4", 663 "EventCode": "0x101E4",
@@ -647,12 +702,12 @@
647 {, 702 {,
648 "EventCode": "0x46080", 703 "EventCode": "0x46080",
649 "EventName": "PM_L2_DISP_ALL_L2MISS", 704 "EventName": "PM_L2_DISP_ALL_L2MISS",
650 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)" 705 "BriefDescription": "All successful D-side-Ld/St or I-side-instruction-fetch dispatches for this thread that were an L2 miss"
651 }, 706 },
652 {, 707 {,
653 "EventCode": "0x160A0", 708 "EventCode": "0xF8B8",
654 "EventName": "PM_L3_PF_MISS_L3", 709 "EventName": "PM_LS1_UNALIGNED_ST",
655 "BriefDescription": "L3 PF missed in L3" 710 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
656 }, 711 },
657 {, 712 {,
658 "EventCode": "0x408C", 713 "EventCode": "0x408C",
@@ -667,7 +722,7 @@
667 {, 722 {,
668 "EventCode": "0x160B2", 723 "EventCode": "0x160B2",
669 "EventName": "PM_L3_LOC_GUESS_CORRECT", 724 "EventName": "PM_L3_LOC_GUESS_CORRECT",
670 "BriefDescription": "initial scope=node/chip (LNS) and data from local node (local) (pred successful) - always PFs only" 725 "BriefDescription": "Prefetch scope predictor selected LNS and was correct"
671 }, 726 },
672 {, 727 {,
673 "EventCode": "0x48B4", 728 "EventCode": "0x48B4",
@@ -767,7 +822,7 @@
767 {, 822 {,
768 "EventCode": "0x36082", 823 "EventCode": "0x36082",
769 "EventName": "PM_L2_LD_DISP", 824 "EventName": "PM_L2_LD_DISP",
770 "BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)" 825 "BriefDescription": "All successful D-side-Ld or I-side-instruction-fetch dispatches for this thread"
771 }, 826 },
772 {, 827 {,
773 "EventCode": "0xF8B0", 828 "EventCode": "0xF8B0",
@@ -787,7 +842,7 @@
787 {, 842 {,
788 "EventCode": "0x16884", 843 "EventCode": "0x16884",
789 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR", 844 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR",
790 "BriefDescription": "All I-od-D side load dispatch attempts for this thread that failed due to address collision with RC/CO/SN/SQ machine (excludes i_l2mru_tch_reqs)" 845 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread that failed due to an address collision conflicts with an L2 machines already working on this line (e.g. ld-hit-stq or Read-claim/Castout/Snoop machines)"
791 }, 846 },
792 {, 847 {,
793 "EventCode": "0x460A0", 848 "EventCode": "0x460A0",
@@ -830,6 +885,11 @@
830 "BriefDescription": "Instruction prefetch requests" 885 "BriefDescription": "Instruction prefetch requests"
831 }, 886 },
832 {, 887 {,
888 "EventCode": "0xC898",
889 "EventName": "PM_LS3_UNALIGNED_LD",
890 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
891 },
892 {,
833 "EventCode": "0x488C", 893 "EventCode": "0x488C",
834 "EventName": "PM_IC_PREF_WRITE", 894 "EventName": "PM_IC_PREF_WRITE",
835 "BriefDescription": "Instruction prefetch written into IL1" 895 "BriefDescription": "Instruction prefetch written into IL1"
@@ -837,7 +897,7 @@
837 {, 897 {,
838 "EventCode": "0xF89C", 898 "EventCode": "0xF89C",
839 "EventName": "PM_XLATE_MISS", 899 "EventName": "PM_XLATE_MISS",
840 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions" 900 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions. Includes instruction, prefetch and demand"
841 }, 901 },
842 {, 902 {,
843 "EventCode": "0x14158", 903 "EventCode": "0x14158",
@@ -850,9 +910,14 @@
850 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load" 910 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load"
851 }, 911 },
852 {, 912 {,
913 "EventCode": "0xC88C",
914 "EventName": "PM_LSU_DTLB_MISS_16G_1G",
915 "BriefDescription": "Data TLB Miss page size 16G (HPT) or 1G (Radix)"
916 },
917 {,
853 "EventCode": "0x268A6", 918 "EventCode": "0x268A6",
854 "EventName": "PM_TM_RST_SC", 919 "EventName": "PM_TM_RST_SC",
855 "BriefDescription": "TM-snp rst RM SC" 920 "BriefDescription": "TM snoop hits line in L3 that is TM_SC state and causes it to be invalidated"
856 }, 921 },
857 {, 922 {,
858 "EventCode": "0x468A4", 923 "EventCode": "0x468A4",
@@ -917,7 +982,7 @@
917 {, 982 {,
918 "EventCode": "0x46086", 983 "EventCode": "0x46086",
919 "EventName": "PM_L2_SN_M_RD_DONE", 984 "EventName": "PM_L2_SN_M_RD_DONE",
920 "BriefDescription": "SNP dispatched for a read and was M (true M)" 985 "BriefDescription": "Snoop dispatched for a read and was M (true M)"
921 }, 986 },
922 {, 987 {,
923 "EventCode": "0x40154", 988 "EventCode": "0x40154",
@@ -980,14 +1045,9 @@
980 "BriefDescription": "Link stack predicts right address" 1045 "BriefDescription": "Link stack predicts right address"
981 }, 1046 },
982 {, 1047 {,
983 "EventCode": "0x4C05A",
984 "EventName": "PM_DTLB_MISS_1G",
985 "BriefDescription": "Data TLB reload (after a miss) page size 1G. Implies radix translation was used"
986 },
987 {,
988 "EventCode": "0x36886", 1048 "EventCode": "0x36886",
989 "EventName": "PM_L2_SN_SX_I_DONE", 1049 "EventName": "PM_L2_SN_SX_I_DONE",
990 "BriefDescription": "SNP dispatched and went from Sx to Ix" 1050 "BriefDescription": "Snoop dispatched and went from Sx to Ix"
991 }, 1051 },
992 {, 1052 {,
993 "EventCode": "0x4E04A", 1053 "EventCode": "0x4E04A",
@@ -1000,11 +1060,6 @@
1000 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load" 1060 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load"
1001 }, 1061 },
1002 {, 1062 {,
1003 "EventCode": "0x2608E",
1004 "EventName": "PM_TM_LD_CONF",
1005 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
1006 },
1007 {,
1008 "EventCode": "0x4080", 1063 "EventCode": "0x4080",
1009 "EventName": "PM_INST_FROM_L1", 1064 "EventName": "PM_INST_FROM_L1",
1010 "BriefDescription": "Instruction fetches from L1. L1 instruction hit" 1065 "BriefDescription": "Instruction fetches from L1. L1 instruction hit"
@@ -1037,7 +1092,7 @@
1037 {, 1092 {,
1038 "EventCode": "0x260A6", 1093 "EventCode": "0x260A6",
1039 "EventName": "PM_NON_TM_RST_SC", 1094 "EventName": "PM_NON_TM_RST_SC",
1040 "BriefDescription": "Non-TM snp rst TM SC" 1095 "BriefDescription": "Non-TM snoop hits line in L3 that is TM_SC state and causes it to be invalidated"
1041 }, 1096 },
1042 {, 1097 {,
1043 "EventCode": "0x3608A", 1098 "EventCode": "0x3608A",
@@ -1065,11 +1120,6 @@
1065 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition" 1120 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition"
1066 }, 1121 },
1067 {, 1122 {,
1068 "EventCode": "0x508C",
1069 "EventName": "PM_SHL_CREATED",
1070 "BriefDescription": "Store-Hit-Load Table Entry Created"
1071 },
1072 {,
1073 "EventCode": "0x1504C", 1123 "EventCode": "0x1504C",
1074 "EventName": "PM_IPTEG_FROM_LL4", 1124 "EventName": "PM_IPTEG_FROM_LL4",
1075 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request" 1125 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request"
@@ -1107,7 +1157,7 @@
1107 {, 1157 {,
1108 "EventCode": "0x2608A", 1158 "EventCode": "0x2608A",
1109 "EventName": "PM_ISIDE_DISP_FAIL_ADDR", 1159 "EventName": "PM_ISIDE_DISP_FAIL_ADDR",
1110 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a addr collision with another machine (excludes i_l2mru_tch_reqs)" 1160 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread that failed due to an address collision conflict with an L2 machine already working on this line (e.g. ld-hit-stq or RC/CO/SN machines)"
1111 }, 1161 },
1112 {, 1162 {,
1113 "EventCode": "0x50B4", 1163 "EventCode": "0x50B4",
@@ -1180,9 +1230,9 @@
1180 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed" 1230 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed"
1181 }, 1231 },
1182 {, 1232 {,
1183 "EventCode": "0xE0B8", 1233 "EventCode": "0xD8AC",
1184 "EventName": "PM_LS2_TM_DISALLOW", 1234 "EventName": "PM_LWSYNC",
1185 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it" 1235 "BriefDescription": ""
1186 }, 1236 },
1187 {, 1237 {,
1188 "EventCode": "0x2094", 1238 "EventCode": "0x2094",
@@ -1210,6 +1260,11 @@
1210 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)" 1260 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)"
1211 }, 1261 },
1212 {, 1262 {,
1263 "EventCode": "0xC894",
1264 "EventName": "PM_LS1_UNALIGNED_LD",
1265 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
1266 },
1267 {,
1213 "EventCode": "0x360A2", 1268 "EventCode": "0x360A2",
1214 "EventName": "PM_L3_L2_CO_HIT", 1269 "EventName": "PM_L3_L2_CO_HIT",
1215 "BriefDescription": "L2 CO hits" 1270 "BriefDescription": "L2 CO hits"
@@ -1292,7 +1347,7 @@
1292 {, 1347 {,
1293 "EventCode": "0xC084", 1348 "EventCode": "0xC084",
1294 "EventName": "PM_LS2_LD_VECTOR_FIN", 1349 "EventName": "PM_LS2_LD_VECTOR_FIN",
1295 "BriefDescription": "" 1350 "BriefDescription": "LS2 finished load vector op"
1296 }, 1351 },
1297 {, 1352 {,
1298 "EventCode": "0x1608E", 1353 "EventCode": "0x1608E",
@@ -1345,6 +1400,11 @@
1345 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running" 1400 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running"
1346 }, 1401 },
1347 {, 1402 {,
1403 "EventCode": "0x36084",
1404 "EventName": "PM_L2_RCST_DISP",
1405 "BriefDescription": "All D-side store dispatch attempts for this thread"
1406 },
1407 {,
1348 "EventCode": "0x46084", 1408 "EventCode": "0x46084",
1349 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER", 1409 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER",
1350 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision" 1410 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision"
@@ -1355,11 +1415,6 @@
1355 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software." 1415 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software."
1356 }, 1416 },
1357 {, 1417 {,
1358 "EventCode": "0x36084",
1359 "EventName": "PM_L2_RCST_DISP",
1360 "BriefDescription": "All D-side store dispatch attempts for this thread"
1361 },
1362 {,
1363 "EventCode": "0x45054", 1418 "EventCode": "0x45054",
1364 "EventName": "PM_FMA_CMPL", 1419 "EventName": "PM_FMA_CMPL",
1365 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. " 1420 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. "
@@ -1372,7 +1427,7 @@
1372 {, 1427 {,
1373 "EventCode": "0x36080", 1428 "EventCode": "0x36080",
1374 "EventName": "PM_L2_INST", 1429 "EventName": "PM_L2_INST",
1375 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)" 1430 "BriefDescription": "All successful I-side-instruction-fetch (e.g. i-demand, i-prefetch) dispatches for this thread"
1376 }, 1431 },
1377 {, 1432 {,
1378 "EventCode": "0x3504C", 1433 "EventCode": "0x3504C",
@@ -1387,7 +1442,7 @@
1387 {, 1442 {,
1388 "EventCode": "0x1688A", 1443 "EventCode": "0x1688A",
1389 "EventName": "PM_ISIDE_DISP", 1444 "EventName": "PM_ISIDE_DISP",
1390 "BriefDescription": "All I-side dispatch attempts for this thread (excludes i_l2mru_tch_reqs)" 1445 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread"
1391 }, 1446 },
1392 {, 1447 {,
1393 "EventCode": "0x468AA", 1448 "EventCode": "0x468AA",
@@ -1420,6 +1475,11 @@
1420 "BriefDescription": "Load tm hit in L1" 1475 "BriefDescription": "Load tm hit in L1"
1421 }, 1476 },
1422 {, 1477 {,
1478 "EventCode": "0xE0B8",
1479 "EventName": "PM_LS2_TM_DISALLOW",
1480 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
1481 },
1482 {,
1423 "EventCode": "0x44044", 1483 "EventCode": "0x44044",
1424 "EventName": "PM_INST_FROM_L31_ECO_MOD", 1484 "EventName": "PM_INST_FROM_L31_ECO_MOD",
1425 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)" 1485 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)"
@@ -1467,7 +1527,7 @@
1467 {, 1527 {,
1468 "EventCode": "0x36086", 1528 "EventCode": "0x36086",
1469 "EventName": "PM_L2_RC_ST_DONE", 1529 "EventName": "PM_L2_RC_ST_DONE",
1470 "BriefDescription": "RC did store to line that was Tx or Sx" 1530 "BriefDescription": "Read-claim machine did store to line that was in Tx or Sx (Tagged or Shared state)"
1471 }, 1531 },
1472 {, 1532 {,
1473 "EventCode": "0xE8AC", 1533 "EventCode": "0xE8AC",
@@ -1500,6 +1560,11 @@
1500 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request" 1560 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request"
1501 }, 1561 },
1502 {, 1562 {,
1563 "EventCode": "0x460A6",
1564 "EventName": "PM_RD_FORMING_SC",
1565 "BriefDescription": "Doesn't occur"
1566 },
1567 {,
1503 "EventCode": "0x35042", 1568 "EventCode": "0x35042",
1504 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT", 1569 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT",
1505 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request" 1570 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request"
@@ -1527,7 +1592,7 @@
1527 {, 1592 {,
1528 "EventCode": "0x36882", 1593 "EventCode": "0x36882",
1529 "EventName": "PM_L2_LD_HIT", 1594 "EventName": "PM_L2_LD_HIT",
1530 "BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)" 1595 "BriefDescription": "All successful D-side-Ld or I-side-instruction-fetch dispatches for this thread that were L2 hits"
1531 }, 1596 },
1532 {, 1597 {,
1533 "EventCode": "0x168AC", 1598 "EventCode": "0x168AC",
@@ -1555,11 +1620,6 @@
1555 "BriefDescription": "ProbeNops dispatched" 1620 "BriefDescription": "ProbeNops dispatched"
1556 }, 1621 },
1557 {, 1622 {,
1558 "EventCode": "0x58A8",
1559 "EventName": "PM_DECODE_HOLD_ICT_FULL",
1560 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
1561 },
1562 {,
1563 "EventCode": "0x10052", 1623 "EventCode": "0x10052",
1564 "EventName": "PM_GRP_PUMP_MPRED_RTY", 1624 "EventName": "PM_GRP_PUMP_MPRED_RTY",
1565 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)" 1625 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
@@ -1572,7 +1632,7 @@
1572 {, 1632 {,
1573 "EventCode": "0x2688A", 1633 "EventCode": "0x2688A",
1574 "EventName": "PM_ISIDE_DISP_FAIL_OTHER", 1634 "EventName": "PM_ISIDE_DISP_FAIL_OTHER",
1575 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a reason other than addrs collision (excludes i_l2mru_tch_reqs)" 1635 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread that failed due to reasons other than an address collision conflict with an L2 machine (e.g. no available RC/CO machines)"
1576 }, 1636 },
1577 {, 1637 {,
1578 "EventCode": "0x2001A", 1638 "EventCode": "0x2001A",
@@ -1652,12 +1712,12 @@
1652 {, 1712 {,
1653 "EventCode": "0x46880", 1713 "EventCode": "0x46880",
1654 "EventName": "PM_ISIDE_MRU_TOUCH", 1714 "EventName": "PM_ISIDE_MRU_TOUCH",
1655 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread" 1715 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread I-side L2 MRU touch commands sent to the L2 for this thread"
1656 }, 1716 },
1657 {, 1717 {,
1658 "EventCode": "0x1C05C", 1718 "EventCode": "0x508C",
1659 "EventName": "PM_DTLB_MISS_2M", 1719 "EventName": "PM_SHL_CREATED",
1660 "BriefDescription": "Data TLB reload (after a miss) page size 2M. Implies radix translation was used" 1720 "BriefDescription": "Store-Hit-Load Table Entry Created"
1661 }, 1721 },
1662 {, 1722 {,
1663 "EventCode": "0x50B8", 1723 "EventCode": "0x50B8",
@@ -1672,7 +1732,7 @@
1672 {, 1732 {,
1673 "EventCode": "0x268B2", 1733 "EventCode": "0x268B2",
1674 "EventName": "PM_L3_LOC_GUESS_WRONG", 1734 "EventName": "PM_L3_LOC_GUESS_WRONG",
1675 "BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low" 1735 "BriefDescription": "Prefetch scope predictor selected LNS, but was wrong"
1676 }, 1736 },
1677 {, 1737 {,
1678 "EventCode": "0x36088", 1738 "EventCode": "0x36088",
@@ -1685,6 +1745,11 @@
1685 "BriefDescription": "L3 PF received retry port 2, every retry counted" 1745 "BriefDescription": "L3 PF received retry port 2, every retry counted"
1686 }, 1746 },
1687 {, 1747 {,
1748 "EventCode": "0xD8B0",
1749 "EventName": "PM_PTESYNC",
1750 "BriefDescription": ""
1751 },
1752 {,
1688 "EventCode": "0x26086", 1753 "EventCode": "0x26086",
1689 "EventName": "PM_CO_TM_SC_FOOTPRINT", 1754 "EventName": "PM_CO_TM_SC_FOOTPRINT",
1690 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus" 1755 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus"
@@ -1740,6 +1805,11 @@
1740 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread" 1805 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread"
1741 }, 1806 },
1742 {, 1807 {,
1808 "EventCode": "0xF8B4",
1809 "EventName": "PM_DC_PREF_XCONS_ALLOC",
1810 "BriefDescription": "Prefetch stream allocated in the Ultra conservative phase by either the hardware prefetch mechanism or software prefetch"
1811 },
1812 {,
1743 "EventCode": "0x35048", 1813 "EventCode": "0x35048",
1744 "EventName": "PM_IPTEG_FROM_DL2L3_SHR", 1814 "EventName": "PM_IPTEG_FROM_DL2L3_SHR",
1745 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request" 1815 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request"
@@ -1782,7 +1852,7 @@
1782 {, 1852 {,
1783 "EventCode": "0x460B2", 1853 "EventCode": "0x460B2",
1784 "EventName": "PM_L3_SYS_GUESS_WRONG", 1854 "EventName": "PM_L3_SYS_GUESS_WRONG",
1785 "BriefDescription": "Initial scope=system (VGS or RNS) but data from local or near. Prediction too high" 1855 "BriefDescription": "Prefetch scope predictor selected VGS or RNS, but was wrong"
1786 }, 1856 },
1787 {, 1857 {,
1788 "EventCode": "0x58B8", 1858 "EventCode": "0x58B8",
@@ -1800,11 +1870,6 @@
1800 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim" 1870 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim"
1801 }, 1871 },
1802 {, 1872 {,
1803 "EventCode": "0x4C054",
1804 "EventName": "PM_DERAT_MISS_16G",
1805 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G"
1806 },
1807 {,
1808 "EventCode": "0x268A0", 1873 "EventCode": "0x268A0",
1809 "EventName": "PM_L3_CO_L31", 1874 "EventName": "PM_L3_CO_L31",
1810 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)" 1875 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)"
@@ -1862,7 +1927,7 @@
1862 {, 1927 {,
1863 "EventCode": "0x368B2", 1928 "EventCode": "0x368B2",
1864 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH", 1929 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH",
1865 "BriefDescription": "Initial scope=group (GS or NNS) but data from local node. Prediction too high" 1930 "BriefDescription": "Prefetch scope predictor selected GS or NNS, but was wrong because scope was VGS or RNS"
1866 }, 1931 },
1867 {, 1932 {,
1868 "EventCode": "0xE8BC", 1933 "EventCode": "0xE8BC",
@@ -1897,7 +1962,7 @@
1897 {, 1962 {,
1898 "EventCode": "0x260B2", 1963 "EventCode": "0x260B2",
1899 "EventName": "PM_L3_SYS_GUESS_CORRECT", 1964 "EventName": "PM_L3_SYS_GUESS_CORRECT",
1900 "BriefDescription": "Initial scope=system (VGS or RNS) and data from outside group (far or rem)(pred successful)" 1965 "BriefDescription": "Prefetch scope predictor selected VGS or RNS and was correct"
1901 }, 1966 },
1902 {, 1967 {,
1903 "EventCode": "0x1D146", 1968 "EventCode": "0x1D146",
@@ -1915,6 +1980,11 @@
1915 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts" 1980 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts"
1916 }, 1981 },
1917 {, 1982 {,
1983 "EventCode": "0xC08C",
1984 "EventName": "PM_LSU_DTLB_MISS_16M_2M",
1985 "BriefDescription": "Data TLB Miss page size 16M (HPT) or 2M (Radix)"
1986 },
1987 {,
1918 "EventCode": "0x16080", 1988 "EventCode": "0x16080",
1919 "EventName": "PM_L2_LD", 1989 "EventName": "PM_L2_LD",
1920 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)" 1990 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)"
@@ -1927,7 +1997,7 @@
1927 {, 1997 {,
1928 "EventCode": "0xC080", 1998 "EventCode": "0xC080",
1929 "EventName": "PM_LS0_LD_VECTOR_FIN", 1999 "EventName": "PM_LS0_LD_VECTOR_FIN",
1930 "BriefDescription": "" 2000 "BriefDescription": "LS0 finished load vector op"
1931 }, 2001 },
1932 {, 2002 {,
1933 "EventCode": "0x368B0", 2003 "EventCode": "0x368B0",
@@ -2000,6 +2070,11 @@
2000 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time" 2070 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time"
2001 }, 2071 },
2002 {, 2072 {,
2073 "EventCode": "0xF0B8",
2074 "EventName": "PM_LS0_UNALIGNED_ST",
2075 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
2076 },
2077 {,
2003 "EventCode": "0x20132", 2078 "EventCode": "0x20132",
2004 "EventName": "PM_MRK_DFU_FIN", 2079 "EventName": "PM_MRK_DFU_FIN",
2005 "BriefDescription": "Decimal Unit marked Instruction Finish" 2080 "BriefDescription": "Decimal Unit marked Instruction Finish"
@@ -2007,7 +2082,7 @@
2007 {, 2082 {,
2008 "EventCode": "0x160A6", 2083 "EventCode": "0x160A6",
2009 "EventName": "PM_TM_SC_CO", 2084 "EventName": "PM_TM_SC_CO",
2010 "BriefDescription": "L3 castout TM SC line" 2085 "BriefDescription": "L3 castout of line that was StoreCopy (original value of speculatively written line) in a Transaction"
2011 }, 2086 },
2012 {, 2087 {,
2013 "EventCode": "0xC8B0", 2088 "EventCode": "0xC8B0",
@@ -2017,7 +2092,7 @@
2017 {, 2092 {,
2018 "EventCode": "0x16084", 2093 "EventCode": "0x16084",
2019 "EventName": "PM_L2_RCLD_DISP", 2094 "EventName": "PM_L2_RCLD_DISP",
2020 "BriefDescription": "All I-or-D side load dispatch attempts for this thread (excludes i_l2mru_tch_reqs)" 2095 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread"
2021 }, 2096 },
2022 {, 2097 {,
2023 "EventCode": "0x3F150", 2098 "EventCode": "0x3F150",
@@ -2122,12 +2197,12 @@
2122 {, 2197 {,
2123 "EventCode": "0x46082", 2198 "EventCode": "0x46082",
2124 "EventName": "PM_L2_ST_DISP", 2199 "EventName": "PM_L2_ST_DISP",
2125 "BriefDescription": "All successful D-side store dispatches for this thread (L2 miss + L2 hits)" 2200 "BriefDescription": "All successful D-side store dispatches for this thread"
2126 }, 2201 },
2127 {, 2202 {,
2128 "EventCode": "0x36880", 2203 "EventCode": "0x36880",
2129 "EventName": "PM_L2_INST_MISS", 2204 "EventName": "PM_L2_INST_MISS",
2130 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)" 2205 "BriefDescription": "All successful I-side-instruction-fetch (e.g. i-demand, i-prefetch) dispatches for this thread that were an L2 miss"
2131 }, 2206 },
2132 {, 2207 {,
2133 "EventCode": "0xE084", 2208 "EventCode": "0xE084",
@@ -2217,7 +2292,7 @@
2217 {, 2292 {,
2218 "EventCode": "0xC884", 2293 "EventCode": "0xC884",
2219 "EventName": "PM_LS3_LD_VECTOR_FIN", 2294 "EventName": "PM_LS3_LD_VECTOR_FIN",
2220 "BriefDescription": "" 2295 "BriefDescription": "LS3 finished load vector op"
2221 }, 2296 },
2222 {, 2297 {,
2223 "EventCode": "0x360A8", 2298 "EventCode": "0x360A8",
@@ -2242,7 +2317,7 @@
2242 {, 2317 {,
2243 "EventCode": "0x168B2", 2318 "EventCode": "0x168B2",
2244 "EventName": "PM_L3_GRP_GUESS_CORRECT", 2319 "EventName": "PM_L3_GRP_GUESS_CORRECT",
2245 "BriefDescription": "Initial scope=group (GS or NNS) and data from same group (near) (pred successful)" 2320 "BriefDescription": "Prefetch scope predictor selected GS or NNS and was correct"
2246 }, 2321 },
2247 {, 2322 {,
2248 "EventCode": "0x48A4", 2323 "EventCode": "0x48A4",
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
index 5af1abbe82c4..b4772f54a271 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
@@ -65,11 +65,6 @@
65 "BriefDescription": "Dispatch Held" 65 "BriefDescription": "Dispatch Held"
66 }, 66 },
67 {, 67 {,
68 "EventCode": "0x3D154",
69 "EventName": "PM_MRK_DERAT_MISS_16M",
70 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M"
71 },
72 {,
73 "EventCode": "0x200F8", 68 "EventCode": "0x200F8",
74 "EventName": "PM_EXT_INT", 69 "EventName": "PM_EXT_INT",
75 "BriefDescription": "external interrupt" 70 "BriefDescription": "external interrupt"
@@ -120,6 +115,11 @@
120 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 115 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
121 }, 116 },
122 {, 117 {,
118 "EventCode": "0x4C15C",
119 "EventName": "PM_MRK_DERAT_MISS_16G_1G",
120 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G (hpt mode) and 1G (radix mode)"
121 },
122 {,
123 "EventCode": "0x10024", 123 "EventCode": "0x10024",
124 "EventName": "PM_PMC5_OVERFLOW", 124 "EventName": "PM_PMC5_OVERFLOW",
125 "BriefDescription": "Overflow from counter 5" 125 "BriefDescription": "Overflow from counter 5"
@@ -155,11 +155,6 @@
155 "BriefDescription": "Ict empty for this thread due to Icache Miss" 155 "BriefDescription": "Ict empty for this thread due to Icache Miss"
156 }, 156 },
157 {, 157 {,
158 "EventCode": "0x3D152",
159 "EventName": "PM_MRK_DERAT_MISS_1G",
160 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
161 },
162 {,
163 "EventCode": "0x4F14A", 158 "EventCode": "0x4F14A",
164 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE", 159 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE",
165 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 160 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -185,11 +180,6 @@
185 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 180 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
186 }, 181 },
187 {, 182 {,
188 "EventCode": "0x2C05A",
189 "EventName": "PM_DERAT_MISS_1G",
190 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
191 },
192 {,
193 "EventCode": "0x1F058", 183 "EventCode": "0x1F058",
194 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2", 184 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2",
195 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation" 185 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation"
@@ -240,11 +230,6 @@
240 "BriefDescription": "Data PTEG reload" 230 "BriefDescription": "Data PTEG reload"
241 }, 231 },
242 {, 232 {,
243 "EventCode": "0x2D152",
244 "EventName": "PM_MRK_DERAT_MISS_2M",
245 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
246 },
247 {,
248 "EventCode": "0x2C046", 233 "EventCode": "0x2C046",
249 "EventName": "PM_DATA_FROM_RL2L3_MOD", 234 "EventName": "PM_DATA_FROM_RL2L3_MOD",
250 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load" 235 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
@@ -290,6 +275,11 @@
290 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle" 275 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle"
291 }, 276 },
292 {, 277 {,
278 "EventCode": "0x3C054",
279 "EventName": "PM_DERAT_MISS_16M_2M",
280 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M (HPT mode) or 2M (Radix mode)"
281 },
282 {,
293 "EventCode": "0x4C04C", 283 "EventCode": "0x4C04C",
294 "EventName": "PM_DATA_FROM_DMEM", 284 "EventName": "PM_DATA_FROM_DMEM",
295 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load" 285 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load"
@@ -360,11 +350,6 @@
360 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)" 350 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)"
361 }, 351 },
362 {, 352 {,
363 "EventCode": "0x1C05A",
364 "EventName": "PM_DERAT_MISS_2M",
365 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
366 },
367 {,
368 "EventCode": "0x30024", 353 "EventCode": "0x30024",
369 "EventName": "PM_PMC6_OVERFLOW", 354 "EventName": "PM_PMC6_OVERFLOW",
370 "BriefDescription": "Overflow from counter 6" 355 "BriefDescription": "Overflow from counter 6"
@@ -375,6 +360,11 @@
375 "BriefDescription": "Branch Instruction Finished" 360 "BriefDescription": "Branch Instruction Finished"
376 }, 361 },
377 {, 362 {,
363 "EventCode": "0x3D154",
364 "EventName": "PM_MRK_DERAT_MISS_16M_2M",
365 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M (hpt mode) or 2M (radix mode)"
366 },
367 {,
378 "EventCode": "0x30020", 368 "EventCode": "0x30020",
379 "EventName": "PM_PMC2_REWIND", 369 "EventName": "PM_PMC2_REWIND",
380 "BriefDescription": "PMC2 Rewind Event (did not match condition)" 370 "BriefDescription": "PMC2 Rewind Event (did not match condition)"
@@ -410,11 +400,6 @@
410 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 400 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
411 }, 401 },
412 {, 402 {,
413 "EventCode": "0x4C15C",
414 "EventName": "PM_MRK_DERAT_MISS_16G",
415 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G"
416 },
417 {,
418 "EventCode": "0x14052", 403 "EventCode": "0x14052",
419 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY", 404 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY",
420 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch" 405 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch"
@@ -445,11 +430,6 @@
445 "BriefDescription": "Icache miss demand cycles" 430 "BriefDescription": "Icache miss demand cycles"
446 }, 431 },
447 {, 432 {,
448 "EventCode": "0x3C054",
449 "EventName": "PM_DERAT_MISS_16M",
450 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M"
451 },
452 {,
453 "EventCode": "0x2D14E", 433 "EventCode": "0x2D14E",
454 "EventName": "PM_MRK_DATA_FROM_L21_SHR", 434 "EventName": "PM_MRK_DATA_FROM_L21_SHR",
455 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load" 435 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
index d0b89f930567..8b3b0f3be664 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
@@ -10,11 +10,6 @@
10 "BriefDescription": "Local memory above threshold for LSU medium" 10 "BriefDescription": "Local memory above threshold for LSU medium"
11 }, 11 },
12 {, 12 {,
13 "EventCode": "0x2C056",
14 "EventName": "PM_DTLB_MISS_4K",
15 "BriefDescription": "Data TLB Miss page size 4k"
16 },
17 {,
18 "EventCode": "0x40118", 13 "EventCode": "0x40118",
19 "EventName": "PM_MRK_DCACHE_RELOAD_INTV", 14 "EventName": "PM_MRK_DCACHE_RELOAD_INTV",
20 "BriefDescription": "Combined Intervention event" 15 "BriefDescription": "Combined Intervention event"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/translation.json b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
index bc8e03d7a6b0..b27642676244 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/translation.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
@@ -30,11 +30,6 @@
30 "BriefDescription": "Store finish count. Includes speculative activity" 30 "BriefDescription": "Store finish count. Includes speculative activity"
31 }, 31 },
32 {, 32 {,
33 "EventCode": "0x44042",
34 "EventName": "PM_INST_FROM_L3",
35 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
36 },
37 {,
38 "EventCode": "0x1504A", 33 "EventCode": "0x1504A",
39 "EventName": "PM_IPTEG_FROM_RL2L3_SHR", 34 "EventName": "PM_IPTEG_FROM_RL2L3_SHR",
40 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request" 35 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request"
@@ -125,6 +120,11 @@
125 "BriefDescription": "PMC1 Rewind Value saved" 120 "BriefDescription": "PMC1 Rewind Value saved"
126 }, 121 },
127 {, 122 {,
123 "EventCode": "0x44042",
124 "EventName": "PM_INST_FROM_L3",
125 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
126 },
127 {,
128 "EventCode": "0x200FE", 128 "EventCode": "0x200FE",
129 "EventName": "PM_DATA_FROM_L2MISS", 129 "EventName": "PM_DATA_FROM_L2MISS",
130 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)" 130 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)"
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/basic.json b/tools/perf/pmu-events/arch/s390/cf_z10/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/extended.json b/tools/perf/pmu-events/arch/s390/cf_z10/extended.json
new file mode 100644
index 000000000000..0feedb40f30f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/extended.json
@@ -0,0 +1,110 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1I_L2_SOURCED_WRITES",
5 "BriefDescription": "L1I L2 Sourced Writes",
6 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from the Level-2 (L1.5) cache"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "L1D_L2_SOURCED_WRITES",
11 "BriefDescription": "L1D L2 Sourced Writes",
12 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from the Level-2 (L1.5) cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "L1I_L3_LOCAL_WRITES",
17 "BriefDescription": "L1I L3 Local Writes",
18 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the installed cache line was sourced from the Level-3 cache that is on the same book as the Instruction cache (Local L2 cache)"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "L1D_L3_LOCAL_WRITES",
23 "BriefDescription": "L1D L3 Local Writes",
24 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installtion cache line was source from the Level-3 cache that is on the same book as the Data cache (Local L2 cache)"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "L1I_L3_REMOTE_WRITES",
29 "BriefDescription": "L1I L3 Remote Writes",
30 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the installed cache line was sourced from a Level-3 cache that is not on the same book as the Instruction cache (Remote L2 cache)"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L3_REMOTE_WRITES",
35 "BriefDescription": "L1D L3 Remote Writes",
36 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from a Level-3 cache that is not on the same book as the Data cache (Remote L2 cache)"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "L1D_LMEM_SOURCED_WRITES",
41 "BriefDescription": "L1D Local Memory Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "L1I_LMEM_SOURCED_WRITES",
47 "BriefDescription": "L1I Local Memory Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 I-Cache where the installed cache line was sourced from memory that is attached to the s ame book as the Instruction cache (Local Memory)"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "L1I_CACHELINE_INVALIDATES",
59 "BriefDescription": "L1I Cacheline Invalidates",
60 "PublicDescription": "A cache line in the Level-1 I-Cache has been invalidated by a store on the same CPU as the Level-1 I-Cache"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "ITLB1_WRITES",
65 "BriefDescription": "ITLB1 Writes",
66 "PublicDescription": "A translation entry has been written into the Level-1 Instruction Translation Lookaside Buffer"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "DTLB1_WRITES",
71 "BriefDescription": "DTLB1 Writes",
72 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TLB2_PTE_WRITES",
77 "BriefDescription": "TLB2 PTE Writes",
78 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TLB2_CRSTE_WRITES",
83 "BriefDescription": "TLB2 CRSTE Writes",
84 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
85 },
86 {
87 "EventCode": "142",
88 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
89 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
90 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
91 },
92 {
93 "EventCode": "145",
94 "EventName": "ITLB1_MISSES",
95 "BriefDescription": "ITLB1 Misses",
96 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle an ITLB1 miss is in progress"
97 },
98 {
99 "EventCode": "146",
100 "EventName": "DTLB1_MISSES",
101 "BriefDescription": "DTLB1 Misses",
102 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle an DTLB1 miss is in progress"
103 },
104 {
105 "EventCode": "147",
106 "EventName": "L2C_STORES_SENT",
107 "BriefDescription": "L2C Stores Sent",
108 "PublicDescription": "Incremented by one for every store sent to Level-2 (L1.5) cache"
109 },
110]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/basic.json b/tools/perf/pmu-events/arch/s390/cf_z13/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/extended.json b/tools/perf/pmu-events/arch/s390/cf_z13/extended.json
new file mode 100644
index 000000000000..9a002b6967f1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/extended.json
@@ -0,0 +1,338 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_RO_EXCL_WRITES",
5 "BriefDescription": "L1D Read-only Exclusive Writes",
6 "PublicDescription": "A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line."
7 },
8 {
9 "EventCode": "129",
10 "EventName": "DTLB1_WRITES",
11 "BriefDescription": "DTLB1 Writes",
12 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB1_MISSES",
17 "BriefDescription": "DTLB1 Misses",
18 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
19 },
20 {
21 "EventCode": "131",
22 "EventName": "DTLB1_HPAGE_WRITES",
23 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
24 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "DTLB1_GPAGE_WRITES",
29 "BriefDescription": "DTLB1 Two-Gigabyte Page Writes",
30 "PublicDescription": "Counter:132 Name:DTLB1_GPAGE_WRITES A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L2D_SOURCED_WRITES",
35 "BriefDescription": "L1D L2D Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "ITLB1_WRITES",
41 "BriefDescription": "ITLB1 Writes",
42 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "ITLB1_MISSES",
47 "BriefDescription": "ITLB1 Misses",
48 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle an ITLB1 miss is in progress"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1I_L2I_SOURCED_WRITES",
53 "BriefDescription": "L1I L2I Sourced Writes",
54 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "TLB2_PTE_WRITES",
59 "BriefDescription": "TLB2 PTE Writes",
60 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
65 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
66 "PublicDescription": "A translation entry has been written to the Level-2 TLB Combined Region Segment Table Entry arrays for a one-megabyte large page translation"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "TLB2_CRSTE_WRITES",
71 "BriefDescription": "TLB2 CRSTE Writes",
72 "PublicDescription": "A translation entry has been written to the Level-2 TLB Combined Region Segment Table Entry arrays"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TX_C_TEND",
77 "BriefDescription": "Completed TEND instructions in constrained TX mode",
78 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TX_NC_TEND",
83 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
84 "PublicDescription": "A TEND instruction has completed in a non-constrained transactional-execution mode"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1C_TLB1_MISSES",
89 "BriefDescription": "L1C TLB1 Misses",
90 "PublicDescription": "Increments by one for any cycle where a Level-1 cache or Level-1 TLB miss is in progress."
91 },
92 {
93 "EventCode": "144",
94 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
101 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache with intervention"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "L1D_ONNODE_L4_SOURCED_WRITES",
107 "BriefDescription": "L1D On-Node L4 Sourced Writes",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-4 cache"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "L1D_ONNODE_L3_SOURCED_WRITES_IV",
113 "BriefDescription": "L1D On-Node L3 Sourced Writes with Intervention",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-3 cache with intervention"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "L1D_ONNODE_L3_SOURCED_WRITES",
119 "BriefDescription": "L1D On-Node L3 Sourced Writes",
120 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-3 cache without intervention"
121 },
122 {
123 "EventCode": "149",
124 "EventName": "L1D_ONDRAWER_L4_SOURCED_WRITES",
125 "BriefDescription": "L1D On-Drawer L4 Sourced Writes",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-4 cache"
127 },
128 {
129 "EventCode": "150",
130 "EventName": "L1D_ONDRAWER_L3_SOURCED_WRITES_IV",
131 "BriefDescription": "L1D On-Drawer L3 Sourced Writes with Intervention",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache with intervention"
133 },
134 {
135 "EventCode": "151",
136 "EventName": "L1D_ONDRAWER_L3_SOURCED_WRITES",
137 "BriefDescription": "L1D On-Drawer L3 Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache without intervention"
139 },
140 {
141 "EventCode": "152",
142 "EventName": "L1D_OFFDRAWER_SCOL_L4_SOURCED_WRITES",
143 "BriefDescription": "L1D Off-Drawer Same-Column L4 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-4 cache"
145 },
146 {
147 "EventCode": "153",
148 "EventName": "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV",
149 "BriefDescription": "L1D Off-Drawer Same-Column L3 Sourced Writes with Intervention",
150 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache with intervention"
151 },
152 {
153 "EventCode": "154",
154 "EventName": "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES",
155 "BriefDescription": "L1D Off-Drawer Same-Column L3 Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache without intervention"
157 },
158 {
159 "EventCode": "155",
160 "EventName": "L1D_OFFDRAWER_FCOL_L4_SOURCED_WRITES",
161 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes",
162 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-4 cache"
163 },
164 {
165 "EventCode": "156",
166 "EventName": "L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV",
167 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes with Intervention",
168 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache with intervention"
169 },
170 {
171 "EventCode": "157",
172 "EventName": "L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES",
173 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes",
174 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache without intervention"
175 },
176 {
177 "EventCode": "158",
178 "EventName": "L1D_ONNODE_MEM_SOURCED_WRITES",
179 "BriefDescription": "L1D On-Node Memory Sourced Writes",
180 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Node memory"
181 },
182 {
183 "EventCode": "159",
184 "EventName": "L1D_ONDRAWER_MEM_SOURCED_WRITES",
185 "BriefDescription": "L1D On-Drawer Memory Sourced Writes",
186 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer memory"
187 },
188 {
189 "EventCode": "160",
190 "EventName": "L1D_OFFDRAWER_MEM_SOURCED_WRITES",
191 "BriefDescription": "L1D Off-Drawer Memory Sourced Writes",
192 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer memory"
193 },
194 {
195 "EventCode": "161",
196 "EventName": "L1D_ONCHIP_MEM_SOURCED_WRITES",
197 "BriefDescription": "L1D On-Chip Memory Sourced Writes",
198 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip memory"
199 },
200 {
201 "EventCode": "162",
202 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
203 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
204 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
205 },
206 {
207 "EventCode": "163",
208 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
209 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
210 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache with intervention"
211 },
212 {
213 "EventCode": "164",
214 "EventName": "L1I_ONNODE_L4_SOURCED_WRITES",
215 "BriefDescription": "L1I On-Chip L4 Sourced Writes",
216 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-4 cache"
217 },
218 {
219 "EventCode": "165",
220 "EventName": "L1I_ONNODE_L3_SOURCED_WRITES_IV",
221 "BriefDescription": "L1I On-Node L3 Sourced Writes with Intervention",
222 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-3 cache with intervention"
223 },
224 {
225 "EventCode": "166",
226 "EventName": "L1I_ONNODE_L3_SOURCED_WRITES",
227 "BriefDescription": "L1I On-Node L3 Sourced Writes",
228 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-3 cache without intervention"
229 },
230 {
231 "EventCode": "167",
232 "EventName": "L1I_ONDRAWER_L4_SOURCED_WRITES",
233 "BriefDescription": "L1I On-Drawer L4 Sourced Writes",
234 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-4 cache"
235 },
236 {
237 "EventCode": "168",
238 "EventName": "L1I_ONDRAWER_L3_SOURCED_WRITES_IV",
239 "BriefDescription": "L1I On-Drawer L3 Sourced Writes with Intervention",
240 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache with intervention"
241 },
242 {
243 "EventCode": "169",
244 "EventName": "L1I_ONDRAWER_L3_SOURCED_WRITES",
245 "BriefDescription": "L1I On-Drawer L3 Sourced Writes",
246 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache without intervention"
247 },
248 {
249 "EventCode": "170",
250 "EventName": "L1I_OFFDRAWER_SCOL_L4_SOURCED_WRITES",
251 "BriefDescription": "L1I Off-Drawer Same-Column L4 Sourced Writes",
252 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-4 cache"
253 },
254 {
255 "EventCode": "171",
256 "EventName": "L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV",
257 "BriefDescription": "L1I Off-Drawer Same-Column L3 Sourced Writes with Intervention",
258 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache with intervention"
259 },
260 {
261 "EventCode": "172",
262 "EventName": "L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES",
263 "BriefDescription": "L1I Off-Drawer Same-Column L3 Sourced Writes",
264 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache without intervention"
265 },
266 {
267 "EventCode": "173",
268 "EventName": "L1I_OFFDRAWER_FCOL_L4_SOURCED_WRITES",
269 "BriefDescription": "L1I Off-Drawer Far-Column L4 Sourced Writes",
270 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-4 cache"
271 },
272 {
273 "EventCode": "174",
274 "EventName": "L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV",
275 "BriefDescription": "L1I Off-Drawer Far-Column L3 Sourced Writes with Intervention",
276 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache with intervention"
277 },
278 {
279 "EventCode": "175",
280 "EventName": "L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES",
281 "BriefDescription": "L1I Off-Drawer Far-Column L3 Sourced Writes",
282 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache without intervention"
283 },
284 {
285 "EventCode": "176",
286 "EventName": "L1I_ONNODE_MEM_SOURCED_WRITES",
287 "BriefDescription": "L1I On-Node Memory Sourced Writes",
288 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Node memory"
289 },
290 {
291 "EventCode": "177",
292 "EventName": "L1I_ONDRAWER_MEM_SOURCED_WRITES",
293 "BriefDescription": "L1I On-Drawer Memory Sourced Writes",
294 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer memory"
295 },
296 {
297 "EventCode": "178",
298 "EventName": "L1I_OFFDRAWER_MEM_SOURCED_WRITES",
299 "BriefDescription": "L1I Off-Drawer Memory Sourced Writes",
300 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer memory"
301 },
302 {
303 "EventCode": "179",
304 "EventName": "L1I_ONCHIP_MEM_SOURCED_WRITES",
305 "BriefDescription": "L1I On-Chip Memory Sourced Writes",
306 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Chip memory"
307 },
308 {
309 "EventCode": "218",
310 "EventName": "TX_NC_TABORT",
311 "BriefDescription": "Aborted transactions in non-constrained TX mode",
312 "PublicDescription": "A transaction abort has occurred in a non-constrained transactional-execution mode"
313 },
314 {
315 "EventCode": "219",
316 "EventName": "TX_C_TABORT_NO_SPECIAL",
317 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
318 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
319 },
320 {
321 "EventCode": "220",
322 "EventName": "TX_C_TABORT_SPECIAL",
323 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
324 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
325 },
326 {
327 "EventCode": "448",
328 "EventName": "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
329 "BriefDescription": "Cycle count with one thread active",
330 "PublicDescription": "Cycle count with one thread active"
331 },
332 {
333 "EventCode": "449",
334 "EventName": "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
335 "BriefDescription": "Cycle count with two threads active",
336 "PublicDescription": "Cycle count with two threads active"
337 },
338]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/basic.json b/tools/perf/pmu-events/arch/s390/cf_z14/basic.json
new file mode 100644
index 000000000000..8f653c9d899d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/basic.json
@@ -0,0 +1,50 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/extended.json b/tools/perf/pmu-events/arch/s390/cf_z14/extended.json
new file mode 100644
index 000000000000..aa4dfb46b65b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/extended.json
@@ -0,0 +1,320 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_RO_EXCL_WRITES",
5 "BriefDescription": "L1D Read-only Exclusive Writes",
6 "PublicDescription": "Counter:128 Name:L1D_RO_EXCL_WRITES A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "DTLB2_WRITES",
11 "BriefDescription": "DTLB2 Writes",
12 "PublicDescription": "A translation has been written into The Translation Lookaside Buffer 2 (TLB2) and the request was made by the data cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB2_MISSES",
17 "BriefDescription": "DTLB2 Misses",
18 "PublicDescription": "A TLB2 miss is in progress for a request made by the data cache. Incremented by one for every TLB2 miss in progress for the Level-1 Data cache on this cycle"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "DTLB2_HPAGE_WRITES",
23 "BriefDescription": "DTLB2 One-Megabyte Page Writes",
24 "PublicDescription": "A translation entry was written into the Combined Region and Segment Table Entry array in the Level-2 TLB for a one-megabyte page or a Last Host Translation was done"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "DTLB2_GPAGE_WRITES",
29 "BriefDescription": "DTLB2 Two-Gigabyte Page Writes",
30 "PublicDescription": "A translation entry for a two-gigabyte page was written into the Level-2 TLB"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L2D_SOURCED_WRITES",
35 "BriefDescription": "L1D L2D Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "ITLB2_WRITES",
41 "BriefDescription": "ITLB2 Writes",
42 "PublicDescription": "A translation entry has been written into the Translation Lookaside Buffer 2 (TLB2) and the request was made by the instruction cache"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "ITLB2_MISSES",
47 "BriefDescription": "ITLB2 Misses",
48 "PublicDescription": "A TLB2 miss is in progress for a request made by the instruction cache. Incremented by one for every TLB2 miss in progress for the Level-1 Instruction cache in a cycle"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1I_L2I_SOURCED_WRITES",
53 "BriefDescription": "L1I L2I Sourced Writes",
54 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "TLB2_PTE_WRITES",
59 "BriefDescription": "TLB2 PTE Writes",
60 "PublicDescription": "A translation entry was written into the Page Table Entry array in the Level-2 TLB"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "TLB2_CRSTE_WRITES",
65 "BriefDescription": "TLB2 CRSTE Writes",
66 "PublicDescription": "Translation entries were written into the Combined Region and Segment Table Entry array and the Page Table Entry array in the Level-2 TLB"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "TLB2_ENGINES_BUSY",
71 "BriefDescription": "TLB2 Engines Busy",
72 "PublicDescription": "The number of Level-2 TLB translation engines busy in a cycle"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TX_C_TEND",
77 "BriefDescription": "Completed TEND instructions in constrained TX mode",
78 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TX_NC_TEND",
83 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
84 "PublicDescription": "A TEND instruction has completed in a non-constrained transactional-execution mode"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1C_TLB2_MISSES",
89 "BriefDescription": "L1C TLB2 Misses",
90 "PublicDescription": "Increments by one for any cycle where a level-1 cache or level-2 TLB miss is in progress"
91 },
92 {
93 "EventCode": "144",
94 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "L1D_ONCHIP_MEMORY_SOURCED_WRITES",
101 "BriefDescription": "L1D On-Chip Memory Sourced Writes",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip memory"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
107 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache with intervention"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "L1D_ONCLUSTER_L3_SOURCED_WRITES",
113 "BriefDescription": "L1D On-Cluster L3 Sourced Writes",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Cluster Level-3 cache withountervention"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "L1D_ONCLUSTER_MEMORY_SOURCED_WRITES",
119 "BriefDescription": "L1D On-Cluster Memory Sourced Writes",
120 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Cluster memory"
121 },
122 {
123 "EventCode": "149",
124 "EventName": "L1D_ONCLUSTER_L3_SOURCED_WRITES_IV",
125 "BriefDescription": "L1D On-Cluster L3 Sourced Writes with Intervention",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Cluster Level-3 cache with intervention"
127 },
128 {
129 "EventCode": "150",
130 "EventName": "L1D_OFFCLUSTER_L3_SOURCED_WRITES",
131 "BriefDescription": "L1D Off-Cluster L3 Sourced Writes",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache without intervention"
133 },
134 {
135 "EventCode": "151",
136 "EventName": "L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES",
137 "BriefDescription": "L1D Off-Cluster Memory Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Cluster memory"
139 },
140 {
141 "EventCode": "152",
142 "EventName": "L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV",
143 "BriefDescription": "L1D Off-Cluster L3 Sourced Writes with Intervention",
144 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache with intervention"
145 },
146 {
147 "EventCode": "153",
148 "EventName": "L1D_OFFDRAWER_L3_SOURCED_WRITES",
149 "BriefDescription": "L1D Off-Drawer L3 Sourced Writes",
150 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache without intervention"
151 },
152 {
153 "EventCode": "154",
154 "EventName": "L1D_OFFDRAWER_MEMORY_SOURCED_WRITES",
155 "BriefDescription": "L1D Off-Drawer Memory Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Drawer memory"
157 },
158 {
159 "EventCode": "155",
160 "EventName": "L1D_OFFDRAWER_L3_SOURCED_WRITES_IV",
161 "BriefDescription": "L1D Off-Drawer L3 Sourced Writes with Intervention",
162 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache with intervention"
163 },
164 {
165 "EventCode": "156",
166 "EventName": "L1D_ONDRAWER_L4_SOURCED_WRITES",
167 "BriefDescription": "L1D On-Drawer L4 Sourced Writes",
168 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer Level-4 cache"
169 },
170 {
171 "EventCode": "157",
172 "EventName": "L1D_OFFDRAWER_L4_SOURCED_WRITES",
173 "BriefDescription": "L1D Off-Drawer L4 Sourced Writes",
174 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Drawer Level-4 cache"
175 },
176 {
177 "EventCode": "158",
178 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_RO",
179 "BriefDescription": "L1D On-Chip L3 Sourced Writes read-only",
180 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip L3 but a read-only invalidate was done to remove other copies of the cache line"
181 },
182 {
183 "EventCode": "162",
184 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
185 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
186 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from an On-Chip Level-3 cache without intervention"
187 },
188 {
189 "EventCode": "163",
190 "EventName": "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
191 "BriefDescription": "L1I On-Chip Memory Sourced Writes",
192 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from On-Chip memory"
193 },
194 {
195 "EventCode": "164",
196 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
197 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
198 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from an On-Chip Level-3 cache with intervention"
199 },
200 {
201 "EventCode": "165",
202 "EventName": "L1I_ONCLUSTER_L3_SOURCED_WRITES",
203 "BriefDescription": "L1I On-Cluster L3 Sourced Writes",
204 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Cluster Level-3 cache without intervention"
205 },
206 {
207 "EventCode": "166",
208 "EventName": "L1I_ONCLUSTER_MEMORY_SOURCED_WRITES",
209 "BriefDescription": "L1I On-Cluster Memory Sourced Writes",
210 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Cluster memory"
211 },
212 {
213 "EventCode": "167",
214 "EventName": "L1I_ONCLUSTER_L3_SOURCED_WRITES_IV",
215 "BriefDescription": "L1I On-Cluster L3 Sourced Writes with Intervention",
216 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Cluster Level-3 cache with intervention"
217 },
218 {
219 "EventCode": "168",
220 "EventName": "L1I_OFFCLUSTER_L3_SOURCED_WRITES",
221 "BriefDescription": "L1I Off-Cluster L3 Sourced Writes",
222 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache without intervention"
223 },
224 {
225 "EventCode": "169",
226 "EventName": "L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES",
227 "BriefDescription": "L1I Off-Cluster Memory Sourced Writes",
228 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Cluster memory"
229 },
230 {
231 "EventCode": "170",
232 "EventName": "L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV",
233 "BriefDescription": "L1I Off-Cluster L3 Sourced Writes with Intervention",
234 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache with intervention"
235 },
236 {
237 "EventCode": "171",
238 "EventName": "L1I_OFFDRAWER_L3_SOURCED_WRITES",
239 "BriefDescription": "L1I Off-Drawer L3 Sourced Writes",
240 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache without intervention"
241 },
242 {
243 "EventCode": "172",
244 "EventName": "L1I_OFFDRAWER_MEMORY_SOURCED_WRITES",
245 "BriefDescription": "L1I Off-Drawer Memory Sourced Writes",
246 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Drawer memory"
247 },
248 {
249 "EventCode": "173",
250 "EventName": "L1I_OFFDRAWER_L3_SOURCED_WRITES_IV",
251 "BriefDescription": "L1I Off-Drawer L3 Sourced Writes with Intervention",
252 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache with intervention"
253 },
254 {
255 "EventCode": "174",
256 "EventName": "L1I_ONDRAWER_L4_SOURCED_WRITES",
257 "BriefDescription": "L1I On-Drawer L4 Sourced Writes",
258 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer Level-4 cache"
259 },
260 {
261 "EventCode": "175",
262 "EventName": "L1I_OFFDRAWER_L4_SOURCED_WRITES",
263 "BriefDescription": "L1I Off-Drawer L4 Sourced Writes",
264 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Drawer Level-4 cache"
265 },
266 {
267 "EventCode": "224",
268 "EventName": "BCD_DFP_EXECUTION_SLOTS",
269 "BriefDescription": "BCD DFP Execution Slots",
270 "PublicDescription": "Count of floating point execution slots used for finished Binary Coded Decimal to Decimal Floating Point conversions. Instructions: CDZT, CXZT, CZDT, CZXT"
271 },
272 {
273 "EventCode": "225",
274 "EventName": "VX_BCD_EXECUTION_SLOTS",
275 "BriefDescription": "VX BCD Execution Slots",
276 "PublicDescription": "Count of floating point execution slots used for finished vector arithmetic Binary Coded Decimal instructions. Instructions: VAP, VSP, VMPVMSP, VDP, VSDP, VRP, VLIP, VSRP, VPSOPVCP, VTP, VPKZ, VUPKZ, VCVB, VCVBG, VCVDVCVDG"
277 },
278 {
279 "EventCode": "226",
280 "EventName": "DECIMAL_INSTRUCTIONS",
281 "BriefDescription": "Decimal Instructions",
282 "PublicDescription": "Decimal instructions dispatched. Instructions: CVB, CVD, AP, CP, DP, ED, EDMK, MP, SRP, SP, ZAP"
283 },
284 {
285 "EventCode": "232",
286 "EventName": "LAST_HOST_TRANSLATIONS",
287 "BriefDescription": "Last host translation done",
288 "PublicDescription": "Last Host Translation done"
289 },
290 {
291 "EventCode": "243",
292 "EventName": "TX_NC_TABORT",
293 "BriefDescription": "Aborted transactions in non-constrained TX mode",
294 "PublicDescription": "A transaction abort has occurred in a non-constrained transactional-execution mode"
295 },
296 {
297 "EventCode": "244",
298 "EventName": "TX_C_TABORT_NO_SPECIAL",
299 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
300 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
301 },
302 {
303 "EventCode": "245",
304 "EventName": "TX_C_TABORT_SPECIAL",
305 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
306 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
307 },
308 {
309 "EventCode": "448",
310 "EventName": "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
311 "BriefDescription": "Cycle count with one thread active",
312 "PublicDescription": "Cycle count with one thread active"
313 },
314 {
315 "EventCode": "449",
316 "EventName": "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
317 "BriefDescription": "Cycle count with two threads active",
318 "PublicDescription": "Cycle count with two threads active"
319 },
320]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/basic.json b/tools/perf/pmu-events/arch/s390/cf_z196/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/extended.json b/tools/perf/pmu-events/arch/s390/cf_z196/extended.json
new file mode 100644
index 000000000000..b6d7fec7c2e7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/extended.json
@@ -0,0 +1,146 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_L2_SOURCED_WRITES",
5 "BriefDescription": "L1D L2 Sourced Writes",
6 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from the Level-2 cache"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "L1I_L2_SOURCED_WRITES",
11 "BriefDescription": "L1I L2 Sourced Writes",
12 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from the Level-2 cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB1_MISSES",
17 "BriefDescription": "DTLB1 Misses",
18 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
19 },
20 {
21 "EventCode": "131",
22 "EventName": "ITLB1_MISSES",
23 "BriefDescription": "ITLB1 Misses",
24 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle a ITLB1 miss is in progress."
25 },
26 {
27 "EventCode": "133",
28 "EventName": "L2C_STORES_SENT",
29 "BriefDescription": "L2C Stores Sent",
30 "PublicDescription": "Incremented by one for every store sent to Level-2 cache"
31 },
32 {
33 "EventCode": "134",
34 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES",
35 "BriefDescription": "L1D Off-Book L3 Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Book Level-3 cache"
37 },
38 {
39 "EventCode": "135",
40 "EventName": "L1D_ONBOOK_L4_SOURCED_WRITES",
41 "BriefDescription": "L1D On-Book L4 Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an On Book Level-4 cache"
43 },
44 {
45 "EventCode": "136",
46 "EventName": "L1I_ONBOOK_L4_SOURCED_WRITES",
47 "BriefDescription": "L1I On-Book L4 Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an On Book Level-4 cache"
49 },
50 {
51 "EventCode": "137",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "138",
58 "EventName": "L1D_OFFBOOK_L4_SOURCED_WRITES",
59 "BriefDescription": "L1D Off-Book L4 Sourced Writes",
60 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
61 },
62 {
63 "EventCode": "139",
64 "EventName": "L1I_OFFBOOK_L4_SOURCED_WRITES",
65 "BriefDescription": "L1I Off-Book L4 Sourced Writes",
66 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
67 },
68 {
69 "EventCode": "140",
70 "EventName": "DTLB1_HPAGE_WRITES",
71 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
72 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
73 },
74 {
75 "EventCode": "141",
76 "EventName": "L1D_LMEM_SOURCED_WRITES",
77 "BriefDescription": "L1D Local Memory Sourced Writes",
78 "PublicDescription": "A directory write to the Level-1 D-Cache where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
79 },
80 {
81 "EventCode": "142",
82 "EventName": "L1I_LMEM_SOURCED_WRITES",
83 "BriefDescription": "L1I Local Memory Sourced Writes",
84 "PublicDescription": "A directory write to the Level-1 I-Cache where the installed cache line was sourced from memory that is attached to the same book as the Instruction cache (Local Memory)"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES",
89 "BriefDescription": "L1I Off-Book L3 Sourced Writes",
90 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Book Level-3 cache"
91 },
92 {
93 "EventCode": "144",
94 "EventName": "DTLB1_WRITES",
95 "BriefDescription": "DTLB1 Writes",
96 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "ITLB1_WRITES",
101 "BriefDescription": "ITLB1 Writes",
102 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "TLB2_PTE_WRITES",
107 "BriefDescription": "TLB2 PTE Writes",
108 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
113 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
114 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "TLB2_CRSTE_WRITES",
119 "BriefDescription": "TLB2 CRSTE Writes",
120 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
121 },
122 {
123 "EventCode": "150",
124 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
125 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
126 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an On Chip Level-3 cache"
127 },
128 {
129 "EventCode": "152",
130 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES",
131 "BriefDescription": "L1D Off-Chip L3 Sourced Writes",
132 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache"
133 },
134 {
135 "EventCode": "153",
136 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
137 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an On Chip Level-3 cache"
139 },
140 {
141 "EventCode": "155",
142 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES",
143 "BriefDescription": "L1I Off-Chip L3 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache"
145 },
146]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json b/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json b/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json b/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json
new file mode 100644
index 000000000000..8682126aabb2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json
@@ -0,0 +1,212 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "DTLB1_MISSES",
5 "BriefDescription": "DTLB1 Misses",
6 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
7 },
8 {
9 "EventCode": "129",
10 "EventName": "ITLB1_MISSES",
11 "BriefDescription": "ITLB1 Misses",
12 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle a ITLB1 miss is in progress."
13 },
14 {
15 "EventCode": "130",
16 "EventName": "L1D_L2I_SOURCED_WRITES",
17 "BriefDescription": "L1D L2I Sourced Writes",
18 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "L1I_L2I_SOURCED_WRITES",
23 "BriefDescription": "L1I L2I Sourced Writes",
24 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "L1D_L2D_SOURCED_WRITES",
29 "BriefDescription": "L1D L2D Sourced Writes",
30 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "DTLB1_WRITES",
35 "BriefDescription": "DTLB1 Writes",
36 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
37 },
38 {
39 "EventCode": "135",
40 "EventName": "L1D_LMEM_SOURCED_WRITES",
41 "BriefDescription": "L1D Local Memory Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 Data cache where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
43 },
44 {
45 "EventCode": "137",
46 "EventName": "L1I_LMEM_SOURCED_WRITES",
47 "BriefDescription": "L1I Local Memory Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 Instruction cache where the installed cache line was sourced from memory that is attached to the same book as the Instruction cache (Local Memory)"
49 },
50 {
51 "EventCode": "138",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "139",
58 "EventName": "DTLB1_HPAGE_WRITES",
59 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
60 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
61 },
62 {
63 "EventCode": "140",
64 "EventName": "ITLB1_WRITES",
65 "BriefDescription": "ITLB1 Writes",
66 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
67 },
68 {
69 "EventCode": "141",
70 "EventName": "TLB2_PTE_WRITES",
71 "BriefDescription": "TLB2 PTE Writes",
72 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
73 },
74 {
75 "EventCode": "142",
76 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
77 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
78 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
79 },
80 {
81 "EventCode": "143",
82 "EventName": "TLB2_CRSTE_WRITES",
83 "BriefDescription": "TLB2 CRSTE Writes",
84 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
85 },
86 {
87 "EventCode": "144",
88 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
89 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
90 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On Chip Level-3 cache without intervention"
91 },
92 {
93 "EventCode": "145",
94 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D Off-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "146",
100 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES",
101 "BriefDescription": "L1D Off-Book L3 Sourced Writes",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-3 cache without intervention"
103 },
104 {
105 "EventCode": "147",
106 "EventName": "L1D_ONBOOK_L4_SOURCED_WRITES",
107 "BriefDescription": "L1D On-Book L4 Sourced Writes",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On Book Level-4 cache"
109 },
110 {
111 "EventCode": "148",
112 "EventName": "L1D_OFFBOOK_L4_SOURCED_WRITES",
113 "BriefDescription": "L1D Off-Book L4 Sourced Writes",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
115 },
116 {
117 "EventCode": "149",
118 "EventName": "TX_NC_TEND",
119 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
120 "PublicDescription": "A TEND instruction has completed in a nonconstrained transactional-execution mode"
121 },
122 {
123 "EventCode": "150",
124 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
125 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from a On Chip Level-3 cache with intervention"
127 },
128 {
129 "EventCode": "151",
130 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES_IV",
131 "BriefDescription": "L1D Off-Chip L3 Sourced Writes with Intervention",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache with intervention"
133 },
134 {
135 "EventCode": "152",
136 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES_IV",
137 "BriefDescription": "L1D Off-Book L3 Sourced Writes with Intervention",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-3 cache with intervention"
139 },
140 {
141 "EventCode": "153",
142 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
143 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache without intervention"
145 },
146 {
147 "EventCode": "154",
148 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES",
149 "BriefDescription": "L1I Off-Chip L3 Sourced Writes",
150 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache without intervention"
151 },
152 {
153 "EventCode": "155",
154 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES",
155 "BriefDescription": "L1I Off-Book L3 Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-3 cache without intervention"
157 },
158 {
159 "EventCode": "156",
160 "EventName": "L1I_ONBOOK_L4_SOURCED_WRITES",
161 "BriefDescription": "L1I On-Book L4 Sourced Writes",
162 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Book Level-4 cache"
163 },
164 {
165 "EventCode": "157",
166 "EventName": "L1I_OFFBOOK_L4_SOURCED_WRITES",
167 "BriefDescription": "L1I Off-Book L4 Sourced Writes",
168 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
169 },
170 {
171 "EventCode": "158",
172 "EventName": "TX_C_TEND",
173 "BriefDescription": "Completed TEND instructions in constrained TX mode",
174 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
175 },
176 {
177 "EventCode": "159",
178 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
179 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
180 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache with intervention"
181 },
182 {
183 "EventCode": "160",
184 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES_IV",
185 "BriefDescription": "L1I Off-Chip L3 Sourced Writes with Intervention",
186 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache with intervention"
187 },
188 {
189 "EventCode": "161",
190 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES_IV",
191 "BriefDescription": "L1I Off-Book L3 Sourced Writes with Intervention",
192 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-3 cache with intervention"
193 },
194 {
195 "EventCode": "177",
196 "EventName": "TX_NC_TABORT",
197 "BriefDescription": "Aborted transactions in non-constrained TX mode",
198 "PublicDescription": "A transaction abort has occurred in a nonconstrained transactional-execution mode"
199 },
200 {
201 "EventCode": "178",
202 "EventName": "TX_C_TABORT_NO_SPECIAL",
203 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
204 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
205 },
206 {
207 "EventCode": "179",
208 "EventName": "TX_C_TABORT_SPECIAL",
209 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
210 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
211 },
212]
diff --git a/tools/perf/pmu-events/arch/s390/mapfile.csv b/tools/perf/pmu-events/arch/s390/mapfile.csv
new file mode 100644
index 000000000000..78bcf7f8e206
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/mapfile.csv
@@ -0,0 +1,6 @@
1Family-model,Version,Filename,EventType
2^IBM.209[78].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z10,core
3^IBM.281[78].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z196,core
4^IBM.282[78].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_zec12,core
5^IBM.296[45].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z13,core
6^IBM.390[67].*[13]\.[1-5].[[:xdigit:]]+$,3,cf_z14,core
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index 93656f2fd53a..7e3cce3bcf3b 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -29,7 +29,6 @@ GenuineIntel-6-4D,v13,silvermont,core
29GenuineIntel-6-4C,v13,silvermont,core 29GenuineIntel-6-4C,v13,silvermont,core
30GenuineIntel-6-2A,v15,sandybridge,core 30GenuineIntel-6-2A,v15,sandybridge,core
31GenuineIntel-6-2C,v2,westmereep-dp,core 31GenuineIntel-6-2C,v2,westmereep-dp,core
32GenuineIntel-6-2C,v2,westmereep-dp,core
33GenuineIntel-6-25,v2,westmereep-sp,core 32GenuineIntel-6-25,v2,westmereep-sp,core
34GenuineIntel-6-2F,v2,westmereex,core 33GenuineIntel-6-2F,v2,westmereex,core
35GenuineIntel-6-55,v1,skylakex,core 34GenuineIntel-6-55,v1,skylakex,core
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index b578aa26e375..db3a594ee1e4 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -39,11 +39,13 @@
39#include <unistd.h> 39#include <unistd.h>
40#include <stdarg.h> 40#include <stdarg.h>
41#include <libgen.h> 41#include <libgen.h>
42#include <limits.h>
42#include <dirent.h> 43#include <dirent.h>
43#include <sys/time.h> /* getrlimit */ 44#include <sys/time.h> /* getrlimit */
44#include <sys/resource.h> /* getrlimit */ 45#include <sys/resource.h> /* getrlimit */
45#include <ftw.h> 46#include <ftw.h>
46#include <sys/stat.h> 47#include <sys/stat.h>
48#include <linux/list.h>
47#include "jsmn.h" 49#include "jsmn.h"
48#include "json.h" 50#include "json.h"
49#include "jevents.h" 51#include "jevents.h"
@@ -249,31 +251,25 @@ static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
249 jsmntok_t *loc = (t); \ 251 jsmntok_t *loc = (t); \
250 if (!(t)->start && (t) > tokens) \ 252 if (!(t)->start && (t) > tokens) \
251 loc = (t) - 1; \ 253 loc = (t) - 1; \
252 pr_err("%s:%d: " m ", got %s\n", fn, \ 254 pr_err("%s:%d: " m ", got %s\n", fn, \
253 json_line(map, loc), \ 255 json_line(map, loc), \
254 json_name(t)); \ 256 json_name(t)); \
257 err = -EIO; \
255 goto out_free; \ 258 goto out_free; \
256} } while (0) 259} } while (0)
257 260
258#define TOPIC_DEPTH 256 261static char *topic;
259static char *topic_array[TOPIC_DEPTH];
260static int topic_level;
261 262
262static char *get_topic(void) 263static char *get_topic(void)
263{ 264{
264 char *tp_old, *tp = NULL; 265 char *tp;
265 int i; 266 int i;
266 267
267 for (i = 0; i < topic_level + 1; i++) { 268 /* tp is free'd in process_one_file() */
268 int n; 269 i = asprintf(&tp, "%s", topic);
269 270 if (i < 0) {
270 tp_old = tp; 271 pr_info("%s: asprintf() error %s\n", prog);
271 n = asprintf(&tp, "%s%s", tp ?: "", topic_array[i]); 272 return NULL;
272 if (n < 0) {
273 pr_info("%s: asprintf() error %s\n", prog);
274 return NULL;
275 }
276 free(tp_old);
277 } 273 }
278 274
279 for (i = 0; i < (int) strlen(tp); i++) { 275 for (i = 0; i < (int) strlen(tp); i++) {
@@ -290,25 +286,15 @@ static char *get_topic(void)
290 return tp; 286 return tp;
291} 287}
292 288
293static int add_topic(int level, char *bname) 289static int add_topic(char *bname)
294{ 290{
295 char *topic; 291 free(topic);
296
297 level -= 2;
298
299 if (level >= TOPIC_DEPTH)
300 return -EINVAL;
301
302 topic = strdup(bname); 292 topic = strdup(bname);
303 if (!topic) { 293 if (!topic) {
304 pr_info("%s: strdup() error %s for file %s\n", prog, 294 pr_info("%s: strdup() error %s for file %s\n", prog,
305 strerror(errno), bname); 295 strerror(errno), bname);
306 return -ENOMEM; 296 return -ENOMEM;
307 } 297 }
308
309 free(topic_array[topic_level]);
310 topic_array[topic_level] = topic;
311 topic_level = level;
312 return 0; 298 return 0;
313} 299}
314 300
@@ -366,6 +352,81 @@ static int print_events_table_entry(void *data, char *name, char *event,
366 return 0; 352 return 0;
367} 353}
368 354
355struct event_struct {
356 struct list_head list;
357 char *name;
358 char *event;
359 char *desc;
360 char *long_desc;
361 char *pmu;
362 char *unit;
363 char *perpkg;
364 char *metric_expr;
365 char *metric_name;
366 char *metric_group;
367};
368
369#define ADD_EVENT_FIELD(field) do { if (field) { \
370 es->field = strdup(field); \
371 if (!es->field) \
372 goto out_free; \
373} } while (0)
374
375#define FREE_EVENT_FIELD(field) free(es->field)
376
377#define TRY_FIXUP_FIELD(field) do { if (es->field && !*field) {\
378 *field = strdup(es->field); \
379 if (!*field) \
380 return -ENOMEM; \
381} } while (0)
382
383#define FOR_ALL_EVENT_STRUCT_FIELDS(op) do { \
384 op(name); \
385 op(event); \
386 op(desc); \
387 op(long_desc); \
388 op(pmu); \
389 op(unit); \
390 op(perpkg); \
391 op(metric_expr); \
392 op(metric_name); \
393 op(metric_group); \
394} while (0)
395
396static LIST_HEAD(arch_std_events);
397
398static void free_arch_std_events(void)
399{
400 struct event_struct *es, *next;
401
402 list_for_each_entry_safe(es, next, &arch_std_events, list) {
403 FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
404 list_del(&es->list);
405 free(es);
406 }
407}
408
409static int save_arch_std_events(void *data, char *name, char *event,
410 char *desc, char *long_desc, char *pmu,
411 char *unit, char *perpkg, char *metric_expr,
412 char *metric_name, char *metric_group)
413{
414 struct event_struct *es;
415 struct stat *sb = data;
416
417 es = malloc(sizeof(*es));
418 if (!es)
419 return -ENOMEM;
420 memset(es, 0, sizeof(*es));
421 FOR_ALL_EVENT_STRUCT_FIELDS(ADD_EVENT_FIELD);
422 list_add_tail(&es->list, &arch_std_events);
423 return 0;
424out_free:
425 FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
426 free(es);
427 return -ENOMEM;
428}
429
369static void print_events_table_suffix(FILE *outfp) 430static void print_events_table_suffix(FILE *outfp)
370{ 431{
371 fprintf(outfp, "{\n"); 432 fprintf(outfp, "{\n");
@@ -407,6 +468,32 @@ static char *real_event(const char *name, char *event)
407 return event; 468 return event;
408} 469}
409 470
471static int
472try_fixup(const char *fn, char *arch_std, char **event, char **desc,
473 char **name, char **long_desc, char **pmu, char **filter,
474 char **perpkg, char **unit, char **metric_expr, char **metric_name,
475 char **metric_group, unsigned long long eventcode)
476{
477 /* try to find matching event from arch standard values */
478 struct event_struct *es;
479
480 list_for_each_entry(es, &arch_std_events, list) {
481 if (!strcmp(arch_std, es->name)) {
482 if (!eventcode && es->event) {
483 /* allow EventCode to be overridden */
484 free(*event);
485 *event = NULL;
486 }
487 FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD);
488 return 0;
489 }
490 }
491
492 pr_err("%s: could not find matching %s for %s\n",
493 prog, arch_std, fn);
494 return -1;
495}
496
410/* Call func with each event in the json file */ 497/* Call func with each event in the json file */
411int json_events(const char *fn, 498int json_events(const char *fn,
412 int (*func)(void *data, char *name, char *event, char *desc, 499 int (*func)(void *data, char *name, char *event, char *desc,
@@ -416,7 +503,7 @@ int json_events(const char *fn,
416 char *metric_name, char *metric_group), 503 char *metric_name, char *metric_group),
417 void *data) 504 void *data)
418{ 505{
419 int err = -EIO; 506 int err;
420 size_t size; 507 size_t size;
421 jsmntok_t *tokens, *tok; 508 jsmntok_t *tokens, *tok;
422 int i, j, len; 509 int i, j, len;
@@ -442,6 +529,7 @@ int json_events(const char *fn,
442 char *metric_expr = NULL; 529 char *metric_expr = NULL;
443 char *metric_name = NULL; 530 char *metric_name = NULL;
444 char *metric_group = NULL; 531 char *metric_group = NULL;
532 char *arch_std = NULL;
445 unsigned long long eventcode = 0; 533 unsigned long long eventcode = 0;
446 struct msrmap *msr = NULL; 534 struct msrmap *msr = NULL;
447 jsmntok_t *msrval = NULL; 535 jsmntok_t *msrval = NULL;
@@ -527,6 +615,10 @@ int json_events(const char *fn,
527 addfield(map, &metric_expr, "", "", val); 615 addfield(map, &metric_expr, "", "", val);
528 for (s = metric_expr; *s; s++) 616 for (s = metric_expr; *s; s++)
529 *s = tolower(*s); 617 *s = tolower(*s);
618 } else if (json_streq(map, field, "ArchStdEvent")) {
619 addfield(map, &arch_std, "", "", val);
620 for (s = arch_std; *s; s++)
621 *s = tolower(*s);
530 } 622 }
531 /* ignore unknown fields */ 623 /* ignore unknown fields */
532 } 624 }
@@ -551,8 +643,21 @@ int json_events(const char *fn,
551 if (name) 643 if (name)
552 fixname(name); 644 fixname(name);
553 645
646 if (arch_std) {
647 /*
648 * An arch standard event is referenced, so try to
649 * fixup any unassigned values.
650 */
651 err = try_fixup(fn, arch_std, &event, &desc, &name,
652 &long_desc, &pmu, &filter, &perpkg,
653 &unit, &metric_expr, &metric_name,
654 &metric_group, eventcode);
655 if (err)
656 goto free_strings;
657 }
554 err = func(data, name, real_event(name, event), desc, long_desc, 658 err = func(data, name, real_event(name, event), desc, long_desc,
555 pmu, unit, perpkg, metric_expr, metric_name, metric_group); 659 pmu, unit, perpkg, metric_expr, metric_name, metric_group);
660free_strings:
556 free(event); 661 free(event);
557 free(desc); 662 free(desc);
558 free(name); 663 free(name);
@@ -565,6 +670,8 @@ int json_events(const char *fn,
565 free(metric_expr); 670 free(metric_expr);
566 free(metric_name); 671 free(metric_name);
567 free(metric_group); 672 free(metric_group);
673 free(arch_std);
674
568 if (err) 675 if (err)
569 break; 676 break;
570 tok += j; 677 tok += j;
@@ -588,7 +695,7 @@ static char *file_name_to_table_name(char *fname)
588 * Derive rest of table name from basename of the JSON file, 695 * Derive rest of table name from basename of the JSON file,
589 * replacing hyphens and stripping out .json suffix. 696 * replacing hyphens and stripping out .json suffix.
590 */ 697 */
591 n = asprintf(&tblname, "pme_%s", basename(fname)); 698 n = asprintf(&tblname, "pme_%s", fname);
592 if (n < 0) { 699 if (n < 0) {
593 pr_info("%s: asprintf() error %s for file %s\n", prog, 700 pr_info("%s: asprintf() error %s for file %s\n", prog,
594 strerror(errno), fname); 701 strerror(errno), fname);
@@ -598,7 +705,7 @@ static char *file_name_to_table_name(char *fname)
598 for (i = 0; i < strlen(tblname); i++) { 705 for (i = 0; i < strlen(tblname); i++) {
599 c = tblname[i]; 706 c = tblname[i];
600 707
601 if (c == '-') 708 if (c == '-' || c == '/')
602 tblname[i] = '_'; 709 tblname[i] = '_';
603 else if (c == '.') { 710 else if (c == '.') {
604 tblname[i] = '\0'; 711 tblname[i] = '\0';
@@ -755,25 +862,106 @@ static int get_maxfds(void)
755static FILE *eventsfp; 862static FILE *eventsfp;
756static char *mapfile; 863static char *mapfile;
757 864
865static int is_leaf_dir(const char *fpath)
866{
867 DIR *d;
868 struct dirent *dir;
869 int res = 1;
870
871 d = opendir(fpath);
872 if (!d)
873 return 0;
874
875 while ((dir = readdir(d)) != NULL) {
876 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
877 continue;
878
879 if (dir->d_type == DT_DIR) {
880 res = 0;
881 break;
882 } else if (dir->d_type == DT_UNKNOWN) {
883 char path[PATH_MAX];
884 struct stat st;
885
886 sprintf(path, "%s/%s", fpath, dir->d_name);
887 if (stat(path, &st))
888 break;
889
890 if (S_ISDIR(st.st_mode)) {
891 res = 0;
892 break;
893 }
894 }
895 }
896
897 closedir(d);
898
899 return res;
900}
901
902static int is_json_file(const char *name)
903{
904 const char *suffix;
905
906 if (strlen(name) < 5)
907 return 0;
908
909 suffix = name + strlen(name) - 5;
910
911 if (strncmp(suffix, ".json", 5) == 0)
912 return 1;
913 return 0;
914}
915
916static int preprocess_arch_std_files(const char *fpath, const struct stat *sb,
917 int typeflag, struct FTW *ftwbuf)
918{
919 int level = ftwbuf->level;
920 int is_file = typeflag == FTW_F;
921
922 if (level == 1 && is_file && is_json_file(fpath))
923 return json_events(fpath, save_arch_std_events, (void *)sb);
924
925 return 0;
926}
927
758static int process_one_file(const char *fpath, const struct stat *sb, 928static int process_one_file(const char *fpath, const struct stat *sb,
759 int typeflag, struct FTW *ftwbuf) 929 int typeflag, struct FTW *ftwbuf)
760{ 930{
761 char *tblname, *bname = (char *) fpath + ftwbuf->base; 931 char *tblname, *bname;
762 int is_dir = typeflag == FTW_D; 932 int is_dir = typeflag == FTW_D;
763 int is_file = typeflag == FTW_F; 933 int is_file = typeflag == FTW_F;
764 int level = ftwbuf->level; 934 int level = ftwbuf->level;
765 int err = 0; 935 int err = 0;
766 936
937 if (level == 2 && is_dir) {
938 /*
939 * For level 2 directory, bname will include parent name,
940 * like vendor/platform. So search back from platform dir
941 * to find this.
942 */
943 bname = (char *) fpath + ftwbuf->base - 2;
944 for (;;) {
945 if (*bname == '/')
946 break;
947 bname--;
948 }
949 bname++;
950 } else
951 bname = (char *) fpath + ftwbuf->base;
952
767 pr_debug("%s %d %7jd %-20s %s\n", 953 pr_debug("%s %d %7jd %-20s %s\n",
768 is_file ? "f" : is_dir ? "d" : "x", 954 is_file ? "f" : is_dir ? "d" : "x",
769 level, sb->st_size, bname, fpath); 955 level, sb->st_size, bname, fpath);
770 956
771 /* base dir */ 957 /* base dir or too deep */
772 if (level == 0) 958 if (level == 0 || level > 3)
773 return 0; 959 return 0;
774 960
961
775 /* model directory, reset topic */ 962 /* model directory, reset topic */
776 if (level == 1 && is_dir) { 963 if ((level == 1 && is_dir && is_leaf_dir(fpath)) ||
964 (level == 2 && is_dir)) {
777 if (close_table) 965 if (close_table)
778 print_events_table_suffix(eventsfp); 966 print_events_table_suffix(eventsfp);
779 967
@@ -798,16 +986,10 @@ static int process_one_file(const char *fpath, const struct stat *sb,
798 * after processing all JSON files (so we can write out the 986 * after processing all JSON files (so we can write out the
799 * mapping table after all PMU events tables). 987 * mapping table after all PMU events tables).
800 * 988 *
801 * TODO: Allow for multiple mapfiles? Punt for now.
802 */ 989 */
803 if (level == 1 && is_file) { 990 if (level == 1 && is_file) {
804 if (!strncmp(bname, "mapfile.csv", 11)) { 991 if (!strcmp(bname, "mapfile.csv")) {
805 if (mapfile) { 992 mapfile = strdup(fpath);
806 pr_info("%s: Many mapfiles? Using %s, ignoring %s\n",
807 prog, mapfile, fpath);
808 } else {
809 mapfile = strdup(fpath);
810 }
811 return 0; 993 return 0;
812 } 994 }
813 995
@@ -820,16 +1002,14 @@ static int process_one_file(const char *fpath, const struct stat *sb,
820 * ignore it. It could be a readme.txt for instance. 1002 * ignore it. It could be a readme.txt for instance.
821 */ 1003 */
822 if (is_file) { 1004 if (is_file) {
823 char *suffix = bname + strlen(bname) - 5; 1005 if (!is_json_file(bname)) {
824
825 if (strncmp(suffix, ".json", 5)) {
826 pr_info("%s: Ignoring file without .json suffix %s\n", prog, 1006 pr_info("%s: Ignoring file without .json suffix %s\n", prog,
827 fpath); 1007 fpath);
828 return 0; 1008 return 0;
829 } 1009 }
830 } 1010 }
831 1011
832 if (level > 1 && add_topic(level, bname)) 1012 if (level > 1 && add_topic(bname))
833 return -ENOMEM; 1013 return -ENOMEM;
834 1014
835 /* 1015 /*
@@ -928,12 +1108,26 @@ int main(int argc, char *argv[])
928 1108
929 maxfds = get_maxfds(); 1109 maxfds = get_maxfds();
930 mapfile = NULL; 1110 mapfile = NULL;
1111 rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0);
1112 if (rc && verbose) {
1113 pr_info("%s: Error preprocessing arch standard files %s\n",
1114 prog, ldirname);
1115 goto empty_map;
1116 } else if (rc < 0) {
1117 /* Make build fail */
1118 free_arch_std_events();
1119 return 1;
1120 } else if (rc) {
1121 goto empty_map;
1122 }
1123
931 rc = nftw(ldirname, process_one_file, maxfds, 0); 1124 rc = nftw(ldirname, process_one_file, maxfds, 0);
932 if (rc && verbose) { 1125 if (rc && verbose) {
933 pr_info("%s: Error walking file tree %s\n", prog, ldirname); 1126 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
934 goto empty_map; 1127 goto empty_map;
935 } else if (rc < 0) { 1128 } else if (rc < 0) {
936 /* Make build fail */ 1129 /* Make build fail */
1130 free_arch_std_events();
937 return 1; 1131 return 1;
938 } else if (rc) { 1132 } else if (rc) {
939 goto empty_map; 1133 goto empty_map;
@@ -958,5 +1152,6 @@ int main(int argc, char *argv[])
958empty_map: 1152empty_map:
959 fclose(eventsfp); 1153 fclose(eventsfp);
960 create_empty_mapping(output_file); 1154 create_empty_mapping(output_file);
1155 free_arch_std_events();
961 return 0; 1156 return 0;
962} 1157}
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index c235c22b107a..0a29c5c3079f 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -42,10 +42,10 @@ def main(context_switch = 0, thread = -1):
42 event = evlist.read_on_cpu(cpu) 42 event = evlist.read_on_cpu(cpu)
43 if not event: 43 if not event:
44 continue 44 continue
45 print "cpu: %2d, pid: %4d, tid: %4d" % (event.sample_cpu, 45 print("cpu: {0}, pid: {1}, tid: {2} {3}".format(event.sample_cpu,
46 event.sample_pid, 46 event.sample_pid,
47 event.sample_tid), 47 event.sample_tid,
48 print event 48 event))
49 49
50if __name__ == '__main__': 50if __name__ == '__main__':
51 """ 51 """
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index fcd1dd667906..1a0d27757eec 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -23,7 +23,17 @@
23#include "../../../perf.h" 23#include "../../../perf.h"
24#include "../../../util/trace-event.h" 24#include "../../../util/trace-event.h"
25 25
26#if PY_MAJOR_VERSION < 3
27#define _PyCapsule_GetPointer(arg1, arg2) \
28 PyCObject_AsVoidPtr(arg1)
29
26PyMODINIT_FUNC initperf_trace_context(void); 30PyMODINIT_FUNC initperf_trace_context(void);
31#else
32#define _PyCapsule_GetPointer(arg1, arg2) \
33 PyCapsule_GetPointer((arg1), (arg2))
34
35PyMODINIT_FUNC PyInit_perf_trace_context(void);
36#endif
27 37
28static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) 38static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
29{ 39{
@@ -34,7 +44,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
34 if (!PyArg_ParseTuple(args, "O", &context)) 44 if (!PyArg_ParseTuple(args, "O", &context))
35 return NULL; 45 return NULL;
36 46
37 scripting_context = PyCObject_AsVoidPtr(context); 47 scripting_context = _PyCapsule_GetPointer(context, NULL);
38 retval = common_pc(scripting_context); 48 retval = common_pc(scripting_context);
39 49
40 return Py_BuildValue("i", retval); 50 return Py_BuildValue("i", retval);
@@ -50,7 +60,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *obj,
50 if (!PyArg_ParseTuple(args, "O", &context)) 60 if (!PyArg_ParseTuple(args, "O", &context))
51 return NULL; 61 return NULL;
52 62
53 scripting_context = PyCObject_AsVoidPtr(context); 63 scripting_context = _PyCapsule_GetPointer(context, NULL);
54 retval = common_flags(scripting_context); 64 retval = common_flags(scripting_context);
55 65
56 return Py_BuildValue("i", retval); 66 return Py_BuildValue("i", retval);
@@ -66,7 +76,7 @@ static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
66 if (!PyArg_ParseTuple(args, "O", &context)) 76 if (!PyArg_ParseTuple(args, "O", &context))
67 return NULL; 77 return NULL;
68 78
69 scripting_context = PyCObject_AsVoidPtr(context); 79 scripting_context = _PyCapsule_GetPointer(context, NULL);
70 retval = common_lock_depth(scripting_context); 80 retval = common_lock_depth(scripting_context);
71 81
72 return Py_BuildValue("i", retval); 82 return Py_BuildValue("i", retval);
@@ -82,7 +92,25 @@ static PyMethodDef ContextMethods[] = {
82 { NULL, NULL, 0, NULL} 92 { NULL, NULL, 0, NULL}
83}; 93};
84 94
95#if PY_MAJOR_VERSION < 3
85PyMODINIT_FUNC initperf_trace_context(void) 96PyMODINIT_FUNC initperf_trace_context(void)
86{ 97{
87 (void) Py_InitModule("perf_trace_context", ContextMethods); 98 (void) Py_InitModule("perf_trace_context", ContextMethods);
88} 99}
100#else
101PyMODINIT_FUNC PyInit_perf_trace_context(void)
102{
103 static struct PyModuleDef moduledef = {
104 PyModuleDef_HEAD_INIT,
105 "perf_trace_context", /* m_name */
106 "", /* m_doc */
107 -1, /* m_size */
108 ContextMethods, /* m_methods */
109 NULL, /* m_reload */
110 NULL, /* m_traverse */
111 NULL, /* m_clear */
112 NULL, /* m_free */
113 };
114 return PyModule_Create(&moduledef);
115}
116#endif
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 87bf3edb037c..6c108fa79ae3 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -20,6 +20,7 @@ perf-y += hists_cumulate.o
20perf-y += python-use.o 20perf-y += python-use.o
21perf-y += bp_signal.o 21perf-y += bp_signal.o
22perf-y += bp_signal_overflow.o 22perf-y += bp_signal_overflow.o
23perf-y += bp_account.o
23perf-y += task-exit.o 24perf-y += task-exit.o
24perf-y += sw-clock.o 25perf-y += sw-clock.o
25perf-y += mmap-thread-lookup.o 26perf-y += mmap-thread-lookup.o
@@ -47,6 +48,7 @@ perf-y += bitmap.o
47perf-y += perf-hooks.o 48perf-y += perf-hooks.o
48perf-y += clang.o 49perf-y += clang.o
49perf-y += unit_number__scnprintf.o 50perf-y += unit_number__scnprintf.o
51perf-y += mem2node.o
50 52
51$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 53$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
52 $(call rule_mkdir) 54 $(call rule_mkdir)
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 97f64ad7fa08..05dfe11c2f9e 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -170,8 +170,8 @@ static int run_dir(const char *d, const char *perf)
170 if (verbose > 0) 170 if (verbose > 0)
171 vcnt++; 171 vcnt++;
172 172
173 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", 173 scnprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
174 d, d, perf, vcnt, v); 174 d, d, perf, vcnt, v);
175 175
176 return system(cmd) ? TEST_FAIL : TEST_OK; 176 return system(cmd) ? TEST_FAIL : TEST_OK;
177} 177}
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index f906b793196f..8a33ca4f9e1f 100644
--- a/tools/perf/tests/attr/test-record-group-sampling
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -35,3 +35,6 @@ inherit=0
35# sampling disabled 35# sampling disabled
36sample_freq=0 36sample_freq=0
37sample_period=0 37sample_period=0
38freq=0
39write_backward=0
40sample_id_all=0
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index e0b1b414d466..6d598cc071ae 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -33,10 +33,9 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
33 for (i = 0; i < evlist->nr_mmaps; i++) { 33 for (i = 0; i < evlist->nr_mmaps; i++) {
34 struct perf_mmap *map = &evlist->overwrite_mmap[i]; 34 struct perf_mmap *map = &evlist->overwrite_mmap[i];
35 union perf_event *event; 35 union perf_event *event;
36 u64 start, end;
37 36
38 perf_mmap__read_init(map, true, &start, &end); 37 perf_mmap__read_init(map);
39 while ((event = perf_mmap__read_event(map, true, &start, end)) != NULL) { 38 while ((event = perf_mmap__read_event(map)) != NULL) {
40 const u32 type = event->header.type; 39 const u32 type = event->header.type;
41 40
42 switch (type) { 41 switch (type) {
diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
new file mode 100644
index 000000000000..a20cbc445426
--- /dev/null
+++ b/tools/perf/tests/bp_account.c
@@ -0,0 +1,193 @@
1/*
2 * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
3 * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
4 */
5#define __SANE_USERSPACE_TYPES__
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <string.h>
11#include <sys/ioctl.h>
12#include <time.h>
13#include <fcntl.h>
14#include <signal.h>
15#include <sys/mman.h>
16#include <linux/compiler.h>
17#include <linux/hw_breakpoint.h>
18#include <sys/ioctl.h>
19
20#include "tests.h"
21#include "debug.h"
22#include "perf.h"
23#include "cloexec.h"
24
25volatile long the_var;
26
27static noinline int test_function(void)
28{
29 return 0;
30}
31
32static int __event(bool is_x, void *addr, struct perf_event_attr *attr)
33{
34 int fd;
35
36 memset(attr, 0, sizeof(struct perf_event_attr));
37 attr->type = PERF_TYPE_BREAKPOINT;
38 attr->size = sizeof(struct perf_event_attr);
39
40 attr->config = 0;
41 attr->bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
42 attr->bp_addr = (unsigned long) addr;
43 attr->bp_len = sizeof(long);
44
45 attr->sample_period = 1;
46 attr->sample_type = PERF_SAMPLE_IP;
47
48 attr->exclude_kernel = 1;
49 attr->exclude_hv = 1;
50
51 fd = sys_perf_event_open(attr, -1, 0, -1,
52 perf_event_open_cloexec_flag());
53 if (fd < 0) {
54 pr_debug("failed opening event %llx\n", attr->config);
55 return TEST_FAIL;
56 }
57
58 return fd;
59}
60
61static int wp_event(void *addr, struct perf_event_attr *attr)
62{
63 return __event(false, addr, attr);
64}
65
66static int bp_event(void *addr, struct perf_event_attr *attr)
67{
68 return __event(true, addr, attr);
69}
70
71static int bp_accounting(int wp_cnt, int share)
72{
73 struct perf_event_attr attr, attr_mod, attr_new;
74 int i, fd[wp_cnt], fd_wp, ret;
75
76 for (i = 0; i < wp_cnt; i++) {
77 fd[i] = wp_event((void *)&the_var, &attr);
78 TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
79 pr_debug("wp %d created\n", i);
80 }
81
82 attr_mod = attr;
83 attr_mod.bp_type = HW_BREAKPOINT_X;
84 attr_mod.bp_addr = (unsigned long) test_function;
85
86 ret = ioctl(fd[0], PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr_mod);
87 TEST_ASSERT_VAL("failed to modify wp\n", ret == 0);
88
89 pr_debug("wp 0 modified to bp\n");
90
91 if (!share) {
92 fd_wp = wp_event((void *)&the_var, &attr_new);
93 TEST_ASSERT_VAL("failed to create max wp\n", fd_wp != -1);
94 pr_debug("wp max created\n");
95 }
96
97 for (i = 0; i < wp_cnt; i++)
98 close(fd[i]);
99
100 return 0;
101}
102
103static int detect_cnt(bool is_x)
104{
105 struct perf_event_attr attr;
106 void *addr = is_x ? (void *)test_function : (void *)&the_var;
107 int fd[100], cnt = 0, i;
108
109 while (1) {
110 if (cnt == 100) {
111 pr_debug("way too many debug registers, fix the test\n");
112 return 0;
113 }
114 fd[cnt] = __event(is_x, addr, &attr);
115
116 if (fd[cnt] < 0)
117 break;
118 cnt++;
119 }
120
121 for (i = 0; i < cnt; i++)
122 close(fd[i]);
123
124 return cnt;
125}
126
127static int detect_ioctl(void)
128{
129 struct perf_event_attr attr;
130 int fd, ret = 1;
131
132 fd = wp_event((void *) &the_var, &attr);
133 if (fd > 0) {
134 ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr);
135 close(fd);
136 }
137
138 return ret ? 0 : 1;
139}
140
141static int detect_share(int wp_cnt, int bp_cnt)
142{
143 struct perf_event_attr attr;
144 int i, fd[wp_cnt + bp_cnt], ret;
145
146 for (i = 0; i < wp_cnt; i++) {
147 fd[i] = wp_event((void *)&the_var, &attr);
148 TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
149 }
150
151 for (; i < (bp_cnt + wp_cnt); i++) {
152 fd[i] = bp_event((void *)test_function, &attr);
153 if (fd[i] == -1)
154 break;
155 }
156
157 ret = i != (bp_cnt + wp_cnt);
158
159 while (i--)
160 close(fd[i]);
161
162 return ret;
163}
164
165/*
166 * This test does following:
167 * - detects the number of watch/break-points,
168 * skip test if any is missing
169 * - detects PERF_EVENT_IOC_MODIFY_ATTRIBUTES ioctl,
170 * skip test if it's missing
171 * - detects if watchpoints and breakpoints share
172 * same slots
173 * - create all possible watchpoints on cpu 0
174 * - change one of it to breakpoint
175 * - in case wp and bp do not share slots,
176 * we create another watchpoint to ensure
177 * the slot accounting is correct
178 */
179int test__bp_accounting(struct test *test __maybe_unused, int subtest __maybe_unused)
180{
181 int has_ioctl = detect_ioctl();
182 int wp_cnt = detect_cnt(false);
183 int bp_cnt = detect_cnt(true);
184 int share = detect_share(wp_cnt, bp_cnt);
185
186 pr_debug("watchpoints count %d, breakpoints count %d, has_ioctl %d, share %d\n",
187 wp_cnt, bp_cnt, has_ioctl, share);
188
189 if (!wp_cnt || !bp_cnt || !has_ioctl)
190 return TEST_SKIP;
191
192 return bp_accounting(wp_cnt, share);
193}
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index e4123c1b0e88..1ca5106df5f1 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -31,7 +31,7 @@ struct bpf_map_def SEC("maps") flip_table = {
31 .max_entries = 1, 31 .max_entries = 1,
32}; 32};
33 33
34SEC("func=SyS_epoll_pwait") 34SEC("func=do_epoll_wait")
35int bpf_func__SyS_epoll_pwait(void *ctx) 35int bpf_func__SyS_epoll_pwait(void *ctx)
36{ 36{
37 int ind =0; 37 int ind =0;
diff --git a/tools/perf/tests/bpf-script-test-kbuild.c b/tools/perf/tests/bpf-script-test-kbuild.c
index 3626924740d8..ff3ec8337f0a 100644
--- a/tools/perf/tests/bpf-script-test-kbuild.c
+++ b/tools/perf/tests/bpf-script-test-kbuild.c
@@ -9,7 +9,6 @@
9#define SEC(NAME) __attribute__((section(NAME), used)) 9#define SEC(NAME) __attribute__((section(NAME), used))
10 10
11#include <uapi/linux/fs.h> 11#include <uapi/linux/fs.h>
12#include <uapi/asm/ptrace.h>
13 12
14SEC("func=vfs_llseek") 13SEC("func=vfs_llseek")
15int bpf_func__vfs_llseek(void *ctx) 14int bpf_func__vfs_llseek(void *ctx)
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index e8399beca62b..79b54f8ddebf 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -176,13 +176,19 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
176 176
177 for (i = 0; i < evlist->nr_mmaps; i++) { 177 for (i = 0; i < evlist->nr_mmaps; i++) {
178 union perf_event *event; 178 union perf_event *event;
179 struct perf_mmap *md;
179 180
180 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 181 md = &evlist->mmap[i];
182 if (perf_mmap__read_init(md) < 0)
183 continue;
184
185 while ((event = perf_mmap__read_event(md)) != NULL) {
181 const u32 type = event->header.type; 186 const u32 type = event->header.type;
182 187
183 if (type == PERF_RECORD_SAMPLE) 188 if (type == PERF_RECORD_SAMPLE)
184 count ++; 189 count ++;
185 } 190 }
191 perf_mmap__read_done(md);
186 } 192 }
187 193
188 if (count != expect) { 194 if (count != expect) {
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index fafa014240cd..cac8f8889bc3 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -116,6 +116,11 @@ static struct test generic_tests[] = {
116 .is_supported = test__bp_signal_is_supported, 116 .is_supported = test__bp_signal_is_supported,
117 }, 117 },
118 { 118 {
119 .desc = "Breakpoint accounting",
120 .func = test__bp_accounting,
121 .is_supported = test__bp_signal_is_supported,
122 },
123 {
119 .desc = "Number of exit events of a simple workload", 124 .desc = "Number of exit events of a simple workload",
120 .func = test__task_exit, 125 .func = test__task_exit,
121 }, 126 },
@@ -271,6 +276,10 @@ static struct test generic_tests[] = {
271 .func = test__unit_number__scnprint, 276 .func = test__unit_number__scnprint,
272 }, 277 },
273 { 278 {
279 .desc = "mem2node",
280 .func = test__mem2node,
281 },
282 {
274 .func = NULL, 283 .func = NULL,
275 }, 284 },
276}; 285};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 3bf7b145b826..99936352df4f 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -409,15 +409,21 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
409 struct state *state) 409 struct state *state)
410{ 410{
411 union perf_event *event; 411 union perf_event *event;
412 struct perf_mmap *md;
412 int i, ret; 413 int i, ret;
413 414
414 for (i = 0; i < evlist->nr_mmaps; i++) { 415 for (i = 0; i < evlist->nr_mmaps; i++) {
415 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 416 md = &evlist->mmap[i];
417 if (perf_mmap__read_init(md) < 0)
418 continue;
419
420 while ((event = perf_mmap__read_event(md)) != NULL) {
416 ret = process_event(machine, evlist, event, state); 421 ret = process_event(machine, evlist, event, state);
417 perf_evlist__mmap_consume(evlist, i); 422 perf_mmap__consume(md);
418 if (ret < 0) 423 if (ret < 0)
419 return ret; 424 return ret;
420 } 425 }
426 perf_mmap__read_done(md);
421 } 427 }
422 return 0; 428 return 0;
423} 429}
@@ -482,6 +488,34 @@ static void fs_something(void)
482 } 488 }
483} 489}
484 490
491static const char *do_determine_event(bool excl_kernel)
492{
493 const char *event = excl_kernel ? "cycles:u" : "cycles";
494
495#ifdef __s390x__
496 char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
497 unsigned int family;
498 int ret, cpum_cf_a;
499
500 if (get_cpuid(cpuid, sizeof(cpuid)))
501 goto out_clocks;
502 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
503 model, cpum_cf_v, &cpum_cf_a);
504 if (ret != 5) /* Not available */
505 goto out_clocks;
506 if (excl_kernel && (cpum_cf_a & 4))
507 return event;
508 if (!excl_kernel && (cpum_cf_a & 2))
509 return event;
510
511 /* Fall through: missing authorization */
512out_clocks:
513 event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
514
515#endif
516 return event;
517}
518
485static void do_something(void) 519static void do_something(void)
486{ 520{
487 fs_something(); 521 fs_something();
@@ -592,10 +626,7 @@ static int do_test_code_reading(bool try_kcore)
592 626
593 perf_evlist__set_maps(evlist, cpus, threads); 627 perf_evlist__set_maps(evlist, cpus, threads);
594 628
595 if (excl_kernel) 629 str = do_determine_event(excl_kernel);
596 str = "cycles:u";
597 else
598 str = "cycles";
599 pr_debug("Parsing event '%s'\n", str); 630 pr_debug("Parsing event '%s'\n", str);
600 ret = parse_events(evlist, str, NULL); 631 ret = parse_events(evlist, str, NULL);
601 if (ret < 0) { 632 if (ret < 0) {
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 260418969120..2f008067d989 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -37,6 +37,19 @@ static int init_live_machine(struct machine *machine)
37 mmap_handler, machine, true, 500); 37 mmap_handler, machine, true, 500);
38} 38}
39 39
40/*
41 * We need to keep these functions global, despite the
42 * fact that they are used only locally in this object,
43 * in order to keep them around even if the binary is
44 * stripped. If they are gone, the unwind check for
45 * symbol fails.
46 */
47int test_dwarf_unwind__thread(struct thread *thread);
48int test_dwarf_unwind__compare(void *p1, void *p2);
49int test_dwarf_unwind__krava_3(struct thread *thread);
50int test_dwarf_unwind__krava_2(struct thread *thread);
51int test_dwarf_unwind__krava_1(struct thread *thread);
52
40#define MAX_STACK 8 53#define MAX_STACK 8
41 54
42static int unwind_entry(struct unwind_entry *entry, void *arg) 55static int unwind_entry(struct unwind_entry *entry, void *arg)
@@ -45,12 +58,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
45 char *symbol = entry->sym ? entry->sym->name : NULL; 58 char *symbol = entry->sym ? entry->sym->name : NULL;
46 static const char *funcs[MAX_STACK] = { 59 static const char *funcs[MAX_STACK] = {
47 "test__arch_unwind_sample", 60 "test__arch_unwind_sample",
48 "unwind_thread", 61 "test_dwarf_unwind__thread",
49 "compare", 62 "test_dwarf_unwind__compare",
50 "bsearch", 63 "bsearch",
51 "krava_3", 64 "test_dwarf_unwind__krava_3",
52 "krava_2", 65 "test_dwarf_unwind__krava_2",
53 "krava_1", 66 "test_dwarf_unwind__krava_1",
54 "test__dwarf_unwind" 67 "test__dwarf_unwind"
55 }; 68 };
56 /* 69 /*
@@ -77,7 +90,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
77 return strcmp((const char *) symbol, funcs[idx]); 90 return strcmp((const char *) symbol, funcs[idx]);
78} 91}
79 92
80static noinline int unwind_thread(struct thread *thread) 93noinline int test_dwarf_unwind__thread(struct thread *thread)
81{ 94{
82 struct perf_sample sample; 95 struct perf_sample sample;
83 unsigned long cnt = 0; 96 unsigned long cnt = 0;
@@ -108,7 +121,7 @@ static noinline int unwind_thread(struct thread *thread)
108 121
109static int global_unwind_retval = -INT_MAX; 122static int global_unwind_retval = -INT_MAX;
110 123
111static noinline int compare(void *p1, void *p2) 124noinline int test_dwarf_unwind__compare(void *p1, void *p2)
112{ 125{
113 /* Any possible value should be 'thread' */ 126 /* Any possible value should be 'thread' */
114 struct thread *thread = *(struct thread **)p1; 127 struct thread *thread = *(struct thread **)p1;
@@ -117,17 +130,17 @@ static noinline int compare(void *p1, void *p2)
117 /* Call unwinder twice for both callchain orders. */ 130 /* Call unwinder twice for both callchain orders. */
118 callchain_param.order = ORDER_CALLER; 131 callchain_param.order = ORDER_CALLER;
119 132
120 global_unwind_retval = unwind_thread(thread); 133 global_unwind_retval = test_dwarf_unwind__thread(thread);
121 if (!global_unwind_retval) { 134 if (!global_unwind_retval) {
122 callchain_param.order = ORDER_CALLEE; 135 callchain_param.order = ORDER_CALLEE;
123 global_unwind_retval = unwind_thread(thread); 136 global_unwind_retval = test_dwarf_unwind__thread(thread);
124 } 137 }
125 } 138 }
126 139
127 return p1 - p2; 140 return p1 - p2;
128} 141}
129 142
130static noinline int krava_3(struct thread *thread) 143noinline int test_dwarf_unwind__krava_3(struct thread *thread)
131{ 144{
132 struct thread *array[2] = {thread, thread}; 145 struct thread *array[2] = {thread, thread};
133 void *fp = &bsearch; 146 void *fp = &bsearch;
@@ -141,18 +154,19 @@ static noinline int krava_3(struct thread *thread)
141 size_t, int (*)(void *, void *)); 154 size_t, int (*)(void *, void *));
142 155
143 _bsearch = fp; 156 _bsearch = fp;
144 _bsearch(array, &thread, 2, sizeof(struct thread **), compare); 157 _bsearch(array, &thread, 2, sizeof(struct thread **),
158 test_dwarf_unwind__compare);
145 return global_unwind_retval; 159 return global_unwind_retval;
146} 160}
147 161
148static noinline int krava_2(struct thread *thread) 162noinline int test_dwarf_unwind__krava_2(struct thread *thread)
149{ 163{
150 return krava_3(thread); 164 return test_dwarf_unwind__krava_3(thread);
151} 165}
152 166
153static noinline int krava_1(struct thread *thread) 167noinline int test_dwarf_unwind__krava_1(struct thread *thread)
154{ 168{
155 return krava_2(thread); 169 return test_dwarf_unwind__krava_2(thread);
156} 170}
157 171
158int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused) 172int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
@@ -189,7 +203,7 @@ int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unu
189 goto out; 203 goto out;
190 } 204 }
191 205
192 err = krava_1(thread); 206 err = test_dwarf_unwind__krava_1(thread);
193 thread__put(thread); 207 thread__put(thread);
194 208
195 out: 209 out:
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index c46530918938..17c46f3e6f1e 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -27,18 +27,23 @@
27static int find_comm(struct perf_evlist *evlist, const char *comm) 27static int find_comm(struct perf_evlist *evlist, const char *comm)
28{ 28{
29 union perf_event *event; 29 union perf_event *event;
30 struct perf_mmap *md;
30 int i, found; 31 int i, found;
31 32
32 found = 0; 33 found = 0;
33 for (i = 0; i < evlist->nr_mmaps; i++) { 34 for (i = 0; i < evlist->nr_mmaps; i++) {
34 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 35 md = &evlist->mmap[i];
36 if (perf_mmap__read_init(md) < 0)
37 continue;
38 while ((event = perf_mmap__read_event(md)) != NULL) {
35 if (event->header.type == PERF_RECORD_COMM && 39 if (event->header.type == PERF_RECORD_COMM &&
36 (pid_t)event->comm.pid == getpid() && 40 (pid_t)event->comm.pid == getpid() &&
37 (pid_t)event->comm.tid == getpid() && 41 (pid_t)event->comm.tid == getpid() &&
38 strcmp(event->comm.comm, comm) == 0) 42 strcmp(event->comm.comm, comm) == 0)
39 found += 1; 43 found += 1;
40 perf_evlist__mmap_consume(evlist, i); 44 perf_mmap__consume(md);
41 } 45 }
46 perf_mmap__read_done(md);
42 } 47 }
43 return found; 48 return found;
44} 49}
diff --git a/tools/perf/tests/mem.c b/tools/perf/tests/mem.c
index 21952e1e6e6d..0f82ee9fd3f7 100644
--- a/tools/perf/tests/mem.c
+++ b/tools/perf/tests/mem.c
@@ -16,7 +16,7 @@ static int check(union perf_mem_data_src data_src,
16 16
17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi); 17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi);
18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi); 18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi);
19 snprintf(failure, sizeof failure, "unexpected %s", out); 19 scnprintf(failure, sizeof failure, "unexpected %s", out);
20 TEST_ASSERT_VAL(failure, !strcmp(string, out)); 20 TEST_ASSERT_VAL(failure, !strcmp(string, out));
21 return 0; 21 return 0;
22} 22}
diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c
new file mode 100644
index 000000000000..0c3c87f86e03
--- /dev/null
+++ b/tools/perf/tests/mem2node.c
@@ -0,0 +1,75 @@
1#include <linux/compiler.h>
2#include <linux/bitmap.h>
3#include "cpumap.h"
4#include "mem2node.h"
5#include "tests.h"
6
7static struct node {
8 int node;
9 const char *map;
10} test_nodes[] = {
11 { .node = 0, .map = "0" },
12 { .node = 1, .map = "1-2" },
13 { .node = 3, .map = "5-7,9" },
14};
15
16#define T TEST_ASSERT_VAL
17
18static unsigned long *get_bitmap(const char *str, int nbits)
19{
20 struct cpu_map *map = cpu_map__new(str);
21 unsigned long *bm = NULL;
22 int i;
23
24 bm = bitmap_alloc(nbits);
25
26 if (map && bm) {
27 bitmap_zero(bm, nbits);
28
29 for (i = 0; i < map->nr; i++) {
30 set_bit(map->map[i], bm);
31 }
32 }
33
34 if (map)
35 cpu_map__put(map);
36 else
37 free(bm);
38
39 return bm && map ? bm : NULL;
40}
41
42int test__mem2node(struct test *t __maybe_unused, int subtest __maybe_unused)
43{
44 struct mem2node map;
45 struct memory_node nodes[3];
46 struct perf_env env = {
47 .memory_nodes = (struct memory_node *) &nodes[0],
48 .nr_memory_nodes = ARRAY_SIZE(nodes),
49 .memory_bsize = 0x100,
50 };
51 unsigned int i;
52
53 for (i = 0; i < ARRAY_SIZE(nodes); i++) {
54 nodes[i].node = test_nodes[i].node;
55 nodes[i].size = 10;
56
57 T("failed: alloc bitmap",
58 (nodes[i].set = get_bitmap(test_nodes[i].map, 10)));
59 }
60
61 T("failed: mem2node__init", !mem2node__init(&map, &env));
62 T("failed: mem2node__node", 0 == mem2node__node(&map, 0x50));
63 T("failed: mem2node__node", 1 == mem2node__node(&map, 0x100));
64 T("failed: mem2node__node", 1 == mem2node__node(&map, 0x250));
65 T("failed: mem2node__node", 3 == mem2node__node(&map, 0x500));
66 T("failed: mem2node__node", 3 == mem2node__node(&map, 0x650));
67 T("failed: mem2node__node", -1 == mem2node__node(&map, 0x450));
68 T("failed: mem2node__node", -1 == mem2node__node(&map, 0x1050));
69
70 for (i = 0; i < ARRAY_SIZE(nodes); i++)
71 free(nodes[i].set);
72
73 mem2node__exit(&map);
74 return 0;
75}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index c0e971da965c..0919b0793e5b 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -38,6 +38,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
38 expected_nr_events[nsyscalls], i, j; 38 expected_nr_events[nsyscalls], i, j;
39 struct perf_evsel *evsels[nsyscalls], *evsel; 39 struct perf_evsel *evsels[nsyscalls], *evsel;
40 char sbuf[STRERR_BUFSIZE]; 40 char sbuf[STRERR_BUFSIZE];
41 struct perf_mmap *md;
41 42
42 threads = thread_map__new(-1, getpid(), UINT_MAX); 43 threads = thread_map__new(-1, getpid(), UINT_MAX);
43 if (threads == NULL) { 44 if (threads == NULL) {
@@ -74,7 +75,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
74 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); 75 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
75 evsels[i] = perf_evsel__newtp("syscalls", name); 76 evsels[i] = perf_evsel__newtp("syscalls", name);
76 if (IS_ERR(evsels[i])) { 77 if (IS_ERR(evsels[i])) {
77 pr_debug("perf_evsel__new\n"); 78 pr_debug("perf_evsel__new(%s)\n", name);
78 goto out_delete_evlist; 79 goto out_delete_evlist;
79 } 80 }
80 81
@@ -106,7 +107,11 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
106 ++foo; 107 ++foo;
107 } 108 }
108 109
109 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 110 md = &evlist->mmap[0];
111 if (perf_mmap__read_init(md) < 0)
112 goto out_init;
113
114 while ((event = perf_mmap__read_event(md)) != NULL) {
110 struct perf_sample sample; 115 struct perf_sample sample;
111 116
112 if (event->header.type != PERF_RECORD_SAMPLE) { 117 if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -129,9 +134,11 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
129 goto out_delete_evlist; 134 goto out_delete_evlist;
130 } 135 }
131 nr_events[evsel->idx]++; 136 nr_events[evsel->idx]++;
132 perf_evlist__mmap_consume(evlist, 0); 137 perf_mmap__consume(md);
133 } 138 }
139 perf_mmap__read_done(md);
134 140
141out_init:
135 err = 0; 142 err = 0;
136 evlist__for_each_entry(evlist, evsel) { 143 evlist__for_each_entry(evlist, evsel) {
137 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 144 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 43519267b93b..344dc3ac2469 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -86,8 +86,13 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
86 86
87 for (i = 0; i < evlist->nr_mmaps; i++) { 87 for (i = 0; i < evlist->nr_mmaps; i++) {
88 union perf_event *event; 88 union perf_event *event;
89 struct perf_mmap *md;
89 90
90 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 91 md = &evlist->mmap[i];
92 if (perf_mmap__read_init(md) < 0)
93 continue;
94
95 while ((event = perf_mmap__read_event(md)) != NULL) {
91 const u32 type = event->header.type; 96 const u32 type = event->header.type;
92 int tp_flags; 97 int tp_flags;
93 struct perf_sample sample; 98 struct perf_sample sample;
@@ -95,7 +100,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
95 ++nr_events; 100 ++nr_events;
96 101
97 if (type != PERF_RECORD_SAMPLE) { 102 if (type != PERF_RECORD_SAMPLE) {
98 perf_evlist__mmap_consume(evlist, i); 103 perf_mmap__consume(md);
99 continue; 104 continue;
100 } 105 }
101 106
@@ -115,6 +120,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
115 120
116 goto out_ok; 121 goto out_ok;
117 } 122 }
123 perf_mmap__read_done(md);
118 } 124 }
119 125
120 if (nr_events == before) 126 if (nr_events == before)
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 0afafab85238..34394cc05077 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -164,8 +164,13 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
164 164
165 for (i = 0; i < evlist->nr_mmaps; i++) { 165 for (i = 0; i < evlist->nr_mmaps; i++) {
166 union perf_event *event; 166 union perf_event *event;
167 struct perf_mmap *md;
167 168
168 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 169 md = &evlist->mmap[i];
170 if (perf_mmap__read_init(md) < 0)
171 continue;
172
173 while ((event = perf_mmap__read_event(md)) != NULL) {
169 const u32 type = event->header.type; 174 const u32 type = event->header.type;
170 const char *name = perf_event__name(type); 175 const char *name = perf_event__name(type);
171 176
@@ -266,8 +271,9 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
266 ++errs; 271 ++errs;
267 } 272 }
268 273
269 perf_evlist__mmap_consume(evlist, i); 274 perf_mmap__consume(md);
270 } 275 }
276 perf_mmap__read_done(md);
271 } 277 }
272 278
273 /* 279 /*
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 9abca267afa9..7bedf8608fdd 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -98,7 +98,7 @@ static char *test_format_dir_get(void)
98 struct test_format *format = &test_formats[i]; 98 struct test_format *format = &test_formats[i];
99 FILE *file; 99 FILE *file;
100 100
101 snprintf(name, PATH_MAX, "%s/%s", dir, format->name); 101 scnprintf(name, PATH_MAX, "%s/%s", dir, format->name);
102 102
103 file = fopen(name, "w"); 103 file = fopen(name, "w");
104 if (!file) 104 if (!file)
diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
index 30a950c9d407..1c16e56cd93e 100644
--- a/tools/perf/tests/shell/lib/probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
@@ -5,7 +5,7 @@ had_vfs_getname=$?
5 5
6cleanup_probe_vfs_getname() { 6cleanup_probe_vfs_getname() {
7 if [ $had_vfs_getname -eq 1 ] ; then 7 if [ $had_vfs_getname -eq 1 ] ; then
8 perf probe -q -d probe:vfs_getname 8 perf probe -q -d probe:vfs_getname*
9 fi 9 fi
10} 10}
11 11
diff --git a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index c446c894b297..ee86473643be 100755
--- a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -15,30 +15,26 @@ nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
15 15
16trace_libc_inet_pton_backtrace() { 16trace_libc_inet_pton_backtrace() {
17 idx=0 17 idx=0
18 expected[0]="PING.*bytes" 18 expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)"
19 expected[1]="64 bytes from ::1.*" 19 expected[1]=".*inet_pton[[:space:]]\($libc|inlined\)$"
20 expected[2]=".*ping statistics.*"
21 expected[3]=".*packets transmitted.*"
22 expected[4]="rtt min.*"
23 expected[5]="[0-9]+\.[0-9]+[[:space:]]+probe_libc:inet_pton:\([[:xdigit:]]+\)"
24 expected[6]=".*inet_pton[[:space:]]\($libc\)$"
25 case "$(uname -m)" in 20 case "$(uname -m)" in
26 s390x) 21 s390x)
27 eventattr='call-graph=dwarf' 22 eventattr='call-graph=dwarf,max-stack=4'
28 expected[7]="gaih_inet[[:space:]]\(inlined\)$" 23 expected[2]="gaih_inet.*[[:space:]]\($libc|inlined\)$"
29 expected[8]="__GI_getaddrinfo[[:space:]]\(inlined\)$" 24 expected[3]="(__GI_)?getaddrinfo[[:space:]]\($libc|inlined\)$"
30 expected[9]="main[[:space:]]\(.*/bin/ping.*\)$" 25 expected[4]="main[[:space:]]\(.*/bin/ping.*\)$"
31 expected[10]="__libc_start_main[[:space:]]\($libc\)$"
32 expected[11]="_start[[:space:]]\(.*/bin/ping.*\)$"
33 ;; 26 ;;
34 *) 27 *)
35 eventattr='max-stack=3' 28 eventattr='max-stack=3'
36 expected[7]="getaddrinfo[[:space:]]\($libc\)$" 29 expected[2]="getaddrinfo[[:space:]]\($libc\)$"
37 expected[8]=".*\(.*/bin/ping.*\)$" 30 expected[3]=".*\(.*/bin/ping.*\)$"
38 ;; 31 ;;
39 esac 32 esac
40 33
41 perf trace --no-syscalls -e probe_libc:inet_pton/$eventattr/ ping -6 -c 1 ::1 2>&1 | grep -v ^$ | while read line ; do 34 file=`mktemp -u /tmp/perf.data.XXX`
35
36 perf record -e probe_libc:inet_pton/$eventattr/ -o $file ping -6 -c 1 ::1 > /dev/null 2>&1
37 perf script -i $file | while read line ; do
42 echo $line 38 echo $line
43 echo "$line" | egrep -q "${expected[$idx]}" 39 echo "$line" | egrep -q "${expected[$idx]}"
44 if [ $? -ne 0 ] ; then 40 if [ $? -ne 0 ] ; then
@@ -48,6 +44,11 @@ trace_libc_inet_pton_backtrace() {
48 let idx+=1 44 let idx+=1
49 [ -z "${expected[$idx]}" ] && break 45 [ -z "${expected[$idx]}" ] && break
50 done 46 done
47
48 # If any statements are executed from this point onwards,
49 # the exit code of the last among these will be reflected
50 # in err below. If the exit code is 0, the test will pass
51 # even if the perf script output does not match.
51} 52}
52 53
53# Check for IPv6 interface existence 54# Check for IPv6 interface existence
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index f6c72f915d48..f9490b237893 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -39,6 +39,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
39 }; 39 };
40 struct cpu_map *cpus; 40 struct cpu_map *cpus;
41 struct thread_map *threads; 41 struct thread_map *threads;
42 struct perf_mmap *md;
42 43
43 attr.sample_freq = 500; 44 attr.sample_freq = 500;
44 45
@@ -93,7 +94,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
93 94
94 perf_evlist__disable(evlist); 95 perf_evlist__disable(evlist);
95 96
96 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 97 md = &evlist->mmap[0];
98 if (perf_mmap__read_init(md) < 0)
99 goto out_init;
100
101 while ((event = perf_mmap__read_event(md)) != NULL) {
97 struct perf_sample sample; 102 struct perf_sample sample;
98 103
99 if (event->header.type != PERF_RECORD_SAMPLE) 104 if (event->header.type != PERF_RECORD_SAMPLE)
@@ -108,9 +113,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
108 total_periods += sample.period; 113 total_periods += sample.period;
109 nr_samples++; 114 nr_samples++;
110next_event: 115next_event:
111 perf_evlist__mmap_consume(evlist, 0); 116 perf_mmap__consume(md);
112 } 117 }
118 perf_mmap__read_done(md);
113 119
120out_init:
114 if ((u64) nr_samples == total_periods) { 121 if ((u64) nr_samples == total_periods) {
115 pr_debug("All (%d) samples have period value of 1!\n", 122 pr_debug("All (%d) samples have period value of 1!\n",
116 nr_samples); 123 nr_samples);
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 33e00295a972..9b5be51e5e7b 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -258,16 +258,22 @@ static int process_events(struct perf_evlist *evlist,
258 unsigned pos, cnt = 0; 258 unsigned pos, cnt = 0;
259 LIST_HEAD(events); 259 LIST_HEAD(events);
260 struct event_node *events_array, *node; 260 struct event_node *events_array, *node;
261 struct perf_mmap *md;
261 int i, ret; 262 int i, ret;
262 263
263 for (i = 0; i < evlist->nr_mmaps; i++) { 264 for (i = 0; i < evlist->nr_mmaps; i++) {
264 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 265 md = &evlist->mmap[i];
266 if (perf_mmap__read_init(md) < 0)
267 continue;
268
269 while ((event = perf_mmap__read_event(md)) != NULL) {
265 cnt += 1; 270 cnt += 1;
266 ret = add_event(evlist, &events, event); 271 ret = add_event(evlist, &events, event);
267 perf_evlist__mmap_consume(evlist, i); 272 perf_mmap__consume(md);
268 if (ret < 0) 273 if (ret < 0)
269 goto out_free_nodes; 274 goto out_free_nodes;
270 } 275 }
276 perf_mmap__read_done(md);
271 } 277 }
272 278
273 events_array = calloc(cnt, sizeof(struct event_node)); 279 events_array = calloc(cnt, sizeof(struct event_node));
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 01b62b81751b..e92fa6029ac7 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -47,6 +47,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
47 char sbuf[STRERR_BUFSIZE]; 47 char sbuf[STRERR_BUFSIZE];
48 struct cpu_map *cpus; 48 struct cpu_map *cpus;
49 struct thread_map *threads; 49 struct thread_map *threads;
50 struct perf_mmap *md;
50 51
51 signal(SIGCHLD, sig_handler); 52 signal(SIGCHLD, sig_handler);
52 53
@@ -110,13 +111,19 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
110 perf_evlist__start_workload(evlist); 111 perf_evlist__start_workload(evlist);
111 112
112retry: 113retry:
113 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 114 md = &evlist->mmap[0];
115 if (perf_mmap__read_init(md) < 0)
116 goto out_init;
117
118 while ((event = perf_mmap__read_event(md)) != NULL) {
114 if (event->header.type == PERF_RECORD_EXIT) 119 if (event->header.type == PERF_RECORD_EXIT)
115 nr_exit++; 120 nr_exit++;
116 121
117 perf_evlist__mmap_consume(evlist, 0); 122 perf_mmap__consume(md);
118 } 123 }
124 perf_mmap__read_done(md);
119 125
126out_init:
120 if (!exited || !nr_exit) { 127 if (!exited || !nr_exit) {
121 perf_evlist__poll(evlist, -1); 128 perf_evlist__poll(evlist, -1);
122 goto retry; 129 goto retry;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 2862b80bc288..a9760e790563 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -58,6 +58,7 @@ int test__hists_link(struct test *test, int subtest);
58int test__python_use(struct test *test, int subtest); 58int test__python_use(struct test *test, int subtest);
59int test__bp_signal(struct test *test, int subtest); 59int test__bp_signal(struct test *test, int subtest);
60int test__bp_signal_overflow(struct test *test, int subtest); 60int test__bp_signal_overflow(struct test *test, int subtest);
61int test__bp_accounting(struct test *test, int subtest);
61int test__task_exit(struct test *test, int subtest); 62int test__task_exit(struct test *test, int subtest);
62int test__mem(struct test *test, int subtest); 63int test__mem(struct test *test, int subtest);
63int test__sw_clock_freq(struct test *test, int subtest); 64int test__sw_clock_freq(struct test *test, int subtest);
@@ -102,6 +103,7 @@ int test__clang(struct test *test, int subtest);
102const char *test__clang_subtest_get_desc(int subtest); 103const char *test__clang_subtest_get_desc(int subtest);
103int test__clang_subtest_get_nr(void); 104int test__clang_subtest_get_nr(void);
104int test__unit_number__scnprint(struct test *test, int subtest); 105int test__unit_number__scnprint(struct test *test, int subtest);
106int test__mem2node(struct test *t, int subtest);
105 107
106bool test__bp_signal_is_supported(void); 108bool test__bp_signal_is_supported(void);
107 109
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index f6789fb029d6..1e5adb65632a 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -56,7 +56,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
56 * be compacted against the list of modules found in the "vmlinux" 56 * be compacted against the list of modules found in the "vmlinux"
57 * code and with the one got from /proc/modules from the "kallsyms" code. 57 * code and with the one got from /proc/modules from the "kallsyms" code.
58 */ 58 */
59 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true) <= 0) { 59 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type) <= 0) {
60 pr_debug("dso__load_kallsyms "); 60 pr_debug("dso__load_kallsyms ");
61 goto out; 61 goto out;
62 } 62 }
@@ -125,7 +125,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
125 125
126 if (pair && UM(pair->start) == mem_start) { 126 if (pair && UM(pair->start) == mem_start) {
127next_pair: 127next_pair:
128 if (strcmp(sym->name, pair->name) == 0) { 128 if (arch__compare_symbol_names(sym->name, pair->name) == 0) {
129 /* 129 /*
130 * kallsyms don't have the symbol end, so we 130 * kallsyms don't have the symbol end, so we
131 * set that by using the next symbol start - 1, 131 * set that by using the next symbol start - 1,
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index 417e3ecfe9d7..9f68077b241b 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -54,6 +54,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
54 P_MMAP_FLAG(EXECUTABLE); 54 P_MMAP_FLAG(EXECUTABLE);
55 P_MMAP_FLAG(FILE); 55 P_MMAP_FLAG(FILE);
56 P_MMAP_FLAG(FIXED); 56 P_MMAP_FLAG(FIXED);
57#ifdef MAP_FIXED_NOREPLACE
58 P_MMAP_FLAG(FIXED_NOREPLACE);
59#endif
57 P_MMAP_FLAG(GROWSDOWN); 60 P_MMAP_FLAG(GROWSDOWN);
58 P_MMAP_FLAG(HUGETLB); 61 P_MMAP_FLAG(HUGETLB);
59 P_MMAP_FLAG(LOCKED); 62 P_MMAP_FLAG(LOCKED);
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 63399af3049f..4f75561424ed 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -45,23 +45,33 @@ void ui_browser__set_percent_color(struct ui_browser *browser,
45 ui_browser__set_color(browser, color); 45 ui_browser__set_color(browser, color);
46} 46}
47 47
48void ui_browser__gotorc(struct ui_browser *browser, int y, int x) 48void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x)
49{ 49{
50 SLsmg_gotorc(browser->y + y, browser->x + x); 50 SLsmg_gotorc(browser->y + y, browser->x + x);
51} 51}
52 52
53void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
54{
55 SLsmg_gotorc(browser->y + y + browser->extra_title_lines, browser->x + x);
56}
57
53void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, 58void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg,
54 unsigned int width) 59 unsigned int width)
55{ 60{
56 slsmg_write_nstring(msg, width); 61 slsmg_write_nstring(msg, width);
57} 62}
58 63
64void ui_browser__vprintf(struct ui_browser *browser __maybe_unused, const char *fmt, va_list args)
65{
66 slsmg_vprintf(fmt, args);
67}
68
59void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...) 69void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...)
60{ 70{
61 va_list args; 71 va_list args;
62 72
63 va_start(args, fmt); 73 va_start(args, fmt);
64 slsmg_vprintf(fmt, args); 74 ui_browser__vprintf(browser, fmt, args);
65 va_end(args); 75 va_end(args);
66} 76}
67 77
@@ -186,6 +196,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser)
186{ 196{
187 browser->width = SLtt_Screen_Cols - 1; 197 browser->width = SLtt_Screen_Cols - 1;
188 browser->height = browser->rows = SLtt_Screen_Rows - 2; 198 browser->height = browser->rows = SLtt_Screen_Rows - 2;
199 browser->rows -= browser->extra_title_lines;
189 browser->y = 1; 200 browser->y = 1;
190 browser->x = 0; 201 browser->x = 0;
191} 202}
@@ -332,8 +343,8 @@ static int __ui_browser__refresh(struct ui_browser *browser)
332 else 343 else
333 width += 1; 344 width += 1;
334 345
335 SLsmg_fill_region(browser->y + row, browser->x, 346 SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x,
336 browser->height - row, width, ' '); 347 browser->rows - row, width, ' ');
337 348
338 return 0; 349 return 0;
339} 350}
@@ -779,6 +790,4 @@ void ui_browser__init(void)
779 struct ui_browser_colorset *c = &ui_browser__colorsets[i++]; 790 struct ui_browser_colorset *c = &ui_browser__colorsets[i++];
780 sltt_set_color(c->colorset, c->name, c->fg, c->bg); 791 sltt_set_color(c->colorset, c->name, c->fg, c->bg);
781 } 792 }
782
783 annotate_browser__init();
784} 793}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 03e1734412b9..aa5932e1d62e 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -3,6 +3,7 @@
3#define _PERF_UI_BROWSER_H_ 1 3#define _PERF_UI_BROWSER_H_ 1
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <stdarg.h>
6 7
7#define HE_COLORSET_TOP 50 8#define HE_COLORSET_TOP 50
8#define HE_COLORSET_MEDIUM 51 9#define HE_COLORSET_MEDIUM 51
@@ -16,6 +17,7 @@ struct ui_browser {
16 u64 index, top_idx; 17 u64 index, top_idx;
17 void *top, *entries; 18 void *top, *entries;
18 u16 y, x, width, height, rows, columns, horiz_scroll; 19 u16 y, x, width, height, rows, columns, horiz_scroll;
20 u8 extra_title_lines;
19 int current_color; 21 int current_color;
20 void *priv; 22 void *priv;
21 const char *title; 23 const char *title;
@@ -37,9 +39,11 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
37void ui_browser__refresh_dimensions(struct ui_browser *browser); 39void ui_browser__refresh_dimensions(struct ui_browser *browser);
38void ui_browser__reset_index(struct ui_browser *browser); 40void ui_browser__reset_index(struct ui_browser *browser);
39 41
42void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x);
40void ui_browser__gotorc(struct ui_browser *browser, int y, int x); 43void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
41void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, 44void ui_browser__write_nstring(struct ui_browser *browser, const char *msg,
42 unsigned int width); 45 unsigned int width);
46void ui_browser__vprintf(struct ui_browser *browser, const char *fmt, va_list args);
43void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...); 47void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
44void ui_browser__write_graph(struct ui_browser *browser, int graph); 48void ui_browser__write_graph(struct ui_browser *browser, int graph);
45void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 49void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
@@ -77,5 +81,4 @@ void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int wh
77unsigned int ui_browser__list_head_refresh(struct ui_browser *browser); 81unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
78 82
79void ui_browser__init(void); 83void ui_browser__init(void);
80void annotate_browser__init(void);
81#endif /* _PERF_UI_BROWSER_H_ */ 84#endif /* _PERF_UI_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index fbf927cf775d..3781d74088a7 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -9,7 +9,6 @@
9#include "../../util/sort.h" 9#include "../../util/sort.h"
10#include "../../util/symbol.h" 10#include "../../util/symbol.h"
11#include "../../util/evsel.h" 11#include "../../util/evsel.h"
12#include "../../util/config.h"
13#include "../../util/evlist.h" 12#include "../../util/evlist.h"
14#include <inttypes.h> 13#include <inttypes.h>
15#include <pthread.h> 14#include <pthread.h>
@@ -22,28 +21,6 @@ struct disasm_line_samples {
22 struct sym_hist_entry he; 21 struct sym_hist_entry he;
23}; 22};
24 23
25#define IPC_WIDTH 6
26#define CYCLES_WIDTH 6
27
28struct browser_line {
29 u32 idx;
30 int idx_asm;
31 int jump_sources;
32};
33
34static struct annotate_browser_opt {
35 bool hide_src_code,
36 use_offset,
37 jump_arrows,
38 show_linenr,
39 show_nr_jumps,
40 show_nr_samples,
41 show_total_period;
42} annotate_browser__opts = {
43 .use_offset = true,
44 .jump_arrows = true,
45};
46
47struct arch; 24struct arch;
48 25
49struct annotate_browser { 26struct annotate_browser {
@@ -51,245 +28,98 @@ struct annotate_browser {
51 struct rb_root entries; 28 struct rb_root entries;
52 struct rb_node *curr_hot; 29 struct rb_node *curr_hot;
53 struct annotation_line *selection; 30 struct annotation_line *selection;
54 struct annotation_line **offsets;
55 struct arch *arch; 31 struct arch *arch;
56 int nr_events;
57 u64 start;
58 int nr_asm_entries;
59 int nr_entries;
60 int max_jump_sources;
61 int nr_jumps;
62 bool searching_backwards; 32 bool searching_backwards;
63 bool have_cycles;
64 u8 addr_width;
65 u8 jumps_width;
66 u8 target_width;
67 u8 min_addr_width;
68 u8 max_addr_width;
69 char search_bf[128]; 33 char search_bf[128];
70}; 34};
71 35
72static inline struct browser_line *browser_line(struct annotation_line *al) 36static inline struct annotation *browser__annotation(struct ui_browser *browser)
73{ 37{
74 void *ptr = al; 38 struct map_symbol *ms = browser->priv;
75 39 return symbol__annotation(ms->sym);
76 ptr = container_of(al, struct disasm_line, al);
77 return ptr - sizeof(struct browser_line);
78} 40}
79 41
80static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 42static bool disasm_line__filter(struct ui_browser *browser, void *entry)
81 void *entry)
82{ 43{
83 if (annotate_browser__opts.hide_src_code) { 44 struct annotation *notes = browser__annotation(browser);
84 struct annotation_line *al = list_entry(entry, struct annotation_line, node); 45 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
85 46 return annotation_line__filter(al, notes);
86 return al->offset == -1;
87 }
88
89 return false;
90} 47}
91 48
92static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 49static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
93 int nr, bool current)
94{ 50{
95 if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 51 struct annotation *notes = browser__annotation(browser);
52
53 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
96 return HE_COLORSET_SELECTED; 54 return HE_COLORSET_SELECTED;
97 if (nr == browser->max_jump_sources) 55 if (nr == notes->max_jump_sources)
98 return HE_COLORSET_TOP; 56 return HE_COLORSET_TOP;
99 if (nr > 1) 57 if (nr > 1)
100 return HE_COLORSET_MEDIUM; 58 return HE_COLORSET_MEDIUM;
101 return HE_COLORSET_NORMAL; 59 return HE_COLORSET_NORMAL;
102} 60}
103 61
104static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 62static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
105 int nr, bool current)
106{ 63{
107 int color = annotate_browser__jumps_percent_color(browser, nr, current); 64 int color = ui_browser__jumps_percent_color(browser, nr, current);
108 return ui_browser__set_color(&browser->b, color); 65 return ui_browser__set_color(browser, color);
109} 66}
110 67
111static int annotate_browser__pcnt_width(struct annotate_browser *ab) 68static int annotate_browser__set_color(void *browser, int color)
112{ 69{
113 return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events; 70 return ui_browser__set_color(browser, color);
114} 71}
115 72
116static int annotate_browser__cycles_width(struct annotate_browser *ab) 73static void annotate_browser__write_graph(void *browser, int graph)
117{ 74{
118 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0; 75 ui_browser__write_graph(browser, graph);
119} 76}
120 77
121static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser, 78static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
122 char *bf, size_t size)
123{ 79{
124 if (dl->ins.ops && dl->ins.ops->scnprintf) { 80 ui_browser__set_percent_color(browser, percent, current);
125 if (ins__is_jump(&dl->ins)) { 81}
126 bool fwd = dl->ops.target.offset > dl->al.offset;
127
128 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
129 SLSMG_UARROW_CHAR);
130 SLsmg_write_char(' ');
131 } else if (ins__is_call(&dl->ins)) {
132 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
133 SLsmg_write_char(' ');
134 } else if (ins__is_ret(&dl->ins)) {
135 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
136 SLsmg_write_char(' ');
137 } else {
138 ui_browser__write_nstring(browser, " ", 2);
139 }
140 } else {
141 ui_browser__write_nstring(browser, " ", 2);
142 }
143 82
144 disasm_line__scnprintf(dl, bf, size, !annotate_browser__opts.use_offset); 83static void annotate_browser__printf(void *browser, const char *fmt, ...)
84{
85 va_list args;
86
87 va_start(args, fmt);
88 ui_browser__vprintf(browser, fmt, args);
89 va_end(args);
145} 90}
146 91
147static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 92static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
148{ 93{
149 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 94 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
95 struct annotation *notes = browser__annotation(browser);
150 struct annotation_line *al = list_entry(entry, struct annotation_line, node); 96 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
151 struct browser_line *bl = browser_line(al); 97 struct annotation_write_ops ops = {
152 bool current_entry = ui_browser__is_current_entry(browser, row); 98 .first_line = row == 0,
153 bool change_color = (!annotate_browser__opts.hide_src_code && 99 .current_entry = ui_browser__is_current_entry(browser, row),
154 (!current_entry || (browser->use_navkeypressed && 100 .change_color = (!notes->options->hide_src_code &&
155 !browser->navkeypressed))); 101 (!ops.current_entry ||
156 int width = browser->width, printed; 102 (browser->use_navkeypressed &&
157 int i, pcnt_width = annotate_browser__pcnt_width(ab), 103 !browser->navkeypressed))),
158 cycles_width = annotate_browser__cycles_width(ab); 104 .width = browser->width,
159 double percent_max = 0.0; 105 .obj = browser,
160 char bf[256]; 106 .set_color = annotate_browser__set_color,
161 bool show_title = false; 107 .set_percent_color = annotate_browser__set_percent_color,
162 108 .set_jumps_percent_color = ui_browser__set_jumps_percent_color,
163 for (i = 0; i < ab->nr_events; i++) { 109 .printf = annotate_browser__printf,
164 if (al->samples[i].percent > percent_max) 110 .write_graph = annotate_browser__write_graph,
165 percent_max = al->samples[i].percent; 111 };
166 }
167
168 if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) {
169 if (ab->have_cycles) {
170 if (al->ipc == 0.0 && al->cycles == 0)
171 show_title = true;
172 } else
173 show_title = true;
174 }
175
176 if (al->offset != -1 && percent_max != 0.0) {
177 for (i = 0; i < ab->nr_events; i++) {
178 ui_browser__set_percent_color(browser,
179 al->samples[i].percent,
180 current_entry);
181 if (annotate_browser__opts.show_total_period) {
182 ui_browser__printf(browser, "%11" PRIu64 " ",
183 al->samples[i].he.period);
184 } else if (annotate_browser__opts.show_nr_samples) {
185 ui_browser__printf(browser, "%6" PRIu64 " ",
186 al->samples[i].he.nr_samples);
187 } else {
188 ui_browser__printf(browser, "%6.2f ",
189 al->samples[i].percent);
190 }
191 }
192 } else {
193 ui_browser__set_percent_color(browser, 0, current_entry);
194
195 if (!show_title)
196 ui_browser__write_nstring(browser, " ", pcnt_width);
197 else {
198 ui_browser__printf(browser, "%*s", pcnt_width,
199 annotate_browser__opts.show_total_period ? "Period" :
200 annotate_browser__opts.show_nr_samples ? "Samples" : "Percent");
201 }
202 }
203 if (ab->have_cycles) {
204 if (al->ipc)
205 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, al->ipc);
206 else if (!show_title)
207 ui_browser__write_nstring(browser, " ", IPC_WIDTH);
208 else
209 ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC");
210
211 if (al->cycles)
212 ui_browser__printf(browser, "%*" PRIu64 " ",
213 CYCLES_WIDTH - 1, al->cycles);
214 else if (!show_title)
215 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
216 else
217 ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle");
218 }
219
220 SLsmg_write_char(' ');
221 112
222 /* The scroll bar isn't being used */ 113 /* The scroll bar isn't being used */
223 if (!browser->navkeypressed) 114 if (!browser->navkeypressed)
224 width += 1; 115 ops.width += 1;
225
226 if (!*al->line)
227 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
228 else if (al->offset == -1) {
229 if (al->line_nr && annotate_browser__opts.show_linenr)
230 printed = scnprintf(bf, sizeof(bf), "%-*d ",
231 ab->addr_width + 1, al->line_nr);
232 else
233 printed = scnprintf(bf, sizeof(bf), "%*s ",
234 ab->addr_width, " ");
235 ui_browser__write_nstring(browser, bf, printed);
236 ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1);
237 } else {
238 u64 addr = al->offset;
239 int color = -1;
240
241 if (!annotate_browser__opts.use_offset)
242 addr += ab->start;
243
244 if (!annotate_browser__opts.use_offset) {
245 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
246 } else {
247 if (bl->jump_sources) {
248 if (annotate_browser__opts.show_nr_jumps) {
249 int prev;
250 printed = scnprintf(bf, sizeof(bf), "%*d ",
251 ab->jumps_width,
252 bl->jump_sources);
253 prev = annotate_browser__set_jumps_percent_color(ab, bl->jump_sources,
254 current_entry);
255 ui_browser__write_nstring(browser, bf, printed);
256 ui_browser__set_color(browser, prev);
257 }
258
259 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
260 ab->target_width, addr);
261 } else {
262 printed = scnprintf(bf, sizeof(bf), "%*s ",
263 ab->addr_width, " ");
264 }
265 }
266
267 if (change_color)
268 color = ui_browser__set_color(browser, HE_COLORSET_ADDR);
269 ui_browser__write_nstring(browser, bf, printed);
270 if (change_color)
271 ui_browser__set_color(browser, color);
272 116
273 disasm_line__write(disasm_line(al), browser, bf, sizeof(bf)); 117 annotation_line__write(al, notes, &ops);
274 118
275 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 119 if (ops.current_entry)
276 }
277
278 if (current_entry)
279 ab->selection = al; 120 ab->selection = al;
280} 121}
281 122
282static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
283{
284 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins)
285 || !disasm_line__has_offset(dl)
286 || dl->ops.target.offset < 0
287 || dl->ops.target.offset >= (s64)symbol__size(sym))
288 return false;
289
290 return true;
291}
292
293static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 123static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
294{ 124{
295 struct disasm_line *pos = list_prev_entry(cursor, al.node); 125 struct disasm_line *pos = list_prev_entry(cursor, al.node);
@@ -314,17 +144,18 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
314 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 144 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
315 struct disasm_line *cursor = disasm_line(ab->selection); 145 struct disasm_line *cursor = disasm_line(ab->selection);
316 struct annotation_line *target; 146 struct annotation_line *target;
317 struct browser_line *btarget, *bcursor;
318 unsigned int from, to; 147 unsigned int from, to;
319 struct map_symbol *ms = ab->b.priv; 148 struct map_symbol *ms = ab->b.priv;
320 struct symbol *sym = ms->sym; 149 struct symbol *sym = ms->sym;
321 u8 pcnt_width = annotate_browser__pcnt_width(ab); 150 struct annotation *notes = symbol__annotation(sym);
151 u8 pcnt_width = annotation__pcnt_width(notes);
152 int width;
322 153
323 /* PLT symbols contain external offsets */ 154 /* PLT symbols contain external offsets */
324 if (strstr(sym->name, "@plt")) 155 if (strstr(sym->name, "@plt"))
325 return; 156 return;
326 157
327 if (!disasm_line__is_valid_jump(cursor, sym)) 158 if (!disasm_line__is_valid_local_jump(cursor, sym))
328 return; 159 return;
329 160
330 /* 161 /*
@@ -347,31 +178,31 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
347 * name right after the '<' token and probably treating this like a 178 * name right after the '<' token and probably treating this like a
348 * 'call' instruction. 179 * 'call' instruction.
349 */ 180 */
350 target = ab->offsets[cursor->ops.target.offset]; 181 target = notes->offsets[cursor->ops.target.offset];
351 if (target == NULL) { 182 if (target == NULL) {
352 ui_helpline__printf("WARN: jump target inconsistency, press 'o', ab->offsets[%#x] = NULL\n", 183 ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
353 cursor->ops.target.offset); 184 cursor->ops.target.offset);
354 return; 185 return;
355 } 186 }
356 187
357 bcursor = browser_line(&cursor->al); 188 if (notes->options->hide_src_code) {
358 btarget = browser_line(target); 189 from = cursor->al.idx_asm;
359 190 to = target->idx_asm;
360 if (annotate_browser__opts.hide_src_code) {
361 from = bcursor->idx_asm;
362 to = btarget->idx_asm;
363 } else { 191 } else {
364 from = (u64)bcursor->idx; 192 from = (u64)cursor->al.idx;
365 to = (u64)btarget->idx; 193 to = (u64)target->idx;
366 } 194 }
367 195
196 width = annotation__cycles_width(notes);
197
368 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 198 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
369 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 199 __ui_browser__line_arrow(browser,
200 pcnt_width + 2 + notes->widths.addr + width,
370 from, to); 201 from, to);
371 202
372 if (is_fused(ab, cursor)) { 203 if (is_fused(ab, cursor)) {
373 ui_browser__mark_fused(browser, 204 ui_browser__mark_fused(browser,
374 pcnt_width + 3 + ab->addr_width, 205 pcnt_width + 3 + notes->widths.addr + width,
375 from - 1, 206 from - 1,
376 to > from ? true : false); 207 to > from ? true : false);
377 } 208 }
@@ -379,15 +210,15 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
379 210
380static unsigned int annotate_browser__refresh(struct ui_browser *browser) 211static unsigned int annotate_browser__refresh(struct ui_browser *browser)
381{ 212{
382 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 213 struct annotation *notes = browser__annotation(browser);
383 int ret = ui_browser__list_head_refresh(browser); 214 int ret = ui_browser__list_head_refresh(browser);
384 int pcnt_width = annotate_browser__pcnt_width(ab); 215 int pcnt_width = annotation__pcnt_width(notes);
385 216
386 if (annotate_browser__opts.jump_arrows) 217 if (notes->options->jump_arrows)
387 annotate_browser__draw_current_jump(browser); 218 annotate_browser__draw_current_jump(browser);
388 219
389 ui_browser__set_color(browser, HE_COLORSET_NORMAL); 220 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
390 __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 221 __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1);
391 return ret; 222 return ret;
392} 223}
393 224
@@ -425,6 +256,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line
425static void annotate_browser__set_top(struct annotate_browser *browser, 256static void annotate_browser__set_top(struct annotate_browser *browser,
426 struct annotation_line *pos, u32 idx) 257 struct annotation_line *pos, u32 idx)
427{ 258{
259 struct annotation *notes = browser__annotation(&browser->b);
428 unsigned back; 260 unsigned back;
429 261
430 ui_browser__refresh_dimensions(&browser->b); 262 ui_browser__refresh_dimensions(&browser->b);
@@ -434,7 +266,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
434 while (browser->b.top_idx != 0 && back != 0) { 266 while (browser->b.top_idx != 0 && back != 0) {
435 pos = list_entry(pos->node.prev, struct annotation_line, node); 267 pos = list_entry(pos->node.prev, struct annotation_line, node);
436 268
437 if (disasm_line__filter(&browser->b, &pos->node)) 269 if (annotation_line__filter(pos, notes))
438 continue; 270 continue;
439 271
440 --browser->b.top_idx; 272 --browser->b.top_idx;
@@ -448,16 +280,12 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
448static void annotate_browser__set_rb_top(struct annotate_browser *browser, 280static void annotate_browser__set_rb_top(struct annotate_browser *browser,
449 struct rb_node *nd) 281 struct rb_node *nd)
450{ 282{
451 struct browser_line *bpos; 283 struct annotation *notes = browser__annotation(&browser->b);
452 struct annotation_line *pos; 284 struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
453 u32 idx; 285 u32 idx = pos->idx;
454 286
455 pos = rb_entry(nd, struct annotation_line, rb_node); 287 if (notes->options->hide_src_code)
456 bpos = browser_line(pos); 288 idx = pos->idx_asm;
457
458 idx = bpos->idx;
459 if (annotate_browser__opts.hide_src_code)
460 idx = bpos->idx_asm;
461 annotate_browser__set_top(browser, pos, idx); 289 annotate_browser__set_top(browser, pos, idx);
462 browser->curr_hot = nd; 290 browser->curr_hot = nd;
463} 291}
@@ -505,47 +333,47 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
505 333
506static bool annotate_browser__toggle_source(struct annotate_browser *browser) 334static bool annotate_browser__toggle_source(struct annotate_browser *browser)
507{ 335{
336 struct annotation *notes = browser__annotation(&browser->b);
508 struct annotation_line *al; 337 struct annotation_line *al;
509 struct browser_line *bl;
510 off_t offset = browser->b.index - browser->b.top_idx; 338 off_t offset = browser->b.index - browser->b.top_idx;
511 339
512 browser->b.seek(&browser->b, offset, SEEK_CUR); 340 browser->b.seek(&browser->b, offset, SEEK_CUR);
513 al = list_entry(browser->b.top, struct annotation_line, node); 341 al = list_entry(browser->b.top, struct annotation_line, node);
514 bl = browser_line(al);
515 342
516 if (annotate_browser__opts.hide_src_code) { 343 if (notes->options->hide_src_code) {
517 if (bl->idx_asm < offset) 344 if (al->idx_asm < offset)
518 offset = bl->idx; 345 offset = al->idx;
519 346
520 browser->b.nr_entries = browser->nr_entries; 347 browser->b.nr_entries = notes->nr_entries;
521 annotate_browser__opts.hide_src_code = false; 348 notes->options->hide_src_code = false;
522 browser->b.seek(&browser->b, -offset, SEEK_CUR); 349 browser->b.seek(&browser->b, -offset, SEEK_CUR);
523 browser->b.top_idx = bl->idx - offset; 350 browser->b.top_idx = al->idx - offset;
524 browser->b.index = bl->idx; 351 browser->b.index = al->idx;
525 } else { 352 } else {
526 if (bl->idx_asm < 0) { 353 if (al->idx_asm < 0) {
527 ui_helpline__puts("Only available for assembly lines."); 354 ui_helpline__puts("Only available for assembly lines.");
528 browser->b.seek(&browser->b, -offset, SEEK_CUR); 355 browser->b.seek(&browser->b, -offset, SEEK_CUR);
529 return false; 356 return false;
530 } 357 }
531 358
532 if (bl->idx_asm < offset) 359 if (al->idx_asm < offset)
533 offset = bl->idx_asm; 360 offset = al->idx_asm;
534 361
535 browser->b.nr_entries = browser->nr_asm_entries; 362 browser->b.nr_entries = notes->nr_asm_entries;
536 annotate_browser__opts.hide_src_code = true; 363 notes->options->hide_src_code = true;
537 browser->b.seek(&browser->b, -offset, SEEK_CUR); 364 browser->b.seek(&browser->b, -offset, SEEK_CUR);
538 browser->b.top_idx = bl->idx_asm - offset; 365 browser->b.top_idx = al->idx_asm - offset;
539 browser->b.index = bl->idx_asm; 366 browser->b.index = al->idx_asm;
540 } 367 }
541 368
542 return true; 369 return true;
543} 370}
544 371
545static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 372static void ui_browser__init_asm_mode(struct ui_browser *browser)
546{ 373{
547 ui_browser__reset_index(&browser->b); 374 struct annotation *notes = browser__annotation(browser);
548 browser->b.nr_entries = browser->nr_asm_entries; 375 ui_browser__reset_index(browser);
376 browser->nr_entries = notes->nr_asm_entries;
549} 377}
550 378
551#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 379#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
@@ -556,6 +384,15 @@ static int sym_title(struct symbol *sym, struct map *map, char *title,
556 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 384 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name);
557} 385}
558 386
387/*
388 * This can be called from external jumps, i.e. jumps from one functon
389 * to another, like from the kernel's entry_SYSCALL_64 function to the
390 * swapgs_restore_regs_and_return_to_usermode() function.
391 *
392 * So all we check here is that dl->ops.target.sym is set, if it is, just
393 * go to that function and when exiting from its disassembly, come back
394 * to the calling function.
395 */
559static bool annotate_browser__callq(struct annotate_browser *browser, 396static bool annotate_browser__callq(struct annotate_browser *browser,
560 struct perf_evsel *evsel, 397 struct perf_evsel *evsel,
561 struct hist_browser_timer *hbt) 398 struct hist_browser_timer *hbt)
@@ -563,35 +400,25 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
563 struct map_symbol *ms = browser->b.priv; 400 struct map_symbol *ms = browser->b.priv;
564 struct disasm_line *dl = disasm_line(browser->selection); 401 struct disasm_line *dl = disasm_line(browser->selection);
565 struct annotation *notes; 402 struct annotation *notes;
566 struct addr_map_symbol target = {
567 .map = ms->map,
568 .addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
569 };
570 char title[SYM_TITLE_MAX_SIZE]; 403 char title[SYM_TITLE_MAX_SIZE];
571 404
572 if (!ins__is_call(&dl->ins)) 405 if (!dl->ops.target.sym) {
573 return false;
574
575 if (map_groups__find_ams(&target) ||
576 map__rip_2objdump(target.map, target.map->map_ip(target.map,
577 target.addr)) !=
578 dl->ops.target.addr) {
579 ui_helpline__puts("The called function was not found."); 406 ui_helpline__puts("The called function was not found.");
580 return true; 407 return true;
581 } 408 }
582 409
583 notes = symbol__annotation(target.sym); 410 notes = symbol__annotation(dl->ops.target.sym);
584 pthread_mutex_lock(&notes->lock); 411 pthread_mutex_lock(&notes->lock);
585 412
586 if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 413 if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) {
587 pthread_mutex_unlock(&notes->lock); 414 pthread_mutex_unlock(&notes->lock);
588 ui__warning("Not enough memory for annotating '%s' symbol!\n", 415 ui__warning("Not enough memory for annotating '%s' symbol!\n",
589 target.sym->name); 416 dl->ops.target.sym->name);
590 return true; 417 return true;
591 } 418 }
592 419
593 pthread_mutex_unlock(&notes->lock); 420 pthread_mutex_unlock(&notes->lock);
594 symbol__tui_annotate(target.sym, target.map, evsel, hbt); 421 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt);
595 sym_title(ms->sym, ms->map, title, sizeof(title)); 422 sym_title(ms->sym, ms->map, title, sizeof(title));
596 ui_browser__show_title(&browser->b, title); 423 ui_browser__show_title(&browser->b, title);
597 return true; 424 return true;
@@ -601,23 +428,23 @@ static
601struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 428struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
602 s64 offset, s64 *idx) 429 s64 offset, s64 *idx)
603{ 430{
604 struct map_symbol *ms = browser->b.priv; 431 struct annotation *notes = browser__annotation(&browser->b);
605 struct symbol *sym = ms->sym;
606 struct annotation *notes = symbol__annotation(sym);
607 struct disasm_line *pos; 432 struct disasm_line *pos;
608 433
609 *idx = 0; 434 *idx = 0;
610 list_for_each_entry(pos, &notes->src->source, al.node) { 435 list_for_each_entry(pos, &notes->src->source, al.node) {
611 if (pos->al.offset == offset) 436 if (pos->al.offset == offset)
612 return pos; 437 return pos;
613 if (!disasm_line__filter(&browser->b, &pos->al.node)) 438 if (!annotation_line__filter(&pos->al, notes))
614 ++*idx; 439 ++*idx;
615 } 440 }
616 441
617 return NULL; 442 return NULL;
618} 443}
619 444
620static bool annotate_browser__jump(struct annotate_browser *browser) 445static bool annotate_browser__jump(struct annotate_browser *browser,
446 struct perf_evsel *evsel,
447 struct hist_browser_timer *hbt)
621{ 448{
622 struct disasm_line *dl = disasm_line(browser->selection); 449 struct disasm_line *dl = disasm_line(browser->selection);
623 u64 offset; 450 u64 offset;
@@ -626,6 +453,11 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
626 if (!ins__is_jump(&dl->ins)) 453 if (!ins__is_jump(&dl->ins))
627 return false; 454 return false;
628 455
456 if (dl->ops.target.outside) {
457 annotate_browser__callq(browser, evsel, hbt);
458 return true;
459 }
460
629 offset = dl->ops.target.offset; 461 offset = dl->ops.target.offset;
630 dl = annotate_browser__find_offset(browser, offset, &idx); 462 dl = annotate_browser__find_offset(browser, offset, &idx);
631 if (dl == NULL) { 463 if (dl == NULL) {
@@ -642,14 +474,12 @@ static
642struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 474struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
643 char *s, s64 *idx) 475 char *s, s64 *idx)
644{ 476{
645 struct map_symbol *ms = browser->b.priv; 477 struct annotation *notes = browser__annotation(&browser->b);
646 struct symbol *sym = ms->sym;
647 struct annotation *notes = symbol__annotation(sym);
648 struct annotation_line *al = browser->selection; 478 struct annotation_line *al = browser->selection;
649 479
650 *idx = browser->b.index; 480 *idx = browser->b.index;
651 list_for_each_entry_continue(al, &notes->src->source, node) { 481 list_for_each_entry_continue(al, &notes->src->source, node) {
652 if (disasm_line__filter(&browser->b, &al->node)) 482 if (annotation_line__filter(al, notes))
653 continue; 483 continue;
654 484
655 ++*idx; 485 ++*idx;
@@ -681,14 +511,12 @@ static
681struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 511struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
682 char *s, s64 *idx) 512 char *s, s64 *idx)
683{ 513{
684 struct map_symbol *ms = browser->b.priv; 514 struct annotation *notes = browser__annotation(&browser->b);
685 struct symbol *sym = ms->sym;
686 struct annotation *notes = symbol__annotation(sym);
687 struct annotation_line *al = browser->selection; 515 struct annotation_line *al = browser->selection;
688 516
689 *idx = browser->b.index; 517 *idx = browser->b.index;
690 list_for_each_entry_continue_reverse(al, &notes->src->source, node) { 518 list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
691 if (disasm_line__filter(&browser->b, &al->node)) 519 if (annotation_line__filter(al, notes))
692 continue; 520 continue;
693 521
694 --*idx; 522 --*idx;
@@ -764,17 +592,21 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
764 return __annotate_browser__search_reverse(browser); 592 return __annotate_browser__search_reverse(browser);
765} 593}
766 594
767static void annotate_browser__update_addr_width(struct annotate_browser *browser) 595static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
768{ 596{
769 if (annotate_browser__opts.use_offset) 597 struct map_symbol *ms = browser->priv;
770 browser->target_width = browser->min_addr_width; 598 struct symbol *sym = ms->sym;
771 else 599 char symbol_dso[SYM_TITLE_MAX_SIZE];
772 browser->target_width = browser->max_addr_width; 600
601 if (ui_browser__show(browser, title, help) < 0)
602 return -1;
773 603
774 browser->addr_width = browser->target_width; 604 sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso));
775 605
776 if (annotate_browser__opts.show_nr_jumps) 606 ui_browser__gotorc_title(browser, 0, 0);
777 browser->addr_width += browser->jumps_width + 1; 607 ui_browser__set_color(browser, HE_COLORSET_ROOT);
608 ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
609 return 0;
778} 610}
779 611
780static int annotate_browser__run(struct annotate_browser *browser, 612static int annotate_browser__run(struct annotate_browser *browser,
@@ -782,15 +614,18 @@ static int annotate_browser__run(struct annotate_browser *browser,
782 struct hist_browser_timer *hbt) 614 struct hist_browser_timer *hbt)
783{ 615{
784 struct rb_node *nd = NULL; 616 struct rb_node *nd = NULL;
617 struct hists *hists = evsel__hists(evsel);
785 struct map_symbol *ms = browser->b.priv; 618 struct map_symbol *ms = browser->b.priv;
786 struct symbol *sym = ms->sym; 619 struct symbol *sym = ms->sym;
620 struct annotation *notes = symbol__annotation(ms->sym);
787 const char *help = "Press 'h' for help on key bindings"; 621 const char *help = "Press 'h' for help on key bindings";
788 int delay_secs = hbt ? hbt->refresh : 0; 622 int delay_secs = hbt ? hbt->refresh : 0;
623 char title[256];
789 int key; 624 int key;
790 char title[SYM_TITLE_MAX_SIZE];
791 625
792 sym_title(sym, ms->map, title, sizeof(title)); 626 annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel);
793 if (ui_browser__show(&browser->b, title, help) < 0) 627
628 if (annotate_browser__show(&browser->b, title, help) < 0)
794 return -1; 629 return -1;
795 630
796 annotate_browser__calc_percent(browser, evsel); 631 annotate_browser__calc_percent(browser, evsel);
@@ -821,8 +656,11 @@ static int annotate_browser__run(struct annotate_browser *browser,
821 if (hbt) 656 if (hbt)
822 hbt->timer(hbt->arg); 657 hbt->timer(hbt->arg);
823 658
824 if (delay_secs != 0) 659 if (delay_secs != 0) {
825 symbol__annotate_decay_histogram(sym, evsel->idx); 660 symbol__annotate_decay_histogram(sym, evsel->idx);
661 hists__scnprintf_title(hists, title, sizeof(title));
662 annotate_browser__show(&browser->b, title, help);
663 }
826 continue; 664 continue;
827 case K_TAB: 665 case K_TAB:
828 if (nd != NULL) { 666 if (nd != NULL) {
@@ -854,10 +692,12 @@ static int annotate_browser__run(struct annotate_browser *browser,
854 "J Toggle showing number of jump sources on targets\n" 692 "J Toggle showing number of jump sources on targets\n"
855 "n Search next string\n" 693 "n Search next string\n"
856 "o Toggle disassembler output/simplified view\n" 694 "o Toggle disassembler output/simplified view\n"
695 "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
857 "s Toggle source code view\n" 696 "s Toggle source code view\n"
858 "t Circulate percent, total period, samples view\n" 697 "t Circulate percent, total period, samples view\n"
859 "/ Search string\n" 698 "/ Search string\n"
860 "k Toggle line numbers\n" 699 "k Toggle line numbers\n"
700 "P Print to [symbol_name].annotation file.\n"
861 "r Run available scripts\n" 701 "r Run available scripts\n"
862 "? Search string backwards\n"); 702 "? Search string backwards\n");
863 continue; 703 continue;
@@ -867,8 +707,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
867 continue; 707 continue;
868 } 708 }
869 case 'k': 709 case 'k':
870 annotate_browser__opts.show_linenr = 710 notes->options->show_linenr = !notes->options->show_linenr;
871 !annotate_browser__opts.show_linenr;
872 break; 711 break;
873 case 'H': 712 case 'H':
874 nd = browser->curr_hot; 713 nd = browser->curr_hot;
@@ -878,15 +717,19 @@ static int annotate_browser__run(struct annotate_browser *browser,
878 ui_helpline__puts(help); 717 ui_helpline__puts(help);
879 continue; 718 continue;
880 case 'o': 719 case 'o':
881 annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 720 notes->options->use_offset = !notes->options->use_offset;
882 annotate_browser__update_addr_width(browser); 721 annotation__update_column_widths(notes);
722 continue;
723 case 'O':
724 if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
725 notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
883 continue; 726 continue;
884 case 'j': 727 case 'j':
885 annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 728 notes->options->jump_arrows = !notes->options->jump_arrows;
886 continue; 729 continue;
887 case 'J': 730 case 'J':
888 annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 731 notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
889 annotate_browser__update_addr_width(browser); 732 annotation__update_column_widths(notes);
890 continue; 733 continue;
891 case '/': 734 case '/':
892 if (annotate_browser__search(browser, delay_secs)) { 735 if (annotate_browser__search(browser, delay_secs)) {
@@ -912,7 +755,7 @@ show_help:
912 browser->b.height, 755 browser->b.height,
913 browser->b.index, 756 browser->b.index,
914 browser->b.top_idx, 757 browser->b.top_idx,
915 browser->nr_asm_entries); 758 notes->nr_asm_entries);
916 } 759 }
917 continue; 760 continue;
918 case K_ENTER: 761 case K_ENTER:
@@ -928,22 +771,25 @@ show_help:
928 goto show_sup_ins; 771 goto show_sup_ins;
929 else if (ins__is_ret(&dl->ins)) 772 else if (ins__is_ret(&dl->ins))
930 goto out; 773 goto out;
931 else if (!(annotate_browser__jump(browser) || 774 else if (!(annotate_browser__jump(browser, evsel, hbt) ||
932 annotate_browser__callq(browser, evsel, hbt))) { 775 annotate_browser__callq(browser, evsel, hbt))) {
933show_sup_ins: 776show_sup_ins:
934 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 777 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
935 } 778 }
936 continue; 779 continue;
937 } 780 }
781 case 'P':
782 map_symbol__annotation_dump(ms, evsel);
783 continue;
938 case 't': 784 case 't':
939 if (annotate_browser__opts.show_total_period) { 785 if (notes->options->show_total_period) {
940 annotate_browser__opts.show_total_period = false; 786 notes->options->show_total_period = false;
941 annotate_browser__opts.show_nr_samples = true; 787 notes->options->show_nr_samples = true;
942 } else if (annotate_browser__opts.show_nr_samples) 788 } else if (notes->options->show_nr_samples)
943 annotate_browser__opts.show_nr_samples = false; 789 notes->options->show_nr_samples = false;
944 else 790 else
945 annotate_browser__opts.show_total_period = true; 791 notes->options->show_total_period = true;
946 annotate_browser__update_addr_width(browser); 792 annotation__update_column_widths(notes);
947 continue; 793 continue;
948 case K_LEFT: 794 case K_LEFT:
949 case K_ESC: 795 case K_ESC:
@@ -965,12 +811,6 @@ out:
965int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 811int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
966 struct hist_browser_timer *hbt) 812 struct hist_browser_timer *hbt)
967{ 813{
968 /* Set default value for show_total_period and show_nr_samples */
969 annotate_browser__opts.show_total_period =
970 symbol_conf.show_total_period;
971 annotate_browser__opts.show_nr_samples =
972 symbol_conf.show_nr_samples;
973
974 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 814 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
975} 815}
976 816
@@ -984,129 +824,11 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
984 return map_symbol__tui_annotate(&he->ms, evsel, hbt); 824 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
985} 825}
986 826
987
988static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end)
989{
990 unsigned n_insn = 0;
991 u64 offset;
992
993 for (offset = start; offset <= end; offset++) {
994 if (browser->offsets[offset])
995 n_insn++;
996 }
997 return n_insn;
998}
999
1000static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,
1001 struct cyc_hist *ch)
1002{
1003 unsigned n_insn;
1004 u64 offset;
1005
1006 n_insn = count_insn(browser, start, end);
1007 if (n_insn && ch->num && ch->cycles) {
1008 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
1009
1010 /* Hide data when there are too many overlaps. */
1011 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
1012 return;
1013
1014 for (offset = start; offset <= end; offset++) {
1015 struct annotation_line *al = browser->offsets[offset];
1016
1017 if (al)
1018 al->ipc = ipc;
1019 }
1020 }
1021}
1022
1023/*
1024 * This should probably be in util/annotate.c to share with the tty
1025 * annotate, but right now we need the per byte offsets arrays,
1026 * which are only here.
1027 */
1028static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,
1029 struct symbol *sym)
1030{
1031 u64 offset;
1032 struct annotation *notes = symbol__annotation(sym);
1033
1034 if (!notes->src || !notes->src->cycles_hist)
1035 return;
1036
1037 pthread_mutex_lock(&notes->lock);
1038 for (offset = 0; offset < size; ++offset) {
1039 struct cyc_hist *ch;
1040
1041 ch = &notes->src->cycles_hist[offset];
1042 if (ch && ch->cycles) {
1043 struct annotation_line *al;
1044
1045 if (ch->have_start)
1046 count_and_fill(browser, ch->start, offset, ch);
1047 al = browser->offsets[offset];
1048 if (al && ch->num_aggr)
1049 al->cycles = ch->cycles_aggr / ch->num_aggr;
1050 browser->have_cycles = true;
1051 }
1052 }
1053 pthread_mutex_unlock(&notes->lock);
1054}
1055
1056static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
1057 size_t size)
1058{
1059 u64 offset;
1060 struct map_symbol *ms = browser->b.priv;
1061 struct symbol *sym = ms->sym;
1062
1063 /* PLT symbols contain external offsets */
1064 if (strstr(sym->name, "@plt"))
1065 return;
1066
1067 for (offset = 0; offset < size; ++offset) {
1068 struct annotation_line *al = browser->offsets[offset];
1069 struct disasm_line *dl;
1070 struct browser_line *blt;
1071
1072 dl = disasm_line(al);
1073
1074 if (!disasm_line__is_valid_jump(dl, sym))
1075 continue;
1076
1077 al = browser->offsets[dl->ops.target.offset];
1078
1079 /*
1080 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
1081 * have to adjust to the previous offset?
1082 */
1083 if (al == NULL)
1084 continue;
1085
1086 blt = browser_line(al);
1087 if (++blt->jump_sources > browser->max_jump_sources)
1088 browser->max_jump_sources = blt->jump_sources;
1089
1090 ++browser->nr_jumps;
1091 }
1092}
1093
1094static inline int width_jumps(int n)
1095{
1096 if (n >= 100)
1097 return 5;
1098 if (n / 10)
1099 return 2;
1100 return 1;
1101}
1102
1103int symbol__tui_annotate(struct symbol *sym, struct map *map, 827int symbol__tui_annotate(struct symbol *sym, struct map *map,
1104 struct perf_evsel *evsel, 828 struct perf_evsel *evsel,
1105 struct hist_browser_timer *hbt) 829 struct hist_browser_timer *hbt)
1106{ 830{
1107 struct annotation_line *al; 831 struct annotation *notes = symbol__annotation(sym);
1108 struct annotation *notes;
1109 size_t size;
1110 struct map_symbol ms = { 832 struct map_symbol ms = {
1111 .map = map, 833 .map = map,
1112 .sym = sym, 834 .sym = sym,
@@ -1117,31 +839,20 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1117 .seek = ui_browser__list_head_seek, 839 .seek = ui_browser__list_head_seek,
1118 .write = annotate_browser__write, 840 .write = annotate_browser__write,
1119 .filter = disasm_line__filter, 841 .filter = disasm_line__filter,
842 .extra_title_lines = 1, /* for hists__scnprintf_title() */
1120 .priv = &ms, 843 .priv = &ms,
1121 .use_navkeypressed = true, 844 .use_navkeypressed = true,
1122 }, 845 },
1123 }; 846 };
1124 int ret = -1, err; 847 int ret = -1, err;
1125 int nr_pcnt = 1;
1126 848
1127 if (sym == NULL) 849 if (sym == NULL)
1128 return -1; 850 return -1;
1129 851
1130 size = symbol__size(sym);
1131
1132 if (map->dso->annotate_warned) 852 if (map->dso->annotate_warned)
1133 return -1; 853 return -1;
1134 854
1135 browser.offsets = zalloc(size * sizeof(struct annotation_line *)); 855 err = symbol__annotate2(sym, map, evsel, &annotation__default_options, &browser.arch);
1136 if (browser.offsets == NULL) {
1137 ui__error("Not enough memory!");
1138 return -1;
1139 }
1140
1141 if (perf_evsel__is_group_event(evsel))
1142 nr_pcnt = evsel->nr_members;
1143
1144 err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch);
1145 if (err) { 856 if (err) {
1146 char msg[BUFSIZ]; 857 char msg[BUFSIZ];
1147 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 858 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
@@ -1149,110 +860,21 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1149 goto out_free_offsets; 860 goto out_free_offsets;
1150 } 861 }
1151 862
1152 symbol__calc_percent(sym, evsel);
1153
1154 ui_helpline__push("Press ESC to exit"); 863 ui_helpline__push("Press ESC to exit");
1155 864
1156 notes = symbol__annotation(sym); 865 browser.b.width = notes->max_line_len;
1157 browser.start = map__rip_2objdump(map, sym->start); 866 browser.b.nr_entries = notes->nr_entries;
1158
1159 list_for_each_entry(al, &notes->src->source, node) {
1160 struct browser_line *bpos;
1161 size_t line_len = strlen(al->line);
1162
1163 if (browser.b.width < line_len)
1164 browser.b.width = line_len;
1165 bpos = browser_line(al);
1166 bpos->idx = browser.nr_entries++;
1167 if (al->offset != -1) {
1168 bpos->idx_asm = browser.nr_asm_entries++;
1169 /*
1170 * FIXME: short term bandaid to cope with assembly
1171 * routines that comes with labels in the same column
1172 * as the address in objdump, sigh.
1173 *
1174 * E.g. copy_user_generic_unrolled
1175 */
1176 if (al->offset < (s64)size)
1177 browser.offsets[al->offset] = al;
1178 } else
1179 bpos->idx_asm = -1;
1180 }
1181
1182 annotate_browser__mark_jump_targets(&browser, size);
1183 annotate__compute_ipc(&browser, size, sym);
1184
1185 browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
1186 browser.max_addr_width = hex_width(sym->end);
1187 browser.jumps_width = width_jumps(browser.max_jump_sources);
1188 browser.nr_events = nr_pcnt;
1189 browser.b.nr_entries = browser.nr_entries;
1190 browser.b.entries = &notes->src->source, 867 browser.b.entries = &notes->src->source,
1191 browser.b.width += 18; /* Percentage */ 868 browser.b.width += 18; /* Percentage */
1192 869
1193 if (annotate_browser__opts.hide_src_code) 870 if (notes->options->hide_src_code)
1194 annotate_browser__init_asm_mode(&browser); 871 ui_browser__init_asm_mode(&browser.b);
1195
1196 annotate_browser__update_addr_width(&browser);
1197 872
1198 ret = annotate_browser__run(&browser, evsel, hbt); 873 ret = annotate_browser__run(&browser, evsel, hbt);
1199 874
1200 annotated_source__purge(notes->src); 875 annotated_source__purge(notes->src);
1201 876
1202out_free_offsets: 877out_free_offsets:
1203 free(browser.offsets); 878 zfree(&notes->offsets);
1204 return ret; 879 return ret;
1205} 880}
1206
1207#define ANNOTATE_CFG(n) \
1208 { .name = #n, .value = &annotate_browser__opts.n, }
1209
1210/*
1211 * Keep the entries sorted, they are bsearch'ed
1212 */
1213static struct annotate_config {
1214 const char *name;
1215 bool *value;
1216} annotate__configs[] = {
1217 ANNOTATE_CFG(hide_src_code),
1218 ANNOTATE_CFG(jump_arrows),
1219 ANNOTATE_CFG(show_linenr),
1220 ANNOTATE_CFG(show_nr_jumps),
1221 ANNOTATE_CFG(show_nr_samples),
1222 ANNOTATE_CFG(show_total_period),
1223 ANNOTATE_CFG(use_offset),
1224};
1225
1226#undef ANNOTATE_CFG
1227
1228static int annotate_config__cmp(const void *name, const void *cfgp)
1229{
1230 const struct annotate_config *cfg = cfgp;
1231
1232 return strcmp(name, cfg->name);
1233}
1234
1235static int annotate__config(const char *var, const char *value,
1236 void *data __maybe_unused)
1237{
1238 struct annotate_config *cfg;
1239 const char *name;
1240
1241 if (!strstarts(var, "annotate."))
1242 return 0;
1243
1244 name = var + 9;
1245 cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs),
1246 sizeof(struct annotate_config), annotate_config__cmp);
1247
1248 if (cfg == NULL)
1249 ui__warning("%s variable unknown, ignoring...", var);
1250 else
1251 *cfg->value = perf_config_bool(name, value);
1252 return 0;
1253}
1254
1255void annotate_browser__init(void)
1256{
1257 perf_config(annotate__config, NULL);
1258}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 6495ee55d9c3..e5f247247daa 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -32,8 +32,7 @@
32 32
33extern void hist_browser__init_hpp(void); 33extern void hist_browser__init_hpp(void);
34 34
35static int perf_evsel_browser_title(struct hist_browser *browser, 35static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size);
36 char *bf, size_t size);
37static void hist_browser__update_nr_entries(struct hist_browser *hb); 36static void hist_browser__update_nr_entries(struct hist_browser *hb);
38 37
39static struct rb_node *hists__filter_entries(struct rb_node *nd, 38static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -62,6 +61,15 @@ static int hist_browser__get_folding(struct hist_browser *browser)
62 return unfolded_rows; 61 return unfolded_rows;
63} 62}
64 63
64static void hist_browser__set_title_space(struct hist_browser *hb)
65{
66 struct ui_browser *browser = &hb->b;
67 struct hists *hists = hb->hists;
68 struct perf_hpp_list *hpp_list = hists->hpp_list;
69
70 browser->extra_title_lines = hb->show_headers ? hpp_list->nr_header_lines : 0;
71}
72
65static u32 hist_browser__nr_entries(struct hist_browser *hb) 73static u32 hist_browser__nr_entries(struct hist_browser *hb)
66{ 74{
67 u32 nr_entries; 75 u32 nr_entries;
@@ -82,10 +90,16 @@ static void hist_browser__update_rows(struct hist_browser *hb)
82 struct ui_browser *browser = &hb->b; 90 struct ui_browser *browser = &hb->b;
83 struct hists *hists = hb->hists; 91 struct hists *hists = hb->hists;
84 struct perf_hpp_list *hpp_list = hists->hpp_list; 92 struct perf_hpp_list *hpp_list = hists->hpp_list;
85 u16 header_offset, index_row; 93 u16 index_row;
86 94
87 header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0; 95 if (!hb->show_headers) {
88 browser->rows = browser->height - header_offset; 96 browser->rows += browser->extra_title_lines;
97 browser->extra_title_lines = 0;
98 return;
99 }
100
101 browser->extra_title_lines = hpp_list->nr_header_lines;
102 browser->rows -= browser->extra_title_lines;
89 /* 103 /*
90 * Verify if we were at the last line and that line isn't 104 * Verify if we were at the last line and that line isn't
91 * visibe because we now show the header line(s). 105 * visibe because we now show the header line(s).
@@ -108,17 +122,6 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser)
108 * changeset. 122 * changeset.
109 */ 123 */
110 ui_browser__refresh_dimensions(browser); 124 ui_browser__refresh_dimensions(browser);
111 hist_browser__update_rows(hb);
112}
113
114static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
115{
116 struct hists *hists = browser->hists;
117 struct perf_hpp_list *hpp_list = hists->hpp_list;
118 u16 header_offset;
119
120 header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0;
121 ui_browser__gotorc(&browser->b, row + header_offset, column);
122} 125}
123 126
124static void hist_browser__reset(struct hist_browser *browser) 127static void hist_browser__reset(struct hist_browser *browser)
@@ -656,9 +659,10 @@ int hist_browser__run(struct hist_browser *browser, const char *help,
656 struct hist_entry *h = rb_entry(browser->b.top, 659 struct hist_entry *h = rb_entry(browser->b.top,
657 struct hist_entry, rb_node); 660 struct hist_entry, rb_node);
658 ui_helpline__pop(); 661 ui_helpline__pop();
659 ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 662 ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
660 seq++, browser->b.nr_entries, 663 seq++, browser->b.nr_entries,
661 browser->hists->nr_entries, 664 browser->hists->nr_entries,
665 browser->b.extra_title_lines,
662 browser->b.rows, 666 browser->b.rows,
663 browser->b.index, 667 browser->b.index,
664 browser->b.top_idx, 668 browser->b.top_idx,
@@ -733,7 +737,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
733 } 737 }
734 738
735 ui_browser__set_color(&browser->b, color); 739 ui_browser__set_color(&browser->b, color);
736 hist_browser__gotorc(browser, row, 0); 740 ui_browser__gotorc(&browser->b, row, 0);
737 ui_browser__write_nstring(&browser->b, " ", offset); 741 ui_browser__write_nstring(&browser->b, " ", offset);
738 ui_browser__printf(&browser->b, "%c", folded_sign); 742 ui_browser__printf(&browser->b, "%c", folded_sign);
739 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); 743 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
@@ -1249,7 +1253,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1249 }; 1253 };
1250 int column = 0; 1254 int column = 0;
1251 1255
1252 hist_browser__gotorc(browser, row, 0); 1256 ui_browser__gotorc(&browser->b, row, 0);
1253 1257
1254 hists__for_each_format(browser->hists, fmt) { 1258 hists__for_each_format(browser->hists, fmt) {
1255 char s[2048]; 1259 char s[2048];
@@ -1358,7 +1362,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
1358 goto show_callchain; 1362 goto show_callchain;
1359 } 1363 }
1360 1364
1361 hist_browser__gotorc(browser, row, 0); 1365 ui_browser__gotorc(&browser->b, row, 0);
1362 1366
1363 if (current_entry && browser->b.navkeypressed) 1367 if (current_entry && browser->b.navkeypressed)
1364 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); 1368 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
@@ -1507,7 +1511,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,
1507 browser->selection = NULL; 1511 browser->selection = NULL;
1508 } 1512 }
1509 1513
1510 hist_browser__gotorc(browser, row, 0); 1514 ui_browser__gotorc(&browser->b, row, 0);
1511 1515
1512 if (current_entry && browser->b.navkeypressed) 1516 if (current_entry && browser->b.navkeypressed)
1513 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); 1517 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
@@ -1713,7 +1717,7 @@ static void hists_browser__headers(struct hist_browser *browser)
1713 hists_browser__scnprintf_headers(browser, headers, 1717 hists_browser__scnprintf_headers(browser, headers,
1714 sizeof(headers), line); 1718 sizeof(headers), line);
1715 1719
1716 ui_browser__gotorc(&browser->b, line, 0); 1720 ui_browser__gotorc_title(&browser->b, line, 0);
1717 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 1721 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1718 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 1722 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1719 } 1723 }
@@ -1740,17 +1744,11 @@ static void ui_browser__hists_init_top(struct ui_browser *browser)
1740static unsigned int hist_browser__refresh(struct ui_browser *browser) 1744static unsigned int hist_browser__refresh(struct ui_browser *browser)
1741{ 1745{
1742 unsigned row = 0; 1746 unsigned row = 0;
1743 u16 header_offset = 0;
1744 struct rb_node *nd; 1747 struct rb_node *nd;
1745 struct hist_browser *hb = container_of(browser, struct hist_browser, b); 1748 struct hist_browser *hb = container_of(browser, struct hist_browser, b);
1746 struct hists *hists = hb->hists;
1747
1748 if (hb->show_headers) {
1749 struct perf_hpp_list *hpp_list = hists->hpp_list;
1750 1749
1750 if (hb->show_headers)
1751 hist_browser__show_headers(hb); 1751 hist_browser__show_headers(hb);
1752 header_offset = hpp_list->nr_header_lines;
1753 }
1754 1752
1755 ui_browser__hists_init_top(browser); 1753 ui_browser__hists_init_top(browser);
1756 hb->he_selection = NULL; 1754 hb->he_selection = NULL;
@@ -1788,7 +1786,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
1788 break; 1786 break;
1789 } 1787 }
1790 1788
1791 return row + header_offset; 1789 return row;
1792} 1790}
1793 1791
1794static struct rb_node *hists__filter_entries(struct rb_node *nd, 1792static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -2143,6 +2141,7 @@ void hist_browser__init(struct hist_browser *browser,
2143 browser->b.seek = ui_browser__hists_seek; 2141 browser->b.seek = ui_browser__hists_seek;
2144 browser->b.use_navkeypressed = true; 2142 browser->b.use_navkeypressed = true;
2145 browser->show_headers = symbol_conf.show_hist_headers; 2143 browser->show_headers = symbol_conf.show_hist_headers;
2144 hist_browser__set_title_space(browser);
2146 2145
2147 if (symbol_conf.report_hierarchy) { 2146 if (symbol_conf.report_hierarchy) {
2148 struct perf_hpp_list_node *fmt_node; 2147 struct perf_hpp_list_node *fmt_node;
@@ -2183,7 +2182,7 @@ perf_evsel_browser__new(struct perf_evsel *evsel,
2183 if (browser) { 2182 if (browser) {
2184 browser->hbt = hbt; 2183 browser->hbt = hbt;
2185 browser->env = env; 2184 browser->env = env;
2186 browser->title = perf_evsel_browser_title; 2185 browser->title = hists_browser__scnprintf_title;
2187 } 2186 }
2188 return browser; 2187 return browser;
2189} 2188}
@@ -2209,79 +2208,11 @@ static inline bool is_report_browser(void *timer)
2209 return timer == NULL; 2208 return timer == NULL;
2210} 2209}
2211 2210
2212static int perf_evsel_browser_title(struct hist_browser *browser, 2211static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size)
2213 char *bf, size_t size)
2214{ 2212{
2215 struct hist_browser_timer *hbt = browser->hbt; 2213 struct hist_browser_timer *hbt = browser->hbt;
2216 struct hists *hists = browser->hists; 2214 int printed = __hists__scnprintf_title(browser->hists, bf, size, !is_report_browser(hbt));
2217 char unit;
2218 int printed;
2219 const struct dso *dso = hists->dso_filter;
2220 const struct thread *thread = hists->thread_filter;
2221 int socket_id = hists->socket_filter;
2222 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
2223 u64 nr_events = hists->stats.total_period;
2224 struct perf_evsel *evsel = hists_to_evsel(hists);
2225 const char *ev_name = perf_evsel__name(evsel);
2226 char buf[512];
2227 size_t buflen = sizeof(buf);
2228 char ref[30] = " show reference callgraph, ";
2229 bool enable_ref = false;
2230
2231 if (symbol_conf.filter_relative) {
2232 nr_samples = hists->stats.nr_non_filtered_samples;
2233 nr_events = hists->stats.total_non_filtered_period;
2234 }
2235
2236 if (perf_evsel__is_group_event(evsel)) {
2237 struct perf_evsel *pos;
2238 2215
2239 perf_evsel__group_desc(evsel, buf, buflen);
2240 ev_name = buf;
2241
2242 for_each_group_member(pos, evsel) {
2243 struct hists *pos_hists = evsel__hists(pos);
2244
2245 if (symbol_conf.filter_relative) {
2246 nr_samples += pos_hists->stats.nr_non_filtered_samples;
2247 nr_events += pos_hists->stats.total_non_filtered_period;
2248 } else {
2249 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
2250 nr_events += pos_hists->stats.total_period;
2251 }
2252 }
2253 }
2254
2255 if (symbol_conf.show_ref_callgraph &&
2256 strstr(ev_name, "call-graph=no"))
2257 enable_ref = true;
2258 nr_samples = convert_unit(nr_samples, &unit);
2259 printed = scnprintf(bf, size,
2260 "Samples: %lu%c of event '%s',%sEvent count (approx.): %" PRIu64,
2261 nr_samples, unit, ev_name, enable_ref ? ref : " ", nr_events);
2262
2263
2264 if (hists->uid_filter_str)
2265 printed += snprintf(bf + printed, size - printed,
2266 ", UID: %s", hists->uid_filter_str);
2267 if (thread) {
2268 if (hists__has(hists, thread)) {
2269 printed += scnprintf(bf + printed, size - printed,
2270 ", Thread: %s(%d)",
2271 (thread->comm_set ? thread__comm_str(thread) : ""),
2272 thread->tid);
2273 } else {
2274 printed += scnprintf(bf + printed, size - printed,
2275 ", Thread: %s",
2276 (thread->comm_set ? thread__comm_str(thread) : ""));
2277 }
2278 }
2279 if (dso)
2280 printed += scnprintf(bf + printed, size - printed,
2281 ", DSO: %s", dso->short_name);
2282 if (socket_id > -1)
2283 printed += scnprintf(bf + printed, size - printed,
2284 ", Processor Socket: %d", socket_id);
2285 if (!is_report_browser(hbt)) { 2216 if (!is_report_browser(hbt)) {
2286 struct perf_top *top = hbt->arg; 2217 struct perf_top *top = hbt->arg;
2287 2218
@@ -2783,7 +2714,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2783 "h/?/F1 Show this window\n" \ 2714 "h/?/F1 Show this window\n" \
2784 "UP/DOWN/PGUP\n" \ 2715 "UP/DOWN/PGUP\n" \
2785 "PGDN/SPACE Navigate\n" \ 2716 "PGDN/SPACE Navigate\n" \
2786 "q/ESC/CTRL+C Exit browser\n\n" \ 2717 "q/ESC/CTRL+C Exit browser or go back to previous screen\n\n" \
2787 "For multiple event sessions:\n\n" \ 2718 "For multiple event sessions:\n\n" \
2788 "TAB/UNTAB Switch events\n\n" \ 2719 "TAB/UNTAB Switch events\n\n" \
2789 "For symbolic views (--sort has sym):\n\n" \ 2720 "For symbolic views (--sort has sym):\n\n" \
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 25dd1e0ecc58..6832fcb2e6ff 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -840,15 +840,11 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp)
840 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 840 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
841 const char *name; 841 const char *name;
842 842
843 if (stats->nr_events[i] == 0)
844 continue;
845
846 name = perf_event__name(i); 843 name = perf_event__name(i);
847 if (!strcmp(name, "UNKNOWN")) 844 if (!strcmp(name, "UNKNOWN"))
848 continue; 845 continue;
849 846
850 ret += fprintf(fp, "%16s events: %10d\n", name, 847 ret += fprintf(fp, "%16s events: %10d\n", name, stats->nr_events[i]);
851 stats->nr_events[i]);
852 } 848 }
853 849
854 return ret; 850 return ret;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index ea0a452550b0..8052373bcd6a 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -106,6 +106,7 @@ libperf-y += units.o
106libperf-y += time-utils.o 106libperf-y += time-utils.o
107libperf-y += expr-bison.o 107libperf-y += expr-bison.o
108libperf-y += branch.o 108libperf-y += branch.o
109libperf-y += mem2node.o
109 110
110libperf-$(CONFIG_LIBBPF) += bpf-loader.o 111libperf-$(CONFIG_LIBBPF) += bpf-loader.o
111libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 112libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 28b233c3dcbe..5d74a30fe00f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,8 +14,10 @@
14#include "sort.h" 14#include "sort.h"
15#include "build-id.h" 15#include "build-id.h"
16#include "color.h" 16#include "color.h"
17#include "config.h"
17#include "cache.h" 18#include "cache.h"
18#include "symbol.h" 19#include "symbol.h"
20#include "units.h"
19#include "debug.h" 21#include "debug.h"
20#include "annotate.h" 22#include "annotate.h"
21#include "evsel.h" 23#include "evsel.h"
@@ -27,8 +29,26 @@
27#include <linux/bitops.h> 29#include <linux/bitops.h>
28#include <linux/kernel.h> 30#include <linux/kernel.h>
29 31
32/* FIXME: For the HE_COLORSET */
33#include "ui/browser.h"
34
35/*
36 * FIXME: Using the same values as slang.h,
37 * but that header may not be available everywhere
38 */
39#define LARROW_CHAR ((unsigned char)',')
40#define RARROW_CHAR ((unsigned char)'+')
41#define DARROW_CHAR ((unsigned char)'.')
42#define UARROW_CHAR ((unsigned char)'-')
43
30#include "sane_ctype.h" 44#include "sane_ctype.h"
31 45
46struct annotation_options annotation__default_options = {
47 .use_offset = true,
48 .jump_arrows = true,
49 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
50};
51
32const char *disassembler_style; 52const char *disassembler_style;
33const char *objdump_path; 53const char *objdump_path;
34static regex_t file_lineno; 54static regex_t file_lineno;
@@ -184,9 +204,13 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
184 return arch->ins_is_fused(arch, ins1, ins2); 204 return arch->ins_is_fused(arch, ins1, ins2);
185} 205}
186 206
187static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 207static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
188{ 208{
189 char *endptr, *tok, *name; 209 char *endptr, *tok, *name;
210 struct map *map = ms->map;
211 struct addr_map_symbol target = {
212 .map = map,
213 };
190 214
191 ops->target.addr = strtoull(ops->raw, &endptr, 16); 215 ops->target.addr = strtoull(ops->raw, &endptr, 16);
192 216
@@ -208,32 +232,36 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *
208 ops->target.name = strdup(name); 232 ops->target.name = strdup(name);
209 *tok = '>'; 233 *tok = '>';
210 234
211 return ops->target.name == NULL ? -1 : 0; 235 if (ops->target.name == NULL)
236 return -1;
237find_target:
238 target.addr = map__objdump_2mem(map, ops->target.addr);
212 239
213indirect_call: 240 if (map_groups__find_ams(&target) == 0 &&
214 tok = strchr(endptr, '*'); 241 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
215 if (tok == NULL) { 242 ops->target.sym = target.sym;
216 struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr));
217 if (sym != NULL)
218 ops->target.name = strdup(sym->name);
219 else
220 ops->target.addr = 0;
221 return 0;
222 }
223 243
224 ops->target.addr = strtoull(tok + 1, NULL, 16);
225 return 0; 244 return 0;
245
246indirect_call:
247 tok = strchr(endptr, '*');
248 if (tok != NULL)
249 ops->target.addr = strtoull(tok + 1, NULL, 16);
250 goto find_target;
226} 251}
227 252
228static int call__scnprintf(struct ins *ins, char *bf, size_t size, 253static int call__scnprintf(struct ins *ins, char *bf, size_t size,
229 struct ins_operands *ops) 254 struct ins_operands *ops)
230{ 255{
231 if (ops->target.name) 256 if (ops->target.sym)
232 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name); 257 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
233 258
234 if (ops->target.addr == 0) 259 if (ops->target.addr == 0)
235 return ins__raw_scnprintf(ins, bf, size, ops); 260 return ins__raw_scnprintf(ins, bf, size, ops);
236 261
262 if (ops->target.name)
263 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name);
264
237 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr); 265 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr);
238} 266}
239 267
@@ -244,14 +272,29 @@ static struct ins_ops call_ops = {
244 272
245bool ins__is_call(const struct ins *ins) 273bool ins__is_call(const struct ins *ins)
246{ 274{
247 return ins->ops == &call_ops; 275 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
248} 276}
249 277
250static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 278static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms)
251{ 279{
252 const char *s = strchr(ops->raw, '+'); 280 struct map *map = ms->map;
281 struct symbol *sym = ms->sym;
282 struct addr_map_symbol target = {
283 .map = map,
284 };
253 const char *c = strchr(ops->raw, ','); 285 const char *c = strchr(ops->raw, ',');
254 286 u64 start, end;
287 /*
288 * Examples of lines to parse for the _cpp_lex_token@@Base
289 * function:
290 *
291 * 1159e6c: jne 115aa32 <_cpp_lex_token@@Base+0xf92>
292 * 1159e8b: jne c469be <cpp_named_operator2name@@Base+0xa72>
293 *
294 * The first is a jump to an offset inside the same function,
295 * the second is to another function, i.e. that 0xa72 is an
296 * offset in the cpp_named_operator2name@@base function.
297 */
255 /* 298 /*
256 * skip over possible up to 2 operands to get to address, e.g.: 299 * skip over possible up to 2 operands to get to address, e.g.:
257 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0> 300 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
@@ -267,8 +310,36 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
267 ops->target.addr = strtoull(ops->raw, NULL, 16); 310 ops->target.addr = strtoull(ops->raw, NULL, 16);
268 } 311 }
269 312
270 if (s++ != NULL) { 313 target.addr = map__objdump_2mem(map, ops->target.addr);
271 ops->target.offset = strtoull(s, NULL, 16); 314 start = map->unmap_ip(map, sym->start),
315 end = map->unmap_ip(map, sym->end);
316
317 ops->target.outside = target.addr < start || target.addr > end;
318
319 /*
320 * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):
321
322 cpp_named_operator2name@@Base+0xa72
323
324 * Point to a place that is after the cpp_named_operator2name
325 * boundaries, i.e. in the ELF symbol table for cc1
326 * cpp_named_operator2name is marked as being 32-bytes long, but it in
327 * fact is much larger than that, so we seem to need a symbols__find()
328 * routine that looks for >= current->start and < next_symbol->start,
329 * possibly just for C++ objects?
330 *
331 * For now lets just make some progress by marking jumps to outside the
332 * current function as call like.
333 *
334 * Actual navigation will come next, with further understanding of how
335 * the symbol searching and disassembly should be done.
336 */
337 if (map_groups__find_ams(&target) == 0 &&
338 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
339 ops->target.sym = target.sym;
340
341 if (!ops->target.outside) {
342 ops->target.offset = target.addr - start;
272 ops->target.offset_avail = true; 343 ops->target.offset_avail = true;
273 } else { 344 } else {
274 ops->target.offset_avail = false; 345 ops->target.offset_avail = false;
@@ -280,11 +351,15 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
280static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 351static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
281 struct ins_operands *ops) 352 struct ins_operands *ops)
282{ 353{
283 const char *c = strchr(ops->raw, ','); 354 const char *c;
284 355
285 if (!ops->target.addr || ops->target.offset < 0) 356 if (!ops->target.addr || ops->target.offset < 0)
286 return ins__raw_scnprintf(ins, bf, size, ops); 357 return ins__raw_scnprintf(ins, bf, size, ops);
287 358
359 if (ops->target.outside && ops->target.sym != NULL)
360 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
361
362 c = strchr(ops->raw, ',');
288 if (c != NULL) { 363 if (c != NULL) {
289 const char *c2 = strchr(c + 1, ','); 364 const char *c2 = strchr(c + 1, ',');
290 365
@@ -340,7 +415,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
340 return 0; 415 return 0;
341} 416}
342 417
343static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 418static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
344{ 419{
345 ops->locked.ops = zalloc(sizeof(*ops->locked.ops)); 420 ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
346 if (ops->locked.ops == NULL) 421 if (ops->locked.ops == NULL)
@@ -355,7 +430,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *
355 goto out_free_ops; 430 goto out_free_ops;
356 431
357 if (ops->locked.ins.ops->parse && 432 if (ops->locked.ins.ops->parse &&
358 ops->locked.ins.ops->parse(arch, ops->locked.ops, map) < 0) 433 ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
359 goto out_free_ops; 434 goto out_free_ops;
360 435
361 return 0; 436 return 0;
@@ -398,7 +473,7 @@ static struct ins_ops lock_ops = {
398 .scnprintf = lock__scnprintf, 473 .scnprintf = lock__scnprintf,
399}; 474};
400 475
401static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *map __maybe_unused) 476static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
402{ 477{
403 char *s = strchr(ops->raw, ','), *target, *comment, prev; 478 char *s = strchr(ops->raw, ','), *target, *comment, prev;
404 479
@@ -459,7 +534,7 @@ static struct ins_ops mov_ops = {
459 .scnprintf = mov__scnprintf, 534 .scnprintf = mov__scnprintf,
460}; 535};
461 536
462static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 537static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
463{ 538{
464 char *target, *comment, *s, prev; 539 char *target, *comment, *s, prev;
465 540
@@ -826,6 +901,66 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
826 return err; 901 return err;
827} 902}
828 903
904static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 end)
905{
906 unsigned n_insn = 0;
907 u64 offset;
908
909 for (offset = start; offset <= end; offset++) {
910 if (notes->offsets[offset])
911 n_insn++;
912 }
913 return n_insn;
914}
915
916static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
917{
918 unsigned n_insn;
919 u64 offset;
920
921 n_insn = annotation__count_insn(notes, start, end);
922 if (n_insn && ch->num && ch->cycles) {
923 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
924
925 /* Hide data when there are too many overlaps. */
926 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
927 return;
928
929 for (offset = start; offset <= end; offset++) {
930 struct annotation_line *al = notes->offsets[offset];
931
932 if (al)
933 al->ipc = ipc;
934 }
935 }
936}
937
938void annotation__compute_ipc(struct annotation *notes, size_t size)
939{
940 u64 offset;
941
942 if (!notes->src || !notes->src->cycles_hist)
943 return;
944
945 pthread_mutex_lock(&notes->lock);
946 for (offset = 0; offset < size; ++offset) {
947 struct cyc_hist *ch;
948
949 ch = &notes->src->cycles_hist[offset];
950 if (ch && ch->cycles) {
951 struct annotation_line *al;
952
953 if (ch->have_start)
954 annotation__count_and_fill(notes, ch->start, offset, ch);
955 al = notes->offsets[offset];
956 if (al && ch->num_aggr)
957 al->cycles = ch->cycles_aggr / ch->num_aggr;
958 notes->have_cycles = true;
959 }
960 }
961 pthread_mutex_unlock(&notes->lock);
962}
963
829int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 964int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
830 int evidx) 965 int evidx)
831{ 966{
@@ -838,14 +973,14 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *samp
838 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample); 973 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
839} 974}
840 975
841static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 976static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
842{ 977{
843 dl->ins.ops = ins__find(arch, dl->ins.name); 978 dl->ins.ops = ins__find(arch, dl->ins.name);
844 979
845 if (!dl->ins.ops) 980 if (!dl->ins.ops)
846 return; 981 return;
847 982
848 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, map) < 0) 983 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
849 dl->ins.ops = NULL; 984 dl->ins.ops = NULL;
850} 985}
851 986
@@ -882,7 +1017,7 @@ out_free_name:
882struct annotate_args { 1017struct annotate_args {
883 size_t privsize; 1018 size_t privsize;
884 struct arch *arch; 1019 struct arch *arch;
885 struct map *map; 1020 struct map_symbol ms;
886 struct perf_evsel *evsel; 1021 struct perf_evsel *evsel;
887 s64 offset; 1022 s64 offset;
888 char *line; 1023 char *line;
@@ -964,7 +1099,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args)
964 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0) 1099 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
965 goto out_free_line; 1100 goto out_free_line;
966 1101
967 disasm_line__init_ins(dl, args->arch, args->map); 1102 disasm_line__init_ins(dl, args->arch, &args->ms);
968 } 1103 }
969 } 1104 }
970 1105
@@ -1128,6 +1263,9 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1128 max_percent = sample->percent; 1263 max_percent = sample->percent;
1129 } 1264 }
1130 1265
1266 if (al->samples_nr > nr_percent)
1267 nr_percent = al->samples_nr;
1268
1131 if (max_percent < min_pcnt) 1269 if (max_percent < min_pcnt)
1132 return -1; 1270 return -1;
1133 1271
@@ -1222,7 +1360,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1222 struct annotate_args *args, 1360 struct annotate_args *args,
1223 int *line_nr) 1361 int *line_nr)
1224{ 1362{
1225 struct map *map = args->map; 1363 struct map *map = args->ms.map;
1226 struct annotation *notes = symbol__annotation(sym); 1364 struct annotation *notes = symbol__annotation(sym);
1227 struct disasm_line *dl; 1365 struct disasm_line *dl;
1228 char *line = NULL, *parsed_line, *tmp, *tmp2; 1366 char *line = NULL, *parsed_line, *tmp, *tmp2;
@@ -1269,6 +1407,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1269 args->offset = offset; 1407 args->offset = offset;
1270 args->line = parsed_line; 1408 args->line = parsed_line;
1271 args->line_nr = *line_nr; 1409 args->line_nr = *line_nr;
1410 args->ms.sym = sym;
1272 1411
1273 dl = disasm_line__new(args); 1412 dl = disasm_line__new(args);
1274 free(line); 1413 free(line);
@@ -1277,14 +1416,14 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1277 if (dl == NULL) 1416 if (dl == NULL)
1278 return -1; 1417 return -1;
1279 1418
1280 if (!disasm_line__has_offset(dl)) { 1419 if (!disasm_line__has_local_offset(dl)) {
1281 dl->ops.target.offset = dl->ops.target.addr - 1420 dl->ops.target.offset = dl->ops.target.addr -
1282 map__rip_2objdump(map, sym->start); 1421 map__rip_2objdump(map, sym->start);
1283 dl->ops.target.offset_avail = true; 1422 dl->ops.target.offset_avail = true;
1284 } 1423 }
1285 1424
1286 /* kcore has no symbols, so add the call target name */ 1425 /* kcore has no symbols, so add the call target symbol */
1287 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) { 1426 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
1288 struct addr_map_symbol target = { 1427 struct addr_map_symbol target = {
1289 .map = map, 1428 .map = map,
1290 .addr = dl->ops.target.addr, 1429 .addr = dl->ops.target.addr,
@@ -1292,7 +1431,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1292 1431
1293 if (!map_groups__find_ams(&target) && 1432 if (!map_groups__find_ams(&target) &&
1294 target.sym->start == target.al_addr) 1433 target.sym->start == target.al_addr)
1295 dl->ops.target.name = strdup(target.sym->name); 1434 dl->ops.target.sym = target.sym;
1296 } 1435 }
1297 1436
1298 annotation_line__add(&dl->al, &notes->src->source); 1437 annotation_line__add(&dl->al, &notes->src->source);
@@ -1421,9 +1560,9 @@ fallback:
1421 1560
1422static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 1561static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1423{ 1562{
1424 struct map *map = args->map; 1563 struct map *map = args->ms.map;
1425 struct dso *dso = map->dso; 1564 struct dso *dso = map->dso;
1426 char command[PATH_MAX * 2]; 1565 char *command;
1427 FILE *file; 1566 FILE *file;
1428 char symfs_filename[PATH_MAX]; 1567 char symfs_filename[PATH_MAX];
1429 struct kcore_extract kce; 1568 struct kcore_extract kce;
@@ -1464,7 +1603,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1464 strcpy(symfs_filename, tmp); 1603 strcpy(symfs_filename, tmp);
1465 } 1604 }
1466 1605
1467 snprintf(command, sizeof(command), 1606 err = asprintf(&command,
1468 "%s %s%s --start-address=0x%016" PRIx64 1607 "%s %s%s --start-address=0x%016" PRIx64
1469 " --stop-address=0x%016" PRIx64 1608 " --stop-address=0x%016" PRIx64
1470 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand", 1609 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
@@ -1477,12 +1616,17 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1477 symbol_conf.annotate_src ? "-S" : "", 1616 symbol_conf.annotate_src ? "-S" : "",
1478 symfs_filename, symfs_filename); 1617 symfs_filename, symfs_filename);
1479 1618
1619 if (err < 0) {
1620 pr_err("Failure allocating memory for the command to run\n");
1621 goto out_remove_tmp;
1622 }
1623
1480 pr_debug("Executing: %s\n", command); 1624 pr_debug("Executing: %s\n", command);
1481 1625
1482 err = -1; 1626 err = -1;
1483 if (pipe(stdout_fd) < 0) { 1627 if (pipe(stdout_fd) < 0) {
1484 pr_err("Failure creating the pipe to run %s\n", command); 1628 pr_err("Failure creating the pipe to run %s\n", command);
1485 goto out_remove_tmp; 1629 goto out_free_command;
1486 } 1630 }
1487 1631
1488 pid = fork(); 1632 pid = fork();
@@ -1509,7 +1653,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1509 * If we were using debug info should retry with 1653 * If we were using debug info should retry with
1510 * original binary. 1654 * original binary.
1511 */ 1655 */
1512 goto out_remove_tmp; 1656 goto out_free_command;
1513 } 1657 }
1514 1658
1515 nline = 0; 1659 nline = 0;
@@ -1537,6 +1681,8 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1537 1681
1538 fclose(file); 1682 fclose(file);
1539 err = 0; 1683 err = 0;
1684out_free_command:
1685 free(command);
1540out_remove_tmp: 1686out_remove_tmp:
1541 close(stdout_fd[0]); 1687 close(stdout_fd[0]);
1542 1688
@@ -1550,7 +1696,7 @@ out:
1550 1696
1551out_close_stdout: 1697out_close_stdout:
1552 close(stdout_fd[1]); 1698 close(stdout_fd[1]);
1553 goto out_remove_tmp; 1699 goto out_free_command;
1554} 1700}
1555 1701
1556static void calc_percent(struct sym_hist *hist, 1702static void calc_percent(struct sym_hist *hist,
@@ -1613,7 +1759,6 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1613{ 1759{
1614 struct annotate_args args = { 1760 struct annotate_args args = {
1615 .privsize = privsize, 1761 .privsize = privsize,
1616 .map = map,
1617 .evsel = evsel, 1762 .evsel = evsel,
1618 }; 1763 };
1619 struct perf_env *env = perf_evsel__env(evsel); 1764 struct perf_env *env = perf_evsel__env(evsel);
@@ -1639,6 +1784,9 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1639 } 1784 }
1640 } 1785 }
1641 1786
1787 args.ms.map = map;
1788 args.ms.sym = sym;
1789
1642 return symbol__disassemble(sym, &args); 1790 return symbol__disassemble(sym, &args);
1643} 1791}
1644 1792
@@ -1879,6 +2027,103 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1879 return more; 2027 return more;
1880} 2028}
1881 2029
2030static void FILE__set_percent_color(void *fp __maybe_unused,
2031 double percent __maybe_unused,
2032 bool current __maybe_unused)
2033{
2034}
2035
2036static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2037 int nr __maybe_unused, bool current __maybe_unused)
2038{
2039 return 0;
2040}
2041
2042static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2043{
2044 return 0;
2045}
2046
2047static void FILE__printf(void *fp, const char *fmt, ...)
2048{
2049 va_list args;
2050
2051 va_start(args, fmt);
2052 vfprintf(fp, fmt, args);
2053 va_end(args);
2054}
2055
2056static void FILE__write_graph(void *fp, int graph)
2057{
2058 const char *s;
2059 switch (graph) {
2060
2061 case DARROW_CHAR: s = "↓"; break;
2062 case UARROW_CHAR: s = "↑"; break;
2063 case LARROW_CHAR: s = "←"; break;
2064 case RARROW_CHAR: s = "→"; break;
2065 default: s = "?"; break;
2066 }
2067
2068 fputs(s, fp);
2069}
2070
2071int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2072{
2073 struct annotation *notes = symbol__annotation(sym);
2074 struct annotation_write_ops ops = {
2075 .first_line = true,
2076 .obj = fp,
2077 .set_color = FILE__set_color,
2078 .set_percent_color = FILE__set_percent_color,
2079 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2080 .printf = FILE__printf,
2081 .write_graph = FILE__write_graph,
2082 };
2083 struct annotation_line *al;
2084
2085 list_for_each_entry(al, &notes->src->source, node) {
2086 if (annotation_line__filter(al, notes))
2087 continue;
2088 annotation_line__write(al, notes, &ops);
2089 fputc('\n', fp);
2090 ops.first_line = false;
2091 }
2092
2093 return 0;
2094}
2095
2096int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2097{
2098 const char *ev_name = perf_evsel__name(evsel);
2099 char buf[1024];
2100 char *filename;
2101 int err = -1;
2102 FILE *fp;
2103
2104 if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2105 return -1;
2106
2107 fp = fopen(filename, "w");
2108 if (fp == NULL)
2109 goto out_free_filename;
2110
2111 if (perf_evsel__is_group_event(evsel)) {
2112 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2113 ev_name = buf;
2114 }
2115
2116 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2117 ms->sym->name, ms->map->dso->long_name, ev_name);
2118 symbol__annotate_fprintf2(ms->sym, fp);
2119
2120 fclose(fp);
2121 err = 0;
2122out_free_filename:
2123 free(filename);
2124 return err;
2125}
2126
1882void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) 2127void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
1883{ 2128{
1884 struct annotation *notes = symbol__annotation(sym); 2129 struct annotation *notes = symbol__annotation(sym);
@@ -1938,8 +2183,109 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)
1938 return printed; 2183 return printed;
1939} 2184}
1940 2185
2186bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
2187{
2188 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2189 !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
2190 dl->ops.target.offset >= (s64)symbol__size(sym))
2191 return false;
2192
2193 return true;
2194}
2195
2196void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2197{
2198 u64 offset, size = symbol__size(sym);
2199
2200 /* PLT symbols contain external offsets */
2201 if (strstr(sym->name, "@plt"))
2202 return;
2203
2204 for (offset = 0; offset < size; ++offset) {
2205 struct annotation_line *al = notes->offsets[offset];
2206 struct disasm_line *dl;
2207
2208 dl = disasm_line(al);
2209
2210 if (!disasm_line__is_valid_local_jump(dl, sym))
2211 continue;
2212
2213 al = notes->offsets[dl->ops.target.offset];
2214
2215 /*
2216 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2217 * have to adjust to the previous offset?
2218 */
2219 if (al == NULL)
2220 continue;
2221
2222 if (++al->jump_sources > notes->max_jump_sources)
2223 notes->max_jump_sources = al->jump_sources;
2224
2225 ++notes->nr_jumps;
2226 }
2227}
2228
2229void annotation__set_offsets(struct annotation *notes, s64 size)
2230{
2231 struct annotation_line *al;
2232
2233 notes->max_line_len = 0;
2234
2235 list_for_each_entry(al, &notes->src->source, node) {
2236 size_t line_len = strlen(al->line);
2237
2238 if (notes->max_line_len < line_len)
2239 notes->max_line_len = line_len;
2240 al->idx = notes->nr_entries++;
2241 if (al->offset != -1) {
2242 al->idx_asm = notes->nr_asm_entries++;
2243 /*
2244 * FIXME: short term bandaid to cope with assembly
2245 * routines that comes with labels in the same column
2246 * as the address in objdump, sigh.
2247 *
2248 * E.g. copy_user_generic_unrolled
2249 */
2250 if (al->offset < size)
2251 notes->offsets[al->offset] = al;
2252 } else
2253 al->idx_asm = -1;
2254 }
2255}
2256
2257static inline int width_jumps(int n)
2258{
2259 if (n >= 100)
2260 return 5;
2261 if (n / 10)
2262 return 2;
2263 return 1;
2264}
2265
2266void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2267{
2268 notes->widths.addr = notes->widths.target =
2269 notes->widths.min_addr = hex_width(symbol__size(sym));
2270 notes->widths.max_addr = hex_width(sym->end);
2271 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2272}
2273
2274void annotation__update_column_widths(struct annotation *notes)
2275{
2276 if (notes->options->use_offset)
2277 notes->widths.target = notes->widths.min_addr;
2278 else
2279 notes->widths.target = notes->widths.max_addr;
2280
2281 notes->widths.addr = notes->widths.target;
2282
2283 if (notes->options->show_nr_jumps)
2284 notes->widths.addr += notes->widths.jumps + 1;
2285}
2286
1941static void annotation__calc_lines(struct annotation *notes, struct map *map, 2287static void annotation__calc_lines(struct annotation *notes, struct map *map,
1942 struct rb_root *root, u64 start) 2288 struct rb_root *root)
1943{ 2289{
1944 struct annotation_line *al; 2290 struct annotation_line *al;
1945 struct rb_root tmp_root = RB_ROOT; 2291 struct rb_root tmp_root = RB_ROOT;
@@ -1960,8 +2306,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
1960 if (percent_max <= 0.5) 2306 if (percent_max <= 0.5)
1961 continue; 2307 continue;
1962 2308
1963 al->path = get_srcline(map->dso, start + al->offset, NULL, 2309 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
1964 false, true, start + al->offset); 2310 false, true, notes->start + al->offset);
1965 insert_source_line(&tmp_root, al); 2311 insert_source_line(&tmp_root, al);
1966 } 2312 }
1967 2313
@@ -1972,9 +2318,36 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map,
1972 struct rb_root *root) 2318 struct rb_root *root)
1973{ 2319{
1974 struct annotation *notes = symbol__annotation(sym); 2320 struct annotation *notes = symbol__annotation(sym);
1975 u64 start = map__rip_2objdump(map, sym->start);
1976 2321
1977 annotation__calc_lines(notes, map, root, start); 2322 annotation__calc_lines(notes, map, root);
2323}
2324
2325int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2326 struct perf_evsel *evsel, bool print_lines,
2327 bool full_paths)
2328{
2329 struct dso *dso = map->dso;
2330 struct rb_root source_line = RB_ROOT;
2331 struct annotation_options opts = annotation__default_options;
2332 struct annotation *notes = symbol__annotation(sym);
2333 char buf[1024];
2334
2335 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
2336 return -1;
2337
2338 if (print_lines) {
2339 srcline_full_filename = full_paths;
2340 symbol__calc_lines(sym, map, &source_line);
2341 print_summary(&source_line, dso->long_name);
2342 }
2343
2344 annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel);
2345 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name);
2346 symbol__annotate_fprintf2(sym, stdout);
2347
2348 annotated_source__purge(symbol__annotation(sym)->src);
2349
2350 return 0;
1978} 2351}
1979 2352
1980int symbol__tty_annotate(struct symbol *sym, struct map *map, 2353int symbol__tty_annotate(struct symbol *sym, struct map *map,
@@ -2007,3 +2380,331 @@ bool ui__has_annotation(void)
2007{ 2380{
2008 return use_browser == 1 && perf_hpp_list.sym; 2381 return use_browser == 1 && perf_hpp_list.sym;
2009} 2382}
2383
2384
2385double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes)
2386{
2387 double percent_max = 0.0;
2388 int i;
2389
2390 for (i = 0; i < notes->nr_events; i++) {
2391 if (al->samples[i].percent > percent_max)
2392 percent_max = al->samples[i].percent;
2393 }
2394
2395 return percent_max;
2396}
2397
2398static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2399 void *obj, char *bf, size_t size,
2400 void (*obj__printf)(void *obj, const char *fmt, ...),
2401 void (*obj__write_graph)(void *obj, int graph))
2402{
2403 if (dl->ins.ops && dl->ins.ops->scnprintf) {
2404 if (ins__is_jump(&dl->ins)) {
2405 bool fwd;
2406
2407 if (dl->ops.target.outside)
2408 goto call_like;
2409 fwd = dl->ops.target.offset > dl->al.offset;
2410 obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2411 obj__printf(obj, " ");
2412 } else if (ins__is_call(&dl->ins)) {
2413call_like:
2414 obj__write_graph(obj, RARROW_CHAR);
2415 obj__printf(obj, " ");
2416 } else if (ins__is_ret(&dl->ins)) {
2417 obj__write_graph(obj, LARROW_CHAR);
2418 obj__printf(obj, " ");
2419 } else {
2420 obj__printf(obj, " ");
2421 }
2422 } else {
2423 obj__printf(obj, " ");
2424 }
2425
2426 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2427}
2428
2429static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2430 bool first_line, bool current_entry, bool change_color, int width,
2431 void *obj,
2432 int (*obj__set_color)(void *obj, int color),
2433 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2434 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2435 void (*obj__printf)(void *obj, const char *fmt, ...),
2436 void (*obj__write_graph)(void *obj, int graph))
2437
2438{
2439 double percent_max = annotation_line__max_percent(al, notes);
2440 int pcnt_width = annotation__pcnt_width(notes),
2441 cycles_width = annotation__cycles_width(notes);
2442 bool show_title = false;
2443 char bf[256];
2444 int printed;
2445
2446 if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2447 if (notes->have_cycles) {
2448 if (al->ipc == 0.0 && al->cycles == 0)
2449 show_title = true;
2450 } else
2451 show_title = true;
2452 }
2453
2454 if (al->offset != -1 && percent_max != 0.0) {
2455 int i;
2456
2457 for (i = 0; i < notes->nr_events; i++) {
2458 obj__set_percent_color(obj, al->samples[i].percent, current_entry);
2459 if (notes->options->show_total_period) {
2460 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period);
2461 } else if (notes->options->show_nr_samples) {
2462 obj__printf(obj, "%6" PRIu64 " ",
2463 al->samples[i].he.nr_samples);
2464 } else {
2465 obj__printf(obj, "%6.2f ",
2466 al->samples[i].percent);
2467 }
2468 }
2469 } else {
2470 obj__set_percent_color(obj, 0, current_entry);
2471
2472 if (!show_title)
2473 obj__printf(obj, "%-*s", pcnt_width, " ");
2474 else {
2475 obj__printf(obj, "%-*s", pcnt_width,
2476 notes->options->show_total_period ? "Period" :
2477 notes->options->show_nr_samples ? "Samples" : "Percent");
2478 }
2479 }
2480
2481 if (notes->have_cycles) {
2482 if (al->ipc)
2483 obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
2484 else if (!show_title)
2485 obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
2486 else
2487 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2488
2489 if (al->cycles)
2490 obj__printf(obj, "%*" PRIu64 " ",
2491 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
2492 else if (!show_title)
2493 obj__printf(obj, "%*s", ANNOTATION__CYCLES_WIDTH, " ");
2494 else
2495 obj__printf(obj, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle");
2496 }
2497
2498 obj__printf(obj, " ");
2499
2500 if (!*al->line)
2501 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
2502 else if (al->offset == -1) {
2503 if (al->line_nr && notes->options->show_linenr)
2504 printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
2505 else
2506 printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " ");
2507 obj__printf(obj, bf);
2508 obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
2509 } else {
2510 u64 addr = al->offset;
2511 int color = -1;
2512
2513 if (!notes->options->use_offset)
2514 addr += notes->start;
2515
2516 if (!notes->options->use_offset) {
2517 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
2518 } else {
2519 if (al->jump_sources &&
2520 notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
2521 if (notes->options->show_nr_jumps) {
2522 int prev;
2523 printed = scnprintf(bf, sizeof(bf), "%*d ",
2524 notes->widths.jumps,
2525 al->jump_sources);
2526 prev = obj__set_jumps_percent_color(obj, al->jump_sources,
2527 current_entry);
2528 obj__printf(obj, bf);
2529 obj__set_color(obj, prev);
2530 }
2531print_addr:
2532 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
2533 notes->widths.target, addr);
2534 } else if (ins__is_call(&disasm_line(al)->ins) &&
2535 notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
2536 goto print_addr;
2537 } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
2538 goto print_addr;
2539 } else {
2540 printed = scnprintf(bf, sizeof(bf), "%-*s ",
2541 notes->widths.addr, " ");
2542 }
2543 }
2544
2545 if (change_color)
2546 color = obj__set_color(obj, HE_COLORSET_ADDR);
2547 obj__printf(obj, bf);
2548 if (change_color)
2549 obj__set_color(obj, color);
2550
2551 disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
2552
2553 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
2554 }
2555
2556}
2557
2558void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2559 struct annotation_write_ops *ops)
2560{
2561 __annotation_line__write(al, notes, ops->first_line, ops->current_entry,
2562 ops->change_color, ops->width, ops->obj,
2563 ops->set_color, ops->set_percent_color,
2564 ops->set_jumps_percent_color, ops->printf,
2565 ops->write_graph);
2566}
2567
2568int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
2569 struct annotation_options *options, struct arch **parch)
2570{
2571 struct annotation *notes = symbol__annotation(sym);
2572 size_t size = symbol__size(sym);
2573 int nr_pcnt = 1, err;
2574
2575 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
2576 if (notes->offsets == NULL)
2577 return -1;
2578
2579 if (perf_evsel__is_group_event(evsel))
2580 nr_pcnt = evsel->nr_members;
2581
2582 err = symbol__annotate(sym, map, evsel, 0, parch);
2583 if (err)
2584 goto out_free_offsets;
2585
2586 notes->options = options;
2587
2588 symbol__calc_percent(sym, evsel);
2589
2590 notes->start = map__rip_2objdump(map, sym->start);
2591
2592 annotation__set_offsets(notes, size);
2593 annotation__mark_jump_targets(notes, sym);
2594 annotation__compute_ipc(notes, size);
2595 annotation__init_column_widths(notes, sym);
2596 notes->nr_events = nr_pcnt;
2597
2598 annotation__update_column_widths(notes);
2599
2600 return 0;
2601
2602out_free_offsets:
2603 zfree(&notes->offsets);
2604 return -1;
2605}
2606
2607int __annotation__scnprintf_samples_period(struct annotation *notes,
2608 char *bf, size_t size,
2609 struct perf_evsel *evsel,
2610 bool show_freq)
2611{
2612 const char *ev_name = perf_evsel__name(evsel);
2613 char buf[1024], ref[30] = " show reference callgraph, ";
2614 char sample_freq_str[64] = "";
2615 unsigned long nr_samples = 0;
2616 int nr_members = 1;
2617 bool enable_ref = false;
2618 u64 nr_events = 0;
2619 char unit;
2620 int i;
2621
2622 if (perf_evsel__is_group_event(evsel)) {
2623 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2624 ev_name = buf;
2625 nr_members = evsel->nr_members;
2626 }
2627
2628 for (i = 0; i < nr_members; i++) {
2629 struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
2630
2631 nr_samples += ah->nr_samples;
2632 nr_events += ah->period;
2633 }
2634
2635 if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
2636 enable_ref = true;
2637
2638 if (show_freq)
2639 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2640
2641 nr_samples = convert_unit(nr_samples, &unit);
2642 return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2643 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2644 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2645}
2646
2647#define ANNOTATION__CFG(n) \
2648 { .name = #n, .value = &annotation__default_options.n, }
2649
2650/*
2651 * Keep the entries sorted, they are bsearch'ed
2652 */
2653static struct annotation_config {
2654 const char *name;
2655 void *value;
2656} annotation__configs[] = {
2657 ANNOTATION__CFG(hide_src_code),
2658 ANNOTATION__CFG(jump_arrows),
2659 ANNOTATION__CFG(offset_level),
2660 ANNOTATION__CFG(show_linenr),
2661 ANNOTATION__CFG(show_nr_jumps),
2662 ANNOTATION__CFG(show_nr_samples),
2663 ANNOTATION__CFG(show_total_period),
2664 ANNOTATION__CFG(use_offset),
2665};
2666
2667#undef ANNOTATION__CFG
2668
2669static int annotation_config__cmp(const void *name, const void *cfgp)
2670{
2671 const struct annotation_config *cfg = cfgp;
2672
2673 return strcmp(name, cfg->name);
2674}
2675
2676static int annotation__config(const char *var, const char *value,
2677 void *data __maybe_unused)
2678{
2679 struct annotation_config *cfg;
2680 const char *name;
2681
2682 if (!strstarts(var, "annotate."))
2683 return 0;
2684
2685 name = var + 9;
2686 cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2687 sizeof(struct annotation_config), annotation_config__cmp);
2688
2689 if (cfg == NULL)
2690 pr_debug("%s variable unknown, ignoring...", var);
2691 else if (strcmp(var, "annotate.offset_level") == 0) {
2692 perf_config_int(cfg->value, name, value);
2693
2694 if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL)
2695 *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL;
2696 else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL)
2697 *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL;
2698 } else {
2699 *(bool *)cfg->value = perf_config_bool(name, value);
2700 }
2701 return 0;
2702}
2703
2704void annotation_config__init(void)
2705{
2706 perf_config(annotation__config, NULL);
2707
2708 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2709 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2710}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index ce427445671f..f28a9e43421d 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -24,9 +24,11 @@ struct ins_operands {
24 struct { 24 struct {
25 char *raw; 25 char *raw;
26 char *name; 26 char *name;
27 struct symbol *sym;
27 u64 addr; 28 u64 addr;
28 s64 offset; 29 s64 offset;
29 bool offset_avail; 30 bool offset_avail;
31 bool outside;
30 } target; 32 } target;
31 union { 33 union {
32 struct { 34 struct {
@@ -45,7 +47,7 @@ struct arch;
45 47
46struct ins_ops { 48struct ins_ops {
47 void (*free)(struct ins_operands *ops); 49 void (*free)(struct ins_operands *ops);
48 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map *map); 50 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms);
49 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 51 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
50 struct ins_operands *ops); 52 struct ins_operands *ops);
51}; 53};
@@ -57,6 +59,30 @@ bool ins__is_lock(const struct ins *ins);
57int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 59int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
58bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 60bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
59 61
62#define ANNOTATION__IPC_WIDTH 6
63#define ANNOTATION__CYCLES_WIDTH 6
64
65struct annotation_options {
66 bool hide_src_code,
67 use_offset,
68 jump_arrows,
69 show_linenr,
70 show_nr_jumps,
71 show_nr_samples,
72 show_total_period;
73 u8 offset_level;
74};
75
76enum {
77 ANNOTATION__OFFSET_JUMP_TARGETS = 1,
78 ANNOTATION__OFFSET_CALL,
79 ANNOTATION__MAX_OFFSET_LEVEL,
80};
81
82#define ANNOTATION__MIN_OFFSET_LEVEL ANNOTATION__OFFSET_JUMP_TARGETS
83
84extern struct annotation_options annotation__default_options;
85
60struct annotation; 86struct annotation;
61 87
62struct sym_hist_entry { 88struct sym_hist_entry {
@@ -76,10 +102,13 @@ struct annotation_line {
76 s64 offset; 102 s64 offset;
77 char *line; 103 char *line;
78 int line_nr; 104 int line_nr;
105 int jump_sources;
79 float ipc; 106 float ipc;
80 u64 cycles; 107 u64 cycles;
81 size_t privsize; 108 size_t privsize;
82 char *path; 109 char *path;
110 u32 idx;
111 int idx_asm;
83 int samples_nr; 112 int samples_nr;
84 struct annotation_data samples[0]; 113 struct annotation_data samples[0];
85}; 114};
@@ -97,14 +126,52 @@ static inline struct disasm_line *disasm_line(struct annotation_line *al)
97 return al ? container_of(al, struct disasm_line, al) : NULL; 126 return al ? container_of(al, struct disasm_line, al) : NULL;
98} 127}
99 128
100static inline bool disasm_line__has_offset(const struct disasm_line *dl) 129/*
130 * Is this offset in the same function as the line it is used?
131 * asm functions jump to other functions, for instance.
132 */
133static inline bool disasm_line__has_local_offset(const struct disasm_line *dl)
101{ 134{
102 return dl->ops.target.offset_avail; 135 return dl->ops.target.offset_avail && !dl->ops.target.outside;
103} 136}
104 137
138/*
139 * Can we draw an arrow from the jump to its target, for instance? I.e.
140 * is the jump and its target in the same function?
141 */
142bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym);
143
105void disasm_line__free(struct disasm_line *dl); 144void disasm_line__free(struct disasm_line *dl);
106struct annotation_line * 145struct annotation_line *
107annotation_line__next(struct annotation_line *pos, struct list_head *head); 146annotation_line__next(struct annotation_line *pos, struct list_head *head);
147
148struct annotation_write_ops {
149 bool first_line, current_entry, change_color;
150 int width;
151 void *obj;
152 int (*set_color)(void *obj, int color);
153 void (*set_percent_color)(void *obj, double percent, bool current);
154 int (*set_jumps_percent_color)(void *obj, int nr, bool current);
155 void (*printf)(void *obj, const char *fmt, ...);
156 void (*write_graph)(void *obj, int graph);
157};
158
159double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes);
160void annotation_line__write(struct annotation_line *al, struct annotation *notes,
161 struct annotation_write_ops *ops);
162
163int __annotation__scnprintf_samples_period(struct annotation *notes,
164 char *bf, size_t size,
165 struct perf_evsel *evsel,
166 bool show_freq);
167
168static inline int annotation__scnprintf_samples_period(struct annotation *notes,
169 char *bf, size_t size,
170 struct perf_evsel *evsel)
171{
172 return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true);
173}
174
108int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 175int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
109size_t disasm__fprintf(struct list_head *head, FILE *fp); 176size_t disasm__fprintf(struct list_head *head, FILE *fp);
110void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 177void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
@@ -150,9 +217,47 @@ struct annotated_source {
150struct annotation { 217struct annotation {
151 pthread_mutex_t lock; 218 pthread_mutex_t lock;
152 u64 max_coverage; 219 u64 max_coverage;
220 u64 start;
221 struct annotation_options *options;
222 struct annotation_line **offsets;
223 int nr_events;
224 int nr_jumps;
225 int max_jump_sources;
226 int nr_entries;
227 int nr_asm_entries;
228 u16 max_line_len;
229 struct {
230 u8 addr;
231 u8 jumps;
232 u8 target;
233 u8 min_addr;
234 u8 max_addr;
235 } widths;
236 bool have_cycles;
153 struct annotated_source *src; 237 struct annotated_source *src;
154}; 238};
155 239
240static inline int annotation__cycles_width(struct annotation *notes)
241{
242 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
243}
244
245static inline int annotation__pcnt_width(struct annotation *notes)
246{
247 return (notes->options->show_total_period ? 12 : 7) * notes->nr_events;
248}
249
250static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
251{
252 return notes->options->hide_src_code && al->offset == -1;
253}
254
255void annotation__set_offsets(struct annotation *notes, s64 size);
256void annotation__compute_ipc(struct annotation *notes, size_t size);
257void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
258void annotation__update_column_widths(struct annotation *notes);
259void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
260
156static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 261static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
157{ 262{
158 return (((void *)&notes->src->histograms) + 263 return (((void *)&notes->src->histograms) +
@@ -180,6 +285,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
180int symbol__annotate(struct symbol *sym, struct map *map, 285int symbol__annotate(struct symbol *sym, struct map *map,
181 struct perf_evsel *evsel, size_t privsize, 286 struct perf_evsel *evsel, size_t privsize,
182 struct arch **parch); 287 struct arch **parch);
288int symbol__annotate2(struct symbol *sym, struct map *map,
289 struct perf_evsel *evsel,
290 struct annotation_options *options,
291 struct arch **parch);
183 292
184enum symbol_disassemble_errno { 293enum symbol_disassemble_errno {
185 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 294 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
@@ -204,16 +313,23 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
204int symbol__annotate_printf(struct symbol *sym, struct map *map, 313int symbol__annotate_printf(struct symbol *sym, struct map *map,
205 struct perf_evsel *evsel, bool full_paths, 314 struct perf_evsel *evsel, bool full_paths,
206 int min_pcnt, int max_lines, int context); 315 int min_pcnt, int max_lines, int context);
316int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
207void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 317void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
208void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 318void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
209void annotated_source__purge(struct annotated_source *as); 319void annotated_source__purge(struct annotated_source *as);
210 320
321int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel);
322
211bool ui__has_annotation(void); 323bool ui__has_annotation(void);
212 324
213int symbol__tty_annotate(struct symbol *sym, struct map *map, 325int symbol__tty_annotate(struct symbol *sym, struct map *map,
214 struct perf_evsel *evsel, bool print_lines, 326 struct perf_evsel *evsel, bool print_lines,
215 bool full_paths, int min_pcnt, int max_lines); 327 bool full_paths, int min_pcnt, int max_lines);
216 328
329int symbol__tty_annotate2(struct symbol *sym, struct map *map,
330 struct perf_evsel *evsel, bool print_lines,
331 bool full_paths);
332
217#ifdef HAVE_SLANG_SUPPORT 333#ifdef HAVE_SLANG_SUPPORT
218int symbol__tui_annotate(struct symbol *sym, struct map *map, 334int symbol__tui_annotate(struct symbol *sym, struct map *map,
219 struct perf_evsel *evsel, 335 struct perf_evsel *evsel,
@@ -231,4 +347,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
231 347
232extern const char *disassembler_style; 348extern const char *disassembler_style;
233 349
350void annotation_config__init(void);
351
234#endif /* __PERF_ANNOTATE_H */ 352#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 6470ea2aa25e..857de69a5361 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -233,9 +233,9 @@ static void *auxtrace_copy_data(u64 size, struct perf_session *session)
233 return p; 233 return p;
234} 234}
235 235
236static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, 236static int auxtrace_queues__queue_buffer(struct auxtrace_queues *queues,
237 unsigned int idx, 237 unsigned int idx,
238 struct auxtrace_buffer *buffer) 238 struct auxtrace_buffer *buffer)
239{ 239{
240 struct auxtrace_queue *queue; 240 struct auxtrace_queue *queue;
241 int err; 241 int err;
@@ -286,7 +286,7 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
286 return -ENOMEM; 286 return -ENOMEM;
287 b->size = BUFFER_LIMIT_FOR_32_BIT; 287 b->size = BUFFER_LIMIT_FOR_32_BIT;
288 b->consecutive = consecutive; 288 b->consecutive = consecutive;
289 err = auxtrace_queues__add_buffer(queues, idx, b); 289 err = auxtrace_queues__queue_buffer(queues, idx, b);
290 if (err) { 290 if (err) {
291 auxtrace_buffer__free(b); 291 auxtrace_buffer__free(b);
292 return err; 292 return err;
@@ -302,31 +302,6 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
302 return 0; 302 return 0;
303} 303}
304 304
305static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
306 struct perf_session *session,
307 unsigned int idx,
308 struct auxtrace_buffer *buffer)
309{
310 if (session->one_mmap) {
311 buffer->data = buffer->data_offset - session->one_mmap_offset +
312 session->one_mmap_addr;
313 } else if (perf_data__is_pipe(session->data)) {
314 buffer->data = auxtrace_copy_data(buffer->size, session);
315 if (!buffer->data)
316 return -ENOMEM;
317 buffer->data_needs_freeing = true;
318 } else if (BITS_PER_LONG == 32 &&
319 buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
320 int err;
321
322 err = auxtrace_queues__split_buffer(queues, idx, buffer);
323 if (err)
324 return err;
325 }
326
327 return auxtrace_queues__add_buffer(queues, idx, buffer);
328}
329
330static bool filter_cpu(struct perf_session *session, int cpu) 305static bool filter_cpu(struct perf_session *session, int cpu)
331{ 306{
332 unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; 307 unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap;
@@ -334,45 +309,71 @@ static bool filter_cpu(struct perf_session *session, int cpu)
334 return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); 309 return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap);
335} 310}
336 311
337int auxtrace_queues__add_event(struct auxtrace_queues *queues, 312static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
338 struct perf_session *session, 313 struct perf_session *session,
339 union perf_event *event, off_t data_offset, 314 unsigned int idx,
340 struct auxtrace_buffer **buffer_ptr) 315 struct auxtrace_buffer *buffer,
316 struct auxtrace_buffer **buffer_ptr)
341{ 317{
342 struct auxtrace_buffer *buffer; 318 int err = -ENOMEM;
343 unsigned int idx;
344 int err;
345 319
346 if (filter_cpu(session, event->auxtrace.cpu)) 320 if (filter_cpu(session, buffer->cpu))
347 return 0; 321 return 0;
348 322
349 buffer = zalloc(sizeof(struct auxtrace_buffer)); 323 buffer = memdup(buffer, sizeof(*buffer));
350 if (!buffer) 324 if (!buffer)
351 return -ENOMEM; 325 return -ENOMEM;
352 326
353 buffer->pid = -1; 327 if (session->one_mmap) {
354 buffer->tid = event->auxtrace.tid; 328 buffer->data = buffer->data_offset - session->one_mmap_offset +
355 buffer->cpu = event->auxtrace.cpu; 329 session->one_mmap_addr;
356 buffer->data_offset = data_offset; 330 } else if (perf_data__is_pipe(session->data)) {
357 buffer->offset = event->auxtrace.offset; 331 buffer->data = auxtrace_copy_data(buffer->size, session);
358 buffer->reference = event->auxtrace.reference; 332 if (!buffer->data)
359 buffer->size = event->auxtrace.size; 333 goto out_free;
360 idx = event->auxtrace.idx; 334 buffer->data_needs_freeing = true;
335 } else if (BITS_PER_LONG == 32 &&
336 buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
337 err = auxtrace_queues__split_buffer(queues, idx, buffer);
338 if (err)
339 goto out_free;
340 }
361 341
362 err = auxtrace_queues__add_event_buffer(queues, session, idx, buffer); 342 err = auxtrace_queues__queue_buffer(queues, idx, buffer);
363 if (err) 343 if (err)
364 goto out_err; 344 goto out_free;
365 345
346 /* FIXME: Doesn't work for split buffer */
366 if (buffer_ptr) 347 if (buffer_ptr)
367 *buffer_ptr = buffer; 348 *buffer_ptr = buffer;
368 349
369 return 0; 350 return 0;
370 351
371out_err: 352out_free:
372 auxtrace_buffer__free(buffer); 353 auxtrace_buffer__free(buffer);
373 return err; 354 return err;
374} 355}
375 356
357int auxtrace_queues__add_event(struct auxtrace_queues *queues,
358 struct perf_session *session,
359 union perf_event *event, off_t data_offset,
360 struct auxtrace_buffer **buffer_ptr)
361{
362 struct auxtrace_buffer buffer = {
363 .pid = -1,
364 .tid = event->auxtrace.tid,
365 .cpu = event->auxtrace.cpu,
366 .data_offset = data_offset,
367 .offset = event->auxtrace.offset,
368 .reference = event->auxtrace.reference,
369 .size = event->auxtrace.size,
370 };
371 unsigned int idx = event->auxtrace.idx;
372
373 return auxtrace_queues__add_buffer(queues, session, idx, &buffer,
374 buffer_ptr);
375}
376
376static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, 377static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
377 struct perf_session *session, 378 struct perf_session *session,
378 off_t file_offset, size_t sz) 379 off_t file_offset, size_t sz)
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 453c148d2158..e731f55da072 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -130,6 +130,7 @@ struct auxtrace_index {
130/** 130/**
131 * struct auxtrace - session callbacks to allow AUX area data decoding. 131 * struct auxtrace - session callbacks to allow AUX area data decoding.
132 * @process_event: lets the decoder see all session events 132 * @process_event: lets the decoder see all session events
133 * @process_auxtrace_event: process a PERF_RECORD_AUXTRACE event
133 * @flush_events: process any remaining data 134 * @flush_events: process any remaining data
134 * @free_events: free resources associated with event processing 135 * @free_events: free resources associated with event processing
135 * @free: free resources associated with the session 136 * @free: free resources associated with the session
@@ -301,6 +302,7 @@ struct auxtrace_mmap_params {
301 * @parse_snapshot_options: parse snapshot options 302 * @parse_snapshot_options: parse snapshot options
302 * @reference: provide a 64-bit reference number for auxtrace_event 303 * @reference: provide a 64-bit reference number for auxtrace_event
303 * @read_finish: called after reading from an auxtrace mmap 304 * @read_finish: called after reading from an auxtrace mmap
305 * @alignment: alignment (if any) for AUX area data
304 */ 306 */
305struct auxtrace_record { 307struct auxtrace_record {
306 int (*recording_options)(struct auxtrace_record *itr, 308 int (*recording_options)(struct auxtrace_record *itr,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 7f8553630c4d..537eadd81914 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -316,7 +316,6 @@ static int machine__write_buildid_table(struct machine *machine,
316 struct feat_fd *fd) 316 struct feat_fd *fd)
317{ 317{
318 int err = 0; 318 int err = 0;
319 char nm[PATH_MAX];
320 struct dso *pos; 319 struct dso *pos;
321 u16 kmisc = PERF_RECORD_MISC_KERNEL, 320 u16 kmisc = PERF_RECORD_MISC_KERNEL,
322 umisc = PERF_RECORD_MISC_USER; 321 umisc = PERF_RECORD_MISC_USER;
@@ -338,9 +337,8 @@ static int machine__write_buildid_table(struct machine *machine,
338 name = pos->short_name; 337 name = pos->short_name;
339 name_len = pos->short_name_len; 338 name_len = pos->short_name_len;
340 } else if (dso__is_kcore(pos)) { 339 } else if (dso__is_kcore(pos)) {
341 machine__mmap_name(machine, nm, sizeof(nm)); 340 name = machine->mmap_name;
342 name = nm; 341 name_len = strlen(name);
343 name_len = strlen(nm);
344 } else { 342 } else {
345 name = pos->long_name; 343 name = pos->long_name;
346 name_len = pos->long_name_len; 344 name_len = pos->long_name_len;
@@ -813,12 +811,10 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
813 bool is_kallsyms = dso__is_kallsyms(dso); 811 bool is_kallsyms = dso__is_kallsyms(dso);
814 bool is_vdso = dso__is_vdso(dso); 812 bool is_vdso = dso__is_vdso(dso);
815 const char *name = dso->long_name; 813 const char *name = dso->long_name;
816 char nm[PATH_MAX];
817 814
818 if (dso__is_kcore(dso)) { 815 if (dso__is_kcore(dso)) {
819 is_kallsyms = true; 816 is_kallsyms = true;
820 machine__mmap_name(machine, nm, sizeof(nm)); 817 name = machine->mmap_name;
821 name = nm;
822 } 818 }
823 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 819 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
824 dso->nsinfo, is_kallsyms, is_vdso); 820 dso->nsinfo, is_kallsyms, is_vdso);
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index a4014d786676..7b042a5ebc68 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -41,7 +41,7 @@ int test__clang_to_IR(void)
41 if (!M) 41 if (!M)
42 return -1; 42 return -1;
43 for (llvm::Function& F : *M) 43 for (llvm::Function& F : *M)
44 if (F.getName() == "bpf_func__SyS_epoll_wait") 44 if (F.getName() == "bpf_func__SyS_epoll_pwait")
45 return 0; 45 return 0;
46 return -1; 46 return -1;
47} 47}
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 1bfc946e37dc..bf31ceab33bd 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -9,6 +9,7 @@
9 * Copyright (C) 2016 Huawei Inc. 9 * Copyright (C) 2016 Huawei Inc.
10 */ 10 */
11 11
12#include "clang/Basic/Version.h"
12#include "clang/CodeGen/CodeGenAction.h" 13#include "clang/CodeGen/CodeGenAction.h"
13#include "clang/Frontend/CompilerInvocation.h" 14#include "clang/Frontend/CompilerInvocation.h"
14#include "clang/Frontend/CompilerInstance.h" 15#include "clang/Frontend/CompilerInstance.h"
@@ -58,7 +59,8 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
58 59
59 FrontendOptions& Opts = CI->getFrontendOpts(); 60 FrontendOptions& Opts = CI->getFrontendOpts();
60 Opts.Inputs.clear(); 61 Opts.Inputs.clear();
61 Opts.Inputs.emplace_back(Path, IK_C); 62 Opts.Inputs.emplace_back(Path,
63 FrontendOptions::getInputKindForExtension("c"));
62 return CI; 64 return CI;
63} 65}
64 66
@@ -71,10 +73,17 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
71 73
72 Clang.setVirtualFileSystem(&*VFS); 74 Clang.setVirtualFileSystem(&*VFS);
73 75
76#if CLANG_VERSION_MAJOR < 4
74 IntrusiveRefCntPtr<CompilerInvocation> CI = 77 IntrusiveRefCntPtr<CompilerInvocation> CI =
75 createCompilerInvocation(std::move(CFlags), Path, 78 createCompilerInvocation(std::move(CFlags), Path,
76 Clang.getDiagnostics()); 79 Clang.getDiagnostics());
77 Clang.setInvocation(&*CI); 80 Clang.setInvocation(&*CI);
81#else
82 std::shared_ptr<CompilerInvocation> CI(
83 createCompilerInvocation(std::move(CFlags), Path,
84 Clang.getDiagnostics()));
85 Clang.setInvocation(CI);
86#endif
78 87
79 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx)); 88 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
80 if (!Clang.ExecuteAction(*Act)) 89 if (!Clang.ExecuteAction(*Act))
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 984f69144f87..decb91f9da82 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -71,7 +71,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
71 return -1; 71 return -1;
72} 72}
73 73
74static int open_cgroup(char *name) 74static int open_cgroup(const char *name)
75{ 75{
76 char path[PATH_MAX + 1]; 76 char path[PATH_MAX + 1];
77 char mnt[PATH_MAX + 1]; 77 char mnt[PATH_MAX + 1];
@@ -81,7 +81,7 @@ static int open_cgroup(char *name)
81 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1)) 81 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
82 return -1; 82 return -1;
83 83
84 snprintf(path, PATH_MAX, "%s/%s", mnt, name); 84 scnprintf(path, PATH_MAX, "%s/%s", mnt, name);
85 85
86 fd = open(path, O_RDONLY); 86 fd = open(path, O_RDONLY);
87 if (fd == -1) 87 if (fd == -1)
@@ -90,41 +90,64 @@ static int open_cgroup(char *name)
90 return fd; 90 return fd;
91} 91}
92 92
93static int add_cgroup(struct perf_evlist *evlist, char *str) 93static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str)
94{ 94{
95 struct perf_evsel *counter; 95 struct perf_evsel *counter;
96 struct cgroup_sel *cgrp = NULL; 96 struct cgroup *cgrp = NULL;
97 int n;
98 /* 97 /*
99 * check if cgrp is already defined, if so we reuse it 98 * check if cgrp is already defined, if so we reuse it
100 */ 99 */
101 evlist__for_each_entry(evlist, counter) { 100 evlist__for_each_entry(evlist, counter) {
102 cgrp = counter->cgrp; 101 if (!counter->cgrp)
103 if (!cgrp)
104 continue; 102 continue;
105 if (!strcmp(cgrp->name, str)) { 103 if (!strcmp(counter->cgrp->name, str)) {
106 refcount_inc(&cgrp->refcnt); 104 cgrp = cgroup__get(counter->cgrp);
107 break; 105 break;
108 } 106 }
109
110 cgrp = NULL;
111 } 107 }
112 108
113 if (!cgrp) { 109 return cgrp;
114 cgrp = zalloc(sizeof(*cgrp)); 110}
115 if (!cgrp)
116 return -1;
117 111
118 cgrp->name = str; 112static struct cgroup *cgroup__new(const char *name)
119 refcount_set(&cgrp->refcnt, 1); 113{
114 struct cgroup *cgroup = zalloc(sizeof(*cgroup));
120 115
121 cgrp->fd = open_cgroup(str); 116 if (cgroup != NULL) {
122 if (cgrp->fd == -1) { 117 refcount_set(&cgroup->refcnt, 1);
123 free(cgrp); 118
124 return -1; 119 cgroup->name = strdup(name);
125 } 120 if (!cgroup->name)
121 goto out_err;
122 cgroup->fd = open_cgroup(name);
123 if (cgroup->fd == -1)
124 goto out_free_name;
126 } 125 }
127 126
127 return cgroup;
128
129out_free_name:
130 free(cgroup->name);
131out_err:
132 free(cgroup);
133 return NULL;
134}
135
136struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name)
137{
138 struct cgroup *cgroup = evlist__find_cgroup(evlist, name);
139
140 return cgroup ?: cgroup__new(name);
141}
142
143static int add_cgroup(struct perf_evlist *evlist, const char *str)
144{
145 struct perf_evsel *counter;
146 struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str);
147 int n;
148
149 if (!cgrp)
150 return -1;
128 /* 151 /*
129 * find corresponding event 152 * find corresponding event
130 * if add cgroup N, then need to find event N 153 * if add cgroup N, then need to find event N
@@ -135,31 +158,58 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
135 goto found; 158 goto found;
136 n++; 159 n++;
137 } 160 }
138 if (refcount_dec_and_test(&cgrp->refcnt))
139 free(cgrp);
140 161
162 cgroup__put(cgrp);
141 return -1; 163 return -1;
142found: 164found:
143 counter->cgrp = cgrp; 165 counter->cgrp = cgrp;
144 return 0; 166 return 0;
145} 167}
146 168
147void close_cgroup(struct cgroup_sel *cgrp) 169static void cgroup__delete(struct cgroup *cgroup)
170{
171 close(cgroup->fd);
172 zfree(&cgroup->name);
173 free(cgroup);
174}
175
176void cgroup__put(struct cgroup *cgrp)
148{ 177{
149 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) { 178 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) {
150 close(cgrp->fd); 179 cgroup__delete(cgrp);
151 zfree(&cgrp->name);
152 free(cgrp);
153 } 180 }
154} 181}
155 182
156int parse_cgroups(const struct option *opt __maybe_unused, const char *str, 183struct cgroup *cgroup__get(struct cgroup *cgroup)
184{
185 if (cgroup)
186 refcount_inc(&cgroup->refcnt);
187 return cgroup;
188}
189
190static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *cgroup)
191{
192 if (evsel->cgrp == NULL)
193 evsel->cgrp = cgroup__get(cgroup);
194}
195
196void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup)
197{
198 struct perf_evsel *evsel;
199
200 evlist__for_each_entry(evlist, evsel)
201 evsel__set_default_cgroup(evsel, cgroup);
202}
203
204int parse_cgroups(const struct option *opt, const char *str,
157 int unset __maybe_unused) 205 int unset __maybe_unused)
158{ 206{
159 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 207 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
208 struct perf_evsel *counter;
209 struct cgroup *cgrp = NULL;
160 const char *p, *e, *eos = str + strlen(str); 210 const char *p, *e, *eos = str + strlen(str);
161 char *s; 211 char *s;
162 int ret; 212 int ret, i;
163 213
164 if (list_empty(&evlist->entries)) { 214 if (list_empty(&evlist->entries)) {
165 fprintf(stderr, "must define events before cgroups\n"); 215 fprintf(stderr, "must define events before cgroups\n");
@@ -177,10 +227,9 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
177 if (!s) 227 if (!s)
178 return -1; 228 return -1;
179 ret = add_cgroup(evlist, s); 229 ret = add_cgroup(evlist, s);
180 if (ret) { 230 free(s);
181 free(s); 231 if (ret)
182 return -1; 232 return -1;
183 }
184 } 233 }
185 /* nr_cgroups is increased een for empty cgroups */ 234 /* nr_cgroups is increased een for empty cgroups */
186 nr_cgroups++; 235 nr_cgroups++;
@@ -188,5 +237,18 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
188 break; 237 break;
189 str = p+1; 238 str = p+1;
190 } 239 }
240 /* for the case one cgroup combine to multiple events */
241 i = 0;
242 if (nr_cgroups == 1) {
243 evlist__for_each_entry(evlist, counter) {
244 if (i == 0)
245 cgrp = counter->cgrp;
246 else {
247 counter->cgrp = cgrp;
248 refcount_inc(&cgrp->refcnt);
249 }
250 i++;
251 }
252 }
191 return 0; 253 return 0;
192} 254}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index afafc87e9201..f033a80c1b14 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -6,7 +6,7 @@
6 6
7struct option; 7struct option;
8 8
9struct cgroup_sel { 9struct cgroup {
10 char *name; 10 char *name;
11 int fd; 11 int fd;
12 refcount_t refcnt; 12 refcount_t refcnt;
@@ -14,7 +14,16 @@ struct cgroup_sel {
14 14
15 15
16extern int nr_cgroups; /* number of explicit cgroups defined */ 16extern int nr_cgroups; /* number of explicit cgroups defined */
17void close_cgroup(struct cgroup_sel *cgrp); 17
18struct cgroup *cgroup__get(struct cgroup *cgroup);
19void cgroup__put(struct cgroup *cgroup);
20
21struct perf_evlist;
22
23struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name);
24
25void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup);
26
18int parse_cgroups(const struct option *opt, const char *str, int unset); 27int parse_cgroups(const struct option *opt, const char *str, int unset);
19 28
20#endif /* __CGROUP_H__ */ 29#endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index 1fb01849f1c7..c8b98fa22997 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -1,6 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * SPDX-License-Identifier: GPL-2.0
3 *
4 * Copyright(C) 2015-2018 Linaro Limited. 3 * Copyright(C) 2015-2018 Linaro Limited.
5 * 4 *
6 * Author: Tor Jeremiassen <tor@ti.com> 5 * Author: Tor Jeremiassen <tor@ti.com>
@@ -78,6 +77,8 @@ int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
78{ 77{
79 ocsd_datapath_resp_t dp_ret; 78 ocsd_datapath_resp_t dp_ret;
80 79
80 decoder->prev_return = OCSD_RESP_CONT;
81
81 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET, 82 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET,
82 0, 0, NULL, NULL); 83 0, 0, NULL, NULL);
83 if (OCSD_DATA_RESP_IS_FATAL(dp_ret)) 84 if (OCSD_DATA_RESP_IS_FATAL(dp_ret))
@@ -253,16 +254,16 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
253 decoder->packet_count = 0; 254 decoder->packet_count = 0;
254 for (i = 0; i < MAX_BUFFER; i++) { 255 for (i = 0; i < MAX_BUFFER; i++) {
255 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL; 256 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
256 decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL; 257 decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL;
257 decoder->packet_buffer[i].exc = false; 258 decoder->packet_buffer[i].last_instr_taken_branch = false;
258 decoder->packet_buffer[i].exc_ret = false; 259 decoder->packet_buffer[i].exc = false;
259 decoder->packet_buffer[i].cpu = INT_MIN; 260 decoder->packet_buffer[i].exc_ret = false;
261 decoder->packet_buffer[i].cpu = INT_MIN;
260 } 262 }
261} 263}
262 264
263static ocsd_datapath_resp_t 265static ocsd_datapath_resp_t
264cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, 266cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
265 const ocsd_generic_trace_elem *elem,
266 const u8 trace_chan_id, 267 const u8 trace_chan_id,
267 enum cs_etm_sample_type sample_type) 268 enum cs_etm_sample_type sample_type)
268{ 269{
@@ -278,18 +279,16 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
278 return OCSD_RESP_FATAL_SYS_ERR; 279 return OCSD_RESP_FATAL_SYS_ERR;
279 280
280 et = decoder->tail; 281 et = decoder->tail;
282 et = (et + 1) & (MAX_BUFFER - 1);
283 decoder->tail = et;
284 decoder->packet_count++;
285
281 decoder->packet_buffer[et].sample_type = sample_type; 286 decoder->packet_buffer[et].sample_type = sample_type;
282 decoder->packet_buffer[et].start_addr = elem->st_addr;
283 decoder->packet_buffer[et].end_addr = elem->en_addr;
284 decoder->packet_buffer[et].exc = false; 287 decoder->packet_buffer[et].exc = false;
285 decoder->packet_buffer[et].exc_ret = false; 288 decoder->packet_buffer[et].exc_ret = false;
286 decoder->packet_buffer[et].cpu = *((int *)inode->priv); 289 decoder->packet_buffer[et].cpu = *((int *)inode->priv);
287 290 decoder->packet_buffer[et].start_addr = 0xdeadbeefdeadbeefUL;
288 /* Wrap around if need be */ 291 decoder->packet_buffer[et].end_addr = 0xdeadbeefdeadbeefUL;
289 et = (et + 1) & (MAX_BUFFER - 1);
290
291 decoder->tail = et;
292 decoder->packet_count++;
293 292
294 if (decoder->packet_count == MAX_BUFFER - 1) 293 if (decoder->packet_count == MAX_BUFFER - 1)
295 return OCSD_RESP_WAIT; 294 return OCSD_RESP_WAIT;
@@ -297,6 +296,47 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
297 return OCSD_RESP_CONT; 296 return OCSD_RESP_CONT;
298} 297}
299 298
299static ocsd_datapath_resp_t
300cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder,
301 const ocsd_generic_trace_elem *elem,
302 const uint8_t trace_chan_id)
303{
304 int ret = 0;
305 struct cs_etm_packet *packet;
306
307 ret = cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
308 CS_ETM_RANGE);
309 if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
310 return ret;
311
312 packet = &decoder->packet_buffer[decoder->tail];
313
314 packet->start_addr = elem->st_addr;
315 packet->end_addr = elem->en_addr;
316 switch (elem->last_i_type) {
317 case OCSD_INSTR_BR:
318 case OCSD_INSTR_BR_INDIRECT:
319 packet->last_instr_taken_branch = elem->last_instr_exec;
320 break;
321 case OCSD_INSTR_ISB:
322 case OCSD_INSTR_DSB_DMB:
323 case OCSD_INSTR_OTHER:
324 default:
325 packet->last_instr_taken_branch = false;
326 break;
327 }
328
329 return ret;
330}
331
332static ocsd_datapath_resp_t
333cs_etm_decoder__buffer_trace_on(struct cs_etm_decoder *decoder,
334 const uint8_t trace_chan_id)
335{
336 return cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
337 CS_ETM_TRACE_ON);
338}
339
300static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( 340static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
301 const void *context, 341 const void *context,
302 const ocsd_trc_index_t indx __maybe_unused, 342 const ocsd_trc_index_t indx __maybe_unused,
@@ -313,12 +353,13 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
313 decoder->trace_on = false; 353 decoder->trace_on = false;
314 break; 354 break;
315 case OCSD_GEN_TRC_ELEM_TRACE_ON: 355 case OCSD_GEN_TRC_ELEM_TRACE_ON:
356 resp = cs_etm_decoder__buffer_trace_on(decoder,
357 trace_chan_id);
316 decoder->trace_on = true; 358 decoder->trace_on = true;
317 break; 359 break;
318 case OCSD_GEN_TRC_ELEM_INSTR_RANGE: 360 case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
319 resp = cs_etm_decoder__buffer_packet(decoder, elem, 361 resp = cs_etm_decoder__buffer_range(decoder, elem,
320 trace_chan_id, 362 trace_chan_id);
321 CS_ETM_RANGE);
322 break; 363 break;
323 case OCSD_GEN_TRC_ELEM_EXCEPTION: 364 case OCSD_GEN_TRC_ELEM_EXCEPTION:
324 decoder->packet_buffer[decoder->tail].exc = true; 365 decoder->packet_buffer[decoder->tail].exc = true;
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
index 3d2e6205d186..743f5f444304 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -24,12 +24,14 @@ struct cs_etm_buffer {
24 24
25enum cs_etm_sample_type { 25enum cs_etm_sample_type {
26 CS_ETM_RANGE = 1 << 0, 26 CS_ETM_RANGE = 1 << 0,
27 CS_ETM_TRACE_ON = 1 << 1,
27}; 28};
28 29
29struct cs_etm_packet { 30struct cs_etm_packet {
30 enum cs_etm_sample_type sample_type; 31 enum cs_etm_sample_type sample_type;
31 u64 start_addr; 32 u64 start_addr;
32 u64 end_addr; 33 u64 end_addr;
34 u8 last_instr_taken_branch;
33 u8 exc; 35 u8 exc;
34 u8 exc_ret; 36 u8 exc_ret;
35 int cpu; 37 int cpu;
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index b9f0a53dfa65..bf16dc9ee507 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -1,6 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * SPDX-License-Identifier: GPL-2.0
3 *
4 * Copyright(C) 2015-2018 Linaro Limited. 3 * Copyright(C) 2015-2018 Linaro Limited.
5 * 4 *
6 * Author: Tor Jeremiassen <tor@ti.com> 5 * Author: Tor Jeremiassen <tor@ti.com>
@@ -32,6 +31,14 @@
32 31
33#define MAX_TIMESTAMP (~0ULL) 32#define MAX_TIMESTAMP (~0ULL)
34 33
34/*
35 * A64 instructions are always 4 bytes
36 *
37 * Only A64 is supported, so can use this constant for converting between
38 * addresses and instruction counts, calculting offsets etc
39 */
40#define A64_INSTR_SIZE 4
41
35struct cs_etm_auxtrace { 42struct cs_etm_auxtrace {
36 struct auxtrace auxtrace; 43 struct auxtrace auxtrace;
37 struct auxtrace_queues queues; 44 struct auxtrace_queues queues;
@@ -45,11 +52,15 @@ struct cs_etm_auxtrace {
45 u8 snapshot_mode; 52 u8 snapshot_mode;
46 u8 data_queued; 53 u8 data_queued;
47 u8 sample_branches; 54 u8 sample_branches;
55 u8 sample_instructions;
48 56
49 int num_cpu; 57 int num_cpu;
50 u32 auxtrace_type; 58 u32 auxtrace_type;
51 u64 branches_sample_type; 59 u64 branches_sample_type;
52 u64 branches_id; 60 u64 branches_id;
61 u64 instructions_sample_type;
62 u64 instructions_sample_period;
63 u64 instructions_id;
53 u64 **metadata; 64 u64 **metadata;
54 u64 kernel_start; 65 u64 kernel_start;
55 unsigned int pmu_type; 66 unsigned int pmu_type;
@@ -68,6 +79,12 @@ struct cs_etm_queue {
68 u64 time; 79 u64 time;
69 u64 timestamp; 80 u64 timestamp;
70 u64 offset; 81 u64 offset;
82 u64 period_instructions;
83 struct branch_stack *last_branch;
84 struct branch_stack *last_branch_rb;
85 size_t last_branch_pos;
86 struct cs_etm_packet *prev_packet;
87 struct cs_etm_packet *packet;
71}; 88};
72 89
73static int cs_etm__update_queues(struct cs_etm_auxtrace *etm); 90static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
@@ -174,6 +191,16 @@ static void cs_etm__free_queue(void *priv)
174{ 191{
175 struct cs_etm_queue *etmq = priv; 192 struct cs_etm_queue *etmq = priv;
176 193
194 if (!etmq)
195 return;
196
197 thread__zput(etmq->thread);
198 cs_etm_decoder__free(etmq->decoder);
199 zfree(&etmq->event_buf);
200 zfree(&etmq->last_branch);
201 zfree(&etmq->last_branch_rb);
202 zfree(&etmq->prev_packet);
203 zfree(&etmq->packet);
177 free(etmq); 204 free(etmq);
178} 205}
179 206
@@ -212,6 +239,7 @@ static void cs_etm__free(struct perf_session *session)
212 for (i = 0; i < aux->num_cpu; i++) 239 for (i = 0; i < aux->num_cpu; i++)
213 zfree(&aux->metadata[i]); 240 zfree(&aux->metadata[i]);
214 241
242 thread__zput(aux->unknown_thread);
215 zfree(&aux->metadata); 243 zfree(&aux->metadata);
216 zfree(&aux); 244 zfree(&aux);
217} 245}
@@ -270,11 +298,35 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
270 struct cs_etm_decoder_params d_params; 298 struct cs_etm_decoder_params d_params;
271 struct cs_etm_trace_params *t_params; 299 struct cs_etm_trace_params *t_params;
272 struct cs_etm_queue *etmq; 300 struct cs_etm_queue *etmq;
301 size_t szp = sizeof(struct cs_etm_packet);
273 302
274 etmq = zalloc(sizeof(*etmq)); 303 etmq = zalloc(sizeof(*etmq));
275 if (!etmq) 304 if (!etmq)
276 return NULL; 305 return NULL;
277 306
307 etmq->packet = zalloc(szp);
308 if (!etmq->packet)
309 goto out_free;
310
311 if (etm->synth_opts.last_branch || etm->sample_branches) {
312 etmq->prev_packet = zalloc(szp);
313 if (!etmq->prev_packet)
314 goto out_free;
315 }
316
317 if (etm->synth_opts.last_branch) {
318 size_t sz = sizeof(struct branch_stack);
319
320 sz += etm->synth_opts.last_branch_sz *
321 sizeof(struct branch_entry);
322 etmq->last_branch = zalloc(sz);
323 if (!etmq->last_branch)
324 goto out_free;
325 etmq->last_branch_rb = zalloc(sz);
326 if (!etmq->last_branch_rb)
327 goto out_free;
328 }
329
278 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); 330 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
279 if (!etmq->event_buf) 331 if (!etmq->event_buf)
280 goto out_free; 332 goto out_free;
@@ -329,6 +381,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
329 goto out_free_decoder; 381 goto out_free_decoder;
330 382
331 etmq->offset = 0; 383 etmq->offset = 0;
384 etmq->period_instructions = 0;
332 385
333 return etmq; 386 return etmq;
334 387
@@ -336,6 +389,10 @@ out_free_decoder:
336 cs_etm_decoder__free(etmq->decoder); 389 cs_etm_decoder__free(etmq->decoder);
337out_free: 390out_free:
338 zfree(&etmq->event_buf); 391 zfree(&etmq->event_buf);
392 zfree(&etmq->last_branch);
393 zfree(&etmq->last_branch_rb);
394 zfree(&etmq->prev_packet);
395 zfree(&etmq->packet);
339 free(etmq); 396 free(etmq);
340 397
341 return NULL; 398 return NULL;
@@ -389,6 +446,129 @@ static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
389 return 0; 446 return 0;
390} 447}
391 448
449static inline void cs_etm__copy_last_branch_rb(struct cs_etm_queue *etmq)
450{
451 struct branch_stack *bs_src = etmq->last_branch_rb;
452 struct branch_stack *bs_dst = etmq->last_branch;
453 size_t nr = 0;
454
455 /*
456 * Set the number of records before early exit: ->nr is used to
457 * determine how many branches to copy from ->entries.
458 */
459 bs_dst->nr = bs_src->nr;
460
461 /*
462 * Early exit when there is nothing to copy.
463 */
464 if (!bs_src->nr)
465 return;
466
467 /*
468 * As bs_src->entries is a circular buffer, we need to copy from it in
469 * two steps. First, copy the branches from the most recently inserted
470 * branch ->last_branch_pos until the end of bs_src->entries buffer.
471 */
472 nr = etmq->etm->synth_opts.last_branch_sz - etmq->last_branch_pos;
473 memcpy(&bs_dst->entries[0],
474 &bs_src->entries[etmq->last_branch_pos],
475 sizeof(struct branch_entry) * nr);
476
477 /*
478 * If we wrapped around at least once, the branches from the beginning
479 * of the bs_src->entries buffer and until the ->last_branch_pos element
480 * are older valid branches: copy them over. The total number of
481 * branches copied over will be equal to the number of branches asked by
482 * the user in last_branch_sz.
483 */
484 if (bs_src->nr >= etmq->etm->synth_opts.last_branch_sz) {
485 memcpy(&bs_dst->entries[nr],
486 &bs_src->entries[0],
487 sizeof(struct branch_entry) * etmq->last_branch_pos);
488 }
489}
490
491static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
492{
493 etmq->last_branch_pos = 0;
494 etmq->last_branch_rb->nr = 0;
495}
496
497static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
498{
499 /*
500 * The packet records the execution range with an exclusive end address
501 *
502 * A64 instructions are constant size, so the last executed
503 * instruction is A64_INSTR_SIZE before the end address
504 * Will need to do instruction level decode for T32 instructions as
505 * they can be variable size (not yet supported).
506 */
507 return packet->end_addr - A64_INSTR_SIZE;
508}
509
510static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
511{
512 /*
513 * Only A64 instructions are currently supported, so can get
514 * instruction count by dividing.
515 * Will need to do instruction level decode for T32 instructions as
516 * they can be variable size (not yet supported).
517 */
518 return (packet->end_addr - packet->start_addr) / A64_INSTR_SIZE;
519}
520
521static inline u64 cs_etm__instr_addr(const struct cs_etm_packet *packet,
522 u64 offset)
523{
524 /*
525 * Only A64 instructions are currently supported, so can get
526 * instruction address by muliplying.
527 * Will need to do instruction level decode for T32 instructions as
528 * they can be variable size (not yet supported).
529 */
530 return packet->start_addr + offset * A64_INSTR_SIZE;
531}
532
533static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
534{
535 struct branch_stack *bs = etmq->last_branch_rb;
536 struct branch_entry *be;
537
538 /*
539 * The branches are recorded in a circular buffer in reverse
540 * chronological order: we start recording from the last element of the
541 * buffer down. After writing the first element of the stack, move the
542 * insert position back to the end of the buffer.
543 */
544 if (!etmq->last_branch_pos)
545 etmq->last_branch_pos = etmq->etm->synth_opts.last_branch_sz;
546
547 etmq->last_branch_pos -= 1;
548
549 be = &bs->entries[etmq->last_branch_pos];
550 be->from = cs_etm__last_executed_instr(etmq->prev_packet);
551 be->to = etmq->packet->start_addr;
552 /* No support for mispredict */
553 be->flags.mispred = 0;
554 be->flags.predicted = 1;
555
556 /*
557 * Increment bs->nr until reaching the number of last branches asked by
558 * the user on the command line.
559 */
560 if (bs->nr < etmq->etm->synth_opts.last_branch_sz)
561 bs->nr += 1;
562}
563
564static int cs_etm__inject_event(union perf_event *event,
565 struct perf_sample *sample, u64 type)
566{
567 event->header.size = perf_event__sample_event_size(sample, type, 0);
568 return perf_event__synthesize_sample(event, type, 0, sample);
569}
570
571
392static int 572static int
393cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq) 573cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
394{ 574{
@@ -433,8 +613,8 @@ cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
433 return buff->len; 613 return buff->len;
434} 614}
435 615
436static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm, 616static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
437 struct auxtrace_queue *queue) 617 struct auxtrace_queue *queue)
438{ 618{
439 struct cs_etm_queue *etmq = queue->priv; 619 struct cs_etm_queue *etmq = queue->priv;
440 620
@@ -453,35 +633,105 @@ static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
453 } 633 }
454} 634}
455 635
636static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
637 u64 addr, u64 period)
638{
639 int ret = 0;
640 struct cs_etm_auxtrace *etm = etmq->etm;
641 union perf_event *event = etmq->event_buf;
642 struct perf_sample sample = {.ip = 0,};
643
644 event->sample.header.type = PERF_RECORD_SAMPLE;
645 event->sample.header.misc = PERF_RECORD_MISC_USER;
646 event->sample.header.size = sizeof(struct perf_event_header);
647
648 sample.ip = addr;
649 sample.pid = etmq->pid;
650 sample.tid = etmq->tid;
651 sample.id = etmq->etm->instructions_id;
652 sample.stream_id = etmq->etm->instructions_id;
653 sample.period = period;
654 sample.cpu = etmq->packet->cpu;
655 sample.flags = 0;
656 sample.insn_len = 1;
657 sample.cpumode = event->header.misc;
658
659 if (etm->synth_opts.last_branch) {
660 cs_etm__copy_last_branch_rb(etmq);
661 sample.branch_stack = etmq->last_branch;
662 }
663
664 if (etm->synth_opts.inject) {
665 ret = cs_etm__inject_event(event, &sample,
666 etm->instructions_sample_type);
667 if (ret)
668 return ret;
669 }
670
671 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
672
673 if (ret)
674 pr_err(
675 "CS ETM Trace: failed to deliver instruction event, error %d\n",
676 ret);
677
678 if (etm->synth_opts.last_branch)
679 cs_etm__reset_last_branch_rb(etmq);
680
681 return ret;
682}
683
456/* 684/*
457 * The cs etm packet encodes an instruction range between a branch target 685 * The cs etm packet encodes an instruction range between a branch target
458 * and the next taken branch. Generate sample accordingly. 686 * and the next taken branch. Generate sample accordingly.
459 */ 687 */
460static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, 688static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
461 struct cs_etm_packet *packet)
462{ 689{
463 int ret = 0; 690 int ret = 0;
464 struct cs_etm_auxtrace *etm = etmq->etm; 691 struct cs_etm_auxtrace *etm = etmq->etm;
465 struct perf_sample sample = {.ip = 0,}; 692 struct perf_sample sample = {.ip = 0,};
466 union perf_event *event = etmq->event_buf; 693 union perf_event *event = etmq->event_buf;
467 u64 start_addr = packet->start_addr; 694 struct dummy_branch_stack {
468 u64 end_addr = packet->end_addr; 695 u64 nr;
696 struct branch_entry entries;
697 } dummy_bs;
469 698
470 event->sample.header.type = PERF_RECORD_SAMPLE; 699 event->sample.header.type = PERF_RECORD_SAMPLE;
471 event->sample.header.misc = PERF_RECORD_MISC_USER; 700 event->sample.header.misc = PERF_RECORD_MISC_USER;
472 event->sample.header.size = sizeof(struct perf_event_header); 701 event->sample.header.size = sizeof(struct perf_event_header);
473 702
474 sample.ip = start_addr; 703 sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
475 sample.pid = etmq->pid; 704 sample.pid = etmq->pid;
476 sample.tid = etmq->tid; 705 sample.tid = etmq->tid;
477 sample.addr = end_addr; 706 sample.addr = etmq->packet->start_addr;
478 sample.id = etmq->etm->branches_id; 707 sample.id = etmq->etm->branches_id;
479 sample.stream_id = etmq->etm->branches_id; 708 sample.stream_id = etmq->etm->branches_id;
480 sample.period = 1; 709 sample.period = 1;
481 sample.cpu = packet->cpu; 710 sample.cpu = etmq->packet->cpu;
482 sample.flags = 0; 711 sample.flags = 0;
483 sample.cpumode = PERF_RECORD_MISC_USER; 712 sample.cpumode = PERF_RECORD_MISC_USER;
484 713
714 /*
715 * perf report cannot handle events without a branch stack
716 */
717 if (etm->synth_opts.last_branch) {
718 dummy_bs = (struct dummy_branch_stack){
719 .nr = 1,
720 .entries = {
721 .from = sample.ip,
722 .to = sample.addr,
723 },
724 };
725 sample.branch_stack = (struct branch_stack *)&dummy_bs;
726 }
727
728 if (etm->synth_opts.inject) {
729 ret = cs_etm__inject_event(event, &sample,
730 etm->branches_sample_type);
731 if (ret)
732 return ret;
733 }
734
485 ret = perf_session__deliver_synth_event(etm->session, event, &sample); 735 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
486 736
487 if (ret) 737 if (ret)
@@ -578,6 +828,24 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
578 etm->sample_branches = true; 828 etm->sample_branches = true;
579 etm->branches_sample_type = attr.sample_type; 829 etm->branches_sample_type = attr.sample_type;
580 etm->branches_id = id; 830 etm->branches_id = id;
831 id += 1;
832 attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
833 }
834
835 if (etm->synth_opts.last_branch)
836 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
837
838 if (etm->synth_opts.instructions) {
839 attr.config = PERF_COUNT_HW_INSTRUCTIONS;
840 attr.sample_period = etm->synth_opts.period;
841 etm->instructions_sample_period = attr.sample_period;
842 err = cs_etm__synth_event(session, &attr, id);
843 if (err)
844 return err;
845 etm->sample_instructions = true;
846 etm->instructions_sample_type = attr.sample_type;
847 etm->instructions_id = id;
848 id += 1;
581 } 849 }
582 850
583 return 0; 851 return 0;
@@ -585,25 +853,108 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
585 853
586static int cs_etm__sample(struct cs_etm_queue *etmq) 854static int cs_etm__sample(struct cs_etm_queue *etmq)
587{ 855{
856 struct cs_etm_auxtrace *etm = etmq->etm;
857 struct cs_etm_packet *tmp;
588 int ret; 858 int ret;
589 struct cs_etm_packet packet; 859 u64 instrs_executed;
590 860
591 while (1) { 861 instrs_executed = cs_etm__instr_count(etmq->packet);
592 ret = cs_etm_decoder__get_packet(etmq->decoder, &packet); 862 etmq->period_instructions += instrs_executed;
593 if (ret <= 0) 863
864 /*
865 * Record a branch when the last instruction in
866 * PREV_PACKET is a branch.
867 */
868 if (etm->synth_opts.last_branch &&
869 etmq->prev_packet &&
870 etmq->prev_packet->sample_type == CS_ETM_RANGE &&
871 etmq->prev_packet->last_instr_taken_branch)
872 cs_etm__update_last_branch_rb(etmq);
873
874 if (etm->sample_instructions &&
875 etmq->period_instructions >= etm->instructions_sample_period) {
876 /*
877 * Emit instruction sample periodically
878 * TODO: allow period to be defined in cycles and clock time
879 */
880
881 /* Get number of instructions executed after the sample point */
882 u64 instrs_over = etmq->period_instructions -
883 etm->instructions_sample_period;
884
885 /*
886 * Calculate the address of the sampled instruction (-1 as
887 * sample is reported as though instruction has just been
888 * executed, but PC has not advanced to next instruction)
889 */
890 u64 offset = (instrs_executed - instrs_over - 1);
891 u64 addr = cs_etm__instr_addr(etmq->packet, offset);
892
893 ret = cs_etm__synth_instruction_sample(
894 etmq, addr, etm->instructions_sample_period);
895 if (ret)
594 return ret; 896 return ret;
595 897
898 /* Carry remaining instructions into next sample period */
899 etmq->period_instructions = instrs_over;
900 }
901
902 if (etm->sample_branches &&
903 etmq->prev_packet &&
904 etmq->prev_packet->sample_type == CS_ETM_RANGE &&
905 etmq->prev_packet->last_instr_taken_branch) {
906 ret = cs_etm__synth_branch_sample(etmq);
907 if (ret)
908 return ret;
909 }
910
911 if (etm->sample_branches || etm->synth_opts.last_branch) {
596 /* 912 /*
597 * If the packet contains an instruction range, generate an 913 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
598 * instruction sequence event. 914 * the next incoming packet.
599 */ 915 */
600 if (packet.sample_type & CS_ETM_RANGE) 916 tmp = etmq->packet;
601 cs_etm__synth_branch_sample(etmq, &packet); 917 etmq->packet = etmq->prev_packet;
918 etmq->prev_packet = tmp;
602 } 919 }
603 920
604 return 0; 921 return 0;
605} 922}
606 923
924static int cs_etm__flush(struct cs_etm_queue *etmq)
925{
926 int err = 0;
927 struct cs_etm_packet *tmp;
928
929 if (etmq->etm->synth_opts.last_branch &&
930 etmq->prev_packet &&
931 etmq->prev_packet->sample_type == CS_ETM_RANGE) {
932 /*
933 * Generate a last branch event for the branches left in the
934 * circular buffer at the end of the trace.
935 *
936 * Use the address of the end of the last reported execution
937 * range
938 */
939 u64 addr = cs_etm__last_executed_instr(etmq->prev_packet);
940
941 err = cs_etm__synth_instruction_sample(
942 etmq, addr,
943 etmq->period_instructions);
944 etmq->period_instructions = 0;
945
946 /*
947 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
948 * the next incoming packet.
949 */
950 tmp = etmq->packet;
951 etmq->packet = etmq->prev_packet;
952 etmq->prev_packet = tmp;
953 }
954
955 return err;
956}
957
607static int cs_etm__run_decoder(struct cs_etm_queue *etmq) 958static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
608{ 959{
609 struct cs_etm_auxtrace *etm = etmq->etm; 960 struct cs_etm_auxtrace *etm = etmq->etm;
@@ -615,45 +966,72 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
615 etm->kernel_start = machine__kernel_start(etm->machine); 966 etm->kernel_start = machine__kernel_start(etm->machine);
616 967
617 /* Go through each buffer in the queue and decode them one by one */ 968 /* Go through each buffer in the queue and decode them one by one */
618more: 969 while (1) {
619 buffer_used = 0; 970 buffer_used = 0;
620 memset(&buffer, 0, sizeof(buffer)); 971 memset(&buffer, 0, sizeof(buffer));
621 err = cs_etm__get_trace(&buffer, etmq); 972 err = cs_etm__get_trace(&buffer, etmq);
622 if (err <= 0) 973 if (err <= 0)
623 return err;
624 /*
625 * We cannot assume consecutive blocks in the data file are contiguous,
626 * reset the decoder to force re-sync.
627 */
628 err = cs_etm_decoder__reset(etmq->decoder);
629 if (err != 0)
630 return err;
631
632 /* Run trace decoder until buffer consumed or end of trace */
633 do {
634 processed = 0;
635
636 err = cs_etm_decoder__process_data_block(
637 etmq->decoder,
638 etmq->offset,
639 &buffer.buf[buffer_used],
640 buffer.len - buffer_used,
641 &processed);
642
643 if (err)
644 return err; 974 return err;
645
646 etmq->offset += processed;
647 buffer_used += processed;
648
649 /* 975 /*
650 * Nothing to do with an error condition, let's hope the next 976 * We cannot assume consecutive blocks in the data file are
651 * chunk will be better. 977 * contiguous, reset the decoder to force re-sync.
652 */ 978 */
653 err = cs_etm__sample(etmq); 979 err = cs_etm_decoder__reset(etmq->decoder);
654 } while (buffer.len > buffer_used); 980 if (err != 0)
981 return err;
655 982
656goto more; 983 /* Run trace decoder until buffer consumed or end of trace */
984 do {
985 processed = 0;
986 err = cs_etm_decoder__process_data_block(
987 etmq->decoder,
988 etmq->offset,
989 &buffer.buf[buffer_used],
990 buffer.len - buffer_used,
991 &processed);
992 if (err)
993 return err;
994
995 etmq->offset += processed;
996 buffer_used += processed;
997
998 /* Process each packet in this chunk */
999 while (1) {
1000 err = cs_etm_decoder__get_packet(etmq->decoder,
1001 etmq->packet);
1002 if (err <= 0)
1003 /*
1004 * Stop processing this chunk on
1005 * end of data or error
1006 */
1007 break;
1008
1009 switch (etmq->packet->sample_type) {
1010 case CS_ETM_RANGE:
1011 /*
1012 * If the packet contains an instruction
1013 * range, generate instruction sequence
1014 * events.
1015 */
1016 cs_etm__sample(etmq);
1017 break;
1018 case CS_ETM_TRACE_ON:
1019 /*
1020 * Discontinuity in trace, flush
1021 * previous branch stack
1022 */
1023 cs_etm__flush(etmq);
1024 break;
1025 default:
1026 break;
1027 }
1028 }
1029 } while (buffer.len > buffer_used);
1030
1031 if (err == 0)
1032 /* Flush any remaining branch stack entries */
1033 err = cs_etm__flush(etmq);
1034 }
657 1035
658 return err; 1036 return err;
659} 1037}
@@ -980,6 +1358,23 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
980 etm->auxtrace.free = cs_etm__free; 1358 etm->auxtrace.free = cs_etm__free;
981 session->auxtrace = &etm->auxtrace; 1359 session->auxtrace = &etm->auxtrace;
982 1360
1361 etm->unknown_thread = thread__new(999999999, 999999999);
1362 if (!etm->unknown_thread)
1363 goto err_free_queues;
1364
1365 /*
1366 * Initialize list node so that at thread__zput() we can avoid
1367 * segmentation fault at list_del_init().
1368 */
1369 INIT_LIST_HEAD(&etm->unknown_thread->node);
1370
1371 err = thread__set_comm(etm->unknown_thread, "unknown", 0);
1372 if (err)
1373 goto err_delete_thread;
1374
1375 if (thread__init_map_groups(etm->unknown_thread, etm->machine))
1376 goto err_delete_thread;
1377
983 if (dump_trace) { 1378 if (dump_trace) {
984 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu); 1379 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
985 return 0; 1380 return 0;
@@ -994,16 +1389,18 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
994 1389
995 err = cs_etm__synth_events(etm, session); 1390 err = cs_etm__synth_events(etm, session);
996 if (err) 1391 if (err)
997 goto err_free_queues; 1392 goto err_delete_thread;
998 1393
999 err = auxtrace_queues__process_index(&etm->queues, session); 1394 err = auxtrace_queues__process_index(&etm->queues, session);
1000 if (err) 1395 if (err)
1001 goto err_free_queues; 1396 goto err_delete_thread;
1002 1397
1003 etm->data_queued = etm->queues.populated; 1398 etm->data_queued = etm->queues.populated;
1004 1399
1005 return 0; 1400 return 0;
1006 1401
1402err_delete_thread:
1403 thread__zput(etm->unknown_thread);
1007err_free_queues: 1404err_free_queues:
1008 auxtrace_queues__free(&etm->queues); 1405 auxtrace_queues__free(&etm->queues);
1009 session->auxtrace = NULL; 1406 session->auxtrace = NULL;
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
index 5864d5dca616..37f8d48179ca 100644
--- a/tools/perf/util/cs-etm.h
+++ b/tools/perf/util/cs-etm.h
@@ -1,18 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved. 3 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 5 */
17 6
18#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__ 7#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index f3a71db83947..3d6459626c2a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -232,7 +232,6 @@ int perf_quiet_option(void)
232 var++; 232 var++;
233 } 233 }
234 234
235 quiet = true;
236 return 0; 235 return 0;
237} 236}
238 237
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index f5acda13dcfa..7eb7de5aee44 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -979,7 +979,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
979 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); 979 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
980} 980}
981 981
982#ifdef HAVE_DWARF_GETLOCATIONS 982#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
983/** 983/**
984 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE 984 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
985 * @sp_die: a subprogram DIE 985 * @sp_die: a subprogram DIE
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 6d311868d850..4c842762e3f2 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -32,6 +32,10 @@ void perf_env__exit(struct perf_env *env)
32 for (i = 0; i < env->caches_cnt; i++) 32 for (i = 0; i < env->caches_cnt; i++)
33 cpu_cache_level__free(&env->caches[i]); 33 cpu_cache_level__free(&env->caches[i]);
34 zfree(&env->caches); 34 zfree(&env->caches);
35
36 for (i = 0; i < env->nr_memory_nodes; i++)
37 free(env->memory_nodes[i].set);
38 zfree(&env->memory_nodes);
35} 39}
36 40
37int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) 41int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index bf970f57dce0..c4ef2e523367 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -27,6 +27,12 @@ struct numa_node {
27 struct cpu_map *map; 27 struct cpu_map *map;
28}; 28};
29 29
30struct memory_node {
31 u64 node;
32 u64 size;
33 unsigned long *set;
34};
35
30struct perf_env { 36struct perf_env {
31 char *hostname; 37 char *hostname;
32 char *os_release; 38 char *os_release;
@@ -43,6 +49,7 @@ struct perf_env {
43 int nr_sibling_cores; 49 int nr_sibling_cores;
44 int nr_sibling_threads; 50 int nr_sibling_threads;
45 int nr_numa_nodes; 51 int nr_numa_nodes;
52 int nr_memory_nodes;
46 int nr_pmu_mappings; 53 int nr_pmu_mappings;
47 int nr_groups; 54 int nr_groups;
48 char *cmdline; 55 char *cmdline;
@@ -54,6 +61,8 @@ struct perf_env {
54 struct cpu_cache_level *caches; 61 struct cpu_cache_level *caches;
55 int caches_cnt; 62 int caches_cnt;
56 struct numa_node *numa_nodes; 63 struct numa_node *numa_nodes;
64 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize;
57}; 66};
58 67
59extern struct perf_env perf_env; 68extern struct perf_env perf_env;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 44e603c27944..98ff3a6a3d50 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -894,8 +894,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
894 struct machine *machine) 894 struct machine *machine)
895{ 895{
896 size_t size; 896 size_t size;
897 const char *mmap_name;
898 char name_buff[PATH_MAX];
899 struct map *map = machine__kernel_map(machine); 897 struct map *map = machine__kernel_map(machine);
900 struct kmap *kmap; 898 struct kmap *kmap;
901 int err; 899 int err;
@@ -918,7 +916,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
918 return -1; 916 return -1;
919 } 917 }
920 918
921 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
922 if (machine__is_host(machine)) { 919 if (machine__is_host(machine)) {
923 /* 920 /*
924 * kernel uses PERF_RECORD_MISC_USER for user space maps, 921 * kernel uses PERF_RECORD_MISC_USER for user space maps,
@@ -931,7 +928,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
931 928
932 kmap = map__kmap(map); 929 kmap = map__kmap(map);
933 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 930 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
934 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; 931 "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
935 size = PERF_ALIGN(size, sizeof(u64)); 932 size = PERF_ALIGN(size, sizeof(u64));
936 event->mmap.header.type = PERF_RECORD_MMAP; 933 event->mmap.header.type = PERF_RECORD_MMAP;
937 event->mmap.header.size = (sizeof(event->mmap) - 934 event->mmap.header.size = (sizeof(event->mmap) -
@@ -1424,7 +1421,9 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
1424size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp) 1421size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
1425{ 1422{
1426 bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT; 1423 bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
1427 const char *in_out = out ? "OUT" : "IN "; 1424 const char *in_out = !out ? "IN " :
1425 !(event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT) ?
1426 "OUT " : "OUT preempt";
1428 1427
1429 if (event->header.type == PERF_RECORD_SWITCH) 1428 if (event->header.type == PERF_RECORD_SWITCH)
1430 return fprintf(fp, " %s\n", in_out); 1429 return fprintf(fp, " %s\n", in_out);
@@ -1591,17 +1590,6 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1591 return -1; 1590 return -1;
1592 1591
1593 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 1592 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
1594 /*
1595 * Have we already created the kernel maps for this machine?
1596 *
1597 * This should have happened earlier, when we processed the kernel MMAP
1598 * events, but for older perf.data files there was no such thing, so do
1599 * it now.
1600 */
1601 if (sample->cpumode == PERF_RECORD_MISC_KERNEL &&
1602 machine__kernel_map(machine) == NULL)
1603 machine__create_kernel_maps(machine);
1604
1605 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al); 1593 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al);
1606 dump_printf(" ...... dso: %s\n", 1594 dump_printf(" ...... dso: %s\n",
1607 al->map ? al->map->dso->long_name : 1595 al->map ? al->map->dso->long_name :
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e5fc14e53c05..a59281d64368 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -702,29 +702,6 @@ static int perf_evlist__resume(struct perf_evlist *evlist)
702 return perf_evlist__set_paused(evlist, false); 702 return perf_evlist__set_paused(evlist, false);
703} 703}
704 704
705union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
706{
707 struct perf_mmap *md = &evlist->mmap[idx];
708
709 /*
710 * Check messup is required for forward overwritable ring buffer:
711 * memory pointed by md->prev can be overwritten in this case.
712 * No need for read-write ring buffer: kernel stop outputting when
713 * it hit md->prev (perf_mmap__consume()).
714 */
715 return perf_mmap__read_forward(md);
716}
717
718union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
719{
720 return perf_evlist__mmap_read_forward(evlist, idx);
721}
722
723void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
724{
725 perf_mmap__consume(&evlist->mmap[idx], false);
726}
727
728static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) 705static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
729{ 706{
730 int i; 707 int i;
@@ -745,7 +722,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
745 zfree(&evlist->overwrite_mmap); 722 zfree(&evlist->overwrite_mmap);
746} 723}
747 724
748static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist) 725static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist,
726 bool overwrite)
749{ 727{
750 int i; 728 int i;
751 struct perf_mmap *map; 729 struct perf_mmap *map;
@@ -759,9 +737,10 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
759 737
760 for (i = 0; i < evlist->nr_mmaps; i++) { 738 for (i = 0; i < evlist->nr_mmaps; i++) {
761 map[i].fd = -1; 739 map[i].fd = -1;
740 map[i].overwrite = overwrite;
762 /* 741 /*
763 * When the perf_mmap() call is made we grab one refcount, plus 742 * When the perf_mmap() call is made we grab one refcount, plus
764 * one extra to let perf_evlist__mmap_consume() get the last 743 * one extra to let perf_mmap__consume() get the last
765 * events after all real references (perf_mmap__get()) are 744 * events after all real references (perf_mmap__get()) are
766 * dropped. 745 * dropped.
767 * 746 *
@@ -802,7 +781,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
802 maps = evlist->overwrite_mmap; 781 maps = evlist->overwrite_mmap;
803 782
804 if (!maps) { 783 if (!maps) {
805 maps = perf_evlist__alloc_mmap(evlist); 784 maps = perf_evlist__alloc_mmap(evlist, true);
806 if (!maps) 785 if (!maps)
807 return -1; 786 return -1;
808 evlist->overwrite_mmap = maps; 787 evlist->overwrite_mmap = maps;
@@ -1052,7 +1031,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1052 struct mmap_params mp; 1031 struct mmap_params mp;
1053 1032
1054 if (!evlist->mmap) 1033 if (!evlist->mmap)
1055 evlist->mmap = perf_evlist__alloc_mmap(evlist); 1034 evlist->mmap = perf_evlist__alloc_mmap(evlist, false);
1056 if (!evlist->mmap) 1035 if (!evlist->mmap)
1057 return -ENOMEM; 1036 return -ENOMEM;
1058 1037
@@ -1086,11 +1065,30 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
1086 1065
1087int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 1066int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
1088{ 1067{
1068 bool all_threads = (target->per_thread && target->system_wide);
1089 struct cpu_map *cpus; 1069 struct cpu_map *cpus;
1090 struct thread_map *threads; 1070 struct thread_map *threads;
1091 1071
1072 /*
1073 * If specify '-a' and '--per-thread' to perf record, perf record
1074 * will override '--per-thread'. target->per_thread = false and
1075 * target->system_wide = true.
1076 *
1077 * If specify '--per-thread' only to perf record,
1078 * target->per_thread = true and target->system_wide = false.
1079 *
1080 * So target->per_thread && target->system_wide is false.
1081 * For perf record, thread_map__new_str doesn't call
1082 * thread_map__new_all_cpus. That will keep perf record's
1083 * current behavior.
1084 *
1085 * For perf stat, it allows the case that target->per_thread and
1086 * target->system_wide are all true. It means to collect system-wide
1087 * per-thread data. thread_map__new_str will call
1088 * thread_map__new_all_cpus to enumerate all threads.
1089 */
1092 threads = thread_map__new_str(target->pid, target->tid, target->uid, 1090 threads = thread_map__new_str(target->pid, target->tid, target->uid,
1093 target->per_thread); 1091 all_threads);
1094 1092
1095 if (!threads) 1093 if (!threads)
1096 return -1; 1094 return -1;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 336b838e6957..6c41b2f78713 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -129,10 +129,6 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
129 129
130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state); 130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
131 131
132union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
133
134union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
135 int idx);
136void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 132void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
137 133
138int perf_evlist__open(struct perf_evlist *evlist); 134int perf_evlist__open(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ef351688b797..4cd2cf93f726 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -244,6 +244,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
244 evsel->metric_name = NULL; 244 evsel->metric_name = NULL;
245 evsel->metric_events = NULL; 245 evsel->metric_events = NULL;
246 evsel->collect_stat = false; 246 evsel->collect_stat = false;
247 evsel->pmu_name = NULL;
247} 248}
248 249
249struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 250struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -621,22 +622,34 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel)
621 return evsel->group_name ?: "anon group"; 622 return evsel->group_name ?: "anon group";
622} 623}
623 624
625/*
626 * Returns the group details for the specified leader,
627 * with following rules.
628 *
629 * For record -e '{cycles,instructions}'
630 * 'anon group { cycles:u, instructions:u }'
631 *
632 * For record -e 'cycles,instructions' and report --group
633 * 'cycles:u, instructions:u'
634 */
624int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) 635int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
625{ 636{
626 int ret; 637 int ret = 0;
627 struct perf_evsel *pos; 638 struct perf_evsel *pos;
628 const char *group_name = perf_evsel__group_name(evsel); 639 const char *group_name = perf_evsel__group_name(evsel);
629 640
630 ret = scnprintf(buf, size, "%s", group_name); 641 if (!evsel->forced_leader)
642 ret = scnprintf(buf, size, "%s { ", group_name);
631 643
632 ret += scnprintf(buf + ret, size - ret, " { %s", 644 ret += scnprintf(buf + ret, size - ret, "%s",
633 perf_evsel__name(evsel)); 645 perf_evsel__name(evsel));
634 646
635 for_each_group_member(pos, evsel) 647 for_each_group_member(pos, evsel)
636 ret += scnprintf(buf + ret, size - ret, ", %s", 648 ret += scnprintf(buf + ret, size - ret, ", %s",
637 perf_evsel__name(pos)); 649 perf_evsel__name(pos));
638 650
639 ret += scnprintf(buf + ret, size - ret, " }"); 651 if (!evsel->forced_leader)
652 ret += scnprintf(buf + ret, size - ret, " }");
640 653
641 return ret; 654 return ret;
642} 655}
@@ -917,8 +930,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
917 * than leader in case leader 'leads' the sampling. 930 * than leader in case leader 'leads' the sampling.
918 */ 931 */
919 if ((leader != evsel) && leader->sample_read) { 932 if ((leader != evsel) && leader->sample_read) {
920 attr->sample_freq = 0; 933 attr->freq = 0;
921 attr->sample_period = 0; 934 attr->sample_freq = 0;
935 attr->sample_period = 0;
936 attr->write_backward = 0;
937 attr->sample_id_all = 0;
922 } 938 }
923 939
924 if (opts->no_samples) 940 if (opts->no_samples)
@@ -1233,7 +1249,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
1233 perf_evsel__free_fd(evsel); 1249 perf_evsel__free_fd(evsel);
1234 perf_evsel__free_id(evsel); 1250 perf_evsel__free_id(evsel);
1235 perf_evsel__free_config_terms(evsel); 1251 perf_evsel__free_config_terms(evsel);
1236 close_cgroup(evsel->cgrp); 1252 cgroup__put(evsel->cgrp);
1237 cpu_map__put(evsel->cpus); 1253 cpu_map__put(evsel->cpus);
1238 cpu_map__put(evsel->own_cpus); 1254 cpu_map__put(evsel->own_cpus);
1239 thread_map__put(evsel->threads); 1255 thread_map__put(evsel->threads);
@@ -1909,12 +1925,16 @@ try_fallback:
1909 goto fallback_missing_features; 1925 goto fallback_missing_features;
1910 } else if (!perf_missing_features.group_read && 1926 } else if (!perf_missing_features.group_read &&
1911 evsel->attr.inherit && 1927 evsel->attr.inherit &&
1912 (evsel->attr.read_format & PERF_FORMAT_GROUP)) { 1928 (evsel->attr.read_format & PERF_FORMAT_GROUP) &&
1929 perf_evsel__is_group_leader(evsel)) {
1913 perf_missing_features.group_read = true; 1930 perf_missing_features.group_read = true;
1914 pr_debug2("switching off group read\n"); 1931 pr_debug2("switching off group read\n");
1915 goto fallback_missing_features; 1932 goto fallback_missing_features;
1916 } 1933 }
1917out_close: 1934out_close:
1935 if (err)
1936 threads->err_thread = thread;
1937
1918 do { 1938 do {
1919 while (--thread >= 0) { 1939 while (--thread >= 0) {
1920 close(FD(evsel, cpu, thread)); 1940 close(FD(evsel, cpu, thread));
@@ -2738,8 +2758,14 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2738 (paranoid = perf_event_paranoid()) > 1) { 2758 (paranoid = perf_event_paranoid()) > 1) {
2739 const char *name = perf_evsel__name(evsel); 2759 const char *name = perf_evsel__name(evsel);
2740 char *new_name; 2760 char *new_name;
2761 const char *sep = ":";
2762
2763 /* Is there already the separator in the name. */
2764 if (strchr(name, '/') ||
2765 strchr(name, ':'))
2766 sep = "";
2741 2767
2742 if (asprintf(&new_name, "%s%su", name, strchr(name, ':') ? "" : ":") < 0) 2768 if (asprintf(&new_name, "%s%su", name, sep) < 0)
2743 return false; 2769 return false;
2744 2770
2745 if (evsel->name) 2771 if (evsel->name)
@@ -2854,8 +2880,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2854#if defined(__i386__) || defined(__x86_64__) 2880#if defined(__i386__) || defined(__x86_64__)
2855 if (evsel->attr.type == PERF_TYPE_HARDWARE) 2881 if (evsel->attr.type == PERF_TYPE_HARDWARE)
2856 return scnprintf(msg, size, "%s", 2882 return scnprintf(msg, size, "%s",
2857 "No hardware sampling interrupt available.\n" 2883 "No hardware sampling interrupt available.\n");
2858 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
2859#endif 2884#endif
2860 break; 2885 break;
2861 case EBUSY: 2886 case EBUSY:
@@ -2878,8 +2903,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2878 2903
2879 return scnprintf(msg, size, 2904 return scnprintf(msg, size,
2880 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 2905 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2881 "/bin/dmesg may provide additional information.\n" 2906 "/bin/dmesg | grep -i perf may provide additional information.\n",
2882 "No CONFIG_PERF_EVENTS=y kernel support configured?",
2883 err, str_error_r(err, sbuf, sizeof(sbuf)), 2907 err, str_error_r(err, sbuf, sizeof(sbuf)),
2884 perf_evsel__name(evsel)); 2908 perf_evsel__name(evsel));
2885} 2909}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index a7487c6d1866..92ec009a292d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -30,7 +30,7 @@ struct perf_sample_id {
30 u64 period; 30 u64 period;
31}; 31};
32 32
33struct cgroup_sel; 33struct cgroup;
34 34
35/* 35/*
36 * The 'struct perf_evsel_config_term' is used to pass event 36 * The 'struct perf_evsel_config_term' is used to pass event
@@ -107,7 +107,7 @@ struct perf_evsel {
107 struct perf_stat_evsel *stats; 107 struct perf_stat_evsel *stats;
108 void *priv; 108 void *priv;
109 u64 db_id; 109 u64 db_id;
110 struct cgroup_sel *cgrp; 110 struct cgroup *cgrp;
111 void *handler; 111 void *handler;
112 struct cpu_map *cpus; 112 struct cpu_map *cpus;
113 struct cpu_map *own_cpus; 113 struct cpu_map *own_cpus;
@@ -115,6 +115,7 @@ struct perf_evsel {
115 unsigned int sample_size; 115 unsigned int sample_size;
116 int id_pos; 116 int id_pos;
117 int is_pos; 117 int is_pos;
118 bool uniquified_name;
118 bool snapshot; 119 bool snapshot;
119 bool supported; 120 bool supported;
120 bool needs_swap; 121 bool needs_swap;
@@ -125,6 +126,7 @@ struct perf_evsel {
125 bool per_pkg; 126 bool per_pkg;
126 bool precise_max; 127 bool precise_max;
127 bool ignore_missing_thread; 128 bool ignore_missing_thread;
129 bool forced_leader;
128 /* parse modifier helper */ 130 /* parse modifier helper */
129 int exclude_GH; 131 int exclude_GH;
130 int nr_members; 132 int nr_members;
@@ -142,6 +144,7 @@ struct perf_evsel {
142 struct perf_evsel **metric_events; 144 struct perf_evsel **metric_events;
143 bool collect_stat; 145 bool collect_stat;
144 bool weak_group; 146 bool weak_group;
147 const char *pmu_name;
145}; 148};
146 149
147union u64_swap { 150union u64_swap {
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index ff17920a5ebc..c3cef36d4176 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -38,7 +38,7 @@ do
38done 38done
39echo "#endif /* HAVE_LIBELF_SUPPORT */" 39echo "#endif /* HAVE_LIBELF_SUPPORT */"
40 40
41echo "#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE)" 41echo "#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)"
42sed -n -e 's/^perf-\([^ ]*\)[ ].* audit*/\1/p' command-list.txt | 42sed -n -e 's/^perf-\([^ ]*\)[ ].* audit*/\1/p' command-list.txt |
43sort | 43sort |
44while read cmd 44while read cmd
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a326e0d8b5b6..a8bff2178fbc 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -17,6 +17,7 @@
17#include <sys/stat.h> 17#include <sys/stat.h>
18#include <sys/utsname.h> 18#include <sys/utsname.h>
19#include <linux/time64.h> 19#include <linux/time64.h>
20#include <dirent.h>
20 21
21#include "evlist.h" 22#include "evlist.h"
22#include "evsel.h" 23#include "evsel.h"
@@ -37,6 +38,7 @@
37#include "asm/bug.h" 38#include "asm/bug.h"
38#include "tool.h" 39#include "tool.h"
39#include "time-utils.h" 40#include "time-utils.h"
41#include "units.h"
40 42
41#include "sane_ctype.h" 43#include "sane_ctype.h"
42 44
@@ -132,6 +134,25 @@ int do_write(struct feat_fd *ff, const void *buf, size_t size)
132} 134}
133 135
134/* Return: 0 if succeded, -ERR if failed. */ 136/* Return: 0 if succeded, -ERR if failed. */
137static int do_write_bitmap(struct feat_fd *ff, unsigned long *set, u64 size)
138{
139 u64 *p = (u64 *) set;
140 int i, ret;
141
142 ret = do_write(ff, &size, sizeof(size));
143 if (ret < 0)
144 return ret;
145
146 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
147 ret = do_write(ff, p + i, sizeof(*p));
148 if (ret < 0)
149 return ret;
150 }
151
152 return 0;
153}
154
155/* Return: 0 if succeded, -ERR if failed. */
135int write_padded(struct feat_fd *ff, const void *bf, 156int write_padded(struct feat_fd *ff, const void *bf,
136 size_t count, size_t count_aligned) 157 size_t count, size_t count_aligned)
137{ 158{
@@ -243,6 +264,38 @@ static char *do_read_string(struct feat_fd *ff)
243 return NULL; 264 return NULL;
244} 265}
245 266
267/* Return: 0 if succeded, -ERR if failed. */
268static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
269{
270 unsigned long *set;
271 u64 size, *p;
272 int i, ret;
273
274 ret = do_read_u64(ff, &size);
275 if (ret)
276 return ret;
277
278 set = bitmap_alloc(size);
279 if (!set)
280 return -ENOMEM;
281
282 bitmap_zero(set, size);
283
284 p = (u64 *) set;
285
286 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
287 ret = do_read_u64(ff, p + i);
288 if (ret < 0) {
289 free(set);
290 return ret;
291 }
292 }
293
294 *pset = set;
295 *psize = size;
296 return 0;
297}
298
246static int write_tracing_data(struct feat_fd *ff, 299static int write_tracing_data(struct feat_fd *ff,
247 struct perf_evlist *evlist) 300 struct perf_evlist *evlist)
248{ 301{
@@ -1196,6 +1249,177 @@ static int write_sample_time(struct feat_fd *ff,
1196 sizeof(evlist->last_sample_time)); 1249 sizeof(evlist->last_sample_time));
1197} 1250}
1198 1251
1252
1253static int memory_node__read(struct memory_node *n, unsigned long idx)
1254{
1255 unsigned int phys, size = 0;
1256 char path[PATH_MAX];
1257 struct dirent *ent;
1258 DIR *dir;
1259
1260#define for_each_memory(mem, dir) \
1261 while ((ent = readdir(dir))) \
1262 if (strcmp(ent->d_name, ".") && \
1263 strcmp(ent->d_name, "..") && \
1264 sscanf(ent->d_name, "memory%u", &mem) == 1)
1265
1266 scnprintf(path, PATH_MAX,
1267 "%s/devices/system/node/node%lu",
1268 sysfs__mountpoint(), idx);
1269
1270 dir = opendir(path);
1271 if (!dir) {
1272 pr_warning("failed: cant' open memory sysfs data\n");
1273 return -1;
1274 }
1275
1276 for_each_memory(phys, dir) {
1277 size = max(phys, size);
1278 }
1279
1280 size++;
1281
1282 n->set = bitmap_alloc(size);
1283 if (!n->set) {
1284 closedir(dir);
1285 return -ENOMEM;
1286 }
1287
1288 bitmap_zero(n->set, size);
1289 n->node = idx;
1290 n->size = size;
1291
1292 rewinddir(dir);
1293
1294 for_each_memory(phys, dir) {
1295 set_bit(phys, n->set);
1296 }
1297
1298 closedir(dir);
1299 return 0;
1300}
1301
1302static int memory_node__sort(const void *a, const void *b)
1303{
1304 const struct memory_node *na = a;
1305 const struct memory_node *nb = b;
1306
1307 return na->node - nb->node;
1308}
1309
1310static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp)
1311{
1312 char path[PATH_MAX];
1313 struct dirent *ent;
1314 DIR *dir;
1315 u64 cnt = 0;
1316 int ret = 0;
1317
1318 scnprintf(path, PATH_MAX, "%s/devices/system/node/",
1319 sysfs__mountpoint());
1320
1321 dir = opendir(path);
1322 if (!dir) {
1323 pr_debug2("%s: could't read %s, does this arch have topology information?\n",
1324 __func__, path);
1325 return -1;
1326 }
1327
1328 while (!ret && (ent = readdir(dir))) {
1329 unsigned int idx;
1330 int r;
1331
1332 if (!strcmp(ent->d_name, ".") ||
1333 !strcmp(ent->d_name, ".."))
1334 continue;
1335
1336 r = sscanf(ent->d_name, "node%u", &idx);
1337 if (r != 1)
1338 continue;
1339
1340 if (WARN_ONCE(cnt >= size,
1341 "failed to write MEM_TOPOLOGY, way too many nodes\n"))
1342 return -1;
1343
1344 ret = memory_node__read(&nodes[cnt++], idx);
1345 }
1346
1347 *cntp = cnt;
1348 closedir(dir);
1349
1350 if (!ret)
1351 qsort(nodes, cnt, sizeof(nodes[0]), memory_node__sort);
1352
1353 return ret;
1354}
1355
1356#define MAX_MEMORY_NODES 2000
1357
1358/*
1359 * The MEM_TOPOLOGY holds physical memory map for every
1360 * node in system. The format of data is as follows:
1361 *
1362 * 0 - version | for future changes
1363 * 8 - block_size_bytes | /sys/devices/system/memory/block_size_bytes
1364 * 16 - count | number of nodes
1365 *
1366 * For each node we store map of physical indexes for
1367 * each node:
1368 *
1369 * 32 - node id | node index
1370 * 40 - size | size of bitmap
1371 * 48 - bitmap | bitmap of memory indexes that belongs to node
1372 */
1373static int write_mem_topology(struct feat_fd *ff __maybe_unused,
1374 struct perf_evlist *evlist __maybe_unused)
1375{
1376 static struct memory_node nodes[MAX_MEMORY_NODES];
1377 u64 bsize, version = 1, i, nr;
1378 int ret;
1379
1380 ret = sysfs__read_xll("devices/system/memory/block_size_bytes",
1381 (unsigned long long *) &bsize);
1382 if (ret)
1383 return ret;
1384
1385 ret = build_mem_topology(&nodes[0], MAX_MEMORY_NODES, &nr);
1386 if (ret)
1387 return ret;
1388
1389 ret = do_write(ff, &version, sizeof(version));
1390 if (ret < 0)
1391 goto out;
1392
1393 ret = do_write(ff, &bsize, sizeof(bsize));
1394 if (ret < 0)
1395 goto out;
1396
1397 ret = do_write(ff, &nr, sizeof(nr));
1398 if (ret < 0)
1399 goto out;
1400
1401 for (i = 0; i < nr; i++) {
1402 struct memory_node *n = &nodes[i];
1403
1404 #define _W(v) \
1405 ret = do_write(ff, &n->v, sizeof(n->v)); \
1406 if (ret < 0) \
1407 goto out;
1408
1409 _W(node)
1410 _W(size)
1411
1412 #undef _W
1413
1414 ret = do_write_bitmap(ff, n->set, n->size);
1415 if (ret < 0)
1416 goto out;
1417 }
1418
1419out:
1420 return ret;
1421}
1422
1199static void print_hostname(struct feat_fd *ff, FILE *fp) 1423static void print_hostname(struct feat_fd *ff, FILE *fp)
1200{ 1424{
1201 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); 1425 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
@@ -1543,6 +1767,35 @@ static void print_sample_time(struct feat_fd *ff, FILE *fp)
1543 fprintf(fp, "# sample duration : %10.3f ms\n", d); 1767 fprintf(fp, "# sample duration : %10.3f ms\n", d);
1544} 1768}
1545 1769
1770static void memory_node__fprintf(struct memory_node *n,
1771 unsigned long long bsize, FILE *fp)
1772{
1773 char buf_map[100], buf_size[50];
1774 unsigned long long size;
1775
1776 size = bsize * bitmap_weight(n->set, n->size);
1777 unit_number__scnprintf(buf_size, 50, size);
1778
1779 bitmap_scnprintf(n->set, n->size, buf_map, 100);
1780 fprintf(fp, "# %3" PRIu64 " [%s]: %s\n", n->node, buf_size, buf_map);
1781}
1782
1783static void print_mem_topology(struct feat_fd *ff, FILE *fp)
1784{
1785 struct memory_node *nodes;
1786 int i, nr;
1787
1788 nodes = ff->ph->env.memory_nodes;
1789 nr = ff->ph->env.nr_memory_nodes;
1790
1791 fprintf(fp, "# memory nodes (nr %d, block size 0x%llx):\n",
1792 nr, ff->ph->env.memory_bsize);
1793
1794 for (i = 0; i < nr; i++) {
1795 memory_node__fprintf(&nodes[i], ff->ph->env.memory_bsize, fp);
1796 }
1797}
1798
1546static int __event_process_build_id(struct build_id_event *bev, 1799static int __event_process_build_id(struct build_id_event *bev,
1547 char *filename, 1800 char *filename,
1548 struct perf_session *session) 1801 struct perf_session *session)
@@ -2205,6 +2458,58 @@ static int process_sample_time(struct feat_fd *ff, void *data __maybe_unused)
2205 return 0; 2458 return 0;
2206} 2459}
2207 2460
2461static int process_mem_topology(struct feat_fd *ff,
2462 void *data __maybe_unused)
2463{
2464 struct memory_node *nodes;
2465 u64 version, i, nr, bsize;
2466 int ret = -1;
2467
2468 if (do_read_u64(ff, &version))
2469 return -1;
2470
2471 if (version != 1)
2472 return -1;
2473
2474 if (do_read_u64(ff, &bsize))
2475 return -1;
2476
2477 if (do_read_u64(ff, &nr))
2478 return -1;
2479
2480 nodes = zalloc(sizeof(*nodes) * nr);
2481 if (!nodes)
2482 return -1;
2483
2484 for (i = 0; i < nr; i++) {
2485 struct memory_node n;
2486
2487 #define _R(v) \
2488 if (do_read_u64(ff, &n.v)) \
2489 goto out; \
2490
2491 _R(node)
2492 _R(size)
2493
2494 #undef _R
2495
2496 if (do_read_bitmap(ff, &n.set, &n.size))
2497 goto out;
2498
2499 nodes[i] = n;
2500 }
2501
2502 ff->ph->env.memory_bsize = bsize;
2503 ff->ph->env.memory_nodes = nodes;
2504 ff->ph->env.nr_memory_nodes = nr;
2505 ret = 0;
2506
2507out:
2508 if (ret)
2509 free(nodes);
2510 return ret;
2511}
2512
2208struct feature_ops { 2513struct feature_ops {
2209 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2514 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2210 void (*print)(struct feat_fd *ff, FILE *fp); 2515 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2263,6 +2568,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2263 FEAT_OPN(STAT, stat, false), 2568 FEAT_OPN(STAT, stat, false),
2264 FEAT_OPN(CACHE, cache, true), 2569 FEAT_OPN(CACHE, cache, true),
2265 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2570 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2571 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2266}; 2572};
2267 2573
2268struct header_print_data { 2574struct header_print_data {
@@ -2318,7 +2624,12 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2318 if (ret == -1) 2624 if (ret == -1)
2319 return -1; 2625 return -1;
2320 2626
2321 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime)); 2627 fprintf(fp, "# captured on : %s", ctime(&st.st_ctime));
2628
2629 fprintf(fp, "# header version : %u\n", header->version);
2630 fprintf(fp, "# data offset : %" PRIu64 "\n", header->data_offset);
2631 fprintf(fp, "# data size : %" PRIu64 "\n", header->data_size);
2632 fprintf(fp, "# feat offset : %" PRIu64 "\n", header->feat_offset);
2322 2633
2323 perf_header__process_sections(header, fd, &hd, 2634 perf_header__process_sections(header, fd, &hd,
2324 perf_file_section__fprintf_info); 2635 perf_file_section__fprintf_info);
@@ -3105,8 +3416,17 @@ int perf_event__synthesize_features(struct perf_tool *tool,
3105 return ret; 3416 return ret;
3106 } 3417 }
3107 } 3418 }
3419
3420 /* Send HEADER_LAST_FEATURE mark. */
3421 fe = ff.buf;
3422 fe->feat_id = HEADER_LAST_FEATURE;
3423 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3424 fe->header.size = sizeof(*fe);
3425
3426 ret = process(tool, ff.buf, NULL, NULL);
3427
3108 free(ff.buf); 3428 free(ff.buf);
3109 return 0; 3429 return ret;
3110} 3430}
3111 3431
3112int perf_event__process_feature(struct perf_tool *tool, 3432int perf_event__process_feature(struct perf_tool *tool,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f28aaaa3a440..90d4577a92dc 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -36,6 +36,7 @@ enum {
36 HEADER_STAT, 36 HEADER_STAT,
37 HEADER_CACHE, 37 HEADER_CACHE,
38 HEADER_SAMPLE_TIME, 38 HEADER_SAMPLE_TIME,
39 HEADER_MEM_TOPOLOGY,
39 HEADER_LAST_FEATURE, 40 HEADER_LAST_FEATURE,
40 HEADER_FEAT_BITS = 256, 41 HEADER_FEAT_BITS = 256,
41}; 42};
@@ -174,4 +175,5 @@ int write_padded(struct feat_fd *fd, const void *bf,
174int get_cpuid(char *buffer, size_t sz); 175int get_cpuid(char *buffer, size_t sz);
175 176
176char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused); 177char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused);
178int strcmp_cpuid_str(const char *s1, const char *s2);
177#endif /* __PERF_HEADER_H */ 179#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b6140950301e..4d602fba40b2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -6,6 +6,7 @@
6#include "session.h" 6#include "session.h"
7#include "namespaces.h" 7#include "namespaces.h"
8#include "sort.h" 8#include "sort.h"
9#include "units.h"
9#include "evlist.h" 10#include "evlist.h"
10#include "evsel.h" 11#include "evsel.h"
11#include "annotate.h" 12#include "annotate.h"
@@ -14,6 +15,7 @@
14#include "ui/progress.h" 15#include "ui/progress.h"
15#include <errno.h> 16#include <errno.h>
16#include <math.h> 17#include <math.h>
18#include <inttypes.h>
17#include <sys/param.h> 19#include <sys/param.h>
18 20
19static bool hists__filter_entry_by_dso(struct hists *hists, 21static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -536,7 +538,7 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
536 * This mem info was allocated from sample__resolve_mem 538 * This mem info was allocated from sample__resolve_mem
537 * and will not be used anymore. 539 * and will not be used anymore.
538 */ 540 */
539 zfree(&entry->mem_info); 541 mem_info__zput(entry->mem_info);
540 542
541 /* If the map of an existing hist_entry has 543 /* If the map of an existing hist_entry has
542 * become out-of-date due to an exec() or 544 * become out-of-date due to an exec() or
@@ -879,7 +881,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
879 * cumulated only one time to prevent entries more than 100% 881 * cumulated only one time to prevent entries more than 100%
880 * overhead. 882 * overhead.
881 */ 883 */
882 he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1)); 884 he_cache = malloc(sizeof(*he_cache) * (callchain_cursor.nr + 1));
883 if (he_cache == NULL) 885 if (he_cache == NULL)
884 return -ENOMEM; 886 return -ENOMEM;
885 887
@@ -1045,8 +1047,6 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1045 if (err) 1047 if (err)
1046 return err; 1048 return err;
1047 1049
1048 iter->max_stack = max_stack_depth;
1049
1050 err = iter->ops->prepare_entry(iter, al); 1050 err = iter->ops->prepare_entry(iter, al);
1051 if (err) 1051 if (err)
1052 goto out; 1052 goto out;
@@ -1141,7 +1141,7 @@ void hist_entry__delete(struct hist_entry *he)
1141 if (he->mem_info) { 1141 if (he->mem_info) {
1142 map__zput(he->mem_info->iaddr.map); 1142 map__zput(he->mem_info->iaddr.map);
1143 map__zput(he->mem_info->daddr.map); 1143 map__zput(he->mem_info->daddr.map);
1144 zfree(&he->mem_info); 1144 mem_info__zput(he->mem_info);
1145 } 1145 }
1146 1146
1147 zfree(&he->stat_acc); 1147 zfree(&he->stat_acc);
@@ -2456,6 +2456,85 @@ u64 hists__total_period(struct hists *hists)
2456 hists->stats.total_period; 2456 hists->stats.total_period;
2457} 2457}
2458 2458
2459int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq)
2460{
2461 char unit;
2462 int printed;
2463 const struct dso *dso = hists->dso_filter;
2464 const struct thread *thread = hists->thread_filter;
2465 int socket_id = hists->socket_filter;
2466 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
2467 u64 nr_events = hists->stats.total_period;
2468 struct perf_evsel *evsel = hists_to_evsel(hists);
2469 const char *ev_name = perf_evsel__name(evsel);
2470 char buf[512], sample_freq_str[64] = "";
2471 size_t buflen = sizeof(buf);
2472 char ref[30] = " show reference callgraph, ";
2473 bool enable_ref = false;
2474
2475 if (symbol_conf.filter_relative) {
2476 nr_samples = hists->stats.nr_non_filtered_samples;
2477 nr_events = hists->stats.total_non_filtered_period;
2478 }
2479
2480 if (perf_evsel__is_group_event(evsel)) {
2481 struct perf_evsel *pos;
2482
2483 perf_evsel__group_desc(evsel, buf, buflen);
2484 ev_name = buf;
2485
2486 for_each_group_member(pos, evsel) {
2487 struct hists *pos_hists = evsel__hists(pos);
2488
2489 if (symbol_conf.filter_relative) {
2490 nr_samples += pos_hists->stats.nr_non_filtered_samples;
2491 nr_events += pos_hists->stats.total_non_filtered_period;
2492 } else {
2493 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
2494 nr_events += pos_hists->stats.total_period;
2495 }
2496 }
2497 }
2498
2499 if (symbol_conf.show_ref_callgraph &&
2500 strstr(ev_name, "call-graph=no"))
2501 enable_ref = true;
2502
2503 if (show_freq)
2504 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2505
2506 nr_samples = convert_unit(nr_samples, &unit);
2507 printed = scnprintf(bf, size,
2508 "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2509 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2510 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2511
2512
2513 if (hists->uid_filter_str)
2514 printed += snprintf(bf + printed, size - printed,
2515 ", UID: %s", hists->uid_filter_str);
2516 if (thread) {
2517 if (hists__has(hists, thread)) {
2518 printed += scnprintf(bf + printed, size - printed,
2519 ", Thread: %s(%d)",
2520 (thread->comm_set ? thread__comm_str(thread) : ""),
2521 thread->tid);
2522 } else {
2523 printed += scnprintf(bf + printed, size - printed,
2524 ", Thread: %s",
2525 (thread->comm_set ? thread__comm_str(thread) : ""));
2526 }
2527 }
2528 if (dso)
2529 printed += scnprintf(bf + printed, size - printed,
2530 ", DSO: %s", dso->short_name);
2531 if (socket_id > -1)
2532 printed += scnprintf(bf + printed, size - printed,
2533 ", Processor Socket: %d", socket_id);
2534
2535 return printed;
2536}
2537
2459int parse_filter_percentage(const struct option *opt __maybe_unused, 2538int parse_filter_percentage(const struct option *opt __maybe_unused,
2460 const char *arg, int unset __maybe_unused) 2539 const char *arg, int unset __maybe_unused)
2461{ 2540{
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 02721b579746..fbabfd8a215d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -61,6 +61,7 @@ enum hist_column {
61 HISTC_SRCLINE_TO, 61 HISTC_SRCLINE_TO,
62 HISTC_TRACE, 62 HISTC_TRACE,
63 HISTC_SYM_SIZE, 63 HISTC_SYM_SIZE,
64 HISTC_DSO_SIZE,
64 HISTC_NR_COLS, /* Last entry */ 65 HISTC_NR_COLS, /* Last entry */
65}; 66};
66 67
@@ -107,7 +108,6 @@ struct hist_entry_iter {
107 int curr; 108 int curr;
108 109
109 bool hide_unresolved; 110 bool hide_unresolved;
110 int max_stack;
111 111
112 struct perf_evsel *evsel; 112 struct perf_evsel *evsel;
113 struct perf_sample *sample; 113 struct perf_sample *sample;
@@ -504,5 +504,11 @@ int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...);
504int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, 504int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
505 struct perf_hpp_list *hpp_list); 505 struct perf_hpp_list *hpp_list);
506int hists__fprintf_headers(struct hists *hists, FILE *fp); 506int hists__fprintf_headers(struct hists *hists, FILE *fp);
507int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq);
508
509static inline int hists__scnprintf_title(struct hists *hists, char *bf, size_t size)
510{
511 return __hists__scnprintf_title(hists, bf, size, true);
512}
507 513
508#endif /* __PERF_HIST_H */ 514#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index aa1593ce551d..f9157aed1289 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -1378,6 +1378,7 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
1378 intel_pt_clear_tx_flags(decoder); 1378 intel_pt_clear_tx_flags(decoder);
1379 decoder->have_tma = false; 1379 decoder->have_tma = false;
1380 decoder->cbr = 0; 1380 decoder->cbr = 0;
1381 decoder->timestamp_insn_cnt = 0;
1381 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1382 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1382 decoder->overflow = true; 1383 decoder->overflow = true;
1383 return -EOVERFLOW; 1384 return -EOVERFLOW;
@@ -1616,6 +1617,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1616 case INTEL_PT_PWRX: 1617 case INTEL_PT_PWRX:
1617 intel_pt_log("ERROR: Missing TIP after FUP\n"); 1618 intel_pt_log("ERROR: Missing TIP after FUP\n");
1618 decoder->pkt_state = INTEL_PT_STATE_ERR3; 1619 decoder->pkt_state = INTEL_PT_STATE_ERR3;
1620 decoder->pkt_step = 0;
1619 return -ENOENT; 1621 return -ENOENT;
1620 1622
1621 case INTEL_PT_OVF: 1623 case INTEL_PT_OVF:
@@ -2390,14 +2392,6 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
2390 return &decoder->state; 2392 return &decoder->state;
2391} 2393}
2392 2394
2393static bool intel_pt_at_psb(unsigned char *buf, size_t len)
2394{
2395 if (len < INTEL_PT_PSB_LEN)
2396 return false;
2397 return memmem(buf, INTEL_PT_PSB_LEN, INTEL_PT_PSB_STR,
2398 INTEL_PT_PSB_LEN);
2399}
2400
2401/** 2395/**
2402 * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet. 2396 * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet.
2403 * @buf: pointer to buffer pointer 2397 * @buf: pointer to buffer pointer
@@ -2486,6 +2480,7 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
2486 * @buf: buffer 2480 * @buf: buffer
2487 * @len: size of buffer 2481 * @len: size of buffer
2488 * @tsc: TSC value returned 2482 * @tsc: TSC value returned
2483 * @rem: returns remaining size when TSC is found
2489 * 2484 *
2490 * Find a TSC packet in @buf and return the TSC value. This function assumes 2485 * Find a TSC packet in @buf and return the TSC value. This function assumes
2491 * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a 2486 * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a
@@ -2493,7 +2488,8 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
2493 * 2488 *
2494 * Return: %true if TSC is found, false otherwise. 2489 * Return: %true if TSC is found, false otherwise.
2495 */ 2490 */
2496static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc) 2491static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
2492 size_t *rem)
2497{ 2493{
2498 struct intel_pt_pkt packet; 2494 struct intel_pt_pkt packet;
2499 int ret; 2495 int ret;
@@ -2504,6 +2500,7 @@ static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc)
2504 return false; 2500 return false;
2505 if (packet.type == INTEL_PT_TSC) { 2501 if (packet.type == INTEL_PT_TSC) {
2506 *tsc = packet.payload; 2502 *tsc = packet.payload;
2503 *rem = len;
2507 return true; 2504 return true;
2508 } 2505 }
2509 if (packet.type == INTEL_PT_PSBEND) 2506 if (packet.type == INTEL_PT_PSBEND)
@@ -2554,6 +2551,8 @@ static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
2554 * @len_a: size of first buffer 2551 * @len_a: size of first buffer
2555 * @buf_b: second buffer 2552 * @buf_b: second buffer
2556 * @len_b: size of second buffer 2553 * @len_b: size of second buffer
2554 * @consecutive: returns true if there is data in buf_b that is consecutive
2555 * to buf_a
2557 * 2556 *
2558 * If the trace contains TSC we can look at the last TSC of @buf_a and the 2557 * If the trace contains TSC we can look at the last TSC of @buf_a and the
2559 * first TSC of @buf_b in order to determine if the buffers overlap, and then 2558 * first TSC of @buf_b in order to determine if the buffers overlap, and then
@@ -2566,33 +2565,41 @@ static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
2566static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a, 2565static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2567 size_t len_a, 2566 size_t len_a,
2568 unsigned char *buf_b, 2567 unsigned char *buf_b,
2569 size_t len_b) 2568 size_t len_b, bool *consecutive)
2570{ 2569{
2571 uint64_t tsc_a, tsc_b; 2570 uint64_t tsc_a, tsc_b;
2572 unsigned char *p; 2571 unsigned char *p;
2573 size_t len; 2572 size_t len, rem_a, rem_b;
2574 2573
2575 p = intel_pt_last_psb(buf_a, len_a); 2574 p = intel_pt_last_psb(buf_a, len_a);
2576 if (!p) 2575 if (!p)
2577 return buf_b; /* No PSB in buf_a => no overlap */ 2576 return buf_b; /* No PSB in buf_a => no overlap */
2578 2577
2579 len = len_a - (p - buf_a); 2578 len = len_a - (p - buf_a);
2580 if (!intel_pt_next_tsc(p, len, &tsc_a)) { 2579 if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a)) {
2581 /* The last PSB+ in buf_a is incomplete, so go back one more */ 2580 /* The last PSB+ in buf_a is incomplete, so go back one more */
2582 len_a -= len; 2581 len_a -= len;
2583 p = intel_pt_last_psb(buf_a, len_a); 2582 p = intel_pt_last_psb(buf_a, len_a);
2584 if (!p) 2583 if (!p)
2585 return buf_b; /* No full PSB+ => assume no overlap */ 2584 return buf_b; /* No full PSB+ => assume no overlap */
2586 len = len_a - (p - buf_a); 2585 len = len_a - (p - buf_a);
2587 if (!intel_pt_next_tsc(p, len, &tsc_a)) 2586 if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a))
2588 return buf_b; /* No TSC in buf_a => assume no overlap */ 2587 return buf_b; /* No TSC in buf_a => assume no overlap */
2589 } 2588 }
2590 2589
2591 while (1) { 2590 while (1) {
2592 /* Ignore PSB+ with no TSC */ 2591 /* Ignore PSB+ with no TSC */
2593 if (intel_pt_next_tsc(buf_b, len_b, &tsc_b) && 2592 if (intel_pt_next_tsc(buf_b, len_b, &tsc_b, &rem_b)) {
2594 intel_pt_tsc_cmp(tsc_a, tsc_b) < 0) 2593 int cmp = intel_pt_tsc_cmp(tsc_a, tsc_b);
2595 return buf_b; /* tsc_a < tsc_b => no overlap */ 2594
2595 /* Same TSC, so buffers are consecutive */
2596 if (!cmp && rem_b >= rem_a) {
2597 *consecutive = true;
2598 return buf_b + len_b - (rem_b - rem_a);
2599 }
2600 if (cmp < 0)
2601 return buf_b; /* tsc_a < tsc_b => no overlap */
2602 }
2596 2603
2597 if (!intel_pt_step_psb(&buf_b, &len_b)) 2604 if (!intel_pt_step_psb(&buf_b, &len_b))
2598 return buf_b + len_b; /* No PSB in buf_b => no data */ 2605 return buf_b + len_b; /* No PSB in buf_b => no data */
@@ -2606,6 +2613,8 @@ static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2606 * @buf_b: second buffer 2613 * @buf_b: second buffer
2607 * @len_b: size of second buffer 2614 * @len_b: size of second buffer
2608 * @have_tsc: can use TSC packets to detect overlap 2615 * @have_tsc: can use TSC packets to detect overlap
2616 * @consecutive: returns true if there is data in buf_b that is consecutive
2617 * to buf_a
2609 * 2618 *
2610 * When trace samples or snapshots are recorded there is the possibility that 2619 * When trace samples or snapshots are recorded there is the possibility that
2611 * the data overlaps. Note that, for the purposes of decoding, data is only 2620 * the data overlaps. Note that, for the purposes of decoding, data is only
@@ -2616,7 +2625,7 @@ static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2616 */ 2625 */
2617unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 2626unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2618 unsigned char *buf_b, size_t len_b, 2627 unsigned char *buf_b, size_t len_b,
2619 bool have_tsc) 2628 bool have_tsc, bool *consecutive)
2620{ 2629{
2621 unsigned char *found; 2630 unsigned char *found;
2622 2631
@@ -2628,7 +2637,8 @@ unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2628 return buf_b; /* No overlap */ 2637 return buf_b; /* No overlap */
2629 2638
2630 if (have_tsc) { 2639 if (have_tsc) {
2631 found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b); 2640 found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b,
2641 consecutive);
2632 if (found) 2642 if (found)
2633 return found; 2643 return found;
2634 } 2644 }
@@ -2643,28 +2653,16 @@ unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2643 } 2653 }
2644 2654
2645 /* Now len_b >= len_a */ 2655 /* Now len_b >= len_a */
2646 if (len_b > len_a) {
2647 /* The leftover buffer 'b' must start at a PSB */
2648 while (!intel_pt_at_psb(buf_b + len_a, len_b - len_a)) {
2649 if (!intel_pt_step_psb(&buf_a, &len_a))
2650 return buf_b; /* No overlap */
2651 }
2652 }
2653
2654 while (1) { 2656 while (1) {
2655 /* Potential overlap so check the bytes */ 2657 /* Potential overlap so check the bytes */
2656 found = memmem(buf_a, len_a, buf_b, len_a); 2658 found = memmem(buf_a, len_a, buf_b, len_a);
2657 if (found) 2659 if (found) {
2660 *consecutive = true;
2658 return buf_b + len_a; 2661 return buf_b + len_a;
2662 }
2659 2663
2660 /* Try again at next PSB in buffer 'a' */ 2664 /* Try again at next PSB in buffer 'a' */
2661 if (!intel_pt_step_psb(&buf_a, &len_a)) 2665 if (!intel_pt_step_psb(&buf_a, &len_a))
2662 return buf_b; /* No overlap */ 2666 return buf_b; /* No overlap */
2663
2664 /* The leftover buffer 'b' must start at a PSB */
2665 while (!intel_pt_at_psb(buf_b + len_a, len_b - len_a)) {
2666 if (!intel_pt_step_psb(&buf_a, &len_a))
2667 return buf_b; /* No overlap */
2668 }
2669 } 2667 }
2670} 2668}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 921b22e8ca0e..fc1752d50019 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -117,7 +117,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder);
117 117
118unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 118unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
119 unsigned char *buf_b, size_t len_b, 119 unsigned char *buf_b, size_t len_b,
120 bool have_tsc); 120 bool have_tsc, bool *consecutive);
121 121
122int intel_pt__strerror(int code, char *buf, size_t buflen); 122int intel_pt__strerror(int code, char *buf, size_t buflen);
123 123
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 3773d9c54f45..0effaff57020 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -132,6 +132,7 @@ struct intel_pt_queue {
132 struct intel_pt *pt; 132 struct intel_pt *pt;
133 unsigned int queue_nr; 133 unsigned int queue_nr;
134 struct auxtrace_buffer *buffer; 134 struct auxtrace_buffer *buffer;
135 struct auxtrace_buffer *old_buffer;
135 void *decoder; 136 void *decoder;
136 const struct intel_pt_state *state; 137 const struct intel_pt_state *state;
137 struct ip_callchain *chain; 138 struct ip_callchain *chain;
@@ -143,6 +144,7 @@ struct intel_pt_queue {
143 bool stop; 144 bool stop;
144 bool step_through_buffers; 145 bool step_through_buffers;
145 bool use_buffer_pid_tid; 146 bool use_buffer_pid_tid;
147 bool sync_switch;
146 pid_t pid, tid; 148 pid_t pid, tid;
147 int cpu; 149 int cpu;
148 int switch_state; 150 int switch_state;
@@ -207,49 +209,28 @@ static void intel_pt_dump_event(struct intel_pt *pt, unsigned char *buf,
207static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a, 209static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a,
208 struct auxtrace_buffer *b) 210 struct auxtrace_buffer *b)
209{ 211{
212 bool consecutive = false;
210 void *start; 213 void *start;
211 214
212 start = intel_pt_find_overlap(a->data, a->size, b->data, b->size, 215 start = intel_pt_find_overlap(a->data, a->size, b->data, b->size,
213 pt->have_tsc); 216 pt->have_tsc, &consecutive);
214 if (!start) 217 if (!start)
215 return -EINVAL; 218 return -EINVAL;
216 b->use_size = b->data + b->size - start; 219 b->use_size = b->data + b->size - start;
217 b->use_data = start; 220 b->use_data = start;
221 if (b->use_size && consecutive)
222 b->consecutive = true;
218 return 0; 223 return 0;
219} 224}
220 225
221static void intel_pt_use_buffer_pid_tid(struct intel_pt_queue *ptq,
222 struct auxtrace_queue *queue,
223 struct auxtrace_buffer *buffer)
224{
225 if (queue->cpu == -1 && buffer->cpu != -1)
226 ptq->cpu = buffer->cpu;
227
228 ptq->pid = buffer->pid;
229 ptq->tid = buffer->tid;
230
231 intel_pt_log("queue %u cpu %d pid %d tid %d\n",
232 ptq->queue_nr, ptq->cpu, ptq->pid, ptq->tid);
233
234 thread__zput(ptq->thread);
235
236 if (ptq->tid != -1) {
237 if (ptq->pid != -1)
238 ptq->thread = machine__findnew_thread(ptq->pt->machine,
239 ptq->pid,
240 ptq->tid);
241 else
242 ptq->thread = machine__find_thread(ptq->pt->machine, -1,
243 ptq->tid);
244 }
245}
246
247/* This function assumes data is processed sequentially only */ 226/* This function assumes data is processed sequentially only */
248static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) 227static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
249{ 228{
250 struct intel_pt_queue *ptq = data; 229 struct intel_pt_queue *ptq = data;
251 struct auxtrace_buffer *buffer = ptq->buffer, *old_buffer = buffer; 230 struct auxtrace_buffer *buffer = ptq->buffer;
231 struct auxtrace_buffer *old_buffer = ptq->old_buffer;
252 struct auxtrace_queue *queue; 232 struct auxtrace_queue *queue;
233 bool might_overlap;
253 234
254 if (ptq->stop) { 235 if (ptq->stop) {
255 b->len = 0; 236 b->len = 0;
@@ -257,7 +238,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
257 } 238 }
258 239
259 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 240 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
260next: 241
261 buffer = auxtrace_buffer__next(queue, buffer); 242 buffer = auxtrace_buffer__next(queue, buffer);
262 if (!buffer) { 243 if (!buffer) {
263 if (old_buffer) 244 if (old_buffer)
@@ -276,7 +257,8 @@ next:
276 return -ENOMEM; 257 return -ENOMEM;
277 } 258 }
278 259
279 if (ptq->pt->snapshot_mode && !buffer->consecutive && old_buffer && 260 might_overlap = ptq->pt->snapshot_mode || ptq->pt->sampling_mode;
261 if (might_overlap && !buffer->consecutive && old_buffer &&
280 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 262 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
281 return -ENOMEM; 263 return -ENOMEM;
282 264
@@ -289,33 +271,24 @@ next:
289 } 271 }
290 b->ref_timestamp = buffer->reference; 272 b->ref_timestamp = buffer->reference;
291 273
292 /* 274 if (!old_buffer || (might_overlap && !buffer->consecutive)) {
293 * If in snapshot mode and the buffer has no usable data, get next
294 * buffer and again check overlap against old_buffer.
295 */
296 if (ptq->pt->snapshot_mode && !b->len)
297 goto next;
298
299 if (old_buffer)
300 auxtrace_buffer__drop_data(old_buffer);
301
302 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
303 !buffer->consecutive)) {
304 b->consecutive = false; 275 b->consecutive = false;
305 b->trace_nr = buffer->buffer_nr + 1; 276 b->trace_nr = buffer->buffer_nr + 1;
306 } else { 277 } else {
307 b->consecutive = true; 278 b->consecutive = true;
308 } 279 }
309 280
310 if (ptq->use_buffer_pid_tid && (ptq->pid != buffer->pid ||
311 ptq->tid != buffer->tid))
312 intel_pt_use_buffer_pid_tid(ptq, queue, buffer);
313
314 if (ptq->step_through_buffers) 281 if (ptq->step_through_buffers)
315 ptq->stop = true; 282 ptq->stop = true;
316 283
317 if (!b->len) 284 if (b->len) {
285 if (old_buffer)
286 auxtrace_buffer__drop_data(old_buffer);
287 ptq->old_buffer = buffer;
288 } else {
289 auxtrace_buffer__drop_data(buffer);
318 return intel_pt_get_trace(b, data); 290 return intel_pt_get_trace(b, data);
291 }
319 292
320 return 0; 293 return 0;
321} 294}
@@ -954,16 +927,15 @@ static int intel_pt_setup_queue(struct intel_pt *pt,
954 ptq->cpu = queue->cpu; 927 ptq->cpu = queue->cpu;
955 ptq->tid = queue->tid; 928 ptq->tid = queue->tid;
956 929
957 if (pt->sampling_mode) { 930 if (pt->sampling_mode && !pt->snapshot_mode &&
958 if (pt->timeless_decoding) 931 pt->timeless_decoding)
959 ptq->step_through_buffers = true; 932 ptq->step_through_buffers = true;
960 if (pt->timeless_decoding || !pt->have_sched_switch) 933
961 ptq->use_buffer_pid_tid = true; 934 ptq->sync_switch = pt->sync_switch;
962 }
963 } 935 }
964 936
965 if (!ptq->on_heap && 937 if (!ptq->on_heap &&
966 (!pt->sync_switch || 938 (!ptq->sync_switch ||
967 ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) { 939 ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) {
968 const struct intel_pt_state *state; 940 const struct intel_pt_state *state;
969 int ret; 941 int ret;
@@ -1546,7 +1518,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1546 if (pt->synth_opts.last_branch) 1518 if (pt->synth_opts.last_branch)
1547 intel_pt_update_last_branch_rb(ptq); 1519 intel_pt_update_last_branch_rb(ptq);
1548 1520
1549 if (!pt->sync_switch) 1521 if (!ptq->sync_switch)
1550 return 0; 1522 return 0;
1551 1523
1552 if (intel_pt_is_switch_ip(ptq, state->to_ip)) { 1524 if (intel_pt_is_switch_ip(ptq, state->to_ip)) {
@@ -1627,6 +1599,21 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1627 return switch_ip; 1599 return switch_ip;
1628} 1600}
1629 1601
1602static void intel_pt_enable_sync_switch(struct intel_pt *pt)
1603{
1604 unsigned int i;
1605
1606 pt->sync_switch = true;
1607
1608 for (i = 0; i < pt->queues.nr_queues; i++) {
1609 struct auxtrace_queue *queue = &pt->queues.queue_array[i];
1610 struct intel_pt_queue *ptq = queue->priv;
1611
1612 if (ptq)
1613 ptq->sync_switch = true;
1614 }
1615}
1616
1630static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) 1617static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1631{ 1618{
1632 const struct intel_pt_state *state = ptq->state; 1619 const struct intel_pt_state *state = ptq->state;
@@ -1643,7 +1630,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1643 if (pt->switch_ip) { 1630 if (pt->switch_ip) {
1644 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", 1631 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n",
1645 pt->switch_ip, pt->ptss_ip); 1632 pt->switch_ip, pt->ptss_ip);
1646 pt->sync_switch = true; 1633 intel_pt_enable_sync_switch(pt);
1647 } 1634 }
1648 } 1635 }
1649 } 1636 }
@@ -1659,9 +1646,9 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1659 if (state->err) { 1646 if (state->err) {
1660 if (state->err == INTEL_PT_ERR_NODATA) 1647 if (state->err == INTEL_PT_ERR_NODATA)
1661 return 1; 1648 return 1;
1662 if (pt->sync_switch && 1649 if (ptq->sync_switch &&
1663 state->from_ip >= pt->kernel_start) { 1650 state->from_ip >= pt->kernel_start) {
1664 pt->sync_switch = false; 1651 ptq->sync_switch = false;
1665 intel_pt_next_tid(pt, ptq); 1652 intel_pt_next_tid(pt, ptq);
1666 } 1653 }
1667 if (pt->synth_opts.errors) { 1654 if (pt->synth_opts.errors) {
@@ -1687,7 +1674,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1687 state->timestamp, state->est_timestamp); 1674 state->timestamp, state->est_timestamp);
1688 ptq->timestamp = state->est_timestamp; 1675 ptq->timestamp = state->est_timestamp;
1689 /* Use estimated TSC in unknown switch state */ 1676 /* Use estimated TSC in unknown switch state */
1690 } else if (pt->sync_switch && 1677 } else if (ptq->sync_switch &&
1691 ptq->switch_state == INTEL_PT_SS_UNKNOWN && 1678 ptq->switch_state == INTEL_PT_SS_UNKNOWN &&
1692 intel_pt_is_switch_ip(ptq, state->to_ip) && 1679 intel_pt_is_switch_ip(ptq, state->to_ip) &&
1693 ptq->next_tid == -1) { 1680 ptq->next_tid == -1) {
@@ -1834,7 +1821,7 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
1834 return 1; 1821 return 1;
1835 1822
1836 ptq = intel_pt_cpu_to_ptq(pt, cpu); 1823 ptq = intel_pt_cpu_to_ptq(pt, cpu);
1837 if (!ptq) 1824 if (!ptq || !ptq->sync_switch)
1838 return 1; 1825 return 1;
1839 1826
1840 switch (ptq->switch_state) { 1827 switch (ptq->switch_state) {
@@ -2075,9 +2062,6 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session,
2075 struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt, 2062 struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
2076 auxtrace); 2063 auxtrace);
2077 2064
2078 if (pt->sampling_mode)
2079 return 0;
2080
2081 if (!pt->data_queued) { 2065 if (!pt->data_queued) {
2082 struct auxtrace_buffer *buffer; 2066 struct auxtrace_buffer *buffer;
2083 off_t data_offset; 2067 off_t data_offset;
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 4952b429caa7..1cca0a2fa641 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -433,6 +433,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
433 char serr[STRERR_BUFSIZE]; 433 char serr[STRERR_BUFSIZE];
434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL; 434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
435 const char *template = llvm_param.clang_bpf_cmd_template; 435 const char *template = llvm_param.clang_bpf_cmd_template;
436 char *command_echo, *command_out;
436 437
437 if (path[0] != '-' && realpath(path, abspath) == NULL) { 438 if (path[0] != '-' && realpath(path, abspath) == NULL) {
438 err = errno; 439 err = errno;
@@ -487,6 +488,16 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
487 (path[0] == '-') ? path : abspath); 488 (path[0] == '-') ? path : abspath);
488 489
489 pr_debug("llvm compiling command template: %s\n", template); 490 pr_debug("llvm compiling command template: %s\n", template);
491
492 if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
493 goto errout;
494
495 err = read_from_pipe(command_echo, (void **) &command_out, NULL);
496 if (err)
497 goto errout;
498
499 pr_debug("llvm compiling command : %s\n", command_out);
500
490 err = read_from_pipe(template, &obj_buf, &obj_buf_sz); 501 err = read_from_pipe(template, &obj_buf, &obj_buf_sz);
491 if (err) { 502 if (err) {
492 pr_err("ERROR:\tunable to compile %s\n", path); 503 pr_err("ERROR:\tunable to compile %s\n", path);
@@ -497,6 +508,8 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
497 goto errout; 508 goto errout;
498 } 509 }
499 510
511 free(command_echo);
512 free(command_out);
500 free(kbuild_dir); 513 free(kbuild_dir);
501 free(kbuild_include_opts); 514 free(kbuild_include_opts);
502 515
@@ -509,6 +522,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
509 *p_obj_buf_sz = obj_buf_sz; 522 *p_obj_buf_sz = obj_buf_sz;
510 return 0; 523 return 0;
511errout: 524errout:
525 free(command_echo);
512 free(kbuild_dir); 526 free(kbuild_dir);
513 free(kbuild_include_opts); 527 free(kbuild_include_opts);
514 free(obj_buf); 528 free(obj_buf);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b05a67464c03..32d50492505d 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -48,8 +48,23 @@ static void machine__threads_init(struct machine *machine)
48 } 48 }
49} 49}
50 50
51static int machine__set_mmap_name(struct machine *machine)
52{
53 if (machine__is_host(machine))
54 machine->mmap_name = strdup("[kernel.kallsyms]");
55 else if (machine__is_default_guest(machine))
56 machine->mmap_name = strdup("[guest.kernel.kallsyms]");
57 else if (asprintf(&machine->mmap_name, "[guest.kernel.kallsyms.%d]",
58 machine->pid) < 0)
59 machine->mmap_name = NULL;
60
61 return machine->mmap_name ? 0 : -ENOMEM;
62}
63
51int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 64int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
52{ 65{
66 int err = -ENOMEM;
67
53 memset(machine, 0, sizeof(*machine)); 68 memset(machine, 0, sizeof(*machine));
54 map_groups__init(&machine->kmaps, machine); 69 map_groups__init(&machine->kmaps, machine);
55 RB_CLEAR_NODE(&machine->rb_node); 70 RB_CLEAR_NODE(&machine->rb_node);
@@ -73,13 +88,16 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
73 if (machine->root_dir == NULL) 88 if (machine->root_dir == NULL)
74 return -ENOMEM; 89 return -ENOMEM;
75 90
91 if (machine__set_mmap_name(machine))
92 goto out;
93
76 if (pid != HOST_KERNEL_ID) { 94 if (pid != HOST_KERNEL_ID) {
77 struct thread *thread = machine__findnew_thread(machine, -1, 95 struct thread *thread = machine__findnew_thread(machine, -1,
78 pid); 96 pid);
79 char comm[64]; 97 char comm[64];
80 98
81 if (thread == NULL) 99 if (thread == NULL)
82 return -ENOMEM; 100 goto out;
83 101
84 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 102 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
85 thread__set_comm(thread, comm, 0); 103 thread__set_comm(thread, comm, 0);
@@ -87,7 +105,13 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
87 } 105 }
88 106
89 machine->current_tid = NULL; 107 machine->current_tid = NULL;
108 err = 0;
90 109
110out:
111 if (err) {
112 zfree(&machine->root_dir);
113 zfree(&machine->mmap_name);
114 }
91 return 0; 115 return 0;
92} 116}
93 117
@@ -119,7 +143,7 @@ struct machine *machine__new_kallsyms(void)
119 * ask for not using the kcore parsing code, once this one is fixed 143 * ask for not using the kcore parsing code, once this one is fixed
120 * to create a map per module. 144 * to create a map per module.
121 */ 145 */
122 if (machine && __machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION, true) <= 0) { 146 if (machine && machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION) <= 0) {
123 machine__delete(machine); 147 machine__delete(machine);
124 machine = NULL; 148 machine = NULL;
125 } 149 }
@@ -180,6 +204,7 @@ void machine__exit(struct machine *machine)
180 dsos__exit(&machine->dsos); 204 dsos__exit(&machine->dsos);
181 machine__exit_vdso(machine); 205 machine__exit_vdso(machine);
182 zfree(&machine->root_dir); 206 zfree(&machine->root_dir);
207 zfree(&machine->mmap_name);
183 zfree(&machine->current_tid); 208 zfree(&machine->current_tid);
184 209
185 for (i = 0; i < THREADS__TABLE_SIZE; i++) { 210 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
@@ -322,20 +347,6 @@ void machines__process_guests(struct machines *machines,
322 } 347 }
323} 348}
324 349
325char *machine__mmap_name(struct machine *machine, char *bf, size_t size)
326{
327 if (machine__is_host(machine))
328 snprintf(bf, size, "[%s]", "kernel.kallsyms");
329 else if (machine__is_default_guest(machine))
330 snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
331 else {
332 snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms",
333 machine->pid);
334 }
335
336 return bf;
337}
338
339void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size) 350void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
340{ 351{
341 struct rb_node *node; 352 struct rb_node *node;
@@ -771,24 +782,18 @@ size_t machine__fprintf(struct machine *machine, FILE *fp)
771 782
772static struct dso *machine__get_kernel(struct machine *machine) 783static struct dso *machine__get_kernel(struct machine *machine)
773{ 784{
774 const char *vmlinux_name = NULL; 785 const char *vmlinux_name = machine->mmap_name;
775 struct dso *kernel; 786 struct dso *kernel;
776 787
777 if (machine__is_host(machine)) { 788 if (machine__is_host(machine)) {
778 vmlinux_name = symbol_conf.vmlinux_name; 789 if (symbol_conf.vmlinux_name)
779 if (!vmlinux_name) 790 vmlinux_name = symbol_conf.vmlinux_name;
780 vmlinux_name = DSO__NAME_KALLSYMS;
781 791
782 kernel = machine__findnew_kernel(machine, vmlinux_name, 792 kernel = machine__findnew_kernel(machine, vmlinux_name,
783 "[kernel]", DSO_TYPE_KERNEL); 793 "[kernel]", DSO_TYPE_KERNEL);
784 } else { 794 } else {
785 char bf[PATH_MAX]; 795 if (symbol_conf.default_guest_vmlinux_name)
786
787 if (machine__is_default_guest(machine))
788 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 796 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
789 if (!vmlinux_name)
790 vmlinux_name = machine__mmap_name(machine, bf,
791 sizeof(bf));
792 797
793 kernel = machine__findnew_kernel(machine, vmlinux_name, 798 kernel = machine__findnew_kernel(machine, vmlinux_name,
794 "[guest.kernel]", 799 "[guest.kernel]",
@@ -849,13 +854,10 @@ static int machine__get_running_kernel_start(struct machine *machine,
849 return 0; 854 return 0;
850} 855}
851 856
852int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 857static int
858__machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
853{ 859{
854 int type; 860 int type;
855 u64 start = 0;
856
857 if (machine__get_running_kernel_start(machine, NULL, &start))
858 return -1;
859 861
860 /* In case of renewal the kernel map, destroy previous one */ 862 /* In case of renewal the kernel map, destroy previous one */
861 machine__destroy_kernel_maps(machine); 863 machine__destroy_kernel_maps(machine);
@@ -864,7 +866,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
864 struct kmap *kmap; 866 struct kmap *kmap;
865 struct map *map; 867 struct map *map;
866 868
867 machine->vmlinux_maps[type] = map__new2(start, kernel, type); 869 machine->vmlinux_maps[type] = map__new2(0, kernel, type);
868 if (machine->vmlinux_maps[type] == NULL) 870 if (machine->vmlinux_maps[type] == NULL)
869 return -1; 871 return -1;
870 872
@@ -987,11 +989,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
987 return machine__create_kernel_maps(machine); 989 return machine__create_kernel_maps(machine);
988} 990}
989 991
990int __machine__load_kallsyms(struct machine *machine, const char *filename, 992int machine__load_kallsyms(struct machine *machine, const char *filename,
991 enum map_type type, bool no_kcore) 993 enum map_type type)
992{ 994{
993 struct map *map = machine__kernel_map(machine); 995 struct map *map = machine__kernel_map(machine);
994 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore); 996 int ret = __dso__load_kallsyms(map->dso, filename, map, true);
995 997
996 if (ret > 0) { 998 if (ret > 0) {
997 dso__set_loaded(map->dso, type); 999 dso__set_loaded(map->dso, type);
@@ -1006,12 +1008,6 @@ int __machine__load_kallsyms(struct machine *machine, const char *filename,
1006 return ret; 1008 return ret;
1007} 1009}
1008 1010
1009int machine__load_kallsyms(struct machine *machine, const char *filename,
1010 enum map_type type)
1011{
1012 return __machine__load_kallsyms(machine, filename, type, false);
1013}
1014
1015int machine__load_vmlinux_path(struct machine *machine, enum map_type type) 1011int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
1016{ 1012{
1017 struct map *map = machine__kernel_map(machine); 1013 struct map *map = machine__kernel_map(machine);
@@ -1023,13 +1019,6 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
1023 return ret; 1019 return ret;
1024} 1020}
1025 1021
1026static void map_groups__fixup_end(struct map_groups *mg)
1027{
1028 int i;
1029 for (i = 0; i < MAP__NR_TYPES; ++i)
1030 __map_groups__fixup_end(mg, i);
1031}
1032
1033static char *get_kernel_version(const char *root_dir) 1022static char *get_kernel_version(const char *root_dir)
1034{ 1023{
1035 char version[PATH_MAX]; 1024 char version[PATH_MAX];
@@ -1215,10 +1204,29 @@ static int machine__create_modules(struct machine *machine)
1215 return 0; 1204 return 0;
1216} 1205}
1217 1206
1207static void machine__set_kernel_mmap(struct machine *machine,
1208 u64 start, u64 end)
1209{
1210 int i;
1211
1212 for (i = 0; i < MAP__NR_TYPES; i++) {
1213 machine->vmlinux_maps[i]->start = start;
1214 machine->vmlinux_maps[i]->end = end;
1215
1216 /*
1217 * Be a bit paranoid here, some perf.data file came with
1218 * a zero sized synthesized MMAP event for the kernel.
1219 */
1220 if (start == 0 && end == 0)
1221 machine->vmlinux_maps[i]->end = ~0ULL;
1222 }
1223}
1224
1218int machine__create_kernel_maps(struct machine *machine) 1225int machine__create_kernel_maps(struct machine *machine)
1219{ 1226{
1220 struct dso *kernel = machine__get_kernel(machine); 1227 struct dso *kernel = machine__get_kernel(machine);
1221 const char *name = NULL; 1228 const char *name = NULL;
1229 struct map *map;
1222 u64 addr = 0; 1230 u64 addr = 0;
1223 int ret; 1231 int ret;
1224 1232
@@ -1239,38 +1247,32 @@ int machine__create_kernel_maps(struct machine *machine)
1239 "continuing anyway...\n", machine->pid); 1247 "continuing anyway...\n", machine->pid);
1240 } 1248 }
1241 1249
1242 /*
1243 * Now that we have all the maps created, just set the ->end of them:
1244 */
1245 map_groups__fixup_end(&machine->kmaps);
1246
1247 if (!machine__get_running_kernel_start(machine, &name, &addr)) { 1250 if (!machine__get_running_kernel_start(machine, &name, &addr)) {
1248 if (name && 1251 if (name &&
1249 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { 1252 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1250 machine__destroy_kernel_maps(machine); 1253 machine__destroy_kernel_maps(machine);
1251 return -1; 1254 return -1;
1252 } 1255 }
1253 }
1254 1256
1255 return 0; 1257 /* we have a real start address now, so re-order the kmaps */
1256} 1258 map = machine__kernel_map(machine);
1257 1259
1258static void machine__set_kernel_mmap_len(struct machine *machine, 1260 map__get(map);
1259 union perf_event *event) 1261 map_groups__remove(&machine->kmaps, map);
1260{
1261 int i;
1262 1262
1263 for (i = 0; i < MAP__NR_TYPES; i++) { 1263 /* assume it's the last in the kmaps */
1264 machine->vmlinux_maps[i]->start = event->mmap.start; 1264 machine__set_kernel_mmap(machine, addr, ~0ULL);
1265 machine->vmlinux_maps[i]->end = (event->mmap.start + 1265
1266 event->mmap.len); 1266 map_groups__insert(&machine->kmaps, map);
1267 /* 1267 map__put(map);
1268 * Be a bit paranoid here, some perf.data file came with
1269 * a zero sized synthesized MMAP event for the kernel.
1270 */
1271 if (machine->vmlinux_maps[i]->end == 0)
1272 machine->vmlinux_maps[i]->end = ~0ULL;
1273 } 1268 }
1269
1270 /* update end address of the kernel map using adjacent module address */
1271 map = map__next(machine__kernel_map(machine));
1272 if (map)
1273 machine__set_kernel_mmap(machine, addr, map->start);
1274
1275 return 0;
1274} 1276}
1275 1277
1276static bool machine__uses_kcore(struct machine *machine) 1278static bool machine__uses_kcore(struct machine *machine)
@@ -1289,7 +1291,6 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1289 union perf_event *event) 1291 union perf_event *event)
1290{ 1292{
1291 struct map *map; 1293 struct map *map;
1292 char kmmap_prefix[PATH_MAX];
1293 enum dso_kernel_type kernel_type; 1294 enum dso_kernel_type kernel_type;
1294 bool is_kernel_mmap; 1295 bool is_kernel_mmap;
1295 1296
@@ -1297,15 +1298,14 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1297 if (machine__uses_kcore(machine)) 1298 if (machine__uses_kcore(machine))
1298 return 0; 1299 return 0;
1299 1300
1300 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
1301 if (machine__is_host(machine)) 1301 if (machine__is_host(machine))
1302 kernel_type = DSO_TYPE_KERNEL; 1302 kernel_type = DSO_TYPE_KERNEL;
1303 else 1303 else
1304 kernel_type = DSO_TYPE_GUEST_KERNEL; 1304 kernel_type = DSO_TYPE_GUEST_KERNEL;
1305 1305
1306 is_kernel_mmap = memcmp(event->mmap.filename, 1306 is_kernel_mmap = memcmp(event->mmap.filename,
1307 kmmap_prefix, 1307 machine->mmap_name,
1308 strlen(kmmap_prefix) - 1) == 0; 1308 strlen(machine->mmap_name) - 1) == 0;
1309 if (event->mmap.filename[0] == '/' || 1309 if (event->mmap.filename[0] == '/' ||
1310 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1310 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
1311 map = machine__findnew_module_map(machine, event->mmap.start, 1311 map = machine__findnew_module_map(machine, event->mmap.start,
@@ -1316,7 +1316,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1316 map->end = map->start + event->mmap.len; 1316 map->end = map->start + event->mmap.len;
1317 } else if (is_kernel_mmap) { 1317 } else if (is_kernel_mmap) {
1318 const char *symbol_name = (event->mmap.filename + 1318 const char *symbol_name = (event->mmap.filename +
1319 strlen(kmmap_prefix)); 1319 strlen(machine->mmap_name));
1320 /* 1320 /*
1321 * Should be there already, from the build-id table in 1321 * Should be there already, from the build-id table in
1322 * the header. 1322 * the header.
@@ -1357,7 +1357,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1357 up_read(&machine->dsos.lock); 1357 up_read(&machine->dsos.lock);
1358 1358
1359 if (kernel == NULL) 1359 if (kernel == NULL)
1360 kernel = machine__findnew_dso(machine, kmmap_prefix); 1360 kernel = machine__findnew_dso(machine, machine->mmap_name);
1361 if (kernel == NULL) 1361 if (kernel == NULL)
1362 goto out_problem; 1362 goto out_problem;
1363 1363
@@ -1370,7 +1370,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1370 if (strstr(kernel->long_name, "vmlinux")) 1370 if (strstr(kernel->long_name, "vmlinux"))
1371 dso__set_short_name(kernel, "[kernel.vmlinux]", false); 1371 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
1372 1372
1373 machine__set_kernel_mmap_len(machine, event); 1373 machine__set_kernel_mmap(machine, event->mmap.start,
1374 event->mmap.start + event->mmap.len);
1374 1375
1375 /* 1376 /*
1376 * Avoid using a zero address (kptr_restrict) for the ref reloc 1377 * Avoid using a zero address (kptr_restrict) for the ref reloc
@@ -1700,7 +1701,7 @@ static void ip__resolve_data(struct thread *thread,
1700struct mem_info *sample__resolve_mem(struct perf_sample *sample, 1701struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1701 struct addr_location *al) 1702 struct addr_location *al)
1702{ 1703{
1703 struct mem_info *mi = zalloc(sizeof(*mi)); 1704 struct mem_info *mi = mem_info__new();
1704 1705
1705 if (!mi) 1706 if (!mi)
1706 return NULL; 1707 return NULL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 5ce860b64c74..66cc200ef86f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -43,6 +43,7 @@ struct machine {
43 bool comm_exec; 43 bool comm_exec;
44 bool kptr_restrict_warned; 44 bool kptr_restrict_warned;
45 char *root_dir; 45 char *root_dir;
46 char *mmap_name;
46 struct threads threads[THREADS__TABLE_SIZE]; 47 struct threads threads[THREADS__TABLE_SIZE];
47 struct vdso_info *vdso_info; 48 struct vdso_info *vdso_info;
48 struct perf_env *env; 49 struct perf_env *env;
@@ -142,8 +143,6 @@ struct machine *machines__find(struct machines *machines, pid_t pid);
142struct machine *machines__findnew(struct machines *machines, pid_t pid); 143struct machine *machines__findnew(struct machines *machines, pid_t pid);
143 144
144void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); 145void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
145char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
146
147void machines__set_comm_exec(struct machines *machines, bool comm_exec); 146void machines__set_comm_exec(struct machines *machines, bool comm_exec);
148 147
149struct machine *machine__new_host(void); 148struct machine *machine__new_host(void);
@@ -226,8 +225,6 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
226 const char *filename); 225 const char *filename);
227int arch__fix_module_text_start(u64 *start, const char *name); 226int arch__fix_module_text_start(u64 *start, const char *name);
228 227
229int __machine__load_kallsyms(struct machine *machine, const char *filename,
230 enum map_type type, bool no_kcore);
231int machine__load_kallsyms(struct machine *machine, const char *filename, 228int machine__load_kallsyms(struct machine *machine, const char *filename,
232 enum map_type type); 229 enum map_type type);
233int machine__load_vmlinux_path(struct machine *machine, enum map_type type); 230int machine__load_vmlinux_path(struct machine *machine, enum map_type type);
@@ -239,7 +236,6 @@ size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
239 bool (skip)(struct dso *dso, int parm), int parm); 236 bool (skip)(struct dso *dso, int parm), int parm);
240 237
241void machine__destroy_kernel_maps(struct machine *machine); 238void machine__destroy_kernel_maps(struct machine *machine);
242int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
243int machine__create_kernel_maps(struct machine *machine); 239int machine__create_kernel_maps(struct machine *machine);
244 240
245int machines__create_kernel_maps(struct machines *machines, pid_t pid); 241int machines__create_kernel_maps(struct machines *machines, pid_t pid);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index edeb7291c8e1..0e9bbe01b0ab 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -103,6 +103,10 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
103 return ip; 103 return ip;
104} 104}
105 105
106static inline size_t map__size(const struct map *map)
107{
108 return map->end - map->start;
109}
106 110
107/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 111/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
108u64 map__rip_2objdump(struct map *map, u64 rip); 112u64 map__rip_2objdump(struct map *map, u64 rip);
diff --git a/tools/perf/util/mem2node.c b/tools/perf/util/mem2node.c
new file mode 100644
index 000000000000..c6fd81c02586
--- /dev/null
+++ b/tools/perf/util/mem2node.c
@@ -0,0 +1,134 @@
1#include <errno.h>
2#include <inttypes.h>
3#include <linux/bitmap.h>
4#include "mem2node.h"
5#include "util.h"
6
7struct phys_entry {
8 struct rb_node rb_node;
9 u64 start;
10 u64 end;
11 u64 node;
12};
13
14static void phys_entry__insert(struct phys_entry *entry, struct rb_root *root)
15{
16 struct rb_node **p = &root->rb_node;
17 struct rb_node *parent = NULL;
18 struct phys_entry *e;
19
20 while (*p != NULL) {
21 parent = *p;
22 e = rb_entry(parent, struct phys_entry, rb_node);
23
24 if (entry->start < e->start)
25 p = &(*p)->rb_left;
26 else
27 p = &(*p)->rb_right;
28 }
29
30 rb_link_node(&entry->rb_node, parent, p);
31 rb_insert_color(&entry->rb_node, root);
32}
33
34static void
35phys_entry__init(struct phys_entry *entry, u64 start, u64 bsize, u64 node)
36{
37 entry->start = start;
38 entry->end = start + bsize;
39 entry->node = node;
40 RB_CLEAR_NODE(&entry->rb_node);
41}
42
43int mem2node__init(struct mem2node *map, struct perf_env *env)
44{
45 struct memory_node *n, *nodes = &env->memory_nodes[0];
46 struct phys_entry *entries, *tmp_entries;
47 u64 bsize = env->memory_bsize;
48 int i, j = 0, max = 0;
49
50 memset(map, 0x0, sizeof(*map));
51 map->root = RB_ROOT;
52
53 for (i = 0; i < env->nr_memory_nodes; i++) {
54 n = &nodes[i];
55 max += bitmap_weight(n->set, n->size);
56 }
57
58 entries = zalloc(sizeof(*entries) * max);
59 if (!entries)
60 return -ENOMEM;
61
62 for (i = 0; i < env->nr_memory_nodes; i++) {
63 u64 bit;
64
65 n = &nodes[i];
66
67 for (bit = 0; bit < n->size; bit++) {
68 u64 start;
69
70 if (!test_bit(bit, n->set))
71 continue;
72
73 start = bit * bsize;
74
75 /*
76 * Merge nearby areas, we walk in order
77 * through the bitmap, so no need to sort.
78 */
79 if (j > 0) {
80 struct phys_entry *prev = &entries[j - 1];
81
82 if ((prev->end == start) &&
83 (prev->node == n->node)) {
84 prev->end += bsize;
85 continue;
86 }
87 }
88
89 phys_entry__init(&entries[j++], start, bsize, n->node);
90 }
91 }
92
93 /* Cut unused entries, due to merging. */
94 tmp_entries = realloc(entries, sizeof(*entries) * j);
95 if (tmp_entries)
96 entries = tmp_entries;
97
98 for (i = 0; i < j; i++) {
99 pr_debug("mem2node %03" PRIu64 " [0x%016" PRIx64 "-0x%016" PRIx64 "]\n",
100 entries[i].node, entries[i].start, entries[i].end);
101
102 phys_entry__insert(&entries[i], &map->root);
103 }
104
105 map->entries = entries;
106 return 0;
107}
108
109void mem2node__exit(struct mem2node *map)
110{
111 zfree(&map->entries);
112}
113
114int mem2node__node(struct mem2node *map, u64 addr)
115{
116 struct rb_node **p, *parent = NULL;
117 struct phys_entry *entry;
118
119 p = &map->root.rb_node;
120 while (*p != NULL) {
121 parent = *p;
122 entry = rb_entry(parent, struct phys_entry, rb_node);
123 if (addr < entry->start)
124 p = &(*p)->rb_left;
125 else if (addr >= entry->end)
126 p = &(*p)->rb_right;
127 else
128 goto out;
129 }
130
131 entry = NULL;
132out:
133 return entry ? (int) entry->node : -1;
134}
diff --git a/tools/perf/util/mem2node.h b/tools/perf/util/mem2node.h
new file mode 100644
index 000000000000..59c4752a2181
--- /dev/null
+++ b/tools/perf/util/mem2node.h
@@ -0,0 +1,19 @@
1#ifndef __MEM2NODE_H
2#define __MEM2NODE_H
3
4#include <linux/rbtree.h>
5#include "env.h"
6
7struct phys_entry;
8
9struct mem2node {
10 struct rb_root root;
11 struct phys_entry *entries;
12 int cnt;
13};
14
15int mem2node__init(struct mem2node *map, struct perf_env *env);
16void mem2node__exit(struct mem2node *map);
17int mem2node__node(struct mem2node *map, u64 addr);
18
19#endif /* __MEM2NODE_H */
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 91531a7c8fbf..fc832676a798 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -64,25 +64,6 @@ static union perf_event *perf_mmap__read(struct perf_mmap *map,
64} 64}
65 65
66/* 66/*
67 * legacy interface for mmap read.
68 * Don't use it. Use perf_mmap__read_event().
69 */
70union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
71{
72 u64 head;
73
74 /*
75 * Check if event was unmapped due to a POLLHUP/POLLERR.
76 */
77 if (!refcount_read(&map->refcnt))
78 return NULL;
79
80 head = perf_mmap__read_head(map);
81
82 return perf_mmap__read(map, &map->prev, head);
83}
84
85/*
86 * Read event from ring buffer one by one. 67 * Read event from ring buffer one by one.
87 * Return one event for each call. 68 * Return one event for each call.
88 * 69 *
@@ -94,9 +75,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
94 * } 75 * }
95 * perf_mmap__read_done() 76 * perf_mmap__read_done()
96 */ 77 */
97union perf_event *perf_mmap__read_event(struct perf_mmap *map, 78union perf_event *perf_mmap__read_event(struct perf_mmap *map)
98 bool overwrite,
99 u64 *startp, u64 end)
100{ 79{
101 union perf_event *event; 80 union perf_event *event;
102 81
@@ -106,17 +85,14 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map,
106 if (!refcount_read(&map->refcnt)) 85 if (!refcount_read(&map->refcnt))
107 return NULL; 86 return NULL;
108 87
109 if (startp == NULL)
110 return NULL;
111
112 /* non-overwirte doesn't pause the ringbuffer */ 88 /* non-overwirte doesn't pause the ringbuffer */
113 if (!overwrite) 89 if (!map->overwrite)
114 end = perf_mmap__read_head(map); 90 map->end = perf_mmap__read_head(map);
115 91
116 event = perf_mmap__read(map, startp, end); 92 event = perf_mmap__read(map, &map->start, map->end);
117 93
118 if (!overwrite) 94 if (!map->overwrite)
119 map->prev = *startp; 95 map->prev = map->start;
120 96
121 return event; 97 return event;
122} 98}
@@ -139,9 +115,9 @@ void perf_mmap__put(struct perf_mmap *map)
139 perf_mmap__munmap(map); 115 perf_mmap__munmap(map);
140} 116}
141 117
142void perf_mmap__consume(struct perf_mmap *map, bool overwrite) 118void perf_mmap__consume(struct perf_mmap *map)
143{ 119{
144 if (!overwrite) { 120 if (!map->overwrite) {
145 u64 old = map->prev; 121 u64 old = map->prev;
146 122
147 perf_mmap__write_tail(map, old); 123 perf_mmap__write_tail(map, old);
@@ -191,7 +167,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
191int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd) 167int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
192{ 168{
193 /* 169 /*
194 * The last one will be done at perf_evlist__mmap_consume(), so that we 170 * The last one will be done at perf_mmap__consume(), so that we
195 * make sure we don't prevent tools from consuming every last event in 171 * make sure we don't prevent tools from consuming every last event in
196 * the ring buffer. 172 * the ring buffer.
197 * 173 *
@@ -223,19 +199,18 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
223 return 0; 199 return 0;
224} 200}
225 201
226static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) 202static int overwrite_rb_find_range(void *buf, int mask, u64 *start, u64 *end)
227{ 203{
228 struct perf_event_header *pheader; 204 struct perf_event_header *pheader;
229 u64 evt_head = head; 205 u64 evt_head = *start;
230 int size = mask + 1; 206 int size = mask + 1;
231 207
232 pr_debug2("overwrite_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); 208 pr_debug2("%s: buf=%p, start=%"PRIx64"\n", __func__, buf, *start);
233 pheader = (struct perf_event_header *)(buf + (head & mask)); 209 pheader = (struct perf_event_header *)(buf + (*start & mask));
234 *start = head;
235 while (true) { 210 while (true) {
236 if (evt_head - head >= (unsigned int)size) { 211 if (evt_head - *start >= (unsigned int)size) {
237 pr_debug("Finished reading overwrite ring buffer: rewind\n"); 212 pr_debug("Finished reading overwrite ring buffer: rewind\n");
238 if (evt_head - head > (unsigned int)size) 213 if (evt_head - *start > (unsigned int)size)
239 evt_head -= pheader->size; 214 evt_head -= pheader->size;
240 *end = evt_head; 215 *end = evt_head;
241 return 0; 216 return 0;
@@ -259,27 +234,26 @@ static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u6
259/* 234/*
260 * Report the start and end of the available data in ringbuffer 235 * Report the start and end of the available data in ringbuffer
261 */ 236 */
262int perf_mmap__read_init(struct perf_mmap *md, bool overwrite, 237static int __perf_mmap__read_init(struct perf_mmap *md)
263 u64 *startp, u64 *endp)
264{ 238{
265 u64 head = perf_mmap__read_head(md); 239 u64 head = perf_mmap__read_head(md);
266 u64 old = md->prev; 240 u64 old = md->prev;
267 unsigned char *data = md->base + page_size; 241 unsigned char *data = md->base + page_size;
268 unsigned long size; 242 unsigned long size;
269 243
270 *startp = overwrite ? head : old; 244 md->start = md->overwrite ? head : old;
271 *endp = overwrite ? old : head; 245 md->end = md->overwrite ? old : head;
272 246
273 if (*startp == *endp) 247 if (md->start == md->end)
274 return -EAGAIN; 248 return -EAGAIN;
275 249
276 size = *endp - *startp; 250 size = md->end - md->start;
277 if (size > (unsigned long)(md->mask) + 1) { 251 if (size > (unsigned long)(md->mask) + 1) {
278 if (!overwrite) { 252 if (!md->overwrite) {
279 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 253 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
280 254
281 md->prev = head; 255 md->prev = head;
282 perf_mmap__consume(md, overwrite); 256 perf_mmap__consume(md);
283 return -EAGAIN; 257 return -EAGAIN;
284 } 258 }
285 259
@@ -287,33 +261,43 @@ int perf_mmap__read_init(struct perf_mmap *md, bool overwrite,
287 * Backward ring buffer is full. We still have a chance to read 261 * Backward ring buffer is full. We still have a chance to read
288 * most of data from it. 262 * most of data from it.
289 */ 263 */
290 if (overwrite_rb_find_range(data, md->mask, head, startp, endp)) 264 if (overwrite_rb_find_range(data, md->mask, &md->start, &md->end))
291 return -EINVAL; 265 return -EINVAL;
292 } 266 }
293 267
294 return 0; 268 return 0;
295} 269}
296 270
297int perf_mmap__push(struct perf_mmap *md, bool overwrite, 271int perf_mmap__read_init(struct perf_mmap *map)
298 void *to, int push(void *to, void *buf, size_t size)) 272{
273 /*
274 * Check if event was unmapped due to a POLLHUP/POLLERR.
275 */
276 if (!refcount_read(&map->refcnt))
277 return -ENOENT;
278
279 return __perf_mmap__read_init(map);
280}
281
282int perf_mmap__push(struct perf_mmap *md, void *to,
283 int push(void *to, void *buf, size_t size))
299{ 284{
300 u64 head = perf_mmap__read_head(md); 285 u64 head = perf_mmap__read_head(md);
301 u64 end, start;
302 unsigned char *data = md->base + page_size; 286 unsigned char *data = md->base + page_size;
303 unsigned long size; 287 unsigned long size;
304 void *buf; 288 void *buf;
305 int rc = 0; 289 int rc = 0;
306 290
307 rc = perf_mmap__read_init(md, overwrite, &start, &end); 291 rc = perf_mmap__read_init(md);
308 if (rc < 0) 292 if (rc < 0)
309 return (rc == -EAGAIN) ? 0 : -1; 293 return (rc == -EAGAIN) ? 0 : -1;
310 294
311 size = end - start; 295 size = md->end - md->start;
312 296
313 if ((start & md->mask) + size != (end & md->mask)) { 297 if ((md->start & md->mask) + size != (md->end & md->mask)) {
314 buf = &data[start & md->mask]; 298 buf = &data[md->start & md->mask];
315 size = md->mask + 1 - (start & md->mask); 299 size = md->mask + 1 - (md->start & md->mask);
316 start += size; 300 md->start += size;
317 301
318 if (push(to, buf, size) < 0) { 302 if (push(to, buf, size) < 0) {
319 rc = -1; 303 rc = -1;
@@ -321,9 +305,9 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
321 } 305 }
322 } 306 }
323 307
324 buf = &data[start & md->mask]; 308 buf = &data[md->start & md->mask];
325 size = end - start; 309 size = md->end - md->start;
326 start += size; 310 md->start += size;
327 311
328 if (push(to, buf, size) < 0) { 312 if (push(to, buf, size) < 0) {
329 rc = -1; 313 rc = -1;
@@ -331,7 +315,7 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
331 } 315 }
332 316
333 md->prev = head; 317 md->prev = head;
334 perf_mmap__consume(md, overwrite); 318 perf_mmap__consume(md);
335out: 319out:
336 return rc; 320 return rc;
337} 321}
@@ -344,5 +328,11 @@ out:
344 */ 328 */
345void perf_mmap__read_done(struct perf_mmap *map) 329void perf_mmap__read_done(struct perf_mmap *map)
346{ 330{
331 /*
332 * Check if event was unmapped due to a POLLHUP/POLLERR.
333 */
334 if (!refcount_read(&map->refcnt))
335 return;
336
347 map->prev = perf_mmap__read_head(map); 337 map->prev = perf_mmap__read_head(map);
348} 338}
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index ec7d3a24e276..d82294db1295 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -20,6 +20,9 @@ struct perf_mmap {
20 int fd; 20 int fd;
21 refcount_t refcnt; 21 refcount_t refcnt;
22 u64 prev; 22 u64 prev;
23 u64 start;
24 u64 end;
25 bool overwrite;
23 struct auxtrace_mmap auxtrace_mmap; 26 struct auxtrace_mmap auxtrace_mmap;
24 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); 27 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
25}; 28};
@@ -63,7 +66,7 @@ void perf_mmap__munmap(struct perf_mmap *map);
63void perf_mmap__get(struct perf_mmap *map); 66void perf_mmap__get(struct perf_mmap *map);
64void perf_mmap__put(struct perf_mmap *map); 67void perf_mmap__put(struct perf_mmap *map);
65 68
66void perf_mmap__consume(struct perf_mmap *map, bool overwrite); 69void perf_mmap__consume(struct perf_mmap *map);
67 70
68static inline u64 perf_mmap__read_head(struct perf_mmap *mm) 71static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
69{ 72{
@@ -86,16 +89,13 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
86 89
87union perf_event *perf_mmap__read_forward(struct perf_mmap *map); 90union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
88 91
89union perf_event *perf_mmap__read_event(struct perf_mmap *map, 92union perf_event *perf_mmap__read_event(struct perf_mmap *map);
90 bool overwrite,
91 u64 *startp, u64 end);
92 93
93int perf_mmap__push(struct perf_mmap *md, bool backward, 94int perf_mmap__push(struct perf_mmap *md, void *to,
94 void *to, int push(void *to, void *buf, size_t size)); 95 int push(void *to, void *buf, size_t size));
95 96
96size_t perf_mmap__mmap_len(struct perf_mmap *map); 97size_t perf_mmap__mmap_len(struct perf_mmap *map);
97 98
98int perf_mmap__read_init(struct perf_mmap *md, bool overwrite, 99int perf_mmap__read_init(struct perf_mmap *md);
99 u64 *startp, u64 *endp);
100void perf_mmap__read_done(struct perf_mmap *map); 100void perf_mmap__read_done(struct perf_mmap *map);
101#endif /*__PERF_MMAP_H */ 101#endif /*__PERF_MMAP_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 34589c427e52..b8b8a9558d32 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -206,8 +206,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
206 206
207 for_each_event(sys_dirent, evt_dir, evt_dirent) { 207 for_each_event(sys_dirent, evt_dir, evt_dirent) {
208 208
209 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 209 scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
210 evt_dirent->d_name); 210 evt_dirent->d_name);
211 fd = open(evt_path, O_RDONLY); 211 fd = open(evt_path, O_RDONLY);
212 if (fd < 0) 212 if (fd < 0)
213 continue; 213 continue;
@@ -1217,7 +1217,7 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
1217 get_config_name(head_config), &config_terms); 1217 get_config_name(head_config), &config_terms);
1218} 1218}
1219 1219
1220static int __parse_events_add_pmu(struct parse_events_state *parse_state, 1220int parse_events_add_pmu(struct parse_events_state *parse_state,
1221 struct list_head *list, char *name, 1221 struct list_head *list, char *name,
1222 struct list_head *head_config, bool auto_merge_stats) 1222 struct list_head *head_config, bool auto_merge_stats)
1223{ 1223{
@@ -1247,7 +1247,12 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1247 if (!head_config) { 1247 if (!head_config) {
1248 attr.type = pmu->type; 1248 attr.type = pmu->type;
1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); 1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
1250 return evsel ? 0 : -ENOMEM; 1250 if (evsel) {
1251 evsel->pmu_name = name;
1252 return 0;
1253 } else {
1254 return -ENOMEM;
1255 }
1251 } 1256 }
1252 1257
1253 if (perf_pmu__check_alias(pmu, head_config, &info)) 1258 if (perf_pmu__check_alias(pmu, head_config, &info))
@@ -1276,18 +1281,12 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1276 evsel->snapshot = info.snapshot; 1281 evsel->snapshot = info.snapshot;
1277 evsel->metric_expr = info.metric_expr; 1282 evsel->metric_expr = info.metric_expr;
1278 evsel->metric_name = info.metric_name; 1283 evsel->metric_name = info.metric_name;
1284 evsel->pmu_name = name;
1279 } 1285 }
1280 1286
1281 return evsel ? 0 : -ENOMEM; 1287 return evsel ? 0 : -ENOMEM;
1282} 1288}
1283 1289
1284int parse_events_add_pmu(struct parse_events_state *parse_state,
1285 struct list_head *list, char *name,
1286 struct list_head *head_config)
1287{
1288 return __parse_events_add_pmu(parse_state, list, name, head_config, false);
1289}
1290
1291int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1290int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1292 char *str, struct list_head **listp) 1291 char *str, struct list_head **listp)
1293{ 1292{
@@ -1317,8 +1316,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1317 return -1; 1316 return -1;
1318 list_add_tail(&term->list, head); 1317 list_add_tail(&term->list, head);
1319 1318
1320 if (!__parse_events_add_pmu(parse_state, list, 1319 if (!parse_events_add_pmu(parse_state, list,
1321 pmu->name, head, true)) { 1320 pmu->name, head, true)) {
1322 pr_debug("%s -> %s/%s/\n", str, 1321 pr_debug("%s -> %s/%s/\n", str,
1323 pmu->name, alias->str); 1322 pmu->name, alias->str);
1324 ok++; 1323 ok++;
@@ -1716,7 +1715,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
1716 struct perf_evsel *last; 1715 struct perf_evsel *last;
1717 1716
1718 if (list_empty(&parse_state.list)) { 1717 if (list_empty(&parse_state.list)) {
1719 WARN_ONCE(true, "WARNING: event parser found nothing"); 1718 WARN_ONCE(true, "WARNING: event parser found nothing\n");
1720 return -1; 1719 return -1;
1721 } 1720 }
1722 1721
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 88108cd11b4c..5015cfd58277 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -167,7 +167,7 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
167 void *ptr, char *type, u64 len); 167 void *ptr, char *type, u64 len);
168int parse_events_add_pmu(struct parse_events_state *parse_state, 168int parse_events_add_pmu(struct parse_events_state *parse_state,
169 struct list_head *list, char *name, 169 struct list_head *list, char *name,
170 struct list_head *head_config); 170 struct list_head *head_config, bool auto_merge_stats);
171 171
172int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 172int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
173 char *str, 173 char *str,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 655ecff636a8..a1a01b1ac8b8 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -175,7 +175,7 @@ bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
175num_dec [0-9]+ 175num_dec [0-9]+
176num_hex 0x[a-fA-F0-9]+ 176num_hex 0x[a-fA-F0-9]+
177num_raw_hex [a-fA-F0-9]+ 177num_raw_hex [a-fA-F0-9]+
178name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 178name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]]*
179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? 180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
181/* If you add a modifier you need to update check_modifier() */ 181/* If you add a modifier you need to update check_modifier() */
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index e81a20ea8d7d..7afeb80cc39e 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -8,6 +8,7 @@
8 8
9#define YYDEBUG 1 9#define YYDEBUG 1
10 10
11#include <fnmatch.h>
11#include <linux/compiler.h> 12#include <linux/compiler.h>
12#include <linux/list.h> 13#include <linux/list.h>
13#include <linux/types.h> 14#include <linux/types.h>
@@ -231,9 +232,13 @@ PE_NAME opt_event_config
231 YYABORT; 232 YYABORT;
232 233
233 ALLOC_LIST(list); 234 ALLOC_LIST(list);
234 if (parse_events_add_pmu(_parse_state, list, $1, $2)) { 235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false)) {
235 struct perf_pmu *pmu = NULL; 236 struct perf_pmu *pmu = NULL;
236 int ok = 0; 237 int ok = 0;
238 char *pattern;
239
240 if (asprintf(&pattern, "%s*", $1) < 0)
241 YYABORT;
237 242
238 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 243 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
239 char *name = pmu->name; 244 char *name = pmu->name;
@@ -241,14 +246,19 @@ PE_NAME opt_event_config
241 if (!strncmp(name, "uncore_", 7) && 246 if (!strncmp(name, "uncore_", 7) &&
242 strncmp($1, "uncore_", 7)) 247 strncmp($1, "uncore_", 7))
243 name += 7; 248 name += 7;
244 if (!strncmp($1, name, strlen($1))) { 249 if (!fnmatch(pattern, name, 0)) {
245 if (parse_events_copy_term_list(orig_terms, &terms)) 250 if (parse_events_copy_term_list(orig_terms, &terms)) {
251 free(pattern);
246 YYABORT; 252 YYABORT;
247 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms)) 253 }
254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true))
248 ok++; 255 ok++;
249 parse_events_terms__delete(terms); 256 parse_events_terms__delete(terms);
250 } 257 }
251 } 258 }
259
260 free(pattern);
261
252 if (!ok) 262 if (!ok)
253 YYABORT; 263 YYABORT;
254 } 264 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57e38fdf0b34..d2fb597c9a8c 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -351,7 +351,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
351 if (pmu_alias_info_file(name)) 351 if (pmu_alias_info_file(name))
352 continue; 352 continue;
353 353
354 snprintf(path, PATH_MAX, "%s/%s", dir, name); 354 scnprintf(path, PATH_MAX, "%s/%s", dir, name);
355 355
356 file = fopen(path, "r"); 356 file = fopen(path, "r");
357 if (!file) { 357 if (!file) {
@@ -539,9 +539,10 @@ static bool pmu_is_uncore(const char *name)
539 539
540/* 540/*
541 * PMU CORE devices have different name other than cpu in sysfs on some 541 * PMU CORE devices have different name other than cpu in sysfs on some
542 * platforms. looking for possible sysfs files to identify as core device. 542 * platforms.
543 * Looking for possible sysfs files to identify the arm core device.
543 */ 544 */
544static int is_pmu_core(const char *name) 545static int is_arm_pmu_core(const char *name)
545{ 546{
546 struct stat st; 547 struct stat st;
547 char path[PATH_MAX]; 548 char path[PATH_MAX];
@@ -550,18 +551,18 @@ static int is_pmu_core(const char *name)
550 if (!sysfs) 551 if (!sysfs)
551 return 0; 552 return 0;
552 553
553 /* Look for cpu sysfs (x86 and others) */
554 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu", sysfs);
555 if ((stat(path, &st) == 0) &&
556 (strncmp(name, "cpu", strlen("cpu")) == 0))
557 return 1;
558
559 /* Look for cpu sysfs (specific to arm) */ 554 /* Look for cpu sysfs (specific to arm) */
560 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus", 555 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
561 sysfs, name); 556 sysfs, name);
562 if (stat(path, &st) == 0) 557 if (stat(path, &st) == 0)
563 return 1; 558 return 1;
564 559
560 /* Look for cpu sysfs (specific to s390) */
561 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s",
562 sysfs, name);
563 if (stat(path, &st) == 0 && !strncmp(name, "cpum_", 5))
564 return 1;
565
565 return 0; 566 return 0;
566} 567}
567 568
@@ -576,6 +577,34 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
576 return NULL; 577 return NULL;
577} 578}
578 579
580/* Return zero when the cpuid from the mapfile.csv matches the
581 * cpuid string generated on this platform.
582 * Otherwise return non-zero.
583 */
584int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
585{
586 regex_t re;
587 regmatch_t pmatch[1];
588 int match;
589
590 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
591 /* Warn unable to generate match particular string. */
592 pr_info("Invalid regular expression %s\n", mapcpuid);
593 return 1;
594 }
595
596 match = !regexec(&re, cpuid, 1, pmatch, 0);
597 regfree(&re);
598 if (match) {
599 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
600
601 /* Verify the entire string matched. */
602 if (match_len == strlen(cpuid))
603 return 0;
604 }
605 return 1;
606}
607
579static char *perf_pmu__getcpuid(struct perf_pmu *pmu) 608static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
580{ 609{
581 char *cpuid; 610 char *cpuid;
@@ -610,31 +639,14 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
610 639
611 i = 0; 640 i = 0;
612 for (;;) { 641 for (;;) {
613 regex_t re;
614 regmatch_t pmatch[1];
615 int match;
616
617 map = &pmu_events_map[i++]; 642 map = &pmu_events_map[i++];
618 if (!map->table) { 643 if (!map->table) {
619 map = NULL; 644 map = NULL;
620 break; 645 break;
621 } 646 }
622 647
623 if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) { 648 if (!strcmp_cpuid_str(map->cpuid, cpuid))
624 /* Warn unable to generate match particular string. */
625 pr_info("Invalid regular expression %s\n", map->cpuid);
626 break; 649 break;
627 }
628
629 match = !regexec(&re, cpuid, 1, pmatch, 0);
630 regfree(&re);
631 if (match) {
632 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
633
634 /* Verify the entire string matched. */
635 if (match_len == strlen(cpuid))
636 break;
637 }
638 } 650 }
639 free(cpuid); 651 free(cpuid);
640 return map; 652 return map;
@@ -651,6 +663,7 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
651 struct pmu_events_map *map; 663 struct pmu_events_map *map;
652 struct pmu_event *pe; 664 struct pmu_event *pe;
653 const char *name = pmu->name; 665 const char *name = pmu->name;
666 const char *pname;
654 667
655 map = perf_pmu__find_map(pmu); 668 map = perf_pmu__find_map(pmu);
656 if (!map) 669 if (!map)
@@ -669,11 +682,9 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
669 break; 682 break;
670 } 683 }
671 684
672 if (!is_pmu_core(name)) { 685 if (!is_arm_pmu_core(name)) {
673 /* check for uncore devices */ 686 pname = pe->pmu ? pe->pmu : "cpu";
674 if (pe->pmu == NULL) 687 if (strncmp(pname, name, strlen(pname)))
675 continue;
676 if (strncmp(pe->pmu, name, strlen(pe->pmu)))
677 continue; 688 continue;
678 } 689 }
679 690
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a5731de0e5eb..c37fbef1711d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
423 pr_warning("Failed to get the type of %s.\n", varname); 423 pr_warning("Failed to get the type of %s.\n", varname);
424 return -ENOENT; 424 return -ENOENT;
425 } 425 }
426 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 426 pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type),
427 (unsigned)dwarf_dieoffset(&type));
427 tag = dwarf_tag(&type); 428 tag = dwarf_tag(&type);
428 429
429 if (field->name[0] == '[' && 430 if (field->name[0] == '[' &&
430 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 431 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
431 if (field->next) 432 /* Save original type for next field or type */
432 /* Save original type for next field */ 433 memcpy(die_mem, &type, sizeof(*die_mem));
433 memcpy(die_mem, &type, sizeof(*die_mem));
434 /* Get the type of this array */ 434 /* Get the type of this array */
435 if (die_get_real_type(&type, &type) == NULL) { 435 if (die_get_real_type(&type, &type) == NULL) {
436 pr_warning("Failed to get the type of %s.\n", varname); 436 pr_warning("Failed to get the type of %s.\n", varname);
437 return -ENOENT; 437 return -ENOENT;
438 } 438 }
439 pr_debug2("Array real type: (%x)\n", 439 pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
440 (unsigned)dwarf_dieoffset(&type)); 440 (unsigned)dwarf_dieoffset(&type));
441 if (tag == DW_TAG_pointer_type) { 441 if (tag == DW_TAG_pointer_type) {
442 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 442 ref = zalloc(sizeof(struct probe_trace_arg_ref));
@@ -448,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
448 *ref_ptr = ref; 448 *ref_ptr = ref;
449 } 449 }
450 ref->offset += dwarf_bytesize(&type) * field->index; 450 ref->offset += dwarf_bytesize(&type) * field->index;
451 if (!field->next)
452 /* Save vr_die for converting types */
453 memcpy(die_mem, vr_die, sizeof(*die_mem));
454 goto next; 451 goto next;
455 } else if (tag == DW_TAG_pointer_type) { 452 } else if (tag == DW_TAG_pointer_type) {
456 /* Check the pointer and dereference */ 453 /* Check the pointer and dereference */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index b1e999bd21ef..863b61478edd 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -12,6 +12,30 @@
12#include "print_binary.h" 12#include "print_binary.h"
13#include "thread_map.h" 13#include "thread_map.h"
14 14
15#if PY_MAJOR_VERSION < 3
16#define _PyUnicode_FromString(arg) \
17 PyString_FromString(arg)
18#define _PyUnicode_AsString(arg) \
19 PyString_AsString(arg)
20#define _PyUnicode_FromFormat(...) \
21 PyString_FromFormat(__VA_ARGS__)
22#define _PyLong_FromLong(arg) \
23 PyInt_FromLong(arg)
24
25#else
26
27#define _PyUnicode_FromString(arg) \
28 PyUnicode_FromString(arg)
29#define _PyUnicode_FromFormat(...) \
30 PyUnicode_FromFormat(__VA_ARGS__)
31#define _PyLong_FromLong(arg) \
32 PyLong_FromLong(arg)
33#endif
34
35#ifndef Py_TYPE
36#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
37#endif
38
15/* 39/*
16 * Provide these two so that we don't have to link against callchain.c and 40 * Provide these two so that we don't have to link against callchain.c and
17 * start dragging hist.c, etc. 41 * start dragging hist.c, etc.
@@ -49,7 +73,11 @@ int eprintf(int level, int var, const char *fmt, ...)
49# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 73# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
50#endif 74#endif
51 75
76#if PY_MAJOR_VERSION < 3
52PyMODINIT_FUNC initperf(void); 77PyMODINIT_FUNC initperf(void);
78#else
79PyMODINIT_FUNC PyInit_perf(void);
80#endif
53 81
54#define member_def(type, member, ptype, help) \ 82#define member_def(type, member, ptype, help) \
55 { #member, ptype, \ 83 { #member, ptype, \
@@ -107,7 +135,7 @@ static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
107 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { 135 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
108 ret = PyErr_NoMemory(); 136 ret = PyErr_NoMemory();
109 } else { 137 } else {
110 ret = PyString_FromString(s); 138 ret = _PyUnicode_FromString(s);
111 free(s); 139 free(s);
112 } 140 }
113 return ret; 141 return ret;
@@ -138,7 +166,7 @@ static PyMemberDef pyrf_task_event__members[] = {
138 166
139static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) 167static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
140{ 168{
141 return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 169 return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
142 "ptid: %u, time: %" PRIu64 "}", 170 "ptid: %u, time: %" PRIu64 "}",
143 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", 171 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
144 pevent->event.fork.pid, 172 pevent->event.fork.pid,
@@ -171,7 +199,7 @@ static PyMemberDef pyrf_comm_event__members[] = {
171 199
172static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) 200static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
173{ 201{
174 return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 202 return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
175 pevent->event.comm.pid, 203 pevent->event.comm.pid,
176 pevent->event.comm.tid, 204 pevent->event.comm.tid,
177 pevent->event.comm.comm); 205 pevent->event.comm.comm);
@@ -202,7 +230,7 @@ static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
202{ 230{
203 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); 231 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
204 232
205 return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 233 return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
206 ", stream_id: %" PRIu64 " }", 234 ", stream_id: %" PRIu64 " }",
207 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", 235 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
208 te->time, te->id, te->stream_id); 236 te->time, te->id, te->stream_id);
@@ -237,7 +265,7 @@ static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
237 pevent->event.lost.id, pevent->event.lost.lost) < 0) { 265 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
238 ret = PyErr_NoMemory(); 266 ret = PyErr_NoMemory();
239 } else { 267 } else {
240 ret = PyString_FromString(s); 268 ret = _PyUnicode_FromString(s);
241 free(s); 269 free(s);
242 } 270 }
243 return ret; 271 return ret;
@@ -264,7 +292,7 @@ static PyMemberDef pyrf_read_event__members[] = {
264 292
265static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) 293static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
266{ 294{
267 return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", 295 return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
268 pevent->event.read.pid, 296 pevent->event.read.pid,
269 pevent->event.read.tid); 297 pevent->event.read.tid);
270 /* 298 /*
@@ -299,7 +327,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
299 if (asprintf(&s, "{ type: sample }") < 0) { 327 if (asprintf(&s, "{ type: sample }") < 0) {
300 ret = PyErr_NoMemory(); 328 ret = PyErr_NoMemory();
301 } else { 329 } else {
302 ret = PyString_FromString(s); 330 ret = _PyUnicode_FromString(s);
303 free(s); 331 free(s);
304 } 332 }
305 return ret; 333 return ret;
@@ -330,7 +358,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
330 } 358 }
331 if (field->flags & FIELD_IS_STRING && 359 if (field->flags & FIELD_IS_STRING &&
332 is_printable_array(data + offset, len)) { 360 is_printable_array(data + offset, len)) {
333 ret = PyString_FromString((char *)data + offset); 361 ret = _PyUnicode_FromString((char *)data + offset);
334 } else { 362 } else {
335 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 363 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
336 field->flags &= ~FIELD_IS_STRING; 364 field->flags &= ~FIELD_IS_STRING;
@@ -352,7 +380,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
352static PyObject* 380static PyObject*
353get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) 381get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
354{ 382{
355 const char *str = PyString_AsString(PyObject_Str(attr_name)); 383 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
356 struct perf_evsel *evsel = pevent->evsel; 384 struct perf_evsel *evsel = pevent->evsel;
357 struct format_field *field; 385 struct format_field *field;
358 386
@@ -416,7 +444,7 @@ static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent)
416 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { 444 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
417 ret = PyErr_NoMemory(); 445 ret = PyErr_NoMemory();
418 } else { 446 } else {
419 ret = PyString_FromString(s); 447 ret = _PyUnicode_FromString(s);
420 free(s); 448 free(s);
421 } 449 }
422 return ret; 450 return ret;
@@ -528,7 +556,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
528static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 556static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
529{ 557{
530 cpu_map__put(pcpus->cpus); 558 cpu_map__put(pcpus->cpus);
531 pcpus->ob_type->tp_free((PyObject*)pcpus); 559 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
532} 560}
533 561
534static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) 562static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
@@ -597,7 +625,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
597static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) 625static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
598{ 626{
599 thread_map__put(pthreads->threads); 627 thread_map__put(pthreads->threads);
600 pthreads->ob_type->tp_free((PyObject*)pthreads); 628 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
601} 629}
602 630
603static Py_ssize_t pyrf_thread_map__length(PyObject *obj) 631static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
@@ -759,7 +787,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
759static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) 787static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
760{ 788{
761 perf_evsel__exit(&pevsel->evsel); 789 perf_evsel__exit(&pevsel->evsel);
762 pevsel->ob_type->tp_free((PyObject*)pevsel); 790 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel);
763} 791}
764 792
765static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, 793static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
@@ -850,7 +878,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
850static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) 878static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
851{ 879{
852 perf_evlist__exit(&pevlist->evlist); 880 perf_evlist__exit(&pevlist->evlist);
853 pevlist->ob_type->tp_free((PyObject*)pevlist); 881 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
854} 882}
855 883
856static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, 884static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
@@ -902,12 +930,16 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
902 930
903 for (i = 0; i < evlist->pollfd.nr; ++i) { 931 for (i = 0; i < evlist->pollfd.nr; ++i) {
904 PyObject *file; 932 PyObject *file;
933#if PY_MAJOR_VERSION < 3
905 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r"); 934 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
906 935
907 if (fp == NULL) 936 if (fp == NULL)
908 goto free_list; 937 goto free_list;
909 938
910 file = PyFile_FromFile(fp, "perf", "r", NULL); 939 file = PyFile_FromFile(fp, "perf", "r", NULL);
940#else
941 file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1);
942#endif
911 if (file == NULL) 943 if (file == NULL)
912 goto free_list; 944 goto free_list;
913 945
@@ -951,13 +983,18 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
951 union perf_event *event; 983 union perf_event *event;
952 int sample_id_all = 1, cpu; 984 int sample_id_all = 1, cpu;
953 static char *kwlist[] = { "cpu", "sample_id_all", NULL }; 985 static char *kwlist[] = { "cpu", "sample_id_all", NULL };
986 struct perf_mmap *md;
954 int err; 987 int err;
955 988
956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 989 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
957 &cpu, &sample_id_all)) 990 &cpu, &sample_id_all))
958 return NULL; 991 return NULL;
959 992
960 event = perf_evlist__mmap_read(evlist, cpu); 993 md = &evlist->mmap[cpu];
994 if (perf_mmap__read_init(md) < 0)
995 goto end;
996
997 event = perf_mmap__read_event(md);
961 if (event != NULL) { 998 if (event != NULL) {
962 PyObject *pyevent = pyrf_event__new(event); 999 PyObject *pyevent = pyrf_event__new(event);
963 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 1000 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
@@ -967,22 +1004,24 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
967 return PyErr_NoMemory(); 1004 return PyErr_NoMemory();
968 1005
969 evsel = perf_evlist__event2evsel(evlist, event); 1006 evsel = perf_evlist__event2evsel(evlist, event);
970 if (!evsel) 1007 if (!evsel) {
1008 Py_INCREF(Py_None);
971 return Py_None; 1009 return Py_None;
1010 }
972 1011
973 pevent->evsel = evsel; 1012 pevent->evsel = evsel;
974 1013
975 err = perf_evsel__parse_sample(evsel, event, &pevent->sample); 1014 err = perf_evsel__parse_sample(evsel, event, &pevent->sample);
976 1015
977 /* Consume the even only after we parsed it out. */ 1016 /* Consume the even only after we parsed it out. */
978 perf_evlist__mmap_consume(evlist, cpu); 1017 perf_mmap__consume(md);
979 1018
980 if (err) 1019 if (err)
981 return PyErr_Format(PyExc_OSError, 1020 return PyErr_Format(PyExc_OSError,
982 "perf: can't parse sample, err=%d", err); 1021 "perf: can't parse sample, err=%d", err);
983 return pyevent; 1022 return pyevent;
984 } 1023 }
985 1024end:
986 Py_INCREF(Py_None); 1025 Py_INCREF(Py_None);
987 return Py_None; 1026 return Py_None;
988} 1027}
@@ -1194,9 +1233,9 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1194 1233
1195 tp_format = trace_event__tp_format(sys, name); 1234 tp_format = trace_event__tp_format(sys, name);
1196 if (IS_ERR(tp_format)) 1235 if (IS_ERR(tp_format))
1197 return PyInt_FromLong(-1); 1236 return _PyLong_FromLong(-1);
1198 1237
1199 return PyInt_FromLong(tp_format->id); 1238 return _PyLong_FromLong(tp_format->id);
1200} 1239}
1201 1240
1202static PyMethodDef perf__methods[] = { 1241static PyMethodDef perf__methods[] = {
@@ -1209,11 +1248,31 @@ static PyMethodDef perf__methods[] = {
1209 { .ml_name = NULL, } 1248 { .ml_name = NULL, }
1210}; 1249};
1211 1250
1251#if PY_MAJOR_VERSION < 3
1212PyMODINIT_FUNC initperf(void) 1252PyMODINIT_FUNC initperf(void)
1253#else
1254PyMODINIT_FUNC PyInit_perf(void)
1255#endif
1213{ 1256{
1214 PyObject *obj; 1257 PyObject *obj;
1215 int i; 1258 int i;
1216 PyObject *dict, *module = Py_InitModule("perf", perf__methods); 1259 PyObject *dict;
1260#if PY_MAJOR_VERSION < 3
1261 PyObject *module = Py_InitModule("perf", perf__methods);
1262#else
1263 static struct PyModuleDef moduledef = {
1264 PyModuleDef_HEAD_INIT,
1265 "perf", /* m_name */
1266 "", /* m_doc */
1267 -1, /* m_size */
1268 perf__methods, /* m_methods */
1269 NULL, /* m_reload */
1270 NULL, /* m_traverse */
1271 NULL, /* m_clear */
1272 NULL, /* m_free */
1273 };
1274 PyObject *module = PyModule_Create(&moduledef);
1275#endif
1217 1276
1218 if (module == NULL || 1277 if (module == NULL ||
1219 pyrf_event__setup_types() < 0 || 1278 pyrf_event__setup_types() < 0 ||
@@ -1221,7 +1280,11 @@ PyMODINIT_FUNC initperf(void)
1221 pyrf_evsel__setup_types() < 0 || 1280 pyrf_evsel__setup_types() < 0 ||
1222 pyrf_thread_map__setup_types() < 0 || 1281 pyrf_thread_map__setup_types() < 0 ||
1223 pyrf_cpu_map__setup_types() < 0) 1282 pyrf_cpu_map__setup_types() < 0)
1283#if PY_MAJOR_VERSION < 3
1224 return; 1284 return;
1285#else
1286 return module;
1287#endif
1225 1288
1226 /* The page_size is placed in util object. */ 1289 /* The page_size is placed in util object. */
1227 page_size = sysconf(_SC_PAGE_SIZE); 1290 page_size = sysconf(_SC_PAGE_SIZE);
@@ -1270,7 +1333,7 @@ PyMODINIT_FUNC initperf(void)
1270 goto error; 1333 goto error;
1271 1334
1272 for (i = 0; perf__constants[i].name != NULL; i++) { 1335 for (i = 0; perf__constants[i].name != NULL; i++) {
1273 obj = PyInt_FromLong(perf__constants[i].value); 1336 obj = _PyLong_FromLong(perf__constants[i].value);
1274 if (obj == NULL) 1337 if (obj == NULL)
1275 goto error; 1338 goto error;
1276 PyDict_SetItemString(dict, perf__constants[i].name, obj); 1339 PyDict_SetItemString(dict, perf__constants[i].name, obj);
@@ -1280,6 +1343,9 @@ PyMODINIT_FUNC initperf(void)
1280error: 1343error:
1281 if (PyErr_Occurred()) 1344 if (PyErr_Occurred())
1282 PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); 1345 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
1346#if PY_MAJOR_VERSION >= 3
1347 return module;
1348#endif
1283} 1349}
1284 1350
1285/* 1351/*
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 6f09e4962dad..9cfc7bf16531 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -5,6 +5,7 @@
5#include "parse-events.h" 5#include "parse-events.h"
6#include <errno.h> 6#include <errno.h>
7#include <api/fs/fs.h> 7#include <api/fs/fs.h>
8#include <subcmd/parse-options.h>
8#include "util.h" 9#include "util.h"
9#include "cloexec.h" 10#include "cloexec.h"
10 11
@@ -219,11 +220,21 @@ static int record_opts__config_freq(struct record_opts *opts)
219 * User specified frequency is over current maximum. 220 * User specified frequency is over current maximum.
220 */ 221 */
221 if (user_freq && (max_rate < opts->freq)) { 222 if (user_freq && (max_rate < opts->freq)) {
222 pr_err("Maximum frequency rate (%u) reached.\n" 223 if (opts->strict_freq) {
223 "Please use -F freq option with lower value or consider\n" 224 pr_err("error: Maximum frequency rate (%'u Hz) exceeded.\n"
224 "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", 225 " Please use -F freq option with a lower value or consider\n"
225 max_rate); 226 " tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
226 return -1; 227 max_rate);
228 return -1;
229 } else {
230 pr_warning("warning: Maximum frequency rate (%'u Hz) exceeded, throttling from %'u Hz to %'u Hz.\n"
231 " The limit can be raised via /proc/sys/kernel/perf_event_max_sample_rate.\n"
232 " The kernel will lower it when perf's interrupts take too long.\n"
233 " Use --strict-freq to disable this throttling, refusing to record.\n",
234 max_rate, opts->freq, max_rate);
235
236 opts->freq = max_rate;
237 }
227 } 238 }
228 239
229 /* 240 /*
@@ -291,3 +302,25 @@ out_delete:
291 perf_evlist__delete(temp_evlist); 302 perf_evlist__delete(temp_evlist);
292 return ret; 303 return ret;
293} 304}
305
306int record__parse_freq(const struct option *opt, const char *str, int unset __maybe_unused)
307{
308 unsigned int freq;
309 struct record_opts *opts = opt->value;
310
311 if (!str)
312 return -EINVAL;
313
314 if (strcasecmp(str, "max") == 0) {
315 if (get_max_rate(&freq)) {
316 pr_err("couldn't read /proc/sys/kernel/perf_event_max_sample_rate\n");
317 return -1;
318 }
319 pr_info("info: Using a maximum frequency rate of %'d Hz\n", freq);
320 } else {
321 freq = atoi(str);
322 }
323
324 opts->user_freq = freq;
325 return 0;
326}
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ea070883c593..10dd5fce082b 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -49,7 +49,37 @@
49#include "print_binary.h" 49#include "print_binary.h"
50#include "stat.h" 50#include "stat.h"
51 51
52#if PY_MAJOR_VERSION < 3
53#define _PyUnicode_FromString(arg) \
54 PyString_FromString(arg)
55#define _PyUnicode_FromStringAndSize(arg1, arg2) \
56 PyString_FromStringAndSize((arg1), (arg2))
57#define _PyBytes_FromStringAndSize(arg1, arg2) \
58 PyString_FromStringAndSize((arg1), (arg2))
59#define _PyLong_FromLong(arg) \
60 PyInt_FromLong(arg)
61#define _PyLong_AsLong(arg) \
62 PyInt_AsLong(arg)
63#define _PyCapsule_New(arg1, arg2, arg3) \
64 PyCObject_FromVoidPtr((arg1), (arg2))
65
52PyMODINIT_FUNC initperf_trace_context(void); 66PyMODINIT_FUNC initperf_trace_context(void);
67#else
68#define _PyUnicode_FromString(arg) \
69 PyUnicode_FromString(arg)
70#define _PyUnicode_FromStringAndSize(arg1, arg2) \
71 PyUnicode_FromStringAndSize((arg1), (arg2))
72#define _PyBytes_FromStringAndSize(arg1, arg2) \
73 PyBytes_FromStringAndSize((arg1), (arg2))
74#define _PyLong_FromLong(arg) \
75 PyLong_FromLong(arg)
76#define _PyLong_AsLong(arg) \
77 PyLong_AsLong(arg)
78#define _PyCapsule_New(arg1, arg2, arg3) \
79 PyCapsule_New((arg1), (arg2), (arg3))
80
81PyMODINIT_FUNC PyInit_perf_trace_context(void);
82#endif
53 83
54#define TRACE_EVENT_TYPE_MAX \ 84#define TRACE_EVENT_TYPE_MAX \
55 ((1 << (sizeof(unsigned short) * 8)) - 1) 85 ((1 << (sizeof(unsigned short) * 8)) - 1)
@@ -135,7 +165,7 @@ static int get_argument_count(PyObject *handler)
135 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, 165 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
136 "co_argcount"); 166 "co_argcount");
137 if (arg_count_obj) { 167 if (arg_count_obj) {
138 arg_count = (int) PyInt_AsLong(arg_count_obj); 168 arg_count = (int) _PyLong_AsLong(arg_count_obj);
139 Py_DECREF(arg_count_obj); 169 Py_DECREF(arg_count_obj);
140 } 170 }
141 Py_DECREF(code_obj); 171 Py_DECREF(code_obj);
@@ -182,10 +212,10 @@ static void define_value(enum print_arg_type field_type,
182 212
183 value = eval_flag(field_value); 213 value = eval_flag(field_value);
184 214
185 PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 215 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
186 PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 216 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
187 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 217 PyTuple_SetItem(t, n++, _PyLong_FromLong(value));
188 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 218 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str));
189 219
190 try_call_object(handler_name, t); 220 try_call_object(handler_name, t);
191 221
@@ -223,10 +253,10 @@ static void define_field(enum print_arg_type field_type,
223 if (!t) 253 if (!t)
224 Py_FatalError("couldn't create Python tuple"); 254 Py_FatalError("couldn't create Python tuple");
225 255
226 PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 256 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
227 PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
228 if (field_type == PRINT_FLAGS) 258 if (field_type == PRINT_FLAGS)
229 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 259 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
230 260
231 try_call_object(handler_name, t); 261 try_call_object(handler_name, t);
232 262
@@ -325,12 +355,12 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
325 if (field->flags & FIELD_IS_SIGNED) { 355 if (field->flags & FIELD_IS_SIGNED) {
326 if ((long long)val >= LONG_MIN && 356 if ((long long)val >= LONG_MIN &&
327 (long long)val <= LONG_MAX) 357 (long long)val <= LONG_MAX)
328 obj = PyInt_FromLong(val); 358 obj = _PyLong_FromLong(val);
329 else 359 else
330 obj = PyLong_FromLongLong(val); 360 obj = PyLong_FromLongLong(val);
331 } else { 361 } else {
332 if (val <= LONG_MAX) 362 if (val <= LONG_MAX)
333 obj = PyInt_FromLong(val); 363 obj = _PyLong_FromLong(val);
334 else 364 else
335 obj = PyLong_FromUnsignedLongLong(val); 365 obj = PyLong_FromUnsignedLongLong(val);
336 } 366 }
@@ -389,9 +419,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
389 pydict_set_item_string_decref(pysym, "end", 419 pydict_set_item_string_decref(pysym, "end",
390 PyLong_FromUnsignedLongLong(node->sym->end)); 420 PyLong_FromUnsignedLongLong(node->sym->end));
391 pydict_set_item_string_decref(pysym, "binding", 421 pydict_set_item_string_decref(pysym, "binding",
392 PyInt_FromLong(node->sym->binding)); 422 _PyLong_FromLong(node->sym->binding));
393 pydict_set_item_string_decref(pysym, "name", 423 pydict_set_item_string_decref(pysym, "name",
394 PyString_FromStringAndSize(node->sym->name, 424 _PyUnicode_FromStringAndSize(node->sym->name,
395 node->sym->namelen)); 425 node->sym->namelen));
396 pydict_set_item_string_decref(pyelem, "sym", pysym); 426 pydict_set_item_string_decref(pyelem, "sym", pysym);
397 } 427 }
@@ -406,7 +436,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
406 dsoname = map->dso->name; 436 dsoname = map->dso->name;
407 } 437 }
408 pydict_set_item_string_decref(pyelem, "dso", 438 pydict_set_item_string_decref(pyelem, "dso",
409 PyString_FromString(dsoname)); 439 _PyUnicode_FromString(dsoname));
410 } 440 }
411 441
412 callchain_cursor_advance(&callchain_cursor); 442 callchain_cursor_advance(&callchain_cursor);
@@ -483,16 +513,16 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
483 if (!dict_sample) 513 if (!dict_sample)
484 Py_FatalError("couldn't create Python dictionary"); 514 Py_FatalError("couldn't create Python dictionary");
485 515
486 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 516 pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel)));
487 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 517 pydict_set_item_string_decref(dict, "attr", _PyUnicode_FromStringAndSize(
488 (const char *)&evsel->attr, sizeof(evsel->attr))); 518 (const char *)&evsel->attr, sizeof(evsel->attr)));
489 519
490 pydict_set_item_string_decref(dict_sample, "pid", 520 pydict_set_item_string_decref(dict_sample, "pid",
491 PyInt_FromLong(sample->pid)); 521 _PyLong_FromLong(sample->pid));
492 pydict_set_item_string_decref(dict_sample, "tid", 522 pydict_set_item_string_decref(dict_sample, "tid",
493 PyInt_FromLong(sample->tid)); 523 _PyLong_FromLong(sample->tid));
494 pydict_set_item_string_decref(dict_sample, "cpu", 524 pydict_set_item_string_decref(dict_sample, "cpu",
495 PyInt_FromLong(sample->cpu)); 525 _PyLong_FromLong(sample->cpu));
496 pydict_set_item_string_decref(dict_sample, "ip", 526 pydict_set_item_string_decref(dict_sample, "ip",
497 PyLong_FromUnsignedLongLong(sample->ip)); 527 PyLong_FromUnsignedLongLong(sample->ip));
498 pydict_set_item_string_decref(dict_sample, "time", 528 pydict_set_item_string_decref(dict_sample, "time",
@@ -504,17 +534,17 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
504 set_sample_read_in_dict(dict_sample, sample, evsel); 534 set_sample_read_in_dict(dict_sample, sample, evsel);
505 pydict_set_item_string_decref(dict, "sample", dict_sample); 535 pydict_set_item_string_decref(dict, "sample", dict_sample);
506 536
507 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 537 pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize(
508 (const char *)sample->raw_data, sample->raw_size)); 538 (const char *)sample->raw_data, sample->raw_size));
509 pydict_set_item_string_decref(dict, "comm", 539 pydict_set_item_string_decref(dict, "comm",
510 PyString_FromString(thread__comm_str(al->thread))); 540 _PyUnicode_FromString(thread__comm_str(al->thread)));
511 if (al->map) { 541 if (al->map) {
512 pydict_set_item_string_decref(dict, "dso", 542 pydict_set_item_string_decref(dict, "dso",
513 PyString_FromString(al->map->dso->name)); 543 _PyUnicode_FromString(al->map->dso->name));
514 } 544 }
515 if (al->sym) { 545 if (al->sym) {
516 pydict_set_item_string_decref(dict, "symbol", 546 pydict_set_item_string_decref(dict, "symbol",
517 PyString_FromString(al->sym->name)); 547 _PyUnicode_FromString(al->sym->name));
518 } 548 }
519 549
520 pydict_set_item_string_decref(dict, "callchain", callchain); 550 pydict_set_item_string_decref(dict, "callchain", callchain);
@@ -574,9 +604,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
574 scripting_context->event_data = data; 604 scripting_context->event_data = data;
575 scripting_context->pevent = evsel->tp_format->pevent; 605 scripting_context->pevent = evsel->tp_format->pevent;
576 606
577 context = PyCObject_FromVoidPtr(scripting_context, NULL); 607 context = _PyCapsule_New(scripting_context, NULL, NULL);
578 608
579 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 609 PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name));
580 PyTuple_SetItem(t, n++, context); 610 PyTuple_SetItem(t, n++, context);
581 611
582 /* ip unwinding */ 612 /* ip unwinding */
@@ -585,18 +615,18 @@ static void python_process_tracepoint(struct perf_sample *sample,
585 Py_INCREF(callchain); 615 Py_INCREF(callchain);
586 616
587 if (!dict) { 617 if (!dict) {
588 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 618 PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu));
589 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 619 PyTuple_SetItem(t, n++, _PyLong_FromLong(s));
590 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 620 PyTuple_SetItem(t, n++, _PyLong_FromLong(ns));
591 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 621 PyTuple_SetItem(t, n++, _PyLong_FromLong(pid));
592 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 622 PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm));
593 PyTuple_SetItem(t, n++, callchain); 623 PyTuple_SetItem(t, n++, callchain);
594 } else { 624 } else {
595 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 625 pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu));
596 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 626 pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s));
597 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 627 pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns));
598 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 628 pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid));
599 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 629 pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm));
600 pydict_set_item_string_decref(dict, "common_callchain", callchain); 630 pydict_set_item_string_decref(dict, "common_callchain", callchain);
601 } 631 }
602 for (field = event->format.fields; field; field = field->next) { 632 for (field = event->format.fields; field; field = field->next) {
@@ -615,7 +645,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
615 } 645 }
616 if (field->flags & FIELD_IS_STRING && 646 if (field->flags & FIELD_IS_STRING &&
617 is_printable_array(data + offset, len)) { 647 is_printable_array(data + offset, len)) {
618 obj = PyString_FromString((char *) data + offset); 648 obj = _PyUnicode_FromString((char *) data + offset);
619 } else { 649 } else {
620 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 650 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
621 field->flags &= ~FIELD_IS_STRING; 651 field->flags &= ~FIELD_IS_STRING;
@@ -668,7 +698,7 @@ static PyObject *tuple_new(unsigned int sz)
668static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) 698static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
669{ 699{
670#if BITS_PER_LONG == 64 700#if BITS_PER_LONG == 64
671 return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 701 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
672#endif 702#endif
673#if BITS_PER_LONG == 32 703#if BITS_PER_LONG == 32
674 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); 704 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
@@ -677,12 +707,12 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
677 707
678static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) 708static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
679{ 709{
680 return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 710 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
681} 711}
682 712
683static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) 713static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
684{ 714{
685 return PyTuple_SetItem(t, pos, PyString_FromString(s)); 715 return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s));
686} 716}
687 717
688static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) 718static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
@@ -1029,8 +1059,8 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
1029 return; 1059 return;
1030 } 1060 }
1031 1061
1032 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 1062 PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu));
1033 PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); 1063 PyTuple_SetItem(t, n++, _PyLong_FromLong(thread));
1034 1064
1035 tuple_set_u64(t, n++, tstamp); 1065 tuple_set_u64(t, n++, tstamp);
1036 tuple_set_u64(t, n++, count->val); 1066 tuple_set_u64(t, n++, count->val);
@@ -1212,27 +1242,58 @@ static void set_table_handlers(struct tables *tables)
1212 SET_TABLE_HANDLER(call_return); 1242 SET_TABLE_HANDLER(call_return);
1213} 1243}
1214 1244
1245#if PY_MAJOR_VERSION < 3
1246static void _free_command_line(const char **command_line, int num)
1247{
1248 free(command_line);
1249}
1250#else
1251static void _free_command_line(wchar_t **command_line, int num)
1252{
1253 int i;
1254 for (i = 0; i < num; i++)
1255 PyMem_RawFree(command_line[i]);
1256 free(command_line);
1257}
1258#endif
1259
1260
1215/* 1261/*
1216 * Start trace script 1262 * Start trace script
1217 */ 1263 */
1218static int python_start_script(const char *script, int argc, const char **argv) 1264static int python_start_script(const char *script, int argc, const char **argv)
1219{ 1265{
1220 struct tables *tables = &tables_global; 1266 struct tables *tables = &tables_global;
1267#if PY_MAJOR_VERSION < 3
1221 const char **command_line; 1268 const char **command_line;
1269#else
1270 wchar_t **command_line;
1271#endif
1222 char buf[PATH_MAX]; 1272 char buf[PATH_MAX];
1223 int i, err = 0; 1273 int i, err = 0;
1224 FILE *fp; 1274 FILE *fp;
1225 1275
1276#if PY_MAJOR_VERSION < 3
1226 command_line = malloc((argc + 1) * sizeof(const char *)); 1277 command_line = malloc((argc + 1) * sizeof(const char *));
1227 command_line[0] = script; 1278 command_line[0] = script;
1228 for (i = 1; i < argc + 1; i++) 1279 for (i = 1; i < argc + 1; i++)
1229 command_line[i] = argv[i - 1]; 1280 command_line[i] = argv[i - 1];
1281#else
1282 command_line = malloc((argc + 1) * sizeof(wchar_t *));
1283 command_line[0] = Py_DecodeLocale(script, NULL);
1284 for (i = 1; i < argc + 1; i++)
1285 command_line[i] = Py_DecodeLocale(argv[i - 1], NULL);
1286#endif
1230 1287
1231 Py_Initialize(); 1288 Py_Initialize();
1232 1289
1290#if PY_MAJOR_VERSION < 3
1233 initperf_trace_context(); 1291 initperf_trace_context();
1234
1235 PySys_SetArgv(argc + 1, (char **)command_line); 1292 PySys_SetArgv(argc + 1, (char **)command_line);
1293#else
1294 PyInit_perf_trace_context();
1295 PySys_SetArgv(argc + 1, command_line);
1296#endif
1236 1297
1237 fp = fopen(script, "r"); 1298 fp = fopen(script, "r");
1238 if (!fp) { 1299 if (!fp) {
@@ -1262,12 +1323,12 @@ static int python_start_script(const char *script, int argc, const char **argv)
1262 goto error; 1323 goto error;
1263 } 1324 }
1264 1325
1265 free(command_line); 1326 _free_command_line(command_line, argc + 1);
1266 1327
1267 return err; 1328 return err;
1268error: 1329error:
1269 Py_Finalize(); 1330 Py_Finalize();
1270 free(command_line); 1331 _free_command_line(command_line, argc + 1);
1271 1332
1272 return err; 1333 return err;
1273} 1334}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c71ced7db152..f4a7a437ee87 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1591,7 +1591,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1591 drop_rate = (double)stats->total_lost_samples / 1591 drop_rate = (double)stats->total_lost_samples /
1592 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); 1592 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);
1593 if (drop_rate > 0.05) { 1593 if (drop_rate > 0.05) {
1594 ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n", 1594 ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n",
1595 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, 1595 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,
1596 drop_rate * 100.0); 1596 drop_rate * 100.0);
1597 } 1597 }
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index af415febbc46..001be4f9d3b9 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python2 1#!/usr/bin/python
2 2
3from os import getenv 3from os import getenv
4 4
@@ -28,6 +28,8 @@ class install_lib(_install_lib):
28cflags = getenv('CFLAGS', '').split() 28cflags = getenv('CFLAGS', '').split()
29# switch off several checks (need to be at the end of cflags list) 29# switch off several checks (need to be at the end of cflags list)
30cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] 30cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
31if cc != "clang":
32 cflags += ['-Wno-cast-function-type' ]
31 33
32src_perf = getenv('srctree') + '/tools/perf' 34src_perf = getenv('srctree') + '/tools/perf'
33build_lib = getenv('PYTHON_EXTBUILD_LIB') 35build_lib = getenv('PYTHON_EXTBUILD_LIB')
@@ -35,11 +37,11 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
35libtraceevent = getenv('LIBTRACEEVENT') 37libtraceevent = getenv('LIBTRACEEVENT')
36libapikfs = getenv('LIBAPI') 38libapikfs = getenv('LIBAPI')
37 39
38ext_sources = [f.strip() for f in file('util/python-ext-sources') 40ext_sources = [f.strip() for f in open('util/python-ext-sources')
39 if len(f.strip()) > 0 and f[0] != '#'] 41 if len(f.strip()) > 0 and f[0] != '#']
40 42
41# use full paths with source files 43# use full paths with source files
42ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources) 44ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources))
43 45
44perf = Extension('perf', 46perf = Extension('perf',
45 sources = ext_sources, 47 sources = ext_sources,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2da4d0456a03..26a68dfd8a4f 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -111,17 +111,20 @@ struct sort_entry sort_thread = {
111 111
112/* --sort comm */ 112/* --sort comm */
113 113
114/*
115 * We can't use pointer comparison in functions below,
116 * because it gives different results based on pointer
117 * values, which could break some sorting assumptions.
118 */
114static int64_t 119static int64_t
115sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 120sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
116{ 121{
117 /* Compare the addr that should be unique among comm */
118 return strcmp(comm__str(right->comm), comm__str(left->comm)); 122 return strcmp(comm__str(right->comm), comm__str(left->comm));
119} 123}
120 124
121static int64_t 125static int64_t
122sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 126sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
123{ 127{
124 /* Compare the addr that should be unique among comm */
125 return strcmp(comm__str(right->comm), comm__str(left->comm)); 128 return strcmp(comm__str(right->comm), comm__str(left->comm));
126} 129}
127 130
@@ -1542,6 +1545,46 @@ struct sort_entry sort_sym_size = {
1542 .se_width_idx = HISTC_SYM_SIZE, 1545 .se_width_idx = HISTC_SYM_SIZE,
1543}; 1546};
1544 1547
1548/* --sort dso_size */
1549
1550static int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r)
1551{
1552 int64_t size_l = map_l != NULL ? map__size(map_l) : 0;
1553 int64_t size_r = map_r != NULL ? map__size(map_r) : 0;
1554
1555 return size_l < size_r ? -1 :
1556 size_l == size_r ? 0 : 1;
1557}
1558
1559static int64_t
1560sort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right)
1561{
1562 return _sort__dso_size_cmp(right->ms.map, left->ms.map);
1563}
1564
1565static int _hist_entry__dso_size_snprintf(struct map *map, char *bf,
1566 size_t bf_size, unsigned int width)
1567{
1568 if (map && map->dso)
1569 return repsep_snprintf(bf, bf_size, "%*d", width,
1570 map__size(map));
1571
1572 return repsep_snprintf(bf, bf_size, "%*s", width, "unknown");
1573}
1574
1575static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf,
1576 size_t size, unsigned int width)
1577{
1578 return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width);
1579}
1580
1581struct sort_entry sort_dso_size = {
1582 .se_header = "DSO size",
1583 .se_cmp = sort__dso_size_cmp,
1584 .se_snprintf = hist_entry__dso_size_snprintf,
1585 .se_width_idx = HISTC_DSO_SIZE,
1586};
1587
1545 1588
1546struct sort_dimension { 1589struct sort_dimension {
1547 const char *name; 1590 const char *name;
@@ -1566,6 +1609,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1566 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1609 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1567 DIM(SORT_TRACE, "trace", sort_trace), 1610 DIM(SORT_TRACE, "trace", sort_trace),
1568 DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), 1611 DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size),
1612 DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size),
1569 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), 1613 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
1570}; 1614};
1571 1615
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index f5901c10a563..035b62e2c60b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -220,6 +220,7 @@ enum sort_type {
220 SORT_TRANSACTION, 220 SORT_TRANSACTION,
221 SORT_TRACE, 221 SORT_TRACE,
222 SORT_SYM_SIZE, 222 SORT_SYM_SIZE,
223 SORT_DSO_SIZE,
223 SORT_CGROUP_ID, 224 SORT_CGROUP_ID,
224 225
225 /* branch stack specific sort keys */ 226 /* branch stack specific sort keys */
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 32235657c1ac..a0061e0b0fad 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -92,7 +92,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
92}; 92};
93#undef ID 93#undef ID
94 94
95void perf_stat_evsel_id_init(struct perf_evsel *evsel) 95static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
96{ 96{
97 struct perf_stat_evsel *ps = evsel->stats; 97 struct perf_stat_evsel *ps = evsel->stats;
98 int i; 98 int i;
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index dbc6f7134f61..8f56ba4fd258 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,8 @@ struct perf_stat_config {
90 bool scale; 90 bool scale;
91 FILE *output; 91 FILE *output;
92 unsigned int interval; 92 unsigned int interval;
93 unsigned int timeout;
94 int times;
93 struct runtime_stat *stats; 95 struct runtime_stat *stats;
94 int stats_num; 96 int stats_num;
95}; 97};
@@ -126,8 +128,6 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
126#define perf_stat_evsel__is(evsel, id) \ 128#define perf_stat_evsel__is(evsel, id) \
127 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id) 129 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id)
128 130
129void perf_stat_evsel_id_init(struct perf_evsel *evsel);
130
131extern struct runtime_stat rt_stat; 131extern struct runtime_stat rt_stat;
132extern struct stats walltime_nsecs_stats; 132extern struct stats walltime_nsecs_stats;
133 133
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index cc065d4bfafc..1466814ebada 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1582,7 +1582,7 @@ int dso__load(struct dso *dso, struct map *map)
1582 bool next_slot = false; 1582 bool next_slot = false;
1583 bool is_reg; 1583 bool is_reg;
1584 bool nsexit; 1584 bool nsexit;
1585 int sirc; 1585 int sirc = -1;
1586 1586
1587 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1587 enum dso_binary_type symtab_type = binary_type_symtab[i];
1588 1588
@@ -1600,16 +1600,14 @@ int dso__load(struct dso *dso, struct map *map)
1600 nsinfo__mountns_exit(&nsc); 1600 nsinfo__mountns_exit(&nsc);
1601 1601
1602 is_reg = is_regular_file(name); 1602 is_reg = is_regular_file(name);
1603 sirc = symsrc__init(ss, dso, name, symtab_type); 1603 if (is_reg)
1604 sirc = symsrc__init(ss, dso, name, symtab_type);
1604 1605
1605 if (nsexit) 1606 if (nsexit)
1606 nsinfo__mountns_enter(dso->nsinfo, &nsc); 1607 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1607 1608
1608 if (!is_reg || sirc < 0) { 1609 if (!is_reg || sirc < 0)
1609 if (sirc >= 0)
1610 symsrc__destroy(ss);
1611 continue; 1610 continue;
1612 }
1613 1611
1614 if (!syms_ss && symsrc__has_symtab(ss)) { 1612 if (!syms_ss && symsrc__has_symtab(ss)) {
1615 syms_ss = ss; 1613 syms_ss = ss;
@@ -1960,8 +1958,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
1960 pr_debug("Using %s for symbols\n", kallsyms_filename); 1958 pr_debug("Using %s for symbols\n", kallsyms_filename);
1961 if (err > 0 && !dso__is_kcore(dso)) { 1959 if (err > 0 && !dso__is_kcore(dso)) {
1962 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1960 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
1963 machine__mmap_name(machine, path, sizeof(path)); 1961 dso__set_long_name(dso, machine->mmap_name, false);
1964 dso__set_long_name(dso, strdup(path), true);
1965 map__fixup_start(map); 1962 map__fixup_start(map);
1966 map__fixup_end(map); 1963 map__fixup_end(map);
1967 } 1964 }
@@ -2094,16 +2091,14 @@ static bool symbol__read_kptr_restrict(void)
2094 2091
2095int symbol__annotation_init(void) 2092int symbol__annotation_init(void)
2096{ 2093{
2094 if (symbol_conf.init_annotation)
2095 return 0;
2096
2097 if (symbol_conf.initialized) { 2097 if (symbol_conf.initialized) {
2098 pr_err("Annotation needs to be init before symbol__init()\n"); 2098 pr_err("Annotation needs to be init before symbol__init()\n");
2099 return -1; 2099 return -1;
2100 } 2100 }
2101 2101
2102 if (symbol_conf.init_annotation) {
2103 pr_warning("Annotation being initialized multiple times\n");
2104 return 0;
2105 }
2106
2107 symbol_conf.priv_size += sizeof(struct annotation); 2102 symbol_conf.priv_size += sizeof(struct annotation);
2108 symbol_conf.init_annotation = true; 2103 symbol_conf.init_annotation = true;
2109 return 0; 2104 return 0;
@@ -2224,3 +2219,25 @@ int symbol__config_symfs(const struct option *opt __maybe_unused,
2224 free(bf); 2219 free(bf);
2225 return 0; 2220 return 0;
2226} 2221}
2222
2223struct mem_info *mem_info__get(struct mem_info *mi)
2224{
2225 if (mi)
2226 refcount_inc(&mi->refcnt);
2227 return mi;
2228}
2229
2230void mem_info__put(struct mem_info *mi)
2231{
2232 if (mi && refcount_dec_and_test(&mi->refcnt))
2233 free(mi);
2234}
2235
2236struct mem_info *mem_info__new(void)
2237{
2238 struct mem_info *mi = zalloc(sizeof(*mi));
2239
2240 if (mi)
2241 refcount_set(&mi->refcnt, 1);
2242 return mi;
2243}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0563f33c1eb3..70c16741f50a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -200,9 +200,10 @@ struct branch_info {
200}; 200};
201 201
202struct mem_info { 202struct mem_info {
203 struct addr_map_symbol iaddr; 203 struct addr_map_symbol iaddr;
204 struct addr_map_symbol daddr; 204 struct addr_map_symbol daddr;
205 union perf_mem_data_src data_src; 205 union perf_mem_data_src data_src;
206 refcount_t refcnt;
206}; 207};
207 208
208struct addr_location { 209struct addr_location {
@@ -389,4 +390,16 @@ int sdt_notes__get_count(struct list_head *start);
389#define SDT_NOTE_NAME "stapsdt" 390#define SDT_NOTE_NAME "stapsdt"
390#define NR_ADDR 3 391#define NR_ADDR 3
391 392
393struct mem_info *mem_info__new(void);
394struct mem_info *mem_info__get(struct mem_info *mi);
395void mem_info__put(struct mem_info *mi);
396
397static inline void __mem_info__zput(struct mem_info **mi)
398{
399 mem_info__put(*mi);
400 *mi = NULL;
401}
402
403#define mem_info__zput(mi) __mem_info__zput(&mi)
404
392#endif /* __PERF_SYMBOL */ 405#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 303bdb84ab5a..0ee7f568d60c 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -17,7 +17,7 @@
17#include <stdlib.h> 17#include <stdlib.h>
18#include <linux/compiler.h> 18#include <linux/compiler.h>
19 19
20#ifdef HAVE_SYSCALL_TABLE 20#ifdef HAVE_SYSCALL_TABLE_SUPPORT
21#include <string.h> 21#include <string.h>
22#include "string2.h" 22#include "string2.h"
23#include "util.h" 23#include "util.h"
@@ -30,6 +30,14 @@ static const char **syscalltbl_native = syscalltbl_x86_64;
30#include <asm/syscalls_64.c> 30#include <asm/syscalls_64.c>
31const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID; 31const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID;
32static const char **syscalltbl_native = syscalltbl_s390_64; 32static const char **syscalltbl_native = syscalltbl_s390_64;
33#elif defined(__powerpc64__)
34#include <asm/syscalls_64.c>
35const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_64_MAX_ID;
36static const char **syscalltbl_native = syscalltbl_powerpc_64;
37#elif defined(__powerpc__)
38#include <asm/syscalls_32.c>
39const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_32_MAX_ID;
40static const char **syscalltbl_native = syscalltbl_powerpc_32;
33#endif 41#endif
34 42
35struct syscall { 43struct syscall {
@@ -131,7 +139,7 @@ int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_g
131 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); 139 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
132} 140}
133 141
134#else /* HAVE_SYSCALL_TABLE */ 142#else /* HAVE_SYSCALL_TABLE_SUPPORT */
135 143
136#include <libaudit.h> 144#include <libaudit.h>
137 145
@@ -168,4 +176,4 @@ int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_g
168{ 176{
169 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); 177 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
170} 178}
171#endif /* HAVE_SYSCALL_TABLE */ 179#endif /* HAVE_SYSCALL_TABLE_SUPPORT */
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 40cfa36c022a..14d44c3235b8 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -26,7 +26,6 @@ struct thread {
26 pid_t ppid; 26 pid_t ppid;
27 int cpu; 27 int cpu;
28 refcount_t refcnt; 28 refcount_t refcnt;
29 char shortname[3];
30 bool comm_set; 29 bool comm_set;
31 int comm_len; 30 int comm_len;
32 bool dead; /* if set thread has exited */ 31 bool dead; /* if set thread has exited */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 3e1038f6491c..5d467d8ae9ab 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -32,6 +32,7 @@ static void thread_map__reset(struct thread_map *map, int start, int nr)
32 size_t size = (nr - start) * sizeof(map->map[0]); 32 size_t size = (nr - start) * sizeof(map->map[0]);
33 33
34 memset(&map->map[start], 0, size); 34 memset(&map->map[start], 0, size);
35 map->err_thread = -1;
35} 36}
36 37
37static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) 38static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
@@ -323,7 +324,7 @@ out_free_threads:
323} 324}
324 325
325struct thread_map *thread_map__new_str(const char *pid, const char *tid, 326struct thread_map *thread_map__new_str(const char *pid, const char *tid,
326 uid_t uid, bool per_thread) 327 uid_t uid, bool all_threads)
327{ 328{
328 if (pid) 329 if (pid)
329 return thread_map__new_by_pid_str(pid); 330 return thread_map__new_by_pid_str(pid);
@@ -331,7 +332,7 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,
331 if (!tid && uid != UINT_MAX) 332 if (!tid && uid != UINT_MAX)
332 return thread_map__new_by_uid(uid); 333 return thread_map__new_by_uid(uid);
333 334
334 if (per_thread) 335 if (all_threads)
335 return thread_map__new_all_cpus(); 336 return thread_map__new_all_cpus();
336 337
337 return thread_map__new_by_tid_str(tid); 338 return thread_map__new_by_tid_str(tid);
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 0a806b99e73c..2f689c90a8c6 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -14,6 +14,7 @@ struct thread_map_data {
14struct thread_map { 14struct thread_map {
15 refcount_t refcnt; 15 refcount_t refcnt;
16 int nr; 16 int nr;
17 int err_thread;
17 struct thread_map_data map[]; 18 struct thread_map_data map[];
18}; 19};
19 20
@@ -31,7 +32,7 @@ struct thread_map *thread_map__get(struct thread_map *map);
31void thread_map__put(struct thread_map *map); 32void thread_map__put(struct thread_map *map);
32 33
33struct thread_map *thread_map__new_str(const char *pid, 34struct thread_map *thread_map__new_str(const char *pid,
34 const char *tid, uid_t uid, bool per_thread); 35 const char *tid, uid_t uid, bool all_threads);
35 36
36struct thread_map *thread_map__new_by_tid_str(const char *tid_str); 37struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
37 38
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 0ac9077f62a2..b1e5c3a2b8e3 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -98,7 +98,7 @@ static void register_python_scripting(struct scripting_ops *scripting_ops)
98 } 98 }
99} 99}
100 100
101#ifdef NO_LIBPYTHON 101#ifndef HAVE_LIBPYTHON_SUPPORT
102void setup_python_scripting(void) 102void setup_python_scripting(void)
103{ 103{
104 register_python_scripting(&python_scripting_unsupported_ops); 104 register_python_scripting(&python_scripting_unsupported_ops);
@@ -161,7 +161,7 @@ static void register_perl_scripting(struct scripting_ops *scripting_ops)
161 } 161 }
162} 162}
163 163
164#ifdef NO_LIBPERL 164#ifndef HAVE_LIBPERL_SUPPORT
165void setup_perl_scripting(void) 165void setup_perl_scripting(void)
166{ 166{
167 register_perl_scripting(&perl_scripting_unsupported_ops); 167 register_perl_scripting(&perl_scripting_unsupported_ops);
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 1e9c974faf67..7bdd239c795c 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -50,7 +50,7 @@ static int __report_module(struct addr_location *al, u64 ip,
50 50
51 if (!mod) 51 if (!mod)
52 mod = dwfl_report_elf(ui->dwfl, dso->short_name, 52 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
53 dso->long_name, -1, al->map->start, 53 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start,
54 false); 54 false);
55 55
56 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; 56 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
@@ -236,7 +236,8 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
236 if (err) 236 if (err)
237 goto out; 237 goto out;
238 238
239 if (!dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui)) 239 err = !dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui);
240 if (err)
240 goto out; 241 goto out;
241 242
242 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui); 243 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 9496365da3d7..c9626c206208 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -11,8 +11,7 @@
11#include <stdlib.h> 11#include <stdlib.h>
12#include <stdarg.h> 12#include <stdarg.h>
13#include <linux/compiler.h> 13#include <linux/compiler.h>
14#include <linux/types.h> 14#include <sys/types.h>
15#include "namespaces.h"
16 15
17/* General helper functions */ 16/* General helper functions */
18void usage(const char *err) __noreturn; 17void usage(const char *err) __noreturn;
@@ -26,6 +25,7 @@ static inline void *zalloc(size_t size)
26#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) 25#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
27 26
28struct dirent; 27struct dirent;
28struct nsinfo;
29struct strlist; 29struct strlist;
30 30
31int mkdir_p(char *path, mode_t mode); 31int mkdir_p(char *path, mode_t mode);
diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config
index 2cccbba64418..f304be71c278 100644
--- a/tools/power/acpi/Makefile.config
+++ b/tools/power/acpi/Makefile.config
@@ -56,6 +56,7 @@ INSTALL_SCRIPT = ${INSTALL_PROGRAM}
56# to compile vs uClibc, that can be done here as well. 56# to compile vs uClibc, that can be done here as well.
57CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- 57CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
58CROSS_COMPILE ?= $(CROSS) 58CROSS_COMPILE ?= $(CROSS)
59LD = $(CC)
59HOSTCC = gcc 60HOSTCC = gcc
60 61
61# check if compiler option is supported 62# check if compiler option is supported
diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c
index dfa6fee1b915..ff8025de8237 100644
--- a/tools/power/acpi/common/cmfsize.c
+++ b/tools/power/acpi/common/cmfsize.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: cfsize - Common get file size function 4 * Module Name: cfsize - Common get file size function
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 * 7 *
26 * Alternatively, this software may be distributed under the terms of the 8 *****************************************************************************/
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#include <acpi/acpi.h> 10#include <acpi/acpi.h>
45#include "accommon.h" 11#include "accommon.h"
diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c
index f7032c9ab35e..7be89b873661 100644
--- a/tools/power/acpi/common/getopt.c
+++ b/tools/power/acpi/common/getopt.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: getopt 4 * Module Name: getopt
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 * 7 *
26 * Alternatively, this software may be distributed under the terms of the 8 *****************************************************************************/
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44/* 10/*
45 * ACPICA getopt() implementation 11 * ACPICA getopt() implementation
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index e7347edfd4f9..a20c703f8b7d 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables 4 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved. 7 *
10 * 8 *****************************************************************************/
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#include "acpidump.h" 10#include "acpidump.h"
45 11
diff --git a/tools/power/acpi/os_specific/service_layers/osunixdir.c b/tools/power/acpi/os_specific/service_layers/osunixdir.c
index 9b5e61b636d9..4fd44e218a83 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixdir.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixdir.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: osunixdir - Unix directory access interfaces 4 * Module Name: osunixdir - Unix directory access interfaces
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved. 7 *
10 * 8 *****************************************************************************/
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#include <acpi/acpi.h> 10#include <acpi/acpi.h>
45 11
diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c
index 8b26924e2602..93d8359309b6 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixmap.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: osunixmap - Unix OSL for file mappings 4 * Module Name: osunixmap - Unix OSL for file mappings
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved. 7 *
10 * 8 *****************************************************************************/
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#include "acpidump.h" 10#include "acpidump.h"
45#include <unistd.h> 11#include <unistd.h>
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 34c044da433c..8a88e87778bd 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: osunixxf - UNIX OSL interfaces 4 * Module Name: osunixxf - UNIX OSL interfaces
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved. 7 *
10 * 8 *****************************************************************************/
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44/* 10/*
45 * These interfaces are required in order to compile the ASL compiler and the 11 * These interfaces are required in order to compile the ASL compiler and the
diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h
index 3c679607d1c3..f69f1f559743 100644
--- a/tools/power/acpi/tools/acpidump/acpidump.h
+++ b/tools/power/acpi/tools/acpidump/acpidump.h
@@ -1,45 +1,11 @@
1/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: acpidump.h - Include file for acpi_dump utility 4 * Module Name: acpidump.h - Include file for acpi_dump utility
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 * 7 *
26 * Alternatively, this software may be distributed under the terms of the 8 *****************************************************************************/
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44/* 10/*
45 * Global variables. Defined in main.c only, externed in all other files 11 * Global variables. Defined in main.c only, externed in all other files
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index 9ad1712e4cf9..a9848de32d8e 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: apdump - Dump routines for ACPI tables (acpidump) 4 * Module Name: apdump - Dump routines for ACPI tables (acpidump)
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved. 7 *
10 * 8 *****************************************************************************/
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#include "acpidump.h" 10#include "acpidump.h"
45 11
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index 856e1b83407b..e86207e5afcf 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: apfiles - File-related functions for acpidump utility 4 * Module Name: apfiles - File-related functions for acpidump utility
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 * 7 *
26 * Alternatively, this software may be distributed under the terms of the 8 *****************************************************************************/
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#include "acpidump.h" 10#include "acpidump.h"
45 11
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index f4ef826800cf..db213171f8d9 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -1,45 +1,11 @@
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
1/****************************************************************************** 2/******************************************************************************
2 * 3 *
3 * Module Name: apmain - Main module for the acpidump utility 4 * Module Name: apmain - Main module for the acpidump utility
4 * 5 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp. 6 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 * 7 *
26 * Alternatively, this software may be distributed under the terms of the 8 *****************************************************************************/
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 9
44#define _DECLARE_GLOBALS 10#define _DECLARE_GLOBALS
45#include "acpidump.h" 11#include "acpidump.h"
diff --git a/tools/power/pm-graph/Makefile b/tools/power/pm-graph/Makefile
index 4e1e999e7b05..c1899cd72c80 100644
--- a/tools/power/pm-graph/Makefile
+++ b/tools/power/pm-graph/Makefile
@@ -7,11 +7,24 @@ all:
7 7
8install : uninstall 8install : uninstall
9 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph 9 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph
10 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph 10 install sleepgraph.py $(DESTDIR)$(PREFIX)/lib/pm-graph
11 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph 11 install bootgraph.py $(DESTDIR)$(PREFIX)/lib/pm-graph
12 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config
13 install -m 644 config/cgskip.txt $(DESTDIR)$(PREFIX)/lib/pm-graph/config
14 install -m 644 config/freeze-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
15 install -m 644 config/freeze.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
16 install -m 644 config/freeze-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
17 install -m 644 config/standby-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
18 install -m 644 config/standby.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
19 install -m 644 config/standby-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
20 install -m 644 config/suspend-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
21 install -m 644 config/suspend.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
22 install -m 644 config/suspend-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
23 install -m 644 config/suspend-x2-proc.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
12 24
13 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py $(DESTDIR)$(PREFIX)/bin/bootgraph 25 install -d $(DESTDIR)$(PREFIX)/bin
14 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py $(DESTDIR)$(PREFIX)/bin/sleepgraph 26 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/bootgraph.py $(DESTDIR)$(PREFIX)/bin/bootgraph
27 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/sleepgraph.py $(DESTDIR)$(PREFIX)/bin/sleepgraph
15 28
16 install -d $(DESTDIR)$(PREFIX)/share/man/man8 29 install -d $(DESTDIR)$(PREFIX)/share/man/man8
17 install bootgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8 30 install bootgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8
@@ -24,9 +37,11 @@ uninstall :
24 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph 37 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph
25 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph 38 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph
26 39
27 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py 40 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/config/*
28 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py 41 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config ] ; then \
29 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*.pyc 42 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph/config; \
43 fi;
44 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*
30 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \ 45 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
31 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \ 46 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
32 fi; 47 fi;
diff --git a/tools/power/pm-graph/bootgraph.8 b/tools/power/pm-graph/bootgraph.8
index dbdafcf546df..64d513f80a2a 100644
--- a/tools/power/pm-graph/bootgraph.8
+++ b/tools/power/pm-graph/bootgraph.8
@@ -37,6 +37,9 @@ Print the current tool version
37Add the dmesg log to the html output. It will be viewable by 37Add the dmesg log to the html output. It will be viewable by
38clicking a button in the timeline. 38clicking a button in the timeline.
39.TP 39.TP
40\fB-result \fIfile\fR
41Export a results table to a text file for parsing.
42.TP
40\fB-o \fIname\fR 43\fB-o \fIname\fR
41Overrides the output subdirectory name when running a new test. 44Overrides the output subdirectory name when running a new test.
42Use {date}, {time}, {hostname} for current values. 45Use {date}, {time}, {hostname} for current values.
@@ -44,14 +47,14 @@ Use {date}, {time}, {hostname} for current values.
44e.g. boot-{hostname}-{date}-{time} 47e.g. boot-{hostname}-{date}-{time}
45.SS "advanced" 48.SS "advanced"
46.TP 49.TP
47\fB-f\fR 50\fB-f or -callgraph\fR
48Use ftrace to add function detail (default: disabled)
49.TP
50\fB-callgraph\fR
51Use ftrace to create initcall callgraphs (default: disabled). If -func 51Use ftrace to create initcall callgraphs (default: disabled). If -func
52is not used there will be one callgraph per initcall. This can produce 52is not used there will be one callgraph per initcall. This can produce
53very large outputs, i.e. 10MB - 100MB. 53very large outputs, i.e. 10MB - 100MB.
54.TP 54.TP
55\fB-fstat\fR
56Use ftrace to add function detail (default: disabled)
57.TP
55\fB-maxdepth \fIlevel\fR 58\fB-maxdepth \fIlevel\fR
56limit the callgraph trace depth to \fIlevel\fR (default: 2). This is 59limit the callgraph trace depth to \fIlevel\fR (default: 2). This is
57the best way to limit the output size when using -callgraph. 60the best way to limit the output size when using -callgraph.
@@ -67,6 +70,13 @@ Reduce callgraph output in the timeline by limiting it to a list of calls. The
67argument can be a single function name or a comma delimited list. 70argument can be a single function name or a comma delimited list.
68(default: none) 71(default: none)
69.TP 72.TP
73\fB-cgskip \fIfile\fR
74Reduce callgraph output in the timeline by skipping over uninteresting
75functions in the trace, e.g. printk or console_unlock. The functions listed
76in this file will show up as empty leaves in the callgraph with only the start/end
77times displayed.
78(default: none)
79.TP
70\fB-timeprec \fIn\fR 80\fB-timeprec \fIn\fR
71Number of significant digits in timestamps (0:S, 3:ms, [6:us]) 81Number of significant digits in timestamps (0:S, 3:ms, [6:us])
72.TP 82.TP
diff --git a/tools/power/pm-graph/analyze_boot.py b/tools/power/pm-graph/bootgraph.py
index e83df141a597..abb4c38f029b 100755
--- a/tools/power/pm-graph/analyze_boot.py
+++ b/tools/power/pm-graph/bootgraph.py
@@ -32,7 +32,7 @@ import platform
32import shutil 32import shutil
33from datetime import datetime, timedelta 33from datetime import datetime, timedelta
34from subprocess import call, Popen, PIPE 34from subprocess import call, Popen, PIPE
35import analyze_suspend as aslib 35import sleepgraph as aslib
36 36
37# ----------------- CLASSES -------------------- 37# ----------------- CLASSES --------------------
38 38
@@ -42,23 +42,18 @@ import analyze_suspend as aslib
42# store system values and test parameters 42# store system values and test parameters
43class SystemValues(aslib.SystemValues): 43class SystemValues(aslib.SystemValues):
44 title = 'BootGraph' 44 title = 'BootGraph'
45 version = '2.1' 45 version = '2.2'
46 hostname = 'localhost' 46 hostname = 'localhost'
47 testtime = '' 47 testtime = ''
48 kernel = '' 48 kernel = ''
49 dmesgfile = '' 49 dmesgfile = ''
50 ftracefile = '' 50 ftracefile = ''
51 htmlfile = 'bootgraph.html' 51 htmlfile = 'bootgraph.html'
52 outfile = ''
53 testdir = '' 52 testdir = ''
54 testdirprefix = 'boot' 53 kparams = ''
55 embedded = False 54 result = ''
56 testlog = False
57 dmesglog = False
58 ftracelog = False
59 useftrace = False 55 useftrace = False
60 usecallgraph = False 56 usecallgraph = False
61 usedevsrc = True
62 suspendmode = 'boot' 57 suspendmode = 'boot'
63 max_graph_depth = 2 58 max_graph_depth = 2
64 graph_filter = 'do_one_initcall' 59 graph_filter = 'do_one_initcall'
@@ -69,11 +64,6 @@ class SystemValues(aslib.SystemValues):
69 bootloader = 'grub' 64 bootloader = 'grub'
70 blexec = [] 65 blexec = []
71 def __init__(self): 66 def __init__(self):
72 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
73 self.embedded = True
74 self.dmesglog = True
75 self.outfile = os.environ['LOG_FILE']
76 self.htmlfile = os.environ['LOG_FILE']
77 self.hostname = platform.node() 67 self.hostname = platform.node()
78 self.testtime = datetime.now().strftime('%Y-%m-%d_%H:%M:%S') 68 self.testtime = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
79 if os.path.exists('/proc/version'): 69 if os.path.exists('/proc/version'):
@@ -148,11 +138,18 @@ class SystemValues(aslib.SystemValues):
148 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0]) 138 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0])
149 args = iter(sys.argv[1:]) 139 args = iter(sys.argv[1:])
150 for arg in args: 140 for arg in args:
151 if arg in ['-h', '-v', '-cronjob', '-reboot']: 141 if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']:
152 continue 142 continue
153 elif arg in ['-o', '-dmesg', '-ftrace', '-func']: 143 elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
154 args.next() 144 args.next()
155 continue 145 continue
146 elif arg == '-result':
147 cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next()))
148 continue
149 elif arg == '-cgskip':
150 file = self.configFile(args.next())
151 cmdline += ' %s "%s"' % (arg, os.path.abspath(file))
152 continue
156 cmdline += ' '+arg 153 cmdline += ' '+arg
157 if self.graph_filter != 'do_one_initcall': 154 if self.graph_filter != 'do_one_initcall':
158 cmdline += ' -func "%s"' % self.graph_filter 155 cmdline += ' -func "%s"' % self.graph_filter
@@ -166,14 +163,6 @@ class SystemValues(aslib.SystemValues):
166 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n' 163 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n'
167 print 'CMDLINE="%s"' % cmdline 164 print 'CMDLINE="%s"' % cmdline
168 sys.exit() 165 sys.exit()
169 def getExec(self, cmd):
170 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
171 '/usr/local/sbin', '/usr/local/bin']
172 for path in dirlist:
173 cmdfull = os.path.join(path, cmd)
174 if os.path.exists(cmdfull):
175 return cmdfull
176 return ''
177 def blGrub(self): 166 def blGrub(self):
178 blcmd = '' 167 blcmd = ''
179 for cmd in ['update-grub', 'grub-mkconfig', 'grub2-mkconfig']: 168 for cmd in ['update-grub', 'grub-mkconfig', 'grub2-mkconfig']:
@@ -199,6 +188,14 @@ class SystemValues(aslib.SystemValues):
199 self.blGrub() 188 self.blGrub()
200 else: 189 else:
201 doError('unknown boot loader: %s' % self.bootloader) 190 doError('unknown boot loader: %s' % self.bootloader)
191 def writeDatafileHeader(self, filename):
192 self.kparams = open('/proc/cmdline', 'r').read().strip()
193 fp = open(filename, 'w')
194 fp.write(self.teststamp+'\n')
195 fp.write(self.sysstamp+'\n')
196 fp.write('# command | %s\n' % self.cmdline)
197 fp.write('# kparams | %s\n' % self.kparams)
198 fp.close()
202 199
203sysvals = SystemValues() 200sysvals = SystemValues()
204 201
@@ -249,7 +246,7 @@ class Data(aslib.Data):
249 return name 246 return name
250 def deviceMatch(self, pid, cg): 247 def deviceMatch(self, pid, cg):
251 if cg.end - cg.start == 0: 248 if cg.end - cg.start == 0:
252 return True 249 return ''
253 for p in data.phases: 250 for p in data.phases:
254 list = self.dmesg[p]['list'] 251 list = self.dmesg[p]['list']
255 for devname in list: 252 for devname in list:
@@ -260,14 +257,25 @@ class Data(aslib.Data):
260 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0): 257 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0):
261 dev['ftrace'] = cg 258 dev['ftrace'] = cg
262 self.do_one_initcall = True 259 self.do_one_initcall = True
263 return True 260 return devname
264 else: 261 else:
265 if(cg.start > dev['start'] and cg.end < dev['end']): 262 if(cg.start > dev['start'] and cg.end < dev['end']):
266 if 'ftraces' not in dev: 263 if 'ftraces' not in dev:
267 dev['ftraces'] = [] 264 dev['ftraces'] = []
268 dev['ftraces'].append(cg) 265 dev['ftraces'].append(cg)
269 return True 266 return devname
270 return False 267 return ''
268 def printDetails(self):
269 sysvals.vprint('Timeline Details:')
270 sysvals.vprint(' Host: %s' % sysvals.hostname)
271 sysvals.vprint(' Kernel: %s' % sysvals.kernel)
272 sysvals.vprint(' Test time: %s' % sysvals.testtime)
273 sysvals.vprint(' Boot time: %s' % self.boottime)
274 for phase in self.phases:
275 dc = len(self.dmesg[phase]['list'])
276 sysvals.vprint('%9s mode: %.3f - %.3f (%d initcalls)' % (phase,
277 self.dmesg[phase]['start']*1000,
278 self.dmesg[phase]['end']*1000, dc))
271 279
272# ----------------- FUNCTIONS -------------------- 280# ----------------- FUNCTIONS --------------------
273 281
@@ -275,6 +283,8 @@ class Data(aslib.Data):
275# Description: 283# Description:
276# parse a kernel log for boot data 284# parse a kernel log for boot data
277def parseKernelLog(): 285def parseKernelLog():
286 sysvals.vprint('Analyzing the dmesg data (%s)...' % \
287 os.path.basename(sysvals.dmesgfile))
278 phase = 'kernel' 288 phase = 'kernel'
279 data = Data(0) 289 data = Data(0)
280 data.dmesg['kernel']['start'] = data.start = ktime = 0.0 290 data.dmesg['kernel']['start'] = data.start = ktime = 0.0
@@ -298,6 +308,12 @@ def parseKernelLog():
298 elif re.match(tp.sysinfofmt, line): 308 elif re.match(tp.sysinfofmt, line):
299 tp.sysinfo = line 309 tp.sysinfo = line
300 continue 310 continue
311 elif re.match(tp.cmdlinefmt, line):
312 tp.cmdline = line
313 continue
314 elif re.match(tp.kparamsfmt, line):
315 tp.kparams = line
316 continue
301 idx = line.find('[') 317 idx = line.find('[')
302 if idx > 1: 318 if idx > 1:
303 line = line[idx:] 319 line = line[idx:]
@@ -353,6 +369,17 @@ def parseKernelLog():
353# Description: 369# Description:
354# Check if trace is available and copy to a temp file 370# Check if trace is available and copy to a temp file
355def parseTraceLog(data): 371def parseTraceLog(data):
372 sysvals.vprint('Analyzing the ftrace data (%s)...' % \
373 os.path.basename(sysvals.ftracefile))
374 # if available, calculate cgfilter allowable ranges
375 cgfilter = []
376 if len(sysvals.cgfilter) > 0:
377 for p in data.phases:
378 list = data.dmesg[p]['list']
379 for i in sysvals.cgfilter:
380 if i in list:
381 cgfilter.append([list[i]['start']-0.0001,
382 list[i]['end']+0.0001])
356 # parse the trace log 383 # parse the trace log
357 ftemp = dict() 384 ftemp = dict()
358 tp = aslib.TestProps() 385 tp = aslib.TestProps()
@@ -366,7 +393,16 @@ def parseTraceLog(data):
366 continue 393 continue
367 m_time, m_proc, m_pid, m_msg, m_dur = \ 394 m_time, m_proc, m_pid, m_msg, m_dur = \
368 m.group('time', 'proc', 'pid', 'msg', 'dur') 395 m.group('time', 'proc', 'pid', 'msg', 'dur')
369 if float(m_time) > data.end: 396 t = float(m_time)
397 if len(cgfilter) > 0:
398 allow = False
399 for r in cgfilter:
400 if t >= r[0] and t < r[1]:
401 allow = True
402 break
403 if not allow:
404 continue
405 if t > data.end:
370 break 406 break
371 if(m_time and m_pid and m_msg): 407 if(m_time and m_pid and m_msg):
372 t = aslib.FTraceLine(m_time, m_msg, m_dur) 408 t = aslib.FTraceLine(m_time, m_msg, m_dur)
@@ -378,24 +414,36 @@ def parseTraceLog(data):
378 key = (m_proc, pid) 414 key = (m_proc, pid)
379 if(key not in ftemp): 415 if(key not in ftemp):
380 ftemp[key] = [] 416 ftemp[key] = []
381 ftemp[key].append(aslib.FTraceCallGraph(pid)) 417 ftemp[key].append(aslib.FTraceCallGraph(pid, sysvals))
382 cg = ftemp[key][-1] 418 cg = ftemp[key][-1]
383 if(cg.addLine(t)): 419 res = cg.addLine(t)
384 ftemp[key].append(aslib.FTraceCallGraph(pid)) 420 if(res != 0):
421 ftemp[key].append(aslib.FTraceCallGraph(pid, sysvals))
422 if(res == -1):
423 ftemp[key][-1].addLine(t)
424
385 tf.close() 425 tf.close()
386 426
387 # add the callgraph data to the device hierarchy 427 # add the callgraph data to the device hierarchy
388 for key in ftemp: 428 for key in ftemp:
389 proc, pid = key 429 proc, pid = key
390 for cg in ftemp[key]: 430 for cg in ftemp[key]:
391 if len(cg.list) < 1 or cg.invalid: 431 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
392 continue 432 continue
393 if(not cg.postProcess()): 433 if(not cg.postProcess()):
394 print('Sanity check failed for %s-%d' % (proc, pid)) 434 print('Sanity check failed for %s-%d' % (proc, pid))
395 continue 435 continue
396 # match cg data to devices 436 # match cg data to devices
397 if not data.deviceMatch(pid, cg): 437 devname = data.deviceMatch(pid, cg)
398 print ' BAD: %s %s-%d [%f - %f]' % (cg.name, proc, pid, cg.start, cg.end) 438 if not devname:
439 kind = 'Orphan'
440 if cg.partial:
441 kind = 'Partial'
442 sysvals.vprint('%s callgraph found for %s %s-%d [%f - %f]' %\
443 (kind, cg.name, proc, pid, cg.start, cg.end))
444 elif len(cg.list) > 1000000:
445 print 'WARNING: the callgraph found for %s is massive! (%d lines)' %\
446 (devname, len(cg.list))
399 447
400# Function: retrieveLogs 448# Function: retrieveLogs
401# Description: 449# Description:
@@ -473,7 +521,7 @@ def createBootGraph(data):
473 devtl = aslib.Timeline(100, 20) 521 devtl = aslib.Timeline(100, 20)
474 522
475 # write the test title and general info header 523 # write the test title and general info header
476 devtl.createHeader(sysvals) 524 devtl.createHeader(sysvals, sysvals.stamp)
477 525
478 # Generate the header for this timeline 526 # Generate the header for this timeline
479 t0 = data.start 527 t0 = data.start
@@ -574,12 +622,9 @@ def createBootGraph(data):
574 data.dmesg[phase]['color'], phase+'_mode', phase[0]) 622 data.dmesg[phase]['color'], phase+'_mode', phase[0])
575 devtl.html += '</div>\n' 623 devtl.html += '</div>\n'
576 624
577 if(sysvals.outfile == sysvals.htmlfile): 625 hf = open(sysvals.htmlfile, 'w')
578 hf = open(sysvals.htmlfile, 'a')
579 else:
580 hf = open(sysvals.htmlfile, 'w')
581 626
582 # add the css if this is not an embedded run 627 # add the css
583 extra = '\ 628 extra = '\
584 .c1 {background:rgba(209,0,0,0.4);}\n\ 629 .c1 {background:rgba(209,0,0,0.4);}\n\
585 .c2 {background:rgba(255,102,34,0.4);}\n\ 630 .c2 {background:rgba(255,102,34,0.4);}\n\
@@ -597,8 +642,7 @@ def createBootGraph(data):
597 .fstat td {text-align:left;width:35px;}\n\ 642 .fstat td {text-align:left;width:35px;}\n\
598 .srccall {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\ 643 .srccall {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\
599 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n' 644 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n'
600 if(not sysvals.embedded): 645 aslib.addCSS(hf, sysvals, 1, False, extra)
601 aslib.addCSS(hf, sysvals, 1, False, extra)
602 646
603 # write the device timeline 647 # write the device timeline
604 hf.write(devtl.html) 648 hf.write(devtl.html)
@@ -631,6 +675,9 @@ def createBootGraph(data):
631 if(sysvals.usecallgraph): 675 if(sysvals.usecallgraph):
632 aslib.addCallgraphs(sysvals, hf, data) 676 aslib.addCallgraphs(sysvals, hf, data)
633 677
678 # add the test log as a hidden div
679 if sysvals.testlog and sysvals.logmsg:
680 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n')
634 # add the dmesg log as a hidden div 681 # add the dmesg log as a hidden div
635 if sysvals.dmesglog: 682 if sysvals.dmesglog:
636 hf.write('<div id="dmesglog" style="display:none;">\n') 683 hf.write('<div id="dmesglog" style="display:none;">\n')
@@ -639,14 +686,9 @@ def createBootGraph(data):
639 hf.write(line) 686 hf.write(line)
640 hf.write('</div>\n') 687 hf.write('</div>\n')
641 688
642 if(not sysvals.embedded): 689 # write the footer and close
643 # write the footer and close 690 aslib.addScriptCode(hf, [data])
644 aslib.addScriptCode(hf, [data]) 691 hf.write('</body>\n</html>\n')
645 hf.write('</body>\n</html>\n')
646 else:
647 # embedded out will be loaded in a page, skip the js
648 hf.write('<div id=bounds style=display:none>%f,%f</div>' % \
649 (data.start*1000, data.end*1000))
650 hf.close() 692 hf.close()
651 return True 693 return True
652 694
@@ -780,6 +822,7 @@ def doError(msg, help=False):
780 if help == True: 822 if help == True:
781 printHelp() 823 printHelp()
782 print 'ERROR: %s\n' % msg 824 print 'ERROR: %s\n' % msg
825 sysvals.outputResult({'error':msg})
783 sys.exit() 826 sys.exit()
784 827
785# Function: printHelp 828# Function: printHelp
@@ -806,18 +849,21 @@ def printHelp():
806 print('Options:') 849 print('Options:')
807 print(' -h Print this help text') 850 print(' -h Print this help text')
808 print(' -v Print the current tool version') 851 print(' -v Print the current tool version')
852 print(' -verbose Print extra information during execution and analysis')
809 print(' -addlogs Add the dmesg log to the html output') 853 print(' -addlogs Add the dmesg log to the html output')
854 print(' -result fn Export a results table to a text file for parsing.')
810 print(' -o name Overrides the output subdirectory name when running a new test') 855 print(' -o name Overrides the output subdirectory name when running a new test')
811 print(' default: boot-{date}-{time}') 856 print(' default: boot-{date}-{time}')
812 print(' [advanced]') 857 print(' [advanced]')
813 print(' -f Use ftrace to add function detail (default: disabled)') 858 print(' -fstat Use ftrace to add function detail and statistics (default: disabled)')
814 print(' -callgraph Add callgraph detail, can be very large (default: disabled)') 859 print(' -f/-callgraph Add callgraph detail, can be very large (default: disabled)')
815 print(' -maxdepth N limit the callgraph data to N call levels (default: 2)') 860 print(' -maxdepth N limit the callgraph data to N call levels (default: 2)')
816 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)') 861 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)')
817 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])') 862 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])')
818 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)') 863 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)')
819 print(' -func list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)') 864 print(' -func list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)')
820 print(' -cgfilter S Filter the callgraph output in the timeline') 865 print(' -cgfilter S Filter the callgraph output in the timeline')
866 print(' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)')
821 print(' -bl name Use the following boot loader for kernel params (default: grub)') 867 print(' -bl name Use the following boot loader for kernel params (default: grub)')
822 print(' -reboot Reboot the machine automatically and generate a new timeline') 868 print(' -reboot Reboot the machine automatically and generate a new timeline')
823 print(' -manual Show the steps to generate a new timeline manually (used with -reboot)') 869 print(' -manual Show the steps to generate a new timeline manually (used with -reboot)')
@@ -837,8 +883,13 @@ if __name__ == '__main__':
837 # loop through the command line arguments 883 # loop through the command line arguments
838 cmd = '' 884 cmd = ''
839 testrun = True 885 testrun = True
886 switchoff = ['disable', 'off', 'false', '0']
840 simplecmds = ['-sysinfo', '-kpupdate', '-flistall', '-checkbl'] 887 simplecmds = ['-sysinfo', '-kpupdate', '-flistall', '-checkbl']
888 cgskip = ''
889 if '-f' in sys.argv:
890 cgskip = sysvals.configFile('cgskip.txt')
841 args = iter(sys.argv[1:]) 891 args = iter(sys.argv[1:])
892 mdset = False
842 for arg in args: 893 for arg in args:
843 if(arg == '-h'): 894 if(arg == '-h'):
844 printHelp() 895 printHelp()
@@ -846,13 +897,17 @@ if __name__ == '__main__':
846 elif(arg == '-v'): 897 elif(arg == '-v'):
847 print("Version %s" % sysvals.version) 898 print("Version %s" % sysvals.version)
848 sys.exit() 899 sys.exit()
900 elif(arg == '-verbose'):
901 sysvals.verbose = True
849 elif(arg in simplecmds): 902 elif(arg in simplecmds):
850 cmd = arg[1:] 903 cmd = arg[1:]
851 elif(arg == '-f'): 904 elif(arg == '-fstat'):
852 sysvals.useftrace = True 905 sysvals.useftrace = True
853 elif(arg == '-callgraph'): 906 elif(arg == '-callgraph' or arg == '-f'):
854 sysvals.useftrace = True 907 sysvals.useftrace = True
855 sysvals.usecallgraph = True 908 sysvals.usecallgraph = True
909 elif(arg == '-cgdump'):
910 sysvals.cgdump = True
856 elif(arg == '-mincg'): 911 elif(arg == '-mincg'):
857 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) 912 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
858 elif(arg == '-cgfilter'): 913 elif(arg == '-cgfilter'):
@@ -860,7 +915,18 @@ if __name__ == '__main__':
860 val = args.next() 915 val = args.next()
861 except: 916 except:
862 doError('No callgraph functions supplied', True) 917 doError('No callgraph functions supplied', True)
863 sysvals.setDeviceFilter(val) 918 sysvals.setCallgraphFilter(val)
919 elif(arg == '-cgskip'):
920 try:
921 val = args.next()
922 except:
923 doError('No file supplied', True)
924 if val.lower() in switchoff:
925 cgskip = ''
926 else:
927 cgskip = sysvals.configFile(val)
928 if(not cgskip):
929 doError('%s does not exist' % cgskip)
864 elif(arg == '-bl'): 930 elif(arg == '-bl'):
865 try: 931 try:
866 val = args.next() 932 val = args.next()
@@ -872,6 +938,7 @@ if __name__ == '__main__':
872 elif(arg == '-timeprec'): 938 elif(arg == '-timeprec'):
873 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6)) 939 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6))
874 elif(arg == '-maxdepth'): 940 elif(arg == '-maxdepth'):
941 mdset = True
875 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) 942 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
876 elif(arg == '-func'): 943 elif(arg == '-func'):
877 try: 944 try:
@@ -902,8 +969,6 @@ if __name__ == '__main__':
902 doError('No dmesg file supplied', True) 969 doError('No dmesg file supplied', True)
903 if(os.path.exists(val) == False): 970 if(os.path.exists(val) == False):
904 doError('%s does not exist' % val) 971 doError('%s does not exist' % val)
905 if(sysvals.htmlfile == val or sysvals.outfile == val):
906 doError('Output filename collision')
907 testrun = False 972 testrun = False
908 sysvals.dmesgfile = val 973 sysvals.dmesgfile = val
909 elif(arg == '-o'): 974 elif(arg == '-o'):
@@ -912,6 +977,12 @@ if __name__ == '__main__':
912 except: 977 except:
913 doError('No subdirectory name supplied', True) 978 doError('No subdirectory name supplied', True)
914 sysvals.testdir = sysvals.setOutputFolder(val) 979 sysvals.testdir = sysvals.setOutputFolder(val)
980 elif(arg == '-result'):
981 try:
982 val = args.next()
983 except:
984 doError('No result file supplied', True)
985 sysvals.result = val
915 elif(arg == '-reboot'): 986 elif(arg == '-reboot'):
916 sysvals.reboot = True 987 sysvals.reboot = True
917 elif(arg == '-manual'): 988 elif(arg == '-manual'):
@@ -947,7 +1018,7 @@ if __name__ == '__main__':
947 sysvals.getBootLoader() 1018 sysvals.getBootLoader()
948 print 'Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec) 1019 print 'Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec)
949 elif(cmd == 'sysinfo'): 1020 elif(cmd == 'sysinfo'):
950 sysvals.printSystemInfo() 1021 sysvals.printSystemInfo(True)
951 sys.exit() 1022 sys.exit()
952 1023
953 # reboot: update grub, setup a cronjob, and reboot 1024 # reboot: update grub, setup a cronjob, and reboot
@@ -963,6 +1034,10 @@ if __name__ == '__main__':
963 sysvals.manualRebootRequired() 1034 sysvals.manualRebootRequired()
964 sys.exit() 1035 sys.exit()
965 1036
1037 if sysvals.usecallgraph and cgskip:
1038 sysvals.vprint('Using cgskip file: %s' % cgskip)
1039 sysvals.setCallgraphBlacklist(cgskip)
1040
966 # cronjob: remove the cronjob, grub changes, and disable ftrace 1041 # cronjob: remove the cronjob, grub changes, and disable ftrace
967 if sysvals.iscronjob: 1042 if sysvals.iscronjob:
968 updateCron(True) 1043 updateCron(True)
@@ -980,29 +1055,23 @@ if __name__ == '__main__':
980 1055
981 # process the log data 1056 # process the log data
982 if sysvals.dmesgfile: 1057 if sysvals.dmesgfile:
1058 if not mdset:
1059 sysvals.max_graph_depth = 0
983 data = parseKernelLog() 1060 data = parseKernelLog()
984 if(not data.valid): 1061 if(not data.valid):
985 doError('No initcall data found in %s' % sysvals.dmesgfile) 1062 doError('No initcall data found in %s' % sysvals.dmesgfile)
986 if sysvals.useftrace and sysvals.ftracefile: 1063 if sysvals.useftrace and sysvals.ftracefile:
987 parseTraceLog(data) 1064 parseTraceLog(data)
1065 if sysvals.cgdump:
1066 data.debugPrint()
1067 sys.exit()
988 else: 1068 else:
989 doError('dmesg file required') 1069 doError('dmesg file required')
990 1070
991 print(' Host: %s' % sysvals.hostname) 1071 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
992 print(' Test time: %s' % sysvals.testtime) 1072 sysvals.vprint('Command:\n %s' % sysvals.cmdline)
993 print(' Boot time: %s' % data.boottime) 1073 sysvals.vprint('Kernel parameters:\n %s' % sysvals.kparams)
994 print('Kernel Version: %s' % sysvals.kernel) 1074 data.printDetails()
995 print(' Kernel start: %.3f' % (data.start * 1000))
996 print('Usermode start: %.3f' % (data.tUserMode * 1000))
997 print('Last Init Call: %.3f' % (data.end * 1000))
998
999 # handle embedded output logs
1000 if(sysvals.outfile and sysvals.embedded):
1001 fp = open(sysvals.outfile, 'w')
1002 fp.write('pass %s initstart %.3f end %.3f boot %s\n' %
1003 (data.valid, data.tUserMode*1000, data.end*1000, data.boottime))
1004 fp.close()
1005
1006 createBootGraph(data) 1075 createBootGraph(data)
1007 1076
1008 # if running as root, change output dir owner to sudo_user 1077 # if running as root, change output dir owner to sudo_user
@@ -1010,3 +1079,7 @@ if __name__ == '__main__':
1010 os.getuid() == 0 and 'SUDO_USER' in os.environ: 1079 os.getuid() == 0 and 'SUDO_USER' in os.environ:
1011 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 1080 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
1012 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True) 1081 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True)
1082
1083 sysvals.stamp['boot'] = (data.tUserMode - data.start) * 1000
1084 sysvals.stamp['lastinit'] = data.end * 1000
1085 sysvals.outputResult(sysvals.stamp)
diff --git a/tools/power/pm-graph/config/cgskip.txt b/tools/power/pm-graph/config/cgskip.txt
new file mode 100644
index 000000000000..e48d588fbfb4
--- /dev/null
+++ b/tools/power/pm-graph/config/cgskip.txt
@@ -0,0 +1,65 @@
1# -----------------------------------------------
2# CallGraph function skip list
3#
4# This file contains a list of functions which are
5# meant to be skipped in the callgraph trace. It reduces
6# the callgraph html file size by treating these functions
7# as leaves with no child calls. It can be editted by
8# adding or removing function symbol names.
9#
10# The sleepgraph tool automatically pulls this file in when
11# it is found in the config folder. It can be ignored if
12# the tool is called with "-cgskip off".
13# -----------------------------------------------
14
15# low level scheduling and timing
16up
17down_timeout
18mutex_lock
19down_read
20complete_all
21schedule_timeout
22wake_up_process
23msleep
24__udelay
25ktime_get
26
27# console calls
28printk
29dev_printk
30console_unlock
31
32# memory handling
33__kmalloc
34__kmalloc_track_caller
35kmem_cache_alloc
36kmem_cache_alloc_trace
37kmem_cache_free
38kstrdup
39kstrdup_const
40kmalloc_slab
41new_slab
42__slab_alloc
43__slab_free
44raw_pci_read
45pci_read
46alloc_pages_current
47
48# debugfs and sysfs setup
49debugfs_remove_recursive
50debugfs_create_dir
51debugfs_create_files
52debugfs_create_dir
53debugfs_get_inode
54sysfs_add_file_mode_ns
55sysfs_add_file
56sysfs_create_dir_ns
57sysfs_create_link
58sysfs_create_group
59sysfs_create_groups
60sysfs_create_bin_file
61dpm_sysfs_add
62sysfs_create_file_ns
63sysfs_merge_group
64sysfs_add_link_to_group
65sysfs_create_link_sd
diff --git a/tools/power/pm-graph/config/custom-timeline-functions.cfg b/tools/power/pm-graph/config/custom-timeline-functions.cfg
new file mode 100644
index 000000000000..4f80ad7d7275
--- /dev/null
+++ b/tools/power/pm-graph/config/custom-timeline-functions.cfg
@@ -0,0 +1,205 @@
1#
2# This is the configuration file for sleepgraph. It contains
3# all the tool arguments so that they don't have to be given on the
4# command line. It also includes advanced settings for functions
5# and kprobes. It is run like this
6#
7# sudo ./sleepgraph.py -config thisfile.txt
8#
9
10[Settings]
11
12# Verbosity
13# print verbose messages (default: false)
14verbose: false
15
16# Suspend Mode
17# e.g. standby, mem, freeze, disk (default: mem)
18mode: mem
19
20# Automatic Wakeup
21# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
22rtcwake: 15
23
24# Add Logs
25# add the dmesg and ftrace log to the html output (default: false)
26addlogs: false
27
28# Display function calls
29# graph source functions in the timeline (default: false)
30dev: true
31
32# Callgraph
33# gather detailed ftrace callgraph data on all timeline events (default: false)
34callgraph: false
35
36# Back to Back Suspend/Resume
37# Run two suspend/resumes back to back (default: false)
38x2: false
39
40# Back to Back Suspend Delay
41# Time delay between the two test runs in ms (default: 0 ms)
42x2delay: 0
43
44# Minimum Device Length
45# graph only devices longer than min in the timeline (default: 0.001 ms)
46mindev: 1
47
48# Minimum Callgraph Length
49# provide callgraph data for blocks longer than min (default: 0.001 ms)
50mincg: 1
51
52# Suspend/Resume Gap
53# insert a small visible gap between suspend and resume on the timeline (default: false)
54srgap: false
55
56# Output Directory Format
57# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
58output-dir: suspend-{hostname}-{date}-{time}-custom
59
60# Override default timeline entries
61# Do not use the internal default functions for timeline entries (default: false)
62# Set this to true if you intend to only use the ones defined in this config
63override-timeline-functions: true
64
65# Override default dev timeline entries
66# Do not use the internal default functions for dev timeline entries (default: false)
67# Set this to true if you intend to only use the ones defined in this config
68override-dev-timeline-functions: true
69
70[timeline_functions_x86_64]
71#
72# Function calls to display in the timeline alongside device callbacks.
73# The tool has an internal set of these functions which should cover the
74# whole of kernel execution, but you can append or override here.
75#
76# This is a list of kprobes which use both symbol data and function arg data.
77# The function calls are displayed on the timeline alongside the device blocks.
78# The args are pulled directly from the stack using this architecture's registers
79# and stack formatting. Three pieces of info are required. The function name,
80# a format string, and an argument list
81#
82# Entry format:
83#
84# function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
85#
86# Required Arguments:
87#
88# function: The symbol name for the function you want probed, this is the
89# minimum required for an entry, it will show up as the function
90# name with no arguments.
91#
92# example: _cpu_up:
93#
94# Optional Arguments:
95#
96# format: The format to display the data on the timeline in. Use braces to
97# enclose the arg names.
98#
99# example: CPU_ON[{cpu}]
100#
101# color: The color of the entry block in the timeline. The default color is
102# transparent, so the entry shares the phase color. The color is an
103# html color string, either a word, or an RGB.
104#
105# example: [color=#CC00CC]
106#
107# arglist: A list of arguments from registers/stack addresses. See URL:
108# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
109#
110# example: cpu=%di:s32
111#
112# Example: Display cpu resume in the timeline
113#
114# _cpu_up: CPU_ON[{cpu}] cpu=%di:s32 [color=orange]
115#
116_cpu_down: CPU_OFF[{cpu}] cpu=%di:s32
117_cpu_up: CPU_ON[{cpu}] cpu=%di:s32
118sys_sync:
119pm_prepare_console:
120pm_notifier_call_chain:
121freeze_processes:
122freeze_kernel_threads:
123pm_restrict_gfp_mask:
124acpi_suspend_begin:
125suspend_console:
126acpi_pm_prepare:
127syscore_suspend:
128arch_enable_nonboot_cpus_end:
129syscore_resume:
130acpi_pm_finish:
131resume_console:
132acpi_pm_end:
133pm_restore_gfp_mask:
134thaw_processes:
135pm_restore_console:
136
137[dev_timeline_functions_x86_64]
138#
139# Dev mode function calls to display inside timeline entries
140#
141# This is a list of kprobes which use both symbol data and function arg data.
142# The function calls are displayed on the timeline alongside the device blocks.
143# The args are pulled directly from the stack using this architecture's registers
144# and stack formatting. Three pieces of info are required. The function name,
145# a format string, and an argument list
146#
147# Entry format:
148#
149# function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
150#
151# Required Arguments:
152#
153# function: The symbol name for the function you want probed, this is the
154# minimum required for an entry, it will show up as the function
155# name with no arguments.
156#
157# example: ata_eh_recover:
158#
159# Optional Arguments:
160#
161# format: The format to display the data on the timeline in. Use braces to
162# enclose the arg names.
163#
164# example: ata{port}_port_reset
165#
166# color: The color of the entry block in the timeline. The default color is
167# transparent, so the entry shares the phase color. The color is an
168# html color string, either a word, or an RGB.
169#
170# example: [color=#CC00CC]
171#
172# arglist: A list of arguments from registers/stack addresses. See URL:
173# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
174#
175# example: port=+36(%di):s32
176#
177# Example: Display ATA port reset as ataN_port_reset in the timeline
178#
179# ata_eh_recover: ata{port}_port_reset port=+36(%di):s32
180#
181msleep: msleep time=%di:s32
182schedule_timeout_uninterruptible: schedule_timeout_uninterruptible timeout=%di:s32
183schedule_timeout: schedule_timeout timeout=%di:s32
184usleep_range: usleep_range min=%di:s32 max=%si:s32
185__const_udelay: udelay loops=%di:s32
186__mutex_lock_slowpath: mutex_lock_slowpath
187ata_eh_recover: ata_eh_recover port=+36(%di):s32
188acpi_os_stall:
189acpi_resume_power_resources:
190acpi_ps_parse_aml:
191ext4_sync_fs:
192i915_gem_resume:
193i915_restore_state:
194intel_opregion_setup:
195g4x_pre_enable_dp:
196vlv_pre_enable_dp:
197chv_pre_enable_dp:
198g4x_enable_dp:
199vlv_enable_dp:
200intel_hpd_init:
201intel_opregion_register:
202intel_dp_detect:
203intel_hdmi_detect:
204intel_opregion_init:
205intel_fbdev_set_suspend:
diff --git a/tools/power/pm-graph/config/example.cfg b/tools/power/pm-graph/config/example.cfg
new file mode 100644
index 000000000000..05b2efb9bb54
--- /dev/null
+++ b/tools/power/pm-graph/config/example.cfg
@@ -0,0 +1,133 @@
1#
2# Generic S3 (Suspend to Mem) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/example.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: true
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# Skip HTML generation
41# Only capture the logs, don't generate the html timeline (default: false)
42skiphtml: false
43
44# Sync filesystem before suspend
45# run sync before the test, minimizes sys_sync call time (default: false)
46sync: true
47
48# Runtime suspend enable/disable
49# Enable/disable runtime suspend for all devices, restore all after test (default: no-action)
50# rs: disable
51
52# Turn display on/off for test
53# Switch the display on/off for the test using xset (default: no-action)
54# display: on
55
56# Print results to text file
57# Print the status of the test run in the given file (default: no-action)
58result: result.txt
59
60# Gzip the log files to save space
61# Gzip the generated log files, and read gzipped log files (default: false)
62gzip: true
63
64# ---- Advanced Options ----
65
66# Command to execute in lieu of suspend (default: "")
67# command: echo mem > /sys/power/state
68
69# Display user processes
70# graph user processes and cpu usage in the timeline (default: false)
71proc: false
72
73# Display function calls
74# graph source functions in the timeline (default: false)
75dev: false
76
77# Multiple test runs
78# Run N tests D seconds apart, generates separate outputs with a summary (default: false)
79# multi: 3 5
80
81# Back to Back Suspend/Resume
82# Run two suspend/resumes back to back and display in the same timeline (default: false)
83x2: false
84
85# Back to Back Suspend Delay
86# Time delay between the two test runs in ms (default: 0 ms)
87x2delay: 0
88
89# Pre Suspend Delay
90# Include an N ms delay before (1st) suspend (default: 0 ms)
91predelay: 0
92
93# Post Resume Delay
94# Include an N ms delay after (last) resume (default: 0 ms)
95postdelay: 0
96
97# Minimum Device Length
98# graph only devices longer than min in the timeline (default: 0.001 ms)
99mindev: 0.001
100
101# ---- Debug Options ----
102
103# Callgraph
104# gather detailed ftrace callgraph data on all timeline events (default: false)
105callgraph: false
106
107# Callgraph phase filter
108# Only enable callgraphs for one phase, i.e. resume_noirq (default: all)
109cgphase: suspend
110
111# Callgraph x2 test filter
112# Only enable callgraphs test 0 or 1 when using -x2 (default: 1)
113cgtest: 0
114
115# Expand Callgraph
116# pre-expand the callgraph data in the html output (default: disabled)
117expandcg: false
118
119# Minimum Callgraph Length
120# provide callgraph data for blocks longer than min (default: 0.001 ms)
121mincg: 1
122
123# Timestamp Precision
124# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
125timeprec: 6
126
127# Device Filter
128# show only devices whose name/driver includes one of these strings
129# devicefilter: _cpu_up,_cpu_down,i915,usb
130
131# Add kprobe functions to the timeline
132# Add functions to the timeline from a text file (default: no-action)
133# fadd: file.txt
diff --git a/tools/power/pm-graph/config/freeze-callgraph.cfg b/tools/power/pm-graph/config/freeze-callgraph.cfg
new file mode 100644
index 000000000000..f692821c4828
--- /dev/null
+++ b/tools/power/pm-graph/config/freeze-callgraph.cfg
@@ -0,0 +1,94 @@
1#
2# Full Callgraph for S2 (Freeze) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/freeze-callgraph.cfg
10#
11# NOTE: the output of this test is very large (> 30MB)
12
13[Settings]
14
15# ---- General Options ----
16
17# Verbosity
18# print verbose messages (default: false)
19verbose: false
20
21# Suspend Mode
22# e.g. standby, mem, freeze, disk (default: mem)
23mode: freeze
24
25# Output Directory Format
26# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
27output-dir: freeze-{hostname}-{date}-{time}-cg
28
29# Automatic Wakeup
30# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
31rtcwake: 15
32
33# Add Logs
34# add the dmesg and ftrace log to the html output (default: false)
35addlogs: false
36
37# Suspend/Resume Gap
38# insert a small visible gap between suspend and resume on the timeline (default: false)
39srgap: false
40
41# ---- Advanced Options ----
42
43# Command to execute in lieu of freeze (default: "")
44# command: echo freeze > /sys/power/state
45
46# Display user processes
47# graph user processes and cpu usage in the timeline (default: false)
48proc: false
49
50# Display function calls
51# graph source functions in the timeline (default: false)
52dev: false
53
54# Back to Back Suspend/Resume
55# Run two suspend/resumes back to back (default: false)
56x2: false
57
58# Back to Back Suspend Delay
59# Time delay between the two test runs in ms (default: 0 ms)
60x2delay: 0
61
62# Pre Suspend Delay
63# Include an N ms delay before (1st) suspend (default: 0 ms)
64predelay: 0
65
66# Post Resume Delay
67# Include an N ms delay after (last) resume (default: 0 ms)
68postdelay: 0
69
70# Minimum Device Length
71# graph only devices longer than min in the timeline (default: 0.001 ms)
72mindev: 1
73
74# ---- Debug Options ----
75
76# Callgraph
77# gather detailed ftrace callgraph data on all timeline events (default: false)
78callgraph: true
79
80# Expand Callgraph
81# pre-expand the callgraph data in the html output (default: disabled)
82expandcg: false
83
84# Minimum Callgraph Length
85# provide callgraph data for blocks longer than min (default: 0.001 ms)
86mincg: 1
87
88# Timestamp Precision
89# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
90timeprec: 6
91
92# Device Filter
93# show only devs whose name/driver includes one of these strings
94# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/freeze-dev.cfg b/tools/power/pm-graph/config/freeze-dev.cfg
new file mode 100644
index 000000000000..c4ad5cea3cbf
--- /dev/null
+++ b/tools/power/pm-graph/config/freeze-dev.cfg
@@ -0,0 +1,93 @@
1#
2# Dev S2 (Freeze) test - includes src calls / kernel threads
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/freeze-dev.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: freeze
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: freeze-{hostname}-{date}-{time}-dev
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of freeze (default: "")
43# command: echo freeze > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: true
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/freeze.cfg b/tools/power/pm-graph/config/freeze.cfg
new file mode 100644
index 000000000000..0b70e0b74527
--- /dev/null
+++ b/tools/power/pm-graph/config/freeze.cfg
@@ -0,0 +1,93 @@
1#
2# Generic S2 (Freeze) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/freeze.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: freeze
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: freeze-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of freeze (default: "")
43# command: echo freeze > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 0.001
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/standby-callgraph.cfg b/tools/power/pm-graph/config/standby-callgraph.cfg
new file mode 100644
index 000000000000..f52a6b9d5c32
--- /dev/null
+++ b/tools/power/pm-graph/config/standby-callgraph.cfg
@@ -0,0 +1,94 @@
1#
2# Full Callgraph for S1 (Standby) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/standby-callgraph.cfg
10#
11# NOTE: the output of this test is very large (> 30MB)
12
13[Settings]
14
15# ---- General Options ----
16
17# Verbosity
18# print verbose messages (default: false)
19verbose: false
20
21# Suspend Mode
22# e.g. standby, mem, freeze, disk (default: mem)
23mode: standby
24
25# Output Directory Format
26# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
27output-dir: standby-{hostname}-{date}-{time}-cg
28
29# Automatic Wakeup
30# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
31rtcwake: 15
32
33# Add Logs
34# add the dmesg and ftrace log to the html output (default: false)
35addlogs: false
36
37# Suspend/Resume Gap
38# insert a small visible gap between suspend and resume on the timeline (default: false)
39srgap: false
40
41# ---- Advanced Options ----
42
43# Command to execute in lieu of standby (default: "")
44# command: echo standby > /sys/power/state
45
46# Display user processes
47# graph user processes and cpu usage in the timeline (default: false)
48proc: false
49
50# Display function calls
51# graph source functions in the timeline (default: false)
52dev: false
53
54# Back to Back Suspend/Resume
55# Run two suspend/resumes back to back (default: false)
56x2: false
57
58# Back to Back Suspend Delay
59# Time delay between the two test runs in ms (default: 0 ms)
60x2delay: 0
61
62# Pre Suspend Delay
63# Include an N ms delay before (1st) suspend (default: 0 ms)
64predelay: 0
65
66# Post Resume Delay
67# Include an N ms delay after (last) resume (default: 0 ms)
68postdelay: 0
69
70# Minimum Device Length
71# graph only devices longer than min in the timeline (default: 0.001 ms)
72mindev: 1
73
74# ---- Debug Options ----
75
76# Callgraph
77# gather detailed ftrace callgraph data on all timeline events (default: false)
78callgraph: true
79
80# Expand Callgraph
81# pre-expand the callgraph data in the html output (default: disabled)
82expandcg: false
83
84# Minimum Callgraph Length
85# provide callgraph data for blocks longer than min (default: 0.001 ms)
86mincg: 1
87
88# Timestamp Precision
89# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
90timeprec: 6
91
92# Device Filter
93# show only devs whose name/driver includes one of these strings
94# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/standby-dev.cfg b/tools/power/pm-graph/config/standby-dev.cfg
new file mode 100644
index 000000000000..a5498ece3def
--- /dev/null
+++ b/tools/power/pm-graph/config/standby-dev.cfg
@@ -0,0 +1,93 @@
1#
2# Dev S1 (Standby) test - includes src calls / kernel threads
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/standby-dev.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: standby
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: standby-{hostname}-{date}-{time}-dev
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of standby (default: "")
43# command: echo standby > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: true
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/standby.cfg b/tools/power/pm-graph/config/standby.cfg
new file mode 100644
index 000000000000..f0dd264dfeff
--- /dev/null
+++ b/tools/power/pm-graph/config/standby.cfg
@@ -0,0 +1,93 @@
1#
2# Generic S1 (Standby) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/standby.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: standby
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: standby-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of standby (default: "")
43# command: echo standby > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 0.001
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend-callgraph.cfg b/tools/power/pm-graph/config/suspend-callgraph.cfg
new file mode 100644
index 000000000000..11b8cbc12d34
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend-callgraph.cfg
@@ -0,0 +1,98 @@
1#
2# Full Callgraph for S3 (Suspend to Mem) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend.cfg
10#
11# NOTE: the output of this test is very large (> 30MB)
12
13[Settings]
14
15# ---- General Options ----
16
17# Verbosity
18# print verbose messages (default: false)
19verbose: false
20
21# Suspend Mode
22# e.g. standby, mem, freeze, disk (default: mem)
23mode: mem
24
25# Output Directory Format
26# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
27output-dir: suspend-{hostname}-{date}-{time}-cg
28
29# Automatic Wakeup
30# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
31rtcwake: 15
32
33# Add Logs
34# add the dmesg and ftrace log to the html output (default: false)
35addlogs: false
36
37# Suspend/Resume Gap
38# insert a small visible gap between suspend and resume on the timeline (default: false)
39srgap: false
40
41# ---- Advanced Options ----
42
43# Command to execute in lieu of suspend (default: "")
44# command: echo mem > /sys/power/state
45
46# Display user processes
47# graph user processes and cpu usage in the timeline (default: false)
48proc: false
49
50# Display function calls
51# graph source functions in the timeline (default: false)
52dev: false
53
54# Back to Back Suspend/Resume
55# Run two suspend/resumes back to back (default: false)
56x2: false
57
58# Back to Back Suspend Delay
59# Time delay between the two test runs in ms (default: 0 ms)
60x2delay: 0
61
62# Pre Suspend Delay
63# Include an N ms delay before (1st) suspend (default: 0 ms)
64predelay: 0
65
66# Post Resume Delay
67# Include an N ms delay after (last) resume (default: 0 ms)
68postdelay: 0
69
70# Minimum Device Length
71# graph only devices longer than min in the timeline (default: 0.001 ms)
72mindev: 0.001
73
74# ---- Debug Options ----
75
76# Callgraph
77# gather detailed ftrace callgraph data on all timeline events (default: false)
78callgraph: true
79
80# Max graph depth
81# limit the callgraph trace to this depth (default: 0 = all)
82maxdepth: 5
83
84# Expand Callgraph
85# pre-expand the callgraph data in the html output (default: disabled)
86expandcg: false
87
88# Minimum Callgraph Length
89# provide callgraph data for blocks longer than min (default: 0.001 ms)
90mincg: 1
91
92# Timestamp Precision
93# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
94timeprec: 6
95
96# Device Filter
97# show only devs whose name/driver includes one of these strings
98# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend-dev.cfg b/tools/power/pm-graph/config/suspend-dev.cfg
new file mode 100644
index 000000000000..56f1d21cc79b
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend-dev.cfg
@@ -0,0 +1,93 @@
1#
2# Dev S3 (Suspend to Mem) test - includes src calls / kernel threads
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend-dev.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}-dev
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of suspend (default: "")
43# command: echo mem > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: true
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend-x2-proc.cfg b/tools/power/pm-graph/config/suspend-x2-proc.cfg
new file mode 100644
index 000000000000..0ecca0ede138
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend-x2-proc.cfg
@@ -0,0 +1,93 @@
1#
2# Proc S3 (Suspend to Mem) x2 test - includes user processes
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend-proc.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}-x2-proc
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of suspend (default: "")
43# command: echo mem > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: true
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: true
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 1000
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 1000
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 1000
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend.cfg b/tools/power/pm-graph/config/suspend.cfg
new file mode 100644
index 000000000000..70d293231b06
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend.cfg
@@ -0,0 +1,93 @@
1#
2# Generic S3 (Suspend to Mem) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of suspend (default: "")
43# command: echo mem > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 0.001
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index fbe7bd3eae8e..18baaf6300c9 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -52,9 +52,32 @@ disable rtcwake and require a user keypress to resume.
52\fB-addlogs\fR 52\fB-addlogs\fR
53Add the dmesg and ftrace logs to the html output. They will be viewable by 53Add the dmesg and ftrace logs to the html output. They will be viewable by
54clicking buttons in the timeline. 54clicking buttons in the timeline.
55.TP
56\fB-result \fIfile\fR
57Export a results table to a text file for parsing.
58.TP
59\fB-sync\fR
60Sync the filesystems before starting the test. This reduces the size of
61the sys_sync call which happens in the suspend_prepare phase.
62.TP
63\fB-rs \fIenable/disable\fR
64During test, enable/disable runtime suspend for all devices. The test is delayed
65by 5 seconds to allow runtime suspend changes to occur. The settings are restored
66after the test is complete.
67.TP
68\fB-display \fIon/off\fR
69Turn the display on or off for the test using the xset command. This helps
70maintain the consistecy of test data for better comparison.
71.TP
72\fB-skiphtml\fR
73Run the test and capture the trace logs, but skip the timeline generation.
55 74
56.SS "advanced" 75.SS "advanced"
57.TP 76.TP
77\fB-gzip\fR
78Gzip the trace and dmesg logs to save space. The tool can also read in gzipped
79logs for processing.
80.TP
58\fB-cmd \fIstr\fR 81\fB-cmd \fIstr\fR
59Run the timeline over a custom suspend command, e.g. pm-suspend. By default 82Run the timeline over a custom suspend command, e.g. pm-suspend. By default
60the tool forces suspend via /sys/power/state so this allows testing over 83the tool forces suspend via /sys/power/state so this allows testing over
@@ -114,6 +137,18 @@ This reduces the html file size as there can be many tiny callgraphs
114which are barely visible in the timeline. 137which are barely visible in the timeline.
115The value is a float: e.g. 0.001 represents 1 us. 138The value is a float: e.g. 0.001 represents 1 us.
116.TP 139.TP
140\fB-cgfilter \fI"func1,func2,..."\fR
141Reduce callgraph output in the timeline by limiting it to a list of calls. The
142argument can be a single function name or a comma delimited list.
143(default: none)
144.TP
145\fB-cgskip \fIfile\fR
146Reduce callgraph timeline size by skipping over uninteresting functions
147in the trace, e.g. printk or console_unlock. The functions listed
148in this file will show up as empty leaves in the callgraph with only the start/end
149times displayed. cgskip.txt is used automatically if found in the path, so
150use "off" to disable completely (default: cgskip.txt)
151.TP
117\fB-cgphase \fIp\fR 152\fB-cgphase \fIp\fR
118Only show callgraph data for phase \fIp\fR (e.g. suspend_late). 153Only show callgraph data for phase \fIp\fR (e.g. suspend_late).
119.TP 154.TP
@@ -122,6 +157,9 @@ In an x2 run, only show callgraph data for test \fIn\fR (e.g. 0 or 1).
122.TP 157.TP
123\fB-timeprec \fIn\fR 158\fB-timeprec \fIn\fR
124Number of significant digits in timestamps (0:S, [3:ms], 6:us). 159Number of significant digits in timestamps (0:S, [3:ms], 6:us).
160.TP
161\fB-bufsize \fIN\fR
162Set trace buffer size to N kilo-bytes (default: all of free memory up to 3GB)
125 163
126.SH COMMANDS 164.SH COMMANDS
127.TP 165.TP
@@ -144,11 +182,8 @@ Print out the contents of the ACPI Firmware Performance Data Table.
144\fB-sysinfo\fR 182\fB-sysinfo\fR
145Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode. 183Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
146.TP 184.TP
147\fB-usbtopo\fR 185\fB-devinfo\fR
148Print out the current USB topology with power info. 186Print out the pm settings of all devices which support runtime suspend.
149.TP
150\fB-usbauto\fR
151Enable autosuspend for all connected USB devices.
152.TP 187.TP
153\fB-flist\fR 188\fB-flist\fR
154Print the list of ftrace functions currently being captured. Functions 189Print the list of ftrace functions currently being captured. Functions
@@ -198,7 +233,7 @@ Execute a mem suspend with a 15 second wakeup. Include the logs in the html.
198.PP 233.PP
199Execute a standby with a 15 second wakeup. Change the output folder name. 234Execute a standby with a 15 second wakeup. Change the output folder name.
200.IP 235.IP
201\f(CW$ sudo sleepgraph -m standby -rtcwake 15 -o "standby-{hostname}-{date}-{time}"\fR 236\f(CW$ sudo sleepgraph -m standby -rtcwake 15 -o "standby-{host}-{date}-{time}"\fR
202.PP 237.PP
203Execute a freeze with no wakeup (require keypress). Change output folder name. 238Execute a freeze with no wakeup (require keypress). Change output folder name.
204.IP 239.IP
diff --git a/tools/power/pm-graph/analyze_suspend.py b/tools/power/pm-graph/sleepgraph.py
index 1b60fe203741..266409fb27ae 100755
--- a/tools/power/pm-graph/analyze_suspend.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -19,7 +19,7 @@
19# Home Page 19# Home Page
20# https://01.org/suspendresume 20# https://01.org/suspendresume
21# Source repo 21# Source repo
22# https://github.com/01org/pm-graph 22# git@github.com:01org/pm-graph
23# 23#
24# Description: 24# Description:
25# This tool is designed to assist kernel and OS developers in optimizing 25# This tool is designed to assist kernel and OS developers in optimizing
@@ -57,6 +57,7 @@ import platform
57from datetime import datetime 57from datetime import datetime
58import struct 58import struct
59import ConfigParser 59import ConfigParser
60import gzip
60from threading import Thread 61from threading import Thread
61from subprocess import call, Popen, PIPE 62from subprocess import call, Popen, PIPE
62 63
@@ -68,8 +69,12 @@ from subprocess import call, Popen, PIPE
68# store system values and test parameters 69# store system values and test parameters
69class SystemValues: 70class SystemValues:
70 title = 'SleepGraph' 71 title = 'SleepGraph'
71 version = '4.7' 72 version = '5.0'
72 ansi = False 73 ansi = False
74 rs = 0
75 display = 0
76 gzip = False
77 sync = False
73 verbose = False 78 verbose = False
74 testlog = True 79 testlog = True
75 dmesglog = False 80 dmesglog = False
@@ -78,14 +83,19 @@ class SystemValues:
78 mincglen = 0.0 83 mincglen = 0.0
79 cgphase = '' 84 cgphase = ''
80 cgtest = -1 85 cgtest = -1
86 cgskip = ''
87 multitest = {'run': False, 'count': 0, 'delay': 0}
81 max_graph_depth = 0 88 max_graph_depth = 0
82 callloopmaxgap = 0.0001 89 callloopmaxgap = 0.0001
83 callloopmaxlen = 0.005 90 callloopmaxlen = 0.005
91 bufsize = 0
84 cpucount = 0 92 cpucount = 0
85 memtotal = 204800 93 memtotal = 204800
94 memfree = 204800
86 srgap = 0 95 srgap = 0
87 cgexp = False 96 cgexp = False
88 testdir = '' 97 testdir = ''
98 outdir = ''
89 tpath = '/sys/kernel/debug/tracing/' 99 tpath = '/sys/kernel/debug/tracing/'
90 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 100 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
91 epath = '/sys/kernel/debug/tracing/events/power/' 101 epath = '/sys/kernel/debug/tracing/events/power/'
@@ -109,22 +119,24 @@ class SystemValues:
109 dmesgfile = '' 119 dmesgfile = ''
110 ftracefile = '' 120 ftracefile = ''
111 htmlfile = 'output.html' 121 htmlfile = 'output.html'
112 embedded = False 122 result = ''
113 rtcwake = True 123 rtcwake = True
114 rtcwaketime = 15 124 rtcwaketime = 15
115 rtcpath = '' 125 rtcpath = ''
116 devicefilter = [] 126 devicefilter = []
127 cgfilter = []
117 stamp = 0 128 stamp = 0
118 execcount = 1 129 execcount = 1
119 x2delay = 0 130 x2delay = 0
131 skiphtml = False
120 usecallgraph = False 132 usecallgraph = False
121 usetraceevents = False 133 usetraceevents = False
122 usetraceeventsonly = False
123 usetracemarkers = True 134 usetracemarkers = True
124 usekprobes = True 135 usekprobes = True
125 usedevsrc = False 136 usedevsrc = False
126 useprocmon = False 137 useprocmon = False
127 notestrun = False 138 notestrun = False
139 cgdump = False
128 mixedphaseheight = True 140 mixedphaseheight = True
129 devprops = dict() 141 devprops = dict()
130 predelay = 0 142 predelay = 0
@@ -134,24 +146,33 @@ class SystemValues:
134 tracertypefmt = '# tracer: (?P<t>.*)' 146 tracertypefmt = '# tracer: (?P<t>.*)'
135 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 147 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
136 tracefuncs = { 148 tracefuncs = {
137 'sys_sync': dict(), 149 'sys_sync': {},
138 'pm_prepare_console': dict(), 150 '__pm_notifier_call_chain': {},
139 'pm_notifier_call_chain': dict(), 151 'pm_prepare_console': {},
140 'freeze_processes': dict(), 152 'pm_notifier_call_chain': {},
141 'freeze_kernel_threads': dict(), 153 'freeze_processes': {},
142 'pm_restrict_gfp_mask': dict(), 154 'freeze_kernel_threads': {},
143 'acpi_suspend_begin': dict(), 155 'pm_restrict_gfp_mask': {},
144 'suspend_console': dict(), 156 'acpi_suspend_begin': {},
145 'acpi_pm_prepare': dict(), 157 'acpi_hibernation_begin': {},
146 'syscore_suspend': dict(), 158 'acpi_hibernation_enter': {},
147 'arch_enable_nonboot_cpus_end': dict(), 159 'acpi_hibernation_leave': {},
148 'syscore_resume': dict(), 160 'acpi_pm_freeze': {},
149 'acpi_pm_finish': dict(), 161 'acpi_pm_thaw': {},
150 'resume_console': dict(), 162 'hibernate_preallocate_memory': {},
151 'acpi_pm_end': dict(), 163 'create_basic_memory_bitmaps': {},
152 'pm_restore_gfp_mask': dict(), 164 'swsusp_write': {},
153 'thaw_processes': dict(), 165 'suspend_console': {},
154 'pm_restore_console': dict(), 166 'acpi_pm_prepare': {},
167 'syscore_suspend': {},
168 'arch_enable_nonboot_cpus_end': {},
169 'syscore_resume': {},
170 'acpi_pm_finish': {},
171 'resume_console': {},
172 'acpi_pm_end': {},
173 'pm_restore_gfp_mask': {},
174 'thaw_processes': {},
175 'pm_restore_console': {},
155 'CPU_OFF': { 176 'CPU_OFF': {
156 'func':'_cpu_down', 177 'func':'_cpu_down',
157 'args_x86_64': {'cpu':'%di:s32'}, 178 'args_x86_64': {'cpu':'%di:s32'},
@@ -173,56 +194,54 @@ class SystemValues:
173 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 }, 194 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 },
174 'acpi_os_stall': {'ub': 1}, 195 'acpi_os_stall': {'ub': 1},
175 # ACPI 196 # ACPI
176 'acpi_resume_power_resources': dict(), 197 'acpi_resume_power_resources': {},
177 'acpi_ps_parse_aml': dict(), 198 'acpi_ps_parse_aml': {},
178 # filesystem 199 # filesystem
179 'ext4_sync_fs': dict(), 200 'ext4_sync_fs': {},
180 # 80211 201 # 80211
181 'iwlagn_mac_start': dict(), 202 'iwlagn_mac_start': {},
182 'iwlagn_alloc_bcast_station': dict(), 203 'iwlagn_alloc_bcast_station': {},
183 'iwl_trans_pcie_start_hw': dict(), 204 'iwl_trans_pcie_start_hw': {},
184 'iwl_trans_pcie_start_fw': dict(), 205 'iwl_trans_pcie_start_fw': {},
185 'iwl_run_init_ucode': dict(), 206 'iwl_run_init_ucode': {},
186 'iwl_load_ucode_wait_alive': dict(), 207 'iwl_load_ucode_wait_alive': {},
187 'iwl_alive_start': dict(), 208 'iwl_alive_start': {},
188 'iwlagn_mac_stop': dict(), 209 'iwlagn_mac_stop': {},
189 'iwlagn_mac_suspend': dict(), 210 'iwlagn_mac_suspend': {},
190 'iwlagn_mac_resume': dict(), 211 'iwlagn_mac_resume': {},
191 'iwlagn_mac_add_interface': dict(), 212 'iwlagn_mac_add_interface': {},
192 'iwlagn_mac_remove_interface': dict(), 213 'iwlagn_mac_remove_interface': {},
193 'iwlagn_mac_change_interface': dict(), 214 'iwlagn_mac_change_interface': {},
194 'iwlagn_mac_config': dict(), 215 'iwlagn_mac_config': {},
195 'iwlagn_configure_filter': dict(), 216 'iwlagn_configure_filter': {},
196 'iwlagn_mac_hw_scan': dict(), 217 'iwlagn_mac_hw_scan': {},
197 'iwlagn_bss_info_changed': dict(), 218 'iwlagn_bss_info_changed': {},
198 'iwlagn_mac_channel_switch': dict(), 219 'iwlagn_mac_channel_switch': {},
199 'iwlagn_mac_flush': dict(), 220 'iwlagn_mac_flush': {},
200 # ATA 221 # ATA
201 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} }, 222 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} },
202 # i915 223 # i915
203 'i915_gem_resume': dict(), 224 'i915_gem_resume': {},
204 'i915_restore_state': dict(), 225 'i915_restore_state': {},
205 'intel_opregion_setup': dict(), 226 'intel_opregion_setup': {},
206 'g4x_pre_enable_dp': dict(), 227 'g4x_pre_enable_dp': {},
207 'vlv_pre_enable_dp': dict(), 228 'vlv_pre_enable_dp': {},
208 'chv_pre_enable_dp': dict(), 229 'chv_pre_enable_dp': {},
209 'g4x_enable_dp': dict(), 230 'g4x_enable_dp': {},
210 'vlv_enable_dp': dict(), 231 'vlv_enable_dp': {},
211 'intel_hpd_init': dict(), 232 'intel_hpd_init': {},
212 'intel_opregion_register': dict(), 233 'intel_opregion_register': {},
213 'intel_dp_detect': dict(), 234 'intel_dp_detect': {},
214 'intel_hdmi_detect': dict(), 235 'intel_hdmi_detect': {},
215 'intel_opregion_init': dict(), 236 'intel_opregion_init': {},
216 'intel_fbdev_set_suspend': dict(), 237 'intel_fbdev_set_suspend': {},
217 } 238 }
239 cgblacklist = []
218 kprobes = dict() 240 kprobes = dict()
219 timeformat = '%.3f' 241 timeformat = '%.3f'
242 cmdline = '%s %s' % \
243 (os.path.basename(sys.argv[0]), string.join(sys.argv[1:], ' '))
220 def __init__(self): 244 def __init__(self):
221 # if this is a phoronix test run, set some default options
222 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
223 self.embedded = True
224 self.dmesglog = self.ftracelog = True
225 self.htmlfile = os.environ['LOG_FILE']
226 self.archargs = 'args_'+platform.machine() 245 self.archargs = 'args_'+platform.machine()
227 self.hostname = platform.node() 246 self.hostname = platform.node()
228 if(self.hostname == ''): 247 if(self.hostname == ''):
@@ -237,18 +256,36 @@ class SystemValues:
237 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 256 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
238 self.ansi = True 257 self.ansi = True
239 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S') 258 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S')
259 def vprint(self, msg):
260 self.logmsg += msg+'\n'
261 if(self.verbose):
262 print(msg)
240 def rootCheck(self, fatal=True): 263 def rootCheck(self, fatal=True):
241 if(os.access(self.powerfile, os.W_OK)): 264 if(os.access(self.powerfile, os.W_OK)):
242 return True 265 return True
243 if fatal: 266 if fatal:
244 doError('This command requires sysfs mount and root access') 267 msg = 'This command requires sysfs mount and root access'
268 print('ERROR: %s\n') % msg
269 self.outputResult({'error':msg})
270 sys.exit()
245 return False 271 return False
246 def rootUser(self, fatal=False): 272 def rootUser(self, fatal=False):
247 if 'USER' in os.environ and os.environ['USER'] == 'root': 273 if 'USER' in os.environ and os.environ['USER'] == 'root':
248 return True 274 return True
249 if fatal: 275 if fatal:
250 doError('This command must be run as root') 276 msg = 'This command must be run as root'
277 print('ERROR: %s\n') % msg
278 self.outputResult({'error':msg})
279 sys.exit()
251 return False 280 return False
281 def getExec(self, cmd):
282 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
283 '/usr/local/sbin', '/usr/local/bin']
284 for path in dirlist:
285 cmdfull = os.path.join(path, cmd)
286 if os.path.exists(cmdfull):
287 return cmdfull
288 return ''
252 def setPrecision(self, num): 289 def setPrecision(self, num):
253 if num < 0 or num > 6: 290 if num < 0 or num > 6:
254 return 291 return
@@ -258,15 +295,15 @@ class SystemValues:
258 n = datetime.now() 295 n = datetime.now()
259 args['date'] = n.strftime('%y%m%d') 296 args['date'] = n.strftime('%y%m%d')
260 args['time'] = n.strftime('%H%M%S') 297 args['time'] = n.strftime('%H%M%S')
261 args['hostname'] = self.hostname 298 args['hostname'] = args['host'] = self.hostname
262 return value.format(**args) 299 return value.format(**args)
263 def setOutputFile(self): 300 def setOutputFile(self):
264 if self.dmesgfile != '': 301 if self.dmesgfile != '':
265 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile) 302 m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile)
266 if(m): 303 if(m):
267 self.htmlfile = m.group('name')+'.html' 304 self.htmlfile = m.group('name')+'.html'
268 if self.ftracefile != '': 305 if self.ftracefile != '':
269 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile) 306 m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile)
270 if(m): 307 if(m):
271 self.htmlfile = m.group('name')+'.html' 308 self.htmlfile = m.group('name')+'.html'
272 def systemInfo(self, info): 309 def systemInfo(self, info):
@@ -283,16 +320,19 @@ class SystemValues:
283 c = info['processor-version'] 320 c = info['processor-version']
284 if 'bios-version' in info: 321 if 'bios-version' in info:
285 b = info['bios-version'] 322 b = info['bios-version']
286 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d' % \ 323 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d | memfr:%d' % \
287 (m, p, c, b, self.cpucount, self.memtotal) 324 (m, p, c, b, self.cpucount, self.memtotal, self.memfree)
288 def printSystemInfo(self): 325 def printSystemInfo(self, fatal=False):
289 self.rootCheck(True) 326 self.rootCheck(True)
290 out = dmidecode(self.mempath, True) 327 out = dmidecode(self.mempath, fatal)
328 if len(out) < 1:
329 return
291 fmt = '%-24s: %s' 330 fmt = '%-24s: %s'
292 for name in sorted(out): 331 for name in sorted(out):
293 print fmt % (name, out[name]) 332 print fmt % (name, out[name])
294 print fmt % ('cpucount', ('%d' % self.cpucount)) 333 print fmt % ('cpucount', ('%d' % self.cpucount))
295 print fmt % ('memtotal', ('%d kB' % self.memtotal)) 334 print fmt % ('memtotal', ('%d kB' % self.memtotal))
335 print fmt % ('memfree', ('%d kB' % self.memfree))
296 def cpuInfo(self): 336 def cpuInfo(self):
297 self.cpucount = 0 337 self.cpucount = 0
298 fp = open('/proc/cpuinfo', 'r') 338 fp = open('/proc/cpuinfo', 'r')
@@ -305,7 +345,9 @@ class SystemValues:
305 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 345 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line)
306 if m: 346 if m:
307 self.memtotal = int(m.group('sz')) 347 self.memtotal = int(m.group('sz'))
308 break 348 m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line)
349 if m:
350 self.memfree = int(m.group('sz'))
309 fp.close() 351 fp.close()
310 def initTestOutput(self, name): 352 def initTestOutput(self, name):
311 self.prefix = self.hostname 353 self.prefix = self.hostname
@@ -315,39 +357,34 @@ class SystemValues:
315 testtime = datetime.now().strftime(fmt) 357 testtime = datetime.now().strftime(fmt)
316 self.teststamp = \ 358 self.teststamp = \
317 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 359 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
318 if(self.embedded): 360 ext = ''
319 self.dmesgfile = \ 361 if self.gzip:
320 '/tmp/'+testtime+'_'+self.suspendmode+'_dmesg.txt' 362 ext = '.gz'
321 self.ftracefile = \
322 '/tmp/'+testtime+'_'+self.suspendmode+'_ftrace.txt'
323 return
324 self.dmesgfile = \ 363 self.dmesgfile = \
325 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt' 364 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext
326 self.ftracefile = \ 365 self.ftracefile = \
327 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt' 366 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext
328 self.htmlfile = \ 367 self.htmlfile = \
329 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' 368 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
330 if not os.path.isdir(self.testdir): 369 if not os.path.isdir(self.testdir):
331 os.mkdir(self.testdir) 370 os.mkdir(self.testdir)
371 def getValueList(self, value):
372 out = []
373 for i in value.split(','):
374 if i.strip():
375 out.append(i.strip())
376 return out
332 def setDeviceFilter(self, value): 377 def setDeviceFilter(self, value):
333 self.devicefilter = [] 378 self.devicefilter = self.getValueList(value)
334 if value: 379 def setCallgraphFilter(self, value):
335 value = value.split(',') 380 self.cgfilter = self.getValueList(value)
336 for i in value: 381 def setCallgraphBlacklist(self, file):
337 self.devicefilter.append(i.strip()) 382 self.cgblacklist = self.listFromFile(file)
338 def rtcWakeAlarmOn(self): 383 def rtcWakeAlarmOn(self):
339 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True) 384 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True)
340 outD = open(self.rtcpath+'/date', 'r').read().strip() 385 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip()
341 outT = open(self.rtcpath+'/time', 'r').read().strip() 386 if nowtime:
342 mD = re.match('^(?P<y>[0-9]*)-(?P<m>[0-9]*)-(?P<d>[0-9]*)', outD) 387 nowtime = int(nowtime)
343 mT = re.match('^(?P<h>[0-9]*):(?P<m>[0-9]*):(?P<s>[0-9]*)', outT)
344 if(mD and mT):
345 # get the current time from hardware
346 utcoffset = int((datetime.now() - datetime.utcnow()).total_seconds())
347 dt = datetime(\
348 int(mD.group('y')), int(mD.group('m')), int(mD.group('d')),
349 int(mT.group('h')), int(mT.group('m')), int(mT.group('s')))
350 nowtime = int(dt.strftime('%s')) + utcoffset
351 else: 388 else:
352 # if hardware time fails, use the software time 389 # if hardware time fails, use the software time
353 nowtime = int(datetime.now().strftime('%s')) 390 nowtime = int(datetime.now().strftime('%s'))
@@ -369,10 +406,10 @@ class SystemValues:
369 ktime = m.group('ktime') 406 ktime = m.group('ktime')
370 fp.close() 407 fp.close()
371 self.dmesgstart = float(ktime) 408 self.dmesgstart = float(ktime)
372 def getdmesg(self): 409 def getdmesg(self, fwdata=[]):
410 op = self.writeDatafileHeader(sysvals.dmesgfile, fwdata)
373 # store all new dmesg lines since initdmesg was called 411 # store all new dmesg lines since initdmesg was called
374 fp = Popen('dmesg', stdout=PIPE).stdout 412 fp = Popen('dmesg', stdout=PIPE).stdout
375 op = open(self.dmesgfile, 'a')
376 for line in fp: 413 for line in fp:
377 line = line.replace('\r\n', '') 414 line = line.replace('\r\n', '')
378 idx = line.find('[') 415 idx = line.find('[')
@@ -386,11 +423,17 @@ class SystemValues:
386 op.write(line) 423 op.write(line)
387 fp.close() 424 fp.close()
388 op.close() 425 op.close()
389 def addFtraceFilterFunctions(self, file): 426 def listFromFile(self, file):
427 list = []
390 fp = open(file) 428 fp = open(file)
391 list = fp.read().split('\n') 429 for i in fp.read().split('\n'):
430 i = i.strip()
431 if i and i[0] != '#':
432 list.append(i)
392 fp.close() 433 fp.close()
393 for i in list: 434 return list
435 def addFtraceFilterFunctions(self, file):
436 for i in self.listFromFile(file):
394 if len(i) < 2: 437 if len(i) < 2:
395 continue 438 continue
396 self.tracefuncs[i] = dict() 439 self.tracefuncs[i] = dict()
@@ -399,9 +442,7 @@ class SystemValues:
399 if not current: 442 if not current:
400 call('cat '+self.tpath+'available_filter_functions', shell=True) 443 call('cat '+self.tpath+'available_filter_functions', shell=True)
401 return 444 return
402 fp = open(self.tpath+'available_filter_functions') 445 master = self.listFromFile(self.tpath+'available_filter_functions')
403 master = fp.read().split('\n')
404 fp.close()
405 for i in self.tracefuncs: 446 for i in self.tracefuncs:
406 if 'func' in self.tracefuncs[i]: 447 if 'func' in self.tracefuncs[i]:
407 i = self.tracefuncs[i]['func'] 448 i = self.tracefuncs[i]['func']
@@ -410,9 +451,7 @@ class SystemValues:
410 else: 451 else:
411 print self.colorText(i) 452 print self.colorText(i)
412 def setFtraceFilterFunctions(self, list): 453 def setFtraceFilterFunctions(self, list):
413 fp = open(self.tpath+'available_filter_functions') 454 master = self.listFromFile(self.tpath+'available_filter_functions')
414 master = fp.read().split('\n')
415 fp.close()
416 flist = '' 455 flist = ''
417 for i in list: 456 for i in list:
418 if i not in master: 457 if i not in master:
@@ -501,6 +540,7 @@ class SystemValues:
501 rejects = [] 540 rejects = []
502 # sort kprobes: trace, ub-dev, custom, dev 541 # sort kprobes: trace, ub-dev, custom, dev
503 kpl = [[], [], [], []] 542 kpl = [[], [], [], []]
543 linesout = len(self.kprobes)
504 for name in sorted(self.kprobes): 544 for name in sorted(self.kprobes):
505 res = self.colorText('YES', 32) 545 res = self.colorText('YES', 32)
506 if not self.testKprobe(name, self.kprobes[name]): 546 if not self.testKprobe(name, self.kprobes[name]):
@@ -528,17 +568,10 @@ class SystemValues:
528 for kp in kplist: 568 for kp in kplist:
529 kprobeevents += self.kprobeText(kp, self.kprobes[kp]) 569 kprobeevents += self.kprobeText(kp, self.kprobes[kp])
530 self.fsetVal(kprobeevents, 'kprobe_events') 570 self.fsetVal(kprobeevents, 'kprobe_events')
531 # verify that the kprobes were set as ordered
532 check = self.fgetVal('kprobe_events')
533 linesout = len(kprobeevents.split('\n')) - 1
534 linesack = len(check.split('\n')) - 1
535 if output: 571 if output:
536 res = '%d/%d' % (linesack, linesout) 572 check = self.fgetVal('kprobe_events')
537 if linesack < linesout: 573 linesack = (len(check.split('\n')) - 1) / 2
538 res = self.colorText(res, 31) 574 print(' kprobe functions enabled: %d/%d' % (linesack, linesout))
539 else:
540 res = self.colorText(res, 32)
541 print(' working kprobe functions enabled: %s' % res)
542 self.fsetVal('1', 'events/kprobes/enable') 575 self.fsetVal('1', 'events/kprobes/enable')
543 def testKprobe(self, kname, kprobe): 576 def testKprobe(self, kname, kprobe):
544 self.fsetVal('0', 'events/kprobes/enable') 577 self.fsetVal('0', 'events/kprobes/enable')
@@ -555,8 +588,7 @@ class SystemValues:
555 if linesack < linesout: 588 if linesack < linesout:
556 return False 589 return False
557 return True 590 return True
558 def fsetVal(self, val, path, mode='w'): 591 def setVal(self, val, file, mode='w'):
559 file = self.tpath+path
560 if not os.path.exists(file): 592 if not os.path.exists(file):
561 return False 593 return False
562 try: 594 try:
@@ -567,8 +599,9 @@ class SystemValues:
567 except: 599 except:
568 return False 600 return False
569 return True 601 return True
570 def fgetVal(self, path): 602 def fsetVal(self, val, path, mode='w'):
571 file = self.tpath+path 603 return self.setVal(val, self.tpath+path, mode)
604 def getVal(self, file):
572 res = '' 605 res = ''
573 if not os.path.exists(file): 606 if not os.path.exists(file):
574 return res 607 return res
@@ -579,10 +612,13 @@ class SystemValues:
579 except: 612 except:
580 pass 613 pass
581 return res 614 return res
615 def fgetVal(self, path):
616 return self.getVal(self.tpath+path)
582 def cleanupFtrace(self): 617 def cleanupFtrace(self):
583 if(self.usecallgraph or self.usetraceevents): 618 if(self.usecallgraph or self.usetraceevents or self.usedevsrc):
584 self.fsetVal('0', 'events/kprobes/enable') 619 self.fsetVal('0', 'events/kprobes/enable')
585 self.fsetVal('', 'kprobe_events') 620 self.fsetVal('', 'kprobe_events')
621 self.fsetVal('1024', 'buffer_size_kb')
586 def setupAllKprobes(self): 622 def setupAllKprobes(self):
587 for name in self.tracefuncs: 623 for name in self.tracefuncs:
588 self.defaultKprobe(name, self.tracefuncs[name]) 624 self.defaultKprobe(name, self.tracefuncs[name])
@@ -599,7 +635,8 @@ class SystemValues:
599 if name == f: 635 if name == f:
600 return True 636 return True
601 return False 637 return False
602 def initFtrace(self, testing=False): 638 def initFtrace(self):
639 self.printSystemInfo(False)
603 print('INITIALIZING FTRACE...') 640 print('INITIALIZING FTRACE...')
604 # turn trace off 641 # turn trace off
605 self.fsetVal('0', 'tracing_on') 642 self.fsetVal('0', 'tracing_on')
@@ -607,17 +644,21 @@ class SystemValues:
607 # set the trace clock to global 644 # set the trace clock to global
608 self.fsetVal('global', 'trace_clock') 645 self.fsetVal('global', 'trace_clock')
609 self.fsetVal('nop', 'current_tracer') 646 self.fsetVal('nop', 'current_tracer')
610 # set trace buffer to a huge value 647 # set trace buffer to an appropriate value
611 if self.usecallgraph or self.usedevsrc: 648 cpus = max(1, self.cpucount)
612 tgtsize = min(self.memtotal / 2, 2*1024*1024) 649 if self.bufsize > 0:
613 maxbuf = '%d' % (tgtsize / max(1, self.cpucount)) 650 tgtsize = self.bufsize
614 if self.cpucount < 1 or not self.fsetVal(maxbuf, 'buffer_size_kb'): 651 elif self.usecallgraph or self.usedevsrc:
615 self.fsetVal('131072', 'buffer_size_kb') 652 tgtsize = min(self.memfree, 3*1024*1024)
616 else: 653 else:
617 self.fsetVal('16384', 'buffer_size_kb') 654 tgtsize = 65536
618 # go no further if this is just a status check 655 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'):
619 if testing: 656 # if the size failed to set, lower it and keep trying
620 return 657 tgtsize -= 65536
658 if tgtsize < 65536:
659 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus
660 break
661 print 'Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus)
621 # initialize the callgraph trace 662 # initialize the callgraph trace
622 if(self.usecallgraph): 663 if(self.usecallgraph):
623 # set trace type 664 # set trace type
@@ -635,7 +676,7 @@ class SystemValues:
635 self.fsetVal('graph-time', 'trace_options') 676 self.fsetVal('graph-time', 'trace_options')
636 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth') 677 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth')
637 cf = ['dpm_run_callback'] 678 cf = ['dpm_run_callback']
638 if(self.usetraceeventsonly): 679 if(self.usetraceevents):
639 cf += ['dpm_prepare', 'dpm_complete'] 680 cf += ['dpm_prepare', 'dpm_complete']
640 for fn in self.tracefuncs: 681 for fn in self.tracefuncs:
641 if 'func' in self.tracefuncs[fn]: 682 if 'func' in self.tracefuncs[fn]:
@@ -688,16 +729,65 @@ class SystemValues:
688 return str 729 return str
689 return '\x1B[%d;40m%s\x1B[m' % (color, str) 730 return '\x1B[%d;40m%s\x1B[m' % (color, str)
690 def writeDatafileHeader(self, filename, fwdata=[]): 731 def writeDatafileHeader(self, filename, fwdata=[]):
691 fp = open(filename, 'w') 732 fp = self.openlog(filename, 'w')
692 fp.write(self.teststamp+'\n') 733 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline))
693 fp.write(self.sysstamp+'\n')
694 if(self.suspendmode == 'mem' or self.suspendmode == 'command'): 734 if(self.suspendmode == 'mem' or self.suspendmode == 'command'):
695 for fw in fwdata: 735 for fw in fwdata:
696 if(fw): 736 if(fw):
697 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) 737 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
738 return fp
739 def sudouser(self, dir):
740 if os.path.exists(dir) and os.getuid() == 0 and \
741 'SUDO_USER' in os.environ:
742 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
743 call(cmd.format(os.environ['SUDO_USER'], dir), shell=True)
744 def outputResult(self, testdata, num=0):
745 if not self.result:
746 return
747 n = ''
748 if num > 0:
749 n = '%d' % num
750 fp = open(self.result, 'a')
751 if 'error' in testdata:
752 fp.write('result%s: fail\n' % n)
753 fp.write('error%s: %s\n' % (n, testdata['error']))
754 else:
755 fp.write('result%s: pass\n' % n)
756 for v in ['suspend', 'resume', 'boot', 'lastinit']:
757 if v in testdata:
758 fp.write('%s%s: %.3f\n' % (v, n, testdata[v]))
759 for v in ['fwsuspend', 'fwresume']:
760 if v in testdata:
761 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0))
762 if 'bugurl' in testdata:
763 fp.write('url%s: %s\n' % (n, testdata['bugurl']))
698 fp.close() 764 fp.close()
765 self.sudouser(self.result)
766 def configFile(self, file):
767 dir = os.path.dirname(os.path.realpath(__file__))
768 if os.path.exists(file):
769 return file
770 elif os.path.exists(dir+'/'+file):
771 return dir+'/'+file
772 elif os.path.exists(dir+'/config/'+file):
773 return dir+'/config/'+file
774 return ''
775 def openlog(self, filename, mode):
776 isgz = self.gzip
777 if mode == 'r':
778 try:
779 with gzip.open(filename, mode+'b') as fp:
780 test = fp.read(64)
781 isgz = True
782 except:
783 isgz = False
784 if isgz:
785 return gzip.open(filename, mode+'b')
786 return open(filename, mode)
699 787
700sysvals = SystemValues() 788sysvals = SystemValues()
789switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
790switchoff = ['disable', 'off', 'false', '0']
701suspendmodename = { 791suspendmodename = {
702 'freeze': 'Freeze (S0)', 792 'freeze': 'Freeze (S0)',
703 'standby': 'Standby (S1)', 793 'standby': 'Standby (S1)',
@@ -826,34 +916,65 @@ class Data:
826 for phase in self.phases: 916 for phase in self.phases:
827 self.devicegroups.append([phase]) 917 self.devicegroups.append([phase])
828 self.errorinfo = {'suspend':[],'resume':[]} 918 self.errorinfo = {'suspend':[],'resume':[]}
829 def extractErrorInfo(self, dmesg): 919 def extractErrorInfo(self):
830 error = '' 920 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
831 tm = 0.0 921 i = 0
832 for i in range(len(dmesg)): 922 list = []
833 if 'Call Trace:' in dmesg[i]: 923 # sl = start line, et = error time, el = error line
834 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) .*', dmesg[i]) 924 type = 'ERROR'
835 if not m: 925 sl = et = el = -1
836 continue 926 for line in lf:
837 tm = float(m.group('ktime')) 927 i += 1
838 if tm < self.start or tm > self.end: 928 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
839 continue 929 if not m:
840 for j in range(i-10, i+1):
841 error += dmesg[j]
842 continue 930 continue
843 if error: 931 t = float(m.group('ktime'))
844 m = re.match('[ \t]*\[ *[0-9\.]*\] \[\<[0-9a-fA-F]*\>\] .*', dmesg[i]) 932 if t < self.start or t > self.end:
845 if m: 933 continue
846 error += dmesg[i] 934 if t < self.tSuspended:
847 else: 935 dir = 'suspend'
848 if tm < self.tSuspended: 936 else:
849 dir = 'suspend' 937 dir = 'resume'
850 else: 938 msg = m.group('msg')
851 dir = 'resume' 939 if re.match('-*\[ *cut here *\]-*', msg):
852 error = error.replace('<', '&lt').replace('>', '&gt') 940 type = 'WARNING'
853 vprint('kernel error found in %s at %f' % (dir, tm)) 941 sl = i
854 self.errorinfo[dir].append((tm, error)) 942 elif re.match('genirq: .*', msg):
943 type = 'IRQ'
944 sl = i
945 elif re.match('BUG: .*', msg) or re.match('kernel BUG .*', msg):
946 type = 'BUG'
947 sl = i
948 elif re.match('-*\[ *end trace .*\]-*', msg) or \
949 re.match('R13: .*', msg):
950 if et >= 0 and sl >= 0:
951 list.append((type, dir, et, sl, i))
855 self.kerror = True 952 self.kerror = True
856 error = '' 953 sl = et = el = -1
954 type = 'ERROR'
955 elif 'Call Trace:' in msg:
956 if el >= 0 and et >= 0:
957 list.append((type, dir, et, el, el))
958 self.kerror = True
959 et, el = t, i
960 if sl < 0 or type == 'BUG':
961 slval = i
962 if sl >= 0:
963 slval = sl
964 list.append((type, dir, et, slval, i))
965 self.kerror = True
966 sl = et = el = -1
967 type = 'ERROR'
968 if el >= 0 and et >= 0:
969 list.append((type, dir, et, el, el))
970 self.kerror = True
971 for e in list:
972 type, dir, t, idx1, idx2 = e
973 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
974 self.errorinfo[dir].append((type, t, idx1, idx2))
975 if self.kerror:
976 sysvals.dmesglog = True
977 lf.close()
857 def setStart(self, time): 978 def setStart(self, time):
858 self.start = time 979 self.start = time
859 def setEnd(self, time): 980 def setEnd(self, time):
@@ -867,6 +988,14 @@ class Data:
867 time < d['end']): 988 time < d['end']):
868 return False 989 return False
869 return True 990 return True
991 def phaseCollision(self, phase, isbegin, line):
992 key = 'end'
993 if isbegin:
994 key = 'start'
995 if self.dmesg[phase][key] >= 0:
996 sysvals.vprint('IGNORE: %s' % line.strip())
997 return True
998 return False
870 def sourcePhase(self, start): 999 def sourcePhase(self, start):
871 for phase in self.phases: 1000 for phase in self.phases:
872 pend = self.dmesg[phase]['end'] 1001 pend = self.dmesg[phase]['end']
@@ -918,7 +1047,7 @@ class Data:
918 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata) 1047 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata)
919 # this should not happen 1048 # this should not happen
920 if not tgtdev: 1049 if not tgtdev:
921 vprint('[%f - %f] %s-%d %s %s %s' % \ 1050 sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \
922 (start, end, proc, pid, kprobename, cdata, rdata)) 1051 (start, end, proc, pid, kprobename, cdata, rdata))
923 return False 1052 return False
924 # place the call data inside the src element of the tgtdev 1053 # place the call data inside the src element of the tgtdev
@@ -1054,6 +1183,13 @@ class Data:
1054 if('src' in d): 1183 if('src' in d):
1055 for e in d['src']: 1184 for e in d['src']:
1056 e.time = self.trimTimeVal(e.time, t0, dT, left) 1185 e.time = self.trimTimeVal(e.time, t0, dT, left)
1186 for dir in ['suspend', 'resume']:
1187 list = []
1188 for e in self.errorinfo[dir]:
1189 type, tm, idx1, idx2 = e
1190 tm = self.trimTimeVal(tm, t0, dT, left)
1191 list.append((type, tm, idx1, idx2))
1192 self.errorinfo[dir] = list
1057 def normalizeTime(self, tZero): 1193 def normalizeTime(self, tZero):
1058 # trim out any standby or freeze clock time 1194 # trim out any standby or freeze clock time
1059 if(self.tSuspended != self.tResumed): 1195 if(self.tSuspended != self.tResumed):
@@ -1100,7 +1236,7 @@ class Data:
1100 if self.dmesg[p]['end'] > dev['start']: 1236 if self.dmesg[p]['end'] > dev['start']:
1101 dev['end'] = self.dmesg[p]['end'] 1237 dev['end'] = self.dmesg[p]['end']
1102 break 1238 break
1103 vprint('%s (%s): callback didnt return' % (devname, phase)) 1239 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase))
1104 def deviceFilter(self, devicefilter): 1240 def deviceFilter(self, devicefilter):
1105 for phase in self.phases: 1241 for phase in self.phases:
1106 list = self.dmesg[phase]['list'] 1242 list = self.dmesg[phase]['list']
@@ -1200,15 +1336,15 @@ class Data:
1200 devlist.append(child) 1336 devlist.append(child)
1201 return devlist 1337 return devlist
1202 def printDetails(self): 1338 def printDetails(self):
1203 vprint('Timeline Details:') 1339 sysvals.vprint('Timeline Details:')
1204 vprint(' test start: %f' % self.start) 1340 sysvals.vprint(' test start: %f' % self.start)
1205 vprint('kernel suspend start: %f' % self.tKernSus) 1341 sysvals.vprint('kernel suspend start: %f' % self.tKernSus)
1206 for phase in self.phases: 1342 for phase in self.phases:
1207 dc = len(self.dmesg[phase]['list']) 1343 dc = len(self.dmesg[phase]['list'])
1208 vprint(' %16s: %f - %f (%d devices)' % (phase, \ 1344 sysvals.vprint(' %16s: %f - %f (%d devices)' % (phase, \
1209 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc)) 1345 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc))
1210 vprint(' kernel resume end: %f' % self.tKernRes) 1346 sysvals.vprint(' kernel resume end: %f' % self.tKernRes)
1211 vprint(' test end: %f' % self.end) 1347 sysvals.vprint(' test end: %f' % self.end)
1212 def deviceChildrenAllPhases(self, devname): 1348 def deviceChildrenAllPhases(self, devname):
1213 devlist = [] 1349 devlist = []
1214 for phase in self.phases: 1350 for phase in self.phases:
@@ -1358,14 +1494,21 @@ class Data:
1358 tres.append(t) 1494 tres.append(t)
1359 # process the events for suspend and resume 1495 # process the events for suspend and resume
1360 if len(proclist) > 0: 1496 if len(proclist) > 0:
1361 vprint('Process Execution:') 1497 sysvals.vprint('Process Execution:')
1362 for ps in proclist: 1498 for ps in proclist:
1363 c = self.addProcessUsageEvent(ps, tsus) 1499 c = self.addProcessUsageEvent(ps, tsus)
1364 if c > 0: 1500 if c > 0:
1365 vprint('%25s (sus): %d' % (ps, c)) 1501 sysvals.vprint('%25s (sus): %d' % (ps, c))
1366 c = self.addProcessUsageEvent(ps, tres) 1502 c = self.addProcessUsageEvent(ps, tres)
1367 if c > 0: 1503 if c > 0:
1368 vprint('%25s (res): %d' % (ps, c)) 1504 sysvals.vprint('%25s (res): %d' % (ps, c))
1505 def debugPrint(self):
1506 for p in self.phases:
1507 list = self.dmesg[p]['list']
1508 for devname in list:
1509 dev = list[devname]
1510 if 'ftrace' in dev:
1511 dev['ftrace'].debugPrint(' [%s]' % devname)
1369 1512
1370# Class: DevFunction 1513# Class: DevFunction
1371# Description: 1514# Description:
@@ -1504,18 +1647,24 @@ class FTraceLine:
1504 # something else (possibly a trace marker) 1647 # something else (possibly a trace marker)
1505 else: 1648 else:
1506 self.name = m 1649 self.name = m
1650 def isCall(self):
1651 return self.fcall and not self.freturn
1652 def isReturn(self):
1653 return self.freturn and not self.fcall
1654 def isLeaf(self):
1655 return self.fcall and self.freturn
1507 def getDepth(self, str): 1656 def getDepth(self, str):
1508 return len(str)/2 1657 return len(str)/2
1509 def debugPrint(self, dev=''): 1658 def debugPrint(self, info=''):
1510 if(self.freturn and self.fcall): 1659 if self.isLeaf():
1511 print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \ 1660 print(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \
1512 self.depth, self.name, self.length*1000000)) 1661 self.depth, self.name, self.length*1000000, info))
1513 elif(self.freturn): 1662 elif self.freturn:
1514 print('%s -- %f (%02d): %s} (%.3f us)' % (dev, self.time, \ 1663 print(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \
1515 self.depth, self.name, self.length*1000000)) 1664 self.depth, self.name, self.length*1000000, info))
1516 else: 1665 else:
1517 print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \ 1666 print(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \
1518 self.depth, self.name, self.length*1000000)) 1667 self.depth, self.name, self.length*1000000, info))
1519 def startMarker(self): 1668 def startMarker(self):
1520 # Is this the starting line of a suspend? 1669 # Is this the starting line of a suspend?
1521 if not self.fevent: 1670 if not self.fevent:
@@ -1558,107 +1707,160 @@ class FTraceCallGraph:
1558 depth = 0 1707 depth = 0
1559 pid = 0 1708 pid = 0
1560 name = '' 1709 name = ''
1561 def __init__(self, pid): 1710 partial = False
1711 vfname = 'missing_function_name'
1712 ignore = False
1713 sv = 0
1714 def __init__(self, pid, sv):
1562 self.start = -1.0 1715 self.start = -1.0
1563 self.end = -1.0 1716 self.end = -1.0
1564 self.list = [] 1717 self.list = []
1565 self.depth = 0 1718 self.depth = 0
1566 self.pid = pid 1719 self.pid = pid
1567 def addLine(self, line, debug=False): 1720 self.sv = sv
1721 def addLine(self, line):
1568 # if this is already invalid, just leave 1722 # if this is already invalid, just leave
1569 if(self.invalid): 1723 if(self.invalid):
1570 return False 1724 if(line.depth == 0 and line.freturn):
1571 # invalidate on too much data or bad depth 1725 return 1
1572 if(len(self.list) >= 1000000 or self.depth < 0): 1726 return 0
1727 # invalidate on bad depth
1728 if(self.depth < 0):
1573 self.invalidate(line) 1729 self.invalidate(line)
1574 return False 1730 return 0
1731 # ignore data til we return to the current depth
1732 if self.ignore:
1733 if line.depth > self.depth:
1734 return 0
1735 else:
1736 self.list[-1].freturn = True
1737 self.list[-1].length = line.time - self.list[-1].time
1738 self.ignore = False
1739 # if this is a return at self.depth, no more work is needed
1740 if line.depth == self.depth and line.isReturn():
1741 if line.depth == 0:
1742 self.end = line.time
1743 return 1
1744 return 0
1575 # compare current depth with this lines pre-call depth 1745 # compare current depth with this lines pre-call depth
1576 prelinedep = line.depth 1746 prelinedep = line.depth
1577 if(line.freturn and not line.fcall): 1747 if line.isReturn():
1578 prelinedep += 1 1748 prelinedep += 1
1579 last = 0 1749 last = 0
1580 lasttime = line.time 1750 lasttime = line.time
1581 virtualfname = 'missing_function_name'
1582 if len(self.list) > 0: 1751 if len(self.list) > 0:
1583 last = self.list[-1] 1752 last = self.list[-1]
1584 lasttime = last.time 1753 lasttime = last.time
1754 if last.isLeaf():
1755 lasttime += last.length
1585 # handle low misalignments by inserting returns 1756 # handle low misalignments by inserting returns
1586 if prelinedep < self.depth: 1757 mismatch = prelinedep - self.depth
1587 if debug and last: 1758 warning = self.sv.verbose and abs(mismatch) > 1
1588 print '-------- task %d --------' % self.pid 1759 info = []
1589 last.debugPrint() 1760 if mismatch < 0:
1590 idx = 0 1761 idx = 0
1591 # add return calls to get the depth down 1762 # add return calls to get the depth down
1592 while prelinedep < self.depth: 1763 while prelinedep < self.depth:
1593 if debug:
1594 print 'MISALIGN LOW (add returns): C%d - eC%d' % (self.depth, prelinedep)
1595 self.depth -= 1 1764 self.depth -= 1
1596 if idx == 0 and last and last.fcall and not last.freturn: 1765 if idx == 0 and last and last.isCall():
1597 # special case, turn last call into a leaf 1766 # special case, turn last call into a leaf
1598 last.depth = self.depth 1767 last.depth = self.depth
1599 last.freturn = True 1768 last.freturn = True
1600 last.length = line.time - last.time 1769 last.length = line.time - last.time
1601 if debug: 1770 if warning:
1602 last.debugPrint() 1771 info.append(('[make leaf]', last))
1603 else: 1772 else:
1604 vline = FTraceLine(lasttime) 1773 vline = FTraceLine(lasttime)
1605 vline.depth = self.depth 1774 vline.depth = self.depth
1606 vline.name = virtualfname 1775 vline.name = self.vfname
1607 vline.freturn = True 1776 vline.freturn = True
1608 self.list.append(vline) 1777 self.list.append(vline)
1609 if debug: 1778 if warning:
1610 vline.debugPrint() 1779 if idx == 0:
1780 info.append(('', last))
1781 info.append(('[add return]', vline))
1611 idx += 1 1782 idx += 1
1612 if debug: 1783 if warning:
1613 line.debugPrint() 1784 info.append(('', line))
1614 print ''
1615 # handle high misalignments by inserting calls 1785 # handle high misalignments by inserting calls
1616 elif prelinedep > self.depth: 1786 elif mismatch > 0:
1617 if debug and last:
1618 print '-------- task %d --------' % self.pid
1619 last.debugPrint()
1620 idx = 0 1787 idx = 0
1788 if warning:
1789 info.append(('', last))
1621 # add calls to get the depth up 1790 # add calls to get the depth up
1622 while prelinedep > self.depth: 1791 while prelinedep > self.depth:
1623 if debug: 1792 if idx == 0 and line.isReturn():
1624 print 'MISALIGN HIGH (add calls): C%d - eC%d' % (self.depth, prelinedep)
1625 if idx == 0 and line.freturn and not line.fcall:
1626 # special case, turn this return into a leaf 1793 # special case, turn this return into a leaf
1627 line.fcall = True 1794 line.fcall = True
1628 prelinedep -= 1 1795 prelinedep -= 1
1796 if warning:
1797 info.append(('[make leaf]', line))
1629 else: 1798 else:
1630 vline = FTraceLine(lasttime) 1799 vline = FTraceLine(lasttime)
1631 vline.depth = self.depth 1800 vline.depth = self.depth
1632 vline.name = virtualfname 1801 vline.name = self.vfname
1633 vline.fcall = True 1802 vline.fcall = True
1634 if debug:
1635 vline.debugPrint()
1636 self.list.append(vline) 1803 self.list.append(vline)
1637 self.depth += 1 1804 self.depth += 1
1638 if not last: 1805 if not last:
1639 self.start = vline.time 1806 self.start = vline.time
1807 if warning:
1808 info.append(('[add call]', vline))
1640 idx += 1 1809 idx += 1
1641 if debug: 1810 if warning and ('[make leaf]', line) not in info:
1642 line.debugPrint() 1811 info.append(('', line))
1643 print '' 1812 if warning:
1813 print 'WARNING: ftrace data missing, corrections made:'
1814 for i in info:
1815 t, obj = i
1816 if obj:
1817 obj.debugPrint(t)
1644 # process the call and set the new depth 1818 # process the call and set the new depth
1645 if(line.fcall and not line.freturn): 1819 skipadd = False
1646 self.depth += 1 1820 md = self.sv.max_graph_depth
1647 elif(line.freturn and not line.fcall): 1821 if line.isCall():
1822 # ignore blacklisted/overdepth funcs
1823 if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist):
1824 self.ignore = True
1825 else:
1826 self.depth += 1
1827 elif line.isReturn():
1648 self.depth -= 1 1828 self.depth -= 1
1829 # remove blacklisted/overdepth/empty funcs that slipped through
1830 if (last and last.isCall() and last.depth == line.depth) or \
1831 (md and last and last.depth >= md) or \
1832 (line.name in self.sv.cgblacklist):
1833 while len(self.list) > 0 and self.list[-1].depth > line.depth:
1834 self.list.pop(-1)
1835 if len(self.list) == 0:
1836 self.invalid = True
1837 return 1
1838 self.list[-1].freturn = True
1839 self.list[-1].length = line.time - self.list[-1].time
1840 self.list[-1].name = line.name
1841 skipadd = True
1649 if len(self.list) < 1: 1842 if len(self.list) < 1:
1650 self.start = line.time 1843 self.start = line.time
1651 self.list.append(line) 1844 # check for a mismatch that returned all the way to callgraph end
1845 res = 1
1846 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn:
1847 line = self.list[-1]
1848 skipadd = True
1849 res = -1
1850 if not skipadd:
1851 self.list.append(line)
1652 if(line.depth == 0 and line.freturn): 1852 if(line.depth == 0 and line.freturn):
1653 if(self.start < 0): 1853 if(self.start < 0):
1654 self.start = line.time 1854 self.start = line.time
1655 self.end = line.time 1855 self.end = line.time
1656 if line.fcall: 1856 if line.fcall:
1657 self.end += line.length 1857 self.end += line.length
1658 if self.list[0].name == virtualfname: 1858 if self.list[0].name == self.vfname:
1659 self.invalid = True 1859 self.invalid = True
1660 return True 1860 if res == -1:
1661 return False 1861 self.partial = True
1862 return res
1863 return 0
1662 def invalidate(self, line): 1864 def invalidate(self, line):
1663 if(len(self.list) > 0): 1865 if(len(self.list) > 0):
1664 first = self.list[0] 1866 first = self.list[0]
@@ -1668,29 +1870,30 @@ class FTraceCallGraph:
1668 id = 'task %s' % (self.pid) 1870 id = 'task %s' % (self.pid)
1669 window = '(%f - %f)' % (self.start, line.time) 1871 window = '(%f - %f)' % (self.start, line.time)
1670 if(self.depth < 0): 1872 if(self.depth < 0):
1671 vprint('Too much data for '+id+\ 1873 print('Data misalignment for '+id+\
1672 ' (buffer overflow), ignoring this callback') 1874 ' (buffer overflow), ignoring this callback')
1673 else: 1875 else:
1674 vprint('Too much data for '+id+\ 1876 print('Too much data for '+id+\
1675 ' '+window+', ignoring this callback') 1877 ' '+window+', ignoring this callback')
1676 def slice(self, t0, tN): 1878 def slice(self, dev):
1677 minicg = FTraceCallGraph(0) 1879 minicg = FTraceCallGraph(dev['pid'], self.sv)
1678 count = -1 1880 minicg.name = self.name
1679 firstdepth = 0 1881 mydepth = -1
1882 good = False
1680 for l in self.list: 1883 for l in self.list:
1681 if(l.time < t0 or l.time > tN): 1884 if(l.time < dev['start'] or l.time > dev['end']):
1682 continue 1885 continue
1683 if(count < 0): 1886 if mydepth < 0:
1684 if(not l.fcall or l.name == 'dev_driver_string'): 1887 if l.name == 'mutex_lock' and l.freturn:
1685 continue 1888 mydepth = l.depth
1686 firstdepth = l.depth 1889 continue
1687 count = 0 1890 elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall:
1688 l.depth -= firstdepth 1891 good = True
1689 minicg.addLine(l)
1690 if((count == 0 and l.freturn and l.fcall) or
1691 (count > 0 and l.depth <= 0)):
1692 break 1892 break
1693 count += 1 1893 l.depth -= mydepth
1894 minicg.addLine(l)
1895 if not good or len(minicg.list) < 1:
1896 return 0
1694 return minicg 1897 return minicg
1695 def repair(self, enddepth): 1898 def repair(self, enddepth):
1696 # bring the depth back to 0 with additional returns 1899 # bring the depth back to 0 with additional returns
@@ -1701,11 +1904,11 @@ class FTraceCallGraph:
1701 t.depth = i 1904 t.depth = i
1702 t.freturn = True 1905 t.freturn = True
1703 fixed = self.addLine(t) 1906 fixed = self.addLine(t)
1704 if fixed: 1907 if fixed != 0:
1705 self.end = last.time 1908 self.end = last.time
1706 return True 1909 return True
1707 return False 1910 return False
1708 def postProcess(self, debug=False): 1911 def postProcess(self):
1709 if len(self.list) > 0: 1912 if len(self.list) > 0:
1710 self.name = self.list[0].name 1913 self.name = self.list[0].name
1711 stack = dict() 1914 stack = dict()
@@ -1714,20 +1917,23 @@ class FTraceCallGraph:
1714 for l in self.list: 1917 for l in self.list:
1715 # ftrace bug: reported duration is not reliable 1918 # ftrace bug: reported duration is not reliable
1716 # check each leaf and clip it at max possible length 1919 # check each leaf and clip it at max possible length
1717 if(last and last.freturn and last.fcall): 1920 if last and last.isLeaf():
1718 if last.length > l.time - last.time: 1921 if last.length > l.time - last.time:
1719 last.length = l.time - last.time 1922 last.length = l.time - last.time
1720 if(l.fcall and not l.freturn): 1923 if l.isCall():
1721 stack[l.depth] = l 1924 stack[l.depth] = l
1722 cnt += 1 1925 cnt += 1
1723 elif(l.freturn and not l.fcall): 1926 elif l.isReturn():
1724 if(l.depth not in stack): 1927 if(l.depth not in stack):
1725 if debug: 1928 if self.sv.verbose:
1726 print 'Post Process Error: Depth missing' 1929 print 'Post Process Error: Depth missing'
1727 l.debugPrint() 1930 l.debugPrint()
1728 return False 1931 return False
1729 # calculate call length from call/return lines 1932 # calculate call length from call/return lines
1730 stack[l.depth].length = l.time - stack[l.depth].time 1933 cl = stack[l.depth]
1934 cl.length = l.time - cl.time
1935 if cl.name == self.vfname:
1936 cl.name = l.name
1731 stack.pop(l.depth) 1937 stack.pop(l.depth)
1732 l.length = 0 1938 l.length = 0
1733 cnt -= 1 1939 cnt -= 1
@@ -1736,13 +1942,13 @@ class FTraceCallGraph:
1736 # trace caught the whole call tree 1942 # trace caught the whole call tree
1737 return True 1943 return True
1738 elif(cnt < 0): 1944 elif(cnt < 0):
1739 if debug: 1945 if self.sv.verbose:
1740 print 'Post Process Error: Depth is less than 0' 1946 print 'Post Process Error: Depth is less than 0'
1741 return False 1947 return False
1742 # trace ended before call tree finished 1948 # trace ended before call tree finished
1743 return self.repair(cnt) 1949 return self.repair(cnt)
1744 def deviceMatch(self, pid, data): 1950 def deviceMatch(self, pid, data):
1745 found = False 1951 found = ''
1746 # add the callgraph data to the device hierarchy 1952 # add the callgraph data to the device hierarchy
1747 borderphase = { 1953 borderphase = {
1748 'dpm_prepare': 'suspend_prepare', 1954 'dpm_prepare': 'suspend_prepare',
@@ -1756,8 +1962,10 @@ class FTraceCallGraph:
1756 if(pid == dev['pid'] and 1962 if(pid == dev['pid'] and
1757 self.start <= dev['start'] and 1963 self.start <= dev['start'] and
1758 self.end >= dev['end']): 1964 self.end >= dev['end']):
1759 dev['ftrace'] = self.slice(dev['start'], dev['end']) 1965 cg = self.slice(dev)
1760 found = True 1966 if cg:
1967 dev['ftrace'] = cg
1968 found = devname
1761 return found 1969 return found
1762 for p in data.phases: 1970 for p in data.phases:
1763 if(data.dmesg[p]['start'] <= self.start and 1971 if(data.dmesg[p]['start'] <= self.start and
@@ -1769,7 +1977,7 @@ class FTraceCallGraph:
1769 self.start <= dev['start'] and 1977 self.start <= dev['start'] and
1770 self.end >= dev['end']): 1978 self.end >= dev['end']):
1771 dev['ftrace'] = self 1979 dev['ftrace'] = self
1772 found = True 1980 found = devname
1773 break 1981 break
1774 break 1982 break
1775 return found 1983 return found
@@ -1793,18 +2001,20 @@ class FTraceCallGraph:
1793 if out: 2001 if out:
1794 phase, myname = out 2002 phase, myname = out
1795 data.dmesg[phase]['list'][myname]['ftrace'] = self 2003 data.dmesg[phase]['list'][myname]['ftrace'] = self
1796 def debugPrint(self): 2004 def debugPrint(self, info=''):
1797 print('[%f - %f] %s (%d)') % (self.start, self.end, self.name, self.pid) 2005 print('%s pid=%d [%f - %f] %.3f us') % \
2006 (self.name, self.pid, self.start, self.end,
2007 (self.end - self.start)*1000000)
1798 for l in self.list: 2008 for l in self.list:
1799 if(l.freturn and l.fcall): 2009 if l.isLeaf():
1800 print('%f (%02d): %s(); (%.3f us)' % (l.time, \ 2010 print('%f (%02d): %s(); (%.3f us)%s' % (l.time, \
1801 l.depth, l.name, l.length*1000000)) 2011 l.depth, l.name, l.length*1000000, info))
1802 elif(l.freturn): 2012 elif l.freturn:
1803 print('%f (%02d): %s} (%.3f us)' % (l.time, \ 2013 print('%f (%02d): %s} (%.3f us)%s' % (l.time, \
1804 l.depth, l.name, l.length*1000000)) 2014 l.depth, l.name, l.length*1000000, info))
1805 else: 2015 else:
1806 print('%f (%02d): %s() { (%.3f us)' % (l.time, \ 2016 print('%f (%02d): %s() { (%.3f us)%s' % (l.time, \
1807 l.depth, l.name, l.length*1000000)) 2017 l.depth, l.name, l.length*1000000, info))
1808 print(' ') 2018 print(' ')
1809 2019
1810class DevItem: 2020class DevItem:
@@ -1839,8 +2049,8 @@ class Timeline:
1839 self.rowH = rowheight 2049 self.rowH = rowheight
1840 self.scaleH = scaleheight 2050 self.scaleH = scaleheight
1841 self.html = '' 2051 self.html = ''
1842 def createHeader(self, sv): 2052 def createHeader(self, sv, stamp):
1843 if(not sv.stamp['time']): 2053 if(not stamp['time']):
1844 return 2054 return
1845 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 2055 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \
1846 % (sv.title, sv.version) 2056 % (sv.title, sv.version)
@@ -1851,12 +2061,12 @@ class Timeline:
1851 if sv.ftracelog: 2061 if sv.ftracelog:
1852 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>' 2062 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>'
1853 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 2063 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
1854 self.html += headline_stamp.format(sv.stamp['host'], sv.stamp['kernel'], 2064 self.html += headline_stamp.format(stamp['host'], stamp['kernel'],
1855 sv.stamp['mode'], sv.stamp['time']) 2065 stamp['mode'], stamp['time'])
1856 if 'man' in sv.stamp and 'plat' in sv.stamp and 'cpu' in sv.stamp: 2066 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \
2067 stamp['man'] and stamp['plat'] and stamp['cpu']:
1857 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n' 2068 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n'
1858 self.html += headline_sysinfo.format(sv.stamp['man'], 2069 self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu'])
1859 sv.stamp['plat'], sv.stamp['cpu'])
1860 2070
1861 # Function: getDeviceRows 2071 # Function: getDeviceRows
1862 # Description: 2072 # Description:
@@ -2067,12 +2277,16 @@ class Timeline:
2067class TestProps: 2277class TestProps:
2068 stamp = '' 2278 stamp = ''
2069 sysinfo = '' 2279 sysinfo = ''
2280 cmdline = ''
2281 kparams = ''
2070 S0i3 = False 2282 S0i3 = False
2071 fwdata = [] 2283 fwdata = []
2072 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ 2284 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
2073 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ 2285 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
2074 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' 2286 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
2075 sysinfofmt = '^# sysinfo .*' 2287 sysinfofmt = '^# sysinfo .*'
2288 cmdlinefmt = '^# command \| (?P<cmd>.*)'
2289 kparamsfmt = '^# kparams \| (?P<kp>.*)'
2076 ftrace_line_fmt_fg = \ 2290 ftrace_line_fmt_fg = \
2077 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2291 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
2078 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2292 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
@@ -2116,13 +2330,20 @@ class TestProps:
2116 sv.hostname = data.stamp['host'] 2330 sv.hostname = data.stamp['host']
2117 sv.suspendmode = data.stamp['mode'] 2331 sv.suspendmode = data.stamp['mode']
2118 if sv.suspendmode == 'command' and sv.ftracefile != '': 2332 if sv.suspendmode == 'command' and sv.ftracefile != '':
2119 modes = ['on', 'freeze', 'standby', 'mem'] 2333 modes = ['on', 'freeze', 'standby', 'mem', 'disk']
2120 out = Popen(['grep', 'suspend_enter', sv.ftracefile], 2334 out = Popen(['grep', 'machine_suspend', sv.ftracefile],
2121 stderr=PIPE, stdout=PIPE).stdout.read() 2335 stderr=PIPE, stdout=PIPE).stdout.read()
2122 m = re.match('.* suspend_enter\[(?P<mode>.*)\]', out) 2336 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', out)
2123 if m and m.group('mode') in ['1', '2', '3']: 2337 if m and m.group('mode') in ['1', '2', '3', '4']:
2124 sv.suspendmode = modes[int(m.group('mode'))] 2338 sv.suspendmode = modes[int(m.group('mode'))]
2125 data.stamp['mode'] = sv.suspendmode 2339 data.stamp['mode'] = sv.suspendmode
2340 m = re.match(self.cmdlinefmt, self.cmdline)
2341 if m:
2342 sv.cmdline = m.group('cmd')
2343 if self.kparams:
2344 m = re.match(self.kparamsfmt, self.kparams)
2345 if m:
2346 sv.kparams = m.group('kp')
2126 if not sv.stamp: 2347 if not sv.stamp:
2127 sv.stamp = data.stamp 2348 sv.stamp = data.stamp
2128 2349
@@ -2186,47 +2407,43 @@ class ProcessMonitor:
2186 2407
2187# ----------------- FUNCTIONS -------------------- 2408# ----------------- FUNCTIONS --------------------
2188 2409
2189# Function: vprint
2190# Description:
2191# verbose print (prints only with -verbose option)
2192# Arguments:
2193# msg: the debug/log message to print
2194def vprint(msg):
2195 sysvals.logmsg += msg+'\n'
2196 if(sysvals.verbose):
2197 print(msg)
2198
2199# Function: doesTraceLogHaveTraceEvents 2410# Function: doesTraceLogHaveTraceEvents
2200# Description: 2411# Description:
2201# Quickly determine if the ftrace log has some or all of the trace events 2412# Quickly determine if the ftrace log has all of the trace events,
2202# required for primary parsing. Set the usetraceevents and/or 2413# markers, and/or kprobes required for primary parsing.
2203# usetraceeventsonly flags in the global sysvals object
2204def doesTraceLogHaveTraceEvents(): 2414def doesTraceLogHaveTraceEvents():
2205 # check for kprobes 2415 kpcheck = ['_cal: (', '_cpu_down()']
2416 techeck = sysvals.traceevents[:]
2417 tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
2206 sysvals.usekprobes = False 2418 sysvals.usekprobes = False
2207 out = call('grep -q "_cal: (" '+sysvals.ftracefile, shell=True) 2419 fp = sysvals.openlog(sysvals.ftracefile, 'r')
2208 if(out == 0): 2420 for line in fp:
2209 sysvals.usekprobes = True 2421 # check for kprobes
2210 # check for callgraph data on trace event blocks 2422 if not sysvals.usekprobes:
2211 out = call('grep -q "_cpu_down()" '+sysvals.ftracefile, shell=True) 2423 for i in kpcheck:
2212 if(out == 0): 2424 if i in line:
2213 sysvals.usekprobes = True 2425 sysvals.usekprobes = True
2214 out = Popen(['head', '-1', sysvals.ftracefile], 2426 # check for all necessary trace events
2215 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 2427 check = techeck[:]
2216 # figure out what level of trace events are supported 2428 for i in techeck:
2217 sysvals.usetraceeventsonly = True 2429 if i in line:
2218 sysvals.usetraceevents = False 2430 check.remove(i)
2219 for e in sysvals.traceevents: 2431 techeck = check
2220 out = call('grep -q "'+e+': " '+sysvals.ftracefile, shell=True) 2432 # check for all necessary trace markers
2221 if(out != 0): 2433 check = tmcheck[:]
2222 sysvals.usetraceeventsonly = False 2434 for i in tmcheck:
2223 if(e == 'suspend_resume' and out == 0): 2435 if i in line:
2224 sysvals.usetraceevents = True 2436 check.remove(i)
2225 # determine is this log is properly formatted 2437 tmcheck = check
2226 for e in ['SUSPEND START', 'RESUME COMPLETE']: 2438 fp.close()
2227 out = call('grep -q "'+e+'" '+sysvals.ftracefile, shell=True) 2439 if len(techeck) == 0:
2228 if(out != 0): 2440 sysvals.usetraceevents = True
2229 sysvals.usetracemarkers = False 2441 else:
2442 sysvals.usetraceevents = False
2443 if len(tmcheck) == 0:
2444 sysvals.usetracemarkers = True
2445 else:
2446 sysvals.usetracemarkers = False
2230 2447
2231# Function: appendIncompleteTraceLog 2448# Function: appendIncompleteTraceLog
2232# Description: 2449# Description:
@@ -2247,9 +2464,10 @@ def appendIncompleteTraceLog(testruns):
2247 testrun.append(TestRun(data)) 2464 testrun.append(TestRun(data))
2248 2465
2249 # extract the callgraph and traceevent data 2466 # extract the callgraph and traceevent data
2250 vprint('Analyzing the ftrace data...') 2467 sysvals.vprint('Analyzing the ftrace data (%s)...' % \
2468 os.path.basename(sysvals.ftracefile))
2251 tp = TestProps() 2469 tp = TestProps()
2252 tf = open(sysvals.ftracefile, 'r') 2470 tf = sysvals.openlog(sysvals.ftracefile, 'r')
2253 data = 0 2471 data = 0
2254 for line in tf: 2472 for line in tf:
2255 # remove any latent carriage returns 2473 # remove any latent carriage returns
@@ -2261,6 +2479,9 @@ def appendIncompleteTraceLog(testruns):
2261 elif re.match(tp.sysinfofmt, line): 2479 elif re.match(tp.sysinfofmt, line):
2262 tp.sysinfo = line 2480 tp.sysinfo = line
2263 continue 2481 continue
2482 elif re.match(tp.cmdlinefmt, line):
2483 tp.cmdline = line
2484 continue
2264 # determine the trace data type (required for further parsing) 2485 # determine the trace data type (required for further parsing)
2265 m = re.match(sysvals.tracertypefmt, line) 2486 m = re.match(sysvals.tracertypefmt, line)
2266 if(m): 2487 if(m):
@@ -2393,11 +2614,14 @@ def appendIncompleteTraceLog(testruns):
2393 # create a callgraph object for the data 2614 # create a callgraph object for the data
2394 if(pid not in testrun[testidx].ftemp): 2615 if(pid not in testrun[testidx].ftemp):
2395 testrun[testidx].ftemp[pid] = [] 2616 testrun[testidx].ftemp[pid] = []
2396 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid)) 2617 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
2397 # when the call is finished, see which device matches it 2618 # when the call is finished, see which device matches it
2398 cg = testrun[testidx].ftemp[pid][-1] 2619 cg = testrun[testidx].ftemp[pid][-1]
2399 if(cg.addLine(t)): 2620 res = cg.addLine(t)
2400 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid)) 2621 if(res != 0):
2622 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
2623 if(res == -1):
2624 testrun[testidx].ftemp[pid][-1].addLine(t)
2401 tf.close() 2625 tf.close()
2402 2626
2403 for test in testrun: 2627 for test in testrun:
@@ -2410,11 +2634,11 @@ def appendIncompleteTraceLog(testruns):
2410 # add the callgraph data to the device hierarchy 2634 # add the callgraph data to the device hierarchy
2411 for pid in test.ftemp: 2635 for pid in test.ftemp:
2412 for cg in test.ftemp[pid]: 2636 for cg in test.ftemp[pid]:
2413 if len(cg.list) < 1 or cg.invalid: 2637 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
2414 continue 2638 continue
2415 if(not cg.postProcess()): 2639 if(not cg.postProcess()):
2416 id = 'task %s cpu %s' % (pid, m.group('cpu')) 2640 id = 'task %s cpu %s' % (pid, m.group('cpu'))
2417 vprint('Sanity check failed for '+\ 2641 sysvals.vprint('Sanity check failed for '+\
2418 id+', ignoring this callback') 2642 id+', ignoring this callback')
2419 continue 2643 continue
2420 callstart = cg.start 2644 callstart = cg.start
@@ -2431,8 +2655,6 @@ def appendIncompleteTraceLog(testruns):
2431 dev['ftrace'] = cg 2655 dev['ftrace'] = cg
2432 break 2656 break
2433 2657
2434 test.data.printDetails()
2435
2436# Function: parseTraceLog 2658# Function: parseTraceLog
2437# Description: 2659# Description:
2438# Analyze an ftrace log output file generated from this app during 2660# Analyze an ftrace log output file generated from this app during
@@ -2441,12 +2663,13 @@ def appendIncompleteTraceLog(testruns):
2441# The ftrace filename is taken from sysvals 2663# The ftrace filename is taken from sysvals
2442# Output: 2664# Output:
2443# An array of Data objects 2665# An array of Data objects
2444def parseTraceLog(): 2666def parseTraceLog(live=False):
2445 vprint('Analyzing the ftrace data...') 2667 sysvals.vprint('Analyzing the ftrace data (%s)...' % \
2668 os.path.basename(sysvals.ftracefile))
2446 if(os.path.exists(sysvals.ftracefile) == False): 2669 if(os.path.exists(sysvals.ftracefile) == False):
2447 doError('%s does not exist' % sysvals.ftracefile) 2670 doError('%s does not exist' % sysvals.ftracefile)
2448 2671 if not live:
2449 sysvals.setupAllKprobes() 2672 sysvals.setupAllKprobes()
2450 tracewatch = [] 2673 tracewatch = []
2451 if sysvals.usekprobes: 2674 if sysvals.usekprobes:
2452 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 2675 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
@@ -2458,7 +2681,7 @@ def parseTraceLog():
2458 testdata = [] 2681 testdata = []
2459 testrun = 0 2682 testrun = 0
2460 data = 0 2683 data = 0
2461 tf = open(sysvals.ftracefile, 'r') 2684 tf = sysvals.openlog(sysvals.ftracefile, 'r')
2462 phase = 'suspend_prepare' 2685 phase = 'suspend_prepare'
2463 for line in tf: 2686 for line in tf:
2464 # remove any latent carriage returns 2687 # remove any latent carriage returns
@@ -2470,6 +2693,9 @@ def parseTraceLog():
2470 elif re.match(tp.sysinfofmt, line): 2693 elif re.match(tp.sysinfofmt, line):
2471 tp.sysinfo = line 2694 tp.sysinfo = line
2472 continue 2695 continue
2696 elif re.match(tp.cmdlinefmt, line):
2697 tp.cmdline = line
2698 continue
2473 # firmware line: pull out any firmware data 2699 # firmware line: pull out any firmware data
2474 m = re.match(sysvals.firmwarefmt, line) 2700 m = re.match(sysvals.firmwarefmt, line)
2475 if(m): 2701 if(m):
@@ -2591,6 +2817,8 @@ def parseTraceLog():
2591 phase = 'suspend_prepare' 2817 phase = 'suspend_prepare'
2592 if(not isbegin): 2818 if(not isbegin):
2593 data.dmesg[phase]['end'] = t.time 2819 data.dmesg[phase]['end'] = t.time
2820 if data.dmesg[phase]['start'] < 0:
2821 data.dmesg[phase]['start'] = data.start
2594 continue 2822 continue
2595 # suspend start 2823 # suspend start
2596 elif(re.match('dpm_suspend\[.*', t.name)): 2824 elif(re.match('dpm_suspend\[.*', t.name)):
@@ -2604,6 +2832,8 @@ def parseTraceLog():
2604 continue 2832 continue
2605 # suspend_noirq start 2833 # suspend_noirq start
2606 elif(re.match('dpm_suspend_noirq\[.*', t.name)): 2834 elif(re.match('dpm_suspend_noirq\[.*', t.name)):
2835 if data.phaseCollision('suspend_noirq', isbegin, line):
2836 continue
2607 phase = 'suspend_noirq' 2837 phase = 'suspend_noirq'
2608 data.setPhase(phase, t.time, isbegin) 2838 data.setPhase(phase, t.time, isbegin)
2609 if(not isbegin): 2839 if(not isbegin):
@@ -2636,6 +2866,8 @@ def parseTraceLog():
2636 continue 2866 continue
2637 # resume_noirq start 2867 # resume_noirq start
2638 elif(re.match('dpm_resume_noirq\[.*', t.name)): 2868 elif(re.match('dpm_resume_noirq\[.*', t.name)):
2869 if data.phaseCollision('resume_noirq', isbegin, line):
2870 continue
2639 phase = 'resume_noirq' 2871 phase = 'resume_noirq'
2640 data.setPhase(phase, t.time, isbegin) 2872 data.setPhase(phase, t.time, isbegin)
2641 if(isbegin): 2873 if(isbegin):
@@ -2742,11 +2974,14 @@ def parseTraceLog():
2742 key = (m_proc, pid) 2974 key = (m_proc, pid)
2743 if(key not in testrun.ftemp): 2975 if(key not in testrun.ftemp):
2744 testrun.ftemp[key] = [] 2976 testrun.ftemp[key] = []
2745 testrun.ftemp[key].append(FTraceCallGraph(pid)) 2977 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
2746 # when the call is finished, see which device matches it 2978 # when the call is finished, see which device matches it
2747 cg = testrun.ftemp[key][-1] 2979 cg = testrun.ftemp[key][-1]
2748 if(cg.addLine(t)): 2980 res = cg.addLine(t)
2749 testrun.ftemp[key].append(FTraceCallGraph(pid)) 2981 if(res != 0):
2982 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
2983 if(res == -1):
2984 testrun.ftemp[key][-1].addLine(t)
2750 tf.close() 2985 tf.close()
2751 2986
2752 if sysvals.suspendmode == 'command': 2987 if sysvals.suspendmode == 'command':
@@ -2812,28 +3047,31 @@ def parseTraceLog():
2812 for key in test.ftemp: 3047 for key in test.ftemp:
2813 proc, pid = key 3048 proc, pid = key
2814 for cg in test.ftemp[key]: 3049 for cg in test.ftemp[key]:
2815 if len(cg.list) < 1 or cg.invalid: 3050 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
2816 continue 3051 continue
2817 if(not cg.postProcess()): 3052 if(not cg.postProcess()):
2818 id = 'task %s' % (pid) 3053 id = 'task %s' % (pid)
2819 vprint('Sanity check failed for '+\ 3054 sysvals.vprint('Sanity check failed for '+\
2820 id+', ignoring this callback') 3055 id+', ignoring this callback')
2821 continue 3056 continue
2822 # match cg data to devices 3057 # match cg data to devices
2823 if sysvals.suspendmode == 'command' or not cg.deviceMatch(pid, data): 3058 devname = ''
3059 if sysvals.suspendmode != 'command':
3060 devname = cg.deviceMatch(pid, data)
3061 if not devname:
2824 sortkey = '%f%f%d' % (cg.start, cg.end, pid) 3062 sortkey = '%f%f%d' % (cg.start, cg.end, pid)
2825 sortlist[sortkey] = cg 3063 sortlist[sortkey] = cg
3064 elif len(cg.list) > 1000000:
3065 print 'WARNING: the callgraph for %s is massive (%d lines)' %\
3066 (devname, len(cg.list))
2826 # create blocks for orphan cg data 3067 # create blocks for orphan cg data
2827 for sortkey in sorted(sortlist): 3068 for sortkey in sorted(sortlist):
2828 cg = sortlist[sortkey] 3069 cg = sortlist[sortkey]
2829 name = cg.name 3070 name = cg.name
2830 if sysvals.isCallgraphFunc(name): 3071 if sysvals.isCallgraphFunc(name):
2831 vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name)) 3072 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
2832 cg.newActionFromFunction(data) 3073 cg.newActionFromFunction(data)
2833
2834 if sysvals.suspendmode == 'command': 3074 if sysvals.suspendmode == 'command':
2835 for data in testdata:
2836 data.printDetails()
2837 return testdata 3075 return testdata
2838 3076
2839 # fill in any missing phases 3077 # fill in any missing phases
@@ -2841,7 +3079,7 @@ def parseTraceLog():
2841 lp = data.phases[0] 3079 lp = data.phases[0]
2842 for p in data.phases: 3080 for p in data.phases:
2843 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): 3081 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0):
2844 vprint('WARNING: phase "%s" is missing!' % p) 3082 sysvals.vprint('WARNING: phase "%s" is missing!' % p)
2845 if(data.dmesg[p]['start'] < 0): 3083 if(data.dmesg[p]['start'] < 0):
2846 data.dmesg[p]['start'] = data.dmesg[lp]['end'] 3084 data.dmesg[p]['start'] = data.dmesg[lp]['end']
2847 if(p == 'resume_machine'): 3085 if(p == 'resume_machine'):
@@ -2859,7 +3097,6 @@ def parseTraceLog():
2859 data.fixupInitcallsThatDidntReturn() 3097 data.fixupInitcallsThatDidntReturn()
2860 if sysvals.usedevsrc: 3098 if sysvals.usedevsrc:
2861 data.optimizeDevSrc() 3099 data.optimizeDevSrc()
2862 data.printDetails()
2863 3100
2864 # x2: merge any overlapping devices between test runs 3101 # x2: merge any overlapping devices between test runs
2865 if sysvals.usedevsrc and len(testdata) > 1: 3102 if sysvals.usedevsrc and len(testdata) > 1:
@@ -2878,19 +3115,18 @@ def parseTraceLog():
2878# The dmesg filename is taken from sysvals 3115# The dmesg filename is taken from sysvals
2879# Output: 3116# Output:
2880# An array of empty Data objects with only their dmesgtext attributes set 3117# An array of empty Data objects with only their dmesgtext attributes set
2881def loadKernelLog(justtext=False): 3118def loadKernelLog():
2882 vprint('Analyzing the dmesg data...') 3119 sysvals.vprint('Analyzing the dmesg data (%s)...' % \
3120 os.path.basename(sysvals.dmesgfile))
2883 if(os.path.exists(sysvals.dmesgfile) == False): 3121 if(os.path.exists(sysvals.dmesgfile) == False):
2884 doError('%s does not exist' % sysvals.dmesgfile) 3122 doError('%s does not exist' % sysvals.dmesgfile)
2885 3123
2886 if justtext:
2887 dmesgtext = []
2888 # there can be multiple test runs in a single file 3124 # there can be multiple test runs in a single file
2889 tp = TestProps() 3125 tp = TestProps()
2890 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown') 3126 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown')
2891 testruns = [] 3127 testruns = []
2892 data = 0 3128 data = 0
2893 lf = open(sysvals.dmesgfile, 'r') 3129 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
2894 for line in lf: 3130 for line in lf:
2895 line = line.replace('\r\n', '') 3131 line = line.replace('\r\n', '')
2896 idx = line.find('[') 3132 idx = line.find('[')
@@ -2903,6 +3139,9 @@ def loadKernelLog(justtext=False):
2903 elif re.match(tp.sysinfofmt, line): 3139 elif re.match(tp.sysinfofmt, line):
2904 tp.sysinfo = line 3140 tp.sysinfo = line
2905 continue 3141 continue
3142 elif re.match(tp.cmdlinefmt, line):
3143 tp.cmdline = line
3144 continue
2906 m = re.match(sysvals.firmwarefmt, line) 3145 m = re.match(sysvals.firmwarefmt, line)
2907 if(m): 3146 if(m):
2908 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) 3147 tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
@@ -2911,9 +3150,6 @@ def loadKernelLog(justtext=False):
2911 if(not m): 3150 if(not m):
2912 continue 3151 continue
2913 msg = m.group("msg") 3152 msg = m.group("msg")
2914 if justtext:
2915 dmesgtext.append(line)
2916 continue
2917 if(re.match('PM: Syncing filesystems.*', msg)): 3153 if(re.match('PM: Syncing filesystems.*', msg)):
2918 if(data): 3154 if(data):
2919 testruns.append(data) 3155 testruns.append(data)
@@ -2934,8 +3170,6 @@ def loadKernelLog(justtext=False):
2934 data.dmesgtext.append(line) 3170 data.dmesgtext.append(line)
2935 lf.close() 3171 lf.close()
2936 3172
2937 if justtext:
2938 return dmesgtext
2939 if data: 3173 if data:
2940 testruns.append(data) 3174 testruns.append(data)
2941 if len(testruns) < 1: 3175 if len(testruns) < 1:
@@ -2975,7 +3209,7 @@ def parseKernelLog(data):
2975 phase = 'suspend_runtime' 3209 phase = 'suspend_runtime'
2976 3210
2977 if(data.fwValid): 3211 if(data.fwValid):
2978 vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \ 3212 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \
2979 (data.fwSuspend, data.fwResume)) 3213 (data.fwSuspend, data.fwResume))
2980 3214
2981 # dmesg phase match table 3215 # dmesg phase match table
@@ -3201,7 +3435,6 @@ def parseKernelLog(data):
3201 for event in actions[name]: 3435 for event in actions[name]:
3202 data.newActionGlobal(name, event['begin'], event['end']) 3436 data.newActionGlobal(name, event['begin'], event['end'])
3203 3437
3204 data.printDetails()
3205 if(len(sysvals.devicefilter) > 0): 3438 if(len(sysvals.devicefilter) > 0):
3206 data.deviceFilter(sysvals.devicefilter) 3439 data.deviceFilter(sysvals.devicefilter)
3207 data.fixupInitcallsThatDidntReturn() 3440 data.fixupInitcallsThatDidntReturn()
@@ -3230,9 +3463,9 @@ def callgraphHTML(sv, hf, num, cg, title, color, devid):
3230 else: 3463 else:
3231 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>' 3464 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>'
3232 flen = fmt % (line.length*1000, line.time) 3465 flen = fmt % (line.length*1000, line.time)
3233 if(line.freturn and line.fcall): 3466 if line.isLeaf():
3234 hf.write(html_func_leaf.format(line.name, flen)) 3467 hf.write(html_func_leaf.format(line.name, flen))
3235 elif(line.freturn): 3468 elif line.freturn:
3236 hf.write(html_func_end) 3469 hf.write(html_func_end)
3237 else: 3470 else:
3238 hf.write(html_func_start.format(num, line.name, flen)) 3471 hf.write(html_func_start.format(num, line.name, flen))
@@ -3249,7 +3482,7 @@ def addCallgraphs(sv, hf, data):
3249 continue 3482 continue
3250 list = data.dmesg[p]['list'] 3483 list = data.dmesg[p]['list']
3251 for devname in data.sortedDevices(p): 3484 for devname in data.sortedDevices(p):
3252 if len(sv.devicefilter) > 0 and devname not in sv.devicefilter: 3485 if len(sv.cgfilter) > 0 and devname not in sv.cgfilter:
3253 continue 3486 continue
3254 dev = list[devname] 3487 dev = list[devname]
3255 color = 'white' 3488 color = 'white'
@@ -3270,7 +3503,6 @@ def addCallgraphs(sv, hf, data):
3270 for cg in dev['ftraces']: 3503 for cg in dev['ftraces']:
3271 num = callgraphHTML(sv, hf, num, cg, 3504 num = callgraphHTML(sv, hf, num, cg,
3272 name+' &rarr; '+cg.name, color, dev['id']) 3505 name+' &rarr; '+cg.name, color, dev['id'])
3273
3274 hf.write('\n\n </section>\n') 3506 hf.write('\n\n </section>\n')
3275 3507
3276# Function: createHTMLSummarySimple 3508# Function: createHTMLSummarySimple
@@ -3311,7 +3543,7 @@ def createHTMLSummarySimple(testruns, htmlfile, folder):
3311 sTimeAvg = rTimeAvg = 0.0 3543 sTimeAvg = rTimeAvg = 0.0
3312 mode = '' 3544 mode = ''
3313 num = 0 3545 num = 0
3314 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'])): 3546 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
3315 if mode != data['mode']: 3547 if mode != data['mode']:
3316 # test average line 3548 # test average line
3317 if(num > 0): 3549 if(num > 0):
@@ -3387,7 +3619,7 @@ def createHTML(testruns):
3387 data.normalizeTime(testruns[-1].tSuspended) 3619 data.normalizeTime(testruns[-1].tSuspended)
3388 3620
3389 # html function templates 3621 # html function templates
3390 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">ERROR&rarr;</div>\n' 3622 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}&rarr;</div>\n'
3391 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n' 3623 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n'
3392 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n' 3624 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n'
3393 html_timetotal = '<table class="time1">\n<tr>'\ 3625 html_timetotal = '<table class="time1">\n<tr>'\
@@ -3416,20 +3648,17 @@ def createHTML(testruns):
3416 scaleH = 40 3648 scaleH = 40
3417 3649
3418 # device timeline 3650 # device timeline
3419 vprint('Creating Device Timeline...')
3420
3421 devtl = Timeline(30, scaleH) 3651 devtl = Timeline(30, scaleH)
3422 3652
3423 # write the test title and general info header 3653 # write the test title and general info header
3424 devtl.createHeader(sysvals) 3654 devtl.createHeader(sysvals, testruns[0].stamp)
3425 3655
3426 # Generate the header for this timeline 3656 # Generate the header for this timeline
3427 for data in testruns: 3657 for data in testruns:
3428 tTotal = data.end - data.start 3658 tTotal = data.end - data.start
3429 sktime, rktime = data.getTimeValues() 3659 sktime, rktime = data.getTimeValues()
3430 if(tTotal == 0): 3660 if(tTotal == 0):
3431 print('ERROR: No timeline data') 3661 doError('No timeline data')
3432 sys.exit()
3433 if(data.tLow > 0): 3662 if(data.tLow > 0):
3434 low_time = '%.0f'%(data.tLow*1000) 3663 low_time = '%.0f'%(data.tLow*1000)
3435 if sysvals.suspendmode == 'command': 3664 if sysvals.suspendmode == 'command':
@@ -3567,9 +3796,10 @@ def createHTML(testruns):
3567 data.dmesg[b]['color'], '') 3796 data.dmesg[b]['color'], '')
3568 for e in data.errorinfo[dir]: 3797 for e in data.errorinfo[dir]:
3569 # draw red lines for any kernel errors found 3798 # draw red lines for any kernel errors found
3570 t, err = e 3799 type, t, idx1, idx2 = e
3800 id = '%d_%d' % (idx1, idx2)
3571 right = '%f' % (((mMax-t)*100.0)/mTotal) 3801 right = '%f' % (((mMax-t)*100.0)/mTotal)
3572 devtl.html += html_error.format(right, err) 3802 devtl.html += html_error.format(right, id, type)
3573 for b in sorted(phases[dir]): 3803 for b in sorted(phases[dir]):
3574 # draw the devices for this phase 3804 # draw the devices for this phase
3575 phaselist = data.dmesg[b]['list'] 3805 phaselist = data.dmesg[b]['list']
@@ -3663,14 +3893,7 @@ def createHTML(testruns):
3663 devtl.html += '</div>\n' 3893 devtl.html += '</div>\n'
3664 3894
3665 hf = open(sysvals.htmlfile, 'w') 3895 hf = open(sysvals.htmlfile, 'w')
3666 3896 addCSS(hf, sysvals, len(testruns), kerror)
3667 # no header or css if its embedded
3668 if(sysvals.embedded):
3669 hf.write('pass True tSus %.3f tRes %.3f tLow %.3f fwvalid %s tSus %.3f tRes %.3f\n' %
3670 (data.tSuspended-data.start, data.end-data.tSuspended, data.tLow, data.fwValid, \
3671 data.fwSuspend/1000000, data.fwResume/1000000))
3672 else:
3673 addCSS(hf, sysvals, len(testruns), kerror)
3674 3897
3675 # write the device timeline 3898 # write the device timeline
3676 hf.write(devtl.html) 3899 hf.write(devtl.html)
@@ -3701,7 +3924,7 @@ def createHTML(testruns):
3701 data = testruns[sysvals.cgtest] 3924 data = testruns[sysvals.cgtest]
3702 else: 3925 else:
3703 data = testruns[-1] 3926 data = testruns[-1]
3704 if(sysvals.usecallgraph and not sysvals.embedded): 3927 if sysvals.usecallgraph:
3705 addCallgraphs(sysvals, hf, data) 3928 addCallgraphs(sysvals, hf, data)
3706 3929
3707 # add the test log as a hidden div 3930 # add the test log as a hidden div
@@ -3710,7 +3933,7 @@ def createHTML(testruns):
3710 # add the dmesg log as a hidden div 3933 # add the dmesg log as a hidden div
3711 if sysvals.dmesglog and sysvals.dmesgfile: 3934 if sysvals.dmesglog and sysvals.dmesgfile:
3712 hf.write('<div id="dmesglog" style="display:none;">\n') 3935 hf.write('<div id="dmesglog" style="display:none;">\n')
3713 lf = open(sysvals.dmesgfile, 'r') 3936 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
3714 for line in lf: 3937 for line in lf:
3715 line = line.replace('<', '&lt').replace('>', '&gt') 3938 line = line.replace('<', '&lt').replace('>', '&gt')
3716 hf.write(line) 3939 hf.write(line)
@@ -3719,28 +3942,15 @@ def createHTML(testruns):
3719 # add the ftrace log as a hidden div 3942 # add the ftrace log as a hidden div
3720 if sysvals.ftracelog and sysvals.ftracefile: 3943 if sysvals.ftracelog and sysvals.ftracefile:
3721 hf.write('<div id="ftracelog" style="display:none;">\n') 3944 hf.write('<div id="ftracelog" style="display:none;">\n')
3722 lf = open(sysvals.ftracefile, 'r') 3945 lf = sysvals.openlog(sysvals.ftracefile, 'r')
3723 for line in lf: 3946 for line in lf:
3724 hf.write(line) 3947 hf.write(line)
3725 lf.close() 3948 lf.close()
3726 hf.write('</div>\n') 3949 hf.write('</div>\n')
3727 3950
3728 if(not sysvals.embedded): 3951 # write the footer and close
3729 # write the footer and close 3952 addScriptCode(hf, testruns)
3730 addScriptCode(hf, testruns) 3953 hf.write('</body>\n</html>\n')
3731 hf.write('</body>\n</html>\n')
3732 else:
3733 # embedded out will be loaded in a page, skip the js
3734 t0 = (testruns[0].start - testruns[-1].tSuspended) * 1000
3735 tMax = (testruns[-1].end - testruns[-1].tSuspended) * 1000
3736 # add js code in a div entry for later evaluation
3737 detail = 'var bounds = [%f,%f];\n' % (t0, tMax)
3738 detail += 'var devtable = [\n'
3739 for data in testruns:
3740 topo = data.deviceTopology()
3741 detail += '\t"%s",\n' % (topo)
3742 detail += '];\n'
3743 hf.write('<div id=customcode style=display:none>\n'+detail+'</div>\n')
3744 hf.close() 3954 hf.close()
3745 return True 3955 return True
3746 3956
@@ -4149,9 +4359,25 @@ def addScriptCode(hf, testruns):
4149 ' win.document.write(html+dt);\n'\ 4359 ' win.document.write(html+dt);\n'\
4150 ' }\n'\ 4360 ' }\n'\
4151 ' function errWindow() {\n'\ 4361 ' function errWindow() {\n'\
4152 ' var text = this.id;\n'\ 4362 ' var range = this.id.split("_");\n'\
4363 ' var idx1 = parseInt(range[0]);\n'\
4364 ' var idx2 = parseInt(range[1]);\n'\
4153 ' var win = window.open();\n'\ 4365 ' var win = window.open();\n'\
4154 ' win.document.write("<pre>"+text+"</pre>");\n'\ 4366 ' var log = document.getElementById("dmesglog");\n'\
4367 ' var title = "<title>dmesg log</title>";\n'\
4368 ' var text = log.innerHTML.split("\\n");\n'\
4369 ' var html = "";\n'\
4370 ' for(var i = 0; i < text.length; i++) {\n'\
4371 ' if(i == idx1) {\n'\
4372 ' html += "<e id=target>"+text[i]+"</e>\\n";\n'\
4373 ' } else if(i > idx1 && i <= idx2) {\n'\
4374 ' html += "<e>"+text[i]+"</e>\\n";\n'\
4375 ' } else {\n'\
4376 ' html += text[i]+"\\n";\n'\
4377 ' }\n'\
4378 ' }\n'\
4379 ' win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\
4380 ' win.location.hash = "#target";\n'\
4155 ' win.document.close();\n'\ 4381 ' win.document.close();\n'\
4156 ' }\n'\ 4382 ' }\n'\
4157 ' function logWindow(e) {\n'\ 4383 ' function logWindow(e) {\n'\
@@ -4219,6 +4445,30 @@ def addScriptCode(hf, testruns):
4219 '</script>\n' 4445 '</script>\n'
4220 hf.write(script_code); 4446 hf.write(script_code);
4221 4447
4448def setRuntimeSuspend(before=True):
4449 global sysvals
4450 sv = sysvals
4451 if sv.rs == 0:
4452 return
4453 if before:
4454 # runtime suspend disable or enable
4455 if sv.rs > 0:
4456 sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled'
4457 else:
4458 sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled'
4459 print('CONFIGURING RUNTIME SUSPEND...')
4460 sv.rslist = deviceInfo(sv.rstgt)
4461 for i in sv.rslist:
4462 sv.setVal(sv.rsval, i)
4463 print('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist)))
4464 print('waiting 5 seconds...')
4465 time.sleep(5)
4466 else:
4467 # runtime suspend re-enable or re-disable
4468 for i in sv.rslist:
4469 sv.setVal(sv.rstgt, i)
4470 print('runtime suspend settings restored on %d devices' % len(sv.rslist))
4471
4222# Function: executeSuspend 4472# Function: executeSuspend
4223# Description: 4473# Description:
4224# Execute system suspend through the sysfs interface, then copy the output 4474# Execute system suspend through the sysfs interface, then copy the output
@@ -4227,6 +4477,19 @@ def executeSuspend():
4227 pm = ProcessMonitor() 4477 pm = ProcessMonitor()
4228 tp = sysvals.tpath 4478 tp = sysvals.tpath
4229 fwdata = [] 4479 fwdata = []
4480 # run these commands to prepare the system for suspend
4481 if sysvals.display:
4482 if sysvals.display > 0:
4483 print('TURN DISPLAY ON')
4484 call('xset -d :0.0 dpms force suspend', shell=True)
4485 call('xset -d :0.0 dpms force on', shell=True)
4486 else:
4487 print('TURN DISPLAY OFF')
4488 call('xset -d :0.0 dpms force suspend', shell=True)
4489 time.sleep(1)
4490 if sysvals.sync:
4491 print('SYNCING FILESYSTEMS')
4492 call('sync', shell=True)
4230 # mark the start point in the kernel ring buffer just as we start 4493 # mark the start point in the kernel ring buffer just as we start
4231 sysvals.initdmesg() 4494 sysvals.initdmesg()
4232 # start ftrace 4495 # start ftrace
@@ -4298,47 +4561,22 @@ def executeSuspend():
4298 pm.stop() 4561 pm.stop()
4299 sysvals.fsetVal('0', 'tracing_on') 4562 sysvals.fsetVal('0', 'tracing_on')
4300 print('CAPTURING TRACE') 4563 print('CAPTURING TRACE')
4301 sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata) 4564 op = sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata)
4302 call('cat '+tp+'trace >> '+sysvals.ftracefile, shell=True) 4565 fp = open(tp+'trace', 'r')
4566 for line in fp:
4567 op.write(line)
4568 op.close()
4303 sysvals.fsetVal('', 'trace') 4569 sysvals.fsetVal('', 'trace')
4304 devProps() 4570 devProps()
4305 # grab a copy of the dmesg output 4571 # grab a copy of the dmesg output
4306 print('CAPTURING DMESG') 4572 print('CAPTURING DMESG')
4307 sysvals.writeDatafileHeader(sysvals.dmesgfile, fwdata) 4573 sysvals.getdmesg(fwdata)
4308 sysvals.getdmesg()
4309 4574
4310# Function: setUSBDevicesAuto 4575def readFile(file):
4311# Description: 4576 if os.path.islink(file):
4312# Set the autosuspend control parameter of all USB devices to auto 4577 return os.readlink(file).split('/')[-1]
4313# This can be dangerous, so use at your own risk, most devices are set 4578 else:
4314# to always-on since the kernel cant determine if the device can 4579 return sysvals.getVal(file).strip()
4315# properly autosuspend
4316def setUSBDevicesAuto():
4317 sysvals.rootCheck(True)
4318 for dirname, dirnames, filenames in os.walk('/sys/devices'):
4319 if(re.match('.*/usb[0-9]*.*', dirname) and
4320 'idVendor' in filenames and 'idProduct' in filenames):
4321 call('echo auto > %s/power/control' % dirname, shell=True)
4322 name = dirname.split('/')[-1]
4323 desc = Popen(['cat', '%s/product' % dirname],
4324 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '')
4325 ctrl = Popen(['cat', '%s/power/control' % dirname],
4326 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '')
4327 print('control is %s for %6s: %s' % (ctrl, name, desc))
4328
4329# Function: yesno
4330# Description:
4331# Print out an equivalent Y or N for a set of known parameter values
4332# Output:
4333# 'Y', 'N', or ' ' if the value is unknown
4334def yesno(val):
4335 yesvals = ['auto', 'enabled', 'active', '1']
4336 novals = ['on', 'disabled', 'suspended', 'forbidden', 'unsupported']
4337 if val in yesvals:
4338 return 'Y'
4339 elif val in novals:
4340 return 'N'
4341 return ' '
4342 4580
4343# Function: ms2nice 4581# Function: ms2nice
4344# Description: 4582# Description:
@@ -4346,69 +4584,81 @@ def yesno(val):
4346# Output: 4584# Output:
4347# The time string, e.g. "1901m16s" 4585# The time string, e.g. "1901m16s"
4348def ms2nice(val): 4586def ms2nice(val):
4349 ms = 0 4587 val = int(val)
4350 try: 4588 h = val / 3600000
4351 ms = int(val) 4589 m = (val / 60000) % 60
4352 except: 4590 s = (val / 1000) % 60
4353 return 0.0 4591 if h > 0:
4354 m = ms / 60000 4592 return '%d:%02d:%02d' % (h, m, s)
4355 s = (ms / 1000) - (m * 60) 4593 if m > 0:
4356 return '%3dm%2ds' % (m, s) 4594 return '%02d:%02d' % (m, s)
4595 return '%ds' % s
4357 4596
4358# Function: detectUSB 4597def yesno(val):
4598 list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D',
4599 'active':'A', 'suspended':'S', 'suspending':'S'}
4600 if val not in list:
4601 return ' '
4602 return list[val]
4603
4604# Function: deviceInfo
4359# Description: 4605# Description:
4360# Detect all the USB hosts and devices currently connected and add 4606# Detect all the USB hosts and devices currently connected and add
4361# a list of USB device names to sysvals for better timeline readability 4607# a list of USB device names to sysvals for better timeline readability
4362def detectUSB(): 4608def deviceInfo(output=''):
4363 field = {'idVendor':'', 'idProduct':'', 'product':'', 'speed':''} 4609 if not output:
4364 power = {'async':'', 'autosuspend':'', 'autosuspend_delay_ms':'', 4610 print('LEGEND')
4365 'control':'', 'persist':'', 'runtime_enabled':'', 4611 print('---------------------------------------------------------------------------------------------')
4366 'runtime_status':'', 'runtime_usage':'', 4612 print(' A = async/sync PM queue (A/S) C = runtime active children')
4367 'runtime_active_time':'', 4613 print(' R = runtime suspend enabled/disabled (E/D) rACTIVE = runtime active (min/sec)')
4368 'runtime_suspended_time':'', 4614 print(' S = runtime status active/suspended (A/S) rSUSPEND = runtime suspend (min/sec)')
4369 'active_duration':'', 4615 print(' U = runtime usage count')
4370 'connected_duration':''} 4616 print('---------------------------------------------------------------------------------------------')
4371 4617 print('DEVICE NAME A R S U C rACTIVE rSUSPEND')
4372 print('LEGEND') 4618 print('---------------------------------------------------------------------------------------------')
4373 print('---------------------------------------------------------------------------------------------') 4619
4374 print(' A = async/sync PM queue Y/N D = autosuspend delay (seconds)') 4620 res = []
4375 print(' S = autosuspend Y/N rACTIVE = runtime active (min/sec)') 4621 tgtval = 'runtime_status'
4376 print(' P = persist across suspend Y/N rSUSPEN = runtime suspend (min/sec)') 4622 lines = dict()
4377 print(' E = runtime suspend enabled/forbidden Y/N ACTIVE = active duration (min/sec)')
4378 print(' R = runtime status active/suspended Y/N CONNECT = connected duration (min/sec)')
4379 print(' U = runtime usage count')
4380 print('---------------------------------------------------------------------------------------------')
4381 print(' NAME ID DESCRIPTION SPEED A S P E R U D rACTIVE rSUSPEN ACTIVE CONNECT')
4382 print('---------------------------------------------------------------------------------------------')
4383
4384 for dirname, dirnames, filenames in os.walk('/sys/devices'): 4623 for dirname, dirnames, filenames in os.walk('/sys/devices'):
4385 if(re.match('.*/usb[0-9]*.*', dirname) and 4624 if(not re.match('.*/power', dirname) or
4386 'idVendor' in filenames and 'idProduct' in filenames): 4625 'control' not in filenames or
4387 for i in field: 4626 tgtval not in filenames):
4388 field[i] = Popen(['cat', '%s/%s' % (dirname, i)], 4627 continue
4389 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 4628 name = ''
4390 name = dirname.split('/')[-1] 4629 dirname = dirname[:-6]
4391 for i in power: 4630 device = dirname.split('/')[-1]
4392 power[i] = Popen(['cat', '%s/power/%s' % (dirname, i)], 4631 power = dict()
4393 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 4632 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval))
4394 if(re.match('usb[0-9]*', name)): 4633 # only list devices which support runtime suspend
4395 first = '%-8s' % name 4634 if power[tgtval] not in ['active', 'suspended', 'suspending']:
4396 else: 4635 continue
4397 first = '%8s' % name 4636 for i in ['product', 'driver', 'subsystem']:
4398 print('%s [%s:%s] %-20s %-4s %1s %1s %1s %1s %1s %1s %1s %s %s %s %s' % \ 4637 file = '%s/%s' % (dirname, i)
4399 (first, field['idVendor'], field['idProduct'], \ 4638 if os.path.exists(file):
4400 field['product'][0:20], field['speed'], \ 4639 name = readFile(file)
4401 yesno(power['async']), \ 4640 break
4402 yesno(power['control']), \ 4641 for i in ['async', 'control', 'runtime_status', 'runtime_usage',
4403 yesno(power['persist']), \ 4642 'runtime_active_kids', 'runtime_active_time',
4404 yesno(power['runtime_enabled']), \ 4643 'runtime_suspended_time']:
4405 yesno(power['runtime_status']), \ 4644 if i in filenames:
4406 power['runtime_usage'], \ 4645 power[i] = readFile('%s/power/%s' % (dirname, i))
4407 power['autosuspend'], \ 4646 if output:
4408 ms2nice(power['runtime_active_time']), \ 4647 if power['control'] == output:
4409 ms2nice(power['runtime_suspended_time']), \ 4648 res.append('%s/power/control' % dirname)
4410 ms2nice(power['active_duration']), \ 4649 continue
4411 ms2nice(power['connected_duration']))) 4650 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \
4651 (device[:26], name[:26],
4652 yesno(power['async']), \
4653 yesno(power['control']), \
4654 yesno(power['runtime_status']), \
4655 power['runtime_usage'], \
4656 power['runtime_active_kids'], \
4657 ms2nice(power['runtime_active_time']), \
4658 ms2nice(power['runtime_suspended_time']))
4659 for i in sorted(lines):
4660 print lines[i]
4661 return res
4412 4662
4413# Function: devProps 4663# Function: devProps
4414# Description: 4664# Description:
@@ -4444,7 +4694,7 @@ def devProps(data=0):
4444 msghead = 'Additional data added by AnalyzeSuspend' 4694 msghead = 'Additional data added by AnalyzeSuspend'
4445 alreadystamped = False 4695 alreadystamped = False
4446 tp = TestProps() 4696 tp = TestProps()
4447 tf = open(sysvals.ftracefile, 'r') 4697 tf = sysvals.openlog(sysvals.ftracefile, 'r')
4448 for line in tf: 4698 for line in tf:
4449 if msghead in line: 4699 if msghead in line:
4450 alreadystamped = True 4700 alreadystamped = True
@@ -4469,7 +4719,7 @@ def devProps(data=0):
4469 if not alreadystamped and sysvals.suspendmode == 'command': 4719 if not alreadystamped and sysvals.suspendmode == 'command':
4470 out = '#\n# '+msghead+'\n# Device Properties: ' 4720 out = '#\n# '+msghead+'\n# Device Properties: '
4471 out += 'testcommandstring,%s,0;' % (sysvals.testcommand) 4721 out += 'testcommandstring,%s,0;' % (sysvals.testcommand)
4472 with open(sysvals.ftracefile, 'a') as fp: 4722 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
4473 fp.write(out+'\n') 4723 fp.write(out+'\n')
4474 sysvals.devprops = props 4724 sysvals.devprops = props
4475 return 4725 return
@@ -4526,7 +4776,7 @@ def devProps(data=0):
4526 out = '#\n# '+msghead+'\n# Device Properties: ' 4776 out = '#\n# '+msghead+'\n# Device Properties: '
4527 for dev in sorted(props): 4777 for dev in sorted(props):
4528 out += props[dev].out(dev) 4778 out += props[dev].out(dev)
4529 with open(sysvals.ftracefile, 'a') as fp: 4779 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
4530 fp.write(out+'\n') 4780 fp.write(out+'\n')
4531 4781
4532 sysvals.devprops = props 4782 sysvals.devprops = props
@@ -4869,20 +5119,12 @@ def statusCheck(probecheck=False):
4869 # what data source are we using 5119 # what data source are we using
4870 res = 'DMESG' 5120 res = 'DMESG'
4871 if(ftgood): 5121 if(ftgood):
4872 sysvals.usetraceeventsonly = True 5122 sysvals.usetraceevents = True
4873 sysvals.usetraceevents = False
4874 for e in sysvals.traceevents: 5123 for e in sysvals.traceevents:
4875 check = False 5124 if not os.path.exists(sysvals.epath+e):
4876 if(os.path.exists(sysvals.epath+e)): 5125 sysvals.usetraceevents = False
4877 check = True 5126 if(sysvals.usetraceevents):
4878 if(not check):
4879 sysvals.usetraceeventsonly = False
4880 if(e == 'suspend_resume' and check):
4881 sysvals.usetraceevents = True
4882 if(sysvals.usetraceevents and sysvals.usetraceeventsonly):
4883 res = 'FTRACE (all trace events found)' 5127 res = 'FTRACE (all trace events found)'
4884 elif(sysvals.usetraceevents):
4885 res = 'DMESG and FTRACE (suspend_resume trace event found)'
4886 print(' timeline data source: %s' % res) 5128 print(' timeline data source: %s' % res)
4887 5129
4888 # check if rtcwake 5130 # check if rtcwake
@@ -4917,6 +5159,7 @@ def doError(msg, help=False):
4917 if(help == True): 5159 if(help == True):
4918 printHelp() 5160 printHelp()
4919 print('ERROR: %s\n') % msg 5161 print('ERROR: %s\n') % msg
5162 sysvals.outputResult({'error':msg})
4920 sys.exit() 5163 sys.exit()
4921 5164
4922# Function: getArgInt 5165# Function: getArgInt
@@ -4957,22 +5200,36 @@ def getArgFloat(name, args, min, max, main=True):
4957 doError(name+': value should be between %f and %f' % (min, max), True) 5200 doError(name+': value should be between %f and %f' % (min, max), True)
4958 return val 5201 return val
4959 5202
4960def processData(): 5203def processData(live=False):
4961 print('PROCESSING DATA') 5204 print('PROCESSING DATA')
4962 if(sysvals.usetraceeventsonly): 5205 if(sysvals.usetraceevents):
4963 testruns = parseTraceLog() 5206 testruns = parseTraceLog(live)
4964 if sysvals.dmesgfile: 5207 if sysvals.dmesgfile:
4965 dmesgtext = loadKernelLog(True)
4966 for data in testruns: 5208 for data in testruns:
4967 data.extractErrorInfo(dmesgtext) 5209 data.extractErrorInfo()
4968 else: 5210 else:
4969 testruns = loadKernelLog() 5211 testruns = loadKernelLog()
4970 for data in testruns: 5212 for data in testruns:
4971 parseKernelLog(data) 5213 parseKernelLog(data)
4972 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 5214 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
4973 appendIncompleteTraceLog(testruns) 5215 appendIncompleteTraceLog(testruns)
5216 sysvals.vprint('Command:\n %s' % sysvals.cmdline)
5217 for data in testruns:
5218 data.printDetails()
5219 if sysvals.cgdump:
5220 for data in testruns:
5221 data.debugPrint()
5222 sys.exit()
5223
5224 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
4974 createHTML(testruns) 5225 createHTML(testruns)
4975 return testruns 5226 print('DONE')
5227 data = testruns[0]
5228 stamp = data.stamp
5229 stamp['suspend'], stamp['resume'] = data.getTimeValues()
5230 if data.fwValid:
5231 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume
5232 return (testruns, stamp)
4976 5233
4977# Function: rerunTest 5234# Function: rerunTest
4978# Description: 5235# Description:
@@ -4980,37 +5237,36 @@ def processData():
4980def rerunTest(): 5237def rerunTest():
4981 if sysvals.ftracefile: 5238 if sysvals.ftracefile:
4982 doesTraceLogHaveTraceEvents() 5239 doesTraceLogHaveTraceEvents()
4983 if not sysvals.dmesgfile and not sysvals.usetraceeventsonly: 5240 if not sysvals.dmesgfile and not sysvals.usetraceevents:
4984 doError('recreating this html output requires a dmesg file') 5241 doError('recreating this html output requires a dmesg file')
4985 sysvals.setOutputFile() 5242 sysvals.setOutputFile()
4986 vprint('Output file: %s' % sysvals.htmlfile)
4987 if os.path.exists(sysvals.htmlfile): 5243 if os.path.exists(sysvals.htmlfile):
4988 if not os.path.isfile(sysvals.htmlfile): 5244 if not os.path.isfile(sysvals.htmlfile):
4989 doError('a directory already exists with this name: %s' % sysvals.htmlfile) 5245 doError('a directory already exists with this name: %s' % sysvals.htmlfile)
4990 elif not os.access(sysvals.htmlfile, os.W_OK): 5246 elif not os.access(sysvals.htmlfile, os.W_OK):
4991 doError('missing permission to write to %s' % sysvals.htmlfile) 5247 doError('missing permission to write to %s' % sysvals.htmlfile)
4992 return processData() 5248 testruns, stamp = processData(False)
5249 return stamp
4993 5250
4994# Function: runTest 5251# Function: runTest
4995# Description: 5252# Description:
4996# execute a suspend/resume, gather the logs, and generate the output 5253# execute a suspend/resume, gather the logs, and generate the output
4997def runTest(): 5254def runTest(n=0):
4998 # prepare for the test 5255 # prepare for the test
4999 sysvals.initFtrace() 5256 sysvals.initFtrace()
5000 sysvals.initTestOutput('suspend') 5257 sysvals.initTestOutput('suspend')
5001 vprint('Output files:\n\t%s\n\t%s\n\t%s' % \
5002 (sysvals.dmesgfile, sysvals.ftracefile, sysvals.htmlfile))
5003 5258
5004 # execute the test 5259 # execute the test
5005 executeSuspend() 5260 executeSuspend()
5006 sysvals.cleanupFtrace() 5261 sysvals.cleanupFtrace()
5007 processData() 5262 if sysvals.skiphtml:
5008 5263 sysvals.sudouser(sysvals.testdir)
5009 # if running as root, change output dir owner to sudo_user 5264 return
5010 if os.path.isdir(sysvals.testdir) and os.getuid() == 0 and \ 5265 testruns, stamp = processData(True)
5011 'SUDO_USER' in os.environ: 5266 for data in testruns:
5012 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 5267 del data
5013 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True) 5268 sysvals.sudouser(sysvals.testdir)
5269 sysvals.outputResult(stamp, n)
5014 5270
5015def find_in_html(html, strs, div=False): 5271def find_in_html(html, strs, div=False):
5016 for str in strs: 5272 for str in strs:
@@ -5072,10 +5328,12 @@ def runSummary(subdir, local=True):
5072# Function: checkArgBool 5328# Function: checkArgBool
5073# Description: 5329# Description:
5074# check if a boolean string value is true or false 5330# check if a boolean string value is true or false
5075def checkArgBool(value): 5331def checkArgBool(name, value):
5076 yes = ['1', 'true', 'yes', 'on'] 5332 if value in switchvalues:
5077 if value.lower() in yes: 5333 if value in switchoff:
5334 return False
5078 return True 5335 return True
5336 doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True)
5079 return False 5337 return False
5080 5338
5081# Function: configFromFile 5339# Function: configFromFile
@@ -5091,60 +5349,116 @@ def configFromFile(file):
5091 if 'Settings' in sections: 5349 if 'Settings' in sections:
5092 for opt in Config.options('Settings'): 5350 for opt in Config.options('Settings'):
5093 value = Config.get('Settings', opt).lower() 5351 value = Config.get('Settings', opt).lower()
5094 if(opt.lower() == 'verbose'): 5352 option = opt.lower()
5095 sysvals.verbose = checkArgBool(value) 5353 if(option == 'verbose'):
5096 elif(opt.lower() == 'addlogs'): 5354 sysvals.verbose = checkArgBool(option, value)
5097 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(value) 5355 elif(option == 'addlogs'):
5098 elif(opt.lower() == 'dev'): 5356 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value)
5099 sysvals.usedevsrc = checkArgBool(value) 5357 elif(option == 'dev'):
5100 elif(opt.lower() == 'proc'): 5358 sysvals.usedevsrc = checkArgBool(option, value)
5101 sysvals.useprocmon = checkArgBool(value) 5359 elif(option == 'proc'):
5102 elif(opt.lower() == 'x2'): 5360 sysvals.useprocmon = checkArgBool(option, value)
5103 if checkArgBool(value): 5361 elif(option == 'x2'):
5362 if checkArgBool(option, value):
5104 sysvals.execcount = 2 5363 sysvals.execcount = 2
5105 elif(opt.lower() == 'callgraph'): 5364 elif(option == 'callgraph'):
5106 sysvals.usecallgraph = checkArgBool(value) 5365 sysvals.usecallgraph = checkArgBool(option, value)
5107 elif(opt.lower() == 'override-timeline-functions'): 5366 elif(option == 'override-timeline-functions'):
5108 overridekprobes = checkArgBool(value) 5367 overridekprobes = checkArgBool(option, value)
5109 elif(opt.lower() == 'override-dev-timeline-functions'): 5368 elif(option == 'override-dev-timeline-functions'):
5110 overridedevkprobes = checkArgBool(value) 5369 overridedevkprobes = checkArgBool(option, value)
5111 elif(opt.lower() == 'devicefilter'): 5370 elif(option == 'skiphtml'):
5371 sysvals.skiphtml = checkArgBool(option, value)
5372 elif(option == 'sync'):
5373 sysvals.sync = checkArgBool(option, value)
5374 elif(option == 'rs' or option == 'runtimesuspend'):
5375 if value in switchvalues:
5376 if value in switchoff:
5377 sysvals.rs = -1
5378 else:
5379 sysvals.rs = 1
5380 else:
5381 doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True)
5382 elif(option == 'display'):
5383 if value in switchvalues:
5384 if value in switchoff:
5385 sysvals.display = -1
5386 else:
5387 sysvals.display = 1
5388 else:
5389 doError('invalid value --> (%s: %s), use "on/off"' % (option, value), True)
5390 elif(option == 'gzip'):
5391 sysvals.gzip = checkArgBool(option, value)
5392 elif(option == 'cgfilter'):
5393 sysvals.setCallgraphFilter(value)
5394 elif(option == 'cgskip'):
5395 if value in switchoff:
5396 sysvals.cgskip = ''
5397 else:
5398 sysvals.cgskip = sysvals.configFile(val)
5399 if(not sysvals.cgskip):
5400 doError('%s does not exist' % sysvals.cgskip)
5401 elif(option == 'cgtest'):
5402 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False)
5403 elif(option == 'cgphase'):
5404 d = Data(0)
5405 if value not in d.phases:
5406 doError('invalid phase --> (%s: %s), valid phases are %s'\
5407 % (option, value, d.phases), True)
5408 sysvals.cgphase = value
5409 elif(option == 'fadd'):
5410 file = sysvals.configFile(value)
5411 if(not file):
5412 doError('%s does not exist' % value)
5413 sysvals.addFtraceFilterFunctions(file)
5414 elif(option == 'result'):
5415 sysvals.result = value
5416 elif(option == 'multi'):
5417 nums = value.split()
5418 if len(nums) != 2:
5419 doError('multi requires 2 integers (exec_count and delay)', True)
5420 sysvals.multitest['run'] = True
5421 sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False)
5422 sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False)
5423 elif(option == 'devicefilter'):
5112 sysvals.setDeviceFilter(value) 5424 sysvals.setDeviceFilter(value)
5113 elif(opt.lower() == 'expandcg'): 5425 elif(option == 'expandcg'):
5114 sysvals.cgexp = checkArgBool(value) 5426 sysvals.cgexp = checkArgBool(option, value)
5115 elif(opt.lower() == 'srgap'): 5427 elif(option == 'srgap'):
5116 if checkArgBool(value): 5428 if checkArgBool(option, value):
5117 sysvals.srgap = 5 5429 sysvals.srgap = 5
5118 elif(opt.lower() == 'mode'): 5430 elif(option == 'mode'):
5119 sysvals.suspendmode = value 5431 sysvals.suspendmode = value
5120 elif(opt.lower() == 'command'): 5432 elif(option == 'command' or option == 'cmd'):
5121 sysvals.testcommand = value 5433 sysvals.testcommand = value
5122 elif(opt.lower() == 'x2delay'): 5434 elif(option == 'x2delay'):
5123 sysvals.x2delay = getArgInt('-x2delay', value, 0, 60000, False) 5435 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False)
5124 elif(opt.lower() == 'predelay'): 5436 elif(option == 'predelay'):
5125 sysvals.predelay = getArgInt('-predelay', value, 0, 60000, False) 5437 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False)
5126 elif(opt.lower() == 'postdelay'): 5438 elif(option == 'postdelay'):
5127 sysvals.postdelay = getArgInt('-postdelay', value, 0, 60000, False) 5439 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False)
5128 elif(opt.lower() == 'maxdepth'): 5440 elif(option == 'maxdepth'):
5129 sysvals.max_graph_depth = getArgInt('-maxdepth', value, 0, 1000, False) 5441 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False)
5130 elif(opt.lower() == 'rtcwake'): 5442 elif(option == 'rtcwake'):
5131 if value.lower() == 'off': 5443 if value in switchoff:
5132 sysvals.rtcwake = False 5444 sysvals.rtcwake = False
5133 else: 5445 else:
5134 sysvals.rtcwake = True 5446 sysvals.rtcwake = True
5135 sysvals.rtcwaketime = getArgInt('-rtcwake', value, 0, 3600, False) 5447 sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False)
5136 elif(opt.lower() == 'timeprec'): 5448 elif(option == 'timeprec'):
5137 sysvals.setPrecision(getArgInt('-timeprec', value, 0, 6, False)) 5449 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False))
5138 elif(opt.lower() == 'mindev'): 5450 elif(option == 'mindev'):
5139 sysvals.mindevlen = getArgFloat('-mindev', value, 0.0, 10000.0, False) 5451 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False)
5140 elif(opt.lower() == 'callloop-maxgap'): 5452 elif(option == 'callloop-maxgap'):
5141 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', value, 0.0, 1.0, False) 5453 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False)
5142 elif(opt.lower() == 'callloop-maxlen'): 5454 elif(option == 'callloop-maxlen'):
5143 sysvals.callloopmaxgap = getArgFloat('-callloop-maxlen', value, 0.0, 1.0, False) 5455 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False)
5144 elif(opt.lower() == 'mincg'): 5456 elif(option == 'mincg'):
5145 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False) 5457 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False)
5146 elif(opt.lower() == 'output-dir'): 5458 elif(option == 'bufsize'):
5147 sysvals.testdir = sysvals.setOutputFolder(value) 5459 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False)
5460 elif(option == 'output-dir'):
5461 sysvals.outdir = sysvals.setOutputFolder(value)
5148 5462
5149 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 5463 if sysvals.suspendmode == 'command' and not sysvals.testcommand:
5150 doError('No command supplied for mode "command"') 5464 doError('No command supplied for mode "command"')
@@ -5259,7 +5573,14 @@ def printHelp():
5259 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)') 5573 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)')
5260 print(' -addlogs Add the dmesg and ftrace logs to the html output') 5574 print(' -addlogs Add the dmesg and ftrace logs to the html output')
5261 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)') 5575 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)')
5576 print(' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)')
5577 print(' -result fn Export a results table to a text file for parsing.')
5578 print(' [testprep]')
5579 print(' -sync Sync the filesystems before starting the test')
5580 print(' -rs on/off Enable/disable runtime suspend for all devices, restore all after test')
5581 print(' -display on/off Turn the display on or off for the test')
5262 print(' [advanced]') 5582 print(' [advanced]')
5583 print(' -gzip Gzip the trace and dmesg logs to save space')
5263 print(' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"') 5584 print(' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"')
5264 print(' -proc Add usermode process info into the timeline (default: disabled)') 5585 print(' -proc Add usermode process info into the timeline (default: disabled)')
5265 print(' -dev Add kernel function calls and threads to the timeline (default: disabled)') 5586 print(' -dev Add kernel function calls and threads to the timeline (default: disabled)')
@@ -5280,14 +5601,16 @@ def printHelp():
5280 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)') 5601 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)')
5281 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)') 5602 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)')
5282 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)') 5603 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)')
5604 print(' -cgfilter S Filter the callgraph output in the timeline')
5605 print(' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)')
5606 print(' -bufsize N Set trace buffer size to N kilo-bytes (default: all of free memory)')
5283 print('') 5607 print('')
5284 print('Other commands:') 5608 print('Other commands:')
5285 print(' -modes List available suspend modes') 5609 print(' -modes List available suspend modes')
5286 print(' -status Test to see if the system is enabled to run this tool') 5610 print(' -status Test to see if the system is enabled to run this tool')
5287 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 5611 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
5288 print(' -sysinfo Print out system info extracted from BIOS') 5612 print(' -sysinfo Print out system info extracted from BIOS')
5289 print(' -usbtopo Print out the current USB topology with power info') 5613 print(' -devinfo Print out the pm settings of all devices which support runtime suspend')
5290 print(' -usbauto Enable autosuspend for all connected USB devices')
5291 print(' -flist Print the list of functions currently being captured in ftrace') 5614 print(' -flist Print the list of functions currently being captured in ftrace')
5292 print(' -flistall Print all functions capable of being captured in ftrace') 5615 print(' -flistall Print all functions capable of being captured in ftrace')
5293 print(' -summary directory Create a summary of all test in this dir') 5616 print(' -summary directory Create a summary of all test in this dir')
@@ -5301,9 +5624,9 @@ def printHelp():
5301# exec start (skipped if script is loaded as library) 5624# exec start (skipped if script is loaded as library)
5302if __name__ == '__main__': 5625if __name__ == '__main__':
5303 cmd = '' 5626 cmd = ''
5304 outdir = '' 5627 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status']
5305 multitest = {'run': False, 'count': 0, 'delay': 0} 5628 if '-f' in sys.argv:
5306 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status'] 5629 sysvals.cgskip = sysvals.configFile('cgskip.txt')
5307 # loop through the command line arguments 5630 # loop through the command line arguments
5308 args = iter(sys.argv[1:]) 5631 args = iter(sys.argv[1:])
5309 for arg in args: 5632 for arg in args:
@@ -5333,6 +5656,10 @@ if __name__ == '__main__':
5333 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000) 5656 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000)
5334 elif(arg == '-f'): 5657 elif(arg == '-f'):
5335 sysvals.usecallgraph = True 5658 sysvals.usecallgraph = True
5659 elif(arg == '-skiphtml'):
5660 sysvals.skiphtml = True
5661 elif(arg == '-cgdump'):
5662 sysvals.cgdump = True
5336 elif(arg == '-addlogs'): 5663 elif(arg == '-addlogs'):
5337 sysvals.dmesglog = sysvals.ftracelog = True 5664 sysvals.dmesglog = sysvals.ftracelog = True
5338 elif(arg == '-verbose'): 5665 elif(arg == '-verbose'):
@@ -5341,6 +5668,34 @@ if __name__ == '__main__':
5341 sysvals.useprocmon = True 5668 sysvals.useprocmon = True
5342 elif(arg == '-dev'): 5669 elif(arg == '-dev'):
5343 sysvals.usedevsrc = True 5670 sysvals.usedevsrc = True
5671 elif(arg == '-sync'):
5672 sysvals.sync = True
5673 elif(arg == '-gzip'):
5674 sysvals.gzip = True
5675 elif(arg == '-rs'):
5676 try:
5677 val = args.next()
5678 except:
5679 doError('-rs requires "enable" or "disable"', True)
5680 if val.lower() in switchvalues:
5681 if val.lower() in switchoff:
5682 sysvals.rs = -1
5683 else:
5684 sysvals.rs = 1
5685 else:
5686 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True)
5687 elif(arg == '-display'):
5688 try:
5689 val = args.next()
5690 except:
5691 doError('-display requires "on" or "off"', True)
5692 if val.lower() in switchvalues:
5693 if val.lower() in switchoff:
5694 sysvals.display = -1
5695 else:
5696 sysvals.display = 1
5697 else:
5698 doError('invalid option: %s, use "on/off"' % val, True)
5344 elif(arg == '-maxdepth'): 5699 elif(arg == '-maxdepth'):
5345 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 5700 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000)
5346 elif(arg == '-rtcwake'): 5701 elif(arg == '-rtcwake'):
@@ -5348,7 +5703,7 @@ if __name__ == '__main__':
5348 val = args.next() 5703 val = args.next()
5349 except: 5704 except:
5350 doError('No rtcwake time supplied', True) 5705 doError('No rtcwake time supplied', True)
5351 if val.lower() == 'off': 5706 if val.lower() in switchoff:
5352 sysvals.rtcwake = False 5707 sysvals.rtcwake = False
5353 else: 5708 else:
5354 sysvals.rtcwake = True 5709 sysvals.rtcwake = True
@@ -5359,6 +5714,8 @@ if __name__ == '__main__':
5359 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0) 5714 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0)
5360 elif(arg == '-mincg'): 5715 elif(arg == '-mincg'):
5361 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0) 5716 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0)
5717 elif(arg == '-bufsize'):
5718 sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8)
5362 elif(arg == '-cgtest'): 5719 elif(arg == '-cgtest'):
5363 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 5720 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1)
5364 elif(arg == '-cgphase'): 5721 elif(arg == '-cgphase'):
@@ -5368,8 +5725,26 @@ if __name__ == '__main__':
5368 doError('No phase name supplied', True) 5725 doError('No phase name supplied', True)
5369 d = Data(0) 5726 d = Data(0)
5370 if val not in d.phases: 5727 if val not in d.phases:
5371 doError('Invalid phase, valid phaess are %s' % d.phases, True) 5728 doError('invalid phase --> (%s: %s), valid phases are %s'\
5729 % (arg, val, d.phases), True)
5372 sysvals.cgphase = val 5730 sysvals.cgphase = val
5731 elif(arg == '-cgfilter'):
5732 try:
5733 val = args.next()
5734 except:
5735 doError('No callgraph functions supplied', True)
5736 sysvals.setCallgraphFilter(val)
5737 elif(arg == '-cgskip'):
5738 try:
5739 val = args.next()
5740 except:
5741 doError('No file supplied', True)
5742 if val.lower() in switchoff:
5743 sysvals.cgskip = ''
5744 else:
5745 sysvals.cgskip = sysvals.configFile(val)
5746 if(not sysvals.cgskip):
5747 doError('%s does not exist' % sysvals.cgskip)
5373 elif(arg == '-callloop-maxgap'): 5748 elif(arg == '-callloop-maxgap'):
5374 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0) 5749 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0)
5375 elif(arg == '-callloop-maxlen'): 5750 elif(arg == '-callloop-maxlen'):
@@ -5386,31 +5761,33 @@ if __name__ == '__main__':
5386 elif(arg == '-srgap'): 5761 elif(arg == '-srgap'):
5387 sysvals.srgap = 5 5762 sysvals.srgap = 5
5388 elif(arg == '-multi'): 5763 elif(arg == '-multi'):
5389 multitest['run'] = True 5764 sysvals.multitest['run'] = True
5390 multitest['count'] = getArgInt('-multi n (exec count)', args, 2, 1000000) 5765 sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000)
5391 multitest['delay'] = getArgInt('-multi d (delay between tests)', args, 0, 3600) 5766 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600)
5392 elif(arg == '-o'): 5767 elif(arg == '-o'):
5393 try: 5768 try:
5394 val = args.next() 5769 val = args.next()
5395 except: 5770 except:
5396 doError('No subdirectory name supplied', True) 5771 doError('No subdirectory name supplied', True)
5397 outdir = sysvals.setOutputFolder(val) 5772 sysvals.outdir = sysvals.setOutputFolder(val)
5398 elif(arg == '-config'): 5773 elif(arg == '-config'):
5399 try: 5774 try:
5400 val = args.next() 5775 val = args.next()
5401 except: 5776 except:
5402 doError('No text file supplied', True) 5777 doError('No text file supplied', True)
5403 if(os.path.exists(val) == False): 5778 file = sysvals.configFile(val)
5779 if(not file):
5404 doError('%s does not exist' % val) 5780 doError('%s does not exist' % val)
5405 configFromFile(val) 5781 configFromFile(file)
5406 elif(arg == '-fadd'): 5782 elif(arg == '-fadd'):
5407 try: 5783 try:
5408 val = args.next() 5784 val = args.next()
5409 except: 5785 except:
5410 doError('No text file supplied', True) 5786 doError('No text file supplied', True)
5411 if(os.path.exists(val) == False): 5787 file = sysvals.configFile(val)
5788 if(not file):
5412 doError('%s does not exist' % val) 5789 doError('%s does not exist' % val)
5413 sysvals.addFtraceFilterFunctions(val) 5790 sysvals.addFtraceFilterFunctions(file)
5414 elif(arg == '-dmesg'): 5791 elif(arg == '-dmesg'):
5415 try: 5792 try:
5416 val = args.next() 5793 val = args.next()
@@ -5435,7 +5812,7 @@ if __name__ == '__main__':
5435 except: 5812 except:
5436 doError('No directory supplied', True) 5813 doError('No directory supplied', True)
5437 cmd = 'summary' 5814 cmd = 'summary'
5438 outdir = val 5815 sysvals.outdir = val
5439 sysvals.notestrun = True 5816 sysvals.notestrun = True
5440 if(os.path.isdir(val) == False): 5817 if(os.path.isdir(val) == False):
5441 doError('%s is not accesible' % val) 5818 doError('%s is not accesible' % val)
@@ -5445,6 +5822,12 @@ if __name__ == '__main__':
5445 except: 5822 except:
5446 doError('No devnames supplied', True) 5823 doError('No devnames supplied', True)
5447 sysvals.setDeviceFilter(val) 5824 sysvals.setDeviceFilter(val)
5825 elif(arg == '-result'):
5826 try:
5827 val = args.next()
5828 except:
5829 doError('No result file supplied', True)
5830 sysvals.result = val
5448 else: 5831 else:
5449 doError('Invalid argument: '+arg, True) 5832 doError('Invalid argument: '+arg, True)
5450 5833
@@ -5454,42 +5837,48 @@ if __name__ == '__main__':
5454 if(sysvals.usecallgraph and sysvals.useprocmon): 5837 if(sysvals.usecallgraph and sysvals.useprocmon):
5455 doError('-proc is not compatible with -f') 5838 doError('-proc is not compatible with -f')
5456 5839
5840 if sysvals.usecallgraph and sysvals.cgskip:
5841 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip)
5842 sysvals.setCallgraphBlacklist(sysvals.cgskip)
5843
5457 # callgraph size cannot exceed device size 5844 # callgraph size cannot exceed device size
5458 if sysvals.mincglen < sysvals.mindevlen: 5845 if sysvals.mincglen < sysvals.mindevlen:
5459 sysvals.mincglen = sysvals.mindevlen 5846 sysvals.mincglen = sysvals.mindevlen
5460 5847
5461 # just run a utility command and exit 5848 # remove existing buffers before calculating memory
5849 if(sysvals.usecallgraph or sysvals.usedevsrc):
5850 sysvals.fsetVal('16', 'buffer_size_kb')
5462 sysvals.cpuInfo() 5851 sysvals.cpuInfo()
5852
5853 # just run a utility command and exit
5463 if(cmd != ''): 5854 if(cmd != ''):
5464 if(cmd == 'status'): 5855 if(cmd == 'status'):
5465 statusCheck(True) 5856 statusCheck(True)
5466 elif(cmd == 'fpdt'): 5857 elif(cmd == 'fpdt'):
5467 getFPDT(True) 5858 getFPDT(True)
5468 elif(cmd == 'sysinfo'): 5859 elif(cmd == 'sysinfo'):
5469 sysvals.printSystemInfo() 5860 sysvals.printSystemInfo(True)
5470 elif(cmd == 'usbtopo'): 5861 elif(cmd == 'devinfo'):
5471 detectUSB() 5862 deviceInfo()
5472 elif(cmd == 'modes'): 5863 elif(cmd == 'modes'):
5473 print getModes() 5864 print getModes()
5474 elif(cmd == 'flist'): 5865 elif(cmd == 'flist'):
5475 sysvals.getFtraceFilterFunctions(True) 5866 sysvals.getFtraceFilterFunctions(True)
5476 elif(cmd == 'flistall'): 5867 elif(cmd == 'flistall'):
5477 sysvals.getFtraceFilterFunctions(False) 5868 sysvals.getFtraceFilterFunctions(False)
5478 elif(cmd == 'usbauto'):
5479 setUSBDevicesAuto()
5480 elif(cmd == 'summary'): 5869 elif(cmd == 'summary'):
5481 runSummary(outdir, True) 5870 runSummary(sysvals.outdir, True)
5482 sys.exit() 5871 sys.exit()
5483 5872
5484 # if instructed, re-analyze existing data files 5873 # if instructed, re-analyze existing data files
5485 if(sysvals.notestrun): 5874 if(sysvals.notestrun):
5486 rerunTest() 5875 stamp = rerunTest()
5876 sysvals.outputResult(stamp)
5487 sys.exit() 5877 sys.exit()
5488 5878
5489 # verify that we can run a test 5879 # verify that we can run a test
5490 if(not statusCheck()): 5880 if(not statusCheck()):
5491 print('Check FAILED, aborting the test run!') 5881 doError('Check FAILED, aborting the test run!')
5492 sys.exit()
5493 5882
5494 # extract mem modes and convert 5883 # extract mem modes and convert
5495 mode = sysvals.suspendmode 5884 mode = sysvals.suspendmode
@@ -5509,25 +5898,35 @@ if __name__ == '__main__':
5509 5898
5510 sysvals.systemInfo(dmidecode(sysvals.mempath)) 5899 sysvals.systemInfo(dmidecode(sysvals.mempath))
5511 5900
5512 if multitest['run']: 5901 setRuntimeSuspend(True)
5902 if sysvals.display:
5903 call('xset -d :0.0 dpms 0 0 0', shell=True)
5904 call('xset -d :0.0 s off', shell=True)
5905 if sysvals.multitest['run']:
5513 # run multiple tests in a separate subdirectory 5906 # run multiple tests in a separate subdirectory
5514 if not outdir: 5907 if not sysvals.outdir:
5515 s = 'suspend-x%d' % multitest['count'] 5908 s = 'suspend-x%d' % sysvals.multitest['count']
5516 outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S') 5909 sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
5517 if not os.path.isdir(outdir): 5910 if not os.path.isdir(sysvals.outdir):
5518 os.mkdir(outdir) 5911 os.mkdir(sysvals.outdir)
5519 for i in range(multitest['count']): 5912 for i in range(sysvals.multitest['count']):
5520 if(i != 0): 5913 if(i != 0):
5521 print('Waiting %d seconds...' % (multitest['delay'])) 5914 print('Waiting %d seconds...' % (sysvals.multitest['delay']))
5522 time.sleep(multitest['delay']) 5915 time.sleep(sysvals.multitest['delay'])
5523 print('TEST (%d/%d) START' % (i+1, multitest['count'])) 5916 print('TEST (%d/%d) START' % (i+1, sysvals.multitest['count']))
5524 fmt = 'suspend-%y%m%d-%H%M%S' 5917 fmt = 'suspend-%y%m%d-%H%M%S'
5525 sysvals.testdir = os.path.join(outdir, datetime.now().strftime(fmt)) 5918 sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt))
5526 runTest() 5919 runTest(i+1)
5527 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count'])) 5920 print('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count']))
5528 runSummary(outdir, False) 5921 sysvals.logmsg = ''
5922 if not sysvals.skiphtml:
5923 runSummary(sysvals.outdir, False)
5924 sysvals.sudouser(sysvals.outdir)
5529 else: 5925 else:
5530 if outdir: 5926 if sysvals.outdir:
5531 sysvals.testdir = outdir 5927 sysvals.testdir = sysvals.outdir
5532 # run the test in the current directory 5928 # run the test in the current directory
5533 runTest() 5929 runTest()
5930 if sysvals.display:
5931 call('xset -d :0.0 s reset', shell=True)
5932 setRuntimeSuspend(False)
diff --git a/tools/scripts/Makefile.arch b/tools/scripts/Makefile.arch
index 78d90a249e88..b10b7a27c33f 100644
--- a/tools/scripts/Makefile.arch
+++ b/tools/scripts/Makefile.arch
@@ -4,8 +4,7 @@ HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
4 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \ 4 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \
5 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 5 -e s/s390x/s390/ -e s/parisc64/parisc/ \
6 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 6 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
7 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ 7 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
8 -e s/tile.*/tile/ )
9 8
10ifndef ARCH 9ifndef ARCH
11ARCH := $(HOSTARCH) 10ARCH := $(HOSTARCH)
@@ -34,14 +33,6 @@ ifeq ($(ARCH),sh64)
34 SRCARCH := sh 33 SRCARCH := sh
35endif 34endif
36 35
37# Additional ARCH settings for tile
38ifeq ($(ARCH),tilepro)
39 SRCARCH := tile
40endif
41ifeq ($(ARCH),tilegx)
42 SRCARCH := tile
43endif
44
45LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 36LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
46ifeq ($(LP64), 1) 37ifeq ($(LP64), 1)
47 IS_64_BIT := 1 38 IS_64_BIT := 1
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index dd614463d4d6..495066bafbe3 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -120,3 +120,5 @@ ifneq ($(silent),1)
120 QUIET_UNINST = @printf ' UNINST %s\n' $1; 120 QUIET_UNINST = @printf ' UNINST %s\n' $1;
121 endif 121 endif
122endif 122endif
123
124pound := \#
diff --git a/tools/testing/ktest/config-bisect.pl b/tools/testing/ktest/config-bisect.pl
new file mode 100755
index 000000000000..b28feea7c363
--- /dev/null
+++ b/tools/testing/ktest/config-bisect.pl
@@ -0,0 +1,770 @@
1#!/usr/bin/perl -w
2#
3# Copyright 2015 - Steven Rostedt, Red Hat Inc.
4# Copyright 2017 - Steven Rostedt, VMware, Inc.
5#
6# Licensed under the terms of the GNU GPL License version 2
7#
8
9# usage:
10# config-bisect.pl [options] good-config bad-config [good|bad]
11#
12
13# Compares a good config to a bad config, then takes half of the diffs
14# and produces a config that is somewhere between the good config and
15# the bad config. That is, the resulting config will start with the
16# good config and will try to make half of the differences of between
17# the good and bad configs match the bad config. It tries because of
18# dependencies between the two configs it may not be able to change
19# exactly half of the configs that are different between the two config
20# files.
21
22# Here's a normal way to use it:
23#
24# $ cd /path/to/linux/kernel
25# $ config-bisect.pl /path/to/good/config /path/to/bad/config
26
27# This will now pull in good config (blowing away .config in that directory
28# so do not make that be one of the good or bad configs), and then
29# build the config with "make oldconfig" to make sure it matches the
30# current kernel. It will then store the configs in that result for
31# the good config. It does the same for the bad config as well.
32# The algorithm will run, merging half of the differences between
33# the two configs and building them with "make oldconfig" to make sure
34# the result changes (dependencies may reset changes the tool had made).
35# It then copies the result of its good config to /path/to/good/config.tmp
36# and the bad config to /path/to/bad/config.tmp (just appends ".tmp" to the
37# files passed in). And the ".config" that you should test will be in
38# directory
39
40# After the first run, determine if the result is good or bad then
41# run the same command appending the result
42
43# For good results:
44# $ config-bisect.pl /path/to/good/config /path/to/bad/config good
45
46# For bad results:
47# $ config-bisect.pl /path/to/good/config /path/to/bad/config bad
48
49# Do not change the good-config or bad-config, config-bisect.pl will
50# copy the good-config to a temp file with the same name as good-config
51# but with a ".tmp" after it. It will do the same with the bad-config.
52
53# If "good" or "bad" is not stated at the end, it will copy the good and
54# bad configs to the .tmp versions. If a .tmp version already exists, it will
55# warn before writing over them (-r will not warn, and just write over them).
56# If the last config is labeled "good", then it will copy it to the good .tmp
57# version. If the last config is labeled "bad", it will copy it to the bad
58# .tmp version. It will continue this until it can not merge the two any more
59# without the result being equal to either the good or bad .tmp configs.
60
61my $start = 0;
62my $val = "";
63
64my $pwd = `pwd`;
65chomp $pwd;
66my $tree = $pwd;
67my $build;
68
69my $output_config;
70my $reset_bisect;
71
72sub usage {
73 print << "EOF"
74
75usage: config-bisect.pl [-l linux-tree][-b build-dir] good-config bad-config [good|bad]
76 -l [optional] define location of linux-tree (default is current directory)
77 -b [optional] define location to build (O=build-dir) (default is linux-tree)
78 good-config the config that is considered good
79 bad-config the config that does not work
80 "good" add this if the last run produced a good config
81 "bad" add this if the last run produced a bad config
82 If "good" or "bad" is not specified, then it is the start of a new bisect
83
84 Note, each run will create copy of good and bad configs with ".tmp" appended.
85
86EOF
87;
88
89 exit(-1);
90}
91
92sub doprint {
93 print @_;
94}
95
96sub dodie {
97 doprint "CRITICAL FAILURE... ", @_, "\n";
98
99 die @_, "\n";
100}
101
102sub expand_path {
103 my ($file) = @_;
104
105 if ($file =~ m,^/,) {
106 return $file;
107 }
108 return "$pwd/$file";
109}
110
111sub read_prompt {
112 my ($cancel, $prompt) = @_;
113
114 my $ans;
115
116 for (;;) {
117 if ($cancel) {
118 print "$prompt [y/n/C] ";
119 } else {
120 print "$prompt [y/N] ";
121 }
122 $ans = <STDIN>;
123 chomp $ans;
124 if ($ans =~ /^\s*$/) {
125 if ($cancel) {
126 $ans = "c";
127 } else {
128 $ans = "n";
129 }
130 }
131 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
132 if ($cancel) {
133 last if ($ans =~ /^c$/i);
134 print "Please answer either 'y', 'n' or 'c'.\n";
135 } else {
136 print "Please answer either 'y' or 'n'.\n";
137 }
138 }
139 if ($ans =~ /^c/i) {
140 exit;
141 }
142 if ($ans !~ /^y$/i) {
143 return 0;
144 }
145 return 1;
146}
147
148sub read_yn {
149 my ($prompt) = @_;
150
151 return read_prompt 0, $prompt;
152}
153
154sub read_ync {
155 my ($prompt) = @_;
156
157 return read_prompt 1, $prompt;
158}
159
160sub run_command {
161 my ($command, $redirect) = @_;
162 my $start_time;
163 my $end_time;
164 my $dord = 0;
165 my $pid;
166
167 $start_time = time;
168
169 doprint("$command ... ");
170
171 $pid = open(CMD, "$command 2>&1 |") or
172 dodie "unable to exec $command";
173
174 if (defined($redirect)) {
175 open (RD, ">$redirect") or
176 dodie "failed to write to redirect $redirect";
177 $dord = 1;
178 }
179
180 while (<CMD>) {
181 print RD if ($dord);
182 }
183
184 waitpid($pid, 0);
185 my $failed = $?;
186
187 close(CMD);
188 close(RD) if ($dord);
189
190 $end_time = time;
191 my $delta = $end_time - $start_time;
192
193 if ($delta == 1) {
194 doprint "[1 second] ";
195 } else {
196 doprint "[$delta seconds] ";
197 }
198
199 if ($failed) {
200 doprint "FAILED!\n";
201 } else {
202 doprint "SUCCESS\n";
203 }
204
205 return !$failed;
206}
207
208###### CONFIG BISECT ######
209
210# config_ignore holds the configs that were set (or unset) for
211# a good config and we will ignore these configs for the rest
212# of a config bisect. These configs stay as they were.
213my %config_ignore;
214
215# config_set holds what all configs were set as.
216my %config_set;
217
218# config_off holds the set of configs that the bad config had disabled.
219# We need to record them and set them in the .config when running
220# olddefconfig, because olddefconfig keeps the defaults.
221my %config_off;
222
223# config_off_tmp holds a set of configs to turn off for now
224my @config_off_tmp;
225
226# config_list is the set of configs that are being tested
227my %config_list;
228my %null_config;
229
230my %dependency;
231
232my $make;
233
234sub make_oldconfig {
235
236 if (!run_command "$make olddefconfig") {
237 # Perhaps olddefconfig doesn't exist in this version of the kernel
238 # try oldnoconfig
239 doprint "olddefconfig failed, trying make oldnoconfig\n";
240 if (!run_command "$make oldnoconfig") {
241 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
242 # try a yes '' | oldconfig
243 run_command "yes '' | $make oldconfig" or
244 dodie "failed make config oldconfig";
245 }
246 }
247}
248
249sub assign_configs {
250 my ($hash, $config) = @_;
251
252 doprint "Reading configs from $config\n";
253
254 open (IN, $config)
255 or dodie "Failed to read $config";
256
257 while (<IN>) {
258 chomp;
259 if (/^((CONFIG\S*)=.*)/) {
260 ${$hash}{$2} = $1;
261 } elsif (/^(# (CONFIG\S*) is not set)/) {
262 ${$hash}{$2} = $1;
263 }
264 }
265
266 close(IN);
267}
268
269sub process_config_ignore {
270 my ($config) = @_;
271
272 assign_configs \%config_ignore, $config;
273}
274
275sub get_dependencies {
276 my ($config) = @_;
277
278 my $arr = $dependency{$config};
279 if (!defined($arr)) {
280 return ();
281 }
282
283 my @deps = @{$arr};
284
285 foreach my $dep (@{$arr}) {
286 print "ADD DEP $dep\n";
287 @deps = (@deps, get_dependencies $dep);
288 }
289
290 return @deps;
291}
292
293sub save_config {
294 my ($pc, $file) = @_;
295
296 my %configs = %{$pc};
297
298 doprint "Saving configs into $file\n";
299
300 open(OUT, ">$file") or dodie "Can not write to $file";
301
302 foreach my $config (keys %configs) {
303 print OUT "$configs{$config}\n";
304 }
305 close(OUT);
306}
307
308sub create_config {
309 my ($name, $pc) = @_;
310
311 doprint "Creating old config from $name configs\n";
312
313 save_config $pc, $output_config;
314
315 make_oldconfig;
316}
317
318# compare two config hashes, and return configs with different vals.
319# It returns B's config values, but you can use A to see what A was.
320sub diff_config_vals {
321 my ($pa, $pb) = @_;
322
323 # crappy Perl way to pass in hashes.
324 my %a = %{$pa};
325 my %b = %{$pb};
326
327 my %ret;
328
329 foreach my $item (keys %a) {
330 if (defined($b{$item}) && $b{$item} ne $a{$item}) {
331 $ret{$item} = $b{$item};
332 }
333 }
334
335 return %ret;
336}
337
338# compare two config hashes and return the configs in B but not A
339sub diff_configs {
340 my ($pa, $pb) = @_;
341
342 my %ret;
343
344 # crappy Perl way to pass in hashes.
345 my %a = %{$pa};
346 my %b = %{$pb};
347
348 foreach my $item (keys %b) {
349 if (!defined($a{$item})) {
350 $ret{$item} = $b{$item};
351 }
352 }
353
354 return %ret;
355}
356
357# return if two configs are equal or not
358# 0 is equal +1 b has something a does not
359# +1 if a and b have a different item.
360# -1 if a has something b does not
361sub compare_configs {
362 my ($pa, $pb) = @_;
363
364 my %ret;
365
366 # crappy Perl way to pass in hashes.
367 my %a = %{$pa};
368 my %b = %{$pb};
369
370 foreach my $item (keys %b) {
371 if (!defined($a{$item})) {
372 return 1;
373 }
374 if ($a{$item} ne $b{$item}) {
375 return 1;
376 }
377 }
378
379 foreach my $item (keys %a) {
380 if (!defined($b{$item})) {
381 return -1;
382 }
383 }
384
385 return 0;
386}
387
388sub process_failed {
389 my ($config) = @_;
390
391 doprint "\n\n***************************************\n";
392 doprint "Found bad config: $config\n";
393 doprint "***************************************\n\n";
394}
395
396sub process_new_config {
397 my ($tc, $nc, $gc, $bc) = @_;
398
399 my %tmp_config = %{$tc};
400 my %good_configs = %{$gc};
401 my %bad_configs = %{$bc};
402
403 my %new_configs;
404
405 my $runtest = 1;
406 my $ret;
407
408 create_config "tmp_configs", \%tmp_config;
409 assign_configs \%new_configs, $output_config;
410
411 $ret = compare_configs \%new_configs, \%bad_configs;
412 if (!$ret) {
413 doprint "New config equals bad config, try next test\n";
414 $runtest = 0;
415 }
416
417 if ($runtest) {
418 $ret = compare_configs \%new_configs, \%good_configs;
419 if (!$ret) {
420 doprint "New config equals good config, try next test\n";
421 $runtest = 0;
422 }
423 }
424
425 %{$nc} = %new_configs;
426
427 return $runtest;
428}
429
430sub convert_config {
431 my ($config) = @_;
432
433 if ($config =~ /^# (.*) is not set/) {
434 $config = "$1=n";
435 }
436
437 $config =~ s/^CONFIG_//;
438 return $config;
439}
440
441sub print_config {
442 my ($sym, $config) = @_;
443
444 $config = convert_config $config;
445 doprint "$sym$config\n";
446}
447
448sub print_config_compare {
449 my ($good_config, $bad_config) = @_;
450
451 $good_config = convert_config $good_config;
452 $bad_config = convert_config $bad_config;
453
454 my $good_value = $good_config;
455 my $bad_value = $bad_config;
456 $good_value =~ s/(.*)=//;
457 my $config = $1;
458
459 $bad_value =~ s/.*=//;
460
461 doprint " $config $good_value -> $bad_value\n";
462}
463
464# Pass in:
465# $phalf: half of the configs names you want to add
466# $oconfigs: The orginial configs to start with
467# $sconfigs: The source to update $oconfigs with (from $phalf)
468# $which: The name of which half that is updating (top / bottom)
469# $type: The name of the source type (good / bad)
470sub make_half {
471 my ($phalf, $oconfigs, $sconfigs, $which, $type) = @_;
472
473 my @half = @{$phalf};
474 my %orig_configs = %{$oconfigs};
475 my %source_configs = %{$sconfigs};
476
477 my %tmp_config = %orig_configs;
478
479 doprint "Settings bisect with $which half of $type configs:\n";
480 foreach my $item (@half) {
481 doprint "Updating $item to $source_configs{$item}\n";
482 $tmp_config{$item} = $source_configs{$item};
483 }
484
485 return %tmp_config;
486}
487
488sub run_config_bisect {
489 my ($pgood, $pbad) = @_;
490
491 my %good_configs = %{$pgood};
492 my %bad_configs = %{$pbad};
493
494 my %diff_configs = diff_config_vals \%good_configs, \%bad_configs;
495 my %b_configs = diff_configs \%good_configs, \%bad_configs;
496 my %g_configs = diff_configs \%bad_configs, \%good_configs;
497
498 # diff_arr is what is in both good and bad but are different (y->n)
499 my @diff_arr = keys %diff_configs;
500 my $len_diff = $#diff_arr + 1;
501
502 # b_arr is what is in bad but not in good (has depends)
503 my @b_arr = keys %b_configs;
504 my $len_b = $#b_arr + 1;
505
506 # g_arr is what is in good but not in bad
507 my @g_arr = keys %g_configs;
508 my $len_g = $#g_arr + 1;
509
510 my $runtest = 0;
511 my %new_configs;
512 my $ret;
513
514 # Look at the configs that are different between good and bad.
515 # This does not include those that depend on other configs
516 # (configs depending on other configs that are not set would
517 # not show up even as a "# CONFIG_FOO is not set"
518
519
520 doprint "# of configs to check: $len_diff\n";
521 doprint "# of configs showing only in good: $len_g\n";
522 doprint "# of configs showing only in bad: $len_b\n";
523
524 if ($len_diff > 0) {
525 # Now test for different values
526
527 doprint "Configs left to check:\n";
528 doprint " Good Config\t\t\tBad Config\n";
529 doprint " -----------\t\t\t----------\n";
530 foreach my $item (@diff_arr) {
531 doprint " $good_configs{$item}\t$bad_configs{$item}\n";
532 }
533
534 my $half = int($#diff_arr / 2);
535 my @tophalf = @diff_arr[0 .. $half];
536
537 doprint "Set tmp config to be good config with some bad config values\n";
538
539 my %tmp_config = make_half \@tophalf, \%good_configs,
540 \%bad_configs, "top", "bad";
541
542 $runtest = process_new_config \%tmp_config, \%new_configs,
543 \%good_configs, \%bad_configs;
544
545 if (!$runtest) {
546 doprint "Set tmp config to be bad config with some good config values\n";
547
548 my %tmp_config = make_half \@tophalf, \%bad_configs,
549 \%good_configs, "top", "good";
550
551 $runtest = process_new_config \%tmp_config, \%new_configs,
552 \%good_configs, \%bad_configs;
553 }
554 }
555
556 if (!$runtest && $len_diff > 0) {
557 # do the same thing, but this time with bottom half
558
559 my $half = int($#diff_arr / 2);
560 my @bottomhalf = @diff_arr[$half+1 .. $#diff_arr];
561
562 doprint "Set tmp config to be good config with some bad config values\n";
563
564 my %tmp_config = make_half \@bottomhalf, \%good_configs,
565 \%bad_configs, "bottom", "bad";
566
567 $runtest = process_new_config \%tmp_config, \%new_configs,
568 \%good_configs, \%bad_configs;
569
570 if (!$runtest) {
571 doprint "Set tmp config to be bad config with some good config values\n";
572
573 my %tmp_config = make_half \@bottomhalf, \%bad_configs,
574 \%good_configs, "bottom", "good";
575
576 $runtest = process_new_config \%tmp_config, \%new_configs,
577 \%good_configs, \%bad_configs;
578 }
579 }
580
581 if ($runtest) {
582 make_oldconfig;
583 doprint "READY TO TEST .config IN $build\n";
584 return 0;
585 }
586
587 doprint "\n%%%%%%%% FAILED TO FIND SINGLE BAD CONFIG %%%%%%%%\n";
588 doprint "Hmm, can't make any more changes without making good == bad?\n";
589 doprint "Difference between good (+) and bad (-)\n";
590
591 foreach my $item (keys %bad_configs) {
592 if (!defined($good_configs{$item})) {
593 print_config "-", $bad_configs{$item};
594 }
595 }
596
597 foreach my $item (keys %good_configs) {
598 next if (!defined($bad_configs{$item}));
599 if ($good_configs{$item} ne $bad_configs{$item}) {
600 print_config_compare $good_configs{$item}, $bad_configs{$item};
601 }
602 }
603
604 foreach my $item (keys %good_configs) {
605 if (!defined($bad_configs{$item})) {
606 print_config "+", $good_configs{$item};
607 }
608 }
609 return -1;
610}
611
612sub config_bisect {
613 my ($good_config, $bad_config) = @_;
614 my $ret;
615
616 my %good_configs;
617 my %bad_configs;
618 my %tmp_configs;
619
620 doprint "Run good configs through make oldconfig\n";
621 assign_configs \%tmp_configs, $good_config;
622 create_config "$good_config", \%tmp_configs;
623 assign_configs \%good_configs, $output_config;
624
625 doprint "Run bad configs through make oldconfig\n";
626 assign_configs \%tmp_configs, $bad_config;
627 create_config "$bad_config", \%tmp_configs;
628 assign_configs \%bad_configs, $output_config;
629
630 save_config \%good_configs, $good_config;
631 save_config \%bad_configs, $bad_config;
632
633 return run_config_bisect \%good_configs, \%bad_configs;
634}
635
636while ($#ARGV >= 0) {
637 if ($ARGV[0] !~ m/^-/) {
638 last;
639 }
640 my $opt = shift @ARGV;
641
642 if ($opt eq "-b") {
643 $val = shift @ARGV;
644 if (!defined($val)) {
645 die "-b requires value\n";
646 }
647 $build = $val;
648 }
649
650 elsif ($opt eq "-l") {
651 $val = shift @ARGV;
652 if (!defined($val)) {
653 die "-l requires value\n";
654 }
655 $tree = $val;
656 }
657
658 elsif ($opt eq "-r") {
659 $reset_bisect = 1;
660 }
661
662 elsif ($opt eq "-h") {
663 usage;
664 }
665
666 else {
667 die "Unknow option $opt\n";
668 }
669}
670
671$build = $tree if (!defined($build));
672
673$tree = expand_path $tree;
674$build = expand_path $build;
675
676if ( ! -d $tree ) {
677 die "$tree not a directory\n";
678}
679
680if ( ! -d $build ) {
681 die "$build not a directory\n";
682}
683
684usage if $#ARGV < 1;
685
686if ($#ARGV == 1) {
687 $start = 1;
688} elsif ($#ARGV == 2) {
689 $val = $ARGV[2];
690 if ($val ne "good" && $val ne "bad") {
691 die "Unknown command '$val', bust be either \"good\" or \"bad\"\n";
692 }
693} else {
694 usage;
695}
696
697my $good_start = expand_path $ARGV[0];
698my $bad_start = expand_path $ARGV[1];
699
700my $good = "$good_start.tmp";
701my $bad = "$bad_start.tmp";
702
703$make = "make";
704
705if ($build ne $tree) {
706 $make = "make O=$build"
707}
708
709$output_config = "$build/.config";
710
711if ($start) {
712 if ( ! -f $good_start ) {
713 die "$good_start not found\n";
714 }
715 if ( ! -f $bad_start ) {
716 die "$bad_start not found\n";
717 }
718 if ( -f $good || -f $bad ) {
719 my $p = "";
720
721 if ( -f $good ) {
722 $p = "$good exists\n";
723 }
724
725 if ( -f $bad ) {
726 $p = "$p$bad exists\n";
727 }
728
729 if (!defined($reset_bisect)) {
730 if (!read_yn "${p}Overwrite and start new bisect anyway?") {
731 exit (-1);
732 }
733 }
734 }
735 run_command "cp $good_start $good" or die "failed to copy to $good\n";
736 run_command "cp $bad_start $bad" or die "faield to copy to $bad\n";
737} else {
738 if ( ! -f $good ) {
739 die "Can not find file $good\n";
740 }
741 if ( ! -f $bad ) {
742 die "Can not find file $bad\n";
743 }
744 if ($val eq "good") {
745 run_command "cp $output_config $good" or die "failed to copy $config to $good\n";
746 } elsif ($val eq "bad") {
747 run_command "cp $output_config $bad" or die "failed to copy $config to $bad\n";
748 }
749}
750
751chdir $tree || die "can't change directory to $tree";
752
753my $ret = config_bisect $good, $bad;
754
755if (!$ret) {
756 exit(0);
757}
758
759if ($ret > 0) {
760 doprint "Cleaning temp files\n";
761 run_command "rm $good";
762 run_command "rm $bad";
763 exit(1);
764} else {
765 doprint "See good and bad configs for details:\n";
766 doprint "good: $good\n";
767 doprint "bad: $bad\n";
768 doprint "%%%%%%%% FAILED TO FIND SINGLE BAD CONFIG %%%%%%%%\n";
769}
770exit(2);
diff --git a/tools/testing/ktest/examples/crosstests.conf b/tools/testing/ktest/examples/crosstests.conf
index a1203148dfa1..6907f32590b2 100644
--- a/tools/testing/ktest/examples/crosstests.conf
+++ b/tools/testing/ktest/examples/crosstests.conf
@@ -59,7 +59,7 @@ DO_DEFAULT := 1
59 59
60# By setting both DO_FAILED and DO_DEFAULT to zero, you can pick a single 60# By setting both DO_FAILED and DO_DEFAULT to zero, you can pick a single
61# arch that you want to test. (uncomment RUN and chose your arch) 61# arch that you want to test. (uncomment RUN and chose your arch)
62#RUN := m32r 62#RUN := arm
63 63
64# At the bottom of the config file exists a bisect test. You can update that 64# At the bottom of the config file exists a bisect test. You can update that
65# test and set DO_FAILED and DO_DEFAULT to zero, and uncomment this variable 65# test and set DO_FAILED and DO_DEFAULT to zero, and uncomment this variable
@@ -106,33 +106,11 @@ TEST_START IF ${RUN} == arm || ${DO_DEFAULT}
106CROSS = arm-unknown-linux-gnueabi 106CROSS = arm-unknown-linux-gnueabi
107ARCH = arm 107ARCH = arm
108 108
109# black fin
110TEST_START IF ${RUN} == bfin || ${DO_DEFAULT}
111CROSS = bfin-uclinux
112ARCH = blackfin
113BUILD_OPTIONS = -j8 vmlinux
114
115# cris - FAILS?
116TEST_START IF ${RUN} == cris || ${RUN} == cris64 || ${DO_FAILED}
117CROSS = cris-linux
118ARCH = cris
119
120# cris32 - not right arch?
121TEST_START IF ${RUN} == cris || ${RUN} == cris32 || ${DO_FAILED}
122CROSS = crisv32-linux
123ARCH = cris
124
125# ia64 109# ia64
126TEST_START IF ${RUN} == ia64 || ${DO_DEFAULT} 110TEST_START IF ${RUN} == ia64 || ${DO_DEFAULT}
127CROSS = ia64-linux 111CROSS = ia64-linux
128ARCH = ia64 112ARCH = ia64
129 113
130# frv
131TEST_START IF ${RUN} == frv || ${DO_FAILED}
132CROSS = frv-linux
133ARCH = frv
134GCC_VER = 4.5.1
135
136# m68k fails with error? 114# m68k fails with error?
137TEST_START IF ${RUN} == m68k || ${DO_DEFAULT} 115TEST_START IF ${RUN} == m68k || ${DO_DEFAULT}
138CROSS = m68k-linux 116CROSS = m68k-linux
@@ -148,13 +126,6 @@ TEST_START IF ${RUN} == mips || ${RUN} == mips32 || ${DO_DEFAULT}
148CROSS = mips-linux 126CROSS = mips-linux
149ARCH = mips 127ARCH = mips
150 128
151# m32r
152TEST_START IF ${RUN} == m32r || ${DO_FAILED}
153CROSS = m32r-linux
154ARCH = m32r
155GCC_VER = 4.5.1
156BUILD_OPTIONS = -j8 vmlinux
157
158# parisc64 failed? 129# parisc64 failed?
159TEST_START IF ${RUN} == hppa || ${RUN} == hppa64 || ${DO_FAILED} 130TEST_START IF ${RUN} == hppa || ${RUN} == hppa64 || ${DO_FAILED}
160CROSS = hppa64-linux 131CROSS = hppa64-linux
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 0c8b61f8398e..87af8a68ab25 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -10,6 +10,7 @@ use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10use File::Path qw(mkpath); 10use File::Path qw(mkpath);
11use File::Copy qw(cp); 11use File::Copy qw(cp);
12use FileHandle; 12use FileHandle;
13use FindBin;
13 14
14my $VERSION = "0.2"; 15my $VERSION = "0.2";
15 16
@@ -22,6 +23,11 @@ my %evals;
22 23
23#default opts 24#default opts
24my %default = ( 25my %default = (
26 "MAILER" => "sendmail", # default mailer
27 "EMAIL_ON_ERROR" => 1,
28 "EMAIL_WHEN_FINISHED" => 1,
29 "EMAIL_WHEN_CANCELED" => 0,
30 "EMAIL_WHEN_STARTED" => 0,
25 "NUM_TESTS" => 1, 31 "NUM_TESTS" => 1,
26 "TEST_TYPE" => "build", 32 "TEST_TYPE" => "build",
27 "BUILD_TYPE" => "randconfig", 33 "BUILD_TYPE" => "randconfig",
@@ -59,6 +65,7 @@ my %default = (
59 "GRUB_REBOOT" => "grub2-reboot", 65 "GRUB_REBOOT" => "grub2-reboot",
60 "SYSLINUX" => "extlinux", 66 "SYSLINUX" => "extlinux",
61 "SYSLINUX_PATH" => "/boot/extlinux", 67 "SYSLINUX_PATH" => "/boot/extlinux",
68 "CONNECT_TIMEOUT" => 25,
62 69
63# required, and we will ask users if they don't have them but we keep the default 70# required, and we will ask users if they don't have them but we keep the default
64# value something that is common. 71# value something that is common.
@@ -163,6 +170,8 @@ my $store_failures;
163my $store_successes; 170my $store_successes;
164my $test_name; 171my $test_name;
165my $timeout; 172my $timeout;
173my $connect_timeout;
174my $config_bisect_exec;
166my $booted_timeout; 175my $booted_timeout;
167my $detect_triplefault; 176my $detect_triplefault;
168my $console; 177my $console;
@@ -204,6 +213,20 @@ my $install_time;
204my $reboot_time; 213my $reboot_time;
205my $test_time; 214my $test_time;
206 215
216my $pwd;
217my $dirname = $FindBin::Bin;
218
219my $mailto;
220my $mailer;
221my $mail_path;
222my $mail_command;
223my $email_on_error;
224my $email_when_finished;
225my $email_when_started;
226my $email_when_canceled;
227
228my $script_start_time = localtime();
229
207# set when a test is something other that just building or install 230# set when a test is something other that just building or install
208# which would require more options. 231# which would require more options.
209my $buildonly = 1; 232my $buildonly = 1;
@@ -229,6 +252,14 @@ my $no_reboot = 1;
229my $reboot_success = 0; 252my $reboot_success = 0;
230 253
231my %option_map = ( 254my %option_map = (
255 "MAILTO" => \$mailto,
256 "MAILER" => \$mailer,
257 "MAIL_PATH" => \$mail_path,
258 "MAIL_COMMAND" => \$mail_command,
259 "EMAIL_ON_ERROR" => \$email_on_error,
260 "EMAIL_WHEN_FINISHED" => \$email_when_finished,
261 "EMAIL_WHEN_STARTED" => \$email_when_started,
262 "EMAIL_WHEN_CANCELED" => \$email_when_canceled,
232 "MACHINE" => \$machine, 263 "MACHINE" => \$machine,
233 "SSH_USER" => \$ssh_user, 264 "SSH_USER" => \$ssh_user,
234 "TMP_DIR" => \$tmpdir, 265 "TMP_DIR" => \$tmpdir,
@@ -296,6 +327,8 @@ my %option_map = (
296 "STORE_SUCCESSES" => \$store_successes, 327 "STORE_SUCCESSES" => \$store_successes,
297 "TEST_NAME" => \$test_name, 328 "TEST_NAME" => \$test_name,
298 "TIMEOUT" => \$timeout, 329 "TIMEOUT" => \$timeout,
330 "CONNECT_TIMEOUT" => \$connect_timeout,
331 "CONFIG_BISECT_EXEC" => \$config_bisect_exec,
299 "BOOTED_TIMEOUT" => \$booted_timeout, 332 "BOOTED_TIMEOUT" => \$booted_timeout,
300 "CONSOLE" => \$console, 333 "CONSOLE" => \$console,
301 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal, 334 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal,
@@ -337,6 +370,7 @@ my %used_options;
337 370
338# default variables that can be used 371# default variables that can be used
339chomp ($variable{"PWD"} = `pwd`); 372chomp ($variable{"PWD"} = `pwd`);
373$pwd = $variable{"PWD"};
340 374
341$config_help{"MACHINE"} = << "EOF" 375$config_help{"MACHINE"} = << "EOF"
342 The machine hostname that you will test. 376 The machine hostname that you will test.
@@ -718,22 +752,14 @@ sub set_value {
718 752
719 my $prvalue = process_variables($rvalue); 753 my $prvalue = process_variables($rvalue);
720 754
721 if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") { 755 if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ &&
756 $prvalue !~ /^(config_|)bisect$/ &&
757 $prvalue !~ /^build$/ &&
758 $buildonly) {
759
722 # Note if a test is something other than build, then we 760 # Note if a test is something other than build, then we
723 # will need other mandatory options. 761 # will need other mandatory options.
724 if ($prvalue ne "install") { 762 if ($prvalue ne "install") {
725 # for bisect, we need to check BISECT_TYPE
726 if ($prvalue ne "bisect") {
727 $buildonly = 0;
728 }
729 } else {
730 # install still limits some mandatory options.
731 $buildonly = 2;
732 }
733 }
734
735 if ($buildonly && $lvalue =~ /^BISECT_TYPE(\[.*\])?$/ && $prvalue ne "build") {
736 if ($prvalue ne "install") {
737 $buildonly = 0; 763 $buildonly = 0;
738 } else { 764 } else {
739 # install still limits some mandatory options. 765 # install still limits some mandatory options.
@@ -1140,7 +1166,8 @@ sub __read_config {
1140sub get_test_case { 1166sub get_test_case {
1141 print "What test case would you like to run?\n"; 1167 print "What test case would you like to run?\n";
1142 print " (build, install or boot)\n"; 1168 print " (build, install or boot)\n";
1143 print " Other tests are available but require editing the config file\n"; 1169 print " Other tests are available but require editing ktest.conf\n";
1170 print " (see tools/testing/ktest/sample.conf)\n";
1144 my $ans = <STDIN>; 1171 my $ans = <STDIN>;
1145 chomp $ans; 1172 chomp $ans;
1146 $default{"TEST_TYPE"} = $ans; 1173 $default{"TEST_TYPE"} = $ans;
@@ -1328,8 +1355,8 @@ sub reboot {
1328 my ($time) = @_; 1355 my ($time) = @_;
1329 my $powercycle = 0; 1356 my $powercycle = 0;
1330 1357
1331 # test if the machine can be connected to within 5 seconds 1358 # test if the machine can be connected to within a few seconds
1332 my $stat = run_ssh("echo check machine status", 5); 1359 my $stat = run_ssh("echo check machine status", $connect_timeout);
1333 if (!$stat) { 1360 if (!$stat) {
1334 doprint("power cycle\n"); 1361 doprint("power cycle\n");
1335 $powercycle = 1; 1362 $powercycle = 1;
@@ -1404,10 +1431,18 @@ sub do_not_reboot {
1404 1431
1405 return $test_type eq "build" || $no_reboot || 1432 return $test_type eq "build" || $no_reboot ||
1406 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1433 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1407 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 1434 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") ||
1435 ($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build");
1408} 1436}
1409 1437
1438my $in_die = 0;
1439
1410sub dodie { 1440sub dodie {
1441
1442 # avoid recusion
1443 return if ($in_die);
1444 $in_die = 1;
1445
1411 doprint "CRITICAL FAILURE... ", @_, "\n"; 1446 doprint "CRITICAL FAILURE... ", @_, "\n";
1412 1447
1413 my $i = $iteration; 1448 my $i = $iteration;
@@ -1426,6 +1461,11 @@ sub dodie {
1426 print " See $opt{LOG_FILE} for more info.\n"; 1461 print " See $opt{LOG_FILE} for more info.\n";
1427 } 1462 }
1428 1463
1464 if ($email_on_error) {
1465 send_email("KTEST: critical failure for your [$test_type] test",
1466 "Your test started at $script_start_time has failed with:\n@_\n");
1467 }
1468
1429 if ($monitor_cnt) { 1469 if ($monitor_cnt) {
1430 # restore terminal settings 1470 # restore terminal settings
1431 system("stty $stty_orig"); 1471 system("stty $stty_orig");
@@ -1477,7 +1517,7 @@ sub exec_console {
1477 close($pts); 1517 close($pts);
1478 1518
1479 exec $console or 1519 exec $console or
1480 die "Can't open console $console"; 1520 dodie "Can't open console $console";
1481} 1521}
1482 1522
1483sub open_console { 1523sub open_console {
@@ -1515,6 +1555,9 @@ sub close_console {
1515 doprint "kill child process $pid\n"; 1555 doprint "kill child process $pid\n";
1516 kill $close_console_signal, $pid; 1556 kill $close_console_signal, $pid;
1517 1557
1558 doprint "wait for child process $pid to exit\n";
1559 waitpid($pid, 0);
1560
1518 print "closing!\n"; 1561 print "closing!\n";
1519 close($fp); 1562 close($fp);
1520 1563
@@ -1625,7 +1668,7 @@ sub save_logs {
1625 1668
1626 if (!-d $dir) { 1669 if (!-d $dir) {
1627 mkpath($dir) or 1670 mkpath($dir) or
1628 die "can't create $dir"; 1671 dodie "can't create $dir";
1629 } 1672 }
1630 1673
1631 my %files = ( 1674 my %files = (
@@ -1638,7 +1681,7 @@ sub save_logs {
1638 while (my ($name, $source) = each(%files)) { 1681 while (my ($name, $source) = each(%files)) {
1639 if (-f "$source") { 1682 if (-f "$source") {
1640 cp "$source", "$dir/$name" or 1683 cp "$source", "$dir/$name" or
1641 die "failed to copy $source"; 1684 dodie "failed to copy $source";
1642 } 1685 }
1643 } 1686 }
1644 1687
@@ -1692,6 +1735,7 @@ sub run_command {
1692 my $end_time; 1735 my $end_time;
1693 my $dolog = 0; 1736 my $dolog = 0;
1694 my $dord = 0; 1737 my $dord = 0;
1738 my $dostdout = 0;
1695 my $pid; 1739 my $pid;
1696 1740
1697 $command =~ s/\$SSH_USER/$ssh_user/g; 1741 $command =~ s/\$SSH_USER/$ssh_user/g;
@@ -1710,9 +1754,15 @@ sub run_command {
1710 } 1754 }
1711 1755
1712 if (defined($redirect)) { 1756 if (defined($redirect)) {
1713 open (RD, ">$redirect") or 1757 if ($redirect eq 1) {
1714 dodie "failed to write to redirect $redirect"; 1758 $dostdout = 1;
1715 $dord = 1; 1759 # Have the output of the command on its own line
1760 doprint "\n";
1761 } else {
1762 open (RD, ">$redirect") or
1763 dodie "failed to write to redirect $redirect";
1764 $dord = 1;
1765 }
1716 } 1766 }
1717 1767
1718 my $hit_timeout = 0; 1768 my $hit_timeout = 0;
@@ -1734,6 +1784,7 @@ sub run_command {
1734 } 1784 }
1735 print LOG $line if ($dolog); 1785 print LOG $line if ($dolog);
1736 print RD $line if ($dord); 1786 print RD $line if ($dord);
1787 print $line if ($dostdout);
1737 } 1788 }
1738 1789
1739 waitpid($pid, 0); 1790 waitpid($pid, 0);
@@ -1812,7 +1863,7 @@ sub get_grub2_index {
1812 $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g; 1863 $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g;
1813 1864
1814 open(IN, "$ssh_grub |") 1865 open(IN, "$ssh_grub |")
1815 or die "unable to get $grub_file"; 1866 or dodie "unable to get $grub_file";
1816 1867
1817 my $found = 0; 1868 my $found = 0;
1818 1869
@@ -1821,13 +1872,13 @@ sub get_grub2_index {
1821 $grub_number++; 1872 $grub_number++;
1822 $found = 1; 1873 $found = 1;
1823 last; 1874 last;
1824 } elsif (/^menuentry\s/) { 1875 } elsif (/^menuentry\s|^submenu\s/) {
1825 $grub_number++; 1876 $grub_number++;
1826 } 1877 }
1827 } 1878 }
1828 close(IN); 1879 close(IN);
1829 1880
1830 die "Could not find '$grub_menu' in $grub_file on $machine" 1881 dodie "Could not find '$grub_menu' in $grub_file on $machine"
1831 if (!$found); 1882 if (!$found);
1832 doprint "$grub_number\n"; 1883 doprint "$grub_number\n";
1833 $last_grub_menu = $grub_menu; 1884 $last_grub_menu = $grub_menu;
@@ -1855,7 +1906,7 @@ sub get_grub_index {
1855 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1906 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1856 1907
1857 open(IN, "$ssh_grub |") 1908 open(IN, "$ssh_grub |")
1858 or die "unable to get menu.lst"; 1909 or dodie "unable to get menu.lst";
1859 1910
1860 my $found = 0; 1911 my $found = 0;
1861 1912
@@ -1870,7 +1921,7 @@ sub get_grub_index {
1870 } 1921 }
1871 close(IN); 1922 close(IN);
1872 1923
1873 die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1924 dodie "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1874 if (!$found); 1925 if (!$found);
1875 doprint "$grub_number\n"; 1926 doprint "$grub_number\n";
1876 $last_grub_menu = $grub_menu; 1927 $last_grub_menu = $grub_menu;
@@ -1983,7 +2034,7 @@ sub monitor {
1983 my $full_line = ""; 2034 my $full_line = "";
1984 2035
1985 open(DMESG, "> $dmesg") or 2036 open(DMESG, "> $dmesg") or
1986 die "unable to write to $dmesg"; 2037 dodie "unable to write to $dmesg";
1987 2038
1988 reboot_to; 2039 reboot_to;
1989 2040
@@ -2862,7 +2913,7 @@ sub run_bisect {
2862sub update_bisect_replay { 2913sub update_bisect_replay {
2863 my $tmp_log = "$tmpdir/ktest_bisect_log"; 2914 my $tmp_log = "$tmpdir/ktest_bisect_log";
2864 run_command "git bisect log > $tmp_log" or 2915 run_command "git bisect log > $tmp_log" or
2865 die "can't create bisect log"; 2916 dodie "can't create bisect log";
2866 return $tmp_log; 2917 return $tmp_log;
2867} 2918}
2868 2919
@@ -2871,9 +2922,9 @@ sub bisect {
2871 2922
2872 my $result; 2923 my $result;
2873 2924
2874 die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 2925 dodie "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good));
2875 die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 2926 dodie "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad));
2876 die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 2927 dodie "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type));
2877 2928
2878 my $good = $bisect_good; 2929 my $good = $bisect_good;
2879 my $bad = $bisect_bad; 2930 my $bad = $bisect_bad;
@@ -2936,7 +2987,7 @@ sub bisect {
2936 if ($check ne "good") { 2987 if ($check ne "good") {
2937 doprint "TESTING BISECT BAD [$bad]\n"; 2988 doprint "TESTING BISECT BAD [$bad]\n";
2938 run_command "git checkout $bad" or 2989 run_command "git checkout $bad" or
2939 die "Failed to checkout $bad"; 2990 dodie "Failed to checkout $bad";
2940 2991
2941 $result = run_bisect $type; 2992 $result = run_bisect $type;
2942 2993
@@ -2948,7 +2999,7 @@ sub bisect {
2948 if ($check ne "bad") { 2999 if ($check ne "bad") {
2949 doprint "TESTING BISECT GOOD [$good]\n"; 3000 doprint "TESTING BISECT GOOD [$good]\n";
2950 run_command "git checkout $good" or 3001 run_command "git checkout $good" or
2951 die "Failed to checkout $good"; 3002 dodie "Failed to checkout $good";
2952 3003
2953 $result = run_bisect $type; 3004 $result = run_bisect $type;
2954 3005
@@ -2959,7 +3010,7 @@ sub bisect {
2959 3010
2960 # checkout where we started 3011 # checkout where we started
2961 run_command "git checkout $head" or 3012 run_command "git checkout $head" or
2962 die "Failed to checkout $head"; 3013 dodie "Failed to checkout $head";
2963 } 3014 }
2964 3015
2965 run_command "git bisect start$start_files" or 3016 run_command "git bisect start$start_files" or
@@ -3092,76 +3143,6 @@ sub create_config {
3092 make_oldconfig; 3143 make_oldconfig;
3093} 3144}
3094 3145
3095# compare two config hashes, and return configs with different vals.
3096# It returns B's config values, but you can use A to see what A was.
3097sub diff_config_vals {
3098 my ($pa, $pb) = @_;
3099
3100 # crappy Perl way to pass in hashes.
3101 my %a = %{$pa};
3102 my %b = %{$pb};
3103
3104 my %ret;
3105
3106 foreach my $item (keys %a) {
3107 if (defined($b{$item}) && $b{$item} ne $a{$item}) {
3108 $ret{$item} = $b{$item};
3109 }
3110 }
3111
3112 return %ret;
3113}
3114
3115# compare two config hashes and return the configs in B but not A
3116sub diff_configs {
3117 my ($pa, $pb) = @_;
3118
3119 my %ret;
3120
3121 # crappy Perl way to pass in hashes.
3122 my %a = %{$pa};
3123 my %b = %{$pb};
3124
3125 foreach my $item (keys %b) {
3126 if (!defined($a{$item})) {
3127 $ret{$item} = $b{$item};
3128 }
3129 }
3130
3131 return %ret;
3132}
3133
3134# return if two configs are equal or not
3135# 0 is equal +1 b has something a does not
3136# +1 if a and b have a different item.
3137# -1 if a has something b does not
3138sub compare_configs {
3139 my ($pa, $pb) = @_;
3140
3141 my %ret;
3142
3143 # crappy Perl way to pass in hashes.
3144 my %a = %{$pa};
3145 my %b = %{$pb};
3146
3147 foreach my $item (keys %b) {
3148 if (!defined($a{$item})) {
3149 return 1;
3150 }
3151 if ($a{$item} ne $b{$item}) {
3152 return 1;
3153 }
3154 }
3155
3156 foreach my $item (keys %a) {
3157 if (!defined($b{$item})) {
3158 return -1;
3159 }
3160 }
3161
3162 return 0;
3163}
3164
3165sub run_config_bisect_test { 3146sub run_config_bisect_test {
3166 my ($type) = @_; 3147 my ($type) = @_;
3167 3148
@@ -3174,166 +3155,57 @@ sub run_config_bisect_test {
3174 return $ret; 3155 return $ret;
3175} 3156}
3176 3157
3177sub process_failed { 3158sub config_bisect_end {
3178 my ($config) = @_; 3159 my ($good, $bad) = @_;
3160 my $diffexec = "diff -u";
3179 3161
3162 if (-f "$builddir/scripts/diffconfig") {
3163 $diffexec = "$builddir/scripts/diffconfig";
3164 }
3180 doprint "\n\n***************************************\n"; 3165 doprint "\n\n***************************************\n";
3181 doprint "Found bad config: $config\n"; 3166 doprint "No more config bisecting possible.\n";
3167 run_command "$diffexec $good $bad", 1;
3182 doprint "***************************************\n\n"; 3168 doprint "***************************************\n\n";
3183} 3169}
3184 3170
3185# used for config bisecting
3186my $good_config;
3187my $bad_config;
3188
3189sub process_new_config {
3190 my ($tc, $nc, $gc, $bc) = @_;
3191
3192 my %tmp_config = %{$tc};
3193 my %good_configs = %{$gc};
3194 my %bad_configs = %{$bc};
3195
3196 my %new_configs;
3197
3198 my $runtest = 1;
3199 my $ret;
3200
3201 create_config "tmp_configs", \%tmp_config;
3202 assign_configs \%new_configs, $output_config;
3203
3204 $ret = compare_configs \%new_configs, \%bad_configs;
3205 if (!$ret) {
3206 doprint "New config equals bad config, try next test\n";
3207 $runtest = 0;
3208 }
3209
3210 if ($runtest) {
3211 $ret = compare_configs \%new_configs, \%good_configs;
3212 if (!$ret) {
3213 doprint "New config equals good config, try next test\n";
3214 $runtest = 0;
3215 }
3216 }
3217
3218 %{$nc} = %new_configs;
3219
3220 return $runtest;
3221}
3222
3223sub run_config_bisect { 3171sub run_config_bisect {
3224 my ($pgood, $pbad) = @_; 3172 my ($good, $bad, $last_result) = @_;
3225 3173 my $reset = "";
3226 my $type = $config_bisect_type; 3174 my $cmd;
3227
3228 my %good_configs = %{$pgood};
3229 my %bad_configs = %{$pbad};
3230
3231 my %diff_configs = diff_config_vals \%good_configs, \%bad_configs;
3232 my %b_configs = diff_configs \%good_configs, \%bad_configs;
3233 my %g_configs = diff_configs \%bad_configs, \%good_configs;
3234
3235 my @diff_arr = keys %diff_configs;
3236 my $len_diff = $#diff_arr + 1;
3237
3238 my @b_arr = keys %b_configs;
3239 my $len_b = $#b_arr + 1;
3240
3241 my @g_arr = keys %g_configs;
3242 my $len_g = $#g_arr + 1;
3243
3244 my $runtest = 1;
3245 my %new_configs;
3246 my $ret; 3175 my $ret;
3247 3176
3248 # First, lets get it down to a single subset. 3177 if (!length($last_result)) {
3249 # Is the problem with a difference in values? 3178 $reset = "-r";
3250 # Is the problem with a missing config?
3251 # Is the problem with a config that breaks things?
3252
3253 # Enable all of one set and see if we get a new bad
3254 # or good config.
3255
3256 # first set the good config to the bad values.
3257
3258 doprint "d=$len_diff g=$len_g b=$len_b\n";
3259
3260 # first lets enable things in bad config that are enabled in good config
3261
3262 if ($len_diff > 0) {
3263 if ($len_b > 0 || $len_g > 0) {
3264 my %tmp_config = %bad_configs;
3265
3266 doprint "Set tmp config to be bad config with good config values\n";
3267 foreach my $item (@diff_arr) {
3268 $tmp_config{$item} = $good_configs{$item};
3269 }
3270
3271 $runtest = process_new_config \%tmp_config, \%new_configs,
3272 \%good_configs, \%bad_configs;
3273 }
3274 } 3179 }
3180 run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1;
3275 3181
3276 if (!$runtest && $len_diff > 0) { 3182 # config-bisect returns:
3277 3183 # 0 if there is more to bisect
3278 if ($len_diff == 1) { 3184 # 1 for finding a good config
3279 process_failed $diff_arr[0]; 3185 # 2 if it can not find any more configs
3280 return 1; 3186 # -1 (255) on error
3281 } 3187 if ($run_command_status) {
3282 my %tmp_config = %bad_configs; 3188 return $run_command_status;
3283
3284 my $half = int($#diff_arr / 2);
3285 my @tophalf = @diff_arr[0 .. $half];
3286
3287 doprint "Settings bisect with top half:\n";
3288 doprint "Set tmp config to be bad config with some good config values\n";
3289 foreach my $item (@tophalf) {
3290 $tmp_config{$item} = $good_configs{$item};
3291 }
3292
3293 $runtest = process_new_config \%tmp_config, \%new_configs,
3294 \%good_configs, \%bad_configs;
3295
3296 if (!$runtest) {
3297 my %tmp_config = %bad_configs;
3298
3299 doprint "Try bottom half\n";
3300
3301 my @bottomhalf = @diff_arr[$half+1 .. $#diff_arr];
3302
3303 foreach my $item (@bottomhalf) {
3304 $tmp_config{$item} = $good_configs{$item};
3305 }
3306
3307 $runtest = process_new_config \%tmp_config, \%new_configs,
3308 \%good_configs, \%bad_configs;
3309 }
3310 } 3189 }
3311 3190
3312 if ($runtest) { 3191 $ret = run_config_bisect_test $config_bisect_type;
3313 $ret = run_config_bisect_test $type; 3192 if ($ret) {
3314 if ($ret) { 3193 doprint "NEW GOOD CONFIG\n";
3315 doprint "NEW GOOD CONFIG\n"; 3194 # Return 3 for good config
3316 %good_configs = %new_configs; 3195 return 3;
3317 run_command "mv $good_config ${good_config}.last"; 3196 } else {
3318 save_config \%good_configs, $good_config; 3197 doprint "NEW BAD CONFIG\n";
3319 %{$pgood} = %good_configs; 3198 # Return 4 for bad config
3320 } else { 3199 return 4;
3321 doprint "NEW BAD CONFIG\n";
3322 %bad_configs = %new_configs;
3323 run_command "mv $bad_config ${bad_config}.last";
3324 save_config \%bad_configs, $bad_config;
3325 %{$pbad} = %bad_configs;
3326 }
3327 return 0;
3328 } 3200 }
3329
3330 fail "Hmm, need to do a mix match?\n";
3331 return -1;
3332} 3201}
3333 3202
3334sub config_bisect { 3203sub config_bisect {
3335 my ($i) = @_; 3204 my ($i) = @_;
3336 3205
3206 my $good_config;
3207 my $bad_config;
3208
3337 my $type = $config_bisect_type; 3209 my $type = $config_bisect_type;
3338 my $ret; 3210 my $ret;
3339 3211
@@ -3353,6 +3225,24 @@ sub config_bisect {
3353 $good_config = $output_config; 3225 $good_config = $output_config;
3354 } 3226 }
3355 3227
3228 if (!defined($config_bisect_exec)) {
3229 # First check the location that ktest.pl ran
3230 my @locations = ( "$pwd/config-bisect.pl",
3231 "$dirname/config-bisect.pl",
3232 "$builddir/tools/testing/ktest/config-bisect.pl",
3233 undef );
3234 foreach my $loc (@locations) {
3235 doprint "loc = $loc\n";
3236 $config_bisect_exec = $loc;
3237 last if (defined($config_bisect_exec && -x $config_bisect_exec));
3238 }
3239 if (!defined($config_bisect_exec)) {
3240 fail "Could not find an executable config-bisect.pl\n",
3241 " Set CONFIG_BISECT_EXEC to point to config-bisect.pl";
3242 return 1;
3243 }
3244 }
3245
3356 # we don't want min configs to cause issues here. 3246 # we don't want min configs to cause issues here.
3357 doprint "Disabling 'MIN_CONFIG' for this test\n"; 3247 doprint "Disabling 'MIN_CONFIG' for this test\n";
3358 undef $minconfig; 3248 undef $minconfig;
@@ -3361,21 +3251,31 @@ sub config_bisect {
3361 my %bad_configs; 3251 my %bad_configs;
3362 my %tmp_configs; 3252 my %tmp_configs;
3363 3253
3254 if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") {
3255 if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") {
3256 if (-f "$tmpdir/good_config.tmp") {
3257 $good_config = "$tmpdir/good_config.tmp";
3258 } else {
3259 $good_config = "$tmpdir/good_config";
3260 }
3261 if (-f "$tmpdir/bad_config.tmp") {
3262 $bad_config = "$tmpdir/bad_config.tmp";
3263 } else {
3264 $bad_config = "$tmpdir/bad_config";
3265 }
3266 }
3267 }
3364 doprint "Run good configs through make oldconfig\n"; 3268 doprint "Run good configs through make oldconfig\n";
3365 assign_configs \%tmp_configs, $good_config; 3269 assign_configs \%tmp_configs, $good_config;
3366 create_config "$good_config", \%tmp_configs; 3270 create_config "$good_config", \%tmp_configs;
3367 assign_configs \%good_configs, $output_config; 3271 $good_config = "$tmpdir/good_config";
3272 system("cp $output_config $good_config") == 0 or dodie "cp good config";
3368 3273
3369 doprint "Run bad configs through make oldconfig\n"; 3274 doprint "Run bad configs through make oldconfig\n";
3370 assign_configs \%tmp_configs, $bad_config; 3275 assign_configs \%tmp_configs, $bad_config;
3371 create_config "$bad_config", \%tmp_configs; 3276 create_config "$bad_config", \%tmp_configs;
3372 assign_configs \%bad_configs, $output_config;
3373
3374 $good_config = "$tmpdir/good_config";
3375 $bad_config = "$tmpdir/bad_config"; 3277 $bad_config = "$tmpdir/bad_config";
3376 3278 system("cp $output_config $bad_config") == 0 or dodie "cp bad config";
3377 save_config \%good_configs, $good_config;
3378 save_config \%bad_configs, $bad_config;
3379 3279
3380 if (defined($config_bisect_check) && $config_bisect_check ne "0") { 3280 if (defined($config_bisect_check) && $config_bisect_check ne "0") {
3381 if ($config_bisect_check ne "good") { 3281 if ($config_bisect_check ne "good") {
@@ -3398,10 +3298,21 @@ sub config_bisect {
3398 } 3298 }
3399 } 3299 }
3400 3300
3301 my $last_run = "";
3302
3401 do { 3303 do {
3402 $ret = run_config_bisect \%good_configs, \%bad_configs; 3304 $ret = run_config_bisect $good_config, $bad_config, $last_run;
3305 if ($ret == 3) {
3306 $last_run = "good";
3307 } elsif ($ret == 4) {
3308 $last_run = "bad";
3309 }
3403 print_times; 3310 print_times;
3404 } while (!$ret); 3311 } while ($ret == 3 || $ret == 4);
3312
3313 if ($ret == 2) {
3314 config_bisect_end "$good_config.tmp", "$bad_config.tmp";
3315 }
3405 3316
3406 return $ret if ($ret < 0); 3317 return $ret if ($ret < 0);
3407 3318
@@ -3416,9 +3327,9 @@ sub patchcheck_reboot {
3416sub patchcheck { 3327sub patchcheck {
3417 my ($i) = @_; 3328 my ($i) = @_;
3418 3329
3419 die "PATCHCHECK_START[$i] not defined\n" 3330 dodie "PATCHCHECK_START[$i] not defined\n"
3420 if (!defined($patchcheck_start)); 3331 if (!defined($patchcheck_start));
3421 die "PATCHCHECK_TYPE[$i] not defined\n" 3332 dodie "PATCHCHECK_TYPE[$i] not defined\n"
3422 if (!defined($patchcheck_type)); 3333 if (!defined($patchcheck_type));
3423 3334
3424 my $start = $patchcheck_start; 3335 my $start = $patchcheck_start;
@@ -3432,7 +3343,7 @@ sub patchcheck {
3432 if (defined($patchcheck_end)) { 3343 if (defined($patchcheck_end)) {
3433 $end = $patchcheck_end; 3344 $end = $patchcheck_end;
3434 } elsif ($cherry) { 3345 } elsif ($cherry) {
3435 die "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n"; 3346 dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n";
3436 } 3347 }
3437 3348
3438 # Get the true sha1's since we can use things like HEAD~3 3349 # Get the true sha1's since we can use things like HEAD~3
@@ -3496,7 +3407,7 @@ sub patchcheck {
3496 doprint "\nProcessing commit \"$item\"\n\n"; 3407 doprint "\nProcessing commit \"$item\"\n\n";
3497 3408
3498 run_command "git checkout $sha1" or 3409 run_command "git checkout $sha1" or
3499 die "Failed to checkout $sha1"; 3410 dodie "Failed to checkout $sha1";
3500 3411
3501 # only clean on the first and last patch 3412 # only clean on the first and last patch
3502 if ($item eq $list[0] || 3413 if ($item eq $list[0] ||
@@ -3587,7 +3498,7 @@ sub read_kconfig {
3587 } 3498 }
3588 3499
3589 open(KIN, "$kconfig") 3500 open(KIN, "$kconfig")
3590 or die "Can't open $kconfig"; 3501 or dodie "Can't open $kconfig";
3591 while (<KIN>) { 3502 while (<KIN>) {
3592 chomp; 3503 chomp;
3593 3504
@@ -3683,8 +3594,6 @@ sub read_depends {
3683 # what directory to look at. 3594 # what directory to look at.
3684 if ($arch eq "i386" || $arch eq "x86_64") { 3595 if ($arch eq "i386" || $arch eq "x86_64") {
3685 $arch = "x86"; 3596 $arch = "x86";
3686 } elsif ($arch =~ /^tile/) {
3687 $arch = "tile";
3688 } 3597 }
3689 3598
3690 my $kconfig = "$builddir/arch/$arch/Kconfig"; 3599 my $kconfig = "$builddir/arch/$arch/Kconfig";
@@ -3748,7 +3657,7 @@ sub get_depends {
3748 3657
3749 $dep =~ s/^[^$valid]*[$valid]+//; 3658 $dep =~ s/^[^$valid]*[$valid]+//;
3750 } else { 3659 } else {
3751 die "this should never happen"; 3660 dodie "this should never happen";
3752 } 3661 }
3753 } 3662 }
3754 3663
@@ -4009,7 +3918,7 @@ sub make_min_config {
4009 # update new ignore configs 3918 # update new ignore configs
4010 if (defined($ignore_config)) { 3919 if (defined($ignore_config)) {
4011 open (OUT, ">$temp_config") 3920 open (OUT, ">$temp_config")
4012 or die "Can't write to $temp_config"; 3921 or dodie "Can't write to $temp_config";
4013 foreach my $config (keys %save_configs) { 3922 foreach my $config (keys %save_configs) {
4014 print OUT "$save_configs{$config}\n"; 3923 print OUT "$save_configs{$config}\n";
4015 } 3924 }
@@ -4037,7 +3946,7 @@ sub make_min_config {
4037 3946
4038 # Save off all the current mandatory configs 3947 # Save off all the current mandatory configs
4039 open (OUT, ">$temp_config") 3948 open (OUT, ">$temp_config")
4040 or die "Can't write to $temp_config"; 3949 or dodie "Can't write to $temp_config";
4041 foreach my $config (keys %keep_configs) { 3950 foreach my $config (keys %keep_configs) {
4042 print OUT "$keep_configs{$config}\n"; 3951 print OUT "$keep_configs{$config}\n";
4043 } 3952 }
@@ -4224,6 +4133,74 @@ sub set_test_option {
4224 return eval_option($name, $option, $i); 4133 return eval_option($name, $option, $i);
4225} 4134}
4226 4135
4136sub find_mailer {
4137 my ($mailer) = @_;
4138
4139 my @paths = split /:/, $ENV{PATH};
4140
4141 # sendmail is usually in /usr/sbin
4142 $paths[$#paths + 1] = "/usr/sbin";
4143
4144 foreach my $path (@paths) {
4145 if (-x "$path/$mailer") {
4146 return $path;
4147 }
4148 }
4149
4150 return undef;
4151}
4152
4153sub do_send_mail {
4154 my ($subject, $message) = @_;
4155
4156 if (!defined($mail_path)) {
4157 # find the mailer
4158 $mail_path = find_mailer $mailer;
4159 if (!defined($mail_path)) {
4160 die "\nCan not find $mailer in PATH\n";
4161 }
4162 }
4163
4164 if (!defined($mail_command)) {
4165 if ($mailer eq "mail" || $mailer eq "mailx") {
4166 $mail_command = "\$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO <<< \'\$MESSAGE\'";
4167 } elsif ($mailer eq "sendmail" ) {
4168 $mail_command = "echo \'Subject: \$SUBJECT\n\n\$MESSAGE\' | \$MAIL_PATH/\$MAILER -t \$MAILTO";
4169 } else {
4170 die "\nYour mailer: $mailer is not supported.\n";
4171 }
4172 }
4173
4174 $mail_command =~ s/\$MAILER/$mailer/g;
4175 $mail_command =~ s/\$MAIL_PATH/$mail_path/g;
4176 $mail_command =~ s/\$MAILTO/$mailto/g;
4177 $mail_command =~ s/\$SUBJECT/$subject/g;
4178 $mail_command =~ s/\$MESSAGE/$message/g;
4179
4180 run_command $mail_command;
4181}
4182
4183sub send_email {
4184
4185 if (defined($mailto)) {
4186 if (!defined($mailer)) {
4187 doprint "No email sent: email or mailer not specified in config.\n";
4188 return;
4189 }
4190 do_send_mail @_;
4191 }
4192}
4193
4194sub cancel_test {
4195 if ($email_when_canceled) {
4196 send_email("KTEST: Your [$test_type] test was cancelled",
4197 "Your test started at $script_start_time was cancelled: sig int");
4198 }
4199 die "\nCaught Sig Int, test interrupted: $!\n"
4200}
4201
4202$SIG{INT} = qw(cancel_test);
4203
4227# First we need to do is the builds 4204# First we need to do is the builds
4228for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 4205for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4229 4206
@@ -4247,11 +4224,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4247 $outputdir = set_test_option("OUTPUT_DIR", $i); 4224 $outputdir = set_test_option("OUTPUT_DIR", $i);
4248 $builddir = set_test_option("BUILD_DIR", $i); 4225 $builddir = set_test_option("BUILD_DIR", $i);
4249 4226
4250 chdir $builddir || die "can't change directory to $builddir"; 4227 chdir $builddir || dodie "can't change directory to $builddir";
4251 4228
4252 if (!-d $outputdir) { 4229 if (!-d $outputdir) {
4253 mkpath($outputdir) or 4230 mkpath($outputdir) or
4254 die "can't create $outputdir"; 4231 dodie "can't create $outputdir";
4255 } 4232 }
4256 4233
4257 $make = "$makecmd O=$outputdir"; 4234 $make = "$makecmd O=$outputdir";
@@ -4264,9 +4241,15 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4264 $start_minconfig_defined = 1; 4241 $start_minconfig_defined = 1;
4265 4242
4266 # The first test may override the PRE_KTEST option 4243 # The first test may override the PRE_KTEST option
4267 if (defined($pre_ktest) && $i == 1) { 4244 if ($i == 1) {
4268 doprint "\n"; 4245 if (defined($pre_ktest)) {
4269 run_command $pre_ktest; 4246 doprint "\n";
4247 run_command $pre_ktest;
4248 }
4249 if ($email_when_started) {
4250 send_email("KTEST: Your [$test_type] test was started",
4251 "Your test was started on $script_start_time");
4252 }
4270 } 4253 }
4271 4254
4272 # Any test can override the POST_KTEST option 4255 # Any test can override the POST_KTEST option
@@ -4282,7 +4265,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4282 4265
4283 if (!-d $tmpdir) { 4266 if (!-d $tmpdir) {
4284 mkpath($tmpdir) or 4267 mkpath($tmpdir) or
4285 die "can't create $tmpdir"; 4268 dodie "can't create $tmpdir";
4286 } 4269 }
4287 4270
4288 $ENV{"SSH_USER"} = $ssh_user; 4271 $ENV{"SSH_USER"} = $ssh_user;
@@ -4355,7 +4338,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4355 4338
4356 if (defined($checkout)) { 4339 if (defined($checkout)) {
4357 run_command "git checkout $checkout" or 4340 run_command "git checkout $checkout" or
4358 die "failed to checkout $checkout"; 4341 dodie "failed to checkout $checkout";
4359 } 4342 }
4360 4343
4361 $no_reboot = 0; 4344 $no_reboot = 0;
@@ -4430,4 +4413,8 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) {
4430 4413
4431doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 4414doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
4432 4415
4416if ($email_when_finished) {
4417 send_email("KTEST: Your [$test_type] test has finished!",
4418 "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!");
4419}
4433exit 0; 4420exit 0;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 6c58cd8bbbae..6ca6ca0ce695 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -1,6 +1,11 @@
1# 1#
2# Config file for ktest.pl 2# Config file for ktest.pl
3# 3#
4# Place your customized version of this, in the working directory that
5# ktest.pl is run from. By default, ktest.pl will look for a file
6# called "ktest.conf", but you can name it anything you like and specify
7# the name of your config file as the first argument of ktest.pl.
8#
4# Note, all paths must be absolute 9# Note, all paths must be absolute
5# 10#
6 11
@@ -396,6 +401,44 @@
396 401
397#### Optional Config Options (all have defaults) #### 402#### Optional Config Options (all have defaults) ####
398 403
404# Email options for receiving notifications. Users must setup
405# the specified mailer prior to using this feature.
406#
407# (default undefined)
408#MAILTO =
409#
410# Supported mailers: sendmail, mail, mailx
411# (default sendmail)
412#MAILER = sendmail
413#
414# The executable to run
415# (default: for sendmail "/usr/sbin/sendmail", otherwise equals ${MAILER})
416#MAIL_EXEC = /usr/sbin/sendmail
417#
418# The command used to send mail, which uses the above options
419# can be modified. By default if the mailer is "sendmail" then
420# MAIL_COMMAND = echo \'Subject: $SUBJECT\n\n$MESSAGE\' | $MAIL_PATH/$MAILER -t $MAILTO
421# For mail or mailx:
422# MAIL_COMMAND = "$MAIL_PATH/$MAILER -s \'$SUBJECT\' $MAILTO <<< \'$MESSAGE\'
423# ktest.pl will do the substitution for MAIL_PATH, MAILER, MAILTO at the time
424# it sends the mail if "$FOO" format is used. If "${FOO}" format is used,
425# then the substitutions will occur at the time the config file is read.
426# But note, MAIL_PATH and MAILER require being set by the config file if
427# ${MAIL_PATH} or ${MAILER} are used, but not if $MAIL_PATH or $MAILER are.
428#MAIL_COMMAND = echo \'Subject: $SUBJECT\n\n$MESSAGE\' | $MAIL_PATH/$MAILER -t $MAILTO
429#
430# Errors are defined as those would terminate the script
431# (default 1)
432#EMAIL_ON_ERROR = 1
433# (default 1)
434#EMAIL_WHEN_FINISHED = 1
435# (default 0)
436#EMAIL_WHEN_STARTED = 1
437#
438# Users can cancel the test by Ctrl^C
439# (default 0)
440#EMAIL_WHEN_CANCELED = 1
441
399# Start a test setup. If you leave this off, all options 442# Start a test setup. If you leave this off, all options
400# will be default and the test will run once. 443# will be default and the test will run once.
401# This is a label and not really an option (it takes no value). 444# This is a label and not really an option (it takes no value).
@@ -725,6 +768,13 @@
725# (default 120) 768# (default 120)
726#TIMEOUT = 120 769#TIMEOUT = 120
727 770
771# The timeout in seconds when to test if the box can be rebooted
772# or not. Before issuing the reboot command, a ssh connection
773# is attempted to see if the target machine is still active.
774# If the target does not connect within this timeout, a power cycle
775# is issued instead of a reboot.
776# CONNECT_TIMEOUT = 25
777
728# In between tests, a reboot of the box may occur, and this 778# In between tests, a reboot of the box may occur, and this
729# is the time to wait for the console after it stops producing 779# is the time to wait for the console after it stops producing
730# output. Some machines may not produce a large lag on reboot 780# output. Some machines may not produce a large lag on reboot
@@ -1167,6 +1217,16 @@
1167# Set it to "good" to test only the good config and set it 1217# Set it to "good" to test only the good config and set it
1168# to "bad" to only test the bad config. 1218# to "bad" to only test the bad config.
1169# 1219#
1220# CONFIG_BISECT_EXEC (optional)
1221# The config bisect is a separate program that comes with ktest.pl.
1222# By befault, it will look for:
1223# `pwd`/config-bisect.pl # the location ktest.pl was executed from.
1224# If it does not find it there, it will look for:
1225# `dirname <ktest.pl>`/config-bisect.pl # The directory that holds ktest.pl
1226# If it does not find it there, it will look for:
1227# ${BUILD_DIR}/tools/testing/ktest/config-bisect.pl
1228# Setting CONFIG_BISECT_EXEC will override where it looks.
1229#
1170# Example: 1230# Example:
1171# TEST_START 1231# TEST_START
1172# TEST_TYPE = config_bisect 1232# TEST_TYPE = config_bisect
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 620fa78b3b1b..4ea385be528f 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -104,7 +104,8 @@ enum {
104 NUM_HINTS = 8, 104 NUM_HINTS = 8,
105 NUM_BDW = NUM_DCR, 105 NUM_BDW = NUM_DCR,
106 NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW, 106 NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW,
107 NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */ + 4 /* spa1 iset */, 107 NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */
108 + 4 /* spa1 iset */ + 1 /* spa11 iset */,
108 DIMM_SIZE = SZ_32M, 109 DIMM_SIZE = SZ_32M,
109 LABEL_SIZE = SZ_128K, 110 LABEL_SIZE = SZ_128K,
110 SPA_VCD_SIZE = SZ_4M, 111 SPA_VCD_SIZE = SZ_4M,
@@ -137,6 +138,7 @@ static u32 handle[] = {
137}; 138};
138 139
139static unsigned long dimm_fail_cmd_flags[NUM_DCR]; 140static unsigned long dimm_fail_cmd_flags[NUM_DCR];
141static int dimm_fail_cmd_code[NUM_DCR];
140 142
141struct nfit_test_fw { 143struct nfit_test_fw {
142 enum intel_fw_update_state state; 144 enum intel_fw_update_state state;
@@ -153,6 +155,7 @@ struct nfit_test {
153 void *nfit_buf; 155 void *nfit_buf;
154 dma_addr_t nfit_dma; 156 dma_addr_t nfit_dma;
155 size_t nfit_size; 157 size_t nfit_size;
158 size_t nfit_filled;
156 int dcr_idx; 159 int dcr_idx;
157 int num_dcr; 160 int num_dcr;
158 int num_pm; 161 int num_pm;
@@ -709,7 +712,9 @@ static void smart_notify(struct device *bus_dev,
709 >= thresh->media_temperature) 712 >= thresh->media_temperature)
710 || ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP) 713 || ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
711 && smart->ctrl_temperature 714 && smart->ctrl_temperature
712 >= thresh->ctrl_temperature)) { 715 >= thresh->ctrl_temperature)
716 || (smart->health != ND_INTEL_SMART_NON_CRITICAL_HEALTH)
717 || (smart->shutdown_state != 0)) {
713 device_lock(bus_dev); 718 device_lock(bus_dev);
714 __acpi_nvdimm_notify(dimm_dev, 0x81); 719 __acpi_nvdimm_notify(dimm_dev, 0x81);
715 device_unlock(bus_dev); 720 device_unlock(bus_dev);
@@ -735,6 +740,32 @@ static int nfit_test_cmd_smart_set_threshold(
735 return 0; 740 return 0;
736} 741}
737 742
743static int nfit_test_cmd_smart_inject(
744 struct nd_intel_smart_inject *inj,
745 unsigned int buf_len,
746 struct nd_intel_smart_threshold *thresh,
747 struct nd_intel_smart *smart,
748 struct device *bus_dev, struct device *dimm_dev)
749{
750 if (buf_len != sizeof(*inj))
751 return -EINVAL;
752
753 if (inj->mtemp_enable)
754 smart->media_temperature = inj->media_temperature;
755 if (inj->spare_enable)
756 smart->spares = inj->spares;
757 if (inj->fatal_enable)
758 smart->health = ND_INTEL_SMART_FATAL_HEALTH;
759 if (inj->unsafe_shutdown_enable) {
760 smart->shutdown_state = 1;
761 smart->shutdown_count++;
762 }
763 inj->status = 0;
764 smart_notify(bus_dev, dimm_dev, smart, thresh);
765
766 return 0;
767}
768
738static void uc_error_notify(struct work_struct *work) 769static void uc_error_notify(struct work_struct *work)
739{ 770{
740 struct nfit_test *t = container_of(work, typeof(*t), work); 771 struct nfit_test *t = container_of(work, typeof(*t), work);
@@ -862,8 +893,11 @@ static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
862 if (i >= ARRAY_SIZE(handle)) 893 if (i >= ARRAY_SIZE(handle))
863 return -ENXIO; 894 return -ENXIO;
864 895
865 if ((1 << func) & dimm_fail_cmd_flags[i]) 896 if ((1 << func) & dimm_fail_cmd_flags[i]) {
897 if (dimm_fail_cmd_code[i])
898 return dimm_fail_cmd_code[i];
866 return -EIO; 899 return -EIO;
900 }
867 901
868 return i; 902 return i;
869} 903}
@@ -935,6 +969,13 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
935 t->dcr_idx], 969 t->dcr_idx],
936 &t->smart[i - t->dcr_idx], 970 &t->smart[i - t->dcr_idx],
937 &t->pdev.dev, t->dimm_dev[i]); 971 &t->pdev.dev, t->dimm_dev[i]);
972 case ND_INTEL_SMART_INJECT:
973 return nfit_test_cmd_smart_inject(buf,
974 buf_len,
975 &t->smart_threshold[i -
976 t->dcr_idx],
977 &t->smart[i - t->dcr_idx],
978 &t->pdev.dev, t->dimm_dev[i]);
938 default: 979 default:
939 return -ENOTTY; 980 return -ENOTTY;
940 } 981 }
@@ -1125,12 +1166,12 @@ static int ars_state_init(struct device *dev, struct ars_state *ars_state)
1125 1166
1126static void put_dimms(void *data) 1167static void put_dimms(void *data)
1127{ 1168{
1128 struct device **dimm_dev = data; 1169 struct nfit_test *t = data;
1129 int i; 1170 int i;
1130 1171
1131 for (i = 0; i < NUM_DCR; i++) 1172 for (i = 0; i < t->num_dcr; i++)
1132 if (dimm_dev[i]) 1173 if (t->dimm_dev[i])
1133 device_unregister(dimm_dev[i]); 1174 device_unregister(t->dimm_dev[i]);
1134} 1175}
1135 1176
1136static struct class *nfit_test_dimm; 1177static struct class *nfit_test_dimm;
@@ -1139,13 +1180,11 @@ static int dimm_name_to_id(struct device *dev)
1139{ 1180{
1140 int dimm; 1181 int dimm;
1141 1182
1142 if (sscanf(dev_name(dev), "test_dimm%d", &dimm) != 1 1183 if (sscanf(dev_name(dev), "test_dimm%d", &dimm) != 1)
1143 || dimm >= NUM_DCR || dimm < 0)
1144 return -ENXIO; 1184 return -ENXIO;
1145 return dimm; 1185 return dimm;
1146} 1186}
1147 1187
1148
1149static ssize_t handle_show(struct device *dev, struct device_attribute *attr, 1188static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
1150 char *buf) 1189 char *buf)
1151{ 1190{
@@ -1154,7 +1193,7 @@ static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
1154 if (dimm < 0) 1193 if (dimm < 0)
1155 return dimm; 1194 return dimm;
1156 1195
1157 return sprintf(buf, "%#x", handle[dimm]); 1196 return sprintf(buf, "%#x\n", handle[dimm]);
1158} 1197}
1159DEVICE_ATTR_RO(handle); 1198DEVICE_ATTR_RO(handle);
1160 1199
@@ -1188,8 +1227,39 @@ static ssize_t fail_cmd_store(struct device *dev, struct device_attribute *attr,
1188} 1227}
1189static DEVICE_ATTR_RW(fail_cmd); 1228static DEVICE_ATTR_RW(fail_cmd);
1190 1229
1230static ssize_t fail_cmd_code_show(struct device *dev, struct device_attribute *attr,
1231 char *buf)
1232{
1233 int dimm = dimm_name_to_id(dev);
1234
1235 if (dimm < 0)
1236 return dimm;
1237
1238 return sprintf(buf, "%d\n", dimm_fail_cmd_code[dimm]);
1239}
1240
1241static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *attr,
1242 const char *buf, size_t size)
1243{
1244 int dimm = dimm_name_to_id(dev);
1245 unsigned long val;
1246 ssize_t rc;
1247
1248 if (dimm < 0)
1249 return dimm;
1250
1251 rc = kstrtol(buf, 0, &val);
1252 if (rc)
1253 return rc;
1254
1255 dimm_fail_cmd_code[dimm] = val;
1256 return size;
1257}
1258static DEVICE_ATTR_RW(fail_cmd_code);
1259
1191static struct attribute *nfit_test_dimm_attributes[] = { 1260static struct attribute *nfit_test_dimm_attributes[] = {
1192 &dev_attr_fail_cmd.attr, 1261 &dev_attr_fail_cmd.attr,
1262 &dev_attr_fail_cmd_code.attr,
1193 &dev_attr_handle.attr, 1263 &dev_attr_handle.attr,
1194 NULL, 1264 NULL,
1195}; 1265};
@@ -1203,6 +1273,23 @@ static const struct attribute_group *nfit_test_dimm_attribute_groups[] = {
1203 NULL, 1273 NULL,
1204}; 1274};
1205 1275
1276static int nfit_test_dimm_init(struct nfit_test *t)
1277{
1278 int i;
1279
1280 if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t))
1281 return -ENOMEM;
1282 for (i = 0; i < t->num_dcr; i++) {
1283 t->dimm_dev[i] = device_create_with_groups(nfit_test_dimm,
1284 &t->pdev.dev, 0, NULL,
1285 nfit_test_dimm_attribute_groups,
1286 "test_dimm%d", i + t->dcr_idx);
1287 if (!t->dimm_dev[i])
1288 return -ENOMEM;
1289 }
1290 return 0;
1291}
1292
1206static void smart_init(struct nfit_test *t) 1293static void smart_init(struct nfit_test *t)
1207{ 1294{
1208 int i; 1295 int i;
@@ -1222,7 +1309,7 @@ static void smart_init(struct nfit_test *t)
1222 | ND_INTEL_SMART_MTEMP_VALID, 1309 | ND_INTEL_SMART_MTEMP_VALID,
1223 .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH, 1310 .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
1224 .media_temperature = 23 * 16, 1311 .media_temperature = 23 * 16,
1225 .ctrl_temperature = 30 * 16, 1312 .ctrl_temperature = 25 * 16,
1226 .pmic_temperature = 40 * 16, 1313 .pmic_temperature = 40 * 16,
1227 .spares = 75, 1314 .spares = 75,
1228 .alarm_flags = ND_INTEL_SMART_SPARE_TRIP 1315 .alarm_flags = ND_INTEL_SMART_SPARE_TRIP
@@ -1298,17 +1385,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
1298 if (!t->_fit) 1385 if (!t->_fit)
1299 return -ENOMEM; 1386 return -ENOMEM;
1300 1387
1301 if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t->dimm_dev)) 1388 if (nfit_test_dimm_init(t))
1302 return -ENOMEM; 1389 return -ENOMEM;
1303 for (i = 0; i < NUM_DCR; i++) {
1304 t->dimm_dev[i] = device_create_with_groups(nfit_test_dimm,
1305 &t->pdev.dev, 0, NULL,
1306 nfit_test_dimm_attribute_groups,
1307 "test_dimm%d", i);
1308 if (!t->dimm_dev[i])
1309 return -ENOMEM;
1310 }
1311
1312 smart_init(t); 1390 smart_init(t);
1313 return ars_state_init(&t->pdev.dev, &t->ars_state); 1391 return ars_state_init(&t->pdev.dev, &t->ars_state);
1314} 1392}
@@ -1340,6 +1418,8 @@ static int nfit_test1_alloc(struct nfit_test *t)
1340 if (!t->spa_set[1]) 1418 if (!t->spa_set[1])
1341 return -ENOMEM; 1419 return -ENOMEM;
1342 1420
1421 if (nfit_test_dimm_init(t))
1422 return -ENOMEM;
1343 smart_init(t); 1423 smart_init(t);
1344 return ars_state_init(&t->pdev.dev, &t->ars_state); 1424 return ars_state_init(&t->pdev.dev, &t->ars_state);
1345} 1425}
@@ -1366,7 +1446,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1366 struct acpi_nfit_data_region *bdw; 1446 struct acpi_nfit_data_region *bdw;
1367 struct acpi_nfit_flush_address *flush; 1447 struct acpi_nfit_flush_address *flush;
1368 struct acpi_nfit_capabilities *pcap; 1448 struct acpi_nfit_capabilities *pcap;
1369 unsigned int offset, i; 1449 unsigned int offset = 0, i;
1370 1450
1371 /* 1451 /*
1372 * spa0 (interleave first half of dimm0 and dimm1, note storage 1452 * spa0 (interleave first half of dimm0 and dimm1, note storage
@@ -1380,93 +1460,102 @@ static void nfit_test0_setup(struct nfit_test *t)
1380 spa->range_index = 0+1; 1460 spa->range_index = 0+1;
1381 spa->address = t->spa_set_dma[0]; 1461 spa->address = t->spa_set_dma[0];
1382 spa->length = SPA0_SIZE; 1462 spa->length = SPA0_SIZE;
1463 offset += spa->header.length;
1383 1464
1384 /* 1465 /*
1385 * spa1 (interleave last half of the 4 DIMMS, note storage 1466 * spa1 (interleave last half of the 4 DIMMS, note storage
1386 * does not actually alias the related block-data-window 1467 * does not actually alias the related block-data-window
1387 * regions) 1468 * regions)
1388 */ 1469 */
1389 spa = nfit_buf + sizeof(*spa); 1470 spa = nfit_buf + offset;
1390 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1471 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1391 spa->header.length = sizeof(*spa); 1472 spa->header.length = sizeof(*spa);
1392 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16); 1473 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
1393 spa->range_index = 1+1; 1474 spa->range_index = 1+1;
1394 spa->address = t->spa_set_dma[1]; 1475 spa->address = t->spa_set_dma[1];
1395 spa->length = SPA1_SIZE; 1476 spa->length = SPA1_SIZE;
1477 offset += spa->header.length;
1396 1478
1397 /* spa2 (dcr0) dimm0 */ 1479 /* spa2 (dcr0) dimm0 */
1398 spa = nfit_buf + sizeof(*spa) * 2; 1480 spa = nfit_buf + offset;
1399 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1481 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1400 spa->header.length = sizeof(*spa); 1482 spa->header.length = sizeof(*spa);
1401 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); 1483 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
1402 spa->range_index = 2+1; 1484 spa->range_index = 2+1;
1403 spa->address = t->dcr_dma[0]; 1485 spa->address = t->dcr_dma[0];
1404 spa->length = DCR_SIZE; 1486 spa->length = DCR_SIZE;
1487 offset += spa->header.length;
1405 1488
1406 /* spa3 (dcr1) dimm1 */ 1489 /* spa3 (dcr1) dimm1 */
1407 spa = nfit_buf + sizeof(*spa) * 3; 1490 spa = nfit_buf + offset;
1408 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1491 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1409 spa->header.length = sizeof(*spa); 1492 spa->header.length = sizeof(*spa);
1410 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); 1493 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
1411 spa->range_index = 3+1; 1494 spa->range_index = 3+1;
1412 spa->address = t->dcr_dma[1]; 1495 spa->address = t->dcr_dma[1];
1413 spa->length = DCR_SIZE; 1496 spa->length = DCR_SIZE;
1497 offset += spa->header.length;
1414 1498
1415 /* spa4 (dcr2) dimm2 */ 1499 /* spa4 (dcr2) dimm2 */
1416 spa = nfit_buf + sizeof(*spa) * 4; 1500 spa = nfit_buf + offset;
1417 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1501 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1418 spa->header.length = sizeof(*spa); 1502 spa->header.length = sizeof(*spa);
1419 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); 1503 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
1420 spa->range_index = 4+1; 1504 spa->range_index = 4+1;
1421 spa->address = t->dcr_dma[2]; 1505 spa->address = t->dcr_dma[2];
1422 spa->length = DCR_SIZE; 1506 spa->length = DCR_SIZE;
1507 offset += spa->header.length;
1423 1508
1424 /* spa5 (dcr3) dimm3 */ 1509 /* spa5 (dcr3) dimm3 */
1425 spa = nfit_buf + sizeof(*spa) * 5; 1510 spa = nfit_buf + offset;
1426 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1511 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1427 spa->header.length = sizeof(*spa); 1512 spa->header.length = sizeof(*spa);
1428 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); 1513 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
1429 spa->range_index = 5+1; 1514 spa->range_index = 5+1;
1430 spa->address = t->dcr_dma[3]; 1515 spa->address = t->dcr_dma[3];
1431 spa->length = DCR_SIZE; 1516 spa->length = DCR_SIZE;
1517 offset += spa->header.length;
1432 1518
1433 /* spa6 (bdw for dcr0) dimm0 */ 1519 /* spa6 (bdw for dcr0) dimm0 */
1434 spa = nfit_buf + sizeof(*spa) * 6; 1520 spa = nfit_buf + offset;
1435 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1521 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1436 spa->header.length = sizeof(*spa); 1522 spa->header.length = sizeof(*spa);
1437 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); 1523 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
1438 spa->range_index = 6+1; 1524 spa->range_index = 6+1;
1439 spa->address = t->dimm_dma[0]; 1525 spa->address = t->dimm_dma[0];
1440 spa->length = DIMM_SIZE; 1526 spa->length = DIMM_SIZE;
1527 offset += spa->header.length;
1441 1528
1442 /* spa7 (bdw for dcr1) dimm1 */ 1529 /* spa7 (bdw for dcr1) dimm1 */
1443 spa = nfit_buf + sizeof(*spa) * 7; 1530 spa = nfit_buf + offset;
1444 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1531 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1445 spa->header.length = sizeof(*spa); 1532 spa->header.length = sizeof(*spa);
1446 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); 1533 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
1447 spa->range_index = 7+1; 1534 spa->range_index = 7+1;
1448 spa->address = t->dimm_dma[1]; 1535 spa->address = t->dimm_dma[1];
1449 spa->length = DIMM_SIZE; 1536 spa->length = DIMM_SIZE;
1537 offset += spa->header.length;
1450 1538
1451 /* spa8 (bdw for dcr2) dimm2 */ 1539 /* spa8 (bdw for dcr2) dimm2 */
1452 spa = nfit_buf + sizeof(*spa) * 8; 1540 spa = nfit_buf + offset;
1453 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1541 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1454 spa->header.length = sizeof(*spa); 1542 spa->header.length = sizeof(*spa);
1455 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); 1543 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
1456 spa->range_index = 8+1; 1544 spa->range_index = 8+1;
1457 spa->address = t->dimm_dma[2]; 1545 spa->address = t->dimm_dma[2];
1458 spa->length = DIMM_SIZE; 1546 spa->length = DIMM_SIZE;
1547 offset += spa->header.length;
1459 1548
1460 /* spa9 (bdw for dcr3) dimm3 */ 1549 /* spa9 (bdw for dcr3) dimm3 */
1461 spa = nfit_buf + sizeof(*spa) * 9; 1550 spa = nfit_buf + offset;
1462 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 1551 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1463 spa->header.length = sizeof(*spa); 1552 spa->header.length = sizeof(*spa);
1464 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); 1553 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
1465 spa->range_index = 9+1; 1554 spa->range_index = 9+1;
1466 spa->address = t->dimm_dma[3]; 1555 spa->address = t->dimm_dma[3];
1467 spa->length = DIMM_SIZE; 1556 spa->length = DIMM_SIZE;
1557 offset += spa->header.length;
1468 1558
1469 offset = sizeof(*spa) * 10;
1470 /* mem-region0 (spa0, dimm0) */ 1559 /* mem-region0 (spa0, dimm0) */
1471 memdev = nfit_buf + offset; 1560 memdev = nfit_buf + offset;
1472 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1561 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
@@ -1481,9 +1570,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1481 memdev->address = 0; 1570 memdev->address = 0;
1482 memdev->interleave_index = 0; 1571 memdev->interleave_index = 0;
1483 memdev->interleave_ways = 2; 1572 memdev->interleave_ways = 2;
1573 offset += memdev->header.length;
1484 1574
1485 /* mem-region1 (spa0, dimm1) */ 1575 /* mem-region1 (spa0, dimm1) */
1486 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map); 1576 memdev = nfit_buf + offset;
1487 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1577 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1488 memdev->header.length = sizeof(*memdev); 1578 memdev->header.length = sizeof(*memdev);
1489 memdev->device_handle = handle[1]; 1579 memdev->device_handle = handle[1];
@@ -1497,9 +1587,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1497 memdev->interleave_index = 0; 1587 memdev->interleave_index = 0;
1498 memdev->interleave_ways = 2; 1588 memdev->interleave_ways = 2;
1499 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED; 1589 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED;
1590 offset += memdev->header.length;
1500 1591
1501 /* mem-region2 (spa1, dimm0) */ 1592 /* mem-region2 (spa1, dimm0) */
1502 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 2; 1593 memdev = nfit_buf + offset;
1503 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1594 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1504 memdev->header.length = sizeof(*memdev); 1595 memdev->header.length = sizeof(*memdev);
1505 memdev->device_handle = handle[0]; 1596 memdev->device_handle = handle[0];
@@ -1513,9 +1604,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1513 memdev->interleave_index = 0; 1604 memdev->interleave_index = 0;
1514 memdev->interleave_ways = 4; 1605 memdev->interleave_ways = 4;
1515 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED; 1606 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED;
1607 offset += memdev->header.length;
1516 1608
1517 /* mem-region3 (spa1, dimm1) */ 1609 /* mem-region3 (spa1, dimm1) */
1518 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 3; 1610 memdev = nfit_buf + offset;
1519 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1611 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1520 memdev->header.length = sizeof(*memdev); 1612 memdev->header.length = sizeof(*memdev);
1521 memdev->device_handle = handle[1]; 1613 memdev->device_handle = handle[1];
@@ -1528,9 +1620,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1528 memdev->address = SPA0_SIZE/2; 1620 memdev->address = SPA0_SIZE/2;
1529 memdev->interleave_index = 0; 1621 memdev->interleave_index = 0;
1530 memdev->interleave_ways = 4; 1622 memdev->interleave_ways = 4;
1623 offset += memdev->header.length;
1531 1624
1532 /* mem-region4 (spa1, dimm2) */ 1625 /* mem-region4 (spa1, dimm2) */
1533 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 4; 1626 memdev = nfit_buf + offset;
1534 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1627 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1535 memdev->header.length = sizeof(*memdev); 1628 memdev->header.length = sizeof(*memdev);
1536 memdev->device_handle = handle[2]; 1629 memdev->device_handle = handle[2];
@@ -1544,9 +1637,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1544 memdev->interleave_index = 0; 1637 memdev->interleave_index = 0;
1545 memdev->interleave_ways = 4; 1638 memdev->interleave_ways = 4;
1546 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED; 1639 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED;
1640 offset += memdev->header.length;
1547 1641
1548 /* mem-region5 (spa1, dimm3) */ 1642 /* mem-region5 (spa1, dimm3) */
1549 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 5; 1643 memdev = nfit_buf + offset;
1550 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1644 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1551 memdev->header.length = sizeof(*memdev); 1645 memdev->header.length = sizeof(*memdev);
1552 memdev->device_handle = handle[3]; 1646 memdev->device_handle = handle[3];
@@ -1559,9 +1653,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1559 memdev->address = SPA0_SIZE/2; 1653 memdev->address = SPA0_SIZE/2;
1560 memdev->interleave_index = 0; 1654 memdev->interleave_index = 0;
1561 memdev->interleave_ways = 4; 1655 memdev->interleave_ways = 4;
1656 offset += memdev->header.length;
1562 1657
1563 /* mem-region6 (spa/dcr0, dimm0) */ 1658 /* mem-region6 (spa/dcr0, dimm0) */
1564 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 6; 1659 memdev = nfit_buf + offset;
1565 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1660 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1566 memdev->header.length = sizeof(*memdev); 1661 memdev->header.length = sizeof(*memdev);
1567 memdev->device_handle = handle[0]; 1662 memdev->device_handle = handle[0];
@@ -1574,9 +1669,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1574 memdev->address = 0; 1669 memdev->address = 0;
1575 memdev->interleave_index = 0; 1670 memdev->interleave_index = 0;
1576 memdev->interleave_ways = 1; 1671 memdev->interleave_ways = 1;
1672 offset += memdev->header.length;
1577 1673
1578 /* mem-region7 (spa/dcr1, dimm1) */ 1674 /* mem-region7 (spa/dcr1, dimm1) */
1579 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 7; 1675 memdev = nfit_buf + offset;
1580 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1676 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1581 memdev->header.length = sizeof(*memdev); 1677 memdev->header.length = sizeof(*memdev);
1582 memdev->device_handle = handle[1]; 1678 memdev->device_handle = handle[1];
@@ -1589,9 +1685,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1589 memdev->address = 0; 1685 memdev->address = 0;
1590 memdev->interleave_index = 0; 1686 memdev->interleave_index = 0;
1591 memdev->interleave_ways = 1; 1687 memdev->interleave_ways = 1;
1688 offset += memdev->header.length;
1592 1689
1593 /* mem-region8 (spa/dcr2, dimm2) */ 1690 /* mem-region8 (spa/dcr2, dimm2) */
1594 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 8; 1691 memdev = nfit_buf + offset;
1595 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1692 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1596 memdev->header.length = sizeof(*memdev); 1693 memdev->header.length = sizeof(*memdev);
1597 memdev->device_handle = handle[2]; 1694 memdev->device_handle = handle[2];
@@ -1604,9 +1701,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1604 memdev->address = 0; 1701 memdev->address = 0;
1605 memdev->interleave_index = 0; 1702 memdev->interleave_index = 0;
1606 memdev->interleave_ways = 1; 1703 memdev->interleave_ways = 1;
1704 offset += memdev->header.length;
1607 1705
1608 /* mem-region9 (spa/dcr3, dimm3) */ 1706 /* mem-region9 (spa/dcr3, dimm3) */
1609 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 9; 1707 memdev = nfit_buf + offset;
1610 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1708 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1611 memdev->header.length = sizeof(*memdev); 1709 memdev->header.length = sizeof(*memdev);
1612 memdev->device_handle = handle[3]; 1710 memdev->device_handle = handle[3];
@@ -1619,9 +1717,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1619 memdev->address = 0; 1717 memdev->address = 0;
1620 memdev->interleave_index = 0; 1718 memdev->interleave_index = 0;
1621 memdev->interleave_ways = 1; 1719 memdev->interleave_ways = 1;
1720 offset += memdev->header.length;
1622 1721
1623 /* mem-region10 (spa/bdw0, dimm0) */ 1722 /* mem-region10 (spa/bdw0, dimm0) */
1624 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 10; 1723 memdev = nfit_buf + offset;
1625 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1724 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1626 memdev->header.length = sizeof(*memdev); 1725 memdev->header.length = sizeof(*memdev);
1627 memdev->device_handle = handle[0]; 1726 memdev->device_handle = handle[0];
@@ -1634,9 +1733,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1634 memdev->address = 0; 1733 memdev->address = 0;
1635 memdev->interleave_index = 0; 1734 memdev->interleave_index = 0;
1636 memdev->interleave_ways = 1; 1735 memdev->interleave_ways = 1;
1736 offset += memdev->header.length;
1637 1737
1638 /* mem-region11 (spa/bdw1, dimm1) */ 1738 /* mem-region11 (spa/bdw1, dimm1) */
1639 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 11; 1739 memdev = nfit_buf + offset;
1640 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1740 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1641 memdev->header.length = sizeof(*memdev); 1741 memdev->header.length = sizeof(*memdev);
1642 memdev->device_handle = handle[1]; 1742 memdev->device_handle = handle[1];
@@ -1649,9 +1749,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1649 memdev->address = 0; 1749 memdev->address = 0;
1650 memdev->interleave_index = 0; 1750 memdev->interleave_index = 0;
1651 memdev->interleave_ways = 1; 1751 memdev->interleave_ways = 1;
1752 offset += memdev->header.length;
1652 1753
1653 /* mem-region12 (spa/bdw2, dimm2) */ 1754 /* mem-region12 (spa/bdw2, dimm2) */
1654 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 12; 1755 memdev = nfit_buf + offset;
1655 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1756 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1656 memdev->header.length = sizeof(*memdev); 1757 memdev->header.length = sizeof(*memdev);
1657 memdev->device_handle = handle[2]; 1758 memdev->device_handle = handle[2];
@@ -1664,9 +1765,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1664 memdev->address = 0; 1765 memdev->address = 0;
1665 memdev->interleave_index = 0; 1766 memdev->interleave_index = 0;
1666 memdev->interleave_ways = 1; 1767 memdev->interleave_ways = 1;
1768 offset += memdev->header.length;
1667 1769
1668 /* mem-region13 (spa/dcr3, dimm3) */ 1770 /* mem-region13 (spa/dcr3, dimm3) */
1669 memdev = nfit_buf + offset + sizeof(struct acpi_nfit_memory_map) * 13; 1771 memdev = nfit_buf + offset;
1670 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1772 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1671 memdev->header.length = sizeof(*memdev); 1773 memdev->header.length = sizeof(*memdev);
1672 memdev->device_handle = handle[3]; 1774 memdev->device_handle = handle[3];
@@ -1680,12 +1782,12 @@ static void nfit_test0_setup(struct nfit_test *t)
1680 memdev->interleave_index = 0; 1782 memdev->interleave_index = 0;
1681 memdev->interleave_ways = 1; 1783 memdev->interleave_ways = 1;
1682 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED; 1784 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED;
1785 offset += memdev->header.length;
1683 1786
1684 offset = offset + sizeof(struct acpi_nfit_memory_map) * 14;
1685 /* dcr-descriptor0: blk */ 1787 /* dcr-descriptor0: blk */
1686 dcr = nfit_buf + offset; 1788 dcr = nfit_buf + offset;
1687 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1789 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1688 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1790 dcr->header.length = sizeof(*dcr);
1689 dcr->region_index = 0+1; 1791 dcr->region_index = 0+1;
1690 dcr_common_init(dcr); 1792 dcr_common_init(dcr);
1691 dcr->serial_number = ~handle[0]; 1793 dcr->serial_number = ~handle[0];
@@ -1696,11 +1798,12 @@ static void nfit_test0_setup(struct nfit_test *t)
1696 dcr->command_size = 8; 1798 dcr->command_size = 8;
1697 dcr->status_offset = 8; 1799 dcr->status_offset = 8;
1698 dcr->status_size = 4; 1800 dcr->status_size = 4;
1801 offset += dcr->header.length;
1699 1802
1700 /* dcr-descriptor1: blk */ 1803 /* dcr-descriptor1: blk */
1701 dcr = nfit_buf + offset + sizeof(struct acpi_nfit_control_region); 1804 dcr = nfit_buf + offset;
1702 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1805 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1703 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1806 dcr->header.length = sizeof(*dcr);
1704 dcr->region_index = 1+1; 1807 dcr->region_index = 1+1;
1705 dcr_common_init(dcr); 1808 dcr_common_init(dcr);
1706 dcr->serial_number = ~handle[1]; 1809 dcr->serial_number = ~handle[1];
@@ -1711,11 +1814,12 @@ static void nfit_test0_setup(struct nfit_test *t)
1711 dcr->command_size = 8; 1814 dcr->command_size = 8;
1712 dcr->status_offset = 8; 1815 dcr->status_offset = 8;
1713 dcr->status_size = 4; 1816 dcr->status_size = 4;
1817 offset += dcr->header.length;
1714 1818
1715 /* dcr-descriptor2: blk */ 1819 /* dcr-descriptor2: blk */
1716 dcr = nfit_buf + offset + sizeof(struct acpi_nfit_control_region) * 2; 1820 dcr = nfit_buf + offset;
1717 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1821 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1718 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1822 dcr->header.length = sizeof(*dcr);
1719 dcr->region_index = 2+1; 1823 dcr->region_index = 2+1;
1720 dcr_common_init(dcr); 1824 dcr_common_init(dcr);
1721 dcr->serial_number = ~handle[2]; 1825 dcr->serial_number = ~handle[2];
@@ -1726,11 +1830,12 @@ static void nfit_test0_setup(struct nfit_test *t)
1726 dcr->command_size = 8; 1830 dcr->command_size = 8;
1727 dcr->status_offset = 8; 1831 dcr->status_offset = 8;
1728 dcr->status_size = 4; 1832 dcr->status_size = 4;
1833 offset += dcr->header.length;
1729 1834
1730 /* dcr-descriptor3: blk */ 1835 /* dcr-descriptor3: blk */
1731 dcr = nfit_buf + offset + sizeof(struct acpi_nfit_control_region) * 3; 1836 dcr = nfit_buf + offset;
1732 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1837 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1733 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1838 dcr->header.length = sizeof(*dcr);
1734 dcr->region_index = 3+1; 1839 dcr->region_index = 3+1;
1735 dcr_common_init(dcr); 1840 dcr_common_init(dcr);
1736 dcr->serial_number = ~handle[3]; 1841 dcr->serial_number = ~handle[3];
@@ -1741,8 +1846,8 @@ static void nfit_test0_setup(struct nfit_test *t)
1741 dcr->command_size = 8; 1846 dcr->command_size = 8;
1742 dcr->status_offset = 8; 1847 dcr->status_offset = 8;
1743 dcr->status_size = 4; 1848 dcr->status_size = 4;
1849 offset += dcr->header.length;
1744 1850
1745 offset = offset + sizeof(struct acpi_nfit_control_region) * 4;
1746 /* dcr-descriptor0: pmem */ 1851 /* dcr-descriptor0: pmem */
1747 dcr = nfit_buf + offset; 1852 dcr = nfit_buf + offset;
1748 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1853 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
@@ -1753,10 +1858,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1753 dcr->serial_number = ~handle[0]; 1858 dcr->serial_number = ~handle[0];
1754 dcr->code = NFIT_FIC_BYTEN; 1859 dcr->code = NFIT_FIC_BYTEN;
1755 dcr->windows = 0; 1860 dcr->windows = 0;
1861 offset += dcr->header.length;
1756 1862
1757 /* dcr-descriptor1: pmem */ 1863 /* dcr-descriptor1: pmem */
1758 dcr = nfit_buf + offset + offsetof(struct acpi_nfit_control_region, 1864 dcr = nfit_buf + offset;
1759 window_size);
1760 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1865 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1761 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1866 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1762 window_size); 1867 window_size);
@@ -1765,10 +1870,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1765 dcr->serial_number = ~handle[1]; 1870 dcr->serial_number = ~handle[1];
1766 dcr->code = NFIT_FIC_BYTEN; 1871 dcr->code = NFIT_FIC_BYTEN;
1767 dcr->windows = 0; 1872 dcr->windows = 0;
1873 offset += dcr->header.length;
1768 1874
1769 /* dcr-descriptor2: pmem */ 1875 /* dcr-descriptor2: pmem */
1770 dcr = nfit_buf + offset + offsetof(struct acpi_nfit_control_region, 1876 dcr = nfit_buf + offset;
1771 window_size) * 2;
1772 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1877 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1773 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1878 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1774 window_size); 1879 window_size);
@@ -1777,10 +1882,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1777 dcr->serial_number = ~handle[2]; 1882 dcr->serial_number = ~handle[2];
1778 dcr->code = NFIT_FIC_BYTEN; 1883 dcr->code = NFIT_FIC_BYTEN;
1779 dcr->windows = 0; 1884 dcr->windows = 0;
1885 offset += dcr->header.length;
1780 1886
1781 /* dcr-descriptor3: pmem */ 1887 /* dcr-descriptor3: pmem */
1782 dcr = nfit_buf + offset + offsetof(struct acpi_nfit_control_region, 1888 dcr = nfit_buf + offset;
1783 window_size) * 3;
1784 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1889 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1785 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1890 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1786 window_size); 1891 window_size);
@@ -1789,54 +1894,56 @@ static void nfit_test0_setup(struct nfit_test *t)
1789 dcr->serial_number = ~handle[3]; 1894 dcr->serial_number = ~handle[3];
1790 dcr->code = NFIT_FIC_BYTEN; 1895 dcr->code = NFIT_FIC_BYTEN;
1791 dcr->windows = 0; 1896 dcr->windows = 0;
1897 offset += dcr->header.length;
1792 1898
1793 offset = offset + offsetof(struct acpi_nfit_control_region,
1794 window_size) * 4;
1795 /* bdw0 (spa/dcr0, dimm0) */ 1899 /* bdw0 (spa/dcr0, dimm0) */
1796 bdw = nfit_buf + offset; 1900 bdw = nfit_buf + offset;
1797 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION; 1901 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION;
1798 bdw->header.length = sizeof(struct acpi_nfit_data_region); 1902 bdw->header.length = sizeof(*bdw);
1799 bdw->region_index = 0+1; 1903 bdw->region_index = 0+1;
1800 bdw->windows = 1; 1904 bdw->windows = 1;
1801 bdw->offset = 0; 1905 bdw->offset = 0;
1802 bdw->size = BDW_SIZE; 1906 bdw->size = BDW_SIZE;
1803 bdw->capacity = DIMM_SIZE; 1907 bdw->capacity = DIMM_SIZE;
1804 bdw->start_address = 0; 1908 bdw->start_address = 0;
1909 offset += bdw->header.length;
1805 1910
1806 /* bdw1 (spa/dcr1, dimm1) */ 1911 /* bdw1 (spa/dcr1, dimm1) */
1807 bdw = nfit_buf + offset + sizeof(struct acpi_nfit_data_region); 1912 bdw = nfit_buf + offset;
1808 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION; 1913 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION;
1809 bdw->header.length = sizeof(struct acpi_nfit_data_region); 1914 bdw->header.length = sizeof(*bdw);
1810 bdw->region_index = 1+1; 1915 bdw->region_index = 1+1;
1811 bdw->windows = 1; 1916 bdw->windows = 1;
1812 bdw->offset = 0; 1917 bdw->offset = 0;
1813 bdw->size = BDW_SIZE; 1918 bdw->size = BDW_SIZE;
1814 bdw->capacity = DIMM_SIZE; 1919 bdw->capacity = DIMM_SIZE;
1815 bdw->start_address = 0; 1920 bdw->start_address = 0;
1921 offset += bdw->header.length;
1816 1922
1817 /* bdw2 (spa/dcr2, dimm2) */ 1923 /* bdw2 (spa/dcr2, dimm2) */
1818 bdw = nfit_buf + offset + sizeof(struct acpi_nfit_data_region) * 2; 1924 bdw = nfit_buf + offset;
1819 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION; 1925 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION;
1820 bdw->header.length = sizeof(struct acpi_nfit_data_region); 1926 bdw->header.length = sizeof(*bdw);
1821 bdw->region_index = 2+1; 1927 bdw->region_index = 2+1;
1822 bdw->windows = 1; 1928 bdw->windows = 1;
1823 bdw->offset = 0; 1929 bdw->offset = 0;
1824 bdw->size = BDW_SIZE; 1930 bdw->size = BDW_SIZE;
1825 bdw->capacity = DIMM_SIZE; 1931 bdw->capacity = DIMM_SIZE;
1826 bdw->start_address = 0; 1932 bdw->start_address = 0;
1933 offset += bdw->header.length;
1827 1934
1828 /* bdw3 (spa/dcr3, dimm3) */ 1935 /* bdw3 (spa/dcr3, dimm3) */
1829 bdw = nfit_buf + offset + sizeof(struct acpi_nfit_data_region) * 3; 1936 bdw = nfit_buf + offset;
1830 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION; 1937 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION;
1831 bdw->header.length = sizeof(struct acpi_nfit_data_region); 1938 bdw->header.length = sizeof(*bdw);
1832 bdw->region_index = 3+1; 1939 bdw->region_index = 3+1;
1833 bdw->windows = 1; 1940 bdw->windows = 1;
1834 bdw->offset = 0; 1941 bdw->offset = 0;
1835 bdw->size = BDW_SIZE; 1942 bdw->size = BDW_SIZE;
1836 bdw->capacity = DIMM_SIZE; 1943 bdw->capacity = DIMM_SIZE;
1837 bdw->start_address = 0; 1944 bdw->start_address = 0;
1945 offset += bdw->header.length;
1838 1946
1839 offset = offset + sizeof(struct acpi_nfit_data_region) * 4;
1840 /* flush0 (dimm0) */ 1947 /* flush0 (dimm0) */
1841 flush = nfit_buf + offset; 1948 flush = nfit_buf + offset;
1842 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1949 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
@@ -1845,48 +1952,52 @@ static void nfit_test0_setup(struct nfit_test *t)
1845 flush->hint_count = NUM_HINTS; 1952 flush->hint_count = NUM_HINTS;
1846 for (i = 0; i < NUM_HINTS; i++) 1953 for (i = 0; i < NUM_HINTS; i++)
1847 flush->hint_address[i] = t->flush_dma[0] + i * sizeof(u64); 1954 flush->hint_address[i] = t->flush_dma[0] + i * sizeof(u64);
1955 offset += flush->header.length;
1848 1956
1849 /* flush1 (dimm1) */ 1957 /* flush1 (dimm1) */
1850 flush = nfit_buf + offset + flush_hint_size * 1; 1958 flush = nfit_buf + offset;
1851 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1959 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1852 flush->header.length = flush_hint_size; 1960 flush->header.length = flush_hint_size;
1853 flush->device_handle = handle[1]; 1961 flush->device_handle = handle[1];
1854 flush->hint_count = NUM_HINTS; 1962 flush->hint_count = NUM_HINTS;
1855 for (i = 0; i < NUM_HINTS; i++) 1963 for (i = 0; i < NUM_HINTS; i++)
1856 flush->hint_address[i] = t->flush_dma[1] + i * sizeof(u64); 1964 flush->hint_address[i] = t->flush_dma[1] + i * sizeof(u64);
1965 offset += flush->header.length;
1857 1966
1858 /* flush2 (dimm2) */ 1967 /* flush2 (dimm2) */
1859 flush = nfit_buf + offset + flush_hint_size * 2; 1968 flush = nfit_buf + offset;
1860 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1969 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1861 flush->header.length = flush_hint_size; 1970 flush->header.length = flush_hint_size;
1862 flush->device_handle = handle[2]; 1971 flush->device_handle = handle[2];
1863 flush->hint_count = NUM_HINTS; 1972 flush->hint_count = NUM_HINTS;
1864 for (i = 0; i < NUM_HINTS; i++) 1973 for (i = 0; i < NUM_HINTS; i++)
1865 flush->hint_address[i] = t->flush_dma[2] + i * sizeof(u64); 1974 flush->hint_address[i] = t->flush_dma[2] + i * sizeof(u64);
1975 offset += flush->header.length;
1866 1976
1867 /* flush3 (dimm3) */ 1977 /* flush3 (dimm3) */
1868 flush = nfit_buf + offset + flush_hint_size * 3; 1978 flush = nfit_buf + offset;
1869 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1979 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1870 flush->header.length = flush_hint_size; 1980 flush->header.length = flush_hint_size;
1871 flush->device_handle = handle[3]; 1981 flush->device_handle = handle[3];
1872 flush->hint_count = NUM_HINTS; 1982 flush->hint_count = NUM_HINTS;
1873 for (i = 0; i < NUM_HINTS; i++) 1983 for (i = 0; i < NUM_HINTS; i++)
1874 flush->hint_address[i] = t->flush_dma[3] + i * sizeof(u64); 1984 flush->hint_address[i] = t->flush_dma[3] + i * sizeof(u64);
1985 offset += flush->header.length;
1875 1986
1876 /* platform capabilities */ 1987 /* platform capabilities */
1877 pcap = nfit_buf + offset + flush_hint_size * 4; 1988 pcap = nfit_buf + offset;
1878 pcap->header.type = ACPI_NFIT_TYPE_CAPABILITIES; 1989 pcap->header.type = ACPI_NFIT_TYPE_CAPABILITIES;
1879 pcap->header.length = sizeof(*pcap); 1990 pcap->header.length = sizeof(*pcap);
1880 pcap->highest_capability = 1; 1991 pcap->highest_capability = 1;
1881 pcap->capabilities = ACPI_NFIT_CAPABILITY_CACHE_FLUSH | 1992 pcap->capabilities = ACPI_NFIT_CAPABILITY_CACHE_FLUSH |
1882 ACPI_NFIT_CAPABILITY_MEM_FLUSH; 1993 ACPI_NFIT_CAPABILITY_MEM_FLUSH;
1994 offset += pcap->header.length;
1883 1995
1884 if (t->setup_hotplug) { 1996 if (t->setup_hotplug) {
1885 offset = offset + flush_hint_size * 4 + sizeof(*pcap);
1886 /* dcr-descriptor4: blk */ 1997 /* dcr-descriptor4: blk */
1887 dcr = nfit_buf + offset; 1998 dcr = nfit_buf + offset;
1888 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1999 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1889 dcr->header.length = sizeof(struct acpi_nfit_control_region); 2000 dcr->header.length = sizeof(*dcr);
1890 dcr->region_index = 8+1; 2001 dcr->region_index = 8+1;
1891 dcr_common_init(dcr); 2002 dcr_common_init(dcr);
1892 dcr->serial_number = ~handle[4]; 2003 dcr->serial_number = ~handle[4];
@@ -1897,8 +2008,8 @@ static void nfit_test0_setup(struct nfit_test *t)
1897 dcr->command_size = 8; 2008 dcr->command_size = 8;
1898 dcr->status_offset = 8; 2009 dcr->status_offset = 8;
1899 dcr->status_size = 4; 2010 dcr->status_size = 4;
2011 offset += dcr->header.length;
1900 2012
1901 offset = offset + sizeof(struct acpi_nfit_control_region);
1902 /* dcr-descriptor4: pmem */ 2013 /* dcr-descriptor4: pmem */
1903 dcr = nfit_buf + offset; 2014 dcr = nfit_buf + offset;
1904 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 2015 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
@@ -1909,21 +2020,20 @@ static void nfit_test0_setup(struct nfit_test *t)
1909 dcr->serial_number = ~handle[4]; 2020 dcr->serial_number = ~handle[4];
1910 dcr->code = NFIT_FIC_BYTEN; 2021 dcr->code = NFIT_FIC_BYTEN;
1911 dcr->windows = 0; 2022 dcr->windows = 0;
2023 offset += dcr->header.length;
1912 2024
1913 offset = offset + offsetof(struct acpi_nfit_control_region,
1914 window_size);
1915 /* bdw4 (spa/dcr4, dimm4) */ 2025 /* bdw4 (spa/dcr4, dimm4) */
1916 bdw = nfit_buf + offset; 2026 bdw = nfit_buf + offset;
1917 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION; 2027 bdw->header.type = ACPI_NFIT_TYPE_DATA_REGION;
1918 bdw->header.length = sizeof(struct acpi_nfit_data_region); 2028 bdw->header.length = sizeof(*bdw);
1919 bdw->region_index = 8+1; 2029 bdw->region_index = 8+1;
1920 bdw->windows = 1; 2030 bdw->windows = 1;
1921 bdw->offset = 0; 2031 bdw->offset = 0;
1922 bdw->size = BDW_SIZE; 2032 bdw->size = BDW_SIZE;
1923 bdw->capacity = DIMM_SIZE; 2033 bdw->capacity = DIMM_SIZE;
1924 bdw->start_address = 0; 2034 bdw->start_address = 0;
2035 offset += bdw->header.length;
1925 2036
1926 offset = offset + sizeof(struct acpi_nfit_data_region);
1927 /* spa10 (dcr4) dimm4 */ 2037 /* spa10 (dcr4) dimm4 */
1928 spa = nfit_buf + offset; 2038 spa = nfit_buf + offset;
1929 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 2039 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
@@ -1932,30 +2042,32 @@ static void nfit_test0_setup(struct nfit_test *t)
1932 spa->range_index = 10+1; 2042 spa->range_index = 10+1;
1933 spa->address = t->dcr_dma[4]; 2043 spa->address = t->dcr_dma[4];
1934 spa->length = DCR_SIZE; 2044 spa->length = DCR_SIZE;
2045 offset += spa->header.length;
1935 2046
1936 /* 2047 /*
1937 * spa11 (single-dimm interleave for hotplug, note storage 2048 * spa11 (single-dimm interleave for hotplug, note storage
1938 * does not actually alias the related block-data-window 2049 * does not actually alias the related block-data-window
1939 * regions) 2050 * regions)
1940 */ 2051 */
1941 spa = nfit_buf + offset + sizeof(*spa); 2052 spa = nfit_buf + offset;
1942 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 2053 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1943 spa->header.length = sizeof(*spa); 2054 spa->header.length = sizeof(*spa);
1944 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16); 2055 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
1945 spa->range_index = 11+1; 2056 spa->range_index = 11+1;
1946 spa->address = t->spa_set_dma[2]; 2057 spa->address = t->spa_set_dma[2];
1947 spa->length = SPA0_SIZE; 2058 spa->length = SPA0_SIZE;
2059 offset += spa->header.length;
1948 2060
1949 /* spa12 (bdw for dcr4) dimm4 */ 2061 /* spa12 (bdw for dcr4) dimm4 */
1950 spa = nfit_buf + offset + sizeof(*spa) * 2; 2062 spa = nfit_buf + offset;
1951 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 2063 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1952 spa->header.length = sizeof(*spa); 2064 spa->header.length = sizeof(*spa);
1953 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); 2065 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
1954 spa->range_index = 12+1; 2066 spa->range_index = 12+1;
1955 spa->address = t->dimm_dma[4]; 2067 spa->address = t->dimm_dma[4];
1956 spa->length = DIMM_SIZE; 2068 spa->length = DIMM_SIZE;
2069 offset += spa->header.length;
1957 2070
1958 offset = offset + sizeof(*spa) * 3;
1959 /* mem-region14 (spa/dcr4, dimm4) */ 2071 /* mem-region14 (spa/dcr4, dimm4) */
1960 memdev = nfit_buf + offset; 2072 memdev = nfit_buf + offset;
1961 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 2073 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
@@ -1970,10 +2082,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1970 memdev->address = 0; 2082 memdev->address = 0;
1971 memdev->interleave_index = 0; 2083 memdev->interleave_index = 0;
1972 memdev->interleave_ways = 1; 2084 memdev->interleave_ways = 1;
2085 offset += memdev->header.length;
1973 2086
1974 /* mem-region15 (spa0, dimm4) */ 2087 /* mem-region15 (spa11, dimm4) */
1975 memdev = nfit_buf + offset + 2088 memdev = nfit_buf + offset;
1976 sizeof(struct acpi_nfit_memory_map);
1977 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 2089 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1978 memdev->header.length = sizeof(*memdev); 2090 memdev->header.length = sizeof(*memdev);
1979 memdev->device_handle = handle[4]; 2091 memdev->device_handle = handle[4];
@@ -1987,10 +2099,10 @@ static void nfit_test0_setup(struct nfit_test *t)
1987 memdev->interleave_index = 0; 2099 memdev->interleave_index = 0;
1988 memdev->interleave_ways = 1; 2100 memdev->interleave_ways = 1;
1989 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED; 2101 memdev->flags = ACPI_NFIT_MEM_HEALTH_ENABLED;
2102 offset += memdev->header.length;
1990 2103
1991 /* mem-region16 (spa/bdw4, dimm4) */ 2104 /* mem-region16 (spa/bdw4, dimm4) */
1992 memdev = nfit_buf + offset + 2105 memdev = nfit_buf + offset;
1993 sizeof(struct acpi_nfit_memory_map) * 2;
1994 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 2106 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
1995 memdev->header.length = sizeof(*memdev); 2107 memdev->header.length = sizeof(*memdev);
1996 memdev->device_handle = handle[4]; 2108 memdev->device_handle = handle[4];
@@ -2003,8 +2115,8 @@ static void nfit_test0_setup(struct nfit_test *t)
2003 memdev->address = 0; 2115 memdev->address = 0;
2004 memdev->interleave_index = 0; 2116 memdev->interleave_index = 0;
2005 memdev->interleave_ways = 1; 2117 memdev->interleave_ways = 1;
2118 offset += memdev->header.length;
2006 2119
2007 offset = offset + sizeof(struct acpi_nfit_memory_map) * 3;
2008 /* flush3 (dimm4) */ 2120 /* flush3 (dimm4) */
2009 flush = nfit_buf + offset; 2121 flush = nfit_buf + offset;
2010 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 2122 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
@@ -2014,8 +2126,14 @@ static void nfit_test0_setup(struct nfit_test *t)
2014 for (i = 0; i < NUM_HINTS; i++) 2126 for (i = 0; i < NUM_HINTS; i++)
2015 flush->hint_address[i] = t->flush_dma[4] 2127 flush->hint_address[i] = t->flush_dma[4]
2016 + i * sizeof(u64); 2128 + i * sizeof(u64);
2129 offset += flush->header.length;
2130
2131 /* sanity check to make sure we've filled the buffer */
2132 WARN_ON(offset != t->nfit_size);
2017 } 2133 }
2018 2134
2135 t->nfit_filled = offset;
2136
2019 post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0], 2137 post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0],
2020 SPA0_SIZE); 2138 SPA0_SIZE);
2021 2139
@@ -2026,6 +2144,7 @@ static void nfit_test0_setup(struct nfit_test *t)
2026 set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en); 2144 set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
2027 set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en); 2145 set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
2028 set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en); 2146 set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
2147 set_bit(ND_INTEL_SMART_INJECT, &acpi_desc->dimm_cmd_force_en);
2029 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en); 2148 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
2030 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 2149 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
2031 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 2150 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
@@ -2061,17 +2180,18 @@ static void nfit_test1_setup(struct nfit_test *t)
2061 spa->range_index = 0+1; 2180 spa->range_index = 0+1;
2062 spa->address = t->spa_set_dma[0]; 2181 spa->address = t->spa_set_dma[0];
2063 spa->length = SPA2_SIZE; 2182 spa->length = SPA2_SIZE;
2183 offset += spa->header.length;
2064 2184
2065 /* virtual cd region */ 2185 /* virtual cd region */
2066 spa = nfit_buf + sizeof(*spa); 2186 spa = nfit_buf + offset;
2067 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 2187 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2068 spa->header.length = sizeof(*spa); 2188 spa->header.length = sizeof(*spa);
2069 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_VCD), 16); 2189 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_VCD), 16);
2070 spa->range_index = 0; 2190 spa->range_index = 0;
2071 spa->address = t->spa_set_dma[1]; 2191 spa->address = t->spa_set_dma[1];
2072 spa->length = SPA_VCD_SIZE; 2192 spa->length = SPA_VCD_SIZE;
2193 offset += spa->header.length;
2073 2194
2074 offset += sizeof(*spa) * 2;
2075 /* mem-region0 (spa0, dimm0) */ 2195 /* mem-region0 (spa0, dimm0) */
2076 memdev = nfit_buf + offset; 2196 memdev = nfit_buf + offset;
2077 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 2197 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
@@ -2089,8 +2209,8 @@ static void nfit_test1_setup(struct nfit_test *t)
2089 memdev->flags = ACPI_NFIT_MEM_SAVE_FAILED | ACPI_NFIT_MEM_RESTORE_FAILED 2209 memdev->flags = ACPI_NFIT_MEM_SAVE_FAILED | ACPI_NFIT_MEM_RESTORE_FAILED
2090 | ACPI_NFIT_MEM_FLUSH_FAILED | ACPI_NFIT_MEM_HEALTH_OBSERVED 2210 | ACPI_NFIT_MEM_FLUSH_FAILED | ACPI_NFIT_MEM_HEALTH_OBSERVED
2091 | ACPI_NFIT_MEM_NOT_ARMED; 2211 | ACPI_NFIT_MEM_NOT_ARMED;
2212 offset += memdev->header.length;
2092 2213
2093 offset += sizeof(*memdev);
2094 /* dcr-descriptor0 */ 2214 /* dcr-descriptor0 */
2095 dcr = nfit_buf + offset; 2215 dcr = nfit_buf + offset;
2096 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 2216 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
@@ -2101,8 +2221,8 @@ static void nfit_test1_setup(struct nfit_test *t)
2101 dcr->serial_number = ~handle[5]; 2221 dcr->serial_number = ~handle[5];
2102 dcr->code = NFIT_FIC_BYTE; 2222 dcr->code = NFIT_FIC_BYTE;
2103 dcr->windows = 0; 2223 dcr->windows = 0;
2104
2105 offset += dcr->header.length; 2224 offset += dcr->header.length;
2225
2106 memdev = nfit_buf + offset; 2226 memdev = nfit_buf + offset;
2107 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 2227 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
2108 memdev->header.length = sizeof(*memdev); 2228 memdev->header.length = sizeof(*memdev);
@@ -2117,9 +2237,9 @@ static void nfit_test1_setup(struct nfit_test *t)
2117 memdev->interleave_index = 0; 2237 memdev->interleave_index = 0;
2118 memdev->interleave_ways = 1; 2238 memdev->interleave_ways = 1;
2119 memdev->flags = ACPI_NFIT_MEM_MAP_FAILED; 2239 memdev->flags = ACPI_NFIT_MEM_MAP_FAILED;
2240 offset += memdev->header.length;
2120 2241
2121 /* dcr-descriptor1 */ 2242 /* dcr-descriptor1 */
2122 offset += sizeof(*memdev);
2123 dcr = nfit_buf + offset; 2243 dcr = nfit_buf + offset;
2124 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 2244 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
2125 dcr->header.length = offsetof(struct acpi_nfit_control_region, 2245 dcr->header.length = offsetof(struct acpi_nfit_control_region,
@@ -2129,6 +2249,12 @@ static void nfit_test1_setup(struct nfit_test *t)
2129 dcr->serial_number = ~handle[6]; 2249 dcr->serial_number = ~handle[6];
2130 dcr->code = NFIT_FIC_BYTE; 2250 dcr->code = NFIT_FIC_BYTE;
2131 dcr->windows = 0; 2251 dcr->windows = 0;
2252 offset += dcr->header.length;
2253
2254 /* sanity check to make sure we've filled the buffer */
2255 WARN_ON(offset != t->nfit_size);
2256
2257 t->nfit_filled = offset;
2132 2258
2133 post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0], 2259 post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0],
2134 SPA2_SIZE); 2260 SPA2_SIZE);
@@ -2139,6 +2265,9 @@ static void nfit_test1_setup(struct nfit_test *t)
2139 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 2265 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
2140 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 2266 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
2141 set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en); 2267 set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en);
2268 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
2269 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
2270 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
2142} 2271}
2143 2272
2144static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 2273static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
@@ -2487,7 +2616,7 @@ static int nfit_test_probe(struct platform_device *pdev)
2487 nd_desc->ndctl = nfit_test_ctl; 2616 nd_desc->ndctl = nfit_test_ctl;
2488 2617
2489 rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf, 2618 rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf,
2490 nfit_test->nfit_size); 2619 nfit_test->nfit_filled);
2491 if (rc) 2620 if (rc)
2492 return rc; 2621 return rc;
2493 2622
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 428344519cdf..33752e06ff8d 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -93,6 +93,7 @@ struct nd_cmd_ars_err_inj_stat {
93#define ND_INTEL_FW_FINISH_UPDATE 15 93#define ND_INTEL_FW_FINISH_UPDATE 15
94#define ND_INTEL_FW_FINISH_QUERY 16 94#define ND_INTEL_FW_FINISH_QUERY 16
95#define ND_INTEL_SMART_SET_THRESHOLD 17 95#define ND_INTEL_SMART_SET_THRESHOLD 17
96#define ND_INTEL_SMART_INJECT 18
96 97
97#define ND_INTEL_SMART_HEALTH_VALID (1 << 0) 98#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
98#define ND_INTEL_SMART_SPARES_VALID (1 << 1) 99#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
@@ -111,6 +112,10 @@ struct nd_cmd_ars_err_inj_stat {
111#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0) 112#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0)
112#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1) 113#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1)
113#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2) 114#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2)
115#define ND_INTEL_SMART_INJECT_MTEMP (1 << 0)
116#define ND_INTEL_SMART_INJECT_SPARE (1 << 1)
117#define ND_INTEL_SMART_INJECT_FATAL (1 << 2)
118#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3)
114 119
115struct nd_intel_smart { 120struct nd_intel_smart {
116 __u32 status; 121 __u32 status;
@@ -158,6 +163,17 @@ struct nd_intel_smart_set_threshold {
158 __u32 status; 163 __u32 status;
159} __packed; 164} __packed;
160 165
166struct nd_intel_smart_inject {
167 __u64 flags;
168 __u8 mtemp_enable;
169 __u16 media_temperature;
170 __u8 spare_enable;
171 __u8 spares;
172 __u8 fatal_enable;
173 __u8 unsafe_shutdown_enable;
174 __u32 status;
175} __packed;
176
161#define INTEL_FW_STORAGE_SIZE 0x100000 177#define INTEL_FW_STORAGE_SIZE 0x100000
162#define INTEL_FW_MAX_SEND_LEN 0xFFEC 178#define INTEL_FW_MAX_SEND_LEN 0xFFEC
163#define INTEL_FW_QUERY_INTERVAL 250000 179#define INTEL_FW_QUERY_INTERVAL 250000
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index fa7ee369b3c9..db66f8a0d4be 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -17,7 +17,7 @@ ifeq ($(BUILD), 32)
17 LDFLAGS += -m32 17 LDFLAGS += -m32
18endif 18endif
19 19
20targets: mapshift $(TARGETS) 20targets: generated/map-shift.h $(TARGETS)
21 21
22main: $(OFILES) 22main: $(OFILES)
23 23
@@ -42,9 +42,7 @@ radix-tree.c: ../../../lib/radix-tree.c
42idr.c: ../../../lib/idr.c 42idr.c: ../../../lib/idr.c
43 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 43 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
44 44
45.PHONY: mapshift 45generated/map-shift.h:
46
47mapshift:
48 @if ! grep -qws $(SHIFT) generated/map-shift.h; then \ 46 @if ! grep -qws $(SHIFT) generated/map-shift.h; then \
49 echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \ 47 echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \
50 generated/map-shift.h; \ 48 generated/map-shift.h; \
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
index e3201ccf54c3..32159c08a52e 100644
--- a/tools/testing/radix-tree/linux/gfp.h
+++ b/tools/testing/radix-tree/linux/gfp.h
@@ -19,6 +19,7 @@
19 19
20#define __GFP_RECLAIM (__GFP_DIRECT_RECLAIM|__GFP_KSWAPD_RECLAIM) 20#define __GFP_RECLAIM (__GFP_DIRECT_RECLAIM|__GFP_KSWAPD_RECLAIM)
21 21
22#define GFP_ZONEMASK 0x0fu
22#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM) 23#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
23#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS) 24#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
24#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM) 25#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 59245b3d587c..7bf405638b0b 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -16,6 +16,7 @@
16#include <linux/radix-tree.h> 16#include <linux/radix-tree.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <pthread.h>
19 20
20#include "test.h" 21#include "test.h"
21 22
@@ -624,6 +625,67 @@ static void multiorder_account(void)
624 item_kill_tree(&tree); 625 item_kill_tree(&tree);
625} 626}
626 627
628bool stop_iteration = false;
629
630static void *creator_func(void *ptr)
631{
632 /* 'order' is set up to ensure we have sibling entries */
633 unsigned int order = RADIX_TREE_MAP_SHIFT - 1;
634 struct radix_tree_root *tree = ptr;
635 int i;
636
637 for (i = 0; i < 10000; i++) {
638 item_insert_order(tree, 0, order);
639 item_delete_rcu(tree, 0);
640 }
641
642 stop_iteration = true;
643 return NULL;
644}
645
646static void *iterator_func(void *ptr)
647{
648 struct radix_tree_root *tree = ptr;
649 struct radix_tree_iter iter;
650 struct item *item;
651 void **slot;
652
653 while (!stop_iteration) {
654 rcu_read_lock();
655 radix_tree_for_each_slot(slot, tree, &iter, 0) {
656 item = radix_tree_deref_slot(slot);
657
658 if (!item)
659 continue;
660 if (radix_tree_deref_retry(item)) {
661 slot = radix_tree_iter_retry(&iter);
662 continue;
663 }
664
665 item_sanity(item, iter.index);
666 }
667 rcu_read_unlock();
668 }
669 return NULL;
670}
671
672static void multiorder_iteration_race(void)
673{
674 const int num_threads = sysconf(_SC_NPROCESSORS_ONLN);
675 pthread_t worker_thread[num_threads];
676 RADIX_TREE(tree, GFP_KERNEL);
677 int i;
678
679 pthread_create(&worker_thread[0], NULL, &creator_func, &tree);
680 for (i = 1; i < num_threads; i++)
681 pthread_create(&worker_thread[i], NULL, &iterator_func, &tree);
682
683 for (i = 0; i < num_threads; i++)
684 pthread_join(worker_thread[i], NULL);
685
686 item_kill_tree(&tree);
687}
688
627void multiorder_checks(void) 689void multiorder_checks(void)
628{ 690{
629 int i; 691 int i;
@@ -644,6 +706,7 @@ void multiorder_checks(void)
644 multiorder_join(); 706 multiorder_join();
645 multiorder_split(); 707 multiorder_split();
646 multiorder_account(); 708 multiorder_account();
709 multiorder_iteration_race();
647 710
648 radix_tree_cpu_dead(0); 711 radix_tree_cpu_dead(0);
649} 712}
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index 5978ab1f403d..def6015570b2 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
75 return 0; 75 return 0;
76} 76}
77 77
78static void item_free_rcu(struct rcu_head *head)
79{
80 struct item *item = container_of(head, struct item, rcu_head);
81
82 free(item);
83}
84
85int item_delete_rcu(struct radix_tree_root *root, unsigned long index)
86{
87 struct item *item = radix_tree_delete(root, index);
88
89 if (item) {
90 item_sanity(item, index);
91 call_rcu(&item->rcu_head, item_free_rcu);
92 return 1;
93 }
94 return 0;
95}
96
78void item_check_present(struct radix_tree_root *root, unsigned long index) 97void item_check_present(struct radix_tree_root *root, unsigned long index)
79{ 98{
80 struct item *item; 99 struct item *item;
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index d9c031dbeb1a..31f1d9b6f506 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -5,6 +5,7 @@
5#include <linux/rcupdate.h> 5#include <linux/rcupdate.h>
6 6
7struct item { 7struct item {
8 struct rcu_head rcu_head;
8 unsigned long index; 9 unsigned long index;
9 unsigned int order; 10 unsigned int order;
10}; 11};
@@ -12,9 +13,11 @@ struct item {
12struct item *item_create(unsigned long index, unsigned int order); 13struct item *item_create(unsigned long index, unsigned int order);
13int __item_insert(struct radix_tree_root *root, struct item *item); 14int __item_insert(struct radix_tree_root *root, struct item *item);
14int item_insert(struct radix_tree_root *root, unsigned long index); 15int item_insert(struct radix_tree_root *root, unsigned long index);
16void item_sanity(struct item *item, unsigned long index);
15int item_insert_order(struct radix_tree_root *root, unsigned long index, 17int item_insert_order(struct radix_tree_root *root, unsigned long index,
16 unsigned order); 18 unsigned order);
17int item_delete(struct radix_tree_root *root, unsigned long index); 19int item_delete(struct radix_tree_root *root, unsigned long index);
20int item_delete_rcu(struct radix_tree_root *root, unsigned long index);
18struct item *item_lookup(struct radix_tree_root *root, unsigned long index); 21struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
19 22
20void item_check_present(struct radix_tree_root *root, unsigned long index); 23void item_check_present(struct radix_tree_root *root, unsigned long index);
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 7442dfb73b7f..32aafa92074c 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -7,6 +7,7 @@ TARGETS += cpufreq
7TARGETS += cpu-hotplug 7TARGETS += cpu-hotplug
8TARGETS += efivarfs 8TARGETS += efivarfs
9TARGETS += exec 9TARGETS += exec
10TARGETS += filesystems
10TARGETS += firmware 11TARGETS += firmware
11TARGETS += ftrace 12TARGETS += ftrace
12TARGETS += futex 13TARGETS += futex
@@ -14,6 +15,7 @@ TARGETS += gpio
14TARGETS += intel_pstate 15TARGETS += intel_pstate
15TARGETS += ipc 16TARGETS += ipc
16TARGETS += kcmp 17TARGETS += kcmp
18TARGETS += kvm
17TARGETS += lib 19TARGETS += lib
18TARGETS += membarrier 20TARGETS += membarrier
19TARGETS += memfd 21TARGETS += memfd
@@ -23,6 +25,7 @@ TARGETS += mqueue
23TARGETS += net 25TARGETS += net
24TARGETS += nsfs 26TARGETS += nsfs
25TARGETS += powerpc 27TARGETS += powerpc
28TARGETS += proc
26TARGETS += pstore 29TARGETS += pstore
27TARGETS += ptrace 30TARGETS += ptrace
28TARGETS += seccomp 31TARGETS += seccomp
@@ -66,6 +69,12 @@ ifndef BUILD
66 BUILD := $(shell pwd) 69 BUILD := $(shell pwd)
67endif 70endif
68 71
72# KSFT_TAP_LEVEL is used from KSFT framework to prevent nested TAP header
73# printing from tests. Applicable to run_tests case where run_tests adds
74# TAP header prior running tests and when a test program invokes another
75# with system() call. Export it here to cover override RUN_TESTS defines.
76export KSFT_TAP_LEVEL=`echo 1`
77
69export BUILD 78export BUILD
70all: 79all:
71 @for TARGET in $(TARGETS); do \ 80 @for TARGET in $(TARGETS); do \
@@ -125,11 +134,14 @@ ifdef INSTALL_PATH
125 echo "else" >> $(ALL_SCRIPT) 134 echo "else" >> $(ALL_SCRIPT)
126 echo " OUTPUT=/dev/stdout" >> $(ALL_SCRIPT) 135 echo " OUTPUT=/dev/stdout" >> $(ALL_SCRIPT)
127 echo "fi" >> $(ALL_SCRIPT) 136 echo "fi" >> $(ALL_SCRIPT)
137 echo "export KSFT_TAP_LEVEL=`echo 1`" >> $(ALL_SCRIPT)
128 138
129 for TARGET in $(TARGETS); do \ 139 for TARGET in $(TARGETS); do \
130 BUILD_TARGET=$$BUILD/$$TARGET; \ 140 BUILD_TARGET=$$BUILD/$$TARGET; \
131 echo "echo ; echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \ 141 echo "echo ; echo TAP version 13" >> $(ALL_SCRIPT); \
142 echo "echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \
132 echo "echo ========================================" >> $(ALL_SCRIPT); \ 143 echo "echo ========================================" >> $(ALL_SCRIPT); \
144 echo "[ -w /dev/kmsg ] && echo \"kselftest: Running tests in $$TARGET\" >> /dev/kmsg" >> $(ALL_SCRIPT); \
133 echo "cd $$TARGET" >> $(ALL_SCRIPT); \ 145 echo "cd $$TARGET" >> $(ALL_SCRIPT); \
134 make -s --no-print-directory OUTPUT=$$BUILD_TARGET -C $$TARGET emit_tests >> $(ALL_SCRIPT); \ 146 make -s --no-print-directory OUTPUT=$$BUILD_TARGET -C $$TARGET emit_tests >> $(ALL_SCRIPT); \
135 echo "cd \$$ROOT" >> $(ALL_SCRIPT); \ 147 echo "cd \$$ROOT" >> $(ALL_SCRIPT); \
diff --git a/tools/testing/selftests/android/ion/.gitignore b/tools/testing/selftests/android/ion/.gitignore
index 67e6f391b2a9..95e8f4561474 100644
--- a/tools/testing/selftests/android/ion/.gitignore
+++ b/tools/testing/selftests/android/ion/.gitignore
@@ -1,2 +1,3 @@
1ionapp_export 1ionapp_export
2ionapp_import 2ionapp_import
3ionmap_test
diff --git a/tools/testing/selftests/android/ion/Makefile b/tools/testing/selftests/android/ion/Makefile
index 96e0c448b39d..e03695287f76 100644
--- a/tools/testing/selftests/android/ion/Makefile
+++ b/tools/testing/selftests/android/ion/Makefile
@@ -1,8 +1,8 @@
1 1
2INCLUDEDIR := -I. -I../../../../../drivers/staging/android/uapi/ 2INCLUDEDIR := -I. -I../../../../../drivers/staging/android/uapi/ -I../../../../../usr/include/
3CFLAGS := $(CFLAGS) $(INCLUDEDIR) -Wall -O2 -g 3CFLAGS := $(CFLAGS) $(INCLUDEDIR) -Wall -O2 -g
4 4
5TEST_GEN_FILES := ionapp_export ionapp_import 5TEST_GEN_FILES := ionapp_export ionapp_import ionmap_test
6 6
7all: $(TEST_GEN_FILES) 7all: $(TEST_GEN_FILES)
8 8
@@ -14,3 +14,4 @@ include ../../lib.mk
14 14
15$(OUTPUT)/ionapp_export: ionapp_export.c ipcsocket.c ionutils.c 15$(OUTPUT)/ionapp_export: ionapp_export.c ipcsocket.c ionutils.c
16$(OUTPUT)/ionapp_import: ionapp_import.c ipcsocket.c ionutils.c 16$(OUTPUT)/ionapp_import: ionapp_import.c ipcsocket.c ionutils.c
17$(OUTPUT)/ionmap_test: ionmap_test.c ionutils.c
diff --git a/tools/testing/selftests/android/ion/config b/tools/testing/selftests/android/ion/config
index 19db6ca9aa2b..b4ad748a9dd9 100644
--- a/tools/testing/selftests/android/ion/config
+++ b/tools/testing/selftests/android/ion/config
@@ -2,3 +2,4 @@ CONFIG_ANDROID=y
2CONFIG_STAGING=y 2CONFIG_STAGING=y
3CONFIG_ION=y 3CONFIG_ION=y
4CONFIG_ION_SYSTEM_HEAP=y 4CONFIG_ION_SYSTEM_HEAP=y
5CONFIG_DRM_VGEM=y
diff --git a/tools/testing/selftests/android/ion/ionmap_test.c b/tools/testing/selftests/android/ion/ionmap_test.c
new file mode 100644
index 000000000000..dab36b06b37d
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ionmap_test.c
@@ -0,0 +1,136 @@
1#include <errno.h>
2#include <fcntl.h>
3#include <stdio.h>
4#include <stdint.h>
5#include <string.h>
6#include <unistd.h>
7
8#include <sys/ioctl.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11
12#include <linux/dma-buf.h>
13
14#include <drm/drm.h>
15
16#include "ion.h"
17#include "ionutils.h"
18
19int check_vgem(int fd)
20{
21 drm_version_t version = { 0 };
22 char name[5];
23 int ret;
24
25 version.name_len = 4;
26 version.name = name;
27
28 ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
29 if (ret)
30 return 1;
31
32 return strcmp(name, "vgem");
33}
34
35int open_vgem(void)
36{
37 int i, fd;
38 const char *drmstr = "/dev/dri/card";
39
40 fd = -1;
41 for (i = 0; i < 16; i++) {
42 char name[80];
43
44 sprintf(name, "%s%u", drmstr, i);
45
46 fd = open(name, O_RDWR);
47 if (fd < 0)
48 continue;
49
50 if (check_vgem(fd)) {
51 close(fd);
52 continue;
53 } else {
54 break;
55 }
56
57 }
58 return fd;
59}
60
61int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
62{
63 struct drm_prime_handle import_handle = { 0 };
64 int ret;
65
66 import_handle.fd = dma_buf_fd;
67 import_handle.flags = 0;
68 import_handle.handle = 0;
69
70 ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
71 if (ret == 0)
72 *handle = import_handle.handle;
73 return ret;
74}
75
76void close_handle(int vgem_fd, uint32_t handle)
77{
78 struct drm_gem_close close = { 0 };
79
80 close.handle = handle;
81 ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
82}
83
84int main()
85{
86 int ret, vgem_fd;
87 struct ion_buffer_info info;
88 uint32_t handle = 0;
89 struct dma_buf_sync sync = { 0 };
90
91 info.heap_type = ION_HEAP_TYPE_SYSTEM;
92 info.heap_size = 4096;
93 info.flag_type = ION_FLAG_CACHED;
94
95 ret = ion_export_buffer_fd(&info);
96 if (ret < 0) {
97 printf("ion buffer alloc failed\n");
98 return -1;
99 }
100
101 vgem_fd = open_vgem();
102 if (vgem_fd < 0) {
103 ret = vgem_fd;
104 printf("Failed to open vgem\n");
105 goto out_ion;
106 }
107
108 ret = import_vgem_fd(vgem_fd, info.buffd, &handle);
109
110 if (ret < 0) {
111 printf("Failed to import buffer\n");
112 goto out_vgem;
113 }
114
115 sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
116 ret = ioctl(info.buffd, DMA_BUF_IOCTL_SYNC, &sync);
117 if (ret)
118 printf("sync start failed %d\n", errno);
119
120 memset(info.buffer, 0xff, 4096);
121
122 sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
123 ret = ioctl(info.buffd, DMA_BUF_IOCTL_SYNC, &sync);
124 if (ret)
125 printf("sync end failed %d\n", errno);
126
127 close_handle(vgem_fd, handle);
128 ret = 0;
129
130out_vgem:
131 close(vgem_fd);
132out_ion:
133 ion_close_buffer_fd(&info);
134 printf("done.\n");
135 return ret;
136}
diff --git a/tools/testing/selftests/android/ion/ionutils.c b/tools/testing/selftests/android/ion/ionutils.c
index ce69c14f51fa..7d1d37c4ef6a 100644
--- a/tools/testing/selftests/android/ion/ionutils.c
+++ b/tools/testing/selftests/android/ion/ionutils.c
@@ -80,11 +80,6 @@ int ion_export_buffer_fd(struct ion_buffer_info *ion_info)
80 heap_id = MAX_HEAP_COUNT + 1; 80 heap_id = MAX_HEAP_COUNT + 1;
81 for (i = 0; i < query.cnt; i++) { 81 for (i = 0; i < query.cnt; i++) {
82 if (heap_data[i].type == ion_info->heap_type) { 82 if (heap_data[i].type == ion_info->heap_type) {
83 printf("--------------------------------------\n");
84 printf("heap type: %d\n", heap_data[i].type);
85 printf(" heap id: %d\n", heap_data[i].heap_id);
86 printf("heap name: %s\n", heap_data[i].name);
87 printf("--------------------------------------\n");
88 heap_id = heap_data[i].heap_id; 83 heap_id = heap_data[i].heap_id;
89 break; 84 break;
90 } 85 }
@@ -204,7 +199,6 @@ void ion_close_buffer_fd(struct ion_buffer_info *ion_info)
204 /* Finally, close the client fd */ 199 /* Finally, close the client fd */
205 if (ion_info->ionfd > 0) 200 if (ion_info->ionfd > 0)
206 close(ion_info->ionfd); 201 close(ion_info->ionfd);
207 printf("<%s>: buffer release successfully....\n", __func__);
208 } 202 }
209} 203}
210 204
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index 9cf83f895d98..5e1ab2f0eb79 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -12,3 +12,6 @@ test_tcpbpf_user
12test_verifier_log 12test_verifier_log
13feature 13feature
14test_libbpf_open 14test_libbpf_open
15test_sock
16test_sock_addr
17urandom_read
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 5c43c187f27c..0a315ddabbf4 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -13,34 +13,49 @@ endif
13CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include 13CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
14LDLIBS += -lcap -lelf -lrt -lpthread 14LDLIBS += -lcap -lelf -lrt -lpthread
15 15
16TEST_CUSTOM_PROGS = $(OUTPUT)/urandom_read
17all: $(TEST_CUSTOM_PROGS)
18
19$(TEST_CUSTOM_PROGS): urandom_read
20
21urandom_read: urandom_read.c
22 $(CC) -o $(TEST_CUSTOM_PROGS) -static $<
23
16# Order correspond to 'make run_tests' order 24# Order correspond to 'make run_tests' order
17TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ 25TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
18 test_align test_verifier_log test_dev_cgroup test_tcpbpf_user 26 test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
27 test_sock test_sock_addr
19 28
20TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 29TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
21 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ 30 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \
22 sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \ 31 sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \
23 test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \ 32 test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \
24 sample_map_ret0.o test_tcpbpf_kern.o 33 sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \
34 sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o
25 35
26# Order correspond to 'make run_tests' order 36# Order correspond to 'make run_tests' order
27TEST_PROGS := test_kmod.sh \ 37TEST_PROGS := test_kmod.sh \
28 test_libbpf.sh \ 38 test_libbpf.sh \
29 test_xdp_redirect.sh \ 39 test_xdp_redirect.sh \
30 test_xdp_meta.sh \ 40 test_xdp_meta.sh \
31 test_offload.py 41 test_offload.py \
42 test_sock_addr.sh
32 43
33# Compile but not part of 'make run_tests' 44# Compile but not part of 'make run_tests'
34TEST_GEN_PROGS_EXTENDED = test_libbpf_open 45TEST_GEN_PROGS_EXTENDED = test_libbpf_open
35 46
36include ../lib.mk 47include ../lib.mk
37 48
38BPFOBJ := $(OUTPUT)/libbpf.a cgroup_helpers.c 49BPFOBJ := $(OUTPUT)/libbpf.a
39 50
40$(TEST_GEN_PROGS): $(BPFOBJ) 51$(TEST_GEN_PROGS): $(BPFOBJ)
41 52
42$(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/libbpf.a 53$(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/libbpf.a
43 54
55$(OUTPUT)/test_dev_cgroup: cgroup_helpers.c
56$(OUTPUT)/test_sock: cgroup_helpers.c
57$(OUTPUT)/test_sock_addr: cgroup_helpers.c
58
44.PHONY: force 59.PHONY: force
45 60
46# force a rebuild of BPFOBJ when its dependencies are updated 61# force a rebuild of BPFOBJ when its dependencies are updated
@@ -72,3 +87,5 @@ $(OUTPUT)/%.o: %.c
72 $(CLANG) $(CLANG_FLAGS) \ 87 $(CLANG) $(CLANG_FLAGS) \
73 -O2 -target bpf -emit-llvm -c $< -o - | \ 88 -O2 -target bpf -emit-llvm -c $< -o - | \
74 $(LLC) -march=bpf -mcpu=$(CPU) -filetype=obj -o $@ 89 $(LLC) -march=bpf -mcpu=$(CPU) -filetype=obj -o $@
90
91EXTRA_CLEAN := $(TEST_CUSTOM_PROGS)
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index dde2c11d7771..d8223d99f96d 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -86,6 +86,16 @@ static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
86 (void *) BPF_FUNC_perf_prog_read_value; 86 (void *) BPF_FUNC_perf_prog_read_value;
87static int (*bpf_override_return)(void *ctx, unsigned long rc) = 87static int (*bpf_override_return)(void *ctx, unsigned long rc) =
88 (void *) BPF_FUNC_override_return; 88 (void *) BPF_FUNC_override_return;
89static int (*bpf_msg_redirect_map)(void *ctx, void *map, int key, int flags) =
90 (void *) BPF_FUNC_msg_redirect_map;
91static int (*bpf_msg_apply_bytes)(void *ctx, int len) =
92 (void *) BPF_FUNC_msg_apply_bytes;
93static int (*bpf_msg_cork_bytes)(void *ctx, int len) =
94 (void *) BPF_FUNC_msg_cork_bytes;
95static int (*bpf_msg_pull_data)(void *ctx, int start, int end, int flags) =
96 (void *) BPF_FUNC_msg_pull_data;
97static int (*bpf_bind)(void *ctx, void *addr, int addr_len) =
98 (void *) BPF_FUNC_bind;
89 99
90/* llvm builtin functions that eBPF C program may use to 100/* llvm builtin functions that eBPF C program may use to
91 * emit BPF_LD_ABS and BPF_LD_IND instructions 101 * emit BPF_LD_ABS and BPF_LD_IND instructions
@@ -123,6 +133,8 @@ static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
123 (void *) BPF_FUNC_skb_under_cgroup; 133 (void *) BPF_FUNC_skb_under_cgroup;
124static int (*bpf_skb_change_head)(void *, int len, int flags) = 134static int (*bpf_skb_change_head)(void *, int len, int flags) =
125 (void *) BPF_FUNC_skb_change_head; 135 (void *) BPF_FUNC_skb_change_head;
136static int (*bpf_skb_pull_data)(void *, int len) =
137 (void *) BPF_FUNC_skb_pull_data;
126 138
127/* Scan the ARCH passed in from ARCH env variable (see Makefile) */ 139/* Scan the ARCH passed in from ARCH env variable (see Makefile) */
128#if defined(__TARGET_ARCH_x86) 140#if defined(__TARGET_ARCH_x86)
diff --git a/tools/testing/selftests/bpf/bpf_rlimit.h b/tools/testing/selftests/bpf/bpf_rlimit.h
new file mode 100644
index 000000000000..9dac9b30f8ef
--- /dev/null
+++ b/tools/testing/selftests/bpf/bpf_rlimit.h
@@ -0,0 +1,28 @@
1#include <sys/resource.h>
2#include <stdio.h>
3
4static __attribute__((constructor)) void bpf_rlimit_ctor(void)
5{
6 struct rlimit rlim_old, rlim_new = {
7 .rlim_cur = RLIM_INFINITY,
8 .rlim_max = RLIM_INFINITY,
9 };
10
11 getrlimit(RLIMIT_MEMLOCK, &rlim_old);
12 /* For the sake of running the test cases, we temporarily
13 * set rlimit to infinity in order for kernel to focus on
14 * errors from actual test cases and not getting noise
15 * from hitting memlock limits. The limit is on per-process
16 * basis and not a global one, hence destructor not really
17 * needed here.
18 */
19 if (setrlimit(RLIMIT_MEMLOCK, &rlim_new) < 0) {
20 perror("Unable to lift memlock rlimit");
21 /* Trying out lower limit, but expect potential test
22 * case failures from this!
23 */
24 rlim_new.rlim_cur = rlim_old.rlim_cur + (1UL << 20);
25 rlim_new.rlim_max = rlim_old.rlim_max + (1UL << 20);
26 setrlimit(RLIMIT_MEMLOCK, &rlim_new);
27 }
28}
diff --git a/tools/testing/selftests/bpf/connect4_prog.c b/tools/testing/selftests/bpf/connect4_prog.c
new file mode 100644
index 000000000000..5a88a681d2ab
--- /dev/null
+++ b/tools/testing/selftests/bpf/connect4_prog.c
@@ -0,0 +1,45 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <string.h>
5
6#include <linux/stddef.h>
7#include <linux/bpf.h>
8#include <linux/in.h>
9#include <linux/in6.h>
10#include <sys/socket.h>
11
12#include "bpf_helpers.h"
13#include "bpf_endian.h"
14
15#define SRC_REWRITE_IP4 0x7f000004U
16#define DST_REWRITE_IP4 0x7f000001U
17#define DST_REWRITE_PORT4 4444
18
19int _version SEC("version") = 1;
20
21SEC("cgroup/connect4")
22int connect_v4_prog(struct bpf_sock_addr *ctx)
23{
24 struct sockaddr_in sa;
25
26 /* Rewrite destination. */
27 ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4);
28 ctx->user_port = bpf_htons(DST_REWRITE_PORT4);
29
30 if (ctx->type == SOCK_DGRAM || ctx->type == SOCK_STREAM) {
31 ///* Rewrite source. */
32 memset(&sa, 0, sizeof(sa));
33
34 sa.sin_family = AF_INET;
35 sa.sin_port = bpf_htons(0);
36 sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
37
38 if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
39 return 0;
40 }
41
42 return 1;
43}
44
45char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/connect6_prog.c b/tools/testing/selftests/bpf/connect6_prog.c
new file mode 100644
index 000000000000..8ea3f7d12dee
--- /dev/null
+++ b/tools/testing/selftests/bpf/connect6_prog.c
@@ -0,0 +1,61 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <string.h>
5
6#include <linux/stddef.h>
7#include <linux/bpf.h>
8#include <linux/in.h>
9#include <linux/in6.h>
10#include <sys/socket.h>
11
12#include "bpf_helpers.h"
13#include "bpf_endian.h"
14
15#define SRC_REWRITE_IP6_0 0
16#define SRC_REWRITE_IP6_1 0
17#define SRC_REWRITE_IP6_2 0
18#define SRC_REWRITE_IP6_3 6
19
20#define DST_REWRITE_IP6_0 0
21#define DST_REWRITE_IP6_1 0
22#define DST_REWRITE_IP6_2 0
23#define DST_REWRITE_IP6_3 1
24
25#define DST_REWRITE_PORT6 6666
26
27int _version SEC("version") = 1;
28
29SEC("cgroup/connect6")
30int connect_v6_prog(struct bpf_sock_addr *ctx)
31{
32 struct sockaddr_in6 sa;
33
34 /* Rewrite destination. */
35 ctx->user_ip6[0] = bpf_htonl(DST_REWRITE_IP6_0);
36 ctx->user_ip6[1] = bpf_htonl(DST_REWRITE_IP6_1);
37 ctx->user_ip6[2] = bpf_htonl(DST_REWRITE_IP6_2);
38 ctx->user_ip6[3] = bpf_htonl(DST_REWRITE_IP6_3);
39
40 ctx->user_port = bpf_htons(DST_REWRITE_PORT6);
41
42 if (ctx->type == SOCK_DGRAM || ctx->type == SOCK_STREAM) {
43 /* Rewrite source. */
44 memset(&sa, 0, sizeof(sa));
45
46 sa.sin6_family = AF_INET6;
47 sa.sin6_port = bpf_htons(0);
48
49 sa.sin6_addr.s6_addr32[0] = bpf_htonl(SRC_REWRITE_IP6_0);
50 sa.sin6_addr.s6_addr32[1] = bpf_htonl(SRC_REWRITE_IP6_1);
51 sa.sin6_addr.s6_addr32[2] = bpf_htonl(SRC_REWRITE_IP6_2);
52 sa.sin6_addr.s6_addr32[3] = bpf_htonl(SRC_REWRITE_IP6_3);
53
54 if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
55 return 0;
56 }
57
58 return 1;
59}
60
61char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/sockmap_parse_prog.c b/tools/testing/selftests/bpf/sockmap_parse_prog.c
index a1dec2b6d9c5..0f92858f6226 100644
--- a/tools/testing/selftests/bpf/sockmap_parse_prog.c
+++ b/tools/testing/selftests/bpf/sockmap_parse_prog.c
@@ -20,14 +20,25 @@ int bpf_prog1(struct __sk_buff *skb)
20 __u32 lport = skb->local_port; 20 __u32 lport = skb->local_port;
21 __u32 rport = skb->remote_port; 21 __u32 rport = skb->remote_port;
22 __u8 *d = data; 22 __u8 *d = data;
23 __u32 len = (__u32) data_end - (__u32) data;
24 int err;
23 25
24 if (data + 10 > data_end) 26 if (data + 10 > data_end) {
25 return skb->len; 27 err = bpf_skb_pull_data(skb, 10);
28 if (err)
29 return SK_DROP;
30
31 data_end = (void *)(long)skb->data_end;
32 data = (void *)(long)skb->data;
33 if (data + 10 > data_end)
34 return SK_DROP;
35 }
26 36
27 /* This write/read is a bit pointless but tests the verifier and 37 /* This write/read is a bit pointless but tests the verifier and
28 * strparser handler for read/write pkt data and access into sk 38 * strparser handler for read/write pkt data and access into sk
29 * fields. 39 * fields.
30 */ 40 */
41 d = data;
31 d[7] = 1; 42 d[7] = 1;
32 return skb->len; 43 return skb->len;
33} 44}
diff --git a/tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c b/tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c
new file mode 100644
index 000000000000..12a7b5c82ed6
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c
@@ -0,0 +1,33 @@
1#include <linux/bpf.h>
2#include "bpf_helpers.h"
3#include "bpf_util.h"
4#include "bpf_endian.h"
5
6int _version SEC("version") = 1;
7
8#define bpf_printk(fmt, ...) \
9({ \
10 char ____fmt[] = fmt; \
11 bpf_trace_printk(____fmt, sizeof(____fmt), \
12 ##__VA_ARGS__); \
13})
14
15SEC("sk_msg1")
16int bpf_prog1(struct sk_msg_md *msg)
17{
18 void *data_end = (void *)(long) msg->data_end;
19 void *data = (void *)(long) msg->data;
20
21 char *d;
22
23 if (data + 8 > data_end)
24 return SK_DROP;
25
26 bpf_printk("data length %i\n", (__u64)msg->data_end - (__u64)msg->data);
27 d = (char *)data;
28 bpf_printk("hello sendmsg hook %i %i\n", d[0], d[1]);
29
30 return SK_PASS;
31}
32
33char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/sockmap_verdict_prog.c b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
index d7bea972cb21..2ce7634a4012 100644
--- a/tools/testing/selftests/bpf/sockmap_verdict_prog.c
+++ b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
@@ -26,6 +26,13 @@ struct bpf_map_def SEC("maps") sock_map_tx = {
26 .max_entries = 20, 26 .max_entries = 20,
27}; 27};
28 28
29struct bpf_map_def SEC("maps") sock_map_msg = {
30 .type = BPF_MAP_TYPE_SOCKMAP,
31 .key_size = sizeof(int),
32 .value_size = sizeof(int),
33 .max_entries = 20,
34};
35
29struct bpf_map_def SEC("maps") sock_map_break = { 36struct bpf_map_def SEC("maps") sock_map_break = {
30 .type = BPF_MAP_TYPE_ARRAY, 37 .type = BPF_MAP_TYPE_ARRAY,
31 .key_size = sizeof(int), 38 .key_size = sizeof(int),
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
index ff8bd7e3e50c..6b1b302310fe 100644
--- a/tools/testing/selftests/bpf/test_align.c
+++ b/tools/testing/selftests/bpf/test_align.c
@@ -9,8 +9,6 @@
9#include <stddef.h> 9#include <stddef.h>
10#include <stdbool.h> 10#include <stdbool.h>
11 11
12#include <sys/resource.h>
13
14#include <linux/unistd.h> 12#include <linux/unistd.h>
15#include <linux/filter.h> 13#include <linux/filter.h>
16#include <linux/bpf_perf_event.h> 14#include <linux/bpf_perf_event.h>
@@ -19,6 +17,7 @@
19#include <bpf/bpf.h> 17#include <bpf/bpf.h>
20 18
21#include "../../../include/linux/filter.h" 19#include "../../../include/linux/filter.h"
20#include "bpf_rlimit.h"
22 21
23#ifndef ARRAY_SIZE 22#ifndef ARRAY_SIZE
24# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 23# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -702,9 +701,6 @@ static int do_test(unsigned int from, unsigned int to)
702int main(int argc, char **argv) 701int main(int argc, char **argv)
703{ 702{
704 unsigned int from = 0, to = ARRAY_SIZE(tests); 703 unsigned int from = 0, to = ARRAY_SIZE(tests);
705 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
706
707 setrlimit(RLIMIT_MEMLOCK, &rinf);
708 704
709 if (argc == 3) { 705 if (argc == 3) {
710 unsigned int l = atoi(argv[argc - 2]); 706 unsigned int l = atoi(argv[argc - 2]);
diff --git a/tools/testing/selftests/bpf/test_dev_cgroup.c b/tools/testing/selftests/bpf/test_dev_cgroup.c
index 3489cc283433..9c8b50bac7e0 100644
--- a/tools/testing/selftests/bpf/test_dev_cgroup.c
+++ b/tools/testing/selftests/bpf/test_dev_cgroup.c
@@ -11,13 +11,13 @@
11#include <errno.h> 11#include <errno.h>
12#include <assert.h> 12#include <assert.h>
13#include <sys/time.h> 13#include <sys/time.h>
14#include <sys/resource.h>
15 14
16#include <linux/bpf.h> 15#include <linux/bpf.h>
17#include <bpf/bpf.h> 16#include <bpf/bpf.h>
18#include <bpf/libbpf.h> 17#include <bpf/libbpf.h>
19 18
20#include "cgroup_helpers.h" 19#include "cgroup_helpers.h"
20#include "bpf_rlimit.h"
21 21
22#define DEV_CGROUP_PROG "./dev_cgroup.o" 22#define DEV_CGROUP_PROG "./dev_cgroup.o"
23 23
@@ -25,15 +25,11 @@
25 25
26int main(int argc, char **argv) 26int main(int argc, char **argv)
27{ 27{
28 struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
29 struct bpf_object *obj; 28 struct bpf_object *obj;
30 int error = EXIT_FAILURE; 29 int error = EXIT_FAILURE;
31 int prog_fd, cgroup_fd; 30 int prog_fd, cgroup_fd;
32 __u32 prog_cnt; 31 __u32 prog_cnt;
33 32
34 if (setrlimit(RLIMIT_MEMLOCK, &limit) < 0)
35 perror("Unable to lift memlock rlimit");
36
37 if (bpf_prog_load(DEV_CGROUP_PROG, BPF_PROG_TYPE_CGROUP_DEVICE, 33 if (bpf_prog_load(DEV_CGROUP_PROG, BPF_PROG_TYPE_CGROUP_DEVICE,
38 &obj, &prog_fd)) { 34 &obj, &prog_fd)) {
39 printf("Failed to load DEV_CGROUP program\n"); 35 printf("Failed to load DEV_CGROUP program\n");
diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c
index 2be87e9ee28d..147e34cfceb7 100644
--- a/tools/testing/selftests/bpf/test_lpm_map.c
+++ b/tools/testing/selftests/bpf/test_lpm_map.c
@@ -22,10 +22,11 @@
22#include <unistd.h> 22#include <unistd.h>
23#include <arpa/inet.h> 23#include <arpa/inet.h>
24#include <sys/time.h> 24#include <sys/time.h>
25#include <sys/resource.h>
26 25
27#include <bpf/bpf.h> 26#include <bpf/bpf.h>
27
28#include "bpf_util.h" 28#include "bpf_util.h"
29#include "bpf_rlimit.h"
29 30
30struct tlpm_node { 31struct tlpm_node {
31 struct tlpm_node *next; 32 struct tlpm_node *next;
@@ -736,17 +737,11 @@ static void test_lpm_multi_thread(void)
736 737
737int main(void) 738int main(void)
738{ 739{
739 struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY }; 740 int i;
740 int i, ret;
741 741
742 /* we want predictable, pseudo random tests */ 742 /* we want predictable, pseudo random tests */
743 srand(0xf00ba1); 743 srand(0xf00ba1);
744 744
745 /* allow unlimited locked memory */
746 ret = setrlimit(RLIMIT_MEMLOCK, &limit);
747 if (ret < 0)
748 perror("Unable to lift memlock rlimit");
749
750 test_lpm_basic(); 745 test_lpm_basic();
751 test_lpm_order(); 746 test_lpm_order();
752 747
@@ -755,11 +750,8 @@ int main(void)
755 test_lpm_map(i); 750 test_lpm_map(i);
756 751
757 test_lpm_ipaddr(); 752 test_lpm_ipaddr();
758
759 test_lpm_delete(); 753 test_lpm_delete();
760
761 test_lpm_get_next_key(); 754 test_lpm_get_next_key();
762
763 test_lpm_multi_thread(); 755 test_lpm_multi_thread();
764 756
765 printf("test_lpm: OK\n"); 757 printf("test_lpm: OK\n");
diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c
index 8c10c9180c1a..781c7de343be 100644
--- a/tools/testing/selftests/bpf/test_lru_map.c
+++ b/tools/testing/selftests/bpf/test_lru_map.c
@@ -16,10 +16,11 @@
16#include <time.h> 16#include <time.h>
17 17
18#include <sys/wait.h> 18#include <sys/wait.h>
19#include <sys/resource.h>
20 19
21#include <bpf/bpf.h> 20#include <bpf/bpf.h>
21
22#include "bpf_util.h" 22#include "bpf_util.h"
23#include "bpf_rlimit.h"
23 24
24#define LOCAL_FREE_TARGET (128) 25#define LOCAL_FREE_TARGET (128)
25#define PERCPU_FREE_TARGET (4) 26#define PERCPU_FREE_TARGET (4)
@@ -613,7 +614,6 @@ static void test_lru_sanity6(int map_type, int map_flags, int tgt_free)
613 614
614int main(int argc, char **argv) 615int main(int argc, char **argv)
615{ 616{
616 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
617 int map_types[] = {BPF_MAP_TYPE_LRU_HASH, 617 int map_types[] = {BPF_MAP_TYPE_LRU_HASH,
618 BPF_MAP_TYPE_LRU_PERCPU_HASH}; 618 BPF_MAP_TYPE_LRU_PERCPU_HASH};
619 int map_flags[] = {0, BPF_F_NO_COMMON_LRU}; 619 int map_flags[] = {0, BPF_F_NO_COMMON_LRU};
@@ -621,8 +621,6 @@ int main(int argc, char **argv)
621 621
622 setbuf(stdout, NULL); 622 setbuf(stdout, NULL);
623 623
624 assert(!setrlimit(RLIMIT_MEMLOCK, &r));
625
626 nr_cpus = bpf_num_possible_cpus(); 624 nr_cpus = bpf_num_possible_cpus();
627 assert(nr_cpus != -1); 625 assert(nr_cpus != -1);
628 printf("nr_cpus:%d\n\n", nr_cpus); 626 printf("nr_cpus:%d\n\n", nr_cpus);
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 9e03a4c356a4..6c253343a6f9 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -17,13 +17,14 @@
17#include <stdlib.h> 17#include <stdlib.h>
18 18
19#include <sys/wait.h> 19#include <sys/wait.h>
20#include <sys/resource.h>
21 20
22#include <linux/bpf.h> 21#include <linux/bpf.h>
23 22
24#include <bpf/bpf.h> 23#include <bpf/bpf.h>
25#include <bpf/libbpf.h> 24#include <bpf/libbpf.h>
25
26#include "bpf_util.h" 26#include "bpf_util.h"
27#include "bpf_rlimit.h"
27 28
28static int map_flags; 29static int map_flags;
29 30
@@ -463,15 +464,17 @@ static void test_devmap(int task, void *data)
463#include <linux/err.h> 464#include <linux/err.h>
464#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o" 465#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
465#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o" 466#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
467#define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
466static void test_sockmap(int tasks, void *data) 468static void test_sockmap(int tasks, void *data)
467{ 469{
468 int one = 1, map_fd_rx = 0, map_fd_tx = 0, map_fd_break, s, sc, rc; 470 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
469 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break; 471 int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
470 int ports[] = {50200, 50201, 50202, 50204}; 472 int ports[] = {50200, 50201, 50202, 50204};
471 int err, i, fd, udp, sfd[6] = {0xdeadbeef}; 473 int err, i, fd, udp, sfd[6] = {0xdeadbeef};
472 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 474 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
473 int parse_prog, verdict_prog; 475 int parse_prog, verdict_prog, msg_prog;
474 struct sockaddr_in addr; 476 struct sockaddr_in addr;
477 int one = 1, s, sc, rc;
475 struct bpf_object *obj; 478 struct bpf_object *obj;
476 struct timeval to; 479 struct timeval to;
477 __u32 key, value; 480 __u32 key, value;
@@ -583,6 +586,12 @@ static void test_sockmap(int tasks, void *data)
583 goto out_sockmap; 586 goto out_sockmap;
584 } 587 }
585 588
589 err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0);
590 if (!err) {
591 printf("Failed invalid msg verdict prog attach\n");
592 goto out_sockmap;
593 }
594
586 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 595 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
587 if (!err) { 596 if (!err) {
588 printf("Failed unknown prog attach\n"); 597 printf("Failed unknown prog attach\n");
@@ -601,6 +610,12 @@ static void test_sockmap(int tasks, void *data)
601 goto out_sockmap; 610 goto out_sockmap;
602 } 611 }
603 612
613 err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
614 if (err) {
615 printf("Failed empty msg verdict prog detach\n");
616 goto out_sockmap;
617 }
618
604 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 619 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
605 if (!err) { 620 if (!err) {
606 printf("Detach invalid prog successful\n"); 621 printf("Detach invalid prog successful\n");
@@ -615,6 +630,13 @@ static void test_sockmap(int tasks, void *data)
615 goto out_sockmap; 630 goto out_sockmap;
616 } 631 }
617 632
633 err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG,
634 BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog);
635 if (err) {
636 printf("Failed to load SK_SKB msg prog\n");
637 goto out_sockmap;
638 }
639
618 err = bpf_prog_load(SOCKMAP_VERDICT_PROG, 640 err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
619 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); 641 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
620 if (err) { 642 if (err) {
@@ -630,7 +652,7 @@ static void test_sockmap(int tasks, void *data)
630 652
631 map_fd_rx = bpf_map__fd(bpf_map_rx); 653 map_fd_rx = bpf_map__fd(bpf_map_rx);
632 if (map_fd_rx < 0) { 654 if (map_fd_rx < 0) {
633 printf("Failed to get map fd\n"); 655 printf("Failed to get map rx fd\n");
634 goto out_sockmap; 656 goto out_sockmap;
635 } 657 }
636 658
@@ -646,6 +668,18 @@ static void test_sockmap(int tasks, void *data)
646 goto out_sockmap; 668 goto out_sockmap;
647 } 669 }
648 670
671 bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg");
672 if (IS_ERR(bpf_map_msg)) {
673 printf("Failed to load map msg from msg_verdict prog\n");
674 goto out_sockmap;
675 }
676
677 map_fd_msg = bpf_map__fd(bpf_map_msg);
678 if (map_fd_msg < 0) {
679 printf("Failed to get map msg fd\n");
680 goto out_sockmap;
681 }
682
649 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 683 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
650 if (IS_ERR(bpf_map_break)) { 684 if (IS_ERR(bpf_map_break)) {
651 printf("Failed to load map tx from verdict prog\n"); 685 printf("Failed to load map tx from verdict prog\n");
@@ -679,6 +713,12 @@ static void test_sockmap(int tasks, void *data)
679 goto out_sockmap; 713 goto out_sockmap;
680 } 714 }
681 715
716 err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0);
717 if (err) {
718 printf("Failed msg verdict bpf prog attach\n");
719 goto out_sockmap;
720 }
721
682 err = bpf_prog_attach(verdict_prog, map_fd_rx, 722 err = bpf_prog_attach(verdict_prog, map_fd_rx,
683 __MAX_BPF_ATTACH_TYPE, 0); 723 __MAX_BPF_ATTACH_TYPE, 0);
684 if (!err) { 724 if (!err) {
@@ -718,6 +758,14 @@ static void test_sockmap(int tasks, void *data)
718 } 758 }
719 } 759 }
720 760
761 /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
762 i = 0;
763 err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY);
764 if (err) {
765 printf("Failed map_fd_msg update sockmap %i\n", err);
766 goto out_sockmap;
767 }
768
721 /* Test map send/recv */ 769 /* Test map send/recv */
722 for (i = 0; i < 2; i++) { 770 for (i = 0; i < 2; i++) {
723 buf[0] = i; 771 buf[0] = i;
@@ -1126,10 +1174,6 @@ static void run_all_tests(void)
1126 1174
1127int main(void) 1175int main(void)
1128{ 1176{
1129 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
1130
1131 setrlimit(RLIMIT_MEMLOCK, &rinf);
1132
1133 map_flags = 0; 1177 map_flags = 0;
1134 run_all_tests(); 1178 run_all_tests();
1135 1179
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index b549308abd19..4123d0ab90ba 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -26,7 +26,6 @@ typedef __u16 __sum16;
26 26
27#include <sys/ioctl.h> 27#include <sys/ioctl.h>
28#include <sys/wait.h> 28#include <sys/wait.h>
29#include <sys/resource.h>
30#include <sys/types.h> 29#include <sys/types.h>
31#include <fcntl.h> 30#include <fcntl.h>
32 31
@@ -34,9 +33,11 @@ typedef __u16 __sum16;
34#include <linux/err.h> 33#include <linux/err.h>
35#include <bpf/bpf.h> 34#include <bpf/bpf.h>
36#include <bpf/libbpf.h> 35#include <bpf/libbpf.h>
36
37#include "test_iptunnel_common.h" 37#include "test_iptunnel_common.h"
38#include "bpf_util.h" 38#include "bpf_util.h"
39#include "bpf_endian.h" 39#include "bpf_endian.h"
40#include "bpf_rlimit.h"
40 41
41static int error_cnt, pass_cnt; 42static int error_cnt, pass_cnt;
42 43
@@ -840,7 +841,8 @@ static void test_tp_attach_query(void)
840static int compare_map_keys(int map1_fd, int map2_fd) 841static int compare_map_keys(int map1_fd, int map2_fd)
841{ 842{
842 __u32 key, next_key; 843 __u32 key, next_key;
843 char val_buf[PERF_MAX_STACK_DEPTH * sizeof(__u64)]; 844 char val_buf[PERF_MAX_STACK_DEPTH *
845 sizeof(struct bpf_stack_build_id)];
844 int err; 846 int err;
845 847
846 err = bpf_map_get_next_key(map1_fd, NULL, &key); 848 err = bpf_map_get_next_key(map1_fd, NULL, &key);
@@ -875,7 +877,7 @@ static void test_stacktrace_map()
875 877
876 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd); 878 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
877 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno)) 879 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
878 goto out; 880 return;
879 881
880 /* Get the ID for the sched/sched_switch tracepoint */ 882 /* Get the ID for the sched/sched_switch tracepoint */
881 snprintf(buf, sizeof(buf), 883 snprintf(buf, sizeof(buf),
@@ -886,6 +888,181 @@ static void test_stacktrace_map()
886 888
887 bytes = read(efd, buf, sizeof(buf)); 889 bytes = read(efd, buf, sizeof(buf));
888 close(efd); 890 close(efd);
891 if (bytes <= 0 || bytes >= sizeof(buf))
892 goto close_prog;
893
894 /* Open the perf event and attach bpf progrram */
895 attr.config = strtol(buf, NULL, 0);
896 attr.type = PERF_TYPE_TRACEPOINT;
897 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
898 attr.sample_period = 1;
899 attr.wakeup_events = 1;
900 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
901 0 /* cpu 0 */, -1 /* group id */,
902 0 /* flags */);
903 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n",
904 pmu_fd, errno))
905 goto close_prog;
906
907 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
908 if (err)
909 goto disable_pmu;
910
911 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
912 if (err)
913 goto disable_pmu;
914
915 /* find map fds */
916 control_map_fd = bpf_find_map(__func__, obj, "control_map");
917 if (control_map_fd < 0)
918 goto disable_pmu;
919
920 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
921 if (stackid_hmap_fd < 0)
922 goto disable_pmu;
923
924 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
925 if (stackmap_fd < 0)
926 goto disable_pmu;
927
928 /* give some time for bpf program run */
929 sleep(1);
930
931 /* disable stack trace collection */
932 key = 0;
933 val = 1;
934 bpf_map_update_elem(control_map_fd, &key, &val, 0);
935
936 /* for every element in stackid_hmap, we can find a corresponding one
937 * in stackmap, and vise versa.
938 */
939 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
940 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
941 "err %d errno %d\n", err, errno))
942 goto disable_pmu_noerr;
943
944 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
945 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
946 "err %d errno %d\n", err, errno))
947 goto disable_pmu_noerr;
948
949 goto disable_pmu_noerr;
950disable_pmu:
951 error_cnt++;
952disable_pmu_noerr:
953 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
954 close(pmu_fd);
955close_prog:
956 bpf_object__close(obj);
957}
958
959static void test_stacktrace_map_raw_tp()
960{
961 int control_map_fd, stackid_hmap_fd, stackmap_fd;
962 const char *file = "./test_stacktrace_map.o";
963 int efd, err, prog_fd;
964 __u32 key, val, duration = 0;
965 struct bpf_object *obj;
966
967 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
968 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
969 return;
970
971 efd = bpf_raw_tracepoint_open("sched_switch", prog_fd);
972 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
973 goto close_prog;
974
975 /* find map fds */
976 control_map_fd = bpf_find_map(__func__, obj, "control_map");
977 if (control_map_fd < 0)
978 goto close_prog;
979
980 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
981 if (stackid_hmap_fd < 0)
982 goto close_prog;
983
984 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
985 if (stackmap_fd < 0)
986 goto close_prog;
987
988 /* give some time for bpf program run */
989 sleep(1);
990
991 /* disable stack trace collection */
992 key = 0;
993 val = 1;
994 bpf_map_update_elem(control_map_fd, &key, &val, 0);
995
996 /* for every element in stackid_hmap, we can find a corresponding one
997 * in stackmap, and vise versa.
998 */
999 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1000 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1001 "err %d errno %d\n", err, errno))
1002 goto close_prog;
1003
1004 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1005 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1006 "err %d errno %d\n", err, errno))
1007 goto close_prog;
1008
1009 goto close_prog_noerr;
1010close_prog:
1011 error_cnt++;
1012close_prog_noerr:
1013 bpf_object__close(obj);
1014}
1015
1016static int extract_build_id(char *build_id, size_t size)
1017{
1018 FILE *fp;
1019 char *line = NULL;
1020 size_t len = 0;
1021
1022 fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r");
1023 if (fp == NULL)
1024 return -1;
1025
1026 if (getline(&line, &len, fp) == -1)
1027 goto err;
1028 fclose(fp);
1029
1030 if (len > size)
1031 len = size;
1032 memcpy(build_id, line, len);
1033 build_id[len] = '\0';
1034 return 0;
1035err:
1036 fclose(fp);
1037 return -1;
1038}
1039
1040static void test_stacktrace_build_id(void)
1041{
1042 int control_map_fd, stackid_hmap_fd, stackmap_fd;
1043 const char *file = "./test_stacktrace_build_id.o";
1044 int bytes, efd, err, pmu_fd, prog_fd;
1045 struct perf_event_attr attr = {};
1046 __u32 key, previous_key, val, duration = 0;
1047 struct bpf_object *obj;
1048 char buf[256];
1049 int i, j;
1050 struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
1051 int build_id_matches = 0;
1052
1053 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1054 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1055 goto out;
1056
1057 /* Get the ID for the sched/sched_switch tracepoint */
1058 snprintf(buf, sizeof(buf),
1059 "/sys/kernel/debug/tracing/events/random/urandom_read/id");
1060 efd = open(buf, O_RDONLY, 0);
1061 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1062 goto close_prog;
1063
1064 bytes = read(efd, buf, sizeof(buf));
1065 close(efd);
889 if (CHECK(bytes <= 0 || bytes >= sizeof(buf), 1066 if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
890 "read", "bytes %d errno %d\n", bytes, errno)) 1067 "read", "bytes %d errno %d\n", bytes, errno))
891 goto close_prog; 1068 goto close_prog;
@@ -929,9 +1106,9 @@ static void test_stacktrace_map()
929 err, errno)) 1106 err, errno))
930 goto disable_pmu; 1107 goto disable_pmu;
931 1108
932 /* give some time for bpf program run */ 1109 assert(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null")
933 sleep(1); 1110 == 0);
934 1111 assert(system("./urandom_read") == 0);
935 /* disable stack trace collection */ 1112 /* disable stack trace collection */
936 key = 0; 1113 key = 0;
937 val = 1; 1114 val = 1;
@@ -948,7 +1125,40 @@ static void test_stacktrace_map()
948 err = compare_map_keys(stackmap_fd, stackid_hmap_fd); 1125 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
949 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap", 1126 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
950 "err %d errno %d\n", err, errno)) 1127 "err %d errno %d\n", err, errno))
951 ; /* fall through */ 1128 goto disable_pmu;
1129
1130 err = extract_build_id(buf, 256);
1131
1132 if (CHECK(err, "get build_id with readelf",
1133 "err %d errno %d\n", err, errno))
1134 goto disable_pmu;
1135
1136 err = bpf_map_get_next_key(stackmap_fd, NULL, &key);
1137 if (CHECK(err, "get_next_key from stackmap",
1138 "err %d, errno %d\n", err, errno))
1139 goto disable_pmu;
1140
1141 do {
1142 char build_id[64];
1143
1144 err = bpf_map_lookup_elem(stackmap_fd, &key, id_offs);
1145 if (CHECK(err, "lookup_elem from stackmap",
1146 "err %d, errno %d\n", err, errno))
1147 goto disable_pmu;
1148 for (i = 0; i < PERF_MAX_STACK_DEPTH; ++i)
1149 if (id_offs[i].status == BPF_STACK_BUILD_ID_VALID &&
1150 id_offs[i].offset != 0) {
1151 for (j = 0; j < 20; ++j)
1152 sprintf(build_id + 2 * j, "%02x",
1153 id_offs[i].build_id[j] & 0xff);
1154 if (strstr(buf, build_id) != NULL)
1155 build_id_matches = 1;
1156 }
1157 previous_key = key;
1158 } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
1159
1160 CHECK(build_id_matches < 1, "build id match",
1161 "Didn't find expected build ID from the map\n");
952 1162
953disable_pmu: 1163disable_pmu:
954 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE); 1164 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
@@ -965,10 +1175,6 @@ out:
965 1175
966int main(void) 1176int main(void)
967{ 1177{
968 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
969
970 setrlimit(RLIMIT_MEMLOCK, &rinf);
971
972 test_pkt_access(); 1178 test_pkt_access();
973 test_xdp(); 1179 test_xdp();
974 test_l4lb_all(); 1180 test_l4lb_all();
@@ -979,6 +1185,8 @@ int main(void)
979 test_obj_name(); 1185 test_obj_name();
980 test_tp_attach_query(); 1186 test_tp_attach_query();
981 test_stacktrace_map(); 1187 test_stacktrace_map();
1188 test_stacktrace_build_id();
1189 test_stacktrace_map_raw_tp();
982 1190
983 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); 1191 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
984 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 1192 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/tools/testing/selftests/bpf/test_sock.c b/tools/testing/selftests/bpf/test_sock.c
new file mode 100644
index 000000000000..f4d99fabc56d
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_sock.c
@@ -0,0 +1,480 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <stdio.h>
5#include <unistd.h>
6
7#include <arpa/inet.h>
8#include <sys/types.h>
9#include <sys/socket.h>
10
11#include <linux/filter.h>
12
13#include <bpf/bpf.h>
14
15#include "cgroup_helpers.h"
16#include "bpf_rlimit.h"
17
18#ifndef ARRAY_SIZE
19# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
20#endif
21
22#define CG_PATH "/foo"
23#define MAX_INSNS 512
24
25char bpf_log_buf[BPF_LOG_BUF_SIZE];
26
27struct sock_test {
28 const char *descr;
29 /* BPF prog properties */
30 struct bpf_insn insns[MAX_INSNS];
31 enum bpf_attach_type expected_attach_type;
32 enum bpf_attach_type attach_type;
33 /* Socket properties */
34 int domain;
35 int type;
36 /* Endpoint to bind() to */
37 const char *ip;
38 unsigned short port;
39 /* Expected test result */
40 enum {
41 LOAD_REJECT,
42 ATTACH_REJECT,
43 BIND_REJECT,
44 SUCCESS,
45 } result;
46};
47
48static struct sock_test tests[] = {
49 {
50 "bind4 load with invalid access: src_ip6",
51 .insns = {
52 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
53 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
54 offsetof(struct bpf_sock, src_ip6[0])),
55 BPF_MOV64_IMM(BPF_REG_0, 1),
56 BPF_EXIT_INSN(),
57 },
58 BPF_CGROUP_INET4_POST_BIND,
59 BPF_CGROUP_INET4_POST_BIND,
60 0,
61 0,
62 NULL,
63 0,
64 LOAD_REJECT,
65 },
66 {
67 "bind4 load with invalid access: mark",
68 .insns = {
69 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
70 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
71 offsetof(struct bpf_sock, mark)),
72 BPF_MOV64_IMM(BPF_REG_0, 1),
73 BPF_EXIT_INSN(),
74 },
75 BPF_CGROUP_INET4_POST_BIND,
76 BPF_CGROUP_INET4_POST_BIND,
77 0,
78 0,
79 NULL,
80 0,
81 LOAD_REJECT,
82 },
83 {
84 "bind6 load with invalid access: src_ip4",
85 .insns = {
86 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
87 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
88 offsetof(struct bpf_sock, src_ip4)),
89 BPF_MOV64_IMM(BPF_REG_0, 1),
90 BPF_EXIT_INSN(),
91 },
92 BPF_CGROUP_INET6_POST_BIND,
93 BPF_CGROUP_INET6_POST_BIND,
94 0,
95 0,
96 NULL,
97 0,
98 LOAD_REJECT,
99 },
100 {
101 "sock_create load with invalid access: src_port",
102 .insns = {
103 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
104 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
105 offsetof(struct bpf_sock, src_port)),
106 BPF_MOV64_IMM(BPF_REG_0, 1),
107 BPF_EXIT_INSN(),
108 },
109 BPF_CGROUP_INET_SOCK_CREATE,
110 BPF_CGROUP_INET_SOCK_CREATE,
111 0,
112 0,
113 NULL,
114 0,
115 LOAD_REJECT,
116 },
117 {
118 "sock_create load w/o expected_attach_type (compat mode)",
119 .insns = {
120 BPF_MOV64_IMM(BPF_REG_0, 1),
121 BPF_EXIT_INSN(),
122 },
123 0,
124 BPF_CGROUP_INET_SOCK_CREATE,
125 AF_INET,
126 SOCK_STREAM,
127 "127.0.0.1",
128 8097,
129 SUCCESS,
130 },
131 {
132 "sock_create load w/ expected_attach_type",
133 .insns = {
134 BPF_MOV64_IMM(BPF_REG_0, 1),
135 BPF_EXIT_INSN(),
136 },
137 BPF_CGROUP_INET_SOCK_CREATE,
138 BPF_CGROUP_INET_SOCK_CREATE,
139 AF_INET,
140 SOCK_STREAM,
141 "127.0.0.1",
142 8097,
143 SUCCESS,
144 },
145 {
146 "attach type mismatch bind4 vs bind6",
147 .insns = {
148 BPF_MOV64_IMM(BPF_REG_0, 1),
149 BPF_EXIT_INSN(),
150 },
151 BPF_CGROUP_INET4_POST_BIND,
152 BPF_CGROUP_INET6_POST_BIND,
153 0,
154 0,
155 NULL,
156 0,
157 ATTACH_REJECT,
158 },
159 {
160 "attach type mismatch bind6 vs bind4",
161 .insns = {
162 BPF_MOV64_IMM(BPF_REG_0, 1),
163 BPF_EXIT_INSN(),
164 },
165 BPF_CGROUP_INET6_POST_BIND,
166 BPF_CGROUP_INET4_POST_BIND,
167 0,
168 0,
169 NULL,
170 0,
171 ATTACH_REJECT,
172 },
173 {
174 "attach type mismatch default vs bind4",
175 .insns = {
176 BPF_MOV64_IMM(BPF_REG_0, 1),
177 BPF_EXIT_INSN(),
178 },
179 0,
180 BPF_CGROUP_INET4_POST_BIND,
181 0,
182 0,
183 NULL,
184 0,
185 ATTACH_REJECT,
186 },
187 {
188 "attach type mismatch bind6 vs sock_create",
189 .insns = {
190 BPF_MOV64_IMM(BPF_REG_0, 1),
191 BPF_EXIT_INSN(),
192 },
193 BPF_CGROUP_INET6_POST_BIND,
194 BPF_CGROUP_INET_SOCK_CREATE,
195 0,
196 0,
197 NULL,
198 0,
199 ATTACH_REJECT,
200 },
201 {
202 "bind4 reject all",
203 .insns = {
204 BPF_MOV64_IMM(BPF_REG_0, 0),
205 BPF_EXIT_INSN(),
206 },
207 BPF_CGROUP_INET4_POST_BIND,
208 BPF_CGROUP_INET4_POST_BIND,
209 AF_INET,
210 SOCK_STREAM,
211 "0.0.0.0",
212 0,
213 BIND_REJECT,
214 },
215 {
216 "bind6 reject all",
217 .insns = {
218 BPF_MOV64_IMM(BPF_REG_0, 0),
219 BPF_EXIT_INSN(),
220 },
221 BPF_CGROUP_INET6_POST_BIND,
222 BPF_CGROUP_INET6_POST_BIND,
223 AF_INET6,
224 SOCK_STREAM,
225 "::",
226 0,
227 BIND_REJECT,
228 },
229 {
230 "bind6 deny specific IP & port",
231 .insns = {
232 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
233
234 /* if (ip == expected && port == expected) */
235 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
236 offsetof(struct bpf_sock, src_ip6[3])),
237 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x01000000, 4),
238 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
239 offsetof(struct bpf_sock, src_port)),
240 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x2001, 2),
241
242 /* return DENY; */
243 BPF_MOV64_IMM(BPF_REG_0, 0),
244 BPF_JMP_A(1),
245
246 /* else return ALLOW; */
247 BPF_MOV64_IMM(BPF_REG_0, 1),
248 BPF_EXIT_INSN(),
249 },
250 BPF_CGROUP_INET6_POST_BIND,
251 BPF_CGROUP_INET6_POST_BIND,
252 AF_INET6,
253 SOCK_STREAM,
254 "::1",
255 8193,
256 BIND_REJECT,
257 },
258 {
259 "bind4 allow specific IP & port",
260 .insns = {
261 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
262
263 /* if (ip == expected && port == expected) */
264 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
265 offsetof(struct bpf_sock, src_ip4)),
266 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x0100007F, 4),
267 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
268 offsetof(struct bpf_sock, src_port)),
269 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x1002, 2),
270
271 /* return ALLOW; */
272 BPF_MOV64_IMM(BPF_REG_0, 1),
273 BPF_JMP_A(1),
274
275 /* else return DENY; */
276 BPF_MOV64_IMM(BPF_REG_0, 0),
277 BPF_EXIT_INSN(),
278 },
279 BPF_CGROUP_INET4_POST_BIND,
280 BPF_CGROUP_INET4_POST_BIND,
281 AF_INET,
282 SOCK_STREAM,
283 "127.0.0.1",
284 4098,
285 SUCCESS,
286 },
287 {
288 "bind4 allow all",
289 .insns = {
290 BPF_MOV64_IMM(BPF_REG_0, 1),
291 BPF_EXIT_INSN(),
292 },
293 BPF_CGROUP_INET4_POST_BIND,
294 BPF_CGROUP_INET4_POST_BIND,
295 AF_INET,
296 SOCK_STREAM,
297 "0.0.0.0",
298 0,
299 SUCCESS,
300 },
301 {
302 "bind6 allow all",
303 .insns = {
304 BPF_MOV64_IMM(BPF_REG_0, 1),
305 BPF_EXIT_INSN(),
306 },
307 BPF_CGROUP_INET6_POST_BIND,
308 BPF_CGROUP_INET6_POST_BIND,
309 AF_INET6,
310 SOCK_STREAM,
311 "::",
312 0,
313 SUCCESS,
314 },
315};
316
317static size_t probe_prog_length(const struct bpf_insn *fp)
318{
319 size_t len;
320
321 for (len = MAX_INSNS - 1; len > 0; --len)
322 if (fp[len].code != 0 || fp[len].imm != 0)
323 break;
324 return len + 1;
325}
326
327static int load_sock_prog(const struct bpf_insn *prog,
328 enum bpf_attach_type attach_type)
329{
330 struct bpf_load_program_attr attr;
331
332 memset(&attr, 0, sizeof(struct bpf_load_program_attr));
333 attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK;
334 attr.expected_attach_type = attach_type;
335 attr.insns = prog;
336 attr.insns_cnt = probe_prog_length(attr.insns);
337 attr.license = "GPL";
338
339 return bpf_load_program_xattr(&attr, bpf_log_buf, BPF_LOG_BUF_SIZE);
340}
341
342static int attach_sock_prog(int cgfd, int progfd,
343 enum bpf_attach_type attach_type)
344{
345 return bpf_prog_attach(progfd, cgfd, attach_type, BPF_F_ALLOW_OVERRIDE);
346}
347
348static int bind_sock(int domain, int type, const char *ip, unsigned short port)
349{
350 struct sockaddr_storage addr;
351 struct sockaddr_in6 *addr6;
352 struct sockaddr_in *addr4;
353 int sockfd = -1;
354 socklen_t len;
355 int err = 0;
356
357 sockfd = socket(domain, type, 0);
358 if (sockfd < 0)
359 goto err;
360
361 memset(&addr, 0, sizeof(addr));
362
363 if (domain == AF_INET) {
364 len = sizeof(struct sockaddr_in);
365 addr4 = (struct sockaddr_in *)&addr;
366 addr4->sin_family = domain;
367 addr4->sin_port = htons(port);
368 if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1)
369 goto err;
370 } else if (domain == AF_INET6) {
371 len = sizeof(struct sockaddr_in6);
372 addr6 = (struct sockaddr_in6 *)&addr;
373 addr6->sin6_family = domain;
374 addr6->sin6_port = htons(port);
375 if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1)
376 goto err;
377 } else {
378 goto err;
379 }
380
381 if (bind(sockfd, (const struct sockaddr *)&addr, len) == -1)
382 goto err;
383
384 goto out;
385err:
386 err = -1;
387out:
388 close(sockfd);
389 return err;
390}
391
392static int run_test_case(int cgfd, const struct sock_test *test)
393{
394 int progfd = -1;
395 int err = 0;
396
397 printf("Test case: %s .. ", test->descr);
398 progfd = load_sock_prog(test->insns, test->expected_attach_type);
399 if (progfd < 0) {
400 if (test->result == LOAD_REJECT)
401 goto out;
402 else
403 goto err;
404 }
405
406 if (attach_sock_prog(cgfd, progfd, test->attach_type) == -1) {
407 if (test->result == ATTACH_REJECT)
408 goto out;
409 else
410 goto err;
411 }
412
413 if (bind_sock(test->domain, test->type, test->ip, test->port) == -1) {
414 /* sys_bind() may fail for different reasons, errno has to be
415 * checked to confirm that BPF program rejected it.
416 */
417 if (test->result == BIND_REJECT && errno == EPERM)
418 goto out;
419 else
420 goto err;
421 }
422
423
424 if (test->result != SUCCESS)
425 goto err;
426
427 goto out;
428err:
429 err = -1;
430out:
431 /* Detaching w/o checking return code: best effort attempt. */
432 if (progfd != -1)
433 bpf_prog_detach(cgfd, test->attach_type);
434 close(progfd);
435 printf("[%s]\n", err ? "FAIL" : "PASS");
436 return err;
437}
438
439static int run_tests(int cgfd)
440{
441 int passes = 0;
442 int fails = 0;
443 int i;
444
445 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
446 if (run_test_case(cgfd, &tests[i]))
447 ++fails;
448 else
449 ++passes;
450 }
451 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
452 return fails ? -1 : 0;
453}
454
455int main(int argc, char **argv)
456{
457 int cgfd = -1;
458 int err = 0;
459
460 if (setup_cgroup_environment())
461 goto err;
462
463 cgfd = create_and_get_cgroup(CG_PATH);
464 if (!cgfd)
465 goto err;
466
467 if (join_cgroup(CG_PATH))
468 goto err;
469
470 if (run_tests(cgfd))
471 goto err;
472
473 goto out;
474err:
475 err = -1;
476out:
477 close(cgfd);
478 cleanup_cgroup_environment();
479 return err;
480}
diff --git a/tools/testing/selftests/bpf/test_sock_addr.c b/tools/testing/selftests/bpf/test_sock_addr.c
new file mode 100644
index 000000000000..2950f80ba7fb
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_sock_addr.c
@@ -0,0 +1,589 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7
8#include <arpa/inet.h>
9#include <sys/types.h>
10#include <sys/socket.h>
11
12#include <linux/filter.h>
13
14#include <bpf/bpf.h>
15#include <bpf/libbpf.h>
16
17#include "cgroup_helpers.h"
18#include "bpf_rlimit.h"
19
20#define CG_PATH "/foo"
21#define CONNECT4_PROG_PATH "./connect4_prog.o"
22#define CONNECT6_PROG_PATH "./connect6_prog.o"
23
24#define SERV4_IP "192.168.1.254"
25#define SERV4_REWRITE_IP "127.0.0.1"
26#define SERV4_PORT 4040
27#define SERV4_REWRITE_PORT 4444
28
29#define SERV6_IP "face:b00c:1234:5678::abcd"
30#define SERV6_REWRITE_IP "::1"
31#define SERV6_PORT 6060
32#define SERV6_REWRITE_PORT 6666
33
34#define INET_NTOP_BUF 40
35
36typedef int (*load_fn)(enum bpf_attach_type, const char *comment);
37typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
38
39struct program {
40 enum bpf_attach_type type;
41 load_fn loadfn;
42 int fd;
43 const char *name;
44 enum bpf_attach_type invalid_type;
45};
46
47char bpf_log_buf[BPF_LOG_BUF_SIZE];
48
49static int mk_sockaddr(int domain, const char *ip, unsigned short port,
50 struct sockaddr *addr, socklen_t addr_len)
51{
52 struct sockaddr_in6 *addr6;
53 struct sockaddr_in *addr4;
54
55 if (domain != AF_INET && domain != AF_INET6) {
56 log_err("Unsupported address family");
57 return -1;
58 }
59
60 memset(addr, 0, addr_len);
61
62 if (domain == AF_INET) {
63 if (addr_len < sizeof(struct sockaddr_in))
64 return -1;
65 addr4 = (struct sockaddr_in *)addr;
66 addr4->sin_family = domain;
67 addr4->sin_port = htons(port);
68 if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) {
69 log_err("Invalid IPv4: %s", ip);
70 return -1;
71 }
72 } else if (domain == AF_INET6) {
73 if (addr_len < sizeof(struct sockaddr_in6))
74 return -1;
75 addr6 = (struct sockaddr_in6 *)addr;
76 addr6->sin6_family = domain;
77 addr6->sin6_port = htons(port);
78 if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) {
79 log_err("Invalid IPv6: %s", ip);
80 return -1;
81 }
82 }
83
84 return 0;
85}
86
87static int load_insns(enum bpf_attach_type attach_type,
88 const struct bpf_insn *insns, size_t insns_cnt,
89 const char *comment)
90{
91 struct bpf_load_program_attr load_attr;
92 int ret;
93
94 memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
95 load_attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
96 load_attr.expected_attach_type = attach_type;
97 load_attr.insns = insns;
98 load_attr.insns_cnt = insns_cnt;
99 load_attr.license = "GPL";
100
101 ret = bpf_load_program_xattr(&load_attr, bpf_log_buf, BPF_LOG_BUF_SIZE);
102 if (ret < 0 && comment) {
103 log_err(">>> Loading %s program error.\n"
104 ">>> Output from verifier:\n%s\n-------\n",
105 comment, bpf_log_buf);
106 }
107
108 return ret;
109}
110
111/* [1] These testing programs try to read different context fields, including
112 * narrow loads of different sizes from user_ip4 and user_ip6, and write to
113 * those allowed to be overridden.
114 *
115 * [2] BPF_LD_IMM64 & BPF_JMP_REG are used below whenever there is a need to
116 * compare a register with unsigned 32bit integer. BPF_JMP_IMM can't be used
117 * in such cases since it accepts only _signed_ 32bit integer as IMM
118 * argument. Also note that BPF_LD_IMM64 contains 2 instructions what matters
119 * to count jumps properly.
120 */
121
122static int bind4_prog_load(enum bpf_attach_type attach_type,
123 const char *comment)
124{
125 union {
126 uint8_t u4_addr8[4];
127 uint16_t u4_addr16[2];
128 uint32_t u4_addr32;
129 } ip4;
130 struct sockaddr_in addr4_rw;
131
132 if (inet_pton(AF_INET, SERV4_IP, (void *)&ip4) != 1) {
133 log_err("Invalid IPv4: %s", SERV4_IP);
134 return -1;
135 }
136
137 if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
138 (struct sockaddr *)&addr4_rw, sizeof(addr4_rw)) == -1)
139 return -1;
140
141 /* See [1]. */
142 struct bpf_insn insns[] = {
143 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
144
145 /* if (sk.family == AF_INET && */
146 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
147 offsetof(struct bpf_sock_addr, family)),
148 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 16),
149
150 /* (sk.type == SOCK_DGRAM || sk.type == SOCK_STREAM) && */
151 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
152 offsetof(struct bpf_sock_addr, type)),
153 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 1),
154 BPF_JMP_A(1),
155 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_STREAM, 12),
156
157 /* 1st_byte_of_user_ip4 == expected && */
158 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6,
159 offsetof(struct bpf_sock_addr, user_ip4)),
160 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[0], 10),
161
162 /* 1st_half_of_user_ip4 == expected && */
163 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6,
164 offsetof(struct bpf_sock_addr, user_ip4)),
165 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr16[0], 8),
166
167 /* whole_user_ip4 == expected) { */
168 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
169 offsetof(struct bpf_sock_addr, user_ip4)),
170 BPF_LD_IMM64(BPF_REG_8, ip4.u4_addr32), /* See [2]. */
171 BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 4),
172
173 /* user_ip4 = addr4_rw.sin_addr */
174 BPF_MOV32_IMM(BPF_REG_7, addr4_rw.sin_addr.s_addr),
175 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
176 offsetof(struct bpf_sock_addr, user_ip4)),
177
178 /* user_port = addr4_rw.sin_port */
179 BPF_MOV32_IMM(BPF_REG_7, addr4_rw.sin_port),
180 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
181 offsetof(struct bpf_sock_addr, user_port)),
182 /* } */
183
184 /* return 1 */
185 BPF_MOV64_IMM(BPF_REG_0, 1),
186 BPF_EXIT_INSN(),
187 };
188
189 return load_insns(attach_type, insns,
190 sizeof(insns) / sizeof(struct bpf_insn), comment);
191}
192
193static int bind6_prog_load(enum bpf_attach_type attach_type,
194 const char *comment)
195{
196 struct sockaddr_in6 addr6_rw;
197 struct in6_addr ip6;
198
199 if (inet_pton(AF_INET6, SERV6_IP, (void *)&ip6) != 1) {
200 log_err("Invalid IPv6: %s", SERV6_IP);
201 return -1;
202 }
203
204 if (mk_sockaddr(AF_INET6, SERV6_REWRITE_IP, SERV6_REWRITE_PORT,
205 (struct sockaddr *)&addr6_rw, sizeof(addr6_rw)) == -1)
206 return -1;
207
208 /* See [1]. */
209 struct bpf_insn insns[] = {
210 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
211
212 /* if (sk.family == AF_INET6 && */
213 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
214 offsetof(struct bpf_sock_addr, family)),
215 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18),
216
217 /* 5th_byte_of_user_ip6 == expected && */
218 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6,
219 offsetof(struct bpf_sock_addr, user_ip6[1])),
220 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip6.s6_addr[4], 16),
221
222 /* 3rd_half_of_user_ip6 == expected && */
223 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6,
224 offsetof(struct bpf_sock_addr, user_ip6[1])),
225 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip6.s6_addr16[2], 14),
226
227 /* last_word_of_user_ip6 == expected) { */
228 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
229 offsetof(struct bpf_sock_addr, user_ip6[3])),
230 BPF_LD_IMM64(BPF_REG_8, ip6.s6_addr32[3]), /* See [2]. */
231 BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 10),
232
233
234#define STORE_IPV6_WORD(N) \
235 BPF_MOV32_IMM(BPF_REG_7, addr6_rw.sin6_addr.s6_addr32[N]), \
236 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, \
237 offsetof(struct bpf_sock_addr, user_ip6[N]))
238
239 /* user_ip6 = addr6_rw.sin6_addr */
240 STORE_IPV6_WORD(0),
241 STORE_IPV6_WORD(1),
242 STORE_IPV6_WORD(2),
243 STORE_IPV6_WORD(3),
244
245 /* user_port = addr6_rw.sin6_port */
246 BPF_MOV32_IMM(BPF_REG_7, addr6_rw.sin6_port),
247 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
248 offsetof(struct bpf_sock_addr, user_port)),
249
250 /* } */
251
252 /* return 1 */
253 BPF_MOV64_IMM(BPF_REG_0, 1),
254 BPF_EXIT_INSN(),
255 };
256
257 return load_insns(attach_type, insns,
258 sizeof(insns) / sizeof(struct bpf_insn), comment);
259}
260
261static int connect_prog_load_path(const char *path,
262 enum bpf_attach_type attach_type,
263 const char *comment)
264{
265 struct bpf_prog_load_attr attr;
266 struct bpf_object *obj;
267 int prog_fd;
268
269 memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
270 attr.file = path;
271 attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
272 attr.expected_attach_type = attach_type;
273
274 if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) {
275 if (comment)
276 log_err(">>> Loading %s program at %s error.\n",
277 comment, path);
278 return -1;
279 }
280
281 return prog_fd;
282}
283
284static int connect4_prog_load(enum bpf_attach_type attach_type,
285 const char *comment)
286{
287 return connect_prog_load_path(CONNECT4_PROG_PATH, attach_type, comment);
288}
289
290static int connect6_prog_load(enum bpf_attach_type attach_type,
291 const char *comment)
292{
293 return connect_prog_load_path(CONNECT6_PROG_PATH, attach_type, comment);
294}
295
296static void print_ip_port(int sockfd, info_fn fn, const char *fmt)
297{
298 char addr_buf[INET_NTOP_BUF];
299 struct sockaddr_storage addr;
300 struct sockaddr_in6 *addr6;
301 struct sockaddr_in *addr4;
302 socklen_t addr_len;
303 unsigned short port;
304 void *nip;
305
306 addr_len = sizeof(struct sockaddr_storage);
307 memset(&addr, 0, addr_len);
308
309 if (fn(sockfd, (struct sockaddr *)&addr, (socklen_t *)&addr_len) == 0) {
310 if (addr.ss_family == AF_INET) {
311 addr4 = (struct sockaddr_in *)&addr;
312 nip = (void *)&addr4->sin_addr;
313 port = ntohs(addr4->sin_port);
314 } else if (addr.ss_family == AF_INET6) {
315 addr6 = (struct sockaddr_in6 *)&addr;
316 nip = (void *)&addr6->sin6_addr;
317 port = ntohs(addr6->sin6_port);
318 } else {
319 return;
320 }
321 const char *addr_str =
322 inet_ntop(addr.ss_family, nip, addr_buf, INET_NTOP_BUF);
323 printf(fmt, addr_str ? addr_str : "??", port);
324 }
325}
326
327static void print_local_ip_port(int sockfd, const char *fmt)
328{
329 print_ip_port(sockfd, getsockname, fmt);
330}
331
332static void print_remote_ip_port(int sockfd, const char *fmt)
333{
334 print_ip_port(sockfd, getpeername, fmt);
335}
336
337static int start_server(int type, const struct sockaddr_storage *addr,
338 socklen_t addr_len)
339{
340
341 int fd;
342
343 fd = socket(addr->ss_family, type, 0);
344 if (fd == -1) {
345 log_err("Failed to create server socket");
346 goto out;
347 }
348
349 if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) {
350 log_err("Failed to bind server socket");
351 goto close_out;
352 }
353
354 if (type == SOCK_STREAM) {
355 if (listen(fd, 128) == -1) {
356 log_err("Failed to listen on server socket");
357 goto close_out;
358 }
359 }
360
361 print_local_ip_port(fd, "\t Actual: bind(%s, %d)\n");
362
363 goto out;
364close_out:
365 close(fd);
366 fd = -1;
367out:
368 return fd;
369}
370
371static int connect_to_server(int type, const struct sockaddr_storage *addr,
372 socklen_t addr_len)
373{
374 int domain;
375 int fd;
376
377 domain = addr->ss_family;
378
379 if (domain != AF_INET && domain != AF_INET6) {
380 log_err("Unsupported address family");
381 return -1;
382 }
383
384 fd = socket(domain, type, 0);
385 if (fd == -1) {
386 log_err("Failed to creating client socket");
387 return -1;
388 }
389
390 if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) {
391 log_err("Fail to connect to server");
392 goto err;
393 }
394
395 print_remote_ip_port(fd, "\t Actual: connect(%s, %d)");
396 print_local_ip_port(fd, " from (%s, %d)\n");
397
398 return 0;
399err:
400 close(fd);
401 return -1;
402}
403
404static void print_test_case_num(int domain, int type)
405{
406 static int test_num;
407
408 printf("Test case #%d (%s/%s):\n", ++test_num,
409 (domain == AF_INET ? "IPv4" :
410 domain == AF_INET6 ? "IPv6" :
411 "unknown_domain"),
412 (type == SOCK_STREAM ? "TCP" :
413 type == SOCK_DGRAM ? "UDP" :
414 "unknown_type"));
415}
416
417static int run_test_case(int domain, int type, const char *ip,
418 unsigned short port)
419{
420 struct sockaddr_storage addr;
421 socklen_t addr_len = sizeof(addr);
422 int servfd = -1;
423 int err = 0;
424
425 print_test_case_num(domain, type);
426
427 if (mk_sockaddr(domain, ip, port, (struct sockaddr *)&addr,
428 addr_len) == -1)
429 return -1;
430
431 printf("\tRequested: bind(%s, %d) ..\n", ip, port);
432 servfd = start_server(type, &addr, addr_len);
433 if (servfd == -1)
434 goto err;
435
436 printf("\tRequested: connect(%s, %d) from (*, *) ..\n", ip, port);
437 if (connect_to_server(type, &addr, addr_len))
438 goto err;
439
440 goto out;
441err:
442 err = -1;
443out:
444 close(servfd);
445 return err;
446}
447
448static void close_progs_fds(struct program *progs, size_t prog_cnt)
449{
450 size_t i;
451
452 for (i = 0; i < prog_cnt; ++i) {
453 close(progs[i].fd);
454 progs[i].fd = -1;
455 }
456}
457
458static int load_and_attach_progs(int cgfd, struct program *progs,
459 size_t prog_cnt)
460{
461 size_t i;
462
463 for (i = 0; i < prog_cnt; ++i) {
464 printf("Load %s with invalid type (can pollute stderr) ",
465 progs[i].name);
466 fflush(stdout);
467 progs[i].fd = progs[i].loadfn(progs[i].invalid_type, NULL);
468 if (progs[i].fd != -1) {
469 log_err("Load with invalid type accepted for %s",
470 progs[i].name);
471 goto err;
472 }
473 printf("... REJECTED\n");
474
475 printf("Load %s with valid type", progs[i].name);
476 progs[i].fd = progs[i].loadfn(progs[i].type, progs[i].name);
477 if (progs[i].fd == -1) {
478 log_err("Failed to load program %s", progs[i].name);
479 goto err;
480 }
481 printf(" ... OK\n");
482
483 printf("Attach %s with invalid type", progs[i].name);
484 if (bpf_prog_attach(progs[i].fd, cgfd, progs[i].invalid_type,
485 BPF_F_ALLOW_OVERRIDE) != -1) {
486 log_err("Attach with invalid type accepted for %s",
487 progs[i].name);
488 goto err;
489 }
490 printf(" ... REJECTED\n");
491
492 printf("Attach %s with valid type", progs[i].name);
493 if (bpf_prog_attach(progs[i].fd, cgfd, progs[i].type,
494 BPF_F_ALLOW_OVERRIDE) == -1) {
495 log_err("Failed to attach program %s", progs[i].name);
496 goto err;
497 }
498 printf(" ... OK\n");
499 }
500
501 return 0;
502err:
503 close_progs_fds(progs, prog_cnt);
504 return -1;
505}
506
507static int run_domain_test(int domain, int cgfd, struct program *progs,
508 size_t prog_cnt, const char *ip, unsigned short port)
509{
510 int err = 0;
511
512 if (load_and_attach_progs(cgfd, progs, prog_cnt) == -1)
513 goto err;
514
515 if (run_test_case(domain, SOCK_STREAM, ip, port) == -1)
516 goto err;
517
518 if (run_test_case(domain, SOCK_DGRAM, ip, port) == -1)
519 goto err;
520
521 goto out;
522err:
523 err = -1;
524out:
525 close_progs_fds(progs, prog_cnt);
526 return err;
527}
528
529static int run_test(void)
530{
531 size_t inet6_prog_cnt;
532 size_t inet_prog_cnt;
533 int cgfd = -1;
534 int err = 0;
535
536 struct program inet6_progs[] = {
537 {BPF_CGROUP_INET6_BIND, bind6_prog_load, -1, "bind6",
538 BPF_CGROUP_INET4_BIND},
539 {BPF_CGROUP_INET6_CONNECT, connect6_prog_load, -1, "connect6",
540 BPF_CGROUP_INET4_CONNECT},
541 };
542 inet6_prog_cnt = sizeof(inet6_progs) / sizeof(struct program);
543
544 struct program inet_progs[] = {
545 {BPF_CGROUP_INET4_BIND, bind4_prog_load, -1, "bind4",
546 BPF_CGROUP_INET6_BIND},
547 {BPF_CGROUP_INET4_CONNECT, connect4_prog_load, -1, "connect4",
548 BPF_CGROUP_INET6_CONNECT},
549 };
550 inet_prog_cnt = sizeof(inet_progs) / sizeof(struct program);
551
552 if (setup_cgroup_environment())
553 goto err;
554
555 cgfd = create_and_get_cgroup(CG_PATH);
556 if (!cgfd)
557 goto err;
558
559 if (join_cgroup(CG_PATH))
560 goto err;
561
562 if (run_domain_test(AF_INET, cgfd, inet_progs, inet_prog_cnt, SERV4_IP,
563 SERV4_PORT) == -1)
564 goto err;
565
566 if (run_domain_test(AF_INET6, cgfd, inet6_progs, inet6_prog_cnt,
567 SERV6_IP, SERV6_PORT) == -1)
568 goto err;
569
570 goto out;
571err:
572 err = -1;
573out:
574 close(cgfd);
575 cleanup_cgroup_environment();
576 printf(err ? "### FAIL\n" : "### SUCCESS\n");
577 return err;
578}
579
580int main(int argc, char **argv)
581{
582 if (argc < 2) {
583 fprintf(stderr,
584 "%s has to be run via %s.sh. Skip direct run.\n",
585 argv[0], argv[0]);
586 exit(0);
587 }
588 return run_test();
589}
diff --git a/tools/testing/selftests/bpf/test_sock_addr.sh b/tools/testing/selftests/bpf/test_sock_addr.sh
new file mode 100755
index 000000000000..9832a875a828
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_sock_addr.sh
@@ -0,0 +1,57 @@
1#!/bin/sh
2
3set -eu
4
5ping_once()
6{
7 ping -${1} -q -c 1 -W 1 ${2%%/*} >/dev/null 2>&1
8}
9
10wait_for_ip()
11{
12 local _i
13 echo -n "Wait for testing IPv4/IPv6 to become available "
14 for _i in $(seq ${MAX_PING_TRIES}); do
15 echo -n "."
16 if ping_once 4 ${TEST_IPv4} && ping_once 6 ${TEST_IPv6}; then
17 echo " OK"
18 return
19 fi
20 done
21 echo 1>&2 "ERROR: Timeout waiting for test IP to become available."
22 exit 1
23}
24
25setup()
26{
27 # Create testing interfaces not to interfere with current environment.
28 ip link add dev ${TEST_IF} type veth peer name ${TEST_IF_PEER}
29 ip link set ${TEST_IF} up
30 ip link set ${TEST_IF_PEER} up
31
32 ip -4 addr add ${TEST_IPv4} dev ${TEST_IF}
33 ip -6 addr add ${TEST_IPv6} dev ${TEST_IF}
34 wait_for_ip
35}
36
37cleanup()
38{
39 ip link del ${TEST_IF} 2>/dev/null || :
40 ip link del ${TEST_IF_PEER} 2>/dev/null || :
41}
42
43main()
44{
45 trap cleanup EXIT 2 3 6 15
46 setup
47 ./test_sock_addr setup_done
48}
49
50BASENAME=$(basename $0 .sh)
51TEST_IF="${BASENAME}1"
52TEST_IF_PEER="${BASENAME}2"
53TEST_IPv4="127.0.0.4/8"
54TEST_IPv6="::6/128"
55MAX_PING_TRIES=5
56
57main
diff --git a/tools/testing/selftests/bpf/test_stacktrace_build_id.c b/tools/testing/selftests/bpf/test_stacktrace_build_id.c
new file mode 100644
index 000000000000..b755bd783ce5
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_stacktrace_build_id.c
@@ -0,0 +1,60 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <linux/bpf.h>
5#include "bpf_helpers.h"
6
7#ifndef PERF_MAX_STACK_DEPTH
8#define PERF_MAX_STACK_DEPTH 127
9#endif
10
11struct bpf_map_def SEC("maps") control_map = {
12 .type = BPF_MAP_TYPE_ARRAY,
13 .key_size = sizeof(__u32),
14 .value_size = sizeof(__u32),
15 .max_entries = 1,
16};
17
18struct bpf_map_def SEC("maps") stackid_hmap = {
19 .type = BPF_MAP_TYPE_HASH,
20 .key_size = sizeof(__u32),
21 .value_size = sizeof(__u32),
22 .max_entries = 10000,
23};
24
25struct bpf_map_def SEC("maps") stackmap = {
26 .type = BPF_MAP_TYPE_STACK_TRACE,
27 .key_size = sizeof(__u32),
28 .value_size = sizeof(struct bpf_stack_build_id)
29 * PERF_MAX_STACK_DEPTH,
30 .max_entries = 128,
31 .map_flags = BPF_F_STACK_BUILD_ID,
32};
33
34/* taken from /sys/kernel/debug/tracing/events/random/urandom_read/format */
35struct random_urandom_args {
36 unsigned long long pad;
37 int got_bits;
38 int pool_left;
39 int input_left;
40};
41
42SEC("tracepoint/random/urandom_read")
43int oncpu(struct random_urandom_args *args)
44{
45 __u32 key = 0, val = 0, *value_p;
46
47 value_p = bpf_map_lookup_elem(&control_map, &key);
48 if (value_p && *value_p)
49 return 0; /* skip if non-zero *value_p */
50
51 /* The size of stackmap and stackid_hmap should be the same */
52 key = bpf_get_stackid(args, &stackmap, BPF_F_USER_STACK);
53 if ((int)key >= 0)
54 bpf_map_update_elem(&stackid_hmap, &key, &val, 0);
55
56 return 0;
57}
58
59char _license[] SEC("license") = "GPL";
60__u32 _version SEC("version") = 1; /* ignored by tracepoints, required by libbpf.a */
diff --git a/tools/testing/selftests/bpf/test_tag.c b/tools/testing/selftests/bpf/test_tag.c
index 8b201895c569..6272c784ca2a 100644
--- a/tools/testing/selftests/bpf/test_tag.c
+++ b/tools/testing/selftests/bpf/test_tag.c
@@ -12,7 +12,6 @@
12#include <assert.h> 12#include <assert.h>
13 13
14#include <sys/socket.h> 14#include <sys/socket.h>
15#include <sys/resource.h>
16 15
17#include <linux/filter.h> 16#include <linux/filter.h>
18#include <linux/bpf.h> 17#include <linux/bpf.h>
@@ -21,6 +20,7 @@
21#include <bpf/bpf.h> 20#include <bpf/bpf.h>
22 21
23#include "../../../include/linux/filter.h" 22#include "../../../include/linux/filter.h"
23#include "bpf_rlimit.h"
24 24
25static struct bpf_insn prog[BPF_MAXINSNS]; 25static struct bpf_insn prog[BPF_MAXINSNS];
26 26
@@ -184,11 +184,9 @@ static void do_test(uint32_t *tests, int start_insns, int fd_map,
184 184
185int main(void) 185int main(void)
186{ 186{
187 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
188 uint32_t tests = 0; 187 uint32_t tests = 0;
189 int i, fd_map; 188 int i, fd_map;
190 189
191 setrlimit(RLIMIT_MEMLOCK, &rinf);
192 fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), 190 fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int),
193 sizeof(int), 1, BPF_F_NO_PREALLOC); 191 sizeof(int), 1, BPF_F_NO_PREALLOC);
194 assert(fd_map > 0); 192 assert(fd_map > 0);
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c
index 95a370f3d378..84ab5163c828 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_user.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c
@@ -11,12 +11,14 @@
11#include <linux/ptrace.h> 11#include <linux/ptrace.h>
12#include <linux/bpf.h> 12#include <linux/bpf.h>
13#include <sys/ioctl.h> 13#include <sys/ioctl.h>
14#include <sys/time.h>
14#include <sys/types.h> 15#include <sys/types.h>
15#include <sys/stat.h> 16#include <sys/stat.h>
16#include <fcntl.h> 17#include <fcntl.h>
17#include <bpf/bpf.h> 18#include <bpf/bpf.h>
18#include <bpf/libbpf.h> 19#include <bpf/libbpf.h>
19#include "bpf_util.h" 20#include "bpf_util.h"
21#include "bpf_rlimit.h"
20#include <linux/perf_event.h> 22#include <linux/perf_event.h>
21#include "test_tcpbpf.h" 23#include "test_tcpbpf.h"
22 24
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 437c0b1c9d21..3e7718b1a9ae 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -24,7 +24,6 @@
24#include <limits.h> 24#include <limits.h>
25 25
26#include <sys/capability.h> 26#include <sys/capability.h>
27#include <sys/resource.h>
28 27
29#include <linux/unistd.h> 28#include <linux/unistd.h>
30#include <linux/filter.h> 29#include <linux/filter.h>
@@ -41,7 +40,7 @@
41# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 40# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
42# endif 41# endif
43#endif 42#endif
44 43#include "bpf_rlimit.h"
45#include "../../../include/linux/filter.h" 44#include "../../../include/linux/filter.h"
46 45
47#ifndef ARRAY_SIZE 46#ifndef ARRAY_SIZE
@@ -57,6 +56,9 @@
57#define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) 56#define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0)
58#define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) 57#define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1)
59 58
59#define UNPRIV_SYSCTL "kernel/unprivileged_bpf_disabled"
60static bool unpriv_disabled = false;
61
60struct bpf_test { 62struct bpf_test {
61 const char *descr; 63 const char *descr;
62 struct bpf_insn insns[MAX_INSNS]; 64 struct bpf_insn insns[MAX_INSNS];
@@ -1595,6 +1597,60 @@ static struct bpf_test tests[] = {
1595 .prog_type = BPF_PROG_TYPE_SK_SKB, 1597 .prog_type = BPF_PROG_TYPE_SK_SKB,
1596 }, 1598 },
1597 { 1599 {
1600 "direct packet read for SK_MSG",
1601 .insns = {
1602 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
1603 offsetof(struct sk_msg_md, data)),
1604 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_1,
1605 offsetof(struct sk_msg_md, data_end)),
1606 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1607 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1608 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1609 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
1610 BPF_MOV64_IMM(BPF_REG_0, 0),
1611 BPF_EXIT_INSN(),
1612 },
1613 .result = ACCEPT,
1614 .prog_type = BPF_PROG_TYPE_SK_MSG,
1615 },
1616 {
1617 "direct packet write for SK_MSG",
1618 .insns = {
1619 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
1620 offsetof(struct sk_msg_md, data)),
1621 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_1,
1622 offsetof(struct sk_msg_md, data_end)),
1623 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1624 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1625 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1626 BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
1627 BPF_MOV64_IMM(BPF_REG_0, 0),
1628 BPF_EXIT_INSN(),
1629 },
1630 .result = ACCEPT,
1631 .prog_type = BPF_PROG_TYPE_SK_MSG,
1632 },
1633 {
1634 "overlapping checks for direct packet access SK_MSG",
1635 .insns = {
1636 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
1637 offsetof(struct sk_msg_md, data)),
1638 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_1,
1639 offsetof(struct sk_msg_md, data_end)),
1640 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1641 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1642 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 4),
1643 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
1644 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
1645 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
1646 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_2, 6),
1647 BPF_MOV64_IMM(BPF_REG_0, 0),
1648 BPF_EXIT_INSN(),
1649 },
1650 .result = ACCEPT,
1651 .prog_type = BPF_PROG_TYPE_SK_MSG,
1652 },
1653 {
1598 "check skb->mark is not writeable by sockets", 1654 "check skb->mark is not writeable by sockets",
1599 .insns = { 1655 .insns = {
1600 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 1656 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
@@ -2587,17 +2643,74 @@ static struct bpf_test tests[] = {
2587 .result = ACCEPT, 2643 .result = ACCEPT,
2588 }, 2644 },
2589 { 2645 {
2646 "runtime/jit: tail_call within bounds, prog once",
2647 .insns = {
2648 BPF_MOV64_IMM(BPF_REG_3, 0),
2649 BPF_LD_MAP_FD(BPF_REG_2, 0),
2650 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2651 BPF_FUNC_tail_call),
2652 BPF_MOV64_IMM(BPF_REG_0, 1),
2653 BPF_EXIT_INSN(),
2654 },
2655 .fixup_prog = { 1 },
2656 .result = ACCEPT,
2657 .retval = 42,
2658 },
2659 {
2660 "runtime/jit: tail_call within bounds, prog loop",
2661 .insns = {
2662 BPF_MOV64_IMM(BPF_REG_3, 1),
2663 BPF_LD_MAP_FD(BPF_REG_2, 0),
2664 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2665 BPF_FUNC_tail_call),
2666 BPF_MOV64_IMM(BPF_REG_0, 1),
2667 BPF_EXIT_INSN(),
2668 },
2669 .fixup_prog = { 1 },
2670 .result = ACCEPT,
2671 .retval = 41,
2672 },
2673 {
2674 "runtime/jit: tail_call within bounds, no prog",
2675 .insns = {
2676 BPF_MOV64_IMM(BPF_REG_3, 2),
2677 BPF_LD_MAP_FD(BPF_REG_2, 0),
2678 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2679 BPF_FUNC_tail_call),
2680 BPF_MOV64_IMM(BPF_REG_0, 1),
2681 BPF_EXIT_INSN(),
2682 },
2683 .fixup_prog = { 1 },
2684 .result = ACCEPT,
2685 .retval = 1,
2686 },
2687 {
2688 "runtime/jit: tail_call out of bounds",
2689 .insns = {
2690 BPF_MOV64_IMM(BPF_REG_3, 256),
2691 BPF_LD_MAP_FD(BPF_REG_2, 0),
2692 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2693 BPF_FUNC_tail_call),
2694 BPF_MOV64_IMM(BPF_REG_0, 2),
2695 BPF_EXIT_INSN(),
2696 },
2697 .fixup_prog = { 1 },
2698 .result = ACCEPT,
2699 .retval = 2,
2700 },
2701 {
2590 "runtime/jit: pass negative index to tail_call", 2702 "runtime/jit: pass negative index to tail_call",
2591 .insns = { 2703 .insns = {
2592 BPF_MOV64_IMM(BPF_REG_3, -1), 2704 BPF_MOV64_IMM(BPF_REG_3, -1),
2593 BPF_LD_MAP_FD(BPF_REG_2, 0), 2705 BPF_LD_MAP_FD(BPF_REG_2, 0),
2594 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 2706 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2595 BPF_FUNC_tail_call), 2707 BPF_FUNC_tail_call),
2596 BPF_MOV64_IMM(BPF_REG_0, 0), 2708 BPF_MOV64_IMM(BPF_REG_0, 2),
2597 BPF_EXIT_INSN(), 2709 BPF_EXIT_INSN(),
2598 }, 2710 },
2599 .fixup_prog = { 1 }, 2711 .fixup_prog = { 1 },
2600 .result = ACCEPT, 2712 .result = ACCEPT,
2713 .retval = 2,
2601 }, 2714 },
2602 { 2715 {
2603 "runtime/jit: pass > 32bit index to tail_call", 2716 "runtime/jit: pass > 32bit index to tail_call",
@@ -2606,11 +2719,12 @@ static struct bpf_test tests[] = {
2606 BPF_LD_MAP_FD(BPF_REG_2, 0), 2719 BPF_LD_MAP_FD(BPF_REG_2, 0),
2607 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 2720 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2608 BPF_FUNC_tail_call), 2721 BPF_FUNC_tail_call),
2609 BPF_MOV64_IMM(BPF_REG_0, 0), 2722 BPF_MOV64_IMM(BPF_REG_0, 2),
2610 BPF_EXIT_INSN(), 2723 BPF_EXIT_INSN(),
2611 }, 2724 },
2612 .fixup_prog = { 2 }, 2725 .fixup_prog = { 2 },
2613 .result = ACCEPT, 2726 .result = ACCEPT,
2727 .retval = 42,
2614 }, 2728 },
2615 { 2729 {
2616 "stack pointer arithmetic", 2730 "stack pointer arithmetic",
@@ -11164,6 +11278,94 @@ static struct bpf_test tests[] = {
11164 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 11278 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
11165 }, 11279 },
11166 { 11280 {
11281 "jit: lsh, rsh, arsh by 1",
11282 .insns = {
11283 BPF_MOV64_IMM(BPF_REG_0, 1),
11284 BPF_MOV64_IMM(BPF_REG_1, 0xff),
11285 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 1),
11286 BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 1),
11287 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x3fc, 1),
11288 BPF_EXIT_INSN(),
11289 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 1),
11290 BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 1),
11291 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0xff, 1),
11292 BPF_EXIT_INSN(),
11293 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_1, 1),
11294 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x7f, 1),
11295 BPF_EXIT_INSN(),
11296 BPF_MOV64_IMM(BPF_REG_0, 2),
11297 BPF_EXIT_INSN(),
11298 },
11299 .result = ACCEPT,
11300 .retval = 2,
11301 },
11302 {
11303 "jit: mov32 for ldimm64, 1",
11304 .insns = {
11305 BPF_MOV64_IMM(BPF_REG_0, 2),
11306 BPF_LD_IMM64(BPF_REG_1, 0xfeffffffffffffffULL),
11307 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 32),
11308 BPF_LD_IMM64(BPF_REG_2, 0xfeffffffULL),
11309 BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1),
11310 BPF_MOV64_IMM(BPF_REG_0, 1),
11311 BPF_EXIT_INSN(),
11312 },
11313 .result = ACCEPT,
11314 .retval = 2,
11315 },
11316 {
11317 "jit: mov32 for ldimm64, 2",
11318 .insns = {
11319 BPF_MOV64_IMM(BPF_REG_0, 1),
11320 BPF_LD_IMM64(BPF_REG_1, 0x1ffffffffULL),
11321 BPF_LD_IMM64(BPF_REG_2, 0xffffffffULL),
11322 BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1),
11323 BPF_MOV64_IMM(BPF_REG_0, 2),
11324 BPF_EXIT_INSN(),
11325 },
11326 .result = ACCEPT,
11327 .retval = 2,
11328 },
11329 {
11330 "jit: various mul tests",
11331 .insns = {
11332 BPF_LD_IMM64(BPF_REG_2, 0xeeff0d413122ULL),
11333 BPF_LD_IMM64(BPF_REG_0, 0xfefefeULL),
11334 BPF_LD_IMM64(BPF_REG_1, 0xefefefULL),
11335 BPF_ALU64_REG(BPF_MUL, BPF_REG_0, BPF_REG_1),
11336 BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_2, 2),
11337 BPF_MOV64_IMM(BPF_REG_0, 1),
11338 BPF_EXIT_INSN(),
11339 BPF_LD_IMM64(BPF_REG_3, 0xfefefeULL),
11340 BPF_ALU64_REG(BPF_MUL, BPF_REG_3, BPF_REG_1),
11341 BPF_JMP_REG(BPF_JEQ, BPF_REG_3, BPF_REG_2, 2),
11342 BPF_MOV64_IMM(BPF_REG_0, 1),
11343 BPF_EXIT_INSN(),
11344 BPF_MOV32_REG(BPF_REG_2, BPF_REG_2),
11345 BPF_LD_IMM64(BPF_REG_0, 0xfefefeULL),
11346 BPF_ALU32_REG(BPF_MUL, BPF_REG_0, BPF_REG_1),
11347 BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_2, 2),
11348 BPF_MOV64_IMM(BPF_REG_0, 1),
11349 BPF_EXIT_INSN(),
11350 BPF_LD_IMM64(BPF_REG_3, 0xfefefeULL),
11351 BPF_ALU32_REG(BPF_MUL, BPF_REG_3, BPF_REG_1),
11352 BPF_JMP_REG(BPF_JEQ, BPF_REG_3, BPF_REG_2, 2),
11353 BPF_MOV64_IMM(BPF_REG_0, 1),
11354 BPF_EXIT_INSN(),
11355 BPF_LD_IMM64(BPF_REG_0, 0x952a7bbcULL),
11356 BPF_LD_IMM64(BPF_REG_1, 0xfefefeULL),
11357 BPF_LD_IMM64(BPF_REG_2, 0xeeff0d413122ULL),
11358 BPF_ALU32_REG(BPF_MUL, BPF_REG_2, BPF_REG_1),
11359 BPF_JMP_REG(BPF_JEQ, BPF_REG_2, BPF_REG_0, 2),
11360 BPF_MOV64_IMM(BPF_REG_0, 1),
11361 BPF_EXIT_INSN(),
11362 BPF_MOV64_IMM(BPF_REG_0, 2),
11363 BPF_EXIT_INSN(),
11364 },
11365 .result = ACCEPT,
11366 .retval = 2,
11367 },
11368 {
11167 "xadd/w check unaligned stack", 11369 "xadd/w check unaligned stack",
11168 .insns = { 11370 .insns = {
11169 BPF_MOV64_IMM(BPF_REG_0, 1), 11371 BPF_MOV64_IMM(BPF_REG_0, 1),
@@ -11245,16 +11447,61 @@ static int create_map(uint32_t size_value, uint32_t max_elem)
11245 return fd; 11447 return fd;
11246} 11448}
11247 11449
11450static int create_prog_dummy1(void)
11451{
11452 struct bpf_insn prog[] = {
11453 BPF_MOV64_IMM(BPF_REG_0, 42),
11454 BPF_EXIT_INSN(),
11455 };
11456
11457 return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog,
11458 ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
11459}
11460
11461static int create_prog_dummy2(int mfd, int idx)
11462{
11463 struct bpf_insn prog[] = {
11464 BPF_MOV64_IMM(BPF_REG_3, idx),
11465 BPF_LD_MAP_FD(BPF_REG_2, mfd),
11466 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
11467 BPF_FUNC_tail_call),
11468 BPF_MOV64_IMM(BPF_REG_0, 41),
11469 BPF_EXIT_INSN(),
11470 };
11471
11472 return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog,
11473 ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
11474}
11475
11248static int create_prog_array(void) 11476static int create_prog_array(void)
11249{ 11477{
11250 int fd; 11478 int p1key = 0, p2key = 1;
11479 int mfd, p1fd, p2fd;
11251 11480
11252 fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int), 11481 mfd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
11253 sizeof(int), 4, 0); 11482 sizeof(int), 4, 0);
11254 if (fd < 0) 11483 if (mfd < 0) {
11255 printf("Failed to create prog array '%s'!\n", strerror(errno)); 11484 printf("Failed to create prog array '%s'!\n", strerror(errno));
11485 return -1;
11486 }
11256 11487
11257 return fd; 11488 p1fd = create_prog_dummy1();
11489 p2fd = create_prog_dummy2(mfd, p2key);
11490 if (p1fd < 0 || p2fd < 0)
11491 goto out;
11492 if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0)
11493 goto out;
11494 if (bpf_map_update_elem(mfd, &p2key, &p2fd, BPF_ANY) < 0)
11495 goto out;
11496 close(p2fd);
11497 close(p1fd);
11498
11499 return mfd;
11500out:
11501 close(p2fd);
11502 close(p1fd);
11503 close(mfd);
11504 return -1;
11258} 11505}
11259 11506
11260static int create_map_in_map(void) 11507static int create_map_in_map(void)
@@ -11375,7 +11622,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
11375 goto fail_log; 11622 goto fail_log;
11376 } 11623 }
11377 if (!strstr(bpf_vlog, expected_err) && !reject_from_alignment) { 11624 if (!strstr(bpf_vlog, expected_err) && !reject_from_alignment) {
11378 printf("FAIL\nUnexpected error message!\n"); 11625 printf("FAIL\nUnexpected error message!\n\tEXP: %s\n\tRES: %s\n",
11626 expected_err, bpf_vlog);
11379 goto fail_log; 11627 goto fail_log;
11380 } 11628 }
11381 } 11629 }
@@ -11459,9 +11707,20 @@ out:
11459 return ret; 11707 return ret;
11460} 11708}
11461 11709
11710static void get_unpriv_disabled()
11711{
11712 char buf[2];
11713 FILE *fd;
11714
11715 fd = fopen("/proc/sys/"UNPRIV_SYSCTL, "r");
11716 if (fgets(buf, 2, fd) == buf && atoi(buf))
11717 unpriv_disabled = true;
11718 fclose(fd);
11719}
11720
11462static int do_test(bool unpriv, unsigned int from, unsigned int to) 11721static int do_test(bool unpriv, unsigned int from, unsigned int to)
11463{ 11722{
11464 int i, passes = 0, errors = 0; 11723 int i, passes = 0, errors = 0, skips = 0;
11465 11724
11466 for (i = from; i < to; i++) { 11725 for (i = from; i < to; i++) {
11467 struct bpf_test *test = &tests[i]; 11726 struct bpf_test *test = &tests[i];
@@ -11469,7 +11728,10 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to)
11469 /* Program types that are not supported by non-root we 11728 /* Program types that are not supported by non-root we
11470 * skip right away. 11729 * skip right away.
11471 */ 11730 */
11472 if (!test->prog_type) { 11731 if (!test->prog_type && unpriv_disabled) {
11732 printf("#%d/u %s SKIP\n", i, test->descr);
11733 skips++;
11734 } else if (!test->prog_type) {
11473 if (!unpriv) 11735 if (!unpriv)
11474 set_admin(false); 11736 set_admin(false);
11475 printf("#%d/u %s ", i, test->descr); 11737 printf("#%d/u %s ", i, test->descr);
@@ -11478,20 +11740,22 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to)
11478 set_admin(true); 11740 set_admin(true);
11479 } 11741 }
11480 11742
11481 if (!unpriv) { 11743 if (unpriv) {
11744 printf("#%d/p %s SKIP\n", i, test->descr);
11745 skips++;
11746 } else {
11482 printf("#%d/p %s ", i, test->descr); 11747 printf("#%d/p %s ", i, test->descr);
11483 do_test_single(test, false, &passes, &errors); 11748 do_test_single(test, false, &passes, &errors);
11484 } 11749 }
11485 } 11750 }
11486 11751
11487 printf("Summary: %d PASSED, %d FAILED\n", passes, errors); 11752 printf("Summary: %d PASSED, %d SKIPPED, %d FAILED\n", passes,
11753 skips, errors);
11488 return errors ? EXIT_FAILURE : EXIT_SUCCESS; 11754 return errors ? EXIT_FAILURE : EXIT_SUCCESS;
11489} 11755}
11490 11756
11491int main(int argc, char **argv) 11757int main(int argc, char **argv)
11492{ 11758{
11493 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
11494 struct rlimit rlim = { 1 << 20, 1 << 20 };
11495 unsigned int from = 0, to = ARRAY_SIZE(tests); 11759 unsigned int from = 0, to = ARRAY_SIZE(tests);
11496 bool unpriv = !is_admin(); 11760 bool unpriv = !is_admin();
11497 11761
@@ -11512,6 +11776,12 @@ int main(int argc, char **argv)
11512 } 11776 }
11513 } 11777 }
11514 11778
11515 setrlimit(RLIMIT_MEMLOCK, unpriv ? &rlim : &rinf); 11779 get_unpriv_disabled();
11780 if (unpriv && unpriv_disabled) {
11781 printf("Cannot run as unprivileged user with sysctl %s.\n",
11782 UNPRIV_SYSCTL);
11783 return EXIT_FAILURE;
11784 }
11785
11516 return do_test(unpriv, from, to); 11786 return do_test(unpriv, from, to);
11517} 11787}
diff --git a/tools/testing/selftests/bpf/test_verifier_log.c b/tools/testing/selftests/bpf/test_verifier_log.c
index e9626cf5607a..8d6918c3b4a2 100644
--- a/tools/testing/selftests/bpf/test_verifier_log.c
+++ b/tools/testing/selftests/bpf/test_verifier_log.c
@@ -4,7 +4,6 @@
4#include <string.h> 4#include <string.h>
5#include <unistd.h> 5#include <unistd.h>
6#include <sys/time.h> 6#include <sys/time.h>
7#include <sys/resource.h>
8 7
9#include <linux/bpf.h> 8#include <linux/bpf.h>
10#include <linux/filter.h> 9#include <linux/filter.h>
@@ -12,6 +11,8 @@
12 11
13#include <bpf/bpf.h> 12#include <bpf/bpf.h>
14 13
14#include "bpf_rlimit.h"
15
15#define LOG_SIZE (1 << 20) 16#define LOG_SIZE (1 << 20)
16 17
17#define err(str...) printf("ERROR: " str) 18#define err(str...) printf("ERROR: " str)
@@ -133,16 +134,11 @@ static void test_log_bad(char *log, size_t log_len, int log_level)
133 134
134int main(int argc, char **argv) 135int main(int argc, char **argv)
135{ 136{
136 struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
137 char full_log[LOG_SIZE]; 137 char full_log[LOG_SIZE];
138 char log[LOG_SIZE]; 138 char log[LOG_SIZE];
139 size_t want_len; 139 size_t want_len;
140 int i; 140 int i;
141 141
142 /* allow unlimited locked memory to have more consistent error code */
143 if (setrlimit(RLIMIT_MEMLOCK, &limit) < 0)
144 perror("Unable to lift memlock rlimit");
145
146 memset(log, 1, LOG_SIZE); 142 memset(log, 1, LOG_SIZE);
147 143
148 /* Test incorrect attr */ 144 /* Test incorrect attr */
diff --git a/tools/testing/selftests/bpf/urandom_read.c b/tools/testing/selftests/bpf/urandom_read.c
new file mode 100644
index 000000000000..4acfdebf36fa
--- /dev/null
+++ b/tools/testing/selftests/bpf/urandom_read.c
@@ -0,0 +1,22 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <stdlib.h>
7
8#define BUF_SIZE 256
9int main(void)
10{
11 int fd = open("/dev/urandom", O_RDONLY);
12 int i;
13 char buf[BUF_SIZE];
14
15 if (fd < 0)
16 return 1;
17 for (i = 0; i < 4; ++i)
18 read(fd, buf, BUF_SIZE);
19
20 close(fd);
21 return 0;
22}
diff --git a/tools/testing/selftests/filesystems/.gitignore b/tools/testing/selftests/filesystems/.gitignore
index 31d6e426b6d4..8449cf6716ce 100644
--- a/tools/testing/selftests/filesystems/.gitignore
+++ b/tools/testing/selftests/filesystems/.gitignore
@@ -1 +1,2 @@
1dnotify_test 1dnotify_test
2devpts_pts
diff --git a/tools/testing/selftests/filesystems/Makefile b/tools/testing/selftests/filesystems/Makefile
index 13a73bf725b5..5c7d7001ad37 100644
--- a/tools/testing/selftests/filesystems/Makefile
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -1,8 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2TEST_PROGS := dnotify_test
3all: $(TEST_PROGS)
4 2
5include ../lib.mk 3TEST_GEN_PROGS := devpts_pts
4TEST_GEN_PROGS_EXTENDED := dnotify_test
6 5
7clean: 6include ../lib.mk
8 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/filesystems/devpts_pts.c b/tools/testing/selftests/filesystems/devpts_pts.c
new file mode 100644
index 000000000000..b9055e974289
--- /dev/null
+++ b/tools/testing/selftests/filesystems/devpts_pts.c
@@ -0,0 +1,313 @@
1// SPDX-License-Identifier: GPL-2.0
2#define _GNU_SOURCE
3#include <errno.h>
4#include <fcntl.h>
5#include <sched.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11#include <sys/ioctl.h>
12#include <sys/mount.h>
13#include <sys/wait.h>
14
15static bool terminal_dup2(int duplicate, int original)
16{
17 int ret;
18
19 ret = dup2(duplicate, original);
20 if (ret < 0)
21 return false;
22
23 return true;
24}
25
26static int terminal_set_stdfds(int fd)
27{
28 int i;
29
30 if (fd < 0)
31 return 0;
32
33 for (i = 0; i < 3; i++)
34 if (!terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO,
35 STDERR_FILENO}[i]))
36 return -1;
37
38 return 0;
39}
40
41static int login_pty(int fd)
42{
43 int ret;
44
45 setsid();
46
47 ret = ioctl(fd, TIOCSCTTY, NULL);
48 if (ret < 0)
49 return -1;
50
51 ret = terminal_set_stdfds(fd);
52 if (ret < 0)
53 return -1;
54
55 if (fd > STDERR_FILENO)
56 close(fd);
57
58 return 0;
59}
60
61static int wait_for_pid(pid_t pid)
62{
63 int status, ret;
64
65again:
66 ret = waitpid(pid, &status, 0);
67 if (ret == -1) {
68 if (errno == EINTR)
69 goto again;
70 return -1;
71 }
72 if (ret != pid)
73 goto again;
74
75 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
76 return -1;
77
78 return 0;
79}
80
81static int resolve_procfd_symlink(int fd, char *buf, size_t buflen)
82{
83 int ret;
84 char procfd[4096];
85
86 ret = snprintf(procfd, 4096, "/proc/self/fd/%d", fd);
87 if (ret < 0 || ret >= 4096)
88 return -1;
89
90 ret = readlink(procfd, buf, buflen);
91 if (ret < 0 || (size_t)ret >= buflen)
92 return -1;
93
94 buf[ret] = '\0';
95
96 return 0;
97}
98
99static int do_tiocgptpeer(char *ptmx, char *expected_procfd_contents)
100{
101 int ret;
102 int master = -1, slave = -1, fret = -1;
103
104 master = open(ptmx, O_RDWR | O_NOCTTY | O_CLOEXEC);
105 if (master < 0) {
106 fprintf(stderr, "Failed to open \"%s\": %s\n", ptmx,
107 strerror(errno));
108 return -1;
109 }
110
111 /*
112 * grantpt() makes assumptions about /dev/pts/ so ignore it. It's also
113 * not really needed.
114 */
115 ret = unlockpt(master);
116 if (ret < 0) {
117 fprintf(stderr, "Failed to unlock terminal\n");
118 goto do_cleanup;
119 }
120
121#ifdef TIOCGPTPEER
122 slave = ioctl(master, TIOCGPTPEER, O_RDWR | O_NOCTTY | O_CLOEXEC);
123#endif
124 if (slave < 0) {
125 if (errno == EINVAL) {
126 fprintf(stderr, "TIOCGPTPEER is not supported. "
127 "Skipping test.\n");
128 fret = EXIT_SUCCESS;
129 }
130
131 fprintf(stderr, "Failed to perform TIOCGPTPEER ioctl\n");
132 goto do_cleanup;
133 }
134
135 pid_t pid = fork();
136 if (pid < 0)
137 goto do_cleanup;
138
139 if (pid == 0) {
140 char buf[4096];
141
142 ret = login_pty(slave);
143 if (ret < 0) {
144 fprintf(stderr, "Failed to setup terminal\n");
145 _exit(EXIT_FAILURE);
146 }
147
148 ret = resolve_procfd_symlink(STDIN_FILENO, buf, sizeof(buf));
149 if (ret < 0) {
150 fprintf(stderr, "Failed to retrieve pathname of pts "
151 "slave file descriptor\n");
152 _exit(EXIT_FAILURE);
153 }
154
155 if (strncmp(expected_procfd_contents, buf,
156 strlen(expected_procfd_contents)) != 0) {
157 fprintf(stderr, "Received invalid contents for "
158 "\"/proc/<pid>/fd/%d\" symlink: %s\n",
159 STDIN_FILENO, buf);
160 _exit(-1);
161 }
162
163 fprintf(stderr, "Contents of \"/proc/<pid>/fd/%d\" "
164 "symlink are valid: %s\n", STDIN_FILENO, buf);
165
166 _exit(EXIT_SUCCESS);
167 }
168
169 ret = wait_for_pid(pid);
170 if (ret < 0)
171 goto do_cleanup;
172
173 fret = EXIT_SUCCESS;
174
175do_cleanup:
176 if (master >= 0)
177 close(master);
178 if (slave >= 0)
179 close(slave);
180
181 return fret;
182}
183
184static int verify_non_standard_devpts_mount(void)
185{
186 char *mntpoint;
187 int ret = -1;
188 char devpts[] = P_tmpdir "/devpts_fs_XXXXXX";
189 char ptmx[] = P_tmpdir "/devpts_fs_XXXXXX/ptmx";
190
191 ret = umount("/dev/pts");
192 if (ret < 0) {
193 fprintf(stderr, "Failed to unmount \"/dev/pts\": %s\n",
194 strerror(errno));
195 return -1;
196 }
197
198 (void)umount("/dev/ptmx");
199
200 mntpoint = mkdtemp(devpts);
201 if (!mntpoint) {
202 fprintf(stderr, "Failed to create temporary mountpoint: %s\n",
203 strerror(errno));
204 return -1;
205 }
206
207 ret = mount("devpts", mntpoint, "devpts", MS_NOSUID | MS_NOEXEC,
208 "newinstance,ptmxmode=0666,mode=0620,gid=5");
209 if (ret < 0) {
210 fprintf(stderr, "Failed to mount devpts fs to \"%s\" in new "
211 "mount namespace: %s\n", mntpoint,
212 strerror(errno));
213 unlink(mntpoint);
214 return -1;
215 }
216
217 ret = snprintf(ptmx, sizeof(ptmx), "%s/ptmx", devpts);
218 if (ret < 0 || (size_t)ret >= sizeof(ptmx)) {
219 unlink(mntpoint);
220 return -1;
221 }
222
223 ret = do_tiocgptpeer(ptmx, mntpoint);
224 unlink(mntpoint);
225 if (ret < 0)
226 return -1;
227
228 return 0;
229}
230
231static int verify_ptmx_bind_mount(void)
232{
233 int ret;
234
235 ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL);
236 if (ret < 0) {
237 fprintf(stderr, "Failed to bind mount \"/dev/pts/ptmx\" to "
238 "\"/dev/ptmx\" mount namespace\n");
239 return -1;
240 }
241
242 ret = do_tiocgptpeer("/dev/ptmx", "/dev/pts/");
243 if (ret < 0)
244 return -1;
245
246 return 0;
247}
248
249static int verify_invalid_ptmx_bind_mount(void)
250{
251 int ret;
252 char mntpoint_fd;
253 char ptmx[] = P_tmpdir "/devpts_ptmx_XXXXXX";
254
255 mntpoint_fd = mkstemp(ptmx);
256 if (mntpoint_fd < 0) {
257 fprintf(stderr, "Failed to create temporary directory: %s\n",
258 strerror(errno));
259 return -1;
260 }
261
262 ret = mount("/dev/pts/ptmx", ptmx, NULL, MS_BIND, NULL);
263 close(mntpoint_fd);
264 if (ret < 0) {
265 fprintf(stderr, "Failed to bind mount \"/dev/pts/ptmx\" to "
266 "\"%s\" mount namespace\n", ptmx);
267 return -1;
268 }
269
270 ret = do_tiocgptpeer(ptmx, "/dev/pts/");
271 if (ret == 0)
272 return -1;
273
274 return 0;
275}
276
277int main(int argc, char *argv[])
278{
279 int ret;
280
281 if (!isatty(STDIN_FILENO)) {
282 fprintf(stderr, "Standard input file desciptor is not attached "
283 "to a terminal. Skipping test\n");
284 exit(EXIT_FAILURE);
285 }
286
287 ret = unshare(CLONE_NEWNS);
288 if (ret < 0) {
289 fprintf(stderr, "Failed to unshare mount namespace\n");
290 exit(EXIT_FAILURE);
291 }
292
293 ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
294 if (ret < 0) {
295 fprintf(stderr, "Failed to make \"/\" MS_PRIVATE in new mount "
296 "namespace\n");
297 exit(EXIT_FAILURE);
298 }
299
300 ret = verify_ptmx_bind_mount();
301 if (ret < 0)
302 exit(EXIT_FAILURE);
303
304 ret = verify_invalid_ptmx_bind_mount();
305 if (ret < 0)
306 exit(EXIT_FAILURE);
307
308 ret = verify_non_standard_devpts_mount();
309 if (ret < 0)
310 exit(EXIT_FAILURE);
311
312 exit(EXIT_SUCCESS);
313}
diff --git a/tools/testing/selftests/firmware/Makefile b/tools/testing/selftests/firmware/Makefile
index 1894d625af2d..261c81f08606 100644
--- a/tools/testing/selftests/firmware/Makefile
+++ b/tools/testing/selftests/firmware/Makefile
@@ -3,7 +3,8 @@
3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" 3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4all: 4all:
5 5
6TEST_PROGS := fw_filesystem.sh fw_fallback.sh 6TEST_PROGS := fw_run_tests.sh
7TEST_FILES := fw_fallback.sh fw_filesystem.sh fw_lib.sh
7 8
8include ../lib.mk 9include ../lib.mk
9 10
diff --git a/tools/testing/selftests/firmware/config b/tools/testing/selftests/firmware/config
index c8137f70e291..bf634dda0720 100644
--- a/tools/testing/selftests/firmware/config
+++ b/tools/testing/selftests/firmware/config
@@ -1 +1,5 @@
1CONFIG_TEST_FIRMWARE=y 1CONFIG_TEST_FIRMWARE=y
2CONFIG_FW_LOADER=y
3CONFIG_FW_LOADER_USER_HELPER=y
4CONFIG_IKCONFIG=y
5CONFIG_IKCONFIG_PROC=y
diff --git a/tools/testing/selftests/firmware/fw_fallback.sh b/tools/testing/selftests/firmware/fw_fallback.sh
index 722cad91df74..8e2e34a2ca69 100755
--- a/tools/testing/selftests/firmware/fw_fallback.sh
+++ b/tools/testing/selftests/firmware/fw_fallback.sh
@@ -1,4 +1,4 @@
1#!/bin/sh 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3# This validates that the kernel will fall back to using the fallback mechanism 3# This validates that the kernel will fall back to using the fallback mechanism
4# to load firmware it can't find on disk itself. We must request a firmware 4# to load firmware it can't find on disk itself. We must request a firmware
@@ -6,31 +6,17 @@
6# won't find so that we can do the load ourself manually. 6# won't find so that we can do the load ourself manually.
7set -e 7set -e
8 8
9modprobe test_firmware 9TEST_REQS_FW_SYSFS_FALLBACK="yes"
10TEST_REQS_FW_SET_CUSTOM_PATH="no"
11TEST_DIR=$(dirname $0)
12source $TEST_DIR/fw_lib.sh
10 13
11DIR=/sys/devices/virtual/misc/test_firmware 14check_mods
15check_setup
16verify_reqs
17setup_tmp_file
12 18
13# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/ 19trap "test_finish" EXIT
14# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
15# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
16HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
17
18if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
19 OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
20else
21 echo "usermode helper disabled so ignoring test"
22 exit 0
23fi
24
25FWPATH=$(mktemp -d)
26FW="$FWPATH/test-firmware.bin"
27
28test_finish()
29{
30 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
31 rm -f "$FW"
32 rmdir "$FWPATH"
33}
34 20
35load_fw() 21load_fw()
36{ 22{
@@ -169,12 +155,6 @@ load_fw_fallback_with_child()
169 return $RET 155 return $RET
170} 156}
171 157
172trap "test_finish" EXIT
173
174# This is an unlikely real-world firmware content. :)
175echo "ABCD0123" >"$FW"
176NAME=$(basename "$FW")
177
178test_syfs_timeout() 158test_syfs_timeout()
179{ 159{
180 DEVPATH="$DIR"/"nope-$NAME"/loading 160 DEVPATH="$DIR"/"nope-$NAME"/loading
@@ -258,8 +238,10 @@ run_sysfs_main_tests()
258 238
259run_sysfs_custom_load_tests() 239run_sysfs_custom_load_tests()
260{ 240{
261 if load_fw_custom "$NAME" "$FW" ; then 241 RANDOM_FILE_PATH=$(setup_random_file)
262 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then 242 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
243 if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then
244 if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then
263 echo "$0: firmware was not loaded" >&2 245 echo "$0: firmware was not loaded" >&2
264 exit 1 246 exit 1
265 else 247 else
@@ -267,8 +249,10 @@ run_sysfs_custom_load_tests()
267 fi 249 fi
268 fi 250 fi
269 251
270 if load_fw_custom "$NAME" "$FW" ; then 252 RANDOM_FILE_PATH=$(setup_random_file)
271 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then 253 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
254 if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then
255 if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then
272 echo "$0: firmware was not loaded" >&2 256 echo "$0: firmware was not loaded" >&2
273 exit 1 257 exit 1
274 else 258 else
@@ -276,8 +260,12 @@ run_sysfs_custom_load_tests()
276 fi 260 fi
277 fi 261 fi
278 262
279 if load_fw_custom_cancel "nope-$NAME" "$FW" ; then 263 RANDOM_FILE_REAL="$RANDOM_FILE_PATH"
280 if diff -q "$FW" /dev/test_firmware >/dev/null ; then 264 FAKE_RANDOM_FILE_PATH=$(setup_random_file_fake)
265 FAKE_RANDOM_FILE="$(basename $FAKE_RANDOM_FILE_PATH)"
266
267 if load_fw_custom_cancel "$FAKE_RANDOM_FILE" "$RANDOM_FILE_REAL" ; then
268 if diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then
281 echo "$0: firmware was expected to be cancelled" >&2 269 echo "$0: firmware was expected to be cancelled" >&2
282 exit 1 270 exit 1
283 else 271 else
@@ -286,7 +274,10 @@ run_sysfs_custom_load_tests()
286 fi 274 fi
287} 275}
288 276
289run_sysfs_main_tests 277if [ "$HAS_FW_LOADER_USER_HELPER_FALLBACK" = "yes" ]; then
278 run_sysfs_main_tests
279fi
280
290run_sysfs_custom_load_tests 281run_sysfs_custom_load_tests
291 282
292exit 0 283exit 0
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index f9508e1a4058..6452d2129cd9 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -1,4 +1,4 @@
1#!/bin/sh 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3# This validates that the kernel will load firmware out of its list of 3# This validates that the kernel will load firmware out of its list of
4# firmware locations on disk. Since the user helper does similar work, 4# firmware locations on disk. Since the user helper does similar work,
@@ -6,52 +6,15 @@
6# know so we can be sure we're not accidentally testing the user helper. 6# know so we can be sure we're not accidentally testing the user helper.
7set -e 7set -e
8 8
9DIR=/sys/devices/virtual/misc/test_firmware 9TEST_REQS_FW_SYSFS_FALLBACK="no"
10TEST_REQS_FW_SET_CUSTOM_PATH="yes"
10TEST_DIR=$(dirname $0) 11TEST_DIR=$(dirname $0)
12source $TEST_DIR/fw_lib.sh
11 13
12test_modprobe() 14check_mods
13{ 15check_setup
14 if [ ! -d $DIR ]; then 16verify_reqs
15 echo "$0: $DIR not present" 17setup_tmp_file
16 echo "You must have the following enabled in your kernel:"
17 cat $TEST_DIR/config
18 exit 1
19 fi
20}
21
22trap "test_modprobe" EXIT
23
24if [ ! -d $DIR ]; then
25 modprobe test_firmware
26fi
27
28# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
29# These days most distros enable CONFIG_FW_LOADER_USER_HELPER but disable
30# CONFIG_FW_LOADER_USER_HELPER_FALLBACK. We use /sys/class/firmware/ as an
31# indicator for CONFIG_FW_LOADER_USER_HELPER.
32HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
33
34if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
35 OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
36fi
37
38OLD_FWPATH=$(cat /sys/module/firmware_class/parameters/path)
39
40FWPATH=$(mktemp -d)
41FW="$FWPATH/test-firmware.bin"
42
43test_finish()
44{
45 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
46 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
47 fi
48 if [ "$OLD_FWPATH" = "" ]; then
49 OLD_FWPATH=" "
50 fi
51 echo -n "$OLD_FWPATH" >/sys/module/firmware_class/parameters/path
52 rm -f "$FW"
53 rmdir "$FWPATH"
54}
55 18
56trap "test_finish" EXIT 19trap "test_finish" EXIT
57 20
@@ -60,14 +23,6 @@ if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
60 echo 1 >/sys/class/firmware/timeout 23 echo 1 >/sys/class/firmware/timeout
61fi 24fi
62 25
63# Set the kernel search path.
64echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path
65
66# This is an unlikely real-world firmware content. :)
67echo "ABCD0123" >"$FW"
68
69NAME=$(basename "$FW")
70
71if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then 26if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
72 echo "$0: empty filename should not succeed" >&2 27 echo "$0: empty filename should not succeed" >&2
73 exit 1 28 exit 1
@@ -275,10 +230,13 @@ test_wait_and_cancel_custom_load()
275test_request_firmware_nowait_custom_nofile() 230test_request_firmware_nowait_custom_nofile()
276{ 231{
277 echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: " 232 echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
233 config_reset
278 config_unset_uevent 234 config_unset_uevent
279 config_set_name nope-test-firmware.bin 235 RANDOM_FILE_PATH=$(setup_random_file_fake)
236 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
237 config_set_name $RANDOM_FILE
280 config_trigger_async & 238 config_trigger_async &
281 test_wait_and_cancel_custom_load nope-test-firmware.bin 239 test_wait_and_cancel_custom_load $RANDOM_FILE
282 wait 240 wait
283 release_all_firmware 241 release_all_firmware
284 echo "OK" 242 echo "OK"
@@ -316,7 +274,11 @@ test_request_firmware_nowait_uevent()
316test_request_firmware_nowait_custom() 274test_request_firmware_nowait_custom()
317{ 275{
318 echo -n "Batched request_firmware_nowait(uevent=false) try #$1: " 276 echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
277 config_reset
319 config_unset_uevent 278 config_unset_uevent
279 RANDOM_FILE_PATH=$(setup_random_file)
280 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
281 config_set_name $RANDOM_FILE
320 config_trigger_async 282 config_trigger_async
321 release_all_firmware 283 release_all_firmware
322 echo "OK" 284 echo "OK"
diff --git a/tools/testing/selftests/firmware/fw_lib.sh b/tools/testing/selftests/firmware/fw_lib.sh
new file mode 100755
index 000000000000..962d7f4ac627
--- /dev/null
+++ b/tools/testing/selftests/firmware/fw_lib.sh
@@ -0,0 +1,196 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Library of helpers for test scripts.
5set -e
6
7DIR=/sys/devices/virtual/misc/test_firmware
8
9PROC_CONFIG="/proc/config.gz"
10TEST_DIR=$(dirname $0)
11
12print_reqs_exit()
13{
14 echo "You must have the following enabled in your kernel:" >&2
15 cat $TEST_DIR/config >&2
16 exit 1
17}
18
19test_modprobe()
20{
21 if [ ! -d $DIR ]; then
22 print_reqs_exit
23 fi
24}
25
26check_mods()
27{
28 trap "test_modprobe" EXIT
29 if [ ! -d $DIR ]; then
30 modprobe test_firmware
31 fi
32 if [ ! -f $PROC_CONFIG ]; then
33 if modprobe configs 2>/dev/null; then
34 echo "Loaded configs module"
35 if [ ! -f $PROC_CONFIG ]; then
36 echo "You must have the following enabled in your kernel:" >&2
37 cat $TEST_DIR/config >&2
38 echo "Resorting to old heuristics" >&2
39 fi
40 else
41 echo "Failed to load configs module, using old heuristics" >&2
42 fi
43 fi
44}
45
46check_setup()
47{
48 HAS_FW_LOADER_USER_HELPER="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER=y)"
49 HAS_FW_LOADER_USER_HELPER_FALLBACK="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y)"
50 PROC_FW_IGNORE_SYSFS_FALLBACK="0"
51 PROC_FW_FORCE_SYSFS_FALLBACK="0"
52
53 if [ -z $PROC_SYS_DIR ]; then
54 PROC_SYS_DIR="/proc/sys/kernel"
55 fi
56
57 FW_PROC="${PROC_SYS_DIR}/firmware_config"
58 FW_FORCE_SYSFS_FALLBACK="$FW_PROC/force_sysfs_fallback"
59 FW_IGNORE_SYSFS_FALLBACK="$FW_PROC/ignore_sysfs_fallback"
60
61 if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
62 PROC_FW_FORCE_SYSFS_FALLBACK="$(cat $FW_FORCE_SYSFS_FALLBACK)"
63 fi
64
65 if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then
66 PROC_FW_IGNORE_SYSFS_FALLBACK="$(cat $FW_IGNORE_SYSFS_FALLBACK)"
67 fi
68
69 if [ "$PROC_FW_FORCE_SYSFS_FALLBACK" = "1" ]; then
70 HAS_FW_LOADER_USER_HELPER="yes"
71 HAS_FW_LOADER_USER_HELPER_FALLBACK="yes"
72 fi
73
74 if [ "$PROC_FW_IGNORE_SYSFS_FALLBACK" = "1" ]; then
75 HAS_FW_LOADER_USER_HELPER_FALLBACK="no"
76 HAS_FW_LOADER_USER_HELPER="no"
77 fi
78
79 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
80 OLD_TIMEOUT="$(cat /sys/class/firmware/timeout)"
81 fi
82
83 OLD_FWPATH="$(cat /sys/module/firmware_class/parameters/path)"
84}
85
86verify_reqs()
87{
88 if [ "$TEST_REQS_FW_SYSFS_FALLBACK" = "yes" ]; then
89 if [ ! "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
90 echo "usermode helper disabled so ignoring test"
91 exit 0
92 fi
93 fi
94}
95
96setup_tmp_file()
97{
98 FWPATH=$(mktemp -d)
99 FW="$FWPATH/test-firmware.bin"
100 echo "ABCD0123" >"$FW"
101 NAME=$(basename "$FW")
102 if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then
103 echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path
104 fi
105}
106
107__setup_random_file()
108{
109 RANDOM_FILE_PATH="$(mktemp -p $FWPATH)"
110 # mktemp says dry-run -n is unsafe, so...
111 if [[ "$1" = "fake" ]]; then
112 rm -rf $RANDOM_FILE_PATH
113 sync
114 else
115 echo "ABCD0123" >"$RANDOM_FILE_PATH"
116 fi
117 echo $RANDOM_FILE_PATH
118}
119
120setup_random_file()
121{
122 echo $(__setup_random_file)
123}
124
125setup_random_file_fake()
126{
127 echo $(__setup_random_file fake)
128}
129
130proc_set_force_sysfs_fallback()
131{
132 if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
133 echo -n $1 > $FW_FORCE_SYSFS_FALLBACK
134 check_setup
135 fi
136}
137
138proc_set_ignore_sysfs_fallback()
139{
140 if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then
141 echo -n $1 > $FW_IGNORE_SYSFS_FALLBACK
142 check_setup
143 fi
144}
145
146proc_restore_defaults()
147{
148 proc_set_force_sysfs_fallback 0
149 proc_set_ignore_sysfs_fallback 0
150}
151
152test_finish()
153{
154 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
155 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
156 fi
157 if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then
158 if [ "$OLD_FWPATH" = "" ]; then
159 # A zero-length write won't work; write a null byte
160 printf '\000' >/sys/module/firmware_class/parameters/path
161 else
162 echo -n "$OLD_FWPATH" >/sys/module/firmware_class/parameters/path
163 fi
164 fi
165 if [ -f $FW ]; then
166 rm -f "$FW"
167 fi
168 if [ -d $FWPATH ]; then
169 rm -rf "$FWPATH"
170 fi
171 proc_restore_defaults
172}
173
174kconfig_has()
175{
176 if [ -f $PROC_CONFIG ]; then
177 if zgrep -q $1 $PROC_CONFIG 2>/dev/null; then
178 echo "yes"
179 else
180 echo "no"
181 fi
182 else
183 # We currently don't have easy heuristics to infer this
184 # so best we can do is just try to use the kernel assuming
185 # you had enabled it. This matches the old behaviour.
186 if [ "$1" = "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y" ]; then
187 echo "yes"
188 elif [ "$1" = "CONFIG_FW_LOADER_USER_HELPER=y" ]; then
189 if [ -d /sys/class/firmware/ ]; then
190 echo yes
191 else
192 echo no
193 fi
194 fi
195 fi
196}
diff --git a/tools/testing/selftests/firmware/fw_run_tests.sh b/tools/testing/selftests/firmware/fw_run_tests.sh
new file mode 100755
index 000000000000..cffdd4eb0a57
--- /dev/null
+++ b/tools/testing/selftests/firmware/fw_run_tests.sh
@@ -0,0 +1,70 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# This runs all known tests across all known possible configurations we could
5# emulate in one run.
6
7set -e
8
9TEST_DIR=$(dirname $0)
10source $TEST_DIR/fw_lib.sh
11
12export HAS_FW_LOADER_USER_HELPER=""
13export HAS_FW_LOADER_USER_HELPER_FALLBACK=""
14
15run_tests()
16{
17 proc_set_force_sysfs_fallback $1
18 proc_set_ignore_sysfs_fallback $2
19 $TEST_DIR/fw_filesystem.sh
20
21 proc_set_force_sysfs_fallback $1
22 proc_set_ignore_sysfs_fallback $2
23 $TEST_DIR/fw_fallback.sh
24}
25
26run_test_config_0001()
27{
28 echo "-----------------------------------------------------"
29 echo "Running kernel configuration test 1 -- rare"
30 echo "Emulates:"
31 echo "CONFIG_FW_LOADER=y"
32 echo "CONFIG_FW_LOADER_USER_HELPER=n"
33 echo "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n"
34 run_tests 0 1
35}
36
37run_test_config_0002()
38{
39 echo "-----------------------------------------------------"
40 echo "Running kernel configuration test 2 -- distro"
41 echo "Emulates:"
42 echo "CONFIG_FW_LOADER=y"
43 echo "CONFIG_FW_LOADER_USER_HELPER=y"
44 echo "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n"
45 proc_set_ignore_sysfs_fallback 0
46 run_tests 0 0
47}
48
49run_test_config_0003()
50{
51 echo "-----------------------------------------------------"
52 echo "Running kernel configuration test 3 -- android"
53 echo "Emulates:"
54 echo "CONFIG_FW_LOADER=y"
55 echo "CONFIG_FW_LOADER_USER_HELPER=y"
56 echo "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y"
57 run_tests 1 0
58}
59
60check_mods
61check_setup
62
63if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
64 run_test_config_0001
65 run_test_config_0002
66 run_test_config_0003
67else
68 echo "Running basic kernel configuration, working with your config"
69 run_tests
70fi
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index df3dd7fe5f9b..2a4f16fc9819 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -59,6 +59,13 @@ disable_events() {
59 echo 0 > events/enable 59 echo 0 > events/enable
60} 60}
61 61
62clear_synthetic_events() { # reset all current synthetic events
63 grep -v ^# synthetic_events |
64 while read line; do
65 echo "!$line" >> synthetic_events
66 done
67}
68
62initialize_ftrace() { # Reset ftrace to initial-state 69initialize_ftrace() { # Reset ftrace to initial-state
63# As the initial state, ftrace will be set to nop tracer, 70# As the initial state, ftrace will be set to nop tracer,
64# no events, no triggers, no filters, no function filters, 71# no events, no triggers, no filters, no function filters,
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc
new file mode 100644
index 000000000000..2aabab363cfb
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc
@@ -0,0 +1,39 @@
1#!/bin/sh
2# description: event trigger - test extended error support
3
4
5do_reset() {
6 reset_trigger
7 echo > set_event
8 clear_trace
9}
10
11fail() { #msg
12 do_reset
13 echo $1
14 exit_fail
15}
16
17if [ ! -f set_event ]; then
18 echo "event tracing is not supported"
19 exit_unsupported
20fi
21
22if [ ! -f synthetic_events ]; then
23 echo "synthetic event is not supported"
24 exit_unsupported
25fi
26
27reset_tracer
28do_reset
29
30echo "Test extended error support"
31echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger
32! echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_wakeup/trigger 2> /dev/null
33if ! grep -q "ERROR:" events/sched/sched_wakeup/hist; then
34 fail "Failed to generate extended error in histogram"
35fi
36
37do_reset
38
39exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc
new file mode 100644
index 000000000000..7fd5b4a8f060
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc
@@ -0,0 +1,54 @@
1#!/bin/sh
2# description: event trigger - test field variable support
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit_fail
14}
15
16if [ ! -f set_event ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f synthetic_events ]; then
22 echo "synthetic event is not supported"
23 exit_unsupported
24fi
25
26clear_synthetic_events
27reset_tracer
28do_reset
29
30echo "Test field variable support"
31
32echo 'wakeup_latency u64 lat; pid_t pid; int prio; char comm[16]' > synthetic_events
33echo 'hist:keys=comm:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_waking/trigger
34echo 'hist:keys=next_comm:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,sched.sched_waking.prio,next_comm) if next_comm=="ping"' > events/sched/sched_switch/trigger
35echo 'hist:keys=pid,prio,comm:vals=lat:sort=pid,prio' > events/synthetic/wakeup_latency/trigger
36
37ping localhost -c 3
38if ! grep -q "ping" events/synthetic/wakeup_latency/hist; then
39 fail "Failed to create inter-event histogram"
40fi
41
42if ! grep -q "synthetic_prio=prio" events/sched/sched_waking/hist; then
43 fail "Failed to create histogram with field variable"
44fi
45
46echo '!hist:keys=next_comm:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,sched.sched_waking.prio,next_comm) if next_comm=="ping"' >> events/sched/sched_switch/trigger
47
48if grep -q "synthetic_prio=prio" events/sched/sched_waking/hist; then
49 fail "Failed to remove histogram with field variable"
50fi
51
52do_reset
53
54exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
new file mode 100644
index 000000000000..c93dbe38b5df
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
@@ -0,0 +1,58 @@
1#!/bin/sh
2# description: event trigger - test inter-event combined histogram trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit_fail
14}
15
16if [ ! -f set_event ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f synthetic_events ]; then
22 echo "synthetic event is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28clear_synthetic_events
29
30echo "Test create synthetic event"
31
32echo 'waking_latency u64 lat pid_t pid' > synthetic_events
33if [ ! -d events/synthetic/waking_latency ]; then
34 fail "Failed to create waking_latency synthetic event"
35fi
36
37echo "Test combined histogram"
38
39echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_waking/trigger
40echo 'hist:keys=pid:waking_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).waking_latency($waking_lat,pid) if comm=="ping"' > events/sched/sched_wakeup/trigger
41echo 'hist:keys=pid,lat:sort=pid,lat' > events/synthetic/waking_latency/trigger
42
43echo 'wakeup_latency u64 lat pid_t pid' >> synthetic_events
44echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_wakeup/trigger
45echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid) if next_comm=="ping"' > events/sched/sched_switch/trigger
46
47echo 'waking+wakeup_latency u64 lat; pid_t pid' >> synthetic_events
48echo 'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking+wakeup_latency($ww_lat,pid)' >> events/synthetic/wakeup_latency/trigger
49echo 'hist:keys=pid,lat:sort=pid,lat' >> events/synthetic/waking+wakeup_latency/trigger
50
51ping localhost -c 3
52if ! grep -q "pid:" events/synthetic/waking+wakeup_latency/hist; then
53 fail "Failed to create combined histogram"
54fi
55
56do_reset
57
58exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc
new file mode 100644
index 000000000000..c193dce611a2
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc
@@ -0,0 +1,44 @@
1#!/bin/sh
2# description: event trigger - test multiple actions on hist trigger
3
4
5do_reset() {
6 reset_trigger
7 echo > set_event
8 clear_trace
9}
10
11fail() { #msg
12 do_reset
13 echo $1
14 exit_fail
15}
16
17if [ ! -f set_event ]; then
18 echo "event tracing is not supported"
19 exit_unsupported
20fi
21
22if [ ! -f synthetic_events ]; then
23 echo "synthetic event is not supported"
24 exit_unsupported
25fi
26
27clear_synthetic_events
28reset_tracer
29do_reset
30
31echo "Test multiple actions on hist trigger"
32echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events
33TRIGGER1=events/sched/sched_wakeup/trigger
34TRIGGER2=events/sched/sched_switch/trigger
35
36echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="cyclictest"' > $TRIGGER1
37echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0 if next_comm=="cyclictest"' >> $TRIGGER2
38echo 'hist:keys=next_pid:onmatch(sched.sched_wakeup).wakeup_latency(sched.sched_switch.$wakeup_lat,next_pid) if next_comm=="cyclictest"' >> $TRIGGER2
39echo 'hist:keys=next_pid:onmatch(sched.sched_wakeup).wakeup_latency(sched.sched_switch.$wakeup_lat,prev_pid) if next_comm=="cyclictest"' >> $TRIGGER2
40echo 'hist:keys=next_pid if next_comm=="cyclictest"' >> $TRIGGER2
41
42do_reset
43
44exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
new file mode 100644
index 000000000000..e84e7d048566
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
@@ -0,0 +1,50 @@
1#!/bin/sh
2# description: event trigger - test inter-event histogram trigger onmatch action
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit_fail
14}
15
16if [ ! -f set_event ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f synthetic_events ]; then
22 echo "synthetic event is not supported"
23 exit_unsupported
24fi
25
26clear_synthetic_events
27reset_tracer
28do_reset
29
30echo "Test create synthetic event"
31
32echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events
33if [ ! -d events/synthetic/wakeup_latency ]; then
34 fail "Failed to create wakeup_latency synthetic event"
35fi
36
37echo "Test create histogram for synthetic event"
38echo "Test histogram variables,simple expression support and onmatch action"
39
40echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger
41echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid,next_comm) if next_comm=="ping"' > events/sched/sched_switch/trigger
42echo 'hist:keys=comm,pid,lat:wakeup_lat=lat:sort=lat' > events/synthetic/wakeup_latency/trigger
43ping localhost -c 5
44if ! grep -q "ping" events/synthetic/wakeup_latency/hist; then
45 fail "Failed to create onmatch action inter-event histogram"
46fi
47
48do_reset
49
50exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
new file mode 100644
index 000000000000..7907d8aacde3
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
@@ -0,0 +1,50 @@
1#!/bin/sh
2# description: event trigger - test inter-event histogram trigger onmatch-onmax action
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit_fail
14}
15
16if [ ! -f set_event ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f synthetic_events ]; then
22 echo "synthetic event is not supported"
23 exit_unsupported
24fi
25
26clear_synthetic_events
27reset_tracer
28do_reset
29
30echo "Test create synthetic event"
31
32echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events
33if [ ! -d events/synthetic/wakeup_latency ]; then
34 fail "Failed to create wakeup_latency synthetic event"
35fi
36
37echo "Test create histogram for synthetic event"
38echo "Test histogram variables,simple expression support and onmatch-onmax action"
39
40echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger
41echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid,next_comm):onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm) if next_comm=="ping"' >> events/sched/sched_switch/trigger
42echo 'hist:keys=comm,pid,lat:wakeup_lat=lat:sort=lat' > events/synthetic/wakeup_latency/trigger
43ping localhost -c 5
44if [ ! grep -q "ping" events/synthetic/wakeup_latency/hist -o ! grep -q "max:" events/sched/sched_switch/hist]; then
45 fail "Failed to create onmatch-onmax action inter-event histogram"
46fi
47
48do_reset
49
50exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc
new file mode 100644
index 000000000000..38b7ed6242b2
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc
@@ -0,0 +1,48 @@
1#!/bin/sh
2# description: event trigger - test inter-event histogram trigger onmax action
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit_fail
14}
15
16if [ ! -f set_event ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f synthetic_events ]; then
22 echo "synthetic event is not supported"
23 exit_unsupported
24fi
25
26clear_synthetic_events
27reset_tracer
28do_reset
29
30echo "Test create synthetic event"
31
32echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events
33if [ ! -d events/synthetic/wakeup_latency ]; then
34 fail "Failed to create wakeup_latency synthetic event"
35fi
36
37echo "Test onmax action"
38
39echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_waking/trigger
40echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm) if next_comm=="ping"' >> events/sched/sched_switch/trigger
41ping localhost -c 3
42if ! grep -q "max:" events/sched/sched_switch/hist; then
43 fail "Failed to create onmax action inter-event histogram"
44fi
45
46do_reset
47
48exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc
new file mode 100644
index 000000000000..cef11377dcbd
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc
@@ -0,0 +1,54 @@
1#!/bin/sh
2# description: event trigger - test synthetic event create remove
3do_reset() {
4 reset_trigger
5 echo > set_event
6 clear_trace
7}
8
9fail() { #msg
10 do_reset
11 echo $1
12 exit_fail
13}
14
15if [ ! -f set_event ]; then
16 echo "event tracing is not supported"
17 exit_unsupported
18fi
19
20if [ ! -f synthetic_events ]; then
21 echo "synthetic event is not supported"
22 exit_unsupported
23fi
24
25clear_synthetic_events
26reset_tracer
27do_reset
28
29echo "Test create synthetic event"
30
31echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events
32if [ ! -d events/synthetic/wakeup_latency ]; then
33 fail "Failed to create wakeup_latency synthetic event"
34fi
35
36reset_trigger
37
38echo "Test create synthetic event with an error"
39echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_events > /dev/null
40if [ -d events/synthetic/wakeup_latency ]; then
41 fail "Created wakeup_latency synthetic event with an invalid format"
42fi
43
44reset_trigger
45
46echo "Test remove synthetic event"
47echo '!wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events
48if [ -d events/synthetic/wakeup_latency ]; then
49 fail "Failed to delete wakeup_latency synthetic event"
50fi
51
52do_reset
53
54exit 0
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile
index a63e8453984d..8497a376ef9d 100644
--- a/tools/testing/selftests/futex/Makefile
+++ b/tools/testing/selftests/futex/Makefile
@@ -18,6 +18,10 @@ all:
18 done 18 done
19 19
20override define RUN_TESTS 20override define RUN_TESTS
21 @export KSFT_TAP_LEVEL=`echo 1`;
22 @echo "TAP version 13";
23 @echo "selftests: futex";
24 @echo "========================================";
21 @cd $(OUTPUT); ./run.sh 25 @cd $(OUTPUT); ./run.sh
22endef 26endef
23 27
diff --git a/tools/testing/selftests/intel_pstate/Makefile b/tools/testing/selftests/intel_pstate/Makefile
index 5a3f7d37e912..7340fd6a9a9f 100644
--- a/tools/testing/selftests/intel_pstate/Makefile
+++ b/tools/testing/selftests/intel_pstate/Makefile
@@ -2,7 +2,10 @@
2CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE 2CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
3LDLIBS := $(LDLIBS) -lm 3LDLIBS := $(LDLIBS) -lm
4 4
5ifeq (,$(filter $(ARCH),x86)) 5uname_M := $(shell uname -m 2>/dev/null || echo not)
6ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
7
8ifeq (x86,$(ARCH))
6TEST_GEN_FILES := msr aperf 9TEST_GEN_FILES := msr aperf
7endif 10endif
8 11
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 1a52b03962a3..1b9d8ecdebce 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -57,7 +57,8 @@ static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
57 57
58static inline void ksft_print_header(void) 58static inline void ksft_print_header(void)
59{ 59{
60 printf("TAP version 13\n"); 60 if (!(getenv("KSFT_TAP_LEVEL")))
61 printf("TAP version 13\n");
61} 62}
62 63
63static inline void ksft_print_cnts(void) 64static inline void ksft_print_cnts(void)
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index e81bd28bdd89..6ae3730c4ee3 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -107,6 +107,27 @@
107 __FILE__, __LINE__, _metadata->name, ##__VA_ARGS__) 107 __FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
108 108
109/** 109/**
110 * XFAIL(statement, fmt, ...)
111 *
112 * @statement: statement to run after reporting XFAIL
113 * @fmt: format string
114 * @...: optional arguments
115 *
116 * This forces a "pass" after reporting a failure with an XFAIL prefix,
117 * and runs "statement", which is usually "return" or "goto skip".
118 */
119#define XFAIL(statement, fmt, ...) do { \
120 if (TH_LOG_ENABLED) { \
121 fprintf(TH_LOG_STREAM, "[ XFAIL! ] " fmt "\n", \
122 ##__VA_ARGS__); \
123 } \
124 /* TODO: find a way to pass xfail to test runner process. */ \
125 _metadata->passed = 1; \
126 _metadata->trigger = 0; \
127 statement; \
128} while (0)
129
130/**
110 * TEST(test_name) - Defines the test function and creates the registration 131 * TEST(test_name) - Defines the test function and creates the registration
111 * stub 132 * stub
112 * 133 *
@@ -198,7 +219,7 @@
198 219
199/** 220/**
200 * FIXTURE_SETUP(fixture_name) - Prepares the setup function for the fixture. 221 * FIXTURE_SETUP(fixture_name) - Prepares the setup function for the fixture.
201 * *_metadata* is included so that ASSERT_* work as a convenience 222 * *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
202 * 223 *
203 * @fixture_name: fixture name 224 * @fixture_name: fixture name
204 * 225 *
@@ -221,6 +242,7 @@
221 FIXTURE_DATA(fixture_name) __attribute__((unused)) *self) 242 FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
222/** 243/**
223 * FIXTURE_TEARDOWN(fixture_name) 244 * FIXTURE_TEARDOWN(fixture_name)
245 * *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
224 * 246 *
225 * @fixture_name: fixture name 247 * @fixture_name: fixture name
226 * 248 *
@@ -253,6 +275,8 @@
253 * Defines a test that depends on a fixture (e.g., is part of a test case). 275 * Defines a test that depends on a fixture (e.g., is part of a test case).
254 * Very similar to TEST() except that *self* is the setup instance of fixture's 276 * Very similar to TEST() except that *self* is the setup instance of fixture's
255 * datatype exposed for use by the implementation. 277 * datatype exposed for use by the implementation.
278 *
279 * Warning: use of ASSERT_* here will skip TEARDOWN.
256 */ 280 */
257/* TODO(wad) register fixtures on dedicated test lists. */ 281/* TODO(wad) register fixtures on dedicated test lists. */
258#define TEST_F(fixture_name, test_name) \ 282#define TEST_F(fixture_name, test_name) \
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
new file mode 100644
index 000000000000..d9d00319b07c
--- /dev/null
+++ b/tools/testing/selftests/kvm/Makefile
@@ -0,0 +1,40 @@
1all:
2
3top_srcdir = ../../../../
4UNAME_M := $(shell uname -m)
5
6LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c
7LIBKVM_x86_64 = lib/x86.c lib/vmx.c
8
9TEST_GEN_PROGS_x86_64 = set_sregs_test
10TEST_GEN_PROGS_x86_64 += sync_regs_test
11TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
12
13TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M))
14LIBKVM += $(LIBKVM_$(UNAME_M))
15
16INSTALL_HDR_PATH = $(top_srcdir)/usr
17LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
18CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I..
19
20# After inclusion, $(OUTPUT) is defined and
21# $(TEST_GEN_PROGS) starts with $(OUTPUT)/
22include ../lib.mk
23
24STATIC_LIBS := $(OUTPUT)/libkvm.a
25LIBKVM_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM))
26EXTRA_CLEAN += $(LIBKVM_OBJ) $(STATIC_LIBS)
27
28x := $(shell mkdir -p $(sort $(dir $(LIBKVM_OBJ))))
29$(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
30 $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
31
32$(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
33 $(AR) crs $@ $^
34
35$(LINUX_HDR_PATH):
36 make -C $(top_srcdir) headers_install
37
38all: $(STATIC_LIBS) $(LINUX_HDR_PATH)
39$(TEST_GEN_PROGS): $(STATIC_LIBS)
40$(TEST_GEN_PROGS) $(LIBKVM_OBJ): | $(LINUX_HDR_PATH)
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
new file mode 100644
index 000000000000..637b7017b6ee
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -0,0 +1,145 @@
1/*
2 * tools/testing/selftests/kvm/include/kvm_util.h
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 */
9#ifndef SELFTEST_KVM_UTIL_H
10#define SELFTEST_KVM_UTIL_H 1
11
12#include "test_util.h"
13
14#include "asm/kvm.h"
15#include "linux/kvm.h"
16#include <sys/ioctl.h>
17
18#include "sparsebit.h"
19
20/*
21 * Memslots can't cover the gfn starting at this gpa otherwise vCPUs can't be
22 * created. Only applies to VMs using EPT.
23 */
24#define KVM_DEFAULT_IDENTITY_MAP_ADDRESS 0xfffbc000ul
25
26
27/* Callers of kvm_util only have an incomplete/opaque description of the
28 * structure kvm_util is using to maintain the state of a VM.
29 */
30struct kvm_vm;
31
32typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
33typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
34
35/* Minimum allocated guest virtual and physical addresses */
36#define KVM_UTIL_MIN_VADDR 0x2000
37
38#define DEFAULT_GUEST_PHY_PAGES 512
39#define DEFAULT_GUEST_STACK_VADDR_MIN 0xab6000
40#define DEFAULT_STACK_PGS 5
41
42enum vm_guest_mode {
43 VM_MODE_FLAT48PG,
44};
45
46enum vm_mem_backing_src_type {
47 VM_MEM_SRC_ANONYMOUS,
48 VM_MEM_SRC_ANONYMOUS_THP,
49 VM_MEM_SRC_ANONYMOUS_HUGETLB,
50};
51
52int kvm_check_cap(long cap);
53
54struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
55void kvm_vm_free(struct kvm_vm *vmp);
56
57int kvm_memcmp_hva_gva(void *hva,
58 struct kvm_vm *vm, const vm_vaddr_t gva, size_t len);
59
60void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename,
61 uint32_t data_memslot, uint32_t pgd_memslot);
62
63void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
64void vcpu_dump(FILE *stream, struct kvm_vm *vm,
65 uint32_t vcpuid, uint8_t indent);
66
67void vm_create_irqchip(struct kvm_vm *vm);
68
69void vm_userspace_mem_region_add(struct kvm_vm *vm,
70 enum vm_mem_backing_src_type src_type,
71 uint64_t guest_paddr, uint32_t slot, uint64_t npages,
72 uint32_t flags);
73
74void vcpu_ioctl(struct kvm_vm *vm,
75 uint32_t vcpuid, unsigned long ioctl, void *arg);
76void vm_ioctl(struct kvm_vm *vm, unsigned long ioctl, void *arg);
77void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
78void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid);
79vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
80 uint32_t data_memslot, uint32_t pgd_memslot);
81void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa);
82void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva);
83vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva);
84vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva);
85
86struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid);
87void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid);
88int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid);
89void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
90 struct kvm_mp_state *mp_state);
91void vcpu_regs_get(struct kvm_vm *vm,
92 uint32_t vcpuid, struct kvm_regs *regs);
93void vcpu_regs_set(struct kvm_vm *vm,
94 uint32_t vcpuid, struct kvm_regs *regs);
95void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...);
96void vcpu_sregs_get(struct kvm_vm *vm,
97 uint32_t vcpuid, struct kvm_sregs *sregs);
98void vcpu_sregs_set(struct kvm_vm *vm,
99 uint32_t vcpuid, struct kvm_sregs *sregs);
100int _vcpu_sregs_set(struct kvm_vm *vm,
101 uint32_t vcpuid, struct kvm_sregs *sregs);
102void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
103 struct kvm_vcpu_events *events);
104void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
105 struct kvm_vcpu_events *events);
106
107const char *exit_reason_str(unsigned int exit_reason);
108
109void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot);
110void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
111 uint32_t pgd_memslot);
112vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
113 vm_paddr_t paddr_min, uint32_t memslot);
114
115struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
116void vcpu_set_cpuid(
117 struct kvm_vm *vm, uint32_t vcpuid, struct kvm_cpuid2 *cpuid);
118
119struct kvm_cpuid_entry2 *
120kvm_get_supported_cpuid_index(uint32_t function, uint32_t index);
121
122static inline struct kvm_cpuid_entry2 *
123kvm_get_supported_cpuid_entry(uint32_t function)
124{
125 return kvm_get_supported_cpuid_index(function, 0);
126}
127
128struct kvm_vm *vm_create_default(uint32_t vcpuid, void *guest_code);
129void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code);
130
131typedef void (*vmx_guest_code_t)(vm_vaddr_t vmxon_vaddr,
132 vm_paddr_t vmxon_paddr,
133 vm_vaddr_t vmcs_vaddr,
134 vm_paddr_t vmcs_paddr);
135
136struct kvm_userspace_memory_region *
137kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
138 uint64_t end);
139
140struct kvm_dirty_log *
141allocate_kvm_dirty_log(struct kvm_userspace_memory_region *region);
142
143int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd);
144
145#endif /* SELFTEST_KVM_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/sparsebit.h b/tools/testing/selftests/kvm/include/sparsebit.h
new file mode 100644
index 000000000000..54cfeb6568d3
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/sparsebit.h
@@ -0,0 +1,75 @@
1/*
2 * tools/testing/selftests/kvm/include/sparsebit.h
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 *
9 * Header file that describes API to the sparsebit library.
10 * This library provides a memory efficient means of storing
11 * the settings of bits indexed via a uint64_t. Memory usage
12 * is reasonable, significantly less than (2^64 / 8) bytes, as
13 * long as bits that are mostly set or mostly cleared are close
14 * to each other. This library is efficient in memory usage
15 * even in the case where most bits are set.
16 */
17
18#ifndef _TEST_SPARSEBIT_H_
19#define _TEST_SPARSEBIT_H_
20
21#include <stdbool.h>
22#include <stdint.h>
23#include <stdio.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29struct sparsebit;
30typedef uint64_t sparsebit_idx_t;
31typedef uint64_t sparsebit_num_t;
32
33struct sparsebit *sparsebit_alloc(void);
34void sparsebit_free(struct sparsebit **sbitp);
35void sparsebit_copy(struct sparsebit *dstp, struct sparsebit *src);
36
37bool sparsebit_is_set(struct sparsebit *sbit, sparsebit_idx_t idx);
38bool sparsebit_is_set_num(struct sparsebit *sbit,
39 sparsebit_idx_t idx, sparsebit_num_t num);
40bool sparsebit_is_clear(struct sparsebit *sbit, sparsebit_idx_t idx);
41bool sparsebit_is_clear_num(struct sparsebit *sbit,
42 sparsebit_idx_t idx, sparsebit_num_t num);
43sparsebit_num_t sparsebit_num_set(struct sparsebit *sbit);
44bool sparsebit_any_set(struct sparsebit *sbit);
45bool sparsebit_any_clear(struct sparsebit *sbit);
46bool sparsebit_all_set(struct sparsebit *sbit);
47bool sparsebit_all_clear(struct sparsebit *sbit);
48sparsebit_idx_t sparsebit_first_set(struct sparsebit *sbit);
49sparsebit_idx_t sparsebit_first_clear(struct sparsebit *sbit);
50sparsebit_idx_t sparsebit_next_set(struct sparsebit *sbit, sparsebit_idx_t prev);
51sparsebit_idx_t sparsebit_next_clear(struct sparsebit *sbit, sparsebit_idx_t prev);
52sparsebit_idx_t sparsebit_next_set_num(struct sparsebit *sbit,
53 sparsebit_idx_t start, sparsebit_num_t num);
54sparsebit_idx_t sparsebit_next_clear_num(struct sparsebit *sbit,
55 sparsebit_idx_t start, sparsebit_num_t num);
56
57void sparsebit_set(struct sparsebit *sbitp, sparsebit_idx_t idx);
58void sparsebit_set_num(struct sparsebit *sbitp, sparsebit_idx_t start,
59 sparsebit_num_t num);
60void sparsebit_set_all(struct sparsebit *sbitp);
61
62void sparsebit_clear(struct sparsebit *sbitp, sparsebit_idx_t idx);
63void sparsebit_clear_num(struct sparsebit *sbitp,
64 sparsebit_idx_t start, sparsebit_num_t num);
65void sparsebit_clear_all(struct sparsebit *sbitp);
66
67void sparsebit_dump(FILE *stream, struct sparsebit *sbit,
68 unsigned int indent);
69void sparsebit_validate_internal(struct sparsebit *sbit);
70
71#ifdef __cplusplus
72}
73#endif
74
75#endif /* _TEST_SPARSEBIT_H_ */
diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h
new file mode 100644
index 000000000000..ac53730b30aa
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/test_util.h
@@ -0,0 +1,46 @@
1/*
2 * tools/testing/selftests/kvm/include/test_util.h
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 */
9
10#ifndef TEST_UTIL_H
11#define TEST_UTIL_H 1
12
13#include <stdlib.h>
14#include <stdarg.h>
15#include <stdbool.h>
16#include <stdio.h>
17#include <string.h>
18#include <inttypes.h>
19#include <errno.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include "kselftest.h"
23
24ssize_t test_write(int fd, const void *buf, size_t count);
25ssize_t test_read(int fd, void *buf, size_t count);
26int test_seq_read(const char *path, char **bufp, size_t *sizep);
27
28void test_assert(bool exp, const char *exp_str,
29 const char *file, unsigned int line, const char *fmt, ...);
30
31#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
32
33#define TEST_ASSERT(e, fmt, ...) \
34 test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
35
36#define ASSERT_EQ(a, b) do { \
37 typeof(a) __a = (a); \
38 typeof(b) __b = (b); \
39 TEST_ASSERT(__a == __b, \
40 "ASSERT_EQ(%s, %s) failed.\n" \
41 "\t%s is %#lx\n" \
42 "\t%s is %#lx", \
43 #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \
44} while (0)
45
46#endif /* TEST_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/vmx.h b/tools/testing/selftests/kvm/include/vmx.h
new file mode 100644
index 000000000000..6ed8499807fd
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/vmx.h
@@ -0,0 +1,494 @@
1/*
2 * tools/testing/selftests/kvm/include/vmx.h
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 */
9
10#ifndef SELFTEST_KVM_VMX_H
11#define SELFTEST_KVM_VMX_H
12
13#include <stdint.h>
14#include "x86.h"
15
16#define CPUID_VMX_BIT 5
17
18#define CPUID_VMX (1 << 5)
19
20/*
21 * Definitions of Primary Processor-Based VM-Execution Controls.
22 */
23#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004
24#define CPU_BASED_USE_TSC_OFFSETING 0x00000008
25#define CPU_BASED_HLT_EXITING 0x00000080
26#define CPU_BASED_INVLPG_EXITING 0x00000200
27#define CPU_BASED_MWAIT_EXITING 0x00000400
28#define CPU_BASED_RDPMC_EXITING 0x00000800
29#define CPU_BASED_RDTSC_EXITING 0x00001000
30#define CPU_BASED_CR3_LOAD_EXITING 0x00008000
31#define CPU_BASED_CR3_STORE_EXITING 0x00010000
32#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
33#define CPU_BASED_CR8_STORE_EXITING 0x00100000
34#define CPU_BASED_TPR_SHADOW 0x00200000
35#define CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000
36#define CPU_BASED_MOV_DR_EXITING 0x00800000
37#define CPU_BASED_UNCOND_IO_EXITING 0x01000000
38#define CPU_BASED_USE_IO_BITMAPS 0x02000000
39#define CPU_BASED_MONITOR_TRAP 0x08000000
40#define CPU_BASED_USE_MSR_BITMAPS 0x10000000
41#define CPU_BASED_MONITOR_EXITING 0x20000000
42#define CPU_BASED_PAUSE_EXITING 0x40000000
43#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000
44
45#define CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x0401e172
46
47/*
48 * Definitions of Secondary Processor-Based VM-Execution Controls.
49 */
50#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
51#define SECONDARY_EXEC_ENABLE_EPT 0x00000002
52#define SECONDARY_EXEC_DESC 0x00000004
53#define SECONDARY_EXEC_RDTSCP 0x00000008
54#define SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE 0x00000010
55#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
56#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
57#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
58#define SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100
59#define SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY 0x00000200
60#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
61#define SECONDARY_EXEC_RDRAND_EXITING 0x00000800
62#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
63#define SECONDARY_EXEC_ENABLE_VMFUNC 0x00002000
64#define SECONDARY_EXEC_SHADOW_VMCS 0x00004000
65#define SECONDARY_EXEC_RDSEED_EXITING 0x00010000
66#define SECONDARY_EXEC_ENABLE_PML 0x00020000
67#define SECONDARY_EPT_VE 0x00040000
68#define SECONDARY_ENABLE_XSAV_RESTORE 0x00100000
69#define SECONDARY_EXEC_TSC_SCALING 0x02000000
70
71#define PIN_BASED_EXT_INTR_MASK 0x00000001
72#define PIN_BASED_NMI_EXITING 0x00000008
73#define PIN_BASED_VIRTUAL_NMIS 0x00000020
74#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040
75#define PIN_BASED_POSTED_INTR 0x00000080
76
77#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
78
79#define VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004
80#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200
81#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000
82#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
83#define VM_EXIT_SAVE_IA32_PAT 0x00040000
84#define VM_EXIT_LOAD_IA32_PAT 0x00080000
85#define VM_EXIT_SAVE_IA32_EFER 0x00100000
86#define VM_EXIT_LOAD_IA32_EFER 0x00200000
87#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000
88
89#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff
90
91#define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004
92#define VM_ENTRY_IA32E_MODE 0x00000200
93#define VM_ENTRY_SMM 0x00000400
94#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
95#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000
96#define VM_ENTRY_LOAD_IA32_PAT 0x00004000
97#define VM_ENTRY_LOAD_IA32_EFER 0x00008000
98
99#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff
100
101#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK 0x0000001f
102#define VMX_MISC_SAVE_EFER_LMA 0x00000020
103
104#define EXIT_REASON_FAILED_VMENTRY 0x80000000
105#define EXIT_REASON_EXCEPTION_NMI 0
106#define EXIT_REASON_EXTERNAL_INTERRUPT 1
107#define EXIT_REASON_TRIPLE_FAULT 2
108#define EXIT_REASON_PENDING_INTERRUPT 7
109#define EXIT_REASON_NMI_WINDOW 8
110#define EXIT_REASON_TASK_SWITCH 9
111#define EXIT_REASON_CPUID 10
112#define EXIT_REASON_HLT 12
113#define EXIT_REASON_INVD 13
114#define EXIT_REASON_INVLPG 14
115#define EXIT_REASON_RDPMC 15
116#define EXIT_REASON_RDTSC 16
117#define EXIT_REASON_VMCALL 18
118#define EXIT_REASON_VMCLEAR 19
119#define EXIT_REASON_VMLAUNCH 20
120#define EXIT_REASON_VMPTRLD 21
121#define EXIT_REASON_VMPTRST 22
122#define EXIT_REASON_VMREAD 23
123#define EXIT_REASON_VMRESUME 24
124#define EXIT_REASON_VMWRITE 25
125#define EXIT_REASON_VMOFF 26
126#define EXIT_REASON_VMON 27
127#define EXIT_REASON_CR_ACCESS 28
128#define EXIT_REASON_DR_ACCESS 29
129#define EXIT_REASON_IO_INSTRUCTION 30
130#define EXIT_REASON_MSR_READ 31
131#define EXIT_REASON_MSR_WRITE 32
132#define EXIT_REASON_INVALID_STATE 33
133#define EXIT_REASON_MWAIT_INSTRUCTION 36
134#define EXIT_REASON_MONITOR_INSTRUCTION 39
135#define EXIT_REASON_PAUSE_INSTRUCTION 40
136#define EXIT_REASON_MCE_DURING_VMENTRY 41
137#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
138#define EXIT_REASON_APIC_ACCESS 44
139#define EXIT_REASON_EOI_INDUCED 45
140#define EXIT_REASON_EPT_VIOLATION 48
141#define EXIT_REASON_EPT_MISCONFIG 49
142#define EXIT_REASON_INVEPT 50
143#define EXIT_REASON_RDTSCP 51
144#define EXIT_REASON_PREEMPTION_TIMER 52
145#define EXIT_REASON_INVVPID 53
146#define EXIT_REASON_WBINVD 54
147#define EXIT_REASON_XSETBV 55
148#define EXIT_REASON_APIC_WRITE 56
149#define EXIT_REASON_INVPCID 58
150#define EXIT_REASON_PML_FULL 62
151#define EXIT_REASON_XSAVES 63
152#define EXIT_REASON_XRSTORS 64
153#define LAST_EXIT_REASON 64
154
155enum vmcs_field {
156 VIRTUAL_PROCESSOR_ID = 0x00000000,
157 POSTED_INTR_NV = 0x00000002,
158 GUEST_ES_SELECTOR = 0x00000800,
159 GUEST_CS_SELECTOR = 0x00000802,
160 GUEST_SS_SELECTOR = 0x00000804,
161 GUEST_DS_SELECTOR = 0x00000806,
162 GUEST_FS_SELECTOR = 0x00000808,
163 GUEST_GS_SELECTOR = 0x0000080a,
164 GUEST_LDTR_SELECTOR = 0x0000080c,
165 GUEST_TR_SELECTOR = 0x0000080e,
166 GUEST_INTR_STATUS = 0x00000810,
167 GUEST_PML_INDEX = 0x00000812,
168 HOST_ES_SELECTOR = 0x00000c00,
169 HOST_CS_SELECTOR = 0x00000c02,
170 HOST_SS_SELECTOR = 0x00000c04,
171 HOST_DS_SELECTOR = 0x00000c06,
172 HOST_FS_SELECTOR = 0x00000c08,
173 HOST_GS_SELECTOR = 0x00000c0a,
174 HOST_TR_SELECTOR = 0x00000c0c,
175 IO_BITMAP_A = 0x00002000,
176 IO_BITMAP_A_HIGH = 0x00002001,
177 IO_BITMAP_B = 0x00002002,
178 IO_BITMAP_B_HIGH = 0x00002003,
179 MSR_BITMAP = 0x00002004,
180 MSR_BITMAP_HIGH = 0x00002005,
181 VM_EXIT_MSR_STORE_ADDR = 0x00002006,
182 VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
183 VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
184 VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
185 VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
186 VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
187 PML_ADDRESS = 0x0000200e,
188 PML_ADDRESS_HIGH = 0x0000200f,
189 TSC_OFFSET = 0x00002010,
190 TSC_OFFSET_HIGH = 0x00002011,
191 VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
192 VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
193 APIC_ACCESS_ADDR = 0x00002014,
194 APIC_ACCESS_ADDR_HIGH = 0x00002015,
195 POSTED_INTR_DESC_ADDR = 0x00002016,
196 POSTED_INTR_DESC_ADDR_HIGH = 0x00002017,
197 EPT_POINTER = 0x0000201a,
198 EPT_POINTER_HIGH = 0x0000201b,
199 EOI_EXIT_BITMAP0 = 0x0000201c,
200 EOI_EXIT_BITMAP0_HIGH = 0x0000201d,
201 EOI_EXIT_BITMAP1 = 0x0000201e,
202 EOI_EXIT_BITMAP1_HIGH = 0x0000201f,
203 EOI_EXIT_BITMAP2 = 0x00002020,
204 EOI_EXIT_BITMAP2_HIGH = 0x00002021,
205 EOI_EXIT_BITMAP3 = 0x00002022,
206 EOI_EXIT_BITMAP3_HIGH = 0x00002023,
207 VMREAD_BITMAP = 0x00002026,
208 VMREAD_BITMAP_HIGH = 0x00002027,
209 VMWRITE_BITMAP = 0x00002028,
210 VMWRITE_BITMAP_HIGH = 0x00002029,
211 XSS_EXIT_BITMAP = 0x0000202C,
212 XSS_EXIT_BITMAP_HIGH = 0x0000202D,
213 TSC_MULTIPLIER = 0x00002032,
214 TSC_MULTIPLIER_HIGH = 0x00002033,
215 GUEST_PHYSICAL_ADDRESS = 0x00002400,
216 GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
217 VMCS_LINK_POINTER = 0x00002800,
218 VMCS_LINK_POINTER_HIGH = 0x00002801,
219 GUEST_IA32_DEBUGCTL = 0x00002802,
220 GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
221 GUEST_IA32_PAT = 0x00002804,
222 GUEST_IA32_PAT_HIGH = 0x00002805,
223 GUEST_IA32_EFER = 0x00002806,
224 GUEST_IA32_EFER_HIGH = 0x00002807,
225 GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808,
226 GUEST_IA32_PERF_GLOBAL_CTRL_HIGH= 0x00002809,
227 GUEST_PDPTR0 = 0x0000280a,
228 GUEST_PDPTR0_HIGH = 0x0000280b,
229 GUEST_PDPTR1 = 0x0000280c,
230 GUEST_PDPTR1_HIGH = 0x0000280d,
231 GUEST_PDPTR2 = 0x0000280e,
232 GUEST_PDPTR2_HIGH = 0x0000280f,
233 GUEST_PDPTR3 = 0x00002810,
234 GUEST_PDPTR3_HIGH = 0x00002811,
235 GUEST_BNDCFGS = 0x00002812,
236 GUEST_BNDCFGS_HIGH = 0x00002813,
237 HOST_IA32_PAT = 0x00002c00,
238 HOST_IA32_PAT_HIGH = 0x00002c01,
239 HOST_IA32_EFER = 0x00002c02,
240 HOST_IA32_EFER_HIGH = 0x00002c03,
241 HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,
242 HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,
243 PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
244 CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
245 EXCEPTION_BITMAP = 0x00004004,
246 PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
247 PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
248 CR3_TARGET_COUNT = 0x0000400a,
249 VM_EXIT_CONTROLS = 0x0000400c,
250 VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
251 VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
252 VM_ENTRY_CONTROLS = 0x00004012,
253 VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
254 VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
255 VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
256 VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
257 TPR_THRESHOLD = 0x0000401c,
258 SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
259 PLE_GAP = 0x00004020,
260 PLE_WINDOW = 0x00004022,
261 VM_INSTRUCTION_ERROR = 0x00004400,
262 VM_EXIT_REASON = 0x00004402,
263 VM_EXIT_INTR_INFO = 0x00004404,
264 VM_EXIT_INTR_ERROR_CODE = 0x00004406,
265 IDT_VECTORING_INFO_FIELD = 0x00004408,
266 IDT_VECTORING_ERROR_CODE = 0x0000440a,
267 VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
268 VMX_INSTRUCTION_INFO = 0x0000440e,
269 GUEST_ES_LIMIT = 0x00004800,
270 GUEST_CS_LIMIT = 0x00004802,
271 GUEST_SS_LIMIT = 0x00004804,
272 GUEST_DS_LIMIT = 0x00004806,
273 GUEST_FS_LIMIT = 0x00004808,
274 GUEST_GS_LIMIT = 0x0000480a,
275 GUEST_LDTR_LIMIT = 0x0000480c,
276 GUEST_TR_LIMIT = 0x0000480e,
277 GUEST_GDTR_LIMIT = 0x00004810,
278 GUEST_IDTR_LIMIT = 0x00004812,
279 GUEST_ES_AR_BYTES = 0x00004814,
280 GUEST_CS_AR_BYTES = 0x00004816,
281 GUEST_SS_AR_BYTES = 0x00004818,
282 GUEST_DS_AR_BYTES = 0x0000481a,
283 GUEST_FS_AR_BYTES = 0x0000481c,
284 GUEST_GS_AR_BYTES = 0x0000481e,
285 GUEST_LDTR_AR_BYTES = 0x00004820,
286 GUEST_TR_AR_BYTES = 0x00004822,
287 GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
288 GUEST_ACTIVITY_STATE = 0X00004826,
289 GUEST_SYSENTER_CS = 0x0000482A,
290 VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
291 HOST_IA32_SYSENTER_CS = 0x00004c00,
292 CR0_GUEST_HOST_MASK = 0x00006000,
293 CR4_GUEST_HOST_MASK = 0x00006002,
294 CR0_READ_SHADOW = 0x00006004,
295 CR4_READ_SHADOW = 0x00006006,
296 CR3_TARGET_VALUE0 = 0x00006008,
297 CR3_TARGET_VALUE1 = 0x0000600a,
298 CR3_TARGET_VALUE2 = 0x0000600c,
299 CR3_TARGET_VALUE3 = 0x0000600e,
300 EXIT_QUALIFICATION = 0x00006400,
301 GUEST_LINEAR_ADDRESS = 0x0000640a,
302 GUEST_CR0 = 0x00006800,
303 GUEST_CR3 = 0x00006802,
304 GUEST_CR4 = 0x00006804,
305 GUEST_ES_BASE = 0x00006806,
306 GUEST_CS_BASE = 0x00006808,
307 GUEST_SS_BASE = 0x0000680a,
308 GUEST_DS_BASE = 0x0000680c,
309 GUEST_FS_BASE = 0x0000680e,
310 GUEST_GS_BASE = 0x00006810,
311 GUEST_LDTR_BASE = 0x00006812,
312 GUEST_TR_BASE = 0x00006814,
313 GUEST_GDTR_BASE = 0x00006816,
314 GUEST_IDTR_BASE = 0x00006818,
315 GUEST_DR7 = 0x0000681a,
316 GUEST_RSP = 0x0000681c,
317 GUEST_RIP = 0x0000681e,
318 GUEST_RFLAGS = 0x00006820,
319 GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
320 GUEST_SYSENTER_ESP = 0x00006824,
321 GUEST_SYSENTER_EIP = 0x00006826,
322 HOST_CR0 = 0x00006c00,
323 HOST_CR3 = 0x00006c02,
324 HOST_CR4 = 0x00006c04,
325 HOST_FS_BASE = 0x00006c06,
326 HOST_GS_BASE = 0x00006c08,
327 HOST_TR_BASE = 0x00006c0a,
328 HOST_GDTR_BASE = 0x00006c0c,
329 HOST_IDTR_BASE = 0x00006c0e,
330 HOST_IA32_SYSENTER_ESP = 0x00006c10,
331 HOST_IA32_SYSENTER_EIP = 0x00006c12,
332 HOST_RSP = 0x00006c14,
333 HOST_RIP = 0x00006c16,
334};
335
336struct vmx_msr_entry {
337 uint32_t index;
338 uint32_t reserved;
339 uint64_t value;
340} __attribute__ ((aligned(16)));
341
342static inline int vmxon(uint64_t phys)
343{
344 uint8_t ret;
345
346 __asm__ __volatile__ ("vmxon %[pa]; setna %[ret]"
347 : [ret]"=rm"(ret)
348 : [pa]"m"(phys)
349 : "cc", "memory");
350
351 return ret;
352}
353
354static inline void vmxoff(void)
355{
356 __asm__ __volatile__("vmxoff");
357}
358
359static inline int vmclear(uint64_t vmcs_pa)
360{
361 uint8_t ret;
362
363 __asm__ __volatile__ ("vmclear %[pa]; setna %[ret]"
364 : [ret]"=rm"(ret)
365 : [pa]"m"(vmcs_pa)
366 : "cc", "memory");
367
368 return ret;
369}
370
371static inline int vmptrld(uint64_t vmcs_pa)
372{
373 uint8_t ret;
374
375 __asm__ __volatile__ ("vmptrld %[pa]; setna %[ret]"
376 : [ret]"=rm"(ret)
377 : [pa]"m"(vmcs_pa)
378 : "cc", "memory");
379
380 return ret;
381}
382
383/*
384 * No guest state (e.g. GPRs) is established by this vmlaunch.
385 */
386static inline int vmlaunch(void)
387{
388 int ret;
389
390 __asm__ __volatile__("push %%rbp;"
391 "push %%rcx;"
392 "push %%rdx;"
393 "push %%rsi;"
394 "push %%rdi;"
395 "push $0;"
396 "vmwrite %%rsp, %[host_rsp];"
397 "lea 1f(%%rip), %%rax;"
398 "vmwrite %%rax, %[host_rip];"
399 "vmlaunch;"
400 "incq (%%rsp);"
401 "1: pop %%rax;"
402 "pop %%rdi;"
403 "pop %%rsi;"
404 "pop %%rdx;"
405 "pop %%rcx;"
406 "pop %%rbp;"
407 : [ret]"=&a"(ret)
408 : [host_rsp]"r"((uint64_t)HOST_RSP),
409 [host_rip]"r"((uint64_t)HOST_RIP)
410 : "memory", "cc", "rbx", "r8", "r9", "r10",
411 "r11", "r12", "r13", "r14", "r15");
412 return ret;
413}
414
415/*
416 * No guest state (e.g. GPRs) is established by this vmresume.
417 */
418static inline int vmresume(void)
419{
420 int ret;
421
422 __asm__ __volatile__("push %%rbp;"
423 "push %%rcx;"
424 "push %%rdx;"
425 "push %%rsi;"
426 "push %%rdi;"
427 "push $0;"
428 "vmwrite %%rsp, %[host_rsp];"
429 "lea 1f(%%rip), %%rax;"
430 "vmwrite %%rax, %[host_rip];"
431 "vmresume;"
432 "incq (%%rsp);"
433 "1: pop %%rax;"
434 "pop %%rdi;"
435 "pop %%rsi;"
436 "pop %%rdx;"
437 "pop %%rcx;"
438 "pop %%rbp;"
439 : [ret]"=&a"(ret)
440 : [host_rsp]"r"((uint64_t)HOST_RSP),
441 [host_rip]"r"((uint64_t)HOST_RIP)
442 : "memory", "cc", "rbx", "r8", "r9", "r10",
443 "r11", "r12", "r13", "r14", "r15");
444 return ret;
445}
446
447static inline int vmread(uint64_t encoding, uint64_t *value)
448{
449 uint64_t tmp;
450 uint8_t ret;
451
452 __asm__ __volatile__("vmread %[encoding], %[value]; setna %[ret]"
453 : [value]"=rm"(tmp), [ret]"=rm"(ret)
454 : [encoding]"r"(encoding)
455 : "cc", "memory");
456
457 *value = tmp;
458 return ret;
459}
460
461/*
462 * A wrapper around vmread that ignores errors and returns zero if the
463 * vmread instruction fails.
464 */
465static inline uint64_t vmreadz(uint64_t encoding)
466{
467 uint64_t value = 0;
468 vmread(encoding, &value);
469 return value;
470}
471
472static inline int vmwrite(uint64_t encoding, uint64_t value)
473{
474 uint8_t ret;
475
476 __asm__ __volatile__ ("vmwrite %[value], %[encoding]; setna %[ret]"
477 : [ret]"=rm"(ret)
478 : [value]"rm"(value), [encoding]"r"(encoding)
479 : "cc", "memory");
480
481 return ret;
482}
483
484static inline uint32_t vmcs_revision(void)
485{
486 return rdmsr(MSR_IA32_VMX_BASIC);
487}
488
489void prepare_for_vmx_operation(void);
490void prepare_vmcs(void *guest_rip, void *guest_rsp);
491struct kvm_vm *vm_create_default_vmx(uint32_t vcpuid,
492 vmx_guest_code_t guest_code);
493
494#endif /* !SELFTEST_KVM_VMX_H */
diff --git a/tools/testing/selftests/kvm/include/x86.h b/tools/testing/selftests/kvm/include/x86.h
new file mode 100644
index 000000000000..4a5b2c4c1a0f
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/x86.h
@@ -0,0 +1,1043 @@
1/*
2 * tools/testing/selftests/kvm/include/x86.h
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 */
9
10#ifndef SELFTEST_KVM_X86_H
11#define SELFTEST_KVM_X86_H
12
13#include <assert.h>
14#include <stdint.h>
15
16#define X86_EFLAGS_FIXED (1u << 1)
17
18#define X86_CR4_VME (1ul << 0)
19#define X86_CR4_PVI (1ul << 1)
20#define X86_CR4_TSD (1ul << 2)
21#define X86_CR4_DE (1ul << 3)
22#define X86_CR4_PSE (1ul << 4)
23#define X86_CR4_PAE (1ul << 5)
24#define X86_CR4_MCE (1ul << 6)
25#define X86_CR4_PGE (1ul << 7)
26#define X86_CR4_PCE (1ul << 8)
27#define X86_CR4_OSFXSR (1ul << 9)
28#define X86_CR4_OSXMMEXCPT (1ul << 10)
29#define X86_CR4_UMIP (1ul << 11)
30#define X86_CR4_VMXE (1ul << 13)
31#define X86_CR4_SMXE (1ul << 14)
32#define X86_CR4_FSGSBASE (1ul << 16)
33#define X86_CR4_PCIDE (1ul << 17)
34#define X86_CR4_OSXSAVE (1ul << 18)
35#define X86_CR4_SMEP (1ul << 20)
36#define X86_CR4_SMAP (1ul << 21)
37#define X86_CR4_PKE (1ul << 22)
38
39/* The enum values match the intruction encoding of each register */
40enum x86_register {
41 RAX = 0,
42 RCX,
43 RDX,
44 RBX,
45 RSP,
46 RBP,
47 RSI,
48 RDI,
49 R8,
50 R9,
51 R10,
52 R11,
53 R12,
54 R13,
55 R14,
56 R15,
57};
58
59struct desc64 {
60 uint16_t limit0;
61 uint16_t base0;
62 unsigned base1:8, type:5, dpl:2, p:1;
63 unsigned limit1:4, zero0:3, g:1, base2:8;
64 uint32_t base3;
65 uint32_t zero1;
66} __attribute__((packed));
67
68struct desc_ptr {
69 uint16_t size;
70 uint64_t address;
71} __attribute__((packed));
72
73static inline uint64_t get_desc64_base(const struct desc64 *desc)
74{
75 return ((uint64_t)desc->base3 << 32) |
76 (desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
77}
78
79static inline uint64_t rdtsc(void)
80{
81 uint32_t eax, edx;
82
83 /*
84 * The lfence is to wait (on Intel CPUs) until all previous
85 * instructions have been executed.
86 */
87 __asm__ __volatile__("lfence; rdtsc" : "=a"(eax), "=d"(edx));
88 return ((uint64_t)edx) << 32 | eax;
89}
90
91static inline uint64_t rdtscp(uint32_t *aux)
92{
93 uint32_t eax, edx;
94
95 __asm__ __volatile__("rdtscp" : "=a"(eax), "=d"(edx), "=c"(*aux));
96 return ((uint64_t)edx) << 32 | eax;
97}
98
99static inline uint64_t rdmsr(uint32_t msr)
100{
101 uint32_t a, d;
102
103 __asm__ __volatile__("rdmsr" : "=a"(a), "=d"(d) : "c"(msr) : "memory");
104
105 return a | ((uint64_t) d << 32);
106}
107
108static inline void wrmsr(uint32_t msr, uint64_t value)
109{
110 uint32_t a = value;
111 uint32_t d = value >> 32;
112
113 __asm__ __volatile__("wrmsr" :: "a"(a), "d"(d), "c"(msr) : "memory");
114}
115
116
117static inline uint16_t inw(uint16_t port)
118{
119 uint16_t tmp;
120
121 __asm__ __volatile__("in %%dx, %%ax"
122 : /* output */ "=a" (tmp)
123 : /* input */ "d" (port));
124
125 return tmp;
126}
127
128static inline uint16_t get_es(void)
129{
130 uint16_t es;
131
132 __asm__ __volatile__("mov %%es, %[es]"
133 : /* output */ [es]"=rm"(es));
134 return es;
135}
136
137static inline uint16_t get_cs(void)
138{
139 uint16_t cs;
140
141 __asm__ __volatile__("mov %%cs, %[cs]"
142 : /* output */ [cs]"=rm"(cs));
143 return cs;
144}
145
146static inline uint16_t get_ss(void)
147{
148 uint16_t ss;
149
150 __asm__ __volatile__("mov %%ss, %[ss]"
151 : /* output */ [ss]"=rm"(ss));
152 return ss;
153}
154
155static inline uint16_t get_ds(void)
156{
157 uint16_t ds;
158
159 __asm__ __volatile__("mov %%ds, %[ds]"
160 : /* output */ [ds]"=rm"(ds));
161 return ds;
162}
163
164static inline uint16_t get_fs(void)
165{
166 uint16_t fs;
167
168 __asm__ __volatile__("mov %%fs, %[fs]"
169 : /* output */ [fs]"=rm"(fs));
170 return fs;
171}
172
173static inline uint16_t get_gs(void)
174{
175 uint16_t gs;
176
177 __asm__ __volatile__("mov %%gs, %[gs]"
178 : /* output */ [gs]"=rm"(gs));
179 return gs;
180}
181
182static inline uint16_t get_tr(void)
183{
184 uint16_t tr;
185
186 __asm__ __volatile__("str %[tr]"
187 : /* output */ [tr]"=rm"(tr));
188 return tr;
189}
190
191static inline uint64_t get_cr0(void)
192{
193 uint64_t cr0;
194
195 __asm__ __volatile__("mov %%cr0, %[cr0]"
196 : /* output */ [cr0]"=r"(cr0));
197 return cr0;
198}
199
200static inline uint64_t get_cr3(void)
201{
202 uint64_t cr3;
203
204 __asm__ __volatile__("mov %%cr3, %[cr3]"
205 : /* output */ [cr3]"=r"(cr3));
206 return cr3;
207}
208
209static inline uint64_t get_cr4(void)
210{
211 uint64_t cr4;
212
213 __asm__ __volatile__("mov %%cr4, %[cr4]"
214 : /* output */ [cr4]"=r"(cr4));
215 return cr4;
216}
217
218static inline void set_cr4(uint64_t val)
219{
220 __asm__ __volatile__("mov %0, %%cr4" : : "r" (val) : "memory");
221}
222
223static inline uint64_t get_gdt_base(void)
224{
225 struct desc_ptr gdt;
226 __asm__ __volatile__("sgdt %[gdt]"
227 : /* output */ [gdt]"=m"(gdt));
228 return gdt.address;
229}
230
231static inline uint64_t get_idt_base(void)
232{
233 struct desc_ptr idt;
234 __asm__ __volatile__("sidt %[idt]"
235 : /* output */ [idt]"=m"(idt));
236 return idt.address;
237}
238
239#define SET_XMM(__var, __xmm) \
240 asm volatile("movq %0, %%"#__xmm : : "r"(__var) : #__xmm)
241
242static inline void set_xmm(int n, unsigned long val)
243{
244 switch (n) {
245 case 0:
246 SET_XMM(val, xmm0);
247 break;
248 case 1:
249 SET_XMM(val, xmm1);
250 break;
251 case 2:
252 SET_XMM(val, xmm2);
253 break;
254 case 3:
255 SET_XMM(val, xmm3);
256 break;
257 case 4:
258 SET_XMM(val, xmm4);
259 break;
260 case 5:
261 SET_XMM(val, xmm5);
262 break;
263 case 6:
264 SET_XMM(val, xmm6);
265 break;
266 case 7:
267 SET_XMM(val, xmm7);
268 break;
269 }
270}
271
272typedef unsigned long v1di __attribute__ ((vector_size (8)));
273static inline unsigned long get_xmm(int n)
274{
275 assert(n >= 0 && n <= 7);
276
277 register v1di xmm0 __asm__("%xmm0");
278 register v1di xmm1 __asm__("%xmm1");
279 register v1di xmm2 __asm__("%xmm2");
280 register v1di xmm3 __asm__("%xmm3");
281 register v1di xmm4 __asm__("%xmm4");
282 register v1di xmm5 __asm__("%xmm5");
283 register v1di xmm6 __asm__("%xmm6");
284 register v1di xmm7 __asm__("%xmm7");
285 switch (n) {
286 case 0:
287 return (unsigned long)xmm0;
288 case 1:
289 return (unsigned long)xmm1;
290 case 2:
291 return (unsigned long)xmm2;
292 case 3:
293 return (unsigned long)xmm3;
294 case 4:
295 return (unsigned long)xmm4;
296 case 5:
297 return (unsigned long)xmm5;
298 case 6:
299 return (unsigned long)xmm6;
300 case 7:
301 return (unsigned long)xmm7;
302 }
303 return 0;
304}
305
306/*
307 * Basic CPU control in CR0
308 */
309#define X86_CR0_PE (1UL<<0) /* Protection Enable */
310#define X86_CR0_MP (1UL<<1) /* Monitor Coprocessor */
311#define X86_CR0_EM (1UL<<2) /* Emulation */
312#define X86_CR0_TS (1UL<<3) /* Task Switched */
313#define X86_CR0_ET (1UL<<4) /* Extension Type */
314#define X86_CR0_NE (1UL<<5) /* Numeric Error */
315#define X86_CR0_WP (1UL<<16) /* Write Protect */
316#define X86_CR0_AM (1UL<<18) /* Alignment Mask */
317#define X86_CR0_NW (1UL<<29) /* Not Write-through */
318#define X86_CR0_CD (1UL<<30) /* Cache Disable */
319#define X86_CR0_PG (1UL<<31) /* Paging */
320
321/*
322 * CPU model specific register (MSR) numbers.
323 */
324
325/* x86-64 specific MSRs */
326#define MSR_EFER 0xc0000080 /* extended feature register */
327#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */
328#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */
329#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */
330#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */
331#define MSR_FS_BASE 0xc0000100 /* 64bit FS base */
332#define MSR_GS_BASE 0xc0000101 /* 64bit GS base */
333#define MSR_KERNEL_GS_BASE 0xc0000102 /* SwapGS GS shadow */
334#define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */
335
336/* EFER bits: */
337#define EFER_SCE (1<<0) /* SYSCALL/SYSRET */
338#define EFER_LME (1<<8) /* Long mode enable */
339#define EFER_LMA (1<<10) /* Long mode active (read-only) */
340#define EFER_NX (1<<11) /* No execute enable */
341#define EFER_SVME (1<<12) /* Enable virtualization */
342#define EFER_LMSLE (1<<13) /* Long Mode Segment Limit Enable */
343#define EFER_FFXSR (1<<14) /* Enable Fast FXSAVE/FXRSTOR */
344
345/* Intel MSRs. Some also available on other CPUs */
346
347#define MSR_PPIN_CTL 0x0000004e
348#define MSR_PPIN 0x0000004f
349
350#define MSR_IA32_PERFCTR0 0x000000c1
351#define MSR_IA32_PERFCTR1 0x000000c2
352#define MSR_FSB_FREQ 0x000000cd
353#define MSR_PLATFORM_INFO 0x000000ce
354#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT 31
355#define MSR_PLATFORM_INFO_CPUID_FAULT BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT)
356
357#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
358#define NHM_C3_AUTO_DEMOTE (1UL << 25)
359#define NHM_C1_AUTO_DEMOTE (1UL << 26)
360#define ATM_LNC_C6_AUTO_DEMOTE (1UL << 25)
361#define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
362#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
363
364#define MSR_MTRRcap 0x000000fe
365#define MSR_IA32_BBL_CR_CTL 0x00000119
366#define MSR_IA32_BBL_CR_CTL3 0x0000011e
367
368#define MSR_IA32_SYSENTER_CS 0x00000174
369#define MSR_IA32_SYSENTER_ESP 0x00000175
370#define MSR_IA32_SYSENTER_EIP 0x00000176
371
372#define MSR_IA32_MCG_CAP 0x00000179
373#define MSR_IA32_MCG_STATUS 0x0000017a
374#define MSR_IA32_MCG_CTL 0x0000017b
375#define MSR_IA32_MCG_EXT_CTL 0x000004d0
376
377#define MSR_OFFCORE_RSP_0 0x000001a6
378#define MSR_OFFCORE_RSP_1 0x000001a7
379#define MSR_TURBO_RATIO_LIMIT 0x000001ad
380#define MSR_TURBO_RATIO_LIMIT1 0x000001ae
381#define MSR_TURBO_RATIO_LIMIT2 0x000001af
382
383#define MSR_LBR_SELECT 0x000001c8
384#define MSR_LBR_TOS 0x000001c9
385#define MSR_LBR_NHM_FROM 0x00000680
386#define MSR_LBR_NHM_TO 0x000006c0
387#define MSR_LBR_CORE_FROM 0x00000040
388#define MSR_LBR_CORE_TO 0x00000060
389
390#define MSR_LBR_INFO_0 0x00000dc0 /* ... 0xddf for _31 */
391#define LBR_INFO_MISPRED BIT_ULL(63)
392#define LBR_INFO_IN_TX BIT_ULL(62)
393#define LBR_INFO_ABORT BIT_ULL(61)
394#define LBR_INFO_CYCLES 0xffff
395
396#define MSR_IA32_PEBS_ENABLE 0x000003f1
397#define MSR_IA32_DS_AREA 0x00000600
398#define MSR_IA32_PERF_CAPABILITIES 0x00000345
399#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6
400
401#define MSR_IA32_RTIT_CTL 0x00000570
402#define MSR_IA32_RTIT_STATUS 0x00000571
403#define MSR_IA32_RTIT_ADDR0_A 0x00000580
404#define MSR_IA32_RTIT_ADDR0_B 0x00000581
405#define MSR_IA32_RTIT_ADDR1_A 0x00000582
406#define MSR_IA32_RTIT_ADDR1_B 0x00000583
407#define MSR_IA32_RTIT_ADDR2_A 0x00000584
408#define MSR_IA32_RTIT_ADDR2_B 0x00000585
409#define MSR_IA32_RTIT_ADDR3_A 0x00000586
410#define MSR_IA32_RTIT_ADDR3_B 0x00000587
411#define MSR_IA32_RTIT_CR3_MATCH 0x00000572
412#define MSR_IA32_RTIT_OUTPUT_BASE 0x00000560
413#define MSR_IA32_RTIT_OUTPUT_MASK 0x00000561
414
415#define MSR_MTRRfix64K_00000 0x00000250
416#define MSR_MTRRfix16K_80000 0x00000258
417#define MSR_MTRRfix16K_A0000 0x00000259
418#define MSR_MTRRfix4K_C0000 0x00000268
419#define MSR_MTRRfix4K_C8000 0x00000269
420#define MSR_MTRRfix4K_D0000 0x0000026a
421#define MSR_MTRRfix4K_D8000 0x0000026b
422#define MSR_MTRRfix4K_E0000 0x0000026c
423#define MSR_MTRRfix4K_E8000 0x0000026d
424#define MSR_MTRRfix4K_F0000 0x0000026e
425#define MSR_MTRRfix4K_F8000 0x0000026f
426#define MSR_MTRRdefType 0x000002ff
427
428#define MSR_IA32_CR_PAT 0x00000277
429
430#define MSR_IA32_DEBUGCTLMSR 0x000001d9
431#define MSR_IA32_LASTBRANCHFROMIP 0x000001db
432#define MSR_IA32_LASTBRANCHTOIP 0x000001dc
433#define MSR_IA32_LASTINTFROMIP 0x000001dd
434#define MSR_IA32_LASTINTTOIP 0x000001de
435
436/* DEBUGCTLMSR bits (others vary by model): */
437#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */
438#define DEBUGCTLMSR_BTF_SHIFT 1
439#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */
440#define DEBUGCTLMSR_TR (1UL << 6)
441#define DEBUGCTLMSR_BTS (1UL << 7)
442#define DEBUGCTLMSR_BTINT (1UL << 8)
443#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9)
444#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10)
445#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
446#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14
447#define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT)
448
449#define MSR_PEBS_FRONTEND 0x000003f7
450
451#define MSR_IA32_POWER_CTL 0x000001fc
452
453#define MSR_IA32_MC0_CTL 0x00000400
454#define MSR_IA32_MC0_STATUS 0x00000401
455#define MSR_IA32_MC0_ADDR 0x00000402
456#define MSR_IA32_MC0_MISC 0x00000403
457
458/* C-state Residency Counters */
459#define MSR_PKG_C3_RESIDENCY 0x000003f8
460#define MSR_PKG_C6_RESIDENCY 0x000003f9
461#define MSR_ATOM_PKG_C6_RESIDENCY 0x000003fa
462#define MSR_PKG_C7_RESIDENCY 0x000003fa
463#define MSR_CORE_C3_RESIDENCY 0x000003fc
464#define MSR_CORE_C6_RESIDENCY 0x000003fd
465#define MSR_CORE_C7_RESIDENCY 0x000003fe
466#define MSR_KNL_CORE_C6_RESIDENCY 0x000003ff
467#define MSR_PKG_C2_RESIDENCY 0x0000060d
468#define MSR_PKG_C8_RESIDENCY 0x00000630
469#define MSR_PKG_C9_RESIDENCY 0x00000631
470#define MSR_PKG_C10_RESIDENCY 0x00000632
471
472/* Interrupt Response Limit */
473#define MSR_PKGC3_IRTL 0x0000060a
474#define MSR_PKGC6_IRTL 0x0000060b
475#define MSR_PKGC7_IRTL 0x0000060c
476#define MSR_PKGC8_IRTL 0x00000633
477#define MSR_PKGC9_IRTL 0x00000634
478#define MSR_PKGC10_IRTL 0x00000635
479
480/* Run Time Average Power Limiting (RAPL) Interface */
481
482#define MSR_RAPL_POWER_UNIT 0x00000606
483
484#define MSR_PKG_POWER_LIMIT 0x00000610
485#define MSR_PKG_ENERGY_STATUS 0x00000611
486#define MSR_PKG_PERF_STATUS 0x00000613
487#define MSR_PKG_POWER_INFO 0x00000614
488
489#define MSR_DRAM_POWER_LIMIT 0x00000618
490#define MSR_DRAM_ENERGY_STATUS 0x00000619
491#define MSR_DRAM_PERF_STATUS 0x0000061b
492#define MSR_DRAM_POWER_INFO 0x0000061c
493
494#define MSR_PP0_POWER_LIMIT 0x00000638
495#define MSR_PP0_ENERGY_STATUS 0x00000639
496#define MSR_PP0_POLICY 0x0000063a
497#define MSR_PP0_PERF_STATUS 0x0000063b
498
499#define MSR_PP1_POWER_LIMIT 0x00000640
500#define MSR_PP1_ENERGY_STATUS 0x00000641
501#define MSR_PP1_POLICY 0x00000642
502
503/* Config TDP MSRs */
504#define MSR_CONFIG_TDP_NOMINAL 0x00000648
505#define MSR_CONFIG_TDP_LEVEL_1 0x00000649
506#define MSR_CONFIG_TDP_LEVEL_2 0x0000064A
507#define MSR_CONFIG_TDP_CONTROL 0x0000064B
508#define MSR_TURBO_ACTIVATION_RATIO 0x0000064C
509
510#define MSR_PLATFORM_ENERGY_STATUS 0x0000064D
511
512#define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658
513#define MSR_PKG_ANY_CORE_C0_RES 0x00000659
514#define MSR_PKG_ANY_GFXE_C0_RES 0x0000065A
515#define MSR_PKG_BOTH_CORE_GFXE_C0_RES 0x0000065B
516
517#define MSR_CORE_C1_RES 0x00000660
518#define MSR_MODULE_C6_RES_MS 0x00000664
519
520#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668
521#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669
522
523#define MSR_ATOM_CORE_RATIOS 0x0000066a
524#define MSR_ATOM_CORE_VIDS 0x0000066b
525#define MSR_ATOM_CORE_TURBO_RATIOS 0x0000066c
526#define MSR_ATOM_CORE_TURBO_VIDS 0x0000066d
527
528
529#define MSR_CORE_PERF_LIMIT_REASONS 0x00000690
530#define MSR_GFX_PERF_LIMIT_REASONS 0x000006B0
531#define MSR_RING_PERF_LIMIT_REASONS 0x000006B1
532
533/* Hardware P state interface */
534#define MSR_PPERF 0x0000064e
535#define MSR_PERF_LIMIT_REASONS 0x0000064f
536#define MSR_PM_ENABLE 0x00000770
537#define MSR_HWP_CAPABILITIES 0x00000771
538#define MSR_HWP_REQUEST_PKG 0x00000772
539#define MSR_HWP_INTERRUPT 0x00000773
540#define MSR_HWP_REQUEST 0x00000774
541#define MSR_HWP_STATUS 0x00000777
542
543/* CPUID.6.EAX */
544#define HWP_BASE_BIT (1<<7)
545#define HWP_NOTIFICATIONS_BIT (1<<8)
546#define HWP_ACTIVITY_WINDOW_BIT (1<<9)
547#define HWP_ENERGY_PERF_PREFERENCE_BIT (1<<10)
548#define HWP_PACKAGE_LEVEL_REQUEST_BIT (1<<11)
549
550/* IA32_HWP_CAPABILITIES */
551#define HWP_HIGHEST_PERF(x) (((x) >> 0) & 0xff)
552#define HWP_GUARANTEED_PERF(x) (((x) >> 8) & 0xff)
553#define HWP_MOSTEFFICIENT_PERF(x) (((x) >> 16) & 0xff)
554#define HWP_LOWEST_PERF(x) (((x) >> 24) & 0xff)
555
556/* IA32_HWP_REQUEST */
557#define HWP_MIN_PERF(x) (x & 0xff)
558#define HWP_MAX_PERF(x) ((x & 0xff) << 8)
559#define HWP_DESIRED_PERF(x) ((x & 0xff) << 16)
560#define HWP_ENERGY_PERF_PREFERENCE(x) (((unsigned long long) x & 0xff) << 24)
561#define HWP_EPP_PERFORMANCE 0x00
562#define HWP_EPP_BALANCE_PERFORMANCE 0x80
563#define HWP_EPP_BALANCE_POWERSAVE 0xC0
564#define HWP_EPP_POWERSAVE 0xFF
565#define HWP_ACTIVITY_WINDOW(x) ((unsigned long long)(x & 0xff3) << 32)
566#define HWP_PACKAGE_CONTROL(x) ((unsigned long long)(x & 0x1) << 42)
567
568/* IA32_HWP_STATUS */
569#define HWP_GUARANTEED_CHANGE(x) (x & 0x1)
570#define HWP_EXCURSION_TO_MINIMUM(x) (x & 0x4)
571
572/* IA32_HWP_INTERRUPT */
573#define HWP_CHANGE_TO_GUARANTEED_INT(x) (x & 0x1)
574#define HWP_EXCURSION_TO_MINIMUM_INT(x) (x & 0x2)
575
576#define MSR_AMD64_MC0_MASK 0xc0010044
577
578#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x))
579#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x))
580#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x))
581#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x))
582
583#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x))
584
585/* These are consecutive and not in the normal 4er MCE bank block */
586#define MSR_IA32_MC0_CTL2 0x00000280
587#define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x))
588
589#define MSR_P6_PERFCTR0 0x000000c1
590#define MSR_P6_PERFCTR1 0x000000c2
591#define MSR_P6_EVNTSEL0 0x00000186
592#define MSR_P6_EVNTSEL1 0x00000187
593
594#define MSR_KNC_PERFCTR0 0x00000020
595#define MSR_KNC_PERFCTR1 0x00000021
596#define MSR_KNC_EVNTSEL0 0x00000028
597#define MSR_KNC_EVNTSEL1 0x00000029
598
599/* Alternative perfctr range with full access. */
600#define MSR_IA32_PMC0 0x000004c1
601
602/* AMD64 MSRs. Not complete. See the architecture manual for a more
603 complete list. */
604
605#define MSR_AMD64_PATCH_LEVEL 0x0000008b
606#define MSR_AMD64_TSC_RATIO 0xc0000104
607#define MSR_AMD64_NB_CFG 0xc001001f
608#define MSR_AMD64_PATCH_LOADER 0xc0010020
609#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
610#define MSR_AMD64_OSVW_STATUS 0xc0010141
611#define MSR_AMD64_LS_CFG 0xc0011020
612#define MSR_AMD64_DC_CFG 0xc0011022
613#define MSR_AMD64_BU_CFG2 0xc001102a
614#define MSR_AMD64_IBSFETCHCTL 0xc0011030
615#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
616#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
617#define MSR_AMD64_IBSFETCH_REG_COUNT 3
618#define MSR_AMD64_IBSFETCH_REG_MASK ((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
619#define MSR_AMD64_IBSOPCTL 0xc0011033
620#define MSR_AMD64_IBSOPRIP 0xc0011034
621#define MSR_AMD64_IBSOPDATA 0xc0011035
622#define MSR_AMD64_IBSOPDATA2 0xc0011036
623#define MSR_AMD64_IBSOPDATA3 0xc0011037
624#define MSR_AMD64_IBSDCLINAD 0xc0011038
625#define MSR_AMD64_IBSDCPHYSAD 0xc0011039
626#define MSR_AMD64_IBSOP_REG_COUNT 7
627#define MSR_AMD64_IBSOP_REG_MASK ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
628#define MSR_AMD64_IBSCTL 0xc001103a
629#define MSR_AMD64_IBSBRTARGET 0xc001103b
630#define MSR_AMD64_IBSOPDATA4 0xc001103d
631#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */
632#define MSR_AMD64_SEV 0xc0010131
633#define MSR_AMD64_SEV_ENABLED_BIT 0
634#define MSR_AMD64_SEV_ENABLED BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
635
636/* Fam 17h MSRs */
637#define MSR_F17H_IRPERF 0xc00000e9
638
639/* Fam 16h MSRs */
640#define MSR_F16H_L2I_PERF_CTL 0xc0010230
641#define MSR_F16H_L2I_PERF_CTR 0xc0010231
642#define MSR_F16H_DR1_ADDR_MASK 0xc0011019
643#define MSR_F16H_DR2_ADDR_MASK 0xc001101a
644#define MSR_F16H_DR3_ADDR_MASK 0xc001101b
645#define MSR_F16H_DR0_ADDR_MASK 0xc0011027
646
647/* Fam 15h MSRs */
648#define MSR_F15H_PERF_CTL 0xc0010200
649#define MSR_F15H_PERF_CTR 0xc0010201
650#define MSR_F15H_NB_PERF_CTL 0xc0010240
651#define MSR_F15H_NB_PERF_CTR 0xc0010241
652#define MSR_F15H_PTSC 0xc0010280
653#define MSR_F15H_IC_CFG 0xc0011021
654
655/* Fam 10h MSRs */
656#define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058
657#define FAM10H_MMIO_CONF_ENABLE (1<<0)
658#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
659#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
660#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL
661#define FAM10H_MMIO_CONF_BASE_SHIFT 20
662#define MSR_FAM10H_NODE_ID 0xc001100c
663#define MSR_F10H_DECFG 0xc0011029
664#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT 1
665#define MSR_F10H_DECFG_LFENCE_SERIALIZE BIT_ULL(MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT)
666
667/* K8 MSRs */
668#define MSR_K8_TOP_MEM1 0xc001001a
669#define MSR_K8_TOP_MEM2 0xc001001d
670#define MSR_K8_SYSCFG 0xc0010010
671#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT 23
672#define MSR_K8_SYSCFG_MEM_ENCRYPT BIT_ULL(MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
673#define MSR_K8_INT_PENDING_MSG 0xc0010055
674/* C1E active bits in int pending message */
675#define K8_INTP_C1E_ACTIVE_MASK 0x18000000
676#define MSR_K8_TSEG_ADDR 0xc0010112
677#define MSR_K8_TSEG_MASK 0xc0010113
678#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */
679#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */
680#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */
681
682/* K7 MSRs */
683#define MSR_K7_EVNTSEL0 0xc0010000
684#define MSR_K7_PERFCTR0 0xc0010004
685#define MSR_K7_EVNTSEL1 0xc0010001
686#define MSR_K7_PERFCTR1 0xc0010005
687#define MSR_K7_EVNTSEL2 0xc0010002
688#define MSR_K7_PERFCTR2 0xc0010006
689#define MSR_K7_EVNTSEL3 0xc0010003
690#define MSR_K7_PERFCTR3 0xc0010007
691#define MSR_K7_CLK_CTL 0xc001001b
692#define MSR_K7_HWCR 0xc0010015
693#define MSR_K7_HWCR_SMMLOCK_BIT 0
694#define MSR_K7_HWCR_SMMLOCK BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
695#define MSR_K7_FID_VID_CTL 0xc0010041
696#define MSR_K7_FID_VID_STATUS 0xc0010042
697
698/* K6 MSRs */
699#define MSR_K6_WHCR 0xc0000082
700#define MSR_K6_UWCCR 0xc0000085
701#define MSR_K6_EPMR 0xc0000086
702#define MSR_K6_PSOR 0xc0000087
703#define MSR_K6_PFIR 0xc0000088
704
705/* Centaur-Hauls/IDT defined MSRs. */
706#define MSR_IDT_FCR1 0x00000107
707#define MSR_IDT_FCR2 0x00000108
708#define MSR_IDT_FCR3 0x00000109
709#define MSR_IDT_FCR4 0x0000010a
710
711#define MSR_IDT_MCR0 0x00000110
712#define MSR_IDT_MCR1 0x00000111
713#define MSR_IDT_MCR2 0x00000112
714#define MSR_IDT_MCR3 0x00000113
715#define MSR_IDT_MCR4 0x00000114
716#define MSR_IDT_MCR5 0x00000115
717#define MSR_IDT_MCR6 0x00000116
718#define MSR_IDT_MCR7 0x00000117
719#define MSR_IDT_MCR_CTRL 0x00000120
720
721/* VIA Cyrix defined MSRs*/
722#define MSR_VIA_FCR 0x00001107
723#define MSR_VIA_LONGHAUL 0x0000110a
724#define MSR_VIA_RNG 0x0000110b
725#define MSR_VIA_BCR2 0x00001147
726
727/* Transmeta defined MSRs */
728#define MSR_TMTA_LONGRUN_CTRL 0x80868010
729#define MSR_TMTA_LONGRUN_FLAGS 0x80868011
730#define MSR_TMTA_LRTI_READOUT 0x80868018
731#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a
732
733/* Intel defined MSRs. */
734#define MSR_IA32_P5_MC_ADDR 0x00000000
735#define MSR_IA32_P5_MC_TYPE 0x00000001
736#define MSR_IA32_TSC 0x00000010
737#define MSR_IA32_PLATFORM_ID 0x00000017
738#define MSR_IA32_EBL_CR_POWERON 0x0000002a
739#define MSR_EBC_FREQUENCY_ID 0x0000002c
740#define MSR_SMI_COUNT 0x00000034
741#define MSR_IA32_FEATURE_CONTROL 0x0000003a
742#define MSR_IA32_TSC_ADJUST 0x0000003b
743#define MSR_IA32_BNDCFGS 0x00000d90
744
745#define MSR_IA32_BNDCFGS_RSVD 0x00000ffc
746
747#define MSR_IA32_XSS 0x00000da0
748
749#define FEATURE_CONTROL_LOCKED (1<<0)
750#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1)
751#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2)
752#define FEATURE_CONTROL_LMCE (1<<20)
753
754#define MSR_IA32_APICBASE 0x0000001b
755#define MSR_IA32_APICBASE_BSP (1<<8)
756#define MSR_IA32_APICBASE_ENABLE (1<<11)
757#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
758
759#define MSR_IA32_TSCDEADLINE 0x000006e0
760
761#define MSR_IA32_UCODE_WRITE 0x00000079
762#define MSR_IA32_UCODE_REV 0x0000008b
763
764#define MSR_IA32_SMM_MONITOR_CTL 0x0000009b
765#define MSR_IA32_SMBASE 0x0000009e
766
767#define MSR_IA32_PERF_STATUS 0x00000198
768#define MSR_IA32_PERF_CTL 0x00000199
769#define INTEL_PERF_CTL_MASK 0xffff
770#define MSR_AMD_PSTATE_DEF_BASE 0xc0010064
771#define MSR_AMD_PERF_STATUS 0xc0010063
772#define MSR_AMD_PERF_CTL 0xc0010062
773
774#define MSR_IA32_MPERF 0x000000e7
775#define MSR_IA32_APERF 0x000000e8
776
777#define MSR_IA32_THERM_CONTROL 0x0000019a
778#define MSR_IA32_THERM_INTERRUPT 0x0000019b
779
780#define THERM_INT_HIGH_ENABLE (1 << 0)
781#define THERM_INT_LOW_ENABLE (1 << 1)
782#define THERM_INT_PLN_ENABLE (1 << 24)
783
784#define MSR_IA32_THERM_STATUS 0x0000019c
785
786#define THERM_STATUS_PROCHOT (1 << 0)
787#define THERM_STATUS_POWER_LIMIT (1 << 10)
788
789#define MSR_THERM2_CTL 0x0000019d
790
791#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16)
792
793#define MSR_IA32_MISC_ENABLE 0x000001a0
794
795#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
796
797#define MSR_MISC_FEATURE_CONTROL 0x000001a4
798#define MSR_MISC_PWR_MGMT 0x000001aa
799
800#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
801#define ENERGY_PERF_BIAS_PERFORMANCE 0
802#define ENERGY_PERF_BIAS_BALANCE_PERFORMANCE 4
803#define ENERGY_PERF_BIAS_NORMAL 6
804#define ENERGY_PERF_BIAS_BALANCE_POWERSAVE 8
805#define ENERGY_PERF_BIAS_POWERSAVE 15
806
807#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
808
809#define PACKAGE_THERM_STATUS_PROCHOT (1 << 0)
810#define PACKAGE_THERM_STATUS_POWER_LIMIT (1 << 10)
811
812#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2
813
814#define PACKAGE_THERM_INT_HIGH_ENABLE (1 << 0)
815#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1)
816#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24)
817
818/* Thermal Thresholds Support */
819#define THERM_INT_THRESHOLD0_ENABLE (1 << 15)
820#define THERM_SHIFT_THRESHOLD0 8
821#define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0)
822#define THERM_INT_THRESHOLD1_ENABLE (1 << 23)
823#define THERM_SHIFT_THRESHOLD1 16
824#define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1)
825#define THERM_STATUS_THRESHOLD0 (1 << 6)
826#define THERM_LOG_THRESHOLD0 (1 << 7)
827#define THERM_STATUS_THRESHOLD1 (1 << 8)
828#define THERM_LOG_THRESHOLD1 (1 << 9)
829
830/* MISC_ENABLE bits: architectural */
831#define MSR_IA32_MISC_ENABLE_FAST_STRING_BIT 0
832#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << MSR_IA32_MISC_ENABLE_FAST_STRING_BIT)
833#define MSR_IA32_MISC_ENABLE_TCC_BIT 1
834#define MSR_IA32_MISC_ENABLE_TCC (1ULL << MSR_IA32_MISC_ENABLE_TCC_BIT)
835#define MSR_IA32_MISC_ENABLE_EMON_BIT 7
836#define MSR_IA32_MISC_ENABLE_EMON (1ULL << MSR_IA32_MISC_ENABLE_EMON_BIT)
837#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT 11
838#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT)
839#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT 12
840#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT)
841#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT 16
842#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT)
843#define MSR_IA32_MISC_ENABLE_MWAIT_BIT 18
844#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << MSR_IA32_MISC_ENABLE_MWAIT_BIT)
845#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT 22
846#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT)
847#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT 23
848#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT)
849#define MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT 34
850#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT)
851
852/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
853#define MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT 2
854#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT)
855#define MSR_IA32_MISC_ENABLE_TM1_BIT 3
856#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << MSR_IA32_MISC_ENABLE_TM1_BIT)
857#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT 4
858#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT)
859#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT 6
860#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT)
861#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT 8
862#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT)
863#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT 9
864#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
865#define MSR_IA32_MISC_ENABLE_FERR_BIT 10
866#define MSR_IA32_MISC_ENABLE_FERR (1ULL << MSR_IA32_MISC_ENABLE_FERR_BIT)
867#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT 10
868#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT)
869#define MSR_IA32_MISC_ENABLE_TM2_BIT 13
870#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << MSR_IA32_MISC_ENABLE_TM2_BIT)
871#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT 19
872#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT)
873#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT 20
874#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT)
875#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT 24
876#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT)
877#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT 37
878#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT)
879#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT 38
880#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT)
881#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT 39
882#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT)
883
884/* MISC_FEATURES_ENABLES non-architectural features */
885#define MSR_MISC_FEATURES_ENABLES 0x00000140
886
887#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT 0
888#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT)
889#define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT 1
890
891#define MSR_IA32_TSC_DEADLINE 0x000006E0
892
893/* P4/Xeon+ specific */
894#define MSR_IA32_MCG_EAX 0x00000180
895#define MSR_IA32_MCG_EBX 0x00000181
896#define MSR_IA32_MCG_ECX 0x00000182
897#define MSR_IA32_MCG_EDX 0x00000183
898#define MSR_IA32_MCG_ESI 0x00000184
899#define MSR_IA32_MCG_EDI 0x00000185
900#define MSR_IA32_MCG_EBP 0x00000186
901#define MSR_IA32_MCG_ESP 0x00000187
902#define MSR_IA32_MCG_EFLAGS 0x00000188
903#define MSR_IA32_MCG_EIP 0x00000189
904#define MSR_IA32_MCG_RESERVED 0x0000018a
905
906/* Pentium IV performance counter MSRs */
907#define MSR_P4_BPU_PERFCTR0 0x00000300
908#define MSR_P4_BPU_PERFCTR1 0x00000301
909#define MSR_P4_BPU_PERFCTR2 0x00000302
910#define MSR_P4_BPU_PERFCTR3 0x00000303
911#define MSR_P4_MS_PERFCTR0 0x00000304
912#define MSR_P4_MS_PERFCTR1 0x00000305
913#define MSR_P4_MS_PERFCTR2 0x00000306
914#define MSR_P4_MS_PERFCTR3 0x00000307
915#define MSR_P4_FLAME_PERFCTR0 0x00000308
916#define MSR_P4_FLAME_PERFCTR1 0x00000309
917#define MSR_P4_FLAME_PERFCTR2 0x0000030a
918#define MSR_P4_FLAME_PERFCTR3 0x0000030b
919#define MSR_P4_IQ_PERFCTR0 0x0000030c
920#define MSR_P4_IQ_PERFCTR1 0x0000030d
921#define MSR_P4_IQ_PERFCTR2 0x0000030e
922#define MSR_P4_IQ_PERFCTR3 0x0000030f
923#define MSR_P4_IQ_PERFCTR4 0x00000310
924#define MSR_P4_IQ_PERFCTR5 0x00000311
925#define MSR_P4_BPU_CCCR0 0x00000360
926#define MSR_P4_BPU_CCCR1 0x00000361
927#define MSR_P4_BPU_CCCR2 0x00000362
928#define MSR_P4_BPU_CCCR3 0x00000363
929#define MSR_P4_MS_CCCR0 0x00000364
930#define MSR_P4_MS_CCCR1 0x00000365
931#define MSR_P4_MS_CCCR2 0x00000366
932#define MSR_P4_MS_CCCR3 0x00000367
933#define MSR_P4_FLAME_CCCR0 0x00000368
934#define MSR_P4_FLAME_CCCR1 0x00000369
935#define MSR_P4_FLAME_CCCR2 0x0000036a
936#define MSR_P4_FLAME_CCCR3 0x0000036b
937#define MSR_P4_IQ_CCCR0 0x0000036c
938#define MSR_P4_IQ_CCCR1 0x0000036d
939#define MSR_P4_IQ_CCCR2 0x0000036e
940#define MSR_P4_IQ_CCCR3 0x0000036f
941#define MSR_P4_IQ_CCCR4 0x00000370
942#define MSR_P4_IQ_CCCR5 0x00000371
943#define MSR_P4_ALF_ESCR0 0x000003ca
944#define MSR_P4_ALF_ESCR1 0x000003cb
945#define MSR_P4_BPU_ESCR0 0x000003b2
946#define MSR_P4_BPU_ESCR1 0x000003b3
947#define MSR_P4_BSU_ESCR0 0x000003a0
948#define MSR_P4_BSU_ESCR1 0x000003a1
949#define MSR_P4_CRU_ESCR0 0x000003b8
950#define MSR_P4_CRU_ESCR1 0x000003b9
951#define MSR_P4_CRU_ESCR2 0x000003cc
952#define MSR_P4_CRU_ESCR3 0x000003cd
953#define MSR_P4_CRU_ESCR4 0x000003e0
954#define MSR_P4_CRU_ESCR5 0x000003e1
955#define MSR_P4_DAC_ESCR0 0x000003a8
956#define MSR_P4_DAC_ESCR1 0x000003a9
957#define MSR_P4_FIRM_ESCR0 0x000003a4
958#define MSR_P4_FIRM_ESCR1 0x000003a5
959#define MSR_P4_FLAME_ESCR0 0x000003a6
960#define MSR_P4_FLAME_ESCR1 0x000003a7
961#define MSR_P4_FSB_ESCR0 0x000003a2
962#define MSR_P4_FSB_ESCR1 0x000003a3
963#define MSR_P4_IQ_ESCR0 0x000003ba
964#define MSR_P4_IQ_ESCR1 0x000003bb
965#define MSR_P4_IS_ESCR0 0x000003b4
966#define MSR_P4_IS_ESCR1 0x000003b5
967#define MSR_P4_ITLB_ESCR0 0x000003b6
968#define MSR_P4_ITLB_ESCR1 0x000003b7
969#define MSR_P4_IX_ESCR0 0x000003c8
970#define MSR_P4_IX_ESCR1 0x000003c9
971#define MSR_P4_MOB_ESCR0 0x000003aa
972#define MSR_P4_MOB_ESCR1 0x000003ab
973#define MSR_P4_MS_ESCR0 0x000003c0
974#define MSR_P4_MS_ESCR1 0x000003c1
975#define MSR_P4_PMH_ESCR0 0x000003ac
976#define MSR_P4_PMH_ESCR1 0x000003ad
977#define MSR_P4_RAT_ESCR0 0x000003bc
978#define MSR_P4_RAT_ESCR1 0x000003bd
979#define MSR_P4_SAAT_ESCR0 0x000003ae
980#define MSR_P4_SAAT_ESCR1 0x000003af
981#define MSR_P4_SSU_ESCR0 0x000003be
982#define MSR_P4_SSU_ESCR1 0x000003bf /* guess: not in manual */
983
984#define MSR_P4_TBPU_ESCR0 0x000003c2
985#define MSR_P4_TBPU_ESCR1 0x000003c3
986#define MSR_P4_TC_ESCR0 0x000003c4
987#define MSR_P4_TC_ESCR1 0x000003c5
988#define MSR_P4_U2L_ESCR0 0x000003b0
989#define MSR_P4_U2L_ESCR1 0x000003b1
990
991#define MSR_P4_PEBS_MATRIX_VERT 0x000003f2
992
993/* Intel Core-based CPU performance counters */
994#define MSR_CORE_PERF_FIXED_CTR0 0x00000309
995#define MSR_CORE_PERF_FIXED_CTR1 0x0000030a
996#define MSR_CORE_PERF_FIXED_CTR2 0x0000030b
997#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x0000038d
998#define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e
999#define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f
1000#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390
1001
1002/* Geode defined MSRs */
1003#define MSR_GEODE_BUSCONT_CONF0 0x00001900
1004
1005/* Intel VT MSRs */
1006#define MSR_IA32_VMX_BASIC 0x00000480
1007#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481
1008#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482
1009#define MSR_IA32_VMX_EXIT_CTLS 0x00000483
1010#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484
1011#define MSR_IA32_VMX_MISC 0x00000485
1012#define MSR_IA32_VMX_CR0_FIXED0 0x00000486
1013#define MSR_IA32_VMX_CR0_FIXED1 0x00000487
1014#define MSR_IA32_VMX_CR4_FIXED0 0x00000488
1015#define MSR_IA32_VMX_CR4_FIXED1 0x00000489
1016#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a
1017#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b
1018#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c
1019#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x0000048d
1020#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
1021#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f
1022#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490
1023#define MSR_IA32_VMX_VMFUNC 0x00000491
1024
1025/* VMX_BASIC bits and bitmasks */
1026#define VMX_BASIC_VMCS_SIZE_SHIFT 32
1027#define VMX_BASIC_TRUE_CTLS (1ULL << 55)
1028#define VMX_BASIC_64 0x0001000000000000LLU
1029#define VMX_BASIC_MEM_TYPE_SHIFT 50
1030#define VMX_BASIC_MEM_TYPE_MASK 0x003c000000000000LLU
1031#define VMX_BASIC_MEM_TYPE_WB 6LLU
1032#define VMX_BASIC_INOUT 0x0040000000000000LLU
1033
1034/* MSR_IA32_VMX_MISC bits */
1035#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
1036#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE 0x1F
1037/* AMD-V MSRs */
1038
1039#define MSR_VM_CR 0xc0010114
1040#define MSR_VM_IGNNE 0xc0010115
1041#define MSR_VM_HSAVE_PA 0xc0010117
1042
1043#endif /* !SELFTEST_KVM_X86_H */
diff --git a/tools/testing/selftests/kvm/lib/assert.c b/tools/testing/selftests/kvm/lib/assert.c
new file mode 100644
index 000000000000..c9f5b7d4ce38
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/assert.c
@@ -0,0 +1,87 @@
1/*
2 * tools/testing/selftests/kvm/lib/assert.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#define _GNU_SOURCE /* for getline(3) and strchrnul(3)*/
10
11#include "test_util.h"
12
13#include <execinfo.h>
14#include <sys/syscall.h>
15
16/* Dumps the current stack trace to stderr. */
17static void __attribute__((noinline)) test_dump_stack(void);
18static void test_dump_stack(void)
19{
20 /*
21 * Build and run this command:
22 *
23 * addr2line -s -e /proc/$PPID/exe -fpai {backtrace addresses} | \
24 * grep -v test_dump_stack | cat -n 1>&2
25 *
26 * Note that the spacing is different and there's no newline.
27 */
28 size_t i;
29 size_t n = 20;
30 void *stack[n];
31 const char *addr2line = "addr2line -s -e /proc/$PPID/exe -fpai";
32 const char *pipeline = "|cat -n 1>&2";
33 char cmd[strlen(addr2line) + strlen(pipeline) +
34 /* N bytes per addr * 2 digits per byte + 1 space per addr: */
35 n * (((sizeof(void *)) * 2) + 1) +
36 /* Null terminator: */
37 1];
38 char *c;
39
40 n = backtrace(stack, n);
41 c = &cmd[0];
42 c += sprintf(c, "%s", addr2line);
43 /*
44 * Skip the first 3 frames: backtrace, test_dump_stack, and
45 * test_assert. We hope that backtrace isn't inlined and the other two
46 * we've declared noinline.
47 */
48 for (i = 2; i < n; i++)
49 c += sprintf(c, " %lx", ((unsigned long) stack[i]) - 1);
50 c += sprintf(c, "%s", pipeline);
51#pragma GCC diagnostic push
52#pragma GCC diagnostic ignored "-Wunused-result"
53 system(cmd);
54#pragma GCC diagnostic pop
55}
56
57static pid_t gettid(void)
58{
59 return syscall(SYS_gettid);
60}
61
62void __attribute__((noinline))
63test_assert(bool exp, const char *exp_str,
64 const char *file, unsigned int line, const char *fmt, ...)
65{
66 va_list ap;
67
68 if (!(exp)) {
69 va_start(ap, fmt);
70
71 fprintf(stderr, "==== Test Assertion Failure ====\n"
72 " %s:%u: %s\n"
73 " pid=%d tid=%d\n",
74 file, line, exp_str, getpid(), gettid());
75 test_dump_stack();
76 if (fmt) {
77 fputs(" ", stderr);
78 vfprintf(stderr, fmt, ap);
79 fputs("\n", stderr);
80 }
81 va_end(ap);
82
83 exit(254);
84 }
85
86 return;
87}
diff --git a/tools/testing/selftests/kvm/lib/elf.c b/tools/testing/selftests/kvm/lib/elf.c
new file mode 100644
index 000000000000..5eb857584aa3
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/elf.c
@@ -0,0 +1,197 @@
1/*
2 * tools/testing/selftests/kvm/lib/elf.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#include "test_util.h"
10
11#include <bits/endian.h>
12#include <linux/elf.h>
13
14#include "kvm_util.h"
15#include "kvm_util_internal.h"
16
17static void elfhdr_get(const char *filename, Elf64_Ehdr *hdrp)
18{
19 off_t offset_rv;
20
21 /* Open the ELF file. */
22 int fd;
23 fd = open(filename, O_RDONLY);
24 TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"
25 " filename: %s\n"
26 " rv: %i errno: %i", filename, fd, errno);
27
28 /* Read in and validate ELF Identification Record.
29 * The ELF Identification record is the first 16 (EI_NIDENT) bytes
30 * of the ELF header, which is at the beginning of the ELF file.
31 * For now it is only safe to read the first EI_NIDENT bytes. Once
32 * read and validated, the value of e_ehsize can be used to determine
33 * the real size of the ELF header.
34 */
35 unsigned char ident[EI_NIDENT];
36 test_read(fd, ident, sizeof(ident));
37 TEST_ASSERT((ident[EI_MAG0] == ELFMAG0) && (ident[EI_MAG1] == ELFMAG1)
38 && (ident[EI_MAG2] == ELFMAG2) && (ident[EI_MAG3] == ELFMAG3),
39 "ELF MAGIC Mismatch,\n"
40 " filename: %s\n"
41 " ident[EI_MAG0 - EI_MAG3]: %02x %02x %02x %02x\n"
42 " Expected: %02x %02x %02x %02x",
43 filename,
44 ident[EI_MAG0], ident[EI_MAG1], ident[EI_MAG2], ident[EI_MAG3],
45 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3);
46 TEST_ASSERT(ident[EI_CLASS] == ELFCLASS64,
47 "Current implementation only able to handle ELFCLASS64,\n"
48 " filename: %s\n"
49 " ident[EI_CLASS]: %02x\n"
50 " expected: %02x",
51 filename,
52 ident[EI_CLASS], ELFCLASS64);
53 TEST_ASSERT(((BYTE_ORDER == LITTLE_ENDIAN)
54 && (ident[EI_DATA] == ELFDATA2LSB))
55 || ((BYTE_ORDER == BIG_ENDIAN)
56 && (ident[EI_DATA] == ELFDATA2MSB)), "Current "
57 "implementation only able to handle\n"
58 "cases where the host and ELF file endianness\n"
59 "is the same:\n"
60 " host BYTE_ORDER: %u\n"
61 " host LITTLE_ENDIAN: %u\n"
62 " host BIG_ENDIAN: %u\n"
63 " ident[EI_DATA]: %u\n"
64 " ELFDATA2LSB: %u\n"
65 " ELFDATA2MSB: %u",
66 BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN,
67 ident[EI_DATA], ELFDATA2LSB, ELFDATA2MSB);
68 TEST_ASSERT(ident[EI_VERSION] == EV_CURRENT,
69 "Current implementation only able to handle current "
70 "ELF version,\n"
71 " filename: %s\n"
72 " ident[EI_VERSION]: %02x\n"
73 " expected: %02x",
74 filename, ident[EI_VERSION], EV_CURRENT);
75
76 /* Read in the ELF header.
77 * With the ELF Identification portion of the ELF header
78 * validated, especially that the value at EI_VERSION is
79 * as expected, it is now safe to read the entire ELF header.
80 */
81 offset_rv = lseek(fd, 0, SEEK_SET);
82 TEST_ASSERT(offset_rv == 0, "Seek to ELF header failed,\n"
83 " rv: %zi expected: %i", offset_rv, 0);
84 test_read(fd, hdrp, sizeof(*hdrp));
85 TEST_ASSERT(hdrp->e_phentsize == sizeof(Elf64_Phdr),
86 "Unexpected physical header size,\n"
87 " hdrp->e_phentsize: %x\n"
88 " expected: %zx",
89 hdrp->e_phentsize, sizeof(Elf64_Phdr));
90 TEST_ASSERT(hdrp->e_shentsize == sizeof(Elf64_Shdr),
91 "Unexpected section header size,\n"
92 " hdrp->e_shentsize: %x\n"
93 " expected: %zx",
94 hdrp->e_shentsize, sizeof(Elf64_Shdr));
95}
96
97/* VM ELF Load
98 *
99 * Input Args:
100 * filename - Path to ELF file
101 *
102 * Output Args: None
103 *
104 * Input/Output Args:
105 * vm - Pointer to opaque type that describes the VM.
106 *
107 * Return: None, TEST_ASSERT failures for all error conditions
108 *
109 * Loads the program image of the ELF file specified by filename,
110 * into the virtual address space of the VM pointed to by vm. On entry
111 * the VM needs to not be using any of the virtual address space used
112 * by the image and it needs to have sufficient available physical pages, to
113 * back the virtual pages used to load the image.
114 */
115void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename,
116 uint32_t data_memslot, uint32_t pgd_memslot)
117{
118 off_t offset, offset_rv;
119 Elf64_Ehdr hdr;
120
121 /* Open the ELF file. */
122 int fd;
123 fd = open(filename, O_RDONLY);
124 TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"
125 " filename: %s\n"
126 " rv: %i errno: %i", filename, fd, errno);
127
128 /* Read in the ELF header. */
129 elfhdr_get(filename, &hdr);
130
131 /* For each program header.
132 * The following ELF header members specify the location
133 * and size of the program headers:
134 *
135 * e_phoff - File offset to start of program headers
136 * e_phentsize - Size of each program header
137 * e_phnum - Number of program header entries
138 */
139 for (unsigned int n1 = 0; n1 < hdr.e_phnum; n1++) {
140 /* Seek to the beginning of the program header. */
141 offset = hdr.e_phoff + (n1 * hdr.e_phentsize);
142 offset_rv = lseek(fd, offset, SEEK_SET);
143 TEST_ASSERT(offset_rv == offset,
144 "Failed to seek to begining of program header %u,\n"
145 " filename: %s\n"
146 " rv: %jd errno: %i",
147 n1, filename, (intmax_t) offset_rv, errno);
148
149 /* Read in the program header. */
150 Elf64_Phdr phdr;
151 test_read(fd, &phdr, sizeof(phdr));
152
153 /* Skip if this header doesn't describe a loadable segment. */
154 if (phdr.p_type != PT_LOAD)
155 continue;
156
157 /* Allocate memory for this segment within the VM. */
158 TEST_ASSERT(phdr.p_memsz > 0, "Unexpected loadable segment "
159 "memsize of 0,\n"
160 " phdr index: %u p_memsz: 0x%" PRIx64,
161 n1, (uint64_t) phdr.p_memsz);
162 vm_vaddr_t seg_vstart = phdr.p_vaddr;
163 seg_vstart &= ~(vm_vaddr_t)(vm->page_size - 1);
164 vm_vaddr_t seg_vend = phdr.p_vaddr + phdr.p_memsz - 1;
165 seg_vend |= vm->page_size - 1;
166 size_t seg_size = seg_vend - seg_vstart + 1;
167
168 vm_vaddr_t vaddr = vm_vaddr_alloc(vm, seg_size, seg_vstart,
169 data_memslot, pgd_memslot);
170 TEST_ASSERT(vaddr == seg_vstart, "Unable to allocate "
171 "virtual memory for segment at requested min addr,\n"
172 " segment idx: %u\n"
173 " seg_vstart: 0x%lx\n"
174 " vaddr: 0x%lx",
175 n1, seg_vstart, vaddr);
176 memset(addr_gva2hva(vm, vaddr), 0, seg_size);
177 /* TODO(lhuemill): Set permissions of each memory segment
178 * based on the least-significant 3 bits of phdr.p_flags.
179 */
180
181 /* Load portion of initial state that is contained within
182 * the ELF file.
183 */
184 if (phdr.p_filesz) {
185 offset_rv = lseek(fd, phdr.p_offset, SEEK_SET);
186 TEST_ASSERT(offset_rv == phdr.p_offset,
187 "Seek to program segment offset failed,\n"
188 " program header idx: %u errno: %i\n"
189 " offset_rv: 0x%jx\n"
190 " expected: 0x%jx\n",
191 n1, errno, (intmax_t) offset_rv,
192 (intmax_t) phdr.p_offset);
193 test_read(fd, addr_gva2hva(vm, phdr.p_vaddr),
194 phdr.p_filesz);
195 }
196 }
197}
diff --git a/tools/testing/selftests/kvm/lib/io.c b/tools/testing/selftests/kvm/lib/io.c
new file mode 100644
index 000000000000..cff869ffe6ee
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/io.c
@@ -0,0 +1,158 @@
1/*
2 * tools/testing/selftests/kvm/lib/io.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#include "test_util.h"
10
11/* Test Write
12 *
13 * A wrapper for write(2), that automatically handles the following
14 * special conditions:
15 *
16 * + Interrupted system call (EINTR)
17 * + Write of less than requested amount
18 * + Non-block return (EAGAIN)
19 *
20 * For each of the above, an additional write is performed to automatically
21 * continue writing the requested data.
22 * There are also many cases where write(2) can return an unexpected
23 * error (e.g. EIO). Such errors cause a TEST_ASSERT failure.
24 *
25 * Note, for function signature compatibility with write(2), this function
26 * returns the number of bytes written, but that value will always be equal
27 * to the number of requested bytes. All other conditions in this and
28 * future enhancements to this function either automatically issue another
29 * write(2) or cause a TEST_ASSERT failure.
30 *
31 * Args:
32 * fd - Opened file descriptor to file to be written.
33 * count - Number of bytes to write.
34 *
35 * Output:
36 * buf - Starting address of data to be written.
37 *
38 * Return:
39 * On success, number of bytes written.
40 * On failure, a TEST_ASSERT failure is caused.
41 */
42ssize_t test_write(int fd, const void *buf, size_t count)
43{
44 ssize_t rc;
45 ssize_t num_written = 0;
46 size_t num_left = count;
47 const char *ptr = buf;
48
49 /* Note: Count of zero is allowed (see "RETURN VALUE" portion of
50 * write(2) manpage for details.
51 */
52 TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count);
53
54 do {
55 rc = write(fd, ptr, num_left);
56
57 switch (rc) {
58 case -1:
59 TEST_ASSERT(errno == EAGAIN || errno == EINTR,
60 "Unexpected write failure,\n"
61 " rc: %zi errno: %i", rc, errno);
62 continue;
63
64 case 0:
65 TEST_ASSERT(false, "Unexpected EOF,\n"
66 " rc: %zi num_written: %zi num_left: %zu",
67 rc, num_written, num_left);
68 break;
69
70 default:
71 TEST_ASSERT(rc >= 0, "Unexpected ret from write,\n"
72 " rc: %zi errno: %i", rc, errno);
73 num_written += rc;
74 num_left -= rc;
75 ptr += rc;
76 break;
77 }
78 } while (num_written < count);
79
80 return num_written;
81}
82
83/* Test Read
84 *
85 * A wrapper for read(2), that automatically handles the following
86 * special conditions:
87 *
88 * + Interrupted system call (EINTR)
89 * + Read of less than requested amount
90 * + Non-block return (EAGAIN)
91 *
92 * For each of the above, an additional read is performed to automatically
93 * continue reading the requested data.
94 * There are also many cases where read(2) can return an unexpected
95 * error (e.g. EIO). Such errors cause a TEST_ASSERT failure. Note,
96 * it is expected that the file opened by fd at the current file position
97 * contains at least the number of requested bytes to be read. A TEST_ASSERT
98 * failure is produced if an End-Of-File condition occurs, before all the
99 * data is read. It is the callers responsibility to assure that sufficient
100 * data exists.
101 *
102 * Note, for function signature compatibility with read(2), this function
103 * returns the number of bytes read, but that value will always be equal
104 * to the number of requested bytes. All other conditions in this and
105 * future enhancements to this function either automatically issue another
106 * read(2) or cause a TEST_ASSERT failure.
107 *
108 * Args:
109 * fd - Opened file descriptor to file to be read.
110 * count - Number of bytes to read.
111 *
112 * Output:
113 * buf - Starting address of where to write the bytes read.
114 *
115 * Return:
116 * On success, number of bytes read.
117 * On failure, a TEST_ASSERT failure is caused.
118 */
119ssize_t test_read(int fd, void *buf, size_t count)
120{
121 ssize_t rc;
122 ssize_t num_read = 0;
123 size_t num_left = count;
124 char *ptr = buf;
125
126 /* Note: Count of zero is allowed (see "If count is zero" portion of
127 * read(2) manpage for details.
128 */
129 TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count);
130
131 do {
132 rc = read(fd, ptr, num_left);
133
134 switch (rc) {
135 case -1:
136 TEST_ASSERT(errno == EAGAIN || errno == EINTR,
137 "Unexpected read failure,\n"
138 " rc: %zi errno: %i", rc, errno);
139 break;
140
141 case 0:
142 TEST_ASSERT(false, "Unexpected EOF,\n"
143 " rc: %zi num_read: %zi num_left: %zu",
144 rc, num_read, num_left);
145 break;
146
147 default:
148 TEST_ASSERT(rc > 0, "Unexpected ret from read,\n"
149 " rc: %zi errno: %i", rc, errno);
150 num_read += rc;
151 num_left -= rc;
152 ptr += rc;
153 break;
154 }
155 } while (num_read < count);
156
157 return num_read;
158}
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
new file mode 100644
index 000000000000..37e2a787d2fc
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -0,0 +1,1486 @@
1/*
2 * tools/testing/selftests/kvm/lib/kvm_util.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#include "test_util.h"
10#include "kvm_util.h"
11#include "kvm_util_internal.h"
12
13#include <assert.h>
14#include <sys/mman.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17
18#define KVM_DEV_PATH "/dev/kvm"
19
20#define KVM_UTIL_PGS_PER_HUGEPG 512
21#define KVM_UTIL_MIN_PADDR 0x2000
22
23/* Aligns x up to the next multiple of size. Size must be a power of 2. */
24static void *align(void *x, size_t size)
25{
26 size_t mask = size - 1;
27 TEST_ASSERT(size != 0 && !(size & (size - 1)),
28 "size not a power of 2: %lu", size);
29 return (void *) (((size_t) x + mask) & ~mask);
30}
31
32/* Capability
33 *
34 * Input Args:
35 * cap - Capability
36 *
37 * Output Args: None
38 *
39 * Return:
40 * On success, the Value corresponding to the capability (KVM_CAP_*)
41 * specified by the value of cap. On failure a TEST_ASSERT failure
42 * is produced.
43 *
44 * Looks up and returns the value corresponding to the capability
45 * (KVM_CAP_*) given by cap.
46 */
47int kvm_check_cap(long cap)
48{
49 int ret;
50 int kvm_fd;
51
52 kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
53 if (kvm_fd < 0)
54 exit(KSFT_SKIP);
55
56 ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, cap);
57 TEST_ASSERT(ret != -1, "KVM_CHECK_EXTENSION IOCTL failed,\n"
58 " rc: %i errno: %i", ret, errno);
59
60 close(kvm_fd);
61
62 return ret;
63}
64
65/* VM Create
66 *
67 * Input Args:
68 * mode - VM Mode (e.g. VM_MODE_FLAT48PG)
69 * phy_pages - Physical memory pages
70 * perm - permission
71 *
72 * Output Args: None
73 *
74 * Return:
75 * Pointer to opaque structure that describes the created VM.
76 *
77 * Creates a VM with the mode specified by mode (e.g. VM_MODE_FLAT48PG).
78 * When phy_pages is non-zero, a memory region of phy_pages physical pages
79 * is created and mapped starting at guest physical address 0. The file
80 * descriptor to control the created VM is created with the permissions
81 * given by perm (e.g. O_RDWR).
82 */
83struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
84{
85 struct kvm_vm *vm;
86 int kvm_fd;
87
88 /* Allocate memory. */
89 vm = calloc(1, sizeof(*vm));
90 TEST_ASSERT(vm != NULL, "Insufficent Memory");
91
92 vm->mode = mode;
93 kvm_fd = open(KVM_DEV_PATH, perm);
94 if (kvm_fd < 0)
95 exit(KSFT_SKIP);
96
97 /* Create VM. */
98 vm->fd = ioctl(kvm_fd, KVM_CREATE_VM, NULL);
99 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
100 "rc: %i errno: %i", vm->fd, errno);
101
102 close(kvm_fd);
103
104 /* Setup mode specific traits. */
105 switch (vm->mode) {
106 case VM_MODE_FLAT48PG:
107 vm->page_size = 0x1000;
108 vm->page_shift = 12;
109
110 /* Limit to 48-bit canonical virtual addresses. */
111 vm->vpages_valid = sparsebit_alloc();
112 sparsebit_set_num(vm->vpages_valid,
113 0, (1ULL << (48 - 1)) >> vm->page_shift);
114 sparsebit_set_num(vm->vpages_valid,
115 (~((1ULL << (48 - 1)) - 1)) >> vm->page_shift,
116 (1ULL << (48 - 1)) >> vm->page_shift);
117
118 /* Limit physical addresses to 52-bits. */
119 vm->max_gfn = ((1ULL << 52) >> vm->page_shift) - 1;
120 break;
121
122 default:
123 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
124 }
125
126 /* Allocate and setup memory for guest. */
127 vm->vpages_mapped = sparsebit_alloc();
128 if (phy_pages != 0)
129 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
130 0, 0, phy_pages, 0);
131
132 return vm;
133}
134
135/* Userspace Memory Region Find
136 *
137 * Input Args:
138 * vm - Virtual Machine
139 * start - Starting VM physical address
140 * end - Ending VM physical address, inclusive.
141 *
142 * Output Args: None
143 *
144 * Return:
145 * Pointer to overlapping region, NULL if no such region.
146 *
147 * Searches for a region with any physical memory that overlaps with
148 * any portion of the guest physical addresses from start to end
149 * inclusive. If multiple overlapping regions exist, a pointer to any
150 * of the regions is returned. Null is returned only when no overlapping
151 * region exists.
152 */
153static struct userspace_mem_region *userspace_mem_region_find(
154 struct kvm_vm *vm, uint64_t start, uint64_t end)
155{
156 struct userspace_mem_region *region;
157
158 for (region = vm->userspace_mem_region_head; region;
159 region = region->next) {
160 uint64_t existing_start = region->region.guest_phys_addr;
161 uint64_t existing_end = region->region.guest_phys_addr
162 + region->region.memory_size - 1;
163 if (start <= existing_end && end >= existing_start)
164 return region;
165 }
166
167 return NULL;
168}
169
170/* KVM Userspace Memory Region Find
171 *
172 * Input Args:
173 * vm - Virtual Machine
174 * start - Starting VM physical address
175 * end - Ending VM physical address, inclusive.
176 *
177 * Output Args: None
178 *
179 * Return:
180 * Pointer to overlapping region, NULL if no such region.
181 *
182 * Public interface to userspace_mem_region_find. Allows tests to look up
183 * the memslot datastructure for a given range of guest physical memory.
184 */
185struct kvm_userspace_memory_region *
186kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
187 uint64_t end)
188{
189 struct userspace_mem_region *region;
190
191 region = userspace_mem_region_find(vm, start, end);
192 if (!region)
193 return NULL;
194
195 return &region->region;
196}
197
198/* VCPU Find
199 *
200 * Input Args:
201 * vm - Virtual Machine
202 * vcpuid - VCPU ID
203 *
204 * Output Args: None
205 *
206 * Return:
207 * Pointer to VCPU structure
208 *
209 * Locates a vcpu structure that describes the VCPU specified by vcpuid and
210 * returns a pointer to it. Returns NULL if the VM doesn't contain a VCPU
211 * for the specified vcpuid.
212 */
213struct vcpu *vcpu_find(struct kvm_vm *vm,
214 uint32_t vcpuid)
215{
216 struct vcpu *vcpup;
217
218 for (vcpup = vm->vcpu_head; vcpup; vcpup = vcpup->next) {
219 if (vcpup->id == vcpuid)
220 return vcpup;
221 }
222
223 return NULL;
224}
225
226/* VM VCPU Remove
227 *
228 * Input Args:
229 * vm - Virtual Machine
230 * vcpuid - VCPU ID
231 *
232 * Output Args: None
233 *
234 * Return: None, TEST_ASSERT failures for all error conditions
235 *
236 * Within the VM specified by vm, removes the VCPU given by vcpuid.
237 */
238static void vm_vcpu_rm(struct kvm_vm *vm, uint32_t vcpuid)
239{
240 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
241
242 int ret = close(vcpu->fd);
243 TEST_ASSERT(ret == 0, "Close of VCPU fd failed, rc: %i "
244 "errno: %i", ret, errno);
245
246 if (vcpu->next)
247 vcpu->next->prev = vcpu->prev;
248 if (vcpu->prev)
249 vcpu->prev->next = vcpu->next;
250 else
251 vm->vcpu_head = vcpu->next;
252 free(vcpu);
253}
254
255
256/* Destroys and frees the VM pointed to by vmp.
257 */
258void kvm_vm_free(struct kvm_vm *vmp)
259{
260 int ret;
261
262 if (vmp == NULL)
263 return;
264
265 /* Free userspace_mem_regions. */
266 while (vmp->userspace_mem_region_head) {
267 struct userspace_mem_region *region
268 = vmp->userspace_mem_region_head;
269
270 region->region.memory_size = 0;
271 ret = ioctl(vmp->fd, KVM_SET_USER_MEMORY_REGION,
272 &region->region);
273 TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed, "
274 "rc: %i errno: %i", ret, errno);
275
276 vmp->userspace_mem_region_head = region->next;
277 sparsebit_free(&region->unused_phy_pages);
278 ret = munmap(region->mmap_start, region->mmap_size);
279 TEST_ASSERT(ret == 0, "munmap failed, rc: %i errno: %i",
280 ret, errno);
281
282 free(region);
283 }
284
285 /* Free VCPUs. */
286 while (vmp->vcpu_head)
287 vm_vcpu_rm(vmp, vmp->vcpu_head->id);
288
289 /* Free sparsebit arrays. */
290 sparsebit_free(&vmp->vpages_valid);
291 sparsebit_free(&vmp->vpages_mapped);
292
293 /* Close file descriptor for the VM. */
294 ret = close(vmp->fd);
295 TEST_ASSERT(ret == 0, "Close of vm fd failed,\n"
296 " vmp->fd: %i rc: %i errno: %i", vmp->fd, ret, errno);
297
298 /* Free the structure describing the VM. */
299 free(vmp);
300}
301
302/* Memory Compare, host virtual to guest virtual
303 *
304 * Input Args:
305 * hva - Starting host virtual address
306 * vm - Virtual Machine
307 * gva - Starting guest virtual address
308 * len - number of bytes to compare
309 *
310 * Output Args: None
311 *
312 * Input/Output Args: None
313 *
314 * Return:
315 * Returns 0 if the bytes starting at hva for a length of len
316 * are equal the guest virtual bytes starting at gva. Returns
317 * a value < 0, if bytes at hva are less than those at gva.
318 * Otherwise a value > 0 is returned.
319 *
320 * Compares the bytes starting at the host virtual address hva, for
321 * a length of len, to the guest bytes starting at the guest virtual
322 * address given by gva.
323 */
324int kvm_memcmp_hva_gva(void *hva,
325 struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
326{
327 size_t amt;
328
329 /* Compare a batch of bytes until either a match is found
330 * or all the bytes have been compared.
331 */
332 for (uintptr_t offset = 0; offset < len; offset += amt) {
333 uintptr_t ptr1 = (uintptr_t)hva + offset;
334
335 /* Determine host address for guest virtual address
336 * at offset.
337 */
338 uintptr_t ptr2 = (uintptr_t)addr_gva2hva(vm, gva + offset);
339
340 /* Determine amount to compare on this pass.
341 * Don't allow the comparsion to cross a page boundary.
342 */
343 amt = len - offset;
344 if ((ptr1 >> vm->page_shift) != ((ptr1 + amt) >> vm->page_shift))
345 amt = vm->page_size - (ptr1 % vm->page_size);
346 if ((ptr2 >> vm->page_shift) != ((ptr2 + amt) >> vm->page_shift))
347 amt = vm->page_size - (ptr2 % vm->page_size);
348
349 assert((ptr1 >> vm->page_shift) == ((ptr1 + amt - 1) >> vm->page_shift));
350 assert((ptr2 >> vm->page_shift) == ((ptr2 + amt - 1) >> vm->page_shift));
351
352 /* Perform the comparison. If there is a difference
353 * return that result to the caller, otherwise need
354 * to continue on looking for a mismatch.
355 */
356 int ret = memcmp((void *)ptr1, (void *)ptr2, amt);
357 if (ret != 0)
358 return ret;
359 }
360
361 /* No mismatch found. Let the caller know the two memory
362 * areas are equal.
363 */
364 return 0;
365}
366
367/* Allocate an instance of struct kvm_cpuid2
368 *
369 * Input Args: None
370 *
371 * Output Args: None
372 *
373 * Return: A pointer to the allocated struct. The caller is responsible
374 * for freeing this struct.
375 *
376 * Since kvm_cpuid2 uses a 0-length array to allow a the size of the
377 * array to be decided at allocation time, allocation is slightly
378 * complicated. This function uses a reasonable default length for
379 * the array and performs the appropriate allocation.
380 */
381static struct kvm_cpuid2 *allocate_kvm_cpuid2(void)
382{
383 struct kvm_cpuid2 *cpuid;
384 int nent = 100;
385 size_t size;
386
387 size = sizeof(*cpuid);
388 size += nent * sizeof(struct kvm_cpuid_entry2);
389 cpuid = malloc(size);
390 if (!cpuid) {
391 perror("malloc");
392 abort();
393 }
394
395 cpuid->nent = nent;
396
397 return cpuid;
398}
399
400/* KVM Supported CPUID Get
401 *
402 * Input Args: None
403 *
404 * Output Args:
405 *
406 * Return: The supported KVM CPUID
407 *
408 * Get the guest CPUID supported by KVM.
409 */
410struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
411{
412 static struct kvm_cpuid2 *cpuid;
413 int ret;
414 int kvm_fd;
415
416 if (cpuid)
417 return cpuid;
418
419 cpuid = allocate_kvm_cpuid2();
420 kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
421 if (kvm_fd < 0)
422 exit(KSFT_SKIP);
423
424 ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
425 TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n",
426 ret, errno);
427
428 close(kvm_fd);
429 return cpuid;
430}
431
432/* Locate a cpuid entry.
433 *
434 * Input Args:
435 * cpuid: The cpuid.
436 * function: The function of the cpuid entry to find.
437 *
438 * Output Args: None
439 *
440 * Return: A pointer to the cpuid entry. Never returns NULL.
441 */
442struct kvm_cpuid_entry2 *
443kvm_get_supported_cpuid_index(uint32_t function, uint32_t index)
444{
445 struct kvm_cpuid2 *cpuid;
446 struct kvm_cpuid_entry2 *entry = NULL;
447 int i;
448
449 cpuid = kvm_get_supported_cpuid();
450 for (i = 0; i < cpuid->nent; i++) {
451 if (cpuid->entries[i].function == function &&
452 cpuid->entries[i].index == index) {
453 entry = &cpuid->entries[i];
454 break;
455 }
456 }
457
458 TEST_ASSERT(entry, "Guest CPUID entry not found: (EAX=%x, ECX=%x).",
459 function, index);
460 return entry;
461}
462
463/* VM Userspace Memory Region Add
464 *
465 * Input Args:
466 * vm - Virtual Machine
467 * backing_src - Storage source for this region.
468 * NULL to use anonymous memory.
469 * guest_paddr - Starting guest physical address
470 * slot - KVM region slot
471 * npages - Number of physical pages
472 * flags - KVM memory region flags (e.g. KVM_MEM_LOG_DIRTY_PAGES)
473 *
474 * Output Args: None
475 *
476 * Return: None
477 *
478 * Allocates a memory area of the number of pages specified by npages
479 * and maps it to the VM specified by vm, at a starting physical address
480 * given by guest_paddr. The region is created with a KVM region slot
481 * given by slot, which must be unique and < KVM_MEM_SLOTS_NUM. The
482 * region is created with the flags given by flags.
483 */
484void vm_userspace_mem_region_add(struct kvm_vm *vm,
485 enum vm_mem_backing_src_type src_type,
486 uint64_t guest_paddr, uint32_t slot, uint64_t npages,
487 uint32_t flags)
488{
489 int ret;
490 unsigned long pmem_size = 0;
491 struct userspace_mem_region *region;
492 size_t huge_page_size = KVM_UTIL_PGS_PER_HUGEPG * vm->page_size;
493
494 TEST_ASSERT((guest_paddr % vm->page_size) == 0, "Guest physical "
495 "address not on a page boundary.\n"
496 " guest_paddr: 0x%lx vm->page_size: 0x%x",
497 guest_paddr, vm->page_size);
498 TEST_ASSERT((((guest_paddr >> vm->page_shift) + npages) - 1)
499 <= vm->max_gfn, "Physical range beyond maximum "
500 "supported physical address,\n"
501 " guest_paddr: 0x%lx npages: 0x%lx\n"
502 " vm->max_gfn: 0x%lx vm->page_size: 0x%x",
503 guest_paddr, npages, vm->max_gfn, vm->page_size);
504
505 /* Confirm a mem region with an overlapping address doesn't
506 * already exist.
507 */
508 region = (struct userspace_mem_region *) userspace_mem_region_find(
509 vm, guest_paddr, guest_paddr + npages * vm->page_size);
510 if (region != NULL)
511 TEST_ASSERT(false, "overlapping userspace_mem_region already "
512 "exists\n"
513 " requested guest_paddr: 0x%lx npages: 0x%lx "
514 "page_size: 0x%x\n"
515 " existing guest_paddr: 0x%lx size: 0x%lx",
516 guest_paddr, npages, vm->page_size,
517 (uint64_t) region->region.guest_phys_addr,
518 (uint64_t) region->region.memory_size);
519
520 /* Confirm no region with the requested slot already exists. */
521 for (region = vm->userspace_mem_region_head; region;
522 region = region->next) {
523 if (region->region.slot == slot)
524 break;
525 if ((guest_paddr <= (region->region.guest_phys_addr
526 + region->region.memory_size))
527 && ((guest_paddr + npages * vm->page_size)
528 >= region->region.guest_phys_addr))
529 break;
530 }
531 if (region != NULL)
532 TEST_ASSERT(false, "A mem region with the requested slot "
533 "or overlapping physical memory range already exists.\n"
534 " requested slot: %u paddr: 0x%lx npages: 0x%lx\n"
535 " existing slot: %u paddr: 0x%lx size: 0x%lx",
536 slot, guest_paddr, npages,
537 region->region.slot,
538 (uint64_t) region->region.guest_phys_addr,
539 (uint64_t) region->region.memory_size);
540
541 /* Allocate and initialize new mem region structure. */
542 region = calloc(1, sizeof(*region));
543 TEST_ASSERT(region != NULL, "Insufficient Memory");
544 region->mmap_size = npages * vm->page_size;
545
546 /* Enough memory to align up to a huge page. */
547 if (src_type == VM_MEM_SRC_ANONYMOUS_THP)
548 region->mmap_size += huge_page_size;
549 region->mmap_start = mmap(NULL, region->mmap_size,
550 PROT_READ | PROT_WRITE,
551 MAP_PRIVATE | MAP_ANONYMOUS
552 | (src_type == VM_MEM_SRC_ANONYMOUS_HUGETLB ? MAP_HUGETLB : 0),
553 -1, 0);
554 TEST_ASSERT(region->mmap_start != MAP_FAILED,
555 "test_malloc failed, mmap_start: %p errno: %i",
556 region->mmap_start, errno);
557
558 /* Align THP allocation up to start of a huge page. */
559 region->host_mem = align(region->mmap_start,
560 src_type == VM_MEM_SRC_ANONYMOUS_THP ? huge_page_size : 1);
561
562 /* As needed perform madvise */
563 if (src_type == VM_MEM_SRC_ANONYMOUS || src_type == VM_MEM_SRC_ANONYMOUS_THP) {
564 ret = madvise(region->host_mem, npages * vm->page_size,
565 src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
566 TEST_ASSERT(ret == 0, "madvise failed,\n"
567 " addr: %p\n"
568 " length: 0x%lx\n"
569 " src_type: %x",
570 region->host_mem, npages * vm->page_size, src_type);
571 }
572
573 region->unused_phy_pages = sparsebit_alloc();
574 sparsebit_set_num(region->unused_phy_pages,
575 guest_paddr >> vm->page_shift, npages);
576 region->region.slot = slot;
577 region->region.flags = flags;
578 region->region.guest_phys_addr = guest_paddr;
579 region->region.memory_size = npages * vm->page_size;
580 region->region.userspace_addr = (uintptr_t) region->host_mem;
581 ret = ioctl(vm->fd, KVM_SET_USER_MEMORY_REGION, &region->region);
582 TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed,\n"
583 " rc: %i errno: %i\n"
584 " slot: %u flags: 0x%x\n"
585 " guest_phys_addr: 0x%lx size: 0x%lx",
586 ret, errno, slot, flags,
587 guest_paddr, (uint64_t) region->region.memory_size);
588
589 /* Add to linked-list of memory regions. */
590 if (vm->userspace_mem_region_head)
591 vm->userspace_mem_region_head->prev = region;
592 region->next = vm->userspace_mem_region_head;
593 vm->userspace_mem_region_head = region;
594}
595
596/* Memslot to region
597 *
598 * Input Args:
599 * vm - Virtual Machine
600 * memslot - KVM memory slot ID
601 *
602 * Output Args: None
603 *
604 * Return:
605 * Pointer to memory region structure that describe memory region
606 * using kvm memory slot ID given by memslot. TEST_ASSERT failure
607 * on error (e.g. currently no memory region using memslot as a KVM
608 * memory slot ID).
609 */
610static struct userspace_mem_region *memslot2region(struct kvm_vm *vm,
611 uint32_t memslot)
612{
613 struct userspace_mem_region *region;
614
615 for (region = vm->userspace_mem_region_head; region;
616 region = region->next) {
617 if (region->region.slot == memslot)
618 break;
619 }
620 if (region == NULL) {
621 fprintf(stderr, "No mem region with the requested slot found,\n"
622 " requested slot: %u\n", memslot);
623 fputs("---- vm dump ----\n", stderr);
624 vm_dump(stderr, vm, 2);
625 TEST_ASSERT(false, "Mem region not found");
626 }
627
628 return region;
629}
630
631/* VM Memory Region Flags Set
632 *
633 * Input Args:
634 * vm - Virtual Machine
635 * flags - Starting guest physical address
636 *
637 * Output Args: None
638 *
639 * Return: None
640 *
641 * Sets the flags of the memory region specified by the value of slot,
642 * to the values given by flags.
643 */
644void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags)
645{
646 int ret;
647 struct userspace_mem_region *region;
648
649 /* Locate memory region. */
650 region = memslot2region(vm, slot);
651
652 region->region.flags = flags;
653
654 ret = ioctl(vm->fd, KVM_SET_USER_MEMORY_REGION, &region->region);
655
656 TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed,\n"
657 " rc: %i errno: %i slot: %u flags: 0x%x",
658 ret, errno, slot, flags);
659}
660
661/* VCPU mmap Size
662 *
663 * Input Args: None
664 *
665 * Output Args: None
666 *
667 * Return:
668 * Size of VCPU state
669 *
670 * Returns the size of the structure pointed to by the return value
671 * of vcpu_state().
672 */
673static int vcpu_mmap_sz(void)
674{
675 int dev_fd, ret;
676
677 dev_fd = open(KVM_DEV_PATH, O_RDONLY);
678 if (dev_fd < 0)
679 exit(KSFT_SKIP);
680
681 ret = ioctl(dev_fd, KVM_GET_VCPU_MMAP_SIZE, NULL);
682 TEST_ASSERT(ret >= sizeof(struct kvm_run),
683 "%s KVM_GET_VCPU_MMAP_SIZE ioctl failed, rc: %i errno: %i",
684 __func__, ret, errno);
685
686 close(dev_fd);
687
688 return ret;
689}
690
691/* VM VCPU Add
692 *
693 * Input Args:
694 * vm - Virtual Machine
695 * vcpuid - VCPU ID
696 *
697 * Output Args: None
698 *
699 * Return: None
700 *
701 * Creates and adds to the VM specified by vm and virtual CPU with
702 * the ID given by vcpuid.
703 */
704void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid)
705{
706 struct vcpu *vcpu;
707
708 /* Confirm a vcpu with the specified id doesn't already exist. */
709 vcpu = vcpu_find(vm, vcpuid);
710 if (vcpu != NULL)
711 TEST_ASSERT(false, "vcpu with the specified id "
712 "already exists,\n"
713 " requested vcpuid: %u\n"
714 " existing vcpuid: %u state: %p",
715 vcpuid, vcpu->id, vcpu->state);
716
717 /* Allocate and initialize new vcpu structure. */
718 vcpu = calloc(1, sizeof(*vcpu));
719 TEST_ASSERT(vcpu != NULL, "Insufficient Memory");
720 vcpu->id = vcpuid;
721 vcpu->fd = ioctl(vm->fd, KVM_CREATE_VCPU, vcpuid);
722 TEST_ASSERT(vcpu->fd >= 0, "KVM_CREATE_VCPU failed, rc: %i errno: %i",
723 vcpu->fd, errno);
724
725 TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->state), "vcpu mmap size "
726 "smaller than expected, vcpu_mmap_sz: %i expected_min: %zi",
727 vcpu_mmap_sz(), sizeof(*vcpu->state));
728 vcpu->state = (struct kvm_run *) mmap(NULL, sizeof(*vcpu->state),
729 PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0);
730 TEST_ASSERT(vcpu->state != MAP_FAILED, "mmap vcpu_state failed, "
731 "vcpu id: %u errno: %i", vcpuid, errno);
732
733 /* Add to linked-list of VCPUs. */
734 if (vm->vcpu_head)
735 vm->vcpu_head->prev = vcpu;
736 vcpu->next = vm->vcpu_head;
737 vm->vcpu_head = vcpu;
738
739 vcpu_setup(vm, vcpuid);
740}
741
742/* VM Virtual Address Unused Gap
743 *
744 * Input Args:
745 * vm - Virtual Machine
746 * sz - Size (bytes)
747 * vaddr_min - Minimum Virtual Address
748 *
749 * Output Args: None
750 *
751 * Return:
752 * Lowest virtual address at or below vaddr_min, with at least
753 * sz unused bytes. TEST_ASSERT failure if no area of at least
754 * size sz is available.
755 *
756 * Within the VM specified by vm, locates the lowest starting virtual
757 * address >= vaddr_min, that has at least sz unallocated bytes. A
758 * TEST_ASSERT failure occurs for invalid input or no area of at least
759 * sz unallocated bytes >= vaddr_min is available.
760 */
761static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz,
762 vm_vaddr_t vaddr_min)
763{
764 uint64_t pages = (sz + vm->page_size - 1) >> vm->page_shift;
765
766 /* Determine lowest permitted virtual page index. */
767 uint64_t pgidx_start = (vaddr_min + vm->page_size - 1) >> vm->page_shift;
768 if ((pgidx_start * vm->page_size) < vaddr_min)
769 goto no_va_found;
770
771 /* Loop over section with enough valid virtual page indexes. */
772 if (!sparsebit_is_set_num(vm->vpages_valid,
773 pgidx_start, pages))
774 pgidx_start = sparsebit_next_set_num(vm->vpages_valid,
775 pgidx_start, pages);
776 do {
777 /*
778 * Are there enough unused virtual pages available at
779 * the currently proposed starting virtual page index.
780 * If not, adjust proposed starting index to next
781 * possible.
782 */
783 if (sparsebit_is_clear_num(vm->vpages_mapped,
784 pgidx_start, pages))
785 goto va_found;
786 pgidx_start = sparsebit_next_clear_num(vm->vpages_mapped,
787 pgidx_start, pages);
788 if (pgidx_start == 0)
789 goto no_va_found;
790
791 /*
792 * If needed, adjust proposed starting virtual address,
793 * to next range of valid virtual addresses.
794 */
795 if (!sparsebit_is_set_num(vm->vpages_valid,
796 pgidx_start, pages)) {
797 pgidx_start = sparsebit_next_set_num(
798 vm->vpages_valid, pgidx_start, pages);
799 if (pgidx_start == 0)
800 goto no_va_found;
801 }
802 } while (pgidx_start != 0);
803
804no_va_found:
805 TEST_ASSERT(false, "No vaddr of specified pages available, "
806 "pages: 0x%lx", pages);
807
808 /* NOT REACHED */
809 return -1;
810
811va_found:
812 TEST_ASSERT(sparsebit_is_set_num(vm->vpages_valid,
813 pgidx_start, pages),
814 "Unexpected, invalid virtual page index range,\n"
815 " pgidx_start: 0x%lx\n"
816 " pages: 0x%lx",
817 pgidx_start, pages);
818 TEST_ASSERT(sparsebit_is_clear_num(vm->vpages_mapped,
819 pgidx_start, pages),
820 "Unexpected, pages already mapped,\n"
821 " pgidx_start: 0x%lx\n"
822 " pages: 0x%lx",
823 pgidx_start, pages);
824
825 return pgidx_start * vm->page_size;
826}
827
828/* VM Virtual Address Allocate
829 *
830 * Input Args:
831 * vm - Virtual Machine
832 * sz - Size in bytes
833 * vaddr_min - Minimum starting virtual address
834 * data_memslot - Memory region slot for data pages
835 * pgd_memslot - Memory region slot for new virtual translation tables
836 *
837 * Output Args: None
838 *
839 * Return:
840 * Starting guest virtual address
841 *
842 * Allocates at least sz bytes within the virtual address space of the vm
843 * given by vm. The allocated bytes are mapped to a virtual address >=
844 * the address given by vaddr_min. Note that each allocation uses a
845 * a unique set of pages, with the minimum real allocation being at least
846 * a page.
847 */
848vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
849 uint32_t data_memslot, uint32_t pgd_memslot)
850{
851 uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
852
853 virt_pgd_alloc(vm, pgd_memslot);
854
855 /* Find an unused range of virtual page addresses of at least
856 * pages in length.
857 */
858 vm_vaddr_t vaddr_start = vm_vaddr_unused_gap(vm, sz, vaddr_min);
859
860 /* Map the virtual pages. */
861 for (vm_vaddr_t vaddr = vaddr_start; pages > 0;
862 pages--, vaddr += vm->page_size) {
863 vm_paddr_t paddr;
864
865 paddr = vm_phy_page_alloc(vm, KVM_UTIL_MIN_PADDR, data_memslot);
866
867 virt_pg_map(vm, vaddr, paddr, pgd_memslot);
868
869 sparsebit_set(vm->vpages_mapped,
870 vaddr >> vm->page_shift);
871 }
872
873 return vaddr_start;
874}
875
876/* Address VM Physical to Host Virtual
877 *
878 * Input Args:
879 * vm - Virtual Machine
880 * gpa - VM physical address
881 *
882 * Output Args: None
883 *
884 * Return:
885 * Equivalent host virtual address
886 *
887 * Locates the memory region containing the VM physical address given
888 * by gpa, within the VM given by vm. When found, the host virtual
889 * address providing the memory to the vm physical address is returned.
890 * A TEST_ASSERT failure occurs if no region containing gpa exists.
891 */
892void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa)
893{
894 struct userspace_mem_region *region;
895 for (region = vm->userspace_mem_region_head; region;
896 region = region->next) {
897 if ((gpa >= region->region.guest_phys_addr)
898 && (gpa <= (region->region.guest_phys_addr
899 + region->region.memory_size - 1)))
900 return (void *) ((uintptr_t) region->host_mem
901 + (gpa - region->region.guest_phys_addr));
902 }
903
904 TEST_ASSERT(false, "No vm physical memory at 0x%lx", gpa);
905 return NULL;
906}
907
908/* Address Host Virtual to VM Physical
909 *
910 * Input Args:
911 * vm - Virtual Machine
912 * hva - Host virtual address
913 *
914 * Output Args: None
915 *
916 * Return:
917 * Equivalent VM physical address
918 *
919 * Locates the memory region containing the host virtual address given
920 * by hva, within the VM given by vm. When found, the equivalent
921 * VM physical address is returned. A TEST_ASSERT failure occurs if no
922 * region containing hva exists.
923 */
924vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva)
925{
926 struct userspace_mem_region *region;
927 for (region = vm->userspace_mem_region_head; region;
928 region = region->next) {
929 if ((hva >= region->host_mem)
930 && (hva <= (region->host_mem
931 + region->region.memory_size - 1)))
932 return (vm_paddr_t) ((uintptr_t)
933 region->region.guest_phys_addr
934 + (hva - (uintptr_t) region->host_mem));
935 }
936
937 TEST_ASSERT(false, "No mapping to a guest physical address, "
938 "hva: %p", hva);
939 return -1;
940}
941
942/* VM Create IRQ Chip
943 *
944 * Input Args:
945 * vm - Virtual Machine
946 *
947 * Output Args: None
948 *
949 * Return: None
950 *
951 * Creates an interrupt controller chip for the VM specified by vm.
952 */
953void vm_create_irqchip(struct kvm_vm *vm)
954{
955 int ret;
956
957 ret = ioctl(vm->fd, KVM_CREATE_IRQCHIP, 0);
958 TEST_ASSERT(ret == 0, "KVM_CREATE_IRQCHIP IOCTL failed, "
959 "rc: %i errno: %i", ret, errno);
960}
961
962/* VM VCPU State
963 *
964 * Input Args:
965 * vm - Virtual Machine
966 * vcpuid - VCPU ID
967 *
968 * Output Args: None
969 *
970 * Return:
971 * Pointer to structure that describes the state of the VCPU.
972 *
973 * Locates and returns a pointer to a structure that describes the
974 * state of the VCPU with the given vcpuid.
975 */
976struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid)
977{
978 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
979 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
980
981 return vcpu->state;
982}
983
984/* VM VCPU Run
985 *
986 * Input Args:
987 * vm - Virtual Machine
988 * vcpuid - VCPU ID
989 *
990 * Output Args: None
991 *
992 * Return: None
993 *
994 * Switch to executing the code for the VCPU given by vcpuid, within the VM
995 * given by vm.
996 */
997void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
998{
999 int ret = _vcpu_run(vm, vcpuid);
1000 TEST_ASSERT(ret == 0, "KVM_RUN IOCTL failed, "
1001 "rc: %i errno: %i", ret, errno);
1002}
1003
1004int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
1005{
1006 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1007 int rc;
1008
1009 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1010 do {
1011 rc = ioctl(vcpu->fd, KVM_RUN, NULL);
1012 } while (rc == -1 && errno == EINTR);
1013 return rc;
1014}
1015
1016/* VM VCPU Set MP State
1017 *
1018 * Input Args:
1019 * vm - Virtual Machine
1020 * vcpuid - VCPU ID
1021 * mp_state - mp_state to be set
1022 *
1023 * Output Args: None
1024 *
1025 * Return: None
1026 *
1027 * Sets the MP state of the VCPU given by vcpuid, to the state given
1028 * by mp_state.
1029 */
1030void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
1031 struct kvm_mp_state *mp_state)
1032{
1033 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1034 int ret;
1035
1036 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1037
1038 ret = ioctl(vcpu->fd, KVM_SET_MP_STATE, mp_state);
1039 TEST_ASSERT(ret == 0, "KVM_SET_MP_STATE IOCTL failed, "
1040 "rc: %i errno: %i", ret, errno);
1041}
1042
1043/* VM VCPU Regs Get
1044 *
1045 * Input Args:
1046 * vm - Virtual Machine
1047 * vcpuid - VCPU ID
1048 *
1049 * Output Args:
1050 * regs - current state of VCPU regs
1051 *
1052 * Return: None
1053 *
1054 * Obtains the current register state for the VCPU specified by vcpuid
1055 * and stores it at the location given by regs.
1056 */
1057void vcpu_regs_get(struct kvm_vm *vm,
1058 uint32_t vcpuid, struct kvm_regs *regs)
1059{
1060 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1061 int ret;
1062
1063 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1064
1065 /* Get the regs. */
1066 ret = ioctl(vcpu->fd, KVM_GET_REGS, regs);
1067 TEST_ASSERT(ret == 0, "KVM_GET_REGS failed, rc: %i errno: %i",
1068 ret, errno);
1069}
1070
1071/* VM VCPU Regs Set
1072 *
1073 * Input Args:
1074 * vm - Virtual Machine
1075 * vcpuid - VCPU ID
1076 * regs - Values to set VCPU regs to
1077 *
1078 * Output Args: None
1079 *
1080 * Return: None
1081 *
1082 * Sets the regs of the VCPU specified by vcpuid to the values
1083 * given by regs.
1084 */
1085void vcpu_regs_set(struct kvm_vm *vm,
1086 uint32_t vcpuid, struct kvm_regs *regs)
1087{
1088 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1089 int ret;
1090
1091 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1092
1093 /* Set the regs. */
1094 ret = ioctl(vcpu->fd, KVM_SET_REGS, regs);
1095 TEST_ASSERT(ret == 0, "KVM_SET_REGS failed, rc: %i errno: %i",
1096 ret, errno);
1097}
1098
1099void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
1100 struct kvm_vcpu_events *events)
1101{
1102 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1103 int ret;
1104
1105 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1106
1107 /* Get the regs. */
1108 ret = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, events);
1109 TEST_ASSERT(ret == 0, "KVM_GET_VCPU_EVENTS, failed, rc: %i errno: %i",
1110 ret, errno);
1111}
1112
1113void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
1114 struct kvm_vcpu_events *events)
1115{
1116 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1117 int ret;
1118
1119 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1120
1121 /* Set the regs. */
1122 ret = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, events);
1123 TEST_ASSERT(ret == 0, "KVM_SET_VCPU_EVENTS, failed, rc: %i errno: %i",
1124 ret, errno);
1125}
1126
1127/* VM VCPU Args Set
1128 *
1129 * Input Args:
1130 * vm - Virtual Machine
1131 * vcpuid - VCPU ID
1132 * num - number of arguments
1133 * ... - arguments, each of type uint64_t
1134 *
1135 * Output Args: None
1136 *
1137 * Return: None
1138 *
1139 * Sets the first num function input arguments to the values
1140 * given as variable args. Each of the variable args is expected to
1141 * be of type uint64_t.
1142 */
1143void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
1144{
1145 va_list ap;
1146 struct kvm_regs regs;
1147
1148 TEST_ASSERT(num >= 1 && num <= 6, "Unsupported number of args,\n"
1149 " num: %u\n",
1150 num);
1151
1152 va_start(ap, num);
1153 vcpu_regs_get(vm, vcpuid, &regs);
1154
1155 if (num >= 1)
1156 regs.rdi = va_arg(ap, uint64_t);
1157
1158 if (num >= 2)
1159 regs.rsi = va_arg(ap, uint64_t);
1160
1161 if (num >= 3)
1162 regs.rdx = va_arg(ap, uint64_t);
1163
1164 if (num >= 4)
1165 regs.rcx = va_arg(ap, uint64_t);
1166
1167 if (num >= 5)
1168 regs.r8 = va_arg(ap, uint64_t);
1169
1170 if (num >= 6)
1171 regs.r9 = va_arg(ap, uint64_t);
1172
1173 vcpu_regs_set(vm, vcpuid, &regs);
1174 va_end(ap);
1175}
1176
1177/* VM VCPU System Regs Get
1178 *
1179 * Input Args:
1180 * vm - Virtual Machine
1181 * vcpuid - VCPU ID
1182 *
1183 * Output Args:
1184 * sregs - current state of VCPU system regs
1185 *
1186 * Return: None
1187 *
1188 * Obtains the current system register state for the VCPU specified by
1189 * vcpuid and stores it at the location given by sregs.
1190 */
1191void vcpu_sregs_get(struct kvm_vm *vm,
1192 uint32_t vcpuid, struct kvm_sregs *sregs)
1193{
1194 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1195 int ret;
1196
1197 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1198
1199 /* Get the regs. */
1200 /* Get the regs. */
1201 ret = ioctl(vcpu->fd, KVM_GET_SREGS, sregs);
1202 TEST_ASSERT(ret == 0, "KVM_GET_SREGS failed, rc: %i errno: %i",
1203 ret, errno);
1204}
1205
1206/* VM VCPU System Regs Set
1207 *
1208 * Input Args:
1209 * vm - Virtual Machine
1210 * vcpuid - VCPU ID
1211 * sregs - Values to set VCPU system regs to
1212 *
1213 * Output Args: None
1214 *
1215 * Return: None
1216 *
1217 * Sets the system regs of the VCPU specified by vcpuid to the values
1218 * given by sregs.
1219 */
1220void vcpu_sregs_set(struct kvm_vm *vm,
1221 uint32_t vcpuid, struct kvm_sregs *sregs)
1222{
1223 int ret = _vcpu_sregs_set(vm, vcpuid, sregs);
1224 TEST_ASSERT(ret == 0, "KVM_RUN IOCTL failed, "
1225 "rc: %i errno: %i", ret, errno);
1226}
1227
1228int _vcpu_sregs_set(struct kvm_vm *vm,
1229 uint32_t vcpuid, struct kvm_sregs *sregs)
1230{
1231 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1232 int ret;
1233
1234 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1235
1236 /* Get the regs. */
1237 return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);
1238}
1239
1240/* VCPU Ioctl
1241 *
1242 * Input Args:
1243 * vm - Virtual Machine
1244 * vcpuid - VCPU ID
1245 * cmd - Ioctl number
1246 * arg - Argument to pass to the ioctl
1247 *
1248 * Return: None
1249 *
1250 * Issues an arbitrary ioctl on a VCPU fd.
1251 */
1252void vcpu_ioctl(struct kvm_vm *vm,
1253 uint32_t vcpuid, unsigned long cmd, void *arg)
1254{
1255 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1256 int ret;
1257
1258 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1259
1260 ret = ioctl(vcpu->fd, cmd, arg);
1261 TEST_ASSERT(ret == 0, "vcpu ioctl %lu failed, rc: %i errno: %i (%s)",
1262 cmd, ret, errno, strerror(errno));
1263}
1264
1265/* VM Ioctl
1266 *
1267 * Input Args:
1268 * vm - Virtual Machine
1269 * cmd - Ioctl number
1270 * arg - Argument to pass to the ioctl
1271 *
1272 * Return: None
1273 *
1274 * Issues an arbitrary ioctl on a VM fd.
1275 */
1276void vm_ioctl(struct kvm_vm *vm, unsigned long cmd, void *arg)
1277{
1278 int ret;
1279
1280 ret = ioctl(vm->fd, cmd, arg);
1281 TEST_ASSERT(ret == 0, "vm ioctl %lu failed, rc: %i errno: %i (%s)",
1282 cmd, ret, errno, strerror(errno));
1283}
1284
1285/* VM Dump
1286 *
1287 * Input Args:
1288 * vm - Virtual Machine
1289 * indent - Left margin indent amount
1290 *
1291 * Output Args:
1292 * stream - Output FILE stream
1293 *
1294 * Return: None
1295 *
1296 * Dumps the current state of the VM given by vm, to the FILE stream
1297 * given by stream.
1298 */
1299void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
1300{
1301 struct userspace_mem_region *region;
1302 struct vcpu *vcpu;
1303
1304 fprintf(stream, "%*smode: 0x%x\n", indent, "", vm->mode);
1305 fprintf(stream, "%*sfd: %i\n", indent, "", vm->fd);
1306 fprintf(stream, "%*spage_size: 0x%x\n", indent, "", vm->page_size);
1307 fprintf(stream, "%*sMem Regions:\n", indent, "");
1308 for (region = vm->userspace_mem_region_head; region;
1309 region = region->next) {
1310 fprintf(stream, "%*sguest_phys: 0x%lx size: 0x%lx "
1311 "host_virt: %p\n", indent + 2, "",
1312 (uint64_t) region->region.guest_phys_addr,
1313 (uint64_t) region->region.memory_size,
1314 region->host_mem);
1315 fprintf(stream, "%*sunused_phy_pages: ", indent + 2, "");
1316 sparsebit_dump(stream, region->unused_phy_pages, 0);
1317 }
1318 fprintf(stream, "%*sMapped Virtual Pages:\n", indent, "");
1319 sparsebit_dump(stream, vm->vpages_mapped, indent + 2);
1320 fprintf(stream, "%*spgd_created: %u\n", indent, "",
1321 vm->pgd_created);
1322 if (vm->pgd_created) {
1323 fprintf(stream, "%*sVirtual Translation Tables:\n",
1324 indent + 2, "");
1325 virt_dump(stream, vm, indent + 4);
1326 }
1327 fprintf(stream, "%*sVCPUs:\n", indent, "");
1328 for (vcpu = vm->vcpu_head; vcpu; vcpu = vcpu->next)
1329 vcpu_dump(stream, vm, vcpu->id, indent + 2);
1330}
1331
1332/* VM VCPU Dump
1333 *
1334 * Input Args:
1335 * vm - Virtual Machine
1336 * vcpuid - VCPU ID
1337 * indent - Left margin indent amount
1338 *
1339 * Output Args:
1340 * stream - Output FILE stream
1341 *
1342 * Return: None
1343 *
1344 * Dumps the current state of the VCPU specified by vcpuid, within the VM
1345 * given by vm, to the FILE stream given by stream.
1346 */
1347void vcpu_dump(FILE *stream, struct kvm_vm *vm,
1348 uint32_t vcpuid, uint8_t indent)
1349{
1350 struct kvm_regs regs;
1351 struct kvm_sregs sregs;
1352
1353 fprintf(stream, "%*scpuid: %u\n", indent, "", vcpuid);
1354
1355 fprintf(stream, "%*sregs:\n", indent + 2, "");
1356 vcpu_regs_get(vm, vcpuid, &regs);
1357 regs_dump(stream, &regs, indent + 4);
1358
1359 fprintf(stream, "%*ssregs:\n", indent + 2, "");
1360 vcpu_sregs_get(vm, vcpuid, &sregs);
1361 sregs_dump(stream, &sregs, indent + 4);
1362}
1363
1364/* Known KVM exit reasons */
1365static struct exit_reason {
1366 unsigned int reason;
1367 const char *name;
1368} exit_reasons_known[] = {
1369 {KVM_EXIT_UNKNOWN, "UNKNOWN"},
1370 {KVM_EXIT_EXCEPTION, "EXCEPTION"},
1371 {KVM_EXIT_IO, "IO"},
1372 {KVM_EXIT_HYPERCALL, "HYPERCALL"},
1373 {KVM_EXIT_DEBUG, "DEBUG"},
1374 {KVM_EXIT_HLT, "HLT"},
1375 {KVM_EXIT_MMIO, "MMIO"},
1376 {KVM_EXIT_IRQ_WINDOW_OPEN, "IRQ_WINDOW_OPEN"},
1377 {KVM_EXIT_SHUTDOWN, "SHUTDOWN"},
1378 {KVM_EXIT_FAIL_ENTRY, "FAIL_ENTRY"},
1379 {KVM_EXIT_INTR, "INTR"},
1380 {KVM_EXIT_SET_TPR, "SET_TPR"},
1381 {KVM_EXIT_TPR_ACCESS, "TPR_ACCESS"},
1382 {KVM_EXIT_S390_SIEIC, "S390_SIEIC"},
1383 {KVM_EXIT_S390_RESET, "S390_RESET"},
1384 {KVM_EXIT_DCR, "DCR"},
1385 {KVM_EXIT_NMI, "NMI"},
1386 {KVM_EXIT_INTERNAL_ERROR, "INTERNAL_ERROR"},
1387 {KVM_EXIT_OSI, "OSI"},
1388 {KVM_EXIT_PAPR_HCALL, "PAPR_HCALL"},
1389#ifdef KVM_EXIT_MEMORY_NOT_PRESENT
1390 {KVM_EXIT_MEMORY_NOT_PRESENT, "MEMORY_NOT_PRESENT"},
1391#endif
1392};
1393
1394/* Exit Reason String
1395 *
1396 * Input Args:
1397 * exit_reason - Exit reason
1398 *
1399 * Output Args: None
1400 *
1401 * Return:
1402 * Constant string pointer describing the exit reason.
1403 *
1404 * Locates and returns a constant string that describes the KVM exit
1405 * reason given by exit_reason. If no such string is found, a constant
1406 * string of "Unknown" is returned.
1407 */
1408const char *exit_reason_str(unsigned int exit_reason)
1409{
1410 unsigned int n1;
1411
1412 for (n1 = 0; n1 < ARRAY_SIZE(exit_reasons_known); n1++) {
1413 if (exit_reason == exit_reasons_known[n1].reason)
1414 return exit_reasons_known[n1].name;
1415 }
1416
1417 return "Unknown";
1418}
1419
1420/* Physical Page Allocate
1421 *
1422 * Input Args:
1423 * vm - Virtual Machine
1424 * paddr_min - Physical address minimum
1425 * memslot - Memory region to allocate page from
1426 *
1427 * Output Args: None
1428 *
1429 * Return:
1430 * Starting physical address
1431 *
1432 * Within the VM specified by vm, locates an available physical page
1433 * at or above paddr_min. If found, the page is marked as in use
1434 * and its address is returned. A TEST_ASSERT failure occurs if no
1435 * page is available at or above paddr_min.
1436 */
1437vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
1438 vm_paddr_t paddr_min, uint32_t memslot)
1439{
1440 struct userspace_mem_region *region;
1441 sparsebit_idx_t pg;
1442
1443 TEST_ASSERT((paddr_min % vm->page_size) == 0, "Min physical address "
1444 "not divisible by page size.\n"
1445 " paddr_min: 0x%lx page_size: 0x%x",
1446 paddr_min, vm->page_size);
1447
1448 /* Locate memory region. */
1449 region = memslot2region(vm, memslot);
1450
1451 /* Locate next available physical page at or above paddr_min. */
1452 pg = paddr_min >> vm->page_shift;
1453
1454 if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
1455 pg = sparsebit_next_set(region->unused_phy_pages, pg);
1456 if (pg == 0) {
1457 fprintf(stderr, "No guest physical page available, "
1458 "paddr_min: 0x%lx page_size: 0x%x memslot: %u",
1459 paddr_min, vm->page_size, memslot);
1460 fputs("---- vm dump ----\n", stderr);
1461 vm_dump(stderr, vm, 2);
1462 abort();
1463 }
1464 }
1465
1466 /* Specify page as in use and return its address. */
1467 sparsebit_clear(region->unused_phy_pages, pg);
1468
1469 return pg * vm->page_size;
1470}
1471
1472/* Address Guest Virtual to Host Virtual
1473 *
1474 * Input Args:
1475 * vm - Virtual Machine
1476 * gva - VM virtual address
1477 *
1478 * Output Args: None
1479 *
1480 * Return:
1481 * Equivalent host virtual address
1482 */
1483void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva)
1484{
1485 return addr_gpa2hva(vm, addr_gva2gpa(vm, gva));
1486}
diff --git a/tools/testing/selftests/kvm/lib/kvm_util_internal.h b/tools/testing/selftests/kvm/lib/kvm_util_internal.h
new file mode 100644
index 000000000000..a0bd1980c81c
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/kvm_util_internal.h
@@ -0,0 +1,67 @@
1/*
2 * tools/testing/selftests/kvm/lib/kvm_util.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#ifndef KVM_UTIL_INTERNAL_H
10#define KVM_UTIL_INTERNAL_H 1
11
12#include "sparsebit.h"
13
14#ifndef BITS_PER_BYTE
15#define BITS_PER_BYTE 8
16#endif
17
18#ifndef BITS_PER_LONG
19#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
20#endif
21
22#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
23#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
24
25/* Concrete definition of struct kvm_vm. */
26struct userspace_mem_region {
27 struct userspace_mem_region *next, *prev;
28 struct kvm_userspace_memory_region region;
29 struct sparsebit *unused_phy_pages;
30 int fd;
31 off_t offset;
32 void *host_mem;
33 void *mmap_start;
34 size_t mmap_size;
35};
36
37struct vcpu {
38 struct vcpu *next, *prev;
39 uint32_t id;
40 int fd;
41 struct kvm_run *state;
42};
43
44struct kvm_vm {
45 int mode;
46 int fd;
47 unsigned int page_size;
48 unsigned int page_shift;
49 uint64_t max_gfn;
50 struct vcpu *vcpu_head;
51 struct userspace_mem_region *userspace_mem_region_head;
52 struct sparsebit *vpages_valid;
53 struct sparsebit *vpages_mapped;
54 bool pgd_created;
55 vm_paddr_t pgd;
56};
57
58struct vcpu *vcpu_find(struct kvm_vm *vm,
59 uint32_t vcpuid);
60void vcpu_setup(struct kvm_vm *vm, int vcpuid);
61void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
62void regs_dump(FILE *stream, struct kvm_regs *regs,
63 uint8_t indent);
64void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
65 uint8_t indent);
66
67#endif
diff --git a/tools/testing/selftests/kvm/lib/sparsebit.c b/tools/testing/selftests/kvm/lib/sparsebit.c
new file mode 100644
index 000000000000..b132bc95d183
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/sparsebit.c
@@ -0,0 +1,2087 @@
1/*
2 * Sparse bit array
3 *
4 * Copyright (C) 2018, Google LLC.
5 * Copyright (C) 2018, Red Hat, Inc. (code style cleanup and fuzzing driver)
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2.
8 *
9 * This library provides functions to support a memory efficient bit array,
10 * with an index size of 2^64. A sparsebit array is allocated through
11 * the use sparsebit_alloc() and free'd via sparsebit_free(),
12 * such as in the following:
13 *
14 * struct sparsebit *s;
15 * s = sparsebit_alloc();
16 * sparsebit_free(&s);
17 *
18 * The struct sparsebit type resolves down to a struct sparsebit.
19 * Note that, sparsebit_free() takes a pointer to the sparsebit
20 * structure. This is so that sparsebit_free() is able to poison
21 * the pointer (e.g. set it to NULL) to the struct sparsebit before
22 * returning to the caller.
23 *
24 * Between the return of sparsebit_alloc() and the call of
25 * sparsebit_free(), there are multiple query and modifying operations
26 * that can be performed on the allocated sparsebit array. All of
27 * these operations take as a parameter the value returned from
28 * sparsebit_alloc() and most also take a bit index. Frequently
29 * used routines include:
30 *
31 * ---- Query Operations
32 * sparsebit_is_set(s, idx)
33 * sparsebit_is_clear(s, idx)
34 * sparsebit_any_set(s)
35 * sparsebit_first_set(s)
36 * sparsebit_next_set(s, prev_idx)
37 *
38 * ---- Modifying Operations
39 * sparsebit_set(s, idx)
40 * sparsebit_clear(s, idx)
41 * sparsebit_set_num(s, idx, num);
42 * sparsebit_clear_num(s, idx, num);
43 *
44 * A common operation, is to itterate over all the bits set in a test
45 * sparsebit array. This can be done via code with the following structure:
46 *
47 * sparsebit_idx_t idx;
48 * if (sparsebit_any_set(s)) {
49 * idx = sparsebit_first_set(s);
50 * do {
51 * ...
52 * idx = sparsebit_next_set(s, idx);
53 * } while (idx != 0);
54 * }
55 *
56 * The index of the first bit set needs to be obtained via
57 * sparsebit_first_set(), because sparsebit_next_set(), needs
58 * the index of the previously set. The sparsebit_idx_t type is
59 * unsigned, so there is no previous index before 0 that is available.
60 * Also, the call to sparsebit_first_set() is not made unless there
61 * is at least 1 bit in the array set. This is because sparsebit_first_set()
62 * aborts if sparsebit_first_set() is called with no bits set.
63 * It is the callers responsibility to assure that the
64 * sparsebit array has at least a single bit set before calling
65 * sparsebit_first_set().
66 *
67 * ==== Implementation Overview ====
68 * For the most part the internal implementation of sparsebit is
69 * opaque to the caller. One important implementation detail that the
70 * caller may need to be aware of is the spatial complexity of the
71 * implementation. This implementation of a sparsebit array is not
72 * only sparse, in that it uses memory proportional to the number of bits
73 * set. It is also efficient in memory usage when most of the bits are
74 * set.
75 *
76 * At a high-level the state of the bit settings are maintained through
77 * the use of a binary-search tree, where each node contains at least
78 * the following members:
79 *
80 * typedef uint64_t sparsebit_idx_t;
81 * typedef uint64_t sparsebit_num_t;
82 *
83 * sparsebit_idx_t idx;
84 * uint32_t mask;
85 * sparsebit_num_t num_after;
86 *
87 * The idx member contains the bit index of the first bit described by this
88 * node, while the mask member stores the setting of the first 32-bits.
89 * The setting of the bit at idx + n, where 0 <= n < 32, is located in the
90 * mask member at 1 << n.
91 *
92 * Nodes are sorted by idx and the bits described by two nodes will never
93 * overlap. The idx member is always aligned to the mask size, i.e. a
94 * multiple of 32.
95 *
96 * Beyond a typical implementation, the nodes in this implementation also
97 * contains a member named num_after. The num_after member holds the
98 * number of bits immediately after the mask bits that are contiguously set.
99 * The use of the num_after member allows this implementation to efficiently
100 * represent cases where most bits are set. For example, the case of all
101 * but the last two bits set, is represented by the following two nodes:
102 *
103 * node 0 - idx: 0x0 mask: 0xffffffff num_after: 0xffffffffffffffc0
104 * node 1 - idx: 0xffffffffffffffe0 mask: 0x3fffffff num_after: 0
105 *
106 * ==== Invariants ====
107 * This implementation usses the following invariants:
108 *
109 * + Node are only used to represent bits that are set.
110 * Nodes with a mask of 0 and num_after of 0 are not allowed.
111 *
112 * + Sum of bits set in all the nodes is equal to the value of
113 * the struct sparsebit_pvt num_set member.
114 *
115 * + The setting of at least one bit is always described in a nodes
116 * mask (mask >= 1).
117 *
118 * + A node with all mask bits set only occurs when the last bit
119 * described by the previous node is not equal to this nodes
120 * starting index - 1. All such occurences of this condition are
121 * avoided by moving the setting of the nodes mask bits into
122 * the previous nodes num_after setting.
123 *
124 * + Node starting index is evenly divisible by the number of bits
125 * within a nodes mask member.
126 *
127 * + Nodes never represent a range of bits that wrap around the
128 * highest supported index.
129 *
130 * (idx + MASK_BITS + num_after - 1) <= ((sparsebit_idx_t) 0) - 1)
131 *
132 * As a consequence of the above, the num_after member of a node
133 * will always be <=:
134 *
135 * maximum_index - nodes_starting_index - number_of_mask_bits
136 *
137 * + Nodes within the binary search tree are sorted based on each
138 * nodes starting index.
139 *
140 * + The range of bits described by any two nodes do not overlap. The
141 * range of bits described by a single node is:
142 *
143 * start: node->idx
144 * end (inclusive): node->idx + MASK_BITS + node->num_after - 1;
145 *
146 * Note, at times these invariants are temporarily violated for a
147 * specific portion of the code. For example, when setting a mask
148 * bit, there is a small delay between when the mask bit is set and the
149 * value in the struct sparsebit_pvt num_set member is updated. Other
150 * temporary violations occur when node_split() is called with a specified
151 * index and assures that a node where its mask represents the bit
152 * at the specified index exists. At times to do this node_split()
153 * must split an existing node into two nodes or create a node that
154 * has no bits set. Such temporary violations must be corrected before
155 * returning to the caller. These corrections are typically performed
156 * by the local function node_reduce().
157 */
158
159#include "test_util.h"
160#include "sparsebit.h"
161#include <limits.h>
162#include <assert.h>
163
164#define DUMP_LINE_MAX 100 /* Does not include indent amount */
165
166typedef uint32_t mask_t;
167#define MASK_BITS (sizeof(mask_t) * CHAR_BIT)
168
169struct node {
170 struct node *parent;
171 struct node *left;
172 struct node *right;
173 sparsebit_idx_t idx; /* index of least-significant bit in mask */
174 sparsebit_num_t num_after; /* num contiguously set after mask */
175 mask_t mask;
176};
177
178struct sparsebit {
179 /*
180 * Points to root node of the binary search
181 * tree. Equal to NULL when no bits are set in
182 * the entire sparsebit array.
183 */
184 struct node *root;
185
186 /*
187 * A redundant count of the total number of bits set. Used for
188 * diagnostic purposes and to change the time complexity of
189 * sparsebit_num_set() from O(n) to O(1).
190 * Note: Due to overflow, a value of 0 means none or all set.
191 */
192 sparsebit_num_t num_set;
193};
194
195/* Returns the number of set bits described by the settings
196 * of the node pointed to by nodep.
197 */
198static sparsebit_num_t node_num_set(struct node *nodep)
199{
200 return nodep->num_after + __builtin_popcount(nodep->mask);
201}
202
203/* Returns a pointer to the node that describes the
204 * lowest bit index.
205 */
206static struct node *node_first(struct sparsebit *s)
207{
208 struct node *nodep;
209
210 for (nodep = s->root; nodep && nodep->left; nodep = nodep->left)
211 ;
212
213 return nodep;
214}
215
216/* Returns a pointer to the node that describes the
217 * lowest bit index > the index of the node pointed to by np.
218 * Returns NULL if no node with a higher index exists.
219 */
220static struct node *node_next(struct sparsebit *s, struct node *np)
221{
222 struct node *nodep = np;
223
224 /*
225 * If current node has a right child, next node is the left-most
226 * of the right child.
227 */
228 if (nodep->right) {
229 for (nodep = nodep->right; nodep->left; nodep = nodep->left)
230 ;
231 return nodep;
232 }
233
234 /*
235 * No right child. Go up until node is left child of a parent.
236 * That parent is then the next node.
237 */
238 while (nodep->parent && nodep == nodep->parent->right)
239 nodep = nodep->parent;
240
241 return nodep->parent;
242}
243
244/* Searches for and returns a pointer to the node that describes the
245 * highest index < the index of the node pointed to by np.
246 * Returns NULL if no node with a lower index exists.
247 */
248static struct node *node_prev(struct sparsebit *s, struct node *np)
249{
250 struct node *nodep = np;
251
252 /*
253 * If current node has a left child, next node is the right-most
254 * of the left child.
255 */
256 if (nodep->left) {
257 for (nodep = nodep->left; nodep->right; nodep = nodep->right)
258 ;
259 return (struct node *) nodep;
260 }
261
262 /*
263 * No left child. Go up until node is right child of a parent.
264 * That parent is then the next node.
265 */
266 while (nodep->parent && nodep == nodep->parent->left)
267 nodep = nodep->parent;
268
269 return (struct node *) nodep->parent;
270}
271
272
273/* Allocates space to hold a copy of the node sub-tree pointed to by
274 * subtree and duplicates the bit settings to the newly allocated nodes.
275 * Returns the newly allocated copy of subtree.
276 */
277static struct node *node_copy_subtree(struct node *subtree)
278{
279 struct node *root;
280
281 /* Duplicate the node at the root of the subtree */
282 root = calloc(1, sizeof(*root));
283 if (!root) {
284 perror("calloc");
285 abort();
286 }
287
288 root->idx = subtree->idx;
289 root->mask = subtree->mask;
290 root->num_after = subtree->num_after;
291
292 /* As needed, recursively duplicate the left and right subtrees */
293 if (subtree->left) {
294 root->left = node_copy_subtree(subtree->left);
295 root->left->parent = root;
296 }
297
298 if (subtree->right) {
299 root->right = node_copy_subtree(subtree->right);
300 root->right->parent = root;
301 }
302
303 return root;
304}
305
306/* Searches for and returns a pointer to the node that describes the setting
307 * of the bit given by idx. A node describes the setting of a bit if its
308 * index is within the bits described by the mask bits or the number of
309 * contiguous bits set after the mask. Returns NULL if there is no such node.
310 */
311static struct node *node_find(struct sparsebit *s, sparsebit_idx_t idx)
312{
313 struct node *nodep;
314
315 /* Find the node that describes the setting of the bit at idx */
316 for (nodep = s->root; nodep;
317 nodep = nodep->idx > idx ? nodep->left : nodep->right) {
318 if (idx >= nodep->idx &&
319 idx <= nodep->idx + MASK_BITS + nodep->num_after - 1)
320 break;
321 }
322
323 return nodep;
324}
325
326/* Entry Requirements:
327 * + A node that describes the setting of idx is not already present.
328 *
329 * Adds a new node to describe the setting of the bit at the index given
330 * by idx. Returns a pointer to the newly added node.
331 *
332 * TODO(lhuemill): Degenerate cases causes the tree to get unbalanced.
333 */
334static struct node *node_add(struct sparsebit *s, sparsebit_idx_t idx)
335{
336 struct node *nodep, *parentp, *prev;
337
338 /* Allocate and initialize the new node. */
339 nodep = calloc(1, sizeof(*nodep));
340 if (!nodep) {
341 perror("calloc");
342 abort();
343 }
344
345 nodep->idx = idx & -MASK_BITS;
346
347 /* If no nodes, set it up as the root node. */
348 if (!s->root) {
349 s->root = nodep;
350 return nodep;
351 }
352
353 /*
354 * Find the parent where the new node should be attached
355 * and add the node there.
356 */
357 parentp = s->root;
358 while (true) {
359 if (idx < parentp->idx) {
360 if (!parentp->left) {
361 parentp->left = nodep;
362 nodep->parent = parentp;
363 break;
364 }
365 parentp = parentp->left;
366 } else {
367 assert(idx > parentp->idx + MASK_BITS + parentp->num_after - 1);
368 if (!parentp->right) {
369 parentp->right = nodep;
370 nodep->parent = parentp;
371 break;
372 }
373 parentp = parentp->right;
374 }
375 }
376
377 /*
378 * Does num_after bits of previous node overlap with the mask
379 * of the new node? If so set the bits in the new nodes mask
380 * and reduce the previous nodes num_after.
381 */
382 prev = node_prev(s, nodep);
383 while (prev && prev->idx + MASK_BITS + prev->num_after - 1 >= nodep->idx) {
384 unsigned int n1 = (prev->idx + MASK_BITS + prev->num_after - 1)
385 - nodep->idx;
386 assert(prev->num_after > 0);
387 assert(n1 < MASK_BITS);
388 assert(!(nodep->mask & (1 << n1)));
389 nodep->mask |= (1 << n1);
390 prev->num_after--;
391 }
392
393 return nodep;
394}
395
396/* Returns whether all the bits in the sparsebit array are set. */
397bool sparsebit_all_set(struct sparsebit *s)
398{
399 /*
400 * If any nodes there must be at least one bit set. Only case
401 * where a bit is set and total num set is 0, is when all bits
402 * are set.
403 */
404 return s->root && s->num_set == 0;
405}
406
407/* Clears all bits described by the node pointed to by nodep, then
408 * removes the node.
409 */
410static void node_rm(struct sparsebit *s, struct node *nodep)
411{
412 struct node *tmp;
413 sparsebit_num_t num_set;
414
415 num_set = node_num_set(nodep);
416 assert(s->num_set >= num_set || sparsebit_all_set(s));
417 s->num_set -= node_num_set(nodep);
418
419 /* Have both left and right child */
420 if (nodep->left && nodep->right) {
421 /*
422 * Move left children to the leftmost leaf node
423 * of the right child.
424 */
425 for (tmp = nodep->right; tmp->left; tmp = tmp->left)
426 ;
427 tmp->left = nodep->left;
428 nodep->left = NULL;
429 tmp->left->parent = tmp;
430 }
431
432 /* Left only child */
433 if (nodep->left) {
434 if (!nodep->parent) {
435 s->root = nodep->left;
436 nodep->left->parent = NULL;
437 } else {
438 nodep->left->parent = nodep->parent;
439 if (nodep == nodep->parent->left)
440 nodep->parent->left = nodep->left;
441 else {
442 assert(nodep == nodep->parent->right);
443 nodep->parent->right = nodep->left;
444 }
445 }
446
447 nodep->parent = nodep->left = nodep->right = NULL;
448 free(nodep);
449
450 return;
451 }
452
453
454 /* Right only child */
455 if (nodep->right) {
456 if (!nodep->parent) {
457 s->root = nodep->right;
458 nodep->right->parent = NULL;
459 } else {
460 nodep->right->parent = nodep->parent;
461 if (nodep == nodep->parent->left)
462 nodep->parent->left = nodep->right;
463 else {
464 assert(nodep == nodep->parent->right);
465 nodep->parent->right = nodep->right;
466 }
467 }
468
469 nodep->parent = nodep->left = nodep->right = NULL;
470 free(nodep);
471
472 return;
473 }
474
475 /* Leaf Node */
476 if (!nodep->parent) {
477 s->root = NULL;
478 } else {
479 if (nodep->parent->left == nodep)
480 nodep->parent->left = NULL;
481 else {
482 assert(nodep == nodep->parent->right);
483 nodep->parent->right = NULL;
484 }
485 }
486
487 nodep->parent = nodep->left = nodep->right = NULL;
488 free(nodep);
489
490 return;
491}
492
493/* Splits the node containing the bit at idx so that there is a node
494 * that starts at the specified index. If no such node exists, a new
495 * node at the specified index is created. Returns the new node.
496 *
497 * idx must start of a mask boundary.
498 */
499static struct node *node_split(struct sparsebit *s, sparsebit_idx_t idx)
500{
501 struct node *nodep1, *nodep2;
502 sparsebit_idx_t offset;
503 sparsebit_num_t orig_num_after;
504
505 assert(!(idx % MASK_BITS));
506
507 /*
508 * Is there a node that describes the setting of idx?
509 * If not, add it.
510 */
511 nodep1 = node_find(s, idx);
512 if (!nodep1)
513 return node_add(s, idx);
514
515 /*
516 * All done if the starting index of the node is where the
517 * split should occur.
518 */
519 if (nodep1->idx == idx)
520 return nodep1;
521
522 /*
523 * Split point not at start of mask, so it must be part of
524 * bits described by num_after.
525 */
526
527 /*
528 * Calculate offset within num_after for where the split is
529 * to occur.
530 */
531 offset = idx - (nodep1->idx + MASK_BITS);
532 orig_num_after = nodep1->num_after;
533
534 /*
535 * Add a new node to describe the bits starting at
536 * the split point.
537 */
538 nodep1->num_after = offset;
539 nodep2 = node_add(s, idx);
540
541 /* Move bits after the split point into the new node */
542 nodep2->num_after = orig_num_after - offset;
543 if (nodep2->num_after >= MASK_BITS) {
544 nodep2->mask = ~(mask_t) 0;
545 nodep2->num_after -= MASK_BITS;
546 } else {
547 nodep2->mask = (1 << nodep2->num_after) - 1;
548 nodep2->num_after = 0;
549 }
550
551 return nodep2;
552}
553
554/* Iteratively reduces the node pointed to by nodep and its adjacent
555 * nodes into a more compact form. For example, a node with a mask with
556 * all bits set adjacent to a previous node, will get combined into a
557 * single node with an increased num_after setting.
558 *
559 * After each reduction, a further check is made to see if additional
560 * reductions are possible with the new previous and next nodes. Note,
561 * a search for a reduction is only done across the nodes nearest nodep
562 * and those that became part of a reduction. Reductions beyond nodep
563 * and the adjacent nodes that are reduced are not discovered. It is the
564 * responsibility of the caller to pass a nodep that is within one node
565 * of each possible reduction.
566 *
567 * This function does not fix the temporary violation of all invariants.
568 * For example it does not fix the case where the bit settings described
569 * by two or more nodes overlap. Such a violation introduces the potential
570 * complication of a bit setting for a specific index having different settings
571 * in different nodes. This would then introduce the further complication
572 * of which node has the correct setting of the bit and thus such conditions
573 * are not allowed.
574 *
575 * This function is designed to fix invariant violations that are introduced
576 * by node_split() and by changes to the nodes mask or num_after members.
577 * For example, when setting a bit within a nodes mask, the function that
578 * sets the bit doesn't have to worry about whether the setting of that
579 * bit caused the mask to have leading only or trailing only bits set.
580 * Instead, the function can call node_reduce(), with nodep equal to the
581 * node address that it set a mask bit in, and node_reduce() will notice
582 * the cases of leading or trailing only bits and that there is an
583 * adjacent node that the bit settings could be merged into.
584 *
585 * This implementation specifically detects and corrects violation of the
586 * following invariants:
587 *
588 * + Node are only used to represent bits that are set.
589 * Nodes with a mask of 0 and num_after of 0 are not allowed.
590 *
591 * + The setting of at least one bit is always described in a nodes
592 * mask (mask >= 1).
593 *
594 * + A node with all mask bits set only occurs when the last bit
595 * described by the previous node is not equal to this nodes
596 * starting index - 1. All such occurences of this condition are
597 * avoided by moving the setting of the nodes mask bits into
598 * the previous nodes num_after setting.
599 */
600static void node_reduce(struct sparsebit *s, struct node *nodep)
601{
602 bool reduction_performed;
603
604 do {
605 reduction_performed = false;
606 struct node *prev, *next, *tmp;
607
608 /* 1) Potential reductions within the current node. */
609
610 /* Nodes with all bits cleared may be removed. */
611 if (nodep->mask == 0 && nodep->num_after == 0) {
612 /*
613 * About to remove the node pointed to by
614 * nodep, which normally would cause a problem
615 * for the next pass through the reduction loop,
616 * because the node at the starting point no longer
617 * exists. This potential problem is handled
618 * by first remembering the location of the next
619 * or previous nodes. Doesn't matter which, because
620 * once the node at nodep is removed, there will be
621 * no other nodes between prev and next.
622 *
623 * Note, the checks performed on nodep against both
624 * both prev and next both check for an adjacent
625 * node that can be reduced into a single node. As
626 * such, after removing the node at nodep, doesn't
627 * matter whether the nodep for the next pass
628 * through the loop is equal to the previous pass
629 * prev or next node. Either way, on the next pass
630 * the one not selected will become either the
631 * prev or next node.
632 */
633 tmp = node_next(s, nodep);
634 if (!tmp)
635 tmp = node_prev(s, nodep);
636
637 node_rm(s, nodep);
638 nodep = NULL;
639
640 nodep = tmp;
641 reduction_performed = true;
642 continue;
643 }
644
645 /*
646 * When the mask is 0, can reduce the amount of num_after
647 * bits by moving the initial num_after bits into the mask.
648 */
649 if (nodep->mask == 0) {
650 assert(nodep->num_after != 0);
651 assert(nodep->idx + MASK_BITS > nodep->idx);
652
653 nodep->idx += MASK_BITS;
654
655 if (nodep->num_after >= MASK_BITS) {
656 nodep->mask = ~0;
657 nodep->num_after -= MASK_BITS;
658 } else {
659 nodep->mask = (1u << nodep->num_after) - 1;
660 nodep->num_after = 0;
661 }
662
663 reduction_performed = true;
664 continue;
665 }
666
667 /*
668 * 2) Potential reductions between the current and
669 * previous nodes.
670 */
671 prev = node_prev(s, nodep);
672 if (prev) {
673 sparsebit_idx_t prev_highest_bit;
674
675 /* Nodes with no bits set can be removed. */
676 if (prev->mask == 0 && prev->num_after == 0) {
677 node_rm(s, prev);
678
679 reduction_performed = true;
680 continue;
681 }
682
683 /*
684 * All mask bits set and previous node has
685 * adjacent index.
686 */
687 if (nodep->mask + 1 == 0 &&
688 prev->idx + MASK_BITS == nodep->idx) {
689 prev->num_after += MASK_BITS + nodep->num_after;
690 nodep->mask = 0;
691 nodep->num_after = 0;
692
693 reduction_performed = true;
694 continue;
695 }
696
697 /*
698 * Is node adjacent to previous node and the node
699 * contains a single contiguous range of bits
700 * starting from the beginning of the mask?
701 */
702 prev_highest_bit = prev->idx + MASK_BITS - 1 + prev->num_after;
703 if (prev_highest_bit + 1 == nodep->idx &&
704 (nodep->mask | (nodep->mask >> 1)) == nodep->mask) {
705 /*
706 * How many contiguous bits are there?
707 * Is equal to the total number of set
708 * bits, due to an earlier check that
709 * there is a single contiguous range of
710 * set bits.
711 */
712 unsigned int num_contiguous
713 = __builtin_popcount(nodep->mask);
714 assert((num_contiguous > 0) &&
715 ((1ULL << num_contiguous) - 1) == nodep->mask);
716
717 prev->num_after += num_contiguous;
718 nodep->mask = 0;
719
720 /*
721 * For predictable performance, handle special
722 * case where all mask bits are set and there
723 * is a non-zero num_after setting. This code
724 * is functionally correct without the following
725 * conditionalized statements, but without them
726 * the value of num_after is only reduced by
727 * the number of mask bits per pass. There are
728 * cases where num_after can be close to 2^64.
729 * Without this code it could take nearly
730 * (2^64) / 32 passes to perform the full
731 * reduction.
732 */
733 if (num_contiguous == MASK_BITS) {
734 prev->num_after += nodep->num_after;
735 nodep->num_after = 0;
736 }
737
738 reduction_performed = true;
739 continue;
740 }
741 }
742
743 /*
744 * 3) Potential reductions between the current and
745 * next nodes.
746 */
747 next = node_next(s, nodep);
748 if (next) {
749 /* Nodes with no bits set can be removed. */
750 if (next->mask == 0 && next->num_after == 0) {
751 node_rm(s, next);
752 reduction_performed = true;
753 continue;
754 }
755
756 /*
757 * Is next node index adjacent to current node
758 * and has a mask with all bits set?
759 */
760 if (next->idx == nodep->idx + MASK_BITS + nodep->num_after &&
761 next->mask == ~(mask_t) 0) {
762 nodep->num_after += MASK_BITS;
763 next->mask = 0;
764 nodep->num_after += next->num_after;
765 next->num_after = 0;
766
767 node_rm(s, next);
768 next = NULL;
769
770 reduction_performed = true;
771 continue;
772 }
773 }
774 } while (nodep && reduction_performed);
775}
776
777/* Returns whether the bit at the index given by idx, within the
778 * sparsebit array is set or not.
779 */
780bool sparsebit_is_set(struct sparsebit *s, sparsebit_idx_t idx)
781{
782 struct node *nodep;
783
784 /* Find the node that describes the setting of the bit at idx */
785 for (nodep = s->root; nodep;
786 nodep = nodep->idx > idx ? nodep->left : nodep->right)
787 if (idx >= nodep->idx &&
788 idx <= nodep->idx + MASK_BITS + nodep->num_after - 1)
789 goto have_node;
790
791 return false;
792
793have_node:
794 /* Bit is set if it is any of the bits described by num_after */
795 if (nodep->num_after && idx >= nodep->idx + MASK_BITS)
796 return true;
797
798 /* Is the corresponding mask bit set */
799 assert(idx >= nodep->idx && idx - nodep->idx < MASK_BITS);
800 return !!(nodep->mask & (1 << (idx - nodep->idx)));
801}
802
803/* Within the sparsebit array pointed to by s, sets the bit
804 * at the index given by idx.
805 */
806static void bit_set(struct sparsebit *s, sparsebit_idx_t idx)
807{
808 struct node *nodep;
809
810 /* Skip bits that are already set */
811 if (sparsebit_is_set(s, idx))
812 return;
813
814 /*
815 * Get a node where the bit at idx is described by the mask.
816 * The node_split will also create a node, if there isn't
817 * already a node that describes the setting of bit.
818 */
819 nodep = node_split(s, idx & -MASK_BITS);
820
821 /* Set the bit within the nodes mask */
822 assert(idx >= nodep->idx && idx <= nodep->idx + MASK_BITS - 1);
823 assert(!(nodep->mask & (1 << (idx - nodep->idx))));
824 nodep->mask |= 1 << (idx - nodep->idx);
825 s->num_set++;
826
827 node_reduce(s, nodep);
828}
829
830/* Within the sparsebit array pointed to by s, clears the bit
831 * at the index given by idx.
832 */
833static void bit_clear(struct sparsebit *s, sparsebit_idx_t idx)
834{
835 struct node *nodep;
836
837 /* Skip bits that are already cleared */
838 if (!sparsebit_is_set(s, idx))
839 return;
840
841 /* Is there a node that describes the setting of this bit? */
842 nodep = node_find(s, idx);
843 if (!nodep)
844 return;
845
846 /*
847 * If a num_after bit, split the node, so that the bit is
848 * part of a node mask.
849 */
850 if (idx >= nodep->idx + MASK_BITS)
851 nodep = node_split(s, idx & -MASK_BITS);
852
853 /*
854 * After node_split above, bit at idx should be within the mask.
855 * Clear that bit.
856 */
857 assert(idx >= nodep->idx && idx <= nodep->idx + MASK_BITS - 1);
858 assert(nodep->mask & (1 << (idx - nodep->idx)));
859 nodep->mask &= ~(1 << (idx - nodep->idx));
860 assert(s->num_set > 0 || sparsebit_all_set(s));
861 s->num_set--;
862
863 node_reduce(s, nodep);
864}
865
866/* Recursively dumps to the FILE stream given by stream the contents
867 * of the sub-tree of nodes pointed to by nodep. Each line of output
868 * is prefixed by the number of spaces given by indent. On each
869 * recursion, the indent amount is increased by 2. This causes nodes
870 * at each level deeper into the binary search tree to be displayed
871 * with a greater indent.
872 */
873static void dump_nodes(FILE *stream, struct node *nodep,
874 unsigned int indent)
875{
876 char *node_type;
877
878 /* Dump contents of node */
879 if (!nodep->parent)
880 node_type = "root";
881 else if (nodep == nodep->parent->left)
882 node_type = "left";
883 else {
884 assert(nodep == nodep->parent->right);
885 node_type = "right";
886 }
887 fprintf(stream, "%*s---- %s nodep: %p\n", indent, "", node_type, nodep);
888 fprintf(stream, "%*s parent: %p left: %p right: %p\n", indent, "",
889 nodep->parent, nodep->left, nodep->right);
890 fprintf(stream, "%*s idx: 0x%lx mask: 0x%x num_after: 0x%lx\n",
891 indent, "", nodep->idx, nodep->mask, nodep->num_after);
892
893 /* If present, dump contents of left child nodes */
894 if (nodep->left)
895 dump_nodes(stream, nodep->left, indent + 2);
896
897 /* If present, dump contents of right child nodes */
898 if (nodep->right)
899 dump_nodes(stream, nodep->right, indent + 2);
900}
901
902static inline sparsebit_idx_t node_first_set(struct node *nodep, int start)
903{
904 mask_t leading = (mask_t)1 << start;
905 int n1 = __builtin_ctz(nodep->mask & -leading);
906
907 return nodep->idx + n1;
908}
909
910static inline sparsebit_idx_t node_first_clear(struct node *nodep, int start)
911{
912 mask_t leading = (mask_t)1 << start;
913 int n1 = __builtin_ctz(~nodep->mask & -leading);
914
915 return nodep->idx + n1;
916}
917
918/* Dumps to the FILE stream specified by stream, the implementation dependent
919 * internal state of s. Each line of output is prefixed with the number
920 * of spaces given by indent. The output is completely implementation
921 * dependent and subject to change. Output from this function should only
922 * be used for diagnostic purposes. For example, this function can be
923 * used by test cases after they detect an unexpected condition, as a means
924 * to capture diagnostic information.
925 */
926static void sparsebit_dump_internal(FILE *stream, struct sparsebit *s,
927 unsigned int indent)
928{
929 /* Dump the contents of s */
930 fprintf(stream, "%*sroot: %p\n", indent, "", s->root);
931 fprintf(stream, "%*snum_set: 0x%lx\n", indent, "", s->num_set);
932
933 if (s->root)
934 dump_nodes(stream, s->root, indent);
935}
936
937/* Allocates and returns a new sparsebit array. The initial state
938 * of the newly allocated sparsebit array has all bits cleared.
939 */
940struct sparsebit *sparsebit_alloc(void)
941{
942 struct sparsebit *s;
943
944 /* Allocate top level structure. */
945 s = calloc(1, sizeof(*s));
946 if (!s) {
947 perror("calloc");
948 abort();
949 }
950
951 return s;
952}
953
954/* Frees the implementation dependent data for the sparsebit array
955 * pointed to by s and poisons the pointer to that data.
956 */
957void sparsebit_free(struct sparsebit **sbitp)
958{
959 struct sparsebit *s = *sbitp;
960
961 if (!s)
962 return;
963
964 sparsebit_clear_all(s);
965 free(s);
966 *sbitp = NULL;
967}
968
969/* Makes a copy of the sparsebit array given by s, to the sparsebit
970 * array given by d. Note, d must have already been allocated via
971 * sparsebit_alloc(). It can though already have bits set, which
972 * if different from src will be cleared.
973 */
974void sparsebit_copy(struct sparsebit *d, struct sparsebit *s)
975{
976 /* First clear any bits already set in the destination */
977 sparsebit_clear_all(d);
978
979 if (s->root) {
980 d->root = node_copy_subtree(s->root);
981 d->num_set = s->num_set;
982 }
983}
984
985/* Returns whether num consecutive bits starting at idx are all set. */
986bool sparsebit_is_set_num(struct sparsebit *s,
987 sparsebit_idx_t idx, sparsebit_num_t num)
988{
989 sparsebit_idx_t next_cleared;
990
991 assert(num > 0);
992 assert(idx + num - 1 >= idx);
993
994 /* With num > 0, the first bit must be set. */
995 if (!sparsebit_is_set(s, idx))
996 return false;
997
998 /* Find the next cleared bit */
999 next_cleared = sparsebit_next_clear(s, idx);
1000
1001 /*
1002 * If no cleared bits beyond idx, then there are at least num
1003 * set bits. idx + num doesn't wrap. Otherwise check if
1004 * there are enough set bits between idx and the next cleared bit.
1005 */
1006 return next_cleared == 0 || next_cleared - idx >= num;
1007}
1008
1009/* Returns whether the bit at the index given by idx. */
1010bool sparsebit_is_clear(struct sparsebit *s,
1011 sparsebit_idx_t idx)
1012{
1013 return !sparsebit_is_set(s, idx);
1014}
1015
1016/* Returns whether num consecutive bits starting at idx are all cleared. */
1017bool sparsebit_is_clear_num(struct sparsebit *s,
1018 sparsebit_idx_t idx, sparsebit_num_t num)
1019{
1020 sparsebit_idx_t next_set;
1021
1022 assert(num > 0);
1023 assert(idx + num - 1 >= idx);
1024
1025 /* With num > 0, the first bit must be cleared. */
1026 if (!sparsebit_is_clear(s, idx))
1027 return false;
1028
1029 /* Find the next set bit */
1030 next_set = sparsebit_next_set(s, idx);
1031
1032 /*
1033 * If no set bits beyond idx, then there are at least num
1034 * cleared bits. idx + num doesn't wrap. Otherwise check if
1035 * there are enough cleared bits between idx and the next set bit.
1036 */
1037 return next_set == 0 || next_set - idx >= num;
1038}
1039
1040/* Returns the total number of bits set. Note: 0 is also returned for
1041 * the case of all bits set. This is because with all bits set, there
1042 * is 1 additional bit set beyond what can be represented in the return
1043 * value. Use sparsebit_any_set(), instead of sparsebit_num_set() > 0,
1044 * to determine if the sparsebit array has any bits set.
1045 */
1046sparsebit_num_t sparsebit_num_set(struct sparsebit *s)
1047{
1048 return s->num_set;
1049}
1050
1051/* Returns whether any bit is set in the sparsebit array. */
1052bool sparsebit_any_set(struct sparsebit *s)
1053{
1054 /*
1055 * Nodes only describe set bits. If any nodes then there
1056 * is at least 1 bit set.
1057 */
1058 if (!s->root)
1059 return false;
1060
1061 /*
1062 * Every node should have a non-zero mask. For now will
1063 * just assure that the root node has a non-zero mask,
1064 * which is a quick check that at least 1 bit is set.
1065 */
1066 assert(s->root->mask != 0);
1067 assert(s->num_set > 0 ||
1068 (s->root->num_after == ((sparsebit_num_t) 0) - MASK_BITS &&
1069 s->root->mask == ~(mask_t) 0));
1070
1071 return true;
1072}
1073
1074/* Returns whether all the bits in the sparsebit array are cleared. */
1075bool sparsebit_all_clear(struct sparsebit *s)
1076{
1077 return !sparsebit_any_set(s);
1078}
1079
1080/* Returns whether all the bits in the sparsebit array are set. */
1081bool sparsebit_any_clear(struct sparsebit *s)
1082{
1083 return !sparsebit_all_set(s);
1084}
1085
1086/* Returns the index of the first set bit. Abort if no bits are set.
1087 */
1088sparsebit_idx_t sparsebit_first_set(struct sparsebit *s)
1089{
1090 struct node *nodep;
1091
1092 /* Validate at least 1 bit is set */
1093 assert(sparsebit_any_set(s));
1094
1095 nodep = node_first(s);
1096 return node_first_set(nodep, 0);
1097}
1098
1099/* Returns the index of the first cleared bit. Abort if
1100 * no bits are cleared.
1101 */
1102sparsebit_idx_t sparsebit_first_clear(struct sparsebit *s)
1103{
1104 struct node *nodep1, *nodep2;
1105
1106 /* Validate at least 1 bit is cleared. */
1107 assert(sparsebit_any_clear(s));
1108
1109 /* If no nodes or first node index > 0 then lowest cleared is 0 */
1110 nodep1 = node_first(s);
1111 if (!nodep1 || nodep1->idx > 0)
1112 return 0;
1113
1114 /* Does the mask in the first node contain any cleared bits. */
1115 if (nodep1->mask != ~(mask_t) 0)
1116 return node_first_clear(nodep1, 0);
1117
1118 /*
1119 * All mask bits set in first node. If there isn't a second node
1120 * then the first cleared bit is the first bit after the bits
1121 * described by the first node.
1122 */
1123 nodep2 = node_next(s, nodep1);
1124 if (!nodep2) {
1125 /*
1126 * No second node. First cleared bit is first bit beyond
1127 * bits described by first node.
1128 */
1129 assert(nodep1->mask == ~(mask_t) 0);
1130 assert(nodep1->idx + MASK_BITS + nodep1->num_after != (sparsebit_idx_t) 0);
1131 return nodep1->idx + MASK_BITS + nodep1->num_after;
1132 }
1133
1134 /*
1135 * There is a second node.
1136 * If it is not adjacent to the first node, then there is a gap
1137 * of cleared bits between the nodes, and the first cleared bit
1138 * is the first bit within the gap.
1139 */
1140 if (nodep1->idx + MASK_BITS + nodep1->num_after != nodep2->idx)
1141 return nodep1->idx + MASK_BITS + nodep1->num_after;
1142
1143 /*
1144 * Second node is adjacent to the first node.
1145 * Because it is adjacent, its mask should be non-zero. If all
1146 * its mask bits are set, then with it being adjacent, it should
1147 * have had the mask bits moved into the num_after setting of the
1148 * previous node.
1149 */
1150 return node_first_clear(nodep2, 0);
1151}
1152
1153/* Returns index of next bit set within s after the index given by prev.
1154 * Returns 0 if there are no bits after prev that are set.
1155 */
1156sparsebit_idx_t sparsebit_next_set(struct sparsebit *s,
1157 sparsebit_idx_t prev)
1158{
1159 sparsebit_idx_t lowest_possible = prev + 1;
1160 sparsebit_idx_t start;
1161 struct node *nodep;
1162
1163 /* A bit after the highest index can't be set. */
1164 if (lowest_possible == 0)
1165 return 0;
1166
1167 /*
1168 * Find the leftmost 'candidate' overlapping or to the right
1169 * of lowest_possible.
1170 */
1171 struct node *candidate = NULL;
1172
1173 /* True iff lowest_possible is within candidate */
1174 bool contains = false;
1175
1176 /*
1177 * Find node that describes setting of bit at lowest_possible.
1178 * If such a node doesn't exist, find the node with the lowest
1179 * starting index that is > lowest_possible.
1180 */
1181 for (nodep = s->root; nodep;) {
1182 if ((nodep->idx + MASK_BITS + nodep->num_after - 1)
1183 >= lowest_possible) {
1184 candidate = nodep;
1185 if (candidate->idx <= lowest_possible) {
1186 contains = true;
1187 break;
1188 }
1189 nodep = nodep->left;
1190 } else {
1191 nodep = nodep->right;
1192 }
1193 }
1194 if (!candidate)
1195 return 0;
1196
1197 assert(candidate->mask != 0);
1198
1199 /* Does the candidate node describe the setting of lowest_possible? */
1200 if (!contains) {
1201 /*
1202 * Candidate doesn't describe setting of bit at lowest_possible.
1203 * Candidate points to the first node with a starting index
1204 * > lowest_possible.
1205 */
1206 assert(candidate->idx > lowest_possible);
1207
1208 return node_first_set(candidate, 0);
1209 }
1210
1211 /*
1212 * Candidate describes setting of bit at lowest_possible.
1213 * Note: although the node describes the setting of the bit
1214 * at lowest_possible, its possible that its setting and the
1215 * setting of all latter bits described by this node are 0.
1216 * For now, just handle the cases where this node describes
1217 * a bit at or after an index of lowest_possible that is set.
1218 */
1219 start = lowest_possible - candidate->idx;
1220
1221 if (start < MASK_BITS && candidate->mask >= (1 << start))
1222 return node_first_set(candidate, start);
1223
1224 if (candidate->num_after) {
1225 sparsebit_idx_t first_num_after_idx = candidate->idx + MASK_BITS;
1226
1227 return lowest_possible < first_num_after_idx
1228 ? first_num_after_idx : lowest_possible;
1229 }
1230
1231 /*
1232 * Although candidate node describes setting of bit at
1233 * the index of lowest_possible, all bits at that index and
1234 * latter that are described by candidate are cleared. With
1235 * this, the next bit is the first bit in the next node, if
1236 * such a node exists. If a next node doesn't exist, then
1237 * there is no next set bit.
1238 */
1239 candidate = node_next(s, candidate);
1240 if (!candidate)
1241 return 0;
1242
1243 return node_first_set(candidate, 0);
1244}
1245
1246/* Returns index of next bit cleared within s after the index given by prev.
1247 * Returns 0 if there are no bits after prev that are cleared.
1248 */
1249sparsebit_idx_t sparsebit_next_clear(struct sparsebit *s,
1250 sparsebit_idx_t prev)
1251{
1252 sparsebit_idx_t lowest_possible = prev + 1;
1253 sparsebit_idx_t idx;
1254 struct node *nodep1, *nodep2;
1255
1256 /* A bit after the highest index can't be set. */
1257 if (lowest_possible == 0)
1258 return 0;
1259
1260 /*
1261 * Does a node describing the setting of lowest_possible exist?
1262 * If not, the bit at lowest_possible is cleared.
1263 */
1264 nodep1 = node_find(s, lowest_possible);
1265 if (!nodep1)
1266 return lowest_possible;
1267
1268 /* Does a mask bit in node 1 describe the next cleared bit. */
1269 for (idx = lowest_possible - nodep1->idx; idx < MASK_BITS; idx++)
1270 if (!(nodep1->mask & (1 << idx)))
1271 return nodep1->idx + idx;
1272
1273 /*
1274 * Next cleared bit is not described by node 1. If there
1275 * isn't a next node, then next cleared bit is described
1276 * by bit after the bits described by the first node.
1277 */
1278 nodep2 = node_next(s, nodep1);
1279 if (!nodep2)
1280 return nodep1->idx + MASK_BITS + nodep1->num_after;
1281
1282 /*
1283 * There is a second node.
1284 * If it is not adjacent to the first node, then there is a gap
1285 * of cleared bits between the nodes, and the next cleared bit
1286 * is the first bit within the gap.
1287 */
1288 if (nodep1->idx + MASK_BITS + nodep1->num_after != nodep2->idx)
1289 return nodep1->idx + MASK_BITS + nodep1->num_after;
1290
1291 /*
1292 * Second node is adjacent to the first node.
1293 * Because it is adjacent, its mask should be non-zero. If all
1294 * its mask bits are set, then with it being adjacent, it should
1295 * have had the mask bits moved into the num_after setting of the
1296 * previous node.
1297 */
1298 return node_first_clear(nodep2, 0);
1299}
1300
1301/* Starting with the index 1 greater than the index given by start, finds
1302 * and returns the index of the first sequence of num consecutively set
1303 * bits. Returns a value of 0 of no such sequence exists.
1304 */
1305sparsebit_idx_t sparsebit_next_set_num(struct sparsebit *s,
1306 sparsebit_idx_t start, sparsebit_num_t num)
1307{
1308 sparsebit_idx_t idx;
1309
1310 assert(num >= 1);
1311
1312 for (idx = sparsebit_next_set(s, start);
1313 idx != 0 && idx + num - 1 >= idx;
1314 idx = sparsebit_next_set(s, idx)) {
1315 assert(sparsebit_is_set(s, idx));
1316
1317 /*
1318 * Does the sequence of bits starting at idx consist of
1319 * num set bits?
1320 */
1321 if (sparsebit_is_set_num(s, idx, num))
1322 return idx;
1323
1324 /*
1325 * Sequence of set bits at idx isn't large enough.
1326 * Skip this entire sequence of set bits.
1327 */
1328 idx = sparsebit_next_clear(s, idx);
1329 if (idx == 0)
1330 return 0;
1331 }
1332
1333 return 0;
1334}
1335
1336/* Starting with the index 1 greater than the index given by start, finds
1337 * and returns the index of the first sequence of num consecutively cleared
1338 * bits. Returns a value of 0 of no such sequence exists.
1339 */
1340sparsebit_idx_t sparsebit_next_clear_num(struct sparsebit *s,
1341 sparsebit_idx_t start, sparsebit_num_t num)
1342{
1343 sparsebit_idx_t idx;
1344
1345 assert(num >= 1);
1346
1347 for (idx = sparsebit_next_clear(s, start);
1348 idx != 0 && idx + num - 1 >= idx;
1349 idx = sparsebit_next_clear(s, idx)) {
1350 assert(sparsebit_is_clear(s, idx));
1351
1352 /*
1353 * Does the sequence of bits starting at idx consist of
1354 * num cleared bits?
1355 */
1356 if (sparsebit_is_clear_num(s, idx, num))
1357 return idx;
1358
1359 /*
1360 * Sequence of cleared bits at idx isn't large enough.
1361 * Skip this entire sequence of cleared bits.
1362 */
1363 idx = sparsebit_next_set(s, idx);
1364 if (idx == 0)
1365 return 0;
1366 }
1367
1368 return 0;
1369}
1370
1371/* Sets the bits * in the inclusive range idx through idx + num - 1. */
1372void sparsebit_set_num(struct sparsebit *s,
1373 sparsebit_idx_t start, sparsebit_num_t num)
1374{
1375 struct node *nodep, *next;
1376 unsigned int n1;
1377 sparsebit_idx_t idx;
1378 sparsebit_num_t n;
1379 sparsebit_idx_t middle_start, middle_end;
1380
1381 assert(num > 0);
1382 assert(start + num - 1 >= start);
1383
1384 /*
1385 * Leading - bits before first mask boundary.
1386 *
1387 * TODO(lhuemill): With some effort it may be possible to
1388 * replace the following loop with a sequential sequence
1389 * of statements. High level sequence would be:
1390 *
1391 * 1. Use node_split() to force node that describes setting
1392 * of idx to be within the mask portion of a node.
1393 * 2. Form mask of bits to be set.
1394 * 3. Determine number of mask bits already set in the node
1395 * and store in a local variable named num_already_set.
1396 * 4. Set the appropriate mask bits within the node.
1397 * 5. Increment struct sparsebit_pvt num_set member
1398 * by the number of bits that were actually set.
1399 * Exclude from the counts bits that were already set.
1400 * 6. Before returning to the caller, use node_reduce() to
1401 * handle the multiple corner cases that this method
1402 * introduces.
1403 */
1404 for (idx = start, n = num; n > 0 && idx % MASK_BITS != 0; idx++, n--)
1405 bit_set(s, idx);
1406
1407 /* Middle - bits spanning one or more entire mask */
1408 middle_start = idx;
1409 middle_end = middle_start + (n & -MASK_BITS) - 1;
1410 if (n >= MASK_BITS) {
1411 nodep = node_split(s, middle_start);
1412
1413 /*
1414 * As needed, split just after end of middle bits.
1415 * No split needed if end of middle bits is at highest
1416 * supported bit index.
1417 */
1418 if (middle_end + 1 > middle_end)
1419 (void) node_split(s, middle_end + 1);
1420
1421 /* Delete nodes that only describe bits within the middle. */
1422 for (next = node_next(s, nodep);
1423 next && (next->idx < middle_end);
1424 next = node_next(s, nodep)) {
1425 assert(next->idx + MASK_BITS + next->num_after - 1 <= middle_end);
1426 node_rm(s, next);
1427 next = NULL;
1428 }
1429
1430 /* As needed set each of the mask bits */
1431 for (n1 = 0; n1 < MASK_BITS; n1++) {
1432 if (!(nodep->mask & (1 << n1))) {
1433 nodep->mask |= 1 << n1;
1434 s->num_set++;
1435 }
1436 }
1437
1438 s->num_set -= nodep->num_after;
1439 nodep->num_after = middle_end - middle_start + 1 - MASK_BITS;
1440 s->num_set += nodep->num_after;
1441
1442 node_reduce(s, nodep);
1443 }
1444 idx = middle_end + 1;
1445 n -= middle_end - middle_start + 1;
1446
1447 /* Trailing - bits at and beyond last mask boundary */
1448 assert(n < MASK_BITS);
1449 for (; n > 0; idx++, n--)
1450 bit_set(s, idx);
1451}
1452
1453/* Clears the bits * in the inclusive range idx through idx + num - 1. */
1454void sparsebit_clear_num(struct sparsebit *s,
1455 sparsebit_idx_t start, sparsebit_num_t num)
1456{
1457 struct node *nodep, *next;
1458 unsigned int n1;
1459 sparsebit_idx_t idx;
1460 sparsebit_num_t n;
1461 sparsebit_idx_t middle_start, middle_end;
1462
1463 assert(num > 0);
1464 assert(start + num - 1 >= start);
1465
1466 /* Leading - bits before first mask boundary */
1467 for (idx = start, n = num; n > 0 && idx % MASK_BITS != 0; idx++, n--)
1468 bit_clear(s, idx);
1469
1470 /* Middle - bits spanning one or more entire mask */
1471 middle_start = idx;
1472 middle_end = middle_start + (n & -MASK_BITS) - 1;
1473 if (n >= MASK_BITS) {
1474 nodep = node_split(s, middle_start);
1475
1476 /*
1477 * As needed, split just after end of middle bits.
1478 * No split needed if end of middle bits is at highest
1479 * supported bit index.
1480 */
1481 if (middle_end + 1 > middle_end)
1482 (void) node_split(s, middle_end + 1);
1483
1484 /* Delete nodes that only describe bits within the middle. */
1485 for (next = node_next(s, nodep);
1486 next && (next->idx < middle_end);
1487 next = node_next(s, nodep)) {
1488 assert(next->idx + MASK_BITS + next->num_after - 1 <= middle_end);
1489 node_rm(s, next);
1490 next = NULL;
1491 }
1492
1493 /* As needed clear each of the mask bits */
1494 for (n1 = 0; n1 < MASK_BITS; n1++) {
1495 if (nodep->mask & (1 << n1)) {
1496 nodep->mask &= ~(1 << n1);
1497 s->num_set--;
1498 }
1499 }
1500
1501 /* Clear any bits described by num_after */
1502 s->num_set -= nodep->num_after;
1503 nodep->num_after = 0;
1504
1505 /*
1506 * Delete the node that describes the beginning of
1507 * the middle bits and perform any allowed reductions
1508 * with the nodes prev or next of nodep.
1509 */
1510 node_reduce(s, nodep);
1511 nodep = NULL;
1512 }
1513 idx = middle_end + 1;
1514 n -= middle_end - middle_start + 1;
1515
1516 /* Trailing - bits at and beyond last mask boundary */
1517 assert(n < MASK_BITS);
1518 for (; n > 0; idx++, n--)
1519 bit_clear(s, idx);
1520}
1521
1522/* Sets the bit at the index given by idx. */
1523void sparsebit_set(struct sparsebit *s, sparsebit_idx_t idx)
1524{
1525 sparsebit_set_num(s, idx, 1);
1526}
1527
1528/* Clears the bit at the index given by idx. */
1529void sparsebit_clear(struct sparsebit *s, sparsebit_idx_t idx)
1530{
1531 sparsebit_clear_num(s, idx, 1);
1532}
1533
1534/* Sets the bits in the entire addressable range of the sparsebit array. */
1535void sparsebit_set_all(struct sparsebit *s)
1536{
1537 sparsebit_set(s, 0);
1538 sparsebit_set_num(s, 1, ~(sparsebit_idx_t) 0);
1539 assert(sparsebit_all_set(s));
1540}
1541
1542/* Clears the bits in the entire addressable range of the sparsebit array. */
1543void sparsebit_clear_all(struct sparsebit *s)
1544{
1545 sparsebit_clear(s, 0);
1546 sparsebit_clear_num(s, 1, ~(sparsebit_idx_t) 0);
1547 assert(!sparsebit_any_set(s));
1548}
1549
1550static size_t display_range(FILE *stream, sparsebit_idx_t low,
1551 sparsebit_idx_t high, bool prepend_comma_space)
1552{
1553 char *fmt_str;
1554 size_t sz;
1555
1556 /* Determine the printf format string */
1557 if (low == high)
1558 fmt_str = prepend_comma_space ? ", 0x%lx" : "0x%lx";
1559 else
1560 fmt_str = prepend_comma_space ? ", 0x%lx:0x%lx" : "0x%lx:0x%lx";
1561
1562 /*
1563 * When stream is NULL, just determine the size of what would
1564 * have been printed, else print the range.
1565 */
1566 if (!stream)
1567 sz = snprintf(NULL, 0, fmt_str, low, high);
1568 else
1569 sz = fprintf(stream, fmt_str, low, high);
1570
1571 return sz;
1572}
1573
1574
1575/* Dumps to the FILE stream given by stream, the bit settings
1576 * of s. Each line of output is prefixed with the number of
1577 * spaces given by indent. The length of each line is implementation
1578 * dependent and does not depend on the indent amount. The following
1579 * is an example output of a sparsebit array that has bits:
1580 *
1581 * 0x5, 0x8, 0xa:0xe, 0x12
1582 *
1583 * This corresponds to a sparsebit whose bits 5, 8, 10, 11, 12, 13, 14, 18
1584 * are set. Note that a ':', instead of a '-' is used to specify a range of
1585 * contiguous bits. This is done because '-' is used to specify command-line
1586 * options, and sometimes ranges are specified as command-line arguments.
1587 */
1588void sparsebit_dump(FILE *stream, struct sparsebit *s,
1589 unsigned int indent)
1590{
1591 size_t current_line_len = 0;
1592 size_t sz;
1593 struct node *nodep;
1594
1595 if (!sparsebit_any_set(s))
1596 return;
1597
1598 /* Display initial indent */
1599 fprintf(stream, "%*s", indent, "");
1600
1601 /* For each node */
1602 for (nodep = node_first(s); nodep; nodep = node_next(s, nodep)) {
1603 unsigned int n1;
1604 sparsebit_idx_t low, high;
1605
1606 /* For each group of bits in the mask */
1607 for (n1 = 0; n1 < MASK_BITS; n1++) {
1608 if (nodep->mask & (1 << n1)) {
1609 low = high = nodep->idx + n1;
1610
1611 for (; n1 < MASK_BITS; n1++) {
1612 if (nodep->mask & (1 << n1))
1613 high = nodep->idx + n1;
1614 else
1615 break;
1616 }
1617
1618 if ((n1 == MASK_BITS) && nodep->num_after)
1619 high += nodep->num_after;
1620
1621 /*
1622 * How much room will it take to display
1623 * this range.
1624 */
1625 sz = display_range(NULL, low, high,
1626 current_line_len != 0);
1627
1628 /*
1629 * If there is not enough room, display
1630 * a newline plus the indent of the next
1631 * line.
1632 */
1633 if (current_line_len + sz > DUMP_LINE_MAX) {
1634 fputs("\n", stream);
1635 fprintf(stream, "%*s", indent, "");
1636 current_line_len = 0;
1637 }
1638
1639 /* Display the range */
1640 sz = display_range(stream, low, high,
1641 current_line_len != 0);
1642 current_line_len += sz;
1643 }
1644 }
1645
1646 /*
1647 * If num_after and most significant-bit of mask is not
1648 * set, then still need to display a range for the bits
1649 * described by num_after.
1650 */
1651 if (!(nodep->mask & (1 << (MASK_BITS - 1))) && nodep->num_after) {
1652 low = nodep->idx + MASK_BITS;
1653 high = nodep->idx + MASK_BITS + nodep->num_after - 1;
1654
1655 /*
1656 * How much room will it take to display
1657 * this range.
1658 */
1659 sz = display_range(NULL, low, high,
1660 current_line_len != 0);
1661
1662 /*
1663 * If there is not enough room, display
1664 * a newline plus the indent of the next
1665 * line.
1666 */
1667 if (current_line_len + sz > DUMP_LINE_MAX) {
1668 fputs("\n", stream);
1669 fprintf(stream, "%*s", indent, "");
1670 current_line_len = 0;
1671 }
1672
1673 /* Display the range */
1674 sz = display_range(stream, low, high,
1675 current_line_len != 0);
1676 current_line_len += sz;
1677 }
1678 }
1679 fputs("\n", stream);
1680}
1681
1682/* Validates the internal state of the sparsebit array given by
1683 * s. On error, diagnostic information is printed to stderr and
1684 * abort is called.
1685 */
1686void sparsebit_validate_internal(struct sparsebit *s)
1687{
1688 bool error_detected = false;
1689 struct node *nodep, *prev = NULL;
1690 sparsebit_num_t total_bits_set = 0;
1691 unsigned int n1;
1692
1693 /* For each node */
1694 for (nodep = node_first(s); nodep;
1695 prev = nodep, nodep = node_next(s, nodep)) {
1696
1697 /*
1698 * Increase total bits set by the number of bits set
1699 * in this node.
1700 */
1701 for (n1 = 0; n1 < MASK_BITS; n1++)
1702 if (nodep->mask & (1 << n1))
1703 total_bits_set++;
1704
1705 total_bits_set += nodep->num_after;
1706
1707 /*
1708 * Arbitrary choice as to whether a mask of 0 is allowed
1709 * or not. For diagnostic purposes it is beneficial to
1710 * have only one valid means to represent a set of bits.
1711 * To support this an arbitrary choice has been made
1712 * to not allow a mask of zero.
1713 */
1714 if (nodep->mask == 0) {
1715 fprintf(stderr, "Node mask of zero, "
1716 "nodep: %p nodep->mask: 0x%x",
1717 nodep, nodep->mask);
1718 error_detected = true;
1719 break;
1720 }
1721
1722 /*
1723 * Validate num_after is not greater than the max index
1724 * - the number of mask bits. The num_after member
1725 * uses 0-based indexing and thus has no value that
1726 * represents all bits set. This limitation is handled
1727 * by requiring a non-zero mask. With a non-zero mask,
1728 * MASK_BITS worth of bits are described by the mask,
1729 * which makes the largest needed num_after equal to:
1730 *
1731 * (~(sparsebit_num_t) 0) - MASK_BITS + 1
1732 */
1733 if (nodep->num_after
1734 > (~(sparsebit_num_t) 0) - MASK_BITS + 1) {
1735 fprintf(stderr, "num_after too large, "
1736 "nodep: %p nodep->num_after: 0x%lx",
1737 nodep, nodep->num_after);
1738 error_detected = true;
1739 break;
1740 }
1741
1742 /* Validate node index is divisible by the mask size */
1743 if (nodep->idx % MASK_BITS) {
1744 fprintf(stderr, "Node index not divisible by "
1745 "mask size,\n"
1746 " nodep: %p nodep->idx: 0x%lx "
1747 "MASK_BITS: %lu\n",
1748 nodep, nodep->idx, MASK_BITS);
1749 error_detected = true;
1750 break;
1751 }
1752
1753 /*
1754 * Validate bits described by node don't wrap beyond the
1755 * highest supported index.
1756 */
1757 if ((nodep->idx + MASK_BITS + nodep->num_after - 1) < nodep->idx) {
1758 fprintf(stderr, "Bits described by node wrap "
1759 "beyond highest supported index,\n"
1760 " nodep: %p nodep->idx: 0x%lx\n"
1761 " MASK_BITS: %lu nodep->num_after: 0x%lx",
1762 nodep, nodep->idx, MASK_BITS, nodep->num_after);
1763 error_detected = true;
1764 break;
1765 }
1766
1767 /* Check parent pointers. */
1768 if (nodep->left) {
1769 if (nodep->left->parent != nodep) {
1770 fprintf(stderr, "Left child parent pointer "
1771 "doesn't point to this node,\n"
1772 " nodep: %p nodep->left: %p "
1773 "nodep->left->parent: %p",
1774 nodep, nodep->left,
1775 nodep->left->parent);
1776 error_detected = true;
1777 break;
1778 }
1779 }
1780
1781 if (nodep->right) {
1782 if (nodep->right->parent != nodep) {
1783 fprintf(stderr, "Right child parent pointer "
1784 "doesn't point to this node,\n"
1785 " nodep: %p nodep->right: %p "
1786 "nodep->right->parent: %p",
1787 nodep, nodep->right,
1788 nodep->right->parent);
1789 error_detected = true;
1790 break;
1791 }
1792 }
1793
1794 if (!nodep->parent) {
1795 if (s->root != nodep) {
1796 fprintf(stderr, "Unexpected root node, "
1797 "s->root: %p nodep: %p",
1798 s->root, nodep);
1799 error_detected = true;
1800 break;
1801 }
1802 }
1803
1804 if (prev) {
1805 /*
1806 * Is index of previous node before index of
1807 * current node?
1808 */
1809 if (prev->idx >= nodep->idx) {
1810 fprintf(stderr, "Previous node index "
1811 ">= current node index,\n"
1812 " prev: %p prev->idx: 0x%lx\n"
1813 " nodep: %p nodep->idx: 0x%lx",
1814 prev, prev->idx, nodep, nodep->idx);
1815 error_detected = true;
1816 break;
1817 }
1818
1819 /*
1820 * Nodes occur in asscending order, based on each
1821 * nodes starting index.
1822 */
1823 if ((prev->idx + MASK_BITS + prev->num_after - 1)
1824 >= nodep->idx) {
1825 fprintf(stderr, "Previous node bit range "
1826 "overlap with current node bit range,\n"
1827 " prev: %p prev->idx: 0x%lx "
1828 "prev->num_after: 0x%lx\n"
1829 " nodep: %p nodep->idx: 0x%lx "
1830 "nodep->num_after: 0x%lx\n"
1831 " MASK_BITS: %lu",
1832 prev, prev->idx, prev->num_after,
1833 nodep, nodep->idx, nodep->num_after,
1834 MASK_BITS);
1835 error_detected = true;
1836 break;
1837 }
1838
1839 /*
1840 * When the node has all mask bits set, it shouldn't
1841 * be adjacent to the last bit described by the
1842 * previous node.
1843 */
1844 if (nodep->mask == ~(mask_t) 0 &&
1845 prev->idx + MASK_BITS + prev->num_after == nodep->idx) {
1846 fprintf(stderr, "Current node has mask with "
1847 "all bits set and is adjacent to the "
1848 "previous node,\n"
1849 " prev: %p prev->idx: 0x%lx "
1850 "prev->num_after: 0x%lx\n"
1851 " nodep: %p nodep->idx: 0x%lx "
1852 "nodep->num_after: 0x%lx\n"
1853 " MASK_BITS: %lu",
1854 prev, prev->idx, prev->num_after,
1855 nodep, nodep->idx, nodep->num_after,
1856 MASK_BITS);
1857
1858 error_detected = true;
1859 break;
1860 }
1861 }
1862 }
1863
1864 if (!error_detected) {
1865 /*
1866 * Is sum of bits set in each node equal to the count
1867 * of total bits set.
1868 */
1869 if (s->num_set != total_bits_set) {
1870 fprintf(stderr, "Number of bits set missmatch,\n"
1871 " s->num_set: 0x%lx total_bits_set: 0x%lx",
1872 s->num_set, total_bits_set);
1873
1874 error_detected = true;
1875 }
1876 }
1877
1878 if (error_detected) {
1879 fputs(" dump_internal:\n", stderr);
1880 sparsebit_dump_internal(stderr, s, 4);
1881 abort();
1882 }
1883}
1884
1885
1886#ifdef FUZZ
1887/* A simple but effective fuzzing driver. Look for bugs with the help
1888 * of some invariants and of a trivial representation of sparsebit.
1889 * Just use 512 bytes of /dev/zero and /dev/urandom as inputs, and let
1890 * afl-fuzz do the magic. :)
1891 */
1892
1893#include <stdlib.h>
1894#include <assert.h>
1895
1896struct range {
1897 sparsebit_idx_t first, last;
1898 bool set;
1899};
1900
1901struct sparsebit *s;
1902struct range ranges[1000];
1903int num_ranges;
1904
1905static bool get_value(sparsebit_idx_t idx)
1906{
1907 int i;
1908
1909 for (i = num_ranges; --i >= 0; )
1910 if (ranges[i].first <= idx && idx <= ranges[i].last)
1911 return ranges[i].set;
1912
1913 return false;
1914}
1915
1916static void operate(int code, sparsebit_idx_t first, sparsebit_idx_t last)
1917{
1918 sparsebit_num_t num;
1919 sparsebit_idx_t next;
1920
1921 if (first < last) {
1922 num = last - first + 1;
1923 } else {
1924 num = first - last + 1;
1925 first = last;
1926 last = first + num - 1;
1927 }
1928
1929 switch (code) {
1930 case 0:
1931 sparsebit_set(s, first);
1932 assert(sparsebit_is_set(s, first));
1933 assert(!sparsebit_is_clear(s, first));
1934 assert(sparsebit_any_set(s));
1935 assert(!sparsebit_all_clear(s));
1936 if (get_value(first))
1937 return;
1938 if (num_ranges == 1000)
1939 exit(0);
1940 ranges[num_ranges++] = (struct range)
1941 { .first = first, .last = first, .set = true };
1942 break;
1943 case 1:
1944 sparsebit_clear(s, first);
1945 assert(!sparsebit_is_set(s, first));
1946 assert(sparsebit_is_clear(s, first));
1947 assert(sparsebit_any_clear(s));
1948 assert(!sparsebit_all_set(s));
1949 if (!get_value(first))
1950 return;
1951 if (num_ranges == 1000)
1952 exit(0);
1953 ranges[num_ranges++] = (struct range)
1954 { .first = first, .last = first, .set = false };
1955 break;
1956 case 2:
1957 assert(sparsebit_is_set(s, first) == get_value(first));
1958 assert(sparsebit_is_clear(s, first) == !get_value(first));
1959 break;
1960 case 3:
1961 if (sparsebit_any_set(s))
1962 assert(get_value(sparsebit_first_set(s)));
1963 if (sparsebit_any_clear(s))
1964 assert(!get_value(sparsebit_first_clear(s)));
1965 sparsebit_set_all(s);
1966 assert(!sparsebit_any_clear(s));
1967 assert(sparsebit_all_set(s));
1968 num_ranges = 0;
1969 ranges[num_ranges++] = (struct range)
1970 { .first = 0, .last = ~(sparsebit_idx_t)0, .set = true };
1971 break;
1972 case 4:
1973 if (sparsebit_any_set(s))
1974 assert(get_value(sparsebit_first_set(s)));
1975 if (sparsebit_any_clear(s))
1976 assert(!get_value(sparsebit_first_clear(s)));
1977 sparsebit_clear_all(s);
1978 assert(!sparsebit_any_set(s));
1979 assert(sparsebit_all_clear(s));
1980 num_ranges = 0;
1981 break;
1982 case 5:
1983 next = sparsebit_next_set(s, first);
1984 assert(next == 0 || next > first);
1985 assert(next == 0 || get_value(next));
1986 break;
1987 case 6:
1988 next = sparsebit_next_clear(s, first);
1989 assert(next == 0 || next > first);
1990 assert(next == 0 || !get_value(next));
1991 break;
1992 case 7:
1993 next = sparsebit_next_clear(s, first);
1994 if (sparsebit_is_set_num(s, first, num)) {
1995 assert(next == 0 || next > last);
1996 if (first)
1997 next = sparsebit_next_set(s, first - 1);
1998 else if (sparsebit_any_set(s))
1999 next = sparsebit_first_set(s);
2000 else
2001 return;
2002 assert(next == first);
2003 } else {
2004 assert(sparsebit_is_clear(s, first) || next <= last);
2005 }
2006 break;
2007 case 8:
2008 next = sparsebit_next_set(s, first);
2009 if (sparsebit_is_clear_num(s, first, num)) {
2010 assert(next == 0 || next > last);
2011 if (first)
2012 next = sparsebit_next_clear(s, first - 1);
2013 else if (sparsebit_any_clear(s))
2014 next = sparsebit_first_clear(s);
2015 else
2016 return;
2017 assert(next == first);
2018 } else {
2019 assert(sparsebit_is_set(s, first) || next <= last);
2020 }
2021 break;
2022 case 9:
2023 sparsebit_set_num(s, first, num);
2024 assert(sparsebit_is_set_num(s, first, num));
2025 assert(!sparsebit_is_clear_num(s, first, num));
2026 assert(sparsebit_any_set(s));
2027 assert(!sparsebit_all_clear(s));
2028 if (num_ranges == 1000)
2029 exit(0);
2030 ranges[num_ranges++] = (struct range)
2031 { .first = first, .last = last, .set = true };
2032 break;
2033 case 10:
2034 sparsebit_clear_num(s, first, num);
2035 assert(!sparsebit_is_set_num(s, first, num));
2036 assert(sparsebit_is_clear_num(s, first, num));
2037 assert(sparsebit_any_clear(s));
2038 assert(!sparsebit_all_set(s));
2039 if (num_ranges == 1000)
2040 exit(0);
2041 ranges[num_ranges++] = (struct range)
2042 { .first = first, .last = last, .set = false };
2043 break;
2044 case 11:
2045 sparsebit_validate_internal(s);
2046 break;
2047 default:
2048 break;
2049 }
2050}
2051
2052unsigned char get8(void)
2053{
2054 int ch;
2055
2056 ch = getchar();
2057 if (ch == EOF)
2058 exit(0);
2059 return ch;
2060}
2061
2062uint64_t get64(void)
2063{
2064 uint64_t x;
2065
2066 x = get8();
2067 x = (x << 8) | get8();
2068 x = (x << 8) | get8();
2069 x = (x << 8) | get8();
2070 x = (x << 8) | get8();
2071 x = (x << 8) | get8();
2072 x = (x << 8) | get8();
2073 return (x << 8) | get8();
2074}
2075
2076int main(void)
2077{
2078 s = sparsebit_alloc();
2079 for (;;) {
2080 uint8_t op = get8() & 0xf;
2081 uint64_t first = get64();
2082 uint64_t last = get64();
2083
2084 operate(op, first, last);
2085 }
2086}
2087#endif
diff --git a/tools/testing/selftests/kvm/lib/vmx.c b/tools/testing/selftests/kvm/lib/vmx.c
new file mode 100644
index 000000000000..0231bc0aae7b
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/vmx.c
@@ -0,0 +1,243 @@
1/*
2 * tools/testing/selftests/kvm/lib/x86.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#define _GNU_SOURCE /* for program_invocation_name */
10
11#include "test_util.h"
12#include "kvm_util.h"
13#include "x86.h"
14#include "vmx.h"
15
16/* Create a default VM for VMX tests.
17 *
18 * Input Args:
19 * vcpuid - The id of the single VCPU to add to the VM.
20 * guest_code - The vCPU's entry point
21 *
22 * Output Args: None
23 *
24 * Return:
25 * Pointer to opaque structure that describes the created VM.
26 */
27struct kvm_vm *
28vm_create_default_vmx(uint32_t vcpuid, vmx_guest_code_t guest_code)
29{
30 struct kvm_cpuid2 *cpuid;
31 struct kvm_vm *vm;
32 vm_vaddr_t vmxon_vaddr;
33 vm_paddr_t vmxon_paddr;
34 vm_vaddr_t vmcs_vaddr;
35 vm_paddr_t vmcs_paddr;
36
37 vm = vm_create_default(vcpuid, (void *) guest_code);
38
39 /* Enable nesting in CPUID */
40 vcpu_set_cpuid(vm, vcpuid, kvm_get_supported_cpuid());
41
42 /* Setup of a region of guest memory for the vmxon region. */
43 vmxon_vaddr = vm_vaddr_alloc(vm, getpagesize(), 0, 0, 0);
44 vmxon_paddr = addr_gva2gpa(vm, vmxon_vaddr);
45
46 /* Setup of a region of guest memory for a vmcs. */
47 vmcs_vaddr = vm_vaddr_alloc(vm, getpagesize(), 0, 0, 0);
48 vmcs_paddr = addr_gva2gpa(vm, vmcs_vaddr);
49
50 vcpu_args_set(vm, vcpuid, 4, vmxon_vaddr, vmxon_paddr, vmcs_vaddr,
51 vmcs_paddr);
52
53 return vm;
54}
55
56void prepare_for_vmx_operation(void)
57{
58 uint64_t feature_control;
59 uint64_t required;
60 unsigned long cr0;
61 unsigned long cr4;
62
63 /*
64 * Ensure bits in CR0 and CR4 are valid in VMX operation:
65 * - Bit X is 1 in _FIXED0: bit X is fixed to 1 in CRx.
66 * - Bit X is 0 in _FIXED1: bit X is fixed to 0 in CRx.
67 */
68 __asm__ __volatile__("mov %%cr0, %0" : "=r"(cr0) : : "memory");
69 cr0 &= rdmsr(MSR_IA32_VMX_CR0_FIXED1);
70 cr0 |= rdmsr(MSR_IA32_VMX_CR0_FIXED0);
71 __asm__ __volatile__("mov %0, %%cr0" : : "r"(cr0) : "memory");
72
73 __asm__ __volatile__("mov %%cr4, %0" : "=r"(cr4) : : "memory");
74 cr4 &= rdmsr(MSR_IA32_VMX_CR4_FIXED1);
75 cr4 |= rdmsr(MSR_IA32_VMX_CR4_FIXED0);
76 /* Enable VMX operation */
77 cr4 |= X86_CR4_VMXE;
78 __asm__ __volatile__("mov %0, %%cr4" : : "r"(cr4) : "memory");
79
80 /*
81 * Configure IA32_FEATURE_CONTROL MSR to allow VMXON:
82 * Bit 0: Lock bit. If clear, VMXON causes a #GP.
83 * Bit 2: Enables VMXON outside of SMX operation. If clear, VMXON
84 * outside of SMX causes a #GP.
85 */
86 required = FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
87 required |= FEATURE_CONTROL_LOCKED;
88 feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
89 if ((feature_control & required) != required)
90 wrmsr(MSR_IA32_FEATURE_CONTROL, feature_control | required);
91}
92
93/*
94 * Initialize the control fields to the most basic settings possible.
95 */
96static inline void init_vmcs_control_fields(void)
97{
98 vmwrite(VIRTUAL_PROCESSOR_ID, 0);
99 vmwrite(POSTED_INTR_NV, 0);
100
101 vmwrite(PIN_BASED_VM_EXEC_CONTROL, rdmsr(MSR_IA32_VMX_PINBASED_CTLS));
102 vmwrite(CPU_BASED_VM_EXEC_CONTROL, rdmsr(MSR_IA32_VMX_PROCBASED_CTLS));
103 vmwrite(EXCEPTION_BITMAP, 0);
104 vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0);
105 vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, -1); /* Never match */
106 vmwrite(CR3_TARGET_COUNT, 0);
107 vmwrite(VM_EXIT_CONTROLS, rdmsr(MSR_IA32_VMX_EXIT_CTLS) |
108 VM_EXIT_HOST_ADDR_SPACE_SIZE); /* 64-bit host */
109 vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
110 vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
111 vmwrite(VM_ENTRY_CONTROLS, rdmsr(MSR_IA32_VMX_ENTRY_CTLS) |
112 VM_ENTRY_IA32E_MODE); /* 64-bit guest */
113 vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
114 vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
115 vmwrite(TPR_THRESHOLD, 0);
116 vmwrite(SECONDARY_VM_EXEC_CONTROL, 0);
117
118 vmwrite(CR0_GUEST_HOST_MASK, 0);
119 vmwrite(CR4_GUEST_HOST_MASK, 0);
120 vmwrite(CR0_READ_SHADOW, get_cr0());
121 vmwrite(CR4_READ_SHADOW, get_cr4());
122}
123
124/*
125 * Initialize the host state fields based on the current host state, with
126 * the exception of HOST_RSP and HOST_RIP, which should be set by vmlaunch
127 * or vmresume.
128 */
129static inline void init_vmcs_host_state(void)
130{
131 uint32_t exit_controls = vmreadz(VM_EXIT_CONTROLS);
132
133 vmwrite(HOST_ES_SELECTOR, get_es());
134 vmwrite(HOST_CS_SELECTOR, get_cs());
135 vmwrite(HOST_SS_SELECTOR, get_ss());
136 vmwrite(HOST_DS_SELECTOR, get_ds());
137 vmwrite(HOST_FS_SELECTOR, get_fs());
138 vmwrite(HOST_GS_SELECTOR, get_gs());
139 vmwrite(HOST_TR_SELECTOR, get_tr());
140
141 if (exit_controls & VM_EXIT_LOAD_IA32_PAT)
142 vmwrite(HOST_IA32_PAT, rdmsr(MSR_IA32_CR_PAT));
143 if (exit_controls & VM_EXIT_LOAD_IA32_EFER)
144 vmwrite(HOST_IA32_EFER, rdmsr(MSR_EFER));
145 if (exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
146 vmwrite(HOST_IA32_PERF_GLOBAL_CTRL,
147 rdmsr(MSR_CORE_PERF_GLOBAL_CTRL));
148
149 vmwrite(HOST_IA32_SYSENTER_CS, rdmsr(MSR_IA32_SYSENTER_CS));
150
151 vmwrite(HOST_CR0, get_cr0());
152 vmwrite(HOST_CR3, get_cr3());
153 vmwrite(HOST_CR4, get_cr4());
154 vmwrite(HOST_FS_BASE, rdmsr(MSR_FS_BASE));
155 vmwrite(HOST_GS_BASE, rdmsr(MSR_GS_BASE));
156 vmwrite(HOST_TR_BASE,
157 get_desc64_base((struct desc64 *)(get_gdt_base() + get_tr())));
158 vmwrite(HOST_GDTR_BASE, get_gdt_base());
159 vmwrite(HOST_IDTR_BASE, get_idt_base());
160 vmwrite(HOST_IA32_SYSENTER_ESP, rdmsr(MSR_IA32_SYSENTER_ESP));
161 vmwrite(HOST_IA32_SYSENTER_EIP, rdmsr(MSR_IA32_SYSENTER_EIP));
162}
163
164/*
165 * Initialize the guest state fields essentially as a clone of
166 * the host state fields. Some host state fields have fixed
167 * values, and we set the corresponding guest state fields accordingly.
168 */
169static inline void init_vmcs_guest_state(void *rip, void *rsp)
170{
171 vmwrite(GUEST_ES_SELECTOR, vmreadz(HOST_ES_SELECTOR));
172 vmwrite(GUEST_CS_SELECTOR, vmreadz(HOST_CS_SELECTOR));
173 vmwrite(GUEST_SS_SELECTOR, vmreadz(HOST_SS_SELECTOR));
174 vmwrite(GUEST_DS_SELECTOR, vmreadz(HOST_DS_SELECTOR));
175 vmwrite(GUEST_FS_SELECTOR, vmreadz(HOST_FS_SELECTOR));
176 vmwrite(GUEST_GS_SELECTOR, vmreadz(HOST_GS_SELECTOR));
177 vmwrite(GUEST_LDTR_SELECTOR, 0);
178 vmwrite(GUEST_TR_SELECTOR, vmreadz(HOST_TR_SELECTOR));
179 vmwrite(GUEST_INTR_STATUS, 0);
180 vmwrite(GUEST_PML_INDEX, 0);
181
182 vmwrite(VMCS_LINK_POINTER, -1ll);
183 vmwrite(GUEST_IA32_DEBUGCTL, 0);
184 vmwrite(GUEST_IA32_PAT, vmreadz(HOST_IA32_PAT));
185 vmwrite(GUEST_IA32_EFER, vmreadz(HOST_IA32_EFER));
186 vmwrite(GUEST_IA32_PERF_GLOBAL_CTRL,
187 vmreadz(HOST_IA32_PERF_GLOBAL_CTRL));
188
189 vmwrite(GUEST_ES_LIMIT, -1);
190 vmwrite(GUEST_CS_LIMIT, -1);
191 vmwrite(GUEST_SS_LIMIT, -1);
192 vmwrite(GUEST_DS_LIMIT, -1);
193 vmwrite(GUEST_FS_LIMIT, -1);
194 vmwrite(GUEST_GS_LIMIT, -1);
195 vmwrite(GUEST_LDTR_LIMIT, -1);
196 vmwrite(GUEST_TR_LIMIT, 0x67);
197 vmwrite(GUEST_GDTR_LIMIT, 0xffff);
198 vmwrite(GUEST_IDTR_LIMIT, 0xffff);
199 vmwrite(GUEST_ES_AR_BYTES,
200 vmreadz(GUEST_ES_SELECTOR) == 0 ? 0x10000 : 0xc093);
201 vmwrite(GUEST_CS_AR_BYTES, 0xa09b);
202 vmwrite(GUEST_SS_AR_BYTES, 0xc093);
203 vmwrite(GUEST_DS_AR_BYTES,
204 vmreadz(GUEST_DS_SELECTOR) == 0 ? 0x10000 : 0xc093);
205 vmwrite(GUEST_FS_AR_BYTES,
206 vmreadz(GUEST_FS_SELECTOR) == 0 ? 0x10000 : 0xc093);
207 vmwrite(GUEST_GS_AR_BYTES,
208 vmreadz(GUEST_GS_SELECTOR) == 0 ? 0x10000 : 0xc093);
209 vmwrite(GUEST_LDTR_AR_BYTES, 0x10000);
210 vmwrite(GUEST_TR_AR_BYTES, 0x8b);
211 vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
212 vmwrite(GUEST_ACTIVITY_STATE, 0);
213 vmwrite(GUEST_SYSENTER_CS, vmreadz(HOST_IA32_SYSENTER_CS));
214 vmwrite(VMX_PREEMPTION_TIMER_VALUE, 0);
215
216 vmwrite(GUEST_CR0, vmreadz(HOST_CR0));
217 vmwrite(GUEST_CR3, vmreadz(HOST_CR3));
218 vmwrite(GUEST_CR4, vmreadz(HOST_CR4));
219 vmwrite(GUEST_ES_BASE, 0);
220 vmwrite(GUEST_CS_BASE, 0);
221 vmwrite(GUEST_SS_BASE, 0);
222 vmwrite(GUEST_DS_BASE, 0);
223 vmwrite(GUEST_FS_BASE, vmreadz(HOST_FS_BASE));
224 vmwrite(GUEST_GS_BASE, vmreadz(HOST_GS_BASE));
225 vmwrite(GUEST_LDTR_BASE, 0);
226 vmwrite(GUEST_TR_BASE, vmreadz(HOST_TR_BASE));
227 vmwrite(GUEST_GDTR_BASE, vmreadz(HOST_GDTR_BASE));
228 vmwrite(GUEST_IDTR_BASE, vmreadz(HOST_IDTR_BASE));
229 vmwrite(GUEST_DR7, 0x400);
230 vmwrite(GUEST_RSP, (uint64_t)rsp);
231 vmwrite(GUEST_RIP, (uint64_t)rip);
232 vmwrite(GUEST_RFLAGS, 2);
233 vmwrite(GUEST_PENDING_DBG_EXCEPTIONS, 0);
234 vmwrite(GUEST_SYSENTER_ESP, vmreadz(HOST_IA32_SYSENTER_ESP));
235 vmwrite(GUEST_SYSENTER_EIP, vmreadz(HOST_IA32_SYSENTER_EIP));
236}
237
238void prepare_vmcs(void *guest_rip, void *guest_rsp)
239{
240 init_vmcs_control_fields();
241 init_vmcs_host_state();
242 init_vmcs_guest_state(guest_rip, guest_rsp);
243}
diff --git a/tools/testing/selftests/kvm/lib/x86.c b/tools/testing/selftests/kvm/lib/x86.c
new file mode 100644
index 000000000000..2f17675f4275
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/x86.c
@@ -0,0 +1,700 @@
1/*
2 * tools/testing/selftests/kvm/lib/x86.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */
8
9#define _GNU_SOURCE /* for program_invocation_name */
10
11#include "test_util.h"
12#include "kvm_util.h"
13#include "kvm_util_internal.h"
14#include "x86.h"
15
16/* Minimum physical address used for virtual translation tables. */
17#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
18
19/* Virtual translation table structure declarations */
20struct pageMapL4Entry {
21 uint64_t present:1;
22 uint64_t writable:1;
23 uint64_t user:1;
24 uint64_t write_through:1;
25 uint64_t cache_disable:1;
26 uint64_t accessed:1;
27 uint64_t ignored_06:1;
28 uint64_t page_size:1;
29 uint64_t ignored_11_08:4;
30 uint64_t address:40;
31 uint64_t ignored_62_52:11;
32 uint64_t execute_disable:1;
33};
34
35struct pageDirectoryPointerEntry {
36 uint64_t present:1;
37 uint64_t writable:1;
38 uint64_t user:1;
39 uint64_t write_through:1;
40 uint64_t cache_disable:1;
41 uint64_t accessed:1;
42 uint64_t ignored_06:1;
43 uint64_t page_size:1;
44 uint64_t ignored_11_08:4;
45 uint64_t address:40;
46 uint64_t ignored_62_52:11;
47 uint64_t execute_disable:1;
48};
49
50struct pageDirectoryEntry {
51 uint64_t present:1;
52 uint64_t writable:1;
53 uint64_t user:1;
54 uint64_t write_through:1;
55 uint64_t cache_disable:1;
56 uint64_t accessed:1;
57 uint64_t ignored_06:1;
58 uint64_t page_size:1;
59 uint64_t ignored_11_08:4;
60 uint64_t address:40;
61 uint64_t ignored_62_52:11;
62 uint64_t execute_disable:1;
63};
64
65struct pageTableEntry {
66 uint64_t present:1;
67 uint64_t writable:1;
68 uint64_t user:1;
69 uint64_t write_through:1;
70 uint64_t cache_disable:1;
71 uint64_t accessed:1;
72 uint64_t dirty:1;
73 uint64_t reserved_07:1;
74 uint64_t global:1;
75 uint64_t ignored_11_09:3;
76 uint64_t address:40;
77 uint64_t ignored_62_52:11;
78 uint64_t execute_disable:1;
79};
80
81/* Register Dump
82 *
83 * Input Args:
84 * indent - Left margin indent amount
85 * regs - register
86 *
87 * Output Args:
88 * stream - Output FILE stream
89 *
90 * Return: None
91 *
92 * Dumps the state of the registers given by regs, to the FILE stream
93 * given by steam.
94 */
95void regs_dump(FILE *stream, struct kvm_regs *regs,
96 uint8_t indent)
97{
98 fprintf(stream, "%*srax: 0x%.16llx rbx: 0x%.16llx "
99 "rcx: 0x%.16llx rdx: 0x%.16llx\n",
100 indent, "",
101 regs->rax, regs->rbx, regs->rcx, regs->rdx);
102 fprintf(stream, "%*srsi: 0x%.16llx rdi: 0x%.16llx "
103 "rsp: 0x%.16llx rbp: 0x%.16llx\n",
104 indent, "",
105 regs->rsi, regs->rdi, regs->rsp, regs->rbp);
106 fprintf(stream, "%*sr8: 0x%.16llx r9: 0x%.16llx "
107 "r10: 0x%.16llx r11: 0x%.16llx\n",
108 indent, "",
109 regs->r8, regs->r9, regs->r10, regs->r11);
110 fprintf(stream, "%*sr12: 0x%.16llx r13: 0x%.16llx "
111 "r14: 0x%.16llx r15: 0x%.16llx\n",
112 indent, "",
113 regs->r12, regs->r13, regs->r14, regs->r15);
114 fprintf(stream, "%*srip: 0x%.16llx rfl: 0x%.16llx\n",
115 indent, "",
116 regs->rip, regs->rflags);
117}
118
119/* Segment Dump
120 *
121 * Input Args:
122 * indent - Left margin indent amount
123 * segment - KVM segment
124 *
125 * Output Args:
126 * stream - Output FILE stream
127 *
128 * Return: None
129 *
130 * Dumps the state of the KVM segment given by segment, to the FILE stream
131 * given by steam.
132 */
133static void segment_dump(FILE *stream, struct kvm_segment *segment,
134 uint8_t indent)
135{
136 fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.8x "
137 "selector: 0x%.4x type: 0x%.2x\n",
138 indent, "", segment->base, segment->limit,
139 segment->selector, segment->type);
140 fprintf(stream, "%*spresent: 0x%.2x dpl: 0x%.2x "
141 "db: 0x%.2x s: 0x%.2x l: 0x%.2x\n",
142 indent, "", segment->present, segment->dpl,
143 segment->db, segment->s, segment->l);
144 fprintf(stream, "%*sg: 0x%.2x avl: 0x%.2x "
145 "unusable: 0x%.2x padding: 0x%.2x\n",
146 indent, "", segment->g, segment->avl,
147 segment->unusable, segment->padding);
148}
149
150/* dtable Dump
151 *
152 * Input Args:
153 * indent - Left margin indent amount
154 * dtable - KVM dtable
155 *
156 * Output Args:
157 * stream - Output FILE stream
158 *
159 * Return: None
160 *
161 * Dumps the state of the KVM dtable given by dtable, to the FILE stream
162 * given by steam.
163 */
164static void dtable_dump(FILE *stream, struct kvm_dtable *dtable,
165 uint8_t indent)
166{
167 fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.4x "
168 "padding: 0x%.4x 0x%.4x 0x%.4x\n",
169 indent, "", dtable->base, dtable->limit,
170 dtable->padding[0], dtable->padding[1], dtable->padding[2]);
171}
172
173/* System Register Dump
174 *
175 * Input Args:
176 * indent - Left margin indent amount
177 * sregs - System registers
178 *
179 * Output Args:
180 * stream - Output FILE stream
181 *
182 * Return: None
183 *
184 * Dumps the state of the system registers given by sregs, to the FILE stream
185 * given by steam.
186 */
187void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
188 uint8_t indent)
189{
190 unsigned int i;
191
192 fprintf(stream, "%*scs:\n", indent, "");
193 segment_dump(stream, &sregs->cs, indent + 2);
194 fprintf(stream, "%*sds:\n", indent, "");
195 segment_dump(stream, &sregs->ds, indent + 2);
196 fprintf(stream, "%*ses:\n", indent, "");
197 segment_dump(stream, &sregs->es, indent + 2);
198 fprintf(stream, "%*sfs:\n", indent, "");
199 segment_dump(stream, &sregs->fs, indent + 2);
200 fprintf(stream, "%*sgs:\n", indent, "");
201 segment_dump(stream, &sregs->gs, indent + 2);
202 fprintf(stream, "%*sss:\n", indent, "");
203 segment_dump(stream, &sregs->ss, indent + 2);
204 fprintf(stream, "%*str:\n", indent, "");
205 segment_dump(stream, &sregs->tr, indent + 2);
206 fprintf(stream, "%*sldt:\n", indent, "");
207 segment_dump(stream, &sregs->ldt, indent + 2);
208
209 fprintf(stream, "%*sgdt:\n", indent, "");
210 dtable_dump(stream, &sregs->gdt, indent + 2);
211 fprintf(stream, "%*sidt:\n", indent, "");
212 dtable_dump(stream, &sregs->idt, indent + 2);
213
214 fprintf(stream, "%*scr0: 0x%.16llx cr2: 0x%.16llx "
215 "cr3: 0x%.16llx cr4: 0x%.16llx\n",
216 indent, "",
217 sregs->cr0, sregs->cr2, sregs->cr3, sregs->cr4);
218 fprintf(stream, "%*scr8: 0x%.16llx efer: 0x%.16llx "
219 "apic_base: 0x%.16llx\n",
220 indent, "",
221 sregs->cr8, sregs->efer, sregs->apic_base);
222
223 fprintf(stream, "%*sinterrupt_bitmap:\n", indent, "");
224 for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++) {
225 fprintf(stream, "%*s%.16llx\n", indent + 2, "",
226 sregs->interrupt_bitmap[i]);
227 }
228}
229
230void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
231{
232 int rc;
233
234 TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
235 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
236
237 /* If needed, create page map l4 table. */
238 if (!vm->pgd_created) {
239 vm_paddr_t paddr = vm_phy_page_alloc(vm,
240 KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
241 vm->pgd = paddr;
242
243 /* Set pointer to pgd tables in all the VCPUs that
244 * have already been created. Future VCPUs will have
245 * the value set as each one is created.
246 */
247 for (struct vcpu *vcpu = vm->vcpu_head; vcpu;
248 vcpu = vcpu->next) {
249 struct kvm_sregs sregs;
250
251 /* Obtain the current system register settings */
252 vcpu_sregs_get(vm, vcpu->id, &sregs);
253
254 /* Set and store the pointer to the start of the
255 * pgd tables.
256 */
257 sregs.cr3 = vm->pgd;
258 vcpu_sregs_set(vm, vcpu->id, &sregs);
259 }
260
261 vm->pgd_created = true;
262 }
263}
264
265/* VM Virtual Page Map
266 *
267 * Input Args:
268 * vm - Virtual Machine
269 * vaddr - VM Virtual Address
270 * paddr - VM Physical Address
271 * pgd_memslot - Memory region slot for new virtual translation tables
272 *
273 * Output Args: None
274 *
275 * Return: None
276 *
277 * Within the VM given by vm, creates a virtual translation for the page
278 * starting at vaddr to the page starting at paddr.
279 */
280void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
281 uint32_t pgd_memslot)
282{
283 uint16_t index[4];
284 struct pageMapL4Entry *pml4e;
285
286 TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
287 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
288
289 TEST_ASSERT((vaddr % vm->page_size) == 0,
290 "Virtual address not on page boundary,\n"
291 " vaddr: 0x%lx vm->page_size: 0x%x",
292 vaddr, vm->page_size);
293 TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
294 (vaddr >> vm->page_shift)),
295 "Invalid virtual address, vaddr: 0x%lx",
296 vaddr);
297 TEST_ASSERT((paddr % vm->page_size) == 0,
298 "Physical address not on page boundary,\n"
299 " paddr: 0x%lx vm->page_size: 0x%x",
300 paddr, vm->page_size);
301 TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
302 "Physical address beyond beyond maximum supported,\n"
303 " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
304 paddr, vm->max_gfn, vm->page_size);
305
306 index[0] = (vaddr >> 12) & 0x1ffu;
307 index[1] = (vaddr >> 21) & 0x1ffu;
308 index[2] = (vaddr >> 30) & 0x1ffu;
309 index[3] = (vaddr >> 39) & 0x1ffu;
310
311 /* Allocate page directory pointer table if not present. */
312 pml4e = addr_gpa2hva(vm, vm->pgd);
313 if (!pml4e[index[3]].present) {
314 pml4e[index[3]].address = vm_phy_page_alloc(vm,
315 KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
316 >> vm->page_shift;
317 pml4e[index[3]].writable = true;
318 pml4e[index[3]].present = true;
319 }
320
321 /* Allocate page directory table if not present. */
322 struct pageDirectoryPointerEntry *pdpe;
323 pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
324 if (!pdpe[index[2]].present) {
325 pdpe[index[2]].address = vm_phy_page_alloc(vm,
326 KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
327 >> vm->page_shift;
328 pdpe[index[2]].writable = true;
329 pdpe[index[2]].present = true;
330 }
331
332 /* Allocate page table if not present. */
333 struct pageDirectoryEntry *pde;
334 pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
335 if (!pde[index[1]].present) {
336 pde[index[1]].address = vm_phy_page_alloc(vm,
337 KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
338 >> vm->page_shift;
339 pde[index[1]].writable = true;
340 pde[index[1]].present = true;
341 }
342
343 /* Fill in page table entry. */
344 struct pageTableEntry *pte;
345 pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
346 pte[index[0]].address = paddr >> vm->page_shift;
347 pte[index[0]].writable = true;
348 pte[index[0]].present = 1;
349}
350
351/* Virtual Translation Tables Dump
352 *
353 * Input Args:
354 * vm - Virtual Machine
355 * indent - Left margin indent amount
356 *
357 * Output Args:
358 * stream - Output FILE stream
359 *
360 * Return: None
361 *
362 * Dumps to the FILE stream given by stream, the contents of all the
363 * virtual translation tables for the VM given by vm.
364 */
365void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
366{
367 struct pageMapL4Entry *pml4e, *pml4e_start;
368 struct pageDirectoryPointerEntry *pdpe, *pdpe_start;
369 struct pageDirectoryEntry *pde, *pde_start;
370 struct pageTableEntry *pte, *pte_start;
371
372 if (!vm->pgd_created)
373 return;
374
375 fprintf(stream, "%*s "
376 " no\n", indent, "");
377 fprintf(stream, "%*s index hvaddr gpaddr "
378 "addr w exec dirty\n",
379 indent, "");
380 pml4e_start = (struct pageMapL4Entry *) addr_gpa2hva(vm,
381 vm->pgd);
382 for (uint16_t n1 = 0; n1 <= 0x1ffu; n1++) {
383 pml4e = &pml4e_start[n1];
384 if (!pml4e->present)
385 continue;
386 fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10lx %u "
387 " %u\n",
388 indent, "",
389 pml4e - pml4e_start, pml4e,
390 addr_hva2gpa(vm, pml4e), (uint64_t) pml4e->address,
391 pml4e->writable, pml4e->execute_disable);
392
393 pdpe_start = addr_gpa2hva(vm, pml4e->address
394 * vm->page_size);
395 for (uint16_t n2 = 0; n2 <= 0x1ffu; n2++) {
396 pdpe = &pdpe_start[n2];
397 if (!pdpe->present)
398 continue;
399 fprintf(stream, "%*spdpe 0x%-3zx %p 0x%-12lx 0x%-10lx "
400 "%u %u\n",
401 indent, "",
402 pdpe - pdpe_start, pdpe,
403 addr_hva2gpa(vm, pdpe),
404 (uint64_t) pdpe->address, pdpe->writable,
405 pdpe->execute_disable);
406
407 pde_start = addr_gpa2hva(vm,
408 pdpe->address * vm->page_size);
409 for (uint16_t n3 = 0; n3 <= 0x1ffu; n3++) {
410 pde = &pde_start[n3];
411 if (!pde->present)
412 continue;
413 fprintf(stream, "%*spde 0x%-3zx %p "
414 "0x%-12lx 0x%-10lx %u %u\n",
415 indent, "", pde - pde_start, pde,
416 addr_hva2gpa(vm, pde),
417 (uint64_t) pde->address, pde->writable,
418 pde->execute_disable);
419
420 pte_start = addr_gpa2hva(vm,
421 pde->address * vm->page_size);
422 for (uint16_t n4 = 0; n4 <= 0x1ffu; n4++) {
423 pte = &pte_start[n4];
424 if (!pte->present)
425 continue;
426 fprintf(stream, "%*spte 0x%-3zx %p "
427 "0x%-12lx 0x%-10lx %u %u "
428 " %u 0x%-10lx\n",
429 indent, "",
430 pte - pte_start, pte,
431 addr_hva2gpa(vm, pte),
432 (uint64_t) pte->address,
433 pte->writable,
434 pte->execute_disable,
435 pte->dirty,
436 ((uint64_t) n1 << 27)
437 | ((uint64_t) n2 << 18)
438 | ((uint64_t) n3 << 9)
439 | ((uint64_t) n4));
440 }
441 }
442 }
443 }
444}
445
446/* Set Unusable Segment
447 *
448 * Input Args: None
449 *
450 * Output Args:
451 * segp - Pointer to segment register
452 *
453 * Return: None
454 *
455 * Sets the segment register pointed to by segp to an unusable state.
456 */
457static void kvm_seg_set_unusable(struct kvm_segment *segp)
458{
459 memset(segp, 0, sizeof(*segp));
460 segp->unusable = true;
461}
462
463/* Set Long Mode Flat Kernel Code Segment
464 *
465 * Input Args:
466 * selector - selector value
467 *
468 * Output Args:
469 * segp - Pointer to KVM segment
470 *
471 * Return: None
472 *
473 * Sets up the KVM segment pointed to by segp, to be a code segment
474 * with the selector value given by selector.
475 */
476static void kvm_seg_set_kernel_code_64bit(uint16_t selector,
477 struct kvm_segment *segp)
478{
479 memset(segp, 0, sizeof(*segp));
480 segp->selector = selector;
481 segp->limit = 0xFFFFFFFFu;
482 segp->s = 0x1; /* kTypeCodeData */
483 segp->type = 0x08 | 0x01 | 0x02; /* kFlagCode | kFlagCodeAccessed
484 * | kFlagCodeReadable
485 */
486 segp->g = true;
487 segp->l = true;
488 segp->present = 1;
489}
490
491/* Set Long Mode Flat Kernel Data Segment
492 *
493 * Input Args:
494 * selector - selector value
495 *
496 * Output Args:
497 * segp - Pointer to KVM segment
498 *
499 * Return: None
500 *
501 * Sets up the KVM segment pointed to by segp, to be a data segment
502 * with the selector value given by selector.
503 */
504static void kvm_seg_set_kernel_data_64bit(uint16_t selector,
505 struct kvm_segment *segp)
506{
507 memset(segp, 0, sizeof(*segp));
508 segp->selector = selector;
509 segp->limit = 0xFFFFFFFFu;
510 segp->s = 0x1; /* kTypeCodeData */
511 segp->type = 0x00 | 0x01 | 0x02; /* kFlagData | kFlagDataAccessed
512 * | kFlagDataWritable
513 */
514 segp->g = true;
515 segp->present = true;
516}
517
518/* Address Guest Virtual to Guest Physical
519 *
520 * Input Args:
521 * vm - Virtual Machine
522 * gpa - VM virtual address
523 *
524 * Output Args: None
525 *
526 * Return:
527 * Equivalent VM physical address
528 *
529 * Translates the VM virtual address given by gva to a VM physical
530 * address and then locates the memory region containing the VM
531 * physical address, within the VM given by vm. When found, the host
532 * virtual address providing the memory to the vm physical address is returned.
533 * A TEST_ASSERT failure occurs if no region containing translated
534 * VM virtual address exists.
535 */
536vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
537{
538 uint16_t index[4];
539 struct pageMapL4Entry *pml4e;
540 struct pageDirectoryPointerEntry *pdpe;
541 struct pageDirectoryEntry *pde;
542 struct pageTableEntry *pte;
543 void *hva;
544
545 TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
546 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
547
548 index[0] = (gva >> 12) & 0x1ffu;
549 index[1] = (gva >> 21) & 0x1ffu;
550 index[2] = (gva >> 30) & 0x1ffu;
551 index[3] = (gva >> 39) & 0x1ffu;
552
553 if (!vm->pgd_created)
554 goto unmapped_gva;
555 pml4e = addr_gpa2hva(vm, vm->pgd);
556 if (!pml4e[index[3]].present)
557 goto unmapped_gva;
558
559 pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
560 if (!pdpe[index[2]].present)
561 goto unmapped_gva;
562
563 pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
564 if (!pde[index[1]].present)
565 goto unmapped_gva;
566
567 pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
568 if (!pte[index[0]].present)
569 goto unmapped_gva;
570
571 return (pte[index[0]].address * vm->page_size) + (gva & 0xfffu);
572
573unmapped_gva:
574 TEST_ASSERT(false, "No mapping for vm virtual address, "
575 "gva: 0x%lx", gva);
576}
577
578void vcpu_setup(struct kvm_vm *vm, int vcpuid)
579{
580 struct kvm_sregs sregs;
581
582 /* Set mode specific system register values. */
583 vcpu_sregs_get(vm, vcpuid, &sregs);
584
585 switch (vm->mode) {
586 case VM_MODE_FLAT48PG:
587 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
588 sregs.cr4 |= X86_CR4_PAE;
589 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
590
591 kvm_seg_set_unusable(&sregs.ldt);
592 kvm_seg_set_kernel_code_64bit(0x8, &sregs.cs);
593 kvm_seg_set_kernel_data_64bit(0x10, &sregs.ds);
594 kvm_seg_set_kernel_data_64bit(0x10, &sregs.es);
595 break;
596
597 default:
598 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
599 }
600 vcpu_sregs_set(vm, vcpuid, &sregs);
601
602 /* If virtual translation table have been setup, set system register
603 * to point to the tables. It's okay if they haven't been setup yet,
604 * in that the code that sets up the virtual translation tables, will
605 * go back through any VCPUs that have already been created and set
606 * their values.
607 */
608 if (vm->pgd_created) {
609 struct kvm_sregs sregs;
610
611 vcpu_sregs_get(vm, vcpuid, &sregs);
612
613 sregs.cr3 = vm->pgd;
614 vcpu_sregs_set(vm, vcpuid, &sregs);
615 }
616}
617/* Adds a vCPU with reasonable defaults (i.e., a stack)
618 *
619 * Input Args:
620 * vcpuid - The id of the VCPU to add to the VM.
621 * guest_code - The vCPU's entry point
622 */
623void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
624{
625 struct kvm_mp_state mp_state;
626 struct kvm_regs regs;
627 vm_vaddr_t stack_vaddr;
628 stack_vaddr = vm_vaddr_alloc(vm, DEFAULT_STACK_PGS * getpagesize(),
629 DEFAULT_GUEST_STACK_VADDR_MIN, 0, 0);
630
631 /* Create VCPU */
632 vm_vcpu_add(vm, vcpuid);
633
634 /* Setup guest general purpose registers */
635 vcpu_regs_get(vm, vcpuid, &regs);
636 regs.rflags = regs.rflags | 0x2;
637 regs.rsp = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize());
638 regs.rip = (unsigned long) guest_code;
639 vcpu_regs_set(vm, vcpuid, &regs);
640
641 /* Setup the MP state */
642 mp_state.mp_state = 0;
643 vcpu_set_mp_state(vm, vcpuid, &mp_state);
644}
645
646/* VM VCPU CPUID Set
647 *
648 * Input Args:
649 * vm - Virtual Machine
650 * vcpuid - VCPU id
651 * cpuid - The CPUID values to set.
652 *
653 * Output Args: None
654 *
655 * Return: void
656 *
657 * Set the VCPU's CPUID.
658 */
659void vcpu_set_cpuid(struct kvm_vm *vm,
660 uint32_t vcpuid, struct kvm_cpuid2 *cpuid)
661{
662 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
663 int rc;
664
665 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
666
667 rc = ioctl(vcpu->fd, KVM_SET_CPUID2, cpuid);
668 TEST_ASSERT(rc == 0, "KVM_SET_CPUID2 failed, rc: %i errno: %i",
669 rc, errno);
670
671}
672/* Create a VM with reasonable defaults
673 *
674 * Input Args:
675 * vcpuid - The id of the single VCPU to add to the VM.
676 * guest_code - The vCPU's entry point
677 *
678 * Output Args: None
679 *
680 * Return:
681 * Pointer to opaque structure that describes the created VM.
682 */
683struct kvm_vm *vm_create_default(uint32_t vcpuid, void *guest_code)
684{
685 struct kvm_vm *vm;
686
687 /* Create VM */
688 vm = vm_create(VM_MODE_FLAT48PG, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
689
690 /* Setup guest code */
691 kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
692
693 /* Setup IRQ Chip */
694 vm_create_irqchip(vm);
695
696 /* Add the first vCPU. */
697 vm_vcpu_add_default(vm, vcpuid, guest_code);
698
699 return vm;
700}
diff --git a/tools/testing/selftests/kvm/set_sregs_test.c b/tools/testing/selftests/kvm/set_sregs_test.c
new file mode 100644
index 000000000000..090fd3f19352
--- /dev/null
+++ b/tools/testing/selftests/kvm/set_sregs_test.c
@@ -0,0 +1,54 @@
1/*
2 * KVM_SET_SREGS tests
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 * This is a regression test for the bug fixed by the following commit:
9 * d3802286fa0f ("kvm: x86: Disallow illegal IA32_APIC_BASE MSR values")
10 *
11 * That bug allowed a user-mode program that called the KVM_SET_SREGS
12 * ioctl to put a VCPU's local APIC into an invalid state.
13 *
14 */
15#define _GNU_SOURCE /* for program_invocation_short_name */
16#include <fcntl.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/ioctl.h>
21
22#include "test_util.h"
23
24#include "kvm_util.h"
25#include "x86.h"
26
27#define VCPU_ID 5
28
29int main(int argc, char *argv[])
30{
31 struct kvm_sregs sregs;
32 struct kvm_vm *vm;
33 int rc;
34
35 /* Tell stdout not to buffer its content */
36 setbuf(stdout, NULL);
37
38 /* Create VM */
39 vm = vm_create_default(VCPU_ID, NULL);
40
41 vcpu_sregs_get(vm, VCPU_ID, &sregs);
42 sregs.apic_base = 1 << 10;
43 rc = _vcpu_sregs_set(vm, VCPU_ID, &sregs);
44 TEST_ASSERT(rc, "Set IA32_APIC_BASE to %llx (invalid)",
45 sregs.apic_base);
46 sregs.apic_base = 1 << 11;
47 rc = _vcpu_sregs_set(vm, VCPU_ID, &sregs);
48 TEST_ASSERT(!rc, "Couldn't set IA32_APIC_BASE to %llx (valid)",
49 sregs.apic_base);
50
51 kvm_vm_free(vm);
52
53 return 0;
54}
diff --git a/tools/testing/selftests/kvm/sync_regs_test.c b/tools/testing/selftests/kvm/sync_regs_test.c
new file mode 100644
index 000000000000..eae1ece3c31b
--- /dev/null
+++ b/tools/testing/selftests/kvm/sync_regs_test.c
@@ -0,0 +1,254 @@
1/*
2 * Test for x86 KVM_CAP_SYNC_REGS
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 * Verifies expected behavior of x86 KVM_CAP_SYNC_REGS functionality,
9 * including requesting an invalid register set, updates to/from values
10 * in kvm_run.s.regs when kvm_valid_regs and kvm_dirty_regs are toggled.
11 */
12
13#define _GNU_SOURCE /* for program_invocation_short_name */
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <sys/ioctl.h>
19
20#include "test_util.h"
21#include "kvm_util.h"
22#include "x86.h"
23
24#define VCPU_ID 5
25#define PORT_HOST_SYNC 0x1000
26
27static void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
28{
29 __asm__ __volatile__("in %[port], %%al"
30 :
31 : [port]"d"(port), "D"(arg0), "S"(arg1)
32 : "rax");
33}
34
35#define exit_to_l0(_port, _arg0, _arg1) \
36 __exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
37
38#define GUEST_ASSERT(_condition) do { \
39 if (!(_condition)) \
40 exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition, 0);\
41} while (0)
42
43void guest_code(void)
44{
45 for (;;) {
46 exit_to_l0(PORT_HOST_SYNC, "hello", 0);
47 asm volatile ("inc %r11");
48 }
49}
50
51static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
52{
53#define REG_COMPARE(reg) \
54 TEST_ASSERT(left->reg == right->reg, \
55 "Register " #reg \
56 " values did not match: 0x%llx, 0x%llx\n", \
57 left->reg, right->reg)
58 REG_COMPARE(rax);
59 REG_COMPARE(rbx);
60 REG_COMPARE(rcx);
61 REG_COMPARE(rdx);
62 REG_COMPARE(rsi);
63 REG_COMPARE(rdi);
64 REG_COMPARE(rsp);
65 REG_COMPARE(rbp);
66 REG_COMPARE(r8);
67 REG_COMPARE(r9);
68 REG_COMPARE(r10);
69 REG_COMPARE(r11);
70 REG_COMPARE(r12);
71 REG_COMPARE(r13);
72 REG_COMPARE(r14);
73 REG_COMPARE(r15);
74 REG_COMPARE(rip);
75 REG_COMPARE(rflags);
76#undef REG_COMPARE
77}
78
79static void compare_sregs(struct kvm_sregs *left, struct kvm_sregs *right)
80{
81}
82
83static void compare_vcpu_events(struct kvm_vcpu_events *left,
84 struct kvm_vcpu_events *right)
85{
86}
87
88#define TEST_SYNC_FIELDS (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS)
89#define INVALID_SYNC_FIELD 0x80000000
90
91int main(int argc, char *argv[])
92{
93 struct kvm_vm *vm;
94 struct kvm_run *run;
95 struct kvm_regs regs;
96 struct kvm_sregs sregs;
97 struct kvm_vcpu_events events;
98 int rv, cap;
99
100 /* Tell stdout not to buffer its content */
101 setbuf(stdout, NULL);
102
103 cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
104 if ((cap & TEST_SYNC_FIELDS) != TEST_SYNC_FIELDS) {
105 fprintf(stderr, "KVM_CAP_SYNC_REGS not supported, skipping test\n");
106 exit(KSFT_SKIP);
107 }
108 if ((cap & INVALID_SYNC_FIELD) != 0) {
109 fprintf(stderr, "The \"invalid\" field is not invalid, skipping test\n");
110 exit(KSFT_SKIP);
111 }
112
113 /* Create VM */
114 vm = vm_create_default(VCPU_ID, guest_code);
115
116 run = vcpu_state(vm, VCPU_ID);
117
118 /* Request reading invalid register set from VCPU. */
119 run->kvm_valid_regs = INVALID_SYNC_FIELD;
120 rv = _vcpu_run(vm, VCPU_ID);
121 TEST_ASSERT(rv < 0 && errno == EINVAL,
122 "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
123 rv);
124 vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
125
126 run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
127 rv = _vcpu_run(vm, VCPU_ID);
128 TEST_ASSERT(rv < 0 && errno == EINVAL,
129 "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
130 rv);
131 vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
132
133 /* Request setting invalid register set into VCPU. */
134 run->kvm_dirty_regs = INVALID_SYNC_FIELD;
135 rv = _vcpu_run(vm, VCPU_ID);
136 TEST_ASSERT(rv < 0 && errno == EINVAL,
137 "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
138 rv);
139 vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
140
141 run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
142 rv = _vcpu_run(vm, VCPU_ID);
143 TEST_ASSERT(rv < 0 && errno == EINVAL,
144 "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
145 rv);
146 vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
147
148 /* Request and verify all valid register sets. */
149 /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
150 run->kvm_valid_regs = TEST_SYNC_FIELDS;
151 rv = _vcpu_run(vm, VCPU_ID);
152 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
153 "Unexpected exit reason: %u (%s),\n",
154 run->exit_reason,
155 exit_reason_str(run->exit_reason));
156
157 vcpu_regs_get(vm, VCPU_ID, &regs);
158 compare_regs(&regs, &run->s.regs.regs);
159
160 vcpu_sregs_get(vm, VCPU_ID, &sregs);
161 compare_sregs(&sregs, &run->s.regs.sregs);
162
163 vcpu_events_get(vm, VCPU_ID, &events);
164 compare_vcpu_events(&events, &run->s.regs.events);
165
166 /* Set and verify various register values. */
167 run->s.regs.regs.r11 = 0xBAD1DEA;
168 run->s.regs.sregs.apic_base = 1 << 11;
169 /* TODO run->s.regs.events.XYZ = ABC; */
170
171 run->kvm_valid_regs = TEST_SYNC_FIELDS;
172 run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS;
173 rv = _vcpu_run(vm, VCPU_ID);
174 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
175 "Unexpected exit reason: %u (%s),\n",
176 run->exit_reason,
177 exit_reason_str(run->exit_reason));
178 TEST_ASSERT(run->s.regs.regs.r11 == 0xBAD1DEA + 1,
179 "r11 sync regs value incorrect 0x%llx.",
180 run->s.regs.regs.r11);
181 TEST_ASSERT(run->s.regs.sregs.apic_base == 1 << 11,
182 "apic_base sync regs value incorrect 0x%llx.",
183 run->s.regs.sregs.apic_base);
184
185 vcpu_regs_get(vm, VCPU_ID, &regs);
186 compare_regs(&regs, &run->s.regs.regs);
187
188 vcpu_sregs_get(vm, VCPU_ID, &sregs);
189 compare_sregs(&sregs, &run->s.regs.sregs);
190
191 vcpu_events_get(vm, VCPU_ID, &events);
192 compare_vcpu_events(&events, &run->s.regs.events);
193
194 /* Clear kvm_dirty_regs bits, verify new s.regs values are
195 * overwritten with existing guest values.
196 */
197 run->kvm_valid_regs = TEST_SYNC_FIELDS;
198 run->kvm_dirty_regs = 0;
199 run->s.regs.regs.r11 = 0xDEADBEEF;
200 rv = _vcpu_run(vm, VCPU_ID);
201 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
202 "Unexpected exit reason: %u (%s),\n",
203 run->exit_reason,
204 exit_reason_str(run->exit_reason));
205 TEST_ASSERT(run->s.regs.regs.r11 != 0xDEADBEEF,
206 "r11 sync regs value incorrect 0x%llx.",
207 run->s.regs.regs.r11);
208
209 /* Clear kvm_valid_regs bits and kvm_dirty_bits.
210 * Verify s.regs values are not overwritten with existing guest values
211 * and that guest values are not overwritten with kvm_sync_regs values.
212 */
213 run->kvm_valid_regs = 0;
214 run->kvm_dirty_regs = 0;
215 run->s.regs.regs.r11 = 0xAAAA;
216 regs.r11 = 0xBAC0;
217 vcpu_regs_set(vm, VCPU_ID, &regs);
218 rv = _vcpu_run(vm, VCPU_ID);
219 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
220 "Unexpected exit reason: %u (%s),\n",
221 run->exit_reason,
222 exit_reason_str(run->exit_reason));
223 TEST_ASSERT(run->s.regs.regs.r11 == 0xAAAA,
224 "r11 sync regs value incorrect 0x%llx.",
225 run->s.regs.regs.r11);
226 vcpu_regs_get(vm, VCPU_ID, &regs);
227 TEST_ASSERT(regs.r11 == 0xBAC0 + 1,
228 "r11 guest value incorrect 0x%llx.",
229 regs.r11);
230
231 /* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
232 * with existing guest values but that guest values are overwritten
233 * with kvm_sync_regs values.
234 */
235 run->kvm_valid_regs = 0;
236 run->kvm_dirty_regs = TEST_SYNC_FIELDS;
237 run->s.regs.regs.r11 = 0xBBBB;
238 rv = _vcpu_run(vm, VCPU_ID);
239 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
240 "Unexpected exit reason: %u (%s),\n",
241 run->exit_reason,
242 exit_reason_str(run->exit_reason));
243 TEST_ASSERT(run->s.regs.regs.r11 == 0xBBBB,
244 "r11 sync regs value incorrect 0x%llx.",
245 run->s.regs.regs.r11);
246 vcpu_regs_get(vm, VCPU_ID, &regs);
247 TEST_ASSERT(regs.r11 == 0xBBBB + 1,
248 "r11 guest value incorrect 0x%llx.",
249 regs.r11);
250
251 kvm_vm_free(vm);
252
253 return 0;
254}
diff --git a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
new file mode 100644
index 000000000000..aaa633263b2c
--- /dev/null
+++ b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
@@ -0,0 +1,231 @@
1/*
2 * gtests/tests/vmx_tsc_adjust_test.c
3 *
4 * Copyright (C) 2018, Google LLC.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2.
7 *
8 *
9 * IA32_TSC_ADJUST test
10 *
11 * According to the SDM, "if an execution of WRMSR to the
12 * IA32_TIME_STAMP_COUNTER MSR adds (or subtracts) value X from the TSC,
13 * the logical processor also adds (or subtracts) value X from the
14 * IA32_TSC_ADJUST MSR.
15 *
16 * Note that when L1 doesn't intercept writes to IA32_TSC, a
17 * WRMSR(IA32_TSC) from L2 sets L1's TSC value, not L2's perceived TSC
18 * value.
19 *
20 * This test verifies that this unusual case is handled correctly.
21 */
22
23#include "test_util.h"
24#include "kvm_util.h"
25#include "x86.h"
26#include "vmx.h"
27
28#include <string.h>
29#include <sys/ioctl.h>
30
31#ifndef MSR_IA32_TSC_ADJUST
32#define MSR_IA32_TSC_ADJUST 0x3b
33#endif
34
35#define PAGE_SIZE 4096
36#define VCPU_ID 5
37
38#define TSC_ADJUST_VALUE (1ll << 32)
39#define TSC_OFFSET_VALUE -(1ll << 48)
40
41enum {
42 PORT_ABORT = 0x1000,
43 PORT_REPORT,
44 PORT_DONE,
45};
46
47struct vmx_page {
48 vm_vaddr_t virt;
49 vm_paddr_t phys;
50};
51
52enum {
53 VMXON_PAGE = 0,
54 VMCS_PAGE,
55 MSR_BITMAP_PAGE,
56
57 NUM_VMX_PAGES,
58};
59
60struct kvm_single_msr {
61 struct kvm_msrs header;
62 struct kvm_msr_entry entry;
63} __attribute__((packed));
64
65/* The virtual machine object. */
66static struct kvm_vm *vm;
67
68/* Array of vmx_page descriptors that is shared with the guest. */
69struct vmx_page *vmx_pages;
70
71#define exit_to_l0(_port, _arg) do_exit_to_l0(_port, (unsigned long) (_arg))
72static void do_exit_to_l0(uint16_t port, unsigned long arg)
73{
74 __asm__ __volatile__("in %[port], %%al"
75 :
76 : [port]"d"(port), "D"(arg)
77 : "rax");
78}
79
80
81#define GUEST_ASSERT(_condition) do { \
82 if (!(_condition)) \
83 exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition); \
84} while (0)
85
86static void check_ia32_tsc_adjust(int64_t max)
87{
88 int64_t adjust;
89
90 adjust = rdmsr(MSR_IA32_TSC_ADJUST);
91 exit_to_l0(PORT_REPORT, adjust);
92 GUEST_ASSERT(adjust <= max);
93}
94
95static void l2_guest_code(void)
96{
97 uint64_t l1_tsc = rdtsc() - TSC_OFFSET_VALUE;
98
99 wrmsr(MSR_IA32_TSC, l1_tsc - TSC_ADJUST_VALUE);
100 check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
101
102 /* Exit to L1 */
103 __asm__ __volatile__("vmcall");
104}
105
106static void l1_guest_code(struct vmx_page *vmx_pages)
107{
108#define L2_GUEST_STACK_SIZE 64
109 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
110 uint32_t control;
111 uintptr_t save_cr3;
112
113 GUEST_ASSERT(rdtsc() < TSC_ADJUST_VALUE);
114 wrmsr(MSR_IA32_TSC, rdtsc() - TSC_ADJUST_VALUE);
115 check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
116
117 prepare_for_vmx_operation();
118
119 /* Enter VMX root operation. */
120 *(uint32_t *)vmx_pages[VMXON_PAGE].virt = vmcs_revision();
121 GUEST_ASSERT(!vmxon(vmx_pages[VMXON_PAGE].phys));
122
123 /* Load a VMCS. */
124 *(uint32_t *)vmx_pages[VMCS_PAGE].virt = vmcs_revision();
125 GUEST_ASSERT(!vmclear(vmx_pages[VMCS_PAGE].phys));
126 GUEST_ASSERT(!vmptrld(vmx_pages[VMCS_PAGE].phys));
127
128 /* Prepare the VMCS for L2 execution. */
129 prepare_vmcs(l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]);
130 control = vmreadz(CPU_BASED_VM_EXEC_CONTROL);
131 control |= CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETING;
132 vmwrite(CPU_BASED_VM_EXEC_CONTROL, control);
133 vmwrite(MSR_BITMAP, vmx_pages[MSR_BITMAP_PAGE].phys);
134 vmwrite(TSC_OFFSET, TSC_OFFSET_VALUE);
135
136 /* Jump into L2. First, test failure to load guest CR3. */
137 save_cr3 = vmreadz(GUEST_CR3);
138 vmwrite(GUEST_CR3, -1ull);
139 GUEST_ASSERT(!vmlaunch());
140 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) ==
141 (EXIT_REASON_FAILED_VMENTRY | EXIT_REASON_INVALID_STATE));
142 check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
143 vmwrite(GUEST_CR3, save_cr3);
144
145 GUEST_ASSERT(!vmlaunch());
146 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
147
148 check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
149
150 exit_to_l0(PORT_DONE, 0);
151}
152
153static void allocate_vmx_page(struct vmx_page *page)
154{
155 vm_vaddr_t virt;
156
157 virt = vm_vaddr_alloc(vm, PAGE_SIZE, 0, 0, 0);
158 memset(addr_gva2hva(vm, virt), 0, PAGE_SIZE);
159
160 page->virt = virt;
161 page->phys = addr_gva2gpa(vm, virt);
162}
163
164static vm_vaddr_t allocate_vmx_pages(void)
165{
166 vm_vaddr_t vmx_pages_vaddr;
167 int i;
168
169 vmx_pages_vaddr = vm_vaddr_alloc(
170 vm, sizeof(struct vmx_page) * NUM_VMX_PAGES, 0, 0, 0);
171
172 vmx_pages = (void *) addr_gva2hva(vm, vmx_pages_vaddr);
173
174 for (i = 0; i < NUM_VMX_PAGES; i++)
175 allocate_vmx_page(&vmx_pages[i]);
176
177 return vmx_pages_vaddr;
178}
179
180void report(int64_t val)
181{
182 printf("IA32_TSC_ADJUST is %ld (%lld * TSC_ADJUST_VALUE + %lld).\n",
183 val, val / TSC_ADJUST_VALUE, val % TSC_ADJUST_VALUE);
184}
185
186int main(int argc, char *argv[])
187{
188 vm_vaddr_t vmx_pages_vaddr;
189 struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
190
191 if (!(entry->ecx & CPUID_VMX)) {
192 fprintf(stderr, "nested VMX not enabled, skipping test\n");
193 exit(KSFT_SKIP);
194 }
195
196 vm = vm_create_default_vmx(VCPU_ID, (void *) l1_guest_code);
197
198 /* Allocate VMX pages and shared descriptors (vmx_pages). */
199 vmx_pages_vaddr = allocate_vmx_pages();
200 vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_vaddr);
201
202 for (;;) {
203 volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
204 struct kvm_regs regs;
205
206 vcpu_run(vm, VCPU_ID);
207 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
208 "Got exit_reason other than KVM_EXIT_IO: %u (%s),\n",
209 run->exit_reason,
210 exit_reason_str(run->exit_reason));
211
212 vcpu_regs_get(vm, VCPU_ID, &regs);
213
214 switch (run->io.port) {
215 case PORT_ABORT:
216 TEST_ASSERT(false, "%s", (const char *) regs.rdi);
217 /* NOT REACHED */
218 case PORT_REPORT:
219 report(regs.rdi);
220 break;
221 case PORT_DONE:
222 goto done;
223 default:
224 TEST_ASSERT(false, "Unknown port 0x%x.", run->io.port);
225 }
226 }
227
228 kvm_vm_free(vm);
229done:
230 return 0;
231}
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
index 7de482a0519d..c1b1a4dc6a96 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -20,9 +20,10 @@ all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
20 20
21.ONESHELL: 21.ONESHELL:
22define RUN_TESTS 22define RUN_TESTS
23 @test_num=`echo 0`; 23 @export KSFT_TAP_LEVEL=`echo 1`; \
24 @echo "TAP version 13"; 24 test_num=`echo 0`; \
25 @for TEST in $(1); do \ 25 echo "TAP version 13"; \
26 for TEST in $(1); do \
26 BASENAME_TEST=`basename $$TEST`; \ 27 BASENAME_TEST=`basename $$TEST`; \
27 test_num=`echo $$test_num+1 | bc`; \ 28 test_num=`echo $$test_num+1 | bc`; \
28 echo "selftests: $$BASENAME_TEST"; \ 29 echo "selftests: $$BASENAME_TEST"; \
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index d7c30d366935..3ff81a478dbe 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -5,7 +5,8 @@ CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
5CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
6 6
7TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh 7TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
8TEST_PROGS += fib_tests.sh 8TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh
9TEST_PROGS_EXTENDED := in_netns.sh
9TEST_GEN_FILES = socket 10TEST_GEN_FILES = socket
10TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy 11TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
11TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa 12TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config
index 7177bea1fdfa..6a75a3ea44ad 100644
--- a/tools/testing/selftests/net/config
+++ b/tools/testing/selftests/net/config
@@ -2,3 +2,8 @@ CONFIG_USER_NS=y
2CONFIG_BPF_SYSCALL=y 2CONFIG_BPF_SYSCALL=y
3CONFIG_TEST_BPF=m 3CONFIG_TEST_BPF=m
4CONFIG_NUMA=y 4CONFIG_NUMA=y
5CONFIG_NET_VRF=y
6CONFIG_NET_L3_MASTER_DEV=y
7CONFIG_IPV6=y
8CONFIG_IPV6_MULTIPLE_TABLES=y
9CONFIG_VETH=y
diff --git a/tools/testing/selftests/net/fib-onlink-tests.sh b/tools/testing/selftests/net/fib-onlink-tests.sh
new file mode 100755
index 000000000000..3991ad1a368d
--- /dev/null
+++ b/tools/testing/selftests/net/fib-onlink-tests.sh
@@ -0,0 +1,467 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# IPv4 and IPv6 onlink tests
5
6PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
7
8# Network interfaces
9# - odd in current namespace; even in peer ns
10declare -A NETIFS
11# default VRF
12NETIFS[p1]=veth1
13NETIFS[p2]=veth2
14NETIFS[p3]=veth3
15NETIFS[p4]=veth4
16# VRF
17NETIFS[p5]=veth5
18NETIFS[p6]=veth6
19NETIFS[p7]=veth7
20NETIFS[p8]=veth8
21
22# /24 network
23declare -A V4ADDRS
24V4ADDRS[p1]=169.254.1.1
25V4ADDRS[p2]=169.254.1.2
26V4ADDRS[p3]=169.254.3.1
27V4ADDRS[p4]=169.254.3.2
28V4ADDRS[p5]=169.254.5.1
29V4ADDRS[p6]=169.254.5.2
30V4ADDRS[p7]=169.254.7.1
31V4ADDRS[p8]=169.254.7.2
32
33# /64 network
34declare -A V6ADDRS
35V6ADDRS[p1]=2001:db8:101::1
36V6ADDRS[p2]=2001:db8:101::2
37V6ADDRS[p3]=2001:db8:301::1
38V6ADDRS[p4]=2001:db8:301::2
39V6ADDRS[p5]=2001:db8:501::1
40V6ADDRS[p6]=2001:db8:501::2
41V6ADDRS[p7]=2001:db8:701::1
42V6ADDRS[p8]=2001:db8:701::2
43
44# Test networks:
45# [1] = default table
46# [2] = VRF
47#
48# /32 host routes
49declare -A TEST_NET4
50TEST_NET4[1]=169.254.101
51TEST_NET4[2]=169.254.102
52# /128 host routes
53declare -A TEST_NET6
54TEST_NET6[1]=2001:db8:101
55TEST_NET6[2]=2001:db8:102
56
57# connected gateway
58CONGW[1]=169.254.1.254
59CONGW[2]=169.254.3.254
60CONGW[3]=169.254.5.254
61
62# recursive gateway
63RECGW4[1]=169.254.11.254
64RECGW4[2]=169.254.12.254
65RECGW6[1]=2001:db8:11::64
66RECGW6[2]=2001:db8:12::64
67
68# for v4 mapped to v6
69declare -A TEST_NET4IN6IN6
70TEST_NET4IN6[1]=10.1.1.254
71TEST_NET4IN6[2]=10.2.1.254
72
73# mcast address
74MCAST6=ff02::1
75
76
77PEER_NS=bart
78PEER_CMD="ip netns exec ${PEER_NS}"
79VRF=lisa
80VRF_TABLE=1101
81PBR_TABLE=101
82
83################################################################################
84# utilities
85
86log_test()
87{
88 local rc=$1
89 local expected=$2
90 local msg="$3"
91
92 if [ ${rc} -eq ${expected} ]; then
93 nsuccess=$((nsuccess+1))
94 printf "\n TEST: %-50s [ OK ]\n" "${msg}"
95 else
96 nfail=$((nfail+1))
97 printf "\n TEST: %-50s [FAIL]\n" "${msg}"
98 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
99 echo
100 echo "hit enter to continue, 'q' to quit"
101 read a
102 [ "$a" = "q" ] && exit 1
103 fi
104 fi
105}
106
107log_section()
108{
109 echo
110 echo "######################################################################"
111 echo "TEST SECTION: $*"
112 echo "######################################################################"
113}
114
115log_subsection()
116{
117 echo
118 echo "#########################################"
119 echo "TEST SUBSECTION: $*"
120}
121
122run_cmd()
123{
124 echo
125 echo "COMMAND: $*"
126 eval $*
127}
128
129get_linklocal()
130{
131 local dev=$1
132 local pfx
133 local addr
134
135 addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
136 awk '{
137 for (i = 3; i <= NF; ++i) {
138 if ($i ~ /^fe80/)
139 print $i
140 }
141 }'
142 )
143 addr=${addr/\/*}
144
145 [ -z "$addr" ] && return 1
146
147 echo $addr
148
149 return 0
150}
151
152################################################################################
153#
154
155setup()
156{
157 echo
158 echo "########################################"
159 echo "Configuring interfaces"
160
161 set -e
162
163 # create namespace
164 ip netns add ${PEER_NS}
165 ip -netns ${PEER_NS} li set lo up
166
167 # add vrf table
168 ip li add ${VRF} type vrf table ${VRF_TABLE}
169 ip li set ${VRF} up
170 ip ro add table ${VRF_TABLE} unreachable default
171 ip -6 ro add table ${VRF_TABLE} unreachable default
172
173 # create test interfaces
174 ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
175 ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
176 ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
177 ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
178
179 # enslave vrf interfaces
180 for n in 5 7; do
181 ip li set ${NETIFS[p${n}]} vrf ${VRF}
182 done
183
184 # add addresses
185 for n in 1 3 5 7; do
186 ip li set ${NETIFS[p${n}]} up
187 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
188 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
189 done
190
191 # move peer interfaces to namespace and add addresses
192 for n in 2 4 6 8; do
193 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
194 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
195 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
196 done
197
198 set +e
199
200 # let DAD complete - assume default of 1 probe
201 sleep 1
202}
203
204cleanup()
205{
206 # make sure we start from a clean slate
207 ip netns del ${PEER_NS} 2>/dev/null
208 for n in 1 3 5 7; do
209 ip link del ${NETIFS[p${n}]} 2>/dev/null
210 done
211 ip link del ${VRF} 2>/dev/null
212 ip ro flush table ${VRF_TABLE}
213 ip -6 ro flush table ${VRF_TABLE}
214}
215
216################################################################################
217# IPv4 tests
218#
219
220run_ip()
221{
222 local table="$1"
223 local prefix="$2"
224 local gw="$3"
225 local dev="$4"
226 local exp_rc="$5"
227 local desc="$6"
228
229 # dev arg may be empty
230 [ -n "${dev}" ] && dev="dev ${dev}"
231
232 run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
233 log_test $? ${exp_rc} "${desc}"
234}
235
236run_ip_mpath()
237{
238 local table="$1"
239 local prefix="$2"
240 local nh1="$3"
241 local nh2="$4"
242 local exp_rc="$5"
243 local desc="$6"
244
245 # dev arg may be empty
246 [ -n "${dev}" ] && dev="dev ${dev}"
247
248 run_cmd ip ro add table "${table}" "${prefix}"/32 \
249 nexthop via ${nh1} nexthop via ${nh2}
250 log_test $? ${exp_rc} "${desc}"
251}
252
253valid_onlink_ipv4()
254{
255 # - unicast connected, unicast recursive
256 #
257 log_subsection "default VRF - main table"
258
259 run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
260 run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"
261
262 log_subsection "VRF ${VRF}"
263
264 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
265 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
266
267 log_subsection "VRF device, PBR table"
268
269 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
270 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
271
272 # multipath version
273 #
274 log_subsection "default VRF - main table - multipath"
275
276 run_ip_mpath 254 ${TEST_NET4[1]}.5 \
277 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
278 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
279 0 "unicast connected - multipath"
280
281 run_ip_mpath 254 ${TEST_NET4[1]}.6 \
282 "${RECGW4[1]} dev ${NETIFS[p1]} onlink" \
283 "${RECGW4[2]} dev ${NETIFS[p3]} onlink" \
284 0 "unicast recursive - multipath"
285
286 run_ip_mpath 254 ${TEST_NET4[1]}.7 \
287 "${CONGW[1]} dev ${NETIFS[p1]}" \
288 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
289 0 "unicast connected - multipath onlink first only"
290
291 run_ip_mpath 254 ${TEST_NET4[1]}.8 \
292 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
293 "${CONGW[2]} dev ${NETIFS[p3]}" \
294 0 "unicast connected - multipath onlink second only"
295}
296
297invalid_onlink_ipv4()
298{
299 run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
300 "Invalid gw - local unicast address"
301
302 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
303 "Invalid gw - local unicast address, VRF"
304
305 run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"
306
307 run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \
308 "Gateway resolves to wrong nexthop device"
309
310 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \
311 "Gateway resolves to wrong nexthop device - VRF"
312}
313
314################################################################################
315# IPv6 tests
316#
317
318run_ip6()
319{
320 local table="$1"
321 local prefix="$2"
322 local gw="$3"
323 local dev="$4"
324 local exp_rc="$5"
325 local desc="$6"
326
327 # dev arg may be empty
328 [ -n "${dev}" ] && dev="dev ${dev}"
329
330 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
331 log_test $? ${exp_rc} "${desc}"
332}
333
334run_ip6_mpath()
335{
336 local table="$1"
337 local prefix="$2"
338 local opts="$3"
339 local nh1="$4"
340 local nh2="$5"
341 local exp_rc="$6"
342 local desc="$7"
343
344 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 "${opts}" \
345 nexthop via ${nh1} nexthop via ${nh2}
346 log_test $? ${exp_rc} "${desc}"
347}
348
349valid_onlink_ipv6()
350{
351 # - unicast connected, unicast recursive, v4-mapped
352 #
353 log_subsection "default VRF - main table"
354
355 run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
356 run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
357 run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"
358
359 log_subsection "VRF ${VRF}"
360
361 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
362 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
363 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
364
365 log_subsection "VRF device, PBR table"
366
367 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
368 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
369 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
370
371 # multipath version
372 #
373 log_subsection "default VRF - main table - multipath"
374
375 run_ip6_mpath 254 ${TEST_NET6[1]}::4 "onlink" \
376 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
377 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
378 0 "unicast connected - multipath onlink"
379
380 run_ip6_mpath 254 ${TEST_NET6[1]}::5 "onlink" \
381 "${RECGW6[1]} dev ${NETIFS[p1]}" \
382 "${RECGW6[2]} dev ${NETIFS[p3]}" \
383 0 "unicast recursive - multipath onlink"
384
385 run_ip6_mpath 254 ${TEST_NET6[1]}::6 "onlink" \
386 "::ffff:${TEST_NET4IN6[1]} dev ${NETIFS[p1]}" \
387 "::ffff:${TEST_NET4IN6[2]} dev ${NETIFS[p3]}" \
388 0 "v4-mapped - multipath onlink"
389
390 run_ip6_mpath 254 ${TEST_NET6[1]}::7 "" \
391 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
392 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
393 0 "unicast connected - multipath onlink both nexthops"
394
395 run_ip6_mpath 254 ${TEST_NET6[1]}::8 "" \
396 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
397 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
398 0 "unicast connected - multipath onlink first only"
399
400 run_ip6_mpath 254 ${TEST_NET6[1]}::9 "" \
401 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
402 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
403 0 "unicast connected - multipath onlink second only"
404}
405
406invalid_onlink_ipv6()
407{
408 local lladdr
409
410 lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1
411
412 run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
413 "Invalid gw - local unicast address"
414 run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
415 "Invalid gw - local linklocal address"
416 run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
417 "Invalid gw - multicast address"
418
419 lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
420 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
421 "Invalid gw - local unicast address, VRF"
422 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
423 "Invalid gw - local linklocal address, VRF"
424 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
425 "Invalid gw - multicast address, VRF"
426
427 run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
428 "No nexthop device given"
429
430 # default VRF validation is done against LOCAL table
431 # run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \
432 # "Gateway resolves to wrong nexthop device"
433
434 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \
435 "Gateway resolves to wrong nexthop device - VRF"
436}
437
438run_onlink_tests()
439{
440 log_section "IPv4 onlink"
441 log_subsection "Valid onlink commands"
442 valid_onlink_ipv4
443 log_subsection "Invalid onlink commands"
444 invalid_onlink_ipv4
445
446 log_section "IPv6 onlink"
447 log_subsection "Valid onlink commands"
448 valid_onlink_ipv6
449 log_subsection "Invalid onlink commands"
450 invalid_onlink_ipv6
451}
452
453################################################################################
454# main
455
456nsuccess=0
457nfail=0
458
459cleanup
460setup
461run_onlink_tests
462cleanup
463
464if [ "$TESTS" != "none" ]; then
465 printf "\nTests passed: %3d\n" ${nsuccess}
466 printf "Tests failed: %3d\n" ${nfail}
467fi
diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
index a9154eefb2e2..9164e60d4b66 100755
--- a/tools/testing/selftests/net/fib_tests.sh
+++ b/tools/testing/selftests/net/fib_tests.sh
@@ -6,154 +6,179 @@
6 6
7ret=0 7ret=0
8 8
9check_err() 9VERBOSE=${VERBOSE:=0}
10{ 10PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
11 if [ $ret -eq 0 ]; then 11IP="ip -netns testns"
12 ret=$1
13 fi
14}
15 12
16check_fail() 13log_test()
17{ 14{
18 if [ $1 -eq 0 ]; then 15 local rc=$1
16 local expected=$2
17 local msg="$3"
18
19 if [ ${rc} -eq ${expected} ]; then
20 printf " TEST: %-60s [ OK ]\n" "${msg}"
21 else
19 ret=1 22 ret=1
23 printf " TEST: %-60s [FAIL]\n" "${msg}"
24 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
25 echo
26 echo "hit enter to continue, 'q' to quit"
27 read a
28 [ "$a" = "q" ] && exit 1
29 fi
20 fi 30 fi
21} 31}
22 32
23netns_create() 33setup()
24{ 34{
25 local testns=$1 35 set -e
36 ip netns add testns
37 $IP link set dev lo up
38
39 $IP link add dummy0 type dummy
40 $IP link set dev dummy0 up
41 $IP address add 198.51.100.1/24 dev dummy0
42 $IP -6 address add 2001:db8:1::1/64 dev dummy0
43 set +e
26 44
27 ip netns add $testns
28 ip netns exec $testns ip link set dev lo up
29} 45}
30 46
31fib_unreg_unicast_test() 47cleanup()
32{ 48{
33 ret=0 49 $IP link del dev dummy0 &> /dev/null
50 ip netns del testns
51}
34 52
35 netns_create "testns" 53get_linklocal()
54{
55 local dev=$1
56 local addr
36 57
37 ip netns exec testns ip link add dummy0 type dummy 58 addr=$($IP -6 -br addr show dev ${dev} | \
38 ip netns exec testns ip link set dev dummy0 up 59 awk '{
60 for (i = 3; i <= NF; ++i) {
61 if ($i ~ /^fe80/)
62 print $i
63 }
64 }'
65 )
66 addr=${addr/\/*}
39 67
40 ip netns exec testns ip address add 198.51.100.1/24 dev dummy0 68 [ -z "$addr" ] && return 1
41 ip netns exec testns ip -6 address add 2001:db8:1::1/64 dev dummy0
42 69
43 ip netns exec testns ip route get fibmatch 198.51.100.2 &> /dev/null 70 echo $addr
44 check_err $?
45 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 &> /dev/null
46 check_err $?
47 71
48 ip netns exec testns ip link del dev dummy0 72 return 0
49 check_err $? 73}
50 74
51 ip netns exec testns ip route get fibmatch 198.51.100.2 &> /dev/null 75fib_unreg_unicast_test()
52 check_fail $? 76{
53 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 &> /dev/null 77 echo
54 check_fail $? 78 echo "Single path route test"
55 79
56 ip netns del testns 80 setup
57 81
58 if [ $ret -ne 0 ]; then 82 echo " Start point"
59 echo "FAIL: unicast route test" 83 $IP route get fibmatch 198.51.100.2 &> /dev/null
60 return 1 84 log_test $? 0 "IPv4 fibmatch"
61 fi 85 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
62 echo "PASS: unicast route test" 86 log_test $? 0 "IPv6 fibmatch"
87
88 set -e
89 $IP link del dev dummy0
90 set +e
91
92 echo " Nexthop device deleted"
93 $IP route get fibmatch 198.51.100.2 &> /dev/null
94 log_test $? 2 "IPv4 fibmatch - no route"
95 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
96 log_test $? 2 "IPv6 fibmatch - no route"
97
98 cleanup
63} 99}
64 100
65fib_unreg_multipath_test() 101fib_unreg_multipath_test()
66{ 102{
67 ret=0
68
69 netns_create "testns"
70 103
71 ip netns exec testns ip link add dummy0 type dummy 104 echo
72 ip netns exec testns ip link set dev dummy0 up 105 echo "Multipath route test"
73 106
74 ip netns exec testns ip link add dummy1 type dummy 107 setup
75 ip netns exec testns ip link set dev dummy1 up
76 108
77 ip netns exec testns ip address add 198.51.100.1/24 dev dummy0 109 set -e
78 ip netns exec testns ip -6 address add 2001:db8:1::1/64 dev dummy0 110 $IP link add dummy1 type dummy
111 $IP link set dev dummy1 up
112 $IP address add 192.0.2.1/24 dev dummy1
113 $IP -6 address add 2001:db8:2::1/64 dev dummy1
79 114
80 ip netns exec testns ip address add 192.0.2.1/24 dev dummy1 115 $IP route add 203.0.113.0/24 \
81 ip netns exec testns ip -6 address add 2001:db8:2::1/64 dev dummy1
82
83 ip netns exec testns ip route add 203.0.113.0/24 \
84 nexthop via 198.51.100.2 dev dummy0 \ 116 nexthop via 198.51.100.2 dev dummy0 \
85 nexthop via 192.0.2.2 dev dummy1 117 nexthop via 192.0.2.2 dev dummy1
86 ip netns exec testns ip -6 route add 2001:db8:3::/64 \ 118 $IP -6 route add 2001:db8:3::/64 \
87 nexthop via 2001:db8:1::2 dev dummy0 \ 119 nexthop via 2001:db8:1::2 dev dummy0 \
88 nexthop via 2001:db8:2::2 dev dummy1 120 nexthop via 2001:db8:2::2 dev dummy1
121 set +e
122
123 echo " Start point"
124 $IP route get fibmatch 203.0.113.1 &> /dev/null
125 log_test $? 0 "IPv4 fibmatch"
126 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
127 log_test $? 0 "IPv6 fibmatch"
89 128
90 ip netns exec testns ip route get fibmatch 203.0.113.1 &> /dev/null 129 set -e
91 check_err $? 130 $IP link del dev dummy0
92 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 &> /dev/null 131 set +e
93 check_err $?
94 132
95 ip netns exec testns ip link del dev dummy0 133 echo " One nexthop device deleted"
96 check_err $? 134 $IP route get fibmatch 203.0.113.1 &> /dev/null
135 log_test $? 2 "IPv4 - multipath route removed on delete"
97 136
98 ip netns exec testns ip route get fibmatch 203.0.113.1 &> /dev/null 137 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
99 check_fail $?
100 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 &> /dev/null
101 # In IPv6 we do not flush the entire multipath route. 138 # In IPv6 we do not flush the entire multipath route.
102 check_err $? 139 log_test $? 0 "IPv6 - multipath down to single path"
103 140
104 ip netns exec testns ip link del dev dummy1 141 set -e
142 $IP link del dev dummy1
143 set +e
105 144
106 ip netns del testns 145 echo " Second nexthop device deleted"
146 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
147 log_test $? 2 "IPv6 - no route"
107 148
108 if [ $ret -ne 0 ]; then 149 cleanup
109 echo "FAIL: multipath route test"
110 return 1
111 fi
112 echo "PASS: multipath route test"
113} 150}
114 151
115fib_unreg_test() 152fib_unreg_test()
116{ 153{
117 echo "Running netdev unregister tests"
118
119 fib_unreg_unicast_test 154 fib_unreg_unicast_test
120 fib_unreg_multipath_test 155 fib_unreg_multipath_test
121} 156}
122 157
123fib_down_unicast_test() 158fib_down_unicast_test()
124{ 159{
125 ret=0 160 echo
126 161 echo "Single path, admin down"
127 netns_create "testns"
128
129 ip netns exec testns ip link add dummy0 type dummy
130 ip netns exec testns ip link set dev dummy0 up
131 162
132 ip netns exec testns ip address add 198.51.100.1/24 dev dummy0 163 setup
133 ip netns exec testns ip -6 address add 2001:db8:1::1/64 dev dummy0
134 164
135 ip netns exec testns ip route get fibmatch 198.51.100.2 &> /dev/null 165 echo " Start point"
136 check_err $? 166 $IP route get fibmatch 198.51.100.2 &> /dev/null
137 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 &> /dev/null 167 log_test $? 0 "IPv4 fibmatch"
138 check_err $? 168 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
169 log_test $? 0 "IPv6 fibmatch"
139 170
140 ip netns exec testns ip link set dev dummy0 down 171 set -e
141 check_err $? 172 $IP link set dev dummy0 down
173 set +e
142 174
143 ip netns exec testns ip route get fibmatch 198.51.100.2 &> /dev/null 175 echo " Route deleted on down"
144 check_fail $? 176 $IP route get fibmatch 198.51.100.2 &> /dev/null
145 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 &> /dev/null 177 log_test $? 2 "IPv4 fibmatch"
146 check_fail $? 178 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
179 log_test $? 2 "IPv6 fibmatch"
147 180
148 ip netns exec testns ip link del dev dummy0 181 cleanup
149
150 ip netns del testns
151
152 if [ $ret -ne 0 ]; then
153 echo "FAIL: unicast route test"
154 return 1
155 fi
156 echo "PASS: unicast route test"
157} 182}
158 183
159fib_down_multipath_test_do() 184fib_down_multipath_test_do()
@@ -161,251 +186,395 @@ fib_down_multipath_test_do()
161 local down_dev=$1 186 local down_dev=$1
162 local up_dev=$2 187 local up_dev=$2
163 188
164 ip netns exec testns ip route get fibmatch 203.0.113.1 \ 189 $IP route get fibmatch 203.0.113.1 \
165 oif $down_dev &> /dev/null 190 oif $down_dev &> /dev/null
166 check_fail $? 191 log_test $? 2 "IPv4 fibmatch on down device"
167 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 \ 192 $IP -6 route get fibmatch 2001:db8:3::1 \
168 oif $down_dev &> /dev/null 193 oif $down_dev &> /dev/null
169 check_fail $? 194 log_test $? 2 "IPv6 fibmatch on down device"
170 195
171 ip netns exec testns ip route get fibmatch 203.0.113.1 \ 196 $IP route get fibmatch 203.0.113.1 \
172 oif $up_dev &> /dev/null 197 oif $up_dev &> /dev/null
173 check_err $? 198 log_test $? 0 "IPv4 fibmatch on up device"
174 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 \ 199 $IP -6 route get fibmatch 2001:db8:3::1 \
175 oif $up_dev &> /dev/null 200 oif $up_dev &> /dev/null
176 check_err $? 201 log_test $? 0 "IPv6 fibmatch on up device"
177 202
178 ip netns exec testns ip route get fibmatch 203.0.113.1 | \ 203 $IP route get fibmatch 203.0.113.1 | \
179 grep $down_dev | grep -q "dead linkdown" 204 grep $down_dev | grep -q "dead linkdown"
180 check_err $? 205 log_test $? 0 "IPv4 flags on down device"
181 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 | \ 206 $IP -6 route get fibmatch 2001:db8:3::1 | \
182 grep $down_dev | grep -q "dead linkdown" 207 grep $down_dev | grep -q "dead linkdown"
183 check_err $? 208 log_test $? 0 "IPv6 flags on down device"
184 209
185 ip netns exec testns ip route get fibmatch 203.0.113.1 | \ 210 $IP route get fibmatch 203.0.113.1 | \
186 grep $up_dev | grep -q "dead linkdown" 211 grep $up_dev | grep -q "dead linkdown"
187 check_fail $? 212 log_test $? 1 "IPv4 flags on up device"
188 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 | \ 213 $IP -6 route get fibmatch 2001:db8:3::1 | \
189 grep $up_dev | grep -q "dead linkdown" 214 grep $up_dev | grep -q "dead linkdown"
190 check_fail $? 215 log_test $? 1 "IPv6 flags on up device"
191} 216}
192 217
193fib_down_multipath_test() 218fib_down_multipath_test()
194{ 219{
195 ret=0 220 echo
196 221 echo "Admin down multipath"
197 netns_create "testns"
198 222
199 ip netns exec testns ip link add dummy0 type dummy 223 setup
200 ip netns exec testns ip link set dev dummy0 up
201 224
202 ip netns exec testns ip link add dummy1 type dummy 225 set -e
203 ip netns exec testns ip link set dev dummy1 up 226 $IP link add dummy1 type dummy
227 $IP link set dev dummy1 up
204 228
205 ip netns exec testns ip address add 198.51.100.1/24 dev dummy0 229 $IP address add 192.0.2.1/24 dev dummy1
206 ip netns exec testns ip -6 address add 2001:db8:1::1/64 dev dummy0 230 $IP -6 address add 2001:db8:2::1/64 dev dummy1
207 231
208 ip netns exec testns ip address add 192.0.2.1/24 dev dummy1 232 $IP route add 203.0.113.0/24 \
209 ip netns exec testns ip -6 address add 2001:db8:2::1/64 dev dummy1
210
211 ip netns exec testns ip route add 203.0.113.0/24 \
212 nexthop via 198.51.100.2 dev dummy0 \ 233 nexthop via 198.51.100.2 dev dummy0 \
213 nexthop via 192.0.2.2 dev dummy1 234 nexthop via 192.0.2.2 dev dummy1
214 ip netns exec testns ip -6 route add 2001:db8:3::/64 \ 235 $IP -6 route add 2001:db8:3::/64 \
215 nexthop via 2001:db8:1::2 dev dummy0 \ 236 nexthop via 2001:db8:1::2 dev dummy0 \
216 nexthop via 2001:db8:2::2 dev dummy1 237 nexthop via 2001:db8:2::2 dev dummy1
238 set +e
239
240 echo " Verify start point"
241 $IP route get fibmatch 203.0.113.1 &> /dev/null
242 log_test $? 0 "IPv4 fibmatch"
217 243
218 ip netns exec testns ip route get fibmatch 203.0.113.1 &> /dev/null 244 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
219 check_err $? 245 log_test $? 0 "IPv6 fibmatch"
220 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 &> /dev/null
221 check_err $?
222 246
223 ip netns exec testns ip link set dev dummy0 down 247 set -e
224 check_err $? 248 $IP link set dev dummy0 down
249 set +e
225 250
251 echo " One device down, one up"
226 fib_down_multipath_test_do "dummy0" "dummy1" 252 fib_down_multipath_test_do "dummy0" "dummy1"
227 253
228 ip netns exec testns ip link set dev dummy0 up 254 set -e
229 check_err $? 255 $IP link set dev dummy0 up
230 ip netns exec testns ip link set dev dummy1 down 256 $IP link set dev dummy1 down
231 check_err $? 257 set +e
232 258
259 echo " Other device down and up"
233 fib_down_multipath_test_do "dummy1" "dummy0" 260 fib_down_multipath_test_do "dummy1" "dummy0"
234 261
235 ip netns exec testns ip link set dev dummy0 down 262 set -e
236 check_err $? 263 $IP link set dev dummy0 down
237 264 set +e
238 ip netns exec testns ip route get fibmatch 203.0.113.1 &> /dev/null
239 check_fail $?
240 ip netns exec testns ip -6 route get fibmatch 2001:db8:3::1 &> /dev/null
241 check_fail $?
242 265
243 ip netns exec testns ip link del dev dummy1 266 echo " Both devices down"
244 ip netns exec testns ip link del dev dummy0 267 $IP route get fibmatch 203.0.113.1 &> /dev/null
245 268 log_test $? 2 "IPv4 fibmatch"
246 ip netns del testns 269 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
270 log_test $? 2 "IPv6 fibmatch"
247 271
248 if [ $ret -ne 0 ]; then 272 $IP link del dev dummy1
249 echo "FAIL: multipath route test" 273 cleanup
250 return 1
251 fi
252 echo "PASS: multipath route test"
253} 274}
254 275
255fib_down_test() 276fib_down_test()
256{ 277{
257 echo "Running netdev down tests"
258
259 fib_down_unicast_test 278 fib_down_unicast_test
260 fib_down_multipath_test 279 fib_down_multipath_test
261} 280}
262 281
282# Local routes should not be affected when carrier changes.
263fib_carrier_local_test() 283fib_carrier_local_test()
264{ 284{
265 ret=0 285 echo
266 286 echo "Local carrier tests - single path"
267 # Local routes should not be affected when carrier changes.
268 netns_create "testns"
269
270 ip netns exec testns ip link add dummy0 type dummy
271 ip netns exec testns ip link set dev dummy0 up
272 287
273 ip netns exec testns ip link set dev dummy0 carrier on 288 setup
274 289
275 ip netns exec testns ip address add 198.51.100.1/24 dev dummy0 290 set -e
276 ip netns exec testns ip -6 address add 2001:db8:1::1/64 dev dummy0 291 $IP link set dev dummy0 carrier on
292 set +e
277 293
278 ip netns exec testns ip route get fibmatch 198.51.100.1 &> /dev/null 294 echo " Start point"
279 check_err $? 295 $IP route get fibmatch 198.51.100.1 &> /dev/null
280 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::1 &> /dev/null 296 log_test $? 0 "IPv4 fibmatch"
281 check_err $? 297 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
298 log_test $? 0 "IPv6 fibmatch"
282 299
283 ip netns exec testns ip route get fibmatch 198.51.100.1 | \ 300 $IP route get fibmatch 198.51.100.1 | \
284 grep -q "linkdown" 301 grep -q "linkdown"
285 check_fail $? 302 log_test $? 1 "IPv4 - no linkdown flag"
286 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::1 | \ 303 $IP -6 route get fibmatch 2001:db8:1::1 | \
287 grep -q "linkdown" 304 grep -q "linkdown"
288 check_fail $? 305 log_test $? 1 "IPv6 - no linkdown flag"
289 306
290 ip netns exec testns ip link set dev dummy0 carrier off 307 set -e
308 $IP link set dev dummy0 carrier off
309 sleep 1
310 set +e
291 311
292 ip netns exec testns ip route get fibmatch 198.51.100.1 &> /dev/null 312 echo " Carrier off on nexthop"
293 check_err $? 313 $IP route get fibmatch 198.51.100.1 &> /dev/null
294 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::1 &> /dev/null 314 log_test $? 0 "IPv4 fibmatch"
295 check_err $? 315 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
316 log_test $? 0 "IPv6 fibmatch"
296 317
297 ip netns exec testns ip route get fibmatch 198.51.100.1 | \ 318 $IP route get fibmatch 198.51.100.1 | \
298 grep -q "linkdown" 319 grep -q "linkdown"
299 check_fail $? 320 log_test $? 1 "IPv4 - linkdown flag set"
300 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::1 | \ 321 $IP -6 route get fibmatch 2001:db8:1::1 | \
301 grep -q "linkdown" 322 grep -q "linkdown"
302 check_fail $? 323 log_test $? 1 "IPv6 - linkdown flag set"
303 324
304 ip netns exec testns ip address add 192.0.2.1/24 dev dummy0 325 set -e
305 ip netns exec testns ip -6 address add 2001:db8:2::1/64 dev dummy0 326 $IP address add 192.0.2.1/24 dev dummy0
327 $IP -6 address add 2001:db8:2::1/64 dev dummy0
328 set +e
306 329
307 ip netns exec testns ip route get fibmatch 192.0.2.1 &> /dev/null 330 echo " Route to local address with carrier down"
308 check_err $? 331 $IP route get fibmatch 192.0.2.1 &> /dev/null
309 ip netns exec testns ip -6 route get fibmatch 2001:db8:2::1 &> /dev/null 332 log_test $? 0 "IPv4 fibmatch"
310 check_err $? 333 $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
334 log_test $? 0 "IPv6 fibmatch"
311 335
312 ip netns exec testns ip route get fibmatch 192.0.2.1 | \ 336 $IP route get fibmatch 192.0.2.1 | \
313 grep -q "linkdown" 337 grep -q "linkdown"
314 check_fail $? 338 log_test $? 1 "IPv4 linkdown flag set"
315 ip netns exec testns ip -6 route get fibmatch 2001:db8:2::1 | \ 339 $IP -6 route get fibmatch 2001:db8:2::1 | \
316 grep -q "linkdown" 340 grep -q "linkdown"
317 check_fail $? 341 log_test $? 1 "IPv6 linkdown flag set"
318 342
319 ip netns exec testns ip link del dev dummy0 343 cleanup
320
321 ip netns del testns
322
323 if [ $ret -ne 0 ]; then
324 echo "FAIL: local route carrier test"
325 return 1
326 fi
327 echo "PASS: local route carrier test"
328} 344}
329 345
330fib_carrier_unicast_test() 346fib_carrier_unicast_test()
331{ 347{
332 ret=0 348 ret=0
333 349
334 netns_create "testns" 350 echo
351 echo "Single path route carrier test"
335 352
336 ip netns exec testns ip link add dummy0 type dummy 353 setup
337 ip netns exec testns ip link set dev dummy0 up
338 354
339 ip netns exec testns ip link set dev dummy0 carrier on 355 set -e
356 $IP link set dev dummy0 carrier on
357 set +e
340 358
341 ip netns exec testns ip address add 198.51.100.1/24 dev dummy0 359 echo " Start point"
342 ip netns exec testns ip -6 address add 2001:db8:1::1/64 dev dummy0 360 $IP route get fibmatch 198.51.100.2 &> /dev/null
361 log_test $? 0 "IPv4 fibmatch"
362 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
363 log_test $? 0 "IPv6 fibmatch"
343 364
344 ip netns exec testns ip route get fibmatch 198.51.100.2 &> /dev/null 365 $IP route get fibmatch 198.51.100.2 | \
345 check_err $?
346 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 &> /dev/null
347 check_err $?
348
349 ip netns exec testns ip route get fibmatch 198.51.100.2 | \
350 grep -q "linkdown" 366 grep -q "linkdown"
351 check_fail $? 367 log_test $? 1 "IPv4 no linkdown flag"
352 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 | \ 368 $IP -6 route get fibmatch 2001:db8:1::2 | \
353 grep -q "linkdown" 369 grep -q "linkdown"
354 check_fail $? 370 log_test $? 1 "IPv6 no linkdown flag"
355 371
356 ip netns exec testns ip link set dev dummy0 carrier off 372 set -e
373 $IP link set dev dummy0 carrier off
374 set +e
357 375
358 ip netns exec testns ip route get fibmatch 198.51.100.2 &> /dev/null 376 echo " Carrier down"
359 check_err $? 377 $IP route get fibmatch 198.51.100.2 &> /dev/null
360 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 &> /dev/null 378 log_test $? 0 "IPv4 fibmatch"
361 check_err $? 379 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
380 log_test $? 0 "IPv6 fibmatch"
362 381
363 ip netns exec testns ip route get fibmatch 198.51.100.2 | \ 382 $IP route get fibmatch 198.51.100.2 | \
364 grep -q "linkdown" 383 grep -q "linkdown"
365 check_err $? 384 log_test $? 0 "IPv4 linkdown flag set"
366 ip netns exec testns ip -6 route get fibmatch 2001:db8:1::2 | \ 385 $IP -6 route get fibmatch 2001:db8:1::2 | \
367 grep -q "linkdown" 386 grep -q "linkdown"
368 check_err $? 387 log_test $? 0 "IPv6 linkdown flag set"
369 388
370 ip netns exec testns ip address add 192.0.2.1/24 dev dummy0 389 set -e
371 ip netns exec testns ip -6 address add 2001:db8:2::1/64 dev dummy0 390 $IP address add 192.0.2.1/24 dev dummy0
391 $IP -6 address add 2001:db8:2::1/64 dev dummy0
392 set +e
372 393
373 ip netns exec testns ip route get fibmatch 192.0.2.2 &> /dev/null 394 echo " Second address added with carrier down"
374 check_err $? 395 $IP route get fibmatch 192.0.2.2 &> /dev/null
375 ip netns exec testns ip -6 route get fibmatch 2001:db8:2::2 &> /dev/null 396 log_test $? 0 "IPv4 fibmatch"
376 check_err $? 397 $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
398 log_test $? 0 "IPv6 fibmatch"
377 399
378 ip netns exec testns ip route get fibmatch 192.0.2.2 | \ 400 $IP route get fibmatch 192.0.2.2 | \
379 grep -q "linkdown" 401 grep -q "linkdown"
380 check_err $? 402 log_test $? 0 "IPv4 linkdown flag set"
381 ip netns exec testns ip -6 route get fibmatch 2001:db8:2::2 | \ 403 $IP -6 route get fibmatch 2001:db8:2::2 | \
382 grep -q "linkdown" 404 grep -q "linkdown"
383 check_err $? 405 log_test $? 0 "IPv6 linkdown flag set"
384 406
385 ip netns exec testns ip link del dev dummy0 407 cleanup
408}
386 409
387 ip netns del testns 410fib_carrier_test()
411{
412 fib_carrier_local_test
413 fib_carrier_unicast_test
414}
388 415
389 if [ $ret -ne 0 ]; then 416################################################################################
390 echo "FAIL: unicast route carrier test" 417# Tests on nexthop spec
391 return 1 418
419# run 'ip route add' with given spec
420add_rt()
421{
422 local desc="$1"
423 local erc=$2
424 local vrf=$3
425 local pfx=$4
426 local gw=$5
427 local dev=$6
428 local cmd out rc
429
430 [ "$vrf" = "-" ] && vrf="default"
431 [ -n "$gw" ] && gw="via $gw"
432 [ -n "$dev" ] && dev="dev $dev"
433
434 cmd="$IP route add vrf $vrf $pfx $gw $dev"
435 if [ "$VERBOSE" = "1" ]; then
436 printf "\n COMMAND: $cmd\n"
437 fi
438
439 out=$(eval $cmd 2>&1)
440 rc=$?
441 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
442 echo " $out"
392 fi 443 fi
393 echo "PASS: unicast route carrier test" 444 log_test $rc $erc "$desc"
394} 445}
395 446
396fib_carrier_test() 447fib4_nexthop()
397{ 448{
398 echo "Running netdev carrier change tests" 449 echo
450 echo "IPv4 nexthop tests"
399 451
400 fib_carrier_local_test 452 echo "<<< write me >>>"
401 fib_carrier_unicast_test
402} 453}
403 454
455fib6_nexthop()
456{
457 local lldummy=$(get_linklocal dummy0)
458 local llv1=$(get_linklocal dummy0)
459
460 if [ -z "$lldummy" ]; then
461 echo "Failed to get linklocal address for dummy0"
462 return 1
463 fi
464 if [ -z "$llv1" ]; then
465 echo "Failed to get linklocal address for veth1"
466 return 1
467 fi
468
469 echo
470 echo "IPv6 nexthop tests"
471
472 add_rt "Directly connected nexthop, unicast address" 0 \
473 - 2001:db8:101::/64 2001:db8:1::2
474 add_rt "Directly connected nexthop, unicast address with device" 0 \
475 - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
476 add_rt "Gateway is linklocal address" 0 \
477 - 2001:db8:103::1/64 $llv1 "veth0"
478
479 # fails because LL address requires a device
480 add_rt "Gateway is linklocal address, no device" 2 \
481 - 2001:db8:104::1/64 $llv1
482
483 # local address can not be a gateway
484 add_rt "Gateway can not be local unicast address" 2 \
485 - 2001:db8:105::/64 2001:db8:1::1
486 add_rt "Gateway can not be local unicast address, with device" 2 \
487 - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
488 add_rt "Gateway can not be a local linklocal address" 2 \
489 - 2001:db8:107::1/64 $lldummy "dummy0"
490
491 # VRF tests
492 add_rt "Gateway can be local address in a VRF" 0 \
493 - 2001:db8:108::/64 2001:db8:51::2
494 add_rt "Gateway can be local address in a VRF, with device" 0 \
495 - 2001:db8:109::/64 2001:db8:51::2 "veth0"
496 add_rt "Gateway can be local linklocal address in a VRF" 0 \
497 - 2001:db8:110::1/64 $llv1 "veth0"
498
499 add_rt "Redirect to VRF lookup" 0 \
500 - 2001:db8:111::/64 "" "red"
501
502 add_rt "VRF route, gateway can be local address in default VRF" 0 \
503 red 2001:db8:112::/64 2001:db8:51::1
504
505 # local address in same VRF fails
506 add_rt "VRF route, gateway can not be a local address" 2 \
507 red 2001:db8:113::1/64 2001:db8:2::1
508 add_rt "VRF route, gateway can not be a local addr with device" 2 \
509 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
510}
511
512# Default VRF:
513# dummy0 - 198.51.100.1/24 2001:db8:1::1/64
514# veth0 - 192.0.2.1/24 2001:db8:51::1/64
515#
516# VRF red:
517# dummy1 - 192.168.2.1/24 2001:db8:2::1/64
518# veth1 - 192.0.2.2/24 2001:db8:51::2/64
519#
520# [ dummy0 veth0 ]--[ veth1 dummy1 ]
521
522fib_nexthop_test()
523{
524 setup
525
526 set -e
527
528 $IP -4 rule add pref 32765 table local
529 $IP -4 rule del pref 0
530 $IP -6 rule add pref 32765 table local
531 $IP -6 rule del pref 0
532
533 $IP link add red type vrf table 1
534 $IP link set red up
535 $IP -4 route add vrf red unreachable default metric 4278198272
536 $IP -6 route add vrf red unreachable default metric 4278198272
537
538 $IP link add veth0 type veth peer name veth1
539 $IP link set dev veth0 up
540 $IP address add 192.0.2.1/24 dev veth0
541 $IP -6 address add 2001:db8:51::1/64 dev veth0
542
543 $IP link set dev veth1 vrf red up
544 $IP address add 192.0.2.2/24 dev veth1
545 $IP -6 address add 2001:db8:51::2/64 dev veth1
546
547 $IP link add dummy1 type dummy
548 $IP link set dev dummy1 vrf red up
549 $IP address add 192.168.2.1/24 dev dummy1
550 $IP -6 address add 2001:db8:2::1/64 dev dummy1
551 set +e
552
553 sleep 1
554 fib4_nexthop
555 fib6_nexthop
556
557 (
558 $IP link del dev dummy1
559 $IP link del veth0
560 $IP link del red
561 ) 2>/dev/null
562 cleanup
563}
564
565################################################################################
566#
567
404fib_test() 568fib_test()
405{ 569{
406 fib_unreg_test 570 if [ -n "$TEST" ]; then
407 fib_down_test 571 eval $TEST
408 fib_carrier_test 572 else
573 fib_unreg_test
574 fib_down_test
575 fib_carrier_test
576 fib_nexthop_test
577 fi
409} 578}
410 579
411if [ "$(id -u)" -ne 0 ];then 580if [ "$(id -u)" -ne 0 ];then
@@ -424,6 +593,9 @@ if [ $? -ne 0 ]; then
424 exit 0 593 exit 0
425fi 594fi
426 595
596# start clean
597cleanup &> /dev/null
598
427fib_test 599fib_test
428 600
429exit $ret 601exit $ret
diff --git a/tools/testing/selftests/net/forwarding/.gitignore b/tools/testing/selftests/net/forwarding/.gitignore
new file mode 100644
index 000000000000..a793eef5b876
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/.gitignore
@@ -0,0 +1 @@
forwarding.config
diff --git a/tools/testing/selftests/net/forwarding/README b/tools/testing/selftests/net/forwarding/README
new file mode 100644
index 000000000000..4a0964c42860
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/README
@@ -0,0 +1,56 @@
1Motivation
2==========
3
4One of the nice things about network namespaces is that they allow one
5to easily create and test complex environments.
6
7Unfortunately, these namespaces can not be used with actual switching
8ASICs, as their ports can not be migrated to other network namespaces
9(NETIF_F_NETNS_LOCAL) and most of them probably do not support the
10L1-separation provided by namespaces.
11
12However, a similar kind of flexibility can be achieved by using VRFs and
13by looping the switch ports together. For example:
14
15 br0
16 +
17 vrf-h1 | vrf-h2
18 + +---+----+ +
19 | | | |
20 192.0.2.1/24 + + + + 192.0.2.2/24
21 swp1 swp2 swp3 swp4
22 + + + +
23 | | | |
24 +--------+ +--------+
25
26The VRFs act as lightweight namespaces representing hosts connected to
27the switch.
28
29This approach for testing switch ASICs has several advantages over the
30traditional method that requires multiple physical machines, to name a
31few:
32
331. Only the device under test (DUT) is being tested without noise from
34other system.
35
362. Ability to easily provision complex topologies. Testing bridging
37between 4-ports LAGs or 8-way ECMP requires many physical links that are
38not always available. With the VRF-based approach one merely needs to
39loopback more ports.
40
41These tests are written with switch ASICs in mind, but they can be run
42on any Linux box using veth pairs to emulate physical loopbacks.
43
44Guidelines for Writing Tests
45============================
46
47o Where possible, reuse an existing topology for different tests instead
48 of recreating the same topology.
49o Where possible, IPv6 and IPv4 addresses shall conform to RFC 3849 and
50 RFC 5737, respectively.
51o Where possible, tests shall be written so that they can be reused by
52 multiple topologies and added to lib.sh.
53o Checks shall be added to lib.sh for any external dependencies.
54o Code shall be checked using ShellCheck [1] prior to submission.
55
561. https://www.shellcheck.net/
diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_aware.sh b/tools/testing/selftests/net/forwarding/bridge_vlan_aware.sh
new file mode 100755
index 000000000000..75d922438bc9
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/bridge_vlan_aware.sh
@@ -0,0 +1,88 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=4
5CHECK_TC="yes"
6source lib.sh
7
8h1_create()
9{
10 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
11}
12
13h1_destroy()
14{
15 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
16}
17
18h2_create()
19{
20 simple_if_init $h2 192.0.2.2/24 2001:db8:1::2/64
21}
22
23h2_destroy()
24{
25 simple_if_fini $h2 192.0.2.2/24 2001:db8:1::2/64
26}
27
28switch_create()
29{
30 # 10 Seconds ageing time.
31 ip link add dev br0 type bridge vlan_filtering 1 ageing_time 1000 \
32 mcast_snooping 0
33
34 ip link set dev $swp1 master br0
35 ip link set dev $swp2 master br0
36
37 ip link set dev br0 up
38 ip link set dev $swp1 up
39 ip link set dev $swp2 up
40}
41
42switch_destroy()
43{
44 ip link set dev $swp2 down
45 ip link set dev $swp1 down
46
47 ip link del dev br0
48}
49
50setup_prepare()
51{
52 h1=${NETIFS[p1]}
53 swp1=${NETIFS[p2]}
54
55 swp2=${NETIFS[p3]}
56 h2=${NETIFS[p4]}
57
58 vrf_prepare
59
60 h1_create
61 h2_create
62
63 switch_create
64}
65
66cleanup()
67{
68 pre_cleanup
69
70 switch_destroy
71
72 h2_destroy
73 h1_destroy
74
75 vrf_cleanup
76}
77
78trap cleanup EXIT
79
80setup_prepare
81setup_wait
82
83ping_test $h1 192.0.2.2
84ping6_test $h1 2001:db8:1::2
85learning_test "br0" $swp1 $h1 $h2
86flood_test $swp2 $h1 $h2
87
88exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh b/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh
new file mode 100755
index 000000000000..1cddf06f691d
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh
@@ -0,0 +1,86 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=4
5source lib.sh
6
7h1_create()
8{
9 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
10}
11
12h1_destroy()
13{
14 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
15}
16
17h2_create()
18{
19 simple_if_init $h2 192.0.2.2/24 2001:db8:1::2/64
20}
21
22h2_destroy()
23{
24 simple_if_fini $h2 192.0.2.2/24 2001:db8:1::2/64
25}
26
27switch_create()
28{
29 # 10 Seconds ageing time.
30 ip link add dev br0 type bridge ageing_time 1000 mcast_snooping 0
31
32 ip link set dev $swp1 master br0
33 ip link set dev $swp2 master br0
34
35 ip link set dev br0 up
36 ip link set dev $swp1 up
37 ip link set dev $swp2 up
38}
39
40switch_destroy()
41{
42 ip link set dev $swp2 down
43 ip link set dev $swp1 down
44
45 ip link del dev br0
46}
47
48setup_prepare()
49{
50 h1=${NETIFS[p1]}
51 swp1=${NETIFS[p2]}
52
53 swp2=${NETIFS[p3]}
54 h2=${NETIFS[p4]}
55
56 vrf_prepare
57
58 h1_create
59 h2_create
60
61 switch_create
62}
63
64cleanup()
65{
66 pre_cleanup
67
68 switch_destroy
69
70 h2_destroy
71 h1_destroy
72
73 vrf_cleanup
74}
75
76trap cleanup EXIT
77
78setup_prepare
79setup_wait
80
81ping_test $h1 192.0.2.2
82ping6_test $h1 2001:db8:1::2
83learning_test "br0" $swp1 $h1 $h2
84flood_test $swp2 $h1 $h2
85
86exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/config b/tools/testing/selftests/net/forwarding/config
new file mode 100644
index 000000000000..5cd2aed97958
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/config
@@ -0,0 +1,12 @@
1CONFIG_BRIDGE=m
2CONFIG_VLAN_8021Q=m
3CONFIG_BRIDGE_VLAN_FILTERING=y
4CONFIG_NET_L3_MASTER_DEV=y
5CONFIG_IPV6_MULTIPLE_TABLES=y
6CONFIG_NET_VRF=m
7CONFIG_BPF_SYSCALL=y
8CONFIG_CGROUP_BPF=y
9CONFIG_NET_CLS_FLOWER=m
10CONFIG_NET_SCH_INGRESS=m
11CONFIG_NET_ACT_GACT=m
12CONFIG_VETH=m
diff --git a/tools/testing/selftests/net/forwarding/forwarding.config.sample b/tools/testing/selftests/net/forwarding/forwarding.config.sample
new file mode 100644
index 000000000000..e819d049d9ce
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/forwarding.config.sample
@@ -0,0 +1,35 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4##############################################################################
5# Topology description. p1 looped back to p2, p3 to p4 and so on.
6declare -A NETIFS
7
8NETIFS[p1]=veth0
9NETIFS[p2]=veth1
10NETIFS[p3]=veth2
11NETIFS[p4]=veth3
12NETIFS[p5]=veth4
13NETIFS[p6]=veth5
14NETIFS[p7]=veth6
15NETIFS[p8]=veth7
16
17##############################################################################
18# Defines
19
20# IPv4 ping utility name
21PING=ping
22# IPv6 ping utility name. Some distributions use 'ping' for IPv6.
23PING6=ping6
24# Packet generator. Some distributions use 'mz'.
25MZ=mausezahn
26# Time to wait after interfaces participating in the test are all UP
27WAIT_TIME=5
28# Whether to pause on failure or not.
29PAUSE_ON_FAIL=no
30# Whether to pause on cleanup or not.
31PAUSE_ON_CLEANUP=no
32# Type of network interface to create
33NETIF_TYPE=veth
34# Whether to create virtual interfaces (veth) or not
35NETIF_CREATE=yes
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
new file mode 100644
index 000000000000..1ac6c62271f3
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -0,0 +1,577 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4##############################################################################
5# Defines
6
7# Can be overridden by the configuration file.
8PING=${PING:=ping}
9PING6=${PING6:=ping6}
10MZ=${MZ:=mausezahn}
11WAIT_TIME=${WAIT_TIME:=5}
12PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
13PAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
14NETIF_TYPE=${NETIF_TYPE:=veth}
15NETIF_CREATE=${NETIF_CREATE:=yes}
16
17if [[ -f forwarding.config ]]; then
18 source forwarding.config
19fi
20
21##############################################################################
22# Sanity checks
23
24check_tc_version()
25{
26 tc -j &> /dev/null
27 if [[ $? -ne 0 ]]; then
28 echo "SKIP: iproute2 too old; tc is missing JSON support"
29 exit 1
30 fi
31
32 tc filter help 2>&1 | grep block &> /dev/null
33 if [[ $? -ne 0 ]]; then
34 echo "SKIP: iproute2 too old; tc is missing shared block support"
35 exit 1
36 fi
37}
38
39if [[ "$(id -u)" -ne 0 ]]; then
40 echo "SKIP: need root privileges"
41 exit 0
42fi
43
44if [[ "$CHECK_TC" = "yes" ]]; then
45 check_tc_version
46fi
47
48if [[ ! -x "$(command -v jq)" ]]; then
49 echo "SKIP: jq not installed"
50 exit 1
51fi
52
53if [[ ! -x "$(command -v $MZ)" ]]; then
54 echo "SKIP: $MZ not installed"
55 exit 1
56fi
57
58if [[ ! -v NUM_NETIFS ]]; then
59 echo "SKIP: importer does not define \"NUM_NETIFS\""
60 exit 1
61fi
62
63##############################################################################
64# Command line options handling
65
66count=0
67
68while [[ $# -gt 0 ]]; do
69 if [[ "$count" -eq "0" ]]; then
70 unset NETIFS
71 declare -A NETIFS
72 fi
73 count=$((count + 1))
74 NETIFS[p$count]="$1"
75 shift
76done
77
78##############################################################################
79# Network interfaces configuration
80
81create_netif_veth()
82{
83 local i
84
85 for i in $(eval echo {1..$NUM_NETIFS}); do
86 local j=$((i+1))
87
88 ip link show dev ${NETIFS[p$i]} &> /dev/null
89 if [[ $? -ne 0 ]]; then
90 ip link add ${NETIFS[p$i]} type veth \
91 peer name ${NETIFS[p$j]}
92 if [[ $? -ne 0 ]]; then
93 echo "Failed to create netif"
94 exit 1
95 fi
96 fi
97 i=$j
98 done
99}
100
101create_netif()
102{
103 case "$NETIF_TYPE" in
104 veth) create_netif_veth
105 ;;
106 *) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
107 exit 1
108 ;;
109 esac
110}
111
112if [[ "$NETIF_CREATE" = "yes" ]]; then
113 create_netif
114fi
115
116for i in $(eval echo {1..$NUM_NETIFS}); do
117 ip link show dev ${NETIFS[p$i]} &> /dev/null
118 if [[ $? -ne 0 ]]; then
119 echo "SKIP: could not find all required interfaces"
120 exit 1
121 fi
122done
123
124##############################################################################
125# Helpers
126
127# Exit status to return at the end. Set in case one of the tests fails.
128EXIT_STATUS=0
129# Per-test return value. Clear at the beginning of each test.
130RET=0
131
132check_err()
133{
134 local err=$1
135 local msg=$2
136
137 if [[ $RET -eq 0 && $err -ne 0 ]]; then
138 RET=$err
139 retmsg=$msg
140 fi
141}
142
143check_fail()
144{
145 local err=$1
146 local msg=$2
147
148 if [[ $RET -eq 0 && $err -eq 0 ]]; then
149 RET=1
150 retmsg=$msg
151 fi
152}
153
154log_test()
155{
156 local test_name=$1
157 local opt_str=$2
158
159 if [[ $# -eq 2 ]]; then
160 opt_str="($opt_str)"
161 fi
162
163 if [[ $RET -ne 0 ]]; then
164 EXIT_STATUS=1
165 printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str"
166 if [[ ! -z "$retmsg" ]]; then
167 printf "\t%s\n" "$retmsg"
168 fi
169 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
170 echo "Hit enter to continue, 'q' to quit"
171 read a
172 [ "$a" = "q" ] && exit 1
173 fi
174 return 1
175 fi
176
177 printf "TEST: %-60s [PASS]\n" "$test_name $opt_str"
178 return 0
179}
180
181log_info()
182{
183 local msg=$1
184
185 echo "INFO: $msg"
186}
187
188setup_wait()
189{
190 for i in $(eval echo {1..$NUM_NETIFS}); do
191 while true; do
192 ip link show dev ${NETIFS[p$i]} up \
193 | grep 'state UP' &> /dev/null
194 if [[ $? -ne 0 ]]; then
195 sleep 1
196 else
197 break
198 fi
199 done
200 done
201
202 # Make sure links are ready.
203 sleep $WAIT_TIME
204}
205
206pre_cleanup()
207{
208 if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
209 echo "Pausing before cleanup, hit any key to continue"
210 read
211 fi
212}
213
214vrf_prepare()
215{
216 ip -4 rule add pref 32765 table local
217 ip -4 rule del pref 0
218 ip -6 rule add pref 32765 table local
219 ip -6 rule del pref 0
220}
221
222vrf_cleanup()
223{
224 ip -6 rule add pref 0 table local
225 ip -6 rule del pref 32765
226 ip -4 rule add pref 0 table local
227 ip -4 rule del pref 32765
228}
229
230__last_tb_id=0
231declare -A __TB_IDS
232
233__vrf_td_id_assign()
234{
235 local vrf_name=$1
236
237 __last_tb_id=$((__last_tb_id + 1))
238 __TB_IDS[$vrf_name]=$__last_tb_id
239 return $__last_tb_id
240}
241
242__vrf_td_id_lookup()
243{
244 local vrf_name=$1
245
246 return ${__TB_IDS[$vrf_name]}
247}
248
249vrf_create()
250{
251 local vrf_name=$1
252 local tb_id
253
254 __vrf_td_id_assign $vrf_name
255 tb_id=$?
256
257 ip link add dev $vrf_name type vrf table $tb_id
258 ip -4 route add table $tb_id unreachable default metric 4278198272
259 ip -6 route add table $tb_id unreachable default metric 4278198272
260}
261
262vrf_destroy()
263{
264 local vrf_name=$1
265 local tb_id
266
267 __vrf_td_id_lookup $vrf_name
268 tb_id=$?
269
270 ip -6 route del table $tb_id unreachable default metric 4278198272
271 ip -4 route del table $tb_id unreachable default metric 4278198272
272 ip link del dev $vrf_name
273}
274
275__addr_add_del()
276{
277 local if_name=$1
278 local add_del=$2
279 local array
280
281 shift
282 shift
283 array=("${@}")
284
285 for addrstr in "${array[@]}"; do
286 ip address $add_del $addrstr dev $if_name
287 done
288}
289
290simple_if_init()
291{
292 local if_name=$1
293 local vrf_name
294 local array
295
296 shift
297 vrf_name=v$if_name
298 array=("${@}")
299
300 vrf_create $vrf_name
301 ip link set dev $if_name master $vrf_name
302 ip link set dev $vrf_name up
303 ip link set dev $if_name up
304
305 __addr_add_del $if_name add "${array[@]}"
306}
307
308simple_if_fini()
309{
310 local if_name=$1
311 local vrf_name
312 local array
313
314 shift
315 vrf_name=v$if_name
316 array=("${@}")
317
318 __addr_add_del $if_name del "${array[@]}"
319
320 ip link set dev $if_name down
321 vrf_destroy $vrf_name
322}
323
324master_name_get()
325{
326 local if_name=$1
327
328 ip -j link show dev $if_name | jq -r '.[]["master"]'
329}
330
331link_stats_tx_packets_get()
332{
333 local if_name=$1
334
335 ip -j -s link show dev $if_name | jq '.[]["stats64"]["tx"]["packets"]'
336}
337
338mac_get()
339{
340 local if_name=$1
341
342 ip -j link show dev $if_name | jq -r '.[]["address"]'
343}
344
345bridge_ageing_time_get()
346{
347 local bridge=$1
348 local ageing_time
349
350 # Need to divide by 100 to convert to seconds.
351 ageing_time=$(ip -j -d link show dev $bridge \
352 | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
353 echo $((ageing_time / 100))
354}
355
356forwarding_enable()
357{
358 ipv4_fwd=$(sysctl -n net.ipv4.conf.all.forwarding)
359 ipv6_fwd=$(sysctl -n net.ipv6.conf.all.forwarding)
360
361 sysctl -q -w net.ipv4.conf.all.forwarding=1
362 sysctl -q -w net.ipv6.conf.all.forwarding=1
363}
364
365forwarding_restore()
366{
367 sysctl -q -w net.ipv6.conf.all.forwarding=$ipv6_fwd
368 sysctl -q -w net.ipv4.conf.all.forwarding=$ipv4_fwd
369}
370
371tc_offload_check()
372{
373 for i in $(eval echo {1..$NUM_NETIFS}); do
374 ethtool -k ${NETIFS[p$i]} \
375 | grep "hw-tc-offload: on" &> /dev/null
376 if [[ $? -ne 0 ]]; then
377 return 1
378 fi
379 done
380
381 return 0
382}
383
384##############################################################################
385# Tests
386
387ping_test()
388{
389 local if_name=$1
390 local dip=$2
391 local vrf_name
392
393 RET=0
394
395 vrf_name=$(master_name_get $if_name)
396 ip vrf exec $vrf_name $PING $dip -c 10 -i 0.1 -w 2 &> /dev/null
397 check_err $?
398 log_test "ping"
399}
400
401ping6_test()
402{
403 local if_name=$1
404 local dip=$2
405 local vrf_name
406
407 RET=0
408
409 vrf_name=$(master_name_get $if_name)
410 ip vrf exec $vrf_name $PING6 $dip -c 10 -i 0.1 -w 2 &> /dev/null
411 check_err $?
412 log_test "ping6"
413}
414
415learning_test()
416{
417 local bridge=$1
418 local br_port1=$2 # Connected to `host1_if`.
419 local host1_if=$3
420 local host2_if=$4
421 local mac=de:ad:be:ef:13:37
422 local ageing_time
423
424 RET=0
425
426 bridge -j fdb show br $bridge brport $br_port1 \
427 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
428 check_fail $? "Found FDB record when should not"
429
430 # Disable unknown unicast flooding on `br_port1` to make sure
431 # packets are only forwarded through the port after a matching
432 # FDB entry was installed.
433 bridge link set dev $br_port1 flood off
434
435 tc qdisc add dev $host1_if ingress
436 tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
437 flower dst_mac $mac action drop
438
439 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
440 sleep 1
441
442 tc -j -s filter show dev $host1_if ingress \
443 | jq -e ".[] | select(.options.handle == 101) \
444 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
445 check_fail $? "Packet reached second host when should not"
446
447 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
448 sleep 1
449
450 bridge -j fdb show br $bridge brport $br_port1 \
451 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
452 check_err $? "Did not find FDB record when should"
453
454 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
455 sleep 1
456
457 tc -j -s filter show dev $host1_if ingress \
458 | jq -e ".[] | select(.options.handle == 101) \
459 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
460 check_err $? "Packet did not reach second host when should"
461
462 # Wait for 10 seconds after the ageing time to make sure FDB
463 # record was aged-out.
464 ageing_time=$(bridge_ageing_time_get $bridge)
465 sleep $((ageing_time + 10))
466
467 bridge -j fdb show br $bridge brport $br_port1 \
468 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
469 check_fail $? "Found FDB record when should not"
470
471 bridge link set dev $br_port1 learning off
472
473 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
474 sleep 1
475
476 bridge -j fdb show br $bridge brport $br_port1 \
477 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
478 check_fail $? "Found FDB record when should not"
479
480 bridge link set dev $br_port1 learning on
481
482 tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
483 tc qdisc del dev $host1_if ingress
484
485 bridge link set dev $br_port1 flood on
486
487 log_test "FDB learning"
488}
489
490flood_test_do()
491{
492 local should_flood=$1
493 local mac=$2
494 local ip=$3
495 local host1_if=$4
496 local host2_if=$5
497 local err=0
498
499 # Add an ACL on `host2_if` which will tell us whether the packet
500 # was flooded to it or not.
501 tc qdisc add dev $host2_if ingress
502 tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
503 flower dst_mac $mac action drop
504
505 $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
506 sleep 1
507
508 tc -j -s filter show dev $host2_if ingress \
509 | jq -e ".[] | select(.options.handle == 101) \
510 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
511 if [[ $? -ne 0 && $should_flood == "true" || \
512 $? -eq 0 && $should_flood == "false" ]]; then
513 err=1
514 fi
515
516 tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
517 tc qdisc del dev $host2_if ingress
518
519 return $err
520}
521
522flood_unicast_test()
523{
524 local br_port=$1
525 local host1_if=$2
526 local host2_if=$3
527 local mac=de:ad:be:ef:13:37
528 local ip=192.0.2.100
529
530 RET=0
531
532 bridge link set dev $br_port flood off
533
534 flood_test_do false $mac $ip $host1_if $host2_if
535 check_err $? "Packet flooded when should not"
536
537 bridge link set dev $br_port flood on
538
539 flood_test_do true $mac $ip $host1_if $host2_if
540 check_err $? "Packet was not flooded when should"
541
542 log_test "Unknown unicast flood"
543}
544
545flood_multicast_test()
546{
547 local br_port=$1
548 local host1_if=$2
549 local host2_if=$3
550 local mac=01:00:5e:00:00:01
551 local ip=239.0.0.1
552
553 RET=0
554
555 bridge link set dev $br_port mcast_flood off
556
557 flood_test_do false $mac $ip $host1_if $host2_if
558 check_err $? "Packet flooded when should not"
559
560 bridge link set dev $br_port mcast_flood on
561
562 flood_test_do true $mac $ip $host1_if $host2_if
563 check_err $? "Packet was not flooded when should"
564
565 log_test "Unregistered multicast flood"
566}
567
568flood_test()
569{
570 # `br_port` is connected to `host2_if`
571 local br_port=$1
572 local host1_if=$2
573 local host2_if=$3
574
575 flood_unicast_test $br_port $host1_if $host2_if
576 flood_multicast_test $br_port $host1_if $host2_if
577}
diff --git a/tools/testing/selftests/net/forwarding/router.sh b/tools/testing/selftests/net/forwarding/router.sh
new file mode 100755
index 000000000000..cc6a14abfa87
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/router.sh
@@ -0,0 +1,125 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=4
5source lib.sh
6
7h1_create()
8{
9 vrf_create "vrf-h1"
10 ip link set dev $h1 master vrf-h1
11
12 ip link set dev vrf-h1 up
13 ip link set dev $h1 up
14
15 ip address add 192.0.2.2/24 dev $h1
16 ip address add 2001:db8:1::2/64 dev $h1
17
18 ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1
19 ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1
20}
21
22h1_destroy()
23{
24 ip route del 2001:db8:2::/64 vrf vrf-h1
25 ip route del 198.51.100.0/24 vrf vrf-h1
26
27 ip address del 2001:db8:1::2/64 dev $h1
28 ip address del 192.0.2.2/24 dev $h1
29
30 ip link set dev $h1 down
31 vrf_destroy "vrf-h1"
32}
33
34h2_create()
35{
36 vrf_create "vrf-h2"
37 ip link set dev $h2 master vrf-h2
38
39 ip link set dev vrf-h2 up
40 ip link set dev $h2 up
41
42 ip address add 198.51.100.2/24 dev $h2
43 ip address add 2001:db8:2::2/64 dev $h2
44
45 ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1
46 ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1
47}
48
49h2_destroy()
50{
51 ip route del 2001:db8:1::/64 vrf vrf-h2
52 ip route del 192.0.2.0/24 vrf vrf-h2
53
54 ip address del 2001:db8:2::2/64 dev $h2
55 ip address del 198.51.100.2/24 dev $h2
56
57 ip link set dev $h2 down
58 vrf_destroy "vrf-h2"
59}
60
61router_create()
62{
63 ip link set dev $rp1 up
64 ip link set dev $rp2 up
65
66 ip address add 192.0.2.1/24 dev $rp1
67 ip address add 2001:db8:1::1/64 dev $rp1
68
69 ip address add 198.51.100.1/24 dev $rp2
70 ip address add 2001:db8:2::1/64 dev $rp2
71}
72
73router_destroy()
74{
75 ip address del 2001:db8:2::1/64 dev $rp2
76 ip address del 198.51.100.1/24 dev $rp2
77
78 ip address del 2001:db8:1::1/64 dev $rp1
79 ip address del 192.0.2.1/24 dev $rp1
80
81 ip link set dev $rp2 down
82 ip link set dev $rp1 down
83}
84
85setup_prepare()
86{
87 h1=${NETIFS[p1]}
88 rp1=${NETIFS[p2]}
89
90 rp2=${NETIFS[p3]}
91 h2=${NETIFS[p4]}
92
93 vrf_prepare
94
95 h1_create
96 h2_create
97
98 router_create
99
100 forwarding_enable
101}
102
103cleanup()
104{
105 pre_cleanup
106
107 forwarding_restore
108
109 router_destroy
110
111 h2_destroy
112 h1_destroy
113
114 vrf_cleanup
115}
116
117trap cleanup EXIT
118
119setup_prepare
120setup_wait
121
122ping_test $h1 198.51.100.2
123ping6_test $h1 2001:db8:2::2
124
125exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/router_multipath.sh b/tools/testing/selftests/net/forwarding/router_multipath.sh
new file mode 100755
index 000000000000..3bc351008db6
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/router_multipath.sh
@@ -0,0 +1,376 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=8
5source lib.sh
6
7h1_create()
8{
9 vrf_create "vrf-h1"
10 ip link set dev $h1 master vrf-h1
11
12 ip link set dev vrf-h1 up
13 ip link set dev $h1 up
14
15 ip address add 192.0.2.2/24 dev $h1
16 ip address add 2001:db8:1::2/64 dev $h1
17
18 ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1
19 ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1
20}
21
22h1_destroy()
23{
24 ip route del 2001:db8:2::/64 vrf vrf-h1
25 ip route del 198.51.100.0/24 vrf vrf-h1
26
27 ip address del 2001:db8:1::2/64 dev $h1
28 ip address del 192.0.2.2/24 dev $h1
29
30 ip link set dev $h1 down
31 vrf_destroy "vrf-h1"
32}
33
34h2_create()
35{
36 vrf_create "vrf-h2"
37 ip link set dev $h2 master vrf-h2
38
39 ip link set dev vrf-h2 up
40 ip link set dev $h2 up
41
42 ip address add 198.51.100.2/24 dev $h2
43 ip address add 2001:db8:2::2/64 dev $h2
44
45 ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1
46 ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1
47}
48
49h2_destroy()
50{
51 ip route del 2001:db8:1::/64 vrf vrf-h2
52 ip route del 192.0.2.0/24 vrf vrf-h2
53
54 ip address del 2001:db8:2::2/64 dev $h2
55 ip address del 198.51.100.2/24 dev $h2
56
57 ip link set dev $h2 down
58 vrf_destroy "vrf-h2"
59}
60
61router1_create()
62{
63 vrf_create "vrf-r1"
64 ip link set dev $rp11 master vrf-r1
65 ip link set dev $rp12 master vrf-r1
66 ip link set dev $rp13 master vrf-r1
67
68 ip link set dev vrf-r1 up
69 ip link set dev $rp11 up
70 ip link set dev $rp12 up
71 ip link set dev $rp13 up
72
73 ip address add 192.0.2.1/24 dev $rp11
74 ip address add 2001:db8:1::1/64 dev $rp11
75
76 ip address add 169.254.2.12/24 dev $rp12
77 ip address add fe80:2::12/64 dev $rp12
78
79 ip address add 169.254.3.13/24 dev $rp13
80 ip address add fe80:3::13/64 dev $rp13
81
82 ip route add 198.51.100.0/24 vrf vrf-r1 \
83 nexthop via 169.254.2.22 dev $rp12 \
84 nexthop via 169.254.3.23 dev $rp13
85 ip route add 2001:db8:2::/64 vrf vrf-r1 \
86 nexthop via fe80:2::22 dev $rp12 \
87 nexthop via fe80:3::23 dev $rp13
88}
89
90router1_destroy()
91{
92 ip route del 2001:db8:2::/64 vrf vrf-r1
93 ip route del 198.51.100.0/24 vrf vrf-r1
94
95 ip address del fe80:3::13/64 dev $rp13
96 ip address del 169.254.3.13/24 dev $rp13
97
98 ip address del fe80:2::12/64 dev $rp12
99 ip address del 169.254.2.12/24 dev $rp12
100
101 ip address del 2001:db8:1::1/64 dev $rp11
102 ip address del 192.0.2.1/24 dev $rp11
103
104 ip link set dev $rp13 down
105 ip link set dev $rp12 down
106 ip link set dev $rp11 down
107
108 vrf_destroy "vrf-r1"
109}
110
111router2_create()
112{
113 vrf_create "vrf-r2"
114 ip link set dev $rp21 master vrf-r2
115 ip link set dev $rp22 master vrf-r2
116 ip link set dev $rp23 master vrf-r2
117
118 ip link set dev vrf-r2 up
119 ip link set dev $rp21 up
120 ip link set dev $rp22 up
121 ip link set dev $rp23 up
122
123 ip address add 198.51.100.1/24 dev $rp21
124 ip address add 2001:db8:2::1/64 dev $rp21
125
126 ip address add 169.254.2.22/24 dev $rp22
127 ip address add fe80:2::22/64 dev $rp22
128
129 ip address add 169.254.3.23/24 dev $rp23
130 ip address add fe80:3::23/64 dev $rp23
131
132 ip route add 192.0.2.0/24 vrf vrf-r2 \
133 nexthop via 169.254.2.12 dev $rp22 \
134 nexthop via 169.254.3.13 dev $rp23
135 ip route add 2001:db8:1::/64 vrf vrf-r2 \
136 nexthop via fe80:2::12 dev $rp22 \
137 nexthop via fe80:3::13 dev $rp23
138}
139
140router2_destroy()
141{
142 ip route del 2001:db8:1::/64 vrf vrf-r2
143 ip route del 192.0.2.0/24 vrf vrf-r2
144
145 ip address del fe80:3::23/64 dev $rp23
146 ip address del 169.254.3.23/24 dev $rp23
147
148 ip address del fe80:2::22/64 dev $rp22
149 ip address del 169.254.2.22/24 dev $rp22
150
151 ip address del 2001:db8:2::1/64 dev $rp21
152 ip address del 198.51.100.1/24 dev $rp21
153
154 ip link set dev $rp23 down
155 ip link set dev $rp22 down
156 ip link set dev $rp21 down
157
158 vrf_destroy "vrf-r2"
159}
160
161multipath_eval()
162{
163 local desc="$1"
164 local weight_rp12=$2
165 local weight_rp13=$3
166 local packets_rp12=$4
167 local packets_rp13=$5
168 local weights_ratio packets_ratio diff
169
170 RET=0
171
172 if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
173 check_err 1 "Packet difference is 0"
174 log_test "Multipath"
175 log_info "Expected ratio $weights_ratio"
176 return
177 fi
178
179 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
180 weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
181 | bc -l)
182 packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
183 | bc -l)
184 else
185 weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" | \
186 bc -l)
187 packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" | \
188 bc -l)
189 fi
190
191 diff=$(echo $weights_ratio - $packets_ratio | bc -l)
192 diff=${diff#-}
193
194 test "$(echo "$diff / $weights_ratio > 0.1" | bc -l)" -eq 0
195 check_err $? "Too large discrepancy between expected and measured ratios"
196 log_test "$desc"
197 log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
198}
199
200multipath4_test()
201{
202 local desc="$1"
203 local weight_rp12=$2
204 local weight_rp13=$3
205 local t0_rp12 t0_rp13 t1_rp12 t1_rp13
206 local packets_rp12 packets_rp13
207 local hash_policy
208
209 # Transmit multiple flows from h1 to h2 and make sure they are
210 # distributed between both multipath links (rp12 and rp13)
211 # according to the configured weights.
212 hash_policy=$(sysctl -n net.ipv4.fib_multipath_hash_policy)
213 sysctl -q -w net.ipv4.fib_multipath_hash_policy=1
214 ip route replace 198.51.100.0/24 vrf vrf-r1 \
215 nexthop via 169.254.2.22 dev $rp12 weight $weight_rp12 \
216 nexthop via 169.254.3.23 dev $rp13 weight $weight_rp13
217
218 t0_rp12=$(link_stats_tx_packets_get $rp12)
219 t0_rp13=$(link_stats_tx_packets_get $rp13)
220
221 ip vrf exec vrf-h1 $MZ -q -p 64 -A 192.0.2.2 -B 198.51.100.2 \
222 -d 1msec -t udp "sp=1024,dp=0-32768"
223
224 t1_rp12=$(link_stats_tx_packets_get $rp12)
225 t1_rp13=$(link_stats_tx_packets_get $rp13)
226
227 let "packets_rp12 = $t1_rp12 - $t0_rp12"
228 let "packets_rp13 = $t1_rp13 - $t0_rp13"
229 multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
230
231 # Restore settings.
232 ip route replace 198.51.100.0/24 vrf vrf-r1 \
233 nexthop via 169.254.2.22 dev $rp12 \
234 nexthop via 169.254.3.23 dev $rp13
235 sysctl -q -w net.ipv4.fib_multipath_hash_policy=$hash_policy
236}
237
238multipath6_l4_test()
239{
240 local desc="$1"
241 local weight_rp12=$2
242 local weight_rp13=$3
243 local t0_rp12 t0_rp13 t1_rp12 t1_rp13
244 local packets_rp12 packets_rp13
245 local hash_policy
246
247 # Transmit multiple flows from h1 to h2 and make sure they are
248 # distributed between both multipath links (rp12 and rp13)
249 # according to the configured weights.
250 hash_policy=$(sysctl -n net.ipv6.fib_multipath_hash_policy)
251 sysctl -q -w net.ipv6.fib_multipath_hash_policy=1
252
253 ip route replace 2001:db8:2::/64 vrf vrf-r1 \
254 nexthop via fe80:2::22 dev $rp12 weight $weight_rp12 \
255 nexthop via fe80:3::23 dev $rp13 weight $weight_rp13
256
257 t0_rp12=$(link_stats_tx_packets_get $rp12)
258 t0_rp13=$(link_stats_tx_packets_get $rp13)
259
260 $MZ $h1 -6 -q -p 64 -A 2001:db8:1::2 -B 2001:db8:2::2 \
261 -d 1msec -t udp "sp=1024,dp=0-32768"
262
263 t1_rp12=$(link_stats_tx_packets_get $rp12)
264 t1_rp13=$(link_stats_tx_packets_get $rp13)
265
266 let "packets_rp12 = $t1_rp12 - $t0_rp12"
267 let "packets_rp13 = $t1_rp13 - $t0_rp13"
268 multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
269
270 ip route replace 2001:db8:2::/64 vrf vrf-r1 \
271 nexthop via fe80:2::22 dev $rp12 \
272 nexthop via fe80:3::23 dev $rp13
273
274 sysctl -q -w net.ipv6.fib_multipath_hash_policy=$hash_policy
275}
276
277multipath6_test()
278{
279 local desc="$1"
280 local weight_rp12=$2
281 local weight_rp13=$3
282 local t0_rp12 t0_rp13 t1_rp12 t1_rp13
283 local packets_rp12 packets_rp13
284
285 ip route replace 2001:db8:2::/64 vrf vrf-r1 \
286 nexthop via fe80:2::22 dev $rp12 weight $weight_rp12 \
287 nexthop via fe80:3::23 dev $rp13 weight $weight_rp13
288
289 t0_rp12=$(link_stats_tx_packets_get $rp12)
290 t0_rp13=$(link_stats_tx_packets_get $rp13)
291
292 # Generate 16384 echo requests, each with a random flow label.
293 for _ in $(seq 1 16384); do
294 ip vrf exec vrf-h1 $PING6 2001:db8:2::2 -F 0 -c 1 -q &> /dev/null
295 done
296
297 t1_rp12=$(link_stats_tx_packets_get $rp12)
298 t1_rp13=$(link_stats_tx_packets_get $rp13)
299
300 let "packets_rp12 = $t1_rp12 - $t0_rp12"
301 let "packets_rp13 = $t1_rp13 - $t0_rp13"
302 multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
303
304 ip route replace 2001:db8:2::/64 vrf vrf-r1 \
305 nexthop via fe80:2::22 dev $rp12 \
306 nexthop via fe80:3::23 dev $rp13
307}
308
309multipath_test()
310{
311 log_info "Running IPv4 multipath tests"
312 multipath4_test "ECMP" 1 1
313 multipath4_test "Weighted MP 2:1" 2 1
314 multipath4_test "Weighted MP 11:45" 11 45
315
316 log_info "Running IPv6 multipath tests"
317 multipath6_test "ECMP" 1 1
318 multipath6_test "Weighted MP 2:1" 2 1
319 multipath6_test "Weighted MP 11:45" 11 45
320
321 log_info "Running IPv6 L4 hash multipath tests"
322 multipath6_l4_test "ECMP" 1 1
323 multipath6_l4_test "Weighted MP 2:1" 2 1
324 multipath6_l4_test "Weighted MP 11:45" 11 45
325}
326
327setup_prepare()
328{
329 h1=${NETIFS[p1]}
330 rp11=${NETIFS[p2]}
331
332 rp12=${NETIFS[p3]}
333 rp22=${NETIFS[p4]}
334
335 rp13=${NETIFS[p5]}
336 rp23=${NETIFS[p6]}
337
338 rp21=${NETIFS[p7]}
339 h2=${NETIFS[p8]}
340
341 vrf_prepare
342
343 h1_create
344 h2_create
345
346 router1_create
347 router2_create
348
349 forwarding_enable
350}
351
352cleanup()
353{
354 pre_cleanup
355
356 forwarding_restore
357
358 router2_destroy
359 router1_destroy
360
361 h2_destroy
362 h1_destroy
363
364 vrf_cleanup
365}
366
367trap cleanup EXIT
368
369setup_prepare
370setup_wait
371
372ping_test $h1 198.51.100.2
373ping6_test $h1 2001:db8:2::2
374multipath_test
375
376exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/tc_actions.sh b/tools/testing/selftests/net/forwarding/tc_actions.sh
new file mode 100755
index 000000000000..3a6385ebd5d0
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/tc_actions.sh
@@ -0,0 +1,202 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=4
5source tc_common.sh
6source lib.sh
7
8tcflags="skip_hw"
9
10h1_create()
11{
12 simple_if_init $h1 192.0.2.1/24
13}
14
15h1_destroy()
16{
17 simple_if_fini $h1 192.0.2.1/24
18}
19
20h2_create()
21{
22 simple_if_init $h2 192.0.2.2/24
23 tc qdisc add dev $h2 clsact
24}
25
26h2_destroy()
27{
28 tc qdisc del dev $h2 clsact
29 simple_if_fini $h2 192.0.2.2/24
30}
31
32switch_create()
33{
34 simple_if_init $swp1 192.0.2.2/24
35 tc qdisc add dev $swp1 clsact
36
37 simple_if_init $swp2 192.0.2.1/24
38}
39
40switch_destroy()
41{
42 simple_if_fini $swp2 192.0.2.1/24
43
44 tc qdisc del dev $swp1 clsact
45 simple_if_fini $swp1 192.0.2.2/24
46}
47
48mirred_egress_test()
49{
50 local action=$1
51
52 RET=0
53
54 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
55 $tcflags dst_ip 192.0.2.2 action drop
56
57 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
58 -t ip -q
59
60 tc_check_packets "dev $h2 ingress" 101 1
61 check_fail $? "Matched without redirect rule inserted"
62
63 tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
64 $tcflags dst_ip 192.0.2.2 action mirred egress $action \
65 dev $swp2
66
67 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
68 -t ip -q
69
70 tc_check_packets "dev $h2 ingress" 101 1
71 check_err $? "Did not match incoming $action packet"
72
73 tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
74 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
75
76 log_test "mirred egress $action ($tcflags)"
77}
78
79gact_drop_and_ok_test()
80{
81 RET=0
82
83 tc filter add dev $swp1 ingress protocol ip pref 2 handle 102 flower \
84 $tcflags dst_ip 192.0.2.2 action drop
85
86 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
87 -t ip -q
88
89 tc_check_packets "dev $swp1 ingress" 102 1
90 check_err $? "Packet was not dropped"
91
92 tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
93 $tcflags dst_ip 192.0.2.2 action ok
94
95 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
96 -t ip -q
97
98 tc_check_packets "dev $swp1 ingress" 101 1
99 check_err $? "Did not see passed packet"
100
101 tc_check_packets "dev $swp1 ingress" 102 2
102 check_fail $? "Packet was dropped and it should not reach here"
103
104 tc filter del dev $swp1 ingress protocol ip pref 2 handle 102 flower
105 tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
106
107 log_test "gact drop and ok ($tcflags)"
108}
109
110gact_trap_test()
111{
112 RET=0
113
114 tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
115 skip_hw dst_ip 192.0.2.2 action drop
116 tc filter add dev $swp1 ingress protocol ip pref 3 handle 103 flower \
117 $tcflags dst_ip 192.0.2.2 action mirred egress redirect \
118 dev $swp2
119
120 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
121 -t ip -q
122
123 tc_check_packets "dev $swp1 ingress" 101 1
124 check_fail $? "Saw packet without trap rule inserted"
125
126 tc filter add dev $swp1 ingress protocol ip pref 2 handle 102 flower \
127 $tcflags dst_ip 192.0.2.2 action trap
128
129 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
130 -t ip -q
131
132 tc_check_packets "dev $swp1 ingress" 102 1
133 check_err $? "Packet was not trapped"
134
135 tc_check_packets "dev $swp1 ingress" 101 1
136 check_err $? "Did not see trapped packet"
137
138 tc filter del dev $swp1 ingress protocol ip pref 3 handle 103 flower
139 tc filter del dev $swp1 ingress protocol ip pref 2 handle 102 flower
140 tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
141
142 log_test "trap ($tcflags)"
143}
144
145setup_prepare()
146{
147 h1=${NETIFS[p1]}
148 swp1=${NETIFS[p2]}
149
150 swp2=${NETIFS[p3]}
151 h2=${NETIFS[p4]}
152
153 h1mac=$(mac_get $h1)
154 h2mac=$(mac_get $h2)
155
156 swp1origmac=$(mac_get $swp1)
157 swp2origmac=$(mac_get $swp2)
158 ip link set $swp1 address $h2mac
159 ip link set $swp2 address $h1mac
160
161 vrf_prepare
162
163 h1_create
164 h2_create
165 switch_create
166}
167
168cleanup()
169{
170 pre_cleanup
171
172 switch_destroy
173 h2_destroy
174 h1_destroy
175
176 vrf_cleanup
177
178 ip link set $swp2 address $swp2origmac
179 ip link set $swp1 address $swp1origmac
180}
181
182trap cleanup EXIT
183
184setup_prepare
185setup_wait
186
187gact_drop_and_ok_test
188mirred_egress_test "redirect"
189mirred_egress_test "mirror"
190
191tc_offload_check
192if [[ $? -ne 0 ]]; then
193 log_info "Could not test offloaded functionality"
194else
195 tcflags="skip_sw"
196 gact_drop_and_ok_test
197 mirred_egress_test "redirect"
198 mirred_egress_test "mirror"
199 gact_trap_test
200fi
201
202exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/tc_chains.sh b/tools/testing/selftests/net/forwarding/tc_chains.sh
new file mode 100755
index 000000000000..2fd15226974b
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/tc_chains.sh
@@ -0,0 +1,122 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=2
5source tc_common.sh
6source lib.sh
7
8tcflags="skip_hw"
9
10h1_create()
11{
12 simple_if_init $h1 192.0.2.1/24
13}
14
15h1_destroy()
16{
17 simple_if_fini $h1 192.0.2.1/24
18}
19
20h2_create()
21{
22 simple_if_init $h2 192.0.2.2/24
23 tc qdisc add dev $h2 clsact
24}
25
26h2_destroy()
27{
28 tc qdisc del dev $h2 clsact
29 simple_if_fini $h2 192.0.2.2/24
30}
31
32unreachable_chain_test()
33{
34 RET=0
35
36 tc filter add dev $h2 ingress chain 1 protocol ip pref 1 handle 1101 \
37 flower $tcflags dst_mac $h2mac action drop
38
39 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
40 -t ip -q
41
42 tc_check_packets "dev $h2 ingress" 1101 1
43 check_fail $? "matched on filter in unreachable chain"
44
45 tc filter del dev $h2 ingress chain 1 protocol ip pref 1 handle 1101 \
46 flower
47
48 log_test "unreachable chain ($tcflags)"
49}
50
51gact_goto_chain_test()
52{
53 RET=0
54
55 tc filter add dev $h2 ingress chain 1 protocol ip pref 1 handle 1101 \
56 flower $tcflags dst_mac $h2mac action drop
57 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
58 $tcflags dst_mac $h2mac action drop
59 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
60 $tcflags dst_mac $h2mac action goto chain 1
61
62 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
63 -t ip -q
64
65 tc_check_packets "dev $h2 ingress" 102 1
66 check_fail $? "Matched on a wrong filter"
67
68 tc_check_packets "dev $h2 ingress" 101 1
69 check_err $? "Did not match on correct filter with goto chain action"
70
71 tc_check_packets "dev $h2 ingress" 1101 1
72 check_err $? "Did not match on correct filter in chain 1"
73
74 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
75 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
76 tc filter del dev $h2 ingress chain 1 protocol ip pref 1 handle 1101 \
77 flower
78
79 log_test "gact goto chain ($tcflags)"
80}
81
82setup_prepare()
83{
84 h1=${NETIFS[p1]}
85 h2=${NETIFS[p2]}
86 h1mac=$(mac_get $h1)
87 h2mac=$(mac_get $h2)
88
89 vrf_prepare
90
91 h1_create
92 h2_create
93}
94
95cleanup()
96{
97 pre_cleanup
98
99 h2_destroy
100 h1_destroy
101
102 vrf_cleanup
103}
104
105trap cleanup EXIT
106
107setup_prepare
108setup_wait
109
110unreachable_chain_test
111gact_goto_chain_test
112
113tc_offload_check
114if [[ $? -ne 0 ]]; then
115 log_info "Could not test offloaded functionality"
116else
117 tcflags="skip_sw"
118 unreachable_chain_test
119 gact_goto_chain_test
120fi
121
122exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/tc_common.sh b/tools/testing/selftests/net/forwarding/tc_common.sh
new file mode 100644
index 000000000000..9d3b64a2a264
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/tc_common.sh
@@ -0,0 +1,25 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4CHECK_TC="yes"
5
6tc_check_packets()
7{
8 local id=$1
9 local handle=$2
10 local count=$3
11 local ret
12
13 output="$(tc -j -s filter show $id)"
14 # workaround the jq bug which causes jq to return 0 in case input is ""
15 ret=$?
16 if [[ $ret -ne 0 ]]; then
17 return $ret
18 fi
19 echo $output | \
20 jq -e ".[] \
21 | select(.options.handle == $handle) \
22 | select(.options.actions[0].stats.packets == $count)" \
23 &> /dev/null
24 return $?
25}
diff --git a/tools/testing/selftests/net/forwarding/tc_flower.sh b/tools/testing/selftests/net/forwarding/tc_flower.sh
new file mode 100755
index 000000000000..032b882adfc0
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/tc_flower.sh
@@ -0,0 +1,196 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=2
5source tc_common.sh
6source lib.sh
7
8tcflags="skip_hw"
9
10h1_create()
11{
12 simple_if_init $h1 192.0.2.1/24 198.51.100.1/24
13}
14
15h1_destroy()
16{
17 simple_if_fini $h1 192.0.2.1/24 198.51.100.1/24
18}
19
20h2_create()
21{
22 simple_if_init $h2 192.0.2.2/24 198.51.100.2/24
23 tc qdisc add dev $h2 clsact
24}
25
26h2_destroy()
27{
28 tc qdisc del dev $h2 clsact
29 simple_if_fini $h2 192.0.2.2/24 198.51.100.2/24
30}
31
32match_dst_mac_test()
33{
34 local dummy_mac=de:ad:be:ef:aa:aa
35
36 RET=0
37
38 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
39 $tcflags dst_mac $dummy_mac action drop
40 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
41 $tcflags dst_mac $h2mac action drop
42
43 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
44 -t ip -q
45
46 tc_check_packets "dev $h2 ingress" 101 1
47 check_fail $? "Matched on a wrong filter"
48
49 tc_check_packets "dev $h2 ingress" 102 1
50 check_err $? "Did not match on correct filter"
51
52 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
53 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
54
55 log_test "dst_mac match ($tcflags)"
56}
57
58match_src_mac_test()
59{
60 local dummy_mac=de:ad:be:ef:aa:aa
61
62 RET=0
63
64 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
65 $tcflags src_mac $dummy_mac action drop
66 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
67 $tcflags src_mac $h1mac action drop
68
69 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
70 -t ip -q
71
72 tc_check_packets "dev $h2 ingress" 101 1
73 check_fail $? "Matched on a wrong filter"
74
75 tc_check_packets "dev $h2 ingress" 102 1
76 check_err $? "Did not match on correct filter"
77
78 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
79 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
80
81 log_test "src_mac match ($tcflags)"
82}
83
84match_dst_ip_test()
85{
86 RET=0
87
88 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
89 $tcflags dst_ip 198.51.100.2 action drop
90 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
91 $tcflags dst_ip 192.0.2.2 action drop
92 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \
93 $tcflags dst_ip 192.0.2.0/24 action drop
94
95 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
96 -t ip -q
97
98 tc_check_packets "dev $h2 ingress" 101 1
99 check_fail $? "Matched on a wrong filter"
100
101 tc_check_packets "dev $h2 ingress" 102 1
102 check_err $? "Did not match on correct filter"
103
104 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
105
106 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
107 -t ip -q
108
109 tc_check_packets "dev $h2 ingress" 103 1
110 check_err $? "Did not match on correct filter with mask"
111
112 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
113 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower
114
115 log_test "dst_ip match ($tcflags)"
116}
117
118match_src_ip_test()
119{
120 RET=0
121
122 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
123 $tcflags src_ip 198.51.100.1 action drop
124 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
125 $tcflags src_ip 192.0.2.1 action drop
126 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \
127 $tcflags src_ip 192.0.2.0/24 action drop
128
129 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
130 -t ip -q
131
132 tc_check_packets "dev $h2 ingress" 101 1
133 check_fail $? "Matched on a wrong filter"
134
135 tc_check_packets "dev $h2 ingress" 102 1
136 check_err $? "Did not match on correct filter"
137
138 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
139
140 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
141 -t ip -q
142
143 tc_check_packets "dev $h2 ingress" 103 1
144 check_err $? "Did not match on correct filter with mask"
145
146 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
147 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower
148
149 log_test "src_ip match ($tcflags)"
150}
151
152setup_prepare()
153{
154 h1=${NETIFS[p1]}
155 h2=${NETIFS[p2]}
156 h1mac=$(mac_get $h1)
157 h2mac=$(mac_get $h2)
158
159 vrf_prepare
160
161 h1_create
162 h2_create
163}
164
165cleanup()
166{
167 pre_cleanup
168
169 h2_destroy
170 h1_destroy
171
172 vrf_cleanup
173}
174
175trap cleanup EXIT
176
177setup_prepare
178setup_wait
179
180match_dst_mac_test
181match_src_mac_test
182match_dst_ip_test
183match_src_ip_test
184
185tc_offload_check
186if [[ $? -ne 0 ]]; then
187 log_info "Could not test offloaded functionality"
188else
189 tcflags="skip_sw"
190 match_dst_mac_test
191 match_src_mac_test
192 match_dst_ip_test
193 match_src_ip_test
194fi
195
196exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/tc_shblocks.sh b/tools/testing/selftests/net/forwarding/tc_shblocks.sh
new file mode 100755
index 000000000000..077b98048ef4
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/tc_shblocks.sh
@@ -0,0 +1,122 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NUM_NETIFS=4
5source tc_common.sh
6source lib.sh
7
8tcflags="skip_hw"
9
10h1_create()
11{
12 simple_if_init $h1 192.0.2.1/24
13}
14
15h1_destroy()
16{
17 simple_if_fini $h1 192.0.2.1/24
18}
19
20h2_create()
21{
22 simple_if_init $h2 192.0.2.1/24
23}
24
25h2_destroy()
26{
27 simple_if_fini $h2 192.0.2.1/24
28}
29
30switch_create()
31{
32 simple_if_init $swp1 192.0.2.2/24
33 tc qdisc add dev $swp1 ingress_block 22 egress_block 23 clsact
34
35 simple_if_init $swp2 192.0.2.2/24
36 tc qdisc add dev $swp2 ingress_block 22 egress_block 23 clsact
37}
38
39switch_destroy()
40{
41 tc qdisc del dev $swp2 clsact
42 simple_if_fini $swp2 192.0.2.2/24
43
44 tc qdisc del dev $swp1 clsact
45 simple_if_fini $swp1 192.0.2.2/24
46}
47
48shared_block_test()
49{
50 RET=0
51
52 tc filter add block 22 protocol ip pref 1 handle 101 flower \
53 $tcflags dst_ip 192.0.2.2 action drop
54
55 $MZ $h1 -c 1 -p 64 -a $h1mac -b $swmac -A 192.0.2.1 -B 192.0.2.2 \
56 -t ip -q
57
58 tc_check_packets "block 22" 101 1
59 check_err $? "Did not match first incoming packet on a block"
60
61 $MZ $h2 -c 1 -p 64 -a $h2mac -b $swmac -A 192.0.2.1 -B 192.0.2.2 \
62 -t ip -q
63
64 tc_check_packets "block 22" 101 2
65 check_err $? "Did not match second incoming packet on a block"
66
67 tc filter del block 22 protocol ip pref 1 handle 101 flower
68
69 log_test "shared block ($tcflags)"
70}
71
72setup_prepare()
73{
74 h1=${NETIFS[p1]}
75 swp1=${NETIFS[p2]}
76
77 swp2=${NETIFS[p3]}
78 h2=${NETIFS[p4]}
79
80 h1mac=$(mac_get $h1)
81 h2mac=$(mac_get $h2)
82
83 swmac=$(mac_get $swp1)
84 swp2origmac=$(mac_get $swp2)
85 ip link set $swp2 address $swmac
86
87 vrf_prepare
88
89 h1_create
90 h2_create
91 switch_create
92}
93
94cleanup()
95{
96 pre_cleanup
97
98 switch_destroy
99 h2_destroy
100 h1_destroy
101
102 vrf_cleanup
103
104 ip link set $swp2 address $swp2origmac
105}
106
107trap cleanup EXIT
108
109setup_prepare
110setup_wait
111
112shared_block_test
113
114tc_offload_check
115if [[ $? -ne 0 ]]; then
116 log_info "Could not test offloaded functionality"
117else
118 tcflags="skip_sw"
119 shared_block_test
120fi
121
122exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/in_netns.sh b/tools/testing/selftests/net/in_netns.sh
new file mode 100755
index 000000000000..88795b510b32
--- /dev/null
+++ b/tools/testing/selftests/net/in_netns.sh
@@ -0,0 +1,23 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Execute a subprocess in a network namespace
5
6set -e
7
8readonly NETNS="ns-$(mktemp -u XXXXXX)"
9
10setup() {
11 ip netns add "${NETNS}"
12 ip -netns "${NETNS}" link set lo up
13}
14
15cleanup() {
16 ip netns del "${NETNS}"
17}
18
19trap cleanup EXIT
20setup
21
22ip netns exec "${NETNS}" "$@"
23exit "$?"
diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c
index e11fe84de0fd..406cc70c571d 100644
--- a/tools/testing/selftests/net/msg_zerocopy.c
+++ b/tools/testing/selftests/net/msg_zerocopy.c
@@ -14,6 +14,9 @@
14 * - SOCK_DGRAM 14 * - SOCK_DGRAM
15 * - SOCK_RAW 15 * - SOCK_RAW
16 * 16 *
17 * PF_RDS
18 * - SOCK_SEQPACKET
19 *
17 * Start this program on two connected hosts, one in send mode and 20 * Start this program on two connected hosts, one in send mode and
18 * the other with option '-r' to put it in receiver mode. 21 * the other with option '-r' to put it in receiver mode.
19 * 22 *
@@ -53,6 +56,7 @@
53#include <sys/types.h> 56#include <sys/types.h>
54#include <sys/wait.h> 57#include <sys/wait.h>
55#include <unistd.h> 58#include <unistd.h>
59#include <linux/rds.h>
56 60
57#ifndef SO_EE_ORIGIN_ZEROCOPY 61#ifndef SO_EE_ORIGIN_ZEROCOPY
58#define SO_EE_ORIGIN_ZEROCOPY 5 62#define SO_EE_ORIGIN_ZEROCOPY 5
@@ -164,17 +168,39 @@ static int do_accept(int fd)
164 return fd; 168 return fd;
165} 169}
166 170
167static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy) 171static void add_zcopy_cookie(struct msghdr *msg, uint32_t cookie)
172{
173 struct cmsghdr *cm;
174
175 if (!msg->msg_control)
176 error(1, errno, "NULL cookie");
177 cm = (void *)msg->msg_control;
178 cm->cmsg_len = CMSG_LEN(sizeof(cookie));
179 cm->cmsg_level = SOL_RDS;
180 cm->cmsg_type = RDS_CMSG_ZCOPY_COOKIE;
181 memcpy(CMSG_DATA(cm), &cookie, sizeof(cookie));
182}
183
184static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy, int domain)
168{ 185{
169 int ret, len, i, flags; 186 int ret, len, i, flags;
187 static uint32_t cookie;
188 char ckbuf[CMSG_SPACE(sizeof(cookie))];
170 189
171 len = 0; 190 len = 0;
172 for (i = 0; i < msg->msg_iovlen; i++) 191 for (i = 0; i < msg->msg_iovlen; i++)
173 len += msg->msg_iov[i].iov_len; 192 len += msg->msg_iov[i].iov_len;
174 193
175 flags = MSG_DONTWAIT; 194 flags = MSG_DONTWAIT;
176 if (do_zerocopy) 195 if (do_zerocopy) {
177 flags |= MSG_ZEROCOPY; 196 flags |= MSG_ZEROCOPY;
197 if (domain == PF_RDS) {
198 memset(&msg->msg_control, 0, sizeof(msg->msg_control));
199 msg->msg_controllen = CMSG_SPACE(sizeof(cookie));
200 msg->msg_control = (struct cmsghdr *)ckbuf;
201 add_zcopy_cookie(msg, ++cookie);
202 }
203 }
178 204
179 ret = sendmsg(fd, msg, flags); 205 ret = sendmsg(fd, msg, flags);
180 if (ret == -1 && errno == EAGAIN) 206 if (ret == -1 && errno == EAGAIN)
@@ -190,6 +216,10 @@ static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy)
190 if (do_zerocopy && ret) 216 if (do_zerocopy && ret)
191 expected_completions++; 217 expected_completions++;
192 } 218 }
219 if (do_zerocopy && domain == PF_RDS) {
220 msg->msg_control = NULL;
221 msg->msg_controllen = 0;
222 }
193 223
194 return true; 224 return true;
195} 225}
@@ -216,7 +246,9 @@ static void do_sendmsg_corked(int fd, struct msghdr *msg)
216 msg->msg_iov[0].iov_len = payload_len + extra_len; 246 msg->msg_iov[0].iov_len = payload_len + extra_len;
217 extra_len = 0; 247 extra_len = 0;
218 248
219 do_sendmsg(fd, msg, do_zerocopy); 249 do_sendmsg(fd, msg, do_zerocopy,
250 (cfg_dst_addr.ss_family == AF_INET ?
251 PF_INET : PF_INET6));
220 } 252 }
221 253
222 do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0); 254 do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
@@ -300,14 +332,65 @@ static int do_setup_tx(int domain, int type, int protocol)
300 if (cfg_zerocopy) 332 if (cfg_zerocopy)
301 do_setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, 1); 333 do_setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, 1);
302 334
303 if (domain != PF_PACKET) 335 if (domain != PF_PACKET && domain != PF_RDS)
304 if (connect(fd, (void *) &cfg_dst_addr, cfg_alen)) 336 if (connect(fd, (void *) &cfg_dst_addr, cfg_alen))
305 error(1, errno, "connect"); 337 error(1, errno, "connect");
306 338
339 if (domain == PF_RDS) {
340 if (bind(fd, (void *) &cfg_src_addr, cfg_alen))
341 error(1, errno, "bind");
342 }
343
307 return fd; 344 return fd;
308} 345}
309 346
310static bool do_recv_completion(int fd) 347static uint32_t do_process_zerocopy_cookies(struct rds_zcopy_cookies *ck)
348{
349 int i;
350
351 if (ck->num > RDS_MAX_ZCOOKIES)
352 error(1, 0, "Returned %d cookies, max expected %d\n",
353 ck->num, RDS_MAX_ZCOOKIES);
354 for (i = 0; i < ck->num; i++)
355 if (cfg_verbose >= 2)
356 fprintf(stderr, "%d\n", ck->cookies[i]);
357 return ck->num;
358}
359
360static bool do_recvmsg_completion(int fd)
361{
362 char cmsgbuf[CMSG_SPACE(sizeof(struct rds_zcopy_cookies))];
363 struct rds_zcopy_cookies *ck;
364 struct cmsghdr *cmsg;
365 struct msghdr msg;
366 bool ret = false;
367
368 memset(&msg, 0, sizeof(msg));
369 msg.msg_control = cmsgbuf;
370 msg.msg_controllen = sizeof(cmsgbuf);
371
372 if (recvmsg(fd, &msg, MSG_DONTWAIT))
373 return ret;
374
375 if (msg.msg_flags & MSG_CTRUNC)
376 error(1, errno, "recvmsg notification: truncated");
377
378 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
379 if (cmsg->cmsg_level == SOL_RDS &&
380 cmsg->cmsg_type == RDS_CMSG_ZCOPY_COMPLETION) {
381
382 ck = (struct rds_zcopy_cookies *)CMSG_DATA(cmsg);
383 completions += do_process_zerocopy_cookies(ck);
384 ret = true;
385 break;
386 }
387 error(0, 0, "ignoring cmsg at level %d type %d\n",
388 cmsg->cmsg_level, cmsg->cmsg_type);
389 }
390 return ret;
391}
392
393static bool do_recv_completion(int fd, int domain)
311{ 394{
312 struct sock_extended_err *serr; 395 struct sock_extended_err *serr;
313 struct msghdr msg = {}; 396 struct msghdr msg = {};
@@ -316,6 +399,9 @@ static bool do_recv_completion(int fd)
316 int ret, zerocopy; 399 int ret, zerocopy;
317 char control[100]; 400 char control[100];
318 401
402 if (domain == PF_RDS)
403 return do_recvmsg_completion(fd);
404
319 msg.msg_control = control; 405 msg.msg_control = control;
320 msg.msg_controllen = sizeof(control); 406 msg.msg_controllen = sizeof(control);
321 407
@@ -337,6 +423,7 @@ static bool do_recv_completion(int fd)
337 cm->cmsg_level, cm->cmsg_type); 423 cm->cmsg_level, cm->cmsg_type);
338 424
339 serr = (void *) CMSG_DATA(cm); 425 serr = (void *) CMSG_DATA(cm);
426
340 if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) 427 if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY)
341 error(1, 0, "serr: wrong origin: %u", serr->ee_origin); 428 error(1, 0, "serr: wrong origin: %u", serr->ee_origin);
342 if (serr->ee_errno != 0) 429 if (serr->ee_errno != 0)
@@ -371,20 +458,20 @@ static bool do_recv_completion(int fd)
371} 458}
372 459
373/* Read all outstanding messages on the errqueue */ 460/* Read all outstanding messages on the errqueue */
374static void do_recv_completions(int fd) 461static void do_recv_completions(int fd, int domain)
375{ 462{
376 while (do_recv_completion(fd)) {} 463 while (do_recv_completion(fd, domain)) {}
377} 464}
378 465
379/* Wait for all remaining completions on the errqueue */ 466/* Wait for all remaining completions on the errqueue */
380static void do_recv_remaining_completions(int fd) 467static void do_recv_remaining_completions(int fd, int domain)
381{ 468{
382 int64_t tstop = gettimeofday_ms() + cfg_waittime_ms; 469 int64_t tstop = gettimeofday_ms() + cfg_waittime_ms;
383 470
384 while (completions < expected_completions && 471 while (completions < expected_completions &&
385 gettimeofday_ms() < tstop) { 472 gettimeofday_ms() < tstop) {
386 if (do_poll(fd, POLLERR)) 473 if (do_poll(fd, domain == PF_RDS ? POLLIN : POLLERR))
387 do_recv_completions(fd); 474 do_recv_completions(fd, domain);
388 } 475 }
389 476
390 if (completions < expected_completions) 477 if (completions < expected_completions)
@@ -444,6 +531,13 @@ static void do_tx(int domain, int type, int protocol)
444 msg.msg_iovlen++; 531 msg.msg_iovlen++;
445 } 532 }
446 533
534 if (domain == PF_RDS) {
535 msg.msg_name = &cfg_dst_addr;
536 msg.msg_namelen = (cfg_dst_addr.ss_family == AF_INET ?
537 sizeof(struct sockaddr_in) :
538 sizeof(struct sockaddr_in6));
539 }
540
447 iov[2].iov_base = payload; 541 iov[2].iov_base = payload;
448 iov[2].iov_len = cfg_payload_len; 542 iov[2].iov_len = cfg_payload_len;
449 msg.msg_iovlen++; 543 msg.msg_iovlen++;
@@ -454,17 +548,17 @@ static void do_tx(int domain, int type, int protocol)
454 if (cfg_cork) 548 if (cfg_cork)
455 do_sendmsg_corked(fd, &msg); 549 do_sendmsg_corked(fd, &msg);
456 else 550 else
457 do_sendmsg(fd, &msg, cfg_zerocopy); 551 do_sendmsg(fd, &msg, cfg_zerocopy, domain);
458 552
459 while (!do_poll(fd, POLLOUT)) { 553 while (!do_poll(fd, POLLOUT)) {
460 if (cfg_zerocopy) 554 if (cfg_zerocopy)
461 do_recv_completions(fd); 555 do_recv_completions(fd, domain);
462 } 556 }
463 557
464 } while (gettimeofday_ms() < tstop); 558 } while (gettimeofday_ms() < tstop);
465 559
466 if (cfg_zerocopy) 560 if (cfg_zerocopy)
467 do_recv_remaining_completions(fd); 561 do_recv_remaining_completions(fd, domain);
468 562
469 if (close(fd)) 563 if (close(fd))
470 error(1, errno, "close"); 564 error(1, errno, "close");
@@ -610,6 +704,7 @@ static void parse_opts(int argc, char **argv)
610 40 /* max tcp options */; 704 40 /* max tcp options */;
611 int c; 705 int c;
612 char *daddr = NULL, *saddr = NULL; 706 char *daddr = NULL, *saddr = NULL;
707 char *cfg_test;
613 708
614 cfg_payload_len = max_payload_len; 709 cfg_payload_len = max_payload_len;
615 710
@@ -667,6 +762,14 @@ static void parse_opts(int argc, char **argv)
667 break; 762 break;
668 } 763 }
669 } 764 }
765
766 cfg_test = argv[argc - 1];
767 if (strcmp(cfg_test, "rds") == 0) {
768 if (!daddr)
769 error(1, 0, "-D <server addr> required for PF_RDS\n");
770 if (!cfg_rx && !saddr)
771 error(1, 0, "-S <client addr> required for PF_RDS\n");
772 }
670 setup_sockaddr(cfg_family, daddr, &cfg_dst_addr); 773 setup_sockaddr(cfg_family, daddr, &cfg_dst_addr);
671 setup_sockaddr(cfg_family, saddr, &cfg_src_addr); 774 setup_sockaddr(cfg_family, saddr, &cfg_src_addr);
672 775
@@ -699,6 +802,8 @@ int main(int argc, char **argv)
699 do_test(cfg_family, SOCK_STREAM, 0); 802 do_test(cfg_family, SOCK_STREAM, 0);
700 else if (!strcmp(cfg_test, "udp")) 803 else if (!strcmp(cfg_test, "udp"))
701 do_test(cfg_family, SOCK_DGRAM, 0); 804 do_test(cfg_family, SOCK_DGRAM, 0);
805 else if (!strcmp(cfg_test, "rds"))
806 do_test(PF_RDS, SOCK_SEQPACKET, 0);
702 else 807 else
703 error(1, 0, "unknown cfg_test %s", cfg_test); 808 error(1, 0, "unknown cfg_test %s", cfg_test);
704 809
diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh
new file mode 100755
index 000000000000..1e428781a625
--- /dev/null
+++ b/tools/testing/selftests/net/pmtu.sh
@@ -0,0 +1,471 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Check that route PMTU values match expectations, and that initial device MTU
5# values are assigned correctly
6#
7# Tests currently implemented:
8#
9# - pmtu_vti4_exception
10# Set up vti tunnel on top of veth, with xfrm states and policies, in two
11# namespaces with matching endpoints. Check that route exception is not
12# created if link layer MTU is not exceeded, then exceed it and check that
13# exception is created with the expected PMTU. The approach described
14# below for IPv6 doesn't apply here, because, on IPv4, administrative MTU
15# changes alone won't affect PMTU
16#
17# - pmtu_vti6_exception
18# Set up vti6 tunnel on top of veth, with xfrm states and policies, in two
19# namespaces with matching endpoints. Check that route exception is
20# created by exceeding link layer MTU with ping to other endpoint. Then
21# decrease and increase MTU of tunnel, checking that route exception PMTU
22# changes accordingly
23#
24# - pmtu_vti4_default_mtu
25# Set up vti4 tunnel on top of veth, in two namespaces with matching
26# endpoints. Check that MTU assigned to vti interface is the MTU of the
27# lower layer (veth) minus additional lower layer headers (zero, for veth)
28# minus IPv4 header length
29#
30# - pmtu_vti6_default_mtu
31# Same as above, for IPv6
32#
33# - pmtu_vti4_link_add_mtu
34# Set up vti4 interface passing MTU value at link creation, check MTU is
35# configured, and that link is not created with invalid MTU values
36#
37# - pmtu_vti6_link_add_mtu
38# Same as above, for IPv6
39#
40# - pmtu_vti6_link_change_mtu
41# Set up two dummy interfaces with different MTUs, create a vti6 tunnel
42# and check that configured MTU is used on link creation and changes, and
43# that MTU is properly calculated instead when MTU is not configured from
44# userspace
45
46tests="
47 pmtu_vti6_exception vti6: PMTU exceptions
48 pmtu_vti4_exception vti4: PMTU exceptions
49 pmtu_vti4_default_mtu vti4: default MTU assignment
50 pmtu_vti6_default_mtu vti6: default MTU assignment
51 pmtu_vti4_link_add_mtu vti4: MTU setting on link creation
52 pmtu_vti6_link_add_mtu vti6: MTU setting on link creation
53 pmtu_vti6_link_change_mtu vti6: MTU changes on link changes"
54
55NS_A="ns-$(mktemp -u XXXXXX)"
56NS_B="ns-$(mktemp -u XXXXXX)"
57ns_a="ip netns exec ${NS_A}"
58ns_b="ip netns exec ${NS_B}"
59
60veth4_a_addr="192.168.1.1"
61veth4_b_addr="192.168.1.2"
62veth4_mask="24"
63veth6_a_addr="fd00:1::a"
64veth6_b_addr="fd00:1::b"
65veth6_mask="64"
66
67vti4_a_addr="192.168.2.1"
68vti4_b_addr="192.168.2.2"
69vti4_mask="24"
70vti6_a_addr="fd00:2::a"
71vti6_b_addr="fd00:2::b"
72vti6_mask="64"
73
74dummy6_0_addr="fc00:1000::0"
75dummy6_1_addr="fc00:1001::0"
76dummy6_mask="64"
77
78cleanup_done=1
79err_buf=
80
81err() {
82 err_buf="${err_buf}${1}
83"
84}
85
86err_flush() {
87 echo -n "${err_buf}"
88 err_buf=
89}
90
91setup_namespaces() {
92 ip netns add ${NS_A} || return 1
93 ip netns add ${NS_B}
94}
95
96setup_veth() {
97 ${ns_a} ip link add veth_a type veth peer name veth_b || return 1
98 ${ns_a} ip link set veth_b netns ${NS_B}
99
100 ${ns_a} ip addr add ${veth4_a_addr}/${veth4_mask} dev veth_a
101 ${ns_b} ip addr add ${veth4_b_addr}/${veth4_mask} dev veth_b
102
103 ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a
104 ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b
105
106 ${ns_a} ip link set veth_a up
107 ${ns_b} ip link set veth_b up
108}
109
110setup_vti() {
111 proto=${1}
112 veth_a_addr="${2}"
113 veth_b_addr="${3}"
114 vti_a_addr="${4}"
115 vti_b_addr="${5}"
116 vti_mask=${6}
117
118 [ ${proto} -eq 6 ] && vti_type="vti6" || vti_type="vti"
119
120 ${ns_a} ip link add vti${proto}_a type ${vti_type} local ${veth_a_addr} remote ${veth_b_addr} key 10 || return 1
121 ${ns_b} ip link add vti${proto}_b type ${vti_type} local ${veth_b_addr} remote ${veth_a_addr} key 10
122
123 ${ns_a} ip addr add ${vti_a_addr}/${vti_mask} dev vti${proto}_a
124 ${ns_b} ip addr add ${vti_b_addr}/${vti_mask} dev vti${proto}_b
125
126 ${ns_a} ip link set vti${proto}_a up
127 ${ns_b} ip link set vti${proto}_b up
128
129 sleep 1
130}
131
132setup_vti4() {
133 setup_vti 4 ${veth4_a_addr} ${veth4_b_addr} ${vti4_a_addr} ${vti4_b_addr} ${vti4_mask}
134}
135
136setup_vti6() {
137 setup_vti 6 ${veth6_a_addr} ${veth6_b_addr} ${vti6_a_addr} ${vti6_b_addr} ${vti6_mask}
138}
139
140setup_xfrm() {
141 proto=${1}
142 veth_a_addr="${2}"
143 veth_b_addr="${3}"
144
145 ${ns_a} ip -${proto} xfrm state add src ${veth_a_addr} dst ${veth_b_addr} spi 0x1000 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel || return 1
146 ${ns_a} ip -${proto} xfrm state add src ${veth_b_addr} dst ${veth_a_addr} spi 0x1001 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel
147 ${ns_a} ip -${proto} xfrm policy add dir out mark 10 tmpl src ${veth_a_addr} dst ${veth_b_addr} proto esp mode tunnel
148 ${ns_a} ip -${proto} xfrm policy add dir in mark 10 tmpl src ${veth_b_addr} dst ${veth_a_addr} proto esp mode tunnel
149
150 ${ns_b} ip -${proto} xfrm state add src ${veth_a_addr} dst ${veth_b_addr} spi 0x1000 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel
151 ${ns_b} ip -${proto} xfrm state add src ${veth_b_addr} dst ${veth_a_addr} spi 0x1001 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel
152 ${ns_b} ip -${proto} xfrm policy add dir out mark 10 tmpl src ${veth_b_addr} dst ${veth_a_addr} proto esp mode tunnel
153 ${ns_b} ip -${proto} xfrm policy add dir in mark 10 tmpl src ${veth_a_addr} dst ${veth_b_addr} proto esp mode tunnel
154}
155
156setup_xfrm4() {
157 setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr}
158}
159
160setup_xfrm6() {
161 setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr}
162}
163
164setup() {
165 [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return 1
166
167 cleanup_done=0
168 for arg do
169 eval setup_${arg} || { echo " ${arg} not supported"; return 1; }
170 done
171}
172
173cleanup() {
174 [ ${cleanup_done} -eq 1 ] && return
175 ip netns del ${NS_A} 2 > /dev/null
176 ip netns del ${NS_B} 2 > /dev/null
177 cleanup_done=1
178}
179
180mtu() {
181 ns_cmd="${1}"
182 dev="${2}"
183 mtu="${3}"
184
185 ${ns_cmd} ip link set dev ${dev} mtu ${mtu}
186}
187
188mtu_parse() {
189 input="${1}"
190
191 next=0
192 for i in ${input}; do
193 [ ${next} -eq 1 ] && echo "${i}" && return
194 [ "${i}" = "mtu" ] && next=1
195 done
196}
197
198link_get() {
199 ns_cmd="${1}"
200 name="${2}"
201
202 ${ns_cmd} ip link show dev "${name}"
203}
204
205link_get_mtu() {
206 ns_cmd="${1}"
207 name="${2}"
208
209 mtu_parse "$(link_get "${ns_cmd}" ${name})"
210}
211
212route_get_dst_exception() {
213 ns_cmd="${1}"
214 dst="${2}"
215
216 ${ns_cmd} ip route get "${dst}"
217}
218
219route_get_dst_pmtu_from_exception() {
220 ns_cmd="${1}"
221 dst="${2}"
222
223 mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})"
224}
225
226test_pmtu_vti4_exception() {
227 setup namespaces veth vti4 xfrm4 || return 2
228
229 veth_mtu=1500
230 vti_mtu=$((veth_mtu - 20))
231
232 # SPI SN IV ICV pad length next header
233 esp_payload_rfc4106=$((vti_mtu - 4 - 4 - 8 - 16 - 1 - 1))
234 ping_payload=$((esp_payload_rfc4106 - 28))
235
236 mtu "${ns_a}" veth_a ${veth_mtu}
237 mtu "${ns_b}" veth_b ${veth_mtu}
238 mtu "${ns_a}" vti4_a ${vti_mtu}
239 mtu "${ns_b}" vti4_b ${vti_mtu}
240
241 # Send DF packet without exceeding link layer MTU, check that no
242 # exception is created
243 ${ns_a} ping -q -M want -i 0.1 -w 2 -s ${ping_payload} ${vti4_b_addr} > /dev/null
244 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})"
245 if [ "${pmtu}" != "" ]; then
246 err " unexpected exception created with PMTU ${pmtu} for IP payload length ${esp_payload_rfc4106}"
247 return 1
248 fi
249
250 # Now exceed link layer MTU by one byte, check that exception is created
251 ${ns_a} ping -q -M want -i 0.1 -w 2 -s $((ping_payload + 1)) ${vti4_b_addr} > /dev/null
252 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})"
253 if [ "${pmtu}" = "" ]; then
254 err " exception not created for IP payload length $((esp_payload_rfc4106 + 1))"
255 return 1
256 fi
257
258 # ...with the right PMTU value
259 if [ ${pmtu} -ne ${esp_payload_rfc4106} ]; then
260 err " wrong PMTU ${pmtu} in exception, expected: ${esp_payload_rfc4106}"
261 return 1
262 fi
263}
264
265test_pmtu_vti6_exception() {
266 setup namespaces veth vti6 xfrm6 || return 2
267 fail=0
268
269 # Create route exception by exceeding link layer MTU
270 mtu "${ns_a}" veth_a 4000
271 mtu "${ns_b}" veth_b 4000
272 mtu "${ns_a}" vti6_a 5000
273 mtu "${ns_b}" vti6_b 5000
274 ${ns_a} ping6 -q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev/null
275
276 # Check that exception was created
277 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" = "" ]; then
278 err " tunnel exceeding link layer MTU didn't create route exception"
279 return 1
280 fi
281
282 # Decrease tunnel MTU, check for PMTU decrease in route exception
283 mtu "${ns_a}" vti6_a 3000
284
285 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 3000 ]; then
286 err " decreasing tunnel MTU didn't decrease route exception PMTU"
287 fail=1
288 fi
289
290 # Increase tunnel MTU, check for PMTU increase in route exception
291 mtu "${ns_a}" vti6_a 9000
292 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 9000 ]; then
293 err " increasing tunnel MTU didn't increase route exception PMTU"
294 fail=1
295 fi
296
297 return ${fail}
298}
299
300test_pmtu_vti4_default_mtu() {
301 setup namespaces veth vti4 || return 2
302
303 # Check that MTU of vti device is MTU of veth minus IPv4 header length
304 veth_mtu="$(link_get_mtu "${ns_a}" veth_a)"
305 vti4_mtu="$(link_get_mtu "${ns_a}" vti4_a)"
306 if [ $((veth_mtu - vti4_mtu)) -ne 20 ]; then
307 err " vti MTU ${vti4_mtu} is not veth MTU ${veth_mtu} minus IPv4 header length"
308 return 1
309 fi
310}
311
312test_pmtu_vti6_default_mtu() {
313 setup namespaces veth vti6 || return 2
314
315 # Check that MTU of vti device is MTU of veth minus IPv6 header length
316 veth_mtu="$(link_get_mtu "${ns_a}" veth_a)"
317 vti6_mtu="$(link_get_mtu "${ns_a}" vti6_a)"
318 if [ $((veth_mtu - vti6_mtu)) -ne 40 ]; then
319 err " vti MTU ${vti6_mtu} is not veth MTU ${veth_mtu} minus IPv6 header length"
320 return 1
321 fi
322}
323
324test_pmtu_vti4_link_add_mtu() {
325 setup namespaces || return 2
326
327 ${ns_a} ip link add vti4_a type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10
328 [ $? -ne 0 ] && err " vti not supported" && return 2
329 ${ns_a} ip link del vti4_a
330
331 fail=0
332
333 min=68
334 max=$((65528 - 20))
335 # Check invalid values first
336 for v in $((min - 1)) $((max + 1)); do
337 ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10 2>/dev/null
338 # This can fail, or MTU can be adjusted to a proper value
339 [ $? -ne 0 ] && continue
340 mtu="$(link_get_mtu "${ns_a}" vti4_a)"
341 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then
342 err " vti tunnel created with invalid MTU ${mtu}"
343 fail=1
344 fi
345 ${ns_a} ip link del vti4_a
346 done
347
348 # Now check valid values
349 for v in ${min} 1300 ${max}; do
350 ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10
351 mtu="$(link_get_mtu "${ns_a}" vti4_a)"
352 ${ns_a} ip link del vti4_a
353 if [ "${mtu}" != "${v}" ]; then
354 err " vti MTU ${mtu} doesn't match configured value ${v}"
355 fail=1
356 fi
357 done
358
359 return ${fail}
360}
361
362test_pmtu_vti6_link_add_mtu() {
363 setup namespaces || return 2
364
365 ${ns_a} ip link add vti6_a type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10
366 [ $? -ne 0 ] && err " vti6 not supported" && return 2
367 ${ns_a} ip link del vti6_a
368
369 fail=0
370
371 min=1280
372 max=$((65535 - 40))
373 # Check invalid values first
374 for v in $((min - 1)) $((max + 1)); do
375 ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10 2>/dev/null
376 # This can fail, or MTU can be adjusted to a proper value
377 [ $? -ne 0 ] && continue
378 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
379 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then
380 err " vti6 tunnel created with invalid MTU ${v}"
381 fail=1
382 fi
383 ${ns_a} ip link del vti6_a
384 done
385
386 # Now check valid values
387 for v in 1280 1300 $((65535 - 40)); do
388 ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10
389 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
390 ${ns_a} ip link del vti6_a
391 if [ "${mtu}" != "${v}" ]; then
392 err " vti6 MTU ${mtu} doesn't match configured value ${v}"
393 fail=1
394 fi
395 done
396
397 return ${fail}
398}
399
400test_pmtu_vti6_link_change_mtu() {
401 setup namespaces || return 2
402
403 ${ns_a} ip link add dummy0 mtu 1500 type dummy
404 [ $? -ne 0 ] && err " dummy not supported" && return 2
405 ${ns_a} ip link add dummy1 mtu 3000 type dummy
406 ${ns_a} ip link set dummy0 up
407 ${ns_a} ip link set dummy1 up
408
409 ${ns_a} ip addr add ${dummy6_0_addr}/${dummy6_mask} dev dummy0
410 ${ns_a} ip addr add ${dummy6_1_addr}/${dummy6_mask} dev dummy1
411
412 fail=0
413
414 # Create vti6 interface bound to device, passing MTU, check it
415 ${ns_a} ip link add vti6_a mtu 1300 type vti6 remote ${dummy6_0_addr} local ${dummy6_0_addr}
416 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
417 if [ ${mtu} -ne 1300 ]; then
418 err " vti6 MTU ${mtu} doesn't match configured value 1300"
419 fail=1
420 fi
421
422 # Move to another device with different MTU, without passing MTU, check
423 # MTU is adjusted
424 ${ns_a} ip link set vti6_a type vti6 remote ${dummy6_1_addr} local ${dummy6_1_addr}
425 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
426 if [ ${mtu} -ne $((3000 - 40)) ]; then
427 err " vti MTU ${mtu} is not dummy MTU 3000 minus IPv6 header length"
428 fail=1
429 fi
430
431 # Move it back, passing MTU, check MTU is not overridden
432 ${ns_a} ip link set vti6_a mtu 1280 type vti6 remote ${dummy6_0_addr} local ${dummy6_0_addr}
433 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
434 if [ ${mtu} -ne 1280 ]; then
435 err " vti6 MTU ${mtu} doesn't match configured value 1280"
436 fail=1
437 fi
438
439 return ${fail}
440}
441
442trap cleanup EXIT
443
444exitcode=0
445desc=0
446IFS="
447"
448for t in ${tests}; do
449 [ $desc -eq 0 ] && name="${t}" && desc=1 && continue || desc=0
450
451 (
452 unset IFS
453 eval test_${name}
454 ret=$?
455 cleanup
456
457 if [ $ret -eq 0 ]; then
458 printf "TEST: %-60s [ OK ]\n" "${t}"
459 elif [ $ret -eq 1 ]; then
460 printf "TEST: %-60s [FAIL]\n" "${t}"
461 err_flush
462 exit 1
463 elif [ $ret -eq 2 ]; then
464 printf "TEST: %-60s [SKIP]\n" "${t}"
465 err_flush
466 fi
467 )
468 [ $? -ne 0 ] && exitcode=1
469done
470
471exit ${exitcode}
diff --git a/tools/testing/selftests/net/psock_fanout.c b/tools/testing/selftests/net/psock_fanout.c
index 989f917068d1..bd9b9632c72b 100644
--- a/tools/testing/selftests/net/psock_fanout.c
+++ b/tools/testing/selftests/net/psock_fanout.c
@@ -50,6 +50,7 @@
50#include <linux/filter.h> 50#include <linux/filter.h>
51#include <linux/bpf.h> 51#include <linux/bpf.h>
52#include <linux/if_packet.h> 52#include <linux/if_packet.h>
53#include <net/if.h>
53#include <net/ethernet.h> 54#include <net/ethernet.h>
54#include <netinet/ip.h> 55#include <netinet/ip.h>
55#include <netinet/udp.h> 56#include <netinet/udp.h>
@@ -73,14 +74,29 @@
73 * @return -1 if mode is bad, a valid socket otherwise */ 74 * @return -1 if mode is bad, a valid socket otherwise */
74static int sock_fanout_open(uint16_t typeflags, uint16_t group_id) 75static int sock_fanout_open(uint16_t typeflags, uint16_t group_id)
75{ 76{
77 struct sockaddr_ll addr = {0};
76 int fd, val; 78 int fd, val;
77 79
78 fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); 80 fd = socket(PF_PACKET, SOCK_RAW, 0);
79 if (fd < 0) { 81 if (fd < 0) {
80 perror("socket packet"); 82 perror("socket packet");
81 exit(1); 83 exit(1);
82 } 84 }
83 85
86 pair_udp_setfilter(fd);
87
88 addr.sll_family = AF_PACKET;
89 addr.sll_protocol = htons(ETH_P_IP);
90 addr.sll_ifindex = if_nametoindex("lo");
91 if (addr.sll_ifindex == 0) {
92 perror("if_nametoindex");
93 exit(1);
94 }
95 if (bind(fd, (void *) &addr, sizeof(addr))) {
96 perror("bind packet");
97 exit(1);
98 }
99
84 val = (((int) typeflags) << 16) | group_id; 100 val = (((int) typeflags) << 16) | group_id;
85 if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &val, sizeof(val))) { 101 if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &val, sizeof(val))) {
86 if (close(fd)) { 102 if (close(fd)) {
@@ -90,7 +106,6 @@ static int sock_fanout_open(uint16_t typeflags, uint16_t group_id)
90 return -1; 106 return -1;
91 } 107 }
92 108
93 pair_udp_setfilter(fd);
94 return fd; 109 return fd;
95} 110}
96 111
@@ -128,6 +143,8 @@ static void sock_fanout_getopts(int fd, uint16_t *typeflags, uint16_t *group_id)
128 143
129static void sock_fanout_set_ebpf(int fd) 144static void sock_fanout_set_ebpf(int fd)
130{ 145{
146 static char log_buf[65536];
147
131 const int len_off = __builtin_offsetof(struct __sk_buff, len); 148 const int len_off = __builtin_offsetof(struct __sk_buff, len);
132 struct bpf_insn prog[] = { 149 struct bpf_insn prog[] = {
133 { BPF_ALU64 | BPF_MOV | BPF_X, 6, 1, 0, 0 }, 150 { BPF_ALU64 | BPF_MOV | BPF_X, 6, 1, 0, 0 },
@@ -140,7 +157,6 @@ static void sock_fanout_set_ebpf(int fd)
140 { BPF_ALU | BPF_MOV | BPF_K, 0, 0, 0, 0 }, 157 { BPF_ALU | BPF_MOV | BPF_K, 0, 0, 0, 0 },
141 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 } 158 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
142 }; 159 };
143 char log_buf[512];
144 union bpf_attr attr; 160 union bpf_attr attr;
145 int pfd; 161 int pfd;
146 162
@@ -228,7 +244,7 @@ static int sock_fanout_read(int fds[], char *rings[], const int expect[])
228 244
229 if ((!(ret[0] == expect[0] && ret[1] == expect[1])) && 245 if ((!(ret[0] == expect[0] && ret[1] == expect[1])) &&
230 (!(ret[0] == expect[1] && ret[1] == expect[0]))) { 246 (!(ret[0] == expect[1] && ret[1] == expect[0]))) {
231 fprintf(stderr, "ERROR: incorrect queue lengths\n"); 247 fprintf(stderr, "warning: incorrect queue lengths\n");
232 return 1; 248 return 1;
233 } 249 }
234 250
@@ -347,7 +363,8 @@ static int test_datapath(uint16_t typeflags, int port_off,
347 uint8_t type = typeflags & 0xFF; 363 uint8_t type = typeflags & 0xFF;
348 int fds[2], fds_udp[2][2], ret; 364 int fds[2], fds_udp[2][2], ret;
349 365
350 fprintf(stderr, "test: datapath 0x%hx\n", typeflags); 366 fprintf(stderr, "\ntest: datapath 0x%hx ports %hu,%hu\n",
367 typeflags, PORT_BASE, PORT_BASE + port_off);
351 368
352 fds[0] = sock_fanout_open(typeflags, 0); 369 fds[0] = sock_fanout_open(typeflags, 0);
353 fds[1] = sock_fanout_open(typeflags, 0); 370 fds[1] = sock_fanout_open(typeflags, 0);
@@ -418,7 +435,7 @@ int main(int argc, char **argv)
418 const int expect_cpu1[2][2] = { { 0, 20 }, { 0, 20 } }; 435 const int expect_cpu1[2][2] = { { 0, 20 }, { 0, 20 } };
419 const int expect_bpf[2][2] = { { 15, 5 }, { 15, 20 } }; 436 const int expect_bpf[2][2] = { { 15, 5 }, { 15, 20 } };
420 const int expect_uniqueid[2][2] = { { 20, 20}, { 20, 20 } }; 437 const int expect_uniqueid[2][2] = { { 20, 20}, { 20, 20 } };
421 int port_off = 2, tries = 5, ret; 438 int port_off = 2, tries = 20, ret;
422 439
423 test_control_single(); 440 test_control_single();
424 test_control_group(); 441 test_control_group();
@@ -427,10 +444,14 @@ int main(int argc, char **argv)
427 /* find a set of ports that do not collide onto the same socket */ 444 /* find a set of ports that do not collide onto the same socket */
428 ret = test_datapath(PACKET_FANOUT_HASH, port_off, 445 ret = test_datapath(PACKET_FANOUT_HASH, port_off,
429 expect_hash[0], expect_hash[1]); 446 expect_hash[0], expect_hash[1]);
430 while (ret && tries--) { 447 while (ret) {
431 fprintf(stderr, "info: trying alternate ports (%d)\n", tries); 448 fprintf(stderr, "info: trying alternate ports (%d)\n", tries);
432 ret = test_datapath(PACKET_FANOUT_HASH, ++port_off, 449 ret = test_datapath(PACKET_FANOUT_HASH, ++port_off,
433 expect_hash[0], expect_hash[1]); 450 expect_hash[0], expect_hash[1]);
451 if (!--tries) {
452 fprintf(stderr, "too many collisions\n");
453 return 1;
454 }
434 } 455 }
435 456
436 ret |= test_datapath(PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_ROLLOVER, 457 ret |= test_datapath(PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_ROLLOVER,
diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh
index a622eeecc3a6..e6f485235435 100755
--- a/tools/testing/selftests/net/rtnetlink.sh
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -517,6 +517,7 @@ kci_test_gretap()
517 ip link help gretap 2>&1 | grep -q "^Usage:" 517 ip link help gretap 2>&1 | grep -q "^Usage:"
518 if [ $? -ne 0 ];then 518 if [ $? -ne 0 ];then
519 echo "SKIP: gretap: iproute2 too old" 519 echo "SKIP: gretap: iproute2 too old"
520 ip netns del "$testns"
520 return 1 521 return 1
521 fi 522 fi
522 523
@@ -543,6 +544,7 @@ kci_test_gretap()
543 544
544 if [ $ret -ne 0 ]; then 545 if [ $ret -ne 0 ]; then
545 echo "FAIL: gretap" 546 echo "FAIL: gretap"
547 ip netns del "$testns"
546 return 1 548 return 1
547 fi 549 fi
548 echo "PASS: gretap" 550 echo "PASS: gretap"
@@ -565,6 +567,7 @@ kci_test_ip6gretap()
565 ip link help ip6gretap 2>&1 | grep -q "^Usage:" 567 ip link help ip6gretap 2>&1 | grep -q "^Usage:"
566 if [ $? -ne 0 ];then 568 if [ $? -ne 0 ];then
567 echo "SKIP: ip6gretap: iproute2 too old" 569 echo "SKIP: ip6gretap: iproute2 too old"
570 ip netns del "$testns"
568 return 1 571 return 1
569 fi 572 fi
570 573
@@ -591,6 +594,7 @@ kci_test_ip6gretap()
591 594
592 if [ $ret -ne 0 ]; then 595 if [ $ret -ne 0 ]; then
593 echo "FAIL: ip6gretap" 596 echo "FAIL: ip6gretap"
597 ip netns del "$testns"
594 return 1 598 return 1
595 fi 599 fi
596 echo "PASS: ip6gretap" 600 echo "PASS: ip6gretap"
@@ -655,6 +659,7 @@ kci_test_erspan()
655 659
656 if [ $ret -ne 0 ]; then 660 if [ $ret -ne 0 ]; then
657 echo "FAIL: erspan" 661 echo "FAIL: erspan"
662 ip netns del "$testns"
658 return 1 663 return 1
659 fi 664 fi
660 echo "PASS: erspan" 665 echo "PASS: erspan"
@@ -720,6 +725,7 @@ kci_test_ip6erspan()
720 725
721 if [ $ret -ne 0 ]; then 726 if [ $ret -ne 0 ]; then
722 echo "FAIL: ip6erspan" 727 echo "FAIL: ip6erspan"
728 ip netns del "$testns"
723 return 1 729 return 1
724 fi 730 fi
725 echo "PASS: ip6erspan" 731 echo "PASS: ip6erspan"
diff --git a/tools/testing/selftests/net/run_afpackettests b/tools/testing/selftests/net/run_afpackettests
index 21fe149e3de1..bea079edc278 100755
--- a/tools/testing/selftests/net/run_afpackettests
+++ b/tools/testing/selftests/net/run_afpackettests
@@ -9,7 +9,7 @@ fi
9echo "--------------------" 9echo "--------------------"
10echo "running psock_fanout test" 10echo "running psock_fanout test"
11echo "--------------------" 11echo "--------------------"
12./psock_fanout 12./in_netns.sh ./psock_fanout
13if [ $? -ne 0 ]; then 13if [ $? -ne 0 ]; then
14 echo "[FAIL]" 14 echo "[FAIL]"
15else 15else
@@ -19,7 +19,7 @@ fi
19echo "--------------------" 19echo "--------------------"
20echo "running psock_tpacket test" 20echo "running psock_tpacket test"
21echo "--------------------" 21echo "--------------------"
22./psock_tpacket 22./in_netns.sh ./psock_tpacket
23if [ $? -ne 0 ]; then 23if [ $? -ne 0 ]; then
24 echo "[FAIL]" 24 echo "[FAIL]"
25else 25else
diff --git a/tools/testing/selftests/networking/timestamping/txtimestamp.c b/tools/testing/selftests/networking/timestamping/txtimestamp.c
index 5df07047ca86..81a98a240456 100644
--- a/tools/testing/selftests/networking/timestamping/txtimestamp.c
+++ b/tools/testing/selftests/networking/timestamping/txtimestamp.c
@@ -68,9 +68,11 @@ static int cfg_num_pkts = 4;
68static int do_ipv4 = 1; 68static int do_ipv4 = 1;
69static int do_ipv6 = 1; 69static int do_ipv6 = 1;
70static int cfg_payload_len = 10; 70static int cfg_payload_len = 10;
71static int cfg_poll_timeout = 100;
71static bool cfg_show_payload; 72static bool cfg_show_payload;
72static bool cfg_do_pktinfo; 73static bool cfg_do_pktinfo;
73static bool cfg_loop_nodata; 74static bool cfg_loop_nodata;
75static bool cfg_no_delay;
74static uint16_t dest_port = 9000; 76static uint16_t dest_port = 9000;
75 77
76static struct sockaddr_in daddr; 78static struct sockaddr_in daddr;
@@ -171,7 +173,7 @@ static void __poll(int fd)
171 173
172 memset(&pollfd, 0, sizeof(pollfd)); 174 memset(&pollfd, 0, sizeof(pollfd));
173 pollfd.fd = fd; 175 pollfd.fd = fd;
174 ret = poll(&pollfd, 1, 100); 176 ret = poll(&pollfd, 1, cfg_poll_timeout);
175 if (ret != 1) 177 if (ret != 1)
176 error(1, errno, "poll"); 178 error(1, errno, "poll");
177} 179}
@@ -371,7 +373,8 @@ static void do_test(int family, unsigned int opt)
371 error(1, errno, "send"); 373 error(1, errno, "send");
372 374
373 /* wait for all errors to be queued, else ACKs arrive OOO */ 375 /* wait for all errors to be queued, else ACKs arrive OOO */
374 usleep(50 * 1000); 376 if (!cfg_no_delay)
377 usleep(50 * 1000);
375 378
376 __poll(fd); 379 __poll(fd);
377 380
@@ -392,6 +395,9 @@ static void __attribute__((noreturn)) usage(const char *filepath)
392 " -4: only IPv4\n" 395 " -4: only IPv4\n"
393 " -6: only IPv6\n" 396 " -6: only IPv6\n"
394 " -h: show this message\n" 397 " -h: show this message\n"
398 " -c N: number of packets for each test\n"
399 " -D: no delay between packets\n"
400 " -F: poll() waits forever for an event\n"
395 " -I: request PKTINFO\n" 401 " -I: request PKTINFO\n"
396 " -l N: send N bytes at a time\n" 402 " -l N: send N bytes at a time\n"
397 " -n: set no-payload option\n" 403 " -n: set no-payload option\n"
@@ -409,7 +415,7 @@ static void parse_opt(int argc, char **argv)
409 int proto_count = 0; 415 int proto_count = 0;
410 char c; 416 char c;
411 417
412 while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) { 418 while ((c = getopt(argc, argv, "46c:DFhIl:np:rRux")) != -1) {
413 switch (c) { 419 switch (c) {
414 case '4': 420 case '4':
415 do_ipv6 = 0; 421 do_ipv6 = 0;
@@ -417,6 +423,15 @@ static void parse_opt(int argc, char **argv)
417 case '6': 423 case '6':
418 do_ipv4 = 0; 424 do_ipv4 = 0;
419 break; 425 break;
426 case 'c':
427 cfg_num_pkts = strtoul(optarg, NULL, 10);
428 break;
429 case 'D':
430 cfg_no_delay = true;
431 break;
432 case 'F':
433 cfg_poll_timeout = -1;
434 break;
420 case 'I': 435 case 'I':
421 cfg_do_pktinfo = true; 436 cfg_do_pktinfo = true;
422 break; 437 break;
diff --git a/tools/testing/selftests/powerpc/benchmarks/.gitignore b/tools/testing/selftests/powerpc/benchmarks/.gitignore
index 04dc1e6ef2ce..9161679b1e1a 100644
--- a/tools/testing/selftests/powerpc/benchmarks/.gitignore
+++ b/tools/testing/selftests/powerpc/benchmarks/.gitignore
@@ -1,5 +1,7 @@
1gettimeofday 1gettimeofday
2context_switch 2context_switch
3fork
4exec_target
3mmap_bench 5mmap_bench
4futex_bench 6futex_bench
5null_syscall 7null_syscall
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile
index a35058e3766c..b4d7432a0ecd 100644
--- a/tools/testing/selftests/powerpc/benchmarks/Makefile
+++ b/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -1,5 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2TEST_GEN_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall 2TEST_GEN_PROGS := gettimeofday context_switch fork mmap_bench futex_bench null_syscall
3TEST_GEN_FILES := exec_target
3 4
4CFLAGS += -O2 5CFLAGS += -O2
5 6
@@ -10,3 +11,7 @@ $(TEST_GEN_PROGS): ../harness.c
10$(OUTPUT)/context_switch: ../utils.c 11$(OUTPUT)/context_switch: ../utils.c
11$(OUTPUT)/context_switch: CFLAGS += -maltivec -mvsx -mabi=altivec 12$(OUTPUT)/context_switch: CFLAGS += -maltivec -mvsx -mabi=altivec
12$(OUTPUT)/context_switch: LDLIBS += -lpthread 13$(OUTPUT)/context_switch: LDLIBS += -lpthread
14
15$(OUTPUT)/fork: LDLIBS += -lpthread
16
17$(OUTPUT)/exec_target: CFLAGS += -static -nostartfiles
diff --git a/tools/testing/selftests/powerpc/benchmarks/exec_target.c b/tools/testing/selftests/powerpc/benchmarks/exec_target.c
new file mode 100644
index 000000000000..3c9c144192be
--- /dev/null
+++ b/tools/testing/selftests/powerpc/benchmarks/exec_target.c
@@ -0,0 +1,13 @@
1// SPDX-License-Identifier: GPL-2.0+
2
3/*
4 * Part of fork context switch microbenchmark.
5 *
6 * Copyright 2018, Anton Blanchard, IBM Corp.
7 */
8
9void _exit(int);
10void _start(void)
11{
12 _exit(0);
13}
diff --git a/tools/testing/selftests/powerpc/benchmarks/fork.c b/tools/testing/selftests/powerpc/benchmarks/fork.c
new file mode 100644
index 000000000000..d312e638cb37
--- /dev/null
+++ b/tools/testing/selftests/powerpc/benchmarks/fork.c
@@ -0,0 +1,325 @@
1// SPDX-License-Identifier: GPL-2.0+
2
3/*
4 * Context switch microbenchmark.
5 *
6 * Copyright 2018, Anton Blanchard, IBM Corp.
7 */
8
9#define _GNU_SOURCE
10#include <assert.h>
11#include <errno.h>
12#include <getopt.h>
13#include <limits.h>
14#include <linux/futex.h>
15#include <pthread.h>
16#include <sched.h>
17#include <signal.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/shm.h>
22#include <sys/syscall.h>
23#include <sys/time.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <unistd.h>
27
28static unsigned int timeout = 30;
29
30static void set_cpu(int cpu)
31{
32 cpu_set_t cpuset;
33
34 if (cpu == -1)
35 return;
36
37 CPU_ZERO(&cpuset);
38 CPU_SET(cpu, &cpuset);
39
40 if (sched_setaffinity(0, sizeof(cpuset), &cpuset)) {
41 perror("sched_setaffinity");
42 exit(1);
43 }
44}
45
46static void start_process_on(void *(*fn)(void *), void *arg, int cpu)
47{
48 int pid;
49
50 pid = fork();
51 if (pid == -1) {
52 perror("fork");
53 exit(1);
54 }
55
56 if (pid)
57 return;
58
59 set_cpu(cpu);
60
61 fn(arg);
62
63 exit(0);
64}
65
66static int cpu;
67static int do_fork = 0;
68static int do_vfork = 0;
69static int do_exec = 0;
70static char *exec_file;
71static int exec_target = 0;
72static unsigned long iterations;
73static unsigned long iterations_prev;
74
75static void run_exec(void)
76{
77 char *const argv[] = { "./exec_target", NULL };
78
79 if (execve("./exec_target", argv, NULL) == -1) {
80 perror("execve");
81 exit(1);
82 }
83}
84
85static void bench_fork(void)
86{
87 while (1) {
88 pid_t pid = fork();
89 if (pid == -1) {
90 perror("fork");
91 exit(1);
92 }
93 if (pid == 0) {
94 if (do_exec)
95 run_exec();
96 _exit(0);
97 }
98 pid = waitpid(pid, NULL, 0);
99 if (pid == -1) {
100 perror("waitpid");
101 exit(1);
102 }
103 iterations++;
104 }
105}
106
107static void bench_vfork(void)
108{
109 while (1) {
110 pid_t pid = vfork();
111 if (pid == -1) {
112 perror("fork");
113 exit(1);
114 }
115 if (pid == 0) {
116 if (do_exec)
117 run_exec();
118 _exit(0);
119 }
120 pid = waitpid(pid, NULL, 0);
121 if (pid == -1) {
122 perror("waitpid");
123 exit(1);
124 }
125 iterations++;
126 }
127}
128
129static void *null_fn(void *arg)
130{
131 pthread_exit(NULL);
132}
133
134static void bench_thread(void)
135{
136 pthread_t tid;
137 cpu_set_t cpuset;
138 pthread_attr_t attr;
139 int rc;
140
141 rc = pthread_attr_init(&attr);
142 if (rc) {
143 errno = rc;
144 perror("pthread_attr_init");
145 exit(1);
146 }
147
148 if (cpu != -1) {
149 CPU_ZERO(&cpuset);
150 CPU_SET(cpu, &cpuset);
151
152 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
153 if (rc) {
154 errno = rc;
155 perror("pthread_attr_setaffinity_np");
156 exit(1);
157 }
158 }
159
160 while (1) {
161 rc = pthread_create(&tid, &attr, null_fn, NULL);
162 if (rc) {
163 errno = rc;
164 perror("pthread_create");
165 exit(1);
166 }
167 rc = pthread_join(tid, NULL);
168 if (rc) {
169 errno = rc;
170 perror("pthread_join");
171 exit(1);
172 }
173 iterations++;
174 }
175}
176
177static void sigalrm_handler(int junk)
178{
179 unsigned long i = iterations;
180
181 printf("%ld\n", i - iterations_prev);
182 iterations_prev = i;
183
184 if (--timeout == 0)
185 kill(0, SIGUSR1);
186
187 alarm(1);
188}
189
190static void sigusr1_handler(int junk)
191{
192 exit(0);
193}
194
195static void *bench_proc(void *arg)
196{
197 signal(SIGALRM, sigalrm_handler);
198 alarm(1);
199
200 if (do_fork)
201 bench_fork();
202 else if (do_vfork)
203 bench_vfork();
204 else
205 bench_thread();
206
207 return NULL;
208}
209
210static struct option options[] = {
211 { "fork", no_argument, &do_fork, 1 },
212 { "vfork", no_argument, &do_vfork, 1 },
213 { "exec", no_argument, &do_exec, 1 },
214 { "timeout", required_argument, 0, 's' },
215 { "exec-target", no_argument, &exec_target, 1 },
216 { NULL },
217};
218
219static void usage(void)
220{
221 fprintf(stderr, "Usage: fork <options> CPU\n\n");
222 fprintf(stderr, "\t\t--fork\tUse fork() (default threads)\n");
223 fprintf(stderr, "\t\t--vfork\tUse vfork() (default threads)\n");
224 fprintf(stderr, "\t\t--exec\tAlso exec() (default no exec)\n");
225 fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n");
226 fprintf(stderr, "\t\t--exec-target\tInternal option for exec workload\n");
227}
228
229int main(int argc, char *argv[])
230{
231 signed char c;
232
233 while (1) {
234 int option_index = 0;
235
236 c = getopt_long(argc, argv, "", options, &option_index);
237
238 if (c == -1)
239 break;
240
241 switch (c) {
242 case 0:
243 if (options[option_index].flag != 0)
244 break;
245
246 usage();
247 exit(1);
248 break;
249
250 case 's':
251 timeout = atoi(optarg);
252 break;
253
254 default:
255 usage();
256 exit(1);
257 }
258 }
259
260 if (do_fork && do_vfork) {
261 usage();
262 exit(1);
263 }
264 if (do_exec && !do_fork && !do_vfork) {
265 usage();
266 exit(1);
267 }
268
269 if (do_exec) {
270 char *dirname = strdup(argv[0]);
271 int i;
272 i = strlen(dirname) - 1;
273 while (i) {
274 if (dirname[i] == '/') {
275 dirname[i] = '\0';
276 if (chdir(dirname) == -1) {
277 perror("chdir");
278 exit(1);
279 }
280 break;
281 }
282 i--;
283 }
284 }
285
286 if (exec_target) {
287 exit(0);
288 }
289
290 if (((argc - optind) != 1)) {
291 cpu = -1;
292 } else {
293 cpu = atoi(argv[optind++]);
294 }
295
296 if (do_exec)
297 exec_file = argv[0];
298
299 set_cpu(cpu);
300
301 printf("Using ");
302 if (do_fork)
303 printf("fork");
304 else if (do_vfork)
305 printf("vfork");
306 else
307 printf("clone");
308
309 if (do_exec)
310 printf(" + exec");
311
312 printf(" on cpu %d\n", cpu);
313
314 /* Create a new process group so we can signal everyone for exit */
315 setpgid(getpid(), getpid());
316
317 signal(SIGUSR1, sigusr1_handler);
318
319 start_process_on(bench_proc, NULL, cpu);
320
321 while (1)
322 sleep(3600);
323
324 return 0;
325}
diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile
index ac4a52e19e59..eedce3366f64 100644
--- a/tools/testing/selftests/powerpc/copyloops/Makefile
+++ b/tools/testing/selftests/powerpc/copyloops/Makefile
@@ -5,8 +5,8 @@ CFLAGS += -I$(CURDIR)
5CFLAGS += -D SELFTEST 5CFLAGS += -D SELFTEST
6CFLAGS += -maltivec 6CFLAGS += -maltivec
7 7
8# Use our CFLAGS for the implicit .S rule 8# Use our CFLAGS for the implicit .S rule & set the asm machine type
9ASFLAGS = $(CFLAGS) 9ASFLAGS = $(CFLAGS) -Wa,-mpower4
10 10
11TEST_GEN_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 11TEST_GEN_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
12EXTRA_SOURCES := validate.c ../harness.c 12EXTRA_SOURCES := validate.c ../harness.c
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 5c72ff978f27..c0e45d2dde25 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -4,7 +4,7 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu
4 4
5TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ 5TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
6 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail tm-unavailable tm-trap \ 6 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail tm-unavailable tm-trap \
7 $(SIGNAL_CONTEXT_CHK_TESTS) 7 $(SIGNAL_CONTEXT_CHK_TESTS) tm-sigreturn
8 8
9include ../../lib.mk 9include ../../lib.mk
10 10
diff --git a/tools/testing/selftests/powerpc/tm/tm-sigreturn.c b/tools/testing/selftests/powerpc/tm/tm-sigreturn.c
new file mode 100644
index 000000000000..85d63449243b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-sigreturn.c
@@ -0,0 +1,92 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright 2015, Laurent Dufour, IBM Corp.
5 *
6 * Test the kernel's signal returning code to check reclaim is done if the
7 * sigreturn() is called while in a transaction (suspended since active is
8 * already dropped trough the system call path).
9 *
10 * The kernel must discard the transaction when entering sigreturn, since
11 * restoring the potential TM SPRS from the signal frame is requiring to not be
12 * in a transaction.
13 */
14
15#include <signal.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <sys/types.h>
20#include <sys/wait.h>
21#include <unistd.h>
22
23#include "tm.h"
24#include "utils.h"
25
26
27void handler(int sig)
28{
29 uint64_t ret;
30
31 asm __volatile__(
32 "li 3,1 ;"
33 "tbegin. ;"
34 "beq 1f ;"
35 "li 3,0 ;"
36 "tsuspend. ;"
37 "1: ;"
38 "std%X[ret] 3, %[ret] ;"
39 : [ret] "=m"(ret)
40 :
41 : "memory", "3", "cr0");
42
43 if (ret)
44 exit(1);
45
46 /*
47 * We return from the signal handle while in a suspended transaction
48 */
49}
50
51
52int tm_sigreturn(void)
53{
54 struct sigaction sa;
55 uint64_t ret = 0;
56
57 SKIP_IF(!have_htm());
58
59 memset(&sa, 0, sizeof(sa));
60 sa.sa_handler = handler;
61 sigemptyset(&sa.sa_mask);
62
63 if (sigaction(SIGSEGV, &sa, NULL))
64 exit(1);
65
66 asm __volatile__(
67 "tbegin. ;"
68 "beq 1f ;"
69 "li 3,0 ;"
70 "std 3,0(3) ;" /* trigger SEGV */
71 "li 3,1 ;"
72 "std%X[ret] 3,%[ret] ;"
73 "tend. ;"
74 "b 2f ;"
75 "1: ;"
76 "li 3,2 ;"
77 "std%X[ret] 3,%[ret] ;"
78 "2: ;"
79 : [ret] "=m"(ret)
80 :
81 : "memory", "3", "cr0");
82
83 if (ret != 2)
84 exit(1);
85
86 exit(0);
87}
88
89int main(void)
90{
91 return test_harness(tm_sigreturn, "tm_sigreturn");
92}
diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
index e6a0fad2bfd0..156c8e750259 100644
--- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c
+++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
@@ -80,7 +80,7 @@ bool is_failure(uint64_t condition_reg)
80 return ((condition_reg >> 28) & 0xa) == 0xa; 80 return ((condition_reg >> 28) & 0xa) == 0xa;
81} 81}
82 82
83void *ping(void *input) 83void *tm_una_ping(void *input)
84{ 84{
85 85
86 /* 86 /*
@@ -280,7 +280,7 @@ void *ping(void *input)
280} 280}
281 281
282/* Thread to force context switch */ 282/* Thread to force context switch */
283void *pong(void *not_used) 283void *tm_una_pong(void *not_used)
284{ 284{
285 /* Wait thread get its name "pong". */ 285 /* Wait thread get its name "pong". */
286 if (DEBUG) 286 if (DEBUG)
@@ -311,11 +311,11 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr)
311 do { 311 do {
312 int rc; 312 int rc;
313 313
314 /* Bind 'ping' to CPU 0, as specified in 'attr'. */ 314 /* Bind to CPU 0, as specified in 'attr'. */
315 rc = pthread_create(&t0, attr, ping, (void *) &flags); 315 rc = pthread_create(&t0, attr, tm_una_ping, (void *) &flags);
316 if (rc) 316 if (rc)
317 pr_err(rc, "pthread_create()"); 317 pr_err(rc, "pthread_create()");
318 rc = pthread_setname_np(t0, "ping"); 318 rc = pthread_setname_np(t0, "tm_una_ping");
319 if (rc) 319 if (rc)
320 pr_warn(rc, "pthread_setname_np"); 320 pr_warn(rc, "pthread_setname_np");
321 rc = pthread_join(t0, &ret_value); 321 rc = pthread_join(t0, &ret_value);
@@ -333,13 +333,15 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr)
333 } 333 }
334} 334}
335 335
336int main(int argc, char **argv) 336int tm_unavailable_test(void)
337{ 337{
338 int rc, exception; /* FP = 0, VEC = 1, VSX = 2 */ 338 int rc, exception; /* FP = 0, VEC = 1, VSX = 2 */
339 pthread_t t1; 339 pthread_t t1;
340 pthread_attr_t attr; 340 pthread_attr_t attr;
341 cpu_set_t cpuset; 341 cpu_set_t cpuset;
342 342
343 SKIP_IF(!have_htm());
344
343 /* Set only CPU 0 in the mask. Both threads will be bound to CPU 0. */ 345 /* Set only CPU 0 in the mask. Both threads will be bound to CPU 0. */
344 CPU_ZERO(&cpuset); 346 CPU_ZERO(&cpuset);
345 CPU_SET(0, &cpuset); 347 CPU_SET(0, &cpuset);
@@ -354,12 +356,12 @@ int main(int argc, char **argv)
354 if (rc) 356 if (rc)
355 pr_err(rc, "pthread_attr_setaffinity_np()"); 357 pr_err(rc, "pthread_attr_setaffinity_np()");
356 358
357 rc = pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL); 359 rc = pthread_create(&t1, &attr /* Bind to CPU 0 */, tm_una_pong, NULL);
358 if (rc) 360 if (rc)
359 pr_err(rc, "pthread_create()"); 361 pr_err(rc, "pthread_create()");
360 362
361 /* Name it for systemtap convenience */ 363 /* Name it for systemtap convenience */
362 rc = pthread_setname_np(t1, "pong"); 364 rc = pthread_setname_np(t1, "tm_una_pong");
363 if (rc) 365 if (rc)
364 pr_warn(rc, "pthread_create()"); 366 pr_warn(rc, "pthread_create()");
365 367
@@ -394,3 +396,9 @@ int main(int argc, char **argv)
394 exit(0); 396 exit(0);
395 } 397 }
396} 398}
399
400int main(int argc, char **argv)
401{
402 test_harness_set_timeout(220);
403 return test_harness(tm_unavailable_test, "tm_unavailable_test");
404}
diff --git a/tools/testing/selftests/proc/.gitignore b/tools/testing/selftests/proc/.gitignore
new file mode 100644
index 000000000000..6c16f77c722c
--- /dev/null
+++ b/tools/testing/selftests/proc/.gitignore
@@ -0,0 +1,8 @@
1/proc-loadavg-001
2/proc-self-map-files-001
3/proc-self-map-files-002
4/proc-self-syscall
5/proc-self-wchan
6/proc-uptime-001
7/proc-uptime-002
8/read
diff --git a/tools/testing/selftests/proc/Makefile b/tools/testing/selftests/proc/Makefile
new file mode 100644
index 000000000000..dbb87e56264c
--- /dev/null
+++ b/tools/testing/selftests/proc/Makefile
@@ -0,0 +1,13 @@
1CFLAGS += -Wall -O2
2
3TEST_GEN_PROGS :=
4TEST_GEN_PROGS += proc-loadavg-001
5TEST_GEN_PROGS += proc-self-map-files-001
6TEST_GEN_PROGS += proc-self-map-files-002
7TEST_GEN_PROGS += proc-self-syscall
8TEST_GEN_PROGS += proc-self-wchan
9TEST_GEN_PROGS += proc-uptime-001
10TEST_GEN_PROGS += proc-uptime-002
11TEST_GEN_PROGS += read
12
13include ../lib.mk
diff --git a/tools/testing/selftests/proc/config b/tools/testing/selftests/proc/config
new file mode 100644
index 000000000000..68fbd2b35884
--- /dev/null
+++ b/tools/testing/selftests/proc/config
@@ -0,0 +1 @@
CONFIG_PROC_FS=y
diff --git a/tools/testing/selftests/proc/proc-loadavg-001.c b/tools/testing/selftests/proc/proc-loadavg-001.c
new file mode 100644
index 000000000000..fcff7047000d
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-loadavg-001.c
@@ -0,0 +1,83 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/* Test that /proc/loadavg correctly reports last pid in pid namespace. */
17#define _GNU_SOURCE
18#include <errno.h>
19#include <sched.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <sys/wait.h>
25
26int main(void)
27{
28 pid_t pid;
29 int wstatus;
30
31 if (unshare(CLONE_NEWPID) == -1) {
32 if (errno == ENOSYS || errno == EPERM)
33 return 2;
34 return 1;
35 }
36
37 pid = fork();
38 if (pid == -1)
39 return 1;
40 if (pid == 0) {
41 char buf[128], *p;
42 int fd;
43 ssize_t rv;
44
45 fd = open("/proc/loadavg" , O_RDONLY);
46 if (fd == -1)
47 return 1;
48 rv = read(fd, buf, sizeof(buf));
49 if (rv < 3)
50 return 1;
51 p = buf + rv;
52
53 /* pid 1 */
54 if (!(p[-3] == ' ' && p[-2] == '1' && p[-1] == '\n'))
55 return 1;
56
57 pid = fork();
58 if (pid == -1)
59 return 1;
60 if (pid == 0)
61 return 0;
62 if (waitpid(pid, NULL, 0) == -1)
63 return 1;
64
65 lseek(fd, 0, SEEK_SET);
66 rv = read(fd, buf, sizeof(buf));
67 if (rv < 3)
68 return 1;
69 p = buf + rv;
70
71 /* pid 2 */
72 if (!(p[-3] == ' ' && p[-2] == '2' && p[-1] == '\n'))
73 return 1;
74
75 return 0;
76 }
77
78 if (waitpid(pid, &wstatus, 0) == -1)
79 return 1;
80 if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0)
81 return 0;
82 return 1;
83}
diff --git a/tools/testing/selftests/proc/proc-self-map-files-001.c b/tools/testing/selftests/proc/proc-self-map-files-001.c
new file mode 100644
index 000000000000..4209c64283d6
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-self-map-files-001.c
@@ -0,0 +1,82 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/* Test readlink /proc/self/map_files/... */
17#include <errno.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <stdio.h>
22#include <unistd.h>
23#include <sys/mman.h>
24#include <stdlib.h>
25
26static void pass(const char *fmt, unsigned long a, unsigned long b)
27{
28 char name[64];
29 char buf[64];
30
31 snprintf(name, sizeof(name), fmt, a, b);
32 if (readlink(name, buf, sizeof(buf)) == -1)
33 exit(1);
34}
35
36static void fail(const char *fmt, unsigned long a, unsigned long b)
37{
38 char name[64];
39 char buf[64];
40
41 snprintf(name, sizeof(name), fmt, a, b);
42 if (readlink(name, buf, sizeof(buf)) == -1 && errno == ENOENT)
43 return;
44 exit(1);
45}
46
47int main(void)
48{
49 const unsigned int PAGE_SIZE = sysconf(_SC_PAGESIZE);
50 void *p;
51 int fd;
52 unsigned long a, b;
53
54 fd = open("/dev/zero", O_RDONLY);
55 if (fd == -1)
56 return 1;
57
58 p = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE, fd, 0);
59 if (p == MAP_FAILED)
60 return 1;
61
62 a = (unsigned long)p;
63 b = (unsigned long)p + PAGE_SIZE;
64
65 pass("/proc/self/map_files/%lx-%lx", a, b);
66 fail("/proc/self/map_files/ %lx-%lx", a, b);
67 fail("/proc/self/map_files/%lx -%lx", a, b);
68 fail("/proc/self/map_files/%lx- %lx", a, b);
69 fail("/proc/self/map_files/%lx-%lx ", a, b);
70 fail("/proc/self/map_files/0%lx-%lx", a, b);
71 fail("/proc/self/map_files/%lx-0%lx", a, b);
72 if (sizeof(long) == 4) {
73 fail("/proc/self/map_files/100000000%lx-%lx", a, b);
74 fail("/proc/self/map_files/%lx-100000000%lx", a, b);
75 } else if (sizeof(long) == 8) {
76 fail("/proc/self/map_files/10000000000000000%lx-%lx", a, b);
77 fail("/proc/self/map_files/%lx-10000000000000000%lx", a, b);
78 } else
79 return 1;
80
81 return 0;
82}
diff --git a/tools/testing/selftests/proc/proc-self-map-files-002.c b/tools/testing/selftests/proc/proc-self-map-files-002.c
new file mode 100644
index 000000000000..6f1f4a6e1ecb
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-self-map-files-002.c
@@ -0,0 +1,85 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/* Test readlink /proc/self/map_files/... with address 0. */
17#include <errno.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <stdio.h>
22#include <unistd.h>
23#include <sys/mman.h>
24#include <stdlib.h>
25
26static void pass(const char *fmt, unsigned long a, unsigned long b)
27{
28 char name[64];
29 char buf[64];
30
31 snprintf(name, sizeof(name), fmt, a, b);
32 if (readlink(name, buf, sizeof(buf)) == -1)
33 exit(1);
34}
35
36static void fail(const char *fmt, unsigned long a, unsigned long b)
37{
38 char name[64];
39 char buf[64];
40
41 snprintf(name, sizeof(name), fmt, a, b);
42 if (readlink(name, buf, sizeof(buf)) == -1 && errno == ENOENT)
43 return;
44 exit(1);
45}
46
47int main(void)
48{
49 const unsigned int PAGE_SIZE = sysconf(_SC_PAGESIZE);
50 void *p;
51 int fd;
52 unsigned long a, b;
53
54 fd = open("/dev/zero", O_RDONLY);
55 if (fd == -1)
56 return 1;
57
58 p = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0);
59 if (p == MAP_FAILED) {
60 if (errno == EPERM)
61 return 2;
62 return 1;
63 }
64
65 a = (unsigned long)p;
66 b = (unsigned long)p + PAGE_SIZE;
67
68 pass("/proc/self/map_files/%lx-%lx", a, b);
69 fail("/proc/self/map_files/ %lx-%lx", a, b);
70 fail("/proc/self/map_files/%lx -%lx", a, b);
71 fail("/proc/self/map_files/%lx- %lx", a, b);
72 fail("/proc/self/map_files/%lx-%lx ", a, b);
73 fail("/proc/self/map_files/0%lx-%lx", a, b);
74 fail("/proc/self/map_files/%lx-0%lx", a, b);
75 if (sizeof(long) == 4) {
76 fail("/proc/self/map_files/100000000%lx-%lx", a, b);
77 fail("/proc/self/map_files/%lx-100000000%lx", a, b);
78 } else if (sizeof(long) == 8) {
79 fail("/proc/self/map_files/10000000000000000%lx-%lx", a, b);
80 fail("/proc/self/map_files/%lx-10000000000000000%lx", a, b);
81 } else
82 return 1;
83
84 return 0;
85}
diff --git a/tools/testing/selftests/proc/proc-self-syscall.c b/tools/testing/selftests/proc/proc-self-syscall.c
new file mode 100644
index 000000000000..5ab5f4810e43
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-self-syscall.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#define _GNU_SOURCE
17#include <unistd.h>
18#include <sys/syscall.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <unistd.h>
24#include <string.h>
25#include <stdio.h>
26
27static inline ssize_t sys_read(int fd, void *buf, size_t len)
28{
29 return syscall(SYS_read, fd, buf, len);
30}
31
32int main(void)
33{
34 char buf1[64];
35 char buf2[64];
36 int fd;
37 ssize_t rv;
38
39 fd = open("/proc/self/syscall", O_RDONLY);
40 if (fd == -1) {
41 if (errno == ENOENT)
42 return 2;
43 return 1;
44 }
45
46 /* Do direct system call as libc can wrap anything. */
47 snprintf(buf1, sizeof(buf1), "%ld 0x%lx 0x%lx 0x%lx",
48 (long)SYS_read, (long)fd, (long)buf2, (long)sizeof(buf2));
49
50 memset(buf2, 0, sizeof(buf2));
51 rv = sys_read(fd, buf2, sizeof(buf2));
52 if (rv < 0)
53 return 1;
54 if (rv < strlen(buf1))
55 return 1;
56 if (strncmp(buf1, buf2, strlen(buf1)) != 0)
57 return 1;
58
59 return 0;
60}
diff --git a/tools/testing/selftests/proc/proc-self-wchan.c b/tools/testing/selftests/proc/proc-self-wchan.c
new file mode 100644
index 000000000000..a38b2fbaa7ad
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-self-wchan.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19#include <errno.h>
20#include <unistd.h>
21
22int main(void)
23{
24 char buf[64];
25 int fd;
26
27 fd = open("/proc/self/wchan", O_RDONLY);
28 if (fd == -1) {
29 if (errno == ENOENT)
30 return 2;
31 return 1;
32 }
33
34 buf[0] = '\0';
35 if (read(fd, buf, sizeof(buf)) != 1)
36 return 1;
37 if (buf[0] != '0')
38 return 1;
39 return 0;
40}
diff --git a/tools/testing/selftests/proc/proc-uptime-001.c b/tools/testing/selftests/proc/proc-uptime-001.c
new file mode 100644
index 000000000000..781f7a50fc3f
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-uptime-001.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16// Test that values in /proc/uptime increment monotonically.
17#undef NDEBUG
18#include <assert.h>
19#include <stdint.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23
24#include "proc-uptime.h"
25
26int main(void)
27{
28 uint64_t start, u0, u1, i0, i1;
29 int fd;
30
31 fd = open("/proc/uptime", O_RDONLY);
32 assert(fd >= 0);
33
34 proc_uptime(fd, &u0, &i0);
35 start = u0;
36 do {
37 proc_uptime(fd, &u1, &i1);
38 assert(u1 >= u0);
39 assert(i1 >= i0);
40 u0 = u1;
41 i0 = i1;
42 } while (u1 - start < 100);
43
44 return 0;
45}
diff --git a/tools/testing/selftests/proc/proc-uptime-002.c b/tools/testing/selftests/proc/proc-uptime-002.c
new file mode 100644
index 000000000000..30e2b7849089
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-uptime-002.c
@@ -0,0 +1,79 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16// Test that values in /proc/uptime increment monotonically
17// while shifting across CPUs.
18#define _GNU_SOURCE
19#undef NDEBUG
20#include <assert.h>
21#include <unistd.h>
22#include <sys/syscall.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <stdint.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <fcntl.h>
30
31#include "proc-uptime.h"
32
33static inline int sys_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *m)
34{
35 return syscall(SYS_sched_getaffinity, pid, len, m);
36}
37
38static inline int sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *m)
39{
40 return syscall(SYS_sched_setaffinity, pid, len, m);
41}
42
43int main(void)
44{
45 unsigned int len;
46 unsigned long *m;
47 unsigned int cpu;
48 uint64_t u0, u1, i0, i1;
49 int fd;
50
51 /* find out "nr_cpu_ids" */
52 m = NULL;
53 len = 0;
54 do {
55 len += sizeof(unsigned long);
56 free(m);
57 m = malloc(len);
58 } while (sys_sched_getaffinity(0, len, m) == -EINVAL);
59
60 fd = open("/proc/uptime", O_RDONLY);
61 assert(fd >= 0);
62
63 proc_uptime(fd, &u0, &i0);
64 for (cpu = 0; cpu < len * 8; cpu++) {
65 memset(m, 0, len);
66 m[cpu / (8 * sizeof(unsigned long))] |= 1UL << (cpu % (8 * sizeof(unsigned long)));
67
68 /* CPU might not exist, ignore error */
69 sys_sched_setaffinity(0, len, m);
70
71 proc_uptime(fd, &u1, &i1);
72 assert(u1 >= u0);
73 assert(i1 >= i0);
74 u0 = u1;
75 i0 = i1;
76 }
77
78 return 0;
79}
diff --git a/tools/testing/selftests/proc/proc-uptime.h b/tools/testing/selftests/proc/proc-uptime.h
new file mode 100644
index 000000000000..0e464b50e9d9
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-uptime.h
@@ -0,0 +1,74 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#undef NDEBUG
17#include <assert.h>
18#include <errno.h>
19#include <string.h>
20#include <stdlib.h>
21#include <unistd.h>
22
23static unsigned long long xstrtoull(const char *p, char **end)
24{
25 if (*p == '0') {
26 *end = (char *)p + 1;
27 return 0;
28 } else if ('1' <= *p && *p <= '9') {
29 unsigned long long val;
30
31 errno = 0;
32 val = strtoull(p, end, 10);
33 assert(errno == 0);
34 return val;
35 } else
36 assert(0);
37}
38
39static void proc_uptime(int fd, uint64_t *uptime, uint64_t *idle)
40{
41 uint64_t val1, val2;
42 char buf[64], *p;
43 ssize_t rv;
44
45 /* save "p < end" checks */
46 memset(buf, 0, sizeof(buf));
47 rv = pread(fd, buf, sizeof(buf), 0);
48 assert(0 <= rv && rv <= sizeof(buf));
49 buf[sizeof(buf) - 1] = '\0';
50
51 p = buf;
52
53 val1 = xstrtoull(p, &p);
54 assert(p[0] == '.');
55 assert('0' <= p[1] && p[1] <= '9');
56 assert('0' <= p[2] && p[2] <= '9');
57 assert(p[3] == ' ');
58
59 val2 = (p[1] - '0') * 10 + p[2] - '0';
60 *uptime = val1 * 100 + val2;
61
62 p += 4;
63
64 val1 = xstrtoull(p, &p);
65 assert(p[0] == '.');
66 assert('0' <= p[1] && p[1] <= '9');
67 assert('0' <= p[2] && p[2] <= '9');
68 assert(p[3] == '\n');
69
70 val2 = (p[1] - '0') * 10 + p[2] - '0';
71 *idle = val1 * 100 + val2;
72
73 assert(p + 4 == buf + rv);
74}
diff --git a/tools/testing/selftests/proc/read.c b/tools/testing/selftests/proc/read.c
new file mode 100644
index 000000000000..1e73c2232097
--- /dev/null
+++ b/tools/testing/selftests/proc/read.c
@@ -0,0 +1,147 @@
1/*
2 * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16// Test
17// 1) read of every file in /proc
18// 2) readlink of every symlink in /proc
19// 3) recursively (1) + (2) for every directory in /proc
20// 4) write to /proc/*/clear_refs and /proc/*/task/*/clear_refs
21// 5) write to /proc/sysrq-trigger
22#undef NDEBUG
23#include <assert.h>
24#include <errno.h>
25#include <sys/types.h>
26#include <dirent.h>
27#include <stdbool.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <unistd.h>
33
34static inline bool streq(const char *s1, const char *s2)
35{
36 return strcmp(s1, s2) == 0;
37}
38
39static struct dirent *xreaddir(DIR *d)
40{
41 struct dirent *de;
42
43 errno = 0;
44 de = readdir(d);
45 if (!de && errno != 0) {
46 exit(1);
47 }
48 return de;
49}
50
51static void f_reg(DIR *d, const char *filename)
52{
53 char buf[4096];
54 int fd;
55 ssize_t rv;
56
57 /* read from /proc/kmsg can block */
58 fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK);
59 if (fd == -1)
60 return;
61 rv = read(fd, buf, sizeof(buf));
62 assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
63 close(fd);
64}
65
66static void f_reg_write(DIR *d, const char *filename, const char *buf, size_t len)
67{
68 int fd;
69 ssize_t rv;
70
71 fd = openat(dirfd(d), filename, O_WRONLY);
72 if (fd == -1)
73 return;
74 rv = write(fd, buf, len);
75 assert((0 <= rv && rv <= len) || rv == -1);
76 close(fd);
77}
78
79static void f_lnk(DIR *d, const char *filename)
80{
81 char buf[4096];
82 ssize_t rv;
83
84 rv = readlinkat(dirfd(d), filename, buf, sizeof(buf));
85 assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
86}
87
88static void f(DIR *d, unsigned int level)
89{
90 struct dirent *de;
91
92 de = xreaddir(d);
93 assert(de->d_type == DT_DIR);
94 assert(streq(de->d_name, "."));
95
96 de = xreaddir(d);
97 assert(de->d_type == DT_DIR);
98 assert(streq(de->d_name, ".."));
99
100 while ((de = xreaddir(d))) {
101 assert(!streq(de->d_name, "."));
102 assert(!streq(de->d_name, ".."));
103
104 switch (de->d_type) {
105 DIR *dd;
106 int fd;
107
108 case DT_REG:
109 if (level == 0 && streq(de->d_name, "sysrq-trigger")) {
110 f_reg_write(d, de->d_name, "h", 1);
111 } else if (level == 1 && streq(de->d_name, "clear_refs")) {
112 f_reg_write(d, de->d_name, "1", 1);
113 } else if (level == 3 && streq(de->d_name, "clear_refs")) {
114 f_reg_write(d, de->d_name, "1", 1);
115 } else {
116 f_reg(d, de->d_name);
117 }
118 break;
119 case DT_DIR:
120 fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY);
121 if (fd == -1)
122 continue;
123 dd = fdopendir(fd);
124 if (!dd)
125 continue;
126 f(dd, level + 1);
127 closedir(dd);
128 break;
129 case DT_LNK:
130 f_lnk(d, de->d_name);
131 break;
132 default:
133 assert(0);
134 }
135 }
136}
137
138int main(void)
139{
140 DIR *d;
141
142 d = opendir("/proc");
143 if (!d)
144 return 2;
145 f(d, 0);
146 return 0;
147}
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index 07a13779eece..65f6655026f0 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -136,6 +136,9 @@ identify_boot_image () {
136 qemu-system-x86_64|qemu-system-i386) 136 qemu-system-x86_64|qemu-system-i386)
137 echo arch/x86/boot/bzImage 137 echo arch/x86/boot/bzImage
138 ;; 138 ;;
139 qemu-system-aarch64)
140 echo arch/arm64/boot/Image
141 ;;
139 *) 142 *)
140 echo vmlinux 143 echo vmlinux
141 ;; 144 ;;
@@ -158,6 +161,9 @@ identify_qemu () {
158 elif echo $u | grep -q "Intel 80386" 161 elif echo $u | grep -q "Intel 80386"
159 then 162 then
160 echo qemu-system-i386 163 echo qemu-system-i386
164 elif echo $u | grep -q aarch64
165 then
166 echo qemu-system-aarch64
161 elif uname -a | grep -q ppc64 167 elif uname -a | grep -q ppc64
162 then 168 then
163 echo qemu-system-ppc64 169 echo qemu-system-ppc64
@@ -176,16 +182,20 @@ identify_qemu () {
176# Output arguments for the qemu "-append" string based on CPU type 182# Output arguments for the qemu "-append" string based on CPU type
177# and the TORTURE_QEMU_INTERACTIVE environment variable. 183# and the TORTURE_QEMU_INTERACTIVE environment variable.
178identify_qemu_append () { 184identify_qemu_append () {
185 local console=ttyS0
179 case "$1" in 186 case "$1" in
180 qemu-system-x86_64|qemu-system-i386) 187 qemu-system-x86_64|qemu-system-i386)
181 echo noapic selinux=0 initcall_debug debug 188 echo noapic selinux=0 initcall_debug debug
182 ;; 189 ;;
190 qemu-system-aarch64)
191 console=ttyAMA0
192 ;;
183 esac 193 esac
184 if test -n "$TORTURE_QEMU_INTERACTIVE" 194 if test -n "$TORTURE_QEMU_INTERACTIVE"
185 then 195 then
186 echo root=/dev/sda 196 echo root=/dev/sda
187 else 197 else
188 echo console=ttyS0 198 echo console=$console
189 fi 199 fi
190} 200}
191 201
@@ -197,6 +207,9 @@ identify_qemu_args () {
197 case "$1" in 207 case "$1" in
198 qemu-system-x86_64|qemu-system-i386) 208 qemu-system-x86_64|qemu-system-i386)
199 ;; 209 ;;
210 qemu-system-aarch64)
211 echo -machine virt,gic-version=host -cpu host
212 ;;
200 qemu-system-ppc64) 213 qemu-system-ppc64)
201 echo -enable-kvm -M pseries -nodefaults 214 echo -enable-kvm -M pseries -nodefaults
202 echo -device spapr-vscsi 215 echo -device spapr-vscsi
@@ -254,7 +267,7 @@ specify_qemu_cpus () {
254 echo $2 267 echo $2
255 else 268 else
256 case "$1" in 269 case "$1" in
257 qemu-system-x86_64|qemu-system-i386) 270 qemu-system-x86_64|qemu-system-i386|qemu-system-aarch64)
258 echo $2 -smp $3 271 echo $2 -smp $3
259 ;; 272 ;;
260 qemu-system-ppc64) 273 qemu-system-ppc64)
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
index 963f71289d22..8948f7926b21 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
@@ -39,30 +39,31 @@ sed -e 's/us : / : /' |
39tr -d '\015' | 39tr -d '\015' |
40awk ' 40awk '
41$8 == "start" { 41$8 == "start" {
42 if (starttask != "") 42 if (startseq != "")
43 nlost++; 43 nlost++;
44 starttask = $1; 44 starttask = $1;
45 starttime = $3; 45 starttime = $3;
46 startseq = $7; 46 startseq = $7;
47 seqtask[startseq] = starttask;
47} 48}
48 49
49$8 == "end" { 50$8 == "end" {
50 if (starttask == $1 && startseq == $7) { 51 if (startseq == $7) {
51 curgpdur = $3 - starttime; 52 curgpdur = $3 - starttime;
52 gptimes[++n] = curgpdur; 53 gptimes[++n] = curgpdur;
53 gptaskcnt[starttask]++; 54 gptaskcnt[starttask]++;
54 sum += curgpdur; 55 sum += curgpdur;
55 if (curgpdur > 1000) 56 if (curgpdur > 1000)
56 print "Long GP " starttime "us to " $3 "us (" curgpdur "us)"; 57 print "Long GP " starttime "us to " $3 "us (" curgpdur "us)";
57 starttask = ""; 58 startseq = "";
58 } else { 59 } else {
59 # Lost a message or some such, reset. 60 # Lost a message or some such, reset.
60 starttask = ""; 61 startseq = "";
61 nlost++; 62 nlost++;
62 } 63 }
63} 64}
64 65
65$8 == "done" { 66$8 == "done" && seqtask[$7] != $1 {
66 piggybackcnt[$1]++; 67 piggybackcnt[$1]++;
67} 68}
68 69
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 1b78a12740e5..5f8fbb0d7c17 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -177,8 +177,8 @@ then
177 exit 0 177 exit 0
178fi 178fi
179echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log 179echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log
180echo $QEMU $qemu_args -m 512 -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 180echo $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
181( $QEMU $qemu_args -m 512 -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & 181( $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
182commandcompleted=0 182commandcompleted=0
183sleep 10 # Give qemu's pid a chance to reach the file 183sleep 10 # Give qemu's pid a chance to reach the file
184if test -s "$resdir/qemu_pid" 184if test -s "$resdir/qemu_pid"
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 7d1f607f0f76..56610dbbdf73 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -1,10 +1,8 @@
1#!/bin/bash 1#!/bin/bash
2# 2#
3# Run a series of 14 tests under KVM. These are not particularly 3# Run a series of tests under KVM. By default, this series is specified
4# well-selected or well-tuned, but are the current set. 4# by the relevant CFLIST file, but can be overridden by the --configs
5# 5# command-line argument.
6# Edit the definitions below to set the locations of the various directories,
7# as well as the test duration.
8# 6#
9# Usage: kvm.sh [ options ] 7# Usage: kvm.sh [ options ]
10# 8#
@@ -44,6 +42,7 @@ TORTURE_BOOT_IMAGE=""
44TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD 42TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD
45TORTURE_KCONFIG_ARG="" 43TORTURE_KCONFIG_ARG=""
46TORTURE_KMAKE_ARG="" 44TORTURE_KMAKE_ARG=""
45TORTURE_QEMU_MEM=512
47TORTURE_SHUTDOWN_GRACE=180 46TORTURE_SHUTDOWN_GRACE=180
48TORTURE_SUITE=rcu 47TORTURE_SUITE=rcu
49resdir="" 48resdir=""
@@ -70,6 +69,7 @@ usage () {
70 echo " --kconfig Kconfig-options" 69 echo " --kconfig Kconfig-options"
71 echo " --kmake-arg kernel-make-arguments" 70 echo " --kmake-arg kernel-make-arguments"
72 echo " --mac nn:nn:nn:nn:nn:nn" 71 echo " --mac nn:nn:nn:nn:nn:nn"
72 echo " --memory megabytes | nnnG"
73 echo " --no-initrd" 73 echo " --no-initrd"
74 echo " --qemu-args qemu-arguments" 74 echo " --qemu-args qemu-arguments"
75 echo " --qemu-cmd qemu-system-..." 75 echo " --qemu-cmd qemu-system-..."
@@ -147,6 +147,11 @@ do
147 TORTURE_QEMU_MAC=$2 147 TORTURE_QEMU_MAC=$2
148 shift 148 shift
149 ;; 149 ;;
150 --memory)
151 checkarg --memory "(memory size)" $# "$2" '^[0-9]\+[MG]\?$' error
152 TORTURE_QEMU_MEM=$2
153 shift
154 ;;
150 --no-initrd) 155 --no-initrd)
151 TORTURE_INITRD=""; export TORTURE_INITRD 156 TORTURE_INITRD=""; export TORTURE_INITRD
152 ;; 157 ;;
@@ -174,6 +179,12 @@ do
174 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--' 179 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--'
175 TORTURE_SUITE=$2 180 TORTURE_SUITE=$2
176 shift 181 shift
182 if test "$TORTURE_SUITE" = rcuperf
183 then
184 # If you really want jitter for rcuperf, specify
185 # it after specifying rcuperf. (But why?)
186 jitter=0
187 fi
177 ;; 188 ;;
178 *) 189 *)
179 echo Unknown argument $1 190 echo Unknown argument $1
@@ -288,6 +299,7 @@ TORTURE_KMAKE_ARG="$TORTURE_KMAKE_ARG"; export TORTURE_KMAKE_ARG
288TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD 299TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD
289TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE 300TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE
290TORTURE_QEMU_MAC="$TORTURE_QEMU_MAC"; export TORTURE_QEMU_MAC 301TORTURE_QEMU_MAC="$TORTURE_QEMU_MAC"; export TORTURE_QEMU_MAC
302TORTURE_QEMU_MEM="$TORTURE_QEMU_MEM"; export TORTURE_QEMU_MEM
291TORTURE_SHUTDOWN_GRACE="$TORTURE_SHUTDOWN_GRACE"; export TORTURE_SHUTDOWN_GRACE 303TORTURE_SHUTDOWN_GRACE="$TORTURE_SHUTDOWN_GRACE"; export TORTURE_SHUTDOWN_GRACE
292TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE 304TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE
293if ! test -e $resdir 305if ! test -e $resdir
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
index c70c51d5ded1..28568b72a31b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
@@ -9,5 +9,4 @@ CONFIG_PREEMPT=y
9CONFIG_HZ_PERIODIC=n 9CONFIG_HZ_PERIODIC=n
10CONFIG_NO_HZ_IDLE=n 10CONFIG_NO_HZ_IDLE=n
11CONFIG_NO_HZ_FULL=y 11CONFIG_NO_HZ_FULL=y
12CONFIG_NO_HZ_FULL_ALL=y
13#CHECK#CONFIG_RCU_EXPERT=n 12#CHECK#CONFIG_RCU_EXPERT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
index cd2a188eeb6d..838297c58318 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
@@ -1 +1 @@
rcutorture.torture_type=tasks rcutorture.torture_type=tasks nohz_full=1
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 27d22695d64c..24c9f6012e35 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -7,7 +7,6 @@ CONFIG_PREEMPT=n
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=n 8CONFIG_NO_HZ_IDLE=n
9CONFIG_NO_HZ_FULL=y 9CONFIG_NO_HZ_FULL=y
10CONFIG_NO_HZ_FULL_ALL=y
11CONFIG_RCU_FAST_NO_HZ=y 10CONFIG_RCU_FAST_NO_HZ=y
12CONFIG_RCU_TRACE=y 11CONFIG_RCU_TRACE=y
13CONFIG_HOTPLUG_CPU=n 12CONFIG_HOTPLUG_CPU=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
index e34c33430447..e6071bb96c7d 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
@@ -1 +1 @@
rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4 rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4 nohz_full=1-7
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 0f4759f4232e..d7afb271a586 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -7,7 +7,6 @@ CONFIG_PREEMPT=n
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=n 8CONFIG_NO_HZ_IDLE=n
9CONFIG_NO_HZ_FULL=y 9CONFIG_NO_HZ_FULL=y
10CONFIG_NO_HZ_FULL_ALL=n
11CONFIG_RCU_FAST_NO_HZ=n 10CONFIG_RCU_FAST_NO_HZ=n
12CONFIG_RCU_TRACE=y 11CONFIG_RCU_TRACE=y
13CONFIG_HOTPLUG_CPU=y 12CONFIG_HOTPLUG_CPU=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
index b9603115d7c7..d36b8fd6f0fc 100644
--- a/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
@@ -20,32 +20,10 @@
20# 20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22 22
23# rcuperf_param_nreaders bootparam-string
24#
25# Adds nreaders rcuperf module parameter if not already specified.
26rcuperf_param_nreaders () {
27 if ! echo "$1" | grep -q "rcuperf.nreaders"
28 then
29 echo rcuperf.nreaders=-1
30 fi
31}
32
33# rcuperf_param_nwriters bootparam-string
34#
35# Adds nwriters rcuperf module parameter if not already specified.
36rcuperf_param_nwriters () {
37 if ! echo "$1" | grep -q "rcuperf.nwriters"
38 then
39 echo rcuperf.nwriters=-1
40 fi
41}
42
43# per_version_boot_params bootparam-string config-file seconds 23# per_version_boot_params bootparam-string config-file seconds
44# 24#
45# Adds per-version torture-module parameters to kernels supporting them. 25# Adds per-version torture-module parameters to kernels supporting them.
46per_version_boot_params () { 26per_version_boot_params () {
47 echo $1 `rcuperf_param_nreaders "$1"` \ 27 echo $1 rcuperf.shutdown=1 \
48 `rcuperf_param_nwriters "$1"` \
49 rcuperf.shutdown=1 \
50 rcuperf.verbose=1 28 rcuperf.verbose=1
51} 29}
diff --git a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
index 66efb59a1bd1..449cf579d6f9 100644
--- a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
+++ b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
@@ -1,4 +1,4 @@
1This document describes one way to created the rcu-test-image file 1This document describes one way to create the rcu-test-image file
2that contains the filesystem used by the guest-OS kernel. There are 2that contains the filesystem used by the guest-OS kernel. There are
3probably much better ways of doing this, and this filesystem could no 3probably much better ways of doing this, and this filesystem could no
4doubt be smaller. It is probably also possible to simply download 4doubt be smaller. It is probably also possible to simply download
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 5df609950a66..168c66d74fc5 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -2860,6 +2860,7 @@ TEST(get_metadata)
2860 int pipefd[2]; 2860 int pipefd[2];
2861 char buf; 2861 char buf;
2862 struct seccomp_metadata md; 2862 struct seccomp_metadata md;
2863 long ret;
2863 2864
2864 ASSERT_EQ(0, pipe(pipefd)); 2865 ASSERT_EQ(0, pipe(pipefd));
2865 2866
@@ -2893,16 +2894,26 @@ TEST(get_metadata)
2893 ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid)); 2894 ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid));
2894 ASSERT_EQ(pid, waitpid(pid, NULL, 0)); 2895 ASSERT_EQ(pid, waitpid(pid, NULL, 0));
2895 2896
2897 /* Past here must not use ASSERT or child process is never killed. */
2898
2896 md.filter_off = 0; 2899 md.filter_off = 0;
2897 ASSERT_EQ(sizeof(md), ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md)); 2900 errno = 0;
2901 ret = ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md);
2902 EXPECT_EQ(sizeof(md), ret) {
2903 if (errno == EINVAL)
2904 XFAIL(goto skip, "Kernel does not support PTRACE_SECCOMP_GET_METADATA (missing CONFIG_CHECKPOINT_RESTORE?)");
2905 }
2906
2898 EXPECT_EQ(md.flags, SECCOMP_FILTER_FLAG_LOG); 2907 EXPECT_EQ(md.flags, SECCOMP_FILTER_FLAG_LOG);
2899 EXPECT_EQ(md.filter_off, 0); 2908 EXPECT_EQ(md.filter_off, 0);
2900 2909
2901 md.filter_off = 1; 2910 md.filter_off = 1;
2902 ASSERT_EQ(sizeof(md), ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md)); 2911 ret = ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md);
2912 EXPECT_EQ(sizeof(md), ret);
2903 EXPECT_EQ(md.flags, 0); 2913 EXPECT_EQ(md.flags, 0);
2904 EXPECT_EQ(md.filter_off, 1); 2914 EXPECT_EQ(md.filter_off, 1);
2905 2915
2916skip:
2906 ASSERT_EQ(0, kill(pid, SIGKILL)); 2917 ASSERT_EQ(0, kill(pid, SIGKILL));
2907} 2918}
2908 2919
diff --git a/tools/testing/selftests/tc-testing/README b/tools/testing/selftests/tc-testing/README
index 970ff294fec8..3a0336782d2d 100644
--- a/tools/testing/selftests/tc-testing/README
+++ b/tools/testing/selftests/tc-testing/README
@@ -14,11 +14,11 @@ REQUIREMENTS
14 14
15* The kernel must have network namespace support 15* The kernel must have network namespace support
16 16
17* The kernel must have veth support available, as a veth pair is created 17* The kernel must have veth support available, as a veth pair is created
18 prior to running the tests. 18 prior to running the tests.
19 19
20* All tc-related features must be built in or available as modules. 20* All tc-related features being tested must be built in or available as
21 To check what is required in current setup run: 21 modules. To check what is required in current setup run:
22 ./tdc.py -c 22 ./tdc.py -c
23 23
24 Note: 24 Note:
@@ -44,10 +44,13 @@ using the -p option when running tdc:
44RUNNING TDC 44RUNNING TDC
45----------- 45-----------
46 46
47To use tdc, root privileges are required. tdc will not run otherwise. 47To use tdc, root privileges are required. This is because the
48commands being tested must be run as root. The code that enforces
49execution by root uid has been moved into a plugin (see PLUGIN
50ARCHITECTURE, below).
48 51
49All tests are executed inside a network namespace to prevent conflicts 52If nsPlugin is linked, all tests are executed inside a network
50within the host. 53namespace to prevent conflicts within the host.
51 54
52Running tdc without any arguments will run all tests. Refer to the section 55Running tdc without any arguments will run all tests. Refer to the section
53on command line arguments for more information, or run: 56on command line arguments for more information, or run:
@@ -59,6 +62,33 @@ output captured from the failing test will be printed immediately following
59the failed test in the TAP output. 62the failed test in the TAP output.
60 63
61 64
65OVERVIEW OF TDC EXECUTION
66-------------------------
67
68One run of tests is considered a "test suite" (this will be refined in the
69future). A test suite has one or more test cases in it.
70
71A test case has four stages:
72
73 - setup
74 - execute
75 - verify
76 - teardown
77
78The setup and teardown stages can run zero or more commands. The setup
79stage does some setup if the test needs it. The teardown stage undoes
80the setup and returns the system to a "neutral" state so any other test
81can be run next. These two stages require any commands run to return
82success, but do not otherwise verify the results.
83
84The execute and verify stages each run one command. The execute stage
85tests the return code against one or more acceptable values. The
86verify stage checks the return code for success, and also compares
87the stdout with a regular expression.
88
89Each of the commands in any stage will run in a shell instance.
90
91
62USER-DEFINED CONSTANTS 92USER-DEFINED CONSTANTS
63---------------------- 93----------------------
64 94
@@ -70,23 +100,132 @@ executed as part of the test. More will be added as test cases require.
70Example: 100Example:
71 $TC qdisc add dev $DEV1 ingress 101 $TC qdisc add dev $DEV1 ingress
72 102
103The NAMES values are used to substitute into the commands in the test cases.
104
73 105
74COMMAND LINE ARGUMENTS 106COMMAND LINE ARGUMENTS
75---------------------- 107----------------------
76 108
77Run tdc.py -h to see the full list of available arguments. 109Run tdc.py -h to see the full list of available arguments.
78 110
79-p PATH Specify the tc executable located at PATH to be used on this 111usage: tdc.py [-h] [-p PATH] [-D DIR [DIR ...]] [-f FILE [FILE ...]]
80 test run 112 [-c [CATG [CATG ...]]] [-e ID [ID ...]] [-l] [-s] [-i] [-v]
81-c Show the available test case categories in this test file 113 [-d DEVICE] [-n NS] [-V]
82-c CATEGORY Run only tests that belong to CATEGORY 114
83-f FILE Read test cases from the JSON file named FILE 115Linux TC unit tests
84-l [CATEGORY] List all test cases in the JSON file. If CATEGORY is 116
85 specified, list test cases matching that category. 117optional arguments:
86-s ID Show the test case matching ID 118 -h, --help show this help message and exit
87-e ID Execute the test case identified by ID 119 -p PATH, --path PATH The full path to the tc executable to use
88-i Generate unique ID numbers for test cases with no existing 120 -v, --verbose Show the commands that are being run
89 ID number 121 -d DEVICE, --device DEVICE
122 Execute the test case in flower category
123
124selection:
125 select which test cases: files plus directories; filtered by categories
126 plus testids
127
128 -D DIR [DIR ...], --directory DIR [DIR ...]
129 Collect tests from the specified directory(ies)
130 (default [tc-tests])
131 -f FILE [FILE ...], --file FILE [FILE ...]
132 Run tests from the specified file(s)
133 -c [CATG [CATG ...]], --category [CATG [CATG ...]]
134 Run tests only from the specified category/ies, or if
135 no category/ies is/are specified, list known
136 categories.
137 -e ID [ID ...], --execute ID [ID ...]
138 Execute the specified test cases with specified IDs
139
140action:
141 select action to perform on selected test cases
142
143 -l, --list List all test cases, or those only within the
144 specified category
145 -s, --show Display the selected test cases
146 -i, --id Generate ID numbers for new test cases
147
148netns:
149 options for nsPlugin(run commands in net namespace)
150
151 -n NS, --namespace NS
152 Run commands in namespace NS
153
154valgrind:
155 options for valgrindPlugin (run command under test under Valgrind)
156
157 -V, --valgrind Run commands under valgrind
158
159
160PLUGIN ARCHITECTURE
161-------------------
162
163There is now a plugin architecture, and some of the functionality that
164was in the tdc.py script has been moved into the plugins.
165
166The plugins are in the directory plugin-lib. The are executed from
167directory plugins. Put symbolic links from plugins to plugin-lib,
168and name them according to the order you want them to run.
169
170Example:
171
172bjb@bee:~/work/tc-testing$ ls -l plugins
173total 4
174lrwxrwxrwx 1 bjb bjb 27 Oct 4 16:12 10-rootPlugin.py -> ../plugin-lib/rootPlugin.py
175lrwxrwxrwx 1 bjb bjb 25 Oct 12 17:55 20-nsPlugin.py -> ../plugin-lib/nsPlugin.py
176-rwxr-xr-x 1 bjb bjb 0 Sep 29 15:56 __init__.py
177
178The plugins are a subclass of TdcPlugin, defined in TdcPlugin.py and
179must be called "SubPlugin" so tdc can find them. They are
180distinguished from each other in the python program by their module
181name.
182
183This base class supplies "hooks" to run extra functions. These hooks are as follows:
184
185pre- and post-suite
186pre- and post-case
187pre- and post-execute stage
188adjust-command (runs in all stages and receives the stage name)
189
190The pre-suite hook receives the number of tests and an array of test ids.
191This allows you to dump out the list of skipped tests in the event of a
192failure during setup or teardown stage.
193
194The pre-case hook receives the ordinal number and test id of the current test.
195
196The adjust-command hook receives the stage id (see list below) and the
197full command to be executed. This allows for last-minute adjustment
198of the command.
199
200The stages are identified by the following strings:
201
202 - pre (pre-suite)
203 - setup
204 - command
205 - verify
206 - teardown
207 - post (post-suite)
208
209
210To write a plugin, you need to inherit from TdcPlugin in
211TdcPlugin.py. To use the plugin, you have to put the
212implementation file in plugin-lib, and add a symbolic link to it from
213plugins. It will be detected at run time and invoked at the
214appropriate times. There are a few examples in the plugin-lib
215directory:
216
217 - rootPlugin.py:
218 implements the enforcement of running as root
219 - nsPlugin.py:
220 sets up a network namespace and runs all commands in that namespace
221 - valgrindPlugin.py
222 runs each command in the execute stage under valgrind,
223 and checks for leaks.
224 This plugin will output an extra test for each test in the test file,
225 one is the existing output as to whether the test passed or failed,
226 and the other is a test whether the command leaked memory or not.
227 (This one is a preliminary version, it may not work quite right yet,
228 but the overall template is there and it should only need tweaks.)
90 229
91 230
92ACKNOWLEDGEMENTS 231ACKNOWLEDGEMENTS
diff --git a/tools/testing/selftests/tc-testing/TODO.txt b/tools/testing/selftests/tc-testing/TODO.txt
index 6a266d811a78..c40698557e2f 100644
--- a/tools/testing/selftests/tc-testing/TODO.txt
+++ b/tools/testing/selftests/tc-testing/TODO.txt
@@ -5,6 +5,27 @@ tc Testing Suite To-Do list:
5 5
6- Add support for multiple versions of tc to run successively 6- Add support for multiple versions of tc to run successively
7 7
8- Improve error messages when tdc aborts its run 8- Improve error messages when tdc aborts its run. Partially done - still
9 need to better handle problems in pre- and post-suite.
9 10
10- Allow tdc to write its results to file 11- Use python logger module for debug/verbose output
12
13- Allow tdc to write its results to file.
14 Maybe use python logger module for this too.
15
16- A better implementation of the "hooks". Currently, every plugin
17 will attempt to run a function at every hook point. Could be
18 changed so that plugin __init__ methods will register functions to
19 be run in the various predefined times. Then if a plugin does not
20 require action at a specific point, no penalty will be paid for
21 trying to run a function that will do nothing.
22
23- Proper exception handling - make an exception class and use it
24
25- a TestCase class, for easier testcase handling, searching, comparison
26
27- a TestSuite class
28 and a way to configure a test suite,
29 to automate running multiple "test suites" with different requirements
30
31- super simple test case example using ls, touch, etc
diff --git a/tools/testing/selftests/tc-testing/TdcPlugin.py b/tools/testing/selftests/tc-testing/TdcPlugin.py
new file mode 100644
index 000000000000..3ee9a6dacb52
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/TdcPlugin.py
@@ -0,0 +1,74 @@
1#!/usr/bin/env python3
2
3class TdcPlugin:
4 def __init__(self):
5 super().__init__()
6 print(' -- {}.__init__'.format(self.sub_class))
7
8 def pre_suite(self, testcount, testidlist):
9 '''run commands before test_runner goes into a test loop'''
10 self.testcount = testcount
11 self.testidlist = testidlist
12 if self.args.verbose > 1:
13 print(' -- {}.pre_suite'.format(self.sub_class))
14
15 def post_suite(self, index):
16 '''run commands after test_runner completes the test loop
17 index is the last ordinal number of test that was attempted'''
18 if self.args.verbose > 1:
19 print(' -- {}.post_suite'.format(self.sub_class))
20
21 def pre_case(self, test_ordinal, testid):
22 '''run commands before test_runner does one test'''
23 if self.args.verbose > 1:
24 print(' -- {}.pre_case'.format(self.sub_class))
25 self.args.testid = testid
26 self.args.test_ordinal = test_ordinal
27
28 def post_case(self):
29 '''run commands after test_runner does one test'''
30 if self.args.verbose > 1:
31 print(' -- {}.post_case'.format(self.sub_class))
32
33 def pre_execute(self):
34 '''run command before test-runner does the execute step'''
35 if self.args.verbose > 1:
36 print(' -- {}.pre_execute'.format(self.sub_class))
37
38 def post_execute(self):
39 '''run command after test-runner does the execute step'''
40 if self.args.verbose > 1:
41 print(' -- {}.post_execute'.format(self.sub_class))
42
43 def adjust_command(self, stage, command):
44 '''adjust the command'''
45 if self.args.verbose > 1:
46 print(' -- {}.adjust_command {}'.format(self.sub_class, stage))
47
48 # if stage == 'pre':
49 # pass
50 # elif stage == 'setup':
51 # pass
52 # elif stage == 'execute':
53 # pass
54 # elif stage == 'verify':
55 # pass
56 # elif stage == 'teardown':
57 # pass
58 # elif stage == 'post':
59 # pass
60 # else:
61 # pass
62
63 return command
64
65 def add_args(self, parser):
66 '''Get the plugin args from the command line'''
67 self.argparser = parser
68 return self.argparser
69
70 def check_args(self, args, remaining):
71 '''Check that the args are set correctly'''
72 self.args = args
73 if self.args.verbose > 1:
74 print(' -- {}.check_args'.format(self.sub_class))
diff --git a/tools/testing/selftests/tc-testing/creating-plugins/AddingPlugins.txt b/tools/testing/selftests/tc-testing/creating-plugins/AddingPlugins.txt
new file mode 100644
index 000000000000..c18f88d09360
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/creating-plugins/AddingPlugins.txt
@@ -0,0 +1,104 @@
1tdc - Adding plugins for tdc
2
3Author: Brenda J. Butler - bjb@mojatatu.com
4
5ADDING PLUGINS
6--------------
7
8A new plugin should be written in python as a class that inherits from TdcPlugin.
9There are some examples in plugin-lib.
10
11The plugin can be used to add functionality to the test framework,
12such as:
13
14- adding commands to be run before and/or after the test suite
15- adding commands to be run before and/or after the test cases
16- adding commands to be run before and/or after the execute phase of the test cases
17- ability to alter the command to be run in any phase:
18 pre (the pre-suite stage)
19 prepare
20 execute
21 verify
22 teardown
23 post (the post-suite stage)
24- ability to add to the command line args, and use them at run time
25
26
27The functions in the class should follow the following interfaces:
28
29 def __init__(self)
30 def pre_suite(self, testcount, testidlist) # see "PRE_SUITE" below
31 def post_suite(self, ordinal) # see "SKIPPING" below
32 def pre_case(self, test_ordinal, testid) # see "PRE_CASE" below
33 def post_case(self)
34 def pre_execute(self)
35 def post_execute(self)
36 def adjust_command(self, stage, command) # see "ADJUST" below
37 def add_args(self, parser) # see "ADD_ARGS" below
38 def check_args(self, args, remaining) # see "CHECK_ARGS" below
39
40
41PRE_SUITE
42
43This method takes a testcount (number of tests to be run) and
44testidlist (array of test ids for tests that will be run). This is
45useful for various things, including when an exception occurs and the
46rest of the tests must be skipped. The info is stored in the object,
47and the post_suite method can refer to it when dumping the "skipped"
48TAP output. The tdc.py script will do that for the test suite as
49defined in the test case, but if the plugin is being used to run extra
50tests on each test (eg, check for memory leaks on associated
51co-processes) then that other tap output can be generated in the
52post-suite method using this info passed in to the pre_suite method.
53
54
55SKIPPING
56
57The post_suite method will receive the ordinal number of the last
58test to be attempted. It can use this info when outputting
59the TAP output for the extra test cases.
60
61
62PRE_CASE
63
64The pre_case method will receive the ordinal number of the test
65and the test id. Useful for outputing the extra test results.
66
67
68ADJUST
69
70The adjust_command method receives a string representing
71the execution stage and a string which is the actual command to be
72executed. The plugin can adjust the command, based on the stage of
73execution.
74
75The stages are represented by the following strings:
76
77 'pre'
78 'setup'
79 'command'
80 'verify'
81 'teardown'
82 'post'
83
84The adjust_command method must return the adjusted command so tdc
85can use it.
86
87
88ADD_ARGS
89
90The add_args method receives the argparser object and can add
91arguments to it. Care should be taken that the new arguments do not
92conflict with any from tdc.py or from other plugins that will be used
93concurrently.
94
95The add_args method should return the argparser object.
96
97
98CHECK_ARGS
99
100The check_args method is so that the plugin can do validation on
101the args, if needed. If there is a problem, and Exception should
102be raised, with a string that explains the problem.
103
104eg: raise Exception('plugin xxx, arg -y is wrong, fix it')
diff --git a/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
index 00438331ba47..17b267dedbd9 100644
--- a/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
+++ b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
@@ -12,14 +12,18 @@ template.json for the required JSON format for test cases.
12Include the 'id' field, but do not assign a value. Running tdc with the -i 12Include the 'id' field, but do not assign a value. Running tdc with the -i
13option will generate a unique ID for that test case. 13option will generate a unique ID for that test case.
14 14
15tdc will recursively search the 'tc' subdirectory for .json files. Any 15tdc will recursively search the 'tc-tests' subdirectory (or the
16test case files you create in these directories will automatically be included. 16directories named with the -D option) for .json files. Any test case
17If you wish to store your custom test cases elsewhere, be sure to run tdc 17files you create in these directories will automatically be included.
18with the -f argument and the path to your file. 18If you wish to store your custom test cases elsewhere, be sure to run
19tdc with the -f argument and the path to your file, or the -D argument
20and the path to your directory(ies).
19 21
20Be aware of required escape characters in the JSON data - particularly when 22Be aware of required escape characters in the JSON data - particularly
21defining the match pattern. Refer to the tctests.json file for examples when 23when defining the match pattern. Refer to the supplied json test files
22in doubt. 24for examples when in doubt. The match pattern is written in json, and
25will be used by python. So the match pattern will be a python regular
26expression, but should be written using json syntax.
23 27
24 28
25TEST CASE STRUCTURE 29TEST CASE STRUCTURE
@@ -69,7 +73,8 @@ SETUP/TEARDOWN ERRORS
69If an error is detected during the setup/teardown process, execution of the 73If an error is detected during the setup/teardown process, execution of the
70tests will immediately stop with an error message and the namespace in which 74tests will immediately stop with an error message and the namespace in which
71the tests are run will be destroyed. This is to prevent inaccurate results 75the tests are run will be destroyed. This is to prevent inaccurate results
72in the test cases. 76in the test cases. tdc will output a series of TAP results for the skipped
77tests.
73 78
74Repeated failures of the setup/teardown may indicate a problem with the test 79Repeated failures of the setup/teardown may indicate a problem with the test
75case, or possibly even a bug in one of the commands that are not being tested. 80case, or possibly even a bug in one of the commands that are not being tested.
@@ -79,3 +84,17 @@ so that it doesn't halt the script for an error that doesn't matter. Turn the
79individual command into a list, with the command being first, followed by all 84individual command into a list, with the command being first, followed by all
80acceptable exit codes for the command. 85acceptable exit codes for the command.
81 86
87Example:
88
89A pair of setup commands. The first can have exit code 0, 1 or 255, the
90second must have exit code 0.
91
92 "setup": [
93 [
94 "$TC actions flush action gact",
95 0,
96 1,
97 255
98 ],
99 "$TC actions add action reclassify index 65536"
100 ],
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/README-PLUGINS b/tools/testing/selftests/tc-testing/plugin-lib/README-PLUGINS
new file mode 100644
index 000000000000..aa8a2669702b
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/plugin-lib/README-PLUGINS
@@ -0,0 +1,27 @@
1tdc.py will look for plugins in a directory plugins off the cwd.
2Make a set of numbered symbolic links from there to the actual plugins.
3Eg:
4
5tdc.py
6plugin-lib/
7plugins/
8 __init__.py
9 10-rootPlugin.py -> ../plugin-lib/rootPlugin.py
10 20-valgrindPlugin.py -> ../plugin-lib/valgrindPlugin.py
11 30-nsPlugin.py -> ../plugin-lib/nsPlugin.py
12
13
14tdc.py will find them and use them.
15
16
17rootPlugin
18 Check if the uid is root. If not, bail out.
19
20valgrindPlugin
21 Run the command under test with valgrind, and produce an extra set of TAP results for the memory tests.
22 This plugin will write files to the cwd, called vgnd-xxx.log. These will contain
23 the valgrind output for test xxx. Any file matching the glob 'vgnd-*.log' will be
24 deleted at the end of the run.
25
26nsPlugin
27 Run all the commands in a network namespace.
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py
new file mode 100644
index 000000000000..a194b1af2b30
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py
@@ -0,0 +1,141 @@
1import os
2import signal
3from string import Template
4import subprocess
5import time
6from TdcPlugin import TdcPlugin
7
8from tdc_config import *
9
10class SubPlugin(TdcPlugin):
11 def __init__(self):
12 self.sub_class = 'ns/SubPlugin'
13 super().__init__()
14
15 def pre_suite(self, testcount, testidlist):
16 '''run commands before test_runner goes into a test loop'''
17 super().pre_suite(testcount, testidlist)
18
19 if self.args.namespace:
20 self._ns_create()
21
22 def post_suite(self, index):
23 '''run commands after test_runner goes into a test loop'''
24 super().post_suite(index)
25 if self.args.verbose:
26 print('{}.post_suite'.format(self.sub_class))
27
28 if self.args.namespace:
29 self._ns_destroy()
30
31 def add_args(self, parser):
32 super().add_args(parser)
33 self.argparser_group = self.argparser.add_argument_group(
34 'netns',
35 'options for nsPlugin(run commands in net namespace)')
36 self.argparser_group.add_argument(
37 '-n', '--namespace', action='store_true',
38 help='Run commands in namespace')
39 return self.argparser
40
41 def adjust_command(self, stage, command):
42 super().adjust_command(stage, command)
43 cmdform = 'list'
44 cmdlist = list()
45
46 if not self.args.namespace:
47 return command
48
49 if self.args.verbose:
50 print('{}.adjust_command'.format(self.sub_class))
51
52 if not isinstance(command, list):
53 cmdform = 'str'
54 cmdlist = command.split()
55 else:
56 cmdlist = command
57 if stage == 'setup' or stage == 'execute' or stage == 'verify' or stage == 'teardown':
58 if self.args.verbose:
59 print('adjust_command: stage is {}; inserting netns stuff in command [{}] list [{}]'.format(stage, command, cmdlist))
60 cmdlist.insert(0, self.args.NAMES['NS'])
61 cmdlist.insert(0, 'exec')
62 cmdlist.insert(0, 'netns')
63 cmdlist.insert(0, 'ip')
64 else:
65 pass
66
67 if cmdform == 'str':
68 command = ' '.join(cmdlist)
69 else:
70 command = cmdlist
71
72 if self.args.verbose:
73 print('adjust_command: return command [{}]'.format(command))
74 return command
75
76 def _ns_create(self):
77 '''
78 Create the network namespace in which the tests will be run and set up
79 the required network devices for it.
80 '''
81 if self.args.namespace:
82 cmd = 'ip netns add {}'.format(self.args.NAMES['NS'])
83 self._exec_cmd('pre', cmd)
84 cmd = 'ip link add $DEV0 type veth peer name $DEV1'
85 self._exec_cmd('pre', cmd)
86 cmd = 'ip link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
87 self._exec_cmd('pre', cmd)
88 cmd = 'ip link set $DEV0 up'
89 self._exec_cmd('pre', cmd)
90 cmd = 'ip -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
91 self._exec_cmd('pre', cmd)
92 if self.args.device:
93 cmd = 'ip link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
94 self._exec_cmd('pre', cmd)
95 cmd = 'ip -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
96 self._exec_cmd('pre', cmd)
97
98 def _ns_destroy(self):
99 '''
100 Destroy the network namespace for testing (and any associated network
101 devices as well)
102 '''
103 if self.args.namespace:
104 cmd = 'ip netns delete {}'.format(self.args.NAMES['NS'])
105 self._exec_cmd('post', cmd)
106
107 def _exec_cmd(self, stage, command):
108 '''
109 Perform any required modifications on an executable command, then run
110 it in a subprocess and return the results.
111 '''
112 if '$' in command:
113 command = self._replace_keywords(command)
114
115 self.adjust_command(stage, command)
116 if self.args.verbose:
117 print('_exec_cmd: command "{}"'.format(command))
118 proc = subprocess.Popen(command,
119 shell=True,
120 stdout=subprocess.PIPE,
121 stderr=subprocess.PIPE,
122 env=ENVIR)
123 (rawout, serr) = proc.communicate()
124
125 if proc.returncode != 0 and len(serr) > 0:
126 foutput = serr.decode("utf-8")
127 else:
128 foutput = rawout.decode("utf-8")
129
130 proc.stdout.close()
131 proc.stderr.close()
132 return proc, foutput
133
134 def _replace_keywords(self, cmd):
135 """
136 For a given executable command, substitute any known
137 variables contained within NAMES with the correct values
138 """
139 tcmd = Template(cmd)
140 subcmd = tcmd.safe_substitute(self.args.NAMES)
141 return subcmd
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/rootPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/rootPlugin.py
new file mode 100644
index 000000000000..e36775bd4d12
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/plugin-lib/rootPlugin.py
@@ -0,0 +1,19 @@
1import os
2import sys
3from TdcPlugin import TdcPlugin
4
5from tdc_config import *
6
7
8class SubPlugin(TdcPlugin):
9 def __init__(self):
10 self.sub_class = 'root/SubPlugin'
11 super().__init__()
12
13 def pre_suite(self, testcount, testidlist):
14 # run commands before test_runner goes into a test loop
15 super().pre_suite(testcount, testidlist)
16
17 if os.geteuid():
18 print('This script must be run with root privileges', file=sys.stderr)
19 exit(1)
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/valgrindPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/valgrindPlugin.py
new file mode 100644
index 000000000000..477a7bd7d7fb
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/plugin-lib/valgrindPlugin.py
@@ -0,0 +1,142 @@
1'''
2run the command under test, under valgrind and collect memory leak info
3as a separate test.
4'''
5
6
7import os
8import re
9import signal
10from string import Template
11import subprocess
12import time
13from TdcPlugin import TdcPlugin
14
15from tdc_config import *
16
17def vp_extract_num_from_string(num_as_string_maybe_with_commas):
18 return int(num_as_string_maybe_with_commas.replace(',',''))
19
20class SubPlugin(TdcPlugin):
21 def __init__(self):
22 self.sub_class = 'valgrind/SubPlugin'
23 self.tap = ''
24 super().__init__()
25
26 def pre_suite(self, testcount, testidlist):
27 '''run commands before test_runner goes into a test loop'''
28 super().pre_suite(testcount, testidlist)
29 if self.args.verbose > 1:
30 print('{}.pre_suite'.format(self.sub_class))
31 if self.args.valgrind:
32 self._add_to_tap('1..{}\n'.format(self.testcount))
33
34 def post_suite(self, index):
35 '''run commands after test_runner goes into a test loop'''
36 super().post_suite(index)
37 self._add_to_tap('\n|---\n')
38 if self.args.verbose > 1:
39 print('{}.post_suite'.format(self.sub_class))
40 print('{}'.format(self.tap))
41 if self.args.verbose < 4:
42 subprocess.check_output('rm -f vgnd-*.log', shell=True)
43
44 def add_args(self, parser):
45 super().add_args(parser)
46 self.argparser_group = self.argparser.add_argument_group(
47 'valgrind',
48 'options for valgrindPlugin (run command under test under Valgrind)')
49
50 self.argparser_group.add_argument(
51 '-V', '--valgrind', action='store_true',
52 help='Run commands under valgrind')
53
54 return self.argparser
55
56 def adjust_command(self, stage, command):
57 super().adjust_command(stage, command)
58 cmdform = 'list'
59 cmdlist = list()
60
61 if not self.args.valgrind:
62 return command
63
64 if self.args.verbose > 1:
65 print('{}.adjust_command'.format(self.sub_class))
66
67 if not isinstance(command, list):
68 cmdform = 'str'
69 cmdlist = command.split()
70 else:
71 cmdlist = command
72
73 if stage == 'execute':
74 if self.args.verbose > 1:
75 print('adjust_command: stage is {}; inserting valgrind stuff in command [{}] list [{}]'.
76 format(stage, command, cmdlist))
77 cmdlist.insert(0, '--track-origins=yes')
78 cmdlist.insert(0, '--show-leak-kinds=definite,indirect')
79 cmdlist.insert(0, '--leak-check=full')
80 cmdlist.insert(0, '--log-file=vgnd-{}.log'.format(self.args.testid))
81 cmdlist.insert(0, '-v') # ask for summary of non-leak errors
82 cmdlist.insert(0, ENVIR['VALGRIND_BIN'])
83 else:
84 pass
85
86 if cmdform == 'str':
87 command = ' '.join(cmdlist)
88 else:
89 command = cmdlist
90
91 if self.args.verbose > 1:
92 print('adjust_command: return command [{}]'.format(command))
93 return command
94
95 def post_execute(self):
96 if not self.args.valgrind:
97 return
98
99 self.definitely_lost_re = re.compile(
100 r'definitely lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\sblocks', re.MULTILINE | re.DOTALL)
101 self.indirectly_lost_re = re.compile(
102 r'indirectly lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\s+blocks', re.MULTILINE | re.DOTALL)
103 self.possibly_lost_re = re.compile(
104 r'possibly lost:\s+([,0-9]+)bytes in\s+([,0-9]+)\s+blocks', re.MULTILINE | re.DOTALL)
105 self.non_leak_error_re = re.compile(
106 r'ERROR SUMMARY:\s+([,0-9]+) errors from\s+([,0-9]+)\s+contexts', re.MULTILINE | re.DOTALL)
107
108 def_num = 0
109 ind_num = 0
110 pos_num = 0
111 nle_num = 0
112
113 # what about concurrent test runs? Maybe force them to be in different directories?
114 with open('vgnd-{}.log'.format(self.args.testid)) as vfd:
115 content = vfd.read()
116 def_mo = self.definitely_lost_re.search(content)
117 ind_mo = self.indirectly_lost_re.search(content)
118 pos_mo = self.possibly_lost_re.search(content)
119 nle_mo = self.non_leak_error_re.search(content)
120
121 if def_mo:
122 def_num = int(def_mo.group(2))
123 if ind_mo:
124 ind_num = int(ind_mo.group(2))
125 if pos_mo:
126 pos_num = int(pos_mo.group(2))
127 if nle_mo:
128 nle_num = int(nle_mo.group(1))
129
130 mem_results = ''
131 if (def_num > 0) or (ind_num > 0) or (pos_num > 0) or (nle_num > 0):
132 mem_results += 'not '
133
134 mem_results += 'ok {} - {}-mem # {}\n'.format(
135 self.args.test_ordinal, self.args.testid, 'memory leak check')
136 self._add_to_tap(mem_results)
137 if mem_results.startswith('not '):
138 print('{}'.format(content))
139 self._add_to_tap(content)
140
141 def _add_to_tap(self, more_tap_output):
142 self.tap += more_tap_output
diff --git a/tools/testing/selftests/tc-testing/plugins/__init__.py b/tools/testing/selftests/tc-testing/plugins/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/plugins/__init__.py
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json b/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
new file mode 100644
index 000000000000..6f289a49e5ec
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
@@ -0,0 +1,294 @@
1[
2 {
3 "id": "d959",
4 "name": "Add cBPF action with valid bytecode",
5 "category": [
6 "actions",
7 "bpf"
8 ],
9 "setup": [
10 [
11 "$TC action flush action bpf",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' index 100",
18 "expExitCode": "0",
19 "verifyCmd": "$TC action get action bpf index 100",
20 "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*index 100 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC action flush action bpf"
24 ]
25 },
26 {
27 "id": "f84a",
28 "name": "Add cBPF action with invalid bytecode",
29 "category": [
30 "actions",
31 "bpf"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action bpf",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,31 0 1 2048,6 0 0 262144,6 0 0 0' index 100",
42 "expExitCode": "255",
43 "verifyCmd": "$TC action get action bpf index 100",
44 "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,31 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*index 100 ref",
45 "matchCount": "0",
46 "teardown": [
47 "$TC actions flush action bpf"
48 ]
49 },
50 {
51 "id": "e939",
52 "name": "Add eBPF action with valid object-file",
53 "category": [
54 "actions",
55 "bpf"
56 ],
57 "setup": [
58 "printf '#include <linux/bpf.h>\nchar l[] __attribute__((section(\"license\"),used))=\"GPL\"; __attribute__((section(\"action\"),used)) int m(struct __sk_buff *s) { return 2; }' | clang -O2 -x c -c - -target bpf -o _b.o",
59 [
60 "$TC action flush action bpf",
61 0,
62 1,
63 255
64 ]
65 ],
66 "cmdUnderTest": "$TC action add action bpf object-file _b.o index 667",
67 "expExitCode": "0",
68 "verifyCmd": "$TC action get action bpf index 667",
69 "matchPattern": "action order [0-9]*: bpf _b.o:\\[action\\] id [0-9]* tag 3b185187f1855c4c( jited)? default-action pipe.*index 667 ref",
70 "matchCount": "1",
71 "teardown": [
72 "$TC action flush action bpf",
73 "rm -f _b.o"
74 ]
75 },
76 {
77 "id": "282d",
78 "name": "Add eBPF action with invalid object-file",
79 "category": [
80 "actions",
81 "bpf"
82 ],
83 "setup": [
84 "printf '#include <linux/bpf.h>\nchar l[] __attribute__((section(\"license\"),used))=\"GPL\"; __attribute__((section(\"action\"),used)) int m(struct __sk_buff *s) { s->data = 0x0; return 2; }' | clang -O2 -x c -c - -target bpf -o _c.o",
85 [
86 "$TC action flush action bpf",
87 0,
88 1,
89 255
90 ]
91 ],
92 "cmdUnderTest": "$TC action add action bpf object-file _c.o index 667",
93 "expExitCode": "255",
94 "verifyCmd": "$TC action get action bpf index 667",
95 "matchPattern": "action order [0-9]*: bpf _c.o:\\[action\\] id [0-9].*index 667 ref",
96 "matchCount": "0",
97 "teardown": [
98 [
99 "$TC action flush action bpf",
100 0,
101 1,
102 255
103 ],
104 "rm -f _c.o"
105 ]
106 },
107 {
108 "id": "d819",
109 "name": "Replace cBPF bytecode and action control",
110 "category": [
111 "actions",
112 "bpf"
113 ],
114 "setup": [
115 [
116 "$TC actions flush action bpf",
117 0,
118 1,
119 255
120 ],
121 [
122 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' index 555",
123 0,
124 1,
125 255
126 ]
127 ],
128 "cmdUnderTest": "$TC action replace action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' drop index 555",
129 "expExitCode": "0",
130 "verifyCmd": "$TC action get action bpf index 555",
131 "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' default-action drop.*index 555 ref",
132 "matchCount": "1",
133 "teardown": [
134 "$TC action flush action bpf"
135 ]
136 },
137 {
138 "id": "6ae3",
139 "name": "Delete cBPF action ",
140 "category": [
141 "actions",
142 "bpf"
143 ],
144 "setup": [
145 [
146 "$TC actions flush action bpf",
147 0,
148 1,
149 255
150 ],
151 [
152 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' index 444",
153 0,
154 1,
155 255
156 ]
157 ],
158 "cmdUnderTest": "$TC action delete action bpf index 444",
159 "expExitCode": "0",
160 "verifyCmd": "$TC action get action bpf index 444",
161 "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*index 444 ref",
162 "matchCount": "0",
163 "teardown": [
164 "$TC action flush action bpf"
165 ]
166 },
167 {
168 "id": "3e0d",
169 "name": "List cBPF actions",
170 "category": [
171 "actions",
172 "bpf"
173 ],
174 "setup": [
175 [
176 "$TC action flush action bpf",
177 0,
178 1,
179 255
180 ],
181 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' ok index 101",
182 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' drop index 102",
183 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 33024,6 0 0 262144,6 0 0 0' continue index 103"
184 ],
185 "cmdUnderTest": "$TC action list action bpf",
186 "expExitCode": "0",
187 "verifyCmd": "$TC action list action bpf",
188 "matchPattern": "action order [0-9]*: bpf bytecode",
189 "matchCount": "3",
190 "teardown": [
191 "$TC actions flush action bpf"
192 ]
193 },
194 {
195 "id": "55ce",
196 "name": "Flush BPF actions",
197 "category": [
198 "actions",
199 "bpf"
200 ],
201 "setup": [
202 [
203 "$TC actions flush action bpf",
204 0,
205 1,
206 255
207 ],
208 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' ok index 101",
209 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' drop index 102",
210 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 33024,6 0 0 262144,6 0 0 0' continue index 103"
211 ],
212 "cmdUnderTest": "$TC action flush action bpf",
213 "expExitCode": "0",
214 "verifyCmd": "$TC action list action bpf",
215 "matchPattern": "action order [0-9]*: bpf bytecode",
216 "matchCount": "0",
217 "teardown": [
218 "$TC actions flush action bpf"
219 ]
220 },
221 {
222 "id": "ccc3",
223 "name": "Add cBPF action with duplicate index",
224 "category": [
225 "actions",
226 "bpf"
227 ],
228 "setup": [
229 [
230 "$TC actions flush action bpf",
231 0,
232 1,
233 255
234 ],
235 "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' index 4294967295"
236 ],
237 "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' index 4294967295",
238 "expExitCode": "255",
239 "verifyCmd": "$TC action get action bpf index 4294967295",
240 "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*index 4294967295",
241 "matchCount": "1",
242 "teardown": [
243 "$TC action flush action bpf"
244 ]
245 },
246 {
247 "id": "89c7",
248 "name": "Add cBPF action with invalid index",
249 "category": [
250 "actions",
251 "bpf"
252 ],
253 "setup": [
254 [
255 "$TC actions flush action bpf",
256 0,
257 1,
258 255
259 ]
260 ],
261 "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' index 4294967296 cookie 12345",
262 "expExitCode": "255",
263 "verifyCmd": "$TC action ls action bpf",
264 "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*cookie 12345",
265 "matchCount": "0",
266 "teardown": [
267 "$TC action flush action bpf"
268 ]
269 },
270 {
271 "id": "7ab9",
272 "name": "Add cBPF action with cookie",
273 "category": [
274 "actions",
275 "bpf"
276 ],
277 "setup": [
278 [
279 "$TC actions flush action bpf",
280 0,
281 1,
282 255
283 ]
284 ],
285 "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' cookie d0d0d0d0d0d0d0d0",
286 "expExitCode": "0",
287 "verifyCmd": "$TC action list action bpf",
288 "matchPattern": "action order [0-9]*: bpf.*cookie d0d0d0d0d0d0d0",
289 "matchCount": "1",
290 "teardown": [
291 "$TC action flush action bpf"
292 ]
293 }
294]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json b/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json
new file mode 100644
index 000000000000..70952bd98ff9
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json
@@ -0,0 +1,291 @@
1[
2 {
3 "id": "2002",
4 "name": "Add valid connmark action with defaults",
5 "category": [
6 "actions",
7 "connmark"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action connmark",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action connmark",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action connmark",
20 "matchPattern": "action order [0-9]+: connmark zone 0 pipe",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action connmark"
24 ]
25 },
26 {
27 "id": "56a5",
28 "name": "Add valid connmark action with control pass",
29 "category": [
30 "actions",
31 "connmark"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action connmark",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action connmark pass index 1",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions get action connmark index 1",
44 "matchPattern": "action order [0-9]+: connmark zone 0 pass.*index 1 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action connmark"
48 ]
49 },
50 {
51 "id": "7c66",
52 "name": "Add valid connmark action with control drop",
53 "category": [
54 "actions",
55 "connmark"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action connmark",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action connmark drop index 100",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions get action connmark index 100",
68 "matchPattern": "action order [0-9]+: connmark zone 0 drop.*index 100 ref",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action connmark"
72 ]
73 },
74 {
75 "id": "a913",
76 "name": "Add valid connmark action with control pipe",
77 "category": [
78 "actions",
79 "connmark"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action connmark",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action connmark pipe index 455",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions get action connmark index 455",
92 "matchPattern": "action order [0-9]+: connmark zone 0 pipe.*index 455 ref",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action connmark"
96 ]
97 },
98 {
99 "id": "bdd8",
100 "name": "Add valid connmark action with control reclassify",
101 "category": [
102 "actions",
103 "connmark"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action connmark",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action connmark reclassify index 7",
114 "expExitCode": "0",
115 "verifyCmd": "$TC actions list action connmark",
116 "matchPattern": "action order [0-9]+: connmark zone 0 reclassify.*index 7 ref",
117 "matchCount": "1",
118 "teardown": [
119 "$TC actions flush action connmark"
120 ]
121 },
122 {
123 "id": "b8be",
124 "name": "Add valid connmark action with control continue",
125 "category": [
126 "actions",
127 "connmark"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action connmark",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action connmark continue index 17",
138 "expExitCode": "0",
139 "verifyCmd": "$TC actions list action connmark",
140 "matchPattern": "action order [0-9]+: connmark zone 0 continue.*index 17 ref",
141 "matchCount": "1",
142 "teardown": [
143 "$TC actions flush action connmark"
144 ]
145 },
146 {
147 "id": "d8a6",
148 "name": "Add valid connmark action with control jump",
149 "category": [
150 "actions",
151 "connmark"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action connmark",
156 0,
157 1,
158 255
159 ]
160 ],
161 "cmdUnderTest": "$TC actions add action connmark jump 10 index 17",
162 "expExitCode": "0",
163 "verifyCmd": "$TC actions list action connmark",
164 "matchPattern": "action order [0-9]+: connmark zone 0 jump 10.*index 17 ref",
165 "matchCount": "1",
166 "teardown": [
167 "$TC actions flush action connmark"
168 ]
169 },
170 {
171 "id": "aae8",
172 "name": "Add valid connmark action with zone argument",
173 "category": [
174 "actions",
175 "connmark"
176 ],
177 "setup": [
178 [
179 "$TC actions flush action connmark",
180 0,
181 1,
182 255
183 ]
184 ],
185 "cmdUnderTest": "$TC actions add action connmark zone 100 pipe index 1",
186 "expExitCode": "0",
187 "verifyCmd": "$TC actions get action connmark index 1",
188 "matchPattern": "action order [0-9]+: connmark zone 100 pipe.*index 1 ref",
189 "matchCount": "1",
190 "teardown": [
191 "$TC actions flush action connmark"
192 ]
193 },
194 {
195 "id": "2f0b",
196 "name": "Add valid connmark action with invalid zone argument",
197 "category": [
198 "actions",
199 "connmark"
200 ],
201 "setup": [
202 [
203 "$TC actions flush action connmark",
204 0,
205 1,
206 255
207 ]
208 ],
209 "cmdUnderTest": "$TC actions add action connmark zone 65536 reclassify index 21",
210 "expExitCode": "255",
211 "verifyCmd": "$TC actions get action connmark index 1",
212 "matchPattern": "action order [0-9]+: connmark zone 65536 reclassify.*index 21 ref",
213 "matchCount": "0",
214 "teardown": [
215 "$TC actions flush action connmark"
216 ]
217 },
218 {
219 "id": "9305",
220 "name": "Add connmark action with unsupported argument",
221 "category": [
222 "actions",
223 "connmark"
224 ],
225 "setup": [
226 [
227 "$TC actions flush action connmark",
228 0,
229 1,
230 255
231 ]
232 ],
233 "cmdUnderTest": "$TC actions add action connmark zone 655 unsupp_arg pass index 2",
234 "expExitCode": "255",
235 "verifyCmd": "$TC actions get action connmark index 2",
236 "matchPattern": "action order [0-9]+: connmark zone 655 unsupp_arg pass.*index 2 ref",
237 "matchCount": "0",
238 "teardown": [
239 "$TC actions flush action connmark"
240 ]
241 },
242 {
243 "id": "71ca",
244 "name": "Add valid connmark action and replace it",
245 "category": [
246 "actions",
247 "connmark"
248 ],
249 "setup": [
250 [
251 "$TC actions flush action connmark",
252 0,
253 1,
254 255
255 ],
256 "$TC actions add action connmark zone 777 pass index 555"
257 ],
258 "cmdUnderTest": "$TC actions replace action connmark zone 555 reclassify index 555",
259 "expExitCode": "0",
260 "verifyCmd": "$TC actions get action connmark index 555",
261 "matchPattern": "action order [0-9]+: connmark zone 555 reclassify.*index 555 ref",
262 "matchCount": "1",
263 "teardown": [
264 "$TC actions flush action connmark"
265 ]
266 },
267 {
268 "id": "5f8f",
269 "name": "Add valid connmark action with cookie",
270 "category": [
271 "actions",
272 "connmark"
273 ],
274 "setup": [
275 [
276 "$TC actions flush action connmark",
277 0,
278 1,
279 255
280 ]
281 ],
282 "cmdUnderTest": "$TC actions add action connmark zone 555 pipe index 5 cookie aabbccddeeff112233445566778800a1",
283 "expExitCode": "0",
284 "verifyCmd": "$TC actions get action connmark index 5",
285 "matchPattern": "action order [0-9]+: connmark zone 555 pipe.*index 5 ref.*cookie aabbccddeeff112233445566778800a1",
286 "matchCount": "1",
287 "teardown": [
288 "$TC actions flush action connmark"
289 ]
290 }
291]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json b/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json
new file mode 100644
index 000000000000..93cf8fea8ae7
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/csum.json
@@ -0,0 +1,410 @@
1[
2 {
3 "id": "6d84",
4 "name": "Add csum iph action",
5 "category": [
6 "actions",
7 "csum"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action csum",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action csum iph index 800",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions get action csum index 800",
20 "matchPattern": "action order [0-9]*: csum \\(iph\\) action pass.*index 800 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action csum"
24 ]
25 },
26 {
27 "id": "1862",
28 "name": "Add csum ip4h action",
29 "category": [
30 "actions",
31 "csum"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action csum",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action csum ip4h index 7",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions get action csum index 7",
44 "matchPattern": "action order [0-9]*: csum \\(iph\\) action pass.*index 7 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action csum"
48 ]
49 },
50 {
51 "id": "15c6",
52 "name": "Add csum ipv4h action",
53 "category": [
54 "actions",
55 "csum"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action csum",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action csum ipv4h index 1122",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions get action csum index 1122",
68 "matchPattern": "action order [0-9]*: csum \\(iph\\) action pass.*index 1122 ref",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action csum"
72 ]
73 },
74 {
75 "id": "bf47",
76 "name": "Add csum icmp action",
77 "category": [
78 "actions",
79 "csum"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action csum",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action csum icmp index 1",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions get action csum index 1",
92 "matchPattern": "action order [0-9]*: csum \\(icmp\\) action pass.*index 1 ref",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action csum"
96 ]
97 },
98 {
99 "id": "cc1d",
100 "name": "Add csum igmp action",
101 "category": [
102 "actions",
103 "csum"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action csum",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action csum igmp index 999",
114 "expExitCode": "0",
115 "verifyCmd": "$TC actions get action csum index 999",
116 "matchPattern": "action order [0-9]*: csum \\(igmp\\) action pass.*index 999 ref",
117 "matchCount": "1",
118 "teardown": [
119 "$TC actions flush action csum"
120 ]
121 },
122 {
123 "id": "bccc",
124 "name": "Add csum foobar action",
125 "category": [
126 "actions",
127 "csum"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action csum",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action csum foobar index 1",
138 "expExitCode": "255",
139 "verifyCmd": "$TC actions ls action csum",
140 "matchPattern": "action order [0-9]*: csum \\(foobar\\) action pass.*index 1 ref",
141 "matchCount": "0",
142 "teardown": [
143 "$TC actions flush action csum"
144 ]
145 },
146 {
147 "id": "3bb4",
148 "name": "Add csum tcp action",
149 "category": [
150 "actions",
151 "csum"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action csum",
156 0,
157 1,
158 255
159 ]
160 ],
161 "cmdUnderTest": "$TC actions add action csum tcp index 9999",
162 "expExitCode": "0",
163 "verifyCmd": "$TC actions get action csum index 9999",
164 "matchPattern": "action order [0-9]*: csum \\(tcp\\) action pass.*index 9999 ref",
165 "matchCount": "1",
166 "teardown": [
167 "$TC actions flush action csum"
168 ]
169 },
170 {
171 "id": "759c",
172 "name": "Add csum udp action",
173 "category": [
174 "actions",
175 "csum"
176 ],
177 "setup": [
178 [
179 "$TC actions flush action csum",
180 0,
181 1,
182 255
183 ]
184 ],
185 "cmdUnderTest": "$TC actions add action csum udp index 334455",
186 "expExitCode": "0",
187 "verifyCmd": "$TC actions get action csum index 334455",
188 "matchPattern": "action order [0-9]*: csum \\(udp\\) action pass.*index 334455 ref",
189 "matchCount": "1",
190 "teardown": [
191 "$TC actions flush action csum"
192 ]
193 },
194 {
195 "id": "bdb6",
196 "name": "Add csum udp xor iph action",
197 "category": [
198 "actions",
199 "csum"
200 ],
201 "setup": [
202 [
203 "$TC actions flush action csum",
204 0,
205 1,
206 255
207 ]
208 ],
209 "cmdUnderTest": "$TC actions add action csum udp xor iph index 3",
210 "expExitCode": "255",
211 "verifyCmd": "$TC actions ls action csum",
212 "matchPattern": "action order [0-9]*: csum \\(udp xor iph\\) action pass.*index 3 ref",
213 "matchCount": "0",
214 "teardown": [
215 "$TC actions flush action csum"
216 ]
217 },
218 {
219 "id": "c220",
220 "name": "Add csum udplite action",
221 "category": [
222 "actions",
223 "csum"
224 ],
225 "setup": [
226 [
227 "$TC actions flush action csum",
228 0,
229 1,
230 255
231 ]
232 ],
233 "cmdUnderTest": "$TC actions add action csum udplite continue index 3",
234 "expExitCode": "0",
235 "verifyCmd": "$TC actions get action csum index 3",
236 "matchPattern": "action order [0-9]*: csum \\(udplite\\) action continue.*index 3 ref",
237 "matchCount": "1",
238 "teardown": [
239 "$TC actions flush action csum"
240 ]
241 },
242 {
243 "id": "8993",
244 "name": "Add csum sctp action",
245 "category": [
246 "actions",
247 "csum"
248 ],
249 "setup": [
250 [
251 "$TC actions flush action csum",
252 0,
253 1,
254 255
255 ]
256 ],
257 "cmdUnderTest": "$TC actions add action csum sctp index 777",
258 "expExitCode": "0",
259 "verifyCmd": "$TC actions get action csum index 777",
260 "matchPattern": "action order [0-9]*: csum \\(sctp\\) action pass.*index 777 ref",
261 "matchCount": "1",
262 "teardown": [
263 "$TC actions flush action csum"
264 ]
265 },
266 {
267 "id": "b138",
268 "name": "Add csum ip & icmp action",
269 "category": [
270 "actions",
271 "csum"
272 ],
273 "setup": [
274 [
275 "$TC actions flush action csum",
276 0,
277 1,
278 255
279 ]
280 ],
281 "cmdUnderTest": "$TC actions add action csum ip and icmp pipe index 123",
282 "expExitCode": "0",
283 "verifyCmd": "$TC actions get action csum index 123",
284 "matchPattern": "action order [0-9]*: csum \\(iph, icmp\\) action pipe.*index 123 ref",
285 "matchCount": "1",
286 "teardown": [
287 "$TC actions flush action csum"
288 ]
289 },
290 {
291 "id": "eeda",
292 "name": "Add csum ip & sctp action",
293 "category": [
294 "actions",
295 "csum"
296 ],
297 "setup": [
298 [
299 "$TC actions flush action csum",
300 0,
301 1,
302 255
303 ]
304 ],
305 "cmdUnderTest": "$TC actions add action csum ipv4h sctp continue index 2",
306 "expExitCode": "0",
307 "verifyCmd": "$TC actions get action csum index 2",
308 "matchPattern": "action order [0-9]*: csum \\(iph, sctp\\) action continue.*index 2 ref",
309 "matchCount": "1",
310 "teardown": [
311 "$TC actions flush action csum"
312 ]
313 },
314 {
315 "id": "0017",
316 "name": "Add csum udp or tcp action",
317 "category": [
318 "actions",
319 "csum"
320 ],
321 "setup": [
322 [
323 "$TC actions flush action csum",
324 0,
325 1,
326 255
327 ]
328 ],
329 "cmdUnderTest": "$TC actions add action csum udp or tcp continue index 27",
330 "expExitCode": "0",
331 "verifyCmd": "$TC actions get action csum index 27",
332 "matchPattern": "action order [0-9]*: csum \\(tcp, udp\\) action continue.*index 27 ref",
333 "matchCount": "1",
334 "teardown": [
335 "$TC actions flush action csum"
336 ]
337 },
338 {
339 "id": "ce92",
340 "name": "Add csum udp action with cookie",
341 "category": [
342 "actions",
343 "csum"
344 ],
345 "setup": [
346 [
347 "$TC actions flush action csum",
348 0,
349 1,
350 255
351 ]
352 ],
353 "cmdUnderTest": "$TC actions add action csum udp pipe index 7 cookie 12345678",
354 "expExitCode": "0",
355 "verifyCmd": "$TC actions get action csum index 7",
356 "matchPattern": "action order [0-9]*: csum \\(udp\\) action pipe.*index 7.*cookie 12345678",
357 "matchCount": "1",
358 "teardown": [
359 "$TC actions flush action csum"
360 ]
361 },
362 {
363 "id": "912f",
364 "name": "Add csum icmp action with large cookie",
365 "category": [
366 "actions",
367 "csum"
368 ],
369 "setup": [
370 [
371 "$TC actions flush action csum",
372 0,
373 1,
374 255
375 ]
376 ],
377 "cmdUnderTest": "$TC actions add action csum icmp pipe index 17 cookie aabbccddeeff1122",
378 "expExitCode": "0",
379 "verifyCmd": "$TC actions get action csum index 17",
380 "matchPattern": "action order [0-9]*: csum \\(icmp\\) action pipe.*index 17.*cookie aabbccddeeff1122",
381 "matchCount": "1",
382 "teardown": [
383 "$TC actions flush action csum"
384 ]
385 },
386 {
387 "id": "879b",
388 "name": "Add batch of 32 csum tcp actions",
389 "category": [
390 "actions",
391 "csum"
392 ],
393 "setup": [
394 [
395 "$TC actions flush action csum",
396 0,
397 1,
398 255
399 ]
400 ],
401 "cmdUnderTest": "for i in `seq 1 32`; do cmd=\"action csum tcp continue index $i \"; args=\"$args$cmd\"; done && $TC actions add $args",
402 "expExitCode": "255",
403 "verifyCmd": "$TC actions ls action csum",
404 "matchPattern": "^[ \t]+index [0-9]* ref",
405 "matchCount": "32",
406 "teardown": [
407 "$TC actions flush action csum"
408 ]
409 }
410]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
index e2187b6e0b7a..68c91023cdb9 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
@@ -465,5 +465,76 @@
465 "teardown": [ 465 "teardown": [
466 "$TC actions flush action gact" 466 "$TC actions flush action gact"
467 ] 467 ]
468 },
469 {
470 "id": "1021",
471 "name": "Add batch of 32 gact pass actions",
472 "category": [
473 "actions",
474 "gact"
475 ],
476 "setup": [
477 [
478 "$TC actions flush action gact",
479 0,
480 1,
481 255
482 ]
483 ],
484 "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action pass index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
485 "expExitCode": "0",
486 "verifyCmd": "$TC actions list action gact",
487 "matchPattern": "^[ \t]+index [0-9]+ ref",
488 "matchCount": "32",
489 "teardown": [
490 "$TC actions flush action gact"
491 ]
492 },
493 {
494 "id": "da7a",
495 "name": "Add batch of 32 gact continue actions with cookie",
496 "category": [
497 "actions",
498 "gact"
499 ],
500 "setup": [
501 [
502 "$TC actions flush action gact",
503 0,
504 1,
505 255
506 ]
507 ],
508 "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action continue index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
509 "expExitCode": "0",
510 "verifyCmd": "$TC actions list action gact",
511 "matchPattern": "^[ \t]+index [0-9]+ ref",
512 "matchCount": "32",
513 "teardown": [
514 "$TC actions flush action gact"
515 ]
516 },
517 {
518 "id": "8aa3",
519 "name": "Delete batch of 32 gact continue actions",
520 "category": [
521 "actions",
522 "gact"
523 ],
524 "setup": [
525 [
526 "$TC actions flush action gact",
527 0,
528 1,
529 255
530 ],
531 "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action continue index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
532 ],
533 "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action gact index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
534 "expExitCode": "0",
535 "verifyCmd": "$TC actions list action gact",
536 "matchPattern": "^[ \t]+index [0-9]+ ref",
537 "matchCount": "0",
538 "teardown": []
468 } 539 }
469] 540]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
index 0fcccf18399b..443c9b3c8664 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
@@ -171,6 +171,198 @@
171 ] 171 ]
172 }, 172 },
173 { 173 {
174 "id": "8917",
175 "name": "Add mirred mirror action with control pass",
176 "category": [
177 "actions",
178 "mirred"
179 ],
180 "setup": [
181 [
182 "$TC actions flush action mirred",
183 0,
184 1,
185 255
186 ]
187 ],
188 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo pass index 1",
189 "expExitCode": "0",
190 "verifyCmd": "$TC actions get action mirred index 1",
191 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) pass.*index 1 ref",
192 "matchCount": "1",
193 "teardown": [
194 "$TC actions flush action mirred"
195 ]
196 },
197 {
198 "id": "1054",
199 "name": "Add mirred mirror action with control pipe",
200 "category": [
201 "actions",
202 "mirred"
203 ],
204 "setup": [
205 [
206 "$TC actions flush action mirred",
207 0,
208 1,
209 255
210 ]
211 ],
212 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo pipe index 15",
213 "expExitCode": "0",
214 "verifyCmd": "$TC actions get action mirred index 15",
215 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) pipe.*index 15 ref",
216 "matchCount": "1",
217 "teardown": [
218 "$TC actions flush action mirred"
219 ]
220 },
221 {
222 "id": "9887",
223 "name": "Add mirred mirror action with control continue",
224 "category": [
225 "actions",
226 "mirred"
227 ],
228 "setup": [
229 [
230 "$TC actions flush action mirred",
231 0,
232 1,
233 255
234 ]
235 ],
236 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo continue index 15",
237 "expExitCode": "0",
238 "verifyCmd": "$TC actions get action mirred index 15",
239 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) continue.*index 15 ref",
240 "matchCount": "1",
241 "teardown": [
242 "$TC actions flush action mirred"
243 ]
244 },
245 {
246 "id": "e4aa",
247 "name": "Add mirred mirror action with control reclassify",
248 "category": [
249 "actions",
250 "mirred"
251 ],
252 "setup": [
253 [
254 "$TC actions flush action mirred",
255 0,
256 1,
257 255
258 ]
259 ],
260 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo reclassify index 150",
261 "expExitCode": "0",
262 "verifyCmd": "$TC actions get action mirred index 150",
263 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) reclassify.*index 150 ref",
264 "matchCount": "1",
265 "teardown": [
266 "$TC actions flush action mirred"
267 ]
268 },
269 {
270 "id": "ece9",
271 "name": "Add mirred mirror action with control drop",
272 "category": [
273 "actions",
274 "mirred"
275 ],
276 "setup": [
277 [
278 "$TC actions flush action mirred",
279 0,
280 1,
281 255
282 ]
283 ],
284 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo drop index 99",
285 "expExitCode": "0",
286 "verifyCmd": "$TC actions get action mirred index 99",
287 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) drop.*index 99 ref",
288 "matchCount": "1",
289 "teardown": [
290 "$TC actions flush action mirred"
291 ]
292 },
293 {
294 "id": "0031",
295 "name": "Add mirred mirror action with control jump",
296 "category": [
297 "actions",
298 "mirred"
299 ],
300 "setup": [
301 [
302 "$TC actions flush action mirred",
303 0,
304 1,
305 255
306 ]
307 ],
308 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo jump 10 index 99",
309 "expExitCode": "0",
310 "verifyCmd": "$TC actions get action mirred index 99",
311 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) jump 10.*index 99 ref",
312 "matchCount": "1",
313 "teardown": [
314 "$TC actions flush action mirred"
315 ]
316 },
317 {
318 "id": "407c",
319 "name": "Add mirred mirror action with cookie",
320 "category": [
321 "actions",
322 "mirred"
323 ],
324 "setup": [
325 [
326 "$TC actions flush action mirred",
327 0,
328 1,
329 255
330 ]
331 ],
332 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo reclassify cookie aa11bb22cc33dd44ee55",
333 "expExitCode": "0",
334 "verifyCmd": "$TC actions ls action mirred",
335 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) reclassify.*cookie aa11bb22cc33dd44ee55",
336 "matchCount": "1",
337 "teardown": [
338 "$TC actions flush action mirred"
339 ]
340 },
341 {
342 "id": "8b69",
343 "name": "Add mirred mirror action with maximum index",
344 "category": [
345 "actions",
346 "mirred"
347 ],
348 "setup": [
349 [
350 "$TC actions flush action mirred",
351 0,
352 1,
353 255
354 ]
355 ],
356 "cmdUnderTest": "$TC actions add action mirred ingress mirror dev lo pipe index 4294967295",
357 "expExitCode": "0",
358 "verifyCmd": "$TC actions get action mirred index 4294967295",
359 "matchPattern": "action order [0-9]*: mirred \\(Ingress Mirror to device lo\\) pipe.*index 4294967295",
360 "matchCount": "1",
361 "teardown": [
362 "$TC actions flush action mirred"
363 ]
364 },
365 {
174 "id": "a70e", 366 "id": "a70e",
175 "name": "Delete mirred mirror action", 367 "name": "Delete mirred mirror action",
176 "category": [ 368 "category": [
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
index 0e602a3f9393..38d85a1d7492 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
@@ -265,6 +265,150 @@
265 ] 265 ]
266 }, 266 },
267 { 267 {
268 "id": "ddd6",
269 "name": "Add police action with invalid rate value",
270 "category": [
271 "actions",
272 "police"
273 ],
274 "setup": [
275 [
276 "$TC actions flush action police",
277 0,
278 1,
279 255
280 ]
281 ],
282 "cmdUnderTest": "$TC actions add action police rate 3tb burst 250k conform-exceed pass/pipe index 5",
283 "expExitCode": "255",
284 "verifyCmd": "$TC actions ls action police",
285 "matchPattern": "action order [0-9]*: police 0x5 rate 3Tb burst 250Kb mtu 2Kb action pass/pipe",
286 "matchCount": "0",
287 "teardown": [
288 "$TC actions flush action police"
289 ]
290 },
291 {
292 "id": "f61c",
293 "name": "Add police action with invalid burst value",
294 "category": [
295 "actions",
296 "police"
297 ],
298 "setup": [
299 [
300 "$TC actions flush action police",
301 0,
302 1,
303 255
304 ]
305 ],
306 "cmdUnderTest": "$TC actions add action police rate 3kbit burst 250P conform-exceed pass/pipe index 5",
307 "expExitCode": "255",
308 "verifyCmd": "$TC actions ls action police",
309 "matchPattern": "action order [0-9]*: police 0x5 rate 3Kbit burst 250Pb mtu 2Kb action pass/pipe",
310 "matchCount": "0",
311 "teardown": [
312 "$TC actions flush action police"
313 ]
314 },
315 {
316 "id": "c26f",
317 "name": "Add police action with invalid peakrate value",
318 "category": [
319 "actions",
320 "police"
321 ],
322 "setup": [
323 [
324 "$TC actions flush action police",
325 0,
326 1,
327 255
328 ]
329 ],
330 "cmdUnderTest": "$TC actions add action police rate 90kbit burst 10k mtu 2kb peakrate 100T index 1",
331 "expExitCode": "255",
332 "verifyCmd": "$TC actions ls action police",
333 "matchPattern": "action order [0-9]*: police 0x1 rate 90Kbit burst 10Kb mtu 2Kb peakrate 100Tbit",
334 "matchCount": "0",
335 "teardown": [
336 "$TC actions flush action police"
337 ]
338 },
339 {
340 "id": "db04",
341 "name": "Add police action with invalid mtu value",
342 "category": [
343 "actions",
344 "police"
345 ],
346 "setup": [
347 [
348 "$TC actions flush action police",
349 0,
350 1,
351 255
352 ]
353 ],
354 "cmdUnderTest": "$TC actions add action police rate 10kbit burst 10k mtu 2Pbit index 1",
355 "expExitCode": "255",
356 "verifyCmd": "$TC actions ls action police",
357 "matchPattern": "action order [0-9]*: police 0x1 rate 10Kbit burst 1Kb mtu 2Pb",
358 "matchCount": "0",
359 "teardown": [
360 "$TC actions flush action police"
361 ]
362 },
363 {
364 "id": "f3c9",
365 "name": "Add police action with cookie",
366 "category": [
367 "actions",
368 "police"
369 ],
370 "setup": [
371 [
372 "$TC actions flush action police",
373 0,
374 1,
375 255
376 ]
377 ],
378 "cmdUnderTest": "$TC actions add action police rate 10mbit burst 10k index 1 cookie a1b1c1d1e1f12233bb",
379 "expExitCode": "0",
380 "verifyCmd": "$TC actions get action police index 1",
381 "matchPattern": "action order [0-9]*: police 0x1 rate 10Mbit burst 10Kb mtu 2Kb.*cookie a1b1c1d1e1f12233bb",
382 "matchCount": "1",
383 "teardown": [
384 "$TC actions flush action police"
385 ]
386 },
387 {
388 "id": "d190",
389 "name": "Add police action with maximum index",
390 "category": [
391 "actions",
392 "police"
393 ],
394 "setup": [
395 [
396 "$TC actions flush action police",
397 0,
398 1,
399 255
400 ]
401 ],
402 "cmdUnderTest": "$TC actions add action police rate 10mbit burst 10k index 4294967295",
403 "expExitCode": "0",
404 "verifyCmd": "$TC actions get action mirred index 4294967295",
405 "matchPattern": "action order [0-9]*: police 0xffffffff rate 10Mbit burst 10Kb mtu 2Kb",
406 "matchCount": "1",
407 "teardown": [
408 "$TC actions flush action mirred"
409 ]
410 },
411 {
268 "id": "336e", 412 "id": "336e",
269 "name": "Delete police action", 413 "name": "Delete police action",
270 "category": [ 414 "category": [
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
index 99635ea4722e..37ecc2716fee 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
@@ -216,6 +216,174 @@
216 ] 216 ]
217 }, 217 },
218 { 218 {
219 "id": "464a",
220 "name": "Add skbedit action with control pipe",
221 "category": [
222 "actions",
223 "skbedit"
224 ],
225 "setup": [
226 [
227 "$TC actions flush action skbedit",
228 0,
229 1,
230 255
231 ]
232 ],
233 "cmdUnderTest": "$TC actions add action skbedit ptype host pipe index 11",
234 "expExitCode": "0",
235 "verifyCmd": "$TC actions get action skbedit index 11",
236 "matchPattern": "action order [0-9]*: skbedit ptype host pipe.*index 11 ref",
237 "matchCount": "1",
238 "teardown": [
239 "$TC actions flush action skbedit"
240 ]
241 },
242 {
243 "id": "212f",
244 "name": "Add skbedit action with control reclassify",
245 "category": [
246 "actions",
247 "skbedit"
248 ],
249 "setup": [
250 [
251 "$TC actions flush action skbedit",
252 0,
253 1,
254 255
255 ]
256 ],
257 "cmdUnderTest": "$TC actions add action skbedit mark 56789 reclassify index 90",
258 "expExitCode": "0",
259 "verifyCmd": "$TC actions get action skbedit index 90",
260 "matchPattern": "action order [0-9]*: skbedit mark 56789 reclassify.*index 90 ref",
261 "matchCount": "1",
262 "teardown": [
263 "$TC actions flush action skbedit"
264 ]
265 },
266 {
267 "id": "0651",
268 "name": "Add skbedit action with control pass",
269 "category": [
270 "actions",
271 "skbedit"
272 ],
273 "setup": [
274 [
275 "$TC actions flush action skbedit",
276 0,
277 1,
278 255
279 ]
280 ],
281 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 3 pass index 271",
282 "expExitCode": "0",
283 "verifyCmd": "$TC actions get action skbedit index 271",
284 "matchPattern": "action order [0-9]*: skbedit queue_mapping 3 pass.*index 271 ref",
285 "matchCount": "1",
286 "teardown": [
287 "$TC actions flush action skbedit"
288 ]
289 },
290 {
291 "id": "cc53",
292 "name": "Add skbedit action with control drop",
293 "category": [
294 "actions",
295 "skbedit"
296 ],
297 "setup": [
298 [
299 "$TC actions flush action skbedit",
300 0,
301 1,
302 255
303 ]
304 ],
305 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 3 drop index 271",
306 "expExitCode": "0",
307 "verifyCmd": "$TC actions get action skbedit index 271",
308 "matchPattern": "action order [0-9]*: skbedit queue_mapping 3 drop.*index 271 ref",
309 "matchCount": "1",
310 "teardown": [
311 "$TC actions flush action skbedit"
312 ]
313 },
314 {
315 "id": "ec16",
316 "name": "Add skbedit action with control jump",
317 "category": [
318 "actions",
319 "skbedit"
320 ],
321 "setup": [
322 [
323 "$TC actions flush action skbedit",
324 0,
325 1,
326 255
327 ]
328 ],
329 "cmdUnderTest": "$TC actions add action skbedit priority 8 jump 9 index 2",
330 "expExitCode": "0",
331 "verifyCmd": "$TC actions get action skbedit index 2",
332 "matchPattern": "action order [0-9]*: skbedit priority :8 jump 9.*index 2 ref",
333 "matchCount": "1",
334 "teardown": [
335 "$TC actions flush action skbedit"
336 ]
337 },
338 {
339 "id": "db54",
340 "name": "Add skbedit action with control continue",
341 "category": [
342 "actions",
343 "skbedit"
344 ],
345 "setup": [
346 [
347 "$TC actions flush action skbedit",
348 0,
349 1,
350 255
351 ]
352 ],
353 "cmdUnderTest": "$TC actions add action skbedit priority 16 continue index 32",
354 "expExitCode": "0",
355 "verifyCmd": "$TC actions get action skbedit index 32",
356 "matchPattern": "action order [0-9]*: skbedit priority :16 continue.*index 32 ref",
357 "matchCount": "1",
358 "teardown": [
359 "$TC actions flush action skbedit"
360 ]
361 },
362 {
363 "id": "1055",
364 "name": "Add skbedit action with cookie",
365 "category": [
366 "actions",
367 "skbedit"
368 ],
369 "setup": [
370 [
371 "$TC actions flush action skbedit",
372 0,
373 1,
374 255
375 ]
376 ],
377 "cmdUnderTest": "$TC actions add action skbedit priority 16 continue index 32 cookie deadbeef",
378 "expExitCode": "0",
379 "verifyCmd": "$TC actions get action skbedit index 32",
380 "matchPattern": "action order [0-9]*: skbedit priority :16 continue.*index 32 ref.*cookie deadbeef",
381 "matchCount": "1",
382 "teardown": [
383 "$TC actions flush action skbedit"
384 ]
385 },
386 {
219 "id": "5172", 387 "id": "5172",
220 "name": "List skbedit actions", 388 "name": "List skbedit actions",
221 "category": [ 389 "category": [
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
index 90bba48c3f07..fe3326e939c1 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
@@ -264,6 +264,30 @@
264 ] 264 ]
265 }, 265 },
266 { 266 {
267 "id": "6046",
268 "name": "Add skbmod action with control reclassify and cookie",
269 "category": [
270 "actions",
271 "skbmod"
272 ],
273 "setup": [
274 [
275 "$TC actions flush action skbmod",
276 0,
277 1,
278 255
279 ]
280 ],
281 "cmdUnderTest": "$TC actions add action skbmod set smac 00:01:02:03:04:01 reclassify index 1 cookie ddeeffaabb11cc22",
282 "expExitCode": "0",
283 "verifyCmd": "$TC actions get action skbmod index 1",
284 "matchPattern": "action order [0-9]*: skbmod reclassify set smac 00:01:02:03:04:01.*index 1 ref.*cookie ddeeffaabb11cc22",
285 "matchCount": "1",
286 "teardown": [
287 "$TC actions flush action skbmod"
288 ]
289 },
290 {
267 "id": "58cb", 291 "id": "58cb",
268 "name": "List skbmod actions", 292 "name": "List skbmod actions",
269 "category": [ 293 "category": [
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json b/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
new file mode 100644
index 000000000000..4510ddfa6e54
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
@@ -0,0 +1,410 @@
1[
2 {
3 "id": "6f5a",
4 "name": "Add vlan pop action",
5 "category": [
6 "actions",
7 "vlan"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action vlan",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action vlan pop index 8",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action vlan",
20 "matchPattern": "action order [0-9]+: vlan.*pop.*index 8 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action vlan"
24 ]
25 },
26 {
27 "id": "ee6f",
28 "name": "Add vlan pop action with large index",
29 "category": [
30 "actions",
31 "vlan"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action vlan",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action vlan pop index 4294967295",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions list action vlan",
44 "matchPattern": "action order [0-9]+: vlan.*pop.*index 4294967295 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action vlan"
48 ]
49 },
50 {
51 "id": "b6b9",
52 "name": "Add vlan pop action with jump opcode",
53 "category": [
54 "actions",
55 "vlan"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action vlan",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action vlan pop jump 10 index 8",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions list action vlan",
68 "matchPattern": "action order [0-9]+: vlan.*jump 10.*index 8 ref",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action vlan"
72 ]
73 },
74 {
75 "id": "87c3",
76 "name": "Add vlan pop action with trap opcode",
77 "category": [
78 "actions",
79 "vlan"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action vlan",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action vlan pop trap index 8",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions list action vlan",
92 "matchPattern": "action order [0-9]+: vlan.*pop trap.*index 8 ref",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action vlan"
96 ]
97 },
98 {
99 "id": "2b91",
100 "name": "Add vlan invalid action",
101 "category": [
102 "actions",
103 "vlan"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action vlan",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action vlan bad_mode",
114 "expExitCode": "255",
115 "verifyCmd": "$TC actions list action vlan",
116 "matchPattern": "action order [0-9]+: vlan.*bad_mode",
117 "matchCount": "0",
118 "teardown": [
119 "$TC actions flush action vlan"
120 ]
121 },
122 {
123 "id": "57fc",
124 "name": "Add vlan action with invalid protocol type",
125 "category": [
126 "actions",
127 "vlan"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action vlan",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action vlan push protocol ABCD",
138 "expExitCode": "255",
139 "verifyCmd": "$TC actions list action vlan",
140 "matchPattern": "action order [0-9]+: vlan.*push",
141 "matchCount": "0",
142 "teardown": [
143 "$TC actions flush action vlan"
144 ]
145 },
146 {
147 "id": "3989",
148 "name": "Add vlan push action with default protocol and priority",
149 "category": [
150 "actions",
151 "vlan"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action vlan",
156 0,
157 1,
158 255
159 ]
160 ],
161 "cmdUnderTest": "$TC actions add action vlan push id 123 index 18",
162 "expExitCode": "0",
163 "verifyCmd": "$TC actions get action vlan index 18",
164 "matchPattern": "action order [0-9]+: vlan.*push id 123 protocol 802.1Q priority 0 pipe.*index 18 ref",
165 "matchCount": "1",
166 "teardown": [
167 "$TC actions flush action vlan"
168 ]
169 },
170 {
171 "id": "79dc",
172 "name": "Add vlan push action with protocol 802.1Q and priority 3",
173 "category": [
174 "actions",
175 "vlan"
176 ],
177 "setup": [
178 [
179 "$TC actions flush action vlan",
180 0,
181 1,
182 255
183 ]
184 ],
185 "cmdUnderTest": "$TC actions add action vlan push id 77 protocol 802.1Q priority 3 continue index 734",
186 "expExitCode": "0",
187 "verifyCmd": "$TC actions get action vlan index 734",
188 "matchPattern": "action order [0-9]+: vlan.*push id 77 protocol 802.1Q priority 3 continue.*index 734 ref",
189 "matchCount": "1",
190 "teardown": [
191 "$TC actions flush action vlan"
192 ]
193 },
194 {
195 "id": "4d73",
196 "name": "Add vlan push action with protocol 802.1AD",
197 "category": [
198 "actions",
199 "vlan"
200 ],
201 "setup": [
202 [
203 "$TC actions flush action vlan",
204 0,
205 1,
206 255
207 ]
208 ],
209 "cmdUnderTest": "$TC actions add action vlan push id 1024 protocol 802.1AD pass index 10000",
210 "expExitCode": "0",
211 "verifyCmd": "$TC actions get action vlan index 10000",
212 "matchPattern": "action order [0-9]+: vlan.*push id 1024 protocol 802.1ad priority 0 pass.*index 10000 ref",
213 "matchCount": "1",
214 "teardown": [
215 "$TC actions flush action vlan"
216 ]
217 },
218 {
219 "id": "1f7b",
220 "name": "Add vlan push action with invalid vlan ID",
221 "category": [
222 "actions",
223 "vlan"
224 ],
225 "setup": [
226 [
227 "$TC actions flush action vlan",
228 0,
229 1,
230 255
231 ]
232 ],
233 "cmdUnderTest": "$TC actions add action vlan push id 5678 index 1",
234 "expExitCode": "255",
235 "verifyCmd": "$TC actions list action vlan",
236 "matchPattern": "action order [0-9]+: vlan.*push id 5678.*index 1 ref",
237 "matchCount": "0",
238 "teardown": [
239 "$TC actions flush action vlan"
240 ]
241 },
242 {
243 "id": "5d02",
244 "name": "Add vlan push action with invalid IEEE 802.1p priority",
245 "category": [
246 "actions",
247 "vlan"
248 ],
249 "setup": [
250 [
251 "$TC actions flush action vlan",
252 0,
253 1,
254 255
255 ]
256 ],
257 "cmdUnderTest": "$TC actions add action vlan push id 5 priority 10 index 1",
258 "expExitCode": "255",
259 "verifyCmd": "$TC actions list action vlan",
260 "matchPattern": "action order [0-9]+: vlan.*push id 5.*index 1 ref",
261 "matchCount": "0",
262 "teardown": [
263 "$TC actions flush action vlan"
264 ]
265 },
266 {
267 "id": "6812",
268 "name": "Add vlan modify action for protocol 802.1Q",
269 "category": [
270 "actions",
271 "vlan"
272 ],
273 "setup": [
274 [
275 "$TC actions flush action vlan",
276 0,
277 1,
278 255
279 ]
280 ],
281 "cmdUnderTest": "$TC actions add action vlan modify protocol 802.1Q id 5 index 100",
282 "expExitCode": "0",
283 "verifyCmd": "$TC actions get action vlan index 100",
284 "matchPattern": "action order [0-9]+: vlan.*modify id 100 protocol 802.1Q priority 0 pipe.*index 100 ref",
285 "matchCount": "0",
286 "teardown": [
287 "$TC actions flush action vlan"
288 ]
289 },
290 {
291 "id": "5a31",
292 "name": "Add vlan modify action for protocol 802.1AD",
293 "category": [
294 "actions",
295 "vlan"
296 ],
297 "setup": [
298 [
299 "$TC actions flush action vlan",
300 0,
301 1,
302 255
303 ]
304 ],
305 "cmdUnderTest": "$TC actions add action vlan modify protocol 802.1ad id 500 reclassify index 12",
306 "expExitCode": "0",
307 "verifyCmd": "$TC actions get action vlan index 12",
308 "matchPattern": "action order [0-9]+: vlan.*modify id 500 protocol 802.1ad priority 0 reclassify.*index 12 ref",
309 "matchCount": "1",
310 "teardown": [
311 "$TC actions flush action vlan"
312 ]
313 },
314 {
315 "id": "83a4",
316 "name": "Delete vlan pop action",
317 "category": [
318 "actions",
319 "vlan"
320 ],
321 "setup": [
322 [
323 "$TC actions flush action vlan",
324 0,
325 1,
326 255
327 ],
328 "$TC actions add action vlan pop index 44"
329 ],
330 "cmdUnderTest": "$TC actions del action vlan index 44",
331 "expExitCode": "0",
332 "verifyCmd": "$TC actions list action vlan",
333 "matchPattern": "action order [0-9]+: vlan.*pop.*index 44 ref",
334 "matchCount": "0",
335 "teardown": []
336 },
337 {
338 "id": "ed1e",
339 "name": "Delete vlan push action for protocol 802.1Q",
340 "category": [
341 "actions",
342 "vlan"
343 ],
344 "setup": [
345 [
346 "$TC actions flush action vlan",
347 0,
348 1,
349 255
350 ],
351 "$TC actions add action vlan push id 4094 protocol 802.1Q index 999"
352 ],
353 "cmdUnderTest": "$TC actions del action vlan index 999",
354 "expExitCode": "0",
355 "verifyCmd": "$TC actions list action vlan",
356 "matchPattern": "action order [0-9]+: vlan.*push id 4094 protocol 802.1Q priority 0 pipe.*index 999 ref",
357 "matchCount": "0",
358 "teardown": []
359 },
360 {
361 "id": "a2a3",
362 "name": "Flush vlan actions",
363 "category": [
364 "actions",
365 "vlan"
366 ],
367 "setup": [
368 [
369 "$TC actions flush action vlan",
370 0,
371 1,
372 255
373 ],
374 "$TC actions add action vlan push id 4 protocol 802.1ad index 10",
375 "$TC actions add action vlan push id 4 protocol 802.1ad index 11",
376 "$TC actions add action vlan push id 4 protocol 802.1ad index 12",
377 "$TC actions add action vlan push id 4 protocol 802.1ad index 13"
378 ],
379 "cmdUnderTest": "$TC actions flush action vlan",
380 "expExitCode": "0",
381 "verifyCmd": "$TC actions list action vlan",
382 "matchPattern": "action order [0-9]+: vlan.*push id 4 protocol 802.1ad",
383 "matchCount": "0",
384 "teardown": []
385 },
386 {
387 "id": "1d78",
388 "name": "Add vlan action with cookie",
389 "category": [
390 "actions",
391 "vlan"
392 ],
393 "setup": [
394 [
395 "$TC actions flush action vlan",
396 0,
397 1,
398 255
399 ]
400 ],
401 "cmdUnderTest": "$TC actions add action vlan push id 4 cookie a0a0a0a0a0a0a0",
402 "expExitCode": "0",
403 "verifyCmd": "$TC actions list action vlan",
404 "matchPattern": "action order [0-9]+: vlan.*push id 4.*cookie a0a0a0a0a0a0a0",
405 "matchCount": "1",
406 "teardown": [
407 "$TC actions flush action vlan"
408 ]
409 }
410]
diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py
index fc373fdf2bdc..87a04a8a5945 100755
--- a/tools/testing/selftests/tc-testing/tdc.py
+++ b/tools/testing/selftests/tc-testing/tdc.py
@@ -11,16 +11,96 @@ import re
11import os 11import os
12import sys 12import sys
13import argparse 13import argparse
14import importlib
14import json 15import json
15import subprocess 16import subprocess
17import time
18import traceback
16from collections import OrderedDict 19from collections import OrderedDict
17from string import Template 20from string import Template
18 21
19from tdc_config import * 22from tdc_config import *
20from tdc_helper import * 23from tdc_helper import *
21 24
22 25import TdcPlugin
23USE_NS = True 26
27
28class PluginMgrTestFail(Exception):
29 def __init__(self, stage, output, message):
30 self.stage = stage
31 self.output = output
32 self.message = message
33
34class PluginMgr:
35 def __init__(self, argparser):
36 super().__init__()
37 self.plugins = {}
38 self.plugin_instances = []
39 self.args = []
40 self.argparser = argparser
41
42 # TODO, put plugins in order
43 plugindir = os.getenv('TDC_PLUGIN_DIR', './plugins')
44 for dirpath, dirnames, filenames in os.walk(plugindir):
45 for fn in filenames:
46 if (fn.endswith('.py') and
47 not fn == '__init__.py' and
48 not fn.startswith('#') and
49 not fn.startswith('.#')):
50 mn = fn[0:-3]
51 foo = importlib.import_module('plugins.' + mn)
52 self.plugins[mn] = foo
53 self.plugin_instances.append(foo.SubPlugin())
54
55 def call_pre_suite(self, testcount, testidlist):
56 for pgn_inst in self.plugin_instances:
57 pgn_inst.pre_suite(testcount, testidlist)
58
59 def call_post_suite(self, index):
60 for pgn_inst in reversed(self.plugin_instances):
61 pgn_inst.post_suite(index)
62
63 def call_pre_case(self, test_ordinal, testid):
64 for pgn_inst in self.plugin_instances:
65 try:
66 pgn_inst.pre_case(test_ordinal, testid)
67 except Exception as ee:
68 print('exception {} in call to pre_case for {} plugin'.
69 format(ee, pgn_inst.__class__))
70 print('test_ordinal is {}'.format(test_ordinal))
71 print('testid is {}'.format(testid))
72 raise
73
74 def call_post_case(self):
75 for pgn_inst in reversed(self.plugin_instances):
76 pgn_inst.post_case()
77
78 def call_pre_execute(self):
79 for pgn_inst in self.plugin_instances:
80 pgn_inst.pre_execute()
81
82 def call_post_execute(self):
83 for pgn_inst in reversed(self.plugin_instances):
84 pgn_inst.post_execute()
85
86 def call_add_args(self, parser):
87 for pgn_inst in self.plugin_instances:
88 parser = pgn_inst.add_args(parser)
89 return parser
90
91 def call_check_args(self, args, remaining):
92 for pgn_inst in self.plugin_instances:
93 pgn_inst.check_args(args, remaining)
94
95 def call_adjust_command(self, stage, command):
96 for pgn_inst in self.plugin_instances:
97 command = pgn_inst.adjust_command(stage, command)
98 return command
99
100 @staticmethod
101 def _make_argparser(args):
102 self.argparser = argparse.ArgumentParser(
103 description='Linux TC unit tests')
24 104
25 105
26def replace_keywords(cmd): 106def replace_keywords(cmd):
@@ -33,21 +113,24 @@ def replace_keywords(cmd):
33 return subcmd 113 return subcmd
34 114
35 115
36def exec_cmd(command, nsonly=True): 116def exec_cmd(args, pm, stage, command):
37 """ 117 """
38 Perform any required modifications on an executable command, then run 118 Perform any required modifications on an executable command, then run
39 it in a subprocess and return the results. 119 it in a subprocess and return the results.
40 """ 120 """
41 if (USE_NS and nsonly): 121 if len(command.strip()) == 0:
42 command = 'ip netns exec $NS ' + command 122 return None, None
43
44 if '$' in command: 123 if '$' in command:
45 command = replace_keywords(command) 124 command = replace_keywords(command)
46 125
126 command = pm.call_adjust_command(stage, command)
127 if args.verbose > 0:
128 print('command "{}"'.format(command))
47 proc = subprocess.Popen(command, 129 proc = subprocess.Popen(command,
48 shell=True, 130 shell=True,
49 stdout=subprocess.PIPE, 131 stdout=subprocess.PIPE,
50 stderr=subprocess.PIPE) 132 stderr=subprocess.PIPE,
133 env=ENVIR)
51 (rawout, serr) = proc.communicate() 134 (rawout, serr) = proc.communicate()
52 135
53 if proc.returncode != 0 and len(serr) > 0: 136 if proc.returncode != 0 and len(serr) > 0:
@@ -60,36 +143,99 @@ def exec_cmd(command, nsonly=True):
60 return proc, foutput 143 return proc, foutput
61 144
62 145
63def prepare_env(cmdlist): 146def prepare_env(args, pm, stage, prefix, cmdlist, output = None):
64 """ 147 """
65 Execute the setup/teardown commands for a test case. Optionally 148 Execute the setup/teardown commands for a test case.
66 terminate test execution if the command fails. 149 Optionally terminate test execution if the command fails.
67 """ 150 """
151 if args.verbose > 0:
152 print('{}'.format(prefix))
68 for cmdinfo in cmdlist: 153 for cmdinfo in cmdlist:
69 if (type(cmdinfo) == list): 154 if isinstance(cmdinfo, list):
70 exit_codes = cmdinfo[1:] 155 exit_codes = cmdinfo[1:]
71 cmd = cmdinfo[0] 156 cmd = cmdinfo[0]
72 else: 157 else:
73 exit_codes = [0] 158 exit_codes = [0]
74 cmd = cmdinfo 159 cmd = cmdinfo
75 160
76 if (len(cmd) == 0): 161 if not cmd:
77 continue 162 continue
78 163
79 (proc, foutput) = exec_cmd(cmd) 164 (proc, foutput) = exec_cmd(args, pm, stage, cmd)
165
166 if proc and (proc.returncode not in exit_codes):
167 print('', file=sys.stderr)
168 print("{} *** Could not execute: \"{}\"".format(prefix, cmd),
169 file=sys.stderr)
170 print("\n{} *** Error message: \"{}\"".format(prefix, foutput),
171 file=sys.stderr)
172 print("\n{} *** Aborting test run.".format(prefix), file=sys.stderr)
173 print("\n\n{} *** stdout ***".format(proc.stdout), file=sys.stderr)
174 print("\n\n{} *** stderr ***".format(proc.stderr), file=sys.stderr)
175 raise PluginMgrTestFail(
176 stage, output,
177 '"{}" did not complete successfully'.format(prefix))
178
179def run_one_test(pm, args, index, tidx):
180 global NAMES
181 result = True
182 tresult = ""
183 tap = ""
184 if args.verbose > 0:
185 print("\t====================\n=====> ", end="")
186 print("Test " + tidx["id"] + ": " + tidx["name"])
187
188 # populate NAMES with TESTID for this test
189 NAMES['TESTID'] = tidx['id']
190
191 pm.call_pre_case(index, tidx['id'])
192 prepare_env(args, pm, 'setup', "-----> prepare stage", tidx["setup"])
193
194 if (args.verbose > 0):
195 print('-----> execute stage')
196 pm.call_pre_execute()
197 (p, procout) = exec_cmd(args, pm, 'execute', tidx["cmdUnderTest"])
198 exit_code = p.returncode
199 pm.call_post_execute()
200
201 if (exit_code != int(tidx["expExitCode"])):
202 result = False
203 print("exit:", exit_code, int(tidx["expExitCode"]))
204 print(procout)
205 else:
206 if args.verbose > 0:
207 print('-----> verify stage')
208 match_pattern = re.compile(
209 str(tidx["matchPattern"]), re.DOTALL | re.MULTILINE)
210 (p, procout) = exec_cmd(args, pm, 'verify', tidx["verifyCmd"])
211 if procout:
212 match_index = re.findall(match_pattern, procout)
213 if len(match_index) != int(tidx["matchCount"]):
214 result = False
215 elif int(tidx["matchCount"]) != 0:
216 result = False
217
218 if not result:
219 tresult += 'not '
220 tresult += 'ok {} - {} # {}\n'.format(str(index), tidx['id'], tidx['name'])
221 tap += tresult
80 222
81 if proc.returncode not in exit_codes: 223 if result == False:
82 print 224 if procout:
83 print("Could not execute:") 225 tap += procout
84 print(cmd) 226 else:
85 print("\nError message:") 227 tap += 'No output!\n'
86 print(foutput) 228
87 print("\nAborting test run.") 229 prepare_env(args, pm, 'teardown', '-----> teardown stage', tidx['teardown'], procout)
88 ns_destroy() 230 pm.call_post_case()
89 exit(1)
90 231
232 index += 1
233
234 # remove TESTID from NAMES
235 del(NAMES['TESTID'])
236 return tap
91 237
92def test_runner(filtered_tests, args): 238def test_runner(pm, args, filtered_tests):
93 """ 239 """
94 Driver function for the unit tests. 240 Driver function for the unit tests.
95 241
@@ -101,75 +247,92 @@ def test_runner(filtered_tests, args):
101 testlist = filtered_tests 247 testlist = filtered_tests
102 tcount = len(testlist) 248 tcount = len(testlist)
103 index = 1 249 index = 1
104 tap = str(index) + ".." + str(tcount) + "\n" 250 tap = ''
105 251 badtest = None
252 stage = None
253 emergency_exit = False
254 emergency_exit_message = ''
255
256 if args.notap:
257 if args.verbose:
258 tap = 'notap requested: omitting test plan\n'
259 else:
260 tap = str(index) + ".." + str(tcount) + "\n"
261 try:
262 pm.call_pre_suite(tcount, [tidx['id'] for tidx in testlist])
263 except Exception as ee:
264 ex_type, ex, ex_tb = sys.exc_info()
265 print('Exception {} {} (caught in pre_suite).'.
266 format(ex_type, ex))
267 # when the extra print statements are uncommented,
268 # the traceback does not appear between them
269 # (it appears way earlier in the tdc.py output)
270 # so don't bother ...
271 # print('--------------------(')
272 # print('traceback')
273 traceback.print_tb(ex_tb)
274 # print('--------------------)')
275 emergency_exit_message = 'EMERGENCY EXIT, call_pre_suite failed with exception {} {}\n'.format(ex_type, ex)
276 emergency_exit = True
277 stage = 'pre-SUITE'
278
279 if emergency_exit:
280 pm.call_post_suite(index)
281 return emergency_exit_message
282 if args.verbose > 1:
283 print('give test rig 2 seconds to stabilize')
284 time.sleep(2)
106 for tidx in testlist: 285 for tidx in testlist:
107 result = True
108 tresult = ""
109 if "flower" in tidx["category"] and args.device == None: 286 if "flower" in tidx["category"] and args.device == None:
287 if args.verbose > 1:
288 print('Not executing test {} {} because DEV2 not defined'.
289 format(tidx['id'], tidx['name']))
110 continue 290 continue
111 print("Test " + tidx["id"] + ": " + tidx["name"]) 291 try:
112 prepare_env(tidx["setup"]) 292 badtest = tidx # in case it goes bad
113 (p, procout) = exec_cmd(tidx["cmdUnderTest"]) 293 tap += run_one_test(pm, args, index, tidx)
114 exit_code = p.returncode 294 except PluginMgrTestFail as pmtf:
115 295 ex_type, ex, ex_tb = sys.exc_info()
116 if (exit_code != int(tidx["expExitCode"])): 296 stage = pmtf.stage
117 result = False 297 message = pmtf.message
118 print("exit:", exit_code, int(tidx["expExitCode"])) 298 output = pmtf.output
119 print(procout) 299 print(message)
120 else: 300 print('Exception {} {} (caught in test_runner, running test {} {} {} stage {})'.
121 match_pattern = re.compile(str(tidx["matchPattern"]), re.DOTALL) 301 format(ex_type, ex, index, tidx['id'], tidx['name'], stage))
122 (p, procout) = exec_cmd(tidx["verifyCmd"]) 302 print('---------------')
123 match_index = re.findall(match_pattern, procout) 303 print('traceback')
124 if len(match_index) != int(tidx["matchCount"]): 304 traceback.print_tb(ex_tb)
125 result = False 305 print('---------------')
126 306 if stage == 'teardown':
127 if result == True: 307 print('accumulated output for this test:')
128 tresult += "ok " 308 if pmtf.output:
129 else: 309 print(pmtf.output)
130 tresult += "not ok " 310 print('---------------')
131 tap += tresult + str(index) + " " + tidx["id"] + " " + tidx["name"] + "\n" 311 break
132
133 if result == False:
134 tap += procout
135
136 prepare_env(tidx["teardown"])
137 index += 1 312 index += 1
138 313
139 return tap 314 # if we failed in setup or teardown,
140 315 # fill in the remaining tests with ok-skipped
316 count = index
317 if not args.notap:
318 tap += 'about to flush the tap output if tests need to be skipped\n'
319 if tcount + 1 != index:
320 for tidx in testlist[index - 1:]:
321 msg = 'skipped - previous {} failed'.format(stage)
322 tap += 'ok {} - {} # {} {} {}\n'.format(
323 count, tidx['id'], msg, index, badtest.get('id', '--Unknown--'))
324 count += 1
141 325
142def ns_create(): 326 tap += 'done flushing skipped test tap output\n'
143 """
144 Create the network namespace in which the tests will be run and set up
145 the required network devices for it.
146 """
147 if (USE_NS):
148 cmd = 'ip netns add $NS'
149 exec_cmd(cmd, False)
150 cmd = 'ip link add $DEV0 type veth peer name $DEV1'
151 exec_cmd(cmd, False)
152 cmd = 'ip link set $DEV1 netns $NS'
153 exec_cmd(cmd, False)
154 cmd = 'ip link set $DEV0 up'
155 exec_cmd(cmd, False)
156 cmd = 'ip -n $NS link set $DEV1 up'
157 exec_cmd(cmd, False)
158 cmd = 'ip link set $DEV2 netns $NS'
159 exec_cmd(cmd, False)
160 cmd = 'ip -n $NS link set $DEV2 up'
161 exec_cmd(cmd, False)
162 327
328 if args.pause:
329 print('Want to pause\nPress enter to continue ...')
330 if input(sys.stdin):
331 print('got something on stdin')
163 332
164def ns_destroy(): 333 pm.call_post_suite(index)
165 """
166 Destroy the network namespace for testing (and any associated network
167 devices as well)
168 """
169 if (USE_NS):
170 cmd = 'ip netns delete $NS'
171 exec_cmd(cmd, False)
172 334
335 return tap
173 336
174def has_blank_ids(idlist): 337def has_blank_ids(idlist):
175 """ 338 """
@@ -209,41 +372,70 @@ def set_args(parser):
209 """ 372 """
210 Set the command line arguments for tdc. 373 Set the command line arguments for tdc.
211 """ 374 """
212 parser.add_argument('-p', '--path', type=str, 375 parser.add_argument(
213 help='The full path to the tc executable to use') 376 '-p', '--path', type=str,
214 parser.add_argument('-c', '--category', type=str, nargs='?', const='+c', 377 help='The full path to the tc executable to use')
215 help='Run tests only from the specified category, or if no category is specified, list known categories.') 378 sg = parser.add_argument_group(
216 parser.add_argument('-f', '--file', type=str, 379 'selection', 'select which test cases: ' +
217 help='Run tests from the specified file') 380 'files plus directories; filtered by categories plus testids')
218 parser.add_argument('-l', '--list', type=str, nargs='?', const="++", metavar='CATEGORY', 381 ag = parser.add_argument_group(
219 help='List all test cases, or those only within the specified category') 382 'action', 'select action to perform on selected test cases')
220 parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID', 383
221 help='Display the test case with specified id') 384 sg.add_argument(
222 parser.add_argument('-e', '--execute', type=str, nargs=1, metavar='ID', 385 '-D', '--directory', nargs='+', metavar='DIR',
223 help='Execute the single test case with specified ID') 386 help='Collect tests from the specified directory(ies) ' +
224 parser.add_argument('-i', '--id', action='store_true', dest='gen_id', 387 '(default [tc-tests])')
225 help='Generate ID numbers for new test cases') 388 sg.add_argument(
389 '-f', '--file', nargs='+', metavar='FILE',
390 help='Run tests from the specified file(s)')
391 sg.add_argument(
392 '-c', '--category', nargs='*', metavar='CATG', default=['+c'],
393 help='Run tests only from the specified category/ies, ' +
394 'or if no category/ies is/are specified, list known categories.')
395 sg.add_argument(
396 '-e', '--execute', nargs='+', metavar='ID',
397 help='Execute the specified test cases with specified IDs')
398 ag.add_argument(
399 '-l', '--list', action='store_true',
400 help='List all test cases, or those only within the specified category')
401 ag.add_argument(
402 '-s', '--show', action='store_true', dest='showID',
403 help='Display the selected test cases')
404 ag.add_argument(
405 '-i', '--id', action='store_true', dest='gen_id',
406 help='Generate ID numbers for new test cases')
407 parser.add_argument(
408 '-v', '--verbose', action='count', default=0,
409 help='Show the commands that are being run')
410 parser.add_argument(
411 '-N', '--notap', action='store_true',
412 help='Suppress tap results for command under test')
226 parser.add_argument('-d', '--device', 413 parser.add_argument('-d', '--device',
227 help='Execute the test case in flower category') 414 help='Execute the test case in flower category')
415 parser.add_argument(
416 '-P', '--pause', action='store_true',
417 help='Pause execution just before post-suite stage')
228 return parser 418 return parser
229 419
230 420
231def check_default_settings(args): 421def check_default_settings(args, remaining, pm):
232 """ 422 """
233 Process any arguments overriding the default settings, and ensure the 423 Process any arguments overriding the default settings,
234 settings are correct. 424 and ensure the settings are correct.
235 """ 425 """
236 # Allow for overriding specific settings 426 # Allow for overriding specific settings
237 global NAMES 427 global NAMES
238 428
239 if args.path != None: 429 if args.path != None:
240 NAMES['TC'] = args.path 430 NAMES['TC'] = args.path
241 if args.device != None: 431 if args.device != None:
242 NAMES['DEV2'] = args.device 432 NAMES['DEV2'] = args.device
243 if not os.path.isfile(NAMES['TC']): 433 if not os.path.isfile(NAMES['TC']):
244 print("The specified tc path " + NAMES['TC'] + " does not exist.") 434 print("The specified tc path " + NAMES['TC'] + " does not exist.")
245 exit(1) 435 exit(1)
246 436
437 pm.call_check_args(args, remaining)
438
247 439
248def get_id_list(alltests): 440def get_id_list(alltests):
249 """ 441 """
@@ -277,7 +469,7 @@ def generate_case_ids(alltests):
277 for c in alltests: 469 for c in alltests:
278 if (c["id"] == ""): 470 if (c["id"] == ""):
279 while True: 471 while True:
280 newid = str('%04x' % random.randrange(16**4)) 472 newid = str('{:04x}'.format(random.randrange(16**4)))
281 if (does_id_exist(alltests, newid)): 473 if (does_id_exist(alltests, newid)):
282 continue 474 continue
283 else: 475 else:
@@ -298,42 +490,110 @@ def generate_case_ids(alltests):
298 testlist.append(t) 490 testlist.append(t)
299 outfile = open(f, "w") 491 outfile = open(f, "w")
300 json.dump(testlist, outfile, indent=4) 492 json.dump(testlist, outfile, indent=4)
493 outfile.write("\n")
301 outfile.close() 494 outfile.close()
302 495
496def filter_tests_by_id(args, testlist):
497 '''
498 Remove tests from testlist that are not in the named id list.
499 If id list is empty, return empty list.
500 '''
501 newlist = list()
502 if testlist and args.execute:
503 target_ids = args.execute
504
505 if isinstance(target_ids, list) and (len(target_ids) > 0):
506 newlist = list(filter(lambda x: x['id'] in target_ids, testlist))
507 return newlist
508
509def filter_tests_by_category(args, testlist):
510 '''
511 Remove tests from testlist that are not in a named category.
512 '''
513 answer = list()
514 if args.category and testlist:
515 test_ids = list()
516 for catg in set(args.category):
517 if catg == '+c':
518 continue
519 print('considering category {}'.format(catg))
520 for tc in testlist:
521 if catg in tc['category'] and tc['id'] not in test_ids:
522 answer.append(tc)
523 test_ids.append(tc['id'])
524
525 return answer
303 526
304def get_test_cases(args): 527def get_test_cases(args):
305 """ 528 """
306 If a test case file is specified, retrieve tests from that file. 529 If a test case file is specified, retrieve tests from that file.
307 Otherwise, glob for all json files in subdirectories and load from 530 Otherwise, glob for all json files in subdirectories and load from
308 each one. 531 each one.
532 Also, if requested, filter by category, and add tests matching
533 certain ids.
309 """ 534 """
310 import fnmatch 535 import fnmatch
311 if args.file != None: 536
312 if not os.path.isfile(args.file): 537 flist = []
313 print("The specified test case file " + args.file + " does not exist.") 538 testdirs = ['tc-tests']
314 exit(1) 539
315 flist = [args.file] 540 if args.file:
316 else: 541 # at least one file was specified - remove the default directory
317 flist = [] 542 testdirs = []
318 for root, dirnames, filenames in os.walk('tc-tests'): 543
544 for ff in args.file:
545 if not os.path.isfile(ff):
546 print("IGNORING file " + ff + "\n\tBECAUSE does not exist.")
547 else:
548 flist.append(os.path.abspath(ff))
549
550 if args.directory:
551 testdirs = args.directory
552
553 for testdir in testdirs:
554 for root, dirnames, filenames in os.walk(testdir):
319 for filename in fnmatch.filter(filenames, '*.json'): 555 for filename in fnmatch.filter(filenames, '*.json'):
320 flist.append(os.path.join(root, filename)) 556 candidate = os.path.abspath(os.path.join(root, filename))
321 alltests = list() 557 if candidate not in testdirs:
558 flist.append(candidate)
559
560 alltestcases = list()
322 for casefile in flist: 561 for casefile in flist:
323 alltests = alltests + (load_from_file(casefile)) 562 alltestcases = alltestcases + (load_from_file(casefile))
324 return alltests 563
564 allcatlist = get_test_categories(alltestcases)
565 allidlist = get_id_list(alltestcases)
325 566
567 testcases_by_cats = get_categorized_testlist(alltestcases, allcatlist)
568 idtestcases = filter_tests_by_id(args, alltestcases)
569 cattestcases = filter_tests_by_category(args, alltestcases)
326 570
327def set_operation_mode(args): 571 cat_ids = [x['id'] for x in cattestcases]
572 if args.execute:
573 if args.category:
574 alltestcases = cattestcases + [x for x in idtestcases if x['id'] not in cat_ids]
575 else:
576 alltestcases = idtestcases
577 else:
578 if cat_ids:
579 alltestcases = cattestcases
580 else:
581 # just accept the existing value of alltestcases,
582 # which has been filtered by file/directory
583 pass
584
585 return allcatlist, allidlist, testcases_by_cats, alltestcases
586
587
588def set_operation_mode(pm, args):
328 """ 589 """
329 Load the test case data and process remaining arguments to determine 590 Load the test case data and process remaining arguments to determine
330 what the script should do for this run, and call the appropriate 591 what the script should do for this run, and call the appropriate
331 function. 592 function.
332 """ 593 """
333 alltests = get_test_cases(args) 594 ucat, idlist, testcases, alltests = get_test_cases(args)
334 595
335 if args.gen_id: 596 if args.gen_id:
336 idlist = get_id_list(alltests)
337 if (has_blank_ids(idlist)): 597 if (has_blank_ids(idlist)):
338 alltests = generate_case_ids(alltests) 598 alltests = generate_case_ids(alltests)
339 else: 599 else:
@@ -347,70 +607,29 @@ def set_operation_mode(args):
347 print("Please correct them before continuing.") 607 print("Please correct them before continuing.")
348 exit(1) 608 exit(1)
349 609
350 ucat = get_test_categories(alltests)
351
352 if args.showID: 610 if args.showID:
353 show_test_case_by_id(alltests, args.showID[0]) 611 for atest in alltests:
612 print_test_case(atest)
354 exit(0) 613 exit(0)
355 614
356 if args.execute: 615 if isinstance(args.category, list) and (len(args.category) == 0):
357 target_id = args.execute[0] 616 print("Available categories:")
358 else: 617 print_sll(ucat)
359 target_id = "" 618 exit(0)
360
361 if args.category:
362 if (args.category == '+c'):
363 print("Available categories:")
364 print_sll(ucat)
365 exit(0)
366 else:
367 target_category = args.category
368 else:
369 target_category = ""
370
371
372 testcases = get_categorized_testlist(alltests, ucat)
373 619
374 if args.list: 620 if args.list:
375 if (args.list == "++"): 621 if args.list:
376 list_test_cases(alltests) 622 list_test_cases(alltests)
377 exit(0) 623 exit(0)
378 elif(len(args.list) > 0):
379 if (args.list not in ucat):
380 print("Unknown category " + args.list)
381 print("Available categories:")
382 print_sll(ucat)
383 exit(1)
384 list_test_cases(testcases[args.list])
385 exit(0)
386
387 if (os.geteuid() != 0):
388 print("This script must be run with root privileges.\n")
389 exit(1)
390
391 ns_create()
392
393 if (len(target_category) == 0):
394 if (len(target_id) > 0):
395 alltests = list(filter(lambda x: target_id in x['id'], alltests))
396 if (len(alltests) == 0):
397 print("Cannot find a test case with ID matching " + target_id)
398 exit(1)
399 catresults = test_runner(alltests, args)
400 print("All test results: " + "\n\n" + catresults)
401 elif (len(target_category) > 0):
402 if (target_category == "flower") and args.device == None:
403 print("Please specify a NIC device (-d) to run category flower")
404 exit(1)
405 if (target_category not in ucat):
406 print("Specified category is not present in this file.")
407 exit(1)
408 else:
409 catresults = test_runner(testcases[target_category], args)
410 print("Category " + target_category + "\n\n" + catresults)
411
412 ns_destroy()
413 624
625 if len(alltests):
626 catresults = test_runner(pm, args, alltests)
627 else:
628 catresults = 'No tests found\n'
629 if args.notap:
630 print('Tap output suppression requested\n')
631 else:
632 print('All test results: \n\n{}'.format(catresults))
414 633
415def main(): 634def main():
416 """ 635 """
@@ -419,10 +638,15 @@ def main():
419 """ 638 """
420 parser = args_parse() 639 parser = args_parse()
421 parser = set_args(parser) 640 parser = set_args(parser)
641 pm = PluginMgr(parser)
642 parser = pm.call_add_args(parser)
422 (args, remaining) = parser.parse_known_args() 643 (args, remaining) = parser.parse_known_args()
423 check_default_settings(args) 644 args.NAMES = NAMES
645 check_default_settings(args, remaining, pm)
646 if args.verbose > 2:
647 print('args is {}'.format(args))
424 648
425 set_operation_mode(args) 649 set_operation_mode(pm, args)
426 650
427 exit(0) 651 exit(0)
428 652
diff --git a/tools/testing/selftests/tc-testing/tdc_batch.py b/tools/testing/selftests/tc-testing/tdc_batch.py
index 707c6bfef689..52fa539dc662 100755
--- a/tools/testing/selftests/tc-testing/tdc_batch.py
+++ b/tools/testing/selftests/tc-testing/tdc_batch.py
@@ -49,13 +49,13 @@ index = 0
49for i in range(0x100): 49for i in range(0x100):
50 for j in range(0x100): 50 for j in range(0x100):
51 for k in range(0x100): 51 for k in range(0x100):
52 mac = ("%02x:%02x:%02x" % (i, j, k)) 52 mac = ("{:02x}:{:02x}:{:02x}".format(i, j, k))
53 src_mac = "e4:11:00:" + mac 53 src_mac = "e4:11:00:" + mac
54 dst_mac = "e4:12:00:" + mac 54 dst_mac = "e4:12:00:" + mac
55 cmd = ("filter add dev %s %s protocol ip parent ffff: flower %s " 55 cmd = ("filter add dev {} {} protocol ip parent ffff: flower {} "
56 "src_mac %s dst_mac %s action drop %s" % 56 "src_mac {} dst_mac {} action drop {}".format
57 (device, prio, skip, src_mac, dst_mac, share_action)) 57 (device, prio, skip, src_mac, dst_mac, share_action))
58 file.write("%s\n" % cmd) 58 file.write("{}\n".format(cmd))
59 index += 1 59 index += 1
60 if index >= number: 60 if index >= number:
61 file.close() 61 file.close()
diff --git a/tools/testing/selftests/tc-testing/tdc_helper.py b/tools/testing/selftests/tc-testing/tdc_helper.py
index db381120a566..9f35c96c88a0 100644
--- a/tools/testing/selftests/tc-testing/tdc_helper.py
+++ b/tools/testing/selftests/tc-testing/tdc_helper.py
@@ -57,20 +57,11 @@ def print_sll(items):
57 57
58def print_test_case(tcase): 58def print_test_case(tcase):
59 """ Pretty-printing of a given test case. """ 59 """ Pretty-printing of a given test case. """
60 print('\n==============\nTest {}\t{}\n'.format(tcase['id'], tcase['name']))
60 for k in tcase.keys(): 61 for k in tcase.keys():
61 if (isinstance(tcase[k], list)): 62 if (isinstance(tcase[k], list)):
62 print(k + ":") 63 print(k + ":")
63 print_list(tcase[k]) 64 print_list(tcase[k])
64 else: 65 else:
65 print(k + ": " + tcase[k]) 66 if not ((k == 'id') or (k == 'name')):
66 67 print(k + ": " + str(tcase[k]))
67
68def show_test_case_by_id(testlist, caseID):
69 """ Find the specified test case to pretty-print. """
70 if not any(d.get('id', None) == caseID for d in testlist):
71 print("That ID does not exist.")
72 exit(1)
73 else:
74 print_test_case(next((d for d in testlist if d['id'] == caseID)))
75
76
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index d744991c0f4f..39f66bc29b82 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -11,7 +11,7 @@ CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c)
11 11
12TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ 12TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \
13 check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \ 13 check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \
14 protection_keys test_vdso test_vsyscall 14 protection_keys test_vdso test_vsyscall mov_ss_trap
15TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ 15TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
16 test_FCMOV test_FCOMI test_FISTTP \ 16 test_FCMOV test_FCOMI test_FISTTP \
17 vdso_restorer 17 vdso_restorer
diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c
new file mode 100644
index 000000000000..3c3a022654f3
--- /dev/null
+++ b/tools/testing/selftests/x86/mov_ss_trap.c
@@ -0,0 +1,285 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * mov_ss_trap.c: Exercise the bizarre side effects of a watchpoint on MOV SS
4 *
5 * This does MOV SS from a watchpointed address followed by various
6 * types of kernel entries. A MOV SS that hits a watchpoint will queue
7 * up a #DB trap but will not actually deliver that trap. The trap
8 * will be delivered after the next instruction instead. The CPU's logic
9 * seems to be:
10 *
11 * - Any fault: drop the pending #DB trap.
12 * - INT $N, INT3, INTO, SYSCALL, SYSENTER: enter the kernel and then
13 * deliver #DB.
14 * - ICEBP: enter the kernel but do not deliver the watchpoint trap
15 * - breakpoint: only one #DB is delivered (phew!)
16 *
17 * There are plenty of ways for a kernel to handle this incorrectly. This
18 * test tries to exercise all the cases.
19 *
20 * This should mostly cover CVE-2018-1087 and CVE-2018-8897.
21 */
22#define _GNU_SOURCE
23
24#include <stdlib.h>
25#include <sys/ptrace.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <sys/user.h>
29#include <sys/syscall.h>
30#include <unistd.h>
31#include <errno.h>
32#include <stddef.h>
33#include <stdio.h>
34#include <err.h>
35#include <string.h>
36#include <setjmp.h>
37#include <sys/prctl.h>
38
39#define X86_EFLAGS_RF (1UL << 16)
40
41#if __x86_64__
42# define REG_IP REG_RIP
43#else
44# define REG_IP REG_EIP
45#endif
46
47unsigned short ss;
48extern unsigned char breakpoint_insn[];
49sigjmp_buf jmpbuf;
50static unsigned char altstack_data[SIGSTKSZ];
51
52static void enable_watchpoint(void)
53{
54 pid_t parent = getpid();
55 int status;
56
57 pid_t child = fork();
58 if (child < 0)
59 err(1, "fork");
60
61 if (child) {
62 if (waitpid(child, &status, 0) != child)
63 err(1, "waitpid for child");
64 } else {
65 unsigned long dr0, dr1, dr7;
66
67 dr0 = (unsigned long)&ss;
68 dr1 = (unsigned long)breakpoint_insn;
69 dr7 = ((1UL << 1) | /* G0 */
70 (3UL << 16) | /* RW0 = read or write */
71 (1UL << 18) | /* LEN0 = 2 bytes */
72 (1UL << 3)); /* G1, RW1 = insn */
73
74 if (ptrace(PTRACE_ATTACH, parent, NULL, NULL) != 0)
75 err(1, "PTRACE_ATTACH");
76
77 if (waitpid(parent, &status, 0) != parent)
78 err(1, "waitpid for child");
79
80 if (ptrace(PTRACE_POKEUSER, parent, (void *)offsetof(struct user, u_debugreg[0]), dr0) != 0)
81 err(1, "PTRACE_POKEUSER DR0");
82
83 if (ptrace(PTRACE_POKEUSER, parent, (void *)offsetof(struct user, u_debugreg[1]), dr1) != 0)
84 err(1, "PTRACE_POKEUSER DR1");
85
86 if (ptrace(PTRACE_POKEUSER, parent, (void *)offsetof(struct user, u_debugreg[7]), dr7) != 0)
87 err(1, "PTRACE_POKEUSER DR7");
88
89 printf("\tDR0 = %lx, DR1 = %lx, DR7 = %lx\n", dr0, dr1, dr7);
90
91 if (ptrace(PTRACE_DETACH, parent, NULL, NULL) != 0)
92 err(1, "PTRACE_DETACH");
93
94 exit(0);
95 }
96}
97
98static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
99 int flags)
100{
101 struct sigaction sa;
102 memset(&sa, 0, sizeof(sa));
103 sa.sa_sigaction = handler;
104 sa.sa_flags = SA_SIGINFO | flags;
105 sigemptyset(&sa.sa_mask);
106 if (sigaction(sig, &sa, 0))
107 err(1, "sigaction");
108}
109
110static char const * const signames[] = {
111 [SIGSEGV] = "SIGSEGV",
112 [SIGBUS] = "SIBGUS",
113 [SIGTRAP] = "SIGTRAP",
114 [SIGILL] = "SIGILL",
115};
116
117static void sigtrap(int sig, siginfo_t *si, void *ctx_void)
118{
119 ucontext_t *ctx = ctx_void;
120
121 printf("\tGot SIGTRAP with RIP=%lx, EFLAGS.RF=%d\n",
122 (unsigned long)ctx->uc_mcontext.gregs[REG_IP],
123 !!(ctx->uc_mcontext.gregs[REG_EFL] & X86_EFLAGS_RF));
124}
125
126static void handle_and_return(int sig, siginfo_t *si, void *ctx_void)
127{
128 ucontext_t *ctx = ctx_void;
129
130 printf("\tGot %s with RIP=%lx\n", signames[sig],
131 (unsigned long)ctx->uc_mcontext.gregs[REG_IP]);
132}
133
134static void handle_and_longjmp(int sig, siginfo_t *si, void *ctx_void)
135{
136 ucontext_t *ctx = ctx_void;
137
138 printf("\tGot %s with RIP=%lx\n", signames[sig],
139 (unsigned long)ctx->uc_mcontext.gregs[REG_IP]);
140
141 siglongjmp(jmpbuf, 1);
142}
143
144int main()
145{
146 unsigned long nr;
147
148 asm volatile ("mov %%ss, %[ss]" : [ss] "=m" (ss));
149 printf("\tSS = 0x%hx, &SS = 0x%p\n", ss, &ss);
150
151 if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0) == 0)
152 printf("\tPR_SET_PTRACER_ANY succeeded\n");
153
154 printf("\tSet up a watchpoint\n");
155 sethandler(SIGTRAP, sigtrap, 0);
156 enable_watchpoint();
157
158 printf("[RUN]\tRead from watched memory (should get SIGTRAP)\n");
159 asm volatile ("mov %[ss], %[tmp]" : [tmp] "=r" (nr) : [ss] "m" (ss));
160
161 printf("[RUN]\tMOV SS; INT3\n");
162 asm volatile ("mov %[ss], %%ss; int3" :: [ss] "m" (ss));
163
164 printf("[RUN]\tMOV SS; INT 3\n");
165 asm volatile ("mov %[ss], %%ss; .byte 0xcd, 0x3" :: [ss] "m" (ss));
166
167 printf("[RUN]\tMOV SS; CS CS INT3\n");
168 asm volatile ("mov %[ss], %%ss; .byte 0x2e, 0x2e; int3" :: [ss] "m" (ss));
169
170 printf("[RUN]\tMOV SS; CSx14 INT3\n");
171 asm volatile ("mov %[ss], %%ss; .fill 14,1,0x2e; int3" :: [ss] "m" (ss));
172
173 printf("[RUN]\tMOV SS; INT 4\n");
174 sethandler(SIGSEGV, handle_and_return, SA_RESETHAND);
175 asm volatile ("mov %[ss], %%ss; int $4" :: [ss] "m" (ss));
176
177#ifdef __i386__
178 printf("[RUN]\tMOV SS; INTO\n");
179 sethandler(SIGSEGV, handle_and_return, SA_RESETHAND);
180 nr = -1;
181 asm volatile ("add $1, %[tmp]; mov %[ss], %%ss; into"
182 : [tmp] "+r" (nr) : [ss] "m" (ss));
183#endif
184
185 if (sigsetjmp(jmpbuf, 1) == 0) {
186 printf("[RUN]\tMOV SS; ICEBP\n");
187
188 /* Some emulators (e.g. QEMU TCG) don't emulate ICEBP. */
189 sethandler(SIGILL, handle_and_longjmp, SA_RESETHAND);
190
191 asm volatile ("mov %[ss], %%ss; .byte 0xf1" :: [ss] "m" (ss));
192 }
193
194 if (sigsetjmp(jmpbuf, 1) == 0) {
195 printf("[RUN]\tMOV SS; CLI\n");
196 sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND);
197 asm volatile ("mov %[ss], %%ss; cli" :: [ss] "m" (ss));
198 }
199
200 if (sigsetjmp(jmpbuf, 1) == 0) {
201 printf("[RUN]\tMOV SS; #PF\n");
202 sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND);
203 asm volatile ("mov %[ss], %%ss; mov (-1), %[tmp]"
204 : [tmp] "=r" (nr) : [ss] "m" (ss));
205 }
206
207 /*
208 * INT $1: if #DB has DPL=3 and there isn't special handling,
209 * then the kernel will die.
210 */
211 if (sigsetjmp(jmpbuf, 1) == 0) {
212 printf("[RUN]\tMOV SS; INT 1\n");
213 sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND);
214 asm volatile ("mov %[ss], %%ss; int $1" :: [ss] "m" (ss));
215 }
216
217#ifdef __x86_64__
218 /*
219 * In principle, we should test 32-bit SYSCALL as well, but
220 * the calling convention is so unpredictable that it's
221 * not obviously worth the effort.
222 */
223 if (sigsetjmp(jmpbuf, 1) == 0) {
224 printf("[RUN]\tMOV SS; SYSCALL\n");
225 sethandler(SIGILL, handle_and_longjmp, SA_RESETHAND);
226 nr = SYS_getpid;
227 /*
228 * Toggle the high bit of RSP to make it noncanonical to
229 * strengthen this test on non-SMAP systems.
230 */
231 asm volatile ("btc $63, %%rsp\n\t"
232 "mov %[ss], %%ss; syscall\n\t"
233 "btc $63, %%rsp"
234 : "+a" (nr) : [ss] "m" (ss)
235 : "rcx"
236#ifdef __x86_64__
237 , "r11"
238#endif
239 );
240 }
241#endif
242
243 printf("[RUN]\tMOV SS; breakpointed NOP\n");
244 asm volatile ("mov %[ss], %%ss; breakpoint_insn: nop" :: [ss] "m" (ss));
245
246 /*
247 * Invoking SYSENTER directly breaks all the rules. Just handle
248 * the SIGSEGV.
249 */
250 if (sigsetjmp(jmpbuf, 1) == 0) {
251 printf("[RUN]\tMOV SS; SYSENTER\n");
252 stack_t stack = {
253 .ss_sp = altstack_data,
254 .ss_size = SIGSTKSZ,
255 };
256 if (sigaltstack(&stack, NULL) != 0)
257 err(1, "sigaltstack");
258 sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND | SA_ONSTACK);
259 nr = SYS_getpid;
260 asm volatile ("mov %[ss], %%ss; SYSENTER" : "+a" (nr)
261 : [ss] "m" (ss) : "flags", "rcx"
262#ifdef __x86_64__
263 , "r11"
264#endif
265 );
266
267 /* We're unreachable here. SYSENTER forgets RIP. */
268 }
269
270 if (sigsetjmp(jmpbuf, 1) == 0) {
271 printf("[RUN]\tMOV SS; INT $0x80\n");
272 sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND);
273 nr = 20; /* compat getpid */
274 asm volatile ("mov %[ss], %%ss; int $0x80"
275 : "+a" (nr) : [ss] "m" (ss)
276 : "flags"
277#ifdef __x86_64__
278 , "r8", "r9", "r10", "r11"
279#endif
280 );
281 }
282
283 printf("[OK]\tI aten't dead\n");
284 return 0;
285}
diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c
index 9c0325e1ea68..50f7e9272481 100644
--- a/tools/testing/selftests/x86/mpx-mini-test.c
+++ b/tools/testing/selftests/x86/mpx-mini-test.c
@@ -368,6 +368,11 @@ static int expected_bnd_index = -1;
368uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */ 368uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */
369unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS]; 369unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS];
370 370
371/* Failed address bound checks: */
372#ifndef SEGV_BNDERR
373# define SEGV_BNDERR 3
374#endif
375
371/* 376/*
372 * The kernel is supposed to provide some information about the bounds 377 * The kernel is supposed to provide some information about the bounds
373 * exception in the siginfo. It should match what we have in the bounds 378 * exception in the siginfo. It should match what we have in the bounds
@@ -419,8 +424,6 @@ void handler(int signum, siginfo_t *si, void *vucontext)
419 br_count++; 424 br_count++;
420 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count); 425 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
421 426
422#define SEGV_BNDERR 3 /* failed address bound checks */
423
424 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n", 427 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
425 status, ip, br_reason); 428 status, ip, br_reason);
426 dprintf2("si_signo: %d\n", si->si_signo); 429 dprintf2("si_signo: %d\n", si->si_signo);
diff --git a/tools/testing/selftests/x86/pkey-helpers.h b/tools/testing/selftests/x86/pkey-helpers.h
index b3cb7670e026..254e5436bdd9 100644
--- a/tools/testing/selftests/x86/pkey-helpers.h
+++ b/tools/testing/selftests/x86/pkey-helpers.h
@@ -26,30 +26,26 @@ static inline void sigsafe_printf(const char *format, ...)
26{ 26{
27 va_list ap; 27 va_list ap;
28 28
29 va_start(ap, format);
30 if (!dprint_in_signal) { 29 if (!dprint_in_signal) {
30 va_start(ap, format);
31 vprintf(format, ap); 31 vprintf(format, ap);
32 va_end(ap);
32 } else { 33 } else {
33 int ret; 34 int ret;
34 int len = vsnprintf(dprint_in_signal_buffer,
35 DPRINT_IN_SIGNAL_BUF_SIZE,
36 format, ap);
37 /* 35 /*
38 * len is amount that would have been printed, 36 * No printf() functions are signal-safe.
39 * but actual write is truncated at BUF_SIZE. 37 * They deadlock easily. Write the format
38 * string to get some output, even if
39 * incomplete.
40 */ 40 */
41 if (len > DPRINT_IN_SIGNAL_BUF_SIZE) 41 ret = write(1, format, strlen(format));
42 len = DPRINT_IN_SIGNAL_BUF_SIZE;
43 ret = write(1, dprint_in_signal_buffer, len);
44 if (ret < 0) 42 if (ret < 0)
45 abort(); 43 exit(1);
46 } 44 }
47 va_end(ap);
48} 45}
49#define dprintf_level(level, args...) do { \ 46#define dprintf_level(level, args...) do { \
50 if (level <= DEBUG_LEVEL) \ 47 if (level <= DEBUG_LEVEL) \
51 sigsafe_printf(args); \ 48 sigsafe_printf(args); \
52 fflush(NULL); \
53} while (0) 49} while (0)
54#define dprintf0(args...) dprintf_level(0, args) 50#define dprintf0(args...) dprintf_level(0, args)
55#define dprintf1(args...) dprintf_level(1, args) 51#define dprintf1(args...) dprintf_level(1, args)
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index f15aa5a76fe3..460b4bdf4c1e 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -72,10 +72,9 @@ extern void abort_hooks(void);
72 test_nr, iteration_nr); \ 72 test_nr, iteration_nr); \
73 dprintf0("errno at assert: %d", errno); \ 73 dprintf0("errno at assert: %d", errno); \
74 abort_hooks(); \ 74 abort_hooks(); \
75 assert(condition); \ 75 exit(__LINE__); \
76 } \ 76 } \
77} while (0) 77} while (0)
78#define raw_assert(cond) assert(cond)
79 78
80void cat_into_file(char *str, char *file) 79void cat_into_file(char *str, char *file)
81{ 80{
@@ -87,12 +86,17 @@ void cat_into_file(char *str, char *file)
87 * these need to be raw because they are called under 86 * these need to be raw because they are called under
88 * pkey_assert() 87 * pkey_assert()
89 */ 88 */
90 raw_assert(fd >= 0); 89 if (fd < 0) {
90 fprintf(stderr, "error opening '%s'\n", str);
91 perror("error: ");
92 exit(__LINE__);
93 }
94
91 ret = write(fd, str, strlen(str)); 95 ret = write(fd, str, strlen(str));
92 if (ret != strlen(str)) { 96 if (ret != strlen(str)) {
93 perror("write to file failed"); 97 perror("write to file failed");
94 fprintf(stderr, "filename: '%s' str: '%s'\n", file, str); 98 fprintf(stderr, "filename: '%s' str: '%s'\n", file, str);
95 raw_assert(0); 99 exit(__LINE__);
96 } 100 }
97 close(fd); 101 close(fd);
98} 102}
@@ -191,26 +195,30 @@ void lots_o_noops_around_write(int *write_to_me)
191#ifdef __i386__ 195#ifdef __i386__
192 196
193#ifndef SYS_mprotect_key 197#ifndef SYS_mprotect_key
194# define SYS_mprotect_key 380 198# define SYS_mprotect_key 380
195#endif 199#endif
200
196#ifndef SYS_pkey_alloc 201#ifndef SYS_pkey_alloc
197# define SYS_pkey_alloc 381 202# define SYS_pkey_alloc 381
198# define SYS_pkey_free 382 203# define SYS_pkey_free 382
199#endif 204#endif
200#define REG_IP_IDX REG_EIP 205
201#define si_pkey_offset 0x14 206#define REG_IP_IDX REG_EIP
207#define si_pkey_offset 0x14
202 208
203#else 209#else
204 210
205#ifndef SYS_mprotect_key 211#ifndef SYS_mprotect_key
206# define SYS_mprotect_key 329 212# define SYS_mprotect_key 329
207#endif 213#endif
214
208#ifndef SYS_pkey_alloc 215#ifndef SYS_pkey_alloc
209# define SYS_pkey_alloc 330 216# define SYS_pkey_alloc 330
210# define SYS_pkey_free 331 217# define SYS_pkey_free 331
211#endif 218#endif
212#define REG_IP_IDX REG_RIP 219
213#define si_pkey_offset 0x20 220#define REG_IP_IDX REG_RIP
221#define si_pkey_offset 0x20
214 222
215#endif 223#endif
216 224
@@ -225,8 +233,14 @@ void dump_mem(void *dumpme, int len_bytes)
225 } 233 }
226} 234}
227 235
228#define SEGV_BNDERR 3 /* failed address bound checks */ 236/* Failed address bound checks: */
229#define SEGV_PKUERR 4 237#ifndef SEGV_BNDERR
238# define SEGV_BNDERR 3
239#endif
240
241#ifndef SEGV_PKUERR
242# define SEGV_PKUERR 4
243#endif
230 244
231static char *si_code_str(int si_code) 245static char *si_code_str(int si_code)
232{ 246{
@@ -289,13 +303,6 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
289 dump_mem(pkru_ptr - 128, 256); 303 dump_mem(pkru_ptr - 128, 256);
290 pkey_assert(*pkru_ptr); 304 pkey_assert(*pkru_ptr);
291 305
292 si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset);
293 dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr);
294 dump_mem(si_pkey_ptr - 8, 24);
295 siginfo_pkey = *si_pkey_ptr;
296 pkey_assert(siginfo_pkey < NR_PKEYS);
297 last_si_pkey = siginfo_pkey;
298
299 if ((si->si_code == SEGV_MAPERR) || 306 if ((si->si_code == SEGV_MAPERR) ||
300 (si->si_code == SEGV_ACCERR) || 307 (si->si_code == SEGV_ACCERR) ||
301 (si->si_code == SEGV_BNDERR)) { 308 (si->si_code == SEGV_BNDERR)) {
@@ -303,6 +310,13 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
303 exit(4); 310 exit(4);
304 } 311 }
305 312
313 si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset);
314 dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr);
315 dump_mem((u8 *)si_pkey_ptr - 8, 24);
316 siginfo_pkey = *si_pkey_ptr;
317 pkey_assert(siginfo_pkey < NR_PKEYS);
318 last_si_pkey = siginfo_pkey;
319
306 dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr); 320 dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr);
307 /* need __rdpkru() version so we do not do shadow_pkru checking */ 321 /* need __rdpkru() version so we do not do shadow_pkru checking */
308 dprintf1("signal pkru from pkru: %08x\n", __rdpkru()); 322 dprintf1("signal pkru from pkru: %08x\n", __rdpkru());
@@ -311,22 +325,6 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
311 dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n"); 325 dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n");
312 pkru_faults++; 326 pkru_faults++;
313 dprintf1("<<<<==================================================\n"); 327 dprintf1("<<<<==================================================\n");
314 return;
315 if (trapno == 14) {
316 fprintf(stderr,
317 "ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n",
318 trapno, ip);
319 fprintf(stderr, "si_addr %p\n", si->si_addr);
320 fprintf(stderr, "REG_ERR: %lx\n",
321 (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
322 exit(1);
323 } else {
324 fprintf(stderr, "unexpected trap %d! at 0x%lx\n", trapno, ip);
325 fprintf(stderr, "si_addr %p\n", si->si_addr);
326 fprintf(stderr, "REG_ERR: %lx\n",
327 (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
328 exit(2);
329 }
330 dprint_in_signal = 0; 328 dprint_in_signal = 0;
331} 329}
332 330
@@ -393,10 +391,15 @@ pid_t fork_lazy_child(void)
393 return forkret; 391 return forkret;
394} 392}
395 393
396#define PKEY_DISABLE_ACCESS 0x1 394#ifndef PKEY_DISABLE_ACCESS
397#define PKEY_DISABLE_WRITE 0x2 395# define PKEY_DISABLE_ACCESS 0x1
396#endif
397
398#ifndef PKEY_DISABLE_WRITE
399# define PKEY_DISABLE_WRITE 0x2
400#endif
398 401
399u32 pkey_get(int pkey, unsigned long flags) 402static u32 hw_pkey_get(int pkey, unsigned long flags)
400{ 403{
401 u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE); 404 u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE);
402 u32 pkru = __rdpkru(); 405 u32 pkru = __rdpkru();
@@ -418,7 +421,7 @@ u32 pkey_get(int pkey, unsigned long flags)
418 return masked_pkru; 421 return masked_pkru;
419} 422}
420 423
421int pkey_set(int pkey, unsigned long rights, unsigned long flags) 424static int hw_pkey_set(int pkey, unsigned long rights, unsigned long flags)
422{ 425{
423 u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE); 426 u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE);
424 u32 old_pkru = __rdpkru(); 427 u32 old_pkru = __rdpkru();
@@ -452,15 +455,15 @@ void pkey_disable_set(int pkey, int flags)
452 pkey, flags); 455 pkey, flags);
453 pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)); 456 pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
454 457
455 pkey_rights = pkey_get(pkey, syscall_flags); 458 pkey_rights = hw_pkey_get(pkey, syscall_flags);
456 459
457 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, 460 dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__,
458 pkey, pkey, pkey_rights); 461 pkey, pkey, pkey_rights);
459 pkey_assert(pkey_rights >= 0); 462 pkey_assert(pkey_rights >= 0);
460 463
461 pkey_rights |= flags; 464 pkey_rights |= flags;
462 465
463 ret = pkey_set(pkey, pkey_rights, syscall_flags); 466 ret = hw_pkey_set(pkey, pkey_rights, syscall_flags);
464 assert(!ret); 467 assert(!ret);
465 /*pkru and flags have the same format */ 468 /*pkru and flags have the same format */
466 shadow_pkru |= flags << (pkey * 2); 469 shadow_pkru |= flags << (pkey * 2);
@@ -468,8 +471,8 @@ void pkey_disable_set(int pkey, int flags)
468 471
469 pkey_assert(ret >= 0); 472 pkey_assert(ret >= 0);
470 473
471 pkey_rights = pkey_get(pkey, syscall_flags); 474 pkey_rights = hw_pkey_get(pkey, syscall_flags);
472 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, 475 dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__,
473 pkey, pkey, pkey_rights); 476 pkey, pkey, pkey_rights);
474 477
475 dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru()); 478 dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru());
@@ -483,24 +486,24 @@ void pkey_disable_clear(int pkey, int flags)
483{ 486{
484 unsigned long syscall_flags = 0; 487 unsigned long syscall_flags = 0;
485 int ret; 488 int ret;
486 int pkey_rights = pkey_get(pkey, syscall_flags); 489 int pkey_rights = hw_pkey_get(pkey, syscall_flags);
487 u32 orig_pkru = rdpkru(); 490 u32 orig_pkru = rdpkru();
488 491
489 pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)); 492 pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
490 493
491 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, 494 dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__,
492 pkey, pkey, pkey_rights); 495 pkey, pkey, pkey_rights);
493 pkey_assert(pkey_rights >= 0); 496 pkey_assert(pkey_rights >= 0);
494 497
495 pkey_rights |= flags; 498 pkey_rights |= flags;
496 499
497 ret = pkey_set(pkey, pkey_rights, 0); 500 ret = hw_pkey_set(pkey, pkey_rights, 0);
498 /* pkru and flags have the same format */ 501 /* pkru and flags have the same format */
499 shadow_pkru &= ~(flags << (pkey * 2)); 502 shadow_pkru &= ~(flags << (pkey * 2));
500 pkey_assert(ret >= 0); 503 pkey_assert(ret >= 0);
501 504
502 pkey_rights = pkey_get(pkey, syscall_flags); 505 pkey_rights = hw_pkey_get(pkey, syscall_flags);
503 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, 506 dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__,
504 pkey, pkey, pkey_rights); 507 pkey, pkey, pkey_rights);
505 508
506 dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru()); 509 dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru());
@@ -674,10 +677,12 @@ int mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
674struct pkey_malloc_record { 677struct pkey_malloc_record {
675 void *ptr; 678 void *ptr;
676 long size; 679 long size;
680 int prot;
677}; 681};
678struct pkey_malloc_record *pkey_malloc_records; 682struct pkey_malloc_record *pkey_malloc_records;
683struct pkey_malloc_record *pkey_last_malloc_record;
679long nr_pkey_malloc_records; 684long nr_pkey_malloc_records;
680void record_pkey_malloc(void *ptr, long size) 685void record_pkey_malloc(void *ptr, long size, int prot)
681{ 686{
682 long i; 687 long i;
683 struct pkey_malloc_record *rec = NULL; 688 struct pkey_malloc_record *rec = NULL;
@@ -709,6 +714,8 @@ void record_pkey_malloc(void *ptr, long size)
709 (int)(rec - pkey_malloc_records), rec, ptr, size); 714 (int)(rec - pkey_malloc_records), rec, ptr, size);
710 rec->ptr = ptr; 715 rec->ptr = ptr;
711 rec->size = size; 716 rec->size = size;
717 rec->prot = prot;
718 pkey_last_malloc_record = rec;
712 nr_pkey_malloc_records++; 719 nr_pkey_malloc_records++;
713} 720}
714 721
@@ -753,7 +760,7 @@ void *malloc_pkey_with_mprotect(long size, int prot, u16 pkey)
753 pkey_assert(ptr != (void *)-1); 760 pkey_assert(ptr != (void *)-1);
754 ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey); 761 ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey);
755 pkey_assert(!ret); 762 pkey_assert(!ret);
756 record_pkey_malloc(ptr, size); 763 record_pkey_malloc(ptr, size, prot);
757 rdpkru(); 764 rdpkru();
758 765
759 dprintf1("%s() for pkey %d @ %p\n", __func__, pkey, ptr); 766 dprintf1("%s() for pkey %d @ %p\n", __func__, pkey, ptr);
@@ -774,7 +781,7 @@ void *malloc_pkey_anon_huge(long size, int prot, u16 pkey)
774 size = ALIGN_UP(size, HPAGE_SIZE * 2); 781 size = ALIGN_UP(size, HPAGE_SIZE * 2);
775 ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 782 ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
776 pkey_assert(ptr != (void *)-1); 783 pkey_assert(ptr != (void *)-1);
777 record_pkey_malloc(ptr, size); 784 record_pkey_malloc(ptr, size, prot);
778 mprotect_pkey(ptr, size, prot, pkey); 785 mprotect_pkey(ptr, size, prot, pkey);
779 786
780 dprintf1("unaligned ptr: %p\n", ptr); 787 dprintf1("unaligned ptr: %p\n", ptr);
@@ -847,7 +854,7 @@ void *malloc_pkey_hugetlb(long size, int prot, u16 pkey)
847 pkey_assert(ptr != (void *)-1); 854 pkey_assert(ptr != (void *)-1);
848 mprotect_pkey(ptr, size, prot, pkey); 855 mprotect_pkey(ptr, size, prot, pkey);
849 856
850 record_pkey_malloc(ptr, size); 857 record_pkey_malloc(ptr, size, prot);
851 858
852 dprintf1("mmap()'d hugetlbfs for pkey %d @ %p\n", pkey, ptr); 859 dprintf1("mmap()'d hugetlbfs for pkey %d @ %p\n", pkey, ptr);
853 return ptr; 860 return ptr;
@@ -869,7 +876,7 @@ void *malloc_pkey_mmap_dax(long size, int prot, u16 pkey)
869 876
870 mprotect_pkey(ptr, size, prot, pkey); 877 mprotect_pkey(ptr, size, prot, pkey);
871 878
872 record_pkey_malloc(ptr, size); 879 record_pkey_malloc(ptr, size, prot);
873 880
874 dprintf1("mmap()'d for pkey %d @ %p\n", pkey, ptr); 881 dprintf1("mmap()'d for pkey %d @ %p\n", pkey, ptr);
875 close(fd); 882 close(fd);
@@ -918,13 +925,21 @@ void *malloc_pkey(long size, int prot, u16 pkey)
918} 925}
919 926
920int last_pkru_faults; 927int last_pkru_faults;
928#define UNKNOWN_PKEY -2
921void expected_pk_fault(int pkey) 929void expected_pk_fault(int pkey)
922{ 930{
923 dprintf2("%s(): last_pkru_faults: %d pkru_faults: %d\n", 931 dprintf2("%s(): last_pkru_faults: %d pkru_faults: %d\n",
924 __func__, last_pkru_faults, pkru_faults); 932 __func__, last_pkru_faults, pkru_faults);
925 dprintf2("%s(%d): last_si_pkey: %d\n", __func__, pkey, last_si_pkey); 933 dprintf2("%s(%d): last_si_pkey: %d\n", __func__, pkey, last_si_pkey);
926 pkey_assert(last_pkru_faults + 1 == pkru_faults); 934 pkey_assert(last_pkru_faults + 1 == pkru_faults);
927 pkey_assert(last_si_pkey == pkey); 935
936 /*
937 * For exec-only memory, we do not know the pkey in
938 * advance, so skip this check.
939 */
940 if (pkey != UNKNOWN_PKEY)
941 pkey_assert(last_si_pkey == pkey);
942
928 /* 943 /*
929 * The signal handler shold have cleared out PKRU to let the 944 * The signal handler shold have cleared out PKRU to let the
930 * test program continue. We now have to restore it. 945 * test program continue. We now have to restore it.
@@ -939,10 +954,11 @@ void expected_pk_fault(int pkey)
939 last_si_pkey = -1; 954 last_si_pkey = -1;
940} 955}
941 956
942void do_not_expect_pk_fault(void) 957#define do_not_expect_pk_fault(msg) do { \
943{ 958 if (last_pkru_faults != pkru_faults) \
944 pkey_assert(last_pkru_faults == pkru_faults); 959 dprintf0("unexpected PK fault: %s\n", msg); \
945} 960 pkey_assert(last_pkru_faults == pkru_faults); \
961} while (0)
946 962
947int test_fds[10] = { -1 }; 963int test_fds[10] = { -1 };
948int nr_test_fds; 964int nr_test_fds;
@@ -1151,12 +1167,15 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
1151 pkey_assert(i < NR_PKEYS*2); 1167 pkey_assert(i < NR_PKEYS*2);
1152 1168
1153 /* 1169 /*
1154 * There are 16 pkeys supported in hardware. One is taken 1170 * There are 16 pkeys supported in hardware. Three are
1155 * up for the default (0) and another can be taken up by 1171 * allocated by the time we get here:
1156 * an execute-only mapping. Ensure that we can allocate 1172 * 1. The default key (0)
1157 * at least 14 (16-2). 1173 * 2. One possibly consumed by an execute-only mapping.
1174 * 3. One allocated by the test code and passed in via
1175 * 'pkey' to this function.
1176 * Ensure that we can allocate at least another 13 (16-3).
1158 */ 1177 */
1159 pkey_assert(i >= NR_PKEYS-2); 1178 pkey_assert(i >= NR_PKEYS-3);
1160 1179
1161 for (i = 0; i < nr_allocated_pkeys; i++) { 1180 for (i = 0; i < nr_allocated_pkeys; i++) {
1162 err = sys_pkey_free(allocated_pkeys[i]); 1181 err = sys_pkey_free(allocated_pkeys[i]);
@@ -1165,6 +1184,35 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
1165 } 1184 }
1166} 1185}
1167 1186
1187/*
1188 * pkey 0 is special. It is allocated by default, so you do not
1189 * have to call pkey_alloc() to use it first. Make sure that it
1190 * is usable.
1191 */
1192void test_mprotect_with_pkey_0(int *ptr, u16 pkey)
1193{
1194 long size;
1195 int prot;
1196
1197 assert(pkey_last_malloc_record);
1198 size = pkey_last_malloc_record->size;
1199 /*
1200 * This is a bit of a hack. But mprotect() requires
1201 * huge-page-aligned sizes when operating on hugetlbfs.
1202 * So, make sure that we use something that's a multiple
1203 * of a huge page when we can.
1204 */
1205 if (size >= HPAGE_SIZE)
1206 size = HPAGE_SIZE;
1207 prot = pkey_last_malloc_record->prot;
1208
1209 /* Use pkey 0 */
1210 mprotect_pkey(ptr, size, prot, 0);
1211
1212 /* Make sure that we can set it back to the original pkey. */
1213 mprotect_pkey(ptr, size, prot, pkey);
1214}
1215
1168void test_ptrace_of_child(int *ptr, u16 pkey) 1216void test_ptrace_of_child(int *ptr, u16 pkey)
1169{ 1217{
1170 __attribute__((__unused__)) int peek_result; 1218 __attribute__((__unused__)) int peek_result;
@@ -1228,7 +1276,7 @@ void test_ptrace_of_child(int *ptr, u16 pkey)
1228 pkey_assert(ret != -1); 1276 pkey_assert(ret != -1);
1229 /* Now access from the current task, and expect NO exception: */ 1277 /* Now access from the current task, and expect NO exception: */
1230 peek_result = read_ptr(plain_ptr); 1278 peek_result = read_ptr(plain_ptr);
1231 do_not_expect_pk_fault(); 1279 do_not_expect_pk_fault("read plain pointer after ptrace");
1232 1280
1233 ret = ptrace(PTRACE_DETACH, child_pid, ignored, 0); 1281 ret = ptrace(PTRACE_DETACH, child_pid, ignored, 0);
1234 pkey_assert(ret != -1); 1282 pkey_assert(ret != -1);
@@ -1241,12 +1289,9 @@ void test_ptrace_of_child(int *ptr, u16 pkey)
1241 free(plain_ptr_unaligned); 1289 free(plain_ptr_unaligned);
1242} 1290}
1243 1291
1244void test_executing_on_unreadable_memory(int *ptr, u16 pkey) 1292void *get_pointer_to_instructions(void)
1245{ 1293{
1246 void *p1; 1294 void *p1;
1247 int scratch;
1248 int ptr_contents;
1249 int ret;
1250 1295
1251 p1 = ALIGN_PTR_UP(&lots_o_noops_around_write, PAGE_SIZE); 1296 p1 = ALIGN_PTR_UP(&lots_o_noops_around_write, PAGE_SIZE);
1252 dprintf3("&lots_o_noops: %p\n", &lots_o_noops_around_write); 1297 dprintf3("&lots_o_noops: %p\n", &lots_o_noops_around_write);
@@ -1256,7 +1301,23 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
1256 /* Point 'p1' at the *second* page of the function: */ 1301 /* Point 'p1' at the *second* page of the function: */
1257 p1 += PAGE_SIZE; 1302 p1 += PAGE_SIZE;
1258 1303
1304 /*
1305 * Try to ensure we fault this in on next touch to ensure
1306 * we get an instruction fault as opposed to a data one
1307 */
1259 madvise(p1, PAGE_SIZE, MADV_DONTNEED); 1308 madvise(p1, PAGE_SIZE, MADV_DONTNEED);
1309
1310 return p1;
1311}
1312
1313void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
1314{
1315 void *p1;
1316 int scratch;
1317 int ptr_contents;
1318 int ret;
1319
1320 p1 = get_pointer_to_instructions();
1260 lots_o_noops_around_write(&scratch); 1321 lots_o_noops_around_write(&scratch);
1261 ptr_contents = read_ptr(p1); 1322 ptr_contents = read_ptr(p1);
1262 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); 1323 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
@@ -1272,12 +1333,55 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
1272 */ 1333 */
1273 madvise(p1, PAGE_SIZE, MADV_DONTNEED); 1334 madvise(p1, PAGE_SIZE, MADV_DONTNEED);
1274 lots_o_noops_around_write(&scratch); 1335 lots_o_noops_around_write(&scratch);
1275 do_not_expect_pk_fault(); 1336 do_not_expect_pk_fault("executing on PROT_EXEC memory");
1276 ptr_contents = read_ptr(p1); 1337 ptr_contents = read_ptr(p1);
1277 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); 1338 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
1278 expected_pk_fault(pkey); 1339 expected_pk_fault(pkey);
1279} 1340}
1280 1341
1342void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
1343{
1344 void *p1;
1345 int scratch;
1346 int ptr_contents;
1347 int ret;
1348
1349 dprintf1("%s() start\n", __func__);
1350
1351 p1 = get_pointer_to_instructions();
1352 lots_o_noops_around_write(&scratch);
1353 ptr_contents = read_ptr(p1);
1354 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
1355
1356 /* Use a *normal* mprotect(), not mprotect_pkey(): */
1357 ret = mprotect(p1, PAGE_SIZE, PROT_EXEC);
1358 pkey_assert(!ret);
1359
1360 dprintf2("pkru: %x\n", rdpkru());
1361
1362 /* Make sure this is an *instruction* fault */
1363 madvise(p1, PAGE_SIZE, MADV_DONTNEED);
1364 lots_o_noops_around_write(&scratch);
1365 do_not_expect_pk_fault("executing on PROT_EXEC memory");
1366 ptr_contents = read_ptr(p1);
1367 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
1368 expected_pk_fault(UNKNOWN_PKEY);
1369
1370 /*
1371 * Put the memory back to non-PROT_EXEC. Should clear the
1372 * exec-only pkey off the VMA and allow it to be readable
1373 * again. Go to PROT_NONE first to check for a kernel bug
1374 * that did not clear the pkey when doing PROT_NONE.
1375 */
1376 ret = mprotect(p1, PAGE_SIZE, PROT_NONE);
1377 pkey_assert(!ret);
1378
1379 ret = mprotect(p1, PAGE_SIZE, PROT_READ|PROT_EXEC);
1380 pkey_assert(!ret);
1381 ptr_contents = read_ptr(p1);
1382 do_not_expect_pk_fault("plain read on recently PROT_EXEC area");
1383}
1384
1281void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey) 1385void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)
1282{ 1386{
1283 int size = PAGE_SIZE; 1387 int size = PAGE_SIZE;
@@ -1302,6 +1406,8 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = {
1302 test_kernel_gup_of_access_disabled_region, 1406 test_kernel_gup_of_access_disabled_region,
1303 test_kernel_gup_write_to_write_disabled_region, 1407 test_kernel_gup_write_to_write_disabled_region,
1304 test_executing_on_unreadable_memory, 1408 test_executing_on_unreadable_memory,
1409 test_implicit_mprotect_exec_only_memory,
1410 test_mprotect_with_pkey_0,
1305 test_ptrace_of_child, 1411 test_ptrace_of_child,
1306 test_pkey_syscalls_on_non_allocated_pkey, 1412 test_pkey_syscalls_on_non_allocated_pkey,
1307 test_pkey_syscalls_bad_args, 1413 test_pkey_syscalls_bad_args,
diff --git a/tools/testing/selftests/x86/test_syscall_vdso.c b/tools/testing/selftests/x86/test_syscall_vdso.c
index 40370354d4c1..c9c3281077bc 100644
--- a/tools/testing/selftests/x86/test_syscall_vdso.c
+++ b/tools/testing/selftests/x86/test_syscall_vdso.c
@@ -100,12 +100,19 @@ asm (
100 " shl $32, %r8\n" 100 " shl $32, %r8\n"
101 " orq $0x7f7f7f7f, %r8\n" 101 " orq $0x7f7f7f7f, %r8\n"
102 " movq %r8, %r9\n" 102 " movq %r8, %r9\n"
103 " movq %r8, %r10\n" 103 " incq %r9\n"
104 " movq %r8, %r11\n" 104 " movq %r9, %r10\n"
105 " movq %r8, %r12\n" 105 " incq %r10\n"
106 " movq %r8, %r13\n" 106 " movq %r10, %r11\n"
107 " movq %r8, %r14\n" 107 " incq %r11\n"
108 " movq %r8, %r15\n" 108 " movq %r11, %r12\n"
109 " incq %r12\n"
110 " movq %r12, %r13\n"
111 " incq %r13\n"
112 " movq %r13, %r14\n"
113 " incq %r14\n"
114 " movq %r14, %r15\n"
115 " incq %r15\n"
109 " ret\n" 116 " ret\n"
110 " .code32\n" 117 " .code32\n"
111 " .popsection\n" 118 " .popsection\n"
@@ -128,12 +135,13 @@ int check_regs64(void)
128 int err = 0; 135 int err = 0;
129 int num = 8; 136 int num = 8;
130 uint64_t *r64 = &regs64.r8; 137 uint64_t *r64 = &regs64.r8;
138 uint64_t expected = 0x7f7f7f7f7f7f7f7fULL;
131 139
132 if (!kernel_is_64bit) 140 if (!kernel_is_64bit)
133 return 0; 141 return 0;
134 142
135 do { 143 do {
136 if (*r64 == 0x7f7f7f7f7f7f7f7fULL) 144 if (*r64 == expected++)
137 continue; /* register did not change */ 145 continue; /* register did not change */
138 if (syscall_addr != (long)&int80) { 146 if (syscall_addr != (long)&int80) {
139 /* 147 /*
@@ -147,18 +155,17 @@ int check_regs64(void)
147 continue; 155 continue;
148 } 156 }
149 } else { 157 } else {
150 /* INT80 syscall entrypoint can be used by 158 /*
159 * INT80 syscall entrypoint can be used by
151 * 64-bit programs too, unlike SYSCALL/SYSENTER. 160 * 64-bit programs too, unlike SYSCALL/SYSENTER.
152 * Therefore it must preserve R12+ 161 * Therefore it must preserve R12+
153 * (they are callee-saved registers in 64-bit C ABI). 162 * (they are callee-saved registers in 64-bit C ABI).
154 * 163 *
155 * This was probably historically not intended, 164 * Starting in Linux 4.17 (and any kernel that
156 * but R8..11 are clobbered (cleared to 0). 165 * backports the change), R8..11 are preserved.
157 * IOW: they are the only registers which aren't 166 * Historically (and probably unintentionally), they
158 * preserved across INT80 syscall. 167 * were clobbered or zeroed.
159 */ 168 */
160 if (*r64 == 0 && num <= 11)
161 continue;
162 } 169 }
163 printf("[FAIL]\tR%d has changed:%016llx\n", num, *r64); 170 printf("[FAIL]\tR%d has changed:%016llx\n", num, *r64);
164 err++; 171 err++;
diff --git a/tools/thermal/tmon/sysfs.c b/tools/thermal/tmon/sysfs.c
index 1c12536f2081..18f523557983 100644
--- a/tools/thermal/tmon/sysfs.c
+++ b/tools/thermal/tmon/sysfs.c
@@ -486,6 +486,7 @@ int zone_instance_to_index(int zone_inst)
486int update_thermal_data() 486int update_thermal_data()
487{ 487{
488 int i; 488 int i;
489 int next_thermal_record = cur_thermal_record + 1;
489 char tz_name[256]; 490 char tz_name[256];
490 static unsigned long samples; 491 static unsigned long samples;
491 492
@@ -495,9 +496,9 @@ int update_thermal_data()
495 } 496 }
496 497
497 /* circular buffer for keeping historic data */ 498 /* circular buffer for keeping historic data */
498 if (cur_thermal_record >= NR_THERMAL_RECORDS) 499 if (next_thermal_record >= NR_THERMAL_RECORDS)
499 cur_thermal_record = 0; 500 next_thermal_record = 0;
500 gettimeofday(&trec[cur_thermal_record].tv, NULL); 501 gettimeofday(&trec[next_thermal_record].tv, NULL);
501 if (tmon_log) { 502 if (tmon_log) {
502 fprintf(tmon_log, "%lu ", ++samples); 503 fprintf(tmon_log, "%lu ", ++samples);
503 fprintf(tmon_log, "%3.1f ", p_param.t_target); 504 fprintf(tmon_log, "%3.1f ", p_param.t_target);
@@ -507,11 +508,12 @@ int update_thermal_data()
507 snprintf(tz_name, 256, "%s/%s%d", THERMAL_SYSFS, TZONE, 508 snprintf(tz_name, 256, "%s/%s%d", THERMAL_SYSFS, TZONE,
508 ptdata.tzi[i].instance); 509 ptdata.tzi[i].instance);
509 sysfs_get_ulong(tz_name, "temp", 510 sysfs_get_ulong(tz_name, "temp",
510 &trec[cur_thermal_record].temp[i]); 511 &trec[next_thermal_record].temp[i]);
511 if (tmon_log) 512 if (tmon_log)
512 fprintf(tmon_log, "%lu ", 513 fprintf(tmon_log, "%lu ",
513 trec[cur_thermal_record].temp[i]/1000); 514 trec[next_thermal_record].temp[i] / 1000);
514 } 515 }
516 cur_thermal_record = next_thermal_record;
515 for (i = 0; i < ptdata.nr_cooling_dev; i++) { 517 for (i = 0; i < ptdata.nr_cooling_dev; i++) {
516 char cdev_name[256]; 518 char cdev_name[256];
517 unsigned long val; 519 unsigned long val;
diff --git a/tools/thermal/tmon/tmon.c b/tools/thermal/tmon/tmon.c
index 9aa19652e8e8..b43138f8b862 100644
--- a/tools/thermal/tmon/tmon.c
+++ b/tools/thermal/tmon/tmon.c
@@ -336,7 +336,6 @@ int main(int argc, char **argv)
336 show_data_w(); 336 show_data_w();
337 show_cooling_device(); 337 show_cooling_device();
338 } 338 }
339 cur_thermal_record++;
340 time_elapsed += ticktime; 339 time_elapsed += ticktime;
341 controller_handler(trec[0].temp[target_tz_index] / 1000, 340 controller_handler(trec[0].temp[target_tz_index] / 1000,
342 &yk); 341 &yk);
diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c
index 001bb8e8f668..bb424638d75b 100644
--- a/tools/usb/usbip/libsrc/usbip_common.c
+++ b/tools/usb/usbip/libsrc/usbip_common.c
@@ -66,6 +66,29 @@ const char *usbip_speed_string(int num)
66 return "Unknown Speed"; 66 return "Unknown Speed";
67} 67}
68 68
69struct op_common_status_string {
70 int num;
71 char *desc;
72};
73
74static struct op_common_status_string op_common_status_strings[] = {
75 { ST_OK, "Request Completed Successfully" },
76 { ST_NA, "Request Failed" },
77 { ST_DEV_BUSY, "Device busy (exported)" },
78 { ST_DEV_ERR, "Device in error state" },
79 { ST_NODEV, "Device not found" },
80 { ST_ERROR, "Unexpected response" },
81 { 0, NULL}
82};
83
84const char *usbip_op_common_status_string(int status)
85{
86 for (int i = 0; op_common_status_strings[i].desc != NULL; i++)
87 if (op_common_status_strings[i].num == status)
88 return op_common_status_strings[i].desc;
89
90 return "Unknown Op Common Status";
91}
69 92
70#define DBG_UDEV_INTEGER(name)\ 93#define DBG_UDEV_INTEGER(name)\
71 dbg("%-20s = %x", to_string(name), (int) udev->name) 94 dbg("%-20s = %x", to_string(name), (int) udev->name)
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
index e45ec9d2fdbc..73a367a7fa10 100644
--- a/tools/usb/usbip/libsrc/usbip_common.h
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -43,6 +43,16 @@
43#define SYSFS_PATH_MAX 256 43#define SYSFS_PATH_MAX 256
44#define SYSFS_BUS_ID_SIZE 32 44#define SYSFS_BUS_ID_SIZE 32
45 45
46/* Defines for op_code status in server/client op_common PDUs */
47#define ST_OK 0x00
48#define ST_NA 0x01
49 /* Device requested for import is not available */
50#define ST_DEV_BUSY 0x02
51 /* Device requested for import is in error state */
52#define ST_DEV_ERR 0x03
53#define ST_NODEV 0x04
54#define ST_ERROR 0x05
55
46extern int usbip_use_syslog; 56extern int usbip_use_syslog;
47extern int usbip_use_stderr; 57extern int usbip_use_stderr;
48extern int usbip_use_debug ; 58extern int usbip_use_debug ;
@@ -130,6 +140,7 @@ int read_usb_interface(struct usbip_usb_device *udev, int i,
130 140
131const char *usbip_speed_string(int num); 141const char *usbip_speed_string(int num);
132const char *usbip_status_string(int32_t status); 142const char *usbip_status_string(int32_t status);
143const char *usbip_op_common_status_string(int status);
133 144
134int usbip_names_init(char *); 145int usbip_names_init(char *);
135void usbip_names_free(void); 146void usbip_names_free(void);
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c
index 6ff7b601f854..dc93fadbee96 100644
--- a/tools/usb/usbip/libsrc/usbip_host_common.c
+++ b/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -234,14 +234,17 @@ int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
234 switch (edev->status) { 234 switch (edev->status) {
235 case SDEV_ST_ERROR: 235 case SDEV_ST_ERROR:
236 dbg("status SDEV_ST_ERROR"); 236 dbg("status SDEV_ST_ERROR");
237 ret = ST_DEV_ERR;
237 break; 238 break;
238 case SDEV_ST_USED: 239 case SDEV_ST_USED:
239 dbg("status SDEV_ST_USED"); 240 dbg("status SDEV_ST_USED");
241 ret = ST_DEV_BUSY;
240 break; 242 break;
241 default: 243 default:
242 dbg("status unknown: 0x%x", edev->status); 244 dbg("status unknown: 0x%x", edev->status);
245 ret = -1;
243 } 246 }
244 return -1; 247 return ret;
245 } 248 }
246 249
247 /* only the first interface is true */ 250 /* only the first interface is true */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index 7f07b2d50f59..ba88728483ff 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -135,6 +135,7 @@ static int query_import_device(int sockfd, char *busid)
135 struct op_import_request request; 135 struct op_import_request request;
136 struct op_import_reply reply; 136 struct op_import_reply reply;
137 uint16_t code = OP_REP_IMPORT; 137 uint16_t code = OP_REP_IMPORT;
138 int status;
138 139
139 memset(&request, 0, sizeof(request)); 140 memset(&request, 0, sizeof(request));
140 memset(&reply, 0, sizeof(reply)); 141 memset(&reply, 0, sizeof(reply));
@@ -157,9 +158,10 @@ static int query_import_device(int sockfd, char *busid)
157 } 158 }
158 159
159 /* receive a reply */ 160 /* receive a reply */
160 rc = usbip_net_recv_op_common(sockfd, &code); 161 rc = usbip_net_recv_op_common(sockfd, &code, &status);
161 if (rc < 0) { 162 if (rc < 0) {
162 err("recv op_common"); 163 err("Attach Request for %s failed - %s\n",
164 busid, usbip_op_common_status_string(status));
163 return -1; 165 return -1;
164 } 166 }
165 167
@@ -194,10 +196,8 @@ static int attach_device(char *host, char *busid)
194 } 196 }
195 197
196 rhport = query_import_device(sockfd, busid); 198 rhport = query_import_device(sockfd, busid);
197 if (rhport < 0) { 199 if (rhport < 0)
198 err("query");
199 return -1; 200 return -1;
200 }
201 201
202 close(sockfd); 202 close(sockfd);
203 203
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index d65a9f444174..8d4ccf4b9480 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -62,6 +62,7 @@ static int get_exported_devices(char *host, int sockfd)
62 struct usbip_usb_interface uintf; 62 struct usbip_usb_interface uintf;
63 unsigned int i; 63 unsigned int i;
64 int rc, j; 64 int rc, j;
65 int status;
65 66
66 rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); 67 rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
67 if (rc < 0) { 68 if (rc < 0) {
@@ -69,9 +70,10 @@ static int get_exported_devices(char *host, int sockfd)
69 return -1; 70 return -1;
70 } 71 }
71 72
72 rc = usbip_net_recv_op_common(sockfd, &code); 73 rc = usbip_net_recv_op_common(sockfd, &code, &status);
73 if (rc < 0) { 74 if (rc < 0) {
74 dbg("usbip_net_recv_op_common failed"); 75 err("Exported Device List Request failed - %s\n",
76 usbip_op_common_status_string(status));
75 return -1; 77 return -1;
76 } 78 }
77 79
diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c
index b4c37e76a6e0..8ffcd47d9638 100644
--- a/tools/usb/usbip/src/usbip_network.c
+++ b/tools/usb/usbip/src/usbip_network.c
@@ -163,7 +163,7 @@ int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
163 return 0; 163 return 0;
164} 164}
165 165
166int usbip_net_recv_op_common(int sockfd, uint16_t *code) 166int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status)
167{ 167{
168 struct op_common op_common; 168 struct op_common op_common;
169 int rc; 169 int rc;
@@ -179,8 +179,8 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code)
179 PACK_OP_COMMON(0, &op_common); 179 PACK_OP_COMMON(0, &op_common);
180 180
181 if (op_common.version != USBIP_VERSION) { 181 if (op_common.version != USBIP_VERSION) {
182 dbg("version mismatch: %d %d", op_common.version, 182 err("USBIP Kernel and tool version mismatch: %d %d:",
183 USBIP_VERSION); 183 op_common.version, USBIP_VERSION);
184 goto err; 184 goto err;
185 } 185 }
186 186
@@ -191,10 +191,14 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code)
191 if (op_common.code != *code) { 191 if (op_common.code != *code) {
192 dbg("unexpected pdu %#0x for %#0x", op_common.code, 192 dbg("unexpected pdu %#0x for %#0x", op_common.code,
193 *code); 193 *code);
194 /* return error status */
195 *status = ST_ERROR;
194 goto err; 196 goto err;
195 } 197 }
196 } 198 }
197 199
200 *status = op_common.status;
201
198 if (op_common.status != ST_OK) { 202 if (op_common.status != ST_OK) {
199 dbg("request failed at peer: %d", op_common.status); 203 dbg("request failed at peer: %d", op_common.status);
200 goto err; 204 goto err;
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
index 7032687621d3..555215eae43e 100644
--- a/tools/usb/usbip/src/usbip_network.h
+++ b/tools/usb/usbip/src/usbip_network.h
@@ -27,9 +27,7 @@ struct op_common {
27#define OP_REPLY (0x00 << 8) 27#define OP_REPLY (0x00 << 8)
28 uint16_t code; 28 uint16_t code;
29 29
30 /* add more error code */ 30 /* status codes defined in usbip_common.h */
31#define ST_OK 0x00
32#define ST_NA 0x01
33 uint32_t status; /* op_code status (for reply) */ 31 uint32_t status; /* op_code status (for reply) */
34 32
35} __attribute__((packed)); 33} __attribute__((packed));
@@ -176,7 +174,7 @@ void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
176ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen); 174ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
177ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen); 175ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
178int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status); 176int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
179int usbip_net_recv_op_common(int sockfd, uint16_t *code); 177int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status);
180int usbip_net_set_reuseaddr(int sockfd); 178int usbip_net_set_reuseaddr(int sockfd);
181int usbip_net_set_nodelay(int sockfd); 179int usbip_net_set_nodelay(int sockfd);
182int usbip_net_set_keepalive(int sockfd); 180int usbip_net_set_keepalive(int sockfd);
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index c6dad2a13c80..32864c52942d 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -107,7 +107,7 @@ static int recv_request_import(int sockfd)
107 struct usbip_usb_device pdu_udev; 107 struct usbip_usb_device pdu_udev;
108 struct list_head *i; 108 struct list_head *i;
109 int found = 0; 109 int found = 0;
110 int error = 0; 110 int status = ST_OK;
111 int rc; 111 int rc;
112 112
113 memset(&req, 0, sizeof(req)); 113 memset(&req, 0, sizeof(req));
@@ -133,22 +133,21 @@ static int recv_request_import(int sockfd)
133 usbip_net_set_nodelay(sockfd); 133 usbip_net_set_nodelay(sockfd);
134 134
135 /* export device needs a TCP/IP socket descriptor */ 135 /* export device needs a TCP/IP socket descriptor */
136 rc = usbip_export_device(edev, sockfd); 136 status = usbip_export_device(edev, sockfd);
137 if (rc < 0) 137 if (status < 0)
138 error = 1; 138 status = ST_NA;
139 } else { 139 } else {
140 info("requested device not found: %s", req.busid); 140 info("requested device not found: %s", req.busid);
141 error = 1; 141 status = ST_NODEV;
142 } 142 }
143 143
144 rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, 144 rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, status);
145 (!error ? ST_OK : ST_NA));
146 if (rc < 0) { 145 if (rc < 0) {
147 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT); 146 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
148 return -1; 147 return -1;
149 } 148 }
150 149
151 if (error) { 150 if (status) {
152 dbg("import request busid %s: failed", req.busid); 151 dbg("import request busid %s: failed", req.busid);
153 return -1; 152 return -1;
154 } 153 }
@@ -176,10 +175,21 @@ static int send_reply_devlist(int connfd)
176 struct list_head *j; 175 struct list_head *j;
177 int rc, i; 176 int rc, i;
178 177
178 /*
179 * Exclude devices that are already exported to a client from
180 * the exportable device list to avoid:
181 * - import requests for devices that are exported only to
182 * fail the request.
183 * - revealing devices that are imported by a client to
184 * another client.
185 */
186
179 reply.ndev = 0; 187 reply.ndev = 0;
180 /* number of exported devices */ 188 /* number of exported devices */
181 list_for_each(j, &driver->edev_list) { 189 list_for_each(j, &driver->edev_list) {
182 reply.ndev += 1; 190 edev = list_entry(j, struct usbip_exported_device, node);
191 if (edev->status != SDEV_ST_USED)
192 reply.ndev += 1;
183 } 193 }
184 info("exportable devices: %d", reply.ndev); 194 info("exportable devices: %d", reply.ndev);
185 195
@@ -198,6 +208,9 @@ static int send_reply_devlist(int connfd)
198 208
199 list_for_each(j, &driver->edev_list) { 209 list_for_each(j, &driver->edev_list) {
200 edev = list_entry(j, struct usbip_exported_device, node); 210 edev = list_entry(j, struct usbip_exported_device, node);
211 if (edev->status == SDEV_ST_USED)
212 continue;
213
201 dump_usb_device(&edev->udev); 214 dump_usb_device(&edev->udev);
202 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); 215 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
203 usbip_net_pack_usb_device(1, &pdu_udev); 216 usbip_net_pack_usb_device(1, &pdu_udev);
@@ -251,8 +264,9 @@ static int recv_pdu(int connfd)
251{ 264{
252 uint16_t code = OP_UNSPEC; 265 uint16_t code = OP_UNSPEC;
253 int ret; 266 int ret;
267 int status;
254 268
255 ret = usbip_net_recv_op_common(connfd, &code); 269 ret = usbip_net_recv_op_common(connfd, &code, &status);
256 if (ret < 0) { 270 if (ret < 0) {
257 dbg("could not receive opcode: %#0x", code); 271 dbg("could not receive opcode: %#0x", code);
258 return -1; 272 return -1;
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c
index 477899c12c51..2d566fbd236b 100644
--- a/tools/virtio/ringtest/ptr_ring.c
+++ b/tools/virtio/ringtest/ptr_ring.c
@@ -17,6 +17,8 @@
17#define likely(x) (__builtin_expect(!!(x), 1)) 17#define likely(x) (__builtin_expect(!!(x), 1))
18#define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) 18#define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a))
19#define SIZE_MAX (~(size_t)0) 19#define SIZE_MAX (~(size_t)0)
20#define KMALLOC_MAX_SIZE SIZE_MAX
21#define BUG_ON(x) assert(x)
20 22
21typedef pthread_spinlock_t spinlock_t; 23typedef pthread_spinlock_t spinlock_t;
22 24
@@ -57,6 +59,9 @@ static void kfree(void *p)
57 free(p); 59 free(p);
58} 60}
59 61
62#define kvmalloc_array kmalloc_array
63#define kvfree kfree
64
60static void spin_lock_init(spinlock_t *lock) 65static void spin_lock_init(spinlock_t *lock)
61{ 66{
62 int r = pthread_spin_init(lock, 0); 67 int r = pthread_spin_init(lock, 0);