aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h6
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h2
-rw-r--r--tools/arch/x86/include/asm/disabled-features.h4
-rwxr-xr-xtools/hv/bondvf.sh232
-rw-r--r--tools/include/asm-generic/hugetlb_encode.h34
-rw-r--r--tools/include/linux/compiler-gcc.h9
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h14
-rw-r--r--tools/include/uapi/drm/drm.h22
-rw-r--r--tools/include/uapi/drm/i915_drm.h51
-rw-r--r--tools/include/uapi/linux/bpf.h78
-rw-r--r--tools/include/uapi/linux/kvm.h3
-rw-r--r--tools/include/uapi/linux/mman.h24
-rw-r--r--tools/include/uapi/linux/perf_event.h4
-rw-r--r--tools/lib/api/Makefile8
-rw-r--r--tools/lib/bpf/Makefile4
-rw-r--r--tools/lib/bpf/bpf.c32
-rw-r--r--tools/lib/bpf/bpf.h6
-rw-r--r--tools/lib/bpf/libbpf.c29
-rw-r--r--tools/lib/bpf/libbpf.h2
-rw-r--r--tools/objtool/Documentation/stack-validation.txt6
-rw-r--r--tools/objtool/arch/x86/decode.c17
-rw-r--r--tools/objtool/check.c43
-rw-r--r--tools/objtool/elf.c33
-rw-r--r--tools/pci/pcitest.c1
-rw-r--r--tools/perf/Documentation/intel-pt.txt2
-rw-r--r--tools/perf/Documentation/perf-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt5
-rw-r--r--tools/perf/Documentation/perf-report.txt1
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/MANIFEST87
-rw-r--r--tools/perf/arch/s390/util/Build1
-rw-r--r--tools/perf/arch/s390/util/sym-handling.c29
-rw-r--r--tools/perf/builtin-config.c2
-rw-r--r--tools/perf/builtin-kmem.c1
-rw-r--r--tools/perf/builtin-mem.c97
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-script.c15
-rw-r--r--tools/perf/builtin-stat.c4
-rw-r--r--tools/perf/builtin-trace.c39
-rw-r--r--tools/perf/perf.c14
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/frontend.json7
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json120
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pipeline.json7
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pmc.json7
-rw-r--r--tools/perf/tests/code-reading.c5
-rw-r--r--tools/perf/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/tests/sample-parsing.c6
-rw-r--r--tools/perf/ui/browsers/annotate.c3
-rw-r--r--tools/perf/ui/browsers/hists.c8
-rw-r--r--tools/perf/ui/progress.c9
-rw-r--r--tools/perf/ui/stdio/hist.c10
-rw-r--r--tools/perf/util/callchain.c84
-rw-r--r--tools/perf/util/callchain.h9
-rw-r--r--tools/perf/util/data.c13
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evsel.c26
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/hist.c4
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/machine.c96
-rw-r--r--tools/perf/util/parse-events.c24
-rw-r--r--tools/perf/util/session.c3
-rw-r--r--tools/perf/util/sort.c42
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/symbol-elf.c8
-rw-r--r--tools/perf/util/symbol.h4
-rw-r--r--tools/perf/util/syscalltbl.c35
-rw-r--r--tools/perf/util/syscalltbl.h3
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c105
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c2
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c2
-rw-r--r--tools/power/cpupower/Makefile2
-rw-r--r--tools/power/cpupower/utils/cpupower.c15
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c4
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h5
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c2
-rw-r--r--tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c4
-rw-r--r--tools/power/cpupower/utils/idle_monitor/mperf_monitor.c3
-rw-r--r--tools/power/cpupower/utils/idle_monitor/nhm_idle.c8
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c4
-rw-r--r--tools/power/pm-graph/Makefile19
-rwxr-xr-xtools/power/pm-graph/analyze_boot.py586
-rwxr-xr-xtools/power/pm-graph/analyze_suspend.py534
-rw-r--r--tools/power/pm-graph/bootgraph.861
-rw-r--r--tools/power/pm-graph/sleepgraph.848
-rw-r--r--tools/scripts/Makefile.include6
-rw-r--r--tools/testing/nvdimm/test/nfit.c7
-rw-r--r--tools/testing/selftests/Makefile18
-rw-r--r--tools/testing/selftests/bpf/Makefile4
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h9
-rw-r--r--tools/testing/selftests/bpf/bpf_util.h17
-rw-r--r--tools/testing/selftests/bpf/sockmap_parse_prog.c38
-rw-r--r--tools/testing/selftests/bpf/sockmap_verdict_prog.c68
-rw-r--r--tools/testing/selftests/bpf/test_align.c462
-rw-r--r--tools/testing/selftests/bpf/test_maps.c442
-rw-r--r--tools/testing/selftests/bpf/test_progs.c71
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c1010
-rw-r--r--tools/testing/selftests/bpf/test_xdp_redirect.c28
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_redirect.sh59
-rw-r--r--tools/testing/selftests/breakpoints/Makefile8
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test.c4
-rw-r--r--tools/testing/selftests/capabilities/test_execve.c193
-rw-r--r--tools/testing/selftests/capabilities/validate_cap.c24
-rwxr-xr-xtools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh14
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest51
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc2
-rw-r--r--tools/testing/selftests/futex/Makefile9
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi.c8
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c3
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c5
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c6
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_timeout.c5
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c3
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_wouldblock.c3
-rw-r--r--tools/testing/selftests/futex/include/logging.h20
-rw-r--r--tools/testing/selftests/intel_pstate/Makefile2
-rwxr-xr-xtools/testing/selftests/intel_pstate/run.sh11
-rw-r--r--tools/testing/selftests/kcmp/kcmp_test.c60
-rw-r--r--tools/testing/selftests/kselftest.h30
-rw-r--r--tools/testing/selftests/kselftest_harness.h39
-rw-r--r--tools/testing/selftests/lib.mk59
-rw-r--r--tools/testing/selftests/memfd/Makefile2
-rw-r--r--tools/testing/selftests/memfd/fuse_test.c2
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c372
-rwxr-xr-xtools/testing/selftests/memfd/run_tests.sh69
-rw-r--r--tools/testing/selftests/mqueue/Makefile4
-rw-r--r--tools/testing/selftests/net/.gitignore2
-rw-r--r--tools/testing/selftests/net/Makefile8
-rw-r--r--tools/testing/selftests/net/msg_zerocopy.c697
-rwxr-xr-xtools/testing/selftests/net/msg_zerocopy.sh112
-rwxr-xr-xtools/testing/selftests/net/netdevice.sh2
-rw-r--r--tools/testing/selftests/net/reuseaddr_conflict.c114
-rwxr-xr-xtools/testing/selftests/net/rtnetlink.sh272
-rw-r--r--tools/testing/selftests/networking/timestamping/.gitignore1
-rw-r--r--tools/testing/selftests/networking/timestamping/Makefile4
-rw-r--r--tools/testing/selftests/networking/timestamping/rxtimestamp.c389
-rw-r--r--tools/testing/selftests/nsfs/config3
-rw-r--r--tools/testing/selftests/powerpc/ptrace/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S2
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c12
-rw-r--r--tools/testing/selftests/pstore/.gitignore2
-rw-r--r--tools/testing/selftests/ptp/Makefile1
-rw-r--r--tools/testing/selftests/seccomp/Makefile18
-rw-r--r--tools/testing/selftests/seccomp/seccomp_benchmark.c99
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c630
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c57
-rw-r--r--tools/testing/selftests/splice/.gitignore1
-rw-r--r--tools/testing/selftests/splice/Makefile5
-rw-r--r--tools/testing/selftests/sync/Makefile24
-rw-r--r--tools/testing/selftests/sync/sync_test.c71
-rw-r--r--tools/testing/selftests/sync/synctest.h3
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/tests.json50
-rw-r--r--tools/testing/selftests/timers/Makefile23
-rw-r--r--tools/testing/selftests/timers/adjtick.c11
-rw-r--r--tools/testing/selftests/timers/alarmtimer-suspend.c11
-rw-r--r--tools/testing/selftests/timers/change_skew.c11
-rw-r--r--tools/testing/selftests/timers/clocksource-switch.c13
-rw-r--r--tools/testing/selftests/timers/inconsistency-check.c11
-rw-r--r--tools/testing/selftests/timers/leap-a-day.c28
-rw-r--r--tools/testing/selftests/timers/leapcrash.c13
-rw-r--r--tools/testing/selftests/timers/mqueue-lat.c11
-rw-r--r--tools/testing/selftests/timers/nanosleep.c11
-rw-r--r--tools/testing/selftests/timers/nsleep-lat.c11
-rw-r--r--tools/testing/selftests/timers/raw_skew.c12
-rw-r--r--tools/testing/selftests/timers/rtctest.c7
-rw-r--r--tools/testing/selftests/timers/set-2038.c11
-rw-r--r--tools/testing/selftests/timers/set-tai.c11
-rw-r--r--tools/testing/selftests/timers/set-timer-lat.c24
-rw-r--r--tools/testing/selftests/timers/set-tz.c11
-rw-r--r--tools/testing/selftests/timers/skew_consistency.c11
-rw-r--r--tools/testing/selftests/timers/threadtest.c12
-rw-r--r--tools/testing/selftests/timers/valid-adjtimex.c11
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c279
-rw-r--r--tools/testing/selftests/watchdog/Makefile7
-rw-r--r--tools/testing/selftests/watchdog/watchdog-test.c190
-rw-r--r--tools/testing/selftests/x86/Makefile2
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c3
-rw-r--r--tools/testing/selftests/x86/protection_keys.c13
181 files changed, 7230 insertions, 2272 deletions
diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h
index 69d09c39bbcd..cd7359e23d86 100644
--- a/tools/arch/s390/include/uapi/asm/kvm.h
+++ b/tools/arch/s390/include/uapi/asm/kvm.h
@@ -88,6 +88,12 @@ struct kvm_s390_io_adapter_req {
88/* kvm attributes for KVM_S390_VM_TOD */ 88/* kvm attributes for KVM_S390_VM_TOD */
89#define KVM_S390_VM_TOD_LOW 0 89#define KVM_S390_VM_TOD_LOW 0
90#define KVM_S390_VM_TOD_HIGH 1 90#define KVM_S390_VM_TOD_HIGH 1
91#define KVM_S390_VM_TOD_EXT 2
92
93struct kvm_s390_vm_tod_clock {
94 __u8 epoch_idx;
95 __u64 tod;
96};
91 97
92/* kvm attributes for KVM_S390_VM_CPU_MODEL */ 98/* kvm attributes for KVM_S390_VM_CPU_MODEL */
93/* processor related attributes are r/w */ 99/* processor related attributes are r/w */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 8ea315a11fe0..2519c6c801c9 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -196,6 +196,7 @@
196 196
197#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ 197#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
198#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ 198#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
199#define X86_FEATURE_SME ( 7*32+10) /* AMD Secure Memory Encryption */
199 200
200#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ 201#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
201#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ 202#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
@@ -287,6 +288,7 @@
287#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ 288#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
288#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ 289#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
289#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */ 290#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
291#define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */
290 292
291/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ 293/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
292#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/ 294#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
index 5dff775af7cd..c10c9128f54e 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -21,11 +21,13 @@
21# define DISABLE_K6_MTRR (1<<(X86_FEATURE_K6_MTRR & 31)) 21# define DISABLE_K6_MTRR (1<<(X86_FEATURE_K6_MTRR & 31))
22# define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31)) 22# define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31))
23# define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31)) 23# define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31))
24# define DISABLE_PCID 0
24#else 25#else
25# define DISABLE_VME 0 26# define DISABLE_VME 0
26# define DISABLE_K6_MTRR 0 27# define DISABLE_K6_MTRR 0
27# define DISABLE_CYRIX_ARR 0 28# define DISABLE_CYRIX_ARR 0
28# define DISABLE_CENTAUR_MCR 0 29# define DISABLE_CENTAUR_MCR 0
30# define DISABLE_PCID (1<<(X86_FEATURE_PCID & 31))
29#endif /* CONFIG_X86_64 */ 31#endif /* CONFIG_X86_64 */
30 32
31#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS 33#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
@@ -49,7 +51,7 @@
49#define DISABLED_MASK1 0 51#define DISABLED_MASK1 0
50#define DISABLED_MASK2 0 52#define DISABLED_MASK2 0
51#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR) 53#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR)
52#define DISABLED_MASK4 0 54#define DISABLED_MASK4 (DISABLE_PCID)
53#define DISABLED_MASK5 0 55#define DISABLED_MASK5 0
54#define DISABLED_MASK6 0 56#define DISABLED_MASK6 0
55#define DISABLED_MASK7 0 57#define DISABLED_MASK7 0
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh
deleted file mode 100755
index 89b25068cd98..000000000000
--- a/tools/hv/bondvf.sh
+++ /dev/null
@@ -1,232 +0,0 @@
1#!/bin/bash
2
3# This example script creates bonding network devices based on synthetic NIC
4# (the virtual network adapter usually provided by Hyper-V) and the matching
5# VF NIC (SRIOV virtual function). So the synthetic NIC and VF NIC can
6# function as one network device, and fail over to the synthetic NIC if VF is
7# down.
8#
9# Usage:
10# - After configured vSwitch and vNIC with SRIOV, start Linux virtual
11# machine (VM)
12# - Run this scripts on the VM. It will create configuration files in
13# distro specific directory.
14# - Reboot the VM, so that the bonding config are enabled.
15#
16# The config files are DHCP by default. You may edit them if you need to change
17# to Static IP or change other settings.
18#
19
20sysdir=/sys/class/net
21netvsc_cls={f8615163-df3e-46c5-913f-f2d2f965ed0e}
22bondcnt=0
23
24# Detect Distro
25if [ -f /etc/redhat-release ];
26then
27 cfgdir=/etc/sysconfig/network-scripts
28 distro=redhat
29elif grep -q 'Ubuntu' /etc/issue
30then
31 cfgdir=/etc/network
32 distro=ubuntu
33elif grep -q 'SUSE' /etc/issue
34then
35 cfgdir=/etc/sysconfig/network
36 distro=suse
37else
38 echo "Unsupported Distro"
39 exit 1
40fi
41
42echo Detected Distro: $distro, or compatible
43
44# Get a list of ethernet names
45list_eth=(`cd $sysdir && ls -d */ | cut -d/ -f1 | grep -v bond`)
46eth_cnt=${#list_eth[@]}
47
48echo List of net devices:
49
50# Get the MAC addresses
51for (( i=0; i < $eth_cnt; i++ ))
52do
53 list_mac[$i]=`cat $sysdir/${list_eth[$i]}/address`
54 echo ${list_eth[$i]}, ${list_mac[$i]}
55done
56
57# Find NIC with matching MAC
58for (( i=0; i < $eth_cnt-1; i++ ))
59do
60 for (( j=i+1; j < $eth_cnt; j++ ))
61 do
62 if [ "${list_mac[$i]}" = "${list_mac[$j]}" ]
63 then
64 list_match[$i]=${list_eth[$j]}
65 break
66 fi
67 done
68done
69
70function create_eth_cfg_redhat {
71 local fn=$cfgdir/ifcfg-$1
72
73 rm -f $fn
74 echo DEVICE=$1 >>$fn
75 echo TYPE=Ethernet >>$fn
76 echo BOOTPROTO=none >>$fn
77 echo UUID=`uuidgen` >>$fn
78 echo ONBOOT=yes >>$fn
79 echo PEERDNS=yes >>$fn
80 echo IPV6INIT=yes >>$fn
81 echo MASTER=$2 >>$fn
82 echo SLAVE=yes >>$fn
83}
84
85function create_eth_cfg_pri_redhat {
86 create_eth_cfg_redhat $1 $2
87}
88
89function create_bond_cfg_redhat {
90 local fn=$cfgdir/ifcfg-$1
91
92 rm -f $fn
93 echo DEVICE=$1 >>$fn
94 echo TYPE=Bond >>$fn
95 echo BOOTPROTO=dhcp >>$fn
96 echo UUID=`uuidgen` >>$fn
97 echo ONBOOT=yes >>$fn
98 echo PEERDNS=yes >>$fn
99 echo IPV6INIT=yes >>$fn
100 echo BONDING_MASTER=yes >>$fn
101 echo BONDING_OPTS=\"mode=active-backup miimon=100 primary=$2\" >>$fn
102}
103
104function del_eth_cfg_ubuntu {
105 local mainfn=$cfgdir/interfaces
106 local fnlist=( $mainfn )
107
108 local dirlist=(`awk '/^[ \t]*source/{print $2}' $mainfn`)
109
110 local i
111 for i in "${dirlist[@]}"
112 do
113 fnlist+=(`ls $i 2>/dev/null`)
114 done
115
116 local tmpfl=$(mktemp)
117
118 local nic_start='^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+'$1
119 local nic_end='^[ \t]*(auto|iface|mapping|allow-.*|source)'
120
121 local fn
122 for fn in "${fnlist[@]}"
123 do
124 awk "/$nic_end/{x=0} x{next} /$nic_start/{x=1;next} 1" \
125 $fn >$tmpfl
126
127 cp $tmpfl $fn
128 done
129
130 rm $tmpfl
131}
132
133function create_eth_cfg_ubuntu {
134 local fn=$cfgdir/interfaces
135
136 del_eth_cfg_ubuntu $1
137 echo $'\n'auto $1 >>$fn
138 echo iface $1 inet manual >>$fn
139 echo bond-master $2 >>$fn
140}
141
142function create_eth_cfg_pri_ubuntu {
143 local fn=$cfgdir/interfaces
144
145 del_eth_cfg_ubuntu $1
146 echo $'\n'allow-hotplug $1 >>$fn
147 echo iface $1 inet manual >>$fn
148 echo bond-master $2 >>$fn
149 echo bond-primary $1 >>$fn
150}
151
152function create_bond_cfg_ubuntu {
153 local fn=$cfgdir/interfaces
154
155 del_eth_cfg_ubuntu $1
156
157 echo $'\n'auto $1 >>$fn
158 echo iface $1 inet dhcp >>$fn
159 echo bond-mode active-backup >>$fn
160 echo bond-miimon 100 >>$fn
161 echo bond-slaves none >>$fn
162}
163
164function create_eth_cfg_suse {
165 local fn=$cfgdir/ifcfg-$1
166
167 rm -f $fn
168 echo BOOTPROTO=none >>$fn
169 echo STARTMODE=auto >>$fn
170}
171
172function create_eth_cfg_pri_suse {
173 local fn=$cfgdir/ifcfg-$1
174
175 rm -f $fn
176 echo BOOTPROTO=none >>$fn
177 echo STARTMODE=hotplug >>$fn
178}
179
180function create_bond_cfg_suse {
181 local fn=$cfgdir/ifcfg-$1
182
183 rm -f $fn
184 echo BOOTPROTO=dhcp >>$fn
185 echo STARTMODE=auto >>$fn
186 echo BONDING_MASTER=yes >>$fn
187 echo BONDING_SLAVE_0=$2 >>$fn
188 echo BONDING_SLAVE_1=$3 >>$fn
189 echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn
190}
191
192function create_bond {
193 local bondname=bond$bondcnt
194 local primary
195 local secondary
196
197 local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null`
198 local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null`
199
200 if [ "$class_id1" = "$netvsc_cls" ]
201 then
202 primary=$2
203 secondary=$1
204 elif [ "$class_id2" = "$netvsc_cls" ]
205 then
206 primary=$1
207 secondary=$2
208 else
209 return 0
210 fi
211
212 echo $'\nBond name:' $bondname
213
214 echo configuring $primary
215 create_eth_cfg_pri_$distro $primary $bondname
216
217 echo configuring $secondary
218 create_eth_cfg_$distro $secondary $bondname
219
220 echo creating: $bondname with primary slave: $primary
221 create_bond_cfg_$distro $bondname $primary $secondary
222
223 let bondcnt=bondcnt+1
224}
225
226for (( i=0; i < $eth_cnt-1; i++ ))
227do
228 if [ -n "${list_match[$i]}" ]
229 then
230 create_bond ${list_eth[$i]} ${list_match[$i]}
231 fi
232done
diff --git a/tools/include/asm-generic/hugetlb_encode.h b/tools/include/asm-generic/hugetlb_encode.h
new file mode 100644
index 000000000000..e4732d3c2998
--- /dev/null
+++ b/tools/include/asm-generic/hugetlb_encode.h
@@ -0,0 +1,34 @@
1#ifndef _ASM_GENERIC_HUGETLB_ENCODE_H_
2#define _ASM_GENERIC_HUGETLB_ENCODE_H_
3
4/*
5 * Several system calls take a flag to request "hugetlb" huge pages.
6 * Without further specification, these system calls will use the
7 * system's default huge page size. If a system supports multiple
8 * huge page sizes, the desired huge page size can be specified in
9 * bits [26:31] of the flag arguments. The value in these 6 bits
10 * will encode the log2 of the huge page size.
11 *
12 * The following definitions are associated with this huge page size
13 * encoding in flag arguments. System call specific header files
14 * that use this encoding should include this file. They can then
15 * provide definitions based on these with their own specific prefix.
16 * for example:
17 * #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
18 */
19
20#define HUGETLB_FLAG_ENCODE_SHIFT 26
21#define HUGETLB_FLAG_ENCODE_MASK 0x3f
22
23#define HUGETLB_FLAG_ENCODE_64KB (16 << HUGETLB_FLAG_ENCODE_SHIFT)
24#define HUGETLB_FLAG_ENCODE_512KB (19 << HUGETLB_FLAG_ENCODE_SHIFT)
25#define HUGETLB_FLAG_ENCODE_1MB (20 << HUGETLB_FLAG_ENCODE_SHIFT)
26#define HUGETLB_FLAG_ENCODE_2MB (21 << HUGETLB_FLAG_ENCODE_SHIFT)
27#define HUGETLB_FLAG_ENCODE_8MB (23 << HUGETLB_FLAG_ENCODE_SHIFT)
28#define HUGETLB_FLAG_ENCODE_16MB (24 << HUGETLB_FLAG_ENCODE_SHIFT)
29#define HUGETLB_FLAG_ENCODE_256MB (28 << HUGETLB_FLAG_ENCODE_SHIFT)
30#define HUGETLB_FLAG_ENCODE_1GB (30 << HUGETLB_FLAG_ENCODE_SHIFT)
31#define HUGETLB_FLAG_ENCODE_2GB (31 << HUGETLB_FLAG_ENCODE_SHIFT)
32#define HUGETLB_FLAG_ENCODE_16GB (34 << HUGETLB_FLAG_ENCODE_SHIFT)
33
34#endif /* _ASM_GENERIC_HUGETLB_ENCODE_H_ */
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
index bd39b2090ad1..3723b9f8f964 100644
--- a/tools/include/linux/compiler-gcc.h
+++ b/tools/include/linux/compiler-gcc.h
@@ -21,11 +21,14 @@
21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) 21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
22 22
23#define noinline __attribute__((noinline)) 23#define noinline __attribute__((noinline))
24 24#ifndef __packed
25#define __packed __attribute__((packed)) 25#define __packed __attribute__((packed))
26 26#endif
27#ifndef __noreturn
27#define __noreturn __attribute__((noreturn)) 28#define __noreturn __attribute__((noreturn))
28 29#endif
30#ifndef __aligned
29#define __aligned(x) __attribute__((aligned(x))) 31#define __aligned(x) __attribute__((aligned(x)))
32#endif
30#define __printf(a, b) __attribute__((format(printf, a, b))) 33#define __printf(a, b) __attribute__((format(printf, a, b)))
31#define __scanf(a, b) __attribute__((format(scanf, a, b))) 34#define __scanf(a, b) __attribute__((format(scanf, a, b)))
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
index 8c27db0c5c08..203268f9231e 100644
--- a/tools/include/uapi/asm-generic/mman-common.h
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -58,20 +58,12 @@
58 overrides the coredump filter bits */ 58 overrides the coredump filter bits */
59#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */ 59#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */
60 60
61#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
62#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
63
61/* compatibility flags */ 64/* compatibility flags */
62#define MAP_FILE 0 65#define MAP_FILE 0
63 66
64/*
65 * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
66 * This gives us 6 bits, which is enough until someone invents 128 bit address
67 * spaces.
68 *
69 * Assume these are all power of twos.
70 * When 0 use the default page size.
71 */
72#define MAP_HUGE_SHIFT 26
73#define MAP_HUGE_MASK 0x3f
74
75#define PKEY_DISABLE_ACCESS 0x1 67#define PKEY_DISABLE_ACCESS 0x1
76#define PKEY_DISABLE_WRITE 0x2 68#define PKEY_DISABLE_WRITE 0x2
77#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\ 69#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h
index 101593ab10ac..97677cd6964d 100644
--- a/tools/include/uapi/drm/drm.h
+++ b/tools/include/uapi/drm/drm.h
@@ -700,6 +700,7 @@ struct drm_prime_handle {
700 700
701struct drm_syncobj_create { 701struct drm_syncobj_create {
702 __u32 handle; 702 __u32 handle;
703#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
703 __u32 flags; 704 __u32 flags;
704}; 705};
705 706
@@ -718,6 +719,24 @@ struct drm_syncobj_handle {
718 __u32 pad; 719 __u32 pad;
719}; 720};
720 721
722#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
723#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
724struct drm_syncobj_wait {
725 __u64 handles;
726 /* absolute timeout */
727 __s64 timeout_nsec;
728 __u32 count_handles;
729 __u32 flags;
730 __u32 first_signaled; /* only valid when not waiting all */
731 __u32 pad;
732};
733
734struct drm_syncobj_array {
735 __u64 handles;
736 __u32 count_handles;
737 __u32 pad;
738};
739
721#if defined(__cplusplus) 740#if defined(__cplusplus)
722} 741}
723#endif 742#endif
@@ -840,6 +859,9 @@ extern "C" {
840#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) 859#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy)
841#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) 860#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
842#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) 861#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
862#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
863#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array)
864#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array)
843 865
844/** 866/**
845 * Device specific ioctls should only be in their respective headers 867 * Device specific ioctls should only be in their respective headers
diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h
index 7ccbd6a2bbe0..6598fb76d2c2 100644
--- a/tools/include/uapi/drm/i915_drm.h
+++ b/tools/include/uapi/drm/i915_drm.h
@@ -260,6 +260,8 @@ typedef struct _drm_i915_sarea {
260#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 260#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
261#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 261#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
262#define DRM_I915_PERF_OPEN 0x36 262#define DRM_I915_PERF_OPEN 0x36
263#define DRM_I915_PERF_ADD_CONFIG 0x37
264#define DRM_I915_PERF_REMOVE_CONFIG 0x38
263 265
264#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 266#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
265#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) 267#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -315,6 +317,8 @@ typedef struct _drm_i915_sarea {
315#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) 317#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
316#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) 318#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
317#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) 319#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
320#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
321#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
318 322
319/* Allow drivers to submit batchbuffers directly to hardware, relying 323/* Allow drivers to submit batchbuffers directly to hardware, relying
320 * on the security mechanisms provided by hardware. 324 * on the security mechanisms provided by hardware.
@@ -431,6 +435,11 @@ typedef struct drm_i915_irq_wait {
431 */ 435 */
432#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48 436#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48
433 437
438/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
439 * drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY.
440 */
441#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49
442
434typedef struct drm_i915_getparam { 443typedef struct drm_i915_getparam {
435 __s32 param; 444 __s32 param;
436 /* 445 /*
@@ -812,6 +821,17 @@ struct drm_i915_gem_exec_object2 {
812 __u64 rsvd2; 821 __u64 rsvd2;
813}; 822};
814 823
824struct drm_i915_gem_exec_fence {
825 /**
826 * User's handle for a drm_syncobj to wait on or signal.
827 */
828 __u32 handle;
829
830#define I915_EXEC_FENCE_WAIT (1<<0)
831#define I915_EXEC_FENCE_SIGNAL (1<<1)
832 __u32 flags;
833};
834
815struct drm_i915_gem_execbuffer2 { 835struct drm_i915_gem_execbuffer2 {
816 /** 836 /**
817 * List of gem_exec_object2 structs 837 * List of gem_exec_object2 structs
@@ -826,7 +846,11 @@ struct drm_i915_gem_execbuffer2 {
826 __u32 DR1; 846 __u32 DR1;
827 __u32 DR4; 847 __u32 DR4;
828 __u32 num_cliprects; 848 __u32 num_cliprects;
829 /** This is a struct drm_clip_rect *cliprects */ 849 /**
850 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
851 * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a
852 * struct drm_i915_gem_exec_fence *fences.
853 */
830 __u64 cliprects_ptr; 854 __u64 cliprects_ptr;
831#define I915_EXEC_RING_MASK (7<<0) 855#define I915_EXEC_RING_MASK (7<<0)
832#define I915_EXEC_DEFAULT (0<<0) 856#define I915_EXEC_DEFAULT (0<<0)
@@ -927,7 +951,14 @@ struct drm_i915_gem_execbuffer2 {
927 * element). 951 * element).
928 */ 952 */
929#define I915_EXEC_BATCH_FIRST (1<<18) 953#define I915_EXEC_BATCH_FIRST (1<<18)
930#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_BATCH_FIRST<<1)) 954
955/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
956 * define an array of i915_gem_exec_fence structures which specify a set of
957 * dma fences to wait upon or signal.
958 */
959#define I915_EXEC_FENCE_ARRAY (1<<19)
960
961#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
931 962
932#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) 963#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
933#define i915_execbuffer2_set_context_id(eb2, context) \ 964#define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1467,6 +1498,22 @@ enum drm_i915_perf_record_type {
1467 DRM_I915_PERF_RECORD_MAX /* non-ABI */ 1498 DRM_I915_PERF_RECORD_MAX /* non-ABI */
1468}; 1499};
1469 1500
1501/**
1502 * Structure to upload perf dynamic configuration into the kernel.
1503 */
1504struct drm_i915_perf_oa_config {
1505 /** String formatted like "%08x-%04x-%04x-%04x-%012x" */
1506 char uuid[36];
1507
1508 __u32 n_mux_regs;
1509 __u32 n_boolean_regs;
1510 __u32 n_flex_regs;
1511
1512 __u64 __user mux_regs_ptr;
1513 __u64 __user boolean_regs_ptr;
1514 __u64 __user flex_regs_ptr;
1515};
1516
1470#if defined(__cplusplus) 1517#if defined(__cplusplus)
1471} 1518}
1472#endif 1519#endif
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index e99e3e6f8b37..43ab5c402f98 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -30,9 +30,14 @@
30#define BPF_FROM_LE BPF_TO_LE 30#define BPF_FROM_LE BPF_TO_LE
31#define BPF_FROM_BE BPF_TO_BE 31#define BPF_FROM_BE BPF_TO_BE
32 32
33/* jmp encodings */
33#define BPF_JNE 0x50 /* jump != */ 34#define BPF_JNE 0x50 /* jump != */
35#define BPF_JLT 0xa0 /* LT is unsigned, '<' */
36#define BPF_JLE 0xb0 /* LE is unsigned, '<=' */
34#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */ 37#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
35#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */ 38#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
39#define BPF_JSLT 0xc0 /* SLT is signed, '<' */
40#define BPF_JSLE 0xd0 /* SLE is signed, '<=' */
36#define BPF_CALL 0x80 /* function call */ 41#define BPF_CALL 0x80 /* function call */
37#define BPF_EXIT 0x90 /* function return */ 42#define BPF_EXIT 0x90 /* function return */
38 43
@@ -104,6 +109,8 @@ enum bpf_map_type {
104 BPF_MAP_TYPE_LPM_TRIE, 109 BPF_MAP_TYPE_LPM_TRIE,
105 BPF_MAP_TYPE_ARRAY_OF_MAPS, 110 BPF_MAP_TYPE_ARRAY_OF_MAPS,
106 BPF_MAP_TYPE_HASH_OF_MAPS, 111 BPF_MAP_TYPE_HASH_OF_MAPS,
112 BPF_MAP_TYPE_DEVMAP,
113 BPF_MAP_TYPE_SOCKMAP,
107}; 114};
108 115
109enum bpf_prog_type { 116enum bpf_prog_type {
@@ -121,6 +128,7 @@ enum bpf_prog_type {
121 BPF_PROG_TYPE_LWT_OUT, 128 BPF_PROG_TYPE_LWT_OUT,
122 BPF_PROG_TYPE_LWT_XMIT, 129 BPF_PROG_TYPE_LWT_XMIT,
123 BPF_PROG_TYPE_SOCK_OPS, 130 BPF_PROG_TYPE_SOCK_OPS,
131 BPF_PROG_TYPE_SK_SKB,
124}; 132};
125 133
126enum bpf_attach_type { 134enum bpf_attach_type {
@@ -128,6 +136,8 @@ enum bpf_attach_type {
128 BPF_CGROUP_INET_EGRESS, 136 BPF_CGROUP_INET_EGRESS,
129 BPF_CGROUP_INET_SOCK_CREATE, 137 BPF_CGROUP_INET_SOCK_CREATE,
130 BPF_CGROUP_SOCK_OPS, 138 BPF_CGROUP_SOCK_OPS,
139 BPF_SK_SKB_STREAM_PARSER,
140 BPF_SK_SKB_STREAM_VERDICT,
131 __MAX_BPF_ATTACH_TYPE 141 __MAX_BPF_ATTACH_TYPE
132}; 142};
133 143
@@ -153,6 +163,7 @@ enum bpf_attach_type {
153#define BPF_NOEXIST 1 /* create new element if it didn't exist */ 163#define BPF_NOEXIST 1 /* create new element if it didn't exist */
154#define BPF_EXIST 2 /* update existing element */ 164#define BPF_EXIST 2 /* update existing element */
155 165
166/* flags for BPF_MAP_CREATE command */
156#define BPF_F_NO_PREALLOC (1U << 0) 167#define BPF_F_NO_PREALLOC (1U << 0)
157/* Instead of having one common LRU list in the 168/* Instead of having one common LRU list in the
158 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list 169 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
@@ -161,6 +172,8 @@ enum bpf_attach_type {
161 * across different LRU lists. 172 * across different LRU lists.
162 */ 173 */
163#define BPF_F_NO_COMMON_LRU (1U << 1) 174#define BPF_F_NO_COMMON_LRU (1U << 1)
175/* Specify numa node during map creation */
176#define BPF_F_NUMA_NODE (1U << 2)
164 177
165union bpf_attr { 178union bpf_attr {
166 struct { /* anonymous struct used by BPF_MAP_CREATE command */ 179 struct { /* anonymous struct used by BPF_MAP_CREATE command */
@@ -168,8 +181,13 @@ union bpf_attr {
168 __u32 key_size; /* size of key in bytes */ 181 __u32 key_size; /* size of key in bytes */
169 __u32 value_size; /* size of value in bytes */ 182 __u32 value_size; /* size of value in bytes */
170 __u32 max_entries; /* max number of entries in a map */ 183 __u32 max_entries; /* max number of entries in a map */
171 __u32 map_flags; /* prealloc or not */ 184 __u32 map_flags; /* BPF_MAP_CREATE related
185 * flags defined above.
186 */
172 __u32 inner_map_fd; /* fd pointing to the inner map */ 187 __u32 inner_map_fd; /* fd pointing to the inner map */
188 __u32 numa_node; /* numa node (effective only if
189 * BPF_F_NUMA_NODE is set).
190 */
173 }; 191 };
174 192
175 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ 193 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
@@ -344,9 +362,20 @@ union bpf_attr {
344 * int bpf_redirect(ifindex, flags) 362 * int bpf_redirect(ifindex, flags)
345 * redirect to another netdev 363 * redirect to another netdev
346 * @ifindex: ifindex of the net device 364 * @ifindex: ifindex of the net device
347 * @flags: bit 0 - if set, redirect to ingress instead of egress 365 * @flags:
348 * other bits - reserved 366 * cls_bpf:
349 * Return: TC_ACT_REDIRECT 367 * bit 0 - if set, redirect to ingress instead of egress
368 * other bits - reserved
369 * xdp_bpf:
370 * all bits - reserved
371 * Return: cls_bpf: TC_ACT_REDIRECT on success or TC_ACT_SHOT on error
372 * xdp_bfp: XDP_REDIRECT on success or XDP_ABORT on error
373 * int bpf_redirect_map(map, key, flags)
374 * redirect to endpoint in map
375 * @map: pointer to dev map
376 * @key: index in map to lookup
377 * @flags: --
378 * Return: XDP_REDIRECT on success or XDP_ABORT on error
350 * 379 *
351 * u32 bpf_get_route_realm(skb) 380 * u32 bpf_get_route_realm(skb)
352 * retrieve a dst's tclassid 381 * retrieve a dst's tclassid
@@ -539,6 +568,20 @@ union bpf_attr {
539 * @mode: operation mode (enum bpf_adj_room_mode) 568 * @mode: operation mode (enum bpf_adj_room_mode)
540 * @flags: reserved for future use 569 * @flags: reserved for future use
541 * Return: 0 on success or negative error code 570 * Return: 0 on success or negative error code
571 *
572 * int bpf_sk_redirect_map(map, key, flags)
573 * Redirect skb to a sock in map using key as a lookup key for the
574 * sock in map.
575 * @map: pointer to sockmap
576 * @key: key to lookup sock in map
577 * @flags: reserved for future use
578 * Return: SK_REDIRECT
579 *
580 * int bpf_sock_map_update(skops, map, key, flags)
581 * @skops: pointer to bpf_sock_ops
582 * @map: pointer to sockmap to update
583 * @key: key to insert/update sock in map
584 * @flags: same flags as map update elem
542 */ 585 */
543#define __BPF_FUNC_MAPPER(FN) \ 586#define __BPF_FUNC_MAPPER(FN) \
544 FN(unspec), \ 587 FN(unspec), \
@@ -591,7 +634,10 @@ union bpf_attr {
591 FN(get_socket_uid), \ 634 FN(get_socket_uid), \
592 FN(set_hash), \ 635 FN(set_hash), \
593 FN(setsockopt), \ 636 FN(setsockopt), \
594 FN(skb_adjust_room), 637 FN(skb_adjust_room), \
638 FN(redirect_map), \
639 FN(sk_redirect_map), \
640 FN(sock_map_update), \
595 641
596/* integer value in 'imm' field of BPF_CALL instruction selects which helper 642/* integer value in 'imm' field of BPF_CALL instruction selects which helper
597 * function eBPF program intends to call 643 * function eBPF program intends to call
@@ -668,6 +714,15 @@ struct __sk_buff {
668 __u32 data; 714 __u32 data;
669 __u32 data_end; 715 __u32 data_end;
670 __u32 napi_id; 716 __u32 napi_id;
717
718 /* accessed by BPF_PROG_TYPE_sk_skb types */
719 __u32 family;
720 __u32 remote_ip4; /* Stored in network byte order */
721 __u32 local_ip4; /* Stored in network byte order */
722 __u32 remote_ip6[4]; /* Stored in network byte order */
723 __u32 local_ip6[4]; /* Stored in network byte order */
724 __u32 remote_port; /* Stored in network byte order */
725 __u32 local_port; /* stored in host byte order */
671}; 726};
672 727
673struct bpf_tunnel_key { 728struct bpf_tunnel_key {
@@ -703,20 +758,23 @@ struct bpf_sock {
703 __u32 family; 758 __u32 family;
704 __u32 type; 759 __u32 type;
705 __u32 protocol; 760 __u32 protocol;
761 __u32 mark;
762 __u32 priority;
706}; 763};
707 764
708#define XDP_PACKET_HEADROOM 256 765#define XDP_PACKET_HEADROOM 256
709 766
710/* User return codes for XDP prog type. 767/* User return codes for XDP prog type.
711 * A valid XDP program must return one of these defined values. All other 768 * A valid XDP program must return one of these defined values. All other
712 * return codes are reserved for future use. Unknown return codes will result 769 * return codes are reserved for future use. Unknown return codes will
713 * in packet drop. 770 * result in packet drops and a warning via bpf_warn_invalid_xdp_action().
714 */ 771 */
715enum xdp_action { 772enum xdp_action {
716 XDP_ABORTED = 0, 773 XDP_ABORTED = 0,
717 XDP_DROP, 774 XDP_DROP,
718 XDP_PASS, 775 XDP_PASS,
719 XDP_TX, 776 XDP_TX,
777 XDP_REDIRECT,
720}; 778};
721 779
722/* user accessible metadata for XDP packet hook 780/* user accessible metadata for XDP packet hook
@@ -727,6 +785,12 @@ struct xdp_md {
727 __u32 data_end; 785 __u32 data_end;
728}; 786};
729 787
788enum sk_action {
789 SK_ABORTED = 0,
790 SK_DROP,
791 SK_REDIRECT,
792};
793
730#define BPF_TAG_SIZE 8 794#define BPF_TAG_SIZE 8
731 795
732struct bpf_prog_info { 796struct bpf_prog_info {
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 6cd63c18708a..838887587411 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -711,7 +711,8 @@ struct kvm_ppc_one_seg_page_size {
711struct kvm_ppc_smmu_info { 711struct kvm_ppc_smmu_info {
712 __u64 flags; 712 __u64 flags;
713 __u32 slb_size; 713 __u32 slb_size;
714 __u32 pad; 714 __u16 data_keys; /* # storage keys supported for data */
715 __u16 instr_keys; /* # storage keys supported for instructions */
715 struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ]; 716 struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
716}; 717};
717 718
diff --git a/tools/include/uapi/linux/mman.h b/tools/include/uapi/linux/mman.h
index 81d8edf11789..a937480d7cd3 100644
--- a/tools/include/uapi/linux/mman.h
+++ b/tools/include/uapi/linux/mman.h
@@ -1,7 +1,8 @@
1#ifndef _UAPI_LINUX_MMAN_H 1#ifndef _UAPI_LINUX_MMAN_H
2#define _UAPI_LINUX_MMAN_H 2#define _UAPI_LINUX_MMAN_H
3 3
4#include <uapi/asm/mman.h> 4#include <asm/mman.h>
5#include <asm-generic/hugetlb_encode.h>
5 6
6#define MREMAP_MAYMOVE 1 7#define MREMAP_MAYMOVE 1
7#define MREMAP_FIXED 2 8#define MREMAP_FIXED 2
@@ -10,4 +11,25 @@
10#define OVERCOMMIT_ALWAYS 1 11#define OVERCOMMIT_ALWAYS 1
11#define OVERCOMMIT_NEVER 2 12#define OVERCOMMIT_NEVER 2
12 13
14/*
15 * Huge page size encoding when MAP_HUGETLB is specified, and a huge page
16 * size other than the default is desired. See hugetlb_encode.h.
17 * All known huge page size encodings are provided here. It is the
18 * responsibility of the application to know which sizes are supported on
19 * the running system. See mmap(2) man page for details.
20 */
21#define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
22#define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
23
24#define MAP_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
25#define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
26#define MAP_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
27#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
28#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
29#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
30#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
31#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
32#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
33#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
34
13#endif /* _UAPI_LINUX_MMAN_H */ 35#endif /* _UAPI_LINUX_MMAN_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 2a37ae925d85..140ae638cfd6 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -139,8 +139,9 @@ enum perf_event_sample_format {
139 PERF_SAMPLE_IDENTIFIER = 1U << 16, 139 PERF_SAMPLE_IDENTIFIER = 1U << 16,
140 PERF_SAMPLE_TRANSACTION = 1U << 17, 140 PERF_SAMPLE_TRANSACTION = 1U << 17,
141 PERF_SAMPLE_REGS_INTR = 1U << 18, 141 PERF_SAMPLE_REGS_INTR = 1U << 18,
142 PERF_SAMPLE_PHYS_ADDR = 1U << 19,
142 143
143 PERF_SAMPLE_MAX = 1U << 19, /* non-ABI */ 144 PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
144}; 145};
145 146
146/* 147/*
@@ -814,6 +815,7 @@ enum perf_event_type {
814 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION 815 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION
815 * { u64 abi; # enum perf_sample_regs_abi 816 * { u64 abi; # enum perf_sample_regs_abi
816 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR 817 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
818 * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
817 * }; 819 * };
818 */ 820 */
819 PERF_RECORD_SAMPLE = 9, 821 PERF_RECORD_SAMPLE = 9,
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 4563ba7ede6f..1e83e3c07448 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -17,13 +17,19 @@ MAKEFLAGS += --no-print-directory
17LIBFILE = $(OUTPUT)libapi.a 17LIBFILE = $(OUTPUT)libapi.a
18 18
19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -fPIC
21 21
22ifeq ($(DEBUG),0)
22ifeq ($(CC_NO_CLANG), 0) 23ifeq ($(CC_NO_CLANG), 0)
23 CFLAGS += -O3 24 CFLAGS += -O3
24else 25else
25 CFLAGS += -O6 26 CFLAGS += -O6
26endif 27endif
28endif
29
30ifeq ($(DEBUG),0)
31 CFLAGS += -D_FORTIFY_SOURCE
32endif
27 33
28# Treat warnings as errors unless directed not to 34# Treat warnings as errors unless directed not to
29ifneq ($(WERROR),0) 35ifneq ($(WERROR),0)
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 4ed0257dc1f3..d2441db34740 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -189,6 +189,10 @@ install_lib: all_cmd
189 $(call QUIET_INSTALL, $(LIB_FILE)) \ 189 $(call QUIET_INSTALL, $(LIB_FILE)) \
190 $(call do_install,$(LIB_FILE),$(libdir_SQ)) 190 $(call do_install,$(LIB_FILE),$(libdir_SQ))
191 191
192install_headers:
193 $(call QUIET_INSTALL, headers) \
194 $(call do_install,bpf.h,$(prefix)/include/bpf,644)
195
192install: install_lib 196install: install_lib
193 197
194### Cleaning rules 198### Cleaning rules
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index e5bbb090bf88..1d6907d379c9 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -57,8 +57,9 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
57 return syscall(__NR_bpf, cmd, attr, size); 57 return syscall(__NR_bpf, cmd, attr, size);
58} 58}
59 59
60int bpf_create_map(enum bpf_map_type map_type, int key_size, 60int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
61 int value_size, int max_entries, __u32 map_flags) 61 int value_size, int max_entries, __u32 map_flags,
62 int node)
62{ 63{
63 union bpf_attr attr; 64 union bpf_attr attr;
64 65
@@ -69,12 +70,24 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size,
69 attr.value_size = value_size; 70 attr.value_size = value_size;
70 attr.max_entries = max_entries; 71 attr.max_entries = max_entries;
71 attr.map_flags = map_flags; 72 attr.map_flags = map_flags;
73 if (node >= 0) {
74 attr.map_flags |= BPF_F_NUMA_NODE;
75 attr.numa_node = node;
76 }
72 77
73 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 78 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
74} 79}
75 80
76int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size, 81int bpf_create_map(enum bpf_map_type map_type, int key_size,
77 int inner_map_fd, int max_entries, __u32 map_flags) 82 int value_size, int max_entries, __u32 map_flags)
83{
84 return bpf_create_map_node(map_type, key_size, value_size,
85 max_entries, map_flags, -1);
86}
87
88int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
89 int inner_map_fd, int max_entries,
90 __u32 map_flags, int node)
78{ 91{
79 union bpf_attr attr; 92 union bpf_attr attr;
80 93
@@ -86,10 +99,21 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
86 attr.inner_map_fd = inner_map_fd; 99 attr.inner_map_fd = inner_map_fd;
87 attr.max_entries = max_entries; 100 attr.max_entries = max_entries;
88 attr.map_flags = map_flags; 101 attr.map_flags = map_flags;
102 if (node >= 0) {
103 attr.map_flags |= BPF_F_NUMA_NODE;
104 attr.numa_node = node;
105 }
89 106
90 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 107 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
91} 108}
92 109
110int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
111 int inner_map_fd, int max_entries, __u32 map_flags)
112{
113 return bpf_create_map_in_map_node(map_type, key_size, inner_map_fd,
114 max_entries, map_flags, -1);
115}
116
93int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 117int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
94 size_t insns_cnt, const char *license, 118 size_t insns_cnt, const char *license,
95 __u32 kern_version, char *log_buf, size_t log_buf_sz) 119 __u32 kern_version, char *log_buf, size_t log_buf_sz)
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 418c86e69bcb..b8ea5843c39e 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -24,8 +24,14 @@
24#include <linux/bpf.h> 24#include <linux/bpf.h>
25#include <stddef.h> 25#include <stddef.h>
26 26
27int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
28 int value_size, int max_entries, __u32 map_flags,
29 int node);
27int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 30int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
28 int max_entries, __u32 map_flags); 31 int max_entries, __u32 map_flags);
32int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
33 int inner_map_fd, int max_entries,
34 __u32 map_flags, int node);
29int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size, 35int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
30 int inner_map_fd, int max_entries, __u32 map_flags); 36 int inner_map_fd, int max_entries, __u32 map_flags);
31 37
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 8c67a90dbd82..35f6dfcdc565 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1745,3 +1745,32 @@ long libbpf_get_error(const void *ptr)
1745 return PTR_ERR(ptr); 1745 return PTR_ERR(ptr);
1746 return 0; 1746 return 0;
1747} 1747}
1748
1749int bpf_prog_load(const char *file, enum bpf_prog_type type,
1750 struct bpf_object **pobj, int *prog_fd)
1751{
1752 struct bpf_program *prog;
1753 struct bpf_object *obj;
1754 int err;
1755
1756 obj = bpf_object__open(file);
1757 if (IS_ERR(obj))
1758 return -ENOENT;
1759
1760 prog = bpf_program__next(NULL, obj);
1761 if (!prog) {
1762 bpf_object__close(obj);
1763 return -ENOENT;
1764 }
1765
1766 bpf_program__set_type(prog, type);
1767 err = bpf_object__load(obj);
1768 if (err) {
1769 bpf_object__close(obj);
1770 return -EINVAL;
1771 }
1772
1773 *pobj = obj;
1774 *prog_fd = bpf_program__fd(prog);
1775 return 0;
1776}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 32c7252f734e..7959086eb9c9 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -243,4 +243,6 @@ int bpf_map__pin(struct bpf_map *map, const char *path);
243 243
244long libbpf_get_error(const void *ptr); 244long libbpf_get_error(const void *ptr);
245 245
246int bpf_prog_load(const char *file, enum bpf_prog_type type,
247 struct bpf_object **pobj, int *prog_fd);
246#endif 248#endif
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
index 6a1af43862df..3995735a878f 100644
--- a/tools/objtool/Documentation/stack-validation.txt
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -194,10 +194,10 @@ they mean, and suggestions for how to fix them.
194 If it's a GCC-compiled .c file, the error may be because the function 194 If it's a GCC-compiled .c file, the error may be because the function
195 uses an inline asm() statement which has a "call" instruction. An 195 uses an inline asm() statement which has a "call" instruction. An
196 asm() statement with a call instruction must declare the use of the 196 asm() statement with a call instruction must declare the use of the
197 stack pointer in its output operand. For example, on x86_64: 197 stack pointer in its output operand. On x86_64, this means adding
198 the ASM_CALL_CONSTRAINT as an output constraint:
198 199
199 register void *__sp asm("rsp"); 200 asm volatile("call func" : ASM_CALL_CONSTRAINT);
200 asm volatile("call func" : "+r" (__sp));
201 201
202 Otherwise the stack frame may not get created before the call. 202 Otherwise the stack frame may not get created before the call.
203 203
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 0e8c8ec4fd4e..34a579f806e3 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
208 break; 208 break;
209 209
210 case 0x89: 210 case 0x89:
211 if (rex == 0x48 && modrm == 0xe5) { 211 if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
212 212
213 /* mov %rsp, %rbp */ 213 /* mov %rsp, reg */
214 *type = INSN_STACK; 214 *type = INSN_STACK;
215 op->src.type = OP_SRC_REG; 215 op->src.type = OP_SRC_REG;
216 op->src.reg = CFI_SP; 216 op->src.reg = CFI_SP;
217 op->dest.type = OP_DEST_REG; 217 op->dest.type = OP_DEST_REG;
218 op->dest.reg = CFI_BP; 218 op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
219 break; 219 break;
220 } 220 }
221 221
@@ -284,11 +284,16 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
284 case 0x8d: 284 case 0x8d:
285 if (sib == 0x24 && rex_w && !rex_b && !rex_x) { 285 if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
286 286
287 /* lea disp(%rsp), reg */
288 *type = INSN_STACK; 287 *type = INSN_STACK;
289 op->src.type = OP_SRC_ADD; 288 if (!insn.displacement.value) {
289 /* lea (%rsp), reg */
290 op->src.type = OP_SRC_REG;
291 } else {
292 /* lea disp(%rsp), reg */
293 op->src.type = OP_SRC_ADD;
294 op->src.offset = insn.displacement.value;
295 }
290 op->src.reg = CFI_SP; 296 op->src.reg = CFI_SP;
291 op->src.offset = insn.displacement.value;
292 op->dest.type = OP_DEST_REG; 297 op->dest.type = OP_DEST_REG;
293 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 298 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
294 299
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f744617c9946..a0c518ecf085 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1203,24 +1203,39 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1203 switch (op->src.type) { 1203 switch (op->src.type) {
1204 1204
1205 case OP_SRC_REG: 1205 case OP_SRC_REG:
1206 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) { 1206 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
1207 cfa->base == CFI_SP &&
1208 regs[CFI_BP].base == CFI_CFA &&
1209 regs[CFI_BP].offset == -cfa->offset) {
1210
1211 /* mov %rsp, %rbp */
1212 cfa->base = op->dest.reg;
1213 state->bp_scratch = false;
1214 }
1207 1215
1208 if (cfa->base == CFI_SP && 1216 else if (op->src.reg == CFI_SP &&
1209 regs[CFI_BP].base == CFI_CFA && 1217 op->dest.reg == CFI_BP && state->drap) {
1210 regs[CFI_BP].offset == -cfa->offset) {
1211 1218
1212 /* mov %rsp, %rbp */ 1219 /* drap: mov %rsp, %rbp */
1213 cfa->base = op->dest.reg; 1220 regs[CFI_BP].base = CFI_BP;
1214 state->bp_scratch = false; 1221 regs[CFI_BP].offset = -state->stack_size;
1215 } 1222 state->bp_scratch = false;
1223 }
1216 1224
1217 else if (state->drap) { 1225 else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1218 1226
1219 /* drap: mov %rsp, %rbp */ 1227 /*
1220 regs[CFI_BP].base = CFI_BP; 1228 * mov %rsp, %reg
1221 regs[CFI_BP].offset = -state->stack_size; 1229 *
1222 state->bp_scratch = false; 1230 * This is needed for the rare case where GCC
1223 } 1231 * does:
1232 *
1233 * mov %rsp, %rax
1234 * ...
1235 * mov %rax, %rsp
1236 */
1237 state->vals[op->dest.reg].base = CFI_CFA;
1238 state->vals[op->dest.reg].offset = -state->stack_size;
1224 } 1239 }
1225 1240
1226 else if (op->dest.reg == cfa->base) { 1241 else if (op->dest.reg == cfa->base) {
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 6e9f980a7d26..24460155c82c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -175,19 +175,20 @@ static int read_sections(struct elf *elf)
175 return -1; 175 return -1;
176 } 176 }
177 177
178 sec->data = elf_getdata(s, NULL); 178 if (sec->sh.sh_size != 0) {
179 if (!sec->data) { 179 sec->data = elf_getdata(s, NULL);
180 WARN_ELF("elf_getdata"); 180 if (!sec->data) {
181 return -1; 181 WARN_ELF("elf_getdata");
182 } 182 return -1;
183 183 }
184 if (sec->data->d_off != 0 || 184 if (sec->data->d_off != 0 ||
185 sec->data->d_size != sec->sh.sh_size) { 185 sec->data->d_size != sec->sh.sh_size) {
186 WARN("unexpected data attributes for %s", sec->name); 186 WARN("unexpected data attributes for %s",
187 return -1; 187 sec->name);
188 return -1;
189 }
188 } 190 }
189 191 sec->len = sec->sh.sh_size;
190 sec->len = sec->data->d_size;
191 } 192 }
192 193
193 /* sanity check, one more call to elf_nextscn() should return NULL */ 194 /* sanity check, one more call to elf_nextscn() should return NULL */
@@ -508,6 +509,7 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
508 strcat(relaname, base->name); 509 strcat(relaname, base->name);
509 510
510 sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0); 511 sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
512 free(relaname);
511 if (!sec) 513 if (!sec)
512 return NULL; 514 return NULL;
513 515
@@ -561,6 +563,7 @@ int elf_write(struct elf *elf)
561 struct section *sec; 563 struct section *sec;
562 Elf_Scn *s; 564 Elf_Scn *s;
563 565
566 /* Update section headers for changed sections: */
564 list_for_each_entry(sec, &elf->sections, list) { 567 list_for_each_entry(sec, &elf->sections, list) {
565 if (sec->changed) { 568 if (sec->changed) {
566 s = elf_getscn(elf->elf, sec->idx); 569 s = elf_getscn(elf->elf, sec->idx);
@@ -568,13 +571,17 @@ int elf_write(struct elf *elf)
568 WARN_ELF("elf_getscn"); 571 WARN_ELF("elf_getscn");
569 return -1; 572 return -1;
570 } 573 }
571 if (!gelf_update_shdr (s, &sec->sh)) { 574 if (!gelf_update_shdr(s, &sec->sh)) {
572 WARN_ELF("gelf_update_shdr"); 575 WARN_ELF("gelf_update_shdr");
573 return -1; 576 return -1;
574 } 577 }
575 } 578 }
576 } 579 }
577 580
581 /* Make sure the new section header entries get updated properly. */
582 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY);
583
584 /* Write all changes to the file. */
578 if (elf_update(elf->elf, ELF_C_WRITE) < 0) { 585 if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
579 WARN_ELF("elf_update"); 586 WARN_ELF("elf_update");
580 return -1; 587 return -1;
diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c
index ad54a58d7dda..9074b477bff0 100644
--- a/tools/pci/pcitest.c
+++ b/tools/pci/pcitest.c
@@ -173,6 +173,7 @@ usage:
173 "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" 173 "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n"
174 "\t-b <bar num> BAR test (bar number between 0..5)\n" 174 "\t-b <bar num> BAR test (bar number between 0..5)\n"
175 "\t-m <msi num> MSI test (msi number between 1..32)\n" 175 "\t-m <msi num> MSI test (msi number between 1..32)\n"
176 "\t-l Legacy IRQ test\n"
176 "\t-r Read buffer test\n" 177 "\t-r Read buffer test\n"
177 "\t-w Write buffer test\n" 178 "\t-w Write buffer test\n"
178 "\t-c Copy buffer test\n" 179 "\t-c Copy buffer test\n"
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index ab1b0825130a..76971d2e4164 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -873,7 +873,7 @@ amended to take the number of elements as a parameter.
873 873
874 $ cat ~/.perfconfig 874 $ cat ~/.perfconfig
875 [intel-pt] 875 [intel-pt]
876 mispred-all 876 mispred-all = on
877 877
878 $ perf record -e intel_pt//u ./sort 3000 878 $ perf record -e intel_pt//u ./sort 3000
879 Bubble sorting array of 3000 elements 879 Bubble sorting array of 3000 elements
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 73496320fca3..4be08a1e3f8d 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -59,6 +59,10 @@ OPTIONS
59--ldload:: 59--ldload::
60 Specify desired latency for loads event. 60 Specify desired latency for loads event.
61 61
62-p::
63--phys-data::
64 Record/Report sample physical addresses
65
62SEE ALSO 66SEE ALSO
63-------- 67--------
64linkperf:perf-record[1], linkperf:perf-report[1] 68linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 9bdea047c5db..e397453e5a46 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -249,7 +249,10 @@ OPTIONS
249 249
250-d:: 250-d::
251--data:: 251--data::
252 Record the sample addresses. 252 Record the sample virtual addresses.
253
254--phys-data::
255 Record the sample physical addresses.
253 256
254-T:: 257-T::
255--timestamp:: 258--timestamp::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9fa84617181e..383a98d992ed 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -137,6 +137,7 @@ OPTIONS
137 - mem: type of memory access for the data at the time of the sample 137 - mem: type of memory access for the data at the time of the sample
138 - snoop: type of snoop (if any) for the data at the time of the sample 138 - snoop: type of snoop (if any) for the data at the time of the sample
139 - dcacheline: the cacheline the data address is on at the time of the sample 139 - dcacheline: the cacheline the data address is on at the time of the sample
140 - phys_daddr: physical address of data being executed on at the time of sample
140 141
141 And the default sort keys are changed to local_weight, mem, sym, dso, 142 And the default sort keys are changed to local_weight, mem, sym, dso,
142 symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. 143 symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 5ee8796be96e..18dfcfa38454 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff, 119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff,
120 callindent, insn, insnlen, synth. 120 callindent, insn, insnlen, synth, phys_addr.
121 Field list can be prepended with the type, trace, sw or hw, 121 Field list can be prepended with the type, trace, sw or hw,
122 to indicate to which event type the field list applies. 122 to indicate to which event type the field list applies.
123 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace 123 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index c1e3288a2dfb..d53bea6bd571 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -37,7 +37,7 @@ OPTIONS
37--expr:: 37--expr::
38--event:: 38--event::
39 List of syscalls and other perf events (tracepoints, HW cache events, 39 List of syscalls and other perf events (tracepoints, HW cache events,
40 etc) to show. 40 etc) to show. Globbing is supported, e.g.: "epoll_*", "*msg*", etc.
41 See 'perf list' for a complete list of events. 41 See 'perf list' for a complete list of events.
42 Prefixing with ! shows all syscalls but the ones specified. You may 42 Prefixing with ! shows all syscalls but the ones specified. You may
43 need to escape it. 43 need to escape it.
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 62072822dc85..627b7cada144 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,34 +1,8 @@
1tools/perf 1tools/perf
2tools/arch/alpha/include/asm/barrier.h 2tools/arch
3tools/arch/arm/include/asm/barrier.h
4tools/arch/arm64/include/asm/barrier.h
5tools/arch/ia64/include/asm/barrier.h
6tools/arch/mips/include/asm/barrier.h
7tools/arch/powerpc/include/asm/barrier.h
8tools/arch/s390/include/asm/barrier.h
9tools/arch/sh/include/asm/barrier.h
10tools/arch/sparc/include/asm/barrier.h
11tools/arch/sparc/include/asm/barrier_32.h
12tools/arch/sparc/include/asm/barrier_64.h
13tools/arch/tile/include/asm/barrier.h
14tools/arch/x86/include/asm/barrier.h
15tools/arch/x86/include/asm/cmpxchg.h
16tools/arch/x86/include/asm/cpufeatures.h
17tools/arch/x86/include/asm/disabled-features.h
18tools/arch/x86/include/asm/required-features.h
19tools/arch/x86/include/uapi/asm/svm.h
20tools/arch/x86/include/uapi/asm/vmx.h
21tools/arch/x86/include/uapi/asm/kvm.h
22tools/arch/x86/include/uapi/asm/kvm_perf.h
23tools/arch/x86/lib/memcpy_64.S
24tools/arch/x86/lib/memset_64.S
25tools/arch/s390/include/uapi/asm/kvm_perf.h
26tools/arch/s390/include/uapi/asm/sie.h
27tools/arch/xtensa/include/asm/barrier.h
28tools/scripts 3tools/scripts
29tools/build 4tools/build
30tools/arch/x86/include/asm/atomic.h 5tools/include
31tools/arch/x86/include/asm/rmwcc.h
32tools/lib/traceevent 6tools/lib/traceevent
33tools/lib/api 7tools/lib/api
34tools/lib/bpf 8tools/lib/bpf
@@ -42,60 +16,3 @@ tools/lib/find_bit.c
42tools/lib/bitmap.c 16tools/lib/bitmap.c
43tools/lib/str_error_r.c 17tools/lib/str_error_r.c
44tools/lib/vsprintf.c 18tools/lib/vsprintf.c
45tools/include/asm/alternative-asm.h
46tools/include/asm/atomic.h
47tools/include/asm/barrier.h
48tools/include/asm/bug.h
49tools/include/asm-generic/atomic-gcc.h
50tools/include/asm-generic/barrier.h
51tools/include/asm-generic/bitops/arch_hweight.h
52tools/include/asm-generic/bitops/atomic.h
53tools/include/asm-generic/bitops/const_hweight.h
54tools/include/asm-generic/bitops/__ffs.h
55tools/include/asm-generic/bitops/__ffz.h
56tools/include/asm-generic/bitops/__fls.h
57tools/include/asm-generic/bitops/find.h
58tools/include/asm-generic/bitops/fls64.h
59tools/include/asm-generic/bitops/fls.h
60tools/include/asm-generic/bitops/hweight.h
61tools/include/asm-generic/bitops.h
62tools/include/linux/atomic.h
63tools/include/linux/bitops.h
64tools/include/linux/compiler.h
65tools/include/linux/compiler-gcc.h
66tools/include/linux/coresight-pmu.h
67tools/include/linux/bug.h
68tools/include/linux/filter.h
69tools/include/linux/hash.h
70tools/include/linux/kernel.h
71tools/include/linux/list.h
72tools/include/linux/log2.h
73tools/include/uapi/asm-generic/fcntl.h
74tools/include/uapi/asm-generic/ioctls.h
75tools/include/uapi/asm-generic/mman-common.h
76tools/include/uapi/asm-generic/mman.h
77tools/include/uapi/drm/drm.h
78tools/include/uapi/drm/i915_drm.h
79tools/include/uapi/linux/bpf.h
80tools/include/uapi/linux/bpf_common.h
81tools/include/uapi/linux/fcntl.h
82tools/include/uapi/linux/hw_breakpoint.h
83tools/include/uapi/linux/kvm.h
84tools/include/uapi/linux/mman.h
85tools/include/uapi/linux/perf_event.h
86tools/include/uapi/linux/sched.h
87tools/include/uapi/linux/stat.h
88tools/include/uapi/linux/vhost.h
89tools/include/uapi/sound/asound.h
90tools/include/linux/poison.h
91tools/include/linux/rbtree.h
92tools/include/linux/rbtree_augmented.h
93tools/include/linux/refcount.h
94tools/include/linux/string.h
95tools/include/linux/stringify.h
96tools/include/linux/types.h
97tools/include/linux/err.h
98tools/include/linux/bitmap.h
99tools/include/linux/time64.h
100tools/arch/*/include/uapi/asm/mman.h
101tools/arch/*/include/uapi/asm/perf_regs.h
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
index bd518b623d7a..5bd7b9260cc0 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -1,5 +1,4 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o
3libperf-y += kvm-stat.o 2libperf-y += kvm-stat.o
4 3
5libperf-$(CONFIG_DWARF) += dwarf-regs.o 4libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/s390/util/sym-handling.c b/tools/perf/arch/s390/util/sym-handling.c
deleted file mode 100644
index e103f6e46afe..000000000000
--- a/tools/perf/arch/s390/util/sym-handling.c
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * Architecture specific ELF symbol handling and relocation mapping.
3 *
4 * Copyright 2017 IBM Corp.
5 * Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
6 *
7 * 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 * as published by the Free Software Foundation.
10 */
11
12#include "symbol.h"
13
14#ifdef HAVE_LIBELF_SUPPORT
15bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
16{
17 if (ehdr.e_type == ET_EXEC)
18 return false;
19 return ehdr.e_type == ET_REL || ehdr.e_type == ET_DYN;
20}
21
22void arch__adjust_sym_map_offset(GElf_Sym *sym,
23 GElf_Shdr *shdr __maybe_unused,
24 struct map *map)
25{
26 if (map->type == MAP__FUNCTION)
27 sym->st_value += map->start;
28}
29#endif
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 3ddcc6e2abeb..a1d82e33282c 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -59,7 +59,7 @@ static int set_config(struct perf_config_set *set, const char *file_name,
59 fprintf(fp, "[%s]\n", section->name); 59 fprintf(fp, "[%s]\n", section->name);
60 60
61 perf_config_items__for_each_entry(&section->items, item) { 61 perf_config_items__for_each_entry(&section->items, item) {
62 if (!use_system_config && section->from_system_config) 62 if (!use_system_config && item->from_system_config)
63 continue; 63 continue;
64 if (item->value) 64 if (item->value)
65 fprintf(fp, "\t%s = %s\n", 65 fprintf(fp, "\t%s = %s\n",
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index a1497c516d85..24ee68ecdd42 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -627,7 +627,6 @@ static const struct {
627 { "GFP_HIGHUSER_MOVABLE", "HUM" }, 627 { "GFP_HIGHUSER_MOVABLE", "HUM" },
628 { "GFP_HIGHUSER", "HU" }, 628 { "GFP_HIGHUSER", "HU" },
629 { "GFP_USER", "U" }, 629 { "GFP_USER", "U" },
630 { "GFP_TEMPORARY", "TMP" },
631 { "GFP_KERNEL_ACCOUNT", "KAC" }, 630 { "GFP_KERNEL_ACCOUNT", "KAC" },
632 { "GFP_KERNEL", "K" }, 631 { "GFP_KERNEL", "K" },
633 { "GFP_NOFS", "NF" }, 632 { "GFP_NOFS", "NF" },
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index e001c0290793..0f15634ef82c 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -23,6 +23,7 @@ struct perf_mem {
23 bool hide_unresolved; 23 bool hide_unresolved;
24 bool dump_raw; 24 bool dump_raw;
25 bool force; 25 bool force;
26 bool phys_addr;
26 int operation; 27 int operation;
27 const char *cpu_list; 28 const char *cpu_list;
28 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -101,6 +102,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
101 102
102 rec_argv[i++] = "-d"; 103 rec_argv[i++] = "-d";
103 104
105 if (mem->phys_addr)
106 rec_argv[i++] = "--phys-data";
107
104 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 108 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
105 if (!perf_mem_events[j].record) 109 if (!perf_mem_events[j].record)
106 continue; 110 continue;
@@ -161,30 +165,60 @@ dump_raw_samples(struct perf_tool *tool,
161 if (al.map != NULL) 165 if (al.map != NULL)
162 al.map->dso->hit = 1; 166 al.map->dso->hit = 1;
163 167
164 if (symbol_conf.field_sep) { 168 if (mem->phys_addr) {
165 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64 169 if (symbol_conf.field_sep) {
166 "%s0x%"PRIx64"%s%s:%s\n"; 170 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s0x%016"PRIx64
171 "%s%"PRIu64"%s0x%"PRIx64"%s%s:%s\n";
172 } else {
173 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
174 "%s0x%016"PRIx64"%s%5"PRIu64"%s0x%06"PRIx64
175 "%s%s:%s\n";
176 symbol_conf.field_sep = " ";
177 }
178
179 printf(fmt,
180 sample->pid,
181 symbol_conf.field_sep,
182 sample->tid,
183 symbol_conf.field_sep,
184 sample->ip,
185 symbol_conf.field_sep,
186 sample->addr,
187 symbol_conf.field_sep,
188 sample->phys_addr,
189 symbol_conf.field_sep,
190 sample->weight,
191 symbol_conf.field_sep,
192 sample->data_src,
193 symbol_conf.field_sep,
194 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
195 al.sym ? al.sym->name : "???");
167 } else { 196 } else {
168 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64 197 if (symbol_conf.field_sep) {
169 "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n"; 198 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64
170 symbol_conf.field_sep = " "; 199 "%s0x%"PRIx64"%s%s:%s\n";
171 } 200 } else {
201 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
202 "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
203 symbol_conf.field_sep = " ";
204 }
172 205
173 printf(fmt, 206 printf(fmt,
174 sample->pid, 207 sample->pid,
175 symbol_conf.field_sep, 208 symbol_conf.field_sep,
176 sample->tid, 209 sample->tid,
177 symbol_conf.field_sep, 210 symbol_conf.field_sep,
178 sample->ip, 211 sample->ip,
179 symbol_conf.field_sep, 212 symbol_conf.field_sep,
180 sample->addr, 213 sample->addr,
181 symbol_conf.field_sep, 214 symbol_conf.field_sep,
182 sample->weight, 215 sample->weight,
183 symbol_conf.field_sep, 216 symbol_conf.field_sep,
184 sample->data_src, 217 sample->data_src,
185 symbol_conf.field_sep, 218 symbol_conf.field_sep,
186 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???", 219 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
187 al.sym ? al.sym->name : "???"); 220 al.sym ? al.sym->name : "???");
221 }
188out_put: 222out_put:
189 addr_location__put(&al); 223 addr_location__put(&al);
190 return 0; 224 return 0;
@@ -224,7 +258,10 @@ static int report_raw_events(struct perf_mem *mem)
224 if (ret < 0) 258 if (ret < 0)
225 goto out_delete; 259 goto out_delete;
226 260
227 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 261 if (mem->phys_addr)
262 printf("# PID, TID, IP, ADDR, PHYS ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
263 else
264 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
228 265
229 ret = perf_session__process_events(session); 266 ret = perf_session__process_events(session);
230 267
@@ -254,9 +291,16 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
254 * there is no weight (cost) associated with stores, so don't print 291 * there is no weight (cost) associated with stores, so don't print
255 * the column 292 * the column
256 */ 293 */
257 if (!(mem->operation & MEM_OPERATION_LOAD)) 294 if (!(mem->operation & MEM_OPERATION_LOAD)) {
258 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr," 295 if (mem->phys_addr)
259 "dso_daddr,tlb,locked"; 296 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
297 "dso_daddr,tlb,locked,phys_daddr";
298 else
299 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
300 "dso_daddr,tlb,locked";
301 } else if (mem->phys_addr)
302 rep_argv[i++] = "--sort=local_weight,mem,sym,dso,symbol_daddr,"
303 "dso_daddr,snoop,tlb,locked,phys_daddr";
260 304
261 for (j = 1; j < argc; j++, i++) 305 for (j = 1; j < argc; j++, i++)
262 rep_argv[i] = argv[j]; 306 rep_argv[i] = argv[j];
@@ -373,6 +417,7 @@ int cmd_mem(int argc, const char **argv)
373 "separator for columns, no spaces will be added" 417 "separator for columns, no spaces will be added"
374 " between columns '.' is reserved."), 418 " between columns '.' is reserved."),
375 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"), 419 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
420 OPT_BOOLEAN('p', "phys-data", &mem.phys_addr, "Record/Report sample physical addresses"),
376 OPT_END() 421 OPT_END()
377 }; 422 };
378 const char *const mem_subcommands[] = { "record", "report", NULL }; 423 const char *const mem_subcommands[] = { "record", "report", NULL };
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 36d7117a7562..56f8142ff97f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1604,6 +1604,8 @@ static struct option __record_options[] = {
1604 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1604 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1605 "per thread counts"), 1605 "per thread counts"),
1606 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1606 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
1607 OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
1608 "Record the sample physical addresses"),
1607 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 1609 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
1608 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1610 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
1609 &record.opts.sample_time_set, 1611 &record.opts.sample_time_set,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 378f76cdf923..3d4c3b5e1868 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -87,6 +87,7 @@ enum perf_output_field {
87 PERF_OUTPUT_BRSTACKINSN = 1U << 23, 87 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
88 PERF_OUTPUT_BRSTACKOFF = 1U << 24, 88 PERF_OUTPUT_BRSTACKOFF = 1U << 24,
89 PERF_OUTPUT_SYNTH = 1U << 25, 89 PERF_OUTPUT_SYNTH = 1U << 25,
90 PERF_OUTPUT_PHYS_ADDR = 1U << 26,
90}; 91};
91 92
92struct output_option { 93struct output_option {
@@ -119,6 +120,7 @@ struct output_option {
119 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, 120 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
120 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, 121 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
121 {.str = "synth", .field = PERF_OUTPUT_SYNTH}, 122 {.str = "synth", .field = PERF_OUTPUT_SYNTH},
123 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
122}; 124};
123 125
124enum { 126enum {
@@ -175,7 +177,8 @@ static struct {
175 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 177 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
176 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 178 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
177 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR | 179 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
178 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT, 180 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT |
181 PERF_OUTPUT_PHYS_ADDR,
179 182
180 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 183 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
181 }, 184 },
@@ -382,6 +385,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
382 PERF_OUTPUT_IREGS)) 385 PERF_OUTPUT_IREGS))
383 return -EINVAL; 386 return -EINVAL;
384 387
388 if (PRINT_FIELD(PHYS_ADDR) &&
389 perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
390 PERF_OUTPUT_PHYS_ADDR))
391 return -EINVAL;
392
385 return 0; 393 return 0;
386} 394}
387 395
@@ -1446,6 +1454,9 @@ static void process_event(struct perf_script *script,
1446 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 1454 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
1447 print_sample_bpf_output(sample); 1455 print_sample_bpf_output(sample);
1448 print_insn(sample, attr, thread, machine); 1456 print_insn(sample, attr, thread, machine);
1457
1458 if (PRINT_FIELD(PHYS_ADDR))
1459 printf("%16" PRIx64, sample->phys_addr);
1449 printf("\n"); 1460 printf("\n");
1450} 1461}
1451 1462
@@ -2729,7 +2740,7 @@ int cmd_script(int argc, const char **argv)
2729 "Valid types: hw,sw,trace,raw,synth. " 2740 "Valid types: hw,sw,trace,raw,synth. "
2730 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2741 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2731 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2742 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2732 "bpf-output,callindent,insn,insnlen,brstackinsn,synth", 2743 "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr",
2733 parse_output_fields), 2744 parse_output_fields),
2734 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2745 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2735 "system-wide collection from all CPUs"), 2746 "system-wide collection from all CPUs"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 866da7aa54bf..69523ed55894 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -707,7 +707,7 @@ try_again:
707 process_interval(); 707 process_interval();
708 } 708 }
709 } 709 }
710 wait(&status); 710 waitpid(child_pid, &status, 0);
711 711
712 if (workload_exec_errno) { 712 if (workload_exec_errno) {
713 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 713 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -1257,7 +1257,7 @@ static bool collect_data(struct perf_evsel *counter,
1257 if (counter->merged_stat) 1257 if (counter->merged_stat)
1258 return false; 1258 return false;
1259 cb(counter, data, true); 1259 cb(counter, data, true);
1260 if (!no_merge) 1260 if (!no_merge && counter->auto_merge_stats)
1261 collect_all_aliases(counter, cb, data); 1261 collect_all_aliases(counter, cb, data);
1262 return true; 1262 return true;
1263} 1263}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d59cdadf3a79..771ddab94bb0 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1261,6 +1261,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1261static int trace__validate_ev_qualifier(struct trace *trace) 1261static int trace__validate_ev_qualifier(struct trace *trace)
1262{ 1262{
1263 int err = 0, i; 1263 int err = 0, i;
1264 size_t nr_allocated;
1264 struct str_node *pos; 1265 struct str_node *pos;
1265 1266
1266 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier); 1267 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
@@ -1274,13 +1275,18 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1274 goto out; 1275 goto out;
1275 } 1276 }
1276 1277
1278 nr_allocated = trace->ev_qualifier_ids.nr;
1277 i = 0; 1279 i = 0;
1278 1280
1279 strlist__for_each_entry(pos, trace->ev_qualifier) { 1281 strlist__for_each_entry(pos, trace->ev_qualifier) {
1280 const char *sc = pos->s; 1282 const char *sc = pos->s;
1281 int id = syscalltbl__id(trace->sctbl, sc); 1283 int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
1282 1284
1283 if (id < 0) { 1285 if (id < 0) {
1286 id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
1287 if (id >= 0)
1288 goto matches;
1289
1284 if (err == 0) { 1290 if (err == 0) {
1285 fputs("Error:\tInvalid syscall ", trace->output); 1291 fputs("Error:\tInvalid syscall ", trace->output);
1286 err = -EINVAL; 1292 err = -EINVAL;
@@ -1290,13 +1296,37 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1290 1296
1291 fputs(sc, trace->output); 1297 fputs(sc, trace->output);
1292 } 1298 }
1293 1299matches:
1294 trace->ev_qualifier_ids.entries[i++] = id; 1300 trace->ev_qualifier_ids.entries[i++] = id;
1301 if (match_next == -1)
1302 continue;
1303
1304 while (1) {
1305 id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
1306 if (id < 0)
1307 break;
1308 if (nr_allocated == trace->ev_qualifier_ids.nr) {
1309 void *entries;
1310
1311 nr_allocated += 8;
1312 entries = realloc(trace->ev_qualifier_ids.entries,
1313 nr_allocated * sizeof(trace->ev_qualifier_ids.entries[0]));
1314 if (entries == NULL) {
1315 err = -ENOMEM;
1316 fputs("\nError:\t Not enough memory for parsing\n", trace->output);
1317 goto out_free;
1318 }
1319 trace->ev_qualifier_ids.entries = entries;
1320 }
1321 trace->ev_qualifier_ids.nr++;
1322 trace->ev_qualifier_ids.entries[i++] = id;
1323 }
1295 } 1324 }
1296 1325
1297 if (err < 0) { 1326 if (err < 0) {
1298 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'" 1327 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1299 "\nHint:\tand: 'man syscalls'\n", trace->output); 1328 "\nHint:\tand: 'man syscalls'\n", trace->output);
1329out_free:
1300 zfree(&trace->ev_qualifier_ids.entries); 1330 zfree(&trace->ev_qualifier_ids.entries);
1301 trace->ev_qualifier_ids.nr = 0; 1331 trace->ev_qualifier_ids.nr = 0;
1302 } 1332 }
@@ -2814,7 +2844,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
2814 struct trace *trace = (struct trace *)opt->value; 2844 struct trace *trace = (struct trace *)opt->value;
2815 const char *s = str; 2845 const char *s = str;
2816 char *sep = NULL, *lists[2] = { NULL, NULL, }; 2846 char *sep = NULL, *lists[2] = { NULL, NULL, };
2817 int len = strlen(str) + 1, err = -1, list; 2847 int len = strlen(str) + 1, err = -1, list, idx;
2818 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); 2848 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
2819 char group_name[PATH_MAX]; 2849 char group_name[PATH_MAX];
2820 2850
@@ -2831,7 +2861,8 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
2831 *sep = '\0'; 2861 *sep = '\0';
2832 2862
2833 list = 0; 2863 list = 0;
2834 if (syscalltbl__id(trace->sctbl, s) >= 0) { 2864 if (syscalltbl__id(trace->sctbl, s) >= 0 ||
2865 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
2835 list = 1; 2866 list = 1;
2836 } else { 2867 } else {
2837 path__join(group_name, sizeof(group_name), strace_groups_dir, s); 2868 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index e0279babe0c0..2f19e03c5c40 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -467,15 +467,21 @@ int main(int argc, const char **argv)
467 * - cannot execute it externally (since it would just do 467 * - cannot execute it externally (since it would just do
468 * the same thing over again) 468 * the same thing over again)
469 * 469 *
470 * So we just directly call the internal command handler, and 470 * So we just directly call the internal command handler. If that one
471 * die if that one cannot handle it. 471 * fails to handle this, then maybe we just run a renamed perf binary
472 * that contains a dash in its name. To handle this scenario, we just
473 * fall through and ignore the "xxxx" part of the command string.
472 */ 474 */
473 if (strstarts(cmd, "perf-")) { 475 if (strstarts(cmd, "perf-")) {
474 cmd += 5; 476 cmd += 5;
475 argv[0] = cmd; 477 argv[0] = cmd;
476 handle_internal_command(argc, argv); 478 handle_internal_command(argc, argv);
477 fprintf(stderr, "cannot handle %s internally", cmd); 479 /*
478 goto out; 480 * If the command is handled, the above function does not
481 * return undo changes and fall through in such a case.
482 */
483 cmd -= 5;
484 argv[0] = cmd;
479 } 485 }
480 if (strstarts(cmd, "trace")) { 486 if (strstarts(cmd, "trace")) {
481#ifdef HAVE_LIBAUDIT_SUPPORT 487#ifdef HAVE_LIBAUDIT_SUPPORT
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 2c010dd6a79d..dc442ba21bf6 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -43,6 +43,7 @@ struct record_opts {
43 bool no_samples; 43 bool no_samples;
44 bool raw_samples; 44 bool raw_samples;
45 bool sample_address; 45 bool sample_address;
46 bool sample_phys_addr;
46 bool sample_weight; 47 bool sample_weight;
47 bool sample_time; 48 bool sample_time;
48 bool sample_time_set; 49 bool sample_time_set;
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
index 7e62c46d7a20..c63a919eda98 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
@@ -80,11 +80,6 @@
80 "BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load." 80 "BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
81 }, 81 },
82 {, 82 {,
83 "EventCode": "0x400F0",
84 "EventName": "PM_LD_MISS_L1",
85 "BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
86 },
87 {,
88 "EventCode": "0x2E01A", 83 "EventCode": "0x2E01A",
89 "EventName": "PM_CMPLU_STALL_LSU_FLUSH_NEXT", 84 "EventName": "PM_CMPLU_STALL_LSU_FLUSH_NEXT",
90 "BriefDescription": "Completion stall of one cycle because the LSU requested to flush the next iop in the sequence. It takes 1 cycle for the ISU to process this request before the LSU instruction is allowed to complete" 85 "BriefDescription": "Completion stall of one cycle because the LSU requested to flush the next iop in the sequence. It takes 1 cycle for the ISU to process this request before the LSU instruction is allowed to complete"
@@ -374,4 +369,4 @@
374 "EventName": "PM_IPTEG_FROM_L31_ECO_MOD", 369 "EventName": "PM_IPTEG_FROM_L31_ECO_MOD",
375 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request" 370 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request"
376 } 371 }
377] \ No newline at end of file 372]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
index 00f3d2a21f31..54cc3be00fc2 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -605,11 +605,6 @@
605 "BriefDescription": "RC retries on PB for any load from core (excludes DCBFs)" 605 "BriefDescription": "RC retries on PB for any load from core (excludes DCBFs)"
606 }, 606 },
607 {, 607 {,
608 "EventCode": "0x3689E",
609 "EventName": "PM_L2_RTY_LD",
610 "BriefDescription": "RC retries on PB for any load from core (excludes DCBFs)"
611 },
612 {,
613 "EventCode": "0xE08C", 608 "EventCode": "0xE08C",
614 "EventName": "PM_LSU0_ERAT_HIT", 609 "EventName": "PM_LSU0_ERAT_HIT",
615 "BriefDescription": "Primary ERAT hit. There is no secondary ERAT" 610 "BriefDescription": "Primary ERAT hit. There is no secondary ERAT"
@@ -715,11 +710,6 @@
715 "BriefDescription": "Lifetime, sample of RD machine 0 valid" 710 "BriefDescription": "Lifetime, sample of RD machine 0 valid"
716 }, 711 },
717 {, 712 {,
718 "EventCode": "0x468B4",
719 "EventName": "PM_L3_RD0_BUSY",
720 "BriefDescription": "Lifetime, sample of RD machine 0 valid"
721 },
722 {,
723 "EventCode": "0x46080", 713 "EventCode": "0x46080",
724 "EventName": "PM_L2_DISP_ALL_L2MISS", 714 "EventName": "PM_L2_DISP_ALL_L2MISS",
725 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)" 715 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)"
@@ -850,21 +840,11 @@
850 "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC lifetime (mach0 used as sample point)" 840 "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC lifetime (mach0 used as sample point)"
851 }, 841 },
852 {, 842 {,
853 "EventCode": "0x2608C",
854 "EventName": "PM_RC0_BUSY",
855 "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC lifetime (mach0 used as sample point)"
856 },
857 {,
858 "EventCode": "0x36082", 843 "EventCode": "0x36082",
859 "EventName": "PM_L2_LD_DISP", 844 "EventName": "PM_L2_LD_DISP",
860 "BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)." 845 "BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)."
861 }, 846 },
862 {, 847 {,
863 "EventCode": "0x1609E",
864 "EventName": "PM_L2_LD_DISP",
865 "BriefDescription": "All successful D side load dispatches for this thread (L2 miss + L2 hits)"
866 },
867 {,
868 "EventCode": "0xF8B0", 848 "EventCode": "0xF8B0",
869 "EventName": "PM_L3_SW_PREF", 849 "EventName": "PM_L3_SW_PREF",
870 "BriefDescription": "L3 load prefetch, sourced from a software prefetch stream, was sent to the nest" 850 "BriefDescription": "L3 load prefetch, sourced from a software prefetch stream, was sent to the nest"
@@ -1040,11 +1020,6 @@
1040 "BriefDescription": "L3 castouts in Mepf state for this thread" 1020 "BriefDescription": "L3 castouts in Mepf state for this thread"
1041 }, 1021 },
1042 {, 1022 {,
1043 "EventCode": "0x168A0",
1044 "EventName": "PM_L3_CO_MEPF",
1045 "BriefDescription": "L3 CO of line in Mep state (includes casthrough to memory). The Mepf state indicates that a line was brought in to satisfy an L3 prefetch request"
1046 },
1047 {,
1048 "EventCode": "0x460A2", 1023 "EventCode": "0x460A2",
1049 "EventName": "PM_L3_LAT_CI_HIT", 1024 "EventName": "PM_L3_LAT_CI_HIT",
1050 "BriefDescription": "L3 Lateral Castins Hit" 1025 "BriefDescription": "L3 Lateral Castins Hit"
@@ -1150,11 +1125,6 @@
1150 "BriefDescription": "RC retries on PB for any store from core (excludes DCBFs)" 1125 "BriefDescription": "RC retries on PB for any store from core (excludes DCBFs)"
1151 }, 1126 },
1152 {, 1127 {,
1153 "EventCode": "0x4689E",
1154 "EventName": "PM_L2_RTY_ST",
1155 "BriefDescription": "RC retries on PB for any store from core (excludes DCBFs)"
1156 },
1157 {,
1158 "EventCode": "0x24040", 1128 "EventCode": "0x24040",
1159 "EventName": "PM_INST_FROM_L2_MEPF", 1129 "EventName": "PM_INST_FROM_L2_MEPF",
1160 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to an instruction fetch (not prefetch)" 1130 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to an instruction fetch (not prefetch)"
@@ -1255,11 +1225,6 @@
1255 "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave CO lifetime (mach0 used as sample point)" 1225 "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave CO lifetime (mach0 used as sample point)"
1256 }, 1226 },
1257 {, 1227 {,
1258 "EventCode": "0x4608C",
1259 "EventName": "PM_CO0_BUSY",
1260 "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave CO lifetime (mach0 used as sample point)"
1261 },
1262 {,
1263 "EventCode": "0x2C122", 1228 "EventCode": "0x2C122",
1264 "EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT_CYC", 1229 "EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT_CYC",
1265 "BriefDescription": "Duration in cycles to reload from local core's L3 with dispatch conflict due to a marked load" 1230 "BriefDescription": "Duration in cycles to reload from local core's L3 with dispatch conflict due to a marked load"
@@ -1395,11 +1360,6 @@
1395 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a instruction side request" 1360 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a instruction side request"
1396 }, 1361 },
1397 {, 1362 {,
1398 "EventCode": "0x40006",
1399 "EventName": "PM_ISLB_MISS",
1400 "BriefDescription": "Number of ISLB misses for this thread"
1401 },
1402 {,
1403 "EventCode": "0xD8A8", 1363 "EventCode": "0xD8A8",
1404 "EventName": "PM_ISLB_MISS", 1364 "EventName": "PM_ISLB_MISS",
1405 "BriefDescription": "Instruction SLB miss - Total of all segment sizes" 1365 "BriefDescription": "Instruction SLB miss - Total of all segment sizes"
@@ -1515,11 +1475,6 @@
1515 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)." 1475 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)."
1516 }, 1476 },
1517 {, 1477 {,
1518 "EventCode": "0x3609E",
1519 "EventName": "PM_L2_INST",
1520 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
1521 },
1522 {,
1523 "EventCode": "0x3504C", 1478 "EventCode": "0x3504C",
1524 "EventName": "PM_IPTEG_FROM_DL4", 1479 "EventName": "PM_IPTEG_FROM_DL4",
1525 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a instruction side request" 1480 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a instruction side request"
@@ -1690,11 +1645,6 @@
1690 "BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)" 1645 "BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)"
1691 }, 1646 },
1692 {, 1647 {,
1693 "EventCode": "0x2609E",
1694 "EventName": "PM_L2_LD_HIT",
1695 "BriefDescription": "All successful D side load dispatches for this thread that were L2 hits for this thread"
1696 },
1697 {,
1698 "EventCode": "0x168AC", 1648 "EventCode": "0x168AC",
1699 "EventName": "PM_L3_CI_USAGE", 1649 "EventName": "PM_L3_CI_USAGE",
1700 "BriefDescription": "Rotating sample of 16 CI or CO actives" 1650 "BriefDescription": "Rotating sample of 16 CI or CO actives"
@@ -1795,21 +1745,11 @@
1795 "BriefDescription": "Rotating sample of 8 WI valid" 1745 "BriefDescription": "Rotating sample of 8 WI valid"
1796 }, 1746 },
1797 {, 1747 {,
1798 "EventCode": "0x260B6",
1799 "EventName": "PM_L3_WI0_BUSY",
1800 "BriefDescription": "Rotating sample of 8 WI valid (duplicate)"
1801 },
1802 {,
1803 "EventCode": "0x368AC", 1748 "EventCode": "0x368AC",
1804 "EventName": "PM_L3_CO0_BUSY", 1749 "EventName": "PM_L3_CO0_BUSY",
1805 "BriefDescription": "Lifetime, sample of CO machine 0 valid" 1750 "BriefDescription": "Lifetime, sample of CO machine 0 valid"
1806 }, 1751 },
1807 {, 1752 {,
1808 "EventCode": "0x468AC",
1809 "EventName": "PM_L3_CO0_BUSY",
1810 "BriefDescription": "Lifetime, sample of CO machine 0 valid"
1811 },
1812 {,
1813 "EventCode": "0x2E040", 1753 "EventCode": "0x2E040",
1814 "EventName": "PM_DPTEG_FROM_L2_MEPF", 1754 "EventName": "PM_DPTEG_FROM_L2_MEPF",
1815 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 1755 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -1840,11 +1780,6 @@
1840 "BriefDescription": "L3 PF received retry port 0, every retry counted" 1780 "BriefDescription": "L3 PF received retry port 0, every retry counted"
1841 }, 1781 },
1842 {, 1782 {,
1843 "EventCode": "0x260AE",
1844 "EventName": "PM_L3_P0_PF_RTY",
1845 "BriefDescription": "L3 PF received retry port 0, every retry counted"
1846 },
1847 {,
1848 "EventCode": "0x268B2", 1783 "EventCode": "0x268B2",
1849 "EventName": "PM_L3_LOC_GUESS_WRONG", 1784 "EventName": "PM_L3_LOC_GUESS_WRONG",
1850 "BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low" 1785 "BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low"
@@ -1895,11 +1830,6 @@
1895 "BriefDescription": "Lifetime, sample of snooper machine 0 valid" 1830 "BriefDescription": "Lifetime, sample of snooper machine 0 valid"
1896 }, 1831 },
1897 {, 1832 {,
1898 "EventCode": "0x460AC",
1899 "EventName": "PM_L3_SN0_BUSY",
1900 "BriefDescription": "Lifetime, sample of snooper machine 0 valid"
1901 },
1902 {,
1903 "EventCode": "0x3005C", 1833 "EventCode": "0x3005C",
1904 "EventName": "PM_BFU_BUSY", 1834 "EventName": "PM_BFU_BUSY",
1905 "BriefDescription": "Cycles in which all 4 Binary Floating Point units are busy. The BFU is running at capacity" 1835 "BriefDescription": "Cycles in which all 4 Binary Floating Point units are busy. The BFU is running at capacity"
@@ -1935,11 +1865,6 @@
1935 "BriefDescription": "Lifetime, sample of PF machine 0 valid" 1865 "BriefDescription": "Lifetime, sample of PF machine 0 valid"
1936 }, 1866 },
1937 {, 1867 {,
1938 "EventCode": "0x460B4",
1939 "EventName": "PM_L3_PF0_BUSY",
1940 "BriefDescription": "Lifetime, sample of PF machine 0 valid"
1941 },
1942 {,
1943 "EventCode": "0xC0B0", 1868 "EventCode": "0xC0B0",
1944 "EventName": "PM_LSU_FLUSH_UE", 1869 "EventName": "PM_LSU_FLUSH_UE",
1945 "BriefDescription": "Correctable ECC error on reload data, reported at critical data forward time" 1870 "BriefDescription": "Correctable ECC error on reload data, reported at critical data forward time"
@@ -2085,11 +2010,6 @@
2085 "BriefDescription": "L3 CO received retry port 1 (memory only), every retry counted" 2010 "BriefDescription": "L3 CO received retry port 1 (memory only), every retry counted"
2086 }, 2011 },
2087 {, 2012 {,
2088 "EventCode": "0x468AE",
2089 "EventName": "PM_L3_P1_CO_RTY",
2090 "BriefDescription": "L3 CO received retry port 3 (memory only), every retry counted"
2091 },
2092 {,
2093 "EventCode": "0xC0AC", 2013 "EventCode": "0xC0AC",
2094 "EventName": "PM_LSU_FLUSH_EMSH", 2014 "EventName": "PM_LSU_FLUSH_EMSH",
2095 "BriefDescription": "An ERAT miss was detected after a set-p hit. Erat tracker indicates fail due to tlbmiss and the instruction gets flushed because the instruction was working on the wrong address" 2015 "BriefDescription": "An ERAT miss was detected after a set-p hit. Erat tracker indicates fail due to tlbmiss and the instruction gets flushed because the instruction was working on the wrong address"
@@ -2195,11 +2115,6 @@
2195 "BriefDescription": "SNP dispatched for a write and was M (true M); for DMA cacheinj this will pulse if rty/push is required (won't pulse if cacheinj is accepted)" 2115 "BriefDescription": "SNP dispatched for a write and was M (true M); for DMA cacheinj this will pulse if rty/push is required (won't pulse if cacheinj is accepted)"
2196 }, 2116 },
2197 {, 2117 {,
2198 "EventCode": "0x46886",
2199 "EventName": "PM_L2_SN_M_WR_DONE",
2200 "BriefDescription": "SNP dispatched for a write and was M (true M); for DMA cacheinj this will pulse if rty/push is required (won't pulse if cacheinj is accepted)"
2201 },
2202 {,
2203 "EventCode": "0x489C", 2118 "EventCode": "0x489C",
2204 "EventName": "PM_BR_CORECT_PRED_TAKEN_CMPL", 2119 "EventName": "PM_BR_CORECT_PRED_TAKEN_CMPL",
2205 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time" 2120 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time"
@@ -2290,21 +2205,11 @@
2290 "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave SN lifetime (mach0 used as sample point)" 2205 "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave SN lifetime (mach0 used as sample point)"
2291 }, 2206 },
2292 {, 2207 {,
2293 "EventCode": "0x26090",
2294 "EventName": "PM_SN0_BUSY",
2295 "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave SN lifetime (mach0 used as sample point)"
2296 },
2297 {,
2298 "EventCode": "0x360AE", 2208 "EventCode": "0x360AE",
2299 "EventName": "PM_L3_P0_CO_RTY", 2209 "EventName": "PM_L3_P0_CO_RTY",
2300 "BriefDescription": "L3 CO received retry port 0 (memory only), every retry counted" 2210 "BriefDescription": "L3 CO received retry port 0 (memory only), every retry counted"
2301 }, 2211 },
2302 {, 2212 {,
2303 "EventCode": "0x460AE",
2304 "EventName": "PM_L3_P0_CO_RTY",
2305 "BriefDescription": "L3 CO received retry port 0 (memory only), every retry counted"
2306 },
2307 {,
2308 "EventCode": "0x168A8", 2213 "EventCode": "0x168A8",
2309 "EventName": "PM_L3_WI_USAGE", 2214 "EventName": "PM_L3_WI_USAGE",
2310 "BriefDescription": "Lifetime, sample of Write Inject machine 0 valid" 2215 "BriefDescription": "Lifetime, sample of Write Inject machine 0 valid"
@@ -2340,26 +2245,11 @@
2340 "BriefDescription": "L3 PF received retry port 1, every retry counted" 2245 "BriefDescription": "L3 PF received retry port 1, every retry counted"
2341 }, 2246 },
2342 {, 2247 {,
2343 "EventCode": "0x268AE",
2344 "EventName": "PM_L3_P1_PF_RTY",
2345 "BriefDescription": "L3 PF received retry port 3, every retry counted"
2346 },
2347 {,
2348 "EventCode": "0x46082", 2248 "EventCode": "0x46082",
2349 "EventName": "PM_L2_ST_DISP", 2249 "EventName": "PM_L2_ST_DISP",
2350 "BriefDescription": "All successful D-side store dispatches for this thread " 2250 "BriefDescription": "All successful D-side store dispatches for this thread "
2351 }, 2251 },
2352 {, 2252 {,
2353 "EventCode": "0x1689E",
2354 "EventName": "PM_L2_ST_DISP",
2355 "BriefDescription": "All successful D-side store dispatches for this thread (L2 miss + L2 hits)"
2356 },
2357 {,
2358 "EventCode": "0x36880",
2359 "EventName": "PM_L2_INST_MISS",
2360 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
2361 },
2362 {,
2363 "EventCode": "0x4609E", 2253 "EventCode": "0x4609E",
2364 "EventName": "PM_L2_INST_MISS", 2254 "EventName": "PM_L2_INST_MISS",
2365 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)" 2255 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
@@ -2430,11 +2320,6 @@
2430 "BriefDescription": "# PPC Dispatched" 2320 "BriefDescription": "# PPC Dispatched"
2431 }, 2321 },
2432 {, 2322 {,
2433 "EventCode": "0x300F2",
2434 "EventName": "PM_INST_DISP",
2435 "BriefDescription": "# PPC Dispatched"
2436 },
2437 {,
2438 "EventCode": "0x4E05E", 2323 "EventCode": "0x4E05E",
2439 "EventName": "PM_TM_OUTER_TBEGIN_DISP", 2324 "EventName": "PM_TM_OUTER_TBEGIN_DISP",
2440 "BriefDescription": "Number of outer tbegin instructions dispatched. The dispatch unit determines whether the tbegin instruction is outer or nested. This is a speculative count, which includes flushed instructions" 2325 "BriefDescription": "Number of outer tbegin instructions dispatched. The dispatch unit determines whether the tbegin instruction is outer or nested. This is a speculative count, which includes flushed instructions"
@@ -2460,11 +2345,6 @@
2460 "BriefDescription": "All successful D-side store dispatches for this thread that were L2 hits" 2345 "BriefDescription": "All successful D-side store dispatches for this thread that were L2 hits"
2461 }, 2346 },
2462 {, 2347 {,
2463 "EventCode": "0x2689E",
2464 "EventName": "PM_L2_ST_HIT",
2465 "BriefDescription": "All successful D-side store dispatches that were L2 hits for this thread"
2466 },
2467 {,
2468 "EventCode": "0x360A8", 2348 "EventCode": "0x360A8",
2469 "EventName": "PM_L3_CO", 2349 "EventName": "PM_L3_CO",
2470 "BriefDescription": "L3 castout occurring (does not include casthrough or log writes (cinj/dmaw))" 2350 "BriefDescription": "L3 castout occurring (does not include casthrough or log writes (cinj/dmaw))"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
index 47a82568a8df..bc2db636dabf 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
@@ -420,11 +420,6 @@
420 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch" 420 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch"
421 }, 421 },
422 {, 422 {,
423 "EventCode": "0x10016",
424 "EventName": "PM_DSLB_MISS",
425 "BriefDescription": "Data SLB Miss - Total of all segment sizes"
426 },
427 {,
428 "EventCode": "0xD0A8", 423 "EventCode": "0xD0A8",
429 "EventName": "PM_DSLB_MISS", 424 "EventName": "PM_DSLB_MISS",
430 "BriefDescription": "Data SLB Miss - Total of all segment sizes" 425 "BriefDescription": "Data SLB Miss - Total of all segment sizes"
@@ -554,4 +549,4 @@
554 "EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC", 549 "EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC",
555 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load" 550 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load"
556 } 551 }
557] \ No newline at end of file 552]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
index a2c95a99e168..3ef8a10aac86 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
@@ -5,11 +5,6 @@
5 "BriefDescription": "Branches that are not strongly biased" 5 "BriefDescription": "Branches that are not strongly biased"
6 }, 6 },
7 {, 7 {,
8 "EventCode": "0x40036",
9 "EventName": "PM_BR_2PATH",
10 "BriefDescription": "Branches that are not strongly biased"
11 },
12 {,
13 "EventCode": "0x40056", 8 "EventCode": "0x40056",
14 "EventName": "PM_MEM_LOC_THRESH_LSU_HIGH", 9 "EventName": "PM_MEM_LOC_THRESH_LSU_HIGH",
15 "BriefDescription": "Local memory above threshold for LSU medium" 10 "BriefDescription": "Local memory above threshold for LSU medium"
@@ -124,4 +119,4 @@
124 "EventName": "PM_1FLOP_CMPL", 119 "EventName": "PM_1FLOP_CMPL",
125 "BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation completed" 120 "BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation completed"
126 } 121 }
127] \ No newline at end of file 122]
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 761c5a448c56..466a462b26d1 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -237,6 +237,11 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
237 237
238 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); 238 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
239 if (!al.map || !al.map->dso) { 239 if (!al.map || !al.map->dso) {
240 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
241 pr_debug("Hypervisor address can not be resolved - skipping\n");
242 return 0;
243 }
244
240 pr_debug("thread__find_addr_map failed\n"); 245 pr_debug("thread__find_addr_map failed\n");
241 return -1; 246 return -1;
242 } 247 }
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 2a7b9b47bbcb..9ba1d216a89f 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -6,7 +6,7 @@
6#include "debug.h" 6#include "debug.h"
7#include "machine.h" 7#include "machine.h"
8#include "event.h" 8#include "event.h"
9#include "unwind.h" 9#include "../util/unwind.h"
10#include "perf_regs.h" 10#include "perf_regs.h"
11#include "map.h" 11#include "map.h"
12#include "thread.h" 12#include "thread.h"
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 6d028f42b3cf..c3858487159d 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -141,6 +141,9 @@ static bool samples_same(const struct perf_sample *s1,
141 } 141 }
142 } 142 }
143 143
144 if (type & PERF_SAMPLE_PHYS_ADDR)
145 COMP(phys_addr);
146
144 return true; 147 return true;
145} 148}
146 149
@@ -206,6 +209,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
206 .mask = sample_regs, 209 .mask = sample_regs,
207 .regs = regs, 210 .regs = regs,
208 }, 211 },
212 .phys_addr = 113,
209 }; 213 };
210 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; 214 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
211 struct perf_sample sample_out; 215 struct perf_sample sample_out;
@@ -305,7 +309,7 @@ int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_u
305 * were added. Please actually update the test rather than just change 309 * were added. Please actually update the test rather than just change
306 * the condition below. 310 * the condition below.
307 */ 311 */
308 if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) { 312 if (PERF_SAMPLE_MAX > PERF_SAMPLE_PHYS_ADDR << 1) {
309 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); 313 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
310 return -1; 314 return -1;
311 } 315 }
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index ba0aee576a2b..786fecaf578e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -829,7 +829,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
829 "q/ESC/CTRL+C Exit\n\n" 829 "q/ESC/CTRL+C Exit\n\n"
830 "ENTER Go to target\n" 830 "ENTER Go to target\n"
831 "ESC Exit\n" 831 "ESC Exit\n"
832 "H Cycle thru hottest instructions\n" 832 "H Go to hottest instruction\n"
833 "TAB/shift+TAB Cycle thru hottest instructions\n"
833 "j Toggle showing jump to target arrows\n" 834 "j Toggle showing jump to target arrows\n"
834 "J Toggle showing number of jump sources on targets\n" 835 "J Toggle showing number of jump sources on targets\n"
835 "n Search next string\n" 836 "n Search next string\n"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index f4bc2462bc2c..13dfb0a0bdeb 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -931,12 +931,8 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
931 browser->show_dso); 931 browser->show_dso);
932 932
933 if (symbol_conf.show_branchflag_count) { 933 if (symbol_conf.show_branchflag_count) {
934 if (need_percent) 934 callchain_list_counts__printf_value(chain, NULL,
935 callchain_list_counts__printf_value(node, chain, NULL, 935 buf, sizeof(buf));
936 buf, sizeof(buf));
937 else
938 callchain_list_counts__printf_value(NULL, chain, NULL,
939 buf, sizeof(buf));
940 936
941 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0) 937 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
942 str = "Not enough memory!"; 938 str = "Not enough memory!";
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index a0f24c7115c5..ae91c8148edf 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,3 +1,4 @@
1#include <linux/kernel.h>
1#include "../cache.h" 2#include "../cache.h"
2#include "progress.h" 3#include "progress.h"
3 4
@@ -14,10 +15,14 @@ struct ui_progress_ops *ui_progress__ops = &null_progress__ops;
14 15
15void ui_progress__update(struct ui_progress *p, u64 adv) 16void ui_progress__update(struct ui_progress *p, u64 adv)
16{ 17{
18 u64 last = p->curr;
19
17 p->curr += adv; 20 p->curr += adv;
18 21
19 if (p->curr >= p->next) { 22 if (p->curr >= p->next) {
20 p->next += p->step; 23 u64 nr = DIV_ROUND_UP(p->curr - last, p->step);
24
25 p->next += nr * p->step;
21 ui_progress__ops->update(p); 26 ui_progress__ops->update(p);
22 } 27 }
23} 28}
@@ -25,7 +30,7 @@ void ui_progress__update(struct ui_progress *p, u64 adv)
25void ui_progress__init(struct ui_progress *p, u64 total, const char *title) 30void ui_progress__init(struct ui_progress *p, u64 total, const char *title)
26{ 31{
27 p->curr = 0; 32 p->curr = 0;
28 p->next = p->step = total / 16; 33 p->next = p->step = total / 16 ?: 1;
29 p->total = total; 34 p->total = total;
30 p->title = title; 35 p->title = title;
31 36
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 5c95b8301c67..8bdb7a500181 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -124,12 +124,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
124 str = callchain_list__sym_name(chain, bf, sizeof(bf), false); 124 str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
125 125
126 if (symbol_conf.show_branchflag_count) { 126 if (symbol_conf.show_branchflag_count) {
127 if (!period) 127 callchain_list_counts__printf_value(chain, NULL,
128 callchain_list_counts__printf_value(node, chain, NULL, 128 buf, sizeof(buf));
129 buf, sizeof(buf));
130 else
131 callchain_list_counts__printf_value(NULL, chain, NULL,
132 buf, sizeof(buf));
133 129
134 if (asprintf(&alloc_str, "%s%s", str, buf) < 0) 130 if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
135 str = "Not enough memory!"; 131 str = "Not enough memory!";
@@ -313,7 +309,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
313 309
314 if (symbol_conf.show_branchflag_count) 310 if (symbol_conf.show_branchflag_count)
315 ret += callchain_list_counts__printf_value( 311 ret += callchain_list_counts__printf_value(
316 NULL, chain, fp, NULL, 0); 312 chain, fp, NULL, 0);
317 ret += fprintf(fp, "\n"); 313 ret += fprintf(fp, "\n");
318 314
319 if (++entries_printed == callchain_param.print_limit) 315 if (++entries_printed == callchain_param.print_limit)
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index f320b0777e0d..be09d77cade0 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -65,8 +65,6 @@ static int parse_callchain_mode(const char *value)
65 callchain_param.mode = CHAIN_FOLDED; 65 callchain_param.mode = CHAIN_FOLDED;
66 return 0; 66 return 0;
67 } 67 }
68
69 pr_err("Invalid callchain mode: %s\n", value);
70 return -1; 68 return -1;
71} 69}
72 70
@@ -82,8 +80,6 @@ static int parse_callchain_order(const char *value)
82 callchain_param.order_set = true; 80 callchain_param.order_set = true;
83 return 0; 81 return 0;
84 } 82 }
85
86 pr_err("Invalid callchain order: %s\n", value);
87 return -1; 83 return -1;
88} 84}
89 85
@@ -105,8 +101,6 @@ static int parse_callchain_sort_key(const char *value)
105 callchain_param.branch_callstack = 1; 101 callchain_param.branch_callstack = 1;
106 return 0; 102 return 0;
107 } 103 }
108
109 pr_err("Invalid callchain sort key: %s\n", value);
110 return -1; 104 return -1;
111} 105}
112 106
@@ -124,8 +118,6 @@ static int parse_callchain_value(const char *value)
124 callchain_param.value = CCVAL_COUNT; 118 callchain_param.value = CCVAL_COUNT;
125 return 0; 119 return 0;
126 } 120 }
127
128 pr_err("Invalid callchain config key: %s\n", value);
129 return -1; 121 return -1;
130} 122}
131 123
@@ -319,12 +311,27 @@ int perf_callchain_config(const char *var, const char *value)
319 311
320 return ret; 312 return ret;
321 } 313 }
322 if (!strcmp(var, "print-type")) 314 if (!strcmp(var, "print-type")){
323 return parse_callchain_mode(value); 315 int ret;
324 if (!strcmp(var, "order")) 316 ret = parse_callchain_mode(value);
325 return parse_callchain_order(value); 317 if (ret == -1)
326 if (!strcmp(var, "sort-key")) 318 pr_err("Invalid callchain mode: %s\n", value);
327 return parse_callchain_sort_key(value); 319 return ret;
320 }
321 if (!strcmp(var, "order")){
322 int ret;
323 ret = parse_callchain_order(value);
324 if (ret == -1)
325 pr_err("Invalid callchain order: %s\n", value);
326 return ret;
327 }
328 if (!strcmp(var, "sort-key")){
329 int ret;
330 ret = parse_callchain_sort_key(value);
331 if (ret == -1)
332 pr_err("Invalid callchain sort key: %s\n", value);
333 return ret;
334 }
328 if (!strcmp(var, "threshold")) { 335 if (!strcmp(var, "threshold")) {
329 callchain_param.min_percent = strtod(value, &endptr); 336 callchain_param.min_percent = strtod(value, &endptr);
330 if (value == endptr) { 337 if (value == endptr) {
@@ -588,7 +595,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
588 call->cycles_count = 595 call->cycles_count =
589 cursor_node->branch_flags.cycles; 596 cursor_node->branch_flags.cycles;
590 call->iter_count = cursor_node->nr_loop_iter; 597 call->iter_count = cursor_node->nr_loop_iter;
591 call->samples_count = cursor_node->samples; 598 call->iter_cycles = cursor_node->iter_cycles;
592 } 599 }
593 } 600 }
594 601
@@ -722,7 +729,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
722 cnode->cycles_count += 729 cnode->cycles_count +=
723 node->branch_flags.cycles; 730 node->branch_flags.cycles;
724 cnode->iter_count += node->nr_loop_iter; 731 cnode->iter_count += node->nr_loop_iter;
725 cnode->samples_count += node->samples; 732 cnode->iter_cycles += node->iter_cycles;
726 } 733 }
727 } 734 }
728 735
@@ -998,7 +1005,7 @@ int callchain_merge(struct callchain_cursor *cursor,
998int callchain_cursor_append(struct callchain_cursor *cursor, 1005int callchain_cursor_append(struct callchain_cursor *cursor,
999 u64 ip, struct map *map, struct symbol *sym, 1006 u64 ip, struct map *map, struct symbol *sym,
1000 bool branch, struct branch_flags *flags, 1007 bool branch, struct branch_flags *flags,
1001 int nr_loop_iter, int samples, u64 branch_from) 1008 int nr_loop_iter, u64 iter_cycles, u64 branch_from)
1002{ 1009{
1003 struct callchain_cursor_node *node = *cursor->last; 1010 struct callchain_cursor_node *node = *cursor->last;
1004 1011
@@ -1016,7 +1023,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
1016 node->sym = sym; 1023 node->sym = sym;
1017 node->branch = branch; 1024 node->branch = branch;
1018 node->nr_loop_iter = nr_loop_iter; 1025 node->nr_loop_iter = nr_loop_iter;
1019 node->samples = samples; 1026 node->iter_cycles = iter_cycles;
1020 1027
1021 if (flags) 1028 if (flags)
1022 memcpy(&node->branch_flags, flags, 1029 memcpy(&node->branch_flags, flags,
@@ -1306,7 +1313,7 @@ static int branch_to_str(char *bf, int bfsize,
1306static int branch_from_str(char *bf, int bfsize, 1313static int branch_from_str(char *bf, int bfsize,
1307 u64 branch_count, 1314 u64 branch_count,
1308 u64 cycles_count, u64 iter_count, 1315 u64 cycles_count, u64 iter_count,
1309 u64 samples_count) 1316 u64 iter_cycles)
1310{ 1317{
1311 int printed = 0, i = 0; 1318 int printed = 0, i = 0;
1312 u64 cycles; 1319 u64 cycles;
@@ -1318,9 +1325,13 @@ static int branch_from_str(char *bf, int bfsize,
1318 bf + printed, bfsize - printed); 1325 bf + printed, bfsize - printed);
1319 } 1326 }
1320 1327
1321 if (iter_count && samples_count) { 1328 if (iter_count) {
1322 printed += count_pri64_printf(i++, "iterations", 1329 printed += count_pri64_printf(i++, "iter",
1323 iter_count / samples_count, 1330 iter_count,
1331 bf + printed, bfsize - printed);
1332
1333 printed += count_pri64_printf(i++, "avg_cycles",
1334 iter_cycles / iter_count,
1324 bf + printed, bfsize - printed); 1335 bf + printed, bfsize - printed);
1325 } 1336 }
1326 1337
@@ -1333,7 +1344,7 @@ static int branch_from_str(char *bf, int bfsize,
1333static int counts_str_build(char *bf, int bfsize, 1344static int counts_str_build(char *bf, int bfsize,
1334 u64 branch_count, u64 predicted_count, 1345 u64 branch_count, u64 predicted_count,
1335 u64 abort_count, u64 cycles_count, 1346 u64 abort_count, u64 cycles_count,
1336 u64 iter_count, u64 samples_count, 1347 u64 iter_count, u64 iter_cycles,
1337 struct branch_type_stat *brtype_stat) 1348 struct branch_type_stat *brtype_stat)
1338{ 1349{
1339 int printed; 1350 int printed;
@@ -1346,7 +1357,7 @@ static int counts_str_build(char *bf, int bfsize,
1346 predicted_count, abort_count, brtype_stat); 1357 predicted_count, abort_count, brtype_stat);
1347 } else { 1358 } else {
1348 printed = branch_from_str(bf, bfsize, branch_count, 1359 printed = branch_from_str(bf, bfsize, branch_count,
1349 cycles_count, iter_count, samples_count); 1360 cycles_count, iter_count, iter_cycles);
1350 } 1361 }
1351 1362
1352 if (!printed) 1363 if (!printed)
@@ -1358,14 +1369,14 @@ static int counts_str_build(char *bf, int bfsize,
1358static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, 1369static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1359 u64 branch_count, u64 predicted_count, 1370 u64 branch_count, u64 predicted_count,
1360 u64 abort_count, u64 cycles_count, 1371 u64 abort_count, u64 cycles_count,
1361 u64 iter_count, u64 samples_count, 1372 u64 iter_count, u64 iter_cycles,
1362 struct branch_type_stat *brtype_stat) 1373 struct branch_type_stat *brtype_stat)
1363{ 1374{
1364 char str[256]; 1375 char str[256];
1365 1376
1366 counts_str_build(str, sizeof(str), branch_count, 1377 counts_str_build(str, sizeof(str), branch_count,
1367 predicted_count, abort_count, cycles_count, 1378 predicted_count, abort_count, cycles_count,
1368 iter_count, samples_count, brtype_stat); 1379 iter_count, iter_cycles, brtype_stat);
1369 1380
1370 if (fp) 1381 if (fp)
1371 return fprintf(fp, "%s", str); 1382 return fprintf(fp, "%s", str);
@@ -1373,31 +1384,23 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1373 return scnprintf(bf, bfsize, "%s", str); 1384 return scnprintf(bf, bfsize, "%s", str);
1374} 1385}
1375 1386
1376int callchain_list_counts__printf_value(struct callchain_node *node, 1387int callchain_list_counts__printf_value(struct callchain_list *clist,
1377 struct callchain_list *clist,
1378 FILE *fp, char *bf, int bfsize) 1388 FILE *fp, char *bf, int bfsize)
1379{ 1389{
1380 u64 branch_count, predicted_count; 1390 u64 branch_count, predicted_count;
1381 u64 abort_count, cycles_count; 1391 u64 abort_count, cycles_count;
1382 u64 iter_count = 0, samples_count = 0; 1392 u64 iter_count, iter_cycles;
1383 1393
1384 branch_count = clist->branch_count; 1394 branch_count = clist->branch_count;
1385 predicted_count = clist->predicted_count; 1395 predicted_count = clist->predicted_count;
1386 abort_count = clist->abort_count; 1396 abort_count = clist->abort_count;
1387 cycles_count = clist->cycles_count; 1397 cycles_count = clist->cycles_count;
1388 1398 iter_count = clist->iter_count;
1389 if (node) { 1399 iter_cycles = clist->iter_cycles;
1390 struct callchain_list *call;
1391
1392 list_for_each_entry(call, &node->val, list) {
1393 iter_count += call->iter_count;
1394 samples_count += call->samples_count;
1395 }
1396 }
1397 1400
1398 return callchain_counts_printf(fp, bf, bfsize, branch_count, 1401 return callchain_counts_printf(fp, bf, bfsize, branch_count,
1399 predicted_count, abort_count, 1402 predicted_count, abort_count,
1400 cycles_count, iter_count, samples_count, 1403 cycles_count, iter_count, iter_cycles,
1401 &clist->brtype_stat); 1404 &clist->brtype_stat);
1402} 1405}
1403 1406
@@ -1523,7 +1526,8 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
1523 1526
1524 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym, 1527 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
1525 node->branch, &node->branch_flags, 1528 node->branch, &node->branch_flags,
1526 node->nr_loop_iter, node->samples, 1529 node->nr_loop_iter,
1530 node->iter_cycles,
1527 node->branch_from); 1531 node->branch_from);
1528 if (rc) 1532 if (rc)
1529 break; 1533 break;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 97738201464a..1ed6fc61d0a5 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -119,7 +119,7 @@ struct callchain_list {
119 u64 abort_count; 119 u64 abort_count;
120 u64 cycles_count; 120 u64 cycles_count;
121 u64 iter_count; 121 u64 iter_count;
122 u64 samples_count; 122 u64 iter_cycles;
123 struct branch_type_stat brtype_stat; 123 struct branch_type_stat brtype_stat;
124 char *srcline; 124 char *srcline;
125 struct list_head list; 125 struct list_head list;
@@ -139,7 +139,7 @@ struct callchain_cursor_node {
139 struct branch_flags branch_flags; 139 struct branch_flags branch_flags;
140 u64 branch_from; 140 u64 branch_from;
141 int nr_loop_iter; 141 int nr_loop_iter;
142 int samples; 142 u64 iter_cycles;
143 struct callchain_cursor_node *next; 143 struct callchain_cursor_node *next;
144}; 144};
145 145
@@ -201,7 +201,7 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
201int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, 201int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
202 struct map *map, struct symbol *sym, 202 struct map *map, struct symbol *sym,
203 bool branch, struct branch_flags *flags, 203 bool branch, struct branch_flags *flags,
204 int nr_loop_iter, int samples, u64 branch_from); 204 int nr_loop_iter, u64 iter_cycles, u64 branch_from);
205 205
206/* Close a cursor writing session. Initialize for the reader */ 206/* Close a cursor writing session. Initialize for the reader */
207static inline void callchain_cursor_commit(struct callchain_cursor *cursor) 207static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
@@ -282,8 +282,7 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
282int callchain_node__fprintf_value(struct callchain_node *node, 282int callchain_node__fprintf_value(struct callchain_node *node,
283 FILE *fp, u64 total); 283 FILE *fp, u64 total);
284 284
285int callchain_list_counts__printf_value(struct callchain_node *node, 285int callchain_list_counts__printf_value(struct callchain_list *clist,
286 struct callchain_list *clist,
287 FILE *fp, char *bf, int bfsize); 286 FILE *fp, char *bf, int bfsize);
288 287
289void free_callchain(struct callchain_root *root); 288void free_callchain(struct callchain_root *root);
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index e84bbc8ec058..263f5a906ba5 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -10,6 +10,16 @@
10#include "util.h" 10#include "util.h"
11#include "debug.h" 11#include "debug.h"
12 12
13#ifndef O_CLOEXEC
14#ifdef __sparc__
15#define O_CLOEXEC 0x400000
16#elif defined(__alpha__) || defined(__hppa__)
17#define O_CLOEXEC 010000000
18#else
19#define O_CLOEXEC 02000000
20#endif
21#endif
22
13static bool check_pipe(struct perf_data_file *file) 23static bool check_pipe(struct perf_data_file *file)
14{ 24{
15 struct stat st; 25 struct stat st;
@@ -96,7 +106,8 @@ static int open_file_write(struct perf_data_file *file)
96 if (check_backup(file)) 106 if (check_backup(file))
97 return -1; 107 return -1;
98 108
99 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 109 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
110 S_IRUSR|S_IWUSR);
100 111
101 if (fd < 0) 112 if (fd < 0)
102 pr_err("failed to open %s : %s\n", file->path, 113 pr_err("failed to open %s : %s\n", file->path,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 423ac82605f3..ee7bcc898d35 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -200,6 +200,7 @@ struct perf_sample {
200 u32 cpu; 200 u32 cpu;
201 u32 raw_size; 201 u32 raw_size;
202 u64 data_src; 202 u64 data_src;
203 u64 phys_addr;
203 u32 flags; 204 u32 flags;
204 u16 insn_len; 205 u16 insn_len;
205 u8 cpumode; 206 u8 cpumode;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d9bd632ed7db..0dccdb89572c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -271,12 +271,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
271 return evsel; 271 return evsel;
272} 272}
273 273
274static bool perf_event_can_profile_kernel(void)
275{
276 return geteuid() == 0 || perf_event_paranoid() == -1;
277}
278
274struct perf_evsel *perf_evsel__new_cycles(bool precise) 279struct perf_evsel *perf_evsel__new_cycles(bool precise)
275{ 280{
276 struct perf_event_attr attr = { 281 struct perf_event_attr attr = {
277 .type = PERF_TYPE_HARDWARE, 282 .type = PERF_TYPE_HARDWARE,
278 .config = PERF_COUNT_HW_CPU_CYCLES, 283 .config = PERF_COUNT_HW_CPU_CYCLES,
279 .exclude_kernel = geteuid() != 0, 284 .exclude_kernel = !perf_event_can_profile_kernel(),
280 }; 285 };
281 struct perf_evsel *evsel; 286 struct perf_evsel *evsel;
282 287
@@ -955,6 +960,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
955 if (opts->sample_address) 960 if (opts->sample_address)
956 perf_evsel__set_sample_bit(evsel, DATA_SRC); 961 perf_evsel__set_sample_bit(evsel, DATA_SRC);
957 962
963 if (opts->sample_phys_addr)
964 perf_evsel__set_sample_bit(evsel, PHYS_ADDR);
965
958 if (opts->no_buffering) { 966 if (opts->no_buffering) {
959 attr->watermark = 0; 967 attr->watermark = 0;
960 attr->wakeup_events = 1; 968 attr->wakeup_events = 1;
@@ -1464,7 +1472,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1464 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1472 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1465 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1473 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1466 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC), 1474 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
1467 bit_name(WEIGHT), 1475 bit_name(WEIGHT), bit_name(PHYS_ADDR),
1468 { .name = NULL, } 1476 { .name = NULL, }
1469 }; 1477 };
1470#undef bit_name 1478#undef bit_name
@@ -2206,6 +2214,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
2206 } 2214 }
2207 } 2215 }
2208 2216
2217 data->phys_addr = 0;
2218 if (type & PERF_SAMPLE_PHYS_ADDR) {
2219 data->phys_addr = *array;
2220 array++;
2221 }
2222
2209 return 0; 2223 return 0;
2210} 2224}
2211 2225
@@ -2311,6 +2325,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
2311 } 2325 }
2312 } 2326 }
2313 2327
2328 if (type & PERF_SAMPLE_PHYS_ADDR)
2329 result += sizeof(u64);
2330
2314 return result; 2331 return result;
2315} 2332}
2316 2333
@@ -2500,6 +2517,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2500 } 2517 }
2501 } 2518 }
2502 2519
2520 if (type & PERF_SAMPLE_PHYS_ADDR) {
2521 *array = sample->phys_addr;
2522 array++;
2523 }
2524
2503 return 0; 2525 return 0;
2504} 2526}
2505 2527
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 351d3b2d8887..dd2c4b5112a5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -131,6 +131,7 @@ struct perf_evsel {
131 bool cmdline_group_boundary; 131 bool cmdline_group_boundary;
132 struct list_head config_terms; 132 struct list_head config_terms;
133 int bpf_fd; 133 int bpf_fd;
134 bool auto_merge_stats;
134 bool merged_stat; 135 bool merged_stat;
135 const char * metric_expr; 136 const char * metric_expr;
136 const char * metric_name; 137 const char * metric_name;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9453b2e27015..e60d8d8ea4c2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -167,6 +167,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
167 symlen = unresolved_col_width + 4 + 2; 167 symlen = unresolved_col_width + 4 + 2;
168 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 168 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
169 } 169 }
170
171 hists__new_col_len(hists, HISTC_MEM_PHYS_DADDR,
172 unresolved_col_width + 4 + 2);
173
170 } else { 174 } else {
171 symlen = unresolved_col_width + 4 + 2; 175 symlen = unresolved_col_width + 4 + 2;
172 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); 176 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ee3670a388df..e60dda26a920 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -47,6 +47,7 @@ enum hist_column {
47 HISTC_GLOBAL_WEIGHT, 47 HISTC_GLOBAL_WEIGHT,
48 HISTC_MEM_DADDR_SYMBOL, 48 HISTC_MEM_DADDR_SYMBOL,
49 HISTC_MEM_DADDR_DSO, 49 HISTC_MEM_DADDR_DSO,
50 HISTC_MEM_PHYS_DADDR,
50 HISTC_MEM_LOCKED, 51 HISTC_MEM_LOCKED,
51 HISTC_MEM_TLB, 52 HISTC_MEM_TLB,
52 HISTC_MEM_LVL, 53 HISTC_MEM_LVL,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 5c8eacaca4f4..df709363ef69 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1635,10 +1635,12 @@ static void ip__resolve_ams(struct thread *thread,
1635 ams->al_addr = al.addr; 1635 ams->al_addr = al.addr;
1636 ams->sym = al.sym; 1636 ams->sym = al.sym;
1637 ams->map = al.map; 1637 ams->map = al.map;
1638 ams->phys_addr = 0;
1638} 1639}
1639 1640
1640static void ip__resolve_data(struct thread *thread, 1641static void ip__resolve_data(struct thread *thread,
1641 u8 m, struct addr_map_symbol *ams, u64 addr) 1642 u8 m, struct addr_map_symbol *ams,
1643 u64 addr, u64 phys_addr)
1642{ 1644{
1643 struct addr_location al; 1645 struct addr_location al;
1644 1646
@@ -1658,6 +1660,7 @@ static void ip__resolve_data(struct thread *thread,
1658 ams->al_addr = al.addr; 1660 ams->al_addr = al.addr;
1659 ams->sym = al.sym; 1661 ams->sym = al.sym;
1660 ams->map = al.map; 1662 ams->map = al.map;
1663 ams->phys_addr = phys_addr;
1661} 1664}
1662 1665
1663struct mem_info *sample__resolve_mem(struct perf_sample *sample, 1666struct mem_info *sample__resolve_mem(struct perf_sample *sample,
@@ -1669,12 +1672,18 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1669 return NULL; 1672 return NULL;
1670 1673
1671 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip); 1674 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
1672 ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr); 1675 ip__resolve_data(al->thread, al->cpumode, &mi->daddr,
1676 sample->addr, sample->phys_addr);
1673 mi->data_src.val = sample->data_src; 1677 mi->data_src.val = sample->data_src;
1674 1678
1675 return mi; 1679 return mi;
1676} 1680}
1677 1681
1682struct iterations {
1683 int nr_loop_iter;
1684 u64 cycles;
1685};
1686
1678static int add_callchain_ip(struct thread *thread, 1687static int add_callchain_ip(struct thread *thread,
1679 struct callchain_cursor *cursor, 1688 struct callchain_cursor *cursor,
1680 struct symbol **parent, 1689 struct symbol **parent,
@@ -1683,11 +1692,12 @@ static int add_callchain_ip(struct thread *thread,
1683 u64 ip, 1692 u64 ip,
1684 bool branch, 1693 bool branch,
1685 struct branch_flags *flags, 1694 struct branch_flags *flags,
1686 int nr_loop_iter, 1695 struct iterations *iter,
1687 int samples,
1688 u64 branch_from) 1696 u64 branch_from)
1689{ 1697{
1690 struct addr_location al; 1698 struct addr_location al;
1699 int nr_loop_iter = 0;
1700 u64 iter_cycles = 0;
1691 1701
1692 al.filtered = 0; 1702 al.filtered = 0;
1693 al.sym = NULL; 1703 al.sym = NULL;
@@ -1737,9 +1747,15 @@ static int add_callchain_ip(struct thread *thread,
1737 1747
1738 if (symbol_conf.hide_unresolved && al.sym == NULL) 1748 if (symbol_conf.hide_unresolved && al.sym == NULL)
1739 return 0; 1749 return 0;
1750
1751 if (iter) {
1752 nr_loop_iter = iter->nr_loop_iter;
1753 iter_cycles = iter->cycles;
1754 }
1755
1740 return callchain_cursor_append(cursor, al.addr, al.map, al.sym, 1756 return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
1741 branch, flags, nr_loop_iter, samples, 1757 branch, flags, nr_loop_iter,
1742 branch_from); 1758 iter_cycles, branch_from);
1743} 1759}
1744 1760
1745struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1761struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1760,6 +1776,18 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1760 return bi; 1776 return bi;
1761} 1777}
1762 1778
1779static void save_iterations(struct iterations *iter,
1780 struct branch_entry *be, int nr)
1781{
1782 int i;
1783
1784 iter->nr_loop_iter = nr;
1785 iter->cycles = 0;
1786
1787 for (i = 0; i < nr; i++)
1788 iter->cycles += be[i].flags.cycles;
1789}
1790
1763#define CHASHSZ 127 1791#define CHASHSZ 127
1764#define CHASHBITS 7 1792#define CHASHBITS 7
1765#define NO_ENTRY 0xff 1793#define NO_ENTRY 0xff
@@ -1767,7 +1795,8 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1767#define PERF_MAX_BRANCH_DEPTH 127 1795#define PERF_MAX_BRANCH_DEPTH 127
1768 1796
1769/* Remove loops. */ 1797/* Remove loops. */
1770static int remove_loops(struct branch_entry *l, int nr) 1798static int remove_loops(struct branch_entry *l, int nr,
1799 struct iterations *iter)
1771{ 1800{
1772 int i, j, off; 1801 int i, j, off;
1773 unsigned char chash[CHASHSZ]; 1802 unsigned char chash[CHASHSZ];
@@ -1792,8 +1821,18 @@ static int remove_loops(struct branch_entry *l, int nr)
1792 break; 1821 break;
1793 } 1822 }
1794 if (is_loop) { 1823 if (is_loop) {
1795 memmove(l + i, l + i + off, 1824 j = nr - (i + off);
1796 (nr - (i + off)) * sizeof(*l)); 1825 if (j > 0) {
1826 save_iterations(iter + i + off,
1827 l + i, off);
1828
1829 memmove(iter + i, iter + i + off,
1830 j * sizeof(*iter));
1831
1832 memmove(l + i, l + i + off,
1833 j * sizeof(*l));
1834 }
1835
1797 nr -= off; 1836 nr -= off;
1798 } 1837 }
1799 } 1838 }
@@ -1883,7 +1922,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1883 1922
1884 err = add_callchain_ip(thread, cursor, parent, 1923 err = add_callchain_ip(thread, cursor, parent,
1885 root_al, &cpumode, ip, 1924 root_al, &cpumode, ip,
1886 branch, flags, 0, 0, 1925 branch, flags, NULL,
1887 branch_from); 1926 branch_from);
1888 if (err) 1927 if (err)
1889 return (err < 0) ? err : 0; 1928 return (err < 0) ? err : 0;
@@ -1909,7 +1948,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1909 int i, j, err, nr_entries; 1948 int i, j, err, nr_entries;
1910 int skip_idx = -1; 1949 int skip_idx = -1;
1911 int first_call = 0; 1950 int first_call = 0;
1912 int nr_loop_iter;
1913 1951
1914 if (chain) 1952 if (chain)
1915 chain_nr = chain->nr; 1953 chain_nr = chain->nr;
@@ -1942,6 +1980,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1942 if (branch && callchain_param.branch_callstack) { 1980 if (branch && callchain_param.branch_callstack) {
1943 int nr = min(max_stack, (int)branch->nr); 1981 int nr = min(max_stack, (int)branch->nr);
1944 struct branch_entry be[nr]; 1982 struct branch_entry be[nr];
1983 struct iterations iter[nr];
1945 1984
1946 if (branch->nr > PERF_MAX_BRANCH_DEPTH) { 1985 if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
1947 pr_warning("corrupted branch chain. skipping...\n"); 1986 pr_warning("corrupted branch chain. skipping...\n");
@@ -1972,38 +2011,21 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1972 be[i] = branch->entries[branch->nr - i - 1]; 2011 be[i] = branch->entries[branch->nr - i - 1];
1973 } 2012 }
1974 2013
1975 nr_loop_iter = nr; 2014 memset(iter, 0, sizeof(struct iterations) * nr);
1976 nr = remove_loops(be, nr); 2015 nr = remove_loops(be, nr, iter);
1977
1978 /*
1979 * Get the number of iterations.
1980 * It's only approximation, but good enough in practice.
1981 */
1982 if (nr_loop_iter > nr)
1983 nr_loop_iter = nr_loop_iter - nr + 1;
1984 else
1985 nr_loop_iter = 0;
1986 2016
1987 for (i = 0; i < nr; i++) { 2017 for (i = 0; i < nr; i++) {
1988 if (i == nr - 1) 2018 err = add_callchain_ip(thread, cursor, parent,
1989 err = add_callchain_ip(thread, cursor, parent, 2019 root_al,
1990 root_al, 2020 NULL, be[i].to,
1991 NULL, be[i].to, 2021 true, &be[i].flags,
1992 true, &be[i].flags, 2022 NULL, be[i].from);
1993 nr_loop_iter, 1,
1994 be[i].from);
1995 else
1996 err = add_callchain_ip(thread, cursor, parent,
1997 root_al,
1998 NULL, be[i].to,
1999 true, &be[i].flags,
2000 0, 0, be[i].from);
2001 2023
2002 if (!err) 2024 if (!err)
2003 err = add_callchain_ip(thread, cursor, parent, root_al, 2025 err = add_callchain_ip(thread, cursor, parent, root_al,
2004 NULL, be[i].from, 2026 NULL, be[i].from,
2005 true, &be[i].flags, 2027 true, &be[i].flags,
2006 0, 0, 0); 2028 &iter[i], 0);
2007 if (err == -EINVAL) 2029 if (err == -EINVAL)
2008 break; 2030 break;
2009 if (err) 2031 if (err)
@@ -2037,7 +2059,7 @@ check_calls:
2037 2059
2038 err = add_callchain_ip(thread, cursor, parent, 2060 err = add_callchain_ip(thread, cursor, parent,
2039 root_al, &cpumode, ip, 2061 root_al, &cpumode, ip,
2040 false, NULL, 0, 0, 0); 2062 false, NULL, NULL, 0);
2041 2063
2042 if (err) 2064 if (err)
2043 return (err < 0) ? err : 0; 2065 return (err < 0) ? err : 0;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f44aeba51d1f..f6257fb4f08c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -310,7 +310,7 @@ static struct perf_evsel *
310__add_event(struct list_head *list, int *idx, 310__add_event(struct list_head *list, int *idx,
311 struct perf_event_attr *attr, 311 struct perf_event_attr *attr,
312 char *name, struct cpu_map *cpus, 312 char *name, struct cpu_map *cpus,
313 struct list_head *config_terms) 313 struct list_head *config_terms, bool auto_merge_stats)
314{ 314{
315 struct perf_evsel *evsel; 315 struct perf_evsel *evsel;
316 316
@@ -324,6 +324,7 @@ __add_event(struct list_head *list, int *idx,
324 evsel->cpus = cpu_map__get(cpus); 324 evsel->cpus = cpu_map__get(cpus);
325 evsel->own_cpus = cpu_map__get(cpus); 325 evsel->own_cpus = cpu_map__get(cpus);
326 evsel->system_wide = !!cpus; 326 evsel->system_wide = !!cpus;
327 evsel->auto_merge_stats = auto_merge_stats;
327 328
328 if (name) 329 if (name)
329 evsel->name = strdup(name); 330 evsel->name = strdup(name);
@@ -339,7 +340,7 @@ static int add_event(struct list_head *list, int *idx,
339 struct perf_event_attr *attr, char *name, 340 struct perf_event_attr *attr, char *name,
340 struct list_head *config_terms) 341 struct list_head *config_terms)
341{ 342{
342 return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM; 343 return __add_event(list, idx, attr, name, NULL, config_terms, false) ? 0 : -ENOMEM;
343} 344}
344 345
345static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 346static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -1209,9 +1210,9 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
1209 get_config_name(head_config), &config_terms); 1210 get_config_name(head_config), &config_terms);
1210} 1211}
1211 1212
1212int parse_events_add_pmu(struct parse_events_state *parse_state, 1213static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1213 struct list_head *list, char *name, 1214 struct list_head *list, char *name,
1214 struct list_head *head_config) 1215 struct list_head *head_config, bool auto_merge_stats)
1215{ 1216{
1216 struct perf_event_attr attr; 1217 struct perf_event_attr attr;
1217 struct perf_pmu_info info; 1218 struct perf_pmu_info info;
@@ -1232,7 +1233,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1232 1233
1233 if (!head_config) { 1234 if (!head_config) {
1234 attr.type = pmu->type; 1235 attr.type = pmu->type;
1235 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL); 1236 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL, auto_merge_stats);
1236 return evsel ? 0 : -ENOMEM; 1237 return evsel ? 0 : -ENOMEM;
1237 } 1238 }
1238 1239
@@ -1254,7 +1255,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1254 1255
1255 evsel = __add_event(list, &parse_state->idx, &attr, 1256 evsel = __add_event(list, &parse_state->idx, &attr,
1256 get_config_name(head_config), pmu->cpus, 1257 get_config_name(head_config), pmu->cpus,
1257 &config_terms); 1258 &config_terms, auto_merge_stats);
1258 if (evsel) { 1259 if (evsel) {
1259 evsel->unit = info.unit; 1260 evsel->unit = info.unit;
1260 evsel->scale = info.scale; 1261 evsel->scale = info.scale;
@@ -1267,6 +1268,13 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1267 return evsel ? 0 : -ENOMEM; 1268 return evsel ? 0 : -ENOMEM;
1268} 1269}
1269 1270
1271int parse_events_add_pmu(struct parse_events_state *parse_state,
1272 struct list_head *list, char *name,
1273 struct list_head *head_config)
1274{
1275 return __parse_events_add_pmu(parse_state, list, name, head_config, false);
1276}
1277
1270int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1278int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1271 char *str, struct list_head **listp) 1279 char *str, struct list_head **listp)
1272{ 1280{
@@ -1296,8 +1304,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1296 return -1; 1304 return -1;
1297 list_add_tail(&term->list, head); 1305 list_add_tail(&term->list, head);
1298 1306
1299 if (!parse_events_add_pmu(parse_state, list, 1307 if (!__parse_events_add_pmu(parse_state, list,
1300 pmu->name, head)) { 1308 pmu->name, head, true)) {
1301 pr_debug("%s -> %s/%s/\n", str, 1309 pr_debug("%s -> %s/%s/\n", str,
1302 pmu->name, alias->str); 1310 pmu->name, alias->str);
1303 ok++; 1311 ok++;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ac863691605f..a7ebd9fe8e40 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1120,6 +1120,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1120 if (sample_type & PERF_SAMPLE_DATA_SRC) 1120 if (sample_type & PERF_SAMPLE_DATA_SRC)
1121 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 1121 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
1122 1122
1123 if (sample_type & PERF_SAMPLE_PHYS_ADDR)
1124 printf(" .. phys_addr: 0x%"PRIx64"\n", sample->phys_addr);
1125
1123 if (sample_type & PERF_SAMPLE_TRANSACTION) 1126 if (sample_type & PERF_SAMPLE_TRANSACTION)
1124 printf("... transaction: %" PRIx64 "\n", sample->transaction); 1127 printf("... transaction: %" PRIx64 "\n", sample->transaction);
1125 1128
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 12359bd986db..eb3ab902a1c0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1316,6 +1316,47 @@ struct sort_entry sort_mem_dcacheline = {
1316}; 1316};
1317 1317
1318static int64_t 1318static int64_t
1319sort__phys_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
1320{
1321 uint64_t l = 0, r = 0;
1322
1323 if (left->mem_info)
1324 l = left->mem_info->daddr.phys_addr;
1325 if (right->mem_info)
1326 r = right->mem_info->daddr.phys_addr;
1327
1328 return (int64_t)(r - l);
1329}
1330
1331static int hist_entry__phys_daddr_snprintf(struct hist_entry *he, char *bf,
1332 size_t size, unsigned int width)
1333{
1334 uint64_t addr = 0;
1335 size_t ret = 0;
1336 size_t len = BITS_PER_LONG / 4;
1337
1338 addr = he->mem_info->daddr.phys_addr;
1339
1340 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", he->level);
1341
1342 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", len, addr);
1343
1344 ret += repsep_snprintf(bf + ret, size - ret, "%-*s", width - ret, "");
1345
1346 if (ret > width)
1347 bf[width] = '\0';
1348
1349 return width;
1350}
1351
1352struct sort_entry sort_mem_phys_daddr = {
1353 .se_header = "Data Physical Address",
1354 .se_cmp = sort__phys_daddr_cmp,
1355 .se_snprintf = hist_entry__phys_daddr_snprintf,
1356 .se_width_idx = HISTC_MEM_PHYS_DADDR,
1357};
1358
1359static int64_t
1319sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 1360sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
1320{ 1361{
1321 if (!left->branch_info || !right->branch_info) 1362 if (!left->branch_info || !right->branch_info)
@@ -1547,6 +1588,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
1547 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), 1588 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1548 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), 1589 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1549 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline), 1590 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
1591 DIM(SORT_MEM_PHYS_DADDR, "phys_daddr", sort_mem_phys_daddr),
1550}; 1592};
1551 1593
1552#undef DIM 1594#undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index b7c75597e18f..f36dc4980a6c 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -245,6 +245,7 @@ enum sort_type {
245 SORT_MEM_SNOOP, 245 SORT_MEM_SNOOP,
246 SORT_MEM_DCACHELINE, 246 SORT_MEM_DCACHELINE,
247 SORT_MEM_IADDR_SYMBOL, 247 SORT_MEM_IADDR_SYMBOL,
248 SORT_MEM_PHYS_DADDR,
248}; 249};
249 250
250/* 251/*
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 5c39f420111e..9cf781f0d8a2 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -810,12 +810,6 @@ static u64 ref_reloc(struct kmap *kmap)
810void __weak arch__sym_update(struct symbol *s __maybe_unused, 810void __weak arch__sym_update(struct symbol *s __maybe_unused,
811 GElf_Sym *sym __maybe_unused) { } 811 GElf_Sym *sym __maybe_unused) { }
812 812
813void __weak arch__adjust_sym_map_offset(GElf_Sym *sym, GElf_Shdr *shdr,
814 struct map *map __maybe_unused)
815{
816 sym->st_value -= shdr->sh_addr - shdr->sh_offset;
817}
818
819int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 813int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
820 struct symsrc *runtime_ss, int kmodule) 814 struct symsrc *runtime_ss, int kmodule)
821{ 815{
@@ -996,7 +990,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
996 990
997 /* Adjust symbol to map to file offset */ 991 /* Adjust symbol to map to file offset */
998 if (adjust_kernel_syms) 992 if (adjust_kernel_syms)
999 arch__adjust_sym_map_offset(&sym, &shdr, map); 993 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1000 994
1001 if (strcmp(section_name, 995 if (strcmp(section_name,
1002 (curr_dso->short_name + 996 (curr_dso->short_name +
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d00a012cfdfb..aad99e7e179b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -186,6 +186,7 @@ struct addr_map_symbol {
186 struct symbol *sym; 186 struct symbol *sym;
187 u64 addr; 187 u64 addr;
188 u64 al_addr; 188 u64 al_addr;
189 u64 phys_addr;
189}; 190};
190 191
191struct branch_info { 192struct branch_info {
@@ -343,9 +344,6 @@ int setup_intlist(struct intlist **list, const char *list_str,
343#ifdef HAVE_LIBELF_SUPPORT 344#ifdef HAVE_LIBELF_SUPPORT
344bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); 345bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
345void arch__sym_update(struct symbol *s, GElf_Sym *sym); 346void arch__sym_update(struct symbol *s, GElf_Sym *sym);
346void arch__adjust_sym_map_offset(GElf_Sym *sym,
347 GElf_Shdr *shdr __maybe_unused,
348 struct map *map __maybe_unused);
349#endif 347#endif
350 348
351#define SYMBOL_A 0 349#define SYMBOL_A 0
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index bbb4c1957578..6eea7cff3d4e 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -15,10 +15,11 @@
15 15
16#include "syscalltbl.h" 16#include "syscalltbl.h"
17#include <stdlib.h> 17#include <stdlib.h>
18#include <linux/compiler.h>
18 19
19#ifdef HAVE_SYSCALL_TABLE 20#ifdef HAVE_SYSCALL_TABLE
20#include <linux/compiler.h>
21#include <string.h> 21#include <string.h>
22#include "string2.h"
22#include "util.h" 23#include "util.h"
23 24
24#if defined(__x86_64__) 25#if defined(__x86_64__)
@@ -105,6 +106,27 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name)
105 return sc ? sc->id : -1; 106 return sc ? sc->id : -1;
106} 107}
107 108
109int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
110{
111 int i;
112 struct syscall *syscalls = tbl->syscalls.entries;
113
114 for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
115 if (strglobmatch(syscalls[i].name, syscall_glob)) {
116 *idx = i;
117 return syscalls[i].id;
118 }
119 }
120
121 return -1;
122}
123
124int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
125{
126 *idx = -1;
127 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
128}
129
108#else /* HAVE_SYSCALL_TABLE */ 130#else /* HAVE_SYSCALL_TABLE */
109 131
110#include <libaudit.h> 132#include <libaudit.h>
@@ -131,4 +153,15 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name)
131{ 153{
132 return audit_name_to_syscall(name, tbl->audit_machine); 154 return audit_name_to_syscall(name, tbl->audit_machine);
133} 155}
156
157int syscalltbl__strglobmatch_next(struct syscalltbl *tbl __maybe_unused,
158 const char *syscall_glob __maybe_unused, int *idx __maybe_unused)
159{
160 return -1;
161}
162
163int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
164{
165 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
166}
134#endif /* HAVE_SYSCALL_TABLE */ 167#endif /* HAVE_SYSCALL_TABLE */
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index e2951510484f..e9fb8786da7c 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -17,4 +17,7 @@ void syscalltbl__delete(struct syscalltbl *tbl);
17const char *syscalltbl__name(const struct syscalltbl *tbl, int id); 17const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
18int syscalltbl__id(struct syscalltbl *tbl, const char *name); 18int syscalltbl__id(struct syscalltbl *tbl, const char *name);
19 19
20int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
21int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
22
20#endif /* __PERF_SYSCALLTBL_H */ 23#endif /* __PERF_SYSCALLTBL_H */
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index 82a2ff896a95..52a39ecf5ca1 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -759,7 +759,7 @@ static acpi_status osl_list_bios_tables(void)
759 759
760 /* Skip NULL entries in RSDT/XSDT */ 760 /* Skip NULL entries in RSDT/XSDT */
761 761
762 if (!table_address) { 762 if (table_address == 0) {
763 continue; 763 continue;
764 } 764 }
765 765
@@ -808,7 +808,8 @@ osl_get_bios_table(char *signature,
808 u8 number_of_tables; 808 u8 number_of_tables;
809 u8 item_size; 809 u8 item_size;
810 u32 current_instance = 0; 810 u32 current_instance = 0;
811 acpi_physical_address table_address = 0; 811 acpi_physical_address table_address;
812 acpi_physical_address first_table_address = 0;
812 u32 table_length = 0; 813 u32 table_length = 0;
813 acpi_status status = AE_OK; 814 acpi_status status = AE_OK;
814 u32 i; 815 u32 i;
@@ -820,9 +821,10 @@ osl_get_bios_table(char *signature,
820 ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) || 821 ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
821 ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) || 822 ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
822 ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 823 ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
823 if (instance > 0) { 824
824 return (AE_LIMIT); 825find_next_instance:
825 } 826
827 table_address = 0;
826 828
827 /* 829 /*
828 * Get the appropriate address, either 32-bit or 64-bit. Be very 830 * Get the appropriate address, either 32-bit or 64-bit. Be very
@@ -830,41 +832,66 @@ osl_get_bios_table(char *signature,
830 * Note: The 64-bit addresses have priority. 832 * Note: The 64-bit addresses have priority.
831 */ 833 */
832 if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) { 834 if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
833 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && 835 if (current_instance < 2) {
834 gbl_fadt->Xdsdt) { 836 if ((gbl_fadt->header.length >=
835 table_address = 837 MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
836 (acpi_physical_address)gbl_fadt->Xdsdt; 838 && current_instance == 0) {
837 } else 839 table_address =
838 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) 840 (acpi_physical_address)gbl_fadt->
839 && gbl_fadt->dsdt) { 841 Xdsdt;
840 table_address = 842 } else
841 (acpi_physical_address)gbl_fadt->dsdt; 843 if ((gbl_fadt->header.length >=
844 MIN_FADT_FOR_DSDT)
845 && gbl_fadt->dsdt !=
846 first_table_address) {
847 table_address =
848 (acpi_physical_address)gbl_fadt->
849 dsdt;
850 }
842 } 851 }
843 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 852 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
844 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && 853 if (current_instance < 2) {
845 gbl_fadt->Xfacs) { 854 if ((gbl_fadt->header.length >=
846 table_address = 855 MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
847 (acpi_physical_address)gbl_fadt->Xfacs; 856 && current_instance == 0) {
848 } else 857 table_address =
849 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) 858 (acpi_physical_address)gbl_fadt->
850 && gbl_fadt->facs) { 859 Xfacs;
851 table_address = 860 } else
852 (acpi_physical_address)gbl_fadt->facs; 861 if ((gbl_fadt->header.length >=
862 MIN_FADT_FOR_FACS)
863 && gbl_fadt->facs !=
864 first_table_address) {
865 table_address =
866 (acpi_physical_address)gbl_fadt->
867 facs;
868 }
853 } 869 }
854 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { 870 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
855 if (!gbl_revision) { 871 if (!gbl_revision) {
856 return (AE_BAD_SIGNATURE); 872 return (AE_BAD_SIGNATURE);
857 } 873 }
858 table_address = 874 if (current_instance == 0) {
859 (acpi_physical_address)gbl_rsdp. 875 table_address =
860 xsdt_physical_address; 876 (acpi_physical_address)gbl_rsdp.
877 xsdt_physical_address;
878 }
861 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { 879 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
862 table_address = 880 if (current_instance == 0) {
863 (acpi_physical_address)gbl_rsdp. 881 table_address =
864 rsdt_physical_address; 882 (acpi_physical_address)gbl_rsdp.
883 rsdt_physical_address;
884 }
865 } else { 885 } else {
866 table_address = (acpi_physical_address)gbl_rsdp_address; 886 if (current_instance == 0) {
867 signature = ACPI_SIG_RSDP; 887 table_address =
888 (acpi_physical_address)gbl_rsdp_address;
889 signature = ACPI_SIG_RSDP;
890 }
891 }
892
893 if (table_address == 0) {
894 goto exit_find_table;
868 } 895 }
869 896
870 /* Now we can get the requested special table */ 897 /* Now we can get the requested special table */
@@ -875,6 +902,18 @@ osl_get_bios_table(char *signature,
875 } 902 }
876 903
877 table_length = ap_get_table_length(mapped_table); 904 table_length = ap_get_table_length(mapped_table);
905 if (first_table_address == 0) {
906 first_table_address = table_address;
907 }
908
909 /* Match table instance */
910
911 if (current_instance != instance) {
912 osl_unmap_table(mapped_table);
913 mapped_table = NULL;
914 current_instance++;
915 goto find_next_instance;
916 }
878 } else { /* Case for a normal ACPI table */ 917 } else { /* Case for a normal ACPI table */
879 918
880 if (osl_can_use_xsdt()) { 919 if (osl_can_use_xsdt()) {
@@ -913,7 +952,7 @@ osl_get_bios_table(char *signature,
913 952
914 /* Skip NULL entries in RSDT/XSDT */ 953 /* Skip NULL entries in RSDT/XSDT */
915 954
916 if (!table_address) { 955 if (table_address == 0) {
917 continue; 956 continue;
918 } 957 }
919 958
@@ -946,6 +985,8 @@ osl_get_bios_table(char *signature,
946 } 985 }
947 } 986 }
948 987
988exit_find_table:
989
949 if (!mapped_table) { 990 if (!mapped_table) {
950 return (AE_LIMIT); 991 return (AE_LIMIT);
951 } 992 }
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index 31b5a7f74015..d686e11936c4 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -61,7 +61,7 @@ static int ap_is_existing_file(char *pathname);
61 61
62static int ap_is_existing_file(char *pathname) 62static int ap_is_existing_file(char *pathname)
63{ 63{
64#ifndef _GNU_EFI 64#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
65 struct stat stat_info; 65 struct stat stat_info;
66 66
67 if (!stat(pathname, &stat_info)) { 67 if (!stat(pathname, &stat_info)) {
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index dd82afa897bd..943b6b614683 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -300,7 +300,7 @@ static int ap_do_options(int argc, char **argv)
300 * 300 *
301 ******************************************************************************/ 301 ******************************************************************************/
302 302
303#ifndef _GNU_EFI 303#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
304int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) 304int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
305#else 305#else
306int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) 306int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index d6e1c02ddcfe..4c5a481a850c 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -26,7 +26,7 @@ endif
26 26
27ifneq ($(OUTPUT),) 27ifneq ($(OUTPUT),)
28# check that the output directory actually exists 28# check that the output directory actually exists
29OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) 29OUTDIR := $(realpath $(OUTPUT))
30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
31endif 31endif
32 32
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 9ea914378985..2dccf4998599 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -12,6 +12,7 @@
12#include <string.h> 12#include <string.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <errno.h> 14#include <errno.h>
15#include <sched.h>
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/stat.h> 17#include <sys/stat.h>
17#include <sys/utsname.h> 18#include <sys/utsname.h>
@@ -31,6 +32,7 @@ static int cmd_help(int argc, const char **argv);
31 */ 32 */
32struct cpupower_cpu_info cpupower_cpu_info; 33struct cpupower_cpu_info cpupower_cpu_info;
33int run_as_root; 34int run_as_root;
35int base_cpu;
34/* Affected cpus chosen by -c/--cpu param */ 36/* Affected cpus chosen by -c/--cpu param */
35struct bitmask *cpus_chosen; 37struct bitmask *cpus_chosen;
36 38
@@ -174,6 +176,7 @@ int main(int argc, const char *argv[])
174 unsigned int i, ret; 176 unsigned int i, ret;
175 struct stat statbuf; 177 struct stat statbuf;
176 struct utsname uts; 178 struct utsname uts;
179 char pathname[32];
177 180
178 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 181 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
179 182
@@ -198,17 +201,23 @@ int main(int argc, const char *argv[])
198 argv[0] = cmd = "help"; 201 argv[0] = cmd = "help";
199 } 202 }
200 203
201 get_cpu_info(0, &cpupower_cpu_info); 204 base_cpu = sched_getcpu();
205 if (base_cpu < 0) {
206 fprintf(stderr, _("No valid cpus found.\n"));
207 return EXIT_FAILURE;
208 }
209
210 get_cpu_info(&cpupower_cpu_info);
202 run_as_root = !geteuid(); 211 run_as_root = !geteuid();
203 if (run_as_root) { 212 if (run_as_root) {
204 ret = uname(&uts); 213 ret = uname(&uts);
214 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
205 if (!ret && !strcmp(uts.machine, "x86_64") && 215 if (!ret && !strcmp(uts.machine, "x86_64") &&
206 stat("/dev/cpu/0/msr", &statbuf) != 0) { 216 stat(pathname, &statbuf) != 0) {
207 if (system("modprobe msr") == -1) 217 if (system("modprobe msr") == -1)
208 fprintf(stderr, _("MSR access not available.\n")); 218 fprintf(stderr, _("MSR access not available.\n"));
209 } 219 }
210 } 220 }
211
212 221
213 for (i = 0; i < ARRAY_SIZE(commands); i++) { 222 for (i = 0; i < ARRAY_SIZE(commands); i++) {
214 struct cmd_struct *p = commands + i; 223 struct cmd_struct *p = commands + i;
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 39c2c7d067bb..32d37c9be791 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -42,7 +42,7 @@ cpuid_func(edx);
42 * 42 *
43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted? 43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
44 */ 44 */
45int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info) 45int get_cpu_info(struct cpupower_cpu_info *cpu_info)
46{ 46{
47 FILE *fp; 47 FILE *fp;
48 char value[64]; 48 char value[64];
@@ -70,7 +70,7 @@ int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
70 if (!strncmp(value, "processor\t: ", 12)) 70 if (!strncmp(value, "processor\t: ", 12))
71 sscanf(value, "processor\t: %u", &proc); 71 sscanf(value, "processor\t: %u", &proc);
72 72
73 if (proc != cpu) 73 if (proc != (unsigned int)base_cpu)
74 continue; 74 continue;
75 75
76 /* Get CPU vendor */ 76 /* Get CPU vendor */
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 799a18be60aa..41da392be448 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -34,6 +34,7 @@
34/* Internationalization ****************************/ 34/* Internationalization ****************************/
35 35
36extern int run_as_root; 36extern int run_as_root;
37extern int base_cpu;
37extern struct bitmask *cpus_chosen; 38extern struct bitmask *cpus_chosen;
38 39
39/* Global verbose (-d) stuff *********************************/ 40/* Global verbose (-d) stuff *********************************/
@@ -87,11 +88,11 @@ struct cpupower_cpu_info {
87 * 88 *
88 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo 89 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
89 * 90 *
90 * Returns 0 on success or a negativ error code 91 * Returns 0 on success or a negative error code
91 * Only used on x86, below global's struct values are zero/unknown on 92 * Only used on x86, below global's struct values are zero/unknown on
92 * other archs 93 * other archs
93 */ 94 */
94extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info); 95extern int get_cpu_info(struct cpupower_cpu_info *cpu_info);
95extern struct cpupower_cpu_info cpupower_cpu_info; 96extern struct cpupower_cpu_info cpupower_cpu_info;
96/* cpuid and cpuinfo helpers **************************/ 97/* cpuid and cpuinfo helpers **************************/
97 98
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index 601d719d4e60..a5e7ddf19dbd 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -13,7 +13,7 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
13 13
14 *support = *active = *states = 0; 14 *support = *active = *states = 0;
15 15
16 ret = get_cpu_info(0, &cpu_info); 16 ret = get_cpu_info(&cpu_info);
17 if (ret) 17 if (ret)
18 return ret; 18 return ret;
19 19
diff --git a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
index ebeaba6571a3..f794d6bbb7e9 100644
--- a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
@@ -123,7 +123,7 @@ static int hsw_ext_start(void)
123 previous_count[num][cpu] = val; 123 previous_count[num][cpu] = val;
124 } 124 }
125 } 125 }
126 hsw_ext_get_count(TSC, &tsc_at_measure_start, 0); 126 hsw_ext_get_count(TSC, &tsc_at_measure_start, base_cpu);
127 return 0; 127 return 0;
128} 128}
129 129
@@ -132,7 +132,7 @@ static int hsw_ext_stop(void)
132 unsigned long long val; 132 unsigned long long val;
133 int num, cpu; 133 int num, cpu;
134 134
135 hsw_ext_get_count(TSC, &tsc_at_measure_end, 0); 135 hsw_ext_get_count(TSC, &tsc_at_measure_end, base_cpu);
136 136
137 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { 137 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) {
138 for (cpu = 0; cpu < cpu_count; cpu++) { 138 for (cpu = 0; cpu < cpu_count; cpu++) {
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index c83f1606970b..d7c2a6d13dea 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -80,7 +80,8 @@ static int *is_valid;
80static int mperf_get_tsc(unsigned long long *tsc) 80static int mperf_get_tsc(unsigned long long *tsc)
81{ 81{
82 int ret; 82 int ret;
83 ret = read_msr(0, MSR_TSC, tsc); 83
84 ret = read_msr(base_cpu, MSR_TSC, tsc);
84 if (ret) 85 if (ret)
85 dprint("Reading TSC MSR failed, returning %llu\n", *tsc); 86 dprint("Reading TSC MSR failed, returning %llu\n", *tsc);
86 return ret; 87 return ret;
diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
index d2a91dd0d563..abf8cb5f7349 100644
--- a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
@@ -129,7 +129,7 @@ static int nhm_start(void)
129 int num, cpu; 129 int num, cpu;
130 unsigned long long dbg, val; 130 unsigned long long dbg, val;
131 131
132 nhm_get_count(TSC, &tsc_at_measure_start, 0); 132 nhm_get_count(TSC, &tsc_at_measure_start, base_cpu);
133 133
134 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 134 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) { 135 for (cpu = 0; cpu < cpu_count; cpu++) {
@@ -137,7 +137,7 @@ static int nhm_start(void)
137 previous_count[num][cpu] = val; 137 previous_count[num][cpu] = val;
138 } 138 }
139 } 139 }
140 nhm_get_count(TSC, &dbg, 0); 140 nhm_get_count(TSC, &dbg, base_cpu);
141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start); 141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
142 return 0; 142 return 0;
143} 143}
@@ -148,7 +148,7 @@ static int nhm_stop(void)
148 unsigned long long dbg; 148 unsigned long long dbg;
149 int num, cpu; 149 int num, cpu;
150 150
151 nhm_get_count(TSC, &tsc_at_measure_end, 0); 151 nhm_get_count(TSC, &tsc_at_measure_end, base_cpu);
152 152
153 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 153 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
154 for (cpu = 0; cpu < cpu_count; cpu++) { 154 for (cpu = 0; cpu < cpu_count; cpu++) {
@@ -156,7 +156,7 @@ static int nhm_stop(void)
156 current_count[num][cpu] = val; 156 current_count[num][cpu] = val;
157 } 157 }
158 } 158 }
159 nhm_get_count(TSC, &dbg, 0); 159 nhm_get_count(TSC, &dbg, base_cpu);
160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end); 160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
161 161
162 return 0; 162 return 0;
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
index efc8a69c9aba..a2b45219648d 100644
--- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -120,7 +120,7 @@ static int snb_start(void)
120 previous_count[num][cpu] = val; 120 previous_count[num][cpu] = val;
121 } 121 }
122 } 122 }
123 snb_get_count(TSC, &tsc_at_measure_start, 0); 123 snb_get_count(TSC, &tsc_at_measure_start, base_cpu);
124 return 0; 124 return 0;
125} 125}
126 126
@@ -129,7 +129,7 @@ static int snb_stop(void)
129 unsigned long long val; 129 unsigned long long val;
130 int num, cpu; 130 int num, cpu;
131 131
132 snb_get_count(TSC, &tsc_at_measure_end, 0); 132 snb_get_count(TSC, &tsc_at_measure_end, base_cpu);
133 133
134 for (num = 0; num < SNB_CSTATE_COUNT; num++) { 134 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) { 135 for (cpu = 0; cpu < cpu_count; cpu++) {
diff --git a/tools/power/pm-graph/Makefile b/tools/power/pm-graph/Makefile
index 4d0ccc89e6c6..32f40eacdafe 100644
--- a/tools/power/pm-graph/Makefile
+++ b/tools/power/pm-graph/Makefile
@@ -4,7 +4,7 @@ DESTDIR ?=
4all: 4all:
5 @echo "Nothing to build" 5 @echo "Nothing to build"
6 6
7install : 7install : uninstall
8 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph 8 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph
9 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph 9 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph
10 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph 10 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph
@@ -17,12 +17,15 @@ install :
17 install sleepgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8 17 install sleepgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8
18 18
19uninstall : 19uninstall :
20 rm $(DESTDIR)$(PREFIX)/share/man/man8/bootgraph.8 20 rm -f $(DESTDIR)$(PREFIX)/share/man/man8/bootgraph.8
21 rm $(DESTDIR)$(PREFIX)/share/man/man8/sleepgraph.8 21 rm -f $(DESTDIR)$(PREFIX)/share/man/man8/sleepgraph.8
22 22
23 rm $(DESTDIR)$(PREFIX)/bin/bootgraph 23 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph
24 rm $(DESTDIR)$(PREFIX)/bin/sleepgraph 24 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph
25 25
26 rm $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py 26 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py
27 rm $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py 27 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py
28 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph 28 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*.pyc
29 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
30 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
31 fi;
diff --git a/tools/power/pm-graph/analyze_boot.py b/tools/power/pm-graph/analyze_boot.py
index 3e1dcbbf1adc..e83df141a597 100755
--- a/tools/power/pm-graph/analyze_boot.py
+++ b/tools/power/pm-graph/analyze_boot.py
@@ -42,7 +42,7 @@ 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.0 45 version = '2.1'
46 hostname = 'localhost' 46 hostname = 'localhost'
47 testtime = '' 47 testtime = ''
48 kernel = '' 48 kernel = ''
@@ -50,9 +50,14 @@ class SystemValues(aslib.SystemValues):
50 ftracefile = '' 50 ftracefile = ''
51 htmlfile = 'bootgraph.html' 51 htmlfile = 'bootgraph.html'
52 outfile = '' 52 outfile = ''
53 phoronix = False 53 testdir = ''
54 addlogs = False 54 testdirprefix = 'boot'
55 embedded = False
56 testlog = False
57 dmesglog = False
58 ftracelog = False
55 useftrace = False 59 useftrace = False
60 usecallgraph = False
56 usedevsrc = True 61 usedevsrc = True
57 suspendmode = 'boot' 62 suspendmode = 'boot'
58 max_graph_depth = 2 63 max_graph_depth = 2
@@ -61,10 +66,12 @@ class SystemValues(aslib.SystemValues):
61 manual = False 66 manual = False
62 iscronjob = False 67 iscronjob = False
63 timeformat = '%.6f' 68 timeformat = '%.6f'
69 bootloader = 'grub'
70 blexec = []
64 def __init__(self): 71 def __init__(self):
65 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ): 72 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
66 self.phoronix = True 73 self.embedded = True
67 self.addlogs = True 74 self.dmesglog = True
68 self.outfile = os.environ['LOG_FILE'] 75 self.outfile = os.environ['LOG_FILE']
69 self.htmlfile = os.environ['LOG_FILE'] 76 self.htmlfile = os.environ['LOG_FILE']
70 self.hostname = platform.node() 77 self.hostname = platform.node()
@@ -76,42 +83,80 @@ class SystemValues(aslib.SystemValues):
76 self.kernel = self.kernelVersion(val) 83 self.kernel = self.kernelVersion(val)
77 else: 84 else:
78 self.kernel = 'unknown' 85 self.kernel = 'unknown'
86 self.testdir = datetime.now().strftime('boot-%y%m%d-%H%M%S')
79 def kernelVersion(self, msg): 87 def kernelVersion(self, msg):
80 return msg.split()[2] 88 return msg.split()[2]
89 def checkFtraceKernelVersion(self):
90 val = tuple(map(int, self.kernel.split('-')[0].split('.')))
91 if val >= (4, 10, 0):
92 return True
93 return False
81 def kernelParams(self): 94 def kernelParams(self):
82 cmdline = 'initcall_debug log_buf_len=32M' 95 cmdline = 'initcall_debug log_buf_len=32M'
83 if self.useftrace: 96 if self.useftrace:
84 cmdline += ' trace_buf_size=128M trace_clock=global '\ 97 if self.cpucount > 0:
98 bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount
99 else:
100 bs = 131072
101 cmdline += ' trace_buf_size=%dK trace_clock=global '\
85 'trace_options=nooverwrite,funcgraph-abstime,funcgraph-cpu,'\ 102 'trace_options=nooverwrite,funcgraph-abstime,funcgraph-cpu,'\
86 'funcgraph-duration,funcgraph-proc,funcgraph-tail,'\ 103 'funcgraph-duration,funcgraph-proc,funcgraph-tail,'\
87 'nofuncgraph-overhead,context-info,graph-time '\ 104 'nofuncgraph-overhead,context-info,graph-time '\
88 'ftrace=function_graph '\ 105 'ftrace=function_graph '\
89 'ftrace_graph_max_depth=%d '\ 106 'ftrace_graph_max_depth=%d '\
90 'ftrace_graph_filter=%s' % \ 107 'ftrace_graph_filter=%s' % \
91 (self.max_graph_depth, self.graph_filter) 108 (bs, self.max_graph_depth, self.graph_filter)
92 return cmdline 109 return cmdline
93 def setGraphFilter(self, val): 110 def setGraphFilter(self, val):
94 fp = open(self.tpath+'available_filter_functions') 111 master = self.getBootFtraceFilterFunctions()
95 master = fp.read().split('\n') 112 fs = ''
96 fp.close()
97 for i in val.split(','): 113 for i in val.split(','):
98 func = i.strip() 114 func = i.strip()
115 if func == '':
116 doError('badly formatted filter function string')
117 if '[' in func or ']' in func:
118 doError('loadable module functions not allowed - "%s"' % func)
119 if ' ' in func:
120 doError('spaces found in filter functions - "%s"' % func)
99 if func not in master: 121 if func not in master:
100 doError('function "%s" not available for ftrace' % func) 122 doError('function "%s" not available for ftrace' % func)
101 self.graph_filter = val 123 if not fs:
124 fs = func
125 else:
126 fs += ','+func
127 if not fs:
128 doError('badly formatted filter function string')
129 self.graph_filter = fs
130 def getBootFtraceFilterFunctions(self):
131 self.rootCheck(True)
132 fp = open(self.tpath+'available_filter_functions')
133 fulllist = fp.read().split('\n')
134 fp.close()
135 list = []
136 for i in fulllist:
137 if not i or ' ' in i or '[' in i or ']' in i:
138 continue
139 list.append(i)
140 return list
141 def myCronJob(self, line):
142 if '@reboot' not in line:
143 return False
144 if 'bootgraph' in line or 'analyze_boot.py' in line or '-cronjob' in line:
145 return True
146 return False
102 def cronjobCmdString(self): 147 def cronjobCmdString(self):
103 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0]) 148 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0])
104 args = iter(sys.argv[1:]) 149 args = iter(sys.argv[1:])
105 for arg in args: 150 for arg in args:
106 if arg in ['-h', '-v', '-cronjob', '-reboot']: 151 if arg in ['-h', '-v', '-cronjob', '-reboot']:
107 continue 152 continue
108 elif arg in ['-o', '-dmesg', '-ftrace', '-filter']: 153 elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
109 args.next() 154 args.next()
110 continue 155 continue
111 cmdline += ' '+arg 156 cmdline += ' '+arg
112 if self.graph_filter != 'do_one_initcall': 157 if self.graph_filter != 'do_one_initcall':
113 cmdline += ' -filter "%s"' % self.graph_filter 158 cmdline += ' -func "%s"' % self.graph_filter
114 cmdline += ' -o "%s"' % os.path.abspath(self.htmlfile) 159 cmdline += ' -o "%s"' % os.path.abspath(self.testdir)
115 return cmdline 160 return cmdline
116 def manualRebootRequired(self): 161 def manualRebootRequired(self):
117 cmdline = self.kernelParams() 162 cmdline = self.kernelParams()
@@ -121,6 +166,39 @@ class SystemValues(aslib.SystemValues):
121 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n' 166 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n'
122 print 'CMDLINE="%s"' % cmdline 167 print 'CMDLINE="%s"' % cmdline
123 sys.exit() 168 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):
178 blcmd = ''
179 for cmd in ['update-grub', 'grub-mkconfig', 'grub2-mkconfig']:
180 if blcmd:
181 break
182 blcmd = self.getExec(cmd)
183 if not blcmd:
184 doError('[GRUB] missing update command')
185 if not os.path.exists('/etc/default/grub'):
186 doError('[GRUB] missing /etc/default/grub')
187 if 'grub2' in blcmd:
188 cfg = '/boot/grub2/grub.cfg'
189 else:
190 cfg = '/boot/grub/grub.cfg'
191 if not os.path.exists(cfg):
192 doError('[GRUB] missing %s' % cfg)
193 if 'update-grub' in blcmd:
194 self.blexec = [blcmd]
195 else:
196 self.blexec = [blcmd, '-o', cfg]
197 def getBootLoader(self):
198 if self.bootloader == 'grub':
199 self.blGrub()
200 else:
201 doError('unknown boot loader: %s' % self.bootloader)
124 202
125sysvals = SystemValues() 203sysvals = SystemValues()
126 204
@@ -136,20 +214,23 @@ class Data(aslib.Data):
136 idstr = '' 214 idstr = ''
137 html_device_id = 0 215 html_device_id = 0
138 valid = False 216 valid = False
139 initstart = 0.0 217 tUserMode = 0.0
140 boottime = '' 218 boottime = ''
141 phases = ['boot'] 219 phases = ['kernel', 'user']
142 do_one_initcall = False 220 do_one_initcall = False
143 def __init__(self, num): 221 def __init__(self, num):
144 self.testnumber = num 222 self.testnumber = num
145 self.idstr = 'a' 223 self.idstr = 'a'
146 self.dmesgtext = [] 224 self.dmesgtext = []
147 self.dmesg = { 225 self.dmesg = {
148 'boot': {'list': dict(), 'start': -1.0, 'end': -1.0, 'row': 0, 'color': '#dddddd'} 226 'kernel': {'list': dict(), 'start': -1.0, 'end': -1.0, 'row': 0,
227 'order': 0, 'color': 'linear-gradient(to bottom, #fff, #bcf)'},
228 'user': {'list': dict(), 'start': -1.0, 'end': -1.0, 'row': 0,
229 'order': 1, 'color': '#fff'}
149 } 230 }
150 def deviceTopology(self): 231 def deviceTopology(self):
151 return '' 232 return ''
152 def newAction(self, phase, name, start, end, ret, ulen): 233 def newAction(self, phase, name, pid, start, end, ret, ulen):
153 # new device callback for a specific phase 234 # new device callback for a specific phase
154 self.html_device_id += 1 235 self.html_device_id += 1
155 devid = '%s%d' % (self.idstr, self.html_device_id) 236 devid = '%s%d' % (self.idstr, self.html_device_id)
@@ -163,41 +244,46 @@ class Data(aslib.Data):
163 name = '%s[%d]' % (origname, i) 244 name = '%s[%d]' % (origname, i)
164 i += 1 245 i += 1
165 list[name] = {'name': name, 'start': start, 'end': end, 246 list[name] = {'name': name, 'start': start, 'end': end,
166 'pid': 0, 'length': length, 'row': 0, 'id': devid, 247 'pid': pid, 'length': length, 'row': 0, 'id': devid,
167 'ret': ret, 'ulen': ulen } 248 'ret': ret, 'ulen': ulen }
168 return name 249 return name
169 def deviceMatch(self, cg): 250 def deviceMatch(self, pid, cg):
170 if cg.end - cg.start == 0: 251 if cg.end - cg.start == 0:
171 return True 252 return True
172 list = self.dmesg['boot']['list'] 253 for p in data.phases:
173 for devname in list: 254 list = self.dmesg[p]['list']
174 dev = list[devname] 255 for devname in list:
175 if cg.name == 'do_one_initcall': 256 dev = list[devname]
176 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0): 257 if pid != dev['pid']:
177 dev['ftrace'] = cg 258 continue
178 self.do_one_initcall = True 259 if cg.name == 'do_one_initcall':
179 return True 260 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0):
180 else: 261 dev['ftrace'] = cg
181 if(cg.start > dev['start'] and cg.end < dev['end']): 262 self.do_one_initcall = True
182 if 'ftraces' not in dev: 263 return True
183 dev['ftraces'] = [] 264 else:
184 dev['ftraces'].append(cg) 265 if(cg.start > dev['start'] and cg.end < dev['end']):
185 return True 266 if 'ftraces' not in dev:
267 dev['ftraces'] = []
268 dev['ftraces'].append(cg)
269 return True
186 return False 270 return False
187 271
188# ----------------- FUNCTIONS -------------------- 272# ----------------- FUNCTIONS --------------------
189 273
190# Function: loadKernelLog 274# Function: parseKernelLog
191# Description: 275# Description:
192# Load a raw kernel log from dmesg 276# parse a kernel log for boot data
193def loadKernelLog(): 277def parseKernelLog():
278 phase = 'kernel'
194 data = Data(0) 279 data = Data(0)
195 data.dmesg['boot']['start'] = data.start = ktime = 0.0 280 data.dmesg['kernel']['start'] = data.start = ktime = 0.0
196 sysvals.stamp = { 281 sysvals.stamp = {
197 'time': datetime.now().strftime('%B %d %Y, %I:%M:%S %p'), 282 'time': datetime.now().strftime('%B %d %Y, %I:%M:%S %p'),
198 'host': sysvals.hostname, 283 'host': sysvals.hostname,
199 'mode': 'boot', 'kernel': ''} 284 'mode': 'boot', 'kernel': ''}
200 285
286 tp = aslib.TestProps()
201 devtemp = dict() 287 devtemp = dict()
202 if(sysvals.dmesgfile): 288 if(sysvals.dmesgfile):
203 lf = open(sysvals.dmesgfile, 'r') 289 lf = open(sysvals.dmesgfile, 'r')
@@ -205,6 +291,13 @@ def loadKernelLog():
205 lf = Popen('dmesg', stdout=PIPE).stdout 291 lf = Popen('dmesg', stdout=PIPE).stdout
206 for line in lf: 292 for line in lf:
207 line = line.replace('\r\n', '') 293 line = line.replace('\r\n', '')
294 # grab the stamp and sysinfo
295 if re.match(tp.stampfmt, line):
296 tp.stamp = line
297 continue
298 elif re.match(tp.sysinfofmt, line):
299 tp.sysinfo = line
300 continue
208 idx = line.find('[') 301 idx = line.find('[')
209 if idx > 1: 302 if idx > 1:
210 line = line[idx:] 303 line = line[idx:]
@@ -215,7 +308,6 @@ def loadKernelLog():
215 if(ktime > 120): 308 if(ktime > 120):
216 break 309 break
217 msg = m.group('msg') 310 msg = m.group('msg')
218 data.end = data.initstart = ktime
219 data.dmesgtext.append(line) 311 data.dmesgtext.append(line)
220 if(ktime == 0.0 and re.match('^Linux version .*', msg)): 312 if(ktime == 0.0 and re.match('^Linux version .*', msg)):
221 if(not sysvals.stamp['kernel']): 313 if(not sysvals.stamp['kernel']):
@@ -228,43 +320,39 @@ def loadKernelLog():
228 data.boottime = bt.strftime('%Y-%m-%d_%H:%M:%S') 320 data.boottime = bt.strftime('%Y-%m-%d_%H:%M:%S')
229 sysvals.stamp['time'] = bt.strftime('%B %d %Y, %I:%M:%S %p') 321 sysvals.stamp['time'] = bt.strftime('%B %d %Y, %I:%M:%S %p')
230 continue 322 continue
231 m = re.match('^calling *(?P<f>.*)\+.*', msg) 323 m = re.match('^calling *(?P<f>.*)\+.* @ (?P<p>[0-9]*)', msg)
232 if(m): 324 if(m):
233 devtemp[m.group('f')] = ktime 325 func = m.group('f')
326 pid = int(m.group('p'))
327 devtemp[func] = (ktime, pid)
234 continue 328 continue
235 m = re.match('^initcall *(?P<f>.*)\+.* returned (?P<r>.*) after (?P<t>.*) usecs', msg) 329 m = re.match('^initcall *(?P<f>.*)\+.* returned (?P<r>.*) after (?P<t>.*) usecs', msg)
236 if(m): 330 if(m):
237 data.valid = True 331 data.valid = True
332 data.end = ktime
238 f, r, t = m.group('f', 'r', 't') 333 f, r, t = m.group('f', 'r', 't')
239 if(f in devtemp): 334 if(f in devtemp):
240 data.newAction('boot', f, devtemp[f], ktime, int(r), int(t)) 335 start, pid = devtemp[f]
241 data.end = ktime 336 data.newAction(phase, f, pid, start, ktime, int(r), int(t))
242 del devtemp[f] 337 del devtemp[f]
243 continue 338 continue
244 if(re.match('^Freeing unused kernel memory.*', msg)): 339 if(re.match('^Freeing unused kernel memory.*', msg)):
245 break 340 data.tUserMode = ktime
246 341 data.dmesg['kernel']['end'] = ktime
247 data.dmesg['boot']['end'] = data.end 342 data.dmesg['user']['start'] = ktime
343 phase = 'user'
344
345 if tp.stamp:
346 sysvals.stamp = 0
347 tp.parseStamp(data, sysvals)
348 data.dmesg['user']['end'] = data.end
248 lf.close() 349 lf.close()
249 return data 350 return data
250 351
251# Function: loadTraceLog 352# Function: parseTraceLog
252# Description: 353# Description:
253# Check if trace is available and copy to a temp file 354# Check if trace is available and copy to a temp file
254def loadTraceLog(data): 355def parseTraceLog(data):
255 # load the data to a temp file if none given
256 if not sysvals.ftracefile:
257 lib = aslib.sysvals
258 aslib.rootCheck(True)
259 if not lib.verifyFtrace():
260 doError('ftrace not available')
261 if lib.fgetVal('current_tracer').strip() != 'function_graph':
262 doError('ftrace not configured for a boot callgraph')
263 sysvals.ftracefile = '/tmp/boot_ftrace.%s.txt' % os.getpid()
264 call('cat '+lib.tpath+'trace > '+sysvals.ftracefile, shell=True)
265 if not sysvals.ftracefile:
266 doError('No trace data available')
267
268 # parse the trace log 356 # parse the trace log
269 ftemp = dict() 357 ftemp = dict()
270 tp = aslib.TestProps() 358 tp = aslib.TestProps()
@@ -306,9 +394,29 @@ def loadTraceLog(data):
306 print('Sanity check failed for %s-%d' % (proc, pid)) 394 print('Sanity check failed for %s-%d' % (proc, pid))
307 continue 395 continue
308 # match cg data to devices 396 # match cg data to devices
309 if not data.deviceMatch(cg): 397 if not data.deviceMatch(pid, cg):
310 print ' BAD: %s %s-%d [%f - %f]' % (cg.name, proc, pid, cg.start, cg.end) 398 print ' BAD: %s %s-%d [%f - %f]' % (cg.name, proc, pid, cg.start, cg.end)
311 399
400# Function: retrieveLogs
401# Description:
402# Create copies of dmesg and/or ftrace for later processing
403def retrieveLogs():
404 # check ftrace is configured first
405 if sysvals.useftrace:
406 tracer = sysvals.fgetVal('current_tracer').strip()
407 if tracer != 'function_graph':
408 doError('ftrace not configured for a boot callgraph')
409 # create the folder and get dmesg
410 sysvals.systemInfo(aslib.dmidecode(sysvals.mempath))
411 sysvals.initTestOutput('boot')
412 sysvals.writeDatafileHeader(sysvals.dmesgfile)
413 call('dmesg >> '+sysvals.dmesgfile, shell=True)
414 if not sysvals.useftrace:
415 return
416 # get ftrace
417 sysvals.writeDatafileHeader(sysvals.ftracefile)
418 call('cat '+sysvals.tpath+'trace >> '+sysvals.ftracefile, shell=True)
419
312# Function: colorForName 420# Function: colorForName
313# Description: 421# Description:
314# Generate a repeatable color from a list for a given name 422# Generate a repeatable color from a list for a given name
@@ -353,18 +461,19 @@ def cgOverview(cg, minlen):
353# testruns: array of Data objects from parseKernelLog or parseTraceLog 461# testruns: array of Data objects from parseKernelLog or parseTraceLog
354# Output: 462# Output:
355# True if the html file was created, false if it failed 463# True if the html file was created, false if it failed
356def createBootGraph(data, embedded): 464def createBootGraph(data):
357 # html function templates 465 # html function templates
358 html_srccall = '<div id={6} title="{5}" class="srccall" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;">{0}</div>\n' 466 html_srccall = '<div id={6} title="{5}" class="srccall" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;">{0}</div>\n'
359 html_timetotal = '<table class="time1">\n<tr>'\ 467 html_timetotal = '<table class="time1">\n<tr>'\
360 '<td class="blue">Time from Kernel Boot to start of User Mode: <b>{0} ms</b></td>'\ 468 '<td class="blue">Init process starts @ <b>{0} ms</b></td>'\
469 '<td class="blue">Last initcall ends @ <b>{1} ms</b></td>'\
361 '</tr>\n</table>\n' 470 '</tr>\n</table>\n'
362 471
363 # device timeline 472 # device timeline
364 devtl = aslib.Timeline(100, 20) 473 devtl = aslib.Timeline(100, 20)
365 474
366 # write the test title and general info header 475 # write the test title and general info header
367 devtl.createHeader(sysvals, 'noftrace') 476 devtl.createHeader(sysvals)
368 477
369 # Generate the header for this timeline 478 # Generate the header for this timeline
370 t0 = data.start 479 t0 = data.start
@@ -373,84 +482,98 @@ def createBootGraph(data, embedded):
373 if(tTotal == 0): 482 if(tTotal == 0):
374 print('ERROR: No timeline data') 483 print('ERROR: No timeline data')
375 return False 484 return False
376 boot_time = '%.0f'%(tTotal*1000) 485 user_mode = '%.0f'%(data.tUserMode*1000)
377 devtl.html += html_timetotal.format(boot_time) 486 last_init = '%.0f'%(tTotal*1000)
487 devtl.html += html_timetotal.format(user_mode, last_init)
378 488
379 # determine the maximum number of rows we need to draw 489 # determine the maximum number of rows we need to draw
380 phase = 'boot'
381 list = data.dmesg[phase]['list']
382 devlist = [] 490 devlist = []
383 for devname in list: 491 for p in data.phases:
384 d = aslib.DevItem(0, phase, list[devname]) 492 list = data.dmesg[p]['list']
385 devlist.append(d) 493 for devname in list:
386 devtl.getPhaseRows(devlist) 494 d = aslib.DevItem(0, p, list[devname])
495 devlist.append(d)
496 devtl.getPhaseRows(devlist, 0, 'start')
387 devtl.calcTotalRows() 497 devtl.calcTotalRows()
388 498
389 # draw the timeline background 499 # draw the timeline background
390 devtl.createZoomBox() 500 devtl.createZoomBox()
391 boot = data.dmesg[phase] 501 devtl.html += devtl.html_tblock.format('boot', '0', '100', devtl.scaleH)
392 length = boot['end']-boot['start'] 502 for p in data.phases:
393 left = '%.3f' % (((boot['start']-t0)*100.0)/tTotal) 503 phase = data.dmesg[p]
394 width = '%.3f' % ((length*100.0)/tTotal) 504 length = phase['end']-phase['start']
395 devtl.html += devtl.html_tblock.format(phase, left, width, devtl.scaleH) 505 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal)
396 devtl.html += devtl.html_phase.format('0', '100', \ 506 width = '%.3f' % ((length*100.0)/tTotal)
397 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \ 507 devtl.html += devtl.html_phase.format(left, width, \
398 'white', '') 508 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \
509 phase['color'], '')
399 510
400 # draw the device timeline 511 # draw the device timeline
401 num = 0 512 num = 0
402 devstats = dict() 513 devstats = dict()
403 for devname in sorted(list): 514 for phase in data.phases:
404 cls, color = colorForName(devname) 515 list = data.dmesg[phase]['list']
405 dev = list[devname] 516 for devname in sorted(list):
406 info = '@|%.3f|%.3f|%.3f|%d' % (dev['start']*1000.0, dev['end']*1000.0, 517 cls, color = colorForName(devname)
407 dev['ulen']/1000.0, dev['ret']) 518 dev = list[devname]
408 devstats[dev['id']] = {'info':info} 519 info = '@|%.3f|%.3f|%.3f|%d' % (dev['start']*1000.0, dev['end']*1000.0,
409 dev['color'] = color 520 dev['ulen']/1000.0, dev['ret'])
410 height = devtl.phaseRowHeight(0, phase, dev['row']) 521 devstats[dev['id']] = {'info':info}
411 top = '%.6f' % ((dev['row']*height) + devtl.scaleH) 522 dev['color'] = color
412 left = '%.6f' % (((dev['start']-t0)*100)/tTotal) 523 height = devtl.phaseRowHeight(0, phase, dev['row'])
413 width = '%.6f' % (((dev['end']-dev['start'])*100)/tTotal) 524 top = '%.6f' % ((dev['row']*height) + devtl.scaleH)
414 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) 525 left = '%.6f' % (((dev['start']-t0)*100)/tTotal)
415 devtl.html += devtl.html_device.format(dev['id'], 526 width = '%.6f' % (((dev['end']-dev['start'])*100)/tTotal)
416 devname+length+'kernel_mode', left, top, '%.3f'%height, 527 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000)
417 width, devname, ' '+cls, '') 528 devtl.html += devtl.html_device.format(dev['id'],
418 rowtop = devtl.phaseRowTop(0, phase, dev['row']) 529 devname+length+phase+'_mode', left, top, '%.3f'%height,
419 height = '%.6f' % (devtl.rowH / 2) 530 width, devname, ' '+cls, '')
420 top = '%.6f' % (rowtop + devtl.scaleH + (devtl.rowH / 2)) 531 rowtop = devtl.phaseRowTop(0, phase, dev['row'])
421 if data.do_one_initcall: 532 height = '%.6f' % (devtl.rowH / 2)
422 if('ftrace' not in dev): 533 top = '%.6f' % (rowtop + devtl.scaleH + (devtl.rowH / 2))
534 if data.do_one_initcall:
535 if('ftrace' not in dev):
536 continue
537 cg = dev['ftrace']
538 large, stats = cgOverview(cg, 0.001)
539 devstats[dev['id']]['fstat'] = stats
540 for l in large:
541 left = '%f' % (((l.time-t0)*100)/tTotal)
542 width = '%f' % (l.length*100/tTotal)
543 title = '%s (%0.3fms)' % (l.name, l.length * 1000.0)
544 devtl.html += html_srccall.format(l.name, left,
545 top, height, width, title, 'x%d'%num)
546 num += 1
547 continue
548 if('ftraces' not in dev):
423 continue 549 continue
424 cg = dev['ftrace'] 550 for cg in dev['ftraces']:
425 large, stats = cgOverview(cg, 0.001) 551 left = '%f' % (((cg.start-t0)*100)/tTotal)
426 devstats[dev['id']]['fstat'] = stats 552 width = '%f' % ((cg.end-cg.start)*100/tTotal)
427 for l in large: 553 cglen = (cg.end - cg.start) * 1000.0
428 left = '%f' % (((l.time-t0)*100)/tTotal) 554 title = '%s (%0.3fms)' % (cg.name, cglen)
429 width = '%f' % (l.length*100/tTotal) 555 cg.id = 'x%d' % num
430 title = '%s (%0.3fms)' % (l.name, l.length * 1000.0) 556 devtl.html += html_srccall.format(cg.name, left,
431 devtl.html += html_srccall.format(l.name, left, 557 top, height, width, title, dev['id']+cg.id)
432 top, height, width, title, 'x%d'%num)
433 num += 1 558 num += 1
434 continue
435 if('ftraces' not in dev):
436 continue
437 for cg in dev['ftraces']:
438 left = '%f' % (((cg.start-t0)*100)/tTotal)
439 width = '%f' % ((cg.end-cg.start)*100/tTotal)
440 cglen = (cg.end - cg.start) * 1000.0
441 title = '%s (%0.3fms)' % (cg.name, cglen)
442 cg.id = 'x%d' % num
443 devtl.html += html_srccall.format(cg.name, left,
444 top, height, width, title, dev['id']+cg.id)
445 num += 1
446 559
447 # draw the time scale, try to make the number of labels readable 560 # draw the time scale, try to make the number of labels readable
448 devtl.createTimeScale(t0, tMax, tTotal, phase) 561 devtl.createTimeScale(t0, tMax, tTotal, 'boot')
449 devtl.html += '</div>\n' 562 devtl.html += '</div>\n'
450 563
451 # timeline is finished 564 # timeline is finished
452 devtl.html += '</div>\n</div>\n' 565 devtl.html += '</div>\n</div>\n'
453 566
567 # draw a legend which describes the phases by color
568 devtl.html += '<div class="legend">\n'
569 pdelta = 20.0
570 pmargin = 36.0
571 for phase in data.phases:
572 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
573 devtl.html += devtl.html_legend.format(order, \
574 data.dmesg[phase]['color'], phase+'_mode', phase[0])
575 devtl.html += '</div>\n'
576
454 if(sysvals.outfile == sysvals.htmlfile): 577 if(sysvals.outfile == sysvals.htmlfile):
455 hf = open(sysvals.htmlfile, 'a') 578 hf = open(sysvals.htmlfile, 'a')
456 else: 579 else:
@@ -474,7 +597,7 @@ def createBootGraph(data, embedded):
474 .fstat td {text-align:left;width:35px;}\n\ 597 .fstat td {text-align:left;width:35px;}\n\
475 .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\ 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\
476 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n' 599 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n'
477 if(not embedded): 600 if(not sysvals.embedded):
478 aslib.addCSS(hf, sysvals, 1, False, extra) 601 aslib.addCSS(hf, sysvals, 1, False, extra)
479 602
480 # write the device timeline 603 # write the device timeline
@@ -495,9 +618,11 @@ def createBootGraph(data, embedded):
495 html = \ 618 html = \
496 '<div id="devicedetailtitle"></div>\n'\ 619 '<div id="devicedetailtitle"></div>\n'\
497 '<div id="devicedetail" style="display:none;">\n'\ 620 '<div id="devicedetail" style="display:none;">\n'\
498 '<div id="devicedetail0">\n'\ 621 '<div id="devicedetail0">\n'
499 '<div id="kernel_mode" class="phaselet" style="left:0%;width:100%;background:#DDDDDD"></div>\n'\ 622 for p in data.phases:
500 '</div>\n</div>\n'\ 623 phase = data.dmesg[p]
624 html += devtl.html_phaselet.format(p+'_mode', '0', '100', phase['color'])
625 html += '</div>\n</div>\n'\
501 '<script type="text/javascript">\n'+statinfo+\ 626 '<script type="text/javascript">\n'+statinfo+\
502 '</script>\n' 627 '</script>\n'
503 hf.write(html) 628 hf.write(html)
@@ -507,21 +632,21 @@ def createBootGraph(data, embedded):
507 aslib.addCallgraphs(sysvals, hf, data) 632 aslib.addCallgraphs(sysvals, hf, data)
508 633
509 # add the dmesg log as a hidden div 634 # add the dmesg log as a hidden div
510 if sysvals.addlogs: 635 if sysvals.dmesglog:
511 hf.write('<div id="dmesglog" style="display:none;">\n') 636 hf.write('<div id="dmesglog" style="display:none;">\n')
512 for line in data.dmesgtext: 637 for line in data.dmesgtext:
513 line = line.replace('<', '&lt').replace('>', '&gt') 638 line = line.replace('<', '&lt').replace('>', '&gt')
514 hf.write(line) 639 hf.write(line)
515 hf.write('</div>\n') 640 hf.write('</div>\n')
516 641
517 if(not embedded): 642 if(not sysvals.embedded):
518 # write the footer and close 643 # write the footer and close
519 aslib.addScriptCode(hf, [data]) 644 aslib.addScriptCode(hf, [data])
520 hf.write('</body>\n</html>\n') 645 hf.write('</body>\n</html>\n')
521 else: 646 else:
522 # embedded out will be loaded in a page, skip the js 647 # embedded out will be loaded in a page, skip the js
523 hf.write('<div id=bounds style=display:none>%f,%f</div>' % \ 648 hf.write('<div id=bounds style=display:none>%f,%f</div>' % \
524 (data.start*1000, data.initstart*1000)) 649 (data.start*1000, data.end*1000))
525 hf.close() 650 hf.close()
526 return True 651 return True
527 652
@@ -533,17 +658,20 @@ def updateCron(restore=False):
533 if not restore: 658 if not restore:
534 sysvals.rootUser(True) 659 sysvals.rootUser(True)
535 crondir = '/var/spool/cron/crontabs/' 660 crondir = '/var/spool/cron/crontabs/'
536 cronfile = crondir+'root' 661 if not os.path.exists(crondir):
537 backfile = crondir+'root-analyze_boot-backup' 662 crondir = '/var/spool/cron/'
538 if not os.path.exists(crondir): 663 if not os.path.exists(crondir):
539 doError('%s not found' % crondir) 664 doError('%s not found' % crondir)
540 out = Popen(['which', 'crontab'], stdout=PIPE).stdout.read() 665 cronfile = crondir+'root'
541 if not out: 666 backfile = crondir+'root-analyze_boot-backup'
667 cmd = sysvals.getExec('crontab')
668 if not cmd:
542 doError('crontab not found') 669 doError('crontab not found')
543 # on restore: move the backup cron back into place 670 # on restore: move the backup cron back into place
544 if restore: 671 if restore:
545 if os.path.exists(backfile): 672 if os.path.exists(backfile):
546 shutil.move(backfile, cronfile) 673 shutil.move(backfile, cronfile)
674 call([cmd, cronfile])
547 return 675 return
548 # backup current cron and install new one with reboot 676 # backup current cron and install new one with reboot
549 if os.path.exists(cronfile): 677 if os.path.exists(cronfile):
@@ -556,13 +684,13 @@ def updateCron(restore=False):
556 fp = open(backfile, 'r') 684 fp = open(backfile, 'r')
557 op = open(cronfile, 'w') 685 op = open(cronfile, 'w')
558 for line in fp: 686 for line in fp:
559 if '@reboot' not in line: 687 if not sysvals.myCronJob(line):
560 op.write(line) 688 op.write(line)
561 continue 689 continue
562 fp.close() 690 fp.close()
563 op.write('@reboot python %s\n' % sysvals.cronjobCmdString()) 691 op.write('@reboot python %s\n' % sysvals.cronjobCmdString())
564 op.close() 692 op.close()
565 res = call('crontab %s' % cronfile, shell=True) 693 res = call([cmd, cronfile])
566 except Exception, e: 694 except Exception, e:
567 print 'Exception: %s' % str(e) 695 print 'Exception: %s' % str(e)
568 shutil.move(backfile, cronfile) 696 shutil.move(backfile, cronfile)
@@ -577,25 +705,16 @@ def updateGrub(restore=False):
577 # call update-grub on restore 705 # call update-grub on restore
578 if restore: 706 if restore:
579 try: 707 try:
580 call(['update-grub'], stderr=PIPE, stdout=PIPE, 708 call(sysvals.blexec, stderr=PIPE, stdout=PIPE,
581 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'}) 709 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'})
582 except Exception, e: 710 except Exception, e:
583 print 'Exception: %s\n' % str(e) 711 print 'Exception: %s\n' % str(e)
584 return 712 return
585 # verify we can do this
586 sysvals.rootUser(True)
587 grubfile = '/etc/default/grub'
588 if not os.path.exists(grubfile):
589 print 'ERROR: Unable to set the kernel parameters via grub.\n'
590 sysvals.manualRebootRequired()
591 out = Popen(['which', 'update-grub'], stdout=PIPE).stdout.read()
592 if not out:
593 print 'ERROR: Unable to set the kernel parameters via grub.\n'
594 sysvals.manualRebootRequired()
595
596 # extract the option and create a grub config without it 713 # extract the option and create a grub config without it
714 sysvals.rootUser(True)
597 tgtopt = 'GRUB_CMDLINE_LINUX_DEFAULT' 715 tgtopt = 'GRUB_CMDLINE_LINUX_DEFAULT'
598 cmdline = '' 716 cmdline = ''
717 grubfile = '/etc/default/grub'
599 tempfile = '/etc/default/grub.analyze_boot' 718 tempfile = '/etc/default/grub.analyze_boot'
600 shutil.move(grubfile, tempfile) 719 shutil.move(grubfile, tempfile)
601 res = -1 720 res = -1
@@ -622,7 +741,7 @@ def updateGrub(restore=False):
622 # if the target option value is in quotes, strip them 741 # if the target option value is in quotes, strip them
623 sp = '"' 742 sp = '"'
624 val = cmdline.strip() 743 val = cmdline.strip()
625 if val[0] == '\'' or val[0] == '"': 744 if val and (val[0] == '\'' or val[0] == '"'):
626 sp = val[0] 745 sp = val[0]
627 val = val.strip(sp) 746 val = val.strip(sp)
628 cmdline = val 747 cmdline = val
@@ -633,7 +752,7 @@ def updateGrub(restore=False):
633 # write out the updated target option 752 # write out the updated target option
634 op.write('\n%s=%s%s%s\n' % (tgtopt, sp, cmdline, sp)) 753 op.write('\n%s=%s%s%s\n' % (tgtopt, sp, cmdline, sp))
635 op.close() 754 op.close()
636 res = call('update-grub') 755 res = call(sysvals.blexec)
637 os.remove(grubfile) 756 os.remove(grubfile)
638 except Exception, e: 757 except Exception, e:
639 print 'Exception: %s' % str(e) 758 print 'Exception: %s' % str(e)
@@ -641,10 +760,18 @@ def updateGrub(restore=False):
641 # cleanup 760 # cleanup
642 shutil.move(tempfile, grubfile) 761 shutil.move(tempfile, grubfile)
643 if res != 0: 762 if res != 0:
644 doError('update-grub failed') 763 doError('update grub failed')
645 764
646# Function: doError 765# Function: updateKernelParams
647# Description: 766# Description:
767# update boot conf for all kernels with our parameters
768def updateKernelParams(restore=False):
769 # find the boot loader
770 sysvals.getBootLoader()
771 if sysvals.bootloader == 'grub':
772 updateGrub(restore)
773
774# Function: doError Description:
648# generic error function for catastrphic failures 775# generic error function for catastrphic failures
649# Arguments: 776# Arguments:
650# msg: the error message to print 777# msg: the error message to print
@@ -660,7 +787,7 @@ def doError(msg, help=False):
660# print out the help text 787# print out the help text
661def printHelp(): 788def printHelp():
662 print('') 789 print('')
663 print('%s v%.1f' % (sysvals.title, sysvals.version)) 790 print('%s v%s' % (sysvals.title, sysvals.version))
664 print('Usage: bootgraph <options> <command>') 791 print('Usage: bootgraph <options> <command>')
665 print('') 792 print('')
666 print('Description:') 793 print('Description:')
@@ -669,13 +796,19 @@ def printHelp():
669 print(' the start of the init process.') 796 print(' the start of the init process.')
670 print('') 797 print('')
671 print(' If no specific command is given the tool reads the current dmesg') 798 print(' If no specific command is given the tool reads the current dmesg')
672 print(' and/or ftrace log and outputs bootgraph.html') 799 print(' and/or ftrace log and creates a timeline')
800 print('')
801 print(' Generates output files in subdirectory: boot-yymmdd-HHMMSS')
802 print(' HTML output: <hostname>_boot.html')
803 print(' raw dmesg output: <hostname>_boot_dmesg.txt')
804 print(' raw ftrace output: <hostname>_boot_ftrace.txt')
673 print('') 805 print('')
674 print('Options:') 806 print('Options:')
675 print(' -h Print this help text') 807 print(' -h Print this help text')
676 print(' -v Print the current tool version') 808 print(' -v Print the current tool version')
677 print(' -addlogs Add the dmesg log to the html output') 809 print(' -addlogs Add the dmesg log to the html output')
678 print(' -o file Html timeline name (default: bootgraph.html)') 810 print(' -o name Overrides the output subdirectory name when running a new test')
811 print(' default: boot-{date}-{time}')
679 print(' [advanced]') 812 print(' [advanced]')
680 print(' -f Use ftrace to add function detail (default: disabled)') 813 print(' -f Use ftrace to add function detail (default: disabled)')
681 print(' -callgraph Add callgraph detail, can be very large (default: disabled)') 814 print(' -callgraph Add callgraph detail, can be very large (default: disabled)')
@@ -683,13 +816,18 @@ def printHelp():
683 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)') 816 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)')
684 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])') 817 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])')
685 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)') 818 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)')
686 print(' -filter list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)') 819 print(' -func list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)')
687 print(' [commands]') 820 print(' -cgfilter S Filter the callgraph output in the timeline')
821 print(' -bl name Use the following boot loader for kernel params (default: grub)')
688 print(' -reboot Reboot the machine automatically and generate a new timeline') 822 print(' -reboot Reboot the machine automatically and generate a new timeline')
689 print(' -manual Show the requirements to generate a new timeline manually') 823 print(' -manual Show the steps to generate a new timeline manually (used with -reboot)')
690 print(' -dmesg file Load a stored dmesg file (used with -ftrace)') 824 print('')
691 print(' -ftrace file Load a stored ftrace file (used with -dmesg)') 825 print('Other commands:')
692 print(' -flistall Print all functions capable of being captured in ftrace') 826 print(' -flistall Print all functions capable of being captured in ftrace')
827 print(' -sysinfo Print out system info extracted from BIOS')
828 print(' [redo]')
829 print(' -dmesg file Create HTML output using dmesg input (used with -ftrace)')
830 print(' -ftrace file Create HTML output using ftrace input (used with -dmesg)')
693 print('') 831 print('')
694 return True 832 return True
695 833
@@ -698,14 +836,15 @@ def printHelp():
698if __name__ == '__main__': 836if __name__ == '__main__':
699 # loop through the command line arguments 837 # loop through the command line arguments
700 cmd = '' 838 cmd = ''
701 simplecmds = ['-updategrub', '-flistall'] 839 testrun = True
840 simplecmds = ['-sysinfo', '-kpupdate', '-flistall', '-checkbl']
702 args = iter(sys.argv[1:]) 841 args = iter(sys.argv[1:])
703 for arg in args: 842 for arg in args:
704 if(arg == '-h'): 843 if(arg == '-h'):
705 printHelp() 844 printHelp()
706 sys.exit() 845 sys.exit()
707 elif(arg == '-v'): 846 elif(arg == '-v'):
708 print("Version %.1f" % sysvals.version) 847 print("Version %s" % sysvals.version)
709 sys.exit() 848 sys.exit()
710 elif(arg in simplecmds): 849 elif(arg in simplecmds):
711 cmd = arg[1:] 850 cmd = arg[1:]
@@ -716,16 +855,32 @@ if __name__ == '__main__':
716 sysvals.usecallgraph = True 855 sysvals.usecallgraph = True
717 elif(arg == '-mincg'): 856 elif(arg == '-mincg'):
718 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) 857 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
858 elif(arg == '-cgfilter'):
859 try:
860 val = args.next()
861 except:
862 doError('No callgraph functions supplied', True)
863 sysvals.setDeviceFilter(val)
864 elif(arg == '-bl'):
865 try:
866 val = args.next()
867 except:
868 doError('No boot loader name supplied', True)
869 if val.lower() not in ['grub']:
870 doError('Unknown boot loader: %s' % val, True)
871 sysvals.bootloader = val.lower()
719 elif(arg == '-timeprec'): 872 elif(arg == '-timeprec'):
720 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6)) 873 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6))
721 elif(arg == '-maxdepth'): 874 elif(arg == '-maxdepth'):
722 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) 875 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
723 elif(arg == '-filter'): 876 elif(arg == '-func'):
724 try: 877 try:
725 val = args.next() 878 val = args.next()
726 except: 879 except:
727 doError('No filter functions supplied', True) 880 doError('No filter functions supplied', True)
728 aslib.rootCheck(True) 881 sysvals.useftrace = True
882 sysvals.usecallgraph = True
883 sysvals.rootCheck(True)
729 sysvals.setGraphFilter(val) 884 sysvals.setGraphFilter(val)
730 elif(arg == '-ftrace'): 885 elif(arg == '-ftrace'):
731 try: 886 try:
@@ -734,9 +889,10 @@ if __name__ == '__main__':
734 doError('No ftrace file supplied', True) 889 doError('No ftrace file supplied', True)
735 if(os.path.exists(val) == False): 890 if(os.path.exists(val) == False):
736 doError('%s does not exist' % val) 891 doError('%s does not exist' % val)
892 testrun = False
737 sysvals.ftracefile = val 893 sysvals.ftracefile = val
738 elif(arg == '-addlogs'): 894 elif(arg == '-addlogs'):
739 sysvals.addlogs = True 895 sysvals.dmesglog = True
740 elif(arg == '-expandcg'): 896 elif(arg == '-expandcg'):
741 sysvals.cgexp = True 897 sysvals.cgexp = True
742 elif(arg == '-dmesg'): 898 elif(arg == '-dmesg'):
@@ -748,18 +904,15 @@ if __name__ == '__main__':
748 doError('%s does not exist' % val) 904 doError('%s does not exist' % val)
749 if(sysvals.htmlfile == val or sysvals.outfile == val): 905 if(sysvals.htmlfile == val or sysvals.outfile == val):
750 doError('Output filename collision') 906 doError('Output filename collision')
907 testrun = False
751 sysvals.dmesgfile = val 908 sysvals.dmesgfile = val
752 elif(arg == '-o'): 909 elif(arg == '-o'):
753 try: 910 try:
754 val = args.next() 911 val = args.next()
755 except: 912 except:
756 doError('No HTML filename supplied', True) 913 doError('No subdirectory name supplied', True)
757 if(sysvals.dmesgfile == val or sysvals.ftracefile == val): 914 sysvals.testdir = sysvals.setOutputFolder(val)
758 doError('Output filename collision')
759 sysvals.htmlfile = val
760 elif(arg == '-reboot'): 915 elif(arg == '-reboot'):
761 if sysvals.iscronjob:
762 doError('-reboot and -cronjob are incompatible')
763 sysvals.reboot = True 916 sysvals.reboot = True
764 elif(arg == '-manual'): 917 elif(arg == '-manual'):
765 sysvals.reboot = True 918 sysvals.reboot = True
@@ -767,58 +920,93 @@ if __name__ == '__main__':
767 # remaining options are only for cron job use 920 # remaining options are only for cron job use
768 elif(arg == '-cronjob'): 921 elif(arg == '-cronjob'):
769 sysvals.iscronjob = True 922 sysvals.iscronjob = True
770 if sysvals.reboot:
771 doError('-reboot and -cronjob are incompatible')
772 else: 923 else:
773 doError('Invalid argument: '+arg, True) 924 doError('Invalid argument: '+arg, True)
774 925
926 # compatibility errors and access checks
927 if(sysvals.iscronjob and (sysvals.reboot or \
928 sysvals.dmesgfile or sysvals.ftracefile or cmd)):
929 doError('-cronjob is meant for batch purposes only')
930 if(sysvals.reboot and (sysvals.dmesgfile or sysvals.ftracefile)):
931 doError('-reboot and -dmesg/-ftrace are incompatible')
932 if cmd or sysvals.reboot or sysvals.iscronjob or testrun:
933 sysvals.rootCheck(True)
934 if (testrun and sysvals.useftrace) or cmd == 'flistall':
935 if not sysvals.verifyFtrace():
936 doError('Ftrace is not properly enabled')
937
938 # run utility commands
939 sysvals.cpuInfo()
775 if cmd != '': 940 if cmd != '':
776 if cmd == 'updategrub': 941 if cmd == 'kpupdate':
777 updateGrub() 942 updateKernelParams()
778 elif cmd == 'flistall': 943 elif cmd == 'flistall':
779 sysvals.getFtraceFilterFunctions(False) 944 for f in sysvals.getBootFtraceFilterFunctions():
945 print f
946 elif cmd == 'checkbl':
947 sysvals.getBootLoader()
948 print 'Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec)
949 elif(cmd == 'sysinfo'):
950 sysvals.printSystemInfo()
780 sys.exit() 951 sys.exit()
781 952
782 # update grub, setup a cronjob, and reboot 953 # reboot: update grub, setup a cronjob, and reboot
783 if sysvals.reboot: 954 if sysvals.reboot:
955 if (sysvals.useftrace or sysvals.usecallgraph) and \
956 not sysvals.checkFtraceKernelVersion():
957 doError('Ftrace functionality requires kernel v4.10 or newer')
784 if not sysvals.manual: 958 if not sysvals.manual:
785 updateGrub() 959 updateKernelParams()
786 updateCron() 960 updateCron()
787 call('reboot') 961 call('reboot')
788 else: 962 else:
789 sysvals.manualRebootRequired() 963 sysvals.manualRebootRequired()
790 sys.exit() 964 sys.exit()
791 965
792 # disable the cronjob 966 # cronjob: remove the cronjob, grub changes, and disable ftrace
793 if sysvals.iscronjob: 967 if sysvals.iscronjob:
794 updateCron(True) 968 updateCron(True)
795 updateGrub(True) 969 updateKernelParams(True)
970 try:
971 sysvals.fsetVal('0', 'tracing_on')
972 except:
973 pass
796 974
797 data = loadKernelLog() 975 # testrun: generate copies of the logs
798 if sysvals.useftrace: 976 if testrun:
799 loadTraceLog(data) 977 retrieveLogs()
800 if sysvals.iscronjob: 978 else:
801 try: 979 sysvals.setOutputFile()
802 sysvals.fsetVal('0', 'tracing_on')
803 except:
804 pass
805 980
806 if(sysvals.outfile and sysvals.phoronix): 981 # process the log data
807 fp = open(sysvals.outfile, 'w') 982 if sysvals.dmesgfile:
808 fp.write('pass %s initstart %.3f end %.3f boot %s\n' % 983 data = parseKernelLog()
809 (data.valid, data.initstart*1000, data.end*1000, data.boottime)) 984 if(not data.valid):
810 fp.close()
811 if(not data.valid):
812 if sysvals.dmesgfile:
813 doError('No initcall data found in %s' % sysvals.dmesgfile) 985 doError('No initcall data found in %s' % sysvals.dmesgfile)
814 else: 986 if sysvals.useftrace and sysvals.ftracefile:
815 doError('No initcall data found, is initcall_debug enabled?') 987 parseTraceLog(data)
988 else:
989 doError('dmesg file required')
816 990
817 print(' Host: %s' % sysvals.hostname) 991 print(' Host: %s' % sysvals.hostname)
818 print(' Test time: %s' % sysvals.testtime) 992 print(' Test time: %s' % sysvals.testtime)
819 print(' Boot time: %s' % data.boottime) 993 print(' Boot time: %s' % data.boottime)
820 print('Kernel Version: %s' % sysvals.kernel) 994 print('Kernel Version: %s' % sysvals.kernel)
821 print(' Kernel start: %.3f' % (data.start * 1000)) 995 print(' Kernel start: %.3f' % (data.start * 1000))
822 print(' init start: %.3f' % (data.initstart * 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)
823 1007
824 createBootGraph(data, sysvals.phoronix) 1008 # if running as root, change output dir owner to sudo_user
1009 if testrun and os.path.isdir(sysvals.testdir) and \
1010 os.getuid() == 0 and 'SUDO_USER' in os.environ:
1011 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
1012 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True)
diff --git a/tools/power/pm-graph/analyze_suspend.py b/tools/power/pm-graph/analyze_suspend.py
index a9206e67fc1f..1b60fe203741 100755
--- a/tools/power/pm-graph/analyze_suspend.py
+++ b/tools/power/pm-graph/analyze_suspend.py
@@ -68,10 +68,12 @@ from subprocess import call, Popen, PIPE
68# store system values and test parameters 68# store system values and test parameters
69class SystemValues: 69class SystemValues:
70 title = 'SleepGraph' 70 title = 'SleepGraph'
71 version = '4.6' 71 version = '4.7'
72 ansi = False 72 ansi = False
73 verbose = False 73 verbose = False
74 addlogs = False 74 testlog = True
75 dmesglog = False
76 ftracelog = False
75 mindevlen = 0.0 77 mindevlen = 0.0
76 mincglen = 0.0 78 mincglen = 0.0
77 cgphase = '' 79 cgphase = ''
@@ -79,10 +81,11 @@ class SystemValues:
79 max_graph_depth = 0 81 max_graph_depth = 0
80 callloopmaxgap = 0.0001 82 callloopmaxgap = 0.0001
81 callloopmaxlen = 0.005 83 callloopmaxlen = 0.005
84 cpucount = 0
85 memtotal = 204800
82 srgap = 0 86 srgap = 0
83 cgexp = False 87 cgexp = False
84 outdir = '' 88 testdir = ''
85 testdir = '.'
86 tpath = '/sys/kernel/debug/tracing/' 89 tpath = '/sys/kernel/debug/tracing/'
87 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 90 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
88 epath = '/sys/kernel/debug/tracing/events/power/' 91 epath = '/sys/kernel/debug/tracing/events/power/'
@@ -95,14 +98,17 @@ class SystemValues:
95 testcommand = '' 98 testcommand = ''
96 mempath = '/dev/mem' 99 mempath = '/dev/mem'
97 powerfile = '/sys/power/state' 100 powerfile = '/sys/power/state'
101 mempowerfile = '/sys/power/mem_sleep'
98 suspendmode = 'mem' 102 suspendmode = 'mem'
103 memmode = ''
99 hostname = 'localhost' 104 hostname = 'localhost'
100 prefix = 'test' 105 prefix = 'test'
101 teststamp = '' 106 teststamp = ''
107 sysstamp = ''
102 dmesgstart = 0.0 108 dmesgstart = 0.0
103 dmesgfile = '' 109 dmesgfile = ''
104 ftracefile = '' 110 ftracefile = ''
105 htmlfile = '' 111 htmlfile = 'output.html'
106 embedded = False 112 embedded = False
107 rtcwake = True 113 rtcwake = True
108 rtcwaketime = 15 114 rtcwaketime = 15
@@ -127,9 +133,6 @@ class SystemValues:
127 devpropfmt = '# Device Properties: .*' 133 devpropfmt = '# Device Properties: .*'
128 tracertypefmt = '# tracer: (?P<t>.*)' 134 tracertypefmt = '# tracer: (?P<t>.*)'
129 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 135 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
130 stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
131 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
132 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
133 tracefuncs = { 136 tracefuncs = {
134 'sys_sync': dict(), 137 'sys_sync': dict(),
135 'pm_prepare_console': dict(), 138 'pm_prepare_console': dict(),
@@ -218,7 +221,7 @@ class SystemValues:
218 # if this is a phoronix test run, set some default options 221 # if this is a phoronix test run, set some default options
219 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ): 222 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
220 self.embedded = True 223 self.embedded = True
221 self.addlogs = True 224 self.dmesglog = self.ftracelog = True
222 self.htmlfile = os.environ['LOG_FILE'] 225 self.htmlfile = os.environ['LOG_FILE']
223 self.archargs = 'args_'+platform.machine() 226 self.archargs = 'args_'+platform.machine()
224 self.hostname = platform.node() 227 self.hostname = platform.node()
@@ -233,6 +236,13 @@ class SystemValues:
233 self.rtcpath = rtc 236 self.rtcpath = rtc
234 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 237 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
235 self.ansi = True 238 self.ansi = True
239 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S')
240 def rootCheck(self, fatal=True):
241 if(os.access(self.powerfile, os.W_OK)):
242 return True
243 if fatal:
244 doError('This command requires sysfs mount and root access')
245 return False
236 def rootUser(self, fatal=False): 246 def rootUser(self, fatal=False):
237 if 'USER' in os.environ and os.environ['USER'] == 'root': 247 if 'USER' in os.environ and os.environ['USER'] == 'root':
238 return True 248 return True
@@ -249,30 +259,60 @@ class SystemValues:
249 args['date'] = n.strftime('%y%m%d') 259 args['date'] = n.strftime('%y%m%d')
250 args['time'] = n.strftime('%H%M%S') 260 args['time'] = n.strftime('%H%M%S')
251 args['hostname'] = self.hostname 261 args['hostname'] = self.hostname
252 self.outdir = value.format(**args) 262 return value.format(**args)
253 def setOutputFile(self): 263 def setOutputFile(self):
254 if((self.htmlfile == '') and (self.dmesgfile != '')): 264 if self.dmesgfile != '':
255 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile) 265 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile)
256 if(m): 266 if(m):
257 self.htmlfile = m.group('name')+'.html' 267 self.htmlfile = m.group('name')+'.html'
258 if((self.htmlfile == '') and (self.ftracefile != '')): 268 if self.ftracefile != '':
259 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile) 269 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile)
260 if(m): 270 if(m):
261 self.htmlfile = m.group('name')+'.html' 271 self.htmlfile = m.group('name')+'.html'
262 if(self.htmlfile == ''): 272 def systemInfo(self, info):
263 self.htmlfile = 'output.html' 273 p = c = m = b = ''
264 def initTestOutput(self, subdir, testpath=''): 274 if 'baseboard-manufacturer' in info:
275 m = info['baseboard-manufacturer']
276 elif 'system-manufacturer' in info:
277 m = info['system-manufacturer']
278 if 'baseboard-product-name' in info:
279 p = info['baseboard-product-name']
280 elif 'system-product-name' in info:
281 p = info['system-product-name']
282 if 'processor-version' in info:
283 c = info['processor-version']
284 if 'bios-version' in info:
285 b = info['bios-version']
286 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d' % \
287 (m, p, c, b, self.cpucount, self.memtotal)
288 def printSystemInfo(self):
289 self.rootCheck(True)
290 out = dmidecode(self.mempath, True)
291 fmt = '%-24s: %s'
292 for name in sorted(out):
293 print fmt % (name, out[name])
294 print fmt % ('cpucount', ('%d' % self.cpucount))
295 print fmt % ('memtotal', ('%d kB' % self.memtotal))
296 def cpuInfo(self):
297 self.cpucount = 0
298 fp = open('/proc/cpuinfo', 'r')
299 for line in fp:
300 if re.match('^processor[ \t]*:[ \t]*[0-9]*', line):
301 self.cpucount += 1
302 fp.close()
303 fp = open('/proc/meminfo', 'r')
304 for line in fp:
305 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line)
306 if m:
307 self.memtotal = int(m.group('sz'))
308 break
309 fp.close()
310 def initTestOutput(self, name):
265 self.prefix = self.hostname 311 self.prefix = self.hostname
266 v = open('/proc/version', 'r').read().strip() 312 v = open('/proc/version', 'r').read().strip()
267 kver = string.split(v)[2] 313 kver = string.split(v)[2]
268 n = datetime.now() 314 fmt = name+'-%m%d%y-%H%M%S'
269 testtime = n.strftime('suspend-%m%d%y-%H%M%S') 315 testtime = datetime.now().strftime(fmt)
270 if not testpath:
271 testpath = n.strftime('suspend-%y%m%d-%H%M%S')
272 if(subdir != "."):
273 self.testdir = subdir+"/"+testpath
274 else:
275 self.testdir = testpath
276 self.teststamp = \ 316 self.teststamp = \
277 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 317 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
278 if(self.embedded): 318 if(self.embedded):
@@ -355,7 +395,7 @@ class SystemValues:
355 continue 395 continue
356 self.tracefuncs[i] = dict() 396 self.tracefuncs[i] = dict()
357 def getFtraceFilterFunctions(self, current): 397 def getFtraceFilterFunctions(self, current):
358 rootCheck(True) 398 self.rootCheck(True)
359 if not current: 399 if not current:
360 call('cat '+self.tpath+'available_filter_functions', shell=True) 400 call('cat '+self.tpath+'available_filter_functions', shell=True)
361 return 401 return
@@ -453,7 +493,7 @@ class SystemValues:
453 val += '\nr:%s_ret %s $retval\n' % (name, func) 493 val += '\nr:%s_ret %s $retval\n' % (name, func)
454 return val 494 return val
455 def addKprobes(self, output=False): 495 def addKprobes(self, output=False):
456 if len(sysvals.kprobes) < 1: 496 if len(self.kprobes) < 1:
457 return 497 return
458 if output: 498 if output:
459 print(' kprobe functions in this kernel:') 499 print(' kprobe functions in this kernel:')
@@ -525,7 +565,7 @@ class SystemValues:
525 fp.flush() 565 fp.flush()
526 fp.close() 566 fp.close()
527 except: 567 except:
528 pass 568 return False
529 return True 569 return True
530 def fgetVal(self, path): 570 def fgetVal(self, path):
531 file = self.tpath+path 571 file = self.tpath+path
@@ -566,9 +606,15 @@ class SystemValues:
566 self.cleanupFtrace() 606 self.cleanupFtrace()
567 # set the trace clock to global 607 # set the trace clock to global
568 self.fsetVal('global', 'trace_clock') 608 self.fsetVal('global', 'trace_clock')
569 # set trace buffer to a huge value
570 self.fsetVal('nop', 'current_tracer') 609 self.fsetVal('nop', 'current_tracer')
571 self.fsetVal('131073', 'buffer_size_kb') 610 # set trace buffer to a huge value
611 if self.usecallgraph or self.usedevsrc:
612 tgtsize = min(self.memtotal / 2, 2*1024*1024)
613 maxbuf = '%d' % (tgtsize / max(1, self.cpucount))
614 if self.cpucount < 1 or not self.fsetVal(maxbuf, 'buffer_size_kb'):
615 self.fsetVal('131072', 'buffer_size_kb')
616 else:
617 self.fsetVal('16384', 'buffer_size_kb')
572 # go no further if this is just a status check 618 # go no further if this is just a status check
573 if testing: 619 if testing:
574 return 620 return
@@ -641,6 +687,15 @@ class SystemValues:
641 if not self.ansi: 687 if not self.ansi:
642 return str 688 return str
643 return '\x1B[%d;40m%s\x1B[m' % (color, str) 689 return '\x1B[%d;40m%s\x1B[m' % (color, str)
690 def writeDatafileHeader(self, filename, fwdata=[]):
691 fp = open(filename, 'w')
692 fp.write(self.teststamp+'\n')
693 fp.write(self.sysstamp+'\n')
694 if(self.suspendmode == 'mem' or self.suspendmode == 'command'):
695 for fw in fwdata:
696 if(fw):
697 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
698 fp.close()
644 699
645sysvals = SystemValues() 700sysvals = SystemValues()
646suspendmodename = { 701suspendmodename = {
@@ -1008,6 +1063,12 @@ class Data:
1008 else: 1063 else:
1009 self.trimTime(self.tSuspended, \ 1064 self.trimTime(self.tSuspended, \
1010 self.tResumed-self.tSuspended, False) 1065 self.tResumed-self.tSuspended, False)
1066 def getTimeValues(self):
1067 sktime = (self.dmesg['suspend_machine']['end'] - \
1068 self.tKernSus) * 1000
1069 rktime = (self.dmesg['resume_complete']['end'] - \
1070 self.dmesg['resume_machine']['start']) * 1000
1071 return (sktime, rktime)
1011 def setPhase(self, phase, ktime, isbegin): 1072 def setPhase(self, phase, ktime, isbegin):
1012 if(isbegin): 1073 if(isbegin):
1013 self.dmesg[phase]['start'] = ktime 1074 self.dmesg[phase]['start'] = ktime
@@ -1517,7 +1578,7 @@ class FTraceCallGraph:
1517 prelinedep += 1 1578 prelinedep += 1
1518 last = 0 1579 last = 0
1519 lasttime = line.time 1580 lasttime = line.time
1520 virtualfname = 'execution_misalignment' 1581 virtualfname = 'missing_function_name'
1521 if len(self.list) > 0: 1582 if len(self.list) > 0:
1522 last = self.list[-1] 1583 last = self.list[-1]
1523 lasttime = last.time 1584 lasttime = last.time
@@ -1773,24 +1834,30 @@ class Timeline:
1773 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n' 1834 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n'
1774 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n' 1835 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n'
1775 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n' 1836 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n'
1837 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}">&nbsp;{2}</div>\n'
1776 def __init__(self, rowheight, scaleheight): 1838 def __init__(self, rowheight, scaleheight):
1777 self.rowH = rowheight 1839 self.rowH = rowheight
1778 self.scaleH = scaleheight 1840 self.scaleH = scaleheight
1779 self.html = '' 1841 self.html = ''
1780 def createHeader(self, sv, suppress=''): 1842 def createHeader(self, sv):
1781 if(not sv.stamp['time']): 1843 if(not sv.stamp['time']):
1782 return 1844 return
1783 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 1845 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \
1784 % (sv.title, sv.version) 1846 % (sv.title, sv.version)
1785 if sv.logmsg and 'log' not in suppress: 1847 if sv.logmsg and sv.testlog:
1786 self.html += '<button id="showtest" class="logbtn">log</button>' 1848 self.html += '<button id="showtest" class="logbtn btnfmt">log</button>'
1787 if sv.addlogs and 'dmesg' not in suppress: 1849 if sv.dmesglog:
1788 self.html += '<button id="showdmesg" class="logbtn">dmesg</button>' 1850 self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>'
1789 if sv.addlogs and sv.ftracefile and 'ftrace' not in suppress: 1851 if sv.ftracelog:
1790 self.html += '<button id="showftrace" class="logbtn">ftrace</button>' 1852 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>'
1791 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 1853 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
1792 self.html += headline_stamp.format(sv.stamp['host'], sv.stamp['kernel'], 1854 self.html += headline_stamp.format(sv.stamp['host'], sv.stamp['kernel'],
1793 sv.stamp['mode'], sv.stamp['time']) 1855 sv.stamp['mode'], sv.stamp['time'])
1856 if 'man' in sv.stamp and 'plat' in sv.stamp and 'cpu' in sv.stamp:
1857 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n'
1858 self.html += headline_sysinfo.format(sv.stamp['man'],
1859 sv.stamp['plat'], sv.stamp['cpu'])
1860
1794 # Function: getDeviceRows 1861 # Function: getDeviceRows
1795 # Description: 1862 # Description:
1796 # determine how may rows the device funcs will take 1863 # determine how may rows the device funcs will take
@@ -1839,7 +1906,7 @@ class Timeline:
1839 # devlist: the list of devices/actions in a group of contiguous phases 1906 # devlist: the list of devices/actions in a group of contiguous phases
1840 # Output: 1907 # Output:
1841 # The total number of rows needed to display this phase of the timeline 1908 # The total number of rows needed to display this phase of the timeline
1842 def getPhaseRows(self, devlist, row=0): 1909 def getPhaseRows(self, devlist, row=0, sortby='length'):
1843 # clear all rows and set them to undefined 1910 # clear all rows and set them to undefined
1844 remaining = len(devlist) 1911 remaining = len(devlist)
1845 rowdata = dict() 1912 rowdata = dict()
@@ -1852,8 +1919,12 @@ class Timeline:
1852 if tp not in myphases: 1919 if tp not in myphases:
1853 myphases.append(tp) 1920 myphases.append(tp)
1854 dev['row'] = -1 1921 dev['row'] = -1
1855 # sort by length 1st, then name 2nd 1922 if sortby == 'start':
1856 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name']) 1923 # sort by start 1st, then length 2nd
1924 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start']))
1925 else:
1926 # sort by length 1st, then name 2nd
1927 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name'])
1857 if 'src' in dev: 1928 if 'src' in dev:
1858 dev['devrows'] = self.getDeviceRows(dev['src']) 1929 dev['devrows'] = self.getDeviceRows(dev['src'])
1859 # sort the devlist by length so that large items graph on top 1930 # sort the devlist by length so that large items graph on top
@@ -1995,8 +2066,13 @@ class Timeline:
1995# A list of values describing the properties of these test runs 2066# A list of values describing the properties of these test runs
1996class TestProps: 2067class TestProps:
1997 stamp = '' 2068 stamp = ''
2069 sysinfo = ''
1998 S0i3 = False 2070 S0i3 = False
1999 fwdata = [] 2071 fwdata = []
2072 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})'+\
2074 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
2075 sysinfofmt = '^# sysinfo .*'
2000 ftrace_line_fmt_fg = \ 2076 ftrace_line_fmt_fg = \
2001 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2077 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
2002 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2078 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
@@ -2019,6 +2095,36 @@ class TestProps:
2019 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 2095 self.ftrace_line_fmt = self.ftrace_line_fmt_nop
2020 else: 2096 else:
2021 doError('Invalid tracer format: [%s]' % tracer) 2097 doError('Invalid tracer format: [%s]' % tracer)
2098 def parseStamp(self, data, sv):
2099 m = re.match(self.stampfmt, self.stamp)
2100 data.stamp = {'time': '', 'host': '', 'mode': ''}
2101 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
2102 int(m.group('d')), int(m.group('H')), int(m.group('M')),
2103 int(m.group('S')))
2104 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
2105 data.stamp['host'] = m.group('host')
2106 data.stamp['mode'] = m.group('mode')
2107 data.stamp['kernel'] = m.group('kernel')
2108 if re.match(self.sysinfofmt, self.sysinfo):
2109 for f in self.sysinfo.split('|'):
2110 if '#' in f:
2111 continue
2112 tmp = f.strip().split(':', 1)
2113 key = tmp[0]
2114 val = tmp[1]
2115 data.stamp[key] = val
2116 sv.hostname = data.stamp['host']
2117 sv.suspendmode = data.stamp['mode']
2118 if sv.suspendmode == 'command' and sv.ftracefile != '':
2119 modes = ['on', 'freeze', 'standby', 'mem']
2120 out = Popen(['grep', 'suspend_enter', sv.ftracefile],
2121 stderr=PIPE, stdout=PIPE).stdout.read()
2122 m = re.match('.* suspend_enter\[(?P<mode>.*)\]', out)
2123 if m and m.group('mode') in ['1', '2', '3']:
2124 sv.suspendmode = modes[int(m.group('mode'))]
2125 data.stamp['mode'] = sv.suspendmode
2126 if not sv.stamp:
2127 sv.stamp = data.stamp
2022 2128
2023# Class: TestRun 2129# Class: TestRun
2024# Description: 2130# Description:
@@ -2090,35 +2196,6 @@ def vprint(msg):
2090 if(sysvals.verbose): 2196 if(sysvals.verbose):
2091 print(msg) 2197 print(msg)
2092 2198
2093# Function: parseStamp
2094# Description:
2095# Pull in the stamp comment line from the data file(s),
2096# create the stamp, and add it to the global sysvals object
2097# Arguments:
2098# m: the valid re.match output for the stamp line
2099def parseStamp(line, data):
2100 m = re.match(sysvals.stampfmt, line)
2101 data.stamp = {'time': '', 'host': '', 'mode': ''}
2102 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
2103 int(m.group('d')), int(m.group('H')), int(m.group('M')),
2104 int(m.group('S')))
2105 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
2106 data.stamp['host'] = m.group('host')
2107 data.stamp['mode'] = m.group('mode')
2108 data.stamp['kernel'] = m.group('kernel')
2109 sysvals.hostname = data.stamp['host']
2110 sysvals.suspendmode = data.stamp['mode']
2111 if sysvals.suspendmode == 'command' and sysvals.ftracefile != '':
2112 modes = ['on', 'freeze', 'standby', 'mem']
2113 out = Popen(['grep', 'suspend_enter', sysvals.ftracefile],
2114 stderr=PIPE, stdout=PIPE).stdout.read()
2115 m = re.match('.* suspend_enter\[(?P<mode>.*)\]', out)
2116 if m and m.group('mode') in ['1', '2', '3']:
2117 sysvals.suspendmode = modes[int(m.group('mode'))]
2118 data.stamp['mode'] = sysvals.suspendmode
2119 if not sysvals.stamp:
2120 sysvals.stamp = data.stamp
2121
2122# Function: doesTraceLogHaveTraceEvents 2199# Function: doesTraceLogHaveTraceEvents
2123# Description: 2200# Description:
2124# Quickly determine if the ftrace log has some or all of the trace events 2201# Quickly determine if the ftrace log has some or all of the trace events
@@ -2136,11 +2213,6 @@ def doesTraceLogHaveTraceEvents():
2136 sysvals.usekprobes = True 2213 sysvals.usekprobes = True
2137 out = Popen(['head', '-1', sysvals.ftracefile], 2214 out = Popen(['head', '-1', sysvals.ftracefile],
2138 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 2215 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '')
2139 m = re.match(sysvals.stampfmt, out)
2140 if m and m.group('mode') == 'command':
2141 sysvals.usetraceeventsonly = True
2142 sysvals.usetraceevents = True
2143 return
2144 # figure out what level of trace events are supported 2216 # figure out what level of trace events are supported
2145 sysvals.usetraceeventsonly = True 2217 sysvals.usetraceeventsonly = True
2146 sysvals.usetraceevents = False 2218 sysvals.usetraceevents = False
@@ -2182,11 +2254,13 @@ def appendIncompleteTraceLog(testruns):
2182 for line in tf: 2254 for line in tf:
2183 # remove any latent carriage returns 2255 # remove any latent carriage returns
2184 line = line.replace('\r\n', '') 2256 line = line.replace('\r\n', '')
2185 # grab the time stamp 2257 # grab the stamp and sysinfo
2186 m = re.match(sysvals.stampfmt, line) 2258 if re.match(tp.stampfmt, line):
2187 if(m):
2188 tp.stamp = line 2259 tp.stamp = line
2189 continue 2260 continue
2261 elif re.match(tp.sysinfofmt, line):
2262 tp.sysinfo = line
2263 continue
2190 # determine the trace data type (required for further parsing) 2264 # determine the trace data type (required for further parsing)
2191 m = re.match(sysvals.tracertypefmt, line) 2265 m = re.match(sysvals.tracertypefmt, line)
2192 if(m): 2266 if(m):
@@ -2219,7 +2293,7 @@ def appendIncompleteTraceLog(testruns):
2219 # look for the suspend start marker 2293 # look for the suspend start marker
2220 if(t.startMarker()): 2294 if(t.startMarker()):
2221 data = testrun[testidx].data 2295 data = testrun[testidx].data
2222 parseStamp(tp.stamp, data) 2296 tp.parseStamp(data, sysvals)
2223 data.setStart(t.time) 2297 data.setStart(t.time)
2224 continue 2298 continue
2225 if(not data): 2299 if(not data):
@@ -2389,11 +2463,13 @@ def parseTraceLog():
2389 for line in tf: 2463 for line in tf:
2390 # remove any latent carriage returns 2464 # remove any latent carriage returns
2391 line = line.replace('\r\n', '') 2465 line = line.replace('\r\n', '')
2392 # stamp line: each stamp means a new test run 2466 # stamp and sysinfo lines
2393 m = re.match(sysvals.stampfmt, line) 2467 if re.match(tp.stampfmt, line):
2394 if(m):
2395 tp.stamp = line 2468 tp.stamp = line
2396 continue 2469 continue
2470 elif re.match(tp.sysinfofmt, line):
2471 tp.sysinfo = line
2472 continue
2397 # firmware line: pull out any firmware data 2473 # firmware line: pull out any firmware data
2398 m = re.match(sysvals.firmwarefmt, line) 2474 m = re.match(sysvals.firmwarefmt, line)
2399 if(m): 2475 if(m):
@@ -2439,7 +2515,7 @@ def parseTraceLog():
2439 testdata.append(data) 2515 testdata.append(data)
2440 testrun = TestRun(data) 2516 testrun = TestRun(data)
2441 testruns.append(testrun) 2517 testruns.append(testrun)
2442 parseStamp(tp.stamp, data) 2518 tp.parseStamp(data, sysvals)
2443 data.setStart(t.time) 2519 data.setStart(t.time)
2444 data.tKernSus = t.time 2520 data.tKernSus = t.time
2445 continue 2521 continue
@@ -2820,10 +2896,13 @@ def loadKernelLog(justtext=False):
2820 idx = line.find('[') 2896 idx = line.find('[')
2821 if idx > 1: 2897 if idx > 1:
2822 line = line[idx:] 2898 line = line[idx:]
2823 m = re.match(sysvals.stampfmt, line) 2899 # grab the stamp and sysinfo
2824 if(m): 2900 if re.match(tp.stampfmt, line):
2825 tp.stamp = line 2901 tp.stamp = line
2826 continue 2902 continue
2903 elif re.match(tp.sysinfofmt, line):
2904 tp.sysinfo = line
2905 continue
2827 m = re.match(sysvals.firmwarefmt, line) 2906 m = re.match(sysvals.firmwarefmt, line)
2828 if(m): 2907 if(m):
2829 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) 2908 tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
@@ -2839,7 +2918,7 @@ def loadKernelLog(justtext=False):
2839 if(data): 2918 if(data):
2840 testruns.append(data) 2919 testruns.append(data)
2841 data = Data(len(testruns)) 2920 data = Data(len(testruns))
2842 parseStamp(tp.stamp, data) 2921 tp.parseStamp(data, sysvals)
2843 if len(tp.fwdata) > data.testnumber: 2922 if len(tp.fwdata) > data.testnumber:
2844 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber] 2923 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber]
2845 if(data.fwSuspend > 0 or data.fwResume > 0): 2924 if(data.fwSuspend > 0 or data.fwResume > 0):
@@ -3170,6 +3249,8 @@ def addCallgraphs(sv, hf, data):
3170 continue 3249 continue
3171 list = data.dmesg[p]['list'] 3250 list = data.dmesg[p]['list']
3172 for devname in data.sortedDevices(p): 3251 for devname in data.sortedDevices(p):
3252 if len(sv.devicefilter) > 0 and devname not in sv.devicefilter:
3253 continue
3173 dev = list[devname] 3254 dev = list[devname]
3174 color = 'white' 3255 color = 'white'
3175 if 'color' in data.dmesg[p]: 3256 if 'color' in data.dmesg[p]:
@@ -3309,7 +3390,6 @@ def createHTML(testruns):
3309 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">ERROR&rarr;</div>\n' 3390 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">ERROR&rarr;</div>\n'
3310 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' 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'
3311 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n' 3392 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n'
3312 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}">&nbsp;{2}</div>\n'
3313 html_timetotal = '<table class="time1">\n<tr>'\ 3393 html_timetotal = '<table class="time1">\n<tr>'\
3314 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\ 3394 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\
3315 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\ 3395 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\
@@ -3346,10 +3426,7 @@ def createHTML(testruns):
3346 # Generate the header for this timeline 3426 # Generate the header for this timeline
3347 for data in testruns: 3427 for data in testruns:
3348 tTotal = data.end - data.start 3428 tTotal = data.end - data.start
3349 sktime = (data.dmesg['suspend_machine']['end'] - \ 3429 sktime, rktime = data.getTimeValues()
3350 data.tKernSus) * 1000
3351 rktime = (data.dmesg['resume_complete']['end'] - \
3352 data.dmesg['resume_machine']['start']) * 1000
3353 if(tTotal == 0): 3430 if(tTotal == 0):
3354 print('ERROR: No timeline data') 3431 print('ERROR: No timeline data')
3355 sys.exit() 3432 sys.exit()
@@ -3581,7 +3658,7 @@ def createHTML(testruns):
3581 id += tmp[1][0] 3658 id += tmp[1][0]
3582 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin) 3659 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
3583 name = string.replace(phase, '_', ' &nbsp;') 3660 name = string.replace(phase, '_', ' &nbsp;')
3584 devtl.html += html_legend.format(order, \ 3661 devtl.html += devtl.html_legend.format(order, \
3585 data.dmesg[phase]['color'], name, id) 3662 data.dmesg[phase]['color'], name, id)
3586 devtl.html += '</div>\n' 3663 devtl.html += '</div>\n'
3587 3664
@@ -3628,10 +3705,10 @@ def createHTML(testruns):
3628 addCallgraphs(sysvals, hf, data) 3705 addCallgraphs(sysvals, hf, data)
3629 3706
3630 # add the test log as a hidden div 3707 # add the test log as a hidden div
3631 if sysvals.logmsg: 3708 if sysvals.testlog and sysvals.logmsg:
3632 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n') 3709 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n')
3633 # add the dmesg log as a hidden div 3710 # add the dmesg log as a hidden div
3634 if sysvals.addlogs and sysvals.dmesgfile: 3711 if sysvals.dmesglog and sysvals.dmesgfile:
3635 hf.write('<div id="dmesglog" style="display:none;">\n') 3712 hf.write('<div id="dmesglog" style="display:none;">\n')
3636 lf = open(sysvals.dmesgfile, 'r') 3713 lf = open(sysvals.dmesgfile, 'r')
3637 for line in lf: 3714 for line in lf:
@@ -3640,7 +3717,7 @@ def createHTML(testruns):
3640 lf.close() 3717 lf.close()
3641 hf.write('</div>\n') 3718 hf.write('</div>\n')
3642 # add the ftrace log as a hidden div 3719 # add the ftrace log as a hidden div
3643 if sysvals.addlogs and sysvals.ftracefile: 3720 if sysvals.ftracelog and sysvals.ftracefile:
3644 hf.write('<div id="ftracelog" style="display:none;">\n') 3721 hf.write('<div id="ftracelog" style="display:none;">\n')
3645 lf = open(sysvals.ftracefile, 'r') 3722 lf = open(sysvals.ftracefile, 'r')
3646 for line in lf: 3723 for line in lf:
@@ -3701,6 +3778,7 @@ def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
3701 <style type=\'text/css\'>\n\ 3778 <style type=\'text/css\'>\n\
3702 body {overflow-y:scroll;}\n\ 3779 body {overflow-y:scroll;}\n\
3703 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\ 3780 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\
3781 .stamp.sysinfo {font:10px Arial;}\n\
3704 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\ 3782 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\
3705 .callgraph article * {padding-left:28px;}\n\ 3783 .callgraph article * {padding-left:28px;}\n\
3706 h1 {color:black;font:bold 30px Times;}\n\ 3784 h1 {color:black;font:bold 30px Times;}\n\
@@ -3746,7 +3824,7 @@ def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
3746 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\ 3824 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\
3747 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\ 3825 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\
3748 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ 3826 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
3749 .logbtn {position:relative;float:right;height:25px;width:50px;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\ 3827 .btnfmt {position:relative;float:right;height:25px;width:auto;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\
3750 .devlist {position:'+devlistpos+';width:190px;}\n\ 3828 .devlist {position:'+devlistpos+';width:190px;}\n\
3751 a:link {color:white;text-decoration:none;}\n\ 3829 a:link {color:white;text-decoration:none;}\n\
3752 a:visited {color:white;}\n\ 3830 a:visited {color:white;}\n\
@@ -4084,8 +4162,6 @@ def addScriptCode(hf, testruns):
4084 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\ 4162 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\
4085 ' win.document.close();\n'\ 4163 ' win.document.close();\n'\
4086 ' }\n'\ 4164 ' }\n'\
4087 ' function onClickPhase(e) {\n'\
4088 ' }\n'\
4089 ' function onMouseDown(e) {\n'\ 4165 ' function onMouseDown(e) {\n'\
4090 ' dragval[0] = e.clientX;\n'\ 4166 ' dragval[0] = e.clientX;\n'\
4091 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\ 4167 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\
@@ -4120,9 +4196,6 @@ def addScriptCode(hf, testruns):
4120 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 4196 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\
4121 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 4197 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\
4122 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 4198 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
4123 ' var list = document.getElementsByClassName("square");\n'\
4124 ' for (var i = 0; i < list.length; i++)\n'\
4125 ' list[i].onclick = onClickPhase;\n'\
4126 ' var list = document.getElementsByClassName("err");\n'\ 4199 ' var list = document.getElementsByClassName("err");\n'\
4127 ' for (var i = 0; i < list.length; i++)\n'\ 4200 ' for (var i = 0; i < list.length; i++)\n'\
4128 ' list[i].onclick = errWindow;\n'\ 4201 ' list[i].onclick = errWindow;\n'\
@@ -4193,8 +4266,14 @@ def executeSuspend():
4193 if sysvals.testcommand != '': 4266 if sysvals.testcommand != '':
4194 call(sysvals.testcommand+' 2>&1', shell=True); 4267 call(sysvals.testcommand+' 2>&1', shell=True);
4195 else: 4268 else:
4269 mode = sysvals.suspendmode
4270 if sysvals.memmode and os.path.exists(sysvals.mempowerfile):
4271 mode = 'mem'
4272 pf = open(sysvals.mempowerfile, 'w')
4273 pf.write(sysvals.memmode)
4274 pf.close()
4196 pf = open(sysvals.powerfile, 'w') 4275 pf = open(sysvals.powerfile, 'w')
4197 pf.write(sysvals.suspendmode) 4276 pf.write(mode)
4198 # execution will pause here 4277 # execution will pause here
4199 try: 4278 try:
4200 pf.close() 4279 pf.close()
@@ -4219,24 +4298,15 @@ def executeSuspend():
4219 pm.stop() 4298 pm.stop()
4220 sysvals.fsetVal('0', 'tracing_on') 4299 sysvals.fsetVal('0', 'tracing_on')
4221 print('CAPTURING TRACE') 4300 print('CAPTURING TRACE')
4222 writeDatafileHeader(sysvals.ftracefile, fwdata) 4301 sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata)
4223 call('cat '+tp+'trace >> '+sysvals.ftracefile, shell=True) 4302 call('cat '+tp+'trace >> '+sysvals.ftracefile, shell=True)
4224 sysvals.fsetVal('', 'trace') 4303 sysvals.fsetVal('', 'trace')
4225 devProps() 4304 devProps()
4226 # grab a copy of the dmesg output 4305 # grab a copy of the dmesg output
4227 print('CAPTURING DMESG') 4306 print('CAPTURING DMESG')
4228 writeDatafileHeader(sysvals.dmesgfile, fwdata) 4307 sysvals.writeDatafileHeader(sysvals.dmesgfile, fwdata)
4229 sysvals.getdmesg() 4308 sysvals.getdmesg()
4230 4309
4231def writeDatafileHeader(filename, fwdata):
4232 fp = open(filename, 'a')
4233 fp.write(sysvals.teststamp+'\n')
4234 if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'):
4235 for fw in fwdata:
4236 if(fw):
4237 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
4238 fp.close()
4239
4240# Function: setUSBDevicesAuto 4310# Function: setUSBDevicesAuto
4241# Description: 4311# Description:
4242# Set the autosuspend control parameter of all USB devices to auto 4312# Set the autosuspend control parameter of all USB devices to auto
@@ -4244,7 +4314,7 @@ def writeDatafileHeader(filename, fwdata):
4244# to always-on since the kernel cant determine if the device can 4314# to always-on since the kernel cant determine if the device can
4245# properly autosuspend 4315# properly autosuspend
4246def setUSBDevicesAuto(): 4316def setUSBDevicesAuto():
4247 rootCheck(True) 4317 sysvals.rootCheck(True)
4248 for dirname, dirnames, filenames in os.walk('/sys/devices'): 4318 for dirname, dirnames, filenames in os.walk('/sys/devices'):
4249 if(re.match('.*/usb[0-9]*.*', dirname) and 4319 if(re.match('.*/usb[0-9]*.*', dirname) and
4250 'idVendor' in filenames and 'idProduct' in filenames): 4320 'idVendor' in filenames and 'idProduct' in filenames):
@@ -4467,13 +4537,146 @@ def devProps(data=0):
4467# Output: 4537# Output:
4468# A string list of the available modes 4538# A string list of the available modes
4469def getModes(): 4539def getModes():
4470 modes = '' 4540 modes = []
4471 if(os.path.exists(sysvals.powerfile)): 4541 if(os.path.exists(sysvals.powerfile)):
4472 fp = open(sysvals.powerfile, 'r') 4542 fp = open(sysvals.powerfile, 'r')
4473 modes = string.split(fp.read()) 4543 modes = string.split(fp.read())
4474 fp.close() 4544 fp.close()
4545 if(os.path.exists(sysvals.mempowerfile)):
4546 deep = False
4547 fp = open(sysvals.mempowerfile, 'r')
4548 for m in string.split(fp.read()):
4549 memmode = m.strip('[]')
4550 if memmode == 'deep':
4551 deep = True
4552 else:
4553 modes.append('mem-%s' % memmode)
4554 fp.close()
4555 if 'mem' in modes and not deep:
4556 modes.remove('mem')
4475 return modes 4557 return modes
4476 4558
4559# Function: dmidecode
4560# Description:
4561# Read the bios tables and pull out system info
4562# Arguments:
4563# mempath: /dev/mem or custom mem path
4564# fatal: True to exit on error, False to return empty dict
4565# Output:
4566# A dict object with all available key/values
4567def dmidecode(mempath, fatal=False):
4568 out = dict()
4569
4570 # the list of values to retrieve, with hardcoded (type, idx)
4571 info = {
4572 'bios-vendor': (0, 4),
4573 'bios-version': (0, 5),
4574 'bios-release-date': (0, 8),
4575 'system-manufacturer': (1, 4),
4576 'system-product-name': (1, 5),
4577 'system-version': (1, 6),
4578 'system-serial-number': (1, 7),
4579 'baseboard-manufacturer': (2, 4),
4580 'baseboard-product-name': (2, 5),
4581 'baseboard-version': (2, 6),
4582 'baseboard-serial-number': (2, 7),
4583 'chassis-manufacturer': (3, 4),
4584 'chassis-type': (3, 5),
4585 'chassis-version': (3, 6),
4586 'chassis-serial-number': (3, 7),
4587 'processor-manufacturer': (4, 7),
4588 'processor-version': (4, 16),
4589 }
4590 if(not os.path.exists(mempath)):
4591 if(fatal):
4592 doError('file does not exist: %s' % mempath)
4593 return out
4594 if(not os.access(mempath, os.R_OK)):
4595 if(fatal):
4596 doError('file is not readable: %s' % mempath)
4597 return out
4598
4599 # by default use legacy scan, but try to use EFI first
4600 memaddr = 0xf0000
4601 memsize = 0x10000
4602 for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']:
4603 if not os.path.exists(ep) or not os.access(ep, os.R_OK):
4604 continue
4605 fp = open(ep, 'r')
4606 buf = fp.read()
4607 fp.close()
4608 i = buf.find('SMBIOS=')
4609 if i >= 0:
4610 try:
4611 memaddr = int(buf[i+7:], 16)
4612 memsize = 0x20
4613 except:
4614 continue
4615
4616 # read in the memory for scanning
4617 fp = open(mempath, 'rb')
4618 try:
4619 fp.seek(memaddr)
4620 buf = fp.read(memsize)
4621 except:
4622 if(fatal):
4623 doError('DMI table is unreachable, sorry')
4624 else:
4625 return out
4626 fp.close()
4627
4628 # search for either an SM table or DMI table
4629 i = base = length = num = 0
4630 while(i < memsize):
4631 if buf[i:i+4] == '_SM_' and i < memsize - 16:
4632 length = struct.unpack('H', buf[i+22:i+24])[0]
4633 base, num = struct.unpack('IH', buf[i+24:i+30])
4634 break
4635 elif buf[i:i+5] == '_DMI_':
4636 length = struct.unpack('H', buf[i+6:i+8])[0]
4637 base, num = struct.unpack('IH', buf[i+8:i+14])
4638 break
4639 i += 16
4640 if base == 0 and length == 0 and num == 0:
4641 if(fatal):
4642 doError('Neither SMBIOS nor DMI were found')
4643 else:
4644 return out
4645
4646 # read in the SM or DMI table
4647 fp = open(mempath, 'rb')
4648 try:
4649 fp.seek(base)
4650 buf = fp.read(length)
4651 except:
4652 if(fatal):
4653 doError('DMI table is unreachable, sorry')
4654 else:
4655 return out
4656 fp.close()
4657
4658 # scan the table for the values we want
4659 count = i = 0
4660 while(count < num and i <= len(buf) - 4):
4661 type, size, handle = struct.unpack('BBH', buf[i:i+4])
4662 n = i + size
4663 while n < len(buf) - 1:
4664 if 0 == struct.unpack('H', buf[n:n+2])[0]:
4665 break
4666 n += 1
4667 data = buf[i+size:n+2].split('\0')
4668 for name in info:
4669 itype, idxadr = info[name]
4670 if itype == type:
4671 idx = struct.unpack('B', buf[i+idxadr])[0]
4672 if idx > 0 and idx < len(data) - 1:
4673 s = data[idx-1].strip()
4674 if s and s.lower() != 'to be filled by o.e.m.':
4675 out[name] = data[idx-1]
4676 i = n + 2
4677 count += 1
4678 return out
4679
4477# Function: getFPDT 4680# Function: getFPDT
4478# Description: 4681# Description:
4479# Read the acpi bios tables and pull out FPDT, the firmware data 4682# Read the acpi bios tables and pull out FPDT, the firmware data
@@ -4487,7 +4690,7 @@ def getFPDT(output):
4487 prectype[0] = 'Basic S3 Resume Performance Record' 4690 prectype[0] = 'Basic S3 Resume Performance Record'
4488 prectype[1] = 'Basic S3 Suspend Performance Record' 4691 prectype[1] = 'Basic S3 Suspend Performance Record'
4489 4692
4490 rootCheck(True) 4693 sysvals.rootCheck(True)
4491 if(not os.path.exists(sysvals.fpdtpath)): 4694 if(not os.path.exists(sysvals.fpdtpath)):
4492 if(output): 4695 if(output):
4493 doError('file does not exist: %s' % sysvals.fpdtpath) 4696 doError('file does not exist: %s' % sysvals.fpdtpath)
@@ -4617,7 +4820,7 @@ def statusCheck(probecheck=False):
4617 4820
4618 # check we have root access 4821 # check we have root access
4619 res = sysvals.colorText('NO (No features of this tool will work!)') 4822 res = sysvals.colorText('NO (No features of this tool will work!)')
4620 if(rootCheck(False)): 4823 if(sysvals.rootCheck(False)):
4621 res = 'YES' 4824 res = 'YES'
4622 print(' have root access: %s' % res) 4825 print(' have root access: %s' % res)
4623 if(res != 'YES'): 4826 if(res != 'YES'):
@@ -4716,16 +4919,6 @@ def doError(msg, help=False):
4716 print('ERROR: %s\n') % msg 4919 print('ERROR: %s\n') % msg
4717 sys.exit() 4920 sys.exit()
4718 4921
4719# Function: rootCheck
4720# Description:
4721# quick check to see if we have root access
4722def rootCheck(fatal):
4723 if(os.access(sysvals.powerfile, os.W_OK)):
4724 return True
4725 if fatal:
4726 doError('This command requires sysfs mount and root access')
4727 return False
4728
4729# Function: getArgInt 4922# Function: getArgInt
4730# Description: 4923# Description:
4731# pull out an integer argument from the command line with checks 4924# pull out an integer argument from the command line with checks
@@ -4779,6 +4972,7 @@ def processData():
4779 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 4972 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
4780 appendIncompleteTraceLog(testruns) 4973 appendIncompleteTraceLog(testruns)
4781 createHTML(testruns) 4974 createHTML(testruns)
4975 return testruns
4782 4976
4783# Function: rerunTest 4977# Function: rerunTest
4784# Description: 4978# Description:
@@ -4790,17 +4984,20 @@ def rerunTest():
4790 doError('recreating this html output requires a dmesg file') 4984 doError('recreating this html output requires a dmesg file')
4791 sysvals.setOutputFile() 4985 sysvals.setOutputFile()
4792 vprint('Output file: %s' % sysvals.htmlfile) 4986 vprint('Output file: %s' % sysvals.htmlfile)
4793 if(os.path.exists(sysvals.htmlfile) and not os.access(sysvals.htmlfile, os.W_OK)): 4987 if os.path.exists(sysvals.htmlfile):
4794 doError('missing permission to write to %s' % sysvals.htmlfile) 4988 if not os.path.isfile(sysvals.htmlfile):
4795 processData() 4989 doError('a directory already exists with this name: %s' % sysvals.htmlfile)
4990 elif not os.access(sysvals.htmlfile, os.W_OK):
4991 doError('missing permission to write to %s' % sysvals.htmlfile)
4992 return processData()
4796 4993
4797# Function: runTest 4994# Function: runTest
4798# Description: 4995# Description:
4799# execute a suspend/resume, gather the logs, and generate the output 4996# execute a suspend/resume, gather the logs, and generate the output
4800def runTest(subdir, testpath=''): 4997def runTest():
4801 # prepare for the test 4998 # prepare for the test
4802 sysvals.initFtrace() 4999 sysvals.initFtrace()
4803 sysvals.initTestOutput(subdir, testpath) 5000 sysvals.initTestOutput('suspend')
4804 vprint('Output files:\n\t%s\n\t%s\n\t%s' % \ 5001 vprint('Output files:\n\t%s\n\t%s\n\t%s' % \
4805 (sysvals.dmesgfile, sysvals.ftracefile, sysvals.htmlfile)) 5002 (sysvals.dmesgfile, sysvals.ftracefile, sysvals.htmlfile))
4806 5003
@@ -4897,7 +5094,7 @@ def configFromFile(file):
4897 if(opt.lower() == 'verbose'): 5094 if(opt.lower() == 'verbose'):
4898 sysvals.verbose = checkArgBool(value) 5095 sysvals.verbose = checkArgBool(value)
4899 elif(opt.lower() == 'addlogs'): 5096 elif(opt.lower() == 'addlogs'):
4900 sysvals.addlogs = checkArgBool(value) 5097 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(value)
4901 elif(opt.lower() == 'dev'): 5098 elif(opt.lower() == 'dev'):
4902 sysvals.usedevsrc = checkArgBool(value) 5099 sysvals.usedevsrc = checkArgBool(value)
4903 elif(opt.lower() == 'proc'): 5100 elif(opt.lower() == 'proc'):
@@ -4947,7 +5144,7 @@ def configFromFile(file):
4947 elif(opt.lower() == 'mincg'): 5144 elif(opt.lower() == 'mincg'):
4948 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False) 5145 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False)
4949 elif(opt.lower() == 'output-dir'): 5146 elif(opt.lower() == 'output-dir'):
4950 sysvals.setOutputFolder(value) 5147 sysvals.testdir = sysvals.setOutputFolder(value)
4951 5148
4952 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 5149 if sysvals.suspendmode == 'command' and not sysvals.testcommand:
4953 doError('No command supplied for mode "command"') 5150 doError('No command supplied for mode "command"')
@@ -5030,8 +5227,6 @@ def configFromFile(file):
5030# Description: 5227# Description:
5031# print out the help text 5228# print out the help text
5032def printHelp(): 5229def printHelp():
5033 modes = getModes()
5034
5035 print('') 5230 print('')
5036 print('%s v%s' % (sysvals.title, sysvals.version)) 5231 print('%s v%s' % (sysvals.title, sysvals.version))
5037 print('Usage: sudo sleepgraph <options> <commands>') 5232 print('Usage: sudo sleepgraph <options> <commands>')
@@ -5048,7 +5243,7 @@ def printHelp():
5048 print(' If no specific command is given, the default behavior is to initiate') 5243 print(' If no specific command is given, the default behavior is to initiate')
5049 print(' a suspend/resume and capture the dmesg/ftrace output as an html timeline.') 5244 print(' a suspend/resume and capture the dmesg/ftrace output as an html timeline.')
5050 print('') 5245 print('')
5051 print(' Generates output files in subdirectory: suspend-mmddyy-HHMMSS') 5246 print(' Generates output files in subdirectory: suspend-yymmdd-HHMMSS')
5052 print(' HTML output: <hostname>_<mode>.html') 5247 print(' HTML output: <hostname>_<mode>.html')
5053 print(' raw dmesg output: <hostname>_<mode>_dmesg.txt') 5248 print(' raw dmesg output: <hostname>_<mode>_dmesg.txt')
5054 print(' raw ftrace output: <hostname>_<mode>_ftrace.txt') 5249 print(' raw ftrace output: <hostname>_<mode>_ftrace.txt')
@@ -5058,8 +5253,9 @@ def printHelp():
5058 print(' -v Print the current tool version') 5253 print(' -v Print the current tool version')
5059 print(' -config fn Pull arguments and config options from file fn') 5254 print(' -config fn Pull arguments and config options from file fn')
5060 print(' -verbose Print extra information during execution and analysis') 5255 print(' -verbose Print extra information during execution and analysis')
5061 print(' -m mode Mode to initiate for suspend %s (default: %s)') % (modes, sysvals.suspendmode) 5256 print(' -m mode Mode to initiate for suspend (default: %s)') % (sysvals.suspendmode)
5062 print(' -o subdir Override the output subdirectory') 5257 print(' -o name Overrides the output subdirectory name when running a new test')
5258 print(' default: suspend-{date}-{time}')
5063 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)') 5259 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)')
5064 print(' -addlogs Add the dmesg and ftrace logs to the html output') 5260 print(' -addlogs Add the dmesg and ftrace logs to the html output')
5065 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)') 5261 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)')
@@ -5084,17 +5280,20 @@ def printHelp():
5084 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)') 5280 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)')
5085 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)') 5281 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)')
5086 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)') 5282 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)')
5087 print(' [commands]') 5283 print('')
5088 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)') 5284 print('Other commands:')
5089 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)')
5090 print(' -summary directory Create a summary of all test in this dir')
5091 print(' -modes List available suspend modes') 5285 print(' -modes List available suspend modes')
5092 print(' -status Test to see if the system is enabled to run this tool') 5286 print(' -status Test to see if the system is enabled to run this tool')
5093 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 5287 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
5288 print(' -sysinfo Print out system info extracted from BIOS')
5094 print(' -usbtopo Print out the current USB topology with power info') 5289 print(' -usbtopo Print out the current USB topology with power info')
5095 print(' -usbauto Enable autosuspend for all connected USB devices') 5290 print(' -usbauto Enable autosuspend for all connected USB devices')
5096 print(' -flist Print the list of functions currently being captured in ftrace') 5291 print(' -flist Print the list of functions currently being captured in ftrace')
5097 print(' -flistall Print all functions capable of being captured in ftrace') 5292 print(' -flistall Print all functions capable of being captured in ftrace')
5293 print(' -summary directory Create a summary of all test in this dir')
5294 print(' [redo]')
5295 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)')
5296 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)')
5098 print('') 5297 print('')
5099 return True 5298 return True
5100 5299
@@ -5102,9 +5301,9 @@ def printHelp():
5102# exec start (skipped if script is loaded as library) 5301# exec start (skipped if script is loaded as library)
5103if __name__ == '__main__': 5302if __name__ == '__main__':
5104 cmd = '' 5303 cmd = ''
5105 cmdarg = '' 5304 outdir = ''
5106 multitest = {'run': False, 'count': 0, 'delay': 0} 5305 multitest = {'run': False, 'count': 0, 'delay': 0}
5107 simplecmds = ['-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status'] 5306 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status']
5108 # loop through the command line arguments 5307 # loop through the command line arguments
5109 args = iter(sys.argv[1:]) 5308 args = iter(sys.argv[1:])
5110 for arg in args: 5309 for arg in args:
@@ -5135,7 +5334,7 @@ if __name__ == '__main__':
5135 elif(arg == '-f'): 5334 elif(arg == '-f'):
5136 sysvals.usecallgraph = True 5335 sysvals.usecallgraph = True
5137 elif(arg == '-addlogs'): 5336 elif(arg == '-addlogs'):
5138 sysvals.addlogs = True 5337 sysvals.dmesglog = sysvals.ftracelog = True
5139 elif(arg == '-verbose'): 5338 elif(arg == '-verbose'):
5140 sysvals.verbose = True 5339 sysvals.verbose = True
5141 elif(arg == '-proc'): 5340 elif(arg == '-proc'):
@@ -5195,7 +5394,7 @@ if __name__ == '__main__':
5195 val = args.next() 5394 val = args.next()
5196 except: 5395 except:
5197 doError('No subdirectory name supplied', True) 5396 doError('No subdirectory name supplied', True)
5198 sysvals.setOutputFolder(val) 5397 outdir = sysvals.setOutputFolder(val)
5199 elif(arg == '-config'): 5398 elif(arg == '-config'):
5200 try: 5399 try:
5201 val = args.next() 5400 val = args.next()
@@ -5236,7 +5435,7 @@ if __name__ == '__main__':
5236 except: 5435 except:
5237 doError('No directory supplied', True) 5436 doError('No directory supplied', True)
5238 cmd = 'summary' 5437 cmd = 'summary'
5239 cmdarg = val 5438 outdir = val
5240 sysvals.notestrun = True 5439 sysvals.notestrun = True
5241 if(os.path.isdir(val) == False): 5440 if(os.path.isdir(val) == False):
5242 doError('%s is not accesible' % val) 5441 doError('%s is not accesible' % val)
@@ -5260,11 +5459,14 @@ if __name__ == '__main__':
5260 sysvals.mincglen = sysvals.mindevlen 5459 sysvals.mincglen = sysvals.mindevlen
5261 5460
5262 # just run a utility command and exit 5461 # just run a utility command and exit
5462 sysvals.cpuInfo()
5263 if(cmd != ''): 5463 if(cmd != ''):
5264 if(cmd == 'status'): 5464 if(cmd == 'status'):
5265 statusCheck(True) 5465 statusCheck(True)
5266 elif(cmd == 'fpdt'): 5466 elif(cmd == 'fpdt'):
5267 getFPDT(True) 5467 getFPDT(True)
5468 elif(cmd == 'sysinfo'):
5469 sysvals.printSystemInfo()
5268 elif(cmd == 'usbtopo'): 5470 elif(cmd == 'usbtopo'):
5269 detectUSB() 5471 detectUSB()
5270 elif(cmd == 'modes'): 5472 elif(cmd == 'modes'):
@@ -5276,7 +5478,7 @@ if __name__ == '__main__':
5276 elif(cmd == 'usbauto'): 5478 elif(cmd == 'usbauto'):
5277 setUSBDevicesAuto() 5479 setUSBDevicesAuto()
5278 elif(cmd == 'summary'): 5480 elif(cmd == 'summary'):
5279 runSummary(cmdarg, True) 5481 runSummary(outdir, True)
5280 sys.exit() 5482 sys.exit()
5281 5483
5282 # if instructed, re-analyze existing data files 5484 # if instructed, re-analyze existing data files
@@ -5289,21 +5491,43 @@ if __name__ == '__main__':
5289 print('Check FAILED, aborting the test run!') 5491 print('Check FAILED, aborting the test run!')
5290 sys.exit() 5492 sys.exit()
5291 5493
5494 # extract mem modes and convert
5495 mode = sysvals.suspendmode
5496 if 'mem' == mode[:3]:
5497 if '-' in mode:
5498 memmode = mode.split('-')[-1]
5499 else:
5500 memmode = 'deep'
5501 if memmode == 'shallow':
5502 mode = 'standby'
5503 elif memmode == 's2idle':
5504 mode = 'freeze'
5505 else:
5506 mode = 'mem'
5507 sysvals.memmode = memmode
5508 sysvals.suspendmode = mode
5509
5510 sysvals.systemInfo(dmidecode(sysvals.mempath))
5511
5292 if multitest['run']: 5512 if multitest['run']:
5293 # run multiple tests in a separate subdirectory 5513 # run multiple tests in a separate subdirectory
5294 s = 'x%d' % multitest['count'] 5514 if not outdir:
5295 if not sysvals.outdir: 5515 s = 'suspend-x%d' % multitest['count']
5296 sysvals.outdir = datetime.now().strftime('suspend-'+s+'-%m%d%y-%H%M%S') 5516 outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
5297 if not os.path.isdir(sysvals.outdir): 5517 if not os.path.isdir(outdir):
5298 os.mkdir(sysvals.outdir) 5518 os.mkdir(outdir)
5299 for i in range(multitest['count']): 5519 for i in range(multitest['count']):
5300 if(i != 0): 5520 if(i != 0):
5301 print('Waiting %d seconds...' % (multitest['delay'])) 5521 print('Waiting %d seconds...' % (multitest['delay']))
5302 time.sleep(multitest['delay']) 5522 time.sleep(multitest['delay'])
5303 print('TEST (%d/%d) START' % (i+1, multitest['count'])) 5523 print('TEST (%d/%d) START' % (i+1, multitest['count']))
5304 runTest(sysvals.outdir) 5524 fmt = 'suspend-%y%m%d-%H%M%S'
5525 sysvals.testdir = os.path.join(outdir, datetime.now().strftime(fmt))
5526 runTest()
5305 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count'])) 5527 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count']))
5306 runSummary(sysvals.outdir, False) 5528 runSummary(outdir, False)
5307 else: 5529 else:
5530 if outdir:
5531 sysvals.testdir = outdir
5308 # run the test in the current directory 5532 # run the test in the current directory
5309 runTest('.', sysvals.outdir) 5533 runTest()
diff --git a/tools/power/pm-graph/bootgraph.8 b/tools/power/pm-graph/bootgraph.8
index 55272a67b0e7..dbdafcf546df 100644
--- a/tools/power/pm-graph/bootgraph.8
+++ b/tools/power/pm-graph/bootgraph.8
@@ -8,14 +8,23 @@ bootgraph \- Kernel boot timing analysis
8.RB [ COMMAND ] 8.RB [ COMMAND ]
9.SH DESCRIPTION 9.SH DESCRIPTION
10\fBbootgraph \fP reads the dmesg log from kernel boot and 10\fBbootgraph \fP reads the dmesg log from kernel boot and
11creates an html representation of the initcall timeline up to the start 11creates an html representation of the initcall timeline. It graphs
12of the init process. 12every module init call found, through both kernel and user modes. The
13timeline is split into two phases: kernel mode & user mode. kernel mode
14represents a single process run on a single cpu with serial init calls.
15Once user mode begins, the init process is called, and the init calls
16start working in parallel.
13.PP 17.PP
14If no specific command is given, the tool reads the current dmesg log and 18If no specific command is given, the tool reads the current dmesg log and
15outputs bootgraph.html. 19outputs a new timeline.
16.PP 20.PP
17The tool can also augment the timeline with ftrace data on custom target 21The tool can also augment the timeline with ftrace data on custom target
18functions as well as full trace callgraphs. 22functions as well as full trace callgraphs.
23.PP
24Generates output files in subdirectory: boot-yymmdd-HHMMSS
25 html timeline : <hostname>_boot.html
26 raw dmesg file : <hostname>_boot_dmesg.txt
27 raw ftrace file : <hostname>_boot_ftrace.txt
19.SH OPTIONS 28.SH OPTIONS
20.TP 29.TP
21\fB-h\fR 30\fB-h\fR
@@ -28,15 +37,18 @@ Print the current tool version
28Add 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
29clicking a button in the timeline. 38clicking a button in the timeline.
30.TP 39.TP
31\fB-o \fIfile\fR 40\fB-o \fIname\fR
32Override the HTML output filename (default: bootgraph.html) 41Overrides the output subdirectory name when running a new test.
33.SS "Ftrace Debug" 42Use {date}, {time}, {hostname} for current values.
43.sp
44e.g. boot-{hostname}-{date}-{time}
45.SS "advanced"
34.TP 46.TP
35\fB-f\fR 47\fB-f\fR
36Use ftrace to add function detail (default: disabled) 48Use ftrace to add function detail (default: disabled)
37.TP 49.TP
38\fB-callgraph\fR 50\fB-callgraph\fR
39Use ftrace to create initcall callgraphs (default: disabled). If -filter 51Use ftrace to create initcall callgraphs (default: disabled). If -func
40is 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
41very large outputs, i.e. 10MB - 100MB. 53very large outputs, i.e. 10MB - 100MB.
42.TP 54.TP
@@ -50,16 +62,19 @@ This reduces the html file size as there can be many tiny callgraphs
50which are barely visible in the timeline. 62which are barely visible in the timeline.
51The value is a float: e.g. 0.001 represents 1 us. 63The value is a float: e.g. 0.001 represents 1 us.
52.TP 64.TP
65\fB-cgfilter \fI"func1,func2,..."\fR
66Reduce 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.
68(default: none)
69.TP
53\fB-timeprec \fIn\fR 70\fB-timeprec \fIn\fR
54Number of significant digits in timestamps (0:S, 3:ms, [6:us]) 71Number of significant digits in timestamps (0:S, 3:ms, [6:us])
55.TP 72.TP
56\fB-expandcg\fR 73\fB-expandcg\fR
57pre-expand the callgraph data in the html output (default: disabled) 74pre-expand the callgraph data in the html output (default: disabled)
58.TP 75.TP
59\fB-filter \fI"func1,func2,..."\fR 76\fB-func \fI"func1,func2,..."\fR
60Instead of tracing each initcall, trace a custom list of functions (default: do_one_initcall) 77Instead of tracing each initcall, trace a custom list of functions (default: do_one_initcall)
61
62.SH COMMANDS
63.TP 78.TP
64\fB-reboot\fR 79\fB-reboot\fR
65Reboot the machine and generate a new timeline automatically. Works in 4 steps. 80Reboot the machine and generate a new timeline automatically. Works in 4 steps.
@@ -73,16 +88,23 @@ Show the requirements to generate a new timeline manually. Requires 3 steps.
73 1. append the string to the kernel command line via your native boot manager. 88 1. append the string to the kernel command line via your native boot manager.
74 2. reboot the system 89 2. reboot the system
75 3. after startup, re-run the tool with the same arguments and no command 90 3. after startup, re-run the tool with the same arguments and no command
91
92.SH COMMANDS
93.SS "rebuild"
76.TP 94.TP
77\fB-dmesg \fIfile\fR 95\fB-dmesg \fIfile\fR
78Create HTML output from an existing dmesg file. 96Create HTML output from an existing dmesg file.
79.TP 97.TP
80\fB-ftrace \fIfile\fR 98\fB-ftrace \fIfile\fR
81Create HTML output from an existing ftrace file (used with -dmesg). 99Create HTML output from an existing ftrace file (used with -dmesg).
100.SS "other"
82.TP 101.TP
83\fB-flistall\fR 102\fB-flistall\fR
84Print all ftrace functions capable of being captured. These are all the 103Print all ftrace functions capable of being captured. These are all the
85possible values you can add to trace via the -filter argument. 104possible values you can add to trace via the -func argument.
105.TP
106\fB-sysinfo\fR
107Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
86 108
87.SH EXAMPLES 109.SH EXAMPLES
88Create a timeline using the current dmesg log. 110Create a timeline using the current dmesg log.
@@ -93,13 +115,13 @@ Create a timeline using the current dmesg and ftrace log.
93.IP 115.IP
94\f(CW$ bootgraph -callgraph\fR 116\f(CW$ bootgraph -callgraph\fR
95.PP 117.PP
96Create a timeline using the current dmesg, add the log to the html and change the name. 118Create a timeline using the current dmesg, add the log to the html and change the folder.
97.IP 119.IP
98\f(CW$ bootgraph -addlogs -o myboot.html\fR 120\f(CW$ bootgraph -addlogs -o "myboot-{date}-{time}"\fR
99.PP 121.PP
100Capture a new boot timeline by automatically rebooting the machine. 122Capture a new boot timeline by automatically rebooting the machine.
101.IP 123.IP
102\f(CW$ sudo bootgraph -reboot -addlogs -o latestboot.html\fR 124\f(CW$ sudo bootgraph -reboot -addlogs -o "latest-{hostname)"\fR
103.PP 125.PP
104Capture a new boot timeline with function trace data. 126Capture a new boot timeline with function trace data.
105.IP 127.IP
@@ -111,7 +133,7 @@ Capture a new boot timeline with trace & callgraph data. Skip callgraphs smaller
111.PP 133.PP
112Capture a new boot timeline with callgraph data over custom functions. 134Capture a new boot timeline with callgraph data over custom functions.
113.IP 135.IP
114\f(CW$ sudo bootgraph -reboot -callgraph -filter "acpi_ps_parse_aml,msleep"\fR 136\f(CW$ sudo bootgraph -reboot -callgraph -func "acpi_ps_parse_aml,msleep"\fR
115.PP 137.PP
116Capture a brand new boot timeline with manual reboot. 138Capture a brand new boot timeline with manual reboot.
117.IP 139.IP
@@ -123,6 +145,15 @@ Capture a brand new boot timeline with manual reboot.
123.IP 145.IP
124\f(CW$ sudo bootgraph -callgraph # re-run the tool after restart\fR 146\f(CW$ sudo bootgraph -callgraph # re-run the tool after restart\fR
125.PP 147.PP
148.SS "rebuild timeline from logs"
149.PP
150Rebuild the html from a previous run's logs, using the same options.
151.IP
152\f(CW$ bootgraph -dmesg dmesg.txt -ftrace ftrace.txt -callgraph\fR
153.PP
154Rebuild the html with different options.
155.IP
156\f(CW$ bootgraph -dmesg dmesg.txt -ftrace ftrace.txt -addlogs\fR
126 157
127.SH "SEE ALSO" 158.SH "SEE ALSO"
128dmesg(1), update-grub(8), crontab(1), reboot(8) 159dmesg(1), update-grub(8), crontab(1), reboot(8)
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index 610e72ebbc06..fbe7bd3eae8e 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -39,8 +39,9 @@ Pull arguments and config options from a file.
39\fB-m \fImode\fR 39\fB-m \fImode\fR
40Mode to initiate for suspend e.g. standby, freeze, mem (default: mem). 40Mode to initiate for suspend e.g. standby, freeze, mem (default: mem).
41.TP 41.TP
42\fB-o \fIsubdir\fR 42\fB-o \fIname\fR
43Override the output subdirectory. Use {date}, {time}, {hostname} for current values. 43Overrides the output subdirectory name when running a new test.
44Use {date}, {time}, {hostname} for current values.
44.sp 45.sp
45e.g. suspend-{hostname}-{date}-{time} 46e.g. suspend-{hostname}-{date}-{time}
46.TP 47.TP
@@ -52,7 +53,7 @@ disable rtcwake and require a user keypress to resume.
52Add 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
53clicking buttons in the timeline. 54clicking buttons in the timeline.
54 55
55.SS "Advanced" 56.SS "advanced"
56.TP 57.TP
57\fB-cmd \fIstr\fR 58\fB-cmd \fIstr\fR
58Run the timeline over a custom suspend command, e.g. pm-suspend. By default 59Run the timeline over a custom suspend command, e.g. pm-suspend. By default
@@ -91,7 +92,7 @@ Include \fIt\fR ms delay after last resume (default: 0 ms).
91Execute \fIn\fR consecutive tests at \fId\fR seconds intervals. The outputs will 92Execute \fIn\fR consecutive tests at \fId\fR seconds intervals. The outputs will
92be created in a new subdirectory with a summary page: suspend-xN-{date}-{time}. 93be created in a new subdirectory with a summary page: suspend-xN-{date}-{time}.
93 94
94.SS "Ftrace Debug" 95.SS "ftrace debug"
95.TP 96.TP
96\fB-f\fR 97\fB-f\fR
97Use ftrace to create device callgraphs (default: disabled). This can produce 98Use ftrace to create device callgraphs (default: disabled). This can produce
@@ -124,12 +125,6 @@ Number of significant digits in timestamps (0:S, [3:ms], 6:us).
124 125
125.SH COMMANDS 126.SH COMMANDS
126.TP 127.TP
127\fB-ftrace \fIfile\fR
128Create HTML output from an existing ftrace file.
129.TP
130\fB-dmesg \fIfile\fR
131Create HTML output from an existing dmesg file.
132.TP
133\fB-summary \fIindir\fR 128\fB-summary \fIindir\fR
134Create a summary page of all tests in \fIindir\fR. Creates summary.html 129Create a summary page of all tests in \fIindir\fR. Creates summary.html
135in the current folder. The output page is a table of tests with 130in the current folder. The output page is a table of tests with
@@ -146,6 +141,9 @@ with any options you intend to use to see if they will work.
146\fB-fpdt\fR 141\fB-fpdt\fR
147Print out the contents of the ACPI Firmware Performance Data Table. 142Print out the contents of the ACPI Firmware Performance Data Table.
148.TP 143.TP
144\fB-sysinfo\fR
145Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
146.TP
149\fB-usbtopo\fR 147\fB-usbtopo\fR
150Print out the current USB topology with power info. 148Print out the current USB topology with power info.
151.TP 149.TP
@@ -162,9 +160,16 @@ with -fadd they will also be checked.
162\fB-flistall\fR 160\fB-flistall\fR
163Print all ftrace functions capable of being captured. These are all the 161Print all ftrace functions capable of being captured. These are all the
164possible values you can add to trace via the -fadd argument. 162possible values you can add to trace via the -fadd argument.
163.SS "rebuild"
164.TP
165\fB-ftrace \fIfile\fR
166Create HTML output from an existing ftrace file.
167.TP
168\fB-dmesg \fIfile\fR
169Create HTML output from an existing dmesg file.
165 170
166.SH EXAMPLES 171.SH EXAMPLES
167.SS "Simple Commands" 172.SS "simple commands"
168Check which suspend modes are currently supported. 173Check which suspend modes are currently supported.
169.IP 174.IP
170\f(CW$ sleepgraph -modes\fR 175\f(CW$ sleepgraph -modes\fR
@@ -185,12 +190,8 @@ Generate a summary of all timelines in a particular folder.
185.IP 190.IP
186\f(CW$ sleepgraph -summary ~/workspace/myresults/\fR 191\f(CW$ sleepgraph -summary ~/workspace/myresults/\fR
187.PP 192.PP
188Re-generate the html output from a previous run's dmesg and ftrace log.
189.IP
190\f(CW$ sleepgraph -dmesg myhost_mem_dmesg.txt -ftrace myhost_mem_ftrace.txt\fR
191.PP
192 193
193.SS "Capturing Simple Timelines" 194.SS "capturing basic timelines"
194Execute a mem suspend with a 15 second wakeup. Include the logs in the html. 195Execute a mem suspend with a 15 second wakeup. Include the logs in the html.
195.IP 196.IP
196\f(CW$ sudo sleepgraph -rtcwake 15 -addlogs\fR 197\f(CW$ sudo sleepgraph -rtcwake 15 -addlogs\fR
@@ -204,7 +205,7 @@ Execute a freeze with no wakeup (require keypress). Change output folder name.
204\f(CW$ sudo sleepgraph -m freeze -rtcwake off -o "freeze-{hostname}-{date}-{time}"\fR 205\f(CW$ sudo sleepgraph -m freeze -rtcwake off -o "freeze-{hostname}-{date}-{time}"\fR
205.PP 206.PP
206 207
207.SS "Capturing Advanced Timelines" 208.SS "capturing advanced timelines"
208Execute a suspend & include dev mode source calls, limit callbacks to 5ms or larger. 209Execute a suspend & include dev mode source calls, limit callbacks to 5ms or larger.
209.IP 210.IP
210\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -dev -mindev 5\fR 211\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -dev -mindev 5\fR
@@ -222,8 +223,7 @@ Execute a suspend using a custom command.
222\f(CW$ sudo sleepgraph -cmd "echo mem > /sys/power/state" -rtcwake 15\fR 223\f(CW$ sudo sleepgraph -cmd "echo mem > /sys/power/state" -rtcwake 15\fR
223.PP 224.PP
224 225
225 226.SS "adding callgraph data"
226.SS "Capturing Timelines with Callgraph Data"
227Add device callgraphs. Limit the trace depth and only show callgraphs 10ms or larger. 227Add device callgraphs. Limit the trace depth and only show callgraphs 10ms or larger.
228.IP 228.IP
229\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -f -maxdepth 5 -mincg 10\fR 229\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -f -maxdepth 5 -mincg 10\fR
@@ -235,6 +235,16 @@ Capture a full callgraph across all suspend, then filter the html by a single ph
235\f(CW$ sleepgraph -dmesg host_mem_dmesg.txt -ftrace host_mem_ftrace.txt -f -cgphase resume 235\f(CW$ sleepgraph -dmesg host_mem_dmesg.txt -ftrace host_mem_ftrace.txt -f -cgphase resume
236.PP 236.PP
237 237
238.SS "rebuild timeline from logs"
239.PP
240Rebuild the html from a previous run's logs, using the same options.
241.IP
242\f(CW$ sleepgraph -dmesg dmesg.txt -ftrace ftrace.txt -callgraph\fR
243.PP
244Rebuild the html with different options.
245.IP
246\f(CW$ sleepgraph -dmesg dmesg.txt -ftrace ftrace.txt -addlogs -srgap\fR
247
238.SH "SEE ALSO" 248.SH "SEE ALSO"
239dmesg(1) 249dmesg(1)
240.PP 250.PP
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 1e8b6116ba3c..9dc8f078a83c 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -1,7 +1,7 @@
1ifneq ($(O),) 1ifneq ($(O),)
2ifeq ($(origin O), command line) 2ifeq ($(origin O), command line)
3 dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) 3 ABSOLUTE_O := $(realpath $(O))
4 ABSOLUTE_O := $(shell cd $(O) ; pwd) 4 dummy := $(if $(ABSOLUTE_O),,$(error O=$(O) does not exist))
5 OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/) 5 OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/)
6 COMMAND_O := O=$(ABSOLUTE_O) 6 COMMAND_O := O=$(ABSOLUTE_O)
7ifeq ($(objtree),) 7ifeq ($(objtree),)
@@ -12,7 +12,7 @@ endif
12 12
13# check that the output directory actually exists 13# check that the output directory actually exists
14ifneq ($(OUTPUT),) 14ifneq ($(OUTPUT),)
15OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) 15OUTDIR := $(realpath $(OUTPUT))
16$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 16$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
17endif 17endif
18 18
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 4c2fa98ef39d..bef419d4266d 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1527,9 +1527,6 @@ static void nfit_test1_setup(struct nfit_test *t)
1527 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 1527 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1528 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 1528 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1529 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 1529 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1530 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1531 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1532 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1533} 1530}
1534 1531
1535static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1532static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
@@ -1546,8 +1543,8 @@ static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
1546 else { 1543 else {
1547 memcpy(iobuf, mmio->addr.base + dpa, len); 1544 memcpy(iobuf, mmio->addr.base + dpa, len);
1548 1545
1549 /* give us some some coverage of the mmio_flush_range() API */ 1546 /* give us some some coverage of the arch_invalidate_pmem() API */
1550 mmio_flush_range(mmio->addr.base + dpa, len); 1547 arch_invalidate_pmem(mmio->addr.base + dpa, len);
1551 } 1548 }
1552 nd_region_release_lane(nd_region, lane); 1549 nd_region_release_lane(nd_region, lane);
1553 1550
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 26ce4f7168be..ff805643b5f7 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -52,6 +52,10 @@ override LDFLAGS =
52override MAKEFLAGS = 52override MAKEFLAGS =
53endif 53endif
54 54
55ifneq ($(KBUILD_SRC),)
56override LDFLAGS =
57endif
58
55BUILD := $(O) 59BUILD := $(O)
56ifndef BUILD 60ifndef BUILD
57 BUILD := $(KBUILD_OUTPUT) 61 BUILD := $(KBUILD_OUTPUT)
@@ -62,32 +66,32 @@ endif
62 66
63export BUILD 67export BUILD
64all: 68all:
65 for TARGET in $(TARGETS); do \ 69 @for TARGET in $(TARGETS); do \
66 BUILD_TARGET=$$BUILD/$$TARGET; \ 70 BUILD_TARGET=$$BUILD/$$TARGET; \
67 mkdir $$BUILD_TARGET -p; \ 71 mkdir $$BUILD_TARGET -p; \
68 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\ 72 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
69 done; 73 done;
70 74
71run_tests: all 75run_tests: all
72 for TARGET in $(TARGETS); do \ 76 @for TARGET in $(TARGETS); do \
73 BUILD_TARGET=$$BUILD/$$TARGET; \ 77 BUILD_TARGET=$$BUILD/$$TARGET; \
74 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\ 78 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\
75 done; 79 done;
76 80
77hotplug: 81hotplug:
78 for TARGET in $(TARGETS_HOTPLUG); do \ 82 @for TARGET in $(TARGETS_HOTPLUG); do \
79 BUILD_TARGET=$$BUILD/$$TARGET; \ 83 BUILD_TARGET=$$BUILD/$$TARGET; \
80 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\ 84 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
81 done; 85 done;
82 86
83run_hotplug: hotplug 87run_hotplug: hotplug
84 for TARGET in $(TARGETS_HOTPLUG); do \ 88 @for TARGET in $(TARGETS_HOTPLUG); do \
85 BUILD_TARGET=$$BUILD/$$TARGET; \ 89 BUILD_TARGET=$$BUILD/$$TARGET; \
86 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\ 90 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\
87 done; 91 done;
88 92
89clean_hotplug: 93clean_hotplug:
90 for TARGET in $(TARGETS_HOTPLUG); do \ 94 @for TARGET in $(TARGETS_HOTPLUG); do \
91 BUILD_TARGET=$$BUILD/$$TARGET; \ 95 BUILD_TARGET=$$BUILD/$$TARGET; \
92 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\ 96 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
93 done; 97 done;
@@ -103,7 +107,7 @@ install:
103ifdef INSTALL_PATH 107ifdef INSTALL_PATH
104 @# Ask all targets to install their files 108 @# Ask all targets to install their files
105 mkdir -p $(INSTALL_PATH) 109 mkdir -p $(INSTALL_PATH)
106 for TARGET in $(TARGETS); do \ 110 @for TARGET in $(TARGETS); do \
107 BUILD_TARGET=$$BUILD/$$TARGET; \ 111 BUILD_TARGET=$$BUILD/$$TARGET; \
108 make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \ 112 make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
109 done; 113 done;
@@ -128,7 +132,7 @@ else
128endif 132endif
129 133
130clean: 134clean:
131 for TARGET in $(TARGETS); do \ 135 @for TARGET in $(TARGETS); do \
132 BUILD_TARGET=$$BUILD/$$TARGET; \ 136 BUILD_TARGET=$$BUILD/$$TARGET; \
133 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\ 137 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
134 done; 138 done;
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 153c3a181a4c..f4b23d697448 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -15,9 +15,9 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
15 test_align 15 test_align
16 16
17TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 17TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
18 test_pkt_md_access.o 18 test_pkt_md_access.o test_xdp_redirect.o sockmap_parse_prog.o sockmap_verdict_prog.o
19 19
20TEST_PROGS := test_kmod.sh 20TEST_PROGS := test_kmod.sh test_xdp_redirect.sh
21 21
22include ../lib.mk 22include ../lib.mk
23 23
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index d50ac342dc92..36fb9161b34a 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -38,6 +38,8 @@ static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
38 (void *) BPF_FUNC_clone_redirect; 38 (void *) BPF_FUNC_clone_redirect;
39static int (*bpf_redirect)(int ifindex, int flags) = 39static int (*bpf_redirect)(int ifindex, int flags) =
40 (void *) BPF_FUNC_redirect; 40 (void *) BPF_FUNC_redirect;
41static int (*bpf_redirect_map)(void *map, int key, int flags) =
42 (void *) BPF_FUNC_redirect_map;
41static int (*bpf_perf_event_output)(void *ctx, void *map, 43static int (*bpf_perf_event_output)(void *ctx, void *map,
42 unsigned long long flags, void *data, 44 unsigned long long flags, void *data,
43 int size) = 45 int size) =
@@ -63,6 +65,12 @@ static int (*bpf_xdp_adjust_head)(void *ctx, int offset) =
63static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval, 65static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval,
64 int optlen) = 66 int optlen) =
65 (void *) BPF_FUNC_setsockopt; 67 (void *) BPF_FUNC_setsockopt;
68static int (*bpf_sk_redirect_map)(void *map, int key, int flags) =
69 (void *) BPF_FUNC_sk_redirect_map;
70static int (*bpf_sock_map_update)(void *map, void *key, void *value,
71 unsigned long long flags) =
72 (void *) BPF_FUNC_sock_map_update;
73
66 74
67/* llvm builtin functions that eBPF C program may use to 75/* llvm builtin functions that eBPF C program may use to
68 * emit BPF_LD_ABS and BPF_LD_IND instructions 76 * emit BPF_LD_ABS and BPF_LD_IND instructions
@@ -85,6 +93,7 @@ struct bpf_map_def {
85 unsigned int max_entries; 93 unsigned int max_entries;
86 unsigned int map_flags; 94 unsigned int map_flags;
87 unsigned int inner_map_idx; 95 unsigned int inner_map_idx;
96 unsigned int numa_node;
88}; 97};
89 98
90static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = 99static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
diff --git a/tools/testing/selftests/bpf/bpf_util.h b/tools/testing/selftests/bpf/bpf_util.h
index 20ecbaa0d85d..6c53a8906eff 100644
--- a/tools/testing/selftests/bpf/bpf_util.h
+++ b/tools/testing/selftests/bpf/bpf_util.h
@@ -12,6 +12,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
12 unsigned int start, end, possible_cpus = 0; 12 unsigned int start, end, possible_cpus = 0;
13 char buff[128]; 13 char buff[128];
14 FILE *fp; 14 FILE *fp;
15 int n;
15 16
16 fp = fopen(fcpu, "r"); 17 fp = fopen(fcpu, "r");
17 if (!fp) { 18 if (!fp) {
@@ -20,17 +21,17 @@ static inline unsigned int bpf_num_possible_cpus(void)
20 } 21 }
21 22
22 while (fgets(buff, sizeof(buff), fp)) { 23 while (fgets(buff, sizeof(buff), fp)) {
23 if (sscanf(buff, "%u-%u", &start, &end) == 2) { 24 n = sscanf(buff, "%u-%u", &start, &end);
24 possible_cpus = start == 0 ? end + 1 : 0; 25 if (n == 0) {
25 break; 26 printf("Failed to retrieve # possible CPUs!\n");
27 exit(1);
28 } else if (n == 1) {
29 end = start;
26 } 30 }
31 possible_cpus = start == 0 ? end + 1 : 0;
32 break;
27 } 33 }
28
29 fclose(fp); 34 fclose(fp);
30 if (!possible_cpus) {
31 printf("Failed to retrieve # possible CPUs!\n");
32 exit(1);
33 }
34 35
35 return possible_cpus; 36 return possible_cpus;
36} 37}
diff --git a/tools/testing/selftests/bpf/sockmap_parse_prog.c b/tools/testing/selftests/bpf/sockmap_parse_prog.c
new file mode 100644
index 000000000000..fae3b96c3aa4
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_parse_prog.c
@@ -0,0 +1,38 @@
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_skb1")
16int bpf_prog1(struct __sk_buff *skb)
17{
18 void *data_end = (void *)(long) skb->data_end;
19 void *data = (void *)(long) skb->data;
20 __u32 lport = skb->local_port;
21 __u32 rport = skb->remote_port;
22 __u8 *d = data;
23
24 if (data + 10 > data_end)
25 return skb->len;
26
27 /* This write/read is a bit pointless but tests the verifier and
28 * strparser handler for read/write pkt data and access into sk
29 * fields.
30 */
31 d[7] = 1;
32
33 bpf_printk("parse: data[0] = (%u): local_port %i remote %i\n",
34 d[0], lport, bpf_ntohl(rport));
35 return skb->len;
36}
37
38char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/sockmap_verdict_prog.c b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
new file mode 100644
index 000000000000..9b99bd10807d
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
@@ -0,0 +1,68 @@
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
15struct bpf_map_def SEC("maps") sock_map_rx = {
16 .type = BPF_MAP_TYPE_SOCKMAP,
17 .key_size = sizeof(int),
18 .value_size = sizeof(int),
19 .max_entries = 20,
20};
21
22struct bpf_map_def SEC("maps") sock_map_tx = {
23 .type = BPF_MAP_TYPE_SOCKMAP,
24 .key_size = sizeof(int),
25 .value_size = sizeof(int),
26 .max_entries = 20,
27};
28
29struct bpf_map_def SEC("maps") sock_map_break = {
30 .type = BPF_MAP_TYPE_ARRAY,
31 .key_size = sizeof(int),
32 .value_size = sizeof(int),
33 .max_entries = 20,
34};
35
36SEC("sk_skb2")
37int bpf_prog2(struct __sk_buff *skb)
38{
39 void *data_end = (void *)(long) skb->data_end;
40 void *data = (void *)(long) skb->data;
41 __u32 lport = skb->local_port;
42 __u32 rport = skb->remote_port;
43 __u8 *d = data;
44 __u8 sk, map;
45
46 if (data + 8 > data_end)
47 return SK_DROP;
48
49 map = d[0];
50 sk = d[1];
51
52 d[0] = 0xd;
53 d[1] = 0xe;
54 d[2] = 0xa;
55 d[3] = 0xd;
56 d[4] = 0xb;
57 d[5] = 0xe;
58 d[6] = 0xe;
59 d[7] = 0xf;
60
61 bpf_printk("verdict: data[0] = redir(%u:%u)\n", map, sk);
62
63 if (!map)
64 return bpf_sk_redirect_map(&sock_map_rx, sk, 0);
65 return bpf_sk_redirect_map(&sock_map_tx, sk, 0);
66}
67
68char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
index 29793694cbc7..8591c89c0828 100644
--- a/tools/testing/selftests/bpf/test_align.c
+++ b/tools/testing/selftests/bpf/test_align.c
@@ -27,6 +27,11 @@
27#define MAX_INSNS 512 27#define MAX_INSNS 512
28#define MAX_MATCHES 16 28#define MAX_MATCHES 16
29 29
30struct bpf_reg_match {
31 unsigned int line;
32 const char *match;
33};
34
30struct bpf_align_test { 35struct bpf_align_test {
31 const char *descr; 36 const char *descr;
32 struct bpf_insn insns[MAX_INSNS]; 37 struct bpf_insn insns[MAX_INSNS];
@@ -36,10 +41,14 @@ struct bpf_align_test {
36 REJECT 41 REJECT
37 } result; 42 } result;
38 enum bpf_prog_type prog_type; 43 enum bpf_prog_type prog_type;
39 const char *matches[MAX_MATCHES]; 44 /* Matches must be in order of increasing line */
45 struct bpf_reg_match matches[MAX_MATCHES];
40}; 46};
41 47
42static struct bpf_align_test tests[] = { 48static struct bpf_align_test tests[] = {
49 /* Four tests of known constants. These aren't staggeringly
50 * interesting since we track exact values now.
51 */
43 { 52 {
44 .descr = "mov", 53 .descr = "mov",
45 .insns = { 54 .insns = {
@@ -53,11 +62,13 @@ static struct bpf_align_test tests[] = {
53 }, 62 },
54 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 63 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
55 .matches = { 64 .matches = {
56 "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 65 {1, "R1=ctx(id=0,off=0,imm=0)"},
57 "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 66 {1, "R10=fp0"},
58 "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 67 {1, "R3=inv2"},
59 "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 68 {2, "R3=inv4"},
60 "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp", 69 {3, "R3=inv8"},
70 {4, "R3=inv16"},
71 {5, "R3=inv32"},
61 }, 72 },
62 }, 73 },
63 { 74 {
@@ -79,17 +90,19 @@ static struct bpf_align_test tests[] = {
79 }, 90 },
80 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 91 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
81 .matches = { 92 .matches = {
82 "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", 93 {1, "R1=ctx(id=0,off=0,imm=0)"},
83 "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 94 {1, "R10=fp0"},
84 "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 95 {1, "R3=inv1"},
85 "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 96 {2, "R3=inv2"},
86 "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 97 {3, "R3=inv4"},
87 "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", 98 {4, "R3=inv8"},
88 "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp", 99 {5, "R3=inv16"},
89 "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 100 {6, "R3=inv1"},
90 "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 101 {7, "R4=inv32"},
91 "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 102 {8, "R4=inv16"},
92 "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 103 {9, "R4=inv8"},
104 {10, "R4=inv4"},
105 {11, "R4=inv2"},
93 }, 106 },
94 }, 107 },
95 { 108 {
@@ -106,12 +119,14 @@ static struct bpf_align_test tests[] = {
106 }, 119 },
107 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 120 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
108 .matches = { 121 .matches = {
109 "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 122 {1, "R1=ctx(id=0,off=0,imm=0)"},
110 "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp", 123 {1, "R10=fp0"},
111 "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp", 124 {1, "R3=inv4"},
112 "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 125 {2, "R3=inv8"},
113 "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp", 126 {3, "R3=inv10"},
114 "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp", 127 {4, "R4=inv8"},
128 {5, "R4=inv12"},
129 {6, "R4=inv14"},
115 }, 130 },
116 }, 131 },
117 { 132 {
@@ -126,13 +141,16 @@ static struct bpf_align_test tests[] = {
126 }, 141 },
127 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 142 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
128 .matches = { 143 .matches = {
129 "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", 144 {1, "R1=ctx(id=0,off=0,imm=0)"},
130 "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", 145 {1, "R10=fp0"},
131 "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp", 146 {1, "R3=inv7"},
132 "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp", 147 {2, "R3=inv7"},
148 {3, "R3=inv14"},
149 {4, "R3=inv56"},
133 }, 150 },
134 }, 151 },
135 152
153 /* Tests using unknown values */
136#define PREP_PKT_POINTERS \ 154#define PREP_PKT_POINTERS \
137 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \ 155 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
138 offsetof(struct __sk_buff, data)), \ 156 offsetof(struct __sk_buff, data)), \
@@ -166,17 +184,19 @@ static struct bpf_align_test tests[] = {
166 }, 184 },
167 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 185 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
168 .matches = { 186 .matches = {
169 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", 187 {7, "R0=pkt(id=0,off=8,r=8,imm=0)"},
170 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp", 188 {7, "R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
171 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp", 189 {8, "R3=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
172 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp", 190 {9, "R3=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
173 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp", 191 {10, "R3=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
174 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp", 192 {11, "R3=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
175 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp", 193 {18, "R3=pkt_end(id=0,off=0,imm=0)"},
176 "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp", 194 {18, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
177 "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp", 195 {19, "R4=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
178 "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp", 196 {20, "R4=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
179 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp", 197 {21, "R4=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
198 {22, "R4=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
199 {23, "R4=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
180 }, 200 },
181 }, 201 },
182 { 202 {
@@ -197,16 +217,16 @@ static struct bpf_align_test tests[] = {
197 }, 217 },
198 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 218 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
199 .matches = { 219 .matches = {
200 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", 220 {7, "R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
201 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 221 {8, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
202 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp", 222 {9, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
203 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 223 {10, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
204 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp", 224 {11, "R4=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
205 "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 225 {12, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
206 "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp", 226 {13, "R4=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
207 "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 227 {14, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
208 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp", 228 {15, "R4=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
209 "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp" 229 {16, "R4=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
210 }, 230 },
211 }, 231 },
212 { 232 {
@@ -237,12 +257,14 @@ static struct bpf_align_test tests[] = {
237 }, 257 },
238 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 258 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
239 .matches = { 259 .matches = {
240 "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp", 260 {4, "R5=pkt(id=0,off=0,r=0,imm=0)"},
241 "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp", 261 {5, "R5=pkt(id=0,off=14,r=0,imm=0)"},
242 "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp", 262 {6, "R4=pkt(id=0,off=14,r=0,imm=0)"},
243 "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp", 263 {10, "R2=pkt(id=0,off=0,r=18,imm=0)"},
244 "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp", 264 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"},
245 "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp", 265 {10, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
266 {14, "R4=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
267 {15, "R4=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
246 }, 268 },
247 }, 269 },
248 { 270 {
@@ -297,62 +319,286 @@ static struct bpf_align_test tests[] = {
297 /* Calculated offset in R6 has unknown value, but known 319 /* Calculated offset in R6 has unknown value, but known
298 * alignment of 4. 320 * alignment of 4.
299 */ 321 */
300 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp", 322 {8, "R2=pkt(id=0,off=0,r=8,imm=0)"},
301 323 {8, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
302 /* Offset is added to packet pointer R5, resulting in known 324 /* Offset is added to packet pointer R5, resulting in
303 * auxiliary alignment and offset. 325 * known fixed offset, and variable offset from R6.
304 */ 326 */
305 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 327 {11, "R5=pkt(id=1,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
306
307 /* At the time the word size load is performed from R5, 328 /* At the time the word size load is performed from R5,
308 * it's total offset is NET_IP_ALIGN + reg->off (0) + 329 * it's total offset is NET_IP_ALIGN + reg->off (0) +
309 * reg->aux_off (14) which is 16. Then the variable 330 * reg->aux_off (14) which is 16. Then the variable
310 * offset is considered using reg->aux_off_align which 331 * offset is considered using reg->aux_off_align which
311 * is 4 and meets the load's requirements. 332 * is 4 and meets the load's requirements.
312 */ 333 */
313 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 334 {15, "R4=pkt(id=1,off=18,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
314 335 {15, "R5=pkt(id=1,off=14,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
315
316 /* Variable offset is added to R5 packet pointer, 336 /* Variable offset is added to R5 packet pointer,
317 * resulting in auxiliary alignment of 4. 337 * resulting in auxiliary alignment of 4.
318 */ 338 */
319 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp", 339 {18, "R5=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
320
321 /* Constant offset is added to R5, resulting in 340 /* Constant offset is added to R5, resulting in
322 * reg->off of 14. 341 * reg->off of 14.
323 */ 342 */
324 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp", 343 {19, "R5=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
325
326 /* At the time the word size load is performed from R5, 344 /* At the time the word size load is performed from R5,
327 * it's total offset is NET_IP_ALIGN + reg->off (14) which 345 * its total fixed offset is NET_IP_ALIGN + reg->off
328 * is 16. Then the variable offset is considered using 346 * (14) which is 16. Then the variable offset is 4-byte
329 * reg->aux_off_align which is 4 and meets the load's 347 * aligned, so the total offset is 4-byte aligned and
330 * requirements. 348 * meets the load's requirements.
331 */ 349 */
332 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp", 350 {23, "R4=pkt(id=2,off=18,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
333 351 {23, "R5=pkt(id=2,off=14,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
334 /* Constant offset is added to R5 packet pointer, 352 /* Constant offset is added to R5 packet pointer,
335 * resulting in reg->off value of 14. 353 * resulting in reg->off value of 14.
336 */ 354 */
337 "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp", 355 {26, "R5=pkt(id=0,off=14,r=8"},
338 /* Variable offset is added to R5, resulting in an 356 /* Variable offset is added to R5, resulting in a
339 * auxiliary offset of 14, and an auxiliary alignment of 4. 357 * variable offset of (4n).
340 */ 358 */
341 "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 359 {27, "R5=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
342 /* Constant is added to R5 again, setting reg->off to 4. */ 360 /* Constant is added to R5 again, setting reg->off to 18. */
343 "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 361 {28, "R5=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
344 /* And once more we add a variable, which causes an accumulation 362 /* And once more we add a variable; resulting var_off
345 * of reg->off into reg->aux_off_align, with resulting value of 363 * is still (4n), fixed offset is not changed.
346 * 18. The auxiliary alignment stays at 4. 364 * Also, we create a new reg->id.
347 */ 365 */
348 "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 366 {29, "R5=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc))"},
349 /* At the time the word size load is performed from R5, 367 /* At the time the word size load is performed from R5,
350 * it's total offset is NET_IP_ALIGN + reg->off (0) + 368 * its total fixed offset is NET_IP_ALIGN + reg->off (18)
351 * reg->aux_off (18) which is 20. Then the variable offset 369 * which is 20. Then the variable offset is (4n), so
352 * is considered using reg->aux_off_align which is 4 and meets 370 * the total offset is 4-byte aligned and meets the
353 * the load's requirements. 371 * load's requirements.
372 */
373 {33, "R4=pkt(id=4,off=22,r=22,umax_value=2040,var_off=(0x0; 0x7fc))"},
374 {33, "R5=pkt(id=4,off=18,r=22,umax_value=2040,var_off=(0x0; 0x7fc))"},
375 },
376 },
377 {
378 .descr = "packet variable offset 2",
379 .insns = {
380 /* Create an unknown offset, (4n+2)-aligned */
381 LOAD_UNKNOWN(BPF_REG_6),
382 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
383 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
384 /* Add it to the packet pointer */
385 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
386 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
387 /* Check bounds and perform a read */
388 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
389 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
390 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
391 BPF_EXIT_INSN(),
392 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
393 /* Make a (4n) offset from the value we just read */
394 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xff),
395 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
396 /* Add it to the packet pointer */
397 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
398 /* Check bounds and perform a read */
399 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
400 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
401 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
402 BPF_EXIT_INSN(),
403 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
404 BPF_MOV64_IMM(BPF_REG_0, 0),
405 BPF_EXIT_INSN(),
406 },
407 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
408 .matches = {
409 /* Calculated offset in R6 has unknown value, but known
410 * alignment of 4.
411 */
412 {8, "R2=pkt(id=0,off=0,r=8,imm=0)"},
413 {8, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
414 /* Adding 14 makes R6 be (4n+2) */
415 {9, "R6=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
416 /* Packet pointer has (4n+2) offset */
417 {11, "R5=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
418 {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
419 /* At the time the word size load is performed from R5,
420 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
421 * which is 2. Then the variable offset is (4n+2), so
422 * the total offset is 4-byte aligned and meets the
423 * load's requirements.
424 */
425 {15, "R5=pkt(id=1,off=0,r=4,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
426 /* Newly read value in R6 was shifted left by 2, so has
427 * known alignment of 4.
428 */
429 {18, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
430 /* Added (4n) to packet pointer's (4n+2) var_off, giving
431 * another (4n+2).
432 */
433 {19, "R5=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
434 {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
435 /* At the time the word size load is performed from R5,
436 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
437 * which is 2. Then the variable offset is (4n+2), so
438 * the total offset is 4-byte aligned and meets the
439 * load's requirements.
440 */
441 {23, "R5=pkt(id=2,off=0,r=4,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
442 },
443 },
444 {
445 .descr = "dubious pointer arithmetic",
446 .insns = {
447 PREP_PKT_POINTERS,
448 BPF_MOV64_IMM(BPF_REG_0, 0),
449 /* ptr & const => unknown & const */
450 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
451 BPF_ALU64_IMM(BPF_AND, BPF_REG_5, 0x40),
452 /* ptr << const => unknown << const */
453 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
454 BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 2),
455 /* We have a (4n) value. Let's make a packet offset
456 * out of it. First add 14, to make it a (4n+2)
457 */
458 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
459 /* Then make sure it's nonnegative */
460 BPF_JMP_IMM(BPF_JSGE, BPF_REG_5, 0, 1),
461 BPF_EXIT_INSN(),
462 /* Add it to packet pointer */
463 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
464 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
465 /* Check bounds and perform a read */
466 BPF_MOV64_REG(BPF_REG_4, BPF_REG_6),
467 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
468 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
469 BPF_EXIT_INSN(),
470 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_6, 0),
471 BPF_EXIT_INSN(),
472 },
473 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
474 .result = REJECT,
475 .matches = {
476 {4, "R5=pkt(id=0,off=0,r=0,imm=0)"},
477 /* ptr & 0x40 == either 0 or 0x40 */
478 {5, "R5=inv(id=0,umax_value=64,var_off=(0x0; 0x40))"},
479 /* ptr << 2 == unknown, (4n) */
480 {7, "R5=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc))"},
481 /* (4n) + 14 == (4n+2). We blow our bounds, because
482 * the add could overflow.
483 */
484 {8, "R5=inv(id=0,var_off=(0x2; 0xfffffffffffffffc))"},
485 /* Checked s>=0 */
486 {10, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
487 /* packet pointer + nonnegative (4n+2) */
488 {12, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
489 {14, "R4=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
490 /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.
491 * We checked the bounds, but it might have been able
492 * to overflow if the packet pointer started in the
493 * upper half of the address space.
494 * So we did not get a 'range' on R6, and the access
495 * attempt will fail.
496 */
497 {16, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
498 }
499 },
500 {
501 .descr = "variable subtraction",
502 .insns = {
503 /* Create an unknown offset, (4n+2)-aligned */
504 LOAD_UNKNOWN(BPF_REG_6),
505 BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
506 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
507 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
508 /* Create another unknown, (4n)-aligned, and subtract
509 * it from the first one
510 */
511 BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
512 BPF_ALU64_REG(BPF_SUB, BPF_REG_6, BPF_REG_7),
513 /* Bounds-check the result */
514 BPF_JMP_IMM(BPF_JSGE, BPF_REG_6, 0, 1),
515 BPF_EXIT_INSN(),
516 /* Add it to the packet pointer */
517 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
518 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
519 /* Check bounds and perform a read */
520 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
521 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
522 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
523 BPF_EXIT_INSN(),
524 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
525 BPF_EXIT_INSN(),
526 },
527 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
528 .matches = {
529 /* Calculated offset in R6 has unknown value, but known
530 * alignment of 4.
531 */
532 {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
533 {9, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
534 /* Adding 14 makes R6 be (4n+2) */
535 {10, "R6=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
536 /* New unknown value in R7 is (4n) */
537 {11, "R7=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
538 /* Subtracting it from R6 blows our unsigned bounds */
539 {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,var_off=(0x2; 0xfffffffffffffffc))"},
540 /* Checked s>= 0 */
541 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
542 /* At the time the word size load is performed from R5,
543 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
544 * which is 2. Then the variable offset is (4n+2), so
545 * the total offset is 4-byte aligned and meets the
546 * load's requirements.
547 */
548 {20, "R5=pkt(id=1,off=0,r=4,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
549 },
550 },
551 {
552 .descr = "pointer variable subtraction",
553 .insns = {
554 /* Create an unknown offset, (4n+2)-aligned and bounded
555 * to [14,74]
556 */
557 LOAD_UNKNOWN(BPF_REG_6),
558 BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
559 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xf),
560 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
561 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
562 /* Subtract it from the packet pointer */
563 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
564 BPF_ALU64_REG(BPF_SUB, BPF_REG_5, BPF_REG_6),
565 /* Create another unknown, (4n)-aligned and >= 74.
566 * That in fact means >= 76, since 74 % 4 == 2
354 */ 567 */
355 "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 568 BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
569 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 76),
570 /* Add it to the packet pointer */
571 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_7),
572 /* Check bounds and perform a read */
573 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
574 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
575 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
576 BPF_EXIT_INSN(),
577 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
578 BPF_EXIT_INSN(),
579 },
580 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
581 .matches = {
582 /* Calculated offset in R6 has unknown value, but known
583 * alignment of 4.
584 */
585 {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
586 {10, "R6=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
587 /* Adding 14 makes R6 be (4n+2) */
588 {11, "R6=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
589 /* Subtracting from packet pointer overflows ubounds */
590 {13, "R5=pkt(id=1,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c))"},
591 /* New unknown value in R7 is (4n), >= 76 */
592 {15, "R7=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
593 /* Adding it to packet pointer gives nice bounds again */
594 {16, "R5=pkt(id=2,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
595 /* At the time the word size load is performed from R5,
596 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
597 * which is 2. Then the variable offset is (4n+2), so
598 * the total offset is 4-byte aligned and meets the
599 * load's requirements.
600 */
601 {20, "R5=pkt(id=2,off=0,r=4,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
356 }, 602 },
357 }, 603 },
358}; 604};
@@ -373,6 +619,9 @@ static int do_test_single(struct bpf_align_test *test)
373{ 619{
374 struct bpf_insn *prog = test->insns; 620 struct bpf_insn *prog = test->insns;
375 int prog_type = test->prog_type; 621 int prog_type = test->prog_type;
622 char bpf_vlog_copy[32768];
623 const char *line_ptr;
624 int cur_line = -1;
376 int prog_len, i; 625 int prog_len, i;
377 int fd_prog; 626 int fd_prog;
378 int ret; 627 int ret;
@@ -381,26 +630,49 @@ static int do_test_single(struct bpf_align_test *test)
381 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 630 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
382 prog, prog_len, 1, "GPL", 0, 631 prog, prog_len, 1, "GPL", 0,
383 bpf_vlog, sizeof(bpf_vlog), 2); 632 bpf_vlog, sizeof(bpf_vlog), 2);
384 if (fd_prog < 0) { 633 if (fd_prog < 0 && test->result != REJECT) {
385 printf("Failed to load program.\n"); 634 printf("Failed to load program.\n");
386 printf("%s", bpf_vlog); 635 printf("%s", bpf_vlog);
387 ret = 1; 636 ret = 1;
637 } else if (fd_prog >= 0 && test->result == REJECT) {
638 printf("Unexpected success to load!\n");
639 printf("%s", bpf_vlog);
640 ret = 1;
641 close(fd_prog);
388 } else { 642 } else {
389 ret = 0; 643 ret = 0;
644 /* We make a local copy so that we can strtok() it */
645 strncpy(bpf_vlog_copy, bpf_vlog, sizeof(bpf_vlog_copy));
646 line_ptr = strtok(bpf_vlog_copy, "\n");
390 for (i = 0; i < MAX_MATCHES; i++) { 647 for (i = 0; i < MAX_MATCHES; i++) {
391 const char *t, *m = test->matches[i]; 648 struct bpf_reg_match m = test->matches[i];
392 649
393 if (!m) 650 if (!m.match)
394 break; 651 break;
395 t = strstr(bpf_vlog, m); 652 while (line_ptr) {
396 if (!t) { 653 cur_line = -1;
397 printf("Failed to find match: %s\n", m); 654 sscanf(line_ptr, "%u: ", &cur_line);
655 if (cur_line == m.line)
656 break;
657 line_ptr = strtok(NULL, "\n");
658 }
659 if (!line_ptr) {
660 printf("Failed to find line %u for match: %s\n",
661 m.line, m.match);
662 ret = 1;
663 printf("%s", bpf_vlog);
664 break;
665 }
666 if (!strstr(line_ptr, m.match)) {
667 printf("Failed to find match %u: %s\n",
668 m.line, m.match);
398 ret = 1; 669 ret = 1;
399 printf("%s", bpf_vlog); 670 printf("%s", bpf_vlog);
400 break; 671 break;
401 } 672 }
402 } 673 }
403 close(fd_prog); 674 if (fd_prog >= 0)
675 close(fd_prog);
404 } 676 }
405 return ret; 677 return ret;
406} 678}
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 79601c81e169..fe3a443a1102 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -22,6 +22,7 @@
22#include <linux/bpf.h> 22#include <linux/bpf.h>
23 23
24#include <bpf/bpf.h> 24#include <bpf/bpf.h>
25#include <bpf/libbpf.h>
25#include "bpf_util.h" 26#include "bpf_util.h"
26 27
27static int map_flags; 28static int map_flags;
@@ -438,6 +439,444 @@ static void test_arraymap_percpu_many_keys(void)
438 close(fd); 439 close(fd);
439} 440}
440 441
442static void test_devmap(int task, void *data)
443{
444 int fd;
445 __u32 key, value;
446
447 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
448 2, 0);
449 if (fd < 0) {
450 printf("Failed to create arraymap '%s'!\n", strerror(errno));
451 exit(1);
452 }
453
454 close(fd);
455}
456
457#include <sys/socket.h>
458#include <sys/ioctl.h>
459#include <arpa/inet.h>
460#include <sys/select.h>
461#include <linux/err.h>
462#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
463#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
464static void test_sockmap(int tasks, void *data)
465{
466 int one = 1, map_fd_rx, map_fd_tx, map_fd_break, s, sc, rc;
467 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break;
468 int ports[] = {50200, 50201, 50202, 50204};
469 int err, i, fd, sfd[6] = {0xdeadbeef};
470 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
471 int parse_prog, verdict_prog;
472 struct sockaddr_in addr;
473 struct bpf_object *obj;
474 struct timeval to;
475 __u32 key, value;
476 pid_t pid[tasks];
477 fd_set w;
478
479 /* Create some sockets to use with sockmap */
480 for (i = 0; i < 2; i++) {
481 sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
482 if (sfd[i] < 0)
483 goto out;
484 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
485 (char *)&one, sizeof(one));
486 if (err) {
487 printf("failed to setsockopt\n");
488 goto out;
489 }
490 err = ioctl(sfd[i], FIONBIO, (char *)&one);
491 if (err < 0) {
492 printf("failed to ioctl\n");
493 goto out;
494 }
495 memset(&addr, 0, sizeof(struct sockaddr_in));
496 addr.sin_family = AF_INET;
497 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
498 addr.sin_port = htons(ports[i]);
499 err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
500 if (err < 0) {
501 printf("failed to bind: err %i: %i:%i\n",
502 err, i, sfd[i]);
503 goto out;
504 }
505 err = listen(sfd[i], 32);
506 if (err < 0) {
507 printf("failed to listen\n");
508 goto out;
509 }
510 }
511
512 for (i = 2; i < 4; i++) {
513 sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
514 if (sfd[i] < 0)
515 goto out;
516 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
517 (char *)&one, sizeof(one));
518 if (err) {
519 printf("set sock opt\n");
520 goto out;
521 }
522 memset(&addr, 0, sizeof(struct sockaddr_in));
523 addr.sin_family = AF_INET;
524 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
525 addr.sin_port = htons(ports[i - 2]);
526 err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
527 if (err) {
528 printf("failed to connect\n");
529 goto out;
530 }
531 }
532
533
534 for (i = 4; i < 6; i++) {
535 sfd[i] = accept(sfd[i - 4], NULL, NULL);
536 if (sfd[i] < 0) {
537 printf("accept failed\n");
538 goto out;
539 }
540 }
541
542 /* Test sockmap with connected sockets */
543 fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
544 sizeof(key), sizeof(value),
545 6, 0);
546 if (fd < 0) {
547 printf("Failed to create sockmap %i\n", fd);
548 goto out_sockmap;
549 }
550
551 /* Test update without programs */
552 for (i = 0; i < 6; i++) {
553 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
554 if (err) {
555 printf("Failed noprog update sockmap '%i:%i'\n",
556 i, sfd[i]);
557 goto out_sockmap;
558 }
559 }
560
561 /* Test attaching/detaching bad fds */
562 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
563 if (!err) {
564 printf("Failed invalid parser prog attach\n");
565 goto out_sockmap;
566 }
567
568 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
569 if (!err) {
570 printf("Failed invalid verdict prog attach\n");
571 goto out_sockmap;
572 }
573
574 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
575 if (!err) {
576 printf("Failed unknown prog attach\n");
577 goto out_sockmap;
578 }
579
580 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
581 if (err) {
582 printf("Failed empty parser prog detach\n");
583 goto out_sockmap;
584 }
585
586 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
587 if (err) {
588 printf("Failed empty verdict prog detach\n");
589 goto out_sockmap;
590 }
591
592 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
593 if (!err) {
594 printf("Detach invalid prog successful\n");
595 goto out_sockmap;
596 }
597
598 /* Load SK_SKB program and Attach */
599 err = bpf_prog_load(SOCKMAP_PARSE_PROG,
600 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
601 if (err) {
602 printf("Failed to load SK_SKB parse prog\n");
603 goto out_sockmap;
604 }
605
606 err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
607 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
608 if (err) {
609 printf("Failed to load SK_SKB verdict prog\n");
610 goto out_sockmap;
611 }
612
613 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
614 if (IS_ERR(bpf_map_rx)) {
615 printf("Failed to load map rx from verdict prog\n");
616 goto out_sockmap;
617 }
618
619 map_fd_rx = bpf_map__fd(bpf_map_rx);
620 if (map_fd_rx < 0) {
621 printf("Failed to get map fd\n");
622 goto out_sockmap;
623 }
624
625 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
626 if (IS_ERR(bpf_map_tx)) {
627 printf("Failed to load map tx from verdict prog\n");
628 goto out_sockmap;
629 }
630
631 map_fd_tx = bpf_map__fd(bpf_map_tx);
632 if (map_fd_tx < 0) {
633 printf("Failed to get map tx fd\n");
634 goto out_sockmap;
635 }
636
637 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
638 if (IS_ERR(bpf_map_break)) {
639 printf("Failed to load map tx from verdict prog\n");
640 goto out_sockmap;
641 }
642
643 map_fd_break = bpf_map__fd(bpf_map_break);
644 if (map_fd_break < 0) {
645 printf("Failed to get map tx fd\n");
646 goto out_sockmap;
647 }
648
649 err = bpf_prog_attach(parse_prog, map_fd_break,
650 BPF_SK_SKB_STREAM_PARSER, 0);
651 if (!err) {
652 printf("Allowed attaching SK_SKB program to invalid map\n");
653 goto out_sockmap;
654 }
655
656 err = bpf_prog_attach(parse_prog, map_fd_rx,
657 BPF_SK_SKB_STREAM_PARSER, 0);
658 if (err) {
659 printf("Failed stream parser bpf prog attach\n");
660 goto out_sockmap;
661 }
662
663 err = bpf_prog_attach(verdict_prog, map_fd_rx,
664 BPF_SK_SKB_STREAM_VERDICT, 0);
665 if (err) {
666 printf("Failed stream verdict bpf prog attach\n");
667 goto out_sockmap;
668 }
669
670 err = bpf_prog_attach(verdict_prog, map_fd_rx,
671 __MAX_BPF_ATTACH_TYPE, 0);
672 if (!err) {
673 printf("Attached unknown bpf prog\n");
674 goto out_sockmap;
675 }
676
677 /* Test map update elem afterwards fd lives in fd and map_fd */
678 for (i = 0; i < 6; i++) {
679 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
680 if (err) {
681 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
682 err, i, sfd[i]);
683 goto out_sockmap;
684 }
685 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
686 if (err) {
687 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
688 err, i, sfd[i]);
689 goto out_sockmap;
690 }
691 }
692
693 /* Test map delete elem and remove send/recv sockets */
694 for (i = 2; i < 4; i++) {
695 err = bpf_map_delete_elem(map_fd_rx, &i);
696 if (err) {
697 printf("Failed delete sockmap rx %i '%i:%i'\n",
698 err, i, sfd[i]);
699 goto out_sockmap;
700 }
701 err = bpf_map_delete_elem(map_fd_tx, &i);
702 if (err) {
703 printf("Failed delete sockmap tx %i '%i:%i'\n",
704 err, i, sfd[i]);
705 goto out_sockmap;
706 }
707 }
708
709 /* Test map send/recv */
710 for (i = 0; i < 2; i++) {
711 buf[0] = i;
712 buf[1] = 0x5;
713 sc = send(sfd[2], buf, 20, 0);
714 if (sc < 0) {
715 printf("Failed sockmap send\n");
716 goto out_sockmap;
717 }
718
719 FD_ZERO(&w);
720 FD_SET(sfd[3], &w);
721 to.tv_sec = 1;
722 to.tv_usec = 0;
723 s = select(sfd[3] + 1, &w, NULL, NULL, &to);
724 if (s == -1) {
725 perror("Failed sockmap select()");
726 goto out_sockmap;
727 } else if (!s) {
728 printf("Failed sockmap unexpected timeout\n");
729 goto out_sockmap;
730 }
731
732 if (!FD_ISSET(sfd[3], &w)) {
733 printf("Failed sockmap select/recv\n");
734 goto out_sockmap;
735 }
736
737 rc = recv(sfd[3], buf, sizeof(buf), 0);
738 if (rc < 0) {
739 printf("Failed sockmap recv\n");
740 goto out_sockmap;
741 }
742 }
743
744 /* Negative null entry lookup from datapath should be dropped */
745 buf[0] = 1;
746 buf[1] = 12;
747 sc = send(sfd[2], buf, 20, 0);
748 if (sc < 0) {
749 printf("Failed sockmap send\n");
750 goto out_sockmap;
751 }
752
753 /* Push fd into same slot */
754 i = 2;
755 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
756 if (!err) {
757 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
758 goto out_sockmap;
759 }
760
761 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
762 if (err) {
763 printf("Failed sockmap update new slot BPF_ANY\n");
764 goto out_sockmap;
765 }
766
767 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
768 if (err) {
769 printf("Failed sockmap update new slot BPF_EXIST\n");
770 goto out_sockmap;
771 }
772
773 /* Delete the elems without programs */
774 for (i = 0; i < 6; i++) {
775 err = bpf_map_delete_elem(fd, &i);
776 if (err) {
777 printf("Failed delete sockmap %i '%i:%i'\n",
778 err, i, sfd[i]);
779 }
780 }
781
782 /* Test having multiple maps open and set with programs on same fds */
783 err = bpf_prog_attach(parse_prog, fd,
784 BPF_SK_SKB_STREAM_PARSER, 0);
785 if (err) {
786 printf("Failed fd bpf parse prog attach\n");
787 goto out_sockmap;
788 }
789 err = bpf_prog_attach(verdict_prog, fd,
790 BPF_SK_SKB_STREAM_VERDICT, 0);
791 if (err) {
792 printf("Failed fd bpf verdict prog attach\n");
793 goto out_sockmap;
794 }
795
796 for (i = 4; i < 6; i++) {
797 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
798 if (!err) {
799 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
800 err, i, sfd[i]);
801 goto out_sockmap;
802 }
803 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
804 if (!err) {
805 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n",
806 err, i, sfd[i]);
807 goto out_sockmap;
808 }
809 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
810 if (!err) {
811 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n",
812 err, i, sfd[i]);
813 goto out_sockmap;
814 }
815 }
816
817 /* Test tasks number of forked operations */
818 for (i = 0; i < tasks; i++) {
819 pid[i] = fork();
820 if (pid[i] == 0) {
821 for (i = 0; i < 6; i++) {
822 bpf_map_delete_elem(map_fd_tx, &i);
823 bpf_map_delete_elem(map_fd_rx, &i);
824 bpf_map_update_elem(map_fd_tx, &i,
825 &sfd[i], BPF_ANY);
826 bpf_map_update_elem(map_fd_rx, &i,
827 &sfd[i], BPF_ANY);
828 }
829 exit(0);
830 } else if (pid[i] == -1) {
831 printf("Couldn't spawn #%d process!\n", i);
832 exit(1);
833 }
834 }
835
836 for (i = 0; i < tasks; i++) {
837 int status;
838
839 assert(waitpid(pid[i], &status, 0) == pid[i]);
840 assert(status == 0);
841 }
842
843 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
844 if (!err) {
845 printf("Detached an invalid prog type.\n");
846 goto out_sockmap;
847 }
848
849 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
850 if (err) {
851 printf("Failed parser prog detach\n");
852 goto out_sockmap;
853 }
854
855 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
856 if (err) {
857 printf("Failed parser prog detach\n");
858 goto out_sockmap;
859 }
860
861 /* Test map close sockets */
862 for (i = 0; i < 6; i++)
863 close(sfd[i]);
864 close(fd);
865 close(map_fd_rx);
866 bpf_object__close(obj);
867 return;
868out:
869 for (i = 0; i < 6; i++)
870 close(sfd[i]);
871 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
872 exit(1);
873out_sockmap:
874 for (i = 0; i < 6; i++)
875 close(sfd[i]);
876 close(fd);
877 exit(1);
878}
879
441#define MAP_SIZE (32 * 1024) 880#define MAP_SIZE (32 * 1024)
442 881
443static void test_map_large(void) 882static void test_map_large(void)
@@ -605,6 +1044,9 @@ static void run_all_tests(void)
605 1044
606 test_arraymap_percpu_many_keys(); 1045 test_arraymap_percpu_many_keys();
607 1046
1047 test_devmap(0, NULL);
1048 test_sockmap(0, NULL);
1049
608 test_map_large(); 1050 test_map_large();
609 test_map_parallel(); 1051 test_map_parallel();
610 test_map_stress(); 1052 test_map_stress();
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 1f7dd35551b9..11ee25cea227 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -75,39 +75,6 @@ static struct {
75 __ret; \ 75 __ret; \
76}) 76})
77 77
78static int bpf_prog_load(const char *file, enum bpf_prog_type type,
79 struct bpf_object **pobj, int *prog_fd)
80{
81 struct bpf_program *prog;
82 struct bpf_object *obj;
83 int err;
84
85 obj = bpf_object__open(file);
86 if (IS_ERR(obj)) {
87 error_cnt++;
88 return -ENOENT;
89 }
90
91 prog = bpf_program__next(NULL, obj);
92 if (!prog) {
93 bpf_object__close(obj);
94 error_cnt++;
95 return -ENOENT;
96 }
97
98 bpf_program__set_type(prog, type);
99 err = bpf_object__load(obj);
100 if (err) {
101 bpf_object__close(obj);
102 error_cnt++;
103 return -EINVAL;
104 }
105
106 *pobj = obj;
107 *prog_fd = bpf_program__fd(prog);
108 return 0;
109}
110
111static int bpf_find_map(const char *test, struct bpf_object *obj, 78static int bpf_find_map(const char *test, struct bpf_object *obj,
112 const char *name) 79 const char *name)
113{ 80{
@@ -130,8 +97,10 @@ static void test_pkt_access(void)
130 int err, prog_fd; 97 int err, prog_fd;
131 98
132 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 99 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
133 if (err) 100 if (err) {
101 error_cnt++;
134 return; 102 return;
103 }
135 104
136 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4), 105 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
137 NULL, NULL, &retval, &duration); 106 NULL, NULL, &retval, &duration);
@@ -162,8 +131,10 @@ static void test_xdp(void)
162 int err, prog_fd, map_fd; 131 int err, prog_fd, map_fd;
163 132
164 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); 133 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
165 if (err) 134 if (err) {
135 error_cnt++;
166 return; 136 return;
137 }
167 138
168 map_fd = bpf_find_map(__func__, obj, "vip2tnl"); 139 map_fd = bpf_find_map(__func__, obj, "vip2tnl");
169 if (map_fd < 0) 140 if (map_fd < 0)
@@ -223,8 +194,10 @@ static void test_l4lb(void)
223 u32 *magic = (u32 *)buf; 194 u32 *magic = (u32 *)buf;
224 195
225 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 196 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
226 if (err) 197 if (err) {
198 error_cnt++;
227 return; 199 return;
200 }
228 201
229 map_fd = bpf_find_map(__func__, obj, "vip_map"); 202 map_fd = bpf_find_map(__func__, obj, "vip_map");
230 if (map_fd < 0) 203 if (map_fd < 0)
@@ -280,8 +253,10 @@ static void test_tcp_estats(void)
280 253
281 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd); 254 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
282 CHECK(err, "", "err %d errno %d\n", err, errno); 255 CHECK(err, "", "err %d errno %d\n", err, errno);
283 if (err) 256 if (err) {
257 error_cnt++;
284 return; 258 return;
259 }
285 260
286 bpf_object__close(obj); 261 bpf_object__close(obj);
287} 262}
@@ -304,7 +279,7 @@ static void test_bpf_obj_id(void)
304 /* +1 to test for the info_len returned by kernel */ 279 /* +1 to test for the info_len returned by kernel */
305 struct bpf_prog_info prog_infos[nr_iters + 1]; 280 struct bpf_prog_info prog_infos[nr_iters + 1];
306 struct bpf_map_info map_infos[nr_iters + 1]; 281 struct bpf_map_info map_infos[nr_iters + 1];
307 char jited_insns[128], xlated_insns[128]; 282 char jited_insns[128], xlated_insns[128], zeros[128];
308 __u32 i, next_id, info_len, nr_id_found, duration = 0; 283 __u32 i, next_id, info_len, nr_id_found, duration = 0;
309 int sysctl_fd, jit_enabled = 0, err = 0; 284 int sysctl_fd, jit_enabled = 0, err = 0;
310 __u64 array_value; 285 __u64 array_value;
@@ -330,17 +305,22 @@ static void test_bpf_obj_id(void)
330 objs[i] = NULL; 305 objs[i] = NULL;
331 306
332 /* Check bpf_obj_get_info_by_fd() */ 307 /* Check bpf_obj_get_info_by_fd() */
308 bzero(zeros, sizeof(zeros));
333 for (i = 0; i < nr_iters; i++) { 309 for (i = 0; i < nr_iters; i++) {
334 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER, 310 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
335 &objs[i], &prog_fds[i]); 311 &objs[i], &prog_fds[i]);
336 /* test_obj_id.o is a dumb prog. It should never fail 312 /* test_obj_id.o is a dumb prog. It should never fail
337 * to load. 313 * to load.
338 */ 314 */
315 if (err)
316 error_cnt++;
339 assert(!err); 317 assert(!err);
340 318
341 /* Check getting prog info */ 319 /* Check getting prog info */
342 info_len = sizeof(struct bpf_prog_info) * 2; 320 info_len = sizeof(struct bpf_prog_info) * 2;
343 bzero(&prog_infos[i], info_len); 321 bzero(&prog_infos[i], info_len);
322 bzero(jited_insns, sizeof(jited_insns));
323 bzero(xlated_insns, sizeof(xlated_insns));
344 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns); 324 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
345 prog_infos[i].jited_prog_len = sizeof(jited_insns); 325 prog_infos[i].jited_prog_len = sizeof(jited_insns);
346 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns); 326 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
@@ -351,15 +331,20 @@ static void test_bpf_obj_id(void)
351 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER || 331 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
352 info_len != sizeof(struct bpf_prog_info) || 332 info_len != sizeof(struct bpf_prog_info) ||
353 (jit_enabled && !prog_infos[i].jited_prog_len) || 333 (jit_enabled && !prog_infos[i].jited_prog_len) ||
354 !prog_infos[i].xlated_prog_len, 334 (jit_enabled &&
335 !memcmp(jited_insns, zeros, sizeof(zeros))) ||
336 !prog_infos[i].xlated_prog_len ||
337 !memcmp(xlated_insns, zeros, sizeof(zeros)),
355 "get-prog-info(fd)", 338 "get-prog-info(fd)",
356 "err %d errno %d i %d type %d(%d) info_len %u(%lu) jit_enabled %d jited_prog_len %u xlated_prog_len %u\n", 339 "err %d errno %d i %d type %d(%d) info_len %u(%lu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d\n",
357 err, errno, i, 340 err, errno, i,
358 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER, 341 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
359 info_len, sizeof(struct bpf_prog_info), 342 info_len, sizeof(struct bpf_prog_info),
360 jit_enabled, 343 jit_enabled,
361 prog_infos[i].jited_prog_len, 344 prog_infos[i].jited_prog_len,
362 prog_infos[i].xlated_prog_len)) 345 prog_infos[i].xlated_prog_len,
346 !!memcmp(jited_insns, zeros, sizeof(zeros)),
347 !!memcmp(xlated_insns, zeros, sizeof(zeros))))
363 goto done; 348 goto done;
364 349
365 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id"); 350 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
@@ -496,8 +481,10 @@ static void test_pkt_md_access(void)
496 int err, prog_fd; 481 int err, prog_fd;
497 482
498 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 483 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
499 if (err) 484 if (err) {
485 error_cnt++;
500 return; 486 return;
487 }
501 488
502 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4), 489 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
503 NULL, NULL, &retval, &duration); 490 NULL, NULL, &retval, &duration);
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index d3ed7324105e..26f3250bdcd2 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -422,7 +422,7 @@ static struct bpf_test tests[] = {
422 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 422 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
423 BPF_EXIT_INSN(), 423 BPF_EXIT_INSN(),
424 }, 424 },
425 .errstr_unpriv = "R1 pointer arithmetic", 425 .errstr_unpriv = "R1 subtraction from stack pointer",
426 .result_unpriv = REJECT, 426 .result_unpriv = REJECT,
427 .errstr = "R1 invalid mem access", 427 .errstr = "R1 invalid mem access",
428 .result = REJECT, 428 .result = REJECT,
@@ -604,8 +604,9 @@ static struct bpf_test tests[] = {
604 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4), 604 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
605 BPF_EXIT_INSN(), 605 BPF_EXIT_INSN(),
606 }, 606 },
607 .errstr = "misaligned access", 607 .errstr = "misaligned stack access",
608 .result = REJECT, 608 .result = REJECT,
609 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
609 }, 610 },
610 { 611 {
611 "invalid map_fd for function call", 612 "invalid map_fd for function call",
@@ -651,8 +652,9 @@ static struct bpf_test tests[] = {
651 BPF_EXIT_INSN(), 652 BPF_EXIT_INSN(),
652 }, 653 },
653 .fixup_map1 = { 3 }, 654 .fixup_map1 = { 3 },
654 .errstr = "misaligned access", 655 .errstr = "misaligned value access",
655 .result = REJECT, 656 .result = REJECT,
657 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
656 }, 658 },
657 { 659 {
658 "sometimes access memory with incorrect alignment", 660 "sometimes access memory with incorrect alignment",
@@ -673,6 +675,7 @@ static struct bpf_test tests[] = {
673 .errstr = "R0 invalid mem access", 675 .errstr = "R0 invalid mem access",
674 .errstr_unpriv = "R0 leaks addr", 676 .errstr_unpriv = "R0 leaks addr",
675 .result = REJECT, 677 .result = REJECT,
678 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
676 }, 679 },
677 { 680 {
678 "jump test 1", 681 "jump test 1",
@@ -964,6 +967,256 @@ static struct bpf_test tests[] = {
964 .result = REJECT, 967 .result = REJECT,
965 }, 968 },
966 { 969 {
970 "invalid access __sk_buff family",
971 .insns = {
972 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
973 offsetof(struct __sk_buff, family)),
974 BPF_EXIT_INSN(),
975 },
976 .errstr = "invalid bpf_context access",
977 .result = REJECT,
978 },
979 {
980 "invalid access __sk_buff remote_ip4",
981 .insns = {
982 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
983 offsetof(struct __sk_buff, remote_ip4)),
984 BPF_EXIT_INSN(),
985 },
986 .errstr = "invalid bpf_context access",
987 .result = REJECT,
988 },
989 {
990 "invalid access __sk_buff local_ip4",
991 .insns = {
992 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
993 offsetof(struct __sk_buff, local_ip4)),
994 BPF_EXIT_INSN(),
995 },
996 .errstr = "invalid bpf_context access",
997 .result = REJECT,
998 },
999 {
1000 "invalid access __sk_buff remote_ip6",
1001 .insns = {
1002 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1003 offsetof(struct __sk_buff, remote_ip6)),
1004 BPF_EXIT_INSN(),
1005 },
1006 .errstr = "invalid bpf_context access",
1007 .result = REJECT,
1008 },
1009 {
1010 "invalid access __sk_buff local_ip6",
1011 .insns = {
1012 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1013 offsetof(struct __sk_buff, local_ip6)),
1014 BPF_EXIT_INSN(),
1015 },
1016 .errstr = "invalid bpf_context access",
1017 .result = REJECT,
1018 },
1019 {
1020 "invalid access __sk_buff remote_port",
1021 .insns = {
1022 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1023 offsetof(struct __sk_buff, remote_port)),
1024 BPF_EXIT_INSN(),
1025 },
1026 .errstr = "invalid bpf_context access",
1027 .result = REJECT,
1028 },
1029 {
1030 "invalid access __sk_buff remote_port",
1031 .insns = {
1032 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1033 offsetof(struct __sk_buff, local_port)),
1034 BPF_EXIT_INSN(),
1035 },
1036 .errstr = "invalid bpf_context access",
1037 .result = REJECT,
1038 },
1039 {
1040 "valid access __sk_buff family",
1041 .insns = {
1042 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1043 offsetof(struct __sk_buff, family)),
1044 BPF_EXIT_INSN(),
1045 },
1046 .result = ACCEPT,
1047 .prog_type = BPF_PROG_TYPE_SK_SKB,
1048 },
1049 {
1050 "valid access __sk_buff remote_ip4",
1051 .insns = {
1052 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1053 offsetof(struct __sk_buff, remote_ip4)),
1054 BPF_EXIT_INSN(),
1055 },
1056 .result = ACCEPT,
1057 .prog_type = BPF_PROG_TYPE_SK_SKB,
1058 },
1059 {
1060 "valid access __sk_buff local_ip4",
1061 .insns = {
1062 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1063 offsetof(struct __sk_buff, local_ip4)),
1064 BPF_EXIT_INSN(),
1065 },
1066 .result = ACCEPT,
1067 .prog_type = BPF_PROG_TYPE_SK_SKB,
1068 },
1069 {
1070 "valid access __sk_buff remote_ip6",
1071 .insns = {
1072 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1073 offsetof(struct __sk_buff, remote_ip6[0])),
1074 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1075 offsetof(struct __sk_buff, remote_ip6[1])),
1076 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1077 offsetof(struct __sk_buff, remote_ip6[2])),
1078 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1079 offsetof(struct __sk_buff, remote_ip6[3])),
1080 BPF_EXIT_INSN(),
1081 },
1082 .result = ACCEPT,
1083 .prog_type = BPF_PROG_TYPE_SK_SKB,
1084 },
1085 {
1086 "valid access __sk_buff local_ip6",
1087 .insns = {
1088 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1089 offsetof(struct __sk_buff, local_ip6[0])),
1090 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1091 offsetof(struct __sk_buff, local_ip6[1])),
1092 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1093 offsetof(struct __sk_buff, local_ip6[2])),
1094 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1095 offsetof(struct __sk_buff, local_ip6[3])),
1096 BPF_EXIT_INSN(),
1097 },
1098 .result = ACCEPT,
1099 .prog_type = BPF_PROG_TYPE_SK_SKB,
1100 },
1101 {
1102 "valid access __sk_buff remote_port",
1103 .insns = {
1104 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1105 offsetof(struct __sk_buff, remote_port)),
1106 BPF_EXIT_INSN(),
1107 },
1108 .result = ACCEPT,
1109 .prog_type = BPF_PROG_TYPE_SK_SKB,
1110 },
1111 {
1112 "valid access __sk_buff remote_port",
1113 .insns = {
1114 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1115 offsetof(struct __sk_buff, local_port)),
1116 BPF_EXIT_INSN(),
1117 },
1118 .result = ACCEPT,
1119 .prog_type = BPF_PROG_TYPE_SK_SKB,
1120 },
1121 {
1122 "invalid access of tc_classid for SK_SKB",
1123 .insns = {
1124 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1125 offsetof(struct __sk_buff, tc_classid)),
1126 BPF_EXIT_INSN(),
1127 },
1128 .result = REJECT,
1129 .prog_type = BPF_PROG_TYPE_SK_SKB,
1130 .errstr = "invalid bpf_context access",
1131 },
1132 {
1133 "check skb->mark is writeable by SK_SKB",
1134 .insns = {
1135 BPF_MOV64_IMM(BPF_REG_0, 0),
1136 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1137 offsetof(struct __sk_buff, mark)),
1138 BPF_EXIT_INSN(),
1139 },
1140 .result = ACCEPT,
1141 .prog_type = BPF_PROG_TYPE_SK_SKB,
1142 },
1143 {
1144 "check skb->tc_index is writeable by SK_SKB",
1145 .insns = {
1146 BPF_MOV64_IMM(BPF_REG_0, 0),
1147 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1148 offsetof(struct __sk_buff, tc_index)),
1149 BPF_EXIT_INSN(),
1150 },
1151 .result = ACCEPT,
1152 .prog_type = BPF_PROG_TYPE_SK_SKB,
1153 },
1154 {
1155 "check skb->priority is writeable by SK_SKB",
1156 .insns = {
1157 BPF_MOV64_IMM(BPF_REG_0, 0),
1158 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1159 offsetof(struct __sk_buff, priority)),
1160 BPF_EXIT_INSN(),
1161 },
1162 .result = ACCEPT,
1163 .prog_type = BPF_PROG_TYPE_SK_SKB,
1164 },
1165 {
1166 "direct packet read for SK_SKB",
1167 .insns = {
1168 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1169 offsetof(struct __sk_buff, data)),
1170 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1171 offsetof(struct __sk_buff, data_end)),
1172 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1173 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1174 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1175 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
1176 BPF_MOV64_IMM(BPF_REG_0, 0),
1177 BPF_EXIT_INSN(),
1178 },
1179 .result = ACCEPT,
1180 .prog_type = BPF_PROG_TYPE_SK_SKB,
1181 },
1182 {
1183 "direct packet write for SK_SKB",
1184 .insns = {
1185 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1186 offsetof(struct __sk_buff, data)),
1187 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1188 offsetof(struct __sk_buff, data_end)),
1189 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1191 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1192 BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
1193 BPF_MOV64_IMM(BPF_REG_0, 0),
1194 BPF_EXIT_INSN(),
1195 },
1196 .result = ACCEPT,
1197 .prog_type = BPF_PROG_TYPE_SK_SKB,
1198 },
1199 {
1200 "overlapping checks for direct packet access SK_SKB",
1201 .insns = {
1202 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1203 offsetof(struct __sk_buff, data)),
1204 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1205 offsetof(struct __sk_buff, data_end)),
1206 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1207 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1208 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 4),
1209 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
1210 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
1211 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
1212 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_2, 6),
1213 BPF_MOV64_IMM(BPF_REG_0, 0),
1214 BPF_EXIT_INSN(),
1215 },
1216 .result = ACCEPT,
1217 .prog_type = BPF_PROG_TYPE_SK_SKB,
1218 },
1219 {
967 "check skb->mark is not writeable by sockets", 1220 "check skb->mark is not writeable by sockets",
968 .insns = { 1221 .insns = {
969 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 1222 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
@@ -1216,8 +1469,9 @@ static struct bpf_test tests[] = {
1216 offsetof(struct __sk_buff, cb[0]) + 1), 1469 offsetof(struct __sk_buff, cb[0]) + 1),
1217 BPF_EXIT_INSN(), 1470 BPF_EXIT_INSN(),
1218 }, 1471 },
1219 .errstr = "misaligned access", 1472 .errstr = "misaligned context access",
1220 .result = REJECT, 1473 .result = REJECT,
1474 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1221 }, 1475 },
1222 { 1476 {
1223 "check __sk_buff->hash, offset 0, half store not permitted", 1477 "check __sk_buff->hash, offset 0, half store not permitted",
@@ -1320,8 +1574,9 @@ static struct bpf_test tests[] = {
1320 offsetof(struct __sk_buff, cb[0]) + 2), 1574 offsetof(struct __sk_buff, cb[0]) + 2),
1321 BPF_EXIT_INSN(), 1575 BPF_EXIT_INSN(),
1322 }, 1576 },
1323 .errstr = "misaligned access", 1577 .errstr = "misaligned context access",
1324 .result = REJECT, 1578 .result = REJECT,
1579 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1325 }, 1580 },
1326 { 1581 {
1327 "check cb access: word, unaligned 2", 1582 "check cb access: word, unaligned 2",
@@ -1331,8 +1586,9 @@ static struct bpf_test tests[] = {
1331 offsetof(struct __sk_buff, cb[4]) + 1), 1586 offsetof(struct __sk_buff, cb[4]) + 1),
1332 BPF_EXIT_INSN(), 1587 BPF_EXIT_INSN(),
1333 }, 1588 },
1334 .errstr = "misaligned access", 1589 .errstr = "misaligned context access",
1335 .result = REJECT, 1590 .result = REJECT,
1591 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1336 }, 1592 },
1337 { 1593 {
1338 "check cb access: word, unaligned 3", 1594 "check cb access: word, unaligned 3",
@@ -1342,8 +1598,9 @@ static struct bpf_test tests[] = {
1342 offsetof(struct __sk_buff, cb[4]) + 2), 1598 offsetof(struct __sk_buff, cb[4]) + 2),
1343 BPF_EXIT_INSN(), 1599 BPF_EXIT_INSN(),
1344 }, 1600 },
1345 .errstr = "misaligned access", 1601 .errstr = "misaligned context access",
1346 .result = REJECT, 1602 .result = REJECT,
1603 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1347 }, 1604 },
1348 { 1605 {
1349 "check cb access: word, unaligned 4", 1606 "check cb access: word, unaligned 4",
@@ -1353,8 +1610,9 @@ static struct bpf_test tests[] = {
1353 offsetof(struct __sk_buff, cb[4]) + 3), 1610 offsetof(struct __sk_buff, cb[4]) + 3),
1354 BPF_EXIT_INSN(), 1611 BPF_EXIT_INSN(),
1355 }, 1612 },
1356 .errstr = "misaligned access", 1613 .errstr = "misaligned context access",
1357 .result = REJECT, 1614 .result = REJECT,
1615 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1358 }, 1616 },
1359 { 1617 {
1360 "check cb access: double", 1618 "check cb access: double",
@@ -1380,8 +1638,9 @@ static struct bpf_test tests[] = {
1380 offsetof(struct __sk_buff, cb[1])), 1638 offsetof(struct __sk_buff, cb[1])),
1381 BPF_EXIT_INSN(), 1639 BPF_EXIT_INSN(),
1382 }, 1640 },
1383 .errstr = "misaligned access", 1641 .errstr = "misaligned context access",
1384 .result = REJECT, 1642 .result = REJECT,
1643 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1385 }, 1644 },
1386 { 1645 {
1387 "check cb access: double, unaligned 2", 1646 "check cb access: double, unaligned 2",
@@ -1391,8 +1650,9 @@ static struct bpf_test tests[] = {
1391 offsetof(struct __sk_buff, cb[3])), 1650 offsetof(struct __sk_buff, cb[3])),
1392 BPF_EXIT_INSN(), 1651 BPF_EXIT_INSN(),
1393 }, 1652 },
1394 .errstr = "misaligned access", 1653 .errstr = "misaligned context access",
1395 .result = REJECT, 1654 .result = REJECT,
1655 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1396 }, 1656 },
1397 { 1657 {
1398 "check cb access: double, oob 1", 1658 "check cb access: double, oob 1",
@@ -1524,7 +1784,8 @@ static struct bpf_test tests[] = {
1524 BPF_EXIT_INSN(), 1784 BPF_EXIT_INSN(),
1525 }, 1785 },
1526 .result = REJECT, 1786 .result = REJECT,
1527 .errstr = "misaligned access off -6 size 8", 1787 .errstr = "misaligned stack access off (0x0; 0x0)+-8+2 size 8",
1788 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1528 }, 1789 },
1529 { 1790 {
1530 "PTR_TO_STACK store/load - bad alignment on reg", 1791 "PTR_TO_STACK store/load - bad alignment on reg",
@@ -1536,7 +1797,8 @@ static struct bpf_test tests[] = {
1536 BPF_EXIT_INSN(), 1797 BPF_EXIT_INSN(),
1537 }, 1798 },
1538 .result = REJECT, 1799 .result = REJECT,
1539 .errstr = "misaligned access off -2 size 8", 1800 .errstr = "misaligned stack access off (0x0; 0x0)+-10+8 size 8",
1801 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1540 }, 1802 },
1541 { 1803 {
1542 "PTR_TO_STACK store/load - out of bounds low", 1804 "PTR_TO_STACK store/load - out of bounds low",
@@ -1580,8 +1842,6 @@ static struct bpf_test tests[] = {
1580 BPF_EXIT_INSN(), 1842 BPF_EXIT_INSN(),
1581 }, 1843 },
1582 .result = ACCEPT, 1844 .result = ACCEPT,
1583 .result_unpriv = REJECT,
1584 .errstr_unpriv = "R1 pointer arithmetic",
1585 }, 1845 },
1586 { 1846 {
1587 "unpriv: add pointer to pointer", 1847 "unpriv: add pointer to pointer",
@@ -1592,7 +1852,7 @@ static struct bpf_test tests[] = {
1592 }, 1852 },
1593 .result = ACCEPT, 1853 .result = ACCEPT,
1594 .result_unpriv = REJECT, 1854 .result_unpriv = REJECT,
1595 .errstr_unpriv = "R1 pointer arithmetic", 1855 .errstr_unpriv = "R1 pointer += pointer",
1596 }, 1856 },
1597 { 1857 {
1598 "unpriv: neg pointer", 1858 "unpriv: neg pointer",
@@ -1933,10 +2193,7 @@ static struct bpf_test tests[] = {
1933 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8), 2193 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
1934 BPF_EXIT_INSN(), 2194 BPF_EXIT_INSN(),
1935 }, 2195 },
1936 .errstr_unpriv = "pointer arithmetic prohibited", 2196 .result = ACCEPT,
1937 .result_unpriv = REJECT,
1938 .errstr = "R1 invalid mem access",
1939 .result = REJECT,
1940 }, 2197 },
1941 { 2198 {
1942 "unpriv: cmp of stack pointer", 2199 "unpriv: cmp of stack pointer",
@@ -2000,7 +2257,7 @@ static struct bpf_test tests[] = {
2000 BPF_EXIT_INSN(), 2257 BPF_EXIT_INSN(),
2001 }, 2258 },
2002 .result = REJECT, 2259 .result = REJECT,
2003 .errstr = "invalid stack type R3", 2260 .errstr = "R4 min value is negative",
2004 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2261 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2005 }, 2262 },
2006 { 2263 {
@@ -2017,7 +2274,7 @@ static struct bpf_test tests[] = {
2017 BPF_EXIT_INSN(), 2274 BPF_EXIT_INSN(),
2018 }, 2275 },
2019 .result = REJECT, 2276 .result = REJECT,
2020 .errstr = "invalid stack type R3", 2277 .errstr = "R4 min value is negative",
2021 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2278 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2022 }, 2279 },
2023 { 2280 {
@@ -2219,7 +2476,7 @@ static struct bpf_test tests[] = {
2219 BPF_EXIT_INSN(), 2476 BPF_EXIT_INSN(),
2220 }, 2477 },
2221 .result = REJECT, 2478 .result = REJECT,
2222 .errstr = "invalid stack type R3 off=-1 access_size=-1", 2479 .errstr = "R4 min value is negative",
2223 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2480 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2224 }, 2481 },
2225 { 2482 {
@@ -2236,7 +2493,7 @@ static struct bpf_test tests[] = {
2236 BPF_EXIT_INSN(), 2493 BPF_EXIT_INSN(),
2237 }, 2494 },
2238 .result = REJECT, 2495 .result = REJECT,
2239 .errstr = "invalid stack type R3 off=-1 access_size=2147483647", 2496 .errstr = "R4 unbounded memory access, use 'var &= const' or 'if (var < const)'",
2240 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2497 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2241 }, 2498 },
2242 { 2499 {
@@ -2253,7 +2510,7 @@ static struct bpf_test tests[] = {
2253 BPF_EXIT_INSN(), 2510 BPF_EXIT_INSN(),
2254 }, 2511 },
2255 .result = REJECT, 2512 .result = REJECT,
2256 .errstr = "invalid stack type R3 off=-512 access_size=2147483647", 2513 .errstr = "R4 unbounded memory access, use 'var &= const' or 'if (var < const)'",
2257 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2514 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2258 }, 2515 },
2259 { 2516 {
@@ -2324,8 +2581,8 @@ static struct bpf_test tests[] = {
2324 offsetof(struct __sk_buff, data)), 2581 offsetof(struct __sk_buff, data)),
2325 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4), 2582 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4),
2326 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1), 2583 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
2327 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 48), 2584 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 49),
2328 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 48), 2585 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 49),
2329 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2), 2586 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2),
2330 BPF_MOV64_REG(BPF_REG_2, BPF_REG_3), 2587 BPF_MOV64_REG(BPF_REG_2, BPF_REG_3),
2331 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8), 2588 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8),
@@ -2653,7 +2910,7 @@ static struct bpf_test tests[] = {
2653 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 2910 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
2654 BPF_JMP_A(-6), 2911 BPF_JMP_A(-6),
2655 }, 2912 },
2656 .errstr = "misaligned packet access off 2+15+-4 size 4", 2913 .errstr = "misaligned packet access off 2+(0x0; 0x0)+15+-4 size 4",
2657 .result = REJECT, 2914 .result = REJECT,
2658 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2915 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2659 .flags = F_LOAD_WITH_STRICT_ALIGNMENT, 2916 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
@@ -2704,11 +2961,11 @@ static struct bpf_test tests[] = {
2704 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff), 2961 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff),
2705 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), 2962 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
2706 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 2963 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
2707 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff), 2964 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0x7fff),
2708 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), 2965 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2709 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 2966 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2710 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4), 2967 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2711 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1), 2968 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0x7fff - 1),
2712 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1), 2969 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
2713 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0), 2970 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2714 BPF_MOV64_IMM(BPF_REG_0, 0), 2971 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2730,10 +2987,10 @@ static struct bpf_test tests[] = {
2730 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), 2987 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2731 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_4, -8), 2988 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_4, -8),
2732 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8), 2989 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2733 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0xffff), 2990 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0x7fff),
2734 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 2991 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2735 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4), 2992 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2736 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1), 2993 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0x7fff - 1),
2737 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1), 2994 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
2738 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0), 2995 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2739 BPF_MOV64_IMM(BPF_REG_0, 0), 2996 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2759,7 +3016,7 @@ static struct bpf_test tests[] = {
2759 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), 3016 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2760 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8), 3017 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8),
2761 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8), 3018 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2762 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 48), 3019 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 49),
2763 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 3020 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2764 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), 3021 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
2765 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2), 3022 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
@@ -2796,7 +3053,7 @@ static struct bpf_test tests[] = {
2796 }, 3053 },
2797 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3054 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2798 .result = REJECT, 3055 .result = REJECT,
2799 .errstr = "cannot add integer value with 47 upper zero bits to ptr_to_packet", 3056 .errstr = "invalid access to packet, off=0 size=8, R5(id=1,off=0,r=0)",
2800 }, 3057 },
2801 { 3058 {
2802 "direct packet access: test24 (x += pkt_ptr, 5)", 3059 "direct packet access: test24 (x += pkt_ptr, 5)",
@@ -2814,7 +3071,7 @@ static struct bpf_test tests[] = {
2814 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4), 3071 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4),
2815 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), 3072 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
2816 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0), 3073 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
2817 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0xffff - 1), 3074 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7fff - 1),
2818 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1), 3075 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
2819 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0), 3076 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0),
2820 BPF_MOV64_IMM(BPF_REG_0, 0), 3077 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2824,6 +3081,79 @@ static struct bpf_test tests[] = {
2824 .result = ACCEPT, 3081 .result = ACCEPT,
2825 }, 3082 },
2826 { 3083 {
3084 "direct packet access: test25 (marking on <, good access)",
3085 .insns = {
3086 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3087 offsetof(struct __sk_buff, data)),
3088 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3089 offsetof(struct __sk_buff, data_end)),
3090 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3091 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3092 BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_3, 2),
3093 BPF_MOV64_IMM(BPF_REG_0, 0),
3094 BPF_EXIT_INSN(),
3095 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3096 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
3097 },
3098 .result = ACCEPT,
3099 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3100 },
3101 {
3102 "direct packet access: test26 (marking on <, bad access)",
3103 .insns = {
3104 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3105 offsetof(struct __sk_buff, data)),
3106 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3107 offsetof(struct __sk_buff, data_end)),
3108 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3109 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3110 BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_3, 3),
3111 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3112 BPF_MOV64_IMM(BPF_REG_0, 0),
3113 BPF_EXIT_INSN(),
3114 BPF_JMP_IMM(BPF_JA, 0, 0, -3),
3115 },
3116 .result = REJECT,
3117 .errstr = "invalid access to packet",
3118 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3119 },
3120 {
3121 "direct packet access: test27 (marking on <=, good access)",
3122 .insns = {
3123 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3124 offsetof(struct __sk_buff, data)),
3125 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3126 offsetof(struct __sk_buff, data_end)),
3127 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3128 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3129 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_0, 1),
3130 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3131 BPF_MOV64_IMM(BPF_REG_0, 1),
3132 BPF_EXIT_INSN(),
3133 },
3134 .result = ACCEPT,
3135 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3136 },
3137 {
3138 "direct packet access: test28 (marking on <=, bad access)",
3139 .insns = {
3140 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3141 offsetof(struct __sk_buff, data)),
3142 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3143 offsetof(struct __sk_buff, data_end)),
3144 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3145 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3146 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_0, 2),
3147 BPF_MOV64_IMM(BPF_REG_0, 1),
3148 BPF_EXIT_INSN(),
3149 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3150 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
3151 },
3152 .result = REJECT,
3153 .errstr = "invalid access to packet",
3154 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3155 },
3156 {
2827 "helper access to packet: test1, valid packet_ptr range", 3157 "helper access to packet: test1, valid packet_ptr range",
2828 .insns = { 3158 .insns = {
2829 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 3159 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -3113,7 +3443,7 @@ static struct bpf_test tests[] = {
3113 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3443 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3114 }, 3444 },
3115 { 3445 {
3116 "helper access to packet: test14, cls helper fail sub", 3446 "helper access to packet: test14, cls helper ok sub",
3117 .insns = { 3447 .insns = {
3118 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3448 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3119 offsetof(struct __sk_buff, data)), 3449 offsetof(struct __sk_buff, data)),
@@ -3133,12 +3463,36 @@ static struct bpf_test tests[] = {
3133 BPF_MOV64_IMM(BPF_REG_0, 0), 3463 BPF_MOV64_IMM(BPF_REG_0, 0),
3134 BPF_EXIT_INSN(), 3464 BPF_EXIT_INSN(),
3135 }, 3465 },
3466 .result = ACCEPT,
3467 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3468 },
3469 {
3470 "helper access to packet: test15, cls helper fail sub",
3471 .insns = {
3472 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3473 offsetof(struct __sk_buff, data)),
3474 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
3475 offsetof(struct __sk_buff, data_end)),
3476 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
3477 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
3478 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
3479 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
3480 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 12),
3481 BPF_MOV64_IMM(BPF_REG_2, 4),
3482 BPF_MOV64_IMM(BPF_REG_3, 0),
3483 BPF_MOV64_IMM(BPF_REG_4, 0),
3484 BPF_MOV64_IMM(BPF_REG_5, 0),
3485 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3486 BPF_FUNC_csum_diff),
3487 BPF_MOV64_IMM(BPF_REG_0, 0),
3488 BPF_EXIT_INSN(),
3489 },
3136 .result = REJECT, 3490 .result = REJECT,
3137 .errstr = "type=inv expected=fp", 3491 .errstr = "invalid access to packet",
3138 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3492 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3139 }, 3493 },
3140 { 3494 {
3141 "helper access to packet: test15, cls helper fail range 1", 3495 "helper access to packet: test16, cls helper fail range 1",
3142 .insns = { 3496 .insns = {
3143 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3497 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3144 offsetof(struct __sk_buff, data)), 3498 offsetof(struct __sk_buff, data)),
@@ -3163,7 +3517,7 @@ static struct bpf_test tests[] = {
3163 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3517 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3164 }, 3518 },
3165 { 3519 {
3166 "helper access to packet: test16, cls helper fail range 2", 3520 "helper access to packet: test17, cls helper fail range 2",
3167 .insns = { 3521 .insns = {
3168 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3522 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3169 offsetof(struct __sk_buff, data)), 3523 offsetof(struct __sk_buff, data)),
@@ -3184,11 +3538,11 @@ static struct bpf_test tests[] = {
3184 BPF_EXIT_INSN(), 3538 BPF_EXIT_INSN(),
3185 }, 3539 },
3186 .result = REJECT, 3540 .result = REJECT,
3187 .errstr = "invalid access to packet", 3541 .errstr = "R2 min value is negative",
3188 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3542 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3189 }, 3543 },
3190 { 3544 {
3191 "helper access to packet: test17, cls helper fail range 3", 3545 "helper access to packet: test18, cls helper fail range 3",
3192 .insns = { 3546 .insns = {
3193 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3547 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3194 offsetof(struct __sk_buff, data)), 3548 offsetof(struct __sk_buff, data)),
@@ -3209,11 +3563,11 @@ static struct bpf_test tests[] = {
3209 BPF_EXIT_INSN(), 3563 BPF_EXIT_INSN(),
3210 }, 3564 },
3211 .result = REJECT, 3565 .result = REJECT,
3212 .errstr = "invalid access to packet", 3566 .errstr = "R2 min value is negative",
3213 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3567 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3214 }, 3568 },
3215 { 3569 {
3216 "helper access to packet: test18, cls helper fail range zero", 3570 "helper access to packet: test19, cls helper fail range zero",
3217 .insns = { 3571 .insns = {
3218 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3572 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3219 offsetof(struct __sk_buff, data)), 3573 offsetof(struct __sk_buff, data)),
@@ -3238,7 +3592,7 @@ static struct bpf_test tests[] = {
3238 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3592 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3239 }, 3593 },
3240 { 3594 {
3241 "helper access to packet: test19, pkt end as input", 3595 "helper access to packet: test20, pkt end as input",
3242 .insns = { 3596 .insns = {
3243 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3597 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3244 offsetof(struct __sk_buff, data)), 3598 offsetof(struct __sk_buff, data)),
@@ -3263,7 +3617,7 @@ static struct bpf_test tests[] = {
3263 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3617 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3264 }, 3618 },
3265 { 3619 {
3266 "helper access to packet: test20, wrong reg", 3620 "helper access to packet: test21, wrong reg",
3267 .insns = { 3621 .insns = {
3268 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3622 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3269 offsetof(struct __sk_buff, data)), 3623 offsetof(struct __sk_buff, data)),
@@ -3323,7 +3677,7 @@ static struct bpf_test tests[] = {
3323 BPF_EXIT_INSN(), 3677 BPF_EXIT_INSN(),
3324 }, 3678 },
3325 .fixup_map2 = { 3 }, 3679 .fixup_map2 = { 3 },
3326 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3680 .errstr_unpriv = "R0 leaks addr",
3327 .result_unpriv = REJECT, 3681 .result_unpriv = REJECT,
3328 .result = ACCEPT, 3682 .result = ACCEPT,
3329 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3683 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3347,7 +3701,7 @@ static struct bpf_test tests[] = {
3347 BPF_EXIT_INSN(), 3701 BPF_EXIT_INSN(),
3348 }, 3702 },
3349 .fixup_map2 = { 3 }, 3703 .fixup_map2 = { 3 },
3350 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3704 .errstr_unpriv = "R0 leaks addr",
3351 .result_unpriv = REJECT, 3705 .result_unpriv = REJECT,
3352 .result = ACCEPT, 3706 .result = ACCEPT,
3353 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3707 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3375,7 +3729,7 @@ static struct bpf_test tests[] = {
3375 BPF_EXIT_INSN(), 3729 BPF_EXIT_INSN(),
3376 }, 3730 },
3377 .fixup_map2 = { 3 }, 3731 .fixup_map2 = { 3 },
3378 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3732 .errstr_unpriv = "R0 leaks addr",
3379 .result_unpriv = REJECT, 3733 .result_unpriv = REJECT,
3380 .result = ACCEPT, 3734 .result = ACCEPT,
3381 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3735 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3416,9 +3770,7 @@ static struct bpf_test tests[] = {
3416 BPF_EXIT_INSN(), 3770 BPF_EXIT_INSN(),
3417 }, 3771 },
3418 .fixup_map2 = { 3 }, 3772 .fixup_map2 = { 3 },
3419 .errstr_unpriv = "R0 pointer arithmetic prohibited",
3420 .errstr = "R0 min value is outside of the array range", 3773 .errstr = "R0 min value is outside of the array range",
3421 .result_unpriv = REJECT,
3422 .result = REJECT, 3774 .result = REJECT,
3423 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3775 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3424 }, 3776 },
@@ -3440,9 +3792,7 @@ static struct bpf_test tests[] = {
3440 BPF_EXIT_INSN(), 3792 BPF_EXIT_INSN(),
3441 }, 3793 },
3442 .fixup_map2 = { 3 }, 3794 .fixup_map2 = { 3 },
3443 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3795 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map",
3444 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
3445 .result_unpriv = REJECT,
3446 .result = REJECT, 3796 .result = REJECT,
3447 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3797 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3448 }, 3798 },
@@ -3456,7 +3806,7 @@ static struct bpf_test tests[] = {
3456 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 3806 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3457 BPF_FUNC_map_lookup_elem), 3807 BPF_FUNC_map_lookup_elem),
3458 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), 3808 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3459 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), 3809 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
3460 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES), 3810 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
3461 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1), 3811 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
3462 BPF_MOV32_IMM(BPF_REG_1, 0), 3812 BPF_MOV32_IMM(BPF_REG_1, 0),
@@ -3467,8 +3817,8 @@ static struct bpf_test tests[] = {
3467 BPF_EXIT_INSN(), 3817 BPF_EXIT_INSN(),
3468 }, 3818 },
3469 .fixup_map2 = { 3 }, 3819 .fixup_map2 = { 3 },
3470 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3820 .errstr_unpriv = "R0 leaks addr",
3471 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3821 .errstr = "R0 unbounded memory access",
3472 .result_unpriv = REJECT, 3822 .result_unpriv = REJECT,
3473 .result = REJECT, 3823 .result = REJECT,
3474 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3824 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3494,7 +3844,7 @@ static struct bpf_test tests[] = {
3494 BPF_EXIT_INSN(), 3844 BPF_EXIT_INSN(),
3495 }, 3845 },
3496 .fixup_map2 = { 3 }, 3846 .fixup_map2 = { 3 },
3497 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3847 .errstr_unpriv = "R0 leaks addr",
3498 .errstr = "invalid access to map value, value_size=48 off=44 size=8", 3848 .errstr = "invalid access to map value, value_size=48 off=44 size=8",
3499 .result_unpriv = REJECT, 3849 .result_unpriv = REJECT,
3500 .result = REJECT, 3850 .result = REJECT,
@@ -3524,8 +3874,8 @@ static struct bpf_test tests[] = {
3524 BPF_EXIT_INSN(), 3874 BPF_EXIT_INSN(),
3525 }, 3875 },
3526 .fixup_map2 = { 3, 11 }, 3876 .fixup_map2 = { 3, 11 },
3527 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3877 .errstr_unpriv = "R0 pointer += pointer",
3528 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3878 .errstr = "R0 invalid mem access 'inv'",
3529 .result_unpriv = REJECT, 3879 .result_unpriv = REJECT,
3530 .result = REJECT, 3880 .result = REJECT,
3531 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3881 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3667,34 +4017,6 @@ static struct bpf_test tests[] = {
3667 .prog_type = BPF_PROG_TYPE_SCHED_CLS 4017 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3668 }, 4018 },
3669 { 4019 {
3670 "multiple registers share map_lookup_elem bad reg type",
3671 .insns = {
3672 BPF_MOV64_IMM(BPF_REG_1, 10),
3673 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
3674 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3675 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3676 BPF_LD_MAP_FD(BPF_REG_1, 0),
3677 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3678 BPF_FUNC_map_lookup_elem),
3679 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
3680 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
3681 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
3682 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
3683 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3684 BPF_MOV64_IMM(BPF_REG_1, 1),
3685 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3686 BPF_MOV64_IMM(BPF_REG_1, 2),
3687 BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 1),
3688 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 0),
3689 BPF_MOV64_IMM(BPF_REG_1, 3),
3690 BPF_EXIT_INSN(),
3691 },
3692 .fixup_map1 = { 4 },
3693 .result = REJECT,
3694 .errstr = "R3 invalid mem access 'inv'",
3695 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3696 },
3697 {
3698 "invalid map access from else condition", 4020 "invalid map access from else condition",
3699 .insns = { 4021 .insns = {
3700 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 4022 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
@@ -3712,9 +4034,9 @@ static struct bpf_test tests[] = {
3712 BPF_EXIT_INSN(), 4034 BPF_EXIT_INSN(),
3713 }, 4035 },
3714 .fixup_map2 = { 3 }, 4036 .fixup_map2 = { 3 },
3715 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map", 4037 .errstr = "R0 unbounded memory access",
3716 .result = REJECT, 4038 .result = REJECT,
3717 .errstr_unpriv = "R0 pointer arithmetic prohibited", 4039 .errstr_unpriv = "R0 leaks addr",
3718 .result_unpriv = REJECT, 4040 .result_unpriv = REJECT,
3719 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 4041 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3720 }, 4042 },
@@ -4092,7 +4414,7 @@ static struct bpf_test tests[] = {
4092 BPF_EXIT_INSN(), 4414 BPF_EXIT_INSN(),
4093 }, 4415 },
4094 .fixup_map2 = { 3 }, 4416 .fixup_map2 = { 3 },
4095 .errstr = "invalid access to map value, value_size=48 off=0 size=-8", 4417 .errstr = "R2 min value is negative",
4096 .result = REJECT, 4418 .result = REJECT,
4097 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4419 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4098 }, 4420 },
@@ -4158,7 +4480,7 @@ static struct bpf_test tests[] = {
4158 BPF_EXIT_INSN(), 4480 BPF_EXIT_INSN(),
4159 }, 4481 },
4160 .fixup_map2 = { 3 }, 4482 .fixup_map2 = { 3 },
4161 .errstr = "R1 min value is outside of the array range", 4483 .errstr = "invalid access to map value, value_size=48 off=4 size=0",
4162 .result = REJECT, 4484 .result = REJECT,
4163 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4485 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4164 }, 4486 },
@@ -4204,7 +4526,7 @@ static struct bpf_test tests[] = {
4204 BPF_EXIT_INSN(), 4526 BPF_EXIT_INSN(),
4205 }, 4527 },
4206 .fixup_map2 = { 3 }, 4528 .fixup_map2 = { 3 },
4207 .errstr = "invalid access to map value, value_size=48 off=4 size=-8", 4529 .errstr = "R2 min value is negative",
4208 .result = REJECT, 4530 .result = REJECT,
4209 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4531 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4210 }, 4532 },
@@ -4226,7 +4548,7 @@ static struct bpf_test tests[] = {
4226 BPF_EXIT_INSN(), 4548 BPF_EXIT_INSN(),
4227 }, 4549 },
4228 .fixup_map2 = { 3 }, 4550 .fixup_map2 = { 3 },
4229 .errstr = "R1 min value is outside of the array range", 4551 .errstr = "R2 min value is negative",
4230 .result = REJECT, 4552 .result = REJECT,
4231 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4553 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4232 }, 4554 },
@@ -4342,7 +4664,7 @@ static struct bpf_test tests[] = {
4342 BPF_EXIT_INSN(), 4664 BPF_EXIT_INSN(),
4343 }, 4665 },
4344 .fixup_map2 = { 3 }, 4666 .fixup_map2 = { 3 },
4345 .errstr = "invalid access to map value, value_size=48 off=4 size=-8", 4667 .errstr = "R2 min value is negative",
4346 .result = REJECT, 4668 .result = REJECT,
4347 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4669 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4348 }, 4670 },
@@ -4365,7 +4687,7 @@ static struct bpf_test tests[] = {
4365 BPF_EXIT_INSN(), 4687 BPF_EXIT_INSN(),
4366 }, 4688 },
4367 .fixup_map2 = { 3 }, 4689 .fixup_map2 = { 3 },
4368 .errstr = "R1 min value is outside of the array range", 4690 .errstr = "R2 min value is negative",
4369 .result = REJECT, 4691 .result = REJECT,
4370 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4692 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4371 }, 4693 },
@@ -4453,13 +4775,13 @@ static struct bpf_test tests[] = {
4453 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4775 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4454 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), 4776 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4455 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), 4777 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4456 BPF_MOV64_IMM(BPF_REG_2, 0), 4778 BPF_MOV64_IMM(BPF_REG_2, 1),
4457 BPF_MOV64_IMM(BPF_REG_3, 0), 4779 BPF_MOV64_IMM(BPF_REG_3, 0),
4458 BPF_EMIT_CALL(BPF_FUNC_probe_read), 4780 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4459 BPF_EXIT_INSN(), 4781 BPF_EXIT_INSN(),
4460 }, 4782 },
4461 .fixup_map2 = { 3 }, 4783 .fixup_map2 = { 3 },
4462 .errstr = "R1 min value is negative, either use unsigned index or do a if (index >=0) check", 4784 .errstr = "R1 unbounded memory access",
4463 .result = REJECT, 4785 .result = REJECT,
4464 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4786 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4465 }, 4787 },
@@ -4490,6 +4812,246 @@ static struct bpf_test tests[] = {
4490 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4812 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4491 }, 4813 },
4492 { 4814 {
4815 "helper access to map: bounds check using <, good access",
4816 .insns = {
4817 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4818 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4819 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4820 BPF_LD_MAP_FD(BPF_REG_1, 0),
4821 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4822 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4823 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4824 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4825 BPF_JMP_IMM(BPF_JLT, BPF_REG_3, 32, 2),
4826 BPF_MOV64_IMM(BPF_REG_0, 0),
4827 BPF_EXIT_INSN(),
4828 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4829 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4830 BPF_MOV64_IMM(BPF_REG_0, 0),
4831 BPF_EXIT_INSN(),
4832 },
4833 .fixup_map2 = { 3 },
4834 .result = ACCEPT,
4835 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4836 },
4837 {
4838 "helper access to map: bounds check using <, bad access",
4839 .insns = {
4840 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4841 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4842 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4843 BPF_LD_MAP_FD(BPF_REG_1, 0),
4844 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4845 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4846 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4847 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4848 BPF_JMP_IMM(BPF_JLT, BPF_REG_3, 32, 4),
4849 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4850 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4851 BPF_MOV64_IMM(BPF_REG_0, 0),
4852 BPF_EXIT_INSN(),
4853 BPF_MOV64_IMM(BPF_REG_0, 0),
4854 BPF_EXIT_INSN(),
4855 },
4856 .fixup_map2 = { 3 },
4857 .result = REJECT,
4858 .errstr = "R1 unbounded memory access",
4859 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4860 },
4861 {
4862 "helper access to map: bounds check using <=, good access",
4863 .insns = {
4864 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4865 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4866 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4867 BPF_LD_MAP_FD(BPF_REG_1, 0),
4868 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4869 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4870 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4871 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4872 BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 32, 2),
4873 BPF_MOV64_IMM(BPF_REG_0, 0),
4874 BPF_EXIT_INSN(),
4875 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4876 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4877 BPF_MOV64_IMM(BPF_REG_0, 0),
4878 BPF_EXIT_INSN(),
4879 },
4880 .fixup_map2 = { 3 },
4881 .result = ACCEPT,
4882 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4883 },
4884 {
4885 "helper access to map: bounds check using <=, bad access",
4886 .insns = {
4887 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4888 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4889 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4890 BPF_LD_MAP_FD(BPF_REG_1, 0),
4891 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4892 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4893 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4894 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4895 BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 32, 4),
4896 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4897 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4898 BPF_MOV64_IMM(BPF_REG_0, 0),
4899 BPF_EXIT_INSN(),
4900 BPF_MOV64_IMM(BPF_REG_0, 0),
4901 BPF_EXIT_INSN(),
4902 },
4903 .fixup_map2 = { 3 },
4904 .result = REJECT,
4905 .errstr = "R1 unbounded memory access",
4906 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4907 },
4908 {
4909 "helper access to map: bounds check using s<, good access",
4910 .insns = {
4911 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4912 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4913 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4914 BPF_LD_MAP_FD(BPF_REG_1, 0),
4915 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4916 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4917 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4918 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4919 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4920 BPF_MOV64_IMM(BPF_REG_0, 0),
4921 BPF_EXIT_INSN(),
4922 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 0, -3),
4923 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4924 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4925 BPF_MOV64_IMM(BPF_REG_0, 0),
4926 BPF_EXIT_INSN(),
4927 },
4928 .fixup_map2 = { 3 },
4929 .result = ACCEPT,
4930 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4931 },
4932 {
4933 "helper access to map: bounds check using s<, good access 2",
4934 .insns = {
4935 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4936 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4937 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4938 BPF_LD_MAP_FD(BPF_REG_1, 0),
4939 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4940 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4941 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4942 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4943 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4944 BPF_MOV64_IMM(BPF_REG_0, 0),
4945 BPF_EXIT_INSN(),
4946 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, -3, -3),
4947 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4948 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4949 BPF_MOV64_IMM(BPF_REG_0, 0),
4950 BPF_EXIT_INSN(),
4951 },
4952 .fixup_map2 = { 3 },
4953 .result = ACCEPT,
4954 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4955 },
4956 {
4957 "helper access to map: bounds check using s<, bad access",
4958 .insns = {
4959 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4960 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4961 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4962 BPF_LD_MAP_FD(BPF_REG_1, 0),
4963 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4964 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4965 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4966 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
4967 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4968 BPF_MOV64_IMM(BPF_REG_0, 0),
4969 BPF_EXIT_INSN(),
4970 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, -3, -3),
4971 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4972 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4973 BPF_MOV64_IMM(BPF_REG_0, 0),
4974 BPF_EXIT_INSN(),
4975 },
4976 .fixup_map2 = { 3 },
4977 .result = REJECT,
4978 .errstr = "R1 min value is negative",
4979 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4980 },
4981 {
4982 "helper access to map: bounds check using s<=, good access",
4983 .insns = {
4984 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4985 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4986 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4987 BPF_LD_MAP_FD(BPF_REG_1, 0),
4988 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4989 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4990 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4991 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4992 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
4993 BPF_MOV64_IMM(BPF_REG_0, 0),
4994 BPF_EXIT_INSN(),
4995 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 0, -3),
4996 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4997 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4998 BPF_MOV64_IMM(BPF_REG_0, 0),
4999 BPF_EXIT_INSN(),
5000 },
5001 .fixup_map2 = { 3 },
5002 .result = ACCEPT,
5003 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5004 },
5005 {
5006 "helper access to map: bounds check using s<=, good access 2",
5007 .insns = {
5008 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5009 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5010 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
5011 BPF_LD_MAP_FD(BPF_REG_1, 0),
5012 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5013 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5014 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5015 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
5016 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5017 BPF_MOV64_IMM(BPF_REG_0, 0),
5018 BPF_EXIT_INSN(),
5019 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, -3, -3),
5020 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5021 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5022 BPF_MOV64_IMM(BPF_REG_0, 0),
5023 BPF_EXIT_INSN(),
5024 },
5025 .fixup_map2 = { 3 },
5026 .result = ACCEPT,
5027 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5028 },
5029 {
5030 "helper access to map: bounds check using s<=, bad access",
5031 .insns = {
5032 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5033 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5034 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
5035 BPF_LD_MAP_FD(BPF_REG_1, 0),
5036 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5037 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5038 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5039 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
5040 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5041 BPF_MOV64_IMM(BPF_REG_0, 0),
5042 BPF_EXIT_INSN(),
5043 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, -3, -3),
5044 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5045 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5046 BPF_MOV64_IMM(BPF_REG_0, 0),
5047 BPF_EXIT_INSN(),
5048 },
5049 .fixup_map2 = { 3 },
5050 .result = REJECT,
5051 .errstr = "R1 min value is negative",
5052 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5053 },
5054 {
4493 "map element value is preserved across register spilling", 5055 "map element value is preserved across register spilling",
4494 .insns = { 5056 .insns = {
4495 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 5057 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -4579,7 +5141,7 @@ static struct bpf_test tests[] = {
4579 BPF_EXIT_INSN(), 5141 BPF_EXIT_INSN(),
4580 }, 5142 },
4581 .fixup_map2 = { 3 }, 5143 .fixup_map2 = { 3 },
4582 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5144 .errstr_unpriv = "R0 leaks addr",
4583 .result = ACCEPT, 5145 .result = ACCEPT,
4584 .result_unpriv = REJECT, 5146 .result_unpriv = REJECT,
4585 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5147 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4607,7 +5169,7 @@ static struct bpf_test tests[] = {
4607 BPF_EXIT_INSN(), 5169 BPF_EXIT_INSN(),
4608 }, 5170 },
4609 .fixup_map2 = { 3 }, 5171 .fixup_map2 = { 3 },
4610 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5172 .errstr_unpriv = "R0 leaks addr",
4611 .result = ACCEPT, 5173 .result = ACCEPT,
4612 .result_unpriv = REJECT, 5174 .result_unpriv = REJECT,
4613 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5175 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4626,7 +5188,7 @@ static struct bpf_test tests[] = {
4626 BPF_EXIT_INSN(), 5188 BPF_EXIT_INSN(),
4627 }, 5189 },
4628 .fixup_map2 = { 3 }, 5190 .fixup_map2 = { 3 },
4629 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5191 .errstr_unpriv = "R0 bitwise operator &= on pointer",
4630 .errstr = "invalid mem access 'inv'", 5192 .errstr = "invalid mem access 'inv'",
4631 .result = REJECT, 5193 .result = REJECT,
4632 .result_unpriv = REJECT, 5194 .result_unpriv = REJECT,
@@ -4645,7 +5207,7 @@ static struct bpf_test tests[] = {
4645 BPF_EXIT_INSN(), 5207 BPF_EXIT_INSN(),
4646 }, 5208 },
4647 .fixup_map2 = { 3 }, 5209 .fixup_map2 = { 3 },
4648 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5210 .errstr_unpriv = "R0 32-bit pointer arithmetic prohibited",
4649 .errstr = "invalid mem access 'inv'", 5211 .errstr = "invalid mem access 'inv'",
4650 .result = REJECT, 5212 .result = REJECT,
4651 .result_unpriv = REJECT, 5213 .result_unpriv = REJECT,
@@ -4664,7 +5226,7 @@ static struct bpf_test tests[] = {
4664 BPF_EXIT_INSN(), 5226 BPF_EXIT_INSN(),
4665 }, 5227 },
4666 .fixup_map2 = { 3 }, 5228 .fixup_map2 = { 3 },
4667 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5229 .errstr_unpriv = "R0 pointer arithmetic with /= operator",
4668 .errstr = "invalid mem access 'inv'", 5230 .errstr = "invalid mem access 'inv'",
4669 .result = REJECT, 5231 .result = REJECT,
4670 .result_unpriv = REJECT, 5232 .result_unpriv = REJECT,
@@ -4707,10 +5269,8 @@ static struct bpf_test tests[] = {
4707 BPF_EXIT_INSN(), 5269 BPF_EXIT_INSN(),
4708 }, 5270 },
4709 .fixup_map2 = { 3 }, 5271 .fixup_map2 = { 3 },
4710 .errstr_unpriv = "R0 invalid mem access 'inv'",
4711 .errstr = "R0 invalid mem access 'inv'", 5272 .errstr = "R0 invalid mem access 'inv'",
4712 .result = REJECT, 5273 .result = REJECT,
4713 .result_unpriv = REJECT,
4714 }, 5274 },
4715 { 5275 {
4716 "map element value is preserved across register spilling", 5276 "map element value is preserved across register spilling",
@@ -4732,7 +5292,7 @@ static struct bpf_test tests[] = {
4732 BPF_EXIT_INSN(), 5292 BPF_EXIT_INSN(),
4733 }, 5293 },
4734 .fixup_map2 = { 3 }, 5294 .fixup_map2 = { 3 },
4735 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5295 .errstr_unpriv = "R0 leaks addr",
4736 .result = ACCEPT, 5296 .result = ACCEPT,
4737 .result_unpriv = REJECT, 5297 .result_unpriv = REJECT,
4738 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5298 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4914,7 +5474,8 @@ static struct bpf_test tests[] = {
4914 BPF_MOV64_IMM(BPF_REG_0, 0), 5474 BPF_MOV64_IMM(BPF_REG_0, 0),
4915 BPF_EXIT_INSN(), 5475 BPF_EXIT_INSN(),
4916 }, 5476 },
4917 .errstr = "R2 unbounded memory access", 5477 /* because max wasn't checked, signed min is negative */
5478 .errstr = "R2 min value is negative, either use unsigned or 'var &= const'",
4918 .result = REJECT, 5479 .result = REJECT,
4919 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5480 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4920 }, 5481 },
@@ -5063,6 +5624,20 @@ static struct bpf_test tests[] = {
5063 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5624 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5064 }, 5625 },
5065 { 5626 {
5627 "helper access to variable memory: size = 0 allowed on NULL",
5628 .insns = {
5629 BPF_MOV64_IMM(BPF_REG_1, 0),
5630 BPF_MOV64_IMM(BPF_REG_2, 0),
5631 BPF_MOV64_IMM(BPF_REG_3, 0),
5632 BPF_MOV64_IMM(BPF_REG_4, 0),
5633 BPF_MOV64_IMM(BPF_REG_5, 0),
5634 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5635 BPF_EXIT_INSN(),
5636 },
5637 .result = ACCEPT,
5638 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5639 },
5640 {
5066 "helper access to variable memory: size > 0 not allowed on NULL", 5641 "helper access to variable memory: size > 0 not allowed on NULL",
5067 .insns = { 5642 .insns = {
5068 BPF_MOV64_IMM(BPF_REG_1, 0), 5643 BPF_MOV64_IMM(BPF_REG_1, 0),
@@ -5076,7 +5651,7 @@ static struct bpf_test tests[] = {
5076 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 5651 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5077 BPF_EXIT_INSN(), 5652 BPF_EXIT_INSN(),
5078 }, 5653 },
5079 .errstr = "R1 type=imm expected=fp", 5654 .errstr = "R1 type=inv expected=fp",
5080 .result = REJECT, 5655 .result = REJECT,
5081 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 5656 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5082 }, 5657 },
@@ -5161,7 +5736,7 @@ static struct bpf_test tests[] = {
5161 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 5736 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5162 BPF_FUNC_map_lookup_elem), 5737 BPF_FUNC_map_lookup_elem),
5163 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), 5738 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5164 BPF_MOV64_IMM(BPF_REG_1, 6), 5739 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
5165 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4), 5740 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4),
5166 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), 5741 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
5167 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 5742 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
@@ -5170,10 +5745,8 @@ static struct bpf_test tests[] = {
5170 BPF_EXIT_INSN(), 5745 BPF_EXIT_INSN(),
5171 }, 5746 },
5172 .fixup_map2 = { 3 }, 5747 .fixup_map2 = { 3 },
5173 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5748 .errstr = "R0 max value is outside of the array range",
5174 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
5175 .result = REJECT, 5749 .result = REJECT,
5176 .result_unpriv = REJECT,
5177 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5750 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
5178 }, 5751 },
5179 { 5752 {
@@ -5202,10 +5775,8 @@ static struct bpf_test tests[] = {
5202 BPF_EXIT_INSN(), 5775 BPF_EXIT_INSN(),
5203 }, 5776 },
5204 .fixup_map2 = { 3 }, 5777 .fixup_map2 = { 3 },
5205 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5778 .errstr = "R0 max value is outside of the array range",
5206 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
5207 .result = REJECT, 5779 .result = REJECT,
5208 .result_unpriv = REJECT,
5209 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5780 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
5210 }, 5781 },
5211 { 5782 {
@@ -5252,7 +5823,7 @@ static struct bpf_test tests[] = {
5252 }, 5823 },
5253 .fixup_map_in_map = { 3 }, 5824 .fixup_map_in_map = { 3 },
5254 .errstr = "R1 type=inv expected=map_ptr", 5825 .errstr = "R1 type=inv expected=map_ptr",
5255 .errstr_unpriv = "R1 pointer arithmetic prohibited", 5826 .errstr_unpriv = "R1 pointer arithmetic on CONST_PTR_TO_MAP prohibited",
5256 .result = REJECT, 5827 .result = REJECT,
5257 }, 5828 },
5258 { 5829 {
@@ -5532,10 +6103,8 @@ static struct bpf_test tests[] = {
5532 BPF_EXIT_INSN(), 6103 BPF_EXIT_INSN(),
5533 }, 6104 },
5534 .fixup_map1 = { 3 }, 6105 .fixup_map1 = { 3 },
5535 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5536 .errstr = "R0 min value is negative", 6106 .errstr = "R0 min value is negative",
5537 .result = REJECT, 6107 .result = REJECT,
5538 .result_unpriv = REJECT,
5539 }, 6108 },
5540 { 6109 {
5541 "bounds checks mixing signed and unsigned", 6110 "bounds checks mixing signed and unsigned",
@@ -5558,10 +6127,8 @@ static struct bpf_test tests[] = {
5558 BPF_EXIT_INSN(), 6127 BPF_EXIT_INSN(),
5559 }, 6128 },
5560 .fixup_map1 = { 3 }, 6129 .fixup_map1 = { 3 },
5561 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5562 .errstr = "R0 min value is negative", 6130 .errstr = "R0 min value is negative",
5563 .result = REJECT, 6131 .result = REJECT,
5564 .result_unpriv = REJECT,
5565 }, 6132 },
5566 { 6133 {
5567 "bounds checks mixing signed and unsigned, variant 2", 6134 "bounds checks mixing signed and unsigned, variant 2",
@@ -5586,10 +6153,8 @@ static struct bpf_test tests[] = {
5586 BPF_EXIT_INSN(), 6153 BPF_EXIT_INSN(),
5587 }, 6154 },
5588 .fixup_map1 = { 3 }, 6155 .fixup_map1 = { 3 },
5589 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5590 .errstr = "R8 invalid mem access 'inv'", 6156 .errstr = "R8 invalid mem access 'inv'",
5591 .result = REJECT, 6157 .result = REJECT,
5592 .result_unpriv = REJECT,
5593 }, 6158 },
5594 { 6159 {
5595 "bounds checks mixing signed and unsigned, variant 3", 6160 "bounds checks mixing signed and unsigned, variant 3",
@@ -5613,10 +6178,8 @@ static struct bpf_test tests[] = {
5613 BPF_EXIT_INSN(), 6178 BPF_EXIT_INSN(),
5614 }, 6179 },
5615 .fixup_map1 = { 3 }, 6180 .fixup_map1 = { 3 },
5616 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5617 .errstr = "R8 invalid mem access 'inv'", 6181 .errstr = "R8 invalid mem access 'inv'",
5618 .result = REJECT, 6182 .result = REJECT,
5619 .result_unpriv = REJECT,
5620 }, 6183 },
5621 { 6184 {
5622 "bounds checks mixing signed and unsigned, variant 4", 6185 "bounds checks mixing signed and unsigned, variant 4",
@@ -5639,10 +6202,7 @@ static struct bpf_test tests[] = {
5639 BPF_EXIT_INSN(), 6202 BPF_EXIT_INSN(),
5640 }, 6203 },
5641 .fixup_map1 = { 3 }, 6204 .fixup_map1 = { 3 },
5642 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6205 .result = ACCEPT,
5643 .errstr = "R0 min value is negative",
5644 .result = REJECT,
5645 .result_unpriv = REJECT,
5646 }, 6206 },
5647 { 6207 {
5648 "bounds checks mixing signed and unsigned, variant 5", 6208 "bounds checks mixing signed and unsigned, variant 5",
@@ -5666,10 +6226,8 @@ static struct bpf_test tests[] = {
5666 BPF_EXIT_INSN(), 6226 BPF_EXIT_INSN(),
5667 }, 6227 },
5668 .fixup_map1 = { 3 }, 6228 .fixup_map1 = { 3 },
5669 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6229 .errstr = "R0 min value is negative",
5670 .errstr = "R0 invalid mem access",
5671 .result = REJECT, 6230 .result = REJECT,
5672 .result_unpriv = REJECT,
5673 }, 6231 },
5674 { 6232 {
5675 "bounds checks mixing signed and unsigned, variant 6", 6233 "bounds checks mixing signed and unsigned, variant 6",
@@ -5690,10 +6248,8 @@ static struct bpf_test tests[] = {
5690 BPF_MOV64_IMM(BPF_REG_0, 0), 6248 BPF_MOV64_IMM(BPF_REG_0, 0),
5691 BPF_EXIT_INSN(), 6249 BPF_EXIT_INSN(),
5692 }, 6250 },
5693 .errstr_unpriv = "R4 min value is negative, either use unsigned",
5694 .errstr = "R4 min value is negative, either use unsigned", 6251 .errstr = "R4 min value is negative, either use unsigned",
5695 .result = REJECT, 6252 .result = REJECT,
5696 .result_unpriv = REJECT,
5697 }, 6253 },
5698 { 6254 {
5699 "bounds checks mixing signed and unsigned, variant 7", 6255 "bounds checks mixing signed and unsigned, variant 7",
@@ -5716,10 +6272,7 @@ static struct bpf_test tests[] = {
5716 BPF_EXIT_INSN(), 6272 BPF_EXIT_INSN(),
5717 }, 6273 },
5718 .fixup_map1 = { 3 }, 6274 .fixup_map1 = { 3 },
5719 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6275 .result = ACCEPT,
5720 .errstr = "R0 min value is negative",
5721 .result = REJECT,
5722 .result_unpriv = REJECT,
5723 }, 6276 },
5724 { 6277 {
5725 "bounds checks mixing signed and unsigned, variant 8", 6278 "bounds checks mixing signed and unsigned, variant 8",
@@ -5730,32 +6283,6 @@ static struct bpf_test tests[] = {
5730 BPF_LD_MAP_FD(BPF_REG_1, 0), 6283 BPF_LD_MAP_FD(BPF_REG_1, 0),
5731 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 6284 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5732 BPF_FUNC_map_lookup_elem), 6285 BPF_FUNC_map_lookup_elem),
5733 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
5734 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
5735 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
5736 BPF_MOV64_IMM(BPF_REG_2, 1024 * 1024 * 1024 + 1),
5737 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
5738 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
5739 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
5740 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
5741 BPF_MOV64_IMM(BPF_REG_0, 0),
5742 BPF_EXIT_INSN(),
5743 },
5744 .fixup_map1 = { 3 },
5745 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5746 .errstr = "R0 min value is negative",
5747 .result = REJECT,
5748 .result_unpriv = REJECT,
5749 },
5750 {
5751 "bounds checks mixing signed and unsigned, variant 9",
5752 .insns = {
5753 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5754 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5755 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5756 BPF_LD_MAP_FD(BPF_REG_1, 0),
5757 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5758 BPF_FUNC_map_lookup_elem),
5759 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9), 6286 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
5760 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8), 6287 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
5761 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16), 6288 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
@@ -5770,13 +6297,11 @@ static struct bpf_test tests[] = {
5770 BPF_EXIT_INSN(), 6297 BPF_EXIT_INSN(),
5771 }, 6298 },
5772 .fixup_map1 = { 3 }, 6299 .fixup_map1 = { 3 },
5773 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5774 .errstr = "R0 min value is negative", 6300 .errstr = "R0 min value is negative",
5775 .result = REJECT, 6301 .result = REJECT,
5776 .result_unpriv = REJECT,
5777 }, 6302 },
5778 { 6303 {
5779 "bounds checks mixing signed and unsigned, variant 10", 6304 "bounds checks mixing signed and unsigned, variant 9",
5780 .insns = { 6305 .insns = {
5781 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6306 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5782 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6307 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5798,13 +6323,10 @@ static struct bpf_test tests[] = {
5798 BPF_EXIT_INSN(), 6323 BPF_EXIT_INSN(),
5799 }, 6324 },
5800 .fixup_map1 = { 3 }, 6325 .fixup_map1 = { 3 },
5801 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6326 .result = ACCEPT,
5802 .errstr = "R0 min value is negative",
5803 .result = REJECT,
5804 .result_unpriv = REJECT,
5805 }, 6327 },
5806 { 6328 {
5807 "bounds checks mixing signed and unsigned, variant 11", 6329 "bounds checks mixing signed and unsigned, variant 10",
5808 .insns = { 6330 .insns = {
5809 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6331 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5810 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6332 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5826,13 +6348,11 @@ static struct bpf_test tests[] = {
5826 BPF_EXIT_INSN(), 6348 BPF_EXIT_INSN(),
5827 }, 6349 },
5828 .fixup_map1 = { 3 }, 6350 .fixup_map1 = { 3 },
5829 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5830 .errstr = "R0 min value is negative", 6351 .errstr = "R0 min value is negative",
5831 .result = REJECT, 6352 .result = REJECT,
5832 .result_unpriv = REJECT,
5833 }, 6353 },
5834 { 6354 {
5835 "bounds checks mixing signed and unsigned, variant 12", 6355 "bounds checks mixing signed and unsigned, variant 11",
5836 .insns = { 6356 .insns = {
5837 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6357 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5838 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6358 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5855,13 +6375,11 @@ static struct bpf_test tests[] = {
5855 BPF_EXIT_INSN(), 6375 BPF_EXIT_INSN(),
5856 }, 6376 },
5857 .fixup_map1 = { 3 }, 6377 .fixup_map1 = { 3 },
5858 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5859 .errstr = "R0 min value is negative", 6378 .errstr = "R0 min value is negative",
5860 .result = REJECT, 6379 .result = REJECT,
5861 .result_unpriv = REJECT,
5862 }, 6380 },
5863 { 6381 {
5864 "bounds checks mixing signed and unsigned, variant 13", 6382 "bounds checks mixing signed and unsigned, variant 12",
5865 .insns = { 6383 .insns = {
5866 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6384 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5867 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6385 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5883,13 +6401,11 @@ static struct bpf_test tests[] = {
5883 BPF_EXIT_INSN(), 6401 BPF_EXIT_INSN(),
5884 }, 6402 },
5885 .fixup_map1 = { 3 }, 6403 .fixup_map1 = { 3 },
5886 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5887 .errstr = "R0 min value is negative", 6404 .errstr = "R0 min value is negative",
5888 .result = REJECT, 6405 .result = REJECT,
5889 .result_unpriv = REJECT,
5890 }, 6406 },
5891 { 6407 {
5892 "bounds checks mixing signed and unsigned, variant 14", 6408 "bounds checks mixing signed and unsigned, variant 13",
5893 .insns = { 6409 .insns = {
5894 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6410 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5895 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6411 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5914,13 +6430,11 @@ static struct bpf_test tests[] = {
5914 BPF_EXIT_INSN(), 6430 BPF_EXIT_INSN(),
5915 }, 6431 },
5916 .fixup_map1 = { 3 }, 6432 .fixup_map1 = { 3 },
5917 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5918 .errstr = "R0 min value is negative", 6433 .errstr = "R0 min value is negative",
5919 .result = REJECT, 6434 .result = REJECT,
5920 .result_unpriv = REJECT,
5921 }, 6435 },
5922 { 6436 {
5923 "bounds checks mixing signed and unsigned, variant 15", 6437 "bounds checks mixing signed and unsigned, variant 14",
5924 .insns = { 6438 .insns = {
5925 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1, 6439 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
5926 offsetof(struct __sk_buff, mark)), 6440 offsetof(struct __sk_buff, mark)),
@@ -5946,13 +6460,11 @@ static struct bpf_test tests[] = {
5946 BPF_JMP_IMM(BPF_JA, 0, 0, -7), 6460 BPF_JMP_IMM(BPF_JA, 0, 0, -7),
5947 }, 6461 },
5948 .fixup_map1 = { 4 }, 6462 .fixup_map1 = { 4 },
5949 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5950 .errstr = "R0 min value is negative", 6463 .errstr = "R0 min value is negative",
5951 .result = REJECT, 6464 .result = REJECT,
5952 .result_unpriv = REJECT,
5953 }, 6465 },
5954 { 6466 {
5955 "bounds checks mixing signed and unsigned, variant 16", 6467 "bounds checks mixing signed and unsigned, variant 15",
5956 .insns = { 6468 .insns = {
5957 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6469 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5958 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6470 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5976,13 +6488,13 @@ static struct bpf_test tests[] = {
5976 BPF_EXIT_INSN(), 6488 BPF_EXIT_INSN(),
5977 }, 6489 },
5978 .fixup_map1 = { 3 }, 6490 .fixup_map1 = { 3 },
5979 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6491 .errstr_unpriv = "R0 pointer comparison prohibited",
5980 .errstr = "R0 min value is negative", 6492 .errstr = "R0 min value is negative",
5981 .result = REJECT, 6493 .result = REJECT,
5982 .result_unpriv = REJECT, 6494 .result_unpriv = REJECT,
5983 }, 6495 },
5984 { 6496 {
5985 "subtraction bounds (map value)", 6497 "subtraction bounds (map value) variant 1",
5986 .insns = { 6498 .insns = {
5987 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6499 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5988 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -6004,10 +6516,134 @@ static struct bpf_test tests[] = {
6004 BPF_EXIT_INSN(), 6516 BPF_EXIT_INSN(),
6005 }, 6517 },
6006 .fixup_map1 = { 3 }, 6518 .fixup_map1 = { 3 },
6007 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6519 .errstr = "R0 max value is outside of the array range",
6520 .result = REJECT,
6521 },
6522 {
6523 "subtraction bounds (map value) variant 2",
6524 .insns = {
6525 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6526 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6527 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6528 BPF_LD_MAP_FD(BPF_REG_1, 0),
6529 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6530 BPF_FUNC_map_lookup_elem),
6531 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6532 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6533 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 6),
6534 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
6535 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 4),
6536 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
6537 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6538 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6539 BPF_EXIT_INSN(),
6540 BPF_MOV64_IMM(BPF_REG_0, 0),
6541 BPF_EXIT_INSN(),
6542 },
6543 .fixup_map1 = { 3 },
6008 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 6544 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
6009 .result = REJECT, 6545 .result = REJECT,
6546 },
6547 {
6548 "variable-offset ctx access",
6549 .insns = {
6550 /* Get an unknown value */
6551 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6552 /* Make it small and 4-byte aligned */
6553 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
6554 /* add it to skb. We now have either &skb->len or
6555 * &skb->pkt_type, but we don't know which
6556 */
6557 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
6558 /* dereference it */
6559 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
6560 BPF_EXIT_INSN(),
6561 },
6562 .errstr = "variable ctx access var_off=(0x0; 0x4)",
6563 .result = REJECT,
6564 .prog_type = BPF_PROG_TYPE_LWT_IN,
6565 },
6566 {
6567 "variable-offset stack access",
6568 .insns = {
6569 /* Fill the top 8 bytes of the stack */
6570 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6571 /* Get an unknown value */
6572 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6573 /* Make it small and 4-byte aligned */
6574 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
6575 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
6576 /* add it to fp. We now have either fp-4 or fp-8, but
6577 * we don't know which
6578 */
6579 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
6580 /* dereference it */
6581 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
6582 BPF_EXIT_INSN(),
6583 },
6584 .errstr = "variable stack access var_off=(0xfffffffffffffff8; 0x4)",
6585 .result = REJECT,
6586 .prog_type = BPF_PROG_TYPE_LWT_IN,
6587 },
6588 {
6589 "liveness pruning and write screening",
6590 .insns = {
6591 /* Get an unknown value */
6592 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6593 /* branch conditions teach us nothing about R2 */
6594 BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
6595 BPF_MOV64_IMM(BPF_REG_0, 0),
6596 BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
6597 BPF_MOV64_IMM(BPF_REG_0, 0),
6598 BPF_EXIT_INSN(),
6599 },
6600 .errstr = "R0 !read_ok",
6601 .result = REJECT,
6602 .prog_type = BPF_PROG_TYPE_LWT_IN,
6603 },
6604 {
6605 "varlen_map_value_access pruning",
6606 .insns = {
6607 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6608 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6609 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6610 BPF_LD_MAP_FD(BPF_REG_1, 0),
6611 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6612 BPF_FUNC_map_lookup_elem),
6613 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6614 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
6615 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
6616 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
6617 BPF_MOV32_IMM(BPF_REG_1, 0),
6618 BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
6619 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6620 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
6621 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
6622 offsetof(struct test_val, foo)),
6623 BPF_EXIT_INSN(),
6624 },
6625 .fixup_map2 = { 3 },
6626 .errstr_unpriv = "R0 leaks addr",
6627 .errstr = "R0 unbounded memory access",
6010 .result_unpriv = REJECT, 6628 .result_unpriv = REJECT,
6629 .result = REJECT,
6630 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
6631 },
6632 {
6633 "invalid 64-bit BPF_END",
6634 .insns = {
6635 BPF_MOV32_IMM(BPF_REG_0, 0),
6636 {
6637 .code = BPF_ALU64 | BPF_END | BPF_TO_LE,
6638 .dst_reg = BPF_REG_0,
6639 .src_reg = 0,
6640 .off = 0,
6641 .imm = 32,
6642 },
6643 BPF_EXIT_INSN(),
6644 },
6645 .errstr = "BPF_END uses reserved fields",
6646 .result = REJECT,
6011 }, 6647 },
6012}; 6648};
6013 6649
diff --git a/tools/testing/selftests/bpf/test_xdp_redirect.c b/tools/testing/selftests/bpf/test_xdp_redirect.c
new file mode 100644
index 000000000000..ef9e704be140
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_redirect.c
@@ -0,0 +1,28 @@
1/* Copyright (c) 2017 VMware
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 */
12#include <linux/bpf.h>
13#include "bpf_helpers.h"
14
15int _version SEC("version") = 1;
16
17SEC("redirect_to_111")
18int xdp_redirect_to_111(struct xdp_md *xdp)
19{
20 return bpf_redirect(111, 0);
21}
22SEC("redirect_to_222")
23int xdp_redirect_to_222(struct xdp_md *xdp)
24{
25 return bpf_redirect(222, 0);
26}
27
28char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_xdp_redirect.sh b/tools/testing/selftests/bpf/test_xdp_redirect.sh
new file mode 100755
index 000000000000..344a3656dea6
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_redirect.sh
@@ -0,0 +1,59 @@
1#!/bin/sh
2# Create 2 namespaces with two veth peers, and
3# forward packets in-between using generic XDP
4#
5# NS1(veth11) NS2(veth22)
6# | |
7# | |
8# (veth1, ------ (veth2,
9# id:111) id:222)
10# | xdp forwarding |
11# ------------------
12
13cleanup()
14{
15 if [ "$?" = "0" ]; then
16 echo "selftests: test_xdp_redirect [PASS]";
17 else
18 echo "selftests: test_xdp_redirect [FAILED]";
19 fi
20
21 set +e
22 ip netns del ns1 2> /dev/null
23 ip netns del ns2 2> /dev/null
24}
25
26ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
27if [ $? -ne 0 ];then
28 echo "selftests: [SKIP] Could not run test without the ip xdpgeneric support"
29 exit 0
30fi
31set -e
32
33ip netns add ns1
34ip netns add ns2
35
36trap cleanup 0 2 3 6 9
37
38ip link add veth1 index 111 type veth peer name veth11
39ip link add veth2 index 222 type veth peer name veth22
40
41ip link set veth11 netns ns1
42ip link set veth22 netns ns2
43
44ip link set veth1 up
45ip link set veth2 up
46
47ip netns exec ns1 ip addr add 10.1.1.11/24 dev veth11
48ip netns exec ns2 ip addr add 10.1.1.22/24 dev veth22
49
50ip netns exec ns1 ip link set dev veth11 up
51ip netns exec ns2 ip link set dev veth22 up
52
53ip link set dev veth1 xdpgeneric obj test_xdp_redirect.o sec redirect_to_222
54ip link set dev veth2 xdpgeneric obj test_xdp_redirect.o sec redirect_to_111
55
56ip netns exec ns1 ping -c 1 10.1.1.22
57ip netns exec ns2 ping -c 1 10.1.1.11
58
59exit 0
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
index 6b214b7b10fb..247b0a1899d7 100644
--- a/tools/testing/selftests/breakpoints/Makefile
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -2,14 +2,14 @@
2uname_M := $(shell uname -m 2>/dev/null || echo not) 2uname_M := $(shell uname -m 2>/dev/null || echo not)
3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) 3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
4 4
5TEST_GEN_PROGS := step_after_suspend_test
6
5ifeq ($(ARCH),x86) 7ifeq ($(ARCH),x86)
6TEST_GEN_PROGS := breakpoint_test 8TEST_GEN_PROGS += breakpoint_test
7endif 9endif
8ifneq (,$(filter $(ARCH),aarch64 arm64)) 10ifneq (,$(filter $(ARCH),aarch64 arm64))
9TEST_GEN_PROGS := breakpoint_test_arm64 11TEST_GEN_PROGS += breakpoint_test_arm64
10endif 12endif
11 13
12TEST_GEN_PROGS += step_after_suspend_test
13
14include ../lib.mk 14include ../lib.mk
15 15
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c
index f63356151ad4..901b85ea6a59 100644
--- a/tools/testing/selftests/breakpoints/breakpoint_test.c
+++ b/tools/testing/selftests/breakpoints/breakpoint_test.c
@@ -367,11 +367,11 @@ static void launch_tests(void)
367 367
368 /* Icebp traps */ 368 /* Icebp traps */
369 ptrace(PTRACE_CONT, child_pid, NULL, 0); 369 ptrace(PTRACE_CONT, child_pid, NULL, 0);
370 check_success("Test icebp"); 370 check_success("Test icebp\n");
371 371
372 /* Int 3 traps */ 372 /* Int 3 traps */
373 ptrace(PTRACE_CONT, child_pid, NULL, 0); 373 ptrace(PTRACE_CONT, child_pid, NULL, 0);
374 check_success("Test int 3 trap"); 374 check_success("Test int 3 trap\n");
375 375
376 ptrace(PTRACE_CONT, child_pid, NULL, 0); 376 ptrace(PTRACE_CONT, child_pid, NULL, 0);
377} 377}
diff --git a/tools/testing/selftests/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c
index 763f37fecfb8..cf6778441381 100644
--- a/tools/testing/selftests/capabilities/test_execve.c
+++ b/tools/testing/selftests/capabilities/test_execve.c
@@ -1,7 +1,6 @@
1#define _GNU_SOURCE 1#define _GNU_SOURCE
2 2
3#include <cap-ng.h> 3#include <cap-ng.h>
4#include <err.h>
5#include <linux/capability.h> 4#include <linux/capability.h>
6#include <stdbool.h> 5#include <stdbool.h>
7#include <string.h> 6#include <string.h>
@@ -18,6 +17,8 @@
18#include <sys/prctl.h> 17#include <sys/prctl.h>
19#include <sys/stat.h> 18#include <sys/stat.h>
20 19
20#include "../kselftest.h"
21
21#ifndef PR_CAP_AMBIENT 22#ifndef PR_CAP_AMBIENT
22#define PR_CAP_AMBIENT 47 23#define PR_CAP_AMBIENT 47
23# define PR_CAP_AMBIENT_IS_SET 1 24# define PR_CAP_AMBIENT_IS_SET 1
@@ -27,6 +28,7 @@
27#endif 28#endif
28 29
29static int nerrs; 30static int nerrs;
31static pid_t mpid; /* main() pid is used to avoid duplicate test counts */
30 32
31static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap) 33static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
32{ 34{
@@ -36,29 +38,32 @@ static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list
36 int buf_len; 38 int buf_len;
37 39
38 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); 40 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
39 if (buf_len < 0) { 41 if (buf_len < 0)
40 err(1, "vsnprintf failed"); 42 ksft_exit_fail_msg("vsnprintf failed - %s\n", strerror(errno));
41 } 43
42 if (buf_len >= sizeof(buf)) { 44 if (buf_len >= sizeof(buf))
43 errx(1, "vsnprintf output truncated"); 45 ksft_exit_fail_msg("vsnprintf output truncated\n");
44 } 46
45 47
46 fd = open(filename, O_WRONLY); 48 fd = open(filename, O_WRONLY);
47 if (fd < 0) { 49 if (fd < 0) {
48 if ((errno == ENOENT) && enoent_ok) 50 if ((errno == ENOENT) && enoent_ok)
49 return; 51 return;
50 err(1, "open of %s failed", filename); 52 ksft_exit_fail_msg("open of %s failed - %s\n",
53 filename, strerror(errno));
51 } 54 }
52 written = write(fd, buf, buf_len); 55 written = write(fd, buf, buf_len);
53 if (written != buf_len) { 56 if (written != buf_len) {
54 if (written >= 0) { 57 if (written >= 0) {
55 errx(1, "short write to %s", filename); 58 ksft_exit_fail_msg("short write to %s\n", filename);
56 } else { 59 } else {
57 err(1, "write to %s failed", filename); 60 ksft_exit_fail_msg("write to %s failed - %s\n",
61 filename, strerror(errno));
58 } 62 }
59 } 63 }
60 if (close(fd) != 0) { 64 if (close(fd) != 0) {
61 err(1, "close of %s failed", filename); 65 ksft_exit_fail_msg("close of %s failed - %s\n",
66 filename, strerror(errno));
62 } 67 }
63} 68}
64 69
@@ -95,11 +100,12 @@ static bool create_and_enter_ns(uid_t inner_uid)
95 */ 100 */
96 101
97 if (unshare(CLONE_NEWNS) == 0) { 102 if (unshare(CLONE_NEWNS) == 0) {
98 printf("[NOTE]\tUsing global UIDs for tests\n"); 103 ksft_print_msg("[NOTE]\tUsing global UIDs for tests\n");
99 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) 104 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)
100 err(1, "PR_SET_KEEPCAPS"); 105 ksft_exit_fail_msg("PR_SET_KEEPCAPS - %s\n",
106 strerror(errno));
101 if (setresuid(inner_uid, inner_uid, -1) != 0) 107 if (setresuid(inner_uid, inner_uid, -1) != 0)
102 err(1, "setresuid"); 108 ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
103 109
104 // Re-enable effective caps 110 // Re-enable effective caps
105 capng_get_caps_process(); 111 capng_get_caps_process();
@@ -107,22 +113,24 @@ static bool create_and_enter_ns(uid_t inner_uid)
107 if (capng_have_capability(CAPNG_PERMITTED, i)) 113 if (capng_have_capability(CAPNG_PERMITTED, i))
108 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i); 114 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
109 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 115 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
110 err(1, "capng_apply"); 116 ksft_exit_fail_msg(
117 "capng_apply - %s\n", strerror(errno));
111 118
112 have_outer_privilege = true; 119 have_outer_privilege = true;
113 } else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) { 120 } else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) {
114 printf("[NOTE]\tUsing a user namespace for tests\n"); 121 ksft_print_msg("[NOTE]\tUsing a user namespace for tests\n");
115 maybe_write_file("/proc/self/setgroups", "deny"); 122 maybe_write_file("/proc/self/setgroups", "deny");
116 write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid); 123 write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid);
117 write_file("/proc/self/gid_map", "0 %d 1", outer_gid); 124 write_file("/proc/self/gid_map", "0 %d 1", outer_gid);
118 125
119 have_outer_privilege = false; 126 have_outer_privilege = false;
120 } else { 127 } else {
121 errx(1, "must be root or be able to create a userns"); 128 ksft_exit_skip("must be root or be able to create a userns\n");
122 } 129 }
123 130
124 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) 131 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
125 err(1, "remount everything private"); 132 ksft_exit_fail_msg("remount everything private - %s\n",
133 strerror(errno));
126 134
127 return have_outer_privilege; 135 return have_outer_privilege;
128} 136}
@@ -131,20 +139,22 @@ static void chdir_to_tmpfs(void)
131{ 139{
132 char cwd[PATH_MAX]; 140 char cwd[PATH_MAX];
133 if (getcwd(cwd, sizeof(cwd)) != cwd) 141 if (getcwd(cwd, sizeof(cwd)) != cwd)
134 err(1, "getcwd"); 142 ksft_exit_fail_msg("getcwd - %s\n", strerror(errno));
135 143
136 if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0) 144 if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0)
137 err(1, "mount private tmpfs"); 145 ksft_exit_fail_msg("mount private tmpfs - %s\n",
146 strerror(errno));
138 147
139 if (chdir(cwd) != 0) 148 if (chdir(cwd) != 0)
140 err(1, "chdir to private tmpfs"); 149 ksft_exit_fail_msg("chdir to private tmpfs - %s\n",
150 strerror(errno));
141} 151}
142 152
143static void copy_fromat_to(int fromfd, const char *fromname, const char *toname) 153static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
144{ 154{
145 int from = openat(fromfd, fromname, O_RDONLY); 155 int from = openat(fromfd, fromname, O_RDONLY);
146 if (from == -1) 156 if (from == -1)
147 err(1, "open copy source"); 157 ksft_exit_fail_msg("open copy source - %s\n", strerror(errno));
148 158
149 int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700); 159 int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700);
150 160
@@ -154,10 +164,11 @@ static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
154 if (sz == 0) 164 if (sz == 0)
155 break; 165 break;
156 if (sz < 0) 166 if (sz < 0)
157 err(1, "read"); 167 ksft_exit_fail_msg("read - %s\n", strerror(errno));
158 168
159 if (write(to, buf, sz) != sz) 169 if (write(to, buf, sz) != sz)
160 err(1, "write"); /* no short writes on tmpfs */ 170 /* no short writes on tmpfs */
171 ksft_exit_fail_msg("write - %s\n", strerror(errno));
161 } 172 }
162 173
163 close(from); 174 close(from);
@@ -174,18 +185,20 @@ static bool fork_wait(void)
174 int status; 185 int status;
175 if (waitpid(child, &status, 0) != child || 186 if (waitpid(child, &status, 0) != child ||
176 !WIFEXITED(status)) { 187 !WIFEXITED(status)) {
177 printf("[FAIL]\tChild died\n"); 188 ksft_print_msg("Child died\n");
178 nerrs++; 189 nerrs++;
179 } else if (WEXITSTATUS(status) != 0) { 190 } else if (WEXITSTATUS(status) != 0) {
180 printf("[FAIL]\tChild failed\n"); 191 ksft_print_msg("Child failed\n");
181 nerrs++; 192 nerrs++;
182 } else { 193 } else {
183 printf("[OK]\tChild succeeded\n"); 194 /* don't print this message for mpid */
195 if (getpid() != mpid)
196 ksft_test_result_pass("Passed\n");
184 } 197 }
185
186 return false; 198 return false;
187 } else { 199 } else {
188 err(1, "fork"); 200 ksft_exit_fail_msg("fork - %s\n", strerror(errno));
201 return false;
189 } 202 }
190} 203}
191 204
@@ -195,7 +208,7 @@ static void exec_other_validate_cap(const char *name,
195 execl(name, name, (eff ? "1" : "0"), 208 execl(name, name, (eff ? "1" : "0"),
196 (perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"), 209 (perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"),
197 NULL); 210 NULL);
198 err(1, "execl"); 211 ksft_exit_fail_msg("execl - %s\n", strerror(errno));
199} 212}
200 213
201static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient) 214static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient)
@@ -209,7 +222,8 @@ static int do_tests(int uid, const char *our_path)
209 222
210 int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY); 223 int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
211 if (ourpath_fd == -1) 224 if (ourpath_fd == -1)
212 err(1, "open '%s'", our_path); 225 ksft_exit_fail_msg("open '%s' - %s\n",
226 our_path, strerror(errno));
213 227
214 chdir_to_tmpfs(); 228 chdir_to_tmpfs();
215 229
@@ -221,30 +235,30 @@ static int do_tests(int uid, const char *our_path)
221 copy_fromat_to(ourpath_fd, "validate_cap", 235 copy_fromat_to(ourpath_fd, "validate_cap",
222 "validate_cap_suidroot"); 236 "validate_cap_suidroot");
223 if (chown("validate_cap_suidroot", 0, -1) != 0) 237 if (chown("validate_cap_suidroot", 0, -1) != 0)
224 err(1, "chown"); 238 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
225 if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0) 239 if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0)
226 err(1, "chmod"); 240 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
227 241
228 copy_fromat_to(ourpath_fd, "validate_cap", 242 copy_fromat_to(ourpath_fd, "validate_cap",
229 "validate_cap_suidnonroot"); 243 "validate_cap_suidnonroot");
230 if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0) 244 if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0)
231 err(1, "chown"); 245 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
232 if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0) 246 if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0)
233 err(1, "chmod"); 247 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
234 248
235 copy_fromat_to(ourpath_fd, "validate_cap", 249 copy_fromat_to(ourpath_fd, "validate_cap",
236 "validate_cap_sgidroot"); 250 "validate_cap_sgidroot");
237 if (chown("validate_cap_sgidroot", -1, 0) != 0) 251 if (chown("validate_cap_sgidroot", -1, 0) != 0)
238 err(1, "chown"); 252 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
239 if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0) 253 if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0)
240 err(1, "chmod"); 254 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
241 255
242 copy_fromat_to(ourpath_fd, "validate_cap", 256 copy_fromat_to(ourpath_fd, "validate_cap",
243 "validate_cap_sgidnonroot"); 257 "validate_cap_sgidnonroot");
244 if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0) 258 if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0)
245 err(1, "chown"); 259 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
246 if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0) 260 if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
247 err(1, "chmod"); 261 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
248 } 262 }
249 263
250 capng_get_caps_process(); 264 capng_get_caps_process();
@@ -252,147 +266,162 @@ static int do_tests(int uid, const char *our_path)
252 /* Make sure that i starts out clear */ 266 /* Make sure that i starts out clear */
253 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 267 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
254 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 268 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
255 err(1, "capng_apply"); 269 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
256 270
257 if (uid == 0) { 271 if (uid == 0) {
258 printf("[RUN]\tRoot => ep\n"); 272 ksft_print_msg("[RUN]\tRoot => ep\n");
259 if (fork_wait()) 273 if (fork_wait())
260 exec_validate_cap(true, true, false, false); 274 exec_validate_cap(true, true, false, false);
261 } else { 275 } else {
262 printf("[RUN]\tNon-root => no caps\n"); 276 ksft_print_msg("[RUN]\tNon-root => no caps\n");
263 if (fork_wait()) 277 if (fork_wait())
264 exec_validate_cap(false, false, false, false); 278 exec_validate_cap(false, false, false, false);
265 } 279 }
266 280
267 printf("[OK]\tCheck cap_ambient manipulation rules\n"); 281 ksft_print_msg("Check cap_ambient manipulation rules\n");
268 282
269 /* We should not be able to add ambient caps yet. */ 283 /* We should not be able to add ambient caps yet. */
270 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) { 284 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) {
271 if (errno == EINVAL) 285 if (errno == EINVAL)
272 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE isn't supported\n"); 286 ksft_test_result_fail(
287 "PR_CAP_AMBIENT_RAISE isn't supported\n");
273 else 288 else
274 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n"); 289 ksft_test_result_fail(
290 "PR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
275 return 1; 291 return 1;
276 } 292 }
277 printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n"); 293 ksft_test_result_pass(
294 "PR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
278 295
279 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW); 296 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW);
280 capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW); 297 capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW);
281 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW); 298 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW);
282 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 299 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
283 err(1, "capng_apply"); 300 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
284 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0, 0) != -1 || errno != EPERM) { 301 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0, 0) != -1 || errno != EPERM) {
285 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n"); 302 ksft_test_result_fail(
303 "PR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
286 return 1; 304 return 1;
287 } 305 }
288 printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-permitted cap\n"); 306 ksft_test_result_pass(
307 "PR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
289 308
290 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 309 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
291 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 310 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
292 err(1, "capng_apply"); 311 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
293 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 312 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
294 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have succeeded\n"); 313 ksft_test_result_fail(
314 "PR_CAP_AMBIENT_RAISE should have succeeded\n");
295 return 1; 315 return 1;
296 } 316 }
297 printf("[OK]\tPR_CAP_AMBIENT_RAISE worked\n"); 317 ksft_test_result_pass("PR_CAP_AMBIENT_RAISE worked\n");
298 318
299 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) { 319 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) {
300 printf("[FAIL]\tPR_CAP_AMBIENT_IS_SET is broken\n"); 320 ksft_test_result_fail("PR_CAP_AMBIENT_IS_SET is broken\n");
301 return 1; 321 return 1;
302 } 322 }
303 323
304 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0) 324 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0)
305 err(1, "PR_CAP_AMBIENT_CLEAR_ALL"); 325 ksft_exit_fail_msg("PR_CAP_AMBIENT_CLEAR_ALL - %s\n",
326 strerror(errno));
306 327
307 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 328 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
308 printf("[FAIL]\tPR_CAP_AMBIENT_CLEAR_ALL didn't work\n"); 329 ksft_test_result_fail(
330 "PR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
309 return 1; 331 return 1;
310 } 332 }
311 333
312 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) 334 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
313 err(1, "PR_CAP_AMBIENT_RAISE"); 335 ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
336 strerror(errno));
314 337
315 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 338 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
316 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 339 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
317 err(1, "capng_apply"); 340 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
318 341
319 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 342 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
320 printf("[FAIL]\tDropping I should have dropped A\n"); 343 ksft_test_result_fail("Dropping I should have dropped A\n");
321 return 1; 344 return 1;
322 } 345 }
323 346
324 printf("[OK]\tBasic manipulation appears to work\n"); 347 ksft_test_result_pass("Basic manipulation appears to work\n");
325 348
326 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 349 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
327 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 350 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
328 err(1, "capng_apply"); 351 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
329 if (uid == 0) { 352 if (uid == 0) {
330 printf("[RUN]\tRoot +i => eip\n"); 353 ksft_print_msg("[RUN]\tRoot +i => eip\n");
331 if (fork_wait()) 354 if (fork_wait())
332 exec_validate_cap(true, true, true, false); 355 exec_validate_cap(true, true, true, false);
333 } else { 356 } else {
334 printf("[RUN]\tNon-root +i => i\n"); 357 ksft_print_msg("[RUN]\tNon-root +i => i\n");
335 if (fork_wait()) 358 if (fork_wait())
336 exec_validate_cap(false, false, true, false); 359 exec_validate_cap(false, false, true, false);
337 } 360 }
338 361
339 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) 362 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
340 err(1, "PR_CAP_AMBIENT_RAISE"); 363 ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
364 strerror(errno));
341 365
342 printf("[RUN]\tUID %d +ia => eipa\n", uid); 366 ksft_print_msg("[RUN]\tUID %d +ia => eipa\n", uid);
343 if (fork_wait()) 367 if (fork_wait())
344 exec_validate_cap(true, true, true, true); 368 exec_validate_cap(true, true, true, true);
345 369
346 /* The remaining tests need real privilege */ 370 /* The remaining tests need real privilege */
347 371
348 if (!have_outer_privilege) { 372 if (!have_outer_privilege) {
349 printf("[SKIP]\tSUID/SGID tests (needs privilege)\n"); 373 ksft_test_result_skip("SUID/SGID tests (needs privilege)\n");
350 goto done; 374 goto done;
351 } 375 }
352 376
353 if (uid == 0) { 377 if (uid == 0) {
354 printf("[RUN]\tRoot +ia, suidroot => eipa\n"); 378 ksft_print_msg("[RUN]\tRoot +ia, suidroot => eipa\n");
355 if (fork_wait()) 379 if (fork_wait())
356 exec_other_validate_cap("./validate_cap_suidroot", 380 exec_other_validate_cap("./validate_cap_suidroot",
357 true, true, true, true); 381 true, true, true, true);
358 382
359 printf("[RUN]\tRoot +ia, suidnonroot => ip\n"); 383 ksft_print_msg("[RUN]\tRoot +ia, suidnonroot => ip\n");
360 if (fork_wait()) 384 if (fork_wait())
361 exec_other_validate_cap("./validate_cap_suidnonroot", 385 exec_other_validate_cap("./validate_cap_suidnonroot",
362 false, true, true, false); 386 false, true, true, false);
363 387
364 printf("[RUN]\tRoot +ia, sgidroot => eipa\n"); 388 ksft_print_msg("[RUN]\tRoot +ia, sgidroot => eipa\n");
365 if (fork_wait()) 389 if (fork_wait())
366 exec_other_validate_cap("./validate_cap_sgidroot", 390 exec_other_validate_cap("./validate_cap_sgidroot",
367 true, true, true, true); 391 true, true, true, true);
368 392
369 if (fork_wait()) { 393 if (fork_wait()) {
370 printf("[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n"); 394 ksft_print_msg(
395 "[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
371 if (setresgid(1, 1, 1) != 0) 396 if (setresgid(1, 1, 1) != 0)
372 err(1, "setresgid"); 397 ksft_exit_fail_msg("setresgid - %s\n",
398 strerror(errno));
373 exec_other_validate_cap("./validate_cap_sgidroot", 399 exec_other_validate_cap("./validate_cap_sgidroot",
374 true, true, true, false); 400 true, true, true, false);
375 } 401 }
376 402
377 printf("[RUN]\tRoot +ia, sgidnonroot => eip\n"); 403 ksft_print_msg("[RUN]\tRoot +ia, sgidnonroot => eip\n");
378 if (fork_wait()) 404 if (fork_wait())
379 exec_other_validate_cap("./validate_cap_sgidnonroot", 405 exec_other_validate_cap("./validate_cap_sgidnonroot",
380 true, true, true, false); 406 true, true, true, false);
381 } else { 407 } else {
382 printf("[RUN]\tNon-root +ia, sgidnonroot => i\n"); 408 ksft_print_msg("[RUN]\tNon-root +ia, sgidnonroot => i\n");
383 exec_other_validate_cap("./validate_cap_sgidnonroot", 409 if (fork_wait())
410 exec_other_validate_cap("./validate_cap_sgidnonroot",
384 false, false, true, false); 411 false, false, true, false);
385 412
386 if (fork_wait()) { 413 if (fork_wait()) {
387 printf("[RUN]\tNon-root +ia, sgidroot => i\n"); 414 ksft_print_msg("[RUN]\tNon-root +ia, sgidroot => i\n");
388 if (setresgid(1, 1, 1) != 0) 415 if (setresgid(1, 1, 1) != 0)
389 err(1, "setresgid"); 416 ksft_exit_fail_msg("setresgid - %s\n",
417 strerror(errno));
390 exec_other_validate_cap("./validate_cap_sgidroot", 418 exec_other_validate_cap("./validate_cap_sgidroot",
391 false, false, true, false); 419 false, false, true, false);
392 } 420 }
393 } 421 }
394 422
395done: 423done:
424 ksft_print_cnts();
396 return nerrs ? 1 : 0; 425 return nerrs ? 1 : 0;
397} 426}
398 427
@@ -400,23 +429,29 @@ int main(int argc, char **argv)
400{ 429{
401 char *tmp1, *tmp2, *our_path; 430 char *tmp1, *tmp2, *our_path;
402 431
432 ksft_print_header();
433
403 /* Find our path */ 434 /* Find our path */
404 tmp1 = strdup(argv[0]); 435 tmp1 = strdup(argv[0]);
405 if (!tmp1) 436 if (!tmp1)
406 err(1, "strdup"); 437 ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
407 tmp2 = dirname(tmp1); 438 tmp2 = dirname(tmp1);
408 our_path = strdup(tmp2); 439 our_path = strdup(tmp2);
409 if (!our_path) 440 if (!our_path)
410 err(1, "strdup"); 441 ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
411 free(tmp1); 442 free(tmp1);
412 443
444 mpid = getpid();
445
413 if (fork_wait()) { 446 if (fork_wait()) {
414 printf("[RUN]\t+++ Tests with uid == 0 +++\n"); 447 ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n");
415 return do_tests(0, our_path); 448 return do_tests(0, our_path);
416 } 449 }
417 450
451 ksft_print_msg("==================================================\n");
452
418 if (fork_wait()) { 453 if (fork_wait()) {
419 printf("[RUN]\t+++ Tests with uid != 0 +++\n"); 454 ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n");
420 return do_tests(1, our_path); 455 return do_tests(1, our_path);
421 } 456 }
422 457
diff --git a/tools/testing/selftests/capabilities/validate_cap.c b/tools/testing/selftests/capabilities/validate_cap.c
index dd3c45f7b23c..694cd73d4493 100644
--- a/tools/testing/selftests/capabilities/validate_cap.c
+++ b/tools/testing/selftests/capabilities/validate_cap.c
@@ -1,5 +1,4 @@
1#include <cap-ng.h> 1#include <cap-ng.h>
2#include <err.h>
3#include <linux/capability.h> 2#include <linux/capability.h>
4#include <stdbool.h> 3#include <stdbool.h>
5#include <string.h> 4#include <string.h>
@@ -7,6 +6,8 @@
7#include <sys/prctl.h> 6#include <sys/prctl.h>
8#include <sys/auxv.h> 7#include <sys/auxv.h>
9 8
9#include "../kselftest.h"
10
10#ifndef PR_CAP_AMBIENT 11#ifndef PR_CAP_AMBIENT
11#define PR_CAP_AMBIENT 47 12#define PR_CAP_AMBIENT 47
12# define PR_CAP_AMBIENT_IS_SET 1 13# define PR_CAP_AMBIENT_IS_SET 1
@@ -25,8 +26,10 @@ static bool bool_arg(char **argv, int i)
25 return false; 26 return false;
26 else if (!strcmp(argv[i], "1")) 27 else if (!strcmp(argv[i], "1"))
27 return true; 28 return true;
28 else 29 else {
29 errx(1, "wrong argv[%d]", i); 30 ksft_exit_fail_msg("wrong argv[%d]\n", i);
31 return false;
32 }
30} 33}
31 34
32int main(int argc, char **argv) 35int main(int argc, char **argv)
@@ -39,7 +42,7 @@ int main(int argc, char **argv)
39 */ 42 */
40 43
41 if (argc != 5) 44 if (argc != 5)
42 errx(1, "wrong argc"); 45 ksft_exit_fail_msg("wrong argc\n");
43 46
44#ifdef HAVE_GETAUXVAL 47#ifdef HAVE_GETAUXVAL
45 if (getauxval(AT_SECURE)) 48 if (getauxval(AT_SECURE))
@@ -51,23 +54,26 @@ int main(int argc, char **argv)
51 capng_get_caps_process(); 54 capng_get_caps_process();
52 55
53 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) { 56 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
54 printf("[FAIL]\tWrong effective state%s\n", atsec); 57 ksft_print_msg("Wrong effective state%s\n", atsec);
55 return 1; 58 return 1;
56 } 59 }
60
57 if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) { 61 if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) {
58 printf("[FAIL]\tWrong permitted state%s\n", atsec); 62 ksft_print_msg("Wrong permitted state%s\n", atsec);
59 return 1; 63 return 1;
60 } 64 }
65
61 if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) { 66 if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) {
62 printf("[FAIL]\tWrong inheritable state%s\n", atsec); 67 ksft_print_msg("Wrong inheritable state%s\n", atsec);
63 return 1; 68 return 1;
64 } 69 }
65 70
66 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) { 71 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) {
67 printf("[FAIL]\tWrong ambient state%s\n", atsec); 72 ksft_print_msg("Wrong ambient state%s\n", atsec);
68 return 1; 73 return 1;
69 } 74 }
70 75
71 printf("[OK]\tCapabilities after execve were correct\n"); 76 ksft_print_msg("%s: Capabilities after execve were correct\n",
77 "validate_cap:");
72 return 0; 78 return 0;
73} 79}
diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
index 98b1d6565f2c..b18b253d7bfb 100755
--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
+++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
@@ -28,6 +28,12 @@ prerequisite()
28 echo "CPU online/offline summary:" 28 echo "CPU online/offline summary:"
29 online_cpus=`cat $SYSFS/devices/system/cpu/online` 29 online_cpus=`cat $SYSFS/devices/system/cpu/online`
30 online_max=${online_cpus##*-} 30 online_max=${online_cpus##*-}
31
32 if [[ "$online_cpus" = "$online_max" ]]; then
33 echo "$msg: since there is only one cpu: $online_cpus"
34 exit 0
35 fi
36
31 echo -e "\t Cpus in online state: $online_cpus" 37 echo -e "\t Cpus in online state: $online_cpus"
32 38
33 offline_cpus=`cat $SYSFS/devices/system/cpu/offline` 39 offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -89,8 +95,10 @@ online_cpu_expect_success()
89 95
90 if ! online_cpu $cpu; then 96 if ! online_cpu $cpu; then
91 echo $FUNCNAME $cpu: unexpected fail >&2 97 echo $FUNCNAME $cpu: unexpected fail >&2
98 exit 1
92 elif ! cpu_is_online $cpu; then 99 elif ! cpu_is_online $cpu; then
93 echo $FUNCNAME $cpu: unexpected offline >&2 100 echo $FUNCNAME $cpu: unexpected offline >&2
101 exit 1
94 fi 102 fi
95} 103}
96 104
@@ -100,8 +108,10 @@ online_cpu_expect_fail()
100 108
101 if online_cpu $cpu 2> /dev/null; then 109 if online_cpu $cpu 2> /dev/null; then
102 echo $FUNCNAME $cpu: unexpected success >&2 110 echo $FUNCNAME $cpu: unexpected success >&2
111 exit 1
103 elif ! cpu_is_offline $cpu; then 112 elif ! cpu_is_offline $cpu; then
104 echo $FUNCNAME $cpu: unexpected online >&2 113 echo $FUNCNAME $cpu: unexpected online >&2
114 exit 1
105 fi 115 fi
106} 116}
107 117
@@ -111,8 +121,10 @@ offline_cpu_expect_success()
111 121
112 if ! offline_cpu $cpu; then 122 if ! offline_cpu $cpu; then
113 echo $FUNCNAME $cpu: unexpected fail >&2 123 echo $FUNCNAME $cpu: unexpected fail >&2
124 exit 1
114 elif ! cpu_is_offline $cpu; then 125 elif ! cpu_is_offline $cpu; then
115 echo $FUNCNAME $cpu: unexpected offline >&2 126 echo $FUNCNAME $cpu: unexpected offline >&2
127 exit 1
116 fi 128 fi
117} 129}
118 130
@@ -122,8 +134,10 @@ offline_cpu_expect_fail()
122 134
123 if offline_cpu $cpu 2> /dev/null; then 135 if offline_cpu $cpu 2> /dev/null; then
124 echo $FUNCNAME $cpu: unexpected success >&2 136 echo $FUNCNAME $cpu: unexpected success >&2
137 exit 1
125 elif ! cpu_is_online $cpu; then 138 elif ! cpu_is_online $cpu; then
126 echo $FUNCNAME $cpu: unexpected offline >&2 139 echo $FUNCNAME $cpu: unexpected offline >&2
140 exit 1
127 fi 141 fi
128} 142}
129 143
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 14a03ea1e21d..abc706cf7702 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -8,15 +8,18 @@
8# Released under the terms of the GPL v2. 8# Released under the terms of the GPL v2.
9 9
10usage() { # errno [message] 10usage() { # errno [message]
11[ "$2" ] && echo $2 11[ ! -z "$2" ] && echo $2
12echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]" 12echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
13echo " Options:" 13echo " Options:"
14echo " -h|--help Show help message" 14echo " -h|--help Show help message"
15echo " -k|--keep Keep passed test logs" 15echo " -k|--keep Keep passed test logs"
16echo " -v|--verbose Increase verbosity of test messages" 16echo " -v|--verbose Increase verbosity of test messages"
17echo " -vv Alias of -v -v (Show all results in stdout)" 17echo " -vv Alias of -v -v (Show all results in stdout)"
18echo " -vvv Alias of -v -v -v (Show all commands immediately)"
19echo " --fail-unsupported Treat UNSUPPORTED as a failure"
18echo " -d|--debug Debug mode (trace all shell commands)" 20echo " -d|--debug Debug mode (trace all shell commands)"
19echo " -l|--logdir <dir> Save logs on the <dir>" 21echo " -l|--logdir <dir> Save logs on the <dir>"
22echo " If <dir> is -, all logs output in console only"
20exit $1 23exit $1
21} 24}
22 25
@@ -47,7 +50,7 @@ parse_opts() { # opts
47 local OPT_TEST_CASES= 50 local OPT_TEST_CASES=
48 local OPT_TEST_DIR= 51 local OPT_TEST_DIR=
49 52
50 while [ "$1" ]; do 53 while [ ! -z "$1" ]; do
51 case "$1" in 54 case "$1" in
52 --help|-h) 55 --help|-h)
53 usage 0 56 usage 0
@@ -56,15 +59,20 @@ parse_opts() { # opts
56 KEEP_LOG=1 59 KEEP_LOG=1
57 shift 1 60 shift 1
58 ;; 61 ;;
59 --verbose|-v|-vv) 62 --verbose|-v|-vv|-vvv)
60 VERBOSE=$((VERBOSE + 1)) 63 VERBOSE=$((VERBOSE + 1))
61 [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1)) 64 [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
65 [ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2))
62 shift 1 66 shift 1
63 ;; 67 ;;
64 --debug|-d) 68 --debug|-d)
65 DEBUG=1 69 DEBUG=1
66 shift 1 70 shift 1
67 ;; 71 ;;
72 --fail-unsupported)
73 UNSUPPORTED_RESULT=1
74 shift 1
75 ;;
68 --logdir|-l) 76 --logdir|-l)
69 LOG_DIR=$2 77 LOG_DIR=$2
70 shift 2 78 shift 2
@@ -88,7 +96,7 @@ parse_opts() { # opts
88 ;; 96 ;;
89 esac 97 esac
90 done 98 done
91 if [ "$OPT_TEST_CASES" ]; then 99 if [ ! -z "$OPT_TEST_CASES" ]; then
92 TEST_CASES=$OPT_TEST_CASES 100 TEST_CASES=$OPT_TEST_CASES
93 fi 101 fi
94} 102}
@@ -108,6 +116,7 @@ LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
108KEEP_LOG=0 116KEEP_LOG=0
109DEBUG=0 117DEBUG=0
110VERBOSE=0 118VERBOSE=0
119UNSUPPORTED_RESULT=0
111# Parse command-line options 120# Parse command-line options
112parse_opts $* 121parse_opts $*
113 122
@@ -119,14 +128,20 @@ if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
119fi 128fi
120 129
121# Preparing logs 130# Preparing logs
122LOG_FILE=$LOG_DIR/ftracetest.log 131if [ "x$LOG_DIR" = "x-" ]; then
123mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR" 132 LOG_FILE=
124date > $LOG_FILE 133 date
134else
135 LOG_FILE=$LOG_DIR/ftracetest.log
136 mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
137 date > $LOG_FILE
138fi
139
125prlog() { # messages 140prlog() { # messages
126 echo "$@" | tee -a $LOG_FILE 141 [ -z "$LOG_FILE" ] && echo "$@" || echo "$@" | tee -a $LOG_FILE
127} 142}
128catlog() { #file 143catlog() { #file
129 cat $1 | tee -a $LOG_FILE 144 [ -z "$LOG_FILE" ] && cat $1 || cat $1 | tee -a $LOG_FILE
130} 145}
131prlog "=== Ftrace unit tests ===" 146prlog "=== Ftrace unit tests ==="
132 147
@@ -187,7 +202,7 @@ eval_result() { # sigval
187 $UNSUPPORTED) 202 $UNSUPPORTED)
188 prlog " [UNSUPPORTED]" 203 prlog " [UNSUPPORTED]"
189 UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO" 204 UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
190 return 1 # this is not a bug, but the result should be reported. 205 return $UNSUPPORTED_RESULT # depends on use case
191 ;; 206 ;;
192 $XFAIL) 207 $XFAIL)
193 prlog " [XFAIL]" 208 prlog " [XFAIL]"
@@ -247,12 +262,20 @@ __run_test() { # testfile
247# Run one test case 262# Run one test case
248run_test() { # testfile 263run_test() { # testfile
249 local testname=`basename $1` 264 local testname=`basename $1`
250 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` 265 if [ ! -z "$LOG_FILE" ] ; then
266 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
267 else
268 local testlog=/proc/self/fd/1
269 fi
251 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX` 270 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
252 testcase $1 271 testcase $1
253 echo "execute$INSTANCE: "$1 > $testlog 272 echo "execute$INSTANCE: "$1 > $testlog
254 SIG_RESULT=0 273 SIG_RESULT=0
255 if [ $VERBOSE -ge 2 ]; then 274 if [ -z "$LOG_FILE" ]; then
275 __run_test $1 2>&1
276 elif [ $VERBOSE -ge 3 ]; then
277 __run_test $1 | tee -a $testlog 2>&1
278 elif [ $VERBOSE -eq 2 ]; then
256 __run_test $1 2>> $testlog | tee -a $testlog 279 __run_test $1 2>> $testlog | tee -a $testlog
257 else 280 else
258 __run_test $1 >> $testlog 2>&1 281 __run_test $1 >> $testlog 2>&1
@@ -260,9 +283,9 @@ run_test() { # testfile
260 eval_result $SIG_RESULT 283 eval_result $SIG_RESULT
261 if [ $? -eq 0 ]; then 284 if [ $? -eq 0 ]; then
262 # Remove test log if the test was done as it was expected. 285 # Remove test log if the test was done as it was expected.
263 [ $KEEP_LOG -eq 0 ] && rm $testlog 286 [ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog
264 else 287 else
265 [ $VERBOSE -ge 1 ] && catlog $testlog 288 [ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog
266 TOTAL_RESULT=1 289 TOTAL_RESULT=1
267 fi 290 fi
268 rm -rf $TMPDIR 291 rm -rf $TMPDIR
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
index 2a1cb9908746..a4fd4c851a5b 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
@@ -1,6 +1,8 @@
1#!/bin/sh 1#!/bin/sh
2# description: Register/unregister many kprobe events 2# description: Register/unregister many kprobe events
3 3
4[ -f kprobe_events ] || exit_unsupported # this is configurable
5
4# ftrace fentry skip size depends on the machine architecture. 6# ftrace fentry skip size depends on the machine architecture.
5# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le 7# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
6case `uname -m` in 8case `uname -m` in
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile
index 7c647f619d63..f0c0369ccb79 100644
--- a/tools/testing/selftests/futex/Makefile
+++ b/tools/testing/selftests/futex/Makefile
@@ -7,14 +7,17 @@ TEST_PROGS := run.sh
7include ../lib.mk 7include ../lib.mk
8 8
9all: 9all:
10 for DIR in $(SUBDIRS); do \ 10 @for DIR in $(SUBDIRS); do \
11 BUILD_TARGET=$(OUTPUT)/$$DIR; \ 11 BUILD_TARGET=$(OUTPUT)/$$DIR; \
12 mkdir $$BUILD_TARGET -p; \ 12 mkdir $$BUILD_TARGET -p; \
13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ 13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
14 if [ -e $$DIR/$(TEST_PROGS) ]; then
15 rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/;
16 fi
14 done 17 done
15 18
16override define RUN_TESTS 19override define RUN_TESTS
17 $(OUTPUT)/run.sh 20 @cd $(OUTPUT); ./run.sh
18endef 21endef
19 22
20override define INSTALL_RULE 23override define INSTALL_RULE
@@ -33,7 +36,7 @@ override define EMIT_TESTS
33endef 36endef
34 37
35override define CLEAN 38override define CLEAN
36 for DIR in $(SUBDIRS); do \ 39 @for DIR in $(SUBDIRS); do \
37 BUILD_TARGET=$(OUTPUT)/$$DIR; \ 40 BUILD_TARGET=$(OUTPUT)/$$DIR; \
38 mkdir $$BUILD_TARGET -p; \ 41 mkdir $$BUILD_TARGET -p; \
39 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ 42 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi.c b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
index d24ab7421e73..54cd5c414e82 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
@@ -394,9 +394,11 @@ int main(int argc, char *argv[])
394 } 394 }
395 } 395 }
396 396
397 printf("%s: Test requeue functionality\n", basename(argv[0])); 397 ksft_print_header();
398 printf("\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n", 398 ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0]));
399 broadcast, locked, owner, timeout_ns); 399 ksft_print_msg(
400 "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
401 broadcast, locked, owner, timeout_ns);
400 402
401 /* 403 /*
402 * FIXME: unit_test is obsolete now that we parse options and the 404 * FIXME: unit_test is obsolete now that we parse options and the
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
index e0a798ad0d21..08187a16507f 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
@@ -78,7 +78,8 @@ int main(int argc, char *argv[])
78 } 78 }
79 } 79 }
80 80
81 printf("%s: Detect mismatched requeue_pi operations\n", 81 ksft_print_header();
82 ksft_print_msg("%s: Detect mismatched requeue_pi operations\n",
82 basename(argv[0])); 83 basename(argv[0]));
83 84
84 if (pthread_create(&child, NULL, blocking_child, NULL)) { 85 if (pthread_create(&child, NULL, blocking_child, NULL)) {
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
index 982f83577501..f0542a344d95 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
@@ -143,9 +143,10 @@ int main(int argc, char *argv[])
143 } 143 }
144 } 144 }
145 145
146 printf("%s: Test signal handling during requeue_pi\n", 146 ksft_print_header();
147 ksft_print_msg("%s: Test signal handling during requeue_pi\n",
147 basename(argv[0])); 148 basename(argv[0]));
148 printf("\tArguments: <none>\n"); 149 ksft_print_msg("\tArguments: <none>\n");
149 150
150 sa.sa_handler = handle_signal; 151 sa.sa_handler = handle_signal;
151 sigemptyset(&sa.sa_mask); 152 sigemptyset(&sa.sa_mask);
diff --git a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
index bdc48dc047e5..6216de828093 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
@@ -97,8 +97,10 @@ int main(int argc, char **argv)
97 } 97 }
98 } 98 }
99 99
100 printf("%s: Test the futex value of private file mappings in FUTEX_WAIT\n", 100 ksft_print_header();
101 basename(argv[0])); 101 ksft_print_msg(
102 "%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
103 basename(argv[0]));
102 104
103 ret = pthread_create(&thr, NULL, thr_futex_wait, NULL); 105 ret = pthread_create(&thr, NULL, thr_futex_wait, NULL);
104 if (ret < 0) { 106 if (ret < 0) {
diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
index 6aadd560366e..bab3dfe1787f 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
@@ -68,9 +68,10 @@ int main(int argc, char *argv[])
68 } 68 }
69 } 69 }
70 70
71 printf("%s: Block on a futex and wait for timeout\n", 71 ksft_print_header();
72 ksft_print_msg("%s: Block on a futex and wait for timeout\n",
72 basename(argv[0])); 73 basename(argv[0]));
73 printf("\tArguments: timeout=%ldns\n", timeout_ns); 74 ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
74 75
75 /* initialize timeout */ 76 /* initialize timeout */
76 to.tv_sec = 0; 77 to.tv_sec = 0;
diff --git a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
index d237a8b702f0..26975322545b 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
@@ -99,7 +99,8 @@ int main(int argc, char **argv)
99 exit(1); 99 exit(1);
100 } 100 }
101 101
102 printf("%s: Test the uninitialized futex value in FUTEX_WAIT\n", 102 ksft_print_header();
103 ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
103 basename(argv[0])); 104 basename(argv[0]));
104 105
105 106
diff --git a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
index 9a2c56fa7305..da15a63269b4 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
@@ -64,7 +64,8 @@ int main(int argc, char *argv[])
64 } 64 }
65 } 65 }
66 66
67 printf("%s: Test the unexpected futex value in FUTEX_WAIT\n", 67 ksft_print_header();
68 ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n",
68 basename(argv[0])); 69 basename(argv[0]));
69 70
70 info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); 71 info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1);
diff --git a/tools/testing/selftests/futex/include/logging.h b/tools/testing/selftests/futex/include/logging.h
index 4e7944984fbb..01989644e50a 100644
--- a/tools/testing/selftests/futex/include/logging.h
+++ b/tools/testing/selftests/futex/include/logging.h
@@ -109,22 +109,20 @@ void log_verbosity(int level)
109 */ 109 */
110void print_result(const char *test_name, int ret) 110void print_result(const char *test_name, int ret)
111{ 111{
112 const char *result = "Unknown return code";
113
114 switch (ret) { 112 switch (ret) {
115 case RET_PASS: 113 case RET_PASS:
116 ksft_inc_pass_cnt(); 114 ksft_test_result_pass("%s\n", test_name);
117 result = PASS; 115 ksft_print_cnts();
118 break; 116 return;
119 case RET_ERROR: 117 case RET_ERROR:
120 result = ERROR; 118 ksft_test_result_error("%s\n", test_name);
121 break; 119 ksft_print_cnts();
120 return;
122 case RET_FAIL: 121 case RET_FAIL:
123 ksft_inc_fail_cnt(); 122 ksft_test_result_fail("%s\n", test_name);
124 result = FAIL; 123 ksft_print_cnts();
125 break; 124 return;
126 } 125 }
127 printf("selftests: %s [%s]\n", test_name, result);
128} 126}
129 127
130/* log level macros */ 128/* log level macros */
diff --git a/tools/testing/selftests/intel_pstate/Makefile b/tools/testing/selftests/intel_pstate/Makefile
index 849a90ffe8dd..a97e24edde39 100644
--- a/tools/testing/selftests/intel_pstate/Makefile
+++ b/tools/testing/selftests/intel_pstate/Makefile
@@ -1,7 +1,9 @@
1CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE 1CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
2LDLIBS := $(LDLIBS) -lm 2LDLIBS := $(LDLIBS) -lm
3 3
4ifeq (,$(filter $(ARCH),x86))
4TEST_GEN_FILES := msr aperf 5TEST_GEN_FILES := msr aperf
6endif
5 7
6TEST_PROGS := run.sh 8TEST_PROGS := run.sh
7 9
diff --git a/tools/testing/selftests/intel_pstate/run.sh b/tools/testing/selftests/intel_pstate/run.sh
index 7868c106b8b1..d3ab48f91cd6 100755
--- a/tools/testing/selftests/intel_pstate/run.sh
+++ b/tools/testing/selftests/intel_pstate/run.sh
@@ -29,13 +29,12 @@
29 29
30EVALUATE_ONLY=0 30EVALUATE_ONLY=0
31 31
32max_cpus=$(($(nproc)-1)) 32if ! uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ | grep -q x86; then
33 echo "$0 # Skipped: Test can only run on x86 architectures."
34 exit 0
35fi
33 36
34# compile programs 37max_cpus=$(($(nproc)-1))
35gcc aperf.c -Wall -D_GNU_SOURCE -o aperf -lm
36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
37gcc -o msr msr.c -lm
38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
39 38
40function run_test () { 39function run_test () {
41 40
diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c
index a5a4da856dfe..73684c4a1ed6 100644
--- a/tools/testing/selftests/kcmp/kcmp_test.c
+++ b/tools/testing/selftests/kcmp/kcmp_test.c
@@ -8,7 +8,6 @@
8#include <errno.h> 8#include <errno.h>
9#include <string.h> 9#include <string.h>
10#include <fcntl.h> 10#include <fcntl.h>
11
12#include <linux/unistd.h> 11#include <linux/unistd.h>
13#include <linux/kcmp.h> 12#include <linux/kcmp.h>
14 13
@@ -16,20 +15,28 @@
16#include <sys/types.h> 15#include <sys/types.h>
17#include <sys/stat.h> 16#include <sys/stat.h>
18#include <sys/wait.h> 17#include <sys/wait.h>
18#include <sys/epoll.h>
19 19
20#include "../kselftest.h" 20#include "../kselftest.h"
21 21
22static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) 22static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
23{ 23{
24 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); 24 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
25} 25}
26 26
27static const unsigned int duped_num = 64;
28
27int main(int argc, char **argv) 29int main(int argc, char **argv)
28{ 30{
29 const char kpath[] = "kcmp-test-file"; 31 const char kpath[] = "kcmp-test-file";
32 struct kcmp_epoll_slot epoll_slot;
33 struct epoll_event ev;
30 int pid1, pid2; 34 int pid1, pid2;
35 int pipefd[2];
31 int fd1, fd2; 36 int fd1, fd2;
37 int epollfd;
32 int status; 38 int status;
39 int fddup;
33 40
34 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644); 41 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
35 pid1 = getpid(); 42 pid1 = getpid();
@@ -39,6 +46,37 @@ int main(int argc, char **argv)
39 ksft_exit_fail(); 46 ksft_exit_fail();
40 } 47 }
41 48
49 if (pipe(pipefd)) {
50 perror("Can't create pipe");
51 ksft_exit_fail();
52 }
53
54 epollfd = epoll_create1(0);
55 if (epollfd < 0) {
56 perror("epoll_create1 failed");
57 ksft_exit_fail();
58 }
59
60 memset(&ev, 0xff, sizeof(ev));
61 ev.events = EPOLLIN | EPOLLOUT;
62
63 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
64 perror("epoll_ctl failed");
65 ksft_exit_fail();
66 }
67
68 fddup = dup2(pipefd[1], duped_num);
69 if (fddup < 0) {
70 perror("dup2 failed");
71 ksft_exit_fail();
72 }
73
74 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
75 perror("epoll_ctl failed");
76 ksft_exit_fail();
77 }
78 close(fddup);
79
42 pid2 = fork(); 80 pid2 = fork();
43 if (pid2 < 0) { 81 if (pid2 < 0) {
44 perror("fork failed"); 82 perror("fork failed");
@@ -95,6 +133,24 @@ int main(int argc, char **argv)
95 ksft_inc_pass_cnt(); 133 ksft_inc_pass_cnt();
96 } 134 }
97 135
136 /* Compare epoll target */
137 epoll_slot = (struct kcmp_epoll_slot) {
138 .efd = epollfd,
139 .tfd = duped_num,
140 .toff = 0,
141 };
142 ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
143 (unsigned long)(void *)&epoll_slot);
144 if (ret) {
145 printf("FAIL: 0 expected but %d returned (%s)\n",
146 ret, strerror(errno));
147 ksft_inc_fail_cnt();
148 ret = -1;
149 } else {
150 printf("PASS: 0 returned as expected\n");
151 ksft_inc_pass_cnt();
152 }
153
98 ksft_print_cnts(); 154 ksft_print_cnts();
99 155
100 if (ret) 156 if (ret)
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 08e90c2cc5cb..1ae565ed9bf0 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -19,7 +19,8 @@
19#define KSFT_FAIL 1 19#define KSFT_FAIL 1
20#define KSFT_XFAIL 2 20#define KSFT_XFAIL 2
21#define KSFT_XPASS 3 21#define KSFT_XPASS 3
22#define KSFT_SKIP 4 22/* Treat skip as pass */
23#define KSFT_SKIP KSFT_PASS
23 24
24/* counters */ 25/* counters */
25struct ksft_count { 26struct ksft_count {
@@ -28,6 +29,7 @@ struct ksft_count {
28 unsigned int ksft_xfail; 29 unsigned int ksft_xfail;
29 unsigned int ksft_xpass; 30 unsigned int ksft_xpass;
30 unsigned int ksft_xskip; 31 unsigned int ksft_xskip;
32 unsigned int ksft_error;
31}; 33};
32 34
33static struct ksft_count ksft_cnt; 35static struct ksft_count ksft_cnt;
@@ -36,7 +38,7 @@ static inline int ksft_test_num(void)
36{ 38{
37 return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail + 39 return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
38 ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass + 40 ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
39 ksft_cnt.ksft_xskip; 41 ksft_cnt.ksft_xskip + ksft_cnt.ksft_error;
40} 42}
41 43
42static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; } 44static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
@@ -44,6 +46,14 @@ static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
44static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; } 46static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
45static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; } 47static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
46static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; } 48static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
49static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; }
50
51static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; }
52static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; }
53static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; }
54static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; }
55static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; }
56static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
47 57
48static inline void ksft_print_header(void) 58static inline void ksft_print_header(void)
49{ 59{
@@ -52,6 +62,10 @@ static inline void ksft_print_header(void)
52 62
53static inline void ksft_print_cnts(void) 63static inline void ksft_print_cnts(void)
54{ 64{
65 printf("Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n",
66 ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
67 ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
68 ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
55 printf("1..%d\n", ksft_test_num()); 69 printf("1..%d\n", ksft_test_num());
56} 70}
57 71
@@ -101,6 +115,18 @@ static inline void ksft_test_result_skip(const char *msg, ...)
101 va_end(args); 115 va_end(args);
102} 116}
103 117
118static inline void ksft_test_result_error(const char *msg, ...)
119{
120 va_list args;
121
122 ksft_cnt.ksft_error++;
123
124 va_start(args, msg);
125 printf("not ok %d # error ", ksft_test_num());
126 vprintf(msg, args);
127 va_end(args);
128}
129
104static inline int ksft_exit_pass(void) 130static inline int ksft_exit_pass(void)
105{ 131{
106 ksft_print_cnts(); 132 ksft_print_cnts();
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index c56f72e07cd7..e81bd28bdd89 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -51,6 +51,9 @@
51#define __KSELFTEST_HARNESS_H 51#define __KSELFTEST_HARNESS_H
52 52
53#define _GNU_SOURCE 53#define _GNU_SOURCE
54#include <asm/types.h>
55#include <errno.h>
56#include <stdbool.h>
54#include <stdint.h> 57#include <stdint.h>
55#include <stdio.h> 58#include <stdio.h>
56#include <stdlib.h> 59#include <stdlib.h>
@@ -84,6 +87,14 @@
84 * E.g., #define TH_LOG_ENABLED 1 87 * E.g., #define TH_LOG_ENABLED 1
85 * 88 *
86 * If no definition is provided, logging is enabled by default. 89 * If no definition is provided, logging is enabled by default.
90 *
91 * If there is no way to print an error message for the process running the
92 * test (e.g. not allowed to write to stderr), it is still possible to get the
93 * ASSERT_* number for which the test failed. This behavior can be enabled by
94 * writing `_metadata->no_print = true;` before the check sequence that is
95 * unable to print. When an error occur, instead of printing an error message
96 * and calling `abort(3)`, the test process call `_exit(2)` with the assert
97 * number as argument, which is then printed by the parent process.
87 */ 98 */
88#define TH_LOG(fmt, ...) do { \ 99#define TH_LOG(fmt, ...) do { \
89 if (TH_LOG_ENABLED) \ 100 if (TH_LOG_ENABLED) \
@@ -555,12 +566,18 @@
555 * return while still providing an optional block to the API consumer. 566 * return while still providing an optional block to the API consumer.
556 */ 567 */
557#define OPTIONAL_HANDLER(_assert) \ 568#define OPTIONAL_HANDLER(_assert) \
558 for (; _metadata->trigger; _metadata->trigger = __bail(_assert)) 569 for (; _metadata->trigger; _metadata->trigger = \
570 __bail(_assert, _metadata->no_print, _metadata->step))
571
572#define __INC_STEP(_metadata) \
573 if (_metadata->passed && _metadata->step < 255) \
574 _metadata->step++;
559 575
560#define __EXPECT(_expected, _seen, _t, _assert) do { \ 576#define __EXPECT(_expected, _seen, _t, _assert) do { \
561 /* Avoid multiple evaluation of the cases */ \ 577 /* Avoid multiple evaluation of the cases */ \
562 __typeof__(_expected) __exp = (_expected); \ 578 __typeof__(_expected) __exp = (_expected); \
563 __typeof__(_seen) __seen = (_seen); \ 579 __typeof__(_seen) __seen = (_seen); \
580 if (_assert) __INC_STEP(_metadata); \
564 if (!(__exp _t __seen)) { \ 581 if (!(__exp _t __seen)) { \
565 unsigned long long __exp_print = (uintptr_t)__exp; \ 582 unsigned long long __exp_print = (uintptr_t)__exp; \
566 unsigned long long __seen_print = (uintptr_t)__seen; \ 583 unsigned long long __seen_print = (uintptr_t)__seen; \
@@ -576,6 +593,7 @@
576#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \ 593#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
577 const char *__exp = (_expected); \ 594 const char *__exp = (_expected); \
578 const char *__seen = (_seen); \ 595 const char *__seen = (_seen); \
596 if (_assert) __INC_STEP(_metadata); \
579 if (!(strcmp(__exp, __seen) _t 0)) { \ 597 if (!(strcmp(__exp, __seen) _t 0)) { \
580 __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \ 598 __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
581 _metadata->passed = 0; \ 599 _metadata->passed = 0; \
@@ -590,6 +608,8 @@ struct __test_metadata {
590 int termsig; 608 int termsig;
591 int passed; 609 int passed;
592 int trigger; /* extra handler after the evaluation */ 610 int trigger; /* extra handler after the evaluation */
611 __u8 step;
612 bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
593 struct __test_metadata *prev, *next; 613 struct __test_metadata *prev, *next;
594}; 614};
595 615
@@ -634,10 +654,13 @@ static inline void __register_test(struct __test_metadata *t)
634 } 654 }
635} 655}
636 656
637static inline int __bail(int for_realz) 657static inline int __bail(int for_realz, bool no_print, __u8 step)
638{ 658{
639 if (for_realz) 659 if (for_realz) {
660 if (no_print)
661 _exit(step);
640 abort(); 662 abort();
663 }
641 return 0; 664 return 0;
642} 665}
643 666
@@ -655,18 +678,24 @@ void __run_test(struct __test_metadata *t)
655 t->passed = 0; 678 t->passed = 0;
656 } else if (child_pid == 0) { 679 } else if (child_pid == 0) {
657 t->fn(t); 680 t->fn(t);
658 _exit(t->passed); 681 /* return the step that failed or 0 */
682 _exit(t->passed ? 0 : t->step);
659 } else { 683 } else {
660 /* TODO(wad) add timeout support. */ 684 /* TODO(wad) add timeout support. */
661 waitpid(child_pid, &status, 0); 685 waitpid(child_pid, &status, 0);
662 if (WIFEXITED(status)) { 686 if (WIFEXITED(status)) {
663 t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0; 687 t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
664 if (t->termsig != -1) { 688 if (t->termsig != -1) {
665 fprintf(TH_LOG_STREAM, 689 fprintf(TH_LOG_STREAM,
666 "%s: Test exited normally " 690 "%s: Test exited normally "
667 "instead of by signal (code: %d)\n", 691 "instead of by signal (code: %d)\n",
668 t->name, 692 t->name,
669 WEXITSTATUS(status)); 693 WEXITSTATUS(status));
694 } else if (!t->passed) {
695 fprintf(TH_LOG_STREAM,
696 "%s: Test failed at step #%d\n",
697 t->name,
698 WEXITSTATUS(status));
670 } 699 }
671 } else if (WIFSIGNALED(status)) { 700 } else if (WIFSIGNALED(status)) {
672 t->passed = 0; 701 t->passed = 0;
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
index 959273c3a52e..f65886af7c0c 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -6,20 +6,49 @@ ifeq (0,$(MAKELEVEL))
6OUTPUT := $(shell pwd) 6OUTPUT := $(shell pwd)
7endif 7endif
8 8
9# The following are built by lib.mk common compile rules.
10# TEST_CUSTOM_PROGS should be used by tests that require
11# custom build rule and prevent common build rule use.
12# TEST_PROGS are for test shell scripts.
13# TEST_CUSTOM_PROGS and TEST_PROGS will be run by common run_tests
14# and install targets. Common clean doesn't touch them.
9TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS)) 15TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
16TEST_GEN_PROGS_EXTENDED := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS_EXTENDED))
10TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES)) 17TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
11 18
12all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) 19all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
13 20
21.ONESHELL:
14define RUN_TESTS 22define RUN_TESTS
15 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \ 23 @test_num=`echo 0`;
24 @echo "TAP version 13";
25 @for TEST in $(1); do \
16 BASENAME_TEST=`basename $$TEST`; \ 26 BASENAME_TEST=`basename $$TEST`; \
17 cd `dirname $$TEST`; (./$$BASENAME_TEST && echo "selftests: $$BASENAME_TEST [PASS]") || echo "selftests: $$BASENAME_TEST [FAIL]"; cd -;\ 27 test_num=`echo $$test_num+1 | bc`; \
28 echo "selftests: $$BASENAME_TEST"; \
29 echo "========================================"; \
30 if [ ! -x $$TEST ]; then \
31 echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
32 echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
33 else \
34 cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
35 fi; \
18 done; 36 done;
19endef 37endef
20 38
21run_tests: all 39run_tests: all
22 $(RUN_TESTS) 40ifneq ($(KBUILD_SRC),)
41 @if [ "X$(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)" != "X" ]; then
42 @rsync -aq $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(OUTPUT)
43 fi
44 @if [ "X$(TEST_PROGS)" != "X" ]; then
45 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(OUTPUT)/$(TEST_PROGS))
46 else
47 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS))
48 fi
49else
50 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS))
51endif
23 52
24define INSTALL_RULE 53define INSTALL_RULE
25 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \ 54 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
@@ -27,10 +56,10 @@ define INSTALL_RULE
27 echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \ 56 echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \
28 rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \ 57 rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \
29 fi 58 fi
30 @if [ "X$(TEST_GEN_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \ 59 @if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \
31 mkdir -p ${INSTALL_PATH}; \ 60 mkdir -p ${INSTALL_PATH}; \
32 echo "rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \ 61 echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \
33 rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \ 62 rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \
34 fi 63 fi
35endef 64endef
36 65
@@ -42,15 +71,20 @@ else
42endif 71endif
43 72
44define EMIT_TESTS 73define EMIT_TESTS
45 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \ 74 @for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \
46 BASENAME_TEST=`basename $$TEST`; \ 75 BASENAME_TEST=`basename $$TEST`; \
47 echo "(./$$BASENAME_TEST && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \ 76 echo "(./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
48 done; 77 done;
49endef 78endef
50 79
51emit_tests: 80emit_tests:
52 $(EMIT_TESTS) 81 $(EMIT_TESTS)
53 82
83# define if isn't already. It is undefined in make O= case.
84ifeq ($(RM),)
85RM := rm -f
86endif
87
54define CLEAN 88define CLEAN
55 $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN) 89 $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
56endef 90endef
@@ -58,6 +92,15 @@ endef
58clean: 92clean:
59 $(CLEAN) 93 $(CLEAN)
60 94
95# When make O= with kselftest target from main level
96# the following aren't defined.
97#
98ifneq ($(KBUILD_SRC),)
99LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
100COMPILE.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
101LINK.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
102endif
103
61$(OUTPUT)/%:%.c 104$(OUTPUT)/%:%.c
62 $(LINK.c) $^ $(LDLIBS) -o $@ 105 $(LINK.c) $^ $(LDLIBS) -o $@
63 106
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index ad8a0897e47f..bc9d02d615da 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I../../../../include/uapi/
3CFLAGS += -I../../../../include/ 3CFLAGS += -I../../../../include/
4CFLAGS += -I../../../../usr/include/ 4CFLAGS += -I../../../../usr/include/
5 5
6TEST_PROGS := run_fuse_test.sh 6TEST_PROGS := run_tests.sh
7TEST_GEN_FILES := memfd_test fuse_mnt fuse_test 7TEST_GEN_FILES := memfd_test fuse_mnt fuse_test
8 8
9fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags) 9fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c
index 67908b18f035..7f3617274bf5 100644
--- a/tools/testing/selftests/memfd/fuse_test.c
+++ b/tools/testing/selftests/memfd/fuse_test.c
@@ -33,7 +33,7 @@
33#include <unistd.h> 33#include <unistd.h>
34 34
35#define MFD_DEF_SIZE 8192 35#define MFD_DEF_SIZE 8192
36#define STACK_SIZE 65535 36#define STACK_SIZE 65536
37 37
38static int sys_memfd_create(const char *name, 38static int sys_memfd_create(const char *name,
39 unsigned int flags) 39 unsigned int flags)
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
index 26546892cd54..f94c6d1fb46f 100644
--- a/tools/testing/selftests/memfd/memfd_test.c
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -18,12 +18,48 @@
18#include <sys/wait.h> 18#include <sys/wait.h>
19#include <unistd.h> 19#include <unistd.h>
20 20
21#define MEMFD_STR "memfd:"
22#define SHARED_FT_STR "(shared file-table)"
23
21#define MFD_DEF_SIZE 8192 24#define MFD_DEF_SIZE 8192
22#define STACK_SIZE 65536 25#define STACK_SIZE 65536
23 26
27/*
28 * Default is not to test hugetlbfs
29 */
30static int hugetlbfs_test;
31static size_t mfd_def_size = MFD_DEF_SIZE;
32
33/*
34 * Copied from mlock2-tests.c
35 */
36static unsigned long default_huge_page_size(void)
37{
38 unsigned long hps = 0;
39 char *line = NULL;
40 size_t linelen = 0;
41 FILE *f = fopen("/proc/meminfo", "r");
42
43 if (!f)
44 return 0;
45 while (getline(&line, &linelen, f) > 0) {
46 if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
47 hps <<= 10;
48 break;
49 }
50 }
51
52 free(line);
53 fclose(f);
54 return hps;
55}
56
24static int sys_memfd_create(const char *name, 57static int sys_memfd_create(const char *name,
25 unsigned int flags) 58 unsigned int flags)
26{ 59{
60 if (hugetlbfs_test)
61 flags |= MFD_HUGETLB;
62
27 return syscall(__NR_memfd_create, name, flags); 63 return syscall(__NR_memfd_create, name, flags);
28} 64}
29 65
@@ -150,7 +186,7 @@ static void *mfd_assert_mmap_shared(int fd)
150 void *p; 186 void *p;
151 187
152 p = mmap(NULL, 188 p = mmap(NULL,
153 MFD_DEF_SIZE, 189 mfd_def_size,
154 PROT_READ | PROT_WRITE, 190 PROT_READ | PROT_WRITE,
155 MAP_SHARED, 191 MAP_SHARED,
156 fd, 192 fd,
@@ -168,7 +204,7 @@ static void *mfd_assert_mmap_private(int fd)
168 void *p; 204 void *p;
169 205
170 p = mmap(NULL, 206 p = mmap(NULL,
171 MFD_DEF_SIZE, 207 mfd_def_size,
172 PROT_READ, 208 PROT_READ,
173 MAP_PRIVATE, 209 MAP_PRIVATE,
174 fd, 210 fd,
@@ -223,7 +259,7 @@ static void mfd_assert_read(int fd)
223 259
224 /* verify PROT_READ *is* allowed */ 260 /* verify PROT_READ *is* allowed */
225 p = mmap(NULL, 261 p = mmap(NULL,
226 MFD_DEF_SIZE, 262 mfd_def_size,
227 PROT_READ, 263 PROT_READ,
228 MAP_PRIVATE, 264 MAP_PRIVATE,
229 fd, 265 fd,
@@ -232,11 +268,11 @@ static void mfd_assert_read(int fd)
232 printf("mmap() failed: %m\n"); 268 printf("mmap() failed: %m\n");
233 abort(); 269 abort();
234 } 270 }
235 munmap(p, MFD_DEF_SIZE); 271 munmap(p, mfd_def_size);
236 272
237 /* verify MAP_PRIVATE is *always* allowed (even writable) */ 273 /* verify MAP_PRIVATE is *always* allowed (even writable) */
238 p = mmap(NULL, 274 p = mmap(NULL,
239 MFD_DEF_SIZE, 275 mfd_def_size,
240 PROT_READ | PROT_WRITE, 276 PROT_READ | PROT_WRITE,
241 MAP_PRIVATE, 277 MAP_PRIVATE,
242 fd, 278 fd,
@@ -245,7 +281,7 @@ static void mfd_assert_read(int fd)
245 printf("mmap() failed: %m\n"); 281 printf("mmap() failed: %m\n");
246 abort(); 282 abort();
247 } 283 }
248 munmap(p, MFD_DEF_SIZE); 284 munmap(p, mfd_def_size);
249} 285}
250 286
251static void mfd_assert_write(int fd) 287static void mfd_assert_write(int fd)
@@ -254,16 +290,22 @@ static void mfd_assert_write(int fd)
254 void *p; 290 void *p;
255 int r; 291 int r;
256 292
257 /* verify write() succeeds */ 293 /*
258 l = write(fd, "\0\0\0\0", 4); 294 * huegtlbfs does not support write, but we want to
259 if (l != 4) { 295 * verify everything else here.
260 printf("write() failed: %m\n"); 296 */
261 abort(); 297 if (!hugetlbfs_test) {
298 /* verify write() succeeds */
299 l = write(fd, "\0\0\0\0", 4);
300 if (l != 4) {
301 printf("write() failed: %m\n");
302 abort();
303 }
262 } 304 }
263 305
264 /* verify PROT_READ | PROT_WRITE is allowed */ 306 /* verify PROT_READ | PROT_WRITE is allowed */
265 p = mmap(NULL, 307 p = mmap(NULL,
266 MFD_DEF_SIZE, 308 mfd_def_size,
267 PROT_READ | PROT_WRITE, 309 PROT_READ | PROT_WRITE,
268 MAP_SHARED, 310 MAP_SHARED,
269 fd, 311 fd,
@@ -273,11 +315,11 @@ static void mfd_assert_write(int fd)
273 abort(); 315 abort();
274 } 316 }
275 *(char *)p = 0; 317 *(char *)p = 0;
276 munmap(p, MFD_DEF_SIZE); 318 munmap(p, mfd_def_size);
277 319
278 /* verify PROT_WRITE is allowed */ 320 /* verify PROT_WRITE is allowed */
279 p = mmap(NULL, 321 p = mmap(NULL,
280 MFD_DEF_SIZE, 322 mfd_def_size,
281 PROT_WRITE, 323 PROT_WRITE,
282 MAP_SHARED, 324 MAP_SHARED,
283 fd, 325 fd,
@@ -287,12 +329,12 @@ static void mfd_assert_write(int fd)
287 abort(); 329 abort();
288 } 330 }
289 *(char *)p = 0; 331 *(char *)p = 0;
290 munmap(p, MFD_DEF_SIZE); 332 munmap(p, mfd_def_size);
291 333
292 /* verify PROT_READ with MAP_SHARED is allowed and a following 334 /* verify PROT_READ with MAP_SHARED is allowed and a following
293 * mprotect(PROT_WRITE) allows writing */ 335 * mprotect(PROT_WRITE) allows writing */
294 p = mmap(NULL, 336 p = mmap(NULL,
295 MFD_DEF_SIZE, 337 mfd_def_size,
296 PROT_READ, 338 PROT_READ,
297 MAP_SHARED, 339 MAP_SHARED,
298 fd, 340 fd,
@@ -302,20 +344,20 @@ static void mfd_assert_write(int fd)
302 abort(); 344 abort();
303 } 345 }
304 346
305 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); 347 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
306 if (r < 0) { 348 if (r < 0) {
307 printf("mprotect() failed: %m\n"); 349 printf("mprotect() failed: %m\n");
308 abort(); 350 abort();
309 } 351 }
310 352
311 *(char *)p = 0; 353 *(char *)p = 0;
312 munmap(p, MFD_DEF_SIZE); 354 munmap(p, mfd_def_size);
313 355
314 /* verify PUNCH_HOLE works */ 356 /* verify PUNCH_HOLE works */
315 r = fallocate(fd, 357 r = fallocate(fd,
316 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 358 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
317 0, 359 0,
318 MFD_DEF_SIZE); 360 mfd_def_size);
319 if (r < 0) { 361 if (r < 0) {
320 printf("fallocate(PUNCH_HOLE) failed: %m\n"); 362 printf("fallocate(PUNCH_HOLE) failed: %m\n");
321 abort(); 363 abort();
@@ -337,7 +379,7 @@ static void mfd_fail_write(int fd)
337 379
338 /* verify PROT_READ | PROT_WRITE is not allowed */ 380 /* verify PROT_READ | PROT_WRITE is not allowed */
339 p = mmap(NULL, 381 p = mmap(NULL,
340 MFD_DEF_SIZE, 382 mfd_def_size,
341 PROT_READ | PROT_WRITE, 383 PROT_READ | PROT_WRITE,
342 MAP_SHARED, 384 MAP_SHARED,
343 fd, 385 fd,
@@ -349,7 +391,7 @@ static void mfd_fail_write(int fd)
349 391
350 /* verify PROT_WRITE is not allowed */ 392 /* verify PROT_WRITE is not allowed */
351 p = mmap(NULL, 393 p = mmap(NULL,
352 MFD_DEF_SIZE, 394 mfd_def_size,
353 PROT_WRITE, 395 PROT_WRITE,
354 MAP_SHARED, 396 MAP_SHARED,
355 fd, 397 fd,
@@ -362,13 +404,13 @@ static void mfd_fail_write(int fd)
362 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not 404 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
363 * allowed. Note that for r/w the kernel already prevents the mmap. */ 405 * allowed. Note that for r/w the kernel already prevents the mmap. */
364 p = mmap(NULL, 406 p = mmap(NULL,
365 MFD_DEF_SIZE, 407 mfd_def_size,
366 PROT_READ, 408 PROT_READ,
367 MAP_SHARED, 409 MAP_SHARED,
368 fd, 410 fd,
369 0); 411 0);
370 if (p != MAP_FAILED) { 412 if (p != MAP_FAILED) {
371 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); 413 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
372 if (r >= 0) { 414 if (r >= 0) {
373 printf("mmap()+mprotect() didn't fail as expected\n"); 415 printf("mmap()+mprotect() didn't fail as expected\n");
374 abort(); 416 abort();
@@ -379,7 +421,7 @@ static void mfd_fail_write(int fd)
379 r = fallocate(fd, 421 r = fallocate(fd,
380 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 422 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
381 0, 423 0,
382 MFD_DEF_SIZE); 424 mfd_def_size);
383 if (r >= 0) { 425 if (r >= 0) {
384 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n"); 426 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
385 abort(); 427 abort();
@@ -390,13 +432,13 @@ static void mfd_assert_shrink(int fd)
390{ 432{
391 int r, fd2; 433 int r, fd2;
392 434
393 r = ftruncate(fd, MFD_DEF_SIZE / 2); 435 r = ftruncate(fd, mfd_def_size / 2);
394 if (r < 0) { 436 if (r < 0) {
395 printf("ftruncate(SHRINK) failed: %m\n"); 437 printf("ftruncate(SHRINK) failed: %m\n");
396 abort(); 438 abort();
397 } 439 }
398 440
399 mfd_assert_size(fd, MFD_DEF_SIZE / 2); 441 mfd_assert_size(fd, mfd_def_size / 2);
400 442
401 fd2 = mfd_assert_open(fd, 443 fd2 = mfd_assert_open(fd,
402 O_RDWR | O_CREAT | O_TRUNC, 444 O_RDWR | O_CREAT | O_TRUNC,
@@ -410,7 +452,7 @@ static void mfd_fail_shrink(int fd)
410{ 452{
411 int r; 453 int r;
412 454
413 r = ftruncate(fd, MFD_DEF_SIZE / 2); 455 r = ftruncate(fd, mfd_def_size / 2);
414 if (r >= 0) { 456 if (r >= 0) {
415 printf("ftruncate(SHRINK) didn't fail as expected\n"); 457 printf("ftruncate(SHRINK) didn't fail as expected\n");
416 abort(); 458 abort();
@@ -425,31 +467,31 @@ static void mfd_assert_grow(int fd)
425{ 467{
426 int r; 468 int r;
427 469
428 r = ftruncate(fd, MFD_DEF_SIZE * 2); 470 r = ftruncate(fd, mfd_def_size * 2);
429 if (r < 0) { 471 if (r < 0) {
430 printf("ftruncate(GROW) failed: %m\n"); 472 printf("ftruncate(GROW) failed: %m\n");
431 abort(); 473 abort();
432 } 474 }
433 475
434 mfd_assert_size(fd, MFD_DEF_SIZE * 2); 476 mfd_assert_size(fd, mfd_def_size * 2);
435 477
436 r = fallocate(fd, 478 r = fallocate(fd,
437 0, 479 0,
438 0, 480 0,
439 MFD_DEF_SIZE * 4); 481 mfd_def_size * 4);
440 if (r < 0) { 482 if (r < 0) {
441 printf("fallocate(ALLOC) failed: %m\n"); 483 printf("fallocate(ALLOC) failed: %m\n");
442 abort(); 484 abort();
443 } 485 }
444 486
445 mfd_assert_size(fd, MFD_DEF_SIZE * 4); 487 mfd_assert_size(fd, mfd_def_size * 4);
446} 488}
447 489
448static void mfd_fail_grow(int fd) 490static void mfd_fail_grow(int fd)
449{ 491{
450 int r; 492 int r;
451 493
452 r = ftruncate(fd, MFD_DEF_SIZE * 2); 494 r = ftruncate(fd, mfd_def_size * 2);
453 if (r >= 0) { 495 if (r >= 0) {
454 printf("ftruncate(GROW) didn't fail as expected\n"); 496 printf("ftruncate(GROW) didn't fail as expected\n");
455 abort(); 497 abort();
@@ -458,7 +500,7 @@ static void mfd_fail_grow(int fd)
458 r = fallocate(fd, 500 r = fallocate(fd,
459 0, 501 0,
460 0, 502 0,
461 MFD_DEF_SIZE * 4); 503 mfd_def_size * 4);
462 if (r >= 0) { 504 if (r >= 0) {
463 printf("fallocate(ALLOC) didn't fail as expected\n"); 505 printf("fallocate(ALLOC) didn't fail as expected\n");
464 abort(); 506 abort();
@@ -467,25 +509,37 @@ static void mfd_fail_grow(int fd)
467 509
468static void mfd_assert_grow_write(int fd) 510static void mfd_assert_grow_write(int fd)
469{ 511{
470 static char buf[MFD_DEF_SIZE * 8]; 512 static char *buf;
471 ssize_t l; 513 ssize_t l;
472 514
473 l = pwrite(fd, buf, sizeof(buf), 0); 515 buf = malloc(mfd_def_size * 8);
474 if (l != sizeof(buf)) { 516 if (!buf) {
517 printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
518 abort();
519 }
520
521 l = pwrite(fd, buf, mfd_def_size * 8, 0);
522 if (l != (mfd_def_size * 8)) {
475 printf("pwrite() failed: %m\n"); 523 printf("pwrite() failed: %m\n");
476 abort(); 524 abort();
477 } 525 }
478 526
479 mfd_assert_size(fd, MFD_DEF_SIZE * 8); 527 mfd_assert_size(fd, mfd_def_size * 8);
480} 528}
481 529
482static void mfd_fail_grow_write(int fd) 530static void mfd_fail_grow_write(int fd)
483{ 531{
484 static char buf[MFD_DEF_SIZE * 8]; 532 static char *buf;
485 ssize_t l; 533 ssize_t l;
486 534
487 l = pwrite(fd, buf, sizeof(buf), 0); 535 buf = malloc(mfd_def_size * 8);
488 if (l == sizeof(buf)) { 536 if (!buf) {
537 printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
538 abort();
539 }
540
541 l = pwrite(fd, buf, mfd_def_size * 8, 0);
542 if (l == (mfd_def_size * 8)) {
489 printf("pwrite() didn't fail as expected\n"); 543 printf("pwrite() didn't fail as expected\n");
490 abort(); 544 abort();
491 } 545 }
@@ -543,6 +597,8 @@ static void test_create(void)
543 char buf[2048]; 597 char buf[2048];
544 int fd; 598 int fd;
545 599
600 printf("%s CREATE\n", MEMFD_STR);
601
546 /* test NULL name */ 602 /* test NULL name */
547 mfd_fail_new(NULL, 0); 603 mfd_fail_new(NULL, 0);
548 604
@@ -570,13 +626,18 @@ static void test_create(void)
570 fd = mfd_assert_new("", 0, MFD_CLOEXEC); 626 fd = mfd_assert_new("", 0, MFD_CLOEXEC);
571 close(fd); 627 close(fd);
572 628
573 /* verify MFD_ALLOW_SEALING is allowed */ 629 if (!hugetlbfs_test) {
574 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING); 630 /* verify MFD_ALLOW_SEALING is allowed */
575 close(fd); 631 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
576 632 close(fd);
577 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */ 633
578 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC); 634 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
579 close(fd); 635 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
636 close(fd);
637 } else {
638 /* sealing is not supported on hugetlbfs */
639 mfd_fail_new("", MFD_ALLOW_SEALING);
640 }
580} 641}
581 642
582/* 643/*
@@ -587,8 +648,14 @@ static void test_basic(void)
587{ 648{
588 int fd; 649 int fd;
589 650
651 /* hugetlbfs does not contain sealing support */
652 if (hugetlbfs_test)
653 return;
654
655 printf("%s BASIC\n", MEMFD_STR);
656
590 fd = mfd_assert_new("kern_memfd_basic", 657 fd = mfd_assert_new("kern_memfd_basic",
591 MFD_DEF_SIZE, 658 mfd_def_size,
592 MFD_CLOEXEC | MFD_ALLOW_SEALING); 659 MFD_CLOEXEC | MFD_ALLOW_SEALING);
593 660
594 /* add basic seals */ 661 /* add basic seals */
@@ -619,7 +686,7 @@ static void test_basic(void)
619 686
620 /* verify sealing does not work without MFD_ALLOW_SEALING */ 687 /* verify sealing does not work without MFD_ALLOW_SEALING */
621 fd = mfd_assert_new("kern_memfd_basic", 688 fd = mfd_assert_new("kern_memfd_basic",
622 MFD_DEF_SIZE, 689 mfd_def_size,
623 MFD_CLOEXEC); 690 MFD_CLOEXEC);
624 mfd_assert_has_seals(fd, F_SEAL_SEAL); 691 mfd_assert_has_seals(fd, F_SEAL_SEAL);
625 mfd_fail_add_seals(fd, F_SEAL_SHRINK | 692 mfd_fail_add_seals(fd, F_SEAL_SHRINK |
@@ -630,6 +697,28 @@ static void test_basic(void)
630} 697}
631 698
632/* 699/*
700 * hugetlbfs doesn't support seals or write, so just verify grow and shrink
701 * on a hugetlbfs file created via memfd_create.
702 */
703static void test_hugetlbfs_grow_shrink(void)
704{
705 int fd;
706
707 printf("%s HUGETLBFS-GROW-SHRINK\n", MEMFD_STR);
708
709 fd = mfd_assert_new("kern_memfd_seal_write",
710 mfd_def_size,
711 MFD_CLOEXEC);
712
713 mfd_assert_read(fd);
714 mfd_assert_write(fd);
715 mfd_assert_shrink(fd);
716 mfd_assert_grow(fd);
717
718 close(fd);
719}
720
721/*
633 * Test SEAL_WRITE 722 * Test SEAL_WRITE
634 * Test whether SEAL_WRITE actually prevents modifications. 723 * Test whether SEAL_WRITE actually prevents modifications.
635 */ 724 */
@@ -637,8 +726,17 @@ static void test_seal_write(void)
637{ 726{
638 int fd; 727 int fd;
639 728
729 /*
730 * hugetlbfs does not contain sealing or write support. Just test
731 * basic grow and shrink via test_hugetlbfs_grow_shrink.
732 */
733 if (hugetlbfs_test)
734 return test_hugetlbfs_grow_shrink();
735
736 printf("%s SEAL-WRITE\n", MEMFD_STR);
737
640 fd = mfd_assert_new("kern_memfd_seal_write", 738 fd = mfd_assert_new("kern_memfd_seal_write",
641 MFD_DEF_SIZE, 739 mfd_def_size,
642 MFD_CLOEXEC | MFD_ALLOW_SEALING); 740 MFD_CLOEXEC | MFD_ALLOW_SEALING);
643 mfd_assert_has_seals(fd, 0); 741 mfd_assert_has_seals(fd, 0);
644 mfd_assert_add_seals(fd, F_SEAL_WRITE); 742 mfd_assert_add_seals(fd, F_SEAL_WRITE);
@@ -661,8 +759,14 @@ static void test_seal_shrink(void)
661{ 759{
662 int fd; 760 int fd;
663 761
762 /* hugetlbfs does not contain sealing support */
763 if (hugetlbfs_test)
764 return;
765
766 printf("%s SEAL-SHRINK\n", MEMFD_STR);
767
664 fd = mfd_assert_new("kern_memfd_seal_shrink", 768 fd = mfd_assert_new("kern_memfd_seal_shrink",
665 MFD_DEF_SIZE, 769 mfd_def_size,
666 MFD_CLOEXEC | MFD_ALLOW_SEALING); 770 MFD_CLOEXEC | MFD_ALLOW_SEALING);
667 mfd_assert_has_seals(fd, 0); 771 mfd_assert_has_seals(fd, 0);
668 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 772 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
@@ -685,8 +789,14 @@ static void test_seal_grow(void)
685{ 789{
686 int fd; 790 int fd;
687 791
792 /* hugetlbfs does not contain sealing support */
793 if (hugetlbfs_test)
794 return;
795
796 printf("%s SEAL-GROW\n", MEMFD_STR);
797
688 fd = mfd_assert_new("kern_memfd_seal_grow", 798 fd = mfd_assert_new("kern_memfd_seal_grow",
689 MFD_DEF_SIZE, 799 mfd_def_size,
690 MFD_CLOEXEC | MFD_ALLOW_SEALING); 800 MFD_CLOEXEC | MFD_ALLOW_SEALING);
691 mfd_assert_has_seals(fd, 0); 801 mfd_assert_has_seals(fd, 0);
692 mfd_assert_add_seals(fd, F_SEAL_GROW); 802 mfd_assert_add_seals(fd, F_SEAL_GROW);
@@ -709,8 +819,14 @@ static void test_seal_resize(void)
709{ 819{
710 int fd; 820 int fd;
711 821
822 /* hugetlbfs does not contain sealing support */
823 if (hugetlbfs_test)
824 return;
825
826 printf("%s SEAL-RESIZE\n", MEMFD_STR);
827
712 fd = mfd_assert_new("kern_memfd_seal_resize", 828 fd = mfd_assert_new("kern_memfd_seal_resize",
713 MFD_DEF_SIZE, 829 mfd_def_size,
714 MFD_CLOEXEC | MFD_ALLOW_SEALING); 830 MFD_CLOEXEC | MFD_ALLOW_SEALING);
715 mfd_assert_has_seals(fd, 0); 831 mfd_assert_has_seals(fd, 0);
716 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); 832 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
@@ -726,15 +842,52 @@ static void test_seal_resize(void)
726} 842}
727 843
728/* 844/*
845 * hugetlbfs does not support seals. Basic test to dup the memfd created
846 * fd and perform some basic operations on it.
847 */
848static void hugetlbfs_dup(char *b_suffix)
849{
850 int fd, fd2;
851
852 printf("%s HUGETLBFS-DUP %s\n", MEMFD_STR, b_suffix);
853
854 fd = mfd_assert_new("kern_memfd_share_dup",
855 mfd_def_size,
856 MFD_CLOEXEC);
857
858 fd2 = mfd_assert_dup(fd);
859
860 mfd_assert_read(fd);
861 mfd_assert_write(fd);
862
863 mfd_assert_shrink(fd2);
864 mfd_assert_grow(fd2);
865
866 close(fd2);
867 close(fd);
868}
869
870/*
729 * Test sharing via dup() 871 * Test sharing via dup()
730 * Test that seals are shared between dupped FDs and they're all equal. 872 * Test that seals are shared between dupped FDs and they're all equal.
731 */ 873 */
732static void test_share_dup(void) 874static void test_share_dup(char *banner, char *b_suffix)
733{ 875{
734 int fd, fd2; 876 int fd, fd2;
735 877
878 /*
879 * hugetlbfs does not contain sealing support. Perform some
880 * basic testing on dup'ed fd instead via hugetlbfs_dup.
881 */
882 if (hugetlbfs_test) {
883 hugetlbfs_dup(b_suffix);
884 return;
885 }
886
887 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
888
736 fd = mfd_assert_new("kern_memfd_share_dup", 889 fd = mfd_assert_new("kern_memfd_share_dup",
737 MFD_DEF_SIZE, 890 mfd_def_size,
738 MFD_CLOEXEC | MFD_ALLOW_SEALING); 891 MFD_CLOEXEC | MFD_ALLOW_SEALING);
739 mfd_assert_has_seals(fd, 0); 892 mfd_assert_has_seals(fd, 0);
740 893
@@ -768,13 +921,19 @@ static void test_share_dup(void)
768 * Test sealing with active mmap()s 921 * Test sealing with active mmap()s
769 * Modifying seals is only allowed if no other mmap() refs exist. 922 * Modifying seals is only allowed if no other mmap() refs exist.
770 */ 923 */
771static void test_share_mmap(void) 924static void test_share_mmap(char *banner, char *b_suffix)
772{ 925{
773 int fd; 926 int fd;
774 void *p; 927 void *p;
775 928
929 /* hugetlbfs does not contain sealing support */
930 if (hugetlbfs_test)
931 return;
932
933 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
934
776 fd = mfd_assert_new("kern_memfd_share_mmap", 935 fd = mfd_assert_new("kern_memfd_share_mmap",
777 MFD_DEF_SIZE, 936 mfd_def_size,
778 MFD_CLOEXEC | MFD_ALLOW_SEALING); 937 MFD_CLOEXEC | MFD_ALLOW_SEALING);
779 mfd_assert_has_seals(fd, 0); 938 mfd_assert_has_seals(fd, 0);
780 939
@@ -784,14 +943,40 @@ static void test_share_mmap(void)
784 mfd_assert_has_seals(fd, 0); 943 mfd_assert_has_seals(fd, 0);
785 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 944 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
786 mfd_assert_has_seals(fd, F_SEAL_SHRINK); 945 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
787 munmap(p, MFD_DEF_SIZE); 946 munmap(p, mfd_def_size);
788 947
789 /* readable ref allows sealing */ 948 /* readable ref allows sealing */
790 p = mfd_assert_mmap_private(fd); 949 p = mfd_assert_mmap_private(fd);
791 mfd_assert_add_seals(fd, F_SEAL_WRITE); 950 mfd_assert_add_seals(fd, F_SEAL_WRITE);
792 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 951 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
793 munmap(p, MFD_DEF_SIZE); 952 munmap(p, mfd_def_size);
953
954 close(fd);
955}
956
957/*
958 * Basic test to make sure we can open the hugetlbfs fd via /proc and
959 * perform some simple operations on it.
960 */
961static void hugetlbfs_proc_open(char *b_suffix)
962{
963 int fd, fd2;
964
965 printf("%s HUGETLBFS-PROC-OPEN %s\n", MEMFD_STR, b_suffix);
794 966
967 fd = mfd_assert_new("kern_memfd_share_open",
968 mfd_def_size,
969 MFD_CLOEXEC);
970
971 fd2 = mfd_assert_open(fd, O_RDWR, 0);
972
973 mfd_assert_read(fd);
974 mfd_assert_write(fd);
975
976 mfd_assert_shrink(fd2);
977 mfd_assert_grow(fd2);
978
979 close(fd2);
795 close(fd); 980 close(fd);
796} 981}
797 982
@@ -801,12 +986,23 @@ static void test_share_mmap(void)
801 * This is *not* like dup(), but like a real separate open(). Make sure the 986 * This is *not* like dup(), but like a real separate open(). Make sure the
802 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR. 987 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
803 */ 988 */
804static void test_share_open(void) 989static void test_share_open(char *banner, char *b_suffix)
805{ 990{
806 int fd, fd2; 991 int fd, fd2;
807 992
993 /*
994 * hugetlbfs does not contain sealing support. So test basic
995 * functionality of using /proc fd via hugetlbfs_proc_open
996 */
997 if (hugetlbfs_test) {
998 hugetlbfs_proc_open(b_suffix);
999 return;
1000 }
1001
1002 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
1003
808 fd = mfd_assert_new("kern_memfd_share_open", 1004 fd = mfd_assert_new("kern_memfd_share_open",
809 MFD_DEF_SIZE, 1005 mfd_def_size,
810 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1006 MFD_CLOEXEC | MFD_ALLOW_SEALING);
811 mfd_assert_has_seals(fd, 0); 1007 mfd_assert_has_seals(fd, 0);
812 1008
@@ -841,13 +1037,19 @@ static void test_share_open(void)
841 * Test sharing via fork() 1037 * Test sharing via fork()
842 * Test whether seal-modifications work as expected with forked childs. 1038 * Test whether seal-modifications work as expected with forked childs.
843 */ 1039 */
844static void test_share_fork(void) 1040static void test_share_fork(char *banner, char *b_suffix)
845{ 1041{
846 int fd; 1042 int fd;
847 pid_t pid; 1043 pid_t pid;
848 1044
1045 /* hugetlbfs does not contain sealing support */
1046 if (hugetlbfs_test)
1047 return;
1048
1049 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
1050
849 fd = mfd_assert_new("kern_memfd_share_fork", 1051 fd = mfd_assert_new("kern_memfd_share_fork",
850 MFD_DEF_SIZE, 1052 mfd_def_size,
851 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1053 MFD_CLOEXEC | MFD_ALLOW_SEALING);
852 mfd_assert_has_seals(fd, 0); 1054 mfd_assert_has_seals(fd, 0);
853 1055
@@ -870,40 +1072,40 @@ int main(int argc, char **argv)
870{ 1072{
871 pid_t pid; 1073 pid_t pid;
872 1074
873 printf("memfd: CREATE\n"); 1075 if (argc == 2) {
1076 if (!strcmp(argv[1], "hugetlbfs")) {
1077 unsigned long hpage_size = default_huge_page_size();
1078
1079 if (!hpage_size) {
1080 printf("Unable to determine huge page size\n");
1081 abort();
1082 }
1083
1084 hugetlbfs_test = 1;
1085 mfd_def_size = hpage_size * 2;
1086 }
1087 }
1088
874 test_create(); 1089 test_create();
875 printf("memfd: BASIC\n");
876 test_basic(); 1090 test_basic();
877 1091
878 printf("memfd: SEAL-WRITE\n");
879 test_seal_write(); 1092 test_seal_write();
880 printf("memfd: SEAL-SHRINK\n");
881 test_seal_shrink(); 1093 test_seal_shrink();
882 printf("memfd: SEAL-GROW\n");
883 test_seal_grow(); 1094 test_seal_grow();
884 printf("memfd: SEAL-RESIZE\n");
885 test_seal_resize(); 1095 test_seal_resize();
886 1096
887 printf("memfd: SHARE-DUP\n"); 1097 test_share_dup("SHARE-DUP", "");
888 test_share_dup(); 1098 test_share_mmap("SHARE-MMAP", "");
889 printf("memfd: SHARE-MMAP\n"); 1099 test_share_open("SHARE-OPEN", "");
890 test_share_mmap(); 1100 test_share_fork("SHARE-FORK", "");
891 printf("memfd: SHARE-OPEN\n");
892 test_share_open();
893 printf("memfd: SHARE-FORK\n");
894 test_share_fork();
895 1101
896 /* Run test-suite in a multi-threaded environment with a shared 1102 /* Run test-suite in a multi-threaded environment with a shared
897 * file-table. */ 1103 * file-table. */
898 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM); 1104 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
899 printf("memfd: SHARE-DUP (shared file-table)\n"); 1105 test_share_dup("SHARE-DUP", SHARED_FT_STR);
900 test_share_dup(); 1106 test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
901 printf("memfd: SHARE-MMAP (shared file-table)\n"); 1107 test_share_open("SHARE-OPEN", SHARED_FT_STR);
902 test_share_mmap(); 1108 test_share_fork("SHARE-FORK", SHARED_FT_STR);
903 printf("memfd: SHARE-OPEN (shared file-table)\n");
904 test_share_open();
905 printf("memfd: SHARE-FORK (shared file-table)\n");
906 test_share_fork();
907 join_idle_thread(pid); 1109 join_idle_thread(pid);
908 1110
909 printf("memfd: DONE\n"); 1111 printf("memfd: DONE\n");
diff --git a/tools/testing/selftests/memfd/run_tests.sh b/tools/testing/selftests/memfd/run_tests.sh
new file mode 100755
index 000000000000..daabb350697c
--- /dev/null
+++ b/tools/testing/selftests/memfd/run_tests.sh
@@ -0,0 +1,69 @@
1#!/bin/bash
2# please run as root
3
4#
5# Normal tests requiring no special resources
6#
7./run_fuse_test.sh
8./memfd_test
9
10#
11# To test memfd_create with hugetlbfs, there needs to be hpages_test
12# huge pages free. Attempt to allocate enough pages to test.
13#
14hpages_test=8
15
16#
17# Get count of free huge pages from /proc/meminfo
18#
19while read name size unit; do
20 if [ "$name" = "HugePages_Free:" ]; then
21 freepgs=$size
22 fi
23done < /proc/meminfo
24
25#
26# If not enough free huge pages for test, attempt to increase
27#
28if [ -n "$freepgs" ] && [ $freepgs -lt $hpages_test ]; then
29 nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
30 hpages_needed=`expr $hpages_test - $freepgs`
31
32 echo 3 > /proc/sys/vm/drop_caches
33 echo $(( $hpages_needed + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
34 if [ $? -ne 0 ]; then
35 echo "Please run this test as root"
36 exit 1
37 fi
38 while read name size unit; do
39 if [ "$name" = "HugePages_Free:" ]; then
40 freepgs=$size
41 fi
42 done < /proc/meminfo
43fi
44
45#
46# If still not enough huge pages available, exit. But, give back any huge
47# pages potentially allocated above.
48#
49if [ $freepgs -lt $hpages_test ]; then
50 # nr_hugepgs non-zero only if we attempted to increase
51 if [ -n "$nr_hugepgs" ]; then
52 echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
53 fi
54 printf "Not enough huge pages available (%d < %d)\n" \
55 $freepgs $needpgs
56 exit 1
57fi
58
59#
60# Run the hugetlbfs test
61#
62./memfd_test hugetlbfs
63
64#
65# Give back any huge pages allocated for the test
66#
67if [ -n "$nr_hugepgs" ]; then
68 echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
69fi
diff --git a/tools/testing/selftests/mqueue/Makefile b/tools/testing/selftests/mqueue/Makefile
index 79a664aeb8d7..152823b6cb21 100644
--- a/tools/testing/selftests/mqueue/Makefile
+++ b/tools/testing/selftests/mqueue/Makefile
@@ -5,8 +5,8 @@ TEST_GEN_PROGS := mq_open_tests mq_perf_tests
5include ../lib.mk 5include ../lib.mk
6 6
7override define RUN_TESTS 7override define RUN_TESTS
8 @./mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]" 8 @$(OUTPUT)/mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
9 @./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]" 9 @$(OUTPUT)/mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
10endef 10endef
11 11
12override define EMIT_TESTS 12override define EMIT_TESTS
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index afe109e5508a..c612d6e38c62 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -1,3 +1,4 @@
1msg_zerocopy
1socket 2socket
2psock_fanout 3psock_fanout
3psock_tpacket 4psock_tpacket
@@ -5,3 +6,4 @@ reuseport_bpf
5reuseport_bpf_cpu 6reuseport_bpf_cpu
6reuseport_bpf_numa 7reuseport_bpf_numa
7reuseport_dualstack 8reuseport_dualstack
9reuseaddr_conflict
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index f6c9dbf478f8..d86bca991f45 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -3,11 +3,11 @@
3CFLAGS = -Wall -Wl,--no-as-needed -O2 -g 3CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
4CFLAGS += -I../../../../usr/include/ 4CFLAGS += -I../../../../usr/include/
5 5
6TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh 6TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
7TEST_GEN_FILES = socket 7TEST_GEN_FILES = socket
8TEST_GEN_FILES += psock_fanout psock_tpacket 8TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
9TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa 9TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
10TEST_GEN_FILES += reuseport_dualstack 10TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict
11 11
12include ../lib.mk 12include ../lib.mk
13 13
diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c
new file mode 100644
index 000000000000..3ab6ec403905
--- /dev/null
+++ b/tools/testing/selftests/net/msg_zerocopy.c
@@ -0,0 +1,697 @@
1/* Evaluate MSG_ZEROCOPY
2 *
3 * Send traffic between two processes over one of the supported
4 * protocols and modes:
5 *
6 * PF_INET/PF_INET6
7 * - SOCK_STREAM
8 * - SOCK_DGRAM
9 * - SOCK_DGRAM with UDP_CORK
10 * - SOCK_RAW
11 * - SOCK_RAW with IP_HDRINCL
12 *
13 * PF_PACKET
14 * - SOCK_DGRAM
15 * - SOCK_RAW
16 *
17 * Start this program on two connected hosts, one in send mode and
18 * the other with option '-r' to put it in receiver mode.
19 *
20 * If zerocopy mode ('-z') is enabled, the sender will verify that
21 * the kernel queues completions on the error queue for all zerocopy
22 * transfers.
23 */
24
25#define _GNU_SOURCE
26
27#include <arpa/inet.h>
28#include <error.h>
29#include <errno.h>
30#include <limits.h>
31#include <linux/errqueue.h>
32#include <linux/if_packet.h>
33#include <linux/ipv6.h>
34#include <linux/socket.h>
35#include <linux/sockios.h>
36#include <net/ethernet.h>
37#include <net/if.h>
38#include <netinet/ip.h>
39#include <netinet/ip6.h>
40#include <netinet/tcp.h>
41#include <netinet/udp.h>
42#include <poll.h>
43#include <sched.h>
44#include <stdbool.h>
45#include <stdio.h>
46#include <stdint.h>
47#include <stdlib.h>
48#include <string.h>
49#include <sys/ioctl.h>
50#include <sys/socket.h>
51#include <sys/stat.h>
52#include <sys/time.h>
53#include <sys/types.h>
54#include <sys/wait.h>
55#include <unistd.h>
56
57#ifndef SO_EE_ORIGIN_ZEROCOPY
58#define SO_EE_ORIGIN_ZEROCOPY 5
59#endif
60
61#ifndef SO_ZEROCOPY
62#define SO_ZEROCOPY 60
63#endif
64
65#ifndef SO_EE_CODE_ZEROCOPY_COPIED
66#define SO_EE_CODE_ZEROCOPY_COPIED 1
67#endif
68
69#ifndef MSG_ZEROCOPY
70#define MSG_ZEROCOPY 0x4000000
71#endif
72
73static int cfg_cork;
74static bool cfg_cork_mixed;
75static int cfg_cpu = -1; /* default: pin to last cpu */
76static int cfg_family = PF_UNSPEC;
77static int cfg_ifindex = 1;
78static int cfg_payload_len;
79static int cfg_port = 8000;
80static bool cfg_rx;
81static int cfg_runtime_ms = 4200;
82static int cfg_verbose;
83static int cfg_waittime_ms = 500;
84static bool cfg_zerocopy;
85
86static socklen_t cfg_alen;
87static struct sockaddr_storage cfg_dst_addr;
88static struct sockaddr_storage cfg_src_addr;
89
90static char payload[IP_MAXPACKET];
91static long packets, bytes, completions, expected_completions;
92static int zerocopied = -1;
93static uint32_t next_completion;
94
95static unsigned long gettimeofday_ms(void)
96{
97 struct timeval tv;
98
99 gettimeofday(&tv, NULL);
100 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
101}
102
103static uint16_t get_ip_csum(const uint16_t *start, int num_words)
104{
105 unsigned long sum = 0;
106 int i;
107
108 for (i = 0; i < num_words; i++)
109 sum += start[i];
110
111 while (sum >> 16)
112 sum = (sum & 0xFFFF) + (sum >> 16);
113
114 return ~sum;
115}
116
117static int do_setcpu(int cpu)
118{
119 cpu_set_t mask;
120
121 CPU_ZERO(&mask);
122 CPU_SET(cpu, &mask);
123 if (sched_setaffinity(0, sizeof(mask), &mask))
124 error(1, 0, "setaffinity %d", cpu);
125
126 if (cfg_verbose)
127 fprintf(stderr, "cpu: %u\n", cpu);
128
129 return 0;
130}
131
132static void do_setsockopt(int fd, int level, int optname, int val)
133{
134 if (setsockopt(fd, level, optname, &val, sizeof(val)))
135 error(1, errno, "setsockopt %d.%d: %d", level, optname, val);
136}
137
138static int do_poll(int fd, int events)
139{
140 struct pollfd pfd;
141 int ret;
142
143 pfd.events = events;
144 pfd.revents = 0;
145 pfd.fd = fd;
146
147 ret = poll(&pfd, 1, cfg_waittime_ms);
148 if (ret == -1)
149 error(1, errno, "poll");
150
151 return ret && (pfd.revents & events);
152}
153
154static int do_accept(int fd)
155{
156 int fda = fd;
157
158 fd = accept(fda, NULL, NULL);
159 if (fd == -1)
160 error(1, errno, "accept");
161 if (close(fda))
162 error(1, errno, "close listen sock");
163
164 return fd;
165}
166
167static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy)
168{
169 int ret, len, i, flags;
170
171 len = 0;
172 for (i = 0; i < msg->msg_iovlen; i++)
173 len += msg->msg_iov[i].iov_len;
174
175 flags = MSG_DONTWAIT;
176 if (do_zerocopy)
177 flags |= MSG_ZEROCOPY;
178
179 ret = sendmsg(fd, msg, flags);
180 if (ret == -1 && errno == EAGAIN)
181 return false;
182 if (ret == -1)
183 error(1, errno, "send");
184 if (cfg_verbose && ret != len)
185 fprintf(stderr, "send: ret=%u != %u\n", ret, len);
186
187 if (len) {
188 packets++;
189 bytes += ret;
190 if (do_zerocopy && ret)
191 expected_completions++;
192 }
193
194 return true;
195}
196
197static void do_sendmsg_corked(int fd, struct msghdr *msg)
198{
199 bool do_zerocopy = cfg_zerocopy;
200 int i, payload_len, extra_len;
201
202 /* split up the packet. for non-multiple, make first buffer longer */
203 payload_len = cfg_payload_len / cfg_cork;
204 extra_len = cfg_payload_len - (cfg_cork * payload_len);
205
206 do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 1);
207
208 for (i = 0; i < cfg_cork; i++) {
209
210 /* in mixed-frags mode, alternate zerocopy and copy frags
211 * start with non-zerocopy, to ensure attach later works
212 */
213 if (cfg_cork_mixed)
214 do_zerocopy = (i & 1);
215
216 msg->msg_iov[0].iov_len = payload_len + extra_len;
217 extra_len = 0;
218
219 do_sendmsg(fd, msg, do_zerocopy);
220 }
221
222 do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
223}
224
225static int setup_iph(struct iphdr *iph, uint16_t payload_len)
226{
227 struct sockaddr_in *daddr = (void *) &cfg_dst_addr;
228 struct sockaddr_in *saddr = (void *) &cfg_src_addr;
229
230 memset(iph, 0, sizeof(*iph));
231
232 iph->version = 4;
233 iph->tos = 0;
234 iph->ihl = 5;
235 iph->ttl = 2;
236 iph->saddr = saddr->sin_addr.s_addr;
237 iph->daddr = daddr->sin_addr.s_addr;
238 iph->protocol = IPPROTO_EGP;
239 iph->tot_len = htons(sizeof(*iph) + payload_len);
240 iph->check = get_ip_csum((void *) iph, iph->ihl << 1);
241
242 return sizeof(*iph);
243}
244
245static int setup_ip6h(struct ipv6hdr *ip6h, uint16_t payload_len)
246{
247 struct sockaddr_in6 *daddr = (void *) &cfg_dst_addr;
248 struct sockaddr_in6 *saddr = (void *) &cfg_src_addr;
249
250 memset(ip6h, 0, sizeof(*ip6h));
251
252 ip6h->version = 6;
253 ip6h->payload_len = htons(payload_len);
254 ip6h->nexthdr = IPPROTO_EGP;
255 ip6h->hop_limit = 2;
256 ip6h->saddr = saddr->sin6_addr;
257 ip6h->daddr = daddr->sin6_addr;
258
259 return sizeof(*ip6h);
260}
261
262static void setup_sockaddr(int domain, const char *str_addr, void *sockaddr)
263{
264 struct sockaddr_in6 *addr6 = (void *) sockaddr;
265 struct sockaddr_in *addr4 = (void *) sockaddr;
266
267 switch (domain) {
268 case PF_INET:
269 addr4->sin_family = AF_INET;
270 addr4->sin_port = htons(cfg_port);
271 if (inet_pton(AF_INET, str_addr, &(addr4->sin_addr)) != 1)
272 error(1, 0, "ipv4 parse error: %s", str_addr);
273 break;
274 case PF_INET6:
275 addr6->sin6_family = AF_INET6;
276 addr6->sin6_port = htons(cfg_port);
277 if (inet_pton(AF_INET6, str_addr, &(addr6->sin6_addr)) != 1)
278 error(1, 0, "ipv6 parse error: %s", str_addr);
279 break;
280 default:
281 error(1, 0, "illegal domain");
282 }
283}
284
285static int do_setup_tx(int domain, int type, int protocol)
286{
287 int fd;
288
289 fd = socket(domain, type, protocol);
290 if (fd == -1)
291 error(1, errno, "socket t");
292
293 do_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, 1 << 21);
294 if (cfg_zerocopy)
295 do_setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, 1);
296
297 if (domain != PF_PACKET)
298 if (connect(fd, (void *) &cfg_dst_addr, cfg_alen))
299 error(1, errno, "connect");
300
301 return fd;
302}
303
304static bool do_recv_completion(int fd)
305{
306 struct sock_extended_err *serr;
307 struct msghdr msg = {};
308 struct cmsghdr *cm;
309 uint32_t hi, lo, range;
310 int ret, zerocopy;
311 char control[100];
312
313 msg.msg_control = control;
314 msg.msg_controllen = sizeof(control);
315
316 ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
317 if (ret == -1 && errno == EAGAIN)
318 return false;
319 if (ret == -1)
320 error(1, errno, "recvmsg notification");
321 if (msg.msg_flags & MSG_CTRUNC)
322 error(1, errno, "recvmsg notification: truncated");
323
324 cm = CMSG_FIRSTHDR(&msg);
325 if (!cm)
326 error(1, 0, "cmsg: no cmsg");
327 if (!((cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_RECVERR) ||
328 (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_RECVERR) ||
329 (cm->cmsg_level == SOL_PACKET && cm->cmsg_type == PACKET_TX_TIMESTAMP)))
330 error(1, 0, "serr: wrong type: %d.%d",
331 cm->cmsg_level, cm->cmsg_type);
332
333 serr = (void *) CMSG_DATA(cm);
334 if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY)
335 error(1, 0, "serr: wrong origin: %u", serr->ee_origin);
336 if (serr->ee_errno != 0)
337 error(1, 0, "serr: wrong error code: %u", serr->ee_errno);
338
339 hi = serr->ee_data;
340 lo = serr->ee_info;
341 range = hi - lo + 1;
342
343 /* Detect notification gaps. These should not happen often, if at all.
344 * Gaps can occur due to drops, reordering and retransmissions.
345 */
346 if (lo != next_completion)
347 fprintf(stderr, "gap: %u..%u does not append to %u\n",
348 lo, hi, next_completion);
349 next_completion = hi + 1;
350
351 zerocopy = !(serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED);
352 if (zerocopied == -1)
353 zerocopied = zerocopy;
354 else if (zerocopied != zerocopy) {
355 fprintf(stderr, "serr: inconsistent\n");
356 zerocopied = zerocopy;
357 }
358
359 if (cfg_verbose >= 2)
360 fprintf(stderr, "completed: %u (h=%u l=%u)\n",
361 range, hi, lo);
362
363 completions += range;
364 return true;
365}
366
367/* Read all outstanding messages on the errqueue */
368static void do_recv_completions(int fd)
369{
370 while (do_recv_completion(fd)) {}
371}
372
373/* Wait for all remaining completions on the errqueue */
374static void do_recv_remaining_completions(int fd)
375{
376 int64_t tstop = gettimeofday_ms() + cfg_waittime_ms;
377
378 while (completions < expected_completions &&
379 gettimeofday_ms() < tstop) {
380 if (do_poll(fd, POLLERR))
381 do_recv_completions(fd);
382 }
383
384 if (completions < expected_completions)
385 fprintf(stderr, "missing notifications: %lu < %lu\n",
386 completions, expected_completions);
387}
388
389static void do_tx(int domain, int type, int protocol)
390{
391 struct iovec iov[3] = { {0} };
392 struct sockaddr_ll laddr;
393 struct msghdr msg = {0};
394 struct ethhdr eth;
395 union {
396 struct ipv6hdr ip6h;
397 struct iphdr iph;
398 } nh;
399 uint64_t tstop;
400 int fd;
401
402 fd = do_setup_tx(domain, type, protocol);
403
404 if (domain == PF_PACKET) {
405 uint16_t proto = cfg_family == PF_INET ? ETH_P_IP : ETH_P_IPV6;
406
407 /* sock_raw passes ll header as data */
408 if (type == SOCK_RAW) {
409 memset(eth.h_dest, 0x06, ETH_ALEN);
410 memset(eth.h_source, 0x02, ETH_ALEN);
411 eth.h_proto = htons(proto);
412 iov[0].iov_base = &eth;
413 iov[0].iov_len = sizeof(eth);
414 msg.msg_iovlen++;
415 }
416
417 /* both sock_raw and sock_dgram expect name */
418 memset(&laddr, 0, sizeof(laddr));
419 laddr.sll_family = AF_PACKET;
420 laddr.sll_ifindex = cfg_ifindex;
421 laddr.sll_protocol = htons(proto);
422 laddr.sll_halen = ETH_ALEN;
423
424 memset(laddr.sll_addr, 0x06, ETH_ALEN);
425
426 msg.msg_name = &laddr;
427 msg.msg_namelen = sizeof(laddr);
428 }
429
430 /* packet and raw sockets with hdrincl must pass network header */
431 if (domain == PF_PACKET || protocol == IPPROTO_RAW) {
432 if (cfg_family == PF_INET)
433 iov[1].iov_len = setup_iph(&nh.iph, cfg_payload_len);
434 else
435 iov[1].iov_len = setup_ip6h(&nh.ip6h, cfg_payload_len);
436
437 iov[1].iov_base = (void *) &nh;
438 msg.msg_iovlen++;
439 }
440
441 iov[2].iov_base = payload;
442 iov[2].iov_len = cfg_payload_len;
443 msg.msg_iovlen++;
444 msg.msg_iov = &iov[3 - msg.msg_iovlen];
445
446 tstop = gettimeofday_ms() + cfg_runtime_ms;
447 do {
448 if (cfg_cork)
449 do_sendmsg_corked(fd, &msg);
450 else
451 do_sendmsg(fd, &msg, cfg_zerocopy);
452
453 while (!do_poll(fd, POLLOUT)) {
454 if (cfg_zerocopy)
455 do_recv_completions(fd);
456 }
457
458 } while (gettimeofday_ms() < tstop);
459
460 if (cfg_zerocopy)
461 do_recv_remaining_completions(fd);
462
463 if (close(fd))
464 error(1, errno, "close");
465
466 fprintf(stderr, "tx=%lu (%lu MB) txc=%lu zc=%c\n",
467 packets, bytes >> 20, completions,
468 zerocopied == 1 ? 'y' : 'n');
469}
470
471static int do_setup_rx(int domain, int type, int protocol)
472{
473 int fd;
474
475 /* If tx over PF_PACKET, rx over PF_INET(6)/SOCK_RAW,
476 * to recv the only copy of the packet, not a clone
477 */
478 if (domain == PF_PACKET)
479 error(1, 0, "Use PF_INET/SOCK_RAW to read");
480
481 if (type == SOCK_RAW && protocol == IPPROTO_RAW)
482 error(1, 0, "IPPROTO_RAW: not supported on Rx");
483
484 fd = socket(domain, type, protocol);
485 if (fd == -1)
486 error(1, errno, "socket r");
487
488 do_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, 1 << 21);
489 do_setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT, 1 << 16);
490 do_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, 1);
491
492 if (bind(fd, (void *) &cfg_dst_addr, cfg_alen))
493 error(1, errno, "bind");
494
495 if (type == SOCK_STREAM) {
496 if (listen(fd, 1))
497 error(1, errno, "listen");
498 fd = do_accept(fd);
499 }
500
501 return fd;
502}
503
504/* Flush all outstanding bytes for the tcp receive queue */
505static void do_flush_tcp(int fd)
506{
507 int ret;
508
509 /* MSG_TRUNC flushes up to len bytes */
510 ret = recv(fd, NULL, 1 << 21, MSG_TRUNC | MSG_DONTWAIT);
511 if (ret == -1 && errno == EAGAIN)
512 return;
513 if (ret == -1)
514 error(1, errno, "flush");
515 if (!ret)
516 return;
517
518 packets++;
519 bytes += ret;
520}
521
522/* Flush all outstanding datagrams. Verify first few bytes of each. */
523static void do_flush_datagram(int fd, int type)
524{
525 int ret, off = 0;
526 char buf[64];
527
528 /* MSG_TRUNC will return full datagram length */
529 ret = recv(fd, buf, sizeof(buf), MSG_DONTWAIT | MSG_TRUNC);
530 if (ret == -1 && errno == EAGAIN)
531 return;
532
533 /* raw ipv4 return with header, raw ipv6 without */
534 if (cfg_family == PF_INET && type == SOCK_RAW) {
535 off += sizeof(struct iphdr);
536 ret -= sizeof(struct iphdr);
537 }
538
539 if (ret == -1)
540 error(1, errno, "recv");
541 if (ret != cfg_payload_len)
542 error(1, 0, "recv: ret=%u != %u", ret, cfg_payload_len);
543 if (ret > sizeof(buf) - off)
544 ret = sizeof(buf) - off;
545 if (memcmp(buf + off, payload, ret))
546 error(1, 0, "recv: data mismatch");
547
548 packets++;
549 bytes += cfg_payload_len;
550}
551
552static void do_rx(int domain, int type, int protocol)
553{
554 uint64_t tstop;
555 int fd;
556
557 fd = do_setup_rx(domain, type, protocol);
558
559 tstop = gettimeofday_ms() + cfg_runtime_ms;
560 do {
561 if (type == SOCK_STREAM)
562 do_flush_tcp(fd);
563 else
564 do_flush_datagram(fd, type);
565
566 do_poll(fd, POLLIN);
567
568 } while (gettimeofday_ms() < tstop);
569
570 if (close(fd))
571 error(1, errno, "close");
572
573 fprintf(stderr, "rx=%lu (%lu MB)\n", packets, bytes >> 20);
574}
575
576static void do_test(int domain, int type, int protocol)
577{
578 int i;
579
580 if (cfg_cork && (domain == PF_PACKET || type != SOCK_DGRAM))
581 error(1, 0, "can only cork udp sockets");
582
583 do_setcpu(cfg_cpu);
584
585 for (i = 0; i < IP_MAXPACKET; i++)
586 payload[i] = 'a' + (i % 26);
587
588 if (cfg_rx)
589 do_rx(domain, type, protocol);
590 else
591 do_tx(domain, type, protocol);
592}
593
594static void usage(const char *filepath)
595{
596 error(1, 0, "Usage: %s [options] <test>", filepath);
597}
598
599static void parse_opts(int argc, char **argv)
600{
601 const int max_payload_len = sizeof(payload) -
602 sizeof(struct ipv6hdr) -
603 sizeof(struct tcphdr) -
604 40 /* max tcp options */;
605 int c;
606
607 cfg_payload_len = max_payload_len;
608
609 while ((c = getopt(argc, argv, "46c:C:D:i:mp:rs:S:t:vz")) != -1) {
610 switch (c) {
611 case '4':
612 if (cfg_family != PF_UNSPEC)
613 error(1, 0, "Pass one of -4 or -6");
614 cfg_family = PF_INET;
615 cfg_alen = sizeof(struct sockaddr_in);
616 break;
617 case '6':
618 if (cfg_family != PF_UNSPEC)
619 error(1, 0, "Pass one of -4 or -6");
620 cfg_family = PF_INET6;
621 cfg_alen = sizeof(struct sockaddr_in6);
622 break;
623 case 'c':
624 cfg_cork = strtol(optarg, NULL, 0);
625 break;
626 case 'C':
627 cfg_cpu = strtol(optarg, NULL, 0);
628 break;
629 case 'D':
630 setup_sockaddr(cfg_family, optarg, &cfg_dst_addr);
631 break;
632 case 'i':
633 cfg_ifindex = if_nametoindex(optarg);
634 if (cfg_ifindex == 0)
635 error(1, errno, "invalid iface: %s", optarg);
636 break;
637 case 'm':
638 cfg_cork_mixed = true;
639 break;
640 case 'p':
641 cfg_port = htons(strtoul(optarg, NULL, 0));
642 break;
643 case 'r':
644 cfg_rx = true;
645 break;
646 case 's':
647 cfg_payload_len = strtoul(optarg, NULL, 0);
648 break;
649 case 'S':
650 setup_sockaddr(cfg_family, optarg, &cfg_src_addr);
651 break;
652 case 't':
653 cfg_runtime_ms = 200 + strtoul(optarg, NULL, 10) * 1000;
654 break;
655 case 'v':
656 cfg_verbose++;
657 break;
658 case 'z':
659 cfg_zerocopy = true;
660 break;
661 }
662 }
663
664 if (cfg_payload_len > max_payload_len)
665 error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
666 if (cfg_cork_mixed && (!cfg_zerocopy || !cfg_cork))
667 error(1, 0, "-m: cork_mixed requires corking and zerocopy");
668
669 if (optind != argc - 1)
670 usage(argv[0]);
671}
672
673int main(int argc, char **argv)
674{
675 const char *cfg_test;
676
677 parse_opts(argc, argv);
678
679 cfg_test = argv[argc - 1];
680
681 if (!strcmp(cfg_test, "packet"))
682 do_test(PF_PACKET, SOCK_RAW, 0);
683 else if (!strcmp(cfg_test, "packet_dgram"))
684 do_test(PF_PACKET, SOCK_DGRAM, 0);
685 else if (!strcmp(cfg_test, "raw"))
686 do_test(cfg_family, SOCK_RAW, IPPROTO_EGP);
687 else if (!strcmp(cfg_test, "raw_hdrincl"))
688 do_test(cfg_family, SOCK_RAW, IPPROTO_RAW);
689 else if (!strcmp(cfg_test, "tcp"))
690 do_test(cfg_family, SOCK_STREAM, 0);
691 else if (!strcmp(cfg_test, "udp"))
692 do_test(cfg_family, SOCK_DGRAM, 0);
693 else
694 error(1, 0, "unknown cfg_test %s", cfg_test);
695
696 return 0;
697}
diff --git a/tools/testing/selftests/net/msg_zerocopy.sh b/tools/testing/selftests/net/msg_zerocopy.sh
new file mode 100755
index 000000000000..d571d213418d
--- /dev/null
+++ b/tools/testing/selftests/net/msg_zerocopy.sh
@@ -0,0 +1,112 @@
1#!/bin/bash
2#
3# Send data between two processes across namespaces
4# Run twice: once without and once with zerocopy
5
6set -e
7
8readonly DEV="veth0"
9readonly DEV_MTU=65535
10readonly BIN="./msg_zerocopy"
11
12readonly RAND="$(mktemp -u XXXXXX)"
13readonly NSPREFIX="ns-${RAND}"
14readonly NS1="${NSPREFIX}1"
15readonly NS2="${NSPREFIX}2"
16
17readonly SADDR4='192.168.1.1'
18readonly DADDR4='192.168.1.2'
19readonly SADDR6='fd::1'
20readonly DADDR6='fd::2'
21
22readonly path_sysctl_mem="net.core.optmem_max"
23
24# Argument parsing
25if [[ "$#" -lt "2" ]]; then
26 echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>"
27 exit 1
28fi
29
30readonly IP="$1"
31shift
32readonly TXMODE="$1"
33shift
34readonly EXTRA_ARGS="$@"
35
36# Argument parsing: configure addresses
37if [[ "${IP}" == "4" ]]; then
38 readonly SADDR="${SADDR4}"
39 readonly DADDR="${DADDR4}"
40elif [[ "${IP}" == "6" ]]; then
41 readonly SADDR="${SADDR6}"
42 readonly DADDR="${DADDR6}"
43else
44 echo "Invalid IP version ${IP}"
45 exit 1
46fi
47
48# Argument parsing: select receive mode
49#
50# This differs from send mode for
51# - packet: use raw recv, because packet receives skb clones
52# - raw_hdrinc: use raw recv, because hdrincl is a tx-only option
53case "${TXMODE}" in
54'packet' | 'packet_dgram' | 'raw_hdrincl')
55 RXMODE='raw'
56 ;;
57*)
58 RXMODE="${TXMODE}"
59 ;;
60esac
61
62# Start of state changes: install cleanup handler
63save_sysctl_mem="$(sysctl -n ${path_sysctl_mem})"
64
65cleanup() {
66 ip netns del "${NS2}"
67 ip netns del "${NS1}"
68 sysctl -w -q "${path_sysctl_mem}=${save_sysctl_mem}"
69}
70
71trap cleanup EXIT
72
73# Configure system settings
74sysctl -w -q "${path_sysctl_mem}=1000000"
75
76# Create virtual ethernet pair between network namespaces
77ip netns add "${NS1}"
78ip netns add "${NS2}"
79
80ip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \
81 peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}"
82
83# Bring the devices up
84ip -netns "${NS1}" link set "${DEV}" up
85ip -netns "${NS2}" link set "${DEV}" up
86
87# Set fixed MAC addresses on the devices
88ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
89ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06
90
91# Add fixed IP addresses to the devices
92ip -netns "${NS1}" addr add 192.168.1.1/24 dev "${DEV}"
93ip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}"
94ip -netns "${NS1}" addr add fd::1/64 dev "${DEV}" nodad
95ip -netns "${NS2}" addr add fd::2/64 dev "${DEV}" nodad
96
97# Optionally disable sg or csum offload to test edge cases
98# ip netns exec "${NS1}" ethtool -K "${DEV}" sg off
99
100do_test() {
101 local readonly ARGS="$1"
102
103 echo "ipv${IP} ${TXMODE} ${ARGS}"
104 ip netns exec "${NS2}" "${BIN}" "-${IP}" -i "${DEV}" -t 2 -C 2 -S "${SADDR}" -D "${DADDR}" ${ARGS} -r "${RXMODE}" &
105 sleep 0.2
106 ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 -S "${SADDR}" -D "${DADDR}" ${ARGS} "${TXMODE}"
107 wait
108}
109
110do_test "${EXTRA_ARGS}"
111do_test "-z ${EXTRA_ARGS}"
112echo ok
diff --git a/tools/testing/selftests/net/netdevice.sh b/tools/testing/selftests/net/netdevice.sh
index 4e00568d70c2..90cb903c3381 100755
--- a/tools/testing/selftests/net/netdevice.sh
+++ b/tools/testing/selftests/net/netdevice.sh
@@ -178,7 +178,7 @@ if [ "$(id -u)" -ne 0 ];then
178 exit 0 178 exit 0
179fi 179fi
180 180
181ip -Version 2>/dev/null >/dev/null 181ip link show 2>/dev/null >/dev/null
182if [ $? -ne 0 ];then 182if [ $? -ne 0 ];then
183 echo "SKIP: Could not run test without the ip tool" 183 echo "SKIP: Could not run test without the ip tool"
184 exit 0 184 exit 0
diff --git a/tools/testing/selftests/net/reuseaddr_conflict.c b/tools/testing/selftests/net/reuseaddr_conflict.c
new file mode 100644
index 000000000000..7c5b12664b03
--- /dev/null
+++ b/tools/testing/selftests/net/reuseaddr_conflict.c
@@ -0,0 +1,114 @@
1/*
2 * Test for the regression introduced by
3 *
4 * b9470c27607b ("inet: kill smallest_size and smallest_port")
5 *
6 * If we open an ipv4 socket on a port with reuseaddr we shouldn't reset the tb
7 * when we open the ipv6 conterpart, which is what was happening previously.
8 */
9#include <errno.h>
10#include <error.h>
11#include <arpa/inet.h>
12#include <netinet/in.h>
13#include <stdbool.h>
14#include <stdio.h>
15#include <sys/socket.h>
16#include <sys/types.h>
17#include <unistd.h>
18
19#define PORT 9999
20
21int open_port(int ipv6, int any)
22{
23 int fd = -1;
24 int reuseaddr = 1;
25 int v6only = 1;
26 int addrlen;
27 int ret = -1;
28 struct sockaddr *addr;
29 int family = ipv6 ? AF_INET6 : AF_INET;
30
31 struct sockaddr_in6 addr6 = {
32 .sin6_family = AF_INET6,
33 .sin6_port = htons(PORT),
34 .sin6_addr = in6addr_any
35 };
36 struct sockaddr_in addr4 = {
37 .sin_family = AF_INET,
38 .sin_port = htons(PORT),
39 .sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"),
40 };
41
42
43 if (ipv6) {
44 addr = (struct sockaddr*)&addr6;
45 addrlen = sizeof(addr6);
46 } else {
47 addr = (struct sockaddr*)&addr4;
48 addrlen = sizeof(addr4);
49 }
50
51 if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
52 perror("socket");
53 goto out;
54 }
55
56 if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only,
57 sizeof(v6only)) < 0) {
58 perror("setsockopt IPV6_V6ONLY");
59 goto out;
60 }
61
62 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
63 sizeof(reuseaddr)) < 0) {
64 perror("setsockopt SO_REUSEADDR");
65 goto out;
66 }
67
68 if (bind(fd, addr, addrlen) < 0) {
69 perror("bind");
70 goto out;
71 }
72
73 if (any)
74 return fd;
75
76 if (listen(fd, 1) < 0) {
77 perror("listen");
78 goto out;
79 }
80 return fd;
81out:
82 close(fd);
83 return ret;
84}
85
86int main(void)
87{
88 int listenfd;
89 int fd1, fd2;
90
91 fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT);
92 listenfd = open_port(0, 0);
93 if (listenfd < 0)
94 error(1, errno, "Couldn't open listen socket");
95 fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
96 fd1 = open_port(0, 1);
97 if (fd1 >= 0)
98 error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
99 fprintf(stderr, "Opening in6addr_any:%d\n", PORT);
100 fd1 = open_port(1, 1);
101 if (fd1 < 0)
102 error(1, errno, "Couldn't open ipv6 reuseport");
103 fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
104 fd2 = open_port(0, 1);
105 if (fd2 >= 0)
106 error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
107 close(fd1);
108 fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT);
109 fd1 = open_port(0, 1);
110 if (fd1 >= 0)
111 error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
112 fprintf(stderr, "Success");
113 return 0;
114}
diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh
new file mode 100755
index 000000000000..57b5ff576240
--- /dev/null
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -0,0 +1,272 @@
1#!/bin/sh
2#
3# This test is for checking rtnetlink callpaths, and get as much coverage as possible.
4#
5# set -e
6
7devdummy="test-dummy0"
8ret=0
9
10# set global exit status, but never reset nonzero one.
11check_err()
12{
13 if [ $ret -eq 0 ]; then
14 ret=$1
15 fi
16}
17
18kci_add_dummy()
19{
20 ip link add name "$devdummy" type dummy
21 check_err $?
22 ip link set "$devdummy" up
23 check_err $?
24}
25
26kci_del_dummy()
27{
28 ip link del dev "$devdummy"
29 check_err $?
30}
31
32# add a bridge with vlans on top
33kci_test_bridge()
34{
35 devbr="test-br0"
36 vlandev="testbr-vlan1"
37
38 ret=0
39 ip link add name "$devbr" type bridge
40 check_err $?
41
42 ip link set dev "$devdummy" master "$devbr"
43 check_err $?
44
45 ip link set "$devbr" up
46 check_err $?
47
48 ip link add link "$devbr" name "$vlandev" type vlan id 1
49 check_err $?
50 ip addr add dev "$vlandev" 10.200.7.23/30
51 check_err $?
52 ip -6 addr add dev "$vlandev" dead:42::1234/64
53 check_err $?
54 ip -d link > /dev/null
55 check_err $?
56 ip r s t all > /dev/null
57 check_err $?
58 ip -6 addr del dev "$vlandev" dead:42::1234/64
59 check_err $?
60
61 ip link del dev "$vlandev"
62 check_err $?
63 ip link del dev "$devbr"
64 check_err $?
65
66 if [ $ret -ne 0 ];then
67 echo "FAIL: bridge setup"
68 return 1
69 fi
70 echo "PASS: bridge setup"
71
72}
73
74kci_test_gre()
75{
76 gredev=neta
77 rem=10.42.42.1
78 loc=10.0.0.1
79
80 ret=0
81 ip tunnel add $gredev mode gre remote $rem local $loc ttl 1
82 check_err $?
83 ip link set $gredev up
84 check_err $?
85 ip addr add 10.23.7.10 dev $gredev
86 check_err $?
87 ip route add 10.23.8.0/30 dev $gredev
88 check_err $?
89 ip addr add dev "$devdummy" 10.23.7.11/24
90 check_err $?
91 ip link > /dev/null
92 check_err $?
93 ip addr > /dev/null
94 check_err $?
95 ip addr del dev "$devdummy" 10.23.7.11/24
96 check_err $?
97
98 ip link del $gredev
99 check_err $?
100
101 if [ $ret -ne 0 ];then
102 echo "FAIL: gre tunnel endpoint"
103 return 1
104 fi
105 echo "PASS: gre tunnel endpoint"
106}
107
108# tc uses rtnetlink too, for full tc testing
109# please see tools/testing/selftests/tc-testing.
110kci_test_tc()
111{
112 dev=lo
113 ret=0
114
115 tc qdisc add dev "$dev" root handle 1: htb
116 check_err $?
117 tc class add dev "$dev" parent 1: classid 1:10 htb rate 1mbit
118 check_err $?
119 tc filter add dev "$dev" parent 1:0 prio 5 handle ffe: protocol ip u32 divisor 256
120 check_err $?
121 tc filter add dev "$dev" parent 1:0 prio 5 handle ffd: protocol ip u32 divisor 256
122 check_err $?
123 tc filter add dev "$dev" parent 1:0 prio 5 handle ffc: protocol ip u32 divisor 256
124 check_err $?
125 tc filter add dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32 ht ffe:2: match ip src 10.0.0.3 flowid 1:10
126 check_err $?
127 tc filter add dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:2 u32 ht ffe:2: match ip src 10.0.0.2 flowid 1:10
128 check_err $?
129 tc filter show dev "$dev" parent 1:0 > /dev/null
130 check_err $?
131 tc filter del dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32
132 check_err $?
133 tc filter show dev "$dev" parent 1:0 > /dev/null
134 check_err $?
135 tc qdisc del dev "$dev" root handle 1: htb
136 check_err $?
137
138 if [ $ret -ne 0 ];then
139 echo "FAIL: tc htb hierarchy"
140 return 1
141 fi
142 echo "PASS: tc htb hierarchy"
143
144}
145
146kci_test_polrouting()
147{
148 ret=0
149 ip rule add fwmark 1 lookup 100
150 check_err $?
151 ip route add local 0.0.0.0/0 dev lo table 100
152 check_err $?
153 ip r s t all > /dev/null
154 check_err $?
155 ip rule del fwmark 1 lookup 100
156 check_err $?
157 ip route del local 0.0.0.0/0 dev lo table 100
158 check_err $?
159
160 if [ $ret -ne 0 ];then
161 echo "FAIL: policy route test"
162 return 1
163 fi
164 echo "PASS: policy routing"
165}
166
167kci_test_route_get()
168{
169 ret=0
170
171 ip route get 127.0.0.1 > /dev/null
172 check_err $?
173 ip route get 127.0.0.1 dev "$devdummy" > /dev/null
174 check_err $?
175 ip route get ::1 > /dev/null
176 check_err $?
177 ip route get fe80::1 dev "$devdummy" > /dev/null
178 check_err $?
179 ip route get 127.0.0.1 from 127.0.0.1 oif lo tos 0x1 mark 0x1 > /dev/null
180 check_err $?
181 ip route get ::1 from ::1 iif lo oif lo tos 0x1 mark 0x1 > /dev/null
182 check_err $?
183 ip addr add dev "$devdummy" 10.23.7.11/24
184 check_err $?
185 ip route get 10.23.7.11 from 10.23.7.12 iif "$devdummy" > /dev/null
186 check_err $?
187 ip addr del dev "$devdummy" 10.23.7.11/24
188 check_err $?
189
190 if [ $ret -ne 0 ];then
191 echo "FAIL: route get"
192 return 1
193 fi
194
195 echo "PASS: route get"
196}
197
198kci_test_addrlabel()
199{
200 ret=0
201
202 ip addrlabel add prefix dead::/64 dev lo label 1
203 check_err $?
204
205 ip addrlabel list |grep -q "prefix dead::/64 dev lo label 1"
206 check_err $?
207
208 ip addrlabel del prefix dead::/64 dev lo label 1 2> /dev/null
209 check_err $?
210
211 ip addrlabel add prefix dead::/64 label 1 2> /dev/null
212 check_err $?
213
214 ip addrlabel del prefix dead::/64 label 1 2> /dev/null
215 check_err $?
216
217 # concurrent add/delete
218 for i in $(seq 1 1000); do
219 ip addrlabel add prefix 1c3::/64 label 12345 2>/dev/null
220 done &
221
222 for i in $(seq 1 1000); do
223 ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
224 done
225
226 wait
227
228 ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
229
230 if [ $ret -ne 0 ];then
231 echo "FAIL: ipv6 addrlabel"
232 return 1
233 fi
234
235 echo "PASS: ipv6 addrlabel"
236}
237
238kci_test_rtnl()
239{
240 kci_add_dummy
241 if [ $ret -ne 0 ];then
242 echo "FAIL: cannot add dummy interface"
243 return 1
244 fi
245
246 kci_test_polrouting
247 kci_test_route_get
248 kci_test_tc
249 kci_test_gre
250 kci_test_bridge
251 kci_test_addrlabel
252
253 kci_del_dummy
254}
255
256#check for needed privileges
257if [ "$(id -u)" -ne 0 ];then
258 echo "SKIP: Need root privileges"
259 exit 0
260fi
261
262for x in ip tc;do
263 $x -Version 2>/dev/null >/dev/null
264 if [ $? -ne 0 ];then
265 echo "SKIP: Could not run test without the $x tool"
266 exit 0
267 fi
268done
269
270kci_test_rtnl
271
272exit $ret
diff --git a/tools/testing/selftests/networking/timestamping/.gitignore b/tools/testing/selftests/networking/timestamping/.gitignore
index 9e69e982fb38..d9355035e746 100644
--- a/tools/testing/selftests/networking/timestamping/.gitignore
+++ b/tools/testing/selftests/networking/timestamping/.gitignore
@@ -1,3 +1,4 @@
1timestamping 1timestamping
2rxtimestamp
2txtimestamp 3txtimestamp
3hwtstamp_config 4hwtstamp_config
diff --git a/tools/testing/selftests/networking/timestamping/Makefile b/tools/testing/selftests/networking/timestamping/Makefile
index ccbb9edbbbb9..92fb8ee917c5 100644
--- a/tools/testing/selftests/networking/timestamping/Makefile
+++ b/tools/testing/selftests/networking/timestamping/Makefile
@@ -1,4 +1,6 @@
1TEST_PROGS := hwtstamp_config timestamping txtimestamp 1CFLAGS += -I../../../../../usr/include
2
3TEST_PROGS := hwtstamp_config rxtimestamp timestamping txtimestamp
2 4
3all: $(TEST_PROGS) 5all: $(TEST_PROGS)
4 6
diff --git a/tools/testing/selftests/networking/timestamping/rxtimestamp.c b/tools/testing/selftests/networking/timestamping/rxtimestamp.c
new file mode 100644
index 000000000000..dd4162fc0419
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/rxtimestamp.c
@@ -0,0 +1,389 @@
1#include <errno.h>
2#include <error.h>
3#include <getopt.h>
4#include <stdbool.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include <sys/time.h>
10#include <sys/socket.h>
11#include <sys/select.h>
12#include <sys/ioctl.h>
13#include <arpa/inet.h>
14#include <net/if.h>
15
16#include <asm/types.h>
17#include <linux/net_tstamp.h>
18#include <linux/errqueue.h>
19
20#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
21
22struct options {
23 int so_timestamp;
24 int so_timestampns;
25 int so_timestamping;
26};
27
28struct tstamps {
29 bool tstamp;
30 bool tstampns;
31 bool swtstamp;
32 bool hwtstamp;
33};
34
35struct socket_type {
36 char *friendly_name;
37 int type;
38 int protocol;
39 bool enabled;
40};
41
42struct test_case {
43 struct options sockopt;
44 struct tstamps expected;
45 bool enabled;
46};
47
48struct sof_flag {
49 int mask;
50 char *name;
51};
52
53static struct sof_flag sof_flags[] = {
54#define SOF_FLAG(f) { f, #f }
55 SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE),
56 SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE),
57 SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE),
58};
59
60static struct socket_type socket_types[] = {
61 { "ip", SOCK_RAW, IPPROTO_EGP },
62 { "udp", SOCK_DGRAM, IPPROTO_UDP },
63 { "tcp", SOCK_STREAM, IPPROTO_TCP },
64};
65
66static struct test_case test_cases[] = {
67 { {}, {} },
68 {
69 { so_timestamp: 1 },
70 { tstamp: true }
71 },
72 {
73 { so_timestampns: 1 },
74 { tstampns: true }
75 },
76 {
77 { so_timestamp: 1, so_timestampns: 1 },
78 { tstampns: true }
79 },
80 {
81 { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE },
82 {}
83 },
84 {
85 /* Loopback device does not support hw timestamps. */
86 { so_timestamping: SOF_TIMESTAMPING_RX_HARDWARE },
87 {}
88 },
89 {
90 { so_timestamping: SOF_TIMESTAMPING_SOFTWARE },
91 {}
92 },
93 {
94 { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE
95 | SOF_TIMESTAMPING_RX_HARDWARE },
96 {}
97 },
98 {
99 { so_timestamping: SOF_TIMESTAMPING_SOFTWARE
100 | SOF_TIMESTAMPING_RX_SOFTWARE },
101 { swtstamp: true }
102 },
103 {
104 { so_timestamp: 1, so_timestamping: SOF_TIMESTAMPING_SOFTWARE
105 | SOF_TIMESTAMPING_RX_SOFTWARE },
106 { tstamp: true, swtstamp: true }
107 },
108};
109
110static struct option long_options[] = {
111 { "list_tests", no_argument, 0, 'l' },
112 { "test_num", required_argument, 0, 'n' },
113 { "op_size", required_argument, 0, 's' },
114 { "tcp", no_argument, 0, 't' },
115 { "udp", no_argument, 0, 'u' },
116 { "ip", no_argument, 0, 'i' },
117};
118
119static int next_port = 19999;
120static int op_size = 10 * 1024;
121
122void print_test_case(struct test_case *t)
123{
124 int f = 0;
125
126 printf("sockopts {");
127 if (t->sockopt.so_timestamp)
128 printf(" SO_TIMESTAMP ");
129 if (t->sockopt.so_timestampns)
130 printf(" SO_TIMESTAMPNS ");
131 if (t->sockopt.so_timestamping) {
132 printf(" SO_TIMESTAMPING: {");
133 for (f = 0; f < ARRAY_SIZE(sof_flags); f++)
134 if (t->sockopt.so_timestamping & sof_flags[f].mask)
135 printf(" %s |", sof_flags[f].name);
136 printf("}");
137 }
138 printf("} expected cmsgs: {");
139 if (t->expected.tstamp)
140 printf(" SCM_TIMESTAMP ");
141 if (t->expected.tstampns)
142 printf(" SCM_TIMESTAMPNS ");
143 if (t->expected.swtstamp || t->expected.hwtstamp) {
144 printf(" SCM_TIMESTAMPING {");
145 if (t->expected.swtstamp)
146 printf("0");
147 if (t->expected.swtstamp && t->expected.hwtstamp)
148 printf(",");
149 if (t->expected.hwtstamp)
150 printf("2");
151 printf("}");
152 }
153 printf("}\n");
154}
155
156void do_send(int src)
157{
158 int r;
159 char *buf = malloc(op_size);
160
161 memset(buf, 'z', op_size);
162 r = write(src, buf, op_size);
163 if (r < 0)
164 error(1, errno, "Failed to sendmsg");
165
166 free(buf);
167}
168
169bool do_recv(int rcv, int read_size, struct tstamps expected)
170{
171 const int CMSG_SIZE = 1024;
172
173 struct scm_timestamping *ts;
174 struct tstamps actual = {};
175 char cmsg_buf[CMSG_SIZE];
176 struct iovec recv_iov;
177 struct cmsghdr *cmsg;
178 bool failed = false;
179 struct msghdr hdr;
180 int flags = 0;
181 int r;
182
183 memset(&hdr, 0, sizeof(hdr));
184 hdr.msg_iov = &recv_iov;
185 hdr.msg_iovlen = 1;
186 recv_iov.iov_base = malloc(read_size);
187 recv_iov.iov_len = read_size;
188
189 hdr.msg_control = cmsg_buf;
190 hdr.msg_controllen = sizeof(cmsg_buf);
191
192 r = recvmsg(rcv, &hdr, flags);
193 if (r < 0)
194 error(1, errno, "Failed to recvmsg");
195 if (r != read_size)
196 error(1, 0, "Only received %d bytes of payload.", r);
197
198 if (hdr.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
199 error(1, 0, "Message was truncated.");
200
201 for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL;
202 cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
203 if (cmsg->cmsg_level != SOL_SOCKET)
204 error(1, 0, "Unexpected cmsg_level %d",
205 cmsg->cmsg_level);
206 switch (cmsg->cmsg_type) {
207 case SCM_TIMESTAMP:
208 actual.tstamp = true;
209 break;
210 case SCM_TIMESTAMPNS:
211 actual.tstampns = true;
212 break;
213 case SCM_TIMESTAMPING:
214 ts = (struct scm_timestamping *)CMSG_DATA(cmsg);
215 actual.swtstamp = !!ts->ts[0].tv_sec;
216 if (ts->ts[1].tv_sec != 0)
217 error(0, 0, "ts[1] should not be set.");
218 actual.hwtstamp = !!ts->ts[2].tv_sec;
219 break;
220 default:
221 error(1, 0, "Unexpected cmsg_type %d", cmsg->cmsg_type);
222 }
223 }
224
225#define VALIDATE(field) \
226 do { \
227 if (expected.field != actual.field) { \
228 if (expected.field) \
229 error(0, 0, "Expected " #field " to be set."); \
230 else \
231 error(0, 0, \
232 "Expected " #field " to not be set."); \
233 failed = true; \
234 } \
235 } while (0)
236
237 VALIDATE(tstamp);
238 VALIDATE(tstampns);
239 VALIDATE(swtstamp);
240 VALIDATE(hwtstamp);
241#undef VALIDATE
242
243 free(recv_iov.iov_base);
244
245 return failed;
246}
247
248void config_so_flags(int rcv, struct options o)
249{
250 int on = 1;
251
252 if (setsockopt(rcv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
253 error(1, errno, "Failed to enable SO_REUSEADDR");
254
255 if (o.so_timestamp &&
256 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMP,
257 &o.so_timestamp, sizeof(o.so_timestamp)) < 0)
258 error(1, errno, "Failed to enable SO_TIMESTAMP");
259
260 if (o.so_timestampns &&
261 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPNS,
262 &o.so_timestampns, sizeof(o.so_timestampns)) < 0)
263 error(1, errno, "Failed to enable SO_TIMESTAMPNS");
264
265 if (o.so_timestamping &&
266 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPING,
267 &o.so_timestamping, sizeof(o.so_timestamping)) < 0)
268 error(1, errno, "Failed to set SO_TIMESTAMPING");
269}
270
271bool run_test_case(struct socket_type s, struct test_case t)
272{
273 int port = (s.type == SOCK_RAW) ? 0 : next_port++;
274 int read_size = op_size;
275 struct sockaddr_in addr;
276 bool failed = false;
277 int src, dst, rcv;
278
279 src = socket(AF_INET, s.type, s.protocol);
280 if (src < 0)
281 error(1, errno, "Failed to open src socket");
282
283 dst = socket(AF_INET, s.type, s.protocol);
284 if (dst < 0)
285 error(1, errno, "Failed to open dst socket");
286
287 memset(&addr, 0, sizeof(addr));
288 addr.sin_family = AF_INET;
289 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
290 addr.sin_port = htons(port);
291
292 if (bind(dst, (struct sockaddr *)&addr, sizeof(addr)) < 0)
293 error(1, errno, "Failed to bind to port %d", port);
294
295 if (s.type == SOCK_STREAM && (listen(dst, 1) < 0))
296 error(1, errno, "Failed to listen");
297
298 if (connect(src, (struct sockaddr *)&addr, sizeof(addr)) < 0)
299 error(1, errno, "Failed to connect");
300
301 if (s.type == SOCK_STREAM) {
302 rcv = accept(dst, NULL, NULL);
303 if (rcv < 0)
304 error(1, errno, "Failed to accept");
305 close(dst);
306 } else {
307 rcv = dst;
308 }
309
310 config_so_flags(rcv, t.sockopt);
311 usleep(20000); /* setsockopt for SO_TIMESTAMPING is asynchronous */
312 do_send(src);
313
314 if (s.type == SOCK_RAW)
315 read_size += 20; /* for IP header */
316 failed = do_recv(rcv, read_size, t.expected);
317
318 close(rcv);
319 close(src);
320
321 return failed;
322}
323
324int main(int argc, char **argv)
325{
326 bool all_protocols = true;
327 bool all_tests = true;
328 int arg_index = 0;
329 int failures = 0;
330 int s, t;
331 char opt;
332
333 while ((opt = getopt_long(argc, argv, "", long_options,
334 &arg_index)) != -1) {
335 switch (opt) {
336 case 'l':
337 for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
338 printf("%d\t", t);
339 print_test_case(&test_cases[t]);
340 }
341 return 0;
342 case 'n':
343 t = atoi(optarg);
344 if (t >= ARRAY_SIZE(test_cases))
345 error(1, 0, "Invalid test case: %d", t);
346 all_tests = false;
347 test_cases[t].enabled = true;
348 break;
349 case 's':
350 op_size = atoi(optarg);
351 break;
352 case 't':
353 all_protocols = false;
354 socket_types[2].enabled = true;
355 break;
356 case 'u':
357 all_protocols = false;
358 socket_types[1].enabled = true;
359 break;
360 case 'i':
361 all_protocols = false;
362 socket_types[0].enabled = true;
363 break;
364 default:
365 error(1, 0, "Failed to parse parameters.");
366 }
367 }
368
369 for (s = 0; s < ARRAY_SIZE(socket_types); s++) {
370 if (!all_protocols && !socket_types[s].enabled)
371 continue;
372
373 printf("Testing %s...\n", socket_types[s].friendly_name);
374 for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
375 if (!all_tests && !test_cases[t].enabled)
376 continue;
377
378 printf("Starting testcase %d...\n", t);
379 if (run_test_case(socket_types[s], test_cases[t])) {
380 failures++;
381 printf("FAILURE in test case ");
382 print_test_case(&test_cases[t]);
383 }
384 }
385 }
386 if (!failures)
387 printf("PASSED.\n");
388 return failures;
389}
diff --git a/tools/testing/selftests/nsfs/config b/tools/testing/selftests/nsfs/config
new file mode 100644
index 000000000000..598d0a225fc9
--- /dev/null
+++ b/tools/testing/selftests/nsfs/config
@@ -0,0 +1,3 @@
1CONFIG_USER_NS=y
2CONFIG_UTS_NS=y
3CONFIG_PID_NS=y
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index fe6bc60dfc60..8932263e5a74 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -6,7 +6,7 @@ include ../../lib.mk
6 6
7all: $(TEST_PROGS) 7all: $(TEST_PROGS)
8 8
9CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm 9CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
10 10
11$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h 11$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
12 12
diff --git a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
index ef7c971abb67..bceb53f57573 100644
--- a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
+++ b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
@@ -8,7 +8,7 @@ message:
8 .section ".toc" 8 .section ".toc"
9 .balign 8 9 .balign 8
10pattern: 10pattern:
11 .llong 0x5555AAAA5555AAAA 11 .8byte 0x5555AAAA5555AAAA
12 12
13 .text 13 .text
14FUNC_START(_start) 14FUNC_START(_start)
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 958c11c14acd..7bfcd454fb2a 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -15,6 +15,7 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S
15$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 15$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
16$(OUTPUT)/tm-tmspr: CFLAGS += -pthread 16$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
17$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 17$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
18$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o
18 19
19SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS)) 20SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
20$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S 21$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index e79ccd6aada1..a7ac2e4c60d9 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -30,6 +30,7 @@
30 30
31#include "utils.h" 31#include "utils.h"
32#include "tm.h" 32#include "tm.h"
33#include "../pmu/lib.h"
33 34
34#define SPRN_DSCR 0x03 35#define SPRN_DSCR 0x03
35 36
@@ -75,8 +76,6 @@ int test_body(void)
75 ); 76 );
76 assert(rv); /* make sure the transaction aborted */ 77 assert(rv); /* make sure the transaction aborted */
77 if ((texasr >> 56) != TM_CAUSE_RESCHED) { 78 if ((texasr >> 56) != TM_CAUSE_RESCHED) {
78 putchar('.');
79 fflush(stdout);
80 continue; 79 continue;
81 } 80 }
82 if (dscr2 != dscr1) { 81 if (dscr2 != dscr1) {
@@ -89,7 +88,12 @@ int test_body(void)
89 } 88 }
90} 89}
91 90
92int main(void) 91static int tm_resched_dscr(void)
93{ 92{
94 return test_harness(test_body, "tm_resched_dscr"); 93 return eat_cpu(test_body);
94}
95
96int main(int argc, const char *argv[])
97{
98 return test_harness(tm_resched_dscr, "tm_resched_dscr");
95} 99}
diff --git a/tools/testing/selftests/pstore/.gitignore b/tools/testing/selftests/pstore/.gitignore
new file mode 100644
index 000000000000..5a4a26e5464b
--- /dev/null
+++ b/tools/testing/selftests/pstore/.gitignore
@@ -0,0 +1,2 @@
1logs
2*uuid
diff --git a/tools/testing/selftests/ptp/Makefile b/tools/testing/selftests/ptp/Makefile
index 83dd42b2129e..d4064c742c26 100644
--- a/tools/testing/selftests/ptp/Makefile
+++ b/tools/testing/selftests/ptp/Makefile
@@ -1,3 +1,4 @@
1CFLAGS += -I../../../../usr/include/
1TEST_PROGS := testptp 2TEST_PROGS := testptp
2LDLIBS += -lrt 3LDLIBS += -lrt
3all: $(TEST_PROGS) 4all: $(TEST_PROGS)
diff --git a/tools/testing/selftests/seccomp/Makefile b/tools/testing/selftests/seccomp/Makefile
index aeb0c805f3ca..553d870b4ca9 100644
--- a/tools/testing/selftests/seccomp/Makefile
+++ b/tools/testing/selftests/seccomp/Makefile
@@ -1,8 +1,16 @@
1TEST_GEN_PROGS := seccomp_bpf 1all:
2CFLAGS += -Wl,-no-as-needed -Wall
3LDFLAGS += -lpthread
4 2
5include ../lib.mk 3include ../lib.mk
6 4
7$(TEST_GEN_PROGS): seccomp_bpf.c ../kselftest_harness.h 5.PHONY: all clean
8 $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ 6
7BINARIES := seccomp_bpf seccomp_benchmark
8CFLAGS += -Wl,-no-as-needed -Wall
9
10seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
11 $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
12
13TEST_PROGS += $(BINARIES)
14EXTRA_CLEAN := $(BINARIES)
15
16all: $(BINARIES)
diff --git a/tools/testing/selftests/seccomp/seccomp_benchmark.c b/tools/testing/selftests/seccomp/seccomp_benchmark.c
new file mode 100644
index 000000000000..5838c8697ec3
--- /dev/null
+++ b/tools/testing/selftests/seccomp/seccomp_benchmark.c
@@ -0,0 +1,99 @@
1/*
2 * Strictly speaking, this is not a test. But it can report during test
3 * runs so relative performace can be measured.
4 */
5#define _GNU_SOURCE
6#include <assert.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <time.h>
10#include <unistd.h>
11#include <linux/filter.h>
12#include <linux/seccomp.h>
13#include <sys/prctl.h>
14#include <sys/syscall.h>
15#include <sys/types.h>
16
17#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
18
19unsigned long long timing(clockid_t clk_id, unsigned long long samples)
20{
21 pid_t pid, ret;
22 unsigned long long i;
23 struct timespec start, finish;
24
25 pid = getpid();
26 assert(clock_gettime(clk_id, &start) == 0);
27 for (i = 0; i < samples; i++) {
28 ret = syscall(__NR_getpid);
29 assert(pid == ret);
30 }
31 assert(clock_gettime(clk_id, &finish) == 0);
32
33 i = finish.tv_sec - start.tv_sec;
34 i *= 1000000000;
35 i += finish.tv_nsec - start.tv_nsec;
36
37 printf("%lu.%09lu - %lu.%09lu = %llu\n",
38 finish.tv_sec, finish.tv_nsec,
39 start.tv_sec, start.tv_nsec,
40 i);
41
42 return i;
43}
44
45unsigned long long calibrate(void)
46{
47 unsigned long long i;
48
49 printf("Calibrating reasonable sample size...\n");
50
51 for (i = 5; ; i++) {
52 unsigned long long samples = 1 << i;
53
54 /* Find something that takes more than 5 seconds to run. */
55 if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5)
56 return samples;
57 }
58}
59
60int main(int argc, char *argv[])
61{
62 struct sock_filter filter[] = {
63 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
64 };
65 struct sock_fprog prog = {
66 .len = (unsigned short)ARRAY_SIZE(filter),
67 .filter = filter,
68 };
69 long ret;
70 unsigned long long samples;
71 unsigned long long native, filtered;
72
73 if (argc > 1)
74 samples = strtoull(argv[1], NULL, 0);
75 else
76 samples = calibrate();
77
78 printf("Benchmarking %llu samples...\n", samples);
79
80 native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
81 printf("getpid native: %llu ns\n", native);
82
83 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
84 assert(ret == 0);
85
86 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
87 assert(ret == 0);
88
89 filtered = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
90 printf("getpid RET_ALLOW: %llu ns\n", filtered);
91
92 printf("Estimated seccomp overhead per syscall: %llu ns\n",
93 filtered - native);
94
95 if (filtered == native)
96 printf("Trying running again with more samples.\n");
97
98 return 0;
99}
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 73f5ea6778ce..24dbf634e2dd 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -6,10 +6,18 @@
6 */ 6 */
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9#include <asm/siginfo.h> 9
10#define __have_siginfo_t 1 10/*
11#define __have_sigval_t 1 11 * glibc 2.26 and later have SIGSYS in siginfo_t. Before that,
12#define __have_sigevent_t 1 12 * we need to use the kernel's siginfo.h file and trick glibc
13 * into accepting it.
14 */
15#if !__GLIBC_PREREQ(2, 26)
16# include <asm/siginfo.h>
17# define __have_siginfo_t 1
18# define __have_sigval_t 1
19# define __have_sigevent_t 1
20#endif
13 21
14#include <errno.h> 22#include <errno.h>
15#include <linux/filter.h> 23#include <linux/filter.h>
@@ -68,17 +76,7 @@
68#define SECCOMP_MODE_FILTER 2 76#define SECCOMP_MODE_FILTER 2
69#endif 77#endif
70 78
71#ifndef SECCOMP_RET_KILL 79#ifndef SECCOMP_RET_ALLOW
72#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
73#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
74#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
75#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
76#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
77
78/* Masks for the return value sections. */
79#define SECCOMP_RET_ACTION 0x7fff0000U
80#define SECCOMP_RET_DATA 0x0000ffffU
81
82struct seccomp_data { 80struct seccomp_data {
83 int nr; 81 int nr;
84 __u32 arch; 82 __u32 arch;
@@ -87,6 +85,70 @@ struct seccomp_data {
87}; 85};
88#endif 86#endif
89 87
88#ifndef SECCOMP_RET_KILL_PROCESS
89#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
90#define SECCOMP_RET_KILL_THREAD 0x00000000U /* kill the thread */
91#endif
92#ifndef SECCOMP_RET_KILL
93#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
94#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
95#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
96#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
97#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
98#endif
99#ifndef SECCOMP_RET_LOG
100#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */
101#endif
102
103#ifndef __NR_seccomp
104# if defined(__i386__)
105# define __NR_seccomp 354
106# elif defined(__x86_64__)
107# define __NR_seccomp 317
108# elif defined(__arm__)
109# define __NR_seccomp 383
110# elif defined(__aarch64__)
111# define __NR_seccomp 277
112# elif defined(__hppa__)
113# define __NR_seccomp 338
114# elif defined(__powerpc__)
115# define __NR_seccomp 358
116# elif defined(__s390__)
117# define __NR_seccomp 348
118# else
119# warning "seccomp syscall number unknown for this architecture"
120# define __NR_seccomp 0xffff
121# endif
122#endif
123
124#ifndef SECCOMP_SET_MODE_STRICT
125#define SECCOMP_SET_MODE_STRICT 0
126#endif
127
128#ifndef SECCOMP_SET_MODE_FILTER
129#define SECCOMP_SET_MODE_FILTER 1
130#endif
131
132#ifndef SECCOMP_GET_ACTION_AVAIL
133#define SECCOMP_GET_ACTION_AVAIL 2
134#endif
135
136#ifndef SECCOMP_FILTER_FLAG_TSYNC
137#define SECCOMP_FILTER_FLAG_TSYNC 1
138#endif
139
140#ifndef SECCOMP_FILTER_FLAG_LOG
141#define SECCOMP_FILTER_FLAG_LOG 2
142#endif
143
144#ifndef seccomp
145int seccomp(unsigned int op, unsigned int flags, void *args)
146{
147 errno = 0;
148 return syscall(__NR_seccomp, op, flags, args);
149}
150#endif
151
90#if __BYTE_ORDER == __LITTLE_ENDIAN 152#if __BYTE_ORDER == __LITTLE_ENDIAN
91#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n])) 153#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
92#elif __BYTE_ORDER == __BIG_ENDIAN 154#elif __BYTE_ORDER == __BIG_ENDIAN
@@ -107,7 +169,7 @@ TEST(mode_strict_support)
107 ASSERT_EQ(0, ret) { 169 ASSERT_EQ(0, ret) {
108 TH_LOG("Kernel does not support CONFIG_SECCOMP"); 170 TH_LOG("Kernel does not support CONFIG_SECCOMP");
109 } 171 }
110 syscall(__NR_exit, 1); 172 syscall(__NR_exit, 0);
111} 173}
112 174
113TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL) 175TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)
@@ -136,7 +198,7 @@ TEST(no_new_privs_support)
136 } 198 }
137} 199}
138 200
139/* Tests kernel support by checking for a copy_from_user() fault on * NULL. */ 201/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
140TEST(mode_filter_support) 202TEST(mode_filter_support)
141{ 203{
142 long ret; 204 long ret;
@@ -342,6 +404,28 @@ TEST(empty_prog)
342 EXPECT_EQ(EINVAL, errno); 404 EXPECT_EQ(EINVAL, errno);
343} 405}
344 406
407TEST(log_all)
408{
409 struct sock_filter filter[] = {
410 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
411 };
412 struct sock_fprog prog = {
413 .len = (unsigned short)ARRAY_SIZE(filter),
414 .filter = filter,
415 };
416 long ret;
417 pid_t parent = getppid();
418
419 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
420 ASSERT_EQ(0, ret);
421
422 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
423 ASSERT_EQ(0, ret);
424
425 /* getppid() should succeed and be logged (no check for logging) */
426 EXPECT_EQ(parent, syscall(__NR_getppid));
427}
428
345TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS) 429TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
346{ 430{
347 struct sock_filter filter[] = { 431 struct sock_filter filter[] = {
@@ -520,6 +604,117 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
520 close(fd); 604 close(fd);
521} 605}
522 606
607/* This is a thread task to die via seccomp filter violation. */
608void *kill_thread(void *data)
609{
610 bool die = (bool)data;
611
612 if (die) {
613 prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
614 return (void *)SIBLING_EXIT_FAILURE;
615 }
616
617 return (void *)SIBLING_EXIT_UNKILLED;
618}
619
620/* Prepare a thread that will kill itself or both of us. */
621void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
622{
623 pthread_t thread;
624 void *status;
625 /* Kill only when calling __NR_prctl. */
626 struct sock_filter filter_thread[] = {
627 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
628 offsetof(struct seccomp_data, nr)),
629 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
630 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
631 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
632 };
633 struct sock_fprog prog_thread = {
634 .len = (unsigned short)ARRAY_SIZE(filter_thread),
635 .filter = filter_thread,
636 };
637 struct sock_filter filter_process[] = {
638 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
639 offsetof(struct seccomp_data, nr)),
640 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
641 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_PROCESS),
642 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
643 };
644 struct sock_fprog prog_process = {
645 .len = (unsigned short)ARRAY_SIZE(filter_process),
646 .filter = filter_process,
647 };
648
649 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
650 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
651 }
652
653 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
654 kill_process ? &prog_process : &prog_thread));
655
656 /*
657 * Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
658 * flag cannot be downgraded by a new filter.
659 */
660 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
661
662 /* Start a thread that will exit immediately. */
663 ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
664 ASSERT_EQ(0, pthread_join(thread, &status));
665 ASSERT_EQ(SIBLING_EXIT_UNKILLED, (unsigned long)status);
666
667 /* Start a thread that will die immediately. */
668 ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)true));
669 ASSERT_EQ(0, pthread_join(thread, &status));
670 ASSERT_NE(SIBLING_EXIT_FAILURE, (unsigned long)status);
671
672 /*
673 * If we get here, only the spawned thread died. Let the parent know
674 * the whole process didn't die (i.e. this thread, the spawner,
675 * stayed running).
676 */
677 exit(42);
678}
679
680TEST(KILL_thread)
681{
682 int status;
683 pid_t child_pid;
684
685 child_pid = fork();
686 ASSERT_LE(0, child_pid);
687 if (child_pid == 0) {
688 kill_thread_or_group(_metadata, false);
689 _exit(38);
690 }
691
692 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
693
694 /* If only the thread was killed, we'll see exit 42. */
695 ASSERT_TRUE(WIFEXITED(status));
696 ASSERT_EQ(42, WEXITSTATUS(status));
697}
698
699TEST(KILL_process)
700{
701 int status;
702 pid_t child_pid;
703
704 child_pid = fork();
705 ASSERT_LE(0, child_pid);
706 if (child_pid == 0) {
707 kill_thread_or_group(_metadata, true);
708 _exit(38);
709 }
710
711 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
712
713 /* If the entire process was killed, we'll see SIGSYS. */
714 ASSERT_TRUE(WIFSIGNALED(status));
715 ASSERT_EQ(SIGSYS, WTERMSIG(status));
716}
717
523/* TODO(wad) add 64-bit versus 32-bit arg tests. */ 718/* TODO(wad) add 64-bit versus 32-bit arg tests. */
524TEST(arg_out_of_range) 719TEST(arg_out_of_range)
525{ 720{
@@ -541,26 +736,30 @@ TEST(arg_out_of_range)
541 EXPECT_EQ(EINVAL, errno); 736 EXPECT_EQ(EINVAL, errno);
542} 737}
543 738
739#define ERRNO_FILTER(name, errno) \
740 struct sock_filter _read_filter_##name[] = { \
741 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, \
742 offsetof(struct seccomp_data, nr)), \
743 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1), \
744 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | errno), \
745 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), \
746 }; \
747 struct sock_fprog prog_##name = { \
748 .len = (unsigned short)ARRAY_SIZE(_read_filter_##name), \
749 .filter = _read_filter_##name, \
750 }
751
752/* Make sure basic errno values are correctly passed through a filter. */
544TEST(ERRNO_valid) 753TEST(ERRNO_valid)
545{ 754{
546 struct sock_filter filter[] = { 755 ERRNO_FILTER(valid, E2BIG);
547 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
548 offsetof(struct seccomp_data, nr)),
549 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
550 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | E2BIG),
551 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
552 };
553 struct sock_fprog prog = {
554 .len = (unsigned short)ARRAY_SIZE(filter),
555 .filter = filter,
556 };
557 long ret; 756 long ret;
558 pid_t parent = getppid(); 757 pid_t parent = getppid();
559 758
560 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 759 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
561 ASSERT_EQ(0, ret); 760 ASSERT_EQ(0, ret);
562 761
563 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 762 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_valid);
564 ASSERT_EQ(0, ret); 763 ASSERT_EQ(0, ret);
565 764
566 EXPECT_EQ(parent, syscall(__NR_getppid)); 765 EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -568,26 +767,17 @@ TEST(ERRNO_valid)
568 EXPECT_EQ(E2BIG, errno); 767 EXPECT_EQ(E2BIG, errno);
569} 768}
570 769
770/* Make sure an errno of zero is correctly handled by the arch code. */
571TEST(ERRNO_zero) 771TEST(ERRNO_zero)
572{ 772{
573 struct sock_filter filter[] = { 773 ERRNO_FILTER(zero, 0);
574 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
575 offsetof(struct seccomp_data, nr)),
576 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
577 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 0),
578 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
579 };
580 struct sock_fprog prog = {
581 .len = (unsigned short)ARRAY_SIZE(filter),
582 .filter = filter,
583 };
584 long ret; 774 long ret;
585 pid_t parent = getppid(); 775 pid_t parent = getppid();
586 776
587 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 777 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
588 ASSERT_EQ(0, ret); 778 ASSERT_EQ(0, ret);
589 779
590 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 780 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_zero);
591 ASSERT_EQ(0, ret); 781 ASSERT_EQ(0, ret);
592 782
593 EXPECT_EQ(parent, syscall(__NR_getppid)); 783 EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -595,26 +785,21 @@ TEST(ERRNO_zero)
595 EXPECT_EQ(0, read(0, NULL, 0)); 785 EXPECT_EQ(0, read(0, NULL, 0));
596} 786}
597 787
788/*
789 * The SECCOMP_RET_DATA mask is 16 bits wide, but errno is smaller.
790 * This tests that the errno value gets capped correctly, fixed by
791 * 580c57f10768 ("seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO").
792 */
598TEST(ERRNO_capped) 793TEST(ERRNO_capped)
599{ 794{
600 struct sock_filter filter[] = { 795 ERRNO_FILTER(capped, 4096);
601 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
602 offsetof(struct seccomp_data, nr)),
603 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
604 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 4096),
605 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
606 };
607 struct sock_fprog prog = {
608 .len = (unsigned short)ARRAY_SIZE(filter),
609 .filter = filter,
610 };
611 long ret; 796 long ret;
612 pid_t parent = getppid(); 797 pid_t parent = getppid();
613 798
614 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 799 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
615 ASSERT_EQ(0, ret); 800 ASSERT_EQ(0, ret);
616 801
617 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 802 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_capped);
618 ASSERT_EQ(0, ret); 803 ASSERT_EQ(0, ret);
619 804
620 EXPECT_EQ(parent, syscall(__NR_getppid)); 805 EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -622,6 +807,37 @@ TEST(ERRNO_capped)
622 EXPECT_EQ(4095, errno); 807 EXPECT_EQ(4095, errno);
623} 808}
624 809
810/*
811 * Filters are processed in reverse order: last applied is executed first.
812 * Since only the SECCOMP_RET_ACTION mask is tested for return values, the
813 * SECCOMP_RET_DATA mask results will follow the most recently applied
814 * matching filter return (and not the lowest or highest value).
815 */
816TEST(ERRNO_order)
817{
818 ERRNO_FILTER(first, 11);
819 ERRNO_FILTER(second, 13);
820 ERRNO_FILTER(third, 12);
821 long ret;
822 pid_t parent = getppid();
823
824 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
825 ASSERT_EQ(0, ret);
826
827 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_first);
828 ASSERT_EQ(0, ret);
829
830 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_second);
831 ASSERT_EQ(0, ret);
832
833 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_third);
834 ASSERT_EQ(0, ret);
835
836 EXPECT_EQ(parent, syscall(__NR_getppid));
837 EXPECT_EQ(-1, read(0, NULL, 0));
838 EXPECT_EQ(12, errno);
839}
840
625FIXTURE_DATA(TRAP) { 841FIXTURE_DATA(TRAP) {
626 struct sock_fprog prog; 842 struct sock_fprog prog;
627}; 843};
@@ -676,7 +892,7 @@ TEST_F_SIGNAL(TRAP, ign, SIGSYS)
676 syscall(__NR_getpid); 892 syscall(__NR_getpid);
677} 893}
678 894
679static struct siginfo TRAP_info; 895static siginfo_t TRAP_info;
680static volatile int TRAP_nr; 896static volatile int TRAP_nr;
681static void TRAP_action(int nr, siginfo_t *info, void *void_context) 897static void TRAP_action(int nr, siginfo_t *info, void *void_context)
682{ 898{
@@ -735,6 +951,7 @@ TEST_F(TRAP, handler)
735 951
736FIXTURE_DATA(precedence) { 952FIXTURE_DATA(precedence) {
737 struct sock_fprog allow; 953 struct sock_fprog allow;
954 struct sock_fprog log;
738 struct sock_fprog trace; 955 struct sock_fprog trace;
739 struct sock_fprog error; 956 struct sock_fprog error;
740 struct sock_fprog trap; 957 struct sock_fprog trap;
@@ -746,6 +963,13 @@ FIXTURE_SETUP(precedence)
746 struct sock_filter allow_insns[] = { 963 struct sock_filter allow_insns[] = {
747 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), 964 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
748 }; 965 };
966 struct sock_filter log_insns[] = {
967 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
968 offsetof(struct seccomp_data, nr)),
969 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
970 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
971 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
972 };
749 struct sock_filter trace_insns[] = { 973 struct sock_filter trace_insns[] = {
750 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 974 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
751 offsetof(struct seccomp_data, nr)), 975 offsetof(struct seccomp_data, nr)),
@@ -782,6 +1006,7 @@ FIXTURE_SETUP(precedence)
782 memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \ 1006 memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
783 self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns) 1007 self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
784 FILTER_ALLOC(allow); 1008 FILTER_ALLOC(allow);
1009 FILTER_ALLOC(log);
785 FILTER_ALLOC(trace); 1010 FILTER_ALLOC(trace);
786 FILTER_ALLOC(error); 1011 FILTER_ALLOC(error);
787 FILTER_ALLOC(trap); 1012 FILTER_ALLOC(trap);
@@ -792,6 +1017,7 @@ FIXTURE_TEARDOWN(precedence)
792{ 1017{
793#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter) 1018#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
794 FILTER_FREE(allow); 1019 FILTER_FREE(allow);
1020 FILTER_FREE(log);
795 FILTER_FREE(trace); 1021 FILTER_FREE(trace);
796 FILTER_FREE(error); 1022 FILTER_FREE(error);
797 FILTER_FREE(trap); 1023 FILTER_FREE(trap);
@@ -809,6 +1035,8 @@ TEST_F(precedence, allow_ok)
809 1035
810 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1036 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
811 ASSERT_EQ(0, ret); 1037 ASSERT_EQ(0, ret);
1038 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1039 ASSERT_EQ(0, ret);
812 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1040 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
813 ASSERT_EQ(0, ret); 1041 ASSERT_EQ(0, ret);
814 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1042 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -833,6 +1061,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
833 1061
834 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1062 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
835 ASSERT_EQ(0, ret); 1063 ASSERT_EQ(0, ret);
1064 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1065 ASSERT_EQ(0, ret);
836 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1066 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
837 ASSERT_EQ(0, ret); 1067 ASSERT_EQ(0, ret);
838 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1068 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -864,6 +1094,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
864 ASSERT_EQ(0, ret); 1094 ASSERT_EQ(0, ret);
865 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1095 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
866 ASSERT_EQ(0, ret); 1096 ASSERT_EQ(0, ret);
1097 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1098 ASSERT_EQ(0, ret);
867 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1099 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
868 ASSERT_EQ(0, ret); 1100 ASSERT_EQ(0, ret);
869 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap); 1101 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
@@ -885,6 +1117,8 @@ TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
885 1117
886 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1118 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
887 ASSERT_EQ(0, ret); 1119 ASSERT_EQ(0, ret);
1120 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1121 ASSERT_EQ(0, ret);
888 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1122 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
889 ASSERT_EQ(0, ret); 1123 ASSERT_EQ(0, ret);
890 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1124 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -910,6 +1144,8 @@ TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
910 ASSERT_EQ(0, ret); 1144 ASSERT_EQ(0, ret);
911 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap); 1145 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
912 ASSERT_EQ(0, ret); 1146 ASSERT_EQ(0, ret);
1147 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1148 ASSERT_EQ(0, ret);
913 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1149 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
914 ASSERT_EQ(0, ret); 1150 ASSERT_EQ(0, ret);
915 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1151 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -931,6 +1167,8 @@ TEST_F(precedence, errno_is_third)
931 1167
932 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1168 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
933 ASSERT_EQ(0, ret); 1169 ASSERT_EQ(0, ret);
1170 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1171 ASSERT_EQ(0, ret);
934 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1172 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
935 ASSERT_EQ(0, ret); 1173 ASSERT_EQ(0, ret);
936 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1174 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -949,6 +1187,8 @@ TEST_F(precedence, errno_is_third_in_any_order)
949 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 1187 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
950 ASSERT_EQ(0, ret); 1188 ASSERT_EQ(0, ret);
951 1189
1190 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1191 ASSERT_EQ(0, ret);
952 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1192 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
953 ASSERT_EQ(0, ret); 1193 ASSERT_EQ(0, ret);
954 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1194 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
@@ -971,6 +1211,8 @@ TEST_F(precedence, trace_is_fourth)
971 1211
972 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1212 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
973 ASSERT_EQ(0, ret); 1213 ASSERT_EQ(0, ret);
1214 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1215 ASSERT_EQ(0, ret);
974 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1216 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
975 ASSERT_EQ(0, ret); 1217 ASSERT_EQ(0, ret);
976 /* Should work just fine. */ 1218 /* Should work just fine. */
@@ -992,12 +1234,54 @@ TEST_F(precedence, trace_is_fourth_in_any_order)
992 ASSERT_EQ(0, ret); 1234 ASSERT_EQ(0, ret);
993 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1235 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
994 ASSERT_EQ(0, ret); 1236 ASSERT_EQ(0, ret);
1237 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1238 ASSERT_EQ(0, ret);
995 /* Should work just fine. */ 1239 /* Should work just fine. */
996 EXPECT_EQ(parent, syscall(__NR_getppid)); 1240 EXPECT_EQ(parent, syscall(__NR_getppid));
997 /* No ptracer */ 1241 /* No ptracer */
998 EXPECT_EQ(-1, syscall(__NR_getpid)); 1242 EXPECT_EQ(-1, syscall(__NR_getpid));
999} 1243}
1000 1244
1245TEST_F(precedence, log_is_fifth)
1246{
1247 pid_t mypid, parent;
1248 long ret;
1249
1250 mypid = getpid();
1251 parent = getppid();
1252 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1253 ASSERT_EQ(0, ret);
1254
1255 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1256 ASSERT_EQ(0, ret);
1257 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1258 ASSERT_EQ(0, ret);
1259 /* Should work just fine. */
1260 EXPECT_EQ(parent, syscall(__NR_getppid));
1261 /* Should also work just fine */
1262 EXPECT_EQ(mypid, syscall(__NR_getpid));
1263}
1264
1265TEST_F(precedence, log_is_fifth_in_any_order)
1266{
1267 pid_t mypid, parent;
1268 long ret;
1269
1270 mypid = getpid();
1271 parent = getppid();
1272 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1273 ASSERT_EQ(0, ret);
1274
1275 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1276 ASSERT_EQ(0, ret);
1277 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1278 ASSERT_EQ(0, ret);
1279 /* Should work just fine. */
1280 EXPECT_EQ(parent, syscall(__NR_getppid));
1281 /* Should also work just fine */
1282 EXPECT_EQ(mypid, syscall(__NR_getpid));
1283}
1284
1001#ifndef PTRACE_O_TRACESECCOMP 1285#ifndef PTRACE_O_TRACESECCOMP
1002#define PTRACE_O_TRACESECCOMP 0x00000080 1286#define PTRACE_O_TRACESECCOMP 0x00000080
1003#endif 1287#endif
@@ -1262,6 +1546,13 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1262# error "Do not know how to find your architecture's registers and syscalls" 1546# error "Do not know how to find your architecture's registers and syscalls"
1263#endif 1547#endif
1264 1548
1549/* When the syscall return can't be changed, stub out the tests for it. */
1550#ifdef SYSCALL_NUM_RET_SHARE_REG
1551# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(-1, action)
1552#else
1553# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(val, action)
1554#endif
1555
1265/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for 1556/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1266 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux). 1557 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1267 */ 1558 */
@@ -1357,7 +1648,7 @@ void change_syscall(struct __test_metadata *_metadata,
1357#ifdef SYSCALL_NUM_RET_SHARE_REG 1648#ifdef SYSCALL_NUM_RET_SHARE_REG
1358 TH_LOG("Can't modify syscall return on this architecture"); 1649 TH_LOG("Can't modify syscall return on this architecture");
1359#else 1650#else
1360 regs.SYSCALL_RET = 1; 1651 regs.SYSCALL_RET = EPERM;
1361#endif 1652#endif
1362 1653
1363#ifdef HAVE_GETREGS 1654#ifdef HAVE_GETREGS
@@ -1426,6 +1717,8 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
1426 1717
1427 if (nr == __NR_getpid) 1718 if (nr == __NR_getpid)
1428 change_syscall(_metadata, tracee, __NR_getppid); 1719 change_syscall(_metadata, tracee, __NR_getppid);
1720 if (nr == __NR_open)
1721 change_syscall(_metadata, tracee, -1);
1429} 1722}
1430 1723
1431FIXTURE_DATA(TRACE_syscall) { 1724FIXTURE_DATA(TRACE_syscall) {
@@ -1480,6 +1773,28 @@ FIXTURE_TEARDOWN(TRACE_syscall)
1480 free(self->prog.filter); 1773 free(self->prog.filter);
1481} 1774}
1482 1775
1776TEST_F(TRACE_syscall, ptrace_syscall_redirected)
1777{
1778 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1779 teardown_trace_fixture(_metadata, self->tracer);
1780 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1781 true);
1782
1783 /* Tracer will redirect getpid to getppid. */
1784 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1785}
1786
1787TEST_F(TRACE_syscall, ptrace_syscall_dropped)
1788{
1789 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1790 teardown_trace_fixture(_metadata, self->tracer);
1791 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1792 true);
1793
1794 /* Tracer should skip the open syscall, resulting in EPERM. */
1795 EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_open));
1796}
1797
1483TEST_F(TRACE_syscall, syscall_allowed) 1798TEST_F(TRACE_syscall, syscall_allowed)
1484{ 1799{
1485 long ret; 1800 long ret;
@@ -1520,13 +1835,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
1520 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); 1835 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1521 ASSERT_EQ(0, ret); 1836 ASSERT_EQ(0, ret);
1522 1837
1523#ifdef SYSCALL_NUM_RET_SHARE_REG
1524 /* gettid has been skipped */
1525 EXPECT_EQ(-1, syscall(__NR_gettid));
1526#else
1527 /* gettid has been skipped and an altered return value stored. */ 1838 /* gettid has been skipped and an altered return value stored. */
1528 EXPECT_EQ(1, syscall(__NR_gettid)); 1839 EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
1529#endif
1530 EXPECT_NE(self->mytid, syscall(__NR_gettid)); 1840 EXPECT_NE(self->mytid, syscall(__NR_gettid));
1531} 1841}
1532 1842
@@ -1557,6 +1867,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
1557 ASSERT_EQ(0, ret); 1867 ASSERT_EQ(0, ret);
1558 1868
1559 /* Tracer will redirect getpid to getppid, and we should see EPERM. */ 1869 /* Tracer will redirect getpid to getppid, and we should see EPERM. */
1870 errno = 0;
1560 EXPECT_EQ(-1, syscall(__NR_getpid)); 1871 EXPECT_EQ(-1, syscall(__NR_getpid));
1561 EXPECT_EQ(EPERM, errno); 1872 EXPECT_EQ(EPERM, errno);
1562} 1873}
@@ -1654,47 +1965,6 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
1654 EXPECT_NE(self->mypid, syscall(__NR_getpid)); 1965 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1655} 1966}
1656 1967
1657#ifndef __NR_seccomp
1658# if defined(__i386__)
1659# define __NR_seccomp 354
1660# elif defined(__x86_64__)
1661# define __NR_seccomp 317
1662# elif defined(__arm__)
1663# define __NR_seccomp 383
1664# elif defined(__aarch64__)
1665# define __NR_seccomp 277
1666# elif defined(__hppa__)
1667# define __NR_seccomp 338
1668# elif defined(__powerpc__)
1669# define __NR_seccomp 358
1670# elif defined(__s390__)
1671# define __NR_seccomp 348
1672# else
1673# warning "seccomp syscall number unknown for this architecture"
1674# define __NR_seccomp 0xffff
1675# endif
1676#endif
1677
1678#ifndef SECCOMP_SET_MODE_STRICT
1679#define SECCOMP_SET_MODE_STRICT 0
1680#endif
1681
1682#ifndef SECCOMP_SET_MODE_FILTER
1683#define SECCOMP_SET_MODE_FILTER 1
1684#endif
1685
1686#ifndef SECCOMP_FILTER_FLAG_TSYNC
1687#define SECCOMP_FILTER_FLAG_TSYNC 1
1688#endif
1689
1690#ifndef seccomp
1691int seccomp(unsigned int op, unsigned int flags, void *args)
1692{
1693 errno = 0;
1694 return syscall(__NR_seccomp, op, flags, args);
1695}
1696#endif
1697
1698TEST(seccomp_syscall) 1968TEST(seccomp_syscall)
1699{ 1969{
1700 struct sock_filter filter[] = { 1970 struct sock_filter filter[] = {
@@ -1783,6 +2053,67 @@ TEST(seccomp_syscall_mode_lock)
1783 } 2053 }
1784} 2054}
1785 2055
2056/*
2057 * Test detection of known and unknown filter flags. Userspace needs to be able
2058 * to check if a filter flag is supported by the current kernel and a good way
2059 * of doing that is by attempting to enter filter mode, with the flag bit in
2060 * question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
2061 * that the flag is valid and EINVAL indicates that the flag is invalid.
2062 */
2063TEST(detect_seccomp_filter_flags)
2064{
2065 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
2066 SECCOMP_FILTER_FLAG_LOG };
2067 unsigned int flag, all_flags;
2068 int i;
2069 long ret;
2070
2071 /* Test detection of known-good filter flags */
2072 for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
2073 flag = flags[i];
2074 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2075 ASSERT_NE(ENOSYS, errno) {
2076 TH_LOG("Kernel does not support seccomp syscall!");
2077 }
2078 EXPECT_EQ(-1, ret);
2079 EXPECT_EQ(EFAULT, errno) {
2080 TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
2081 flag);
2082 }
2083
2084 all_flags |= flag;
2085 }
2086
2087 /* Test detection of all known-good filter flags */
2088 ret = seccomp(SECCOMP_SET_MODE_FILTER, all_flags, NULL);
2089 EXPECT_EQ(-1, ret);
2090 EXPECT_EQ(EFAULT, errno) {
2091 TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
2092 all_flags);
2093 }
2094
2095 /* Test detection of an unknown filter flag */
2096 flag = -1;
2097 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2098 EXPECT_EQ(-1, ret);
2099 EXPECT_EQ(EINVAL, errno) {
2100 TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
2101 flag);
2102 }
2103
2104 /*
2105 * Test detection of an unknown filter flag that may simply need to be
2106 * added to this test
2107 */
2108 flag = flags[ARRAY_SIZE(flags) - 1] << 1;
2109 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2110 EXPECT_EQ(-1, ret);
2111 EXPECT_EQ(EINVAL, errno) {
2112 TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported! Does a new flag need to be added to this test?",
2113 flag);
2114 }
2115}
2116
1786TEST(TSYNC_first) 2117TEST(TSYNC_first)
1787{ 2118{
1788 struct sock_filter filter[] = { 2119 struct sock_filter filter[] = {
@@ -2421,6 +2752,99 @@ TEST(syscall_restart)
2421 _metadata->passed = 0; 2752 _metadata->passed = 0;
2422} 2753}
2423 2754
2755TEST_SIGNAL(filter_flag_log, SIGSYS)
2756{
2757 struct sock_filter allow_filter[] = {
2758 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2759 };
2760 struct sock_filter kill_filter[] = {
2761 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2762 offsetof(struct seccomp_data, nr)),
2763 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
2764 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2765 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2766 };
2767 struct sock_fprog allow_prog = {
2768 .len = (unsigned short)ARRAY_SIZE(allow_filter),
2769 .filter = allow_filter,
2770 };
2771 struct sock_fprog kill_prog = {
2772 .len = (unsigned short)ARRAY_SIZE(kill_filter),
2773 .filter = kill_filter,
2774 };
2775 long ret;
2776 pid_t parent = getppid();
2777
2778 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2779 ASSERT_EQ(0, ret);
2780
2781 /* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
2782 ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
2783 &allow_prog);
2784 ASSERT_NE(ENOSYS, errno) {
2785 TH_LOG("Kernel does not support seccomp syscall!");
2786 }
2787 EXPECT_NE(0, ret) {
2788 TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
2789 }
2790 EXPECT_EQ(EINVAL, errno) {
2791 TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
2792 }
2793
2794 /* Verify that a simple, permissive filter can be added with no flags */
2795 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
2796 EXPECT_EQ(0, ret);
2797
2798 /* See if the same filter can be added with the FILTER_FLAG_LOG flag */
2799 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
2800 &allow_prog);
2801 ASSERT_NE(EINVAL, errno) {
2802 TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
2803 }
2804 EXPECT_EQ(0, ret);
2805
2806 /* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
2807 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
2808 &kill_prog);
2809 EXPECT_EQ(0, ret);
2810
2811 EXPECT_EQ(parent, syscall(__NR_getppid));
2812 /* getpid() should never return. */
2813 EXPECT_EQ(0, syscall(__NR_getpid));
2814}
2815
2816TEST(get_action_avail)
2817{
2818 __u32 actions[] = { SECCOMP_RET_KILL_THREAD, SECCOMP_RET_TRAP,
2819 SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
2820 SECCOMP_RET_LOG, SECCOMP_RET_ALLOW };
2821 __u32 unknown_action = 0x10000000U;
2822 int i;
2823 long ret;
2824
2825 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[0]);
2826 ASSERT_NE(ENOSYS, errno) {
2827 TH_LOG("Kernel does not support seccomp syscall!");
2828 }
2829 ASSERT_NE(EINVAL, errno) {
2830 TH_LOG("Kernel does not support SECCOMP_GET_ACTION_AVAIL operation!");
2831 }
2832 EXPECT_EQ(ret, 0);
2833
2834 for (i = 0; i < ARRAY_SIZE(actions); i++) {
2835 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[i]);
2836 EXPECT_EQ(ret, 0) {
2837 TH_LOG("Expected action (0x%X) not available!",
2838 actions[i]);
2839 }
2840 }
2841
2842 /* Check that an unknown action is handled properly (EOPNOTSUPP) */
2843 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &unknown_action);
2844 EXPECT_EQ(ret, -1);
2845 EXPECT_EQ(errno, EOPNOTSUPP);
2846}
2847
2424/* 2848/*
2425 * TODO: 2849 * TODO:
2426 * - add microbenchmarks 2850 * - add microbenchmarks
@@ -2429,6 +2853,8 @@ TEST(syscall_restart)
2429 * - endianness checking when appropriate 2853 * - endianness checking when appropriate
2430 * - 64-bit arg prodding 2854 * - 64-bit arg prodding
2431 * - arch value testing (x86 modes especially) 2855 * - arch value testing (x86 modes especially)
2856 * - verify that FILTER_FLAG_LOG filters generate log messages
2857 * - verify that RET_LOG generates log messages
2432 * - ... 2858 * - ...
2433 */ 2859 */
2434 2860
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
index ccd07343d418..97bb150837df 100644
--- a/tools/testing/selftests/sigaltstack/sas.c
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -17,6 +17,8 @@
17#include <assert.h> 17#include <assert.h>
18#include <errno.h> 18#include <errno.h>
19 19
20#include "../kselftest.h"
21
20#ifndef SS_AUTODISARM 22#ifndef SS_AUTODISARM
21#define SS_AUTODISARM (1U << 31) 23#define SS_AUTODISARM (1U << 31)
22#endif 24#endif
@@ -37,12 +39,15 @@ void my_usr1(int sig, siginfo_t *si, void *u)
37 stack_t stk; 39 stack_t stk;
38 struct stk_data *p; 40 struct stk_data *p;
39 41
42#if __s390x__
43 register unsigned long sp asm("%15");
44#else
40 register unsigned long sp asm("sp"); 45 register unsigned long sp asm("sp");
46#endif
41 47
42 if (sp < (unsigned long)sstack || 48 if (sp < (unsigned long)sstack ||
43 sp >= (unsigned long)sstack + SIGSTKSZ) { 49 sp >= (unsigned long)sstack + SIGSTKSZ) {
44 printf("[FAIL]\tSP is not on sigaltstack\n"); 50 ksft_exit_fail_msg("SP is not on sigaltstack\n");
45 exit(EXIT_FAILURE);
46 } 51 }
47 /* put some data on stack. other sighandler will try to overwrite it */ 52 /* put some data on stack. other sighandler will try to overwrite it */
48 aa = alloca(1024); 53 aa = alloca(1024);
@@ -50,21 +55,22 @@ void my_usr1(int sig, siginfo_t *si, void *u)
50 p = (struct stk_data *)(aa + 512); 55 p = (struct stk_data *)(aa + 512);
51 strcpy(p->msg, msg); 56 strcpy(p->msg, msg);
52 p->flag = 1; 57 p->flag = 1;
53 printf("[RUN]\tsignal USR1\n"); 58 ksft_print_msg("[RUN]\tsignal USR1\n");
54 err = sigaltstack(NULL, &stk); 59 err = sigaltstack(NULL, &stk);
55 if (err) { 60 if (err) {
56 perror("[FAIL]\tsigaltstack()"); 61 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
57 exit(EXIT_FAILURE); 62 exit(EXIT_FAILURE);
58 } 63 }
59 if (stk.ss_flags != SS_DISABLE) 64 if (stk.ss_flags != SS_DISABLE)
60 printf("[FAIL]\tss_flags=%x, should be SS_DISABLE\n", 65 ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",
61 stk.ss_flags); 66 stk.ss_flags);
62 else 67 else
63 printf("[OK]\tsigaltstack is disabled in sighandler\n"); 68 ksft_test_result_pass(
69 "sigaltstack is disabled in sighandler\n");
64 swapcontext(&sc, &uc); 70 swapcontext(&sc, &uc);
65 printf("%s\n", p->msg); 71 ksft_print_msg("%s\n", p->msg);
66 if (!p->flag) { 72 if (!p->flag) {
67 printf("[RUN]\tAborting\n"); 73 ksft_exit_skip("[RUN]\tAborting\n");
68 exit(EXIT_FAILURE); 74 exit(EXIT_FAILURE);
69 } 75 }
70} 76}
@@ -74,13 +80,13 @@ void my_usr2(int sig, siginfo_t *si, void *u)
74 char *aa; 80 char *aa;
75 struct stk_data *p; 81 struct stk_data *p;
76 82
77 printf("[RUN]\tsignal USR2\n"); 83 ksft_print_msg("[RUN]\tsignal USR2\n");
78 aa = alloca(1024); 84 aa = alloca(1024);
79 /* dont run valgrind on this */ 85 /* dont run valgrind on this */
80 /* try to find the data stored by previous sighandler */ 86 /* try to find the data stored by previous sighandler */
81 p = memmem(aa, 1024, msg, strlen(msg)); 87 p = memmem(aa, 1024, msg, strlen(msg));
82 if (p) { 88 if (p) {
83 printf("[FAIL]\tsigaltstack re-used\n"); 89 ksft_test_result_fail("sigaltstack re-used\n");
84 /* corrupt the data */ 90 /* corrupt the data */
85 strcpy(p->msg, msg2); 91 strcpy(p->msg, msg2);
86 /* tell other sighandler that his data is corrupted */ 92 /* tell other sighandler that his data is corrupted */
@@ -90,7 +96,7 @@ void my_usr2(int sig, siginfo_t *si, void *u)
90 96
91static void switch_fn(void) 97static void switch_fn(void)
92{ 98{
93 printf("[RUN]\tswitched to user ctx\n"); 99 ksft_print_msg("[RUN]\tswitched to user ctx\n");
94 raise(SIGUSR2); 100 raise(SIGUSR2);
95 setcontext(&sc); 101 setcontext(&sc);
96} 102}
@@ -101,6 +107,8 @@ int main(void)
101 stack_t stk; 107 stack_t stk;
102 int err; 108 int err;
103 109
110 ksft_print_header();
111
104 sigemptyset(&act.sa_mask); 112 sigemptyset(&act.sa_mask);
105 act.sa_flags = SA_ONSTACK | SA_SIGINFO; 113 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
106 act.sa_sigaction = my_usr1; 114 act.sa_sigaction = my_usr1;
@@ -110,19 +118,20 @@ int main(void)
110 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 118 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
111 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 119 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
112 if (sstack == MAP_FAILED) { 120 if (sstack == MAP_FAILED) {
113 perror("mmap()"); 121 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
114 return EXIT_FAILURE; 122 return EXIT_FAILURE;
115 } 123 }
116 124
117 err = sigaltstack(NULL, &stk); 125 err = sigaltstack(NULL, &stk);
118 if (err) { 126 if (err) {
119 perror("[FAIL]\tsigaltstack()"); 127 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
120 exit(EXIT_FAILURE); 128 exit(EXIT_FAILURE);
121 } 129 }
122 if (stk.ss_flags == SS_DISABLE) { 130 if (stk.ss_flags == SS_DISABLE) {
123 printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n"); 131 ksft_test_result_pass(
132 "Initial sigaltstack state was SS_DISABLE\n");
124 } else { 133 } else {
125 printf("[FAIL]\tInitial sigaltstack state was %x; " 134 ksft_exit_fail_msg("Initial sigaltstack state was %x; "
126 "should have been SS_DISABLE\n", stk.ss_flags); 135 "should have been SS_DISABLE\n", stk.ss_flags);
127 return EXIT_FAILURE; 136 return EXIT_FAILURE;
128 } 137 }
@@ -133,7 +142,8 @@ int main(void)
133 err = sigaltstack(&stk, NULL); 142 err = sigaltstack(&stk, NULL);
134 if (err) { 143 if (err) {
135 if (errno == EINVAL) { 144 if (errno == EINVAL) {
136 printf("[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n"); 145 ksft_exit_skip(
146 "[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
137 /* 147 /*
138 * If test cases for the !SS_AUTODISARM variant were 148 * If test cases for the !SS_AUTODISARM variant were
139 * added, we could still run them. We don't have any 149 * added, we could still run them. We don't have any
@@ -142,7 +152,9 @@ int main(void)
142 */ 152 */
143 return 0; 153 return 0;
144 } else { 154 } else {
145 perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)"); 155 ksft_exit_fail_msg(
156 "sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n",
157 strerror(errno));
146 return EXIT_FAILURE; 158 return EXIT_FAILURE;
147 } 159 }
148 } 160 }
@@ -150,7 +162,7 @@ int main(void)
150 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 162 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
151 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 163 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
152 if (ustack == MAP_FAILED) { 164 if (ustack == MAP_FAILED) {
153 perror("mmap()"); 165 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
154 return EXIT_FAILURE; 166 return EXIT_FAILURE;
155 } 167 }
156 getcontext(&uc); 168 getcontext(&uc);
@@ -162,16 +174,17 @@ int main(void)
162 174
163 err = sigaltstack(NULL, &stk); 175 err = sigaltstack(NULL, &stk);
164 if (err) { 176 if (err) {
165 perror("[FAIL]\tsigaltstack()"); 177 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
166 exit(EXIT_FAILURE); 178 exit(EXIT_FAILURE);
167 } 179 }
168 if (stk.ss_flags != SS_AUTODISARM) { 180 if (stk.ss_flags != SS_AUTODISARM) {
169 printf("[FAIL]\tss_flags=%x, should be SS_AUTODISARM\n", 181 ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",
170 stk.ss_flags); 182 stk.ss_flags);
171 exit(EXIT_FAILURE); 183 exit(EXIT_FAILURE);
172 } 184 }
173 printf("[OK]\tsigaltstack is still SS_AUTODISARM after signal\n"); 185 ksft_test_result_pass(
186 "sigaltstack is still SS_AUTODISARM after signal\n");
174 187
175 printf("[OK]\tTest passed\n"); 188 ksft_exit_pass();
176 return 0; 189 return 0;
177} 190}
diff --git a/tools/testing/selftests/splice/.gitignore b/tools/testing/selftests/splice/.gitignore
new file mode 100644
index 000000000000..1e23fefd68e8
--- /dev/null
+++ b/tools/testing/selftests/splice/.gitignore
@@ -0,0 +1 @@
default_file_splice_read
diff --git a/tools/testing/selftests/splice/Makefile b/tools/testing/selftests/splice/Makefile
index 9fc78e5e5451..7e1187e007fa 100644
--- a/tools/testing/selftests/splice/Makefile
+++ b/tools/testing/selftests/splice/Makefile
@@ -1,7 +1,4 @@
1TEST_PROGS := default_file_splice_read.sh 1TEST_PROGS := default_file_splice_read.sh
2EXTRA := default_file_splice_read 2TEST_GEN_PROGS_EXTENDED := default_file_splice_read
3all: $(TEST_PROGS) $(EXTRA)
4 3
5include ../lib.mk 4include ../lib.mk
6
7EXTRA_CLEAN := $(EXTRA)
diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 4981c6b6d050..8e04d0afcbd7 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -2,12 +2,16 @@ CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
2CFLAGS += -I../../../../usr/include/ 2CFLAGS += -I../../../../usr/include/
3LDFLAGS += -pthread 3LDFLAGS += -pthread
4 4
5TEST_PROGS = sync_test 5.PHONY: all clean
6
7all: $(TEST_PROGS)
8 6
9include ../lib.mk 7include ../lib.mk
10 8
9# lib.mk TEST_CUSTOM_PROGS var is for custom tests that need special
10# build rules. lib.mk will run and install them.
11
12TEST_CUSTOM_PROGS := $(OUTPUT)/sync_test
13all: $(TEST_CUSTOM_PROGS)
14
11OBJS = sync_test.o sync.o 15OBJS = sync_test.o sync.o
12 16
13TESTS += sync_alloc.o 17TESTS += sync_alloc.o
@@ -18,6 +22,16 @@ TESTS += sync_stress_parallelism.o
18TESTS += sync_stress_consumer.o 22TESTS += sync_stress_consumer.o
19TESTS += sync_stress_merge.o 23TESTS += sync_stress_merge.o
20 24
21sync_test: $(OBJS) $(TESTS) 25OBJS := $(patsubst %,$(OUTPUT)/%,$(OBJS))
26TESTS := $(patsubst %,$(OUTPUT)/%,$(TESTS))
27
28$(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS)
29 $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS)
30
31$(OBJS): $(OUTPUT)/%.o: %.c
32 $(CC) -c $^ -o $@
33
34$(TESTS): $(OUTPUT)/%.o: %.c
35 $(CC) -c $^ -o $@
22 36
23EXTRA_CLEAN := sync_test $(OBJS) $(TESTS) 37EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS)
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index 62fa666e501a..7f7938263c5c 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -31,62 +31,83 @@
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/stat.h> 32#include <sys/stat.h>
33#include <sys/wait.h> 33#include <sys/wait.h>
34#include <errno.h>
35#include <string.h>
34 36
37#include "../kselftest.h"
35#include "synctest.h" 38#include "synctest.h"
36 39
37static int run_test(int (*test)(void), char *name) 40static int run_test(int (*test)(void), char *name)
38{ 41{
39 int result; 42 int result;
40 pid_t childpid; 43 pid_t childpid;
44 int ret;
41 45
42 fflush(stdout); 46 fflush(stdout);
43 childpid = fork(); 47 childpid = fork();
44 48
45 if (childpid) { 49 if (childpid) {
46 waitpid(childpid, &result, 0); 50 waitpid(childpid, &result, 0);
47 if (WIFEXITED(result)) 51 if (WIFEXITED(result)) {
48 return WEXITSTATUS(result); 52 ret = WEXITSTATUS(result);
53 if (!ret)
54 ksft_test_result_pass("[RUN]\t%s\n", name);
55 else
56 ksft_test_result_fail("[RUN]\t%s\n", name);
57 return ret;
58 }
49 return 1; 59 return 1;
50 } 60 }
51 61
52 printf("[RUN]\tExecuting %s\n", name);
53 exit(test()); 62 exit(test());
54} 63}
55 64
56static int sync_api_supported(void) 65static void sync_api_supported(void)
57{ 66{
58 struct stat sbuf; 67 struct stat sbuf;
68 int ret;
59 69
60 return 0 == stat("/sys/kernel/debug/sync/sw_sync", &sbuf); 70 ret = stat("/sys/kernel/debug/sync/sw_sync", &sbuf);
71 if (!ret)
72 return;
73
74 if (errno == ENOENT)
75 ksft_exit_skip("Sync framework not supported by kernel\n");
76
77 if (errno == EACCES)
78 ksft_exit_skip("Run Sync test as root.\n");
79
80 ksft_exit_fail_msg("stat failed on /sys/kernel/debug/sync/sw_sync: %s",
81 strerror(errno));
61} 82}
62 83
63int main(void) 84int main(void)
64{ 85{
65 int err = 0; 86 int err;
66 87
67 if (!sync_api_supported()) { 88 ksft_print_header();
68 printf("SKIP: Sync framework not supported by kernel\n"); 89
69 return 0; 90 sync_api_supported();
70 }
71 91
72 printf("[RUN]\tTesting sync framework\n"); 92 ksft_print_msg("[RUN]\tTesting sync framework\n");
73 93
74 err += RUN_TEST(test_alloc_timeline); 94 RUN_TEST(test_alloc_timeline);
75 err += RUN_TEST(test_alloc_fence); 95 RUN_TEST(test_alloc_fence);
76 err += RUN_TEST(test_alloc_fence_negative); 96 RUN_TEST(test_alloc_fence_negative);
77 97
78 err += RUN_TEST(test_fence_one_timeline_wait); 98 RUN_TEST(test_fence_one_timeline_wait);
79 err += RUN_TEST(test_fence_one_timeline_merge); 99 RUN_TEST(test_fence_one_timeline_merge);
80 err += RUN_TEST(test_fence_merge_same_fence); 100 RUN_TEST(test_fence_merge_same_fence);
81 err += RUN_TEST(test_fence_multi_timeline_wait); 101 RUN_TEST(test_fence_multi_timeline_wait);
82 err += RUN_TEST(test_stress_two_threads_shared_timeline); 102 RUN_TEST(test_stress_two_threads_shared_timeline);
83 err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer); 103 RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
84 err += RUN_TEST(test_merge_stress_random_merge); 104 RUN_TEST(test_merge_stress_random_merge);
85 105
106 err = ksft_get_fail_cnt();
86 if (err) 107 if (err)
87 printf("[FAIL]\tsync errors: %d\n", err); 108 ksft_exit_fail_msg("%d out of %d sync tests failed\n",
88 else 109 err, ksft_test_num());
89 printf("[OK]\tsync\n");
90 110
91 return !!err; 111 /* need this return to keep gcc happy */
112 return ksft_exit_pass();
92} 113}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index e7d1d57dba7a..90a8e5369914 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -29,10 +29,11 @@
29#define SELFTESTS_SYNCTEST_H 29#define SELFTESTS_SYNCTEST_H
30 30
31#include <stdio.h> 31#include <stdio.h>
32#include "../kselftest.h"
32 33
33#define ASSERT(cond, msg) do { \ 34#define ASSERT(cond, msg) do { \
34 if (!(cond)) { \ 35 if (!(cond)) { \
35 printf("[ERROR]\t%s", (msg)); \ 36 ksft_print_msg("[ERROR]\t%s", (msg)); \
36 return 1; \ 37 return 1; \
37 } \ 38 } \
38} while (0) 39} while (0)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
index af519bc97a8e..6973bdc5b5bf 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
@@ -1111,5 +1111,55 @@
1111 "teardown": [ 1111 "teardown": [
1112 "$TC actions flush action gact" 1112 "$TC actions flush action gact"
1113 ] 1113 ]
1114 },
1115 {
1116 "id": "a568",
1117 "name": "Add action with ife type",
1118 "category": [
1119 "actions",
1120 "ife"
1121 ],
1122 "setup": [
1123 [
1124 "$TC actions flush action ife",
1125 0,
1126 1,
1127 255
1128 ],
1129 "$TC actions add action ife encode type 0xDEAD index 1"
1130 ],
1131 "cmdUnderTest": "$TC actions get action ife index 1",
1132 "expExitCode": "0",
1133 "verifyCmd": "$TC actions get action ife index 1",
1134 "matchPattern": "type 0xDEAD",
1135 "matchCount": "1",
1136 "teardown": [
1137 "$TC actions flush action ife"
1138 ]
1139 },
1140 {
1141 "id": "b983",
1142 "name": "Add action without ife type",
1143 "category": [
1144 "actions",
1145 "ife"
1146 ],
1147 "setup": [
1148 [
1149 "$TC actions flush action ife",
1150 0,
1151 1,
1152 255
1153 ],
1154 "$TC actions add action ife encode index 1"
1155 ],
1156 "cmdUnderTest": "$TC actions get action ife index 1",
1157 "expExitCode": "0",
1158 "verifyCmd": "$TC actions get action ife index 1",
1159 "matchPattern": "type 0xED3E",
1160 "matchCount": "1",
1161 "teardown": [
1162 "$TC actions flush action ife"
1163 ]
1114 } 1164 }
1115] \ No newline at end of file 1165] \ No newline at end of file
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index a9b86133b9b3..ae4593115408 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,5 +1,4 @@
1BUILD_FLAGS = -DKTEST 1CFLAGS += -O3 -Wl,-no-as-needed -Wall
2CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
3LDFLAGS += -lrt -lpthread -lm 2LDFLAGS += -lrt -lpthread -lm
4 3
5# these are all "safe" tests that don't modify 4# these are all "safe" tests that don't modify
@@ -7,9 +6,11 @@ LDFLAGS += -lrt -lpthread -lm
7TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \ 6TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
8 inconsistency-check raw_skew threadtest rtctest 7 inconsistency-check raw_skew threadtest rtctest
9 8
10TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ 9DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
11 skew_consistency clocksource-switch freq-step leap-a-day \ 10 skew_consistency clocksource-switch freq-step leap-a-day \
12 leapcrash set-tai set-2038 set-tz rtctest_setdate 11 leapcrash set-tai set-2038 set-tz
12
13TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS) rtctest_setdate
13 14
14 15
15include ../lib.mk 16include ../lib.mk
@@ -18,16 +19,4 @@ include ../lib.mk
18# and may modify the system time or trigger 19# and may modify the system time or trigger
19# other behavior like suspend 20# other behavior like suspend
20run_destructive_tests: run_tests 21run_destructive_tests: run_tests
21 ./alarmtimer-suspend 22 $(call RUN_TESTS, $(DESTRUCTIVE_TESTS))
22 ./valid-adjtimex
23 ./adjtick
24 ./change_skew
25 ./skew_consistency
26 ./clocksource-switch
27 ./freq-step
28 ./leap-a-day -s -i 10
29 ./leapcrash
30 ./set-tz
31 ./set-tai
32 ./set-2038
33
diff --git a/tools/testing/selftests/timers/adjtick.c b/tools/testing/selftests/timers/adjtick.c
index 9887fd538fec..0caca3a06bd2 100644
--- a/tools/testing/selftests/timers/adjtick.c
+++ b/tools/testing/selftests/timers/adjtick.c
@@ -23,18 +23,7 @@
23#include <sys/timex.h> 23#include <sys/timex.h>
24#include <time.h> 24#include <time.h>
25 25
26#ifdef KTEST
27#include "../kselftest.h" 26#include "../kselftest.h"
28#else
29static inline int ksft_exit_pass(void)
30{
31 exit(0);
32}
33static inline int ksft_exit_fail(void)
34{
35 exit(1);
36}
37#endif
38 27
39#define CLOCK_MONOTONIC_RAW 4 28#define CLOCK_MONOTONIC_RAW 4
40 29
diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/testing/selftests/timers/alarmtimer-suspend.c
index 2b361b830395..4da09dbf83ba 100644
--- a/tools/testing/selftests/timers/alarmtimer-suspend.c
+++ b/tools/testing/selftests/timers/alarmtimer-suspend.c
@@ -28,18 +28,7 @@
28#include <signal.h> 28#include <signal.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <pthread.h> 30#include <pthread.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define CLOCK_REALTIME 0 33#define CLOCK_REALTIME 0
45#define CLOCK_MONOTONIC 1 34#define CLOCK_MONOTONIC 1
diff --git a/tools/testing/selftests/timers/change_skew.c b/tools/testing/selftests/timers/change_skew.c
index cb1968977c04..c4eab7124990 100644
--- a/tools/testing/selftests/timers/change_skew.c
+++ b/tools/testing/selftests/timers/change_skew.c
@@ -28,18 +28,7 @@
28#include <sys/time.h> 28#include <sys/time.h>
29#include <sys/timex.h> 29#include <sys/timex.h>
30#include <time.h> 30#include <time.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define NSEC_PER_SEC 1000000000LL 33#define NSEC_PER_SEC 1000000000LL
45 34
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c
index 5ff165373f8b..bfc974b4572d 100644
--- a/tools/testing/selftests/timers/clocksource-switch.c
+++ b/tools/testing/selftests/timers/clocksource-switch.c
@@ -34,18 +34,7 @@
34#include <fcntl.h> 34#include <fcntl.h>
35#include <string.h> 35#include <string.h>
36#include <sys/wait.h> 36#include <sys/wait.h>
37#ifdef KTEST
38#include "../kselftest.h" 37#include "../kselftest.h"
39#else
40static inline int ksft_exit_pass(void)
41{
42 exit(0);
43}
44static inline int ksft_exit_fail(void)
45{
46 exit(1);
47}
48#endif
49 38
50 39
51int get_clocksources(char list[][30]) 40int get_clocksources(char list[][30])
@@ -61,7 +50,7 @@ int get_clocksources(char list[][30])
61 50
62 close(fd); 51 close(fd);
63 52
64 for (i = 0; i < 30; i++) 53 for (i = 0; i < 10; i++)
65 list[i][0] = '\0'; 54 list[i][0] = '\0';
66 55
67 head = buf; 56 head = buf;
diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c
index 74c60e8759a0..022d3ffe3fbf 100644
--- a/tools/testing/selftests/timers/inconsistency-check.c
+++ b/tools/testing/selftests/timers/inconsistency-check.c
@@ -28,18 +28,7 @@
28#include <sys/timex.h> 28#include <sys/timex.h>
29#include <string.h> 29#include <string.h>
30#include <signal.h> 30#include <signal.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define CALLS_PER_LOOP 64 33#define CALLS_PER_LOOP 64
45#define NSEC_PER_SEC 1000000000ULL 34#define NSEC_PER_SEC 1000000000ULL
diff --git a/tools/testing/selftests/timers/leap-a-day.c b/tools/testing/selftests/timers/leap-a-day.c
index fb46ad6ac92c..19e46ed5dfb5 100644
--- a/tools/testing/selftests/timers/leap-a-day.c
+++ b/tools/testing/selftests/timers/leap-a-day.c
@@ -48,18 +48,7 @@
48#include <string.h> 48#include <string.h>
49#include <signal.h> 49#include <signal.h>
50#include <unistd.h> 50#include <unistd.h>
51#ifdef KTEST
52#include "../kselftest.h" 51#include "../kselftest.h"
53#else
54static inline int ksft_exit_pass(void)
55{
56 exit(0);
57}
58static inline int ksft_exit_fail(void)
59{
60 exit(1);
61}
62#endif
63 52
64#define NSEC_PER_SEC 1000000000ULL 53#define NSEC_PER_SEC 1000000000ULL
65#define CLOCK_TAI 11 54#define CLOCK_TAI 11
@@ -190,18 +179,18 @@ int main(int argc, char **argv)
190 struct sigevent se; 179 struct sigevent se;
191 struct sigaction act; 180 struct sigaction act;
192 int signum = SIGRTMAX; 181 int signum = SIGRTMAX;
193 int settime = 0; 182 int settime = 1;
194 int tai_time = 0; 183 int tai_time = 0;
195 int insert = 1; 184 int insert = 1;
196 int iterations = -1; 185 int iterations = 10;
197 int opt; 186 int opt;
198 187
199 /* Process arguments */ 188 /* Process arguments */
200 while ((opt = getopt(argc, argv, "sti:")) != -1) { 189 while ((opt = getopt(argc, argv, "sti:")) != -1) {
201 switch (opt) { 190 switch (opt) {
202 case 's': 191 case 'w':
203 printf("Setting time to speed up testing\n"); 192 printf("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n");
204 settime = 1; 193 settime = 0;
205 break; 194 break;
206 case 'i': 195 case 'i':
207 iterations = atoi(optarg); 196 iterations = atoi(optarg);
@@ -210,9 +199,10 @@ int main(int argc, char **argv)
210 tai_time = 1; 199 tai_time = 1;
211 break; 200 break;
212 default: 201 default:
213 printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]); 202 printf("Usage: %s [-w] [-i <iterations>]\n", argv[0]);
214 printf(" -s: Set time to right before leap second each iteration\n"); 203 printf(" -w: Set flag and wait for leap second each iteration");
215 printf(" -i: Number of iterations\n"); 204 printf(" (default sets time to right before leapsecond)\n");
205 printf(" -i: Number of iterations (-1 = infinite, default is 10)\n");
216 printf(" -t: Print TAI time\n"); 206 printf(" -t: Print TAI time\n");
217 exit(-1); 207 exit(-1);
218 } 208 }
diff --git a/tools/testing/selftests/timers/leapcrash.c b/tools/testing/selftests/timers/leapcrash.c
index a1071bdbdeb7..830c462f605d 100644
--- a/tools/testing/selftests/timers/leapcrash.c
+++ b/tools/testing/selftests/timers/leapcrash.c
@@ -22,20 +22,7 @@
22#include <sys/timex.h> 22#include <sys/timex.h>
23#include <string.h> 23#include <string.h>
24#include <signal.h> 24#include <signal.h>
25#ifdef KTEST
26#include "../kselftest.h" 25#include "../kselftest.h"
27#else
28static inline int ksft_exit_pass(void)
29{
30 exit(0);
31}
32static inline int ksft_exit_fail(void)
33{
34 exit(1);
35}
36#endif
37
38
39 26
40/* clear NTP time_status & time_state */ 27/* clear NTP time_status & time_state */
41int clear_time_state(void) 28int clear_time_state(void)
diff --git a/tools/testing/selftests/timers/mqueue-lat.c b/tools/testing/selftests/timers/mqueue-lat.c
index a2a3924d0b41..1867db5d6f5e 100644
--- a/tools/testing/selftests/timers/mqueue-lat.c
+++ b/tools/testing/selftests/timers/mqueue-lat.c
@@ -29,18 +29,7 @@
29#include <signal.h> 29#include <signal.h>
30#include <errno.h> 30#include <errno.h>
31#include <mqueue.h> 31#include <mqueue.h>
32#ifdef KTEST
33#include "../kselftest.h" 32#include "../kselftest.h"
34#else
35static inline int ksft_exit_pass(void)
36{
37 exit(0);
38}
39static inline int ksft_exit_fail(void)
40{
41 exit(1);
42}
43#endif
44 33
45#define NSEC_PER_SEC 1000000000ULL 34#define NSEC_PER_SEC 1000000000ULL
46 35
diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/selftests/timers/nanosleep.c
index ff942ff7c9b3..8adb0bb51d4d 100644
--- a/tools/testing/selftests/timers/nanosleep.c
+++ b/tools/testing/selftests/timers/nanosleep.c
@@ -27,18 +27,7 @@
27#include <sys/timex.h> 27#include <sys/timex.h>
28#include <string.h> 28#include <string.h>
29#include <signal.h> 29#include <signal.h>
30#ifdef KTEST
31#include "../kselftest.h" 30#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42 31
43#define NSEC_PER_SEC 1000000000ULL 32#define NSEC_PER_SEC 1000000000ULL
44 33
diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c
index 2d7898fda0f1..c3c3dc10db17 100644
--- a/tools/testing/selftests/timers/nsleep-lat.c
+++ b/tools/testing/selftests/timers/nsleep-lat.c
@@ -24,18 +24,7 @@
24#include <sys/timex.h> 24#include <sys/timex.h>
25#include <string.h> 25#include <string.h>
26#include <signal.h> 26#include <signal.h>
27#ifdef KTEST
28#include "../kselftest.h" 27#include "../kselftest.h"
29#else
30static inline int ksft_exit_pass(void)
31{
32 exit(0);
33}
34static inline int ksft_exit_fail(void)
35{
36 exit(1);
37}
38#endif
39 28
40#define NSEC_PER_SEC 1000000000ULL 29#define NSEC_PER_SEC 1000000000ULL
41 30
diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c
index 30906bfd9c1b..ca6cd146aafe 100644
--- a/tools/testing/selftests/timers/raw_skew.c
+++ b/tools/testing/selftests/timers/raw_skew.c
@@ -25,19 +25,7 @@
25#include <sys/time.h> 25#include <sys/time.h>
26#include <sys/timex.h> 26#include <sys/timex.h>
27#include <time.h> 27#include <time.h>
28#ifdef KTEST
29#include "../kselftest.h" 28#include "../kselftest.h"
30#else
31static inline int ksft_exit_pass(void)
32{
33 exit(0);
34}
35static inline int ksft_exit_fail(void)
36{
37 exit(1);
38}
39#endif
40
41 29
42#define CLOCK_MONOTONIC_RAW 4 30#define CLOCK_MONOTONIC_RAW 4
43#define NSEC_PER_SEC 1000000000LL 31#define NSEC_PER_SEC 1000000000LL
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index f61170f7b024..411eff625e66 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -221,6 +221,11 @@ test_READ:
221 /* Read the current alarm settings */ 221 /* Read the current alarm settings */
222 retval = ioctl(fd, RTC_ALM_READ, &rtc_tm); 222 retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
223 if (retval == -1) { 223 if (retval == -1) {
224 if (errno == EINVAL) {
225 fprintf(stderr,
226 "\n...EINVAL reading current alarm setting.\n");
227 goto test_PIE;
228 }
224 perror("RTC_ALM_READ ioctl"); 229 perror("RTC_ALM_READ ioctl");
225 exit(errno); 230 exit(errno);
226 } 231 }
@@ -231,7 +236,7 @@ test_READ:
231 /* Enable alarm interrupts */ 236 /* Enable alarm interrupts */
232 retval = ioctl(fd, RTC_AIE_ON, 0); 237 retval = ioctl(fd, RTC_AIE_ON, 0);
233 if (retval == -1) { 238 if (retval == -1) {
234 if (errno == EINVAL) { 239 if (errno == EINVAL || errno == EIO) {
235 fprintf(stderr, 240 fprintf(stderr,
236 "\n...Alarm IRQs not supported.\n"); 241 "\n...Alarm IRQs not supported.\n");
237 goto test_PIE; 242 goto test_PIE;
diff --git a/tools/testing/selftests/timers/set-2038.c b/tools/testing/selftests/timers/set-2038.c
index c8a7e14446b1..688cfd81b531 100644
--- a/tools/testing/selftests/timers/set-2038.c
+++ b/tools/testing/selftests/timers/set-2038.c
@@ -27,18 +27,7 @@
27#include <unistd.h> 27#include <unistd.h>
28#include <time.h> 28#include <time.h>
29#include <sys/time.h> 29#include <sys/time.h>
30#ifdef KTEST
31#include "../kselftest.h" 30#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42 31
43#define NSEC_PER_SEC 1000000000LL 32#define NSEC_PER_SEC 1000000000LL
44 33
diff --git a/tools/testing/selftests/timers/set-tai.c b/tools/testing/selftests/timers/set-tai.c
index dc88dbc8831f..70fed27d8fd3 100644
--- a/tools/testing/selftests/timers/set-tai.c
+++ b/tools/testing/selftests/timers/set-tai.c
@@ -23,18 +23,7 @@
23#include <string.h> 23#include <string.h>
24#include <signal.h> 24#include <signal.h>
25#include <unistd.h> 25#include <unistd.h>
26#ifdef KTEST
27#include "../kselftest.h" 26#include "../kselftest.h"
28#else
29static inline int ksft_exit_pass(void)
30{
31 exit(0);
32}
33static inline int ksft_exit_fail(void)
34{
35 exit(1);
36}
37#endif
38 27
39int set_tai(int offset) 28int set_tai(int offset)
40{ 29{
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c
index 15434da23b04..50da45437daa 100644
--- a/tools/testing/selftests/timers/set-timer-lat.c
+++ b/tools/testing/selftests/timers/set-timer-lat.c
@@ -28,18 +28,7 @@
28#include <signal.h> 28#include <signal.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <pthread.h> 30#include <pthread.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define CLOCK_REALTIME 0 33#define CLOCK_REALTIME 0
45#define CLOCK_MONOTONIC 1 34#define CLOCK_MONOTONIC 1
@@ -154,7 +143,8 @@ int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
154 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n", 143 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n",
155 clockstring(clock_id), 144 clockstring(clock_id),
156 flags ? "ABSTIME":"RELTIME"); 145 flags ? "ABSTIME":"RELTIME");
157 return 0; 146 /* Indicate timer isn't set, so caller doesn't wait */
147 return 1;
158 } 148 }
159 printf("%s - timer_create() failed\n", clockstring(clock_id)); 149 printf("%s - timer_create() failed\n", clockstring(clock_id));
160 return -1; 150 return -1;
@@ -224,8 +214,9 @@ int do_timer(int clock_id, int flags)
224 int err; 214 int err;
225 215
226 err = setup_timer(clock_id, flags, interval, &tm1); 216 err = setup_timer(clock_id, flags, interval, &tm1);
217 /* Unsupported case - return 0 to not fail the test */
227 if (err) 218 if (err)
228 return err; 219 return err == 1 ? 0 : err;
229 220
230 while (alarmcount < 5) 221 while (alarmcount < 5)
231 sleep(1); 222 sleep(1);
@@ -239,18 +230,17 @@ int do_timer_oneshot(int clock_id, int flags)
239 timer_t tm1; 230 timer_t tm1;
240 const int interval = 0; 231 const int interval = 0;
241 struct timeval timeout; 232 struct timeval timeout;
242 fd_set fds;
243 int err; 233 int err;
244 234
245 err = setup_timer(clock_id, flags, interval, &tm1); 235 err = setup_timer(clock_id, flags, interval, &tm1);
236 /* Unsupported case - return 0 to not fail the test */
246 if (err) 237 if (err)
247 return err; 238 return err == 1 ? 0 : err;
248 239
249 memset(&timeout, 0, sizeof(timeout)); 240 memset(&timeout, 0, sizeof(timeout));
250 timeout.tv_sec = 5; 241 timeout.tv_sec = 5;
251 FD_ZERO(&fds);
252 do { 242 do {
253 err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); 243 err = select(0, NULL, NULL, NULL, &timeout);
254 } while (err == -1 && errno == EINTR); 244 } while (err == -1 && errno == EINTR);
255 245
256 timer_delete(tm1); 246 timer_delete(tm1);
diff --git a/tools/testing/selftests/timers/set-tz.c b/tools/testing/selftests/timers/set-tz.c
index f4184928b16b..877fd5532fee 100644
--- a/tools/testing/selftests/timers/set-tz.c
+++ b/tools/testing/selftests/timers/set-tz.c
@@ -23,18 +23,7 @@
23#include <string.h> 23#include <string.h>
24#include <signal.h> 24#include <signal.h>
25#include <unistd.h> 25#include <unistd.h>
26#ifdef KTEST
27#include "../kselftest.h" 26#include "../kselftest.h"
28#else
29static inline int ksft_exit_pass(void)
30{
31 exit(0);
32}
33static inline int ksft_exit_fail(void)
34{
35 exit(1);
36}
37#endif
38 27
39int set_tz(int min, int dst) 28int set_tz(int min, int dst)
40{ 29{
diff --git a/tools/testing/selftests/timers/skew_consistency.c b/tools/testing/selftests/timers/skew_consistency.c
index 2a996e072259..022b711c78ee 100644
--- a/tools/testing/selftests/timers/skew_consistency.c
+++ b/tools/testing/selftests/timers/skew_consistency.c
@@ -35,18 +35,7 @@
35#include <stdlib.h> 35#include <stdlib.h>
36#include <string.h> 36#include <string.h>
37#include <sys/wait.h> 37#include <sys/wait.h>
38#ifdef KTEST
39#include "../kselftest.h" 38#include "../kselftest.h"
40#else
41static inline int ksft_exit_pass(void)
42{
43 exit(0);
44}
45static inline int ksft_exit_fail(void)
46{
47 exit(1);
48}
49#endif
50 39
51#define NSEC_PER_SEC 1000000000LL 40#define NSEC_PER_SEC 1000000000LL
52 41
diff --git a/tools/testing/selftests/timers/threadtest.c b/tools/testing/selftests/timers/threadtest.c
index e632e116f05e..759c9c06f1a0 100644
--- a/tools/testing/selftests/timers/threadtest.c
+++ b/tools/testing/selftests/timers/threadtest.c
@@ -21,19 +21,7 @@
21#include <stdlib.h> 21#include <stdlib.h>
22#include <sys/time.h> 22#include <sys/time.h>
23#include <pthread.h> 23#include <pthread.h>
24#ifdef KTEST
25#include "../kselftest.h" 24#include "../kselftest.h"
26#else
27static inline int ksft_exit_pass(void)
28{
29 exit(0);
30}
31static inline int ksft_exit_fail(void)
32{
33 exit(1);
34}
35#endif
36
37 25
38/* serializes shared list access */ 26/* serializes shared list access */
39pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER; 27pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
index 60fe3c569bd9..d9d3ab93b31a 100644
--- a/tools/testing/selftests/timers/valid-adjtimex.c
+++ b/tools/testing/selftests/timers/valid-adjtimex.c
@@ -32,18 +32,7 @@
32#include <string.h> 32#include <string.h>
33#include <signal.h> 33#include <signal.h>
34#include <unistd.h> 34#include <unistd.h>
35#ifdef KTEST
36#include "../kselftest.h" 35#include "../kselftest.h"
37#else
38static inline int ksft_exit_pass(void)
39{
40 exit(0);
41}
42static inline int ksft_exit_fail(void)
43{
44 exit(1);
45}
46#endif
47 36
48#define NSEC_PER_SEC 1000000000LL 37#define NSEC_PER_SEC 1000000000LL
49#define USEC_PER_SEC 1000000LL 38#define USEC_PER_SEC 1000000LL
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 1eae79ae5b4e..a2c53a3d223d 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -66,6 +66,8 @@
66#include <sys/wait.h> 66#include <sys/wait.h>
67#include <pthread.h> 67#include <pthread.h>
68#include <linux/userfaultfd.h> 68#include <linux/userfaultfd.h>
69#include <setjmp.h>
70#include <stdbool.h>
69 71
70#ifdef __NR_userfaultfd 72#ifdef __NR_userfaultfd
71 73
@@ -82,11 +84,17 @@ static int bounces;
82#define TEST_SHMEM 3 84#define TEST_SHMEM 3
83static int test_type; 85static int test_type;
84 86
87/* exercise the test_uffdio_*_eexist every ALARM_INTERVAL_SECS */
88#define ALARM_INTERVAL_SECS 10
89static volatile bool test_uffdio_copy_eexist = true;
90static volatile bool test_uffdio_zeropage_eexist = true;
91
92static bool map_shared;
85static int huge_fd; 93static int huge_fd;
86static char *huge_fd_off0; 94static char *huge_fd_off0;
87static unsigned long long *count_verify; 95static unsigned long long *count_verify;
88static int uffd, uffd_flags, finished, *pipefd; 96static int uffd, uffd_flags, finished, *pipefd;
89static char *area_src, *area_dst; 97static char *area_src, *area_src_alias, *area_dst, *area_dst_alias;
90static char *zeropage; 98static char *zeropage;
91pthread_attr_t attr; 99pthread_attr_t attr;
92 100
@@ -125,6 +133,9 @@ static void anon_allocate_area(void **alloc_area)
125 } 133 }
126} 134}
127 135
136static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
137{
138}
128 139
129/* HugeTLB memory */ 140/* HugeTLB memory */
130static int hugetlb_release_pages(char *rel_area) 141static int hugetlb_release_pages(char *rel_area)
@@ -145,17 +156,51 @@ static int hugetlb_release_pages(char *rel_area)
145 156
146static void hugetlb_allocate_area(void **alloc_area) 157static void hugetlb_allocate_area(void **alloc_area)
147{ 158{
159 void *area_alias = NULL;
160 char **alloc_area_alias;
148 *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, 161 *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
149 MAP_PRIVATE | MAP_HUGETLB, huge_fd, 162 (map_shared ? MAP_SHARED : MAP_PRIVATE) |
150 *alloc_area == area_src ? 0 : 163 MAP_HUGETLB,
151 nr_pages * page_size); 164 huge_fd, *alloc_area == area_src ? 0 :
165 nr_pages * page_size);
152 if (*alloc_area == MAP_FAILED) { 166 if (*alloc_area == MAP_FAILED) {
153 fprintf(stderr, "mmap of hugetlbfs file failed\n"); 167 fprintf(stderr, "mmap of hugetlbfs file failed\n");
154 *alloc_area = NULL; 168 *alloc_area = NULL;
155 } 169 }
156 170
157 if (*alloc_area == area_src) 171 if (map_shared) {
172 area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
173 MAP_SHARED | MAP_HUGETLB,
174 huge_fd, *alloc_area == area_src ? 0 :
175 nr_pages * page_size);
176 if (area_alias == MAP_FAILED) {
177 if (munmap(*alloc_area, nr_pages * page_size) < 0)
178 perror("hugetlb munmap"), exit(1);
179 *alloc_area = NULL;
180 return;
181 }
182 }
183 if (*alloc_area == area_src) {
158 huge_fd_off0 = *alloc_area; 184 huge_fd_off0 = *alloc_area;
185 alloc_area_alias = &area_src_alias;
186 } else {
187 alloc_area_alias = &area_dst_alias;
188 }
189 if (area_alias)
190 *alloc_area_alias = area_alias;
191}
192
193static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset)
194{
195 if (!map_shared)
196 return;
197 /*
198 * We can't zap just the pagetable with hugetlbfs because
199 * MADV_DONTEED won't work. So exercise -EEXIST on a alias
200 * mapping where the pagetables are not established initially,
201 * this way we'll exercise the -EEXEC at the fs level.
202 */
203 *start = (unsigned long) area_dst_alias + offset;
159} 204}
160 205
161/* Shared memory */ 206/* Shared memory */
@@ -185,6 +230,7 @@ struct uffd_test_ops {
185 unsigned long expected_ioctls; 230 unsigned long expected_ioctls;
186 void (*allocate_area)(void **alloc_area); 231 void (*allocate_area)(void **alloc_area);
187 int (*release_pages)(char *rel_area); 232 int (*release_pages)(char *rel_area);
233 void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset);
188}; 234};
189 235
190#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \ 236#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
@@ -195,18 +241,21 @@ static struct uffd_test_ops anon_uffd_test_ops = {
195 .expected_ioctls = ANON_EXPECTED_IOCTLS, 241 .expected_ioctls = ANON_EXPECTED_IOCTLS,
196 .allocate_area = anon_allocate_area, 242 .allocate_area = anon_allocate_area,
197 .release_pages = anon_release_pages, 243 .release_pages = anon_release_pages,
244 .alias_mapping = noop_alias_mapping,
198}; 245};
199 246
200static struct uffd_test_ops shmem_uffd_test_ops = { 247static struct uffd_test_ops shmem_uffd_test_ops = {
201 .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC, 248 .expected_ioctls = ANON_EXPECTED_IOCTLS,
202 .allocate_area = shmem_allocate_area, 249 .allocate_area = shmem_allocate_area,
203 .release_pages = shmem_release_pages, 250 .release_pages = shmem_release_pages,
251 .alias_mapping = noop_alias_mapping,
204}; 252};
205 253
206static struct uffd_test_ops hugetlb_uffd_test_ops = { 254static struct uffd_test_ops hugetlb_uffd_test_ops = {
207 .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC, 255 .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
208 .allocate_area = hugetlb_allocate_area, 256 .allocate_area = hugetlb_allocate_area,
209 .release_pages = hugetlb_release_pages, 257 .release_pages = hugetlb_release_pages,
258 .alias_mapping = hugetlb_alias_mapping,
210}; 259};
211 260
212static struct uffd_test_ops *uffd_test_ops; 261static struct uffd_test_ops *uffd_test_ops;
@@ -331,6 +380,23 @@ static void *locking_thread(void *arg)
331 return NULL; 380 return NULL;
332} 381}
333 382
383static void retry_copy_page(int ufd, struct uffdio_copy *uffdio_copy,
384 unsigned long offset)
385{
386 uffd_test_ops->alias_mapping(&uffdio_copy->dst,
387 uffdio_copy->len,
388 offset);
389 if (ioctl(ufd, UFFDIO_COPY, uffdio_copy)) {
390 /* real retval in ufdio_copy.copy */
391 if (uffdio_copy->copy != -EEXIST)
392 fprintf(stderr, "UFFDIO_COPY retry error %Ld\n",
393 uffdio_copy->copy), exit(1);
394 } else {
395 fprintf(stderr, "UFFDIO_COPY retry unexpected %Ld\n",
396 uffdio_copy->copy), exit(1);
397 }
398}
399
334static int copy_page(int ufd, unsigned long offset) 400static int copy_page(int ufd, unsigned long offset)
335{ 401{
336 struct uffdio_copy uffdio_copy; 402 struct uffdio_copy uffdio_copy;
@@ -351,8 +417,13 @@ static int copy_page(int ufd, unsigned long offset)
351 } else if (uffdio_copy.copy != page_size) { 417 } else if (uffdio_copy.copy != page_size) {
352 fprintf(stderr, "UFFDIO_COPY unexpected copy %Ld\n", 418 fprintf(stderr, "UFFDIO_COPY unexpected copy %Ld\n",
353 uffdio_copy.copy), exit(1); 419 uffdio_copy.copy), exit(1);
354 } else 420 } else {
421 if (test_uffdio_copy_eexist) {
422 test_uffdio_copy_eexist = false;
423 retry_copy_page(ufd, &uffdio_copy, offset);
424 }
355 return 1; 425 return 1;
426 }
356 return 0; 427 return 0;
357} 428}
358 429
@@ -408,6 +479,7 @@ static void *uffd_poll_thread(void *arg)
408 userfaults++; 479 userfaults++;
409 break; 480 break;
410 case UFFD_EVENT_FORK: 481 case UFFD_EVENT_FORK:
482 close(uffd);
411 uffd = msg.arg.fork.ufd; 483 uffd = msg.arg.fork.ufd;
412 pollfd[0].fd = uffd; 484 pollfd[0].fd = uffd;
413 break; 485 break;
@@ -572,6 +644,17 @@ static int userfaultfd_open(int features)
572 return 0; 644 return 0;
573} 645}
574 646
647sigjmp_buf jbuf, *sigbuf;
648
649static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
650{
651 if (sig == SIGBUS) {
652 if (sigbuf)
653 siglongjmp(*sigbuf, 1);
654 abort();
655 }
656}
657
575/* 658/*
576 * For non-cooperative userfaultfd test we fork() a process that will 659 * For non-cooperative userfaultfd test we fork() a process that will
577 * generate pagefaults, will mremap the area monitored by the 660 * generate pagefaults, will mremap the area monitored by the
@@ -585,19 +668,59 @@ static int userfaultfd_open(int features)
585 * The release of the pages currently generates event for shmem and 668 * The release of the pages currently generates event for shmem and
586 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked 669 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
587 * for hugetlb. 670 * for hugetlb.
671 * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register
672 * monitored area, generate pagefaults and test that signal is delivered.
673 * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2
674 * test robustness use case - we release monitored area, fork a process
675 * that will generate pagefaults and verify signal is generated.
676 * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
677 * feature. Using monitor thread, verify no userfault events are generated.
588 */ 678 */
589static int faulting_process(void) 679static int faulting_process(int signal_test)
590{ 680{
591 unsigned long nr; 681 unsigned long nr;
592 unsigned long long count; 682 unsigned long long count;
593 unsigned long split_nr_pages; 683 unsigned long split_nr_pages;
684 unsigned long lastnr;
685 struct sigaction act;
686 unsigned long signalled = 0;
594 687
595 if (test_type != TEST_HUGETLB) 688 if (test_type != TEST_HUGETLB)
596 split_nr_pages = (nr_pages + 1) / 2; 689 split_nr_pages = (nr_pages + 1) / 2;
597 else 690 else
598 split_nr_pages = nr_pages; 691 split_nr_pages = nr_pages;
599 692
693 if (signal_test) {
694 sigbuf = &jbuf;
695 memset(&act, 0, sizeof(act));
696 act.sa_sigaction = sighndl;
697 act.sa_flags = SA_SIGINFO;
698 if (sigaction(SIGBUS, &act, 0)) {
699 perror("sigaction");
700 return 1;
701 }
702 lastnr = (unsigned long)-1;
703 }
704
600 for (nr = 0; nr < split_nr_pages; nr++) { 705 for (nr = 0; nr < split_nr_pages; nr++) {
706 if (signal_test) {
707 if (sigsetjmp(*sigbuf, 1) != 0) {
708 if (nr == lastnr) {
709 fprintf(stderr, "Signal repeated\n");
710 return 1;
711 }
712
713 lastnr = nr;
714 if (signal_test == 1) {
715 if (copy_page(uffd, nr * page_size))
716 signalled++;
717 } else {
718 signalled++;
719 continue;
720 }
721 }
722 }
723
601 count = *area_count(area_dst, nr); 724 count = *area_count(area_dst, nr);
602 if (count != count_verify[nr]) { 725 if (count != count_verify[nr]) {
603 fprintf(stderr, 726 fprintf(stderr,
@@ -607,6 +730,9 @@ static int faulting_process(void)
607 } 730 }
608 } 731 }
609 732
733 if (signal_test)
734 return signalled != split_nr_pages;
735
610 if (test_type == TEST_HUGETLB) 736 if (test_type == TEST_HUGETLB)
611 return 0; 737 return 0;
612 738
@@ -636,6 +762,23 @@ static int faulting_process(void)
636 return 0; 762 return 0;
637} 763}
638 764
765static void retry_uffdio_zeropage(int ufd,
766 struct uffdio_zeropage *uffdio_zeropage,
767 unsigned long offset)
768{
769 uffd_test_ops->alias_mapping(&uffdio_zeropage->range.start,
770 uffdio_zeropage->range.len,
771 offset);
772 if (ioctl(ufd, UFFDIO_ZEROPAGE, uffdio_zeropage)) {
773 if (uffdio_zeropage->zeropage != -EEXIST)
774 fprintf(stderr, "UFFDIO_ZEROPAGE retry error %Ld\n",
775 uffdio_zeropage->zeropage), exit(1);
776 } else {
777 fprintf(stderr, "UFFDIO_ZEROPAGE retry unexpected %Ld\n",
778 uffdio_zeropage->zeropage), exit(1);
779 }
780}
781
639static int uffdio_zeropage(int ufd, unsigned long offset) 782static int uffdio_zeropage(int ufd, unsigned long offset)
640{ 783{
641 struct uffdio_zeropage uffdio_zeropage; 784 struct uffdio_zeropage uffdio_zeropage;
@@ -670,8 +813,14 @@ static int uffdio_zeropage(int ufd, unsigned long offset)
670 if (uffdio_zeropage.zeropage != page_size) { 813 if (uffdio_zeropage.zeropage != page_size) {
671 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n", 814 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n",
672 uffdio_zeropage.zeropage), exit(1); 815 uffdio_zeropage.zeropage), exit(1);
673 } else 816 } else {
817 if (test_uffdio_zeropage_eexist) {
818 test_uffdio_zeropage_eexist = false;
819 retry_uffdio_zeropage(ufd, &uffdio_zeropage,
820 offset);
821 }
674 return 1; 822 return 1;
823 }
675 } else { 824 } else {
676 fprintf(stderr, 825 fprintf(stderr,
677 "UFFDIO_ZEROPAGE succeeded %Ld\n", 826 "UFFDIO_ZEROPAGE succeeded %Ld\n",
@@ -761,7 +910,7 @@ static int userfaultfd_events_test(void)
761 perror("fork"), exit(1); 910 perror("fork"), exit(1);
762 911
763 if (!pid) 912 if (!pid)
764 return faulting_process(); 913 return faulting_process(0);
765 914
766 waitpid(pid, &err, 0); 915 waitpid(pid, &err, 0);
767 if (err) 916 if (err)
@@ -778,6 +927,72 @@ static int userfaultfd_events_test(void)
778 return userfaults != nr_pages; 927 return userfaults != nr_pages;
779} 928}
780 929
930static int userfaultfd_sig_test(void)
931{
932 struct uffdio_register uffdio_register;
933 unsigned long expected_ioctls;
934 unsigned long userfaults;
935 pthread_t uffd_mon;
936 int err, features;
937 pid_t pid;
938 char c;
939
940 printf("testing signal delivery: ");
941 fflush(stdout);
942
943 if (uffd_test_ops->release_pages(area_dst))
944 return 1;
945
946 features = UFFD_FEATURE_EVENT_FORK|UFFD_FEATURE_SIGBUS;
947 if (userfaultfd_open(features) < 0)
948 return 1;
949 fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
950
951 uffdio_register.range.start = (unsigned long) area_dst;
952 uffdio_register.range.len = nr_pages * page_size;
953 uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
954 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
955 fprintf(stderr, "register failure\n"), exit(1);
956
957 expected_ioctls = uffd_test_ops->expected_ioctls;
958 if ((uffdio_register.ioctls & expected_ioctls) !=
959 expected_ioctls)
960 fprintf(stderr,
961 "unexpected missing ioctl for anon memory\n"),
962 exit(1);
963
964 if (faulting_process(1))
965 fprintf(stderr, "faulting process failed\n"), exit(1);
966
967 if (uffd_test_ops->release_pages(area_dst))
968 return 1;
969
970 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
971 perror("uffd_poll_thread create"), exit(1);
972
973 pid = fork();
974 if (pid < 0)
975 perror("fork"), exit(1);
976
977 if (!pid)
978 exit(faulting_process(2));
979
980 waitpid(pid, &err, 0);
981 if (err)
982 fprintf(stderr, "faulting process failed\n"), exit(1);
983
984 if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
985 perror("pipe write"), exit(1);
986 if (pthread_join(uffd_mon, (void **)&userfaults))
987 return 1;
988
989 printf("done.\n");
990 if (userfaults)
991 fprintf(stderr, "Signal test failed, userfaults: %ld\n",
992 userfaults);
993 close(uffd);
994 return userfaults != 0;
995}
781static int userfaultfd_stress(void) 996static int userfaultfd_stress(void)
782{ 997{
783 void *area; 998 void *area;
@@ -879,6 +1094,15 @@ static int userfaultfd_stress(void)
879 return 1; 1094 return 1;
880 } 1095 }
881 1096
1097 if (area_dst_alias) {
1098 uffdio_register.range.start = (unsigned long)
1099 area_dst_alias;
1100 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) {
1101 fprintf(stderr, "register failure alias\n");
1102 return 1;
1103 }
1104 }
1105
882 /* 1106 /*
883 * The madvise done previously isn't enough: some 1107 * The madvise done previously isn't enough: some
884 * uffd_thread could have read userfaults (one of 1108 * uffd_thread could have read userfaults (one of
@@ -912,9 +1136,17 @@ static int userfaultfd_stress(void)
912 1136
913 /* unregister */ 1137 /* unregister */
914 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) { 1138 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) {
915 fprintf(stderr, "register failure\n"); 1139 fprintf(stderr, "unregister failure\n");
916 return 1; 1140 return 1;
917 } 1141 }
1142 if (area_dst_alias) {
1143 uffdio_register.range.start = (unsigned long) area_dst;
1144 if (ioctl(uffd, UFFDIO_UNREGISTER,
1145 &uffdio_register.range)) {
1146 fprintf(stderr, "unregister failure alias\n");
1147 return 1;
1148 }
1149 }
918 1150
919 /* verification */ 1151 /* verification */
920 if (bounces & BOUNCE_VERIFY) { 1152 if (bounces & BOUNCE_VERIFY) {
@@ -936,6 +1168,10 @@ static int userfaultfd_stress(void)
936 area_src = area_dst; 1168 area_src = area_dst;
937 area_dst = tmp_area; 1169 area_dst = tmp_area;
938 1170
1171 tmp_area = area_src_alias;
1172 area_src_alias = area_dst_alias;
1173 area_dst_alias = tmp_area;
1174
939 printf("userfaults:"); 1175 printf("userfaults:");
940 for (cpu = 0; cpu < nr_cpus; cpu++) 1176 for (cpu = 0; cpu < nr_cpus; cpu++)
941 printf(" %lu", userfaults[cpu]); 1177 printf(" %lu", userfaults[cpu]);
@@ -946,7 +1182,8 @@ static int userfaultfd_stress(void)
946 return err; 1182 return err;
947 1183
948 close(uffd); 1184 close(uffd);
949 return userfaultfd_zeropage_test() || userfaultfd_events_test(); 1185 return userfaultfd_zeropage_test() || userfaultfd_sig_test()
1186 || userfaultfd_events_test();
950} 1187}
951 1188
952/* 1189/*
@@ -981,7 +1218,12 @@ static void set_test_type(const char *type)
981 } else if (!strcmp(type, "hugetlb")) { 1218 } else if (!strcmp(type, "hugetlb")) {
982 test_type = TEST_HUGETLB; 1219 test_type = TEST_HUGETLB;
983 uffd_test_ops = &hugetlb_uffd_test_ops; 1220 uffd_test_ops = &hugetlb_uffd_test_ops;
1221 } else if (!strcmp(type, "hugetlb_shared")) {
1222 map_shared = true;
1223 test_type = TEST_HUGETLB;
1224 uffd_test_ops = &hugetlb_uffd_test_ops;
984 } else if (!strcmp(type, "shmem")) { 1225 } else if (!strcmp(type, "shmem")) {
1226 map_shared = true;
985 test_type = TEST_SHMEM; 1227 test_type = TEST_SHMEM;
986 uffd_test_ops = &shmem_uffd_test_ops; 1228 uffd_test_ops = &shmem_uffd_test_ops;
987 } else { 1229 } else {
@@ -1001,12 +1243,25 @@ static void set_test_type(const char *type)
1001 fprintf(stderr, "Impossible to run this test\n"), exit(2); 1243 fprintf(stderr, "Impossible to run this test\n"), exit(2);
1002} 1244}
1003 1245
1246static void sigalrm(int sig)
1247{
1248 if (sig != SIGALRM)
1249 abort();
1250 test_uffdio_copy_eexist = true;
1251 test_uffdio_zeropage_eexist = true;
1252 alarm(ALARM_INTERVAL_SECS);
1253}
1254
1004int main(int argc, char **argv) 1255int main(int argc, char **argv)
1005{ 1256{
1006 if (argc < 4) 1257 if (argc < 4)
1007 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"), 1258 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"),
1008 exit(1); 1259 exit(1);
1009 1260
1261 if (signal(SIGALRM, sigalrm) == SIG_ERR)
1262 fprintf(stderr, "failed to arm SIGALRM"), exit(1);
1263 alarm(ALARM_INTERVAL_SECS);
1264
1010 set_test_type(argv[1]); 1265 set_test_type(argv[1]);
1011 1266
1012 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 1267 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
diff --git a/tools/testing/selftests/watchdog/Makefile b/tools/testing/selftests/watchdog/Makefile
index f863c664e3d1..ee068511fd0b 100644
--- a/tools/testing/selftests/watchdog/Makefile
+++ b/tools/testing/selftests/watchdog/Makefile
@@ -1,8 +1,3 @@
1TEST_PROGS := watchdog-test 1TEST_GEN_PROGS := watchdog-test
2
3all: $(TEST_PROGS)
4 2
5include ../lib.mk 3include ../lib.mk
6
7clean:
8 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/watchdog/watchdog-test.c b/tools/testing/selftests/watchdog/watchdog-test.c
index a74c9d739d07..a1391be2dc1e 100644
--- a/tools/testing/selftests/watchdog/watchdog-test.c
+++ b/tools/testing/selftests/watchdog/watchdog-test.c
@@ -9,12 +9,25 @@
9#include <unistd.h> 9#include <unistd.h>
10#include <fcntl.h> 10#include <fcntl.h>
11#include <signal.h> 11#include <signal.h>
12#include <getopt.h>
12#include <sys/ioctl.h> 13#include <sys/ioctl.h>
13#include <linux/types.h> 14#include <linux/types.h>
14#include <linux/watchdog.h> 15#include <linux/watchdog.h>
15 16
17#define DEFAULT_PING_RATE 1
18
16int fd; 19int fd;
17const char v = 'V'; 20const char v = 'V';
21static const char sopts[] = "bdehp:t:";
22static const struct option lopts[] = {
23 {"bootstatus", no_argument, NULL, 'b'},
24 {"disable", no_argument, NULL, 'd'},
25 {"enable", no_argument, NULL, 'e'},
26 {"help", no_argument, NULL, 'h'},
27 {"pingrate", required_argument, NULL, 'p'},
28 {"timeout", required_argument, NULL, 't'},
29 {NULL, no_argument, NULL, 0x0}
30};
18 31
19/* 32/*
20 * This function simply sends an IOCTL to the driver, which in turn ticks 33 * This function simply sends an IOCTL to the driver, which in turn ticks
@@ -23,12 +36,12 @@ const char v = 'V';
23 */ 36 */
24static void keep_alive(void) 37static void keep_alive(void)
25{ 38{
26 int dummy; 39 int dummy;
27 int ret; 40 int ret;
28 41
29 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy); 42 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
30 if (!ret) 43 if (!ret)
31 printf("."); 44 printf(".");
32} 45}
33 46
34/* 47/*
@@ -38,75 +51,110 @@ static void keep_alive(void)
38 51
39static void term(int sig) 52static void term(int sig)
40{ 53{
41 int ret = write(fd, &v, 1); 54 int ret = write(fd, &v, 1);
42 55
43 close(fd); 56 close(fd);
44 if (ret < 0) 57 if (ret < 0)
45 printf("\nStopping watchdog ticks failed (%d)...\n", errno); 58 printf("\nStopping watchdog ticks failed (%d)...\n", errno);
46 else 59 else
47 printf("\nStopping watchdog ticks...\n"); 60 printf("\nStopping watchdog ticks...\n");
48 exit(0); 61 exit(0);
62}
63
64static void usage(char *progname)
65{
66 printf("Usage: %s [options]\n", progname);
67 printf(" -b, --bootstatus Get last boot status (Watchdog/POR)\n");
68 printf(" -d, --disable Turn off the watchdog timer\n");
69 printf(" -e, --enable Turn on the watchdog timer\n");
70 printf(" -h, --help Print the help message\n");
71 printf(" -p, --pingrate=P Set ping rate to P seconds (default %d)\n", DEFAULT_PING_RATE);
72 printf(" -t, --timeout=T Set timeout to T seconds\n");
73 printf("\n");
74 printf("Parameters are parsed left-to-right in real-time.\n");
75 printf("Example: %s -d -t 10 -p 5 -e\n", progname);
49} 76}
50 77
51int main(int argc, char *argv[]) 78int main(int argc, char *argv[])
52{ 79{
53 int flags; 80 int flags;
54 unsigned int ping_rate = 1; 81 unsigned int ping_rate = DEFAULT_PING_RATE;
55 int ret; 82 int ret;
56 int i; 83 int c;
57 84 int oneshot = 0;
58 setbuf(stdout, NULL); 85
59 86 setbuf(stdout, NULL);
60 fd = open("/dev/watchdog", O_WRONLY); 87
61 88 fd = open("/dev/watchdog", O_WRONLY);
62 if (fd == -1) { 89
63 printf("Watchdog device not enabled.\n"); 90 if (fd == -1) {
64 exit(-1); 91 printf("Watchdog device not enabled.\n");
65 } 92 exit(-1);
66 93 }
67 for (i = 1; i < argc; i++) { 94
68 if (!strncasecmp(argv[i], "-d", 2)) { 95 while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
69 flags = WDIOS_DISABLECARD; 96 switch (c) {
70 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 97 case 'b':
71 if (!ret) 98 flags = 0;
72 printf("Watchdog card disabled.\n"); 99 oneshot = 1;
73 } else if (!strncasecmp(argv[i], "-e", 2)) { 100 ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
74 flags = WDIOS_ENABLECARD; 101 if (!ret)
75 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 102 printf("Last boot is caused by: %s.\n", (flags != 0) ?
76 if (!ret) 103 "Watchdog" : "Power-On-Reset");
77 printf("Watchdog card enabled.\n"); 104 else
78 } else if (!strncasecmp(argv[i], "-t", 2) && argv[2]) { 105 printf("WDIOC_GETBOOTSTATUS errno '%s'\n", strerror(errno));
79 flags = atoi(argv[i + 1]); 106 break;
80 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags); 107 case 'd':
81 if (!ret) 108 flags = WDIOS_DISABLECARD;
82 printf("Watchdog timeout set to %u seconds.\n", flags); 109 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
83 i++; 110 if (!ret)
84 } else if (!strncasecmp(argv[i], "-p", 2) && argv[2]) { 111 printf("Watchdog card disabled.\n");
85 ping_rate = strtoul(argv[i + 1], NULL, 0); 112 else
86 printf("Watchdog ping rate set to %u seconds.\n", ping_rate); 113 printf("WDIOS_DISABLECARD errno '%s'\n", strerror(errno));
87 i++; 114 break;
88 } else { 115 case 'e':
89 printf("-d to disable, -e to enable, -t <n> to set " 116 flags = WDIOS_ENABLECARD;
90 "the timeout,\n-p <n> to set the ping rate, and "); 117 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
91 printf("run by itself to tick the card.\n"); 118 if (!ret)
92 printf("Parameters are parsed left-to-right in real-time.\n"); 119 printf("Watchdog card enabled.\n");
93 printf("Example: %s -d -t 10 -p 5 -e\n", argv[0]); 120 else
94 goto end; 121 printf("WDIOS_ENABLECARD errno '%s'\n", strerror(errno));
95 } 122 break;
96 } 123 case 'p':
97 124 ping_rate = strtoul(optarg, NULL, 0);
98 printf("Watchdog Ticking Away!\n"); 125 if (!ping_rate)
99 126 ping_rate = DEFAULT_PING_RATE;
100 signal(SIGINT, term); 127 printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
101 128 break;
102 while(1) { 129 case 't':
103 keep_alive(); 130 flags = strtoul(optarg, NULL, 0);
104 sleep(ping_rate); 131 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
105 } 132 if (!ret)
133 printf("Watchdog timeout set to %u seconds.\n", flags);
134 else
135 printf("WDIOC_SETTIMEOUT errno '%s'\n", strerror(errno));
136 break;
137 default:
138 usage(argv[0]);
139 goto end;
140 }
141 }
142
143 if (oneshot)
144 goto end;
145
146 printf("Watchdog Ticking Away!\n");
147
148 signal(SIGINT, term);
149
150 while (1) {
151 keep_alive();
152 sleep(ping_rate);
153 }
106end: 154end:
107 ret = write(fd, &v, 1); 155 ret = write(fd, &v, 1);
108 if (ret < 0) 156 if (ret < 0)
109 printf("Stopping watchdog ticks failed (%d)...\n", errno); 157 printf("Stopping watchdog ticks failed (%d)...\n", errno);
110 close(fd); 158 close(fd);
111 return 0; 159 return 0;
112} 160}
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 97f187e2663f..0a74a20ca32b 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -20,7 +20,7 @@ BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64)
20BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32)) 20BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
21BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64)) 21BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
22 22
23CFLAGS := -O2 -g -std=gnu99 -pthread -Wall 23CFLAGS := -O2 -g -std=gnu99 -pthread -Wall -no-pie
24 24
25UNAME_M := $(shell uname -m) 25UNAME_M := $(shell uname -m)
26CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32) 26CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32)
diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c
index a8df159a8924..ec0f6b45ce8b 100644
--- a/tools/testing/selftests/x86/mpx-mini-test.c
+++ b/tools/testing/selftests/x86/mpx-mini-test.c
@@ -391,8 +391,7 @@ void handler(int signum, siginfo_t *si, void *vucontext)
391 br_count++; 391 br_count++;
392 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count); 392 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
393 393
394#define __SI_FAULT (3 << 16) 394#define SEGV_BNDERR 3 /* failed address bound checks */
395#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */
396 395
397 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n", 396 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
398 status, ip, br_reason); 397 status, ip, br_reason);
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index 3237bc010e1c..23927845518d 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -212,19 +212,18 @@ void dump_mem(void *dumpme, int len_bytes)
212 } 212 }
213} 213}
214 214
215#define __SI_FAULT (3 << 16) 215#define SEGV_BNDERR 3 /* failed address bound checks */
216#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */ 216#define SEGV_PKUERR 4
217#define SEGV_PKUERR (__SI_FAULT|4)
218 217
219static char *si_code_str(int si_code) 218static char *si_code_str(int si_code)
220{ 219{
221 if (si_code & SEGV_MAPERR) 220 if (si_code == SEGV_MAPERR)
222 return "SEGV_MAPERR"; 221 return "SEGV_MAPERR";
223 if (si_code & SEGV_ACCERR) 222 if (si_code == SEGV_ACCERR)
224 return "SEGV_ACCERR"; 223 return "SEGV_ACCERR";
225 if (si_code & SEGV_BNDERR) 224 if (si_code == SEGV_BNDERR)
226 return "SEGV_BNDERR"; 225 return "SEGV_BNDERR";
227 if (si_code & SEGV_PKUERR) 226 if (si_code == SEGV_PKUERR)
228 return "SEGV_PKUERR"; 227 return "SEGV_PKUERR";
229 return "UNKNOWN"; 228 return "UNKNOWN";
230} 229}