aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-10-29 02:12:34 -0400
committerIngo Molnar <mingo@kernel.org>2018-10-29 02:12:34 -0400
commit97ec37c57dd411d0815455bca07166411c0da1df (patch)
treed64850c43778d15c137772957788093a8b7d032c /tools
parentace6485a03266cc3c198ce8e927a1ce0ce139699 (diff)
parentb59dfdaef173677b0b7e10f375226c0a1114fd20 (diff)
Merge branch 'linus' into x86/urgent, to refresh the tree
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile13
-rw-r--r--tools/accounting/getdelays.c8
-rw-r--r--tools/arch/arm64/include/asm/barrier.h70
-rw-r--r--tools/arch/ia64/include/asm/barrier.h13
-rw-r--r--tools/arch/powerpc/include/asm/barrier.h16
-rw-r--r--tools/arch/s390/include/asm/barrier.h13
-rw-r--r--tools/arch/sparc/include/asm/barrier_64.h13
-rw-r--r--tools/arch/x86/include/asm/barrier.h14
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h10
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-map.rst19
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-net.rst139
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-prog.rst19
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool.rst16
-rw-r--r--tools/bpf/bpftool/Makefile9
-rw-r--r--tools/bpf/bpftool/bash-completion/bpftool78
-rw-r--r--tools/bpf/bpftool/common.c26
-rw-r--r--tools/bpf/bpftool/jit_disasm.c4
-rw-r--r--tools/bpf/bpftool/main.c13
-rw-r--r--tools/bpf/bpftool/main.h18
-rw-r--r--tools/bpf/bpftool/map.c255
-rw-r--r--tools/bpf/bpftool/map_perf_ring.c10
-rw-r--r--tools/bpf/bpftool/net.c275
-rw-r--r--tools/bpf/bpftool/netlink_dumper.c178
-rw-r--r--tools/bpf/bpftool/netlink_dumper.h95
-rw-r--r--tools/bpf/bpftool/prog.c116
-rw-r--r--tools/crypto/getstat.c294
-rw-r--r--tools/include/asm/barrier.h35
-rw-r--r--tools/include/linux/ring_buffer.h73
-rw-r--r--tools/include/uapi/linux/bpf.h168
-rw-r--r--tools/include/uapi/linux/if_link.h2
-rw-r--r--tools/include/uapi/linux/kvm.h5
-rw-r--r--tools/include/uapi/linux/tls.h78
-rw-r--r--tools/lib/bpf/Build2
-rw-r--r--tools/lib/bpf/Makefile5
-rw-r--r--tools/lib/bpf/bpf.c143
-rw-r--r--tools/lib/bpf/bpf.h131
-rw-r--r--tools/lib/bpf/btf.c2
-rw-r--r--tools/lib/bpf/btf.h30
-rw-r--r--tools/lib/bpf/libbpf.c282
-rw-r--r--tools/lib/bpf/libbpf.h222
-rw-r--r--tools/lib/bpf/libbpf_errno.c16
-rw-r--r--tools/lib/bpf/netlink.c337
-rw-r--r--tools/lib/bpf/nlattr.c90
-rw-r--r--tools/lib/bpf/nlattr.h82
-rw-r--r--tools/lib/bpf/str_error.c4
-rw-r--r--tools/lib/bpf/str_error.h10
-rw-r--r--tools/pci/Build1
-rw-r--r--tools/pci/Makefile53
-rw-r--r--tools/pci/pcitest.c7
-rw-r--r--tools/perf/arch/powerpc/util/book3s_hv_exits.h1
-rw-r--r--tools/perf/util/mmap.h15
-rw-r--r--tools/testing/nvdimm/Kbuild1
-rw-r--r--tools/testing/nvdimm/acpi_nfit_test.c8
-rw-r--r--tools/testing/nvdimm/test/nfit.c4
-rw-r--r--tools/testing/nvdimm/test/nfit_test.h24
-rw-r--r--tools/testing/selftests/bpf/.gitignore8
-rw-r--r--tools/testing/selftests/bpf/Makefile19
-rw-r--r--tools/testing/selftests/bpf/bpf_flow.c373
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h25
-rw-r--r--tools/testing/selftests/bpf/config2
-rw-r--r--tools/testing/selftests/bpf/flow_dissector_load.c140
-rw-r--r--tools/testing/selftests/bpf/netcnt_common.h24
-rw-r--r--tools/testing/selftests/bpf/netcnt_prog.c71
-rw-r--r--tools/testing/selftests/bpf/test_btf.c179
-rw-r--r--tools/testing/selftests/bpf/test_cgroup_storage.c60
-rw-r--r--tools/testing/selftests/bpf/test_flow_dissector.c782
-rwxr-xr-xtools/testing/selftests/bpf/test_flow_dissector.sh115
-rwxr-xr-xtools/testing/selftests/bpf/test_libbpf.sh2
-rw-r--r--tools/testing/selftests/bpf/test_maps.c122
-rw-r--r--tools/testing/selftests/bpf/test_netcnt.c158
-rw-r--r--tools/testing/selftests/bpf/test_progs.c157
-rw-r--r--tools/testing/selftests/bpf/test_queue_map.c4
-rw-r--r--tools/testing/selftests/bpf/test_queue_stack_map.h59
-rw-r--r--tools/testing/selftests/bpf/test_section_names.c208
-rw-r--r--tools/testing/selftests/bpf/test_sk_lookup_kern.c180
-rw-r--r--tools/testing/selftests/bpf/test_socket_cookie.c6
-rw-r--r--tools/testing/selftests/bpf/test_sockmap.c373
-rw-r--r--tools/testing/selftests/bpf/test_sockmap_kern.h97
-rw-r--r--tools/testing/selftests/bpf/test_stack_map.c4
-rw-r--r--tools/testing/selftests/bpf/test_tcpbpf_kern.c38
-rw-r--r--tools/testing/selftests/bpf/test_tcpbpf_user.c31
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c1623
-rw-r--r--tools/testing/selftests/bpf/test_xdp_vlan.c292
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_vlan.sh195
-rw-r--r--tools/testing/selftests/bpf/trace_helpers.c8
-rwxr-xr-xtools/testing/selftests/bpf/with_addr.sh54
-rwxr-xr-xtools/testing/selftests/bpf/with_tunnels.sh36
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh347
-rw-r--r--tools/testing/selftests/kvm/.gitignore14
-rw-r--r--tools/testing/selftests/kvm/Makefile39
-rw-r--r--tools/testing/selftests/kvm/dirty_log_test.c374
-rw-r--r--tools/testing/selftests/kvm/include/aarch64/processor.h55
-rw-r--r--tools/testing/selftests/kvm/include/evmcs.h1098
-rw-r--r--tools/testing/selftests/kvm/include/kvm_util.h169
-rw-r--r--tools/testing/selftests/kvm/include/sparsebit.h6
-rw-r--r--tools/testing/selftests/kvm/include/test_util.h6
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/processor.h (renamed from tools/testing/selftests/kvm/include/x86.h)28
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/vmx.h (renamed from tools/testing/selftests/kvm/include/vmx.h)35
-rw-r--r--tools/testing/selftests/kvm/lib/aarch64/processor.c311
-rw-r--r--tools/testing/selftests/kvm/lib/assert.c2
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util.c564
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util_internal.h33
-rw-r--r--tools/testing/selftests/kvm/lib/ucall.c144
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/processor.c (renamed from tools/testing/selftests/kvm/lib/x86.c)263
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/vmx.c (renamed from tools/testing/selftests/kvm/lib/vmx.c)55
-rw-r--r--tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c (renamed from tools/testing/selftests/kvm/cr4_cpuid_sync_test.c)14
-rw-r--r--tools/testing/selftests/kvm/x86_64/evmcs_test.c160
-rw-r--r--tools/testing/selftests/kvm/x86_64/platform_info_test.c (renamed from tools/testing/selftests/kvm/platform_info_test.c)14
-rw-r--r--tools/testing/selftests/kvm/x86_64/set_sregs_test.c (renamed from tools/testing/selftests/kvm/set_sregs_test.c)2
-rw-r--r--tools/testing/selftests/kvm/x86_64/state_test.c (renamed from tools/testing/selftests/kvm/state_test.c)47
-rw-r--r--tools/testing/selftests/kvm/x86_64/sync_regs_test.c (renamed from tools/testing/selftests/kvm/sync_regs_test.c)2
-rw-r--r--tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c (renamed from tools/testing/selftests/kvm/vmx_tsc_adjust_test.c)24
-rw-r--r--tools/testing/selftests/net/.gitignore1
-rw-r--r--tools/testing/selftests/net/Makefile4
-rwxr-xr-xtools/testing/selftests/net/fib-onlink-tests.sh14
-rwxr-xr-xtools/testing/selftests/net/fib_tests.sh167
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_sticky_fdb.sh69
-rw-r--r--tools/testing/selftests/net/forwarding/lib.sh27
-rw-r--r--tools/testing/selftests/net/ip_defrag.c393
-rwxr-xr-xtools/testing/selftests/net/ip_defrag.sh39
-rwxr-xr-xtools/testing/selftests/net/pmtu.sh327
-rw-r--r--tools/testing/selftests/net/tls.c57
-rw-r--r--tools/testing/selftests/powerpc/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/include/reg.h1
-rw-r--r--tools/testing/selftests/powerpc/include/utils.h18
-rw-r--r--tools/testing/selftests/powerpc/mm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/mm/wild_bctr.c155
-rw-r--r--tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c8
-rw-r--r--tools/testing/selftests/powerpc/ptrace/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c228
-rw-r--r--tools/testing/selftests/powerpc/security/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/security/rfi_flush.c132
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tmspr.c27
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-unavailable.c9
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h9
-rw-r--r--tools/testing/selftests/powerpc/utils.c152
-rw-r--r--tools/testing/selftests/tc-testing/README2
-rw-r--r--tools/testing/selftests/tc-testing/bpf/Makefile29
-rw-r--r--tools/testing/selftests/tc-testing/bpf/action.c23
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/buildebpfPlugin.py66
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json16
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/gact.json24
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/police.json24
-rw-r--r--tools/testing/selftests/tc-testing/tdc_config.py4
-rw-r--r--tools/testing/selftests/vm/.gitignore1
-rw-r--r--tools/testing/selftests/vm/Makefile1
-rw-r--r--tools/testing/selftests/vm/gup_benchmark.c42
-rw-r--r--tools/testing/selftests/vm/map_fixed_noreplace.c206
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c134
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.c6
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.c2
152 files changed, 13324 insertions, 1930 deletions
diff --git a/tools/Makefile b/tools/Makefile
index be02c8b904db..abb358a70ad0 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -21,6 +21,7 @@ help:
21 @echo ' leds - LEDs tools' 21 @echo ' leds - LEDs tools'
22 @echo ' liblockdep - user-space wrapper for kernel locking-validator' 22 @echo ' liblockdep - user-space wrapper for kernel locking-validator'
23 @echo ' bpf - misc BPF tools' 23 @echo ' bpf - misc BPF tools'
24 @echo ' pci - PCI tools'
24 @echo ' perf - Linux performance measurement and analysis tool' 25 @echo ' perf - Linux performance measurement and analysis tool'
25 @echo ' selftests - various kernel selftests' 26 @echo ' selftests - various kernel selftests'
26 @echo ' spi - spi tools' 27 @echo ' spi - spi tools'
@@ -59,7 +60,7 @@ acpi: FORCE
59cpupower: FORCE 60cpupower: FORCE
60 $(call descend,power/$@) 61 $(call descend,power/$@)
61 62
62cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds wmi: FORCE 63cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds wmi pci: FORCE
63 $(call descend,$@) 64 $(call descend,$@)
64 65
65liblockdep: FORCE 66liblockdep: FORCE
@@ -94,7 +95,7 @@ kvm_stat: FORCE
94all: acpi cgroup cpupower gpio hv firewire liblockdep \ 95all: acpi cgroup cpupower gpio hv firewire liblockdep \
95 perf selftests spi turbostat usb \ 96 perf selftests spi turbostat usb \
96 virtio vm bpf x86_energy_perf_policy \ 97 virtio vm bpf x86_energy_perf_policy \
97 tmon freefall iio objtool kvm_stat wmi 98 tmon freefall iio objtool kvm_stat wmi pci
98 99
99acpi_install: 100acpi_install:
100 $(call descend,power/$(@:_install=),install) 101 $(call descend,power/$(@:_install=),install)
@@ -102,7 +103,7 @@ acpi_install:
102cpupower_install: 103cpupower_install:
103 $(call descend,power/$(@:_install=),install) 104 $(call descend,power/$(@:_install=),install)
104 105
105cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install: 106cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install:
106 $(call descend,$(@:_install=),install) 107 $(call descend,$(@:_install=),install)
107 108
108liblockdep_install: 109liblockdep_install:
@@ -128,7 +129,7 @@ install: acpi_install cgroup_install cpupower_install gpio_install \
128 perf_install selftests_install turbostat_install usb_install \ 129 perf_install selftests_install turbostat_install usb_install \
129 virtio_install vm_install bpf_install x86_energy_perf_policy_install \ 130 virtio_install vm_install bpf_install x86_energy_perf_policy_install \
130 tmon_install freefall_install objtool_install kvm_stat_install \ 131 tmon_install freefall_install objtool_install kvm_stat_install \
131 wmi_install 132 wmi_install pci_install
132 133
133acpi_clean: 134acpi_clean:
134 $(call descend,power/acpi,clean) 135 $(call descend,power/acpi,clean)
@@ -136,7 +137,7 @@ acpi_clean:
136cpupower_clean: 137cpupower_clean:
137 $(call descend,power/cpupower,clean) 138 $(call descend,power/cpupower,clean)
138 139
139cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean: 140cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean:
140 $(call descend,$(@:_clean=),clean) 141 $(call descend,$(@:_clean=),clean)
141 142
142liblockdep_clean: 143liblockdep_clean:
@@ -174,6 +175,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \
174 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ 175 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
175 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 176 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
176 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ 177 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
177 gpio_clean objtool_clean leds_clean wmi_clean 178 gpio_clean objtool_clean leds_clean wmi_clean pci_clean
178 179
179.PHONY: FORCE 180.PHONY: FORCE
diff --git a/tools/accounting/getdelays.c b/tools/accounting/getdelays.c
index 9f420d98b5fb..8cb504d30384 100644
--- a/tools/accounting/getdelays.c
+++ b/tools/accounting/getdelays.c
@@ -203,6 +203,8 @@ static void print_delayacct(struct taskstats *t)
203 "SWAP %15s%15s%15s\n" 203 "SWAP %15s%15s%15s\n"
204 " %15llu%15llu%15llums\n" 204 " %15llu%15llu%15llums\n"
205 "RECLAIM %12s%15s%15s\n" 205 "RECLAIM %12s%15s%15s\n"
206 " %15llu%15llu%15llums\n"
207 "THRASHING%12s%15s%15s\n"
206 " %15llu%15llu%15llums\n", 208 " %15llu%15llu%15llums\n",
207 "count", "real total", "virtual total", 209 "count", "real total", "virtual total",
208 "delay total", "delay average", 210 "delay total", "delay average",
@@ -222,7 +224,11 @@ static void print_delayacct(struct taskstats *t)
222 "count", "delay total", "delay average", 224 "count", "delay total", "delay average",
223 (unsigned long long)t->freepages_count, 225 (unsigned long long)t->freepages_count,
224 (unsigned long long)t->freepages_delay_total, 226 (unsigned long long)t->freepages_delay_total,
225 average_ms(t->freepages_delay_total, t->freepages_count)); 227 average_ms(t->freepages_delay_total, t->freepages_count),
228 "count", "delay total", "delay average",
229 (unsigned long long)t->thrashing_count,
230 (unsigned long long)t->thrashing_delay_total,
231 average_ms(t->thrashing_delay_total, t->thrashing_count));
226} 232}
227 233
228static void task_context_switch_counts(struct taskstats *t) 234static void task_context_switch_counts(struct taskstats *t)
diff --git a/tools/arch/arm64/include/asm/barrier.h b/tools/arch/arm64/include/asm/barrier.h
index 40bde6b23501..12835ea0e417 100644
--- a/tools/arch/arm64/include/asm/barrier.h
+++ b/tools/arch/arm64/include/asm/barrier.h
@@ -14,4 +14,74 @@
14#define wmb() asm volatile("dmb ishst" ::: "memory") 14#define wmb() asm volatile("dmb ishst" ::: "memory")
15#define rmb() asm volatile("dmb ishld" ::: "memory") 15#define rmb() asm volatile("dmb ishld" ::: "memory")
16 16
17#define smp_store_release(p, v) \
18do { \
19 union { typeof(*p) __val; char __c[1]; } __u = \
20 { .__val = (__force typeof(*p)) (v) }; \
21 \
22 switch (sizeof(*p)) { \
23 case 1: \
24 asm volatile ("stlrb %w1, %0" \
25 : "=Q" (*p) \
26 : "r" (*(__u8 *)__u.__c) \
27 : "memory"); \
28 break; \
29 case 2: \
30 asm volatile ("stlrh %w1, %0" \
31 : "=Q" (*p) \
32 : "r" (*(__u16 *)__u.__c) \
33 : "memory"); \
34 break; \
35 case 4: \
36 asm volatile ("stlr %w1, %0" \
37 : "=Q" (*p) \
38 : "r" (*(__u32 *)__u.__c) \
39 : "memory"); \
40 break; \
41 case 8: \
42 asm volatile ("stlr %1, %0" \
43 : "=Q" (*p) \
44 : "r" (*(__u64 *)__u.__c) \
45 : "memory"); \
46 break; \
47 default: \
48 /* Only to shut up gcc ... */ \
49 mb(); \
50 break; \
51 } \
52} while (0)
53
54#define smp_load_acquire(p) \
55({ \
56 union { typeof(*p) __val; char __c[1]; } __u; \
57 \
58 switch (sizeof(*p)) { \
59 case 1: \
60 asm volatile ("ldarb %w0, %1" \
61 : "=r" (*(__u8 *)__u.__c) \
62 : "Q" (*p) : "memory"); \
63 break; \
64 case 2: \
65 asm volatile ("ldarh %w0, %1" \
66 : "=r" (*(__u16 *)__u.__c) \
67 : "Q" (*p) : "memory"); \
68 break; \
69 case 4: \
70 asm volatile ("ldar %w0, %1" \
71 : "=r" (*(__u32 *)__u.__c) \
72 : "Q" (*p) : "memory"); \
73 break; \
74 case 8: \
75 asm volatile ("ldar %0, %1" \
76 : "=r" (*(__u64 *)__u.__c) \
77 : "Q" (*p) : "memory"); \
78 break; \
79 default: \
80 /* Only to shut up gcc ... */ \
81 mb(); \
82 break; \
83 } \
84 __u.__val; \
85})
86
17#endif /* _TOOLS_LINUX_ASM_AARCH64_BARRIER_H */ 87#endif /* _TOOLS_LINUX_ASM_AARCH64_BARRIER_H */
diff --git a/tools/arch/ia64/include/asm/barrier.h b/tools/arch/ia64/include/asm/barrier.h
index d808ee0e77b5..4d471d9511a5 100644
--- a/tools/arch/ia64/include/asm/barrier.h
+++ b/tools/arch/ia64/include/asm/barrier.h
@@ -46,4 +46,17 @@
46#define rmb() mb() 46#define rmb() mb()
47#define wmb() mb() 47#define wmb() mb()
48 48
49#define smp_store_release(p, v) \
50do { \
51 barrier(); \
52 WRITE_ONCE(*p, v); \
53} while (0)
54
55#define smp_load_acquire(p) \
56({ \
57 typeof(*p) ___p1 = READ_ONCE(*p); \
58 barrier(); \
59 ___p1; \
60})
61
49#endif /* _TOOLS_LINUX_ASM_IA64_BARRIER_H */ 62#endif /* _TOOLS_LINUX_ASM_IA64_BARRIER_H */
diff --git a/tools/arch/powerpc/include/asm/barrier.h b/tools/arch/powerpc/include/asm/barrier.h
index a634da05bc97..905a2c66d96d 100644
--- a/tools/arch/powerpc/include/asm/barrier.h
+++ b/tools/arch/powerpc/include/asm/barrier.h
@@ -27,4 +27,20 @@
27#define rmb() __asm__ __volatile__ ("sync" : : : "memory") 27#define rmb() __asm__ __volatile__ ("sync" : : : "memory")
28#define wmb() __asm__ __volatile__ ("sync" : : : "memory") 28#define wmb() __asm__ __volatile__ ("sync" : : : "memory")
29 29
30#if defined(__powerpc64__)
31#define smp_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory")
32
33#define smp_store_release(p, v) \
34do { \
35 smp_lwsync(); \
36 WRITE_ONCE(*p, v); \
37} while (0)
38
39#define smp_load_acquire(p) \
40({ \
41 typeof(*p) ___p1 = READ_ONCE(*p); \
42 smp_lwsync(); \
43 ___p1; \
44})
45#endif /* defined(__powerpc64__) */
30#endif /* _TOOLS_LINUX_ASM_POWERPC_BARRIER_H */ 46#endif /* _TOOLS_LINUX_ASM_POWERPC_BARRIER_H */
diff --git a/tools/arch/s390/include/asm/barrier.h b/tools/arch/s390/include/asm/barrier.h
index 5030c99f47d2..de362fa664d4 100644
--- a/tools/arch/s390/include/asm/barrier.h
+++ b/tools/arch/s390/include/asm/barrier.h
@@ -28,4 +28,17 @@
28#define rmb() mb() 28#define rmb() mb()
29#define wmb() mb() 29#define wmb() mb()
30 30
31#define smp_store_release(p, v) \
32do { \
33 barrier(); \
34 WRITE_ONCE(*p, v); \
35} while (0)
36
37#define smp_load_acquire(p) \
38({ \
39 typeof(*p) ___p1 = READ_ONCE(*p); \
40 barrier(); \
41 ___p1; \
42})
43
31#endif /* __TOOLS_LIB_ASM_BARRIER_H */ 44#endif /* __TOOLS_LIB_ASM_BARRIER_H */
diff --git a/tools/arch/sparc/include/asm/barrier_64.h b/tools/arch/sparc/include/asm/barrier_64.h
index ba61344287d5..cfb0fdc8ccf0 100644
--- a/tools/arch/sparc/include/asm/barrier_64.h
+++ b/tools/arch/sparc/include/asm/barrier_64.h
@@ -40,4 +40,17 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
40#define rmb() __asm__ __volatile__("":::"memory") 40#define rmb() __asm__ __volatile__("":::"memory")
41#define wmb() __asm__ __volatile__("":::"memory") 41#define wmb() __asm__ __volatile__("":::"memory")
42 42
43#define smp_store_release(p, v) \
44do { \
45 barrier(); \
46 WRITE_ONCE(*p, v); \
47} while (0)
48
49#define smp_load_acquire(p) \
50({ \
51 typeof(*p) ___p1 = READ_ONCE(*p); \
52 barrier(); \
53 ___p1; \
54})
55
43#endif /* !(__TOOLS_LINUX_SPARC64_BARRIER_H) */ 56#endif /* !(__TOOLS_LINUX_SPARC64_BARRIER_H) */
diff --git a/tools/arch/x86/include/asm/barrier.h b/tools/arch/x86/include/asm/barrier.h
index 8774dee27471..58919868473c 100644
--- a/tools/arch/x86/include/asm/barrier.h
+++ b/tools/arch/x86/include/asm/barrier.h
@@ -26,4 +26,18 @@
26#define wmb() asm volatile("sfence" ::: "memory") 26#define wmb() asm volatile("sfence" ::: "memory")
27#endif 27#endif
28 28
29#if defined(__x86_64__)
30#define smp_store_release(p, v) \
31do { \
32 barrier(); \
33 WRITE_ONCE(*p, v); \
34} while (0)
35
36#define smp_load_acquire(p) \
37({ \
38 typeof(*p) ___p1 = READ_ONCE(*p); \
39 barrier(); \
40 ___p1; \
41})
42#endif /* defined(__x86_64__) */
29#endif /* _TOOLS_LINUX_ASM_X86_BARRIER_H */ 43#endif /* _TOOLS_LINUX_ASM_X86_BARRIER_H */
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index fd23d5778ea1..8a6eff9c27f3 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -288,6 +288,7 @@ struct kvm_reinject_control {
288#define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002 288#define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002
289#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 289#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004
290#define KVM_VCPUEVENT_VALID_SMM 0x00000008 290#define KVM_VCPUEVENT_VALID_SMM 0x00000008
291#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010
291 292
292/* Interrupt shadow states */ 293/* Interrupt shadow states */
293#define KVM_X86_SHADOW_INT_MOV_SS 0x01 294#define KVM_X86_SHADOW_INT_MOV_SS 0x01
@@ -299,7 +300,10 @@ struct kvm_vcpu_events {
299 __u8 injected; 300 __u8 injected;
300 __u8 nr; 301 __u8 nr;
301 __u8 has_error_code; 302 __u8 has_error_code;
302 __u8 pad; 303 union {
304 __u8 pad;
305 __u8 pending;
306 };
303 __u32 error_code; 307 __u32 error_code;
304 } exception; 308 } exception;
305 struct { 309 struct {
@@ -322,7 +326,9 @@ struct kvm_vcpu_events {
322 __u8 smm_inside_nmi; 326 __u8 smm_inside_nmi;
323 __u8 latched_init; 327 __u8 latched_init;
324 } smi; 328 } smi;
325 __u32 reserved[9]; 329 __u8 reserved[27];
330 __u8 exception_has_payload;
331 __u64 exception_payload;
326}; 332};
327 333
328/* for KVM_GET/SET_DEBUGREGS */ 334/* for KVM_GET/SET_DEBUGREGS */
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
index a6258bc8ec4f..f55a2daed59b 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -15,13 +15,15 @@ SYNOPSIS
15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } } 15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
16 16
17 *COMMANDS* := 17 *COMMANDS* :=
18 { **show** | **list** | **dump** | **update** | **lookup** | **getnext** | **delete** 18 { **show** | **list** | **create** | **dump** | **update** | **lookup** | **getnext**
19 | **pin** | **help** } 19 | **delete** | **pin** | **help** }
20 20
21MAP COMMANDS 21MAP COMMANDS
22============= 22=============
23 23
24| **bpftool** **map { show | list }** [*MAP*] 24| **bpftool** **map { show | list }** [*MAP*]
25| **bpftool** **map create** *FILE* **type** *TYPE* **key** *KEY_SIZE* **value** *VALUE_SIZE* \
26| **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**dev** *NAME*]
25| **bpftool** **map dump** *MAP* 27| **bpftool** **map dump** *MAP*
26| **bpftool** **map update** *MAP* **key** *DATA* **value** *VALUE* [*UPDATE_FLAGS*] 28| **bpftool** **map update** *MAP* **key** *DATA* **value** *VALUE* [*UPDATE_FLAGS*]
27| **bpftool** **map lookup** *MAP* **key** *DATA* 29| **bpftool** **map lookup** *MAP* **key** *DATA*
@@ -36,6 +38,11 @@ MAP COMMANDS
36| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* } 38| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
37| *VALUE* := { *DATA* | *MAP* | *PROG* } 39| *VALUE* := { *DATA* | *MAP* | *PROG* }
38| *UPDATE_FLAGS* := { **any** | **exist** | **noexist** } 40| *UPDATE_FLAGS* := { **any** | **exist** | **noexist** }
41| *TYPE* := { **hash** | **array** | **prog_array** | **perf_event_array** | **percpu_hash**
42| | **percpu_array** | **stack_trace** | **cgroup_array** | **lru_hash**
43| | **lru_percpu_hash** | **lpm_trie** | **array_of_maps** | **hash_of_maps**
44| | **devmap** | **sockmap** | **cpumap** | **xskmap** | **sockhash**
45| | **cgroup_storage** | **reuseport_sockarray** | **percpu_cgroup_storage** }
39 46
40DESCRIPTION 47DESCRIPTION
41=========== 48===========
@@ -47,6 +54,10 @@ DESCRIPTION
47 Output will start with map ID followed by map type and 54 Output will start with map ID followed by map type and
48 zero or more named attributes (depending on kernel version). 55 zero or more named attributes (depending on kernel version).
49 56
57 **bpftool map create** *FILE* **type** *TYPE* **key** *KEY_SIZE* **value** *VALUE_SIZE* **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**dev** *NAME*]
58 Create a new map with given parameters and pin it to *bpffs*
59 as *FILE*.
60
50 **bpftool map dump** *MAP* 61 **bpftool map dump** *MAP*
51 Dump all entries in a given *MAP*. 62 Dump all entries in a given *MAP*.
52 63
@@ -75,7 +86,9 @@ DESCRIPTION
75 **bpftool map pin** *MAP* *FILE* 86 **bpftool map pin** *MAP* *FILE*
76 Pin map *MAP* as *FILE*. 87 Pin map *MAP* as *FILE*.
77 88
78 Note: *FILE* must be located in *bpffs* mount. 89 Note: *FILE* must be located in *bpffs* mount. It must not
90 contain a dot character ('.'), which is reserved for future
91 extensions of *bpffs*.
79 92
80 **bpftool** **map event_pipe** *MAP* [**cpu** *N* **index** *M*] 93 **bpftool** **map event_pipe** *MAP* [**cpu** *N* **index** *M*]
81 Read events from a BPF_MAP_TYPE_PERF_EVENT_ARRAY map. 94 Read events from a BPF_MAP_TYPE_PERF_EVENT_ARRAY map.
diff --git a/tools/bpf/bpftool/Documentation/bpftool-net.rst b/tools/bpf/bpftool/Documentation/bpftool-net.rst
new file mode 100644
index 000000000000..408ec30d8872
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-net.rst
@@ -0,0 +1,139 @@
1================
2bpftool-net
3================
4-------------------------------------------------------------------------------
5tool for inspection of netdev/tc related bpf prog attachments
6-------------------------------------------------------------------------------
7
8:Manual section: 8
9
10SYNOPSIS
11========
12
13 **bpftool** [*OPTIONS*] **net** *COMMAND*
14
15 *OPTIONS* := { [{ **-j** | **--json** }] [{ **-p** | **--pretty** }] }
16
17 *COMMANDS* :=
18 { **show** | **list** } [ **dev** name ] | **help**
19
20NET COMMANDS
21============
22
23| **bpftool** **net { show | list } [ dev name ]**
24| **bpftool** **net help**
25
26DESCRIPTION
27===========
28 **bpftool net { show | list } [ dev name ]**
29 List bpf program attachments in the kernel networking subsystem.
30
31 Currently, only device driver xdp attachments and tc filter
32 classification/action attachments are implemented, i.e., for
33 program types **BPF_PROG_TYPE_SCHED_CLS**,
34 **BPF_PROG_TYPE_SCHED_ACT** and **BPF_PROG_TYPE_XDP**.
35 For programs attached to a particular cgroup, e.g.,
36 **BPF_PROG_TYPE_CGROUP_SKB**, **BPF_PROG_TYPE_CGROUP_SOCK**,
37 **BPF_PROG_TYPE_SOCK_OPS** and **BPF_PROG_TYPE_CGROUP_SOCK_ADDR**,
38 users can use **bpftool cgroup** to dump cgroup attachments.
39 For sk_{filter, skb, msg, reuseport} and lwt/seg6
40 bpf programs, users should consult other tools, e.g., iproute2.
41
42 The current output will start with all xdp program attachments, followed by
43 all tc class/qdisc bpf program attachments. Both xdp programs and
44 tc programs are ordered based on ifindex number. If multiple bpf
45 programs attached to the same networking device through **tc filter**,
46 the order will be first all bpf programs attached to tc classes, then
47 all bpf programs attached to non clsact qdiscs, and finally all
48 bpf programs attached to root and clsact qdisc.
49
50 **bpftool net help**
51 Print short help message.
52
53OPTIONS
54=======
55 -h, --help
56 Print short generic help message (similar to **bpftool help**).
57
58 -v, --version
59 Print version number (similar to **bpftool version**).
60
61 -j, --json
62 Generate JSON output. For commands that cannot produce JSON, this
63 option has no effect.
64
65 -p, --pretty
66 Generate human-readable JSON output. Implies **-j**.
67
68EXAMPLES
69========
70
71| **# bpftool net**
72
73::
74
75 xdp:
76 eth0(2) driver id 198
77
78 tc:
79 eth0(2) htb name prefix_matcher.o:[cls_prefix_matcher_htb] id 111727 act []
80 eth0(2) clsact/ingress fbflow_icmp id 130246 act []
81 eth0(2) clsact/egress prefix_matcher.o:[cls_prefix_matcher_clsact] id 111726
82 eth0(2) clsact/egress cls_fg_dscp id 108619 act []
83 eth0(2) clsact/egress fbflow_egress id 130245
84
85|
86| **# bpftool -jp net**
87
88::
89
90 [{
91 "xdp": [{
92 "devname": "eth0",
93 "ifindex": 2,
94 "mode": "driver",
95 "id": 198
96 }
97 ],
98 "tc": [{
99 "devname": "eth0",
100 "ifindex": 2,
101 "kind": "htb",
102 "name": "prefix_matcher.o:[cls_prefix_matcher_htb]",
103 "id": 111727,
104 "act": []
105 },{
106 "devname": "eth0",
107 "ifindex": 2,
108 "kind": "clsact/ingress",
109 "name": "fbflow_icmp",
110 "id": 130246,
111 "act": []
112 },{
113 "devname": "eth0",
114 "ifindex": 2,
115 "kind": "clsact/egress",
116 "name": "prefix_matcher.o:[cls_prefix_matcher_clsact]",
117 "id": 111726,
118 },{
119 "devname": "eth0",
120 "ifindex": 2,
121 "kind": "clsact/egress",
122 "name": "cls_fg_dscp",
123 "id": 108619,
124 "act": []
125 },{
126 "devname": "eth0",
127 "ifindex": 2,
128 "kind": "clsact/egress",
129 "name": "fbflow_egress",
130 "id": 130245,
131 }
132 ]
133 }
134 ]
135
136
137SEE ALSO
138========
139 **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index 64156a16d530..ac4e904b10fb 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -25,6 +25,8 @@ MAP COMMANDS
25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] 25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
26| **bpftool** **prog pin** *PROG* *FILE* 26| **bpftool** **prog pin** *PROG* *FILE*
27| **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] 27| **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
28| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP*
29| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP*
28| **bpftool** **prog help** 30| **bpftool** **prog help**
29| 31|
30| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* } 32| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
@@ -37,6 +39,7 @@ MAP COMMANDS
37| **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** | 39| **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
38| **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** 40| **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6**
39| } 41| }
42| *ATTACH_TYPE* := { **msg_verdict** | **skb_verdict** | **skb_parse** }
40 43
41 44
42DESCRIPTION 45DESCRIPTION
@@ -72,7 +75,9 @@ DESCRIPTION
72 **bpftool prog pin** *PROG* *FILE* 75 **bpftool prog pin** *PROG* *FILE*
73 Pin program *PROG* as *FILE*. 76 Pin program *PROG* as *FILE*.
74 77
75 Note: *FILE* must be located in *bpffs* mount. 78 Note: *FILE* must be located in *bpffs* mount. It must not
79 contain a dot character ('.'), which is reserved for future
80 extensions of *bpffs*.
76 81
77 **bpftool prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] 82 **bpftool prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
78 Load bpf program from binary *OBJ* and pin as *FILE*. 83 Load bpf program from binary *OBJ* and pin as *FILE*.
@@ -88,7 +93,17 @@ DESCRIPTION
88 If **dev** *NAME* is specified program will be loaded onto 93 If **dev** *NAME* is specified program will be loaded onto
89 given networking device (offload). 94 given networking device (offload).
90 95
91 Note: *FILE* must be located in *bpffs* mount. 96 Note: *FILE* must be located in *bpffs* mount. It must not
97 contain a dot character ('.'), which is reserved for future
98 extensions of *bpffs*.
99
100 **bpftool prog attach** *PROG* *ATTACH_TYPE* *MAP*
101 Attach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
102 to the map *MAP*.
103
104 **bpftool prog detach** *PROG* *ATTACH_TYPE* *MAP*
105 Detach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
106 from the map *MAP*.
92 107
93 **bpftool prog help** 108 **bpftool prog help**
94 Print short help message. 109 Print short help message.
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
index b6f5d560460d..04cd4f92ab89 100644
--- a/tools/bpf/bpftool/Documentation/bpftool.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -16,22 +16,24 @@ SYNOPSIS
16 16
17 **bpftool** **version** 17 **bpftool** **version**
18 18
19 *OBJECT* := { **map** | **program** | **cgroup** | **perf** } 19 *OBJECT* := { **map** | **program** | **cgroup** | **perf** | **net** }
20 20
21 *OPTIONS* := { { **-V** | **--version** } | { **-h** | **--help** } 21 *OPTIONS* := { { **-V** | **--version** } | { **-h** | **--help** }
22 | { **-j** | **--json** } [{ **-p** | **--pretty** }] } 22 | { **-j** | **--json** } [{ **-p** | **--pretty** }] }
23 23
24 *MAP-COMMANDS* := 24 *MAP-COMMANDS* :=
25 { **show** | **list** | **dump** | **update** | **lookup** | **getnext** | **delete** 25 { **show** | **list** | **create** | **dump** | **update** | **lookup** | **getnext**
26 | **pin** | **event_pipe** | **help** } 26 | **delete** | **pin** | **event_pipe** | **help** }
27 27
28 *PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin** 28 *PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin**
29 | **load** | **help** } 29 | **load** | **attach** | **detach** | **help** }
30 30
31 *CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** } 31 *CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** }
32 32
33 *PERF-COMMANDS* := { **show** | **list** | **help** } 33 *PERF-COMMANDS* := { **show** | **list** | **help** }
34 34
35 *NET-COMMANDS* := { **show** | **list** | **help** }
36
35DESCRIPTION 37DESCRIPTION
36=========== 38===========
37 *bpftool* allows for inspection and simple modification of BPF objects 39 *bpftool* allows for inspection and simple modification of BPF objects
@@ -55,7 +57,11 @@ OPTIONS
55 -p, --pretty 57 -p, --pretty
56 Generate human-readable JSON output. Implies **-j**. 58 Generate human-readable JSON output. Implies **-j**.
57 59
60 -m, --mapcompat
61 Allow loading maps with unknown map definitions.
62
63
58SEE ALSO 64SEE ALSO
59======== 65========
60 **bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8) 66 **bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
61 **bpftool-perf**\ (8) 67 **bpftool-perf**\ (8), **bpftool-net**\ (8)
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 74288a2197ab..dac7eff4c7e5 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -46,6 +46,13 @@ CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ \
46 -I$(srctree)/tools/lib/bpf \ 46 -I$(srctree)/tools/lib/bpf \
47 -I$(srctree)/tools/perf 47 -I$(srctree)/tools/perf
48CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"' 48CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"'
49ifneq ($(EXTRA_CFLAGS),)
50CFLAGS += $(EXTRA_CFLAGS)
51endif
52ifneq ($(EXTRA_LDFLAGS),)
53LDFLAGS += $(EXTRA_LDFLAGS)
54endif
55
49LIBS = -lelf -lbfd -lopcodes $(LIBBPF) 56LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
50 57
51INSTALL ?= install 58INSTALL ?= install
@@ -90,7 +97,7 @@ $(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
90 $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $< 97 $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<
91 98
92$(OUTPUT)bpftool: $(OBJS) $(LIBBPF) 99$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
93 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ $(LIBS) 100 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
94 101
95$(OUTPUT)%.o: %.c 102$(OUTPUT)%.o: %.c
96 $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $< 103 $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 598066c40191..3f78e6404589 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -143,7 +143,7 @@ _bpftool_map_update_map_type()
143 local type 143 local type
144 type=$(bpftool -jp map show $keyword $ref | \ 144 type=$(bpftool -jp map show $keyword $ref | \
145 command sed -n 's/.*"type": "\(.*\)",$/\1/p') 145 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
146 printf $type 146 [[ -n $type ]] && printf $type
147} 147}
148 148
149_bpftool_map_update_get_id() 149_bpftool_map_update_get_id()
@@ -184,7 +184,7 @@ _bpftool()
184 184
185 # Deal with options 185 # Deal with options
186 if [[ ${words[cword]} == -* ]]; then 186 if [[ ${words[cword]} == -* ]]; then
187 local c='--version --json --pretty --bpffs' 187 local c='--version --json --pretty --bpffs --mapcompat'
188 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 188 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
189 return 0 189 return 0
190 fi 190 fi
@@ -292,6 +292,23 @@ _bpftool()
292 fi 292 fi
293 return 0 293 return 0
294 ;; 294 ;;
295 attach|detach)
296 if [[ ${#words[@]} == 7 ]]; then
297 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
298 return 0
299 fi
300
301 if [[ ${#words[@]} == 6 ]]; then
302 COMPREPLY=( $( compgen -W "msg_verdict skb_verdict skb_parse" -- "$cur" ) )
303 return 0
304 fi
305
306 if [[ $prev == "$command" ]]; then
307 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
308 return 0
309 fi
310 return 0
311 ;;
295 load) 312 load)
296 local obj 313 local obj
297 314
@@ -347,7 +364,7 @@ _bpftool()
347 ;; 364 ;;
348 *) 365 *)
349 [[ $prev == $object ]] && \ 366 [[ $prev == $object ]] && \
350 COMPREPLY=( $( compgen -W 'dump help pin load \ 367 COMPREPLY=( $( compgen -W 'dump help pin attach detach load \
351 show list' -- "$cur" ) ) 368 show list' -- "$cur" ) )
352 ;; 369 ;;
353 esac 370 esac
@@ -370,6 +387,42 @@ _bpftool()
370 ;; 387 ;;
371 esac 388 esac
372 ;; 389 ;;
390 create)
391 case $prev in
392 $command)
393 _filedir
394 return 0
395 ;;
396 type)
397 COMPREPLY=( $( compgen -W 'hash array prog_array \
398 perf_event_array percpu_hash percpu_array \
399 stack_trace cgroup_array lru_hash \
400 lru_percpu_hash lpm_trie array_of_maps \
401 hash_of_maps devmap sockmap cpumap xskmap \
402 sockhash cgroup_storage reuseport_sockarray \
403 percpu_cgroup_storage' -- \
404 "$cur" ) )
405 return 0
406 ;;
407 key|value|flags|name|entries)
408 return 0
409 ;;
410 dev)
411 _sysfs_get_netdevs
412 return 0
413 ;;
414 *)
415 _bpftool_once_attr 'type'
416 _bpftool_once_attr 'key'
417 _bpftool_once_attr 'value'
418 _bpftool_once_attr 'entries'
419 _bpftool_once_attr 'name'
420 _bpftool_once_attr 'flags'
421 _bpftool_once_attr 'dev'
422 return 0
423 ;;
424 esac
425 ;;
373 lookup|getnext|delete) 426 lookup|getnext|delete)
374 case $prev in 427 case $prev in
375 $command) 428 $command)
@@ -483,7 +536,7 @@ _bpftool()
483 *) 536 *)
484 [[ $prev == $object ]] && \ 537 [[ $prev == $object ]] && \
485 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 538 COMPREPLY=( $( compgen -W 'delete dump getnext help \
486 lookup pin event_pipe show list update' -- \ 539 lookup pin event_pipe show list update create' -- \
487 "$cur" ) ) 540 "$cur" ) )
488 ;; 541 ;;
489 esac 542 esac
@@ -494,10 +547,10 @@ _bpftool()
494 _filedir 547 _filedir
495 return 0 548 return 0
496 ;; 549 ;;
497 tree) 550 tree)
498 _filedir 551 _filedir
499 return 0 552 return 0
500 ;; 553 ;;
501 attach|detach) 554 attach|detach)
502 local ATTACH_TYPES='ingress egress sock_create sock_ops \ 555 local ATTACH_TYPES='ingress egress sock_create sock_ops \
503 device bind4 bind6 post_bind4 post_bind6 connect4 \ 556 device bind4 bind6 post_bind4 post_bind6 connect4 \
@@ -552,6 +605,15 @@ _bpftool()
552 ;; 605 ;;
553 esac 606 esac
554 ;; 607 ;;
608 net)
609 case $command in
610 *)
611 [[ $prev == $object ]] && \
612 COMPREPLY=( $( compgen -W 'help \
613 show list' -- "$cur" ) )
614 ;;
615 esac
616 ;;
555 esac 617 esac
556} && 618} &&
557complete -F _bpftool bpftool 619complete -F _bpftool bpftool
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index b3a0709ea7ed..25af85304ebe 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -554,7 +554,9 @@ static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
554 return read_sysfs_hex_int(full_path); 554 return read_sysfs_hex_int(full_path);
555} 555}
556 556
557const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino) 557const char *
558ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino,
559 const char **opt)
558{ 560{
559 char devname[IF_NAMESIZE]; 561 char devname[IF_NAMESIZE];
560 int vendor_id; 562 int vendor_id;
@@ -579,6 +581,7 @@ const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino)
579 device_id != 0x6000 && 581 device_id != 0x6000 &&
580 device_id != 0x6003) 582 device_id != 0x6003)
581 p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch"); 583 p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
584 *opt = "ctx4";
582 return "NFP-6xxx"; 585 return "NFP-6xxx";
583 default: 586 default:
584 p_err("Can't get bfd arch name for device vendor id 0x%04x", 587 p_err("Can't get bfd arch name for device vendor id 0x%04x",
@@ -618,3 +621,24 @@ void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
618 jsonw_string_field(json_wtr, "ifname", name); 621 jsonw_string_field(json_wtr, "ifname", name);
619 jsonw_end_object(json_wtr); 622 jsonw_end_object(json_wtr);
620} 623}
624
625int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what)
626{
627 char *endptr;
628
629 NEXT_ARGP();
630
631 if (*val) {
632 p_err("%s already specified", what);
633 return -1;
634 }
635
636 *val = strtoul(**argv, &endptr, 0);
637 if (*endptr) {
638 p_err("can't parse %s as %s", **argv, what);
639 return -1;
640 }
641 NEXT_ARGP();
642
643 return 0;
644}
diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c
index 87439320ef70..c75ffd9ce2bb 100644
--- a/tools/bpf/bpftool/jit_disasm.c
+++ b/tools/bpf/bpftool/jit_disasm.c
@@ -77,7 +77,7 @@ static int fprintf_json(void *out, const char *fmt, ...)
77} 77}
78 78
79void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, 79void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
80 const char *arch) 80 const char *arch, const char *disassembler_options)
81{ 81{
82 disassembler_ftype disassemble; 82 disassembler_ftype disassemble;
83 struct disassemble_info info; 83 struct disassemble_info info;
@@ -116,6 +116,8 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
116 116
117 info.arch = bfd_get_arch(bfdf); 117 info.arch = bfd_get_arch(bfdf);
118 info.mach = bfd_get_mach(bfdf); 118 info.mach = bfd_get_mach(bfdf);
119 if (disassembler_options)
120 info.disassembler_options = disassembler_options;
119 info.buffer = image; 121 info.buffer = image;
120 info.buffer_length = len; 122 info.buffer_length = len;
121 123
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index d15a62be6cf0..75a3296dc0bc 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -55,6 +55,7 @@ json_writer_t *json_wtr;
55bool pretty_output; 55bool pretty_output;
56bool json_output; 56bool json_output;
57bool show_pinned; 57bool show_pinned;
58int bpf_flags;
58struct pinned_obj_table prog_table; 59struct pinned_obj_table prog_table;
59struct pinned_obj_table map_table; 60struct pinned_obj_table map_table;
60 61
@@ -85,7 +86,7 @@ static int do_help(int argc, char **argv)
85 " %s batch file FILE\n" 86 " %s batch file FILE\n"
86 " %s version\n" 87 " %s version\n"
87 "\n" 88 "\n"
88 " OBJECT := { prog | map | cgroup | perf }\n" 89 " OBJECT := { prog | map | cgroup | perf | net }\n"
89 " " HELP_SPEC_OPTIONS "\n" 90 " " HELP_SPEC_OPTIONS "\n"
90 "", 91 "",
91 bin_name, bin_name, bin_name); 92 bin_name, bin_name, bin_name);
@@ -215,6 +216,7 @@ static const struct cmd cmds[] = {
215 { "map", do_map }, 216 { "map", do_map },
216 { "cgroup", do_cgroup }, 217 { "cgroup", do_cgroup },
217 { "perf", do_perf }, 218 { "perf", do_perf },
219 { "net", do_net },
218 { "version", do_version }, 220 { "version", do_version },
219 { 0 } 221 { 0 }
220}; 222};
@@ -319,7 +321,8 @@ static int do_batch(int argc, char **argv)
319 p_err("reading batch file failed: %s", strerror(errno)); 321 p_err("reading batch file failed: %s", strerror(errno));
320 err = -1; 322 err = -1;
321 } else { 323 } else {
322 p_info("processed %d commands", lines); 324 if (!json_output)
325 printf("processed %d commands\n", lines);
323 err = 0; 326 err = 0;
324 } 327 }
325err_close: 328err_close:
@@ -340,6 +343,7 @@ int main(int argc, char **argv)
340 { "pretty", no_argument, NULL, 'p' }, 343 { "pretty", no_argument, NULL, 'p' },
341 { "version", no_argument, NULL, 'V' }, 344 { "version", no_argument, NULL, 'V' },
342 { "bpffs", no_argument, NULL, 'f' }, 345 { "bpffs", no_argument, NULL, 'f' },
346 { "mapcompat", no_argument, NULL, 'm' },
343 { 0 } 347 { 0 }
344 }; 348 };
345 int opt, ret; 349 int opt, ret;
@@ -354,7 +358,7 @@ int main(int argc, char **argv)
354 hash_init(map_table.table); 358 hash_init(map_table.table);
355 359
356 opterr = 0; 360 opterr = 0;
357 while ((opt = getopt_long(argc, argv, "Vhpjf", 361 while ((opt = getopt_long(argc, argv, "Vhpjfm",
358 options, NULL)) >= 0) { 362 options, NULL)) >= 0) {
359 switch (opt) { 363 switch (opt) {
360 case 'V': 364 case 'V':
@@ -378,6 +382,9 @@ int main(int argc, char **argv)
378 case 'f': 382 case 'f':
379 show_pinned = true; 383 show_pinned = true;
380 break; 384 break;
385 case 'm':
386 bpf_flags = MAPS_RELAX_COMPAT;
387 break;
381 default: 388 default:
382 p_err("unrecognized option '%s'", argv[optind - 1]); 389 p_err("unrecognized option '%s'", argv[optind - 1]);
383 if (json_output) 390 if (json_output)
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 238e734d75b3..28322ace2856 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -74,7 +74,7 @@
74#define HELP_SPEC_PROGRAM \ 74#define HELP_SPEC_PROGRAM \
75 "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }" 75 "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
76#define HELP_SPEC_OPTIONS \ 76#define HELP_SPEC_OPTIONS \
77 "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} }" 77 "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} | {-m|--mapcompat}"
78#define HELP_SPEC_MAP \ 78#define HELP_SPEC_MAP \
79 "MAP := { id MAP_ID | pinned FILE }" 79 "MAP := { id MAP_ID | pinned FILE }"
80 80
@@ -89,6 +89,7 @@ extern const char *bin_name;
89extern json_writer_t *json_wtr; 89extern json_writer_t *json_wtr;
90extern bool json_output; 90extern bool json_output;
91extern bool show_pinned; 91extern bool show_pinned;
92extern int bpf_flags;
92extern struct pinned_obj_table prog_table; 93extern struct pinned_obj_table prog_table;
93extern struct pinned_obj_table map_table; 94extern struct pinned_obj_table map_table;
94 95
@@ -136,19 +137,23 @@ int do_map(int argc, char **arg);
136int do_event_pipe(int argc, char **argv); 137int do_event_pipe(int argc, char **argv);
137int do_cgroup(int argc, char **arg); 138int do_cgroup(int argc, char **arg);
138int do_perf(int argc, char **arg); 139int do_perf(int argc, char **arg);
140int do_net(int argc, char **arg);
139 141
142int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
140int prog_parse_fd(int *argc, char ***argv); 143int prog_parse_fd(int *argc, char ***argv);
141int map_parse_fd(int *argc, char ***argv); 144int map_parse_fd(int *argc, char ***argv);
142int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len); 145int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);
143 146
144void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, 147void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
145 const char *arch); 148 const char *arch, const char *disassembler_options);
146void print_data_json(uint8_t *data, size_t len); 149void print_data_json(uint8_t *data, size_t len);
147void print_hex_data_json(uint8_t *data, size_t len); 150void print_hex_data_json(uint8_t *data, size_t len);
148 151
149unsigned int get_page_size(void); 152unsigned int get_page_size(void);
150unsigned int get_possible_cpus(void); 153unsigned int get_possible_cpus(void);
151const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino); 154const char *
155ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino,
156 const char **opt);
152 157
153struct btf_dumper { 158struct btf_dumper {
154 const struct btf *btf; 159 const struct btf *btf;
@@ -165,4 +170,11 @@ struct btf_dumper {
165 */ 170 */
166int btf_dumper_type(const struct btf_dumper *d, __u32 type_id, 171int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
167 const void *data); 172 const void *data);
173
174struct nlattr;
175struct ifinfomsg;
176struct tcmsg;
177int do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb);
178int do_filter_dump(struct tcmsg *ifinfo, struct nlattr **tb, const char *kind,
179 const char *devname, int ifindex);
168#endif 180#endif
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index b455930a3eaf..7bf38f0e152e 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -36,6 +36,7 @@
36#include <fcntl.h> 36#include <fcntl.h>
37#include <linux/err.h> 37#include <linux/err.h>
38#include <linux/kernel.h> 38#include <linux/kernel.h>
39#include <net/if.h>
39#include <stdbool.h> 40#include <stdbool.h>
40#include <stdio.h> 41#include <stdio.h>
41#include <stdlib.h> 42#include <stdlib.h>
@@ -71,13 +72,16 @@ static const char * const map_type_name[] = {
71 [BPF_MAP_TYPE_XSKMAP] = "xskmap", 72 [BPF_MAP_TYPE_XSKMAP] = "xskmap",
72 [BPF_MAP_TYPE_SOCKHASH] = "sockhash", 73 [BPF_MAP_TYPE_SOCKHASH] = "sockhash",
73 [BPF_MAP_TYPE_CGROUP_STORAGE] = "cgroup_storage", 74 [BPF_MAP_TYPE_CGROUP_STORAGE] = "cgroup_storage",
75 [BPF_MAP_TYPE_REUSEPORT_SOCKARRAY] = "reuseport_sockarray",
76 [BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE] = "percpu_cgroup_storage",
74}; 77};
75 78
76static bool map_is_per_cpu(__u32 type) 79static bool map_is_per_cpu(__u32 type)
77{ 80{
78 return type == BPF_MAP_TYPE_PERCPU_HASH || 81 return type == BPF_MAP_TYPE_PERCPU_HASH ||
79 type == BPF_MAP_TYPE_PERCPU_ARRAY || 82 type == BPF_MAP_TYPE_PERCPU_ARRAY ||
80 type == BPF_MAP_TYPE_LRU_PERCPU_HASH; 83 type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
84 type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
81} 85}
82 86
83static bool map_is_map_of_maps(__u32 type) 87static bool map_is_map_of_maps(__u32 type)
@@ -91,6 +95,17 @@ static bool map_is_map_of_progs(__u32 type)
91 return type == BPF_MAP_TYPE_PROG_ARRAY; 95 return type == BPF_MAP_TYPE_PROG_ARRAY;
92} 96}
93 97
98static int map_type_from_str(const char *type)
99{
100 unsigned int i;
101
102 for (i = 0; i < ARRAY_SIZE(map_type_name); i++)
103 /* Don't allow prefixing in case of possible future shadowing */
104 if (map_type_name[i] && !strcmp(map_type_name[i], type))
105 return i;
106 return -1;
107}
108
94static void *alloc_value(struct bpf_map_info *info) 109static void *alloc_value(struct bpf_map_info *info)
95{ 110{
96 if (map_is_per_cpu(info->type)) 111 if (map_is_per_cpu(info->type))
@@ -170,9 +185,28 @@ static int do_dump_btf(const struct btf_dumper *d,
170 if (ret) 185 if (ret)
171 goto err_end_obj; 186 goto err_end_obj;
172 187
173 jsonw_name(d->jw, "value"); 188 if (!map_is_per_cpu(map_info->type)) {
189 jsonw_name(d->jw, "value");
190 ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
191 } else {
192 unsigned int i, n, step;
174 193
175 ret = btf_dumper_type(d, map_info->btf_value_type_id, value); 194 jsonw_name(d->jw, "values");
195 jsonw_start_array(d->jw);
196 n = get_possible_cpus();
197 step = round_up(map_info->value_size, 8);
198 for (i = 0; i < n; i++) {
199 jsonw_start_object(d->jw);
200 jsonw_int_field(d->jw, "cpu", i);
201 jsonw_name(d->jw, "value");
202 ret = btf_dumper_type(d, map_info->btf_value_type_id,
203 value + i * step);
204 jsonw_end_object(d->jw);
205 if (ret)
206 break;
207 }
208 jsonw_end_array(d->jw);
209 }
176 210
177err_end_obj: 211err_end_obj:
178 /* end of key-value pair */ 212 /* end of key-value pair */
@@ -299,11 +333,40 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
299 jsonw_end_object(json_wtr); 333 jsonw_end_object(json_wtr);
300 } 334 }
301 jsonw_end_array(json_wtr); 335 jsonw_end_array(json_wtr);
336 if (btf) {
337 struct btf_dumper d = {
338 .btf = btf,
339 .jw = json_wtr,
340 .is_plain_text = false,
341 };
342
343 jsonw_name(json_wtr, "formatted");
344 do_dump_btf(&d, info, key, value);
345 }
302 } 346 }
303 347
304 jsonw_end_object(json_wtr); 348 jsonw_end_object(json_wtr);
305} 349}
306 350
351static void print_entry_error(struct bpf_map_info *info, unsigned char *key,
352 const char *value)
353{
354 int value_size = strlen(value);
355 bool single_line, break_names;
356
357 break_names = info->key_size > 16 || value_size > 16;
358 single_line = info->key_size + value_size <= 24 && !break_names;
359
360 printf("key:%c", break_names ? '\n' : ' ');
361 fprint_hex(stdout, key, info->key_size, " ");
362
363 printf(single_line ? " " : "\n");
364
365 printf("value:%c%s", break_names ? '\n' : ' ', value);
366
367 printf("\n");
368}
369
307static void print_entry_plain(struct bpf_map_info *info, unsigned char *key, 370static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
308 unsigned char *value) 371 unsigned char *value)
309{ 372{
@@ -626,6 +689,54 @@ static int do_show(int argc, char **argv)
626 return errno == ENOENT ? 0 : -1; 689 return errno == ENOENT ? 0 : -1;
627} 690}
628 691
692static int dump_map_elem(int fd, void *key, void *value,
693 struct bpf_map_info *map_info, struct btf *btf,
694 json_writer_t *btf_wtr)
695{
696 int num_elems = 0;
697 int lookup_errno;
698
699 if (!bpf_map_lookup_elem(fd, key, value)) {
700 if (json_output) {
701 print_entry_json(map_info, key, value, btf);
702 } else {
703 if (btf) {
704 struct btf_dumper d = {
705 .btf = btf,
706 .jw = btf_wtr,
707 .is_plain_text = true,
708 };
709
710 do_dump_btf(&d, map_info, key, value);
711 } else {
712 print_entry_plain(map_info, key, value);
713 }
714 num_elems++;
715 }
716 return num_elems;
717 }
718
719 /* lookup error handling */
720 lookup_errno = errno;
721
722 if (map_is_map_of_maps(map_info->type) ||
723 map_is_map_of_progs(map_info->type))
724 return 0;
725
726 if (json_output) {
727 jsonw_name(json_wtr, "key");
728 print_hex_data_json(key, map_info->key_size);
729 jsonw_name(json_wtr, "value");
730 jsonw_start_object(json_wtr);
731 jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
732 jsonw_end_object(json_wtr);
733 } else {
734 print_entry_error(map_info, key, strerror(lookup_errno));
735 }
736
737 return 0;
738}
739
629static int do_dump(int argc, char **argv) 740static int do_dump(int argc, char **argv)
630{ 741{
631 struct bpf_map_info info = {}; 742 struct bpf_map_info info = {};
@@ -644,12 +755,6 @@ static int do_dump(int argc, char **argv)
644 if (fd < 0) 755 if (fd < 0)
645 return -1; 756 return -1;
646 757
647 if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
648 p_err("Dumping maps of maps and program maps not supported");
649 close(fd);
650 return -1;
651 }
652
653 key = malloc(info.key_size); 758 key = malloc(info.key_size);
654 value = alloc_value(&info); 759 value = alloc_value(&info);
655 if (!key || !value) { 760 if (!key || !value) {
@@ -687,40 +792,8 @@ static int do_dump(int argc, char **argv)
687 err = 0; 792 err = 0;
688 break; 793 break;
689 } 794 }
690 795 num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr);
691 if (!bpf_map_lookup_elem(fd, key, value)) {
692 if (json_output)
693 print_entry_json(&info, key, value, btf);
694 else
695 if (btf) {
696 struct btf_dumper d = {
697 .btf = btf,
698 .jw = btf_wtr,
699 .is_plain_text = true,
700 };
701
702 do_dump_btf(&d, &info, key, value);
703 } else {
704 print_entry_plain(&info, key, value);
705 }
706 } else {
707 if (json_output) {
708 jsonw_name(json_wtr, "key");
709 print_hex_data_json(key, info.key_size);
710 jsonw_name(json_wtr, "value");
711 jsonw_start_object(json_wtr);
712 jsonw_string_field(json_wtr, "error",
713 "can't lookup element");
714 jsonw_end_object(json_wtr);
715 } else {
716 p_info("can't lookup element with key: ");
717 fprint_hex(stderr, key, info.key_size, " ");
718 fprintf(stderr, "\n");
719 }
720 }
721
722 prev_key = key; 796 prev_key = key;
723 num_elems++;
724 } 797 }
725 798
726 if (json_output) 799 if (json_output)
@@ -997,6 +1070,92 @@ static int do_pin(int argc, char **argv)
997 return err; 1070 return err;
998} 1071}
999 1072
1073static int do_create(int argc, char **argv)
1074{
1075 struct bpf_create_map_attr attr = { NULL, };
1076 const char *pinfile;
1077 int err, fd;
1078
1079 if (!REQ_ARGS(7))
1080 return -1;
1081 pinfile = GET_ARG();
1082
1083 while (argc) {
1084 if (!REQ_ARGS(2))
1085 return -1;
1086
1087 if (is_prefix(*argv, "type")) {
1088 NEXT_ARG();
1089
1090 if (attr.map_type) {
1091 p_err("map type already specified");
1092 return -1;
1093 }
1094
1095 attr.map_type = map_type_from_str(*argv);
1096 if ((int)attr.map_type < 0) {
1097 p_err("unrecognized map type: %s", *argv);
1098 return -1;
1099 }
1100 NEXT_ARG();
1101 } else if (is_prefix(*argv, "name")) {
1102 NEXT_ARG();
1103 attr.name = GET_ARG();
1104 } else if (is_prefix(*argv, "key")) {
1105 if (parse_u32_arg(&argc, &argv, &attr.key_size,
1106 "key size"))
1107 return -1;
1108 } else if (is_prefix(*argv, "value")) {
1109 if (parse_u32_arg(&argc, &argv, &attr.value_size,
1110 "value size"))
1111 return -1;
1112 } else if (is_prefix(*argv, "entries")) {
1113 if (parse_u32_arg(&argc, &argv, &attr.max_entries,
1114 "max entries"))
1115 return -1;
1116 } else if (is_prefix(*argv, "flags")) {
1117 if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1118 "flags"))
1119 return -1;
1120 } else if (is_prefix(*argv, "dev")) {
1121 NEXT_ARG();
1122
1123 if (attr.map_ifindex) {
1124 p_err("offload device already specified");
1125 return -1;
1126 }
1127
1128 attr.map_ifindex = if_nametoindex(*argv);
1129 if (!attr.map_ifindex) {
1130 p_err("unrecognized netdevice '%s': %s",
1131 *argv, strerror(errno));
1132 return -1;
1133 }
1134 NEXT_ARG();
1135 }
1136 }
1137
1138 if (!attr.name) {
1139 p_err("map name not specified");
1140 return -1;
1141 }
1142
1143 fd = bpf_create_map_xattr(&attr);
1144 if (fd < 0) {
1145 p_err("map create failed: %s", strerror(errno));
1146 return -1;
1147 }
1148
1149 err = do_pin_fd(fd, pinfile);
1150 close(fd);
1151 if (err)
1152 return err;
1153
1154 if (json_output)
1155 jsonw_null(json_wtr);
1156 return 0;
1157}
1158
1000static int do_help(int argc, char **argv) 1159static int do_help(int argc, char **argv)
1001{ 1160{
1002 if (json_output) { 1161 if (json_output) {
@@ -1006,6 +1165,9 @@ static int do_help(int argc, char **argv)
1006 1165
1007 fprintf(stderr, 1166 fprintf(stderr,
1008 "Usage: %s %s { show | list } [MAP]\n" 1167 "Usage: %s %s { show | list } [MAP]\n"
1168 " %s %s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1169 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1170 " [dev NAME]\n"
1009 " %s %s dump MAP\n" 1171 " %s %s dump MAP\n"
1010 " %s %s update MAP key DATA value VALUE [UPDATE_FLAGS]\n" 1172 " %s %s update MAP key DATA value VALUE [UPDATE_FLAGS]\n"
1011 " %s %s lookup MAP key DATA\n" 1173 " %s %s lookup MAP key DATA\n"
@@ -1020,11 +1182,17 @@ static int do_help(int argc, char **argv)
1020 " " HELP_SPEC_PROGRAM "\n" 1182 " " HELP_SPEC_PROGRAM "\n"
1021 " VALUE := { DATA | MAP | PROG }\n" 1183 " VALUE := { DATA | MAP | PROG }\n"
1022 " UPDATE_FLAGS := { any | exist | noexist }\n" 1184 " UPDATE_FLAGS := { any | exist | noexist }\n"
1185 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1186 " percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1187 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1188 " devmap | sockmap | cpumap | xskmap | sockhash |\n"
1189 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n"
1023 " " HELP_SPEC_OPTIONS "\n" 1190 " " HELP_SPEC_OPTIONS "\n"
1024 "", 1191 "",
1025 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1192 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1026 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1193 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1027 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1194 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1195 bin_name, argv[-2]);
1028 1196
1029 return 0; 1197 return 0;
1030} 1198}
@@ -1040,6 +1208,7 @@ static const struct cmd cmds[] = {
1040 { "delete", do_delete }, 1208 { "delete", do_delete },
1041 { "pin", do_pin }, 1209 { "pin", do_pin },
1042 { "event_pipe", do_event_pipe }, 1210 { "event_pipe", do_event_pipe },
1211 { "create", do_create },
1043 { 0 } 1212 { 0 }
1044}; 1213};
1045 1214
diff --git a/tools/bpf/bpftool/map_perf_ring.c b/tools/bpf/bpftool/map_perf_ring.c
index 6d41323be291..bdaf4062e26e 100644
--- a/tools/bpf/bpftool/map_perf_ring.c
+++ b/tools/bpf/bpftool/map_perf_ring.c
@@ -50,15 +50,17 @@ static void int_exit(int signo)
50 stop = true; 50 stop = true;
51} 51}
52 52
53static enum bpf_perf_event_ret print_bpf_output(void *event, void *priv) 53static enum bpf_perf_event_ret
54print_bpf_output(struct perf_event_header *event, void *private_data)
54{ 55{
55 struct event_ring_info *ring = priv; 56 struct perf_event_sample *e = container_of(event, struct perf_event_sample,
56 struct perf_event_sample *e = event; 57 header);
58 struct event_ring_info *ring = private_data;
57 struct { 59 struct {
58 struct perf_event_header header; 60 struct perf_event_header header;
59 __u64 id; 61 __u64 id;
60 __u64 lost; 62 __u64 lost;
61 } *lost = event; 63 } *lost = (typeof(lost))event;
62 64
63 if (json_output) { 65 if (json_output) {
64 jsonw_start_object(json_wtr); 66 jsonw_start_object(json_wtr);
diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
new file mode 100644
index 000000000000..d441bb7035ca
--- /dev/null
+++ b/tools/bpf/bpftool/net.c
@@ -0,0 +1,275 @@
1// SPDX-License-Identifier: GPL-2.0+
2// Copyright (C) 2018 Facebook
3
4#define _GNU_SOURCE
5#include <errno.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9#include <libbpf.h>
10#include <net/if.h>
11#include <linux/if.h>
12#include <linux/rtnetlink.h>
13#include <linux/tc_act/tc_bpf.h>
14#include <sys/socket.h>
15
16#include <bpf.h>
17#include <nlattr.h>
18#include "main.h"
19#include "netlink_dumper.h"
20
21struct ip_devname_ifindex {
22 char devname[64];
23 int ifindex;
24};
25
26struct bpf_netdev_t {
27 struct ip_devname_ifindex *devices;
28 int used_len;
29 int array_len;
30 int filter_idx;
31};
32
33struct tc_kind_handle {
34 char kind[64];
35 int handle;
36};
37
38struct bpf_tcinfo_t {
39 struct tc_kind_handle *handle_array;
40 int used_len;
41 int array_len;
42 bool is_qdisc;
43};
44
45struct bpf_filter_t {
46 const char *kind;
47 const char *devname;
48 int ifindex;
49};
50
51static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
52{
53 struct bpf_netdev_t *netinfo = cookie;
54 struct ifinfomsg *ifinfo = msg;
55
56 if (netinfo->filter_idx > 0 && netinfo->filter_idx != ifinfo->ifi_index)
57 return 0;
58
59 if (netinfo->used_len == netinfo->array_len) {
60 netinfo->devices = realloc(netinfo->devices,
61 (netinfo->array_len + 16) *
62 sizeof(struct ip_devname_ifindex));
63 if (!netinfo->devices)
64 return -ENOMEM;
65
66 netinfo->array_len += 16;
67 }
68 netinfo->devices[netinfo->used_len].ifindex = ifinfo->ifi_index;
69 snprintf(netinfo->devices[netinfo->used_len].devname,
70 sizeof(netinfo->devices[netinfo->used_len].devname),
71 "%s",
72 tb[IFLA_IFNAME]
73 ? libbpf_nla_getattr_str(tb[IFLA_IFNAME])
74 : "");
75 netinfo->used_len++;
76
77 return do_xdp_dump(ifinfo, tb);
78}
79
80static int dump_class_qdisc_nlmsg(void *cookie, void *msg, struct nlattr **tb)
81{
82 struct bpf_tcinfo_t *tcinfo = cookie;
83 struct tcmsg *info = msg;
84
85 if (tcinfo->is_qdisc) {
86 /* skip clsact qdisc */
87 if (tb[TCA_KIND] &&
88 strcmp(libbpf_nla_data(tb[TCA_KIND]), "clsact") == 0)
89 return 0;
90 if (info->tcm_handle == 0)
91 return 0;
92 }
93
94 if (tcinfo->used_len == tcinfo->array_len) {
95 tcinfo->handle_array = realloc(tcinfo->handle_array,
96 (tcinfo->array_len + 16) * sizeof(struct tc_kind_handle));
97 if (!tcinfo->handle_array)
98 return -ENOMEM;
99
100 tcinfo->array_len += 16;
101 }
102 tcinfo->handle_array[tcinfo->used_len].handle = info->tcm_handle;
103 snprintf(tcinfo->handle_array[tcinfo->used_len].kind,
104 sizeof(tcinfo->handle_array[tcinfo->used_len].kind),
105 "%s",
106 tb[TCA_KIND]
107 ? libbpf_nla_getattr_str(tb[TCA_KIND])
108 : "unknown");
109 tcinfo->used_len++;
110
111 return 0;
112}
113
114static int dump_filter_nlmsg(void *cookie, void *msg, struct nlattr **tb)
115{
116 const struct bpf_filter_t *filter_info = cookie;
117
118 return do_filter_dump((struct tcmsg *)msg, tb, filter_info->kind,
119 filter_info->devname, filter_info->ifindex);
120}
121
122static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
123 struct ip_devname_ifindex *dev)
124{
125 struct bpf_filter_t filter_info;
126 struct bpf_tcinfo_t tcinfo;
127 int i, handle, ret = 0;
128
129 tcinfo.handle_array = NULL;
130 tcinfo.used_len = 0;
131 tcinfo.array_len = 0;
132
133 tcinfo.is_qdisc = false;
134 ret = libbpf_nl_get_class(sock, nl_pid, dev->ifindex,
135 dump_class_qdisc_nlmsg, &tcinfo);
136 if (ret)
137 goto out;
138
139 tcinfo.is_qdisc = true;
140 ret = libbpf_nl_get_qdisc(sock, nl_pid, dev->ifindex,
141 dump_class_qdisc_nlmsg, &tcinfo);
142 if (ret)
143 goto out;
144
145 filter_info.devname = dev->devname;
146 filter_info.ifindex = dev->ifindex;
147 for (i = 0; i < tcinfo.used_len; i++) {
148 filter_info.kind = tcinfo.handle_array[i].kind;
149 ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex,
150 tcinfo.handle_array[i].handle,
151 dump_filter_nlmsg, &filter_info);
152 if (ret)
153 goto out;
154 }
155
156 /* root, ingress and egress handle */
157 handle = TC_H_ROOT;
158 filter_info.kind = "root";
159 ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
160 dump_filter_nlmsg, &filter_info);
161 if (ret)
162 goto out;
163
164 handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS);
165 filter_info.kind = "clsact/ingress";
166 ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
167 dump_filter_nlmsg, &filter_info);
168 if (ret)
169 goto out;
170
171 handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS);
172 filter_info.kind = "clsact/egress";
173 ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
174 dump_filter_nlmsg, &filter_info);
175 if (ret)
176 goto out;
177
178out:
179 free(tcinfo.handle_array);
180 return 0;
181}
182
183static int do_show(int argc, char **argv)
184{
185 int i, sock, ret, filter_idx = -1;
186 struct bpf_netdev_t dev_array;
187 unsigned int nl_pid;
188 char err_buf[256];
189
190 if (argc == 2) {
191 if (strcmp(argv[0], "dev") != 0)
192 usage();
193 filter_idx = if_nametoindex(argv[1]);
194 if (filter_idx == 0) {
195 fprintf(stderr, "invalid dev name %s\n", argv[1]);
196 return -1;
197 }
198 } else if (argc != 0) {
199 usage();
200 }
201
202 sock = libbpf_netlink_open(&nl_pid);
203 if (sock < 0) {
204 fprintf(stderr, "failed to open netlink sock\n");
205 return -1;
206 }
207
208 dev_array.devices = NULL;
209 dev_array.used_len = 0;
210 dev_array.array_len = 0;
211 dev_array.filter_idx = filter_idx;
212
213 if (json_output)
214 jsonw_start_array(json_wtr);
215 NET_START_OBJECT;
216 NET_START_ARRAY("xdp", "%s:\n");
217 ret = libbpf_nl_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array);
218 NET_END_ARRAY("\n");
219
220 if (!ret) {
221 NET_START_ARRAY("tc", "%s:\n");
222 for (i = 0; i < dev_array.used_len; i++) {
223 ret = show_dev_tc_bpf(sock, nl_pid,
224 &dev_array.devices[i]);
225 if (ret)
226 break;
227 }
228 NET_END_ARRAY("\n");
229 }
230 NET_END_OBJECT;
231 if (json_output)
232 jsonw_end_array(json_wtr);
233
234 if (ret) {
235 if (json_output)
236 jsonw_null(json_wtr);
237 libbpf_strerror(ret, err_buf, sizeof(err_buf));
238 fprintf(stderr, "Error: %s\n", err_buf);
239 }
240 free(dev_array.devices);
241 close(sock);
242 return ret;
243}
244
245static int do_help(int argc, char **argv)
246{
247 if (json_output) {
248 jsonw_null(json_wtr);
249 return 0;
250 }
251
252 fprintf(stderr,
253 "Usage: %s %s { show | list } [dev <devname>]\n"
254 " %s %s help\n"
255 "Note: Only xdp and tc attachments are supported now.\n"
256 " For progs attached to cgroups, use \"bpftool cgroup\"\n"
257 " to dump program attachments. For program types\n"
258 " sk_{filter,skb,msg,reuseport} and lwt/seg6, please\n"
259 " consult iproute2.\n",
260 bin_name, argv[-2], bin_name, argv[-2]);
261
262 return 0;
263}
264
265static const struct cmd cmds[] = {
266 { "show", do_show },
267 { "list", do_show },
268 { "help", do_help },
269 { 0 }
270};
271
272int do_net(int argc, char **argv)
273{
274 return cmd_select(cmds, argc, argv, do_help);
275}
diff --git a/tools/bpf/bpftool/netlink_dumper.c b/tools/bpf/bpftool/netlink_dumper.c
new file mode 100644
index 000000000000..4e9f4531269f
--- /dev/null
+++ b/tools/bpf/bpftool/netlink_dumper.c
@@ -0,0 +1,178 @@
1// SPDX-License-Identifier: GPL-2.0+
2// Copyright (C) 2018 Facebook
3
4#include <stdlib.h>
5#include <string.h>
6#include <libbpf.h>
7#include <linux/rtnetlink.h>
8#include <linux/tc_act/tc_bpf.h>
9
10#include <nlattr.h>
11#include "main.h"
12#include "netlink_dumper.h"
13
14static void xdp_dump_prog_id(struct nlattr **tb, int attr,
15 const char *mode,
16 bool new_json_object)
17{
18 if (!tb[attr])
19 return;
20
21 if (new_json_object)
22 NET_START_OBJECT
23 NET_DUMP_STR("mode", " %s", mode);
24 NET_DUMP_UINT("id", " id %u", libbpf_nla_getattr_u32(tb[attr]))
25 if (new_json_object)
26 NET_END_OBJECT
27}
28
29static int do_xdp_dump_one(struct nlattr *attr, unsigned int ifindex,
30 const char *name)
31{
32 struct nlattr *tb[IFLA_XDP_MAX + 1];
33 unsigned char mode;
34
35 if (libbpf_nla_parse_nested(tb, IFLA_XDP_MAX, attr, NULL) < 0)
36 return -1;
37
38 if (!tb[IFLA_XDP_ATTACHED])
39 return 0;
40
41 mode = libbpf_nla_getattr_u8(tb[IFLA_XDP_ATTACHED]);
42 if (mode == XDP_ATTACHED_NONE)
43 return 0;
44
45 NET_START_OBJECT;
46 if (name)
47 NET_DUMP_STR("devname", "%s", name);
48 NET_DUMP_UINT("ifindex", "(%d)", ifindex);
49
50 if (mode == XDP_ATTACHED_MULTI) {
51 if (json_output) {
52 jsonw_name(json_wtr, "multi_attachments");
53 jsonw_start_array(json_wtr);
54 }
55 xdp_dump_prog_id(tb, IFLA_XDP_SKB_PROG_ID, "generic", true);
56 xdp_dump_prog_id(tb, IFLA_XDP_DRV_PROG_ID, "driver", true);
57 xdp_dump_prog_id(tb, IFLA_XDP_HW_PROG_ID, "offload", true);
58 if (json_output)
59 jsonw_end_array(json_wtr);
60 } else if (mode == XDP_ATTACHED_DRV) {
61 xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "driver", false);
62 } else if (mode == XDP_ATTACHED_SKB) {
63 xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "generic", false);
64 } else if (mode == XDP_ATTACHED_HW) {
65 xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "offload", false);
66 }
67
68 NET_END_OBJECT_FINAL;
69 return 0;
70}
71
72int do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb)
73{
74 if (!tb[IFLA_XDP])
75 return 0;
76
77 return do_xdp_dump_one(tb[IFLA_XDP], ifinfo->ifi_index,
78 libbpf_nla_getattr_str(tb[IFLA_IFNAME]));
79}
80
81static int do_bpf_dump_one_act(struct nlattr *attr)
82{
83 struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
84
85 if (libbpf_nla_parse_nested(tb, TCA_ACT_BPF_MAX, attr, NULL) < 0)
86 return -LIBBPF_ERRNO__NLPARSE;
87
88 if (!tb[TCA_ACT_BPF_PARMS])
89 return -LIBBPF_ERRNO__NLPARSE;
90
91 NET_START_OBJECT_NESTED2;
92 if (tb[TCA_ACT_BPF_NAME])
93 NET_DUMP_STR("name", "%s",
94 libbpf_nla_getattr_str(tb[TCA_ACT_BPF_NAME]));
95 if (tb[TCA_ACT_BPF_ID])
96 NET_DUMP_UINT("id", " id %u",
97 libbpf_nla_getattr_u32(tb[TCA_ACT_BPF_ID]));
98 NET_END_OBJECT_NESTED;
99 return 0;
100}
101
102static int do_dump_one_act(struct nlattr *attr)
103{
104 struct nlattr *tb[TCA_ACT_MAX + 1];
105
106 if (!attr)
107 return 0;
108
109 if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX, attr, NULL) < 0)
110 return -LIBBPF_ERRNO__NLPARSE;
111
112 if (tb[TCA_ACT_KIND] &&
113 strcmp(libbpf_nla_data(tb[TCA_ACT_KIND]), "bpf") == 0)
114 return do_bpf_dump_one_act(tb[TCA_ACT_OPTIONS]);
115
116 return 0;
117}
118
119static int do_bpf_act_dump(struct nlattr *attr)
120{
121 struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
122 int act, ret;
123
124 if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX_PRIO, attr, NULL) < 0)
125 return -LIBBPF_ERRNO__NLPARSE;
126
127 NET_START_ARRAY("act", " %s [");
128 for (act = 0; act <= TCA_ACT_MAX_PRIO; act++) {
129 ret = do_dump_one_act(tb[act]);
130 if (ret)
131 break;
132 }
133 NET_END_ARRAY("] ");
134
135 return ret;
136}
137
138static int do_bpf_filter_dump(struct nlattr *attr)
139{
140 struct nlattr *tb[TCA_BPF_MAX + 1];
141 int ret;
142
143 if (libbpf_nla_parse_nested(tb, TCA_BPF_MAX, attr, NULL) < 0)
144 return -LIBBPF_ERRNO__NLPARSE;
145
146 if (tb[TCA_BPF_NAME])
147 NET_DUMP_STR("name", " %s",
148 libbpf_nla_getattr_str(tb[TCA_BPF_NAME]));
149 if (tb[TCA_BPF_ID])
150 NET_DUMP_UINT("id", " id %u",
151 libbpf_nla_getattr_u32(tb[TCA_BPF_ID]));
152 if (tb[TCA_BPF_ACT]) {
153 ret = do_bpf_act_dump(tb[TCA_BPF_ACT]);
154 if (ret)
155 return ret;
156 }
157
158 return 0;
159}
160
161int do_filter_dump(struct tcmsg *info, struct nlattr **tb, const char *kind,
162 const char *devname, int ifindex)
163{
164 int ret = 0;
165
166 if (tb[TCA_OPTIONS] &&
167 strcmp(libbpf_nla_data(tb[TCA_KIND]), "bpf") == 0) {
168 NET_START_OBJECT;
169 if (devname[0] != '\0')
170 NET_DUMP_STR("devname", "%s", devname);
171 NET_DUMP_UINT("ifindex", "(%u)", ifindex);
172 NET_DUMP_STR("kind", " %s", kind);
173 ret = do_bpf_filter_dump(tb[TCA_OPTIONS]);
174 NET_END_OBJECT_FINAL;
175 }
176
177 return ret;
178}
diff --git a/tools/bpf/bpftool/netlink_dumper.h b/tools/bpf/bpftool/netlink_dumper.h
new file mode 100644
index 000000000000..e3516b586a34
--- /dev/null
+++ b/tools/bpf/bpftool/netlink_dumper.h
@@ -0,0 +1,95 @@
1// SPDX-License-Identifier: GPL-2.0+
2// Copyright (C) 2018 Facebook
3
4#ifndef _NETLINK_DUMPER_H_
5#define _NETLINK_DUMPER_H_
6
7#define NET_START_OBJECT \
8{ \
9 if (json_output) \
10 jsonw_start_object(json_wtr); \
11}
12
13#define NET_START_OBJECT_NESTED(name) \
14{ \
15 if (json_output) { \
16 jsonw_name(json_wtr, name); \
17 jsonw_start_object(json_wtr); \
18 } else { \
19 fprintf(stdout, "%s {", name); \
20 } \
21}
22
23#define NET_START_OBJECT_NESTED2 \
24{ \
25 if (json_output) \
26 jsonw_start_object(json_wtr); \
27 else \
28 fprintf(stdout, "{"); \
29}
30
31#define NET_END_OBJECT_NESTED \
32{ \
33 if (json_output) \
34 jsonw_end_object(json_wtr); \
35 else \
36 fprintf(stdout, "}"); \
37}
38
39#define NET_END_OBJECT \
40{ \
41 if (json_output) \
42 jsonw_end_object(json_wtr); \
43}
44
45#define NET_END_OBJECT_FINAL \
46{ \
47 if (json_output) \
48 jsonw_end_object(json_wtr); \
49 else \
50 fprintf(stdout, "\n"); \
51}
52
53#define NET_START_ARRAY(name, fmt_str) \
54{ \
55 if (json_output) { \
56 jsonw_name(json_wtr, name); \
57 jsonw_start_array(json_wtr); \
58 } else { \
59 fprintf(stdout, fmt_str, name); \
60 } \
61}
62
63#define NET_END_ARRAY(endstr) \
64{ \
65 if (json_output) \
66 jsonw_end_array(json_wtr); \
67 else \
68 fprintf(stdout, "%s", endstr); \
69}
70
71#define NET_DUMP_UINT(name, fmt_str, val) \
72{ \
73 if (json_output) \
74 jsonw_uint_field(json_wtr, name, val); \
75 else \
76 fprintf(stdout, fmt_str, val); \
77}
78
79#define NET_DUMP_STR(name, fmt_str, str) \
80{ \
81 if (json_output) \
82 jsonw_string_field(json_wtr, name, str);\
83 else \
84 fprintf(stdout, fmt_str, str); \
85}
86
87#define NET_DUMP_STR_ONLY(str) \
88{ \
89 if (json_output) \
90 jsonw_string(json_wtr, str); \
91 else \
92 fprintf(stdout, "%s ", str); \
93}
94
95#endif
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index dce960d22106..5302ee282409 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -74,8 +74,29 @@ static const char * const prog_type_name[] = {
74 [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint", 74 [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint",
75 [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr", 75 [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr",
76 [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2", 76 [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2",
77 [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector",
77}; 78};
78 79
80static const char * const attach_type_strings[] = {
81 [BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
82 [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
83 [BPF_SK_MSG_VERDICT] = "msg_verdict",
84 [__MAX_BPF_ATTACH_TYPE] = NULL,
85};
86
87enum bpf_attach_type parse_attach_type(const char *str)
88{
89 enum bpf_attach_type type;
90
91 for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
92 if (attach_type_strings[type] &&
93 is_prefix(str, attach_type_strings[type]))
94 return type;
95 }
96
97 return __MAX_BPF_ATTACH_TYPE;
98}
99
79static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) 100static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
80{ 101{
81 struct timespec real_time_ts, boot_time_ts; 102 struct timespec real_time_ts, boot_time_ts;
@@ -428,6 +449,7 @@ static int do_dump(int argc, char **argv)
428 unsigned long *func_ksyms = NULL; 449 unsigned long *func_ksyms = NULL;
429 struct bpf_prog_info info = {}; 450 struct bpf_prog_info info = {};
430 unsigned int *func_lens = NULL; 451 unsigned int *func_lens = NULL;
452 const char *disasm_opt = NULL;
431 unsigned int nr_func_ksyms; 453 unsigned int nr_func_ksyms;
432 unsigned int nr_func_lens; 454 unsigned int nr_func_lens;
433 struct dump_data dd = {}; 455 struct dump_data dd = {};
@@ -586,9 +608,10 @@ static int do_dump(int argc, char **argv)
586 const char *name = NULL; 608 const char *name = NULL;
587 609
588 if (info.ifindex) { 610 if (info.ifindex) {
589 name = ifindex_to_bfd_name_ns(info.ifindex, 611 name = ifindex_to_bfd_params(info.ifindex,
590 info.netns_dev, 612 info.netns_dev,
591 info.netns_ino); 613 info.netns_ino,
614 &disasm_opt);
592 if (!name) 615 if (!name)
593 goto err_free; 616 goto err_free;
594 } 617 }
@@ -630,7 +653,8 @@ static int do_dump(int argc, char **argv)
630 printf("%s:\n", sym_name); 653 printf("%s:\n", sym_name);
631 } 654 }
632 655
633 disasm_print_insn(img, lens[i], opcodes, name); 656 disasm_print_insn(img, lens[i], opcodes, name,
657 disasm_opt);
634 img += lens[i]; 658 img += lens[i];
635 659
636 if (json_output) 660 if (json_output)
@@ -642,7 +666,8 @@ static int do_dump(int argc, char **argv)
642 if (json_output) 666 if (json_output)
643 jsonw_end_array(json_wtr); 667 jsonw_end_array(json_wtr);
644 } else { 668 } else {
645 disasm_print_insn(buf, *member_len, opcodes, name); 669 disasm_print_insn(buf, *member_len, opcodes, name,
670 disasm_opt);
646 } 671 }
647 } else if (visual) { 672 } else if (visual) {
648 if (json_output) 673 if (json_output)
@@ -696,6 +721,77 @@ int map_replace_compar(const void *p1, const void *p2)
696 return a->idx - b->idx; 721 return a->idx - b->idx;
697} 722}
698 723
724static int do_attach(int argc, char **argv)
725{
726 enum bpf_attach_type attach_type;
727 int err, mapfd, progfd;
728
729 if (!REQ_ARGS(5)) {
730 p_err("too few parameters for map attach");
731 return -EINVAL;
732 }
733
734 progfd = prog_parse_fd(&argc, &argv);
735 if (progfd < 0)
736 return progfd;
737
738 attach_type = parse_attach_type(*argv);
739 if (attach_type == __MAX_BPF_ATTACH_TYPE) {
740 p_err("invalid attach type");
741 return -EINVAL;
742 }
743 NEXT_ARG();
744
745 mapfd = map_parse_fd(&argc, &argv);
746 if (mapfd < 0)
747 return mapfd;
748
749 err = bpf_prog_attach(progfd, mapfd, attach_type, 0);
750 if (err) {
751 p_err("failed prog attach to map");
752 return -EINVAL;
753 }
754
755 if (json_output)
756 jsonw_null(json_wtr);
757 return 0;
758}
759
760static int do_detach(int argc, char **argv)
761{
762 enum bpf_attach_type attach_type;
763 int err, mapfd, progfd;
764
765 if (!REQ_ARGS(5)) {
766 p_err("too few parameters for map detach");
767 return -EINVAL;
768 }
769
770 progfd = prog_parse_fd(&argc, &argv);
771 if (progfd < 0)
772 return progfd;
773
774 attach_type = parse_attach_type(*argv);
775 if (attach_type == __MAX_BPF_ATTACH_TYPE) {
776 p_err("invalid attach type");
777 return -EINVAL;
778 }
779 NEXT_ARG();
780
781 mapfd = map_parse_fd(&argc, &argv);
782 if (mapfd < 0)
783 return mapfd;
784
785 err = bpf_prog_detach2(progfd, mapfd, attach_type);
786 if (err) {
787 p_err("failed prog detach from map");
788 return -EINVAL;
789 }
790
791 if (json_output)
792 jsonw_null(json_wtr);
793 return 0;
794}
699static int do_load(int argc, char **argv) 795static int do_load(int argc, char **argv)
700{ 796{
701 enum bpf_attach_type expected_attach_type; 797 enum bpf_attach_type expected_attach_type;
@@ -816,7 +912,7 @@ static int do_load(int argc, char **argv)
816 } 912 }
817 } 913 }
818 914
819 obj = bpf_object__open_xattr(&attr); 915 obj = __bpf_object__open_xattr(&attr, bpf_flags);
820 if (IS_ERR_OR_NULL(obj)) { 916 if (IS_ERR_OR_NULL(obj)) {
821 p_err("failed to open object file"); 917 p_err("failed to open object file");
822 goto err_free_reuse_maps; 918 goto err_free_reuse_maps;
@@ -941,6 +1037,8 @@ static int do_help(int argc, char **argv)
941 " %s %s pin PROG FILE\n" 1037 " %s %s pin PROG FILE\n"
942 " %s %s load OBJ FILE [type TYPE] [dev NAME] \\\n" 1038 " %s %s load OBJ FILE [type TYPE] [dev NAME] \\\n"
943 " [map { idx IDX | name NAME } MAP]\n" 1039 " [map { idx IDX | name NAME } MAP]\n"
1040 " %s %s attach PROG ATTACH_TYPE MAP\n"
1041 " %s %s detach PROG ATTACH_TYPE MAP\n"
944 " %s %s help\n" 1042 " %s %s help\n"
945 "\n" 1043 "\n"
946 " " HELP_SPEC_MAP "\n" 1044 " " HELP_SPEC_MAP "\n"
@@ -952,10 +1050,12 @@ static int do_help(int argc, char **argv)
952 " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" 1050 " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
953 " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" 1051 " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
954 " cgroup/sendmsg4 | cgroup/sendmsg6 }\n" 1052 " cgroup/sendmsg4 | cgroup/sendmsg6 }\n"
1053 " ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse }\n"
955 " " HELP_SPEC_OPTIONS "\n" 1054 " " HELP_SPEC_OPTIONS "\n"
956 "", 1055 "",
957 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1056 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
958 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1057 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1058 bin_name, argv[-2], bin_name, argv[-2]);
959 1059
960 return 0; 1060 return 0;
961} 1061}
@@ -967,6 +1067,8 @@ static const struct cmd cmds[] = {
967 { "dump", do_dump }, 1067 { "dump", do_dump },
968 { "pin", do_pin }, 1068 { "pin", do_pin },
969 { "load", do_load }, 1069 { "load", do_load },
1070 { "attach", do_attach },
1071 { "detach", do_detach },
970 { 0 } 1072 { 0 }
971}; 1073};
972 1074
diff --git a/tools/crypto/getstat.c b/tools/crypto/getstat.c
new file mode 100644
index 000000000000..24115173a483
--- /dev/null
+++ b/tools/crypto/getstat.c
@@ -0,0 +1,294 @@
1/* Heavily copied from libkcapi 2015 - 2017, Stephan Mueller <smueller@chronox.de> */
2#include <errno.h>
3#include <linux/cryptouser.h>
4#include <linux/netlink.h>
5#include <linux/rtnetlink.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <string.h>
11#include <time.h>
12#include <unistd.h>
13
14#define CR_RTA(x) ((struct rtattr *)(((char *)(x)) + NLMSG_ALIGN(sizeof(struct crypto_user_alg))))
15
16static int get_stat(const char *drivername)
17{
18 struct {
19 struct nlmsghdr n;
20 struct crypto_user_alg cru;
21 } req;
22 struct sockaddr_nl nl;
23 int sd = 0, ret;
24 socklen_t addr_len;
25 struct iovec iov;
26 struct msghdr msg;
27 char buf[4096];
28 struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
29 struct crypto_user_alg *cru_res = NULL;
30 int res_len = 0;
31 struct rtattr *tb[CRYPTOCFGA_MAX + 1];
32 struct rtattr *rta;
33 struct nlmsgerr *errmsg;
34
35 memset(&req, 0, sizeof(req));
36 memset(&buf, 0, sizeof(buf));
37 memset(&msg, 0, sizeof(msg));
38
39 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.cru));
40 req.n.nlmsg_flags = NLM_F_REQUEST;
41 req.n.nlmsg_type = CRYPTO_MSG_GETSTAT;
42 req.n.nlmsg_seq = time(NULL);
43
44 strncpy(req.cru.cru_driver_name, drivername, strlen(drivername));
45
46 sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_CRYPTO);
47 if (sd < 0) {
48 fprintf(stderr, "Netlink error: cannot open netlink socket");
49 return -errno;
50 }
51 memset(&nl, 0, sizeof(nl));
52 nl.nl_family = AF_NETLINK;
53 if (bind(sd, (struct sockaddr *)&nl, sizeof(nl)) < 0) {
54 ret = -errno;
55 fprintf(stderr, "Netlink error: cannot bind netlink socket");
56 goto out;
57 }
58
59 /* sanity check that netlink socket was successfully opened */
60 addr_len = sizeof(nl);
61 if (getsockname(sd, (struct sockaddr *)&nl, &addr_len) < 0) {
62 ret = -errno;
63 printf("Netlink error: cannot getsockname");
64 goto out;
65 }
66 if (addr_len != sizeof(nl)) {
67 ret = -errno;
68 printf("Netlink error: wrong address length %d", addr_len);
69 goto out;
70 }
71 if (nl.nl_family != AF_NETLINK) {
72 ret = -errno;
73 printf("Netlink error: wrong address family %d",
74 nl.nl_family);
75 goto out;
76 }
77
78 memset(&nl, 0, sizeof(nl));
79 nl.nl_family = AF_NETLINK;
80 iov.iov_base = (void *)&req.n;
81 iov.iov_len = req.n.nlmsg_len;
82 msg.msg_name = &nl;
83 msg.msg_namelen = sizeof(nl);
84 msg.msg_iov = &iov;
85 msg.msg_iovlen = 1;
86 if (sendmsg(sd, &msg, 0) < 0) {
87 ret = -errno;
88 printf("Netlink error: sendmsg failed");
89 goto out;
90 }
91 memset(buf, 0, sizeof(buf));
92 iov.iov_base = buf;
93 while (1) {
94 iov.iov_len = sizeof(buf);
95 ret = recvmsg(sd, &msg, 0);
96 if (ret < 0) {
97 if (errno == EINTR || errno == EAGAIN)
98 continue;
99 ret = -errno;
100 printf("Netlink error: netlink receive error");
101 goto out;
102 }
103 if (ret == 0) {
104 ret = -errno;
105 printf("Netlink error: no data");
106 goto out;
107 }
108 if (ret > sizeof(buf)) {
109 ret = -errno;
110 printf("Netlink error: received too much data");
111 goto out;
112 }
113 break;
114 }
115
116 ret = -EFAULT;
117 res_len = res_n->nlmsg_len;
118 if (res_n->nlmsg_type == NLMSG_ERROR) {
119 errmsg = NLMSG_DATA(res_n);
120 fprintf(stderr, "Fail with %d\n", errmsg->error);
121 ret = errmsg->error;
122 goto out;
123 }
124
125 if (res_n->nlmsg_type == CRYPTO_MSG_GETSTAT) {
126 cru_res = NLMSG_DATA(res_n);
127 res_len -= NLMSG_SPACE(sizeof(*cru_res));
128 }
129 if (res_len < 0) {
130 printf("Netlink error: nlmsg len %d\n", res_len);
131 goto out;
132 }
133
134 if (!cru_res) {
135 ret = -EFAULT;
136 printf("Netlink error: no cru_res\n");
137 goto out;
138 }
139
140 rta = CR_RTA(cru_res);
141 memset(tb, 0, sizeof(struct rtattr *) * (CRYPTOCFGA_MAX + 1));
142 while (RTA_OK(rta, res_len)) {
143 if ((rta->rta_type <= CRYPTOCFGA_MAX) && (!tb[rta->rta_type]))
144 tb[rta->rta_type] = rta;
145 rta = RTA_NEXT(rta, res_len);
146 }
147 if (res_len) {
148 printf("Netlink error: unprocessed data %d",
149 res_len);
150 goto out;
151 }
152
153 if (tb[CRYPTOCFGA_STAT_HASH]) {
154 struct rtattr *rta = tb[CRYPTOCFGA_STAT_HASH];
155 struct crypto_stat *rhash =
156 (struct crypto_stat *)RTA_DATA(rta);
157 printf("%s\tHash\n\tHash: %u bytes: %llu\n\tErrors: %u\n",
158 drivername,
159 rhash->stat_hash_cnt, rhash->stat_hash_tlen,
160 rhash->stat_hash_err_cnt);
161 } else if (tb[CRYPTOCFGA_STAT_COMPRESS]) {
162 struct rtattr *rta = tb[CRYPTOCFGA_STAT_COMPRESS];
163 struct crypto_stat *rblk =
164 (struct crypto_stat *)RTA_DATA(rta);
165 printf("%s\tCompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n",
166 drivername,
167 rblk->stat_compress_cnt, rblk->stat_compress_tlen,
168 rblk->stat_decompress_cnt, rblk->stat_decompress_tlen,
169 rblk->stat_compress_err_cnt);
170 } else if (tb[CRYPTOCFGA_STAT_ACOMP]) {
171 struct rtattr *rta = tb[CRYPTOCFGA_STAT_ACOMP];
172 struct crypto_stat *rcomp =
173 (struct crypto_stat *)RTA_DATA(rta);
174 printf("%s\tACompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n",
175 drivername,
176 rcomp->stat_compress_cnt, rcomp->stat_compress_tlen,
177 rcomp->stat_decompress_cnt, rcomp->stat_decompress_tlen,
178 rcomp->stat_compress_err_cnt);
179 } else if (tb[CRYPTOCFGA_STAT_AEAD]) {
180 struct rtattr *rta = tb[CRYPTOCFGA_STAT_AEAD];
181 struct crypto_stat *raead =
182 (struct crypto_stat *)RTA_DATA(rta);
183 printf("%s\tAEAD\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n",
184 drivername,
185 raead->stat_encrypt_cnt, raead->stat_encrypt_tlen,
186 raead->stat_decrypt_cnt, raead->stat_decrypt_tlen,
187 raead->stat_aead_err_cnt);
188 } else if (tb[CRYPTOCFGA_STAT_BLKCIPHER]) {
189 struct rtattr *rta = tb[CRYPTOCFGA_STAT_BLKCIPHER];
190 struct crypto_stat *rblk =
191 (struct crypto_stat *)RTA_DATA(rta);
192 printf("%s\tCipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n",
193 drivername,
194 rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen,
195 rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen,
196 rblk->stat_cipher_err_cnt);
197 } else if (tb[CRYPTOCFGA_STAT_AKCIPHER]) {
198 struct rtattr *rta = tb[CRYPTOCFGA_STAT_AKCIPHER];
199 struct crypto_stat *rblk =
200 (struct crypto_stat *)RTA_DATA(rta);
201 printf("%s\tAkcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tSign: %u\n\tVerify: %u\n\tErrors: %u\n",
202 drivername,
203 rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen,
204 rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen,
205 rblk->stat_sign_cnt, rblk->stat_verify_cnt,
206 rblk->stat_akcipher_err_cnt);
207 } else if (tb[CRYPTOCFGA_STAT_CIPHER]) {
208 struct rtattr *rta = tb[CRYPTOCFGA_STAT_CIPHER];
209 struct crypto_stat *rblk =
210 (struct crypto_stat *)RTA_DATA(rta);
211 printf("%s\tcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n",
212 drivername,
213 rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen,
214 rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen,
215 rblk->stat_cipher_err_cnt);
216 } else if (tb[CRYPTOCFGA_STAT_RNG]) {
217 struct rtattr *rta = tb[CRYPTOCFGA_STAT_RNG];
218 struct crypto_stat *rrng =
219 (struct crypto_stat *)RTA_DATA(rta);
220 printf("%s\tRNG\n\tSeed: %u\n\tGenerate: %u bytes: %llu\n\tErrors: %u\n",
221 drivername,
222 rrng->stat_seed_cnt,
223 rrng->stat_generate_cnt, rrng->stat_generate_tlen,
224 rrng->stat_rng_err_cnt);
225 } else if (tb[CRYPTOCFGA_STAT_KPP]) {
226 struct rtattr *rta = tb[CRYPTOCFGA_STAT_KPP];
227 struct crypto_stat *rkpp =
228 (struct crypto_stat *)RTA_DATA(rta);
229 printf("%s\tKPP\n\tSetsecret: %u\n\tGenerate public key: %u\n\tCompute_shared_secret: %u\n\tErrors: %u\n",
230 drivername,
231 rkpp->stat_setsecret_cnt,
232 rkpp->stat_generate_public_key_cnt,
233 rkpp->stat_compute_shared_secret_cnt,
234 rkpp->stat_kpp_err_cnt);
235 } else {
236 fprintf(stderr, "%s is of an unknown algorithm\n", drivername);
237 }
238 ret = 0;
239out:
240 close(sd);
241 return ret;
242}
243
244int main(int argc, const char *argv[])
245{
246 char buf[4096];
247 FILE *procfd;
248 int i, lastspace;
249 int ret;
250
251 procfd = fopen("/proc/crypto", "r");
252 if (!procfd) {
253 ret = errno;
254 fprintf(stderr, "Cannot open /proc/crypto %s\n", strerror(errno));
255 return ret;
256 }
257 if (argc > 1) {
258 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
259 printf("Usage: %s [-h|--help] display this help\n", argv[0]);
260 printf("Usage: %s display all crypto statistics\n", argv[0]);
261 printf("Usage: %s drivername1 drivername2 ... = display crypto statistics about drivername1 ...\n", argv[0]);
262 return 0;
263 }
264 for (i = 1; i < argc; i++) {
265 ret = get_stat(argv[i]);
266 if (ret) {
267 fprintf(stderr, "Failed with %s\n", strerror(-ret));
268 return ret;
269 }
270 }
271 return 0;
272 }
273
274 while (fgets(buf, sizeof(buf), procfd)) {
275 if (!strncmp(buf, "driver", 6)) {
276 lastspace = 0;
277 i = 0;
278 while (i < strlen(buf)) {
279 i++;
280 if (buf[i] == ' ')
281 lastspace = i;
282 }
283 buf[strlen(buf) - 1] = '\0';
284 ret = get_stat(buf + lastspace + 1);
285 if (ret) {
286 fprintf(stderr, "Failed with %s\n", strerror(-ret));
287 goto out;
288 }
289 }
290 }
291out:
292 fclose(procfd);
293 return ret;
294}
diff --git a/tools/include/asm/barrier.h b/tools/include/asm/barrier.h
index 391d942536e5..8d378c57cb01 100644
--- a/tools/include/asm/barrier.h
+++ b/tools/include/asm/barrier.h
@@ -1,4 +1,5 @@
1/* SPDX-License-Identifier: GPL-2.0 */ 1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/compiler.h>
2#if defined(__i386__) || defined(__x86_64__) 3#if defined(__i386__) || defined(__x86_64__)
3#include "../../arch/x86/include/asm/barrier.h" 4#include "../../arch/x86/include/asm/barrier.h"
4#elif defined(__arm__) 5#elif defined(__arm__)
@@ -26,3 +27,37 @@
26#else 27#else
27#include <asm-generic/barrier.h> 28#include <asm-generic/barrier.h>
28#endif 29#endif
30
31/*
32 * Generic fallback smp_*() definitions for archs that haven't
33 * been updated yet.
34 */
35
36#ifndef smp_rmb
37# define smp_rmb() rmb()
38#endif
39
40#ifndef smp_wmb
41# define smp_wmb() wmb()
42#endif
43
44#ifndef smp_mb
45# define smp_mb() mb()
46#endif
47
48#ifndef smp_store_release
49# define smp_store_release(p, v) \
50do { \
51 smp_mb(); \
52 WRITE_ONCE(*p, v); \
53} while (0)
54#endif
55
56#ifndef smp_load_acquire
57# define smp_load_acquire(p) \
58({ \
59 typeof(*p) ___p1 = READ_ONCE(*p); \
60 smp_mb(); \
61 ___p1; \
62})
63#endif
diff --git a/tools/include/linux/ring_buffer.h b/tools/include/linux/ring_buffer.h
new file mode 100644
index 000000000000..9a083ae60473
--- /dev/null
+++ b/tools/include/linux/ring_buffer.h
@@ -0,0 +1,73 @@
1#ifndef _TOOLS_LINUX_RING_BUFFER_H_
2#define _TOOLS_LINUX_RING_BUFFER_H_
3
4#include <asm/barrier.h>
5
6/*
7 * Contract with kernel for walking the perf ring buffer from
8 * user space requires the following barrier pairing (quote
9 * from kernel/events/ring_buffer.c):
10 *
11 * Since the mmap() consumer (userspace) can run on a
12 * different CPU:
13 *
14 * kernel user
15 *
16 * if (LOAD ->data_tail) { LOAD ->data_head
17 * (A) smp_rmb() (C)
18 * STORE $data LOAD $data
19 * smp_wmb() (B) smp_mb() (D)
20 * STORE ->data_head STORE ->data_tail
21 * }
22 *
23 * Where A pairs with D, and B pairs with C.
24 *
25 * In our case A is a control dependency that separates the
26 * load of the ->data_tail and the stores of $data. In case
27 * ->data_tail indicates there is no room in the buffer to
28 * store $data we do not.
29 *
30 * D needs to be a full barrier since it separates the data
31 * READ from the tail WRITE.
32 *
33 * For B a WMB is sufficient since it separates two WRITEs,
34 * and for C an RMB is sufficient since it separates two READs.
35 *
36 * Note, instead of B, C, D we could also use smp_store_release()
37 * in B and D as well as smp_load_acquire() in C.
38 *
39 * However, this optimization does not make sense for all kernel
40 * supported architectures since for a fair number it would
41 * resolve into READ_ONCE() + smp_mb() pair for smp_load_acquire(),
42 * and smp_mb() + WRITE_ONCE() pair for smp_store_release().
43 *
44 * Thus for those smp_wmb() in B and smp_rmb() in C would still
45 * be less expensive. For the case of D this has either the same
46 * cost or is less expensive, for example, due to TSO x86 can
47 * avoid the CPU barrier entirely.
48 */
49
50static inline u64 ring_buffer_read_head(struct perf_event_mmap_page *base)
51{
52/*
53 * Architectures where smp_load_acquire() does not fallback to
54 * READ_ONCE() + smp_mb() pair.
55 */
56#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
57 defined(__ia64__) || defined(__sparc__) && defined(__arch64__)
58 return smp_load_acquire(&base->data_head);
59#else
60 u64 head = READ_ONCE(base->data_head);
61
62 smp_rmb();
63 return head;
64#endif
65}
66
67static inline void ring_buffer_write_tail(struct perf_event_mmap_page *base,
68 u64 tail)
69{
70 smp_store_release(&base->data_tail, tail);
71}
72
73#endif /* _TOOLS_LINUX_RING_BUFFER_H_ */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 66917a4eba27..852dc17ab47a 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -103,6 +103,7 @@ enum bpf_cmd {
103 BPF_BTF_LOAD, 103 BPF_BTF_LOAD,
104 BPF_BTF_GET_FD_BY_ID, 104 BPF_BTF_GET_FD_BY_ID,
105 BPF_TASK_FD_QUERY, 105 BPF_TASK_FD_QUERY,
106 BPF_MAP_LOOKUP_AND_DELETE_ELEM,
106}; 107};
107 108
108enum bpf_map_type { 109enum bpf_map_type {
@@ -127,6 +128,9 @@ enum bpf_map_type {
127 BPF_MAP_TYPE_SOCKHASH, 128 BPF_MAP_TYPE_SOCKHASH,
128 BPF_MAP_TYPE_CGROUP_STORAGE, 129 BPF_MAP_TYPE_CGROUP_STORAGE,
129 BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 130 BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
131 BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
132 BPF_MAP_TYPE_QUEUE,
133 BPF_MAP_TYPE_STACK,
130}; 134};
131 135
132enum bpf_prog_type { 136enum bpf_prog_type {
@@ -152,6 +156,7 @@ enum bpf_prog_type {
152 BPF_PROG_TYPE_LWT_SEG6LOCAL, 156 BPF_PROG_TYPE_LWT_SEG6LOCAL,
153 BPF_PROG_TYPE_LIRC_MODE2, 157 BPF_PROG_TYPE_LIRC_MODE2,
154 BPF_PROG_TYPE_SK_REUSEPORT, 158 BPF_PROG_TYPE_SK_REUSEPORT,
159 BPF_PROG_TYPE_FLOW_DISSECTOR,
155}; 160};
156 161
157enum bpf_attach_type { 162enum bpf_attach_type {
@@ -172,6 +177,7 @@ enum bpf_attach_type {
172 BPF_CGROUP_UDP4_SENDMSG, 177 BPF_CGROUP_UDP4_SENDMSG,
173 BPF_CGROUP_UDP6_SENDMSG, 178 BPF_CGROUP_UDP6_SENDMSG,
174 BPF_LIRC_MODE2, 179 BPF_LIRC_MODE2,
180 BPF_FLOW_DISSECTOR,
175 __MAX_BPF_ATTACH_TYPE 181 __MAX_BPF_ATTACH_TYPE
176}; 182};
177 183
@@ -459,6 +465,28 @@ union bpf_attr {
459 * Return 465 * Return
460 * 0 on success, or a negative error in case of failure. 466 * 0 on success, or a negative error in case of failure.
461 * 467 *
468 * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)
469 * Description
470 * Push an element *value* in *map*. *flags* is one of:
471 *
472 * **BPF_EXIST**
473 * If the queue/stack is full, the oldest element is removed to
474 * make room for this.
475 * Return
476 * 0 on success, or a negative error in case of failure.
477 *
478 * int bpf_map_pop_elem(struct bpf_map *map, void *value)
479 * Description
480 * Pop an element from *map*.
481 * Return
482 * 0 on success, or a negative error in case of failure.
483 *
484 * int bpf_map_peek_elem(struct bpf_map *map, void *value)
485 * Description
486 * Get an element from *map* without removing it.
487 * Return
488 * 0 on success, or a negative error in case of failure.
489 *
462 * int bpf_probe_read(void *dst, u32 size, const void *src) 490 * int bpf_probe_read(void *dst, u32 size, const void *src)
463 * Description 491 * Description
464 * For tracing programs, safely attempt to read *size* bytes from 492 * For tracing programs, safely attempt to read *size* bytes from
@@ -1430,7 +1458,7 @@ union bpf_attr {
1430 * Return 1458 * Return
1431 * 0 on success, or a negative error in case of failure. 1459 * 0 on success, or a negative error in case of failure.
1432 * 1460 *
1433 * int bpf_skb_adjust_room(struct sk_buff *skb, u32 len_diff, u32 mode, u64 flags) 1461 * int bpf_skb_adjust_room(struct sk_buff *skb, s32 len_diff, u32 mode, u64 flags)
1434 * Description 1462 * Description
1435 * Grow or shrink the room for data in the packet associated to 1463 * Grow or shrink the room for data in the packet associated to
1436 * *skb* by *len_diff*, and according to the selected *mode*. 1464 * *skb* by *len_diff*, and according to the selected *mode*.
@@ -2141,6 +2169,94 @@ union bpf_attr {
2141 * request in the skb. 2169 * request in the skb.
2142 * Return 2170 * Return
2143 * 0 on success, or a negative error in case of failure. 2171 * 0 on success, or a negative error in case of failure.
2172 *
2173 * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u32 netns, u64 flags)
2174 * Description
2175 * Look for TCP socket matching *tuple*, optionally in a child
2176 * network namespace *netns*. The return value must be checked,
2177 * and if non-NULL, released via **bpf_sk_release**\ ().
2178 *
2179 * The *ctx* should point to the context of the program, such as
2180 * the skb or socket (depending on the hook in use). This is used
2181 * to determine the base network namespace for the lookup.
2182 *
2183 * *tuple_size* must be one of:
2184 *
2185 * **sizeof**\ (*tuple*\ **->ipv4**)
2186 * Look for an IPv4 socket.
2187 * **sizeof**\ (*tuple*\ **->ipv6**)
2188 * Look for an IPv6 socket.
2189 *
2190 * If the *netns* is zero, then the socket lookup table in the
2191 * netns associated with the *ctx* will be used. For the TC hooks,
2192 * this in the netns of the device in the skb. For socket hooks,
2193 * this in the netns of the socket. If *netns* is non-zero, then
2194 * it specifies the ID of the netns relative to the netns
2195 * associated with the *ctx*.
2196 *
2197 * All values for *flags* are reserved for future usage, and must
2198 * be left at zero.
2199 *
2200 * This helper is available only if the kernel was compiled with
2201 * **CONFIG_NET** configuration option.
2202 * Return
2203 * Pointer to *struct bpf_sock*, or NULL in case of failure.
2204 *
2205 * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u32 netns, u64 flags)
2206 * Description
2207 * Look for UDP socket matching *tuple*, optionally in a child
2208 * network namespace *netns*. The return value must be checked,
2209 * and if non-NULL, released via **bpf_sk_release**\ ().
2210 *
2211 * The *ctx* should point to the context of the program, such as
2212 * the skb or socket (depending on the hook in use). This is used
2213 * to determine the base network namespace for the lookup.
2214 *
2215 * *tuple_size* must be one of:
2216 *
2217 * **sizeof**\ (*tuple*\ **->ipv4**)
2218 * Look for an IPv4 socket.
2219 * **sizeof**\ (*tuple*\ **->ipv6**)
2220 * Look for an IPv6 socket.
2221 *
2222 * If the *netns* is zero, then the socket lookup table in the
2223 * netns associated with the *ctx* will be used. For the TC hooks,
2224 * this in the netns of the device in the skb. For socket hooks,
2225 * this in the netns of the socket. If *netns* is non-zero, then
2226 * it specifies the ID of the netns relative to the netns
2227 * associated with the *ctx*.
2228 *
2229 * All values for *flags* are reserved for future usage, and must
2230 * be left at zero.
2231 *
2232 * This helper is available only if the kernel was compiled with
2233 * **CONFIG_NET** configuration option.
2234 * Return
2235 * Pointer to *struct bpf_sock*, or NULL in case of failure.
2236 *
2237 * int bpf_sk_release(struct bpf_sock *sk)
2238 * Description
2239 * Release the reference held by *sock*. *sock* must be a non-NULL
2240 * pointer that was returned from bpf_sk_lookup_xxx\ ().
2241 * Return
2242 * 0 on success, or a negative error in case of failure.
2243 *
2244 * int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags)
2245 * Description
2246 * For socket policies, insert *len* bytes into msg at offset
2247 * *start*.
2248 *
2249 * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a
2250 * *msg* it may want to insert metadata or options into the msg.
2251 * This can later be read and used by any of the lower layer BPF
2252 * hooks.
2253 *
2254 * This helper may fail if under memory pressure (a malloc
2255 * fails) in these cases BPF programs will get an appropriate
2256 * error and BPF programs will need to handle them.
2257 *
2258 * Return
2259 * 0 on success, or a negative error in case of failure.
2144 */ 2260 */
2145#define __BPF_FUNC_MAPPER(FN) \ 2261#define __BPF_FUNC_MAPPER(FN) \
2146 FN(unspec), \ 2262 FN(unspec), \
@@ -2226,7 +2342,14 @@ union bpf_attr {
2226 FN(get_current_cgroup_id), \ 2342 FN(get_current_cgroup_id), \
2227 FN(get_local_storage), \ 2343 FN(get_local_storage), \
2228 FN(sk_select_reuseport), \ 2344 FN(sk_select_reuseport), \
2229 FN(skb_ancestor_cgroup_id), 2345 FN(skb_ancestor_cgroup_id), \
2346 FN(sk_lookup_tcp), \
2347 FN(sk_lookup_udp), \
2348 FN(sk_release), \
2349 FN(map_push_elem), \
2350 FN(map_pop_elem), \
2351 FN(map_peek_elem), \
2352 FN(msg_push_data),
2230 2353
2231/* integer value in 'imm' field of BPF_CALL instruction selects which helper 2354/* integer value in 'imm' field of BPF_CALL instruction selects which helper
2232 * function eBPF program intends to call 2355 * function eBPF program intends to call
@@ -2333,6 +2456,7 @@ struct __sk_buff {
2333 /* ... here. */ 2456 /* ... here. */
2334 2457
2335 __u32 data_meta; 2458 __u32 data_meta;
2459 struct bpf_flow_keys *flow_keys;
2336}; 2460};
2337 2461
2338struct bpf_tunnel_key { 2462struct bpf_tunnel_key {
@@ -2395,6 +2519,23 @@ struct bpf_sock {
2395 */ 2519 */
2396}; 2520};
2397 2521
2522struct bpf_sock_tuple {
2523 union {
2524 struct {
2525 __be32 saddr;
2526 __be32 daddr;
2527 __be16 sport;
2528 __be16 dport;
2529 } ipv4;
2530 struct {
2531 __be32 saddr[4];
2532 __be32 daddr[4];
2533 __be16 sport;
2534 __be16 dport;
2535 } ipv6;
2536 };
2537};
2538
2398#define XDP_PACKET_HEADROOM 256 2539#define XDP_PACKET_HEADROOM 256
2399 2540
2400/* User return codes for XDP prog type. 2541/* User return codes for XDP prog type.
@@ -2778,4 +2919,27 @@ enum bpf_task_fd_type {
2778 BPF_FD_TYPE_URETPROBE, /* filename + offset */ 2919 BPF_FD_TYPE_URETPROBE, /* filename + offset */
2779}; 2920};
2780 2921
2922struct bpf_flow_keys {
2923 __u16 nhoff;
2924 __u16 thoff;
2925 __u16 addr_proto; /* ETH_P_* of valid addrs */
2926 __u8 is_frag;
2927 __u8 is_first_frag;
2928 __u8 is_encap;
2929 __u8 ip_proto;
2930 __be16 n_proto;
2931 __be16 sport;
2932 __be16 dport;
2933 union {
2934 struct {
2935 __be32 ipv4_src;
2936 __be32 ipv4_dst;
2937 };
2938 struct {
2939 __u32 ipv6_src[4]; /* in6_addr; network order */
2940 __u32 ipv6_dst[4]; /* in6_addr; network order */
2941 };
2942 };
2943};
2944
2781#endif /* _UAPI__LINUX_BPF_H__ */ 2945#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 43391e2d1153..58faab897201 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -161,6 +161,7 @@ enum {
161 IFLA_EVENT, 161 IFLA_EVENT,
162 IFLA_NEW_NETNSID, 162 IFLA_NEW_NETNSID,
163 IFLA_IF_NETNSID, 163 IFLA_IF_NETNSID,
164 IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */
164 IFLA_CARRIER_UP_COUNT, 165 IFLA_CARRIER_UP_COUNT,
165 IFLA_CARRIER_DOWN_COUNT, 166 IFLA_CARRIER_DOWN_COUNT,
166 IFLA_NEW_IFINDEX, 167 IFLA_NEW_IFINDEX,
@@ -554,6 +555,7 @@ enum {
554 IFLA_GENEVE_UDP_ZERO_CSUM6_TX, 555 IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
555 IFLA_GENEVE_UDP_ZERO_CSUM6_RX, 556 IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
556 IFLA_GENEVE_LABEL, 557 IFLA_GENEVE_LABEL,
558 IFLA_GENEVE_TTL_INHERIT,
557 __IFLA_GENEVE_MAX 559 __IFLA_GENEVE_MAX
558}; 560};
559#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) 561#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 251be353f950..2875ce85b322 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -719,6 +719,7 @@ struct kvm_ppc_one_seg_page_size {
719 719
720#define KVM_PPC_PAGE_SIZES_REAL 0x00000001 720#define KVM_PPC_PAGE_SIZES_REAL 0x00000001
721#define KVM_PPC_1T_SEGMENTS 0x00000002 721#define KVM_PPC_1T_SEGMENTS 0x00000002
722#define KVM_PPC_NO_HASH 0x00000004
722 723
723struct kvm_ppc_smmu_info { 724struct kvm_ppc_smmu_info {
724 __u64 flags; 725 __u64 flags;
@@ -953,6 +954,10 @@ struct kvm_ppc_resize_hpt {
953#define KVM_CAP_NESTED_STATE 157 954#define KVM_CAP_NESTED_STATE 157
954#define KVM_CAP_ARM_INJECT_SERROR_ESR 158 955#define KVM_CAP_ARM_INJECT_SERROR_ESR 158
955#define KVM_CAP_MSR_PLATFORM_INFO 159 956#define KVM_CAP_MSR_PLATFORM_INFO 159
957#define KVM_CAP_PPC_NESTED_HV 160
958#define KVM_CAP_HYPERV_SEND_IPI 161
959#define KVM_CAP_COALESCED_PIO 162
960#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
956 961
957#ifdef KVM_CAP_IRQ_ROUTING 962#ifdef KVM_CAP_IRQ_ROUTING
958 963
diff --git a/tools/include/uapi/linux/tls.h b/tools/include/uapi/linux/tls.h
new file mode 100644
index 000000000000..ff02287495ac
--- /dev/null
+++ b/tools/include/uapi/linux/tls.h
@@ -0,0 +1,78 @@
1/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR Linux-OpenIB) */
2/*
3 * Copyright (c) 2016-2017, Mellanox Technologies. All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34#ifndef _UAPI_LINUX_TLS_H
35#define _UAPI_LINUX_TLS_H
36
37#include <linux/types.h>
38
39/* TLS socket options */
40#define TLS_TX 1 /* Set transmit parameters */
41#define TLS_RX 2 /* Set receive parameters */
42
43/* Supported versions */
44#define TLS_VERSION_MINOR(ver) ((ver) & 0xFF)
45#define TLS_VERSION_MAJOR(ver) (((ver) >> 8) & 0xFF)
46
47#define TLS_VERSION_NUMBER(id) ((((id##_VERSION_MAJOR) & 0xFF) << 8) | \
48 ((id##_VERSION_MINOR) & 0xFF))
49
50#define TLS_1_2_VERSION_MAJOR 0x3
51#define TLS_1_2_VERSION_MINOR 0x3
52#define TLS_1_2_VERSION TLS_VERSION_NUMBER(TLS_1_2)
53
54/* Supported ciphers */
55#define TLS_CIPHER_AES_GCM_128 51
56#define TLS_CIPHER_AES_GCM_128_IV_SIZE 8
57#define TLS_CIPHER_AES_GCM_128_KEY_SIZE 16
58#define TLS_CIPHER_AES_GCM_128_SALT_SIZE 4
59#define TLS_CIPHER_AES_GCM_128_TAG_SIZE 16
60#define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 8
61
62#define TLS_SET_RECORD_TYPE 1
63#define TLS_GET_RECORD_TYPE 2
64
65struct tls_crypto_info {
66 __u16 version;
67 __u16 cipher_type;
68};
69
70struct tls12_crypto_info_aes_gcm_128 {
71 struct tls_crypto_info info;
72 unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE];
73 unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE];
74 unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE];
75 unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE];
76};
77
78#endif /* _UAPI_LINUX_TLS_H */
diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index 6eb9bacd1948..7bc31c905018 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1 @@
libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o netlink.o
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index d49902e818b5..425b480bda75 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -1,4 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2# Most of this file is copied from tools/lib/traceevent/Makefile 2# Most of this file is copied from tools/lib/traceevent/Makefile
3 3
4BPF_VERSION = 0 4BPF_VERSION = 0
@@ -69,7 +69,7 @@ FEATURE_USER = .libbpf
69FEATURE_TESTS = libelf libelf-mmap bpf reallocarray 69FEATURE_TESTS = libelf libelf-mmap bpf reallocarray
70FEATURE_DISPLAY = libelf bpf 70FEATURE_DISPLAY = libelf bpf
71 71
72INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi -I$(srctree)/tools/perf 72INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
73FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES) 73FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES)
74 74
75check_feat := 1 75check_feat := 1
@@ -125,6 +125,7 @@ override CFLAGS += $(EXTRA_WARNINGS)
125override CFLAGS += -Werror -Wall 125override CFLAGS += -Werror -Wall
126override CFLAGS += -fPIC 126override CFLAGS += -fPIC
127override CFLAGS += $(INCLUDES) 127override CFLAGS += $(INCLUDES)
128override CFLAGS += -fvisibility=hidden
128 129
129ifeq ($(VERBOSE),1) 130ifeq ($(VERBOSE),1)
130 Q = 131 Q =
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 60aa4ca8b2c5..03f9bcc4ef50 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: LGPL-2.1 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 2
3/* 3/*
4 * common eBPF ELF operations. 4 * common eBPF ELF operations.
@@ -28,16 +28,8 @@
28#include <linux/bpf.h> 28#include <linux/bpf.h>
29#include "bpf.h" 29#include "bpf.h"
30#include "libbpf.h" 30#include "libbpf.h"
31#include "nlattr.h"
32#include <linux/rtnetlink.h>
33#include <linux/if_link.h>
34#include <sys/socket.h>
35#include <errno.h> 31#include <errno.h>
36 32
37#ifndef SOL_NETLINK
38#define SOL_NETLINK 270
39#endif
40
41/* 33/*
42 * When building perf, unistd.h is overridden. __NR_bpf is 34 * When building perf, unistd.h is overridden. __NR_bpf is
43 * required to be defined explicitly. 35 * required to be defined explicitly.
@@ -286,6 +278,18 @@ int bpf_map_lookup_elem(int fd, const void *key, void *value)
286 return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); 278 return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
287} 279}
288 280
281int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
282{
283 union bpf_attr attr;
284
285 bzero(&attr, sizeof(attr));
286 attr.map_fd = fd;
287 attr.key = ptr_to_u64(key);
288 attr.value = ptr_to_u64(value);
289
290 return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
291}
292
289int bpf_map_delete_elem(int fd, const void *key) 293int bpf_map_delete_elem(int fd, const void *key)
290{ 294{
291 union bpf_attr attr; 295 union bpf_attr attr;
@@ -499,127 +503,6 @@ int bpf_raw_tracepoint_open(const char *name, int prog_fd)
499 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); 503 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
500} 504}
501 505
502int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
503{
504 struct sockaddr_nl sa;
505 int sock, seq = 0, len, ret = -1;
506 char buf[4096];
507 struct nlattr *nla, *nla_xdp;
508 struct {
509 struct nlmsghdr nh;
510 struct ifinfomsg ifinfo;
511 char attrbuf[64];
512 } req;
513 struct nlmsghdr *nh;
514 struct nlmsgerr *err;
515 socklen_t addrlen;
516 int one = 1;
517
518 memset(&sa, 0, sizeof(sa));
519 sa.nl_family = AF_NETLINK;
520
521 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
522 if (sock < 0) {
523 return -errno;
524 }
525
526 if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
527 &one, sizeof(one)) < 0) {
528 fprintf(stderr, "Netlink error reporting not supported\n");
529 }
530
531 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
532 ret = -errno;
533 goto cleanup;
534 }
535
536 addrlen = sizeof(sa);
537 if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
538 ret = -errno;
539 goto cleanup;
540 }
541
542 if (addrlen != sizeof(sa)) {
543 ret = -LIBBPF_ERRNO__INTERNAL;
544 goto cleanup;
545 }
546
547 memset(&req, 0, sizeof(req));
548 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
549 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
550 req.nh.nlmsg_type = RTM_SETLINK;
551 req.nh.nlmsg_pid = 0;
552 req.nh.nlmsg_seq = ++seq;
553 req.ifinfo.ifi_family = AF_UNSPEC;
554 req.ifinfo.ifi_index = ifindex;
555
556 /* started nested attribute for XDP */
557 nla = (struct nlattr *)(((char *)&req)
558 + NLMSG_ALIGN(req.nh.nlmsg_len));
559 nla->nla_type = NLA_F_NESTED | IFLA_XDP;
560 nla->nla_len = NLA_HDRLEN;
561
562 /* add XDP fd */
563 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
564 nla_xdp->nla_type = IFLA_XDP_FD;
565 nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
566 memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
567 nla->nla_len += nla_xdp->nla_len;
568
569 /* if user passed in any flags, add those too */
570 if (flags) {
571 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
572 nla_xdp->nla_type = IFLA_XDP_FLAGS;
573 nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
574 memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
575 nla->nla_len += nla_xdp->nla_len;
576 }
577
578 req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
579
580 if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
581 ret = -errno;
582 goto cleanup;
583 }
584
585 len = recv(sock, buf, sizeof(buf), 0);
586 if (len < 0) {
587 ret = -errno;
588 goto cleanup;
589 }
590
591 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
592 nh = NLMSG_NEXT(nh, len)) {
593 if (nh->nlmsg_pid != sa.nl_pid) {
594 ret = -LIBBPF_ERRNO__WRNGPID;
595 goto cleanup;
596 }
597 if (nh->nlmsg_seq != seq) {
598 ret = -LIBBPF_ERRNO__INVSEQ;
599 goto cleanup;
600 }
601 switch (nh->nlmsg_type) {
602 case NLMSG_ERROR:
603 err = (struct nlmsgerr *)NLMSG_DATA(nh);
604 if (!err->error)
605 continue;
606 ret = err->error;
607 nla_dump_errormsg(nh);
608 goto cleanup;
609 case NLMSG_DONE:
610 break;
611 default:
612 break;
613 }
614 }
615
616 ret = 0;
617
618cleanup:
619 close(sock);
620 return ret;
621}
622
623int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, 506int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
624 bool do_log) 507 bool do_log)
625{ 508{
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 6f38164b2618..26a51538213c 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -1,4 +1,4 @@
1/* SPDX-License-Identifier: LGPL-2.1 */ 1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 2
3/* 3/*
4 * common eBPF ELF operations. 4 * common eBPF ELF operations.
@@ -20,13 +20,17 @@
20 * You should have received a copy of the GNU Lesser General Public 20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this program; if not, see <http://www.gnu.org/licenses> 21 * License along with this program; if not, see <http://www.gnu.org/licenses>
22 */ 22 */
23#ifndef __BPF_BPF_H 23#ifndef __LIBBPF_BPF_H
24#define __BPF_BPF_H 24#define __LIBBPF_BPF_H
25 25
26#include <linux/bpf.h> 26#include <linux/bpf.h>
27#include <stdbool.h> 27#include <stdbool.h>
28#include <stddef.h> 28#include <stddef.h>
29 29
30#ifndef LIBBPF_API
31#define LIBBPF_API __attribute__((visibility("default")))
32#endif
33
30struct bpf_create_map_attr { 34struct bpf_create_map_attr {
31 const char *name; 35 const char *name;
32 enum bpf_map_type map_type; 36 enum bpf_map_type map_type;
@@ -42,21 +46,24 @@ struct bpf_create_map_attr {
42 __u32 inner_map_fd; 46 __u32 inner_map_fd;
43}; 47};
44 48
45int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr); 49LIBBPF_API int
46int bpf_create_map_node(enum bpf_map_type map_type, const char *name, 50bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr);
47 int key_size, int value_size, int max_entries, 51LIBBPF_API int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
48 __u32 map_flags, int node); 52 int key_size, int value_size,
49int bpf_create_map_name(enum bpf_map_type map_type, const char *name, 53 int max_entries, __u32 map_flags, int node);
50 int key_size, int value_size, int max_entries, 54LIBBPF_API int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
51 __u32 map_flags); 55 int key_size, int value_size,
52int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 56 int max_entries, __u32 map_flags);
53 int max_entries, __u32 map_flags); 57LIBBPF_API int bpf_create_map(enum bpf_map_type map_type, int key_size,
54int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name, 58 int value_size, int max_entries, __u32 map_flags);
55 int key_size, int inner_map_fd, int max_entries, 59LIBBPF_API int bpf_create_map_in_map_node(enum bpf_map_type map_type,
56 __u32 map_flags, int node); 60 const char *name, int key_size,
57int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, 61 int inner_map_fd, int max_entries,
58 int key_size, int inner_map_fd, int max_entries, 62 __u32 map_flags, int node);
59 __u32 map_flags); 63LIBBPF_API int bpf_create_map_in_map(enum bpf_map_type map_type,
64 const char *name, int key_size,
65 int inner_map_fd, int max_entries,
66 __u32 map_flags);
60 67
61struct bpf_load_program_attr { 68struct bpf_load_program_attr {
62 enum bpf_prog_type prog_type; 69 enum bpf_prog_type prog_type;
@@ -69,46 +76,56 @@ struct bpf_load_program_attr {
69 __u32 prog_ifindex; 76 __u32 prog_ifindex;
70}; 77};
71 78
79/* Flags to direct loading requirements */
80#define MAPS_RELAX_COMPAT 0x01
81
72/* Recommend log buffer size */ 82/* Recommend log buffer size */
73#define BPF_LOG_BUF_SIZE (256 * 1024) 83#define BPF_LOG_BUF_SIZE (256 * 1024)
74int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, 84LIBBPF_API int
75 char *log_buf, size_t log_buf_sz); 85bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
76int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 86 char *log_buf, size_t log_buf_sz);
77 size_t insns_cnt, const char *license, 87LIBBPF_API int bpf_load_program(enum bpf_prog_type type,
78 __u32 kern_version, char *log_buf, 88 const struct bpf_insn *insns, size_t insns_cnt,
79 size_t log_buf_sz); 89 const char *license, __u32 kern_version,
80int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 90 char *log_buf, size_t log_buf_sz);
81 size_t insns_cnt, int strict_alignment, 91LIBBPF_API int bpf_verify_program(enum bpf_prog_type type,
82 const char *license, __u32 kern_version, 92 const struct bpf_insn *insns,
83 char *log_buf, size_t log_buf_sz, int log_level); 93 size_t insns_cnt, int strict_alignment,
94 const char *license, __u32 kern_version,
95 char *log_buf, size_t log_buf_sz,
96 int log_level);
84 97
85int bpf_map_update_elem(int fd, const void *key, const void *value, 98LIBBPF_API int bpf_map_update_elem(int fd, const void *key, const void *value,
86 __u64 flags); 99 __u64 flags);
87 100
88int bpf_map_lookup_elem(int fd, const void *key, void *value); 101LIBBPF_API int bpf_map_lookup_elem(int fd, const void *key, void *value);
89int bpf_map_delete_elem(int fd, const void *key); 102LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key,
90int bpf_map_get_next_key(int fd, const void *key, void *next_key); 103 void *value);
91int bpf_obj_pin(int fd, const char *pathname); 104LIBBPF_API int bpf_map_delete_elem(int fd, const void *key);
92int bpf_obj_get(const char *pathname); 105LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key);
93int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type, 106LIBBPF_API int bpf_obj_pin(int fd, const char *pathname);
94 unsigned int flags); 107LIBBPF_API int bpf_obj_get(const char *pathname);
95int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); 108LIBBPF_API int bpf_prog_attach(int prog_fd, int attachable_fd,
96int bpf_prog_detach2(int prog_fd, int attachable_fd, enum bpf_attach_type type); 109 enum bpf_attach_type type, unsigned int flags);
97int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, 110LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
98 void *data_out, __u32 *size_out, __u32 *retval, 111LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
99 __u32 *duration); 112 enum bpf_attach_type type);
100int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id); 113LIBBPF_API int bpf_prog_test_run(int prog_fd, int repeat, void *data,
101int bpf_map_get_next_id(__u32 start_id, __u32 *next_id); 114 __u32 size, void *data_out, __u32 *size_out,
102int bpf_prog_get_fd_by_id(__u32 id); 115 __u32 *retval, __u32 *duration);
103int bpf_map_get_fd_by_id(__u32 id); 116LIBBPF_API int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
104int bpf_btf_get_fd_by_id(__u32 id); 117LIBBPF_API int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
105int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len); 118LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
106int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, 119LIBBPF_API int bpf_map_get_fd_by_id(__u32 id);
107 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt); 120LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
108int bpf_raw_tracepoint_open(const char *name, int prog_fd); 121LIBBPF_API int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len);
109int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, 122LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type,
110 bool do_log); 123 __u32 query_flags, __u32 *attach_flags,
111int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, 124 __u32 *prog_ids, __u32 *prog_cnt);
112 __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, 125LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
113 __u64 *probe_addr); 126LIBBPF_API int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf,
114#endif 127 __u32 log_buf_size, bool do_log);
128LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
129 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
130 __u64 *probe_offset, __u64 *probe_addr);
131#endif /* __LIBBPF_BPF_H */
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index cf94b0770522..449591aa9900 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: LGPL-2.1 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2/* Copyright (c) 2018 Facebook */ 2/* Copyright (c) 2018 Facebook */
3 3
4#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 4897e0724d4e..b77e7080f7e7 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -1,11 +1,15 @@
1/* SPDX-License-Identifier: LGPL-2.1 */ 1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2/* Copyright (c) 2018 Facebook */ 2/* Copyright (c) 2018 Facebook */
3 3
4#ifndef __BPF_BTF_H 4#ifndef __LIBBPF_BTF_H
5#define __BPF_BTF_H 5#define __LIBBPF_BTF_H
6 6
7#include <linux/types.h> 7#include <linux/types.h>
8 8
9#ifndef LIBBPF_API
10#define LIBBPF_API __attribute__((visibility("default")))
11#endif
12
9#define BTF_ELF_SEC ".BTF" 13#define BTF_ELF_SEC ".BTF"
10 14
11struct btf; 15struct btf;
@@ -14,13 +18,15 @@ struct btf_type;
14typedef int (*btf_print_fn_t)(const char *, ...) 18typedef int (*btf_print_fn_t)(const char *, ...)
15 __attribute__((format(printf, 1, 2))); 19 __attribute__((format(printf, 1, 2)));
16 20
17void btf__free(struct btf *btf); 21LIBBPF_API void btf__free(struct btf *btf);
18struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log); 22LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
19__s32 btf__find_by_name(const struct btf *btf, const char *type_name); 23LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
20const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id); 24 const char *type_name);
21__s64 btf__resolve_size(const struct btf *btf, __u32 type_id); 25LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
22int btf__resolve_type(const struct btf *btf, __u32 type_id); 26 __u32 id);
23int btf__fd(const struct btf *btf); 27LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
24const char *btf__name_by_offset(const struct btf *btf, __u32 offset); 28LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
29LIBBPF_API int btf__fd(const struct btf *btf);
30LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
25 31
26#endif 32#endif /* __LIBBPF_BTF_H */
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index bdb94939fd60..b607be7236d3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: LGPL-2.1 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 2
3/* 3/*
4 * Common eBPF ELF object loading operations. 4 * Common eBPF ELF object loading operations.
@@ -7,19 +7,6 @@
7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
8 * Copyright (C) 2015 Huawei Inc. 8 * Copyright (C) 2015 Huawei Inc.
9 * Copyright (C) 2017 Nicira, Inc. 9 * Copyright (C) 2017 Nicira, Inc.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation;
14 * version 2.1 of the License (not later!)
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, see <http://www.gnu.org/licenses>
23 */ 10 */
24 11
25#define _GNU_SOURCE 12#define _GNU_SOURCE
@@ -32,7 +19,6 @@
32#include <unistd.h> 19#include <unistd.h>
33#include <fcntl.h> 20#include <fcntl.h>
34#include <errno.h> 21#include <errno.h>
35#include <perf-sys.h>
36#include <asm/unistd.h> 22#include <asm/unistd.h>
37#include <linux/err.h> 23#include <linux/err.h>
38#include <linux/kernel.h> 24#include <linux/kernel.h>
@@ -40,6 +26,8 @@
40#include <linux/btf.h> 26#include <linux/btf.h>
41#include <linux/list.h> 27#include <linux/list.h>
42#include <linux/limits.h> 28#include <linux/limits.h>
29#include <linux/perf_event.h>
30#include <linux/ring_buffer.h>
43#include <sys/stat.h> 31#include <sys/stat.h>
44#include <sys/types.h> 32#include <sys/types.h>
45#include <sys/vfs.h> 33#include <sys/vfs.h>
@@ -182,7 +170,7 @@ static LIST_HEAD(bpf_objects_list);
182 170
183struct bpf_object { 171struct bpf_object {
184 char license[64]; 172 char license[64];
185 u32 kern_version; 173 __u32 kern_version;
186 174
187 struct bpf_program *programs; 175 struct bpf_program *programs;
188 size_t nr_programs; 176 size_t nr_programs;
@@ -228,7 +216,7 @@ struct bpf_object {
228}; 216};
229#define obj_elf_valid(o) ((o)->efile.elf) 217#define obj_elf_valid(o) ((o)->efile.elf)
230 218
231static void bpf_program__unload(struct bpf_program *prog) 219void bpf_program__unload(struct bpf_program *prog)
232{ 220{
233 int i; 221 int i;
234 222
@@ -470,7 +458,8 @@ static int bpf_object__elf_init(struct bpf_object *obj)
470 obj->efile.fd = open(obj->path, O_RDONLY); 458 obj->efile.fd = open(obj->path, O_RDONLY);
471 if (obj->efile.fd < 0) { 459 if (obj->efile.fd < 0) {
472 char errmsg[STRERR_BUFSIZE]; 460 char errmsg[STRERR_BUFSIZE];
473 char *cp = str_error(errno, errmsg, sizeof(errmsg)); 461 char *cp = libbpf_strerror_r(errno, errmsg,
462 sizeof(errmsg));
474 463
475 pr_warning("failed to open %s: %s\n", obj->path, cp); 464 pr_warning("failed to open %s: %s\n", obj->path, cp);
476 return -errno; 465 return -errno;
@@ -552,7 +541,7 @@ static int
552bpf_object__init_kversion(struct bpf_object *obj, 541bpf_object__init_kversion(struct bpf_object *obj,
553 void *data, size_t size) 542 void *data, size_t size)
554{ 543{
555 u32 kver; 544 __u32 kver;
556 545
557 if (size != sizeof(kver)) { 546 if (size != sizeof(kver)) {
558 pr_warning("invalid kver section in %s\n", obj->path); 547 pr_warning("invalid kver section in %s\n", obj->path);
@@ -574,8 +563,9 @@ static int compare_bpf_map(const void *_a, const void *_b)
574} 563}
575 564
576static int 565static int
577bpf_object__init_maps(struct bpf_object *obj) 566bpf_object__init_maps(struct bpf_object *obj, int flags)
578{ 567{
568 bool strict = !(flags & MAPS_RELAX_COMPAT);
579 int i, map_idx, map_def_sz, nr_maps = 0; 569 int i, map_idx, map_def_sz, nr_maps = 0;
580 Elf_Scn *scn; 570 Elf_Scn *scn;
581 Elf_Data *data; 571 Elf_Data *data;
@@ -697,7 +687,8 @@ bpf_object__init_maps(struct bpf_object *obj)
697 "has unrecognized, non-zero " 687 "has unrecognized, non-zero "
698 "options\n", 688 "options\n",
699 obj->path, map_name); 689 obj->path, map_name);
700 return -EINVAL; 690 if (strict)
691 return -EINVAL;
701 } 692 }
702 } 693 }
703 memcpy(&obj->maps[map_idx].def, def, 694 memcpy(&obj->maps[map_idx].def, def,
@@ -728,7 +719,7 @@ static bool section_have_execinstr(struct bpf_object *obj, int idx)
728 return false; 719 return false;
729} 720}
730 721
731static int bpf_object__elf_collect(struct bpf_object *obj) 722static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
732{ 723{
733 Elf *elf = obj->efile.elf; 724 Elf *elf = obj->efile.elf;
734 GElf_Ehdr *ep = &obj->efile.ehdr; 725 GElf_Ehdr *ep = &obj->efile.ehdr;
@@ -811,7 +802,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
811 data->d_size, name, idx); 802 data->d_size, name, idx);
812 if (err) { 803 if (err) {
813 char errmsg[STRERR_BUFSIZE]; 804 char errmsg[STRERR_BUFSIZE];
814 char *cp = str_error(-err, errmsg, sizeof(errmsg)); 805 char *cp = libbpf_strerror_r(-err, errmsg,
806 sizeof(errmsg));
815 807
816 pr_warning("failed to alloc program %s (%s): %s", 808 pr_warning("failed to alloc program %s (%s): %s",
817 name, obj->path, cp); 809 name, obj->path, cp);
@@ -854,7 +846,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
854 return LIBBPF_ERRNO__FORMAT; 846 return LIBBPF_ERRNO__FORMAT;
855 } 847 }
856 if (obj->efile.maps_shndx >= 0) { 848 if (obj->efile.maps_shndx >= 0) {
857 err = bpf_object__init_maps(obj); 849 err = bpf_object__init_maps(obj, flags);
858 if (err) 850 if (err)
859 goto out; 851 goto out;
860 } 852 }
@@ -1140,7 +1132,7 @@ bpf_object__create_maps(struct bpf_object *obj)
1140 1132
1141 *pfd = bpf_create_map_xattr(&create_attr); 1133 *pfd = bpf_create_map_xattr(&create_attr);
1142 if (*pfd < 0 && create_attr.btf_key_type_id) { 1134 if (*pfd < 0 && create_attr.btf_key_type_id) {
1143 cp = str_error(errno, errmsg, sizeof(errmsg)); 1135 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
1144 pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n", 1136 pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n",
1145 map->name, cp, errno); 1137 map->name, cp, errno);
1146 create_attr.btf_fd = 0; 1138 create_attr.btf_fd = 0;
@@ -1155,7 +1147,7 @@ bpf_object__create_maps(struct bpf_object *obj)
1155 size_t j; 1147 size_t j;
1156 1148
1157 err = *pfd; 1149 err = *pfd;
1158 cp = str_error(errno, errmsg, sizeof(errmsg)); 1150 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
1159 pr_warning("failed to create map (name: '%s'): %s\n", 1151 pr_warning("failed to create map (name: '%s'): %s\n",
1160 map->name, cp); 1152 map->name, cp);
1161 for (j = 0; j < i; j++) 1153 for (j = 0; j < i; j++)
@@ -1306,7 +1298,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1306static int 1298static int
1307load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type, 1299load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type,
1308 const char *name, struct bpf_insn *insns, int insns_cnt, 1300 const char *name, struct bpf_insn *insns, int insns_cnt,
1309 char *license, u32 kern_version, int *pfd, int prog_ifindex) 1301 char *license, __u32 kern_version, int *pfd, int prog_ifindex)
1310{ 1302{
1311 struct bpf_load_program_attr load_attr; 1303 struct bpf_load_program_attr load_attr;
1312 char *cp, errmsg[STRERR_BUFSIZE]; 1304 char *cp, errmsg[STRERR_BUFSIZE];
@@ -1339,7 +1331,7 @@ load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type,
1339 } 1331 }
1340 1332
1341 ret = -LIBBPF_ERRNO__LOAD; 1333 ret = -LIBBPF_ERRNO__LOAD;
1342 cp = str_error(errno, errmsg, sizeof(errmsg)); 1334 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
1343 pr_warning("load bpf program failed: %s\n", cp); 1335 pr_warning("load bpf program failed: %s\n", cp);
1344 1336
1345 if (log_buf && log_buf[0] != '\0') { 1337 if (log_buf && log_buf[0] != '\0') {
@@ -1375,9 +1367,9 @@ out:
1375 return ret; 1367 return ret;
1376} 1368}
1377 1369
1378static int 1370int
1379bpf_program__load(struct bpf_program *prog, 1371bpf_program__load(struct bpf_program *prog,
1380 char *license, u32 kern_version) 1372 char *license, __u32 kern_version)
1381{ 1373{
1382 int err = 0, fd, i; 1374 int err = 0, fd, i;
1383 1375
@@ -1502,6 +1494,7 @@ static bool bpf_prog_type__needs_kver(enum bpf_prog_type type)
1502 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: 1494 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
1503 case BPF_PROG_TYPE_LIRC_MODE2: 1495 case BPF_PROG_TYPE_LIRC_MODE2:
1504 case BPF_PROG_TYPE_SK_REUSEPORT: 1496 case BPF_PROG_TYPE_SK_REUSEPORT:
1497 case BPF_PROG_TYPE_FLOW_DISSECTOR:
1505 return false; 1498 return false;
1506 case BPF_PROG_TYPE_UNSPEC: 1499 case BPF_PROG_TYPE_UNSPEC:
1507 case BPF_PROG_TYPE_KPROBE: 1500 case BPF_PROG_TYPE_KPROBE:
@@ -1525,7 +1518,7 @@ static int bpf_object__validate(struct bpf_object *obj, bool needs_kver)
1525 1518
1526static struct bpf_object * 1519static struct bpf_object *
1527__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz, 1520__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz,
1528 bool needs_kver) 1521 bool needs_kver, int flags)
1529{ 1522{
1530 struct bpf_object *obj; 1523 struct bpf_object *obj;
1531 int err; 1524 int err;
@@ -1541,7 +1534,7 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz,
1541 1534
1542 CHECK_ERR(bpf_object__elf_init(obj), err, out); 1535 CHECK_ERR(bpf_object__elf_init(obj), err, out);
1543 CHECK_ERR(bpf_object__check_endianness(obj), err, out); 1536 CHECK_ERR(bpf_object__check_endianness(obj), err, out);
1544 CHECK_ERR(bpf_object__elf_collect(obj), err, out); 1537 CHECK_ERR(bpf_object__elf_collect(obj, flags), err, out);
1545 CHECK_ERR(bpf_object__collect_reloc(obj), err, out); 1538 CHECK_ERR(bpf_object__collect_reloc(obj), err, out);
1546 CHECK_ERR(bpf_object__validate(obj, needs_kver), err, out); 1539 CHECK_ERR(bpf_object__validate(obj, needs_kver), err, out);
1547 1540
@@ -1552,7 +1545,8 @@ out:
1552 return ERR_PTR(err); 1545 return ERR_PTR(err);
1553} 1546}
1554 1547
1555struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr) 1548struct bpf_object *__bpf_object__open_xattr(struct bpf_object_open_attr *attr,
1549 int flags)
1556{ 1550{
1557 /* param validation */ 1551 /* param validation */
1558 if (!attr->file) 1552 if (!attr->file)
@@ -1561,7 +1555,13 @@ struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr)
1561 pr_debug("loading %s\n", attr->file); 1555 pr_debug("loading %s\n", attr->file);
1562 1556
1563 return __bpf_object__open(attr->file, NULL, 0, 1557 return __bpf_object__open(attr->file, NULL, 0,
1564 bpf_prog_type__needs_kver(attr->prog_type)); 1558 bpf_prog_type__needs_kver(attr->prog_type),
1559 flags);
1560}
1561
1562struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr)
1563{
1564 return __bpf_object__open_xattr(attr, 0);
1565} 1565}
1566 1566
1567struct bpf_object *bpf_object__open(const char *path) 1567struct bpf_object *bpf_object__open(const char *path)
@@ -1594,7 +1594,7 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf,
1594 pr_debug("loading object '%s' from buffer\n", 1594 pr_debug("loading object '%s' from buffer\n",
1595 name); 1595 name);
1596 1596
1597 return __bpf_object__open(name, obj_buf, obj_buf_sz, true); 1597 return __bpf_object__open(name, obj_buf, obj_buf_sz, true, true);
1598} 1598}
1599 1599
1600int bpf_object__unload(struct bpf_object *obj) 1600int bpf_object__unload(struct bpf_object *obj)
@@ -1654,7 +1654,7 @@ static int check_path(const char *path)
1654 1654
1655 dir = dirname(dname); 1655 dir = dirname(dname);
1656 if (statfs(dir, &st_fs)) { 1656 if (statfs(dir, &st_fs)) {
1657 cp = str_error(errno, errmsg, sizeof(errmsg)); 1657 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
1658 pr_warning("failed to statfs %s: %s\n", dir, cp); 1658 pr_warning("failed to statfs %s: %s\n", dir, cp);
1659 err = -errno; 1659 err = -errno;
1660 } 1660 }
@@ -1690,7 +1690,7 @@ int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
1690 } 1690 }
1691 1691
1692 if (bpf_obj_pin(prog->instances.fds[instance], path)) { 1692 if (bpf_obj_pin(prog->instances.fds[instance], path)) {
1693 cp = str_error(errno, errmsg, sizeof(errmsg)); 1693 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
1694 pr_warning("failed to pin program: %s\n", cp); 1694 pr_warning("failed to pin program: %s\n", cp);
1695 return -errno; 1695 return -errno;
1696 } 1696 }
@@ -1708,7 +1708,7 @@ static int make_dir(const char *path)
1708 err = -errno; 1708 err = -errno;
1709 1709
1710 if (err) { 1710 if (err) {
1711 cp = str_error(-err, errmsg, sizeof(errmsg)); 1711 cp = libbpf_strerror_r(-err, errmsg, sizeof(errmsg));
1712 pr_warning("failed to mkdir %s: %s\n", path, cp); 1712 pr_warning("failed to mkdir %s: %s\n", path, cp);
1713 } 1713 }
1714 return err; 1714 return err;
@@ -1770,7 +1770,7 @@ int bpf_map__pin(struct bpf_map *map, const char *path)
1770 } 1770 }
1771 1771
1772 if (bpf_obj_pin(map->fd, path)) { 1772 if (bpf_obj_pin(map->fd, path)) {
1773 cp = str_error(errno, errmsg, sizeof(errmsg)); 1773 cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
1774 pr_warning("failed to pin map: %s\n", cp); 1774 pr_warning("failed to pin map: %s\n", cp);
1775 return -errno; 1775 return -errno;
1776 } 1776 }
@@ -2084,57 +2084,90 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
2084 prog->expected_attach_type = type; 2084 prog->expected_attach_type = type;
2085} 2085}
2086 2086
2087#define BPF_PROG_SEC_FULL(string, ptype, atype) \ 2087#define BPF_PROG_SEC_IMPL(string, ptype, eatype, atype) \
2088 { string, sizeof(string) - 1, ptype, atype } 2088 { string, sizeof(string) - 1, ptype, eatype, atype }
2089 2089
2090#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_FULL(string, ptype, 0) 2090/* Programs that can NOT be attached. */
2091#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, -EINVAL)
2091 2092
2092#define BPF_S_PROG_SEC(string, ptype) \ 2093/* Programs that can be attached. */
2093 BPF_PROG_SEC_FULL(string, BPF_PROG_TYPE_CGROUP_SOCK, ptype) 2094#define BPF_APROG_SEC(string, ptype, atype) \
2095 BPF_PROG_SEC_IMPL(string, ptype, 0, atype)
2094 2096
2095#define BPF_SA_PROG_SEC(string, ptype) \ 2097/* Programs that must specify expected attach type at load time. */
2096 BPF_PROG_SEC_FULL(string, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, ptype) 2098#define BPF_EAPROG_SEC(string, ptype, eatype) \
2099 BPF_PROG_SEC_IMPL(string, ptype, eatype, eatype)
2100
2101/* Programs that can be attached but attach type can't be identified by section
2102 * name. Kept for backward compatibility.
2103 */
2104#define BPF_APROG_COMPAT(string, ptype) BPF_PROG_SEC(string, ptype)
2097 2105
2098static const struct { 2106static const struct {
2099 const char *sec; 2107 const char *sec;
2100 size_t len; 2108 size_t len;
2101 enum bpf_prog_type prog_type; 2109 enum bpf_prog_type prog_type;
2102 enum bpf_attach_type expected_attach_type; 2110 enum bpf_attach_type expected_attach_type;
2111 enum bpf_attach_type attach_type;
2103} section_names[] = { 2112} section_names[] = {
2104 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), 2113 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
2105 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE), 2114 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE),
2106 BPF_PROG_SEC("kretprobe/", BPF_PROG_TYPE_KPROBE), 2115 BPF_PROG_SEC("kretprobe/", BPF_PROG_TYPE_KPROBE),
2107 BPF_PROG_SEC("classifier", BPF_PROG_TYPE_SCHED_CLS), 2116 BPF_PROG_SEC("classifier", BPF_PROG_TYPE_SCHED_CLS),
2108 BPF_PROG_SEC("action", BPF_PROG_TYPE_SCHED_ACT), 2117 BPF_PROG_SEC("action", BPF_PROG_TYPE_SCHED_ACT),
2109 BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT), 2118 BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT),
2110 BPF_PROG_SEC("raw_tracepoint/", BPF_PROG_TYPE_RAW_TRACEPOINT), 2119 BPF_PROG_SEC("raw_tracepoint/", BPF_PROG_TYPE_RAW_TRACEPOINT),
2111 BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP), 2120 BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
2112 BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT), 2121 BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
2113 BPF_PROG_SEC("cgroup/skb", BPF_PROG_TYPE_CGROUP_SKB), 2122 BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN),
2114 BPF_PROG_SEC("cgroup/sock", BPF_PROG_TYPE_CGROUP_SOCK), 2123 BPF_PROG_SEC("lwt_out", BPF_PROG_TYPE_LWT_OUT),
2115 BPF_PROG_SEC("cgroup/dev", BPF_PROG_TYPE_CGROUP_DEVICE), 2124 BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT),
2116 BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN), 2125 BPF_PROG_SEC("lwt_seg6local", BPF_PROG_TYPE_LWT_SEG6LOCAL),
2117 BPF_PROG_SEC("lwt_out", BPF_PROG_TYPE_LWT_OUT), 2126 BPF_APROG_SEC("cgroup_skb/ingress", BPF_PROG_TYPE_CGROUP_SKB,
2118 BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT), 2127 BPF_CGROUP_INET_INGRESS),
2119 BPF_PROG_SEC("lwt_seg6local", BPF_PROG_TYPE_LWT_SEG6LOCAL), 2128 BPF_APROG_SEC("cgroup_skb/egress", BPF_PROG_TYPE_CGROUP_SKB,
2120 BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS), 2129 BPF_CGROUP_INET_EGRESS),
2121 BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), 2130 BPF_APROG_COMPAT("cgroup/skb", BPF_PROG_TYPE_CGROUP_SKB),
2122 BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG), 2131 BPF_APROG_SEC("cgroup/sock", BPF_PROG_TYPE_CGROUP_SOCK,
2123 BPF_PROG_SEC("lirc_mode2", BPF_PROG_TYPE_LIRC_MODE2), 2132 BPF_CGROUP_INET_SOCK_CREATE),
2124 BPF_SA_PROG_SEC("cgroup/bind4", BPF_CGROUP_INET4_BIND), 2133 BPF_EAPROG_SEC("cgroup/post_bind4", BPF_PROG_TYPE_CGROUP_SOCK,
2125 BPF_SA_PROG_SEC("cgroup/bind6", BPF_CGROUP_INET6_BIND), 2134 BPF_CGROUP_INET4_POST_BIND),
2126 BPF_SA_PROG_SEC("cgroup/connect4", BPF_CGROUP_INET4_CONNECT), 2135 BPF_EAPROG_SEC("cgroup/post_bind6", BPF_PROG_TYPE_CGROUP_SOCK,
2127 BPF_SA_PROG_SEC("cgroup/connect6", BPF_CGROUP_INET6_CONNECT), 2136 BPF_CGROUP_INET6_POST_BIND),
2128 BPF_SA_PROG_SEC("cgroup/sendmsg4", BPF_CGROUP_UDP4_SENDMSG), 2137 BPF_APROG_SEC("cgroup/dev", BPF_PROG_TYPE_CGROUP_DEVICE,
2129 BPF_SA_PROG_SEC("cgroup/sendmsg6", BPF_CGROUP_UDP6_SENDMSG), 2138 BPF_CGROUP_DEVICE),
2130 BPF_S_PROG_SEC("cgroup/post_bind4", BPF_CGROUP_INET4_POST_BIND), 2139 BPF_APROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS,
2131 BPF_S_PROG_SEC("cgroup/post_bind6", BPF_CGROUP_INET6_POST_BIND), 2140 BPF_CGROUP_SOCK_OPS),
2141 BPF_APROG_SEC("sk_skb/stream_parser", BPF_PROG_TYPE_SK_SKB,
2142 BPF_SK_SKB_STREAM_PARSER),
2143 BPF_APROG_SEC("sk_skb/stream_verdict", BPF_PROG_TYPE_SK_SKB,
2144 BPF_SK_SKB_STREAM_VERDICT),
2145 BPF_APROG_COMPAT("sk_skb", BPF_PROG_TYPE_SK_SKB),
2146 BPF_APROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG,
2147 BPF_SK_MSG_VERDICT),
2148 BPF_APROG_SEC("lirc_mode2", BPF_PROG_TYPE_LIRC_MODE2,
2149 BPF_LIRC_MODE2),
2150 BPF_APROG_SEC("flow_dissector", BPF_PROG_TYPE_FLOW_DISSECTOR,
2151 BPF_FLOW_DISSECTOR),
2152 BPF_EAPROG_SEC("cgroup/bind4", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
2153 BPF_CGROUP_INET4_BIND),
2154 BPF_EAPROG_SEC("cgroup/bind6", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
2155 BPF_CGROUP_INET6_BIND),
2156 BPF_EAPROG_SEC("cgroup/connect4", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
2157 BPF_CGROUP_INET4_CONNECT),
2158 BPF_EAPROG_SEC("cgroup/connect6", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
2159 BPF_CGROUP_INET6_CONNECT),
2160 BPF_EAPROG_SEC("cgroup/sendmsg4", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
2161 BPF_CGROUP_UDP4_SENDMSG),
2162 BPF_EAPROG_SEC("cgroup/sendmsg6", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
2163 BPF_CGROUP_UDP6_SENDMSG),
2132}; 2164};
2133 2165
2166#undef BPF_PROG_SEC_IMPL
2134#undef BPF_PROG_SEC 2167#undef BPF_PROG_SEC
2135#undef BPF_PROG_SEC_FULL 2168#undef BPF_APROG_SEC
2136#undef BPF_S_PROG_SEC 2169#undef BPF_EAPROG_SEC
2137#undef BPF_SA_PROG_SEC 2170#undef BPF_APROG_COMPAT
2138 2171
2139int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type, 2172int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
2140 enum bpf_attach_type *expected_attach_type) 2173 enum bpf_attach_type *expected_attach_type)
@@ -2154,6 +2187,25 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
2154 return -EINVAL; 2187 return -EINVAL;
2155} 2188}
2156 2189
2190int libbpf_attach_type_by_name(const char *name,
2191 enum bpf_attach_type *attach_type)
2192{
2193 int i;
2194
2195 if (!name)
2196 return -EINVAL;
2197
2198 for (i = 0; i < ARRAY_SIZE(section_names); i++) {
2199 if (strncmp(name, section_names[i].sec, section_names[i].len))
2200 continue;
2201 if (section_names[i].attach_type == -EINVAL)
2202 return -EINVAL;
2203 *attach_type = section_names[i].attach_type;
2204 return 0;
2205 }
2206 return -EINVAL;
2207}
2208
2157static int 2209static int
2158bpf_program__identify_section(struct bpf_program *prog, 2210bpf_program__identify_section(struct bpf_program *prog,
2159 enum bpf_prog_type *prog_type, 2211 enum bpf_prog_type *prog_type,
@@ -2336,7 +2388,7 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
2336 bpf_program__set_expected_attach_type(prog, 2388 bpf_program__set_expected_attach_type(prog,
2337 expected_attach_type); 2389 expected_attach_type);
2338 2390
2339 if (!bpf_program__is_function_storage(prog, obj) && !first_prog) 2391 if (!first_prog)
2340 first_prog = prog; 2392 first_prog = prog;
2341 } 2393 }
2342 2394
@@ -2363,61 +2415,49 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
2363} 2415}
2364 2416
2365enum bpf_perf_event_ret 2417enum bpf_perf_event_ret
2366bpf_perf_event_read_simple(void *mem, unsigned long size, 2418bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
2367 unsigned long page_size, void **buf, size_t *buf_len, 2419 void **copy_mem, size_t *copy_size,
2368 bpf_perf_event_print_t fn, void *priv) 2420 bpf_perf_event_print_t fn, void *private_data)
2369{ 2421{
2370 volatile struct perf_event_mmap_page *header = mem; 2422 struct perf_event_mmap_page *header = mmap_mem;
2423 __u64 data_head = ring_buffer_read_head(header);
2371 __u64 data_tail = header->data_tail; 2424 __u64 data_tail = header->data_tail;
2372 __u64 data_head = header->data_head; 2425 void *base = ((__u8 *)header) + page_size;
2373 int ret = LIBBPF_PERF_EVENT_ERROR; 2426 int ret = LIBBPF_PERF_EVENT_CONT;
2374 void *base, *begin, *end; 2427 struct perf_event_header *ehdr;
2375 2428 size_t ehdr_size;
2376 asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */ 2429
2377 if (data_head == data_tail) 2430 while (data_head != data_tail) {
2378 return LIBBPF_PERF_EVENT_CONT; 2431 ehdr = base + (data_tail & (mmap_size - 1));
2379 2432 ehdr_size = ehdr->size;
2380 base = ((char *)header) + page_size; 2433
2381 2434 if (((void *)ehdr) + ehdr_size > base + mmap_size) {
2382 begin = base + data_tail % size; 2435 void *copy_start = ehdr;
2383 end = base + data_head % size; 2436 size_t len_first = base + mmap_size - copy_start;
2384 2437 size_t len_secnd = ehdr_size - len_first;
2385 while (begin != end) { 2438
2386 struct perf_event_header *ehdr; 2439 if (*copy_size < ehdr_size) {
2387 2440 free(*copy_mem);
2388 ehdr = begin; 2441 *copy_mem = malloc(ehdr_size);
2389 if (begin + ehdr->size > base + size) { 2442 if (!*copy_mem) {
2390 long len = base + size - begin; 2443 *copy_size = 0;
2391
2392 if (*buf_len < ehdr->size) {
2393 free(*buf);
2394 *buf = malloc(ehdr->size);
2395 if (!*buf) {
2396 ret = LIBBPF_PERF_EVENT_ERROR; 2444 ret = LIBBPF_PERF_EVENT_ERROR;
2397 break; 2445 break;
2398 } 2446 }
2399 *buf_len = ehdr->size; 2447 *copy_size = ehdr_size;
2400 } 2448 }
2401 2449
2402 memcpy(*buf, begin, len); 2450 memcpy(*copy_mem, copy_start, len_first);
2403 memcpy(*buf + len, base, ehdr->size - len); 2451 memcpy(*copy_mem + len_first, base, len_secnd);
2404 ehdr = (void *)*buf; 2452 ehdr = *copy_mem;
2405 begin = base + ehdr->size - len;
2406 } else if (begin + ehdr->size == base + size) {
2407 begin = base;
2408 } else {
2409 begin += ehdr->size;
2410 } 2453 }
2411 2454
2412 ret = fn(ehdr, priv); 2455 ret = fn(ehdr, private_data);
2456 data_tail += ehdr_size;
2413 if (ret != LIBBPF_PERF_EVENT_CONT) 2457 if (ret != LIBBPF_PERF_EVENT_CONT)
2414 break; 2458 break;
2415
2416 data_tail += ehdr->size;
2417 } 2459 }
2418 2460
2419 __sync_synchronize(); /* smp_mb() */ 2461 ring_buffer_write_tail(header, data_tail);
2420 header->data_tail = data_tail;
2421
2422 return ret; 2462 return ret;
2423} 2463}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 96c55fac54c3..1f3468dad8b2 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -1,4 +1,4 @@
1/* SPDX-License-Identifier: LGPL-2.1 */ 1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 2
3/* 3/*
4 * Common eBPF ELF object loading operations. 4 * Common eBPF ELF object loading operations.
@@ -6,22 +6,9 @@
6 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 6 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
8 * Copyright (C) 2015 Huawei Inc. 8 * Copyright (C) 2015 Huawei Inc.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation;
13 * version 2.1 of the License (not later!)
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this program; if not, see <http://www.gnu.org/licenses>
22 */ 9 */
23#ifndef __BPF_LIBBPF_H 10#ifndef __LIBBPF_LIBBPF_H
24#define __BPF_LIBBPF_H 11#define __LIBBPF_LIBBPF_H
25 12
26#include <stdio.h> 13#include <stdio.h>
27#include <stdint.h> 14#include <stdint.h>
@@ -29,6 +16,10 @@
29#include <sys/types.h> // for size_t 16#include <sys/types.h> // for size_t
30#include <linux/bpf.h> 17#include <linux/bpf.h>
31 18
19#ifndef LIBBPF_API
20#define LIBBPF_API __attribute__((visibility("default")))
21#endif
22
32enum libbpf_errno { 23enum libbpf_errno {
33 __LIBBPF_ERRNO__START = 4000, 24 __LIBBPF_ERRNO__START = 4000,
34 25
@@ -46,10 +37,11 @@ enum libbpf_errno {
46 LIBBPF_ERRNO__PROGTYPE, /* Kernel doesn't support this program type */ 37 LIBBPF_ERRNO__PROGTYPE, /* Kernel doesn't support this program type */
47 LIBBPF_ERRNO__WRNGPID, /* Wrong pid in netlink message */ 38 LIBBPF_ERRNO__WRNGPID, /* Wrong pid in netlink message */
48 LIBBPF_ERRNO__INVSEQ, /* Invalid netlink sequence */ 39 LIBBPF_ERRNO__INVSEQ, /* Invalid netlink sequence */
40 LIBBPF_ERRNO__NLPARSE, /* netlink parsing error */
49 __LIBBPF_ERRNO__END, 41 __LIBBPF_ERRNO__END,
50}; 42};
51 43
52int libbpf_strerror(int err, char *buf, size_t size); 44LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size);
53 45
54/* 46/*
55 * __printf is defined in include/linux/compiler-gcc.h. However, 47 * __printf is defined in include/linux/compiler-gcc.h. However,
@@ -59,9 +51,9 @@ int libbpf_strerror(int err, char *buf, size_t size);
59typedef int (*libbpf_print_fn_t)(const char *, ...) 51typedef int (*libbpf_print_fn_t)(const char *, ...)
60 __attribute__((format(printf, 1, 2))); 52 __attribute__((format(printf, 1, 2)));
61 53
62void libbpf_set_print(libbpf_print_fn_t warn, 54LIBBPF_API void libbpf_set_print(libbpf_print_fn_t warn,
63 libbpf_print_fn_t info, 55 libbpf_print_fn_t info,
64 libbpf_print_fn_t debug); 56 libbpf_print_fn_t debug);
65 57
66/* Hide internal to user */ 58/* Hide internal to user */
67struct bpf_object; 59struct bpf_object;
@@ -71,25 +63,28 @@ struct bpf_object_open_attr {
71 enum bpf_prog_type prog_type; 63 enum bpf_prog_type prog_type;
72}; 64};
73 65
74struct bpf_object *bpf_object__open(const char *path); 66LIBBPF_API struct bpf_object *bpf_object__open(const char *path);
75struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr); 67LIBBPF_API struct bpf_object *
76struct bpf_object *bpf_object__open_buffer(void *obj_buf, 68bpf_object__open_xattr(struct bpf_object_open_attr *attr);
77 size_t obj_buf_sz, 69struct bpf_object *__bpf_object__open_xattr(struct bpf_object_open_attr *attr,
78 const char *name); 70 int flags);
79int bpf_object__pin(struct bpf_object *object, const char *path); 71LIBBPF_API struct bpf_object *bpf_object__open_buffer(void *obj_buf,
80void bpf_object__close(struct bpf_object *object); 72 size_t obj_buf_sz,
73 const char *name);
74LIBBPF_API int bpf_object__pin(struct bpf_object *object, const char *path);
75LIBBPF_API void bpf_object__close(struct bpf_object *object);
81 76
82/* Load/unload object into/from kernel */ 77/* Load/unload object into/from kernel */
83int bpf_object__load(struct bpf_object *obj); 78LIBBPF_API int bpf_object__load(struct bpf_object *obj);
84int bpf_object__unload(struct bpf_object *obj); 79LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
85const char *bpf_object__name(struct bpf_object *obj); 80LIBBPF_API const char *bpf_object__name(struct bpf_object *obj);
86unsigned int bpf_object__kversion(struct bpf_object *obj); 81LIBBPF_API unsigned int bpf_object__kversion(struct bpf_object *obj);
87int bpf_object__btf_fd(const struct bpf_object *obj); 82LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
88 83
89struct bpf_program * 84LIBBPF_API struct bpf_program *
90bpf_object__find_program_by_title(struct bpf_object *obj, const char *title); 85bpf_object__find_program_by_title(struct bpf_object *obj, const char *title);
91 86
92struct bpf_object *bpf_object__next(struct bpf_object *prev); 87LIBBPF_API struct bpf_object *bpf_object__next(struct bpf_object *prev);
93#define bpf_object__for_each_safe(pos, tmp) \ 88#define bpf_object__for_each_safe(pos, tmp) \
94 for ((pos) = bpf_object__next(NULL), \ 89 for ((pos) = bpf_object__next(NULL), \
95 (tmp) = bpf_object__next(pos); \ 90 (tmp) = bpf_object__next(pos); \
@@ -97,17 +92,20 @@ struct bpf_object *bpf_object__next(struct bpf_object *prev);
97 (pos) = (tmp), (tmp) = bpf_object__next(tmp)) 92 (pos) = (tmp), (tmp) = bpf_object__next(tmp))
98 93
99typedef void (*bpf_object_clear_priv_t)(struct bpf_object *, void *); 94typedef void (*bpf_object_clear_priv_t)(struct bpf_object *, void *);
100int bpf_object__set_priv(struct bpf_object *obj, void *priv, 95LIBBPF_API int bpf_object__set_priv(struct bpf_object *obj, void *priv,
101 bpf_object_clear_priv_t clear_priv); 96 bpf_object_clear_priv_t clear_priv);
102void *bpf_object__priv(struct bpf_object *prog); 97LIBBPF_API void *bpf_object__priv(struct bpf_object *prog);
103 98
104int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type, 99LIBBPF_API int
105 enum bpf_attach_type *expected_attach_type); 100libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
101 enum bpf_attach_type *expected_attach_type);
102LIBBPF_API int libbpf_attach_type_by_name(const char *name,
103 enum bpf_attach_type *attach_type);
106 104
107/* Accessors of bpf_program */ 105/* Accessors of bpf_program */
108struct bpf_program; 106struct bpf_program;
109struct bpf_program *bpf_program__next(struct bpf_program *prog, 107LIBBPF_API struct bpf_program *bpf_program__next(struct bpf_program *prog,
110 struct bpf_object *obj); 108 struct bpf_object *obj);
111 109
112#define bpf_object__for_each_program(pos, obj) \ 110#define bpf_object__for_each_program(pos, obj) \
113 for ((pos) = bpf_program__next(NULL, (obj)); \ 111 for ((pos) = bpf_program__next(NULL, (obj)); \
@@ -117,18 +115,24 @@ struct bpf_program *bpf_program__next(struct bpf_program *prog,
117typedef void (*bpf_program_clear_priv_t)(struct bpf_program *, 115typedef void (*bpf_program_clear_priv_t)(struct bpf_program *,
118 void *); 116 void *);
119 117
120int bpf_program__set_priv(struct bpf_program *prog, void *priv, 118LIBBPF_API int bpf_program__set_priv(struct bpf_program *prog, void *priv,
121 bpf_program_clear_priv_t clear_priv); 119 bpf_program_clear_priv_t clear_priv);
122 120
123void *bpf_program__priv(struct bpf_program *prog); 121LIBBPF_API void *bpf_program__priv(struct bpf_program *prog);
124void bpf_program__set_ifindex(struct bpf_program *prog, __u32 ifindex); 122LIBBPF_API void bpf_program__set_ifindex(struct bpf_program *prog,
123 __u32 ifindex);
125 124
126const char *bpf_program__title(struct bpf_program *prog, bool needs_copy); 125LIBBPF_API const char *bpf_program__title(struct bpf_program *prog,
126 bool needs_copy);
127 127
128int bpf_program__fd(struct bpf_program *prog); 128LIBBPF_API int bpf_program__load(struct bpf_program *prog, char *license,
129int bpf_program__pin_instance(struct bpf_program *prog, const char *path, 129 __u32 kern_version);
130 int instance); 130LIBBPF_API int bpf_program__fd(struct bpf_program *prog);
131int bpf_program__pin(struct bpf_program *prog, const char *path); 131LIBBPF_API int bpf_program__pin_instance(struct bpf_program *prog,
132 const char *path,
133 int instance);
134LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path);
135LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
132 136
133struct bpf_insn; 137struct bpf_insn;
134 138
@@ -189,34 +193,36 @@ typedef int (*bpf_program_prep_t)(struct bpf_program *prog, int n,
189 struct bpf_insn *insns, int insns_cnt, 193 struct bpf_insn *insns, int insns_cnt,
190 struct bpf_prog_prep_result *res); 194 struct bpf_prog_prep_result *res);
191 195
192int bpf_program__set_prep(struct bpf_program *prog, int nr_instance, 196LIBBPF_API int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
193 bpf_program_prep_t prep); 197 bpf_program_prep_t prep);
194 198
195int bpf_program__nth_fd(struct bpf_program *prog, int n); 199LIBBPF_API int bpf_program__nth_fd(struct bpf_program *prog, int n);
196 200
197/* 201/*
198 * Adjust type of BPF program. Default is kprobe. 202 * Adjust type of BPF program. Default is kprobe.
199 */ 203 */
200int bpf_program__set_socket_filter(struct bpf_program *prog); 204LIBBPF_API int bpf_program__set_socket_filter(struct bpf_program *prog);
201int bpf_program__set_tracepoint(struct bpf_program *prog); 205LIBBPF_API int bpf_program__set_tracepoint(struct bpf_program *prog);
202int bpf_program__set_raw_tracepoint(struct bpf_program *prog); 206LIBBPF_API int bpf_program__set_raw_tracepoint(struct bpf_program *prog);
203int bpf_program__set_kprobe(struct bpf_program *prog); 207LIBBPF_API int bpf_program__set_kprobe(struct bpf_program *prog);
204int bpf_program__set_sched_cls(struct bpf_program *prog); 208LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
205int bpf_program__set_sched_act(struct bpf_program *prog); 209LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
206int bpf_program__set_xdp(struct bpf_program *prog); 210LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
207int bpf_program__set_perf_event(struct bpf_program *prog); 211LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
208void bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type); 212LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
209void bpf_program__set_expected_attach_type(struct bpf_program *prog, 213 enum bpf_prog_type type);
210 enum bpf_attach_type type); 214LIBBPF_API void
211 215bpf_program__set_expected_attach_type(struct bpf_program *prog,
212bool bpf_program__is_socket_filter(struct bpf_program *prog); 216 enum bpf_attach_type type);
213bool bpf_program__is_tracepoint(struct bpf_program *prog); 217
214bool bpf_program__is_raw_tracepoint(struct bpf_program *prog); 218LIBBPF_API bool bpf_program__is_socket_filter(struct bpf_program *prog);
215bool bpf_program__is_kprobe(struct bpf_program *prog); 219LIBBPF_API bool bpf_program__is_tracepoint(struct bpf_program *prog);
216bool bpf_program__is_sched_cls(struct bpf_program *prog); 220LIBBPF_API bool bpf_program__is_raw_tracepoint(struct bpf_program *prog);
217bool bpf_program__is_sched_act(struct bpf_program *prog); 221LIBBPF_API bool bpf_program__is_kprobe(struct bpf_program *prog);
218bool bpf_program__is_xdp(struct bpf_program *prog); 222LIBBPF_API bool bpf_program__is_sched_cls(struct bpf_program *prog);
219bool bpf_program__is_perf_event(struct bpf_program *prog); 223LIBBPF_API bool bpf_program__is_sched_act(struct bpf_program *prog);
224LIBBPF_API bool bpf_program__is_xdp(struct bpf_program *prog);
225LIBBPF_API bool bpf_program__is_perf_event(struct bpf_program *prog);
220 226
221/* 227/*
222 * No need for __attribute__((packed)), all members of 'bpf_map_def' 228 * No need for __attribute__((packed)), all members of 'bpf_map_def'
@@ -237,39 +243,39 @@ struct bpf_map_def {
237 * so no need to worry about a name clash. 243 * so no need to worry about a name clash.
238 */ 244 */
239struct bpf_map; 245struct bpf_map;
240struct bpf_map * 246LIBBPF_API struct bpf_map *
241bpf_object__find_map_by_name(struct bpf_object *obj, const char *name); 247bpf_object__find_map_by_name(struct bpf_object *obj, const char *name);
242 248
243/* 249/*
244 * Get bpf_map through the offset of corresponding struct bpf_map_def 250 * Get bpf_map through the offset of corresponding struct bpf_map_def
245 * in the BPF object file. 251 * in the BPF object file.
246 */ 252 */
247struct bpf_map * 253LIBBPF_API struct bpf_map *
248bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset); 254bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset);
249 255
250struct bpf_map * 256LIBBPF_API struct bpf_map *
251bpf_map__next(struct bpf_map *map, struct bpf_object *obj); 257bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
252#define bpf_map__for_each(pos, obj) \ 258#define bpf_map__for_each(pos, obj) \
253 for ((pos) = bpf_map__next(NULL, (obj)); \ 259 for ((pos) = bpf_map__next(NULL, (obj)); \
254 (pos) != NULL; \ 260 (pos) != NULL; \
255 (pos) = bpf_map__next((pos), (obj))) 261 (pos) = bpf_map__next((pos), (obj)))
256 262
257int bpf_map__fd(struct bpf_map *map); 263LIBBPF_API int bpf_map__fd(struct bpf_map *map);
258const struct bpf_map_def *bpf_map__def(struct bpf_map *map); 264LIBBPF_API const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
259const char *bpf_map__name(struct bpf_map *map); 265LIBBPF_API const char *bpf_map__name(struct bpf_map *map);
260__u32 bpf_map__btf_key_type_id(const struct bpf_map *map); 266LIBBPF_API __u32 bpf_map__btf_key_type_id(const struct bpf_map *map);
261__u32 bpf_map__btf_value_type_id(const struct bpf_map *map); 267LIBBPF_API __u32 bpf_map__btf_value_type_id(const struct bpf_map *map);
262 268
263typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); 269typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
264int bpf_map__set_priv(struct bpf_map *map, void *priv, 270LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
265 bpf_map_clear_priv_t clear_priv); 271 bpf_map_clear_priv_t clear_priv);
266void *bpf_map__priv(struct bpf_map *map); 272LIBBPF_API void *bpf_map__priv(struct bpf_map *map);
267int bpf_map__reuse_fd(struct bpf_map *map, int fd); 273LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
268bool bpf_map__is_offload_neutral(struct bpf_map *map); 274LIBBPF_API bool bpf_map__is_offload_neutral(struct bpf_map *map);
269void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex); 275LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
270int bpf_map__pin(struct bpf_map *map, const char *path); 276LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path);
271 277
272long libbpf_get_error(const void *ptr); 278LIBBPF_API long libbpf_get_error(const void *ptr);
273 279
274struct bpf_prog_load_attr { 280struct bpf_prog_load_attr {
275 const char *file; 281 const char *file;
@@ -278,12 +284,12 @@ struct bpf_prog_load_attr {
278 int ifindex; 284 int ifindex;
279}; 285};
280 286
281int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr, 287LIBBPF_API int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
282 struct bpf_object **pobj, int *prog_fd); 288 struct bpf_object **pobj, int *prog_fd);
283int bpf_prog_load(const char *file, enum bpf_prog_type type, 289LIBBPF_API int bpf_prog_load(const char *file, enum bpf_prog_type type,
284 struct bpf_object **pobj, int *prog_fd); 290 struct bpf_object **pobj, int *prog_fd);
285 291
286int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags); 292LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
287 293
288enum bpf_perf_event_ret { 294enum bpf_perf_event_ret {
289 LIBBPF_PERF_EVENT_DONE = 0, 295 LIBBPF_PERF_EVENT_DONE = 0,
@@ -291,10 +297,24 @@ enum bpf_perf_event_ret {
291 LIBBPF_PERF_EVENT_CONT = -2, 297 LIBBPF_PERF_EVENT_CONT = -2,
292}; 298};
293 299
294typedef enum bpf_perf_event_ret (*bpf_perf_event_print_t)(void *event, 300struct perf_event_header;
295 void *priv); 301typedef enum bpf_perf_event_ret
296int bpf_perf_event_read_simple(void *mem, unsigned long size, 302 (*bpf_perf_event_print_t)(struct perf_event_header *hdr,
297 unsigned long page_size, 303 void *private_data);
298 void **buf, size_t *buf_len, 304LIBBPF_API enum bpf_perf_event_ret
299 bpf_perf_event_print_t fn, void *priv); 305bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
300#endif 306 void **copy_mem, size_t *copy_size,
307 bpf_perf_event_print_t fn, void *private_data);
308
309struct nlattr;
310typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
311int libbpf_netlink_open(unsigned int *nl_pid);
312int libbpf_nl_get_link(int sock, unsigned int nl_pid,
313 libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
314int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
315 libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie);
316int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
317 libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie);
318int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
319 libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
320#endif /* __LIBBPF_LIBBPF_H */
diff --git a/tools/lib/bpf/libbpf_errno.c b/tools/lib/bpf/libbpf_errno.c
index d9ba851bd7f9..d83b17f8435c 100644
--- a/tools/lib/bpf/libbpf_errno.c
+++ b/tools/lib/bpf/libbpf_errno.c
@@ -1,23 +1,10 @@
1// SPDX-License-Identifier: LGPL-2.1 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 2
3/* 3/*
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 * Copyright (C) 2017 Nicira, Inc. 7 * Copyright (C) 2017 Nicira, Inc.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation;
12 * version 2.1 of the License (not later!)
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, see <http://www.gnu.org/licenses>
21 */ 8 */
22 9
23#include <stdio.h> 10#include <stdio.h>
@@ -42,6 +29,7 @@ static const char *libbpf_strerror_table[NR_ERRNO] = {
42 [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", 29 [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type",
43 [ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message", 30 [ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message",
44 [ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence", 31 [ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence",
32 [ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing",
45}; 33};
46 34
47int libbpf_strerror(int err, char *buf, size_t size) 35int libbpf_strerror(int err, char *buf, size_t size)
diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c
new file mode 100644
index 000000000000..0ce67aea8f3b
--- /dev/null
+++ b/tools/lib/bpf/netlink.c
@@ -0,0 +1,337 @@
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2/* Copyright (c) 2018 Facebook */
3
4#include <stdlib.h>
5#include <memory.h>
6#include <unistd.h>
7#include <linux/bpf.h>
8#include <linux/rtnetlink.h>
9#include <sys/socket.h>
10#include <errno.h>
11#include <time.h>
12
13#include "bpf.h"
14#include "libbpf.h"
15#include "nlattr.h"
16
17#ifndef SOL_NETLINK
18#define SOL_NETLINK 270
19#endif
20
21typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t,
22 void *cookie);
23
24int libbpf_netlink_open(__u32 *nl_pid)
25{
26 struct sockaddr_nl sa;
27 socklen_t addrlen;
28 int one = 1, ret;
29 int sock;
30
31 memset(&sa, 0, sizeof(sa));
32 sa.nl_family = AF_NETLINK;
33
34 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
35 if (sock < 0)
36 return -errno;
37
38 if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
39 &one, sizeof(one)) < 0) {
40 fprintf(stderr, "Netlink error reporting not supported\n");
41 }
42
43 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
44 ret = -errno;
45 goto cleanup;
46 }
47
48 addrlen = sizeof(sa);
49 if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
50 ret = -errno;
51 goto cleanup;
52 }
53
54 if (addrlen != sizeof(sa)) {
55 ret = -LIBBPF_ERRNO__INTERNAL;
56 goto cleanup;
57 }
58
59 *nl_pid = sa.nl_pid;
60 return sock;
61
62cleanup:
63 close(sock);
64 return ret;
65}
66
67static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq,
68 __dump_nlmsg_t _fn, libbpf_dump_nlmsg_t fn,
69 void *cookie)
70{
71 bool multipart = true;
72 struct nlmsgerr *err;
73 struct nlmsghdr *nh;
74 char buf[4096];
75 int len, ret;
76
77 while (multipart) {
78 multipart = false;
79 len = recv(sock, buf, sizeof(buf), 0);
80 if (len < 0) {
81 ret = -errno;
82 goto done;
83 }
84
85 if (len == 0)
86 break;
87
88 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
89 nh = NLMSG_NEXT(nh, len)) {
90 if (nh->nlmsg_pid != nl_pid) {
91 ret = -LIBBPF_ERRNO__WRNGPID;
92 goto done;
93 }
94 if (nh->nlmsg_seq != seq) {
95 ret = -LIBBPF_ERRNO__INVSEQ;
96 goto done;
97 }
98 if (nh->nlmsg_flags & NLM_F_MULTI)
99 multipart = true;
100 switch (nh->nlmsg_type) {
101 case NLMSG_ERROR:
102 err = (struct nlmsgerr *)NLMSG_DATA(nh);
103 if (!err->error)
104 continue;
105 ret = err->error;
106 libbpf_nla_dump_errormsg(nh);
107 goto done;
108 case NLMSG_DONE:
109 return 0;
110 default:
111 break;
112 }
113 if (_fn) {
114 ret = _fn(nh, fn, cookie);
115 if (ret)
116 return ret;
117 }
118 }
119 }
120 ret = 0;
121done:
122 return ret;
123}
124
125int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
126{
127 int sock, seq = 0, ret;
128 struct nlattr *nla, *nla_xdp;
129 struct {
130 struct nlmsghdr nh;
131 struct ifinfomsg ifinfo;
132 char attrbuf[64];
133 } req;
134 __u32 nl_pid;
135
136 sock = libbpf_netlink_open(&nl_pid);
137 if (sock < 0)
138 return sock;
139
140 memset(&req, 0, sizeof(req));
141 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
142 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
143 req.nh.nlmsg_type = RTM_SETLINK;
144 req.nh.nlmsg_pid = 0;
145 req.nh.nlmsg_seq = ++seq;
146 req.ifinfo.ifi_family = AF_UNSPEC;
147 req.ifinfo.ifi_index = ifindex;
148
149 /* started nested attribute for XDP */
150 nla = (struct nlattr *)(((char *)&req)
151 + NLMSG_ALIGN(req.nh.nlmsg_len));
152 nla->nla_type = NLA_F_NESTED | IFLA_XDP;
153 nla->nla_len = NLA_HDRLEN;
154
155 /* add XDP fd */
156 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
157 nla_xdp->nla_type = IFLA_XDP_FD;
158 nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
159 memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
160 nla->nla_len += nla_xdp->nla_len;
161
162 /* if user passed in any flags, add those too */
163 if (flags) {
164 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
165 nla_xdp->nla_type = IFLA_XDP_FLAGS;
166 nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
167 memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
168 nla->nla_len += nla_xdp->nla_len;
169 }
170
171 req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
172
173 if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
174 ret = -errno;
175 goto cleanup;
176 }
177 ret = bpf_netlink_recv(sock, nl_pid, seq, NULL, NULL, NULL);
178
179cleanup:
180 close(sock);
181 return ret;
182}
183
184static int __dump_link_nlmsg(struct nlmsghdr *nlh,
185 libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
186{
187 struct nlattr *tb[IFLA_MAX + 1], *attr;
188 struct ifinfomsg *ifi = NLMSG_DATA(nlh);
189 int len;
190
191 len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
192 attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
193 if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0)
194 return -LIBBPF_ERRNO__NLPARSE;
195
196 return dump_link_nlmsg(cookie, ifi, tb);
197}
198
199int libbpf_nl_get_link(int sock, unsigned int nl_pid,
200 libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
201{
202 struct {
203 struct nlmsghdr nlh;
204 struct ifinfomsg ifm;
205 } req = {
206 .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
207 .nlh.nlmsg_type = RTM_GETLINK,
208 .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
209 .ifm.ifi_family = AF_PACKET,
210 };
211 int seq = time(NULL);
212
213 req.nlh.nlmsg_seq = seq;
214 if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
215 return -errno;
216
217 return bpf_netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg,
218 dump_link_nlmsg, cookie);
219}
220
221static int __dump_class_nlmsg(struct nlmsghdr *nlh,
222 libbpf_dump_nlmsg_t dump_class_nlmsg,
223 void *cookie)
224{
225 struct nlattr *tb[TCA_MAX + 1], *attr;
226 struct tcmsg *t = NLMSG_DATA(nlh);
227 int len;
228
229 len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
230 attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
231 if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
232 return -LIBBPF_ERRNO__NLPARSE;
233
234 return dump_class_nlmsg(cookie, t, tb);
235}
236
237int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
238 libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie)
239{
240 struct {
241 struct nlmsghdr nlh;
242 struct tcmsg t;
243 } req = {
244 .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
245 .nlh.nlmsg_type = RTM_GETTCLASS,
246 .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
247 .t.tcm_family = AF_UNSPEC,
248 .t.tcm_ifindex = ifindex,
249 };
250 int seq = time(NULL);
251
252 req.nlh.nlmsg_seq = seq;
253 if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
254 return -errno;
255
256 return bpf_netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg,
257 dump_class_nlmsg, cookie);
258}
259
260static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh,
261 libbpf_dump_nlmsg_t dump_qdisc_nlmsg,
262 void *cookie)
263{
264 struct nlattr *tb[TCA_MAX + 1], *attr;
265 struct tcmsg *t = NLMSG_DATA(nlh);
266 int len;
267
268 len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
269 attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
270 if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
271 return -LIBBPF_ERRNO__NLPARSE;
272
273 return dump_qdisc_nlmsg(cookie, t, tb);
274}
275
276int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
277 libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie)
278{
279 struct {
280 struct nlmsghdr nlh;
281 struct tcmsg t;
282 } req = {
283 .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
284 .nlh.nlmsg_type = RTM_GETQDISC,
285 .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
286 .t.tcm_family = AF_UNSPEC,
287 .t.tcm_ifindex = ifindex,
288 };
289 int seq = time(NULL);
290
291 req.nlh.nlmsg_seq = seq;
292 if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
293 return -errno;
294
295 return bpf_netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg,
296 dump_qdisc_nlmsg, cookie);
297}
298
299static int __dump_filter_nlmsg(struct nlmsghdr *nlh,
300 libbpf_dump_nlmsg_t dump_filter_nlmsg,
301 void *cookie)
302{
303 struct nlattr *tb[TCA_MAX + 1], *attr;
304 struct tcmsg *t = NLMSG_DATA(nlh);
305 int len;
306
307 len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
308 attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
309 if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
310 return -LIBBPF_ERRNO__NLPARSE;
311
312 return dump_filter_nlmsg(cookie, t, tb);
313}
314
315int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
316 libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie)
317{
318 struct {
319 struct nlmsghdr nlh;
320 struct tcmsg t;
321 } req = {
322 .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
323 .nlh.nlmsg_type = RTM_GETTFILTER,
324 .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
325 .t.tcm_family = AF_UNSPEC,
326 .t.tcm_ifindex = ifindex,
327 .t.tcm_parent = handle,
328 };
329 int seq = time(NULL);
330
331 req.nlh.nlmsg_seq = seq;
332 if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
333 return -errno;
334
335 return bpf_netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg,
336 dump_filter_nlmsg, cookie);
337}
diff --git a/tools/lib/bpf/nlattr.c b/tools/lib/bpf/nlattr.c
index 4719434278b2..1e69c0c8d413 100644
--- a/tools/lib/bpf/nlattr.c
+++ b/tools/lib/bpf/nlattr.c
@@ -1,13 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 2
3/* 3/*
4 * NETLINK Netlink attributes 4 * NETLINK Netlink attributes
5 * 5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation version 2.1
9 * of the License.
10 *
11 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch> 6 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
12 */ 7 */
13 8
@@ -17,20 +12,15 @@
17#include <string.h> 12#include <string.h>
18#include <stdio.h> 13#include <stdio.h>
19 14
20static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { 15static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = {
21 [NLA_U8] = sizeof(uint8_t), 16 [LIBBPF_NLA_U8] = sizeof(uint8_t),
22 [NLA_U16] = sizeof(uint16_t), 17 [LIBBPF_NLA_U16] = sizeof(uint16_t),
23 [NLA_U32] = sizeof(uint32_t), 18 [LIBBPF_NLA_U32] = sizeof(uint32_t),
24 [NLA_U64] = sizeof(uint64_t), 19 [LIBBPF_NLA_U64] = sizeof(uint64_t),
25 [NLA_STRING] = 1, 20 [LIBBPF_NLA_STRING] = 1,
26 [NLA_FLAG] = 0, 21 [LIBBPF_NLA_FLAG] = 0,
27}; 22};
28 23
29static int nla_len(const struct nlattr *nla)
30{
31 return nla->nla_len - NLA_HDRLEN;
32}
33
34static struct nlattr *nla_next(const struct nlattr *nla, int *remaining) 24static struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
35{ 25{
36 int totlen = NLA_ALIGN(nla->nla_len); 26 int totlen = NLA_ALIGN(nla->nla_len);
@@ -46,20 +36,15 @@ static int nla_ok(const struct nlattr *nla, int remaining)
46 nla->nla_len <= remaining; 36 nla->nla_len <= remaining;
47} 37}
48 38
49static void *nla_data(const struct nlattr *nla)
50{
51 return (char *) nla + NLA_HDRLEN;
52}
53
54static int nla_type(const struct nlattr *nla) 39static int nla_type(const struct nlattr *nla)
55{ 40{
56 return nla->nla_type & NLA_TYPE_MASK; 41 return nla->nla_type & NLA_TYPE_MASK;
57} 42}
58 43
59static int validate_nla(struct nlattr *nla, int maxtype, 44static int validate_nla(struct nlattr *nla, int maxtype,
60 struct nla_policy *policy) 45 struct libbpf_nla_policy *policy)
61{ 46{
62 struct nla_policy *pt; 47 struct libbpf_nla_policy *pt;
63 unsigned int minlen = 0; 48 unsigned int minlen = 0;
64 int type = nla_type(nla); 49 int type = nla_type(nla);
65 50
@@ -68,23 +53,24 @@ static int validate_nla(struct nlattr *nla, int maxtype,
68 53
69 pt = &policy[type]; 54 pt = &policy[type];
70 55
71 if (pt->type > NLA_TYPE_MAX) 56 if (pt->type > LIBBPF_NLA_TYPE_MAX)
72 return 0; 57 return 0;
73 58
74 if (pt->minlen) 59 if (pt->minlen)
75 minlen = pt->minlen; 60 minlen = pt->minlen;
76 else if (pt->type != NLA_UNSPEC) 61 else if (pt->type != LIBBPF_NLA_UNSPEC)
77 minlen = nla_attr_minlen[pt->type]; 62 minlen = nla_attr_minlen[pt->type];
78 63
79 if (nla_len(nla) < minlen) 64 if (libbpf_nla_len(nla) < minlen)
80 return -1; 65 return -1;
81 66
82 if (pt->maxlen && nla_len(nla) > pt->maxlen) 67 if (pt->maxlen && libbpf_nla_len(nla) > pt->maxlen)
83 return -1; 68 return -1;
84 69
85 if (pt->type == NLA_STRING) { 70 if (pt->type == LIBBPF_NLA_STRING) {
86 char *data = nla_data(nla); 71 char *data = libbpf_nla_data(nla);
87 if (data[nla_len(nla) - 1] != '\0') 72
73 if (data[libbpf_nla_len(nla) - 1] != '\0')
88 return -1; 74 return -1;
89 } 75 }
90 76
@@ -114,15 +100,15 @@ static inline int nlmsg_len(const struct nlmsghdr *nlh)
114 * @see nla_validate 100 * @see nla_validate
115 * @return 0 on success or a negative error code. 101 * @return 0 on success or a negative error code.
116 */ 102 */
117static int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, 103int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
118 struct nla_policy *policy) 104 int len, struct libbpf_nla_policy *policy)
119{ 105{
120 struct nlattr *nla; 106 struct nlattr *nla;
121 int rem, err; 107 int rem, err;
122 108
123 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 109 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
124 110
125 nla_for_each_attr(nla, head, len, rem) { 111 libbpf_nla_for_each_attr(nla, head, len, rem) {
126 int type = nla_type(nla); 112 int type = nla_type(nla);
127 113
128 if (type > maxtype) 114 if (type > maxtype)
@@ -146,12 +132,33 @@ errout:
146 return err; 132 return err;
147} 133}
148 134
135/**
136 * Create attribute index based on nested attribute
137 * @arg tb Index array to be filled (maxtype+1 elements).
138 * @arg maxtype Maximum attribute type expected and accepted.
139 * @arg nla Nested Attribute.
140 * @arg policy Attribute validation policy.
141 *
142 * Feeds the stream of attributes nested into the specified attribute
143 * to libbpf_nla_parse().
144 *
145 * @see libbpf_nla_parse
146 * @return 0 on success or a negative error code.
147 */
148int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
149 struct nlattr *nla,
150 struct libbpf_nla_policy *policy)
151{
152 return libbpf_nla_parse(tb, maxtype, libbpf_nla_data(nla),
153 libbpf_nla_len(nla), policy);
154}
155
149/* dump netlink extended ack error message */ 156/* dump netlink extended ack error message */
150int nla_dump_errormsg(struct nlmsghdr *nlh) 157int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh)
151{ 158{
152 struct nla_policy extack_policy[NLMSGERR_ATTR_MAX + 1] = { 159 struct libbpf_nla_policy extack_policy[NLMSGERR_ATTR_MAX + 1] = {
153 [NLMSGERR_ATTR_MSG] = { .type = NLA_STRING }, 160 [NLMSGERR_ATTR_MSG] = { .type = LIBBPF_NLA_STRING },
154 [NLMSGERR_ATTR_OFFS] = { .type = NLA_U32 }, 161 [NLMSGERR_ATTR_OFFS] = { .type = LIBBPF_NLA_U32 },
155 }; 162 };
156 struct nlattr *tb[NLMSGERR_ATTR_MAX + 1], *attr; 163 struct nlattr *tb[NLMSGERR_ATTR_MAX + 1], *attr;
157 struct nlmsgerr *err; 164 struct nlmsgerr *err;
@@ -172,14 +179,15 @@ int nla_dump_errormsg(struct nlmsghdr *nlh)
172 attr = (struct nlattr *) ((void *) err + hlen); 179 attr = (struct nlattr *) ((void *) err + hlen);
173 alen = nlh->nlmsg_len - hlen; 180 alen = nlh->nlmsg_len - hlen;
174 181
175 if (nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen, extack_policy) != 0) { 182 if (libbpf_nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen,
183 extack_policy) != 0) {
176 fprintf(stderr, 184 fprintf(stderr,
177 "Failed to parse extended error attributes\n"); 185 "Failed to parse extended error attributes\n");
178 return 0; 186 return 0;
179 } 187 }
180 188
181 if (tb[NLMSGERR_ATTR_MSG]) 189 if (tb[NLMSGERR_ATTR_MSG])
182 errmsg = (char *) nla_data(tb[NLMSGERR_ATTR_MSG]); 190 errmsg = (char *) libbpf_nla_data(tb[NLMSGERR_ATTR_MSG]);
183 191
184 fprintf(stderr, "Kernel error message: %s\n", errmsg); 192 fprintf(stderr, "Kernel error message: %s\n", errmsg);
185 193
diff --git a/tools/lib/bpf/nlattr.h b/tools/lib/bpf/nlattr.h
index 931a71f68f93..6cc3ac91690f 100644
--- a/tools/lib/bpf/nlattr.h
+++ b/tools/lib/bpf/nlattr.h
@@ -1,18 +1,13 @@
1/* SPDX-License-Identifier: LGPL-2.1 */ 1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 2
3/* 3/*
4 * NETLINK Netlink attributes 4 * NETLINK Netlink attributes
5 * 5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation version 2.1
9 * of the License.
10 *
11 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch> 6 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
12 */ 7 */
13 8
14#ifndef __NLATTR_H 9#ifndef __LIBBPF_NLATTR_H
15#define __NLATTR_H 10#define __LIBBPF_NLATTR_H
16 11
17#include <stdint.h> 12#include <stdint.h>
18#include <linux/netlink.h> 13#include <linux/netlink.h>
@@ -23,19 +18,19 @@
23 * Standard attribute types to specify validation policy 18 * Standard attribute types to specify validation policy
24 */ 19 */
25enum { 20enum {
26 NLA_UNSPEC, /**< Unspecified type, binary data chunk */ 21 LIBBPF_NLA_UNSPEC, /**< Unspecified type, binary data chunk */
27 NLA_U8, /**< 8 bit integer */ 22 LIBBPF_NLA_U8, /**< 8 bit integer */
28 NLA_U16, /**< 16 bit integer */ 23 LIBBPF_NLA_U16, /**< 16 bit integer */
29 NLA_U32, /**< 32 bit integer */ 24 LIBBPF_NLA_U32, /**< 32 bit integer */
30 NLA_U64, /**< 64 bit integer */ 25 LIBBPF_NLA_U64, /**< 64 bit integer */
31 NLA_STRING, /**< NUL terminated character string */ 26 LIBBPF_NLA_STRING, /**< NUL terminated character string */
32 NLA_FLAG, /**< Flag */ 27 LIBBPF_NLA_FLAG, /**< Flag */
33 NLA_MSECS, /**< Micro seconds (64bit) */ 28 LIBBPF_NLA_MSECS, /**< Micro seconds (64bit) */
34 NLA_NESTED, /**< Nested attributes */ 29 LIBBPF_NLA_NESTED, /**< Nested attributes */
35 __NLA_TYPE_MAX, 30 __LIBBPF_NLA_TYPE_MAX,
36}; 31};
37 32
38#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) 33#define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1)
39 34
40/** 35/**
41 * @ingroup attr 36 * @ingroup attr
@@ -43,8 +38,8 @@ enum {
43 * 38 *
44 * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. 39 * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
45 */ 40 */
46struct nla_policy { 41struct libbpf_nla_policy {
47 /** Type of attribute or NLA_UNSPEC */ 42 /** Type of attribute or LIBBPF_NLA_UNSPEC */
48 uint16_t type; 43 uint16_t type;
49 44
50 /** Minimal length of payload required */ 45 /** Minimal length of payload required */
@@ -62,11 +57,50 @@ struct nla_policy {
62 * @arg len length of attribute stream 57 * @arg len length of attribute stream
63 * @arg rem initialized to len, holds bytes currently remaining in stream 58 * @arg rem initialized to len, holds bytes currently remaining in stream
64 */ 59 */
65#define nla_for_each_attr(pos, head, len, rem) \ 60#define libbpf_nla_for_each_attr(pos, head, len, rem) \
66 for (pos = head, rem = len; \ 61 for (pos = head, rem = len; \
67 nla_ok(pos, rem); \ 62 nla_ok(pos, rem); \
68 pos = nla_next(pos, &(rem))) 63 pos = nla_next(pos, &(rem)))
69 64
70int nla_dump_errormsg(struct nlmsghdr *nlh); 65/**
66 * libbpf_nla_data - head of payload
67 * @nla: netlink attribute
68 */
69static inline void *libbpf_nla_data(const struct nlattr *nla)
70{
71 return (char *) nla + NLA_HDRLEN;
72}
73
74static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla)
75{
76 return *(uint8_t *)libbpf_nla_data(nla);
77}
78
79static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla)
80{
81 return *(uint32_t *)libbpf_nla_data(nla);
82}
83
84static inline const char *libbpf_nla_getattr_str(const struct nlattr *nla)
85{
86 return (const char *)libbpf_nla_data(nla);
87}
88
89/**
90 * libbpf_nla_len - length of payload
91 * @nla: netlink attribute
92 */
93static inline int libbpf_nla_len(const struct nlattr *nla)
94{
95 return nla->nla_len - NLA_HDRLEN;
96}
97
98int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
99 int len, struct libbpf_nla_policy *policy);
100int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
101 struct nlattr *nla,
102 struct libbpf_nla_policy *policy);
103
104int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh);
71 105
72#endif /* __NLATTR_H */ 106#endif /* __LIBBPF_NLATTR_H */
diff --git a/tools/lib/bpf/str_error.c b/tools/lib/bpf/str_error.c
index b8798114a357..00e48ac5b806 100644
--- a/tools/lib/bpf/str_error.c
+++ b/tools/lib/bpf/str_error.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: LGPL-2.1 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2#undef _GNU_SOURCE 2#undef _GNU_SOURCE
3#include <string.h> 3#include <string.h>
4#include <stdio.h> 4#include <stdio.h>
@@ -9,7 +9,7 @@
9 * libc, while checking strerror_r() return to avoid having to check this in 9 * libc, while checking strerror_r() return to avoid having to check this in
10 * all places calling it. 10 * all places calling it.
11 */ 11 */
12char *str_error(int err, char *dst, int len) 12char *libbpf_strerror_r(int err, char *dst, int len)
13{ 13{
14 int ret = strerror_r(err, dst, len); 14 int ret = strerror_r(err, dst, len);
15 if (ret) 15 if (ret)
diff --git a/tools/lib/bpf/str_error.h b/tools/lib/bpf/str_error.h
index 355b1db571d1..a139334d57b6 100644
--- a/tools/lib/bpf/str_error.h
+++ b/tools/lib/bpf/str_error.h
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: LGPL-2.1 1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2#ifndef BPF_STR_ERROR 2#ifndef __LIBBPF_STR_ERROR_H
3#define BPF_STR_ERROR 3#define __LIBBPF_STR_ERROR_H
4 4
5char *str_error(int err, char *dst, int len); 5char *libbpf_strerror_r(int err, char *dst, int len);
6#endif // BPF_STR_ERROR 6#endif /* __LIBBPF_STR_ERROR_H */
diff --git a/tools/pci/Build b/tools/pci/Build
new file mode 100644
index 000000000000..c375aea21790
--- /dev/null
+++ b/tools/pci/Build
@@ -0,0 +1 @@
pcitest-y += pcitest.o
diff --git a/tools/pci/Makefile b/tools/pci/Makefile
new file mode 100644
index 000000000000..46e4c2f318c9
--- /dev/null
+++ b/tools/pci/Makefile
@@ -0,0 +1,53 @@
1# SPDX-License-Identifier: GPL-2.0
2include ../scripts/Makefile.include
3
4bindir ?= /usr/bin
5
6ifeq ($(srctree),)
7srctree := $(patsubst %/,%,$(dir $(CURDIR)))
8srctree := $(patsubst %/,%,$(dir $(srctree)))
9endif
10
11# Do not use make's built-in rules
12# (this improves performance and avoids hard-to-debug behaviour);
13MAKEFLAGS += -r
14
15CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
16
17ALL_TARGETS := pcitest pcitest.sh
18ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
19
20all: $(ALL_PROGRAMS)
21
22export srctree OUTPUT CC LD CFLAGS
23include $(srctree)/tools/build/Makefile.include
24
25#
26# We need the following to be outside of kernel tree
27#
28$(OUTPUT)include/linux/: ../../include/uapi/linux/
29 mkdir -p $(OUTPUT)include/linux/ 2>&1 || true
30 ln -sf $(CURDIR)/../../include/uapi/linux/pcitest.h $@
31
32prepare: $(OUTPUT)include/linux/
33
34PCITEST_IN := $(OUTPUT)pcitest-in.o
35$(PCITEST_IN): prepare FORCE
36 $(Q)$(MAKE) $(build)=pcitest
37$(OUTPUT)pcitest: $(PCITEST_IN)
38 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
39
40clean:
41 rm -f $(ALL_PROGRAMS)
42 rm -rf $(OUTPUT)include/
43 find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
44
45install: $(ALL_PROGRAMS)
46 install -d -m 755 $(DESTDIR)$(bindir); \
47 for program in $(ALL_PROGRAMS); do \
48 install $$program $(DESTDIR)$(bindir); \
49 done
50
51FORCE:
52
53.PHONY: all install clean FORCE prepare
diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c
index af146bb03b4d..ec4d51f3308b 100644
--- a/tools/pci/pcitest.c
+++ b/tools/pci/pcitest.c
@@ -23,7 +23,6 @@
23#include <stdio.h> 23#include <stdio.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include <sys/ioctl.h> 25#include <sys/ioctl.h>
26#include <time.h>
27#include <unistd.h> 26#include <unistd.h>
28 27
29#include <linux/pcitest.h> 28#include <linux/pcitest.h>
@@ -48,17 +47,15 @@ struct pci_test {
48 unsigned long size; 47 unsigned long size;
49}; 48};
50 49
51static int run_test(struct pci_test *test) 50static void run_test(struct pci_test *test)
52{ 51{
53 long ret; 52 long ret;
54 int fd; 53 int fd;
55 struct timespec start, end;
56 double time;
57 54
58 fd = open(test->device, O_RDWR); 55 fd = open(test->device, O_RDWR);
59 if (fd < 0) { 56 if (fd < 0) {
60 perror("can't open PCI Endpoint Test device"); 57 perror("can't open PCI Endpoint Test device");
61 return fd; 58 return;
62 } 59 }
63 60
64 if (test->barnum >= 0 && test->barnum <= 5) { 61 if (test->barnum >= 0 && test->barnum <= 5) {
diff --git a/tools/perf/arch/powerpc/util/book3s_hv_exits.h b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
index 853b95d1e139..2011376c7ab5 100644
--- a/tools/perf/arch/powerpc/util/book3s_hv_exits.h
+++ b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
@@ -15,7 +15,6 @@
15 {0x400, "INST_STORAGE"}, \ 15 {0x400, "INST_STORAGE"}, \
16 {0x480, "INST_SEGMENT"}, \ 16 {0x480, "INST_SEGMENT"}, \
17 {0x500, "EXTERNAL"}, \ 17 {0x500, "EXTERNAL"}, \
18 {0x501, "EXTERNAL_LEVEL"}, \
19 {0x502, "EXTERNAL_HV"}, \ 18 {0x502, "EXTERNAL_HV"}, \
20 {0x600, "ALIGNMENT"}, \ 19 {0x600, "ALIGNMENT"}, \
21 {0x700, "PROGRAM"}, \ 20 {0x700, "PROGRAM"}, \
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index e603314dc792..cc5e2d6d17a9 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -4,7 +4,7 @@
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/refcount.h> 5#include <linux/refcount.h>
6#include <linux/types.h> 6#include <linux/types.h>
7#include <asm/barrier.h> 7#include <linux/ring_buffer.h>
8#include <stdbool.h> 8#include <stdbool.h>
9#include "auxtrace.h" 9#include "auxtrace.h"
10#include "event.h" 10#include "event.h"
@@ -71,21 +71,12 @@ void perf_mmap__consume(struct perf_mmap *map);
71 71
72static inline u64 perf_mmap__read_head(struct perf_mmap *mm) 72static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
73{ 73{
74 struct perf_event_mmap_page *pc = mm->base; 74 return ring_buffer_read_head(mm->base);
75 u64 head = READ_ONCE(pc->data_head);
76 rmb();
77 return head;
78} 75}
79 76
80static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail) 77static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
81{ 78{
82 struct perf_event_mmap_page *pc = md->base; 79 ring_buffer_write_tail(md->base, tail);
83
84 /*
85 * ensure all reads are done before we write the tail out.
86 */
87 mb();
88 pc->data_tail = tail;
89} 80}
90 81
91union perf_event *perf_mmap__read_forward(struct perf_mmap *map); 82union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index 0392153a0009..778ceb651000 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -22,6 +22,7 @@ NVDIMM_SRC := $(DRIVERS)/nvdimm
22ACPI_SRC := $(DRIVERS)/acpi/nfit 22ACPI_SRC := $(DRIVERS)/acpi/nfit
23DAX_SRC := $(DRIVERS)/dax 23DAX_SRC := $(DRIVERS)/dax
24ccflags-y := -I$(src)/$(NVDIMM_SRC)/ 24ccflags-y := -I$(src)/$(NVDIMM_SRC)/
25ccflags-y += -I$(src)/$(ACPI_SRC)/
25 26
26obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o 27obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
27obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o 28obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
diff --git a/tools/testing/nvdimm/acpi_nfit_test.c b/tools/testing/nvdimm/acpi_nfit_test.c
index 43521512e577..fec8fb1b7715 100644
--- a/tools/testing/nvdimm/acpi_nfit_test.c
+++ b/tools/testing/nvdimm/acpi_nfit_test.c
@@ -4,5 +4,13 @@
4#include <linux/module.h> 4#include <linux/module.h>
5#include <linux/printk.h> 5#include <linux/printk.h>
6#include "watermark.h" 6#include "watermark.h"
7#include <nfit.h>
7 8
8nfit_test_watermark(acpi_nfit); 9nfit_test_watermark(acpi_nfit);
10
11/* strong / override definition of nfit_intel_shutdown_status */
12void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
13{
14 set_bit(NFIT_MEM_DIRTY_COUNT, &nfit_mem->flags);
15 nfit_mem->dirty_shutdown = 42;
16}
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index cffc2c5a778d..9527d47a1070 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -24,6 +24,7 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <nd-core.h> 26#include <nd-core.h>
27#include <intel.h>
27#include <nfit.h> 28#include <nfit.h>
28#include <nd.h> 29#include <nd.h>
29#include "nfit_test.h" 30#include "nfit_test.h"
@@ -148,6 +149,7 @@ static const struct nd_intel_smart smart_def = {
148 | ND_INTEL_SMART_ALARM_VALID 149 | ND_INTEL_SMART_ALARM_VALID
149 | ND_INTEL_SMART_USED_VALID 150 | ND_INTEL_SMART_USED_VALID
150 | ND_INTEL_SMART_SHUTDOWN_VALID 151 | ND_INTEL_SMART_SHUTDOWN_VALID
152 | ND_INTEL_SMART_SHUTDOWN_COUNT_VALID
151 | ND_INTEL_SMART_MTEMP_VALID 153 | ND_INTEL_SMART_MTEMP_VALID
152 | ND_INTEL_SMART_CTEMP_VALID, 154 | ND_INTEL_SMART_CTEMP_VALID,
153 .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH, 155 .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
@@ -160,8 +162,8 @@ static const struct nd_intel_smart smart_def = {
160 .ait_status = 1, 162 .ait_status = 1,
161 .life_used = 5, 163 .life_used = 5,
162 .shutdown_state = 0, 164 .shutdown_state = 0,
165 .shutdown_count = 42,
163 .vendor_size = 0, 166 .vendor_size = 0,
164 .shutdown_count = 100,
165}; 167};
166 168
167struct nfit_test_fw { 169struct nfit_test_fw {
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 33752e06ff8d..ade14fe3837e 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -117,30 +117,6 @@ struct nd_cmd_ars_err_inj_stat {
117#define ND_INTEL_SMART_INJECT_FATAL (1 << 2) 117#define ND_INTEL_SMART_INJECT_FATAL (1 << 2)
118#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3) 118#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3)
119 119
120struct nd_intel_smart {
121 __u32 status;
122 union {
123 struct {
124 __u32 flags;
125 __u8 reserved0[4];
126 __u8 health;
127 __u8 spares;
128 __u8 life_used;
129 __u8 alarm_flags;
130 __u16 media_temperature;
131 __u16 ctrl_temperature;
132 __u32 shutdown_count;
133 __u8 ait_status;
134 __u16 pmic_temperature;
135 __u8 reserved1[8];
136 __u8 shutdown_state;
137 __u32 vendor_size;
138 __u8 vendor_data[92];
139 } __packed;
140 __u8 data[128];
141 };
142} __packed;
143
144struct nd_intel_smart_threshold { 120struct nd_intel_smart_threshold {
145 __u32 status; 121 __u32 status;
146 union { 122 union {
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index 49938d72cf63..1b799e30c06d 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -19,3 +19,11 @@ test_btf
19test_sockmap 19test_sockmap
20test_lirc_mode2_user 20test_lirc_mode2_user
21get_cgroup_id_user 21get_cgroup_id_user
22test_skb_cgroup_id_user
23test_socket_cookie
24test_cgroup_storage
25test_select_reuseport
26test_flow_dissector
27flow_dissector_load
28test_netcnt
29test_section_names
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index fff7fb1285fc..e39dfb4e7970 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -23,7 +23,8 @@ $(TEST_CUSTOM_PROGS): $(OUTPUT)/%: %.c
23TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ 23TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
24 test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ 24 test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
25 test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \ 25 test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \
26 test_socket_cookie test_cgroup_storage test_select_reuseport 26 test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names \
27 test_netcnt
27 28
28TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 29TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
29 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ 30 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \
@@ -35,7 +36,8 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test
35 test_get_stack_rawtp.o test_sockmap_kern.o test_sockhash_kern.o \ 36 test_get_stack_rawtp.o test_sockmap_kern.o test_sockhash_kern.o \
36 test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o test_lirc_mode2_kern.o \ 37 test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o test_lirc_mode2_kern.o \
37 get_cgroup_id_kern.o socket_cookie_prog.o test_select_reuseport_kern.o \ 38 get_cgroup_id_kern.o socket_cookie_prog.o test_select_reuseport_kern.o \
38 test_skb_cgroup_id_kern.o 39 test_skb_cgroup_id_kern.o bpf_flow.o netcnt_prog.o \
40 test_sk_lookup_kern.o test_xdp_vlan.o test_queue_map.o test_stack_map.o
39 41
40# Order correspond to 'make run_tests' order 42# Order correspond to 'make run_tests' order
41TEST_PROGS := test_kmod.sh \ 43TEST_PROGS := test_kmod.sh \
@@ -47,10 +49,15 @@ TEST_PROGS := test_kmod.sh \
47 test_tunnel.sh \ 49 test_tunnel.sh \
48 test_lwt_seg6local.sh \ 50 test_lwt_seg6local.sh \
49 test_lirc_mode2.sh \ 51 test_lirc_mode2.sh \
50 test_skb_cgroup_id.sh 52 test_skb_cgroup_id.sh \
53 test_flow_dissector.sh \
54 test_xdp_vlan.sh
55
56TEST_PROGS_EXTENDED := with_addr.sh
51 57
52# Compile but not part of 'make run_tests' 58# Compile but not part of 'make run_tests'
53TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user 59TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
60 flow_dissector_load test_flow_dissector
54 61
55include ../lib.mk 62include ../lib.mk
56 63
@@ -70,6 +77,7 @@ $(OUTPUT)/test_tcpbpf_user: cgroup_helpers.c
70$(OUTPUT)/test_progs: trace_helpers.c 77$(OUTPUT)/test_progs: trace_helpers.c
71$(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c 78$(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c
72$(OUTPUT)/test_cgroup_storage: cgroup_helpers.c 79$(OUTPUT)/test_cgroup_storage: cgroup_helpers.c
80$(OUTPUT)/test_netcnt: cgroup_helpers.c
73 81
74.PHONY: force 82.PHONY: force
75 83
@@ -110,6 +118,9 @@ CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \
110$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline 118$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline
111$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline 119$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
112 120
121$(OUTPUT)/test_queue_map.o: test_queue_stack_map.h
122$(OUTPUT)/test_stack_map.o: test_queue_stack_map.h
123
113BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) 124BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
114BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) 125BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
115BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') 126BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm')
diff --git a/tools/testing/selftests/bpf/bpf_flow.c b/tools/testing/selftests/bpf/bpf_flow.c
new file mode 100644
index 000000000000..107350a7821d
--- /dev/null
+++ b/tools/testing/selftests/bpf/bpf_flow.c
@@ -0,0 +1,373 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <limits.h>
3#include <stddef.h>
4#include <stdbool.h>
5#include <string.h>
6#include <linux/pkt_cls.h>
7#include <linux/bpf.h>
8#include <linux/in.h>
9#include <linux/if_ether.h>
10#include <linux/icmp.h>
11#include <linux/ip.h>
12#include <linux/ipv6.h>
13#include <linux/tcp.h>
14#include <linux/udp.h>
15#include <linux/if_packet.h>
16#include <sys/socket.h>
17#include <linux/if_tunnel.h>
18#include <linux/mpls.h>
19#include "bpf_helpers.h"
20#include "bpf_endian.h"
21
22int _version SEC("version") = 1;
23#define PROG(F) SEC(#F) int bpf_func_##F
24
25/* These are the identifiers of the BPF programs that will be used in tail
26 * calls. Name is limited to 16 characters, with the terminating character and
27 * bpf_func_ above, we have only 6 to work with, anything after will be cropped.
28 */
29enum {
30 IP,
31 IPV6,
32 IPV6OP, /* Destination/Hop-by-Hop Options IPv6 Extension header */
33 IPV6FR, /* Fragmentation IPv6 Extension Header */
34 MPLS,
35 VLAN,
36};
37
38#define IP_MF 0x2000
39#define IP_OFFSET 0x1FFF
40#define IP6_MF 0x0001
41#define IP6_OFFSET 0xFFF8
42
43struct vlan_hdr {
44 __be16 h_vlan_TCI;
45 __be16 h_vlan_encapsulated_proto;
46};
47
48struct gre_hdr {
49 __be16 flags;
50 __be16 proto;
51};
52
53struct frag_hdr {
54 __u8 nexthdr;
55 __u8 reserved;
56 __be16 frag_off;
57 __be32 identification;
58};
59
60struct bpf_map_def SEC("maps") jmp_table = {
61 .type = BPF_MAP_TYPE_PROG_ARRAY,
62 .key_size = sizeof(__u32),
63 .value_size = sizeof(__u32),
64 .max_entries = 8
65};
66
67static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb,
68 __u16 hdr_size,
69 void *buffer)
70{
71 void *data_end = (void *)(long)skb->data_end;
72 void *data = (void *)(long)skb->data;
73 __u16 nhoff = skb->flow_keys->nhoff;
74 __u8 *hdr;
75
76 /* Verifies this variable offset does not overflow */
77 if (nhoff > (USHRT_MAX - hdr_size))
78 return NULL;
79
80 hdr = data + nhoff;
81 if (hdr + hdr_size <= data_end)
82 return hdr;
83
84 if (bpf_skb_load_bytes(skb, nhoff, buffer, hdr_size))
85 return NULL;
86
87 return buffer;
88}
89
90/* Dispatches on ETHERTYPE */
91static __always_inline int parse_eth_proto(struct __sk_buff *skb, __be16 proto)
92{
93 struct bpf_flow_keys *keys = skb->flow_keys;
94
95 keys->n_proto = proto;
96 switch (proto) {
97 case bpf_htons(ETH_P_IP):
98 bpf_tail_call(skb, &jmp_table, IP);
99 break;
100 case bpf_htons(ETH_P_IPV6):
101 bpf_tail_call(skb, &jmp_table, IPV6);
102 break;
103 case bpf_htons(ETH_P_MPLS_MC):
104 case bpf_htons(ETH_P_MPLS_UC):
105 bpf_tail_call(skb, &jmp_table, MPLS);
106 break;
107 case bpf_htons(ETH_P_8021Q):
108 case bpf_htons(ETH_P_8021AD):
109 bpf_tail_call(skb, &jmp_table, VLAN);
110 break;
111 default:
112 /* Protocol not supported */
113 return BPF_DROP;
114 }
115
116 return BPF_DROP;
117}
118
119SEC("dissect")
120int _dissect(struct __sk_buff *skb)
121{
122 if (!skb->vlan_present)
123 return parse_eth_proto(skb, skb->protocol);
124 else
125 return parse_eth_proto(skb, skb->vlan_proto);
126}
127
128/* Parses on IPPROTO_* */
129static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto)
130{
131 struct bpf_flow_keys *keys = skb->flow_keys;
132 void *data_end = (void *)(long)skb->data_end;
133 struct icmphdr *icmp, _icmp;
134 struct gre_hdr *gre, _gre;
135 struct ethhdr *eth, _eth;
136 struct tcphdr *tcp, _tcp;
137 struct udphdr *udp, _udp;
138
139 keys->ip_proto = proto;
140 switch (proto) {
141 case IPPROTO_ICMP:
142 icmp = bpf_flow_dissect_get_header(skb, sizeof(*icmp), &_icmp);
143 if (!icmp)
144 return BPF_DROP;
145 return BPF_OK;
146 case IPPROTO_IPIP:
147 keys->is_encap = true;
148 return parse_eth_proto(skb, bpf_htons(ETH_P_IP));
149 case IPPROTO_IPV6:
150 keys->is_encap = true;
151 return parse_eth_proto(skb, bpf_htons(ETH_P_IPV6));
152 case IPPROTO_GRE:
153 gre = bpf_flow_dissect_get_header(skb, sizeof(*gre), &_gre);
154 if (!gre)
155 return BPF_DROP;
156
157 if (bpf_htons(gre->flags & GRE_VERSION))
158 /* Only inspect standard GRE packets with version 0 */
159 return BPF_OK;
160
161 keys->nhoff += sizeof(*gre); /* Step over GRE Flags and Proto */
162 if (GRE_IS_CSUM(gre->flags))
163 keys->nhoff += 4; /* Step over chksum and Padding */
164 if (GRE_IS_KEY(gre->flags))
165 keys->nhoff += 4; /* Step over key */
166 if (GRE_IS_SEQ(gre->flags))
167 keys->nhoff += 4; /* Step over sequence number */
168
169 keys->is_encap = true;
170
171 if (gre->proto == bpf_htons(ETH_P_TEB)) {
172 eth = bpf_flow_dissect_get_header(skb, sizeof(*eth),
173 &_eth);
174 if (!eth)
175 return BPF_DROP;
176
177 keys->nhoff += sizeof(*eth);
178
179 return parse_eth_proto(skb, eth->h_proto);
180 } else {
181 return parse_eth_proto(skb, gre->proto);
182 }
183 case IPPROTO_TCP:
184 tcp = bpf_flow_dissect_get_header(skb, sizeof(*tcp), &_tcp);
185 if (!tcp)
186 return BPF_DROP;
187
188 if (tcp->doff < 5)
189 return BPF_DROP;
190
191 if ((__u8 *)tcp + (tcp->doff << 2) > data_end)
192 return BPF_DROP;
193
194 keys->thoff = keys->nhoff;
195 keys->sport = tcp->source;
196 keys->dport = tcp->dest;
197 return BPF_OK;
198 case IPPROTO_UDP:
199 case IPPROTO_UDPLITE:
200 udp = bpf_flow_dissect_get_header(skb, sizeof(*udp), &_udp);
201 if (!udp)
202 return BPF_DROP;
203
204 keys->thoff = keys->nhoff;
205 keys->sport = udp->source;
206 keys->dport = udp->dest;
207 return BPF_OK;
208 default:
209 return BPF_DROP;
210 }
211
212 return BPF_DROP;
213}
214
215static __always_inline int parse_ipv6_proto(struct __sk_buff *skb, __u8 nexthdr)
216{
217 struct bpf_flow_keys *keys = skb->flow_keys;
218
219 keys->ip_proto = nexthdr;
220 switch (nexthdr) {
221 case IPPROTO_HOPOPTS:
222 case IPPROTO_DSTOPTS:
223 bpf_tail_call(skb, &jmp_table, IPV6OP);
224 break;
225 case IPPROTO_FRAGMENT:
226 bpf_tail_call(skb, &jmp_table, IPV6FR);
227 break;
228 default:
229 return parse_ip_proto(skb, nexthdr);
230 }
231
232 return BPF_DROP;
233}
234
235PROG(IP)(struct __sk_buff *skb)
236{
237 void *data_end = (void *)(long)skb->data_end;
238 struct bpf_flow_keys *keys = skb->flow_keys;
239 void *data = (void *)(long)skb->data;
240 struct iphdr *iph, _iph;
241 bool done = false;
242
243 iph = bpf_flow_dissect_get_header(skb, sizeof(*iph), &_iph);
244 if (!iph)
245 return BPF_DROP;
246
247 /* IP header cannot be smaller than 20 bytes */
248 if (iph->ihl < 5)
249 return BPF_DROP;
250
251 keys->addr_proto = ETH_P_IP;
252 keys->ipv4_src = iph->saddr;
253 keys->ipv4_dst = iph->daddr;
254
255 keys->nhoff += iph->ihl << 2;
256 if (data + keys->nhoff > data_end)
257 return BPF_DROP;
258
259 if (iph->frag_off & bpf_htons(IP_MF | IP_OFFSET)) {
260 keys->is_frag = true;
261 if (iph->frag_off & bpf_htons(IP_OFFSET))
262 /* From second fragment on, packets do not have headers
263 * we can parse.
264 */
265 done = true;
266 else
267 keys->is_first_frag = true;
268 }
269
270 if (done)
271 return BPF_OK;
272
273 return parse_ip_proto(skb, iph->protocol);
274}
275
276PROG(IPV6)(struct __sk_buff *skb)
277{
278 struct bpf_flow_keys *keys = skb->flow_keys;
279 struct ipv6hdr *ip6h, _ip6h;
280
281 ip6h = bpf_flow_dissect_get_header(skb, sizeof(*ip6h), &_ip6h);
282 if (!ip6h)
283 return BPF_DROP;
284
285 keys->addr_proto = ETH_P_IPV6;
286 memcpy(&keys->ipv6_src, &ip6h->saddr, 2*sizeof(ip6h->saddr));
287
288 keys->nhoff += sizeof(struct ipv6hdr);
289
290 return parse_ipv6_proto(skb, ip6h->nexthdr);
291}
292
293PROG(IPV6OP)(struct __sk_buff *skb)
294{
295 struct ipv6_opt_hdr *ip6h, _ip6h;
296
297 ip6h = bpf_flow_dissect_get_header(skb, sizeof(*ip6h), &_ip6h);
298 if (!ip6h)
299 return BPF_DROP;
300
301 /* hlen is in 8-octets and does not include the first 8 bytes
302 * of the header
303 */
304 skb->flow_keys->nhoff += (1 + ip6h->hdrlen) << 3;
305
306 return parse_ipv6_proto(skb, ip6h->nexthdr);
307}
308
309PROG(IPV6FR)(struct __sk_buff *skb)
310{
311 struct bpf_flow_keys *keys = skb->flow_keys;
312 struct frag_hdr *fragh, _fragh;
313
314 fragh = bpf_flow_dissect_get_header(skb, sizeof(*fragh), &_fragh);
315 if (!fragh)
316 return BPF_DROP;
317
318 keys->nhoff += sizeof(*fragh);
319 keys->is_frag = true;
320 if (!(fragh->frag_off & bpf_htons(IP6_OFFSET)))
321 keys->is_first_frag = true;
322
323 return parse_ipv6_proto(skb, fragh->nexthdr);
324}
325
326PROG(MPLS)(struct __sk_buff *skb)
327{
328 struct mpls_label *mpls, _mpls;
329
330 mpls = bpf_flow_dissect_get_header(skb, sizeof(*mpls), &_mpls);
331 if (!mpls)
332 return BPF_DROP;
333
334 return BPF_OK;
335}
336
337PROG(VLAN)(struct __sk_buff *skb)
338{
339 struct bpf_flow_keys *keys = skb->flow_keys;
340 struct vlan_hdr *vlan, _vlan;
341 __be16 proto;
342
343 /* Peek back to see if single or double-tagging */
344 if (bpf_skb_load_bytes(skb, keys->nhoff - sizeof(proto), &proto,
345 sizeof(proto)))
346 return BPF_DROP;
347
348 /* Account for double-tagging */
349 if (proto == bpf_htons(ETH_P_8021AD)) {
350 vlan = bpf_flow_dissect_get_header(skb, sizeof(*vlan), &_vlan);
351 if (!vlan)
352 return BPF_DROP;
353
354 if (vlan->h_vlan_encapsulated_proto != bpf_htons(ETH_P_8021Q))
355 return BPF_DROP;
356
357 keys->nhoff += sizeof(*vlan);
358 }
359
360 vlan = bpf_flow_dissect_get_header(skb, sizeof(*vlan), &_vlan);
361 if (!vlan)
362 return BPF_DROP;
363
364 keys->nhoff += sizeof(*vlan);
365 /* Only allow 8021AD + 8021Q double tagging and no triple tagging.*/
366 if (vlan->h_vlan_encapsulated_proto == bpf_htons(ETH_P_8021AD) ||
367 vlan->h_vlan_encapsulated_proto == bpf_htons(ETH_P_8021Q))
368 return BPF_DROP;
369
370 return parse_eth_proto(skb, vlan->h_vlan_encapsulated_proto);
371}
372
373char __license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index e4be7730222d..686e57ce40f4 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -16,6 +16,13 @@ static int (*bpf_map_update_elem)(void *map, void *key, void *value,
16 (void *) BPF_FUNC_map_update_elem; 16 (void *) BPF_FUNC_map_update_elem;
17static int (*bpf_map_delete_elem)(void *map, void *key) = 17static int (*bpf_map_delete_elem)(void *map, void *key) =
18 (void *) BPF_FUNC_map_delete_elem; 18 (void *) BPF_FUNC_map_delete_elem;
19static int (*bpf_map_push_elem)(void *map, void *value,
20 unsigned long long flags) =
21 (void *) BPF_FUNC_map_push_elem;
22static int (*bpf_map_pop_elem)(void *map, void *value) =
23 (void *) BPF_FUNC_map_pop_elem;
24static int (*bpf_map_peek_elem)(void *map, void *value) =
25 (void *) BPF_FUNC_map_peek_elem;
19static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) = 26static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) =
20 (void *) BPF_FUNC_probe_read; 27 (void *) BPF_FUNC_probe_read;
21static unsigned long long (*bpf_ktime_get_ns)(void) = 28static unsigned long long (*bpf_ktime_get_ns)(void) =
@@ -104,6 +111,8 @@ static int (*bpf_msg_cork_bytes)(void *ctx, int len) =
104 (void *) BPF_FUNC_msg_cork_bytes; 111 (void *) BPF_FUNC_msg_cork_bytes;
105static int (*bpf_msg_pull_data)(void *ctx, int start, int end, int flags) = 112static int (*bpf_msg_pull_data)(void *ctx, int start, int end, int flags) =
106 (void *) BPF_FUNC_msg_pull_data; 113 (void *) BPF_FUNC_msg_pull_data;
114static int (*bpf_msg_push_data)(void *ctx, int start, int end, int flags) =
115 (void *) BPF_FUNC_msg_push_data;
107static int (*bpf_bind)(void *ctx, void *addr, int addr_len) = 116static int (*bpf_bind)(void *ctx, void *addr, int addr_len) =
108 (void *) BPF_FUNC_bind; 117 (void *) BPF_FUNC_bind;
109static int (*bpf_xdp_adjust_tail)(void *ctx, int offset) = 118static int (*bpf_xdp_adjust_tail)(void *ctx, int offset) =
@@ -143,6 +152,22 @@ static unsigned long long (*bpf_skb_cgroup_id)(void *ctx) =
143 (void *) BPF_FUNC_skb_cgroup_id; 152 (void *) BPF_FUNC_skb_cgroup_id;
144static unsigned long long (*bpf_skb_ancestor_cgroup_id)(void *ctx, int level) = 153static unsigned long long (*bpf_skb_ancestor_cgroup_id)(void *ctx, int level) =
145 (void *) BPF_FUNC_skb_ancestor_cgroup_id; 154 (void *) BPF_FUNC_skb_ancestor_cgroup_id;
155static struct bpf_sock *(*bpf_sk_lookup_tcp)(void *ctx,
156 struct bpf_sock_tuple *tuple,
157 int size, unsigned int netns_id,
158 unsigned long long flags) =
159 (void *) BPF_FUNC_sk_lookup_tcp;
160static struct bpf_sock *(*bpf_sk_lookup_udp)(void *ctx,
161 struct bpf_sock_tuple *tuple,
162 int size, unsigned int netns_id,
163 unsigned long long flags) =
164 (void *) BPF_FUNC_sk_lookup_udp;
165static int (*bpf_sk_release)(struct bpf_sock *sk) =
166 (void *) BPF_FUNC_sk_release;
167static int (*bpf_skb_vlan_push)(void *ctx, __be16 vlan_proto, __u16 vlan_tci) =
168 (void *) BPF_FUNC_skb_vlan_push;
169static int (*bpf_skb_vlan_pop)(void *ctx) =
170 (void *) BPF_FUNC_skb_vlan_pop;
146 171
147/* llvm builtin functions that eBPF C program may use to 172/* llvm builtin functions that eBPF C program may use to
148 * emit BPF_LD_ABS and BPF_LD_IND instructions 173 * emit BPF_LD_ABS and BPF_LD_IND instructions
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index b4994a94968b..dd49df5e2df4 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -18,3 +18,5 @@ CONFIG_CRYPTO_HMAC=m
18CONFIG_CRYPTO_SHA256=m 18CONFIG_CRYPTO_SHA256=m
19CONFIG_VXLAN=y 19CONFIG_VXLAN=y
20CONFIG_GENEVE=y 20CONFIG_GENEVE=y
21CONFIG_NET_CLS_FLOWER=m
22CONFIG_LWTUNNEL=y
diff --git a/tools/testing/selftests/bpf/flow_dissector_load.c b/tools/testing/selftests/bpf/flow_dissector_load.c
new file mode 100644
index 000000000000..d3273b5b3173
--- /dev/null
+++ b/tools/testing/selftests/bpf/flow_dissector_load.c
@@ -0,0 +1,140 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <error.h>
3#include <errno.h>
4#include <getopt.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <bpf/bpf.h>
12#include <bpf/libbpf.h>
13
14const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
15const char *cfg_map_name = "jmp_table";
16bool cfg_attach = true;
17char *cfg_section_name;
18char *cfg_path_name;
19
20static void load_and_attach_program(void)
21{
22 struct bpf_program *prog, *main_prog;
23 struct bpf_map *prog_array;
24 int i, fd, prog_fd, ret;
25 struct bpf_object *obj;
26 int prog_array_fd;
27
28 ret = bpf_prog_load(cfg_path_name, BPF_PROG_TYPE_FLOW_DISSECTOR, &obj,
29 &prog_fd);
30 if (ret)
31 error(1, 0, "bpf_prog_load %s", cfg_path_name);
32
33 main_prog = bpf_object__find_program_by_title(obj, cfg_section_name);
34 if (!main_prog)
35 error(1, 0, "bpf_object__find_program_by_title %s",
36 cfg_section_name);
37
38 prog_fd = bpf_program__fd(main_prog);
39 if (prog_fd < 0)
40 error(1, 0, "bpf_program__fd");
41
42 prog_array = bpf_object__find_map_by_name(obj, cfg_map_name);
43 if (!prog_array)
44 error(1, 0, "bpf_object__find_map_by_name %s", cfg_map_name);
45
46 prog_array_fd = bpf_map__fd(prog_array);
47 if (prog_array_fd < 0)
48 error(1, 0, "bpf_map__fd %s", cfg_map_name);
49
50 i = 0;
51 bpf_object__for_each_program(prog, obj) {
52 fd = bpf_program__fd(prog);
53 if (fd < 0)
54 error(1, 0, "bpf_program__fd");
55
56 if (fd != prog_fd) {
57 printf("%d: %s\n", i, bpf_program__title(prog, false));
58 bpf_map_update_elem(prog_array_fd, &i, &fd, BPF_ANY);
59 ++i;
60 }
61 }
62
63 ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0);
64 if (ret)
65 error(1, 0, "bpf_prog_attach %s", cfg_path_name);
66
67 ret = bpf_object__pin(obj, cfg_pin_path);
68 if (ret)
69 error(1, 0, "bpf_object__pin %s", cfg_pin_path);
70
71}
72
73static void detach_program(void)
74{
75 char command[64];
76 int ret;
77
78 ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
79 if (ret)
80 error(1, 0, "bpf_prog_detach");
81
82 /* To unpin, it is necessary and sufficient to just remove this dir */
83 sprintf(command, "rm -r %s", cfg_pin_path);
84 ret = system(command);
85 if (ret)
86 error(1, errno, command);
87}
88
89static void parse_opts(int argc, char **argv)
90{
91 bool attach = false;
92 bool detach = false;
93 int c;
94
95 while ((c = getopt(argc, argv, "adp:s:")) != -1) {
96 switch (c) {
97 case 'a':
98 if (detach)
99 error(1, 0, "attach/detach are exclusive");
100 attach = true;
101 break;
102 case 'd':
103 if (attach)
104 error(1, 0, "attach/detach are exclusive");
105 detach = true;
106 break;
107 case 'p':
108 if (cfg_path_name)
109 error(1, 0, "only one prog name can be given");
110
111 cfg_path_name = optarg;
112 break;
113 case 's':
114 if (cfg_section_name)
115 error(1, 0, "only one section can be given");
116
117 cfg_section_name = optarg;
118 break;
119 }
120 }
121
122 if (detach)
123 cfg_attach = false;
124
125 if (cfg_attach && !cfg_path_name)
126 error(1, 0, "must provide a path to the BPF program");
127
128 if (cfg_attach && !cfg_section_name)
129 error(1, 0, "must provide a section name");
130}
131
132int main(int argc, char **argv)
133{
134 parse_opts(argc, argv);
135 if (cfg_attach)
136 load_and_attach_program();
137 else
138 detach_program();
139 return 0;
140}
diff --git a/tools/testing/selftests/bpf/netcnt_common.h b/tools/testing/selftests/bpf/netcnt_common.h
new file mode 100644
index 000000000000..81084c1c2c23
--- /dev/null
+++ b/tools/testing/selftests/bpf/netcnt_common.h
@@ -0,0 +1,24 @@
1// SPDX-License-Identifier: GPL-2.0
2#ifndef __NETCNT_COMMON_H
3#define __NETCNT_COMMON_H
4
5#include <linux/types.h>
6
7#define MAX_PERCPU_PACKETS 32
8
9struct percpu_net_cnt {
10 __u64 packets;
11 __u64 bytes;
12
13 __u64 prev_ts;
14
15 __u64 prev_packets;
16 __u64 prev_bytes;
17};
18
19struct net_cnt {
20 __u64 packets;
21 __u64 bytes;
22};
23
24#endif
diff --git a/tools/testing/selftests/bpf/netcnt_prog.c b/tools/testing/selftests/bpf/netcnt_prog.c
new file mode 100644
index 000000000000..1198abca1360
--- /dev/null
+++ b/tools/testing/selftests/bpf/netcnt_prog.c
@@ -0,0 +1,71 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/bpf.h>
3#include <linux/version.h>
4
5#include "bpf_helpers.h"
6#include "netcnt_common.h"
7
8#define MAX_BPS (3 * 1024 * 1024)
9
10#define REFRESH_TIME_NS 100000000
11#define NS_PER_SEC 1000000000
12
13struct bpf_map_def SEC("maps") percpu_netcnt = {
14 .type = BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
15 .key_size = sizeof(struct bpf_cgroup_storage_key),
16 .value_size = sizeof(struct percpu_net_cnt),
17};
18
19struct bpf_map_def SEC("maps") netcnt = {
20 .type = BPF_MAP_TYPE_CGROUP_STORAGE,
21 .key_size = sizeof(struct bpf_cgroup_storage_key),
22 .value_size = sizeof(struct net_cnt),
23};
24
25SEC("cgroup/skb")
26int bpf_nextcnt(struct __sk_buff *skb)
27{
28 struct percpu_net_cnt *percpu_cnt;
29 char fmt[] = "%d %llu %llu\n";
30 struct net_cnt *cnt;
31 __u64 ts, dt;
32 int ret;
33
34 cnt = bpf_get_local_storage(&netcnt, 0);
35 percpu_cnt = bpf_get_local_storage(&percpu_netcnt, 0);
36
37 percpu_cnt->packets++;
38 percpu_cnt->bytes += skb->len;
39
40 if (percpu_cnt->packets > MAX_PERCPU_PACKETS) {
41 __sync_fetch_and_add(&cnt->packets,
42 percpu_cnt->packets);
43 percpu_cnt->packets = 0;
44
45 __sync_fetch_and_add(&cnt->bytes,
46 percpu_cnt->bytes);
47 percpu_cnt->bytes = 0;
48 }
49
50 ts = bpf_ktime_get_ns();
51 dt = ts - percpu_cnt->prev_ts;
52
53 dt *= MAX_BPS;
54 dt /= NS_PER_SEC;
55
56 if (cnt->bytes + percpu_cnt->bytes - percpu_cnt->prev_bytes < dt)
57 ret = 1;
58 else
59 ret = 0;
60
61 if (dt > REFRESH_TIME_NS) {
62 percpu_cnt->prev_ts = ts;
63 percpu_cnt->prev_packets = cnt->packets;
64 percpu_cnt->prev_bytes = cnt->bytes;
65 }
66
67 return !!ret;
68}
69
70char _license[] SEC("license") = "GPL";
71__u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index 6b5cfeb7a9cc..f42b3396d622 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -4,6 +4,7 @@
4#include <linux/bpf.h> 4#include <linux/bpf.h>
5#include <linux/btf.h> 5#include <linux/btf.h>
6#include <linux/err.h> 6#include <linux/err.h>
7#include <linux/kernel.h>
7#include <bpf/bpf.h> 8#include <bpf/bpf.h>
8#include <sys/resource.h> 9#include <sys/resource.h>
9#include <libelf.h> 10#include <libelf.h>
@@ -45,7 +46,6 @@ static int count_result(int err)
45 return err; 46 return err;
46} 47}
47 48
48#define min(a, b) ((a) < (b) ? (a) : (b))
49#define __printf(a, b) __attribute__((format(printf, a, b))) 49#define __printf(a, b) __attribute__((format(printf, a, b)))
50 50
51__printf(1, 2) 51__printf(1, 2)
@@ -130,6 +130,7 @@ struct btf_raw_test {
130 bool map_create_err; 130 bool map_create_err;
131 bool ordered_map; 131 bool ordered_map;
132 bool lossless_map; 132 bool lossless_map;
133 bool percpu_map;
133 int hdr_len_delta; 134 int hdr_len_delta;
134 int type_off_delta; 135 int type_off_delta;
135 int str_off_delta; 136 int str_off_delta;
@@ -2157,6 +2158,7 @@ static struct btf_pprint_test_meta {
2157 const char *map_name; 2158 const char *map_name;
2158 bool ordered_map; 2159 bool ordered_map;
2159 bool lossless_map; 2160 bool lossless_map;
2161 bool percpu_map;
2160} pprint_tests_meta[] = { 2162} pprint_tests_meta[] = {
2161{ 2163{
2162 .descr = "BTF pretty print array", 2164 .descr = "BTF pretty print array",
@@ -2164,6 +2166,7 @@ static struct btf_pprint_test_meta {
2164 .map_name = "pprint_test_array", 2166 .map_name = "pprint_test_array",
2165 .ordered_map = true, 2167 .ordered_map = true,
2166 .lossless_map = true, 2168 .lossless_map = true,
2169 .percpu_map = false,
2167}, 2170},
2168 2171
2169{ 2172{
@@ -2172,6 +2175,7 @@ static struct btf_pprint_test_meta {
2172 .map_name = "pprint_test_hash", 2175 .map_name = "pprint_test_hash",
2173 .ordered_map = false, 2176 .ordered_map = false,
2174 .lossless_map = true, 2177 .lossless_map = true,
2178 .percpu_map = false,
2175}, 2179},
2176 2180
2177{ 2181{
@@ -2180,30 +2184,83 @@ static struct btf_pprint_test_meta {
2180 .map_name = "pprint_test_lru_hash", 2184 .map_name = "pprint_test_lru_hash",
2181 .ordered_map = false, 2185 .ordered_map = false,
2182 .lossless_map = false, 2186 .lossless_map = false,
2187 .percpu_map = false,
2188},
2189
2190{
2191 .descr = "BTF pretty print percpu array",
2192 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY,
2193 .map_name = "pprint_test_percpu_array",
2194 .ordered_map = true,
2195 .lossless_map = true,
2196 .percpu_map = true,
2197},
2198
2199{
2200 .descr = "BTF pretty print percpu hash",
2201 .map_type = BPF_MAP_TYPE_PERCPU_HASH,
2202 .map_name = "pprint_test_percpu_hash",
2203 .ordered_map = false,
2204 .lossless_map = true,
2205 .percpu_map = true,
2206},
2207
2208{
2209 .descr = "BTF pretty print lru percpu hash",
2210 .map_type = BPF_MAP_TYPE_LRU_PERCPU_HASH,
2211 .map_name = "pprint_test_lru_percpu_hash",
2212 .ordered_map = false,
2213 .lossless_map = false,
2214 .percpu_map = true,
2183}, 2215},
2184 2216
2185}; 2217};
2186 2218
2187 2219
2188static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i) 2220static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
2221 int num_cpus, int rounded_value_size)
2189{ 2222{
2190 v->ui32 = i; 2223 int cpu;
2191 v->si32 = -i; 2224
2192 v->unused_bits2a = 3; 2225 for (cpu = 0; cpu < num_cpus; cpu++) {
2193 v->bits28 = i; 2226 v->ui32 = i + cpu;
2194 v->unused_bits2b = 3; 2227 v->si32 = -i;
2195 v->ui64 = i; 2228 v->unused_bits2a = 3;
2196 v->aenum = i & 0x03; 2229 v->bits28 = i;
2230 v->unused_bits2b = 3;
2231 v->ui64 = i;
2232 v->aenum = i & 0x03;
2233 v = (void *)v + rounded_value_size;
2234 }
2197} 2235}
2198 2236
2237static int check_line(const char *expected_line, int nexpected_line,
2238 int expected_line_len, const char *line)
2239{
2240 if (CHECK(nexpected_line == expected_line_len,
2241 "expected_line is too long"))
2242 return -1;
2243
2244 if (strcmp(expected_line, line)) {
2245 fprintf(stderr, "unexpected pprint output\n");
2246 fprintf(stderr, "expected: %s", expected_line);
2247 fprintf(stderr, " read: %s", line);
2248 return -1;
2249 }
2250
2251 return 0;
2252}
2253
2254
2199static int do_test_pprint(void) 2255static int do_test_pprint(void)
2200{ 2256{
2201 const struct btf_raw_test *test = &pprint_test_template; 2257 const struct btf_raw_test *test = &pprint_test_template;
2202 struct bpf_create_map_attr create_attr = {}; 2258 struct bpf_create_map_attr create_attr = {};
2259 bool ordered_map, lossless_map, percpu_map;
2260 int err, ret, num_cpus, rounded_value_size;
2261 struct pprint_mapv *mapv = NULL;
2203 unsigned int key, nr_read_elems; 2262 unsigned int key, nr_read_elems;
2204 bool ordered_map, lossless_map;
2205 int map_fd = -1, btf_fd = -1; 2263 int map_fd = -1, btf_fd = -1;
2206 struct pprint_mapv mapv = {};
2207 unsigned int raw_btf_size; 2264 unsigned int raw_btf_size;
2208 char expected_line[255]; 2265 char expected_line[255];
2209 FILE *pin_file = NULL; 2266 FILE *pin_file = NULL;
@@ -2212,7 +2269,6 @@ static int do_test_pprint(void)
2212 char *line = NULL; 2269 char *line = NULL;
2213 uint8_t *raw_btf; 2270 uint8_t *raw_btf;
2214 ssize_t nread; 2271 ssize_t nread;
2215 int err, ret;
2216 2272
2217 fprintf(stderr, "%s......", test->descr); 2273 fprintf(stderr, "%s......", test->descr);
2218 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types, 2274 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
@@ -2261,9 +2317,18 @@ static int do_test_pprint(void)
2261 if (CHECK(err, "bpf_obj_pin(%s): errno:%d.", pin_path, errno)) 2317 if (CHECK(err, "bpf_obj_pin(%s): errno:%d.", pin_path, errno))
2262 goto done; 2318 goto done;
2263 2319
2320 percpu_map = test->percpu_map;
2321 num_cpus = percpu_map ? bpf_num_possible_cpus() : 1;
2322 rounded_value_size = round_up(sizeof(struct pprint_mapv), 8);
2323 mapv = calloc(num_cpus, rounded_value_size);
2324 if (CHECK(!mapv, "mapv allocation failure")) {
2325 err = -1;
2326 goto done;
2327 }
2328
2264 for (key = 0; key < test->max_entries; key++) { 2329 for (key = 0; key < test->max_entries; key++) {
2265 set_pprint_mapv(&mapv, key); 2330 set_pprint_mapv(mapv, key, num_cpus, rounded_value_size);
2266 bpf_map_update_elem(map_fd, &key, &mapv, 0); 2331 bpf_map_update_elem(map_fd, &key, mapv, 0);
2267 } 2332 }
2268 2333
2269 pin_file = fopen(pin_path, "r"); 2334 pin_file = fopen(pin_path, "r");
@@ -2286,33 +2351,74 @@ static int do_test_pprint(void)
2286 ordered_map = test->ordered_map; 2351 ordered_map = test->ordered_map;
2287 lossless_map = test->lossless_map; 2352 lossless_map = test->lossless_map;
2288 do { 2353 do {
2354 struct pprint_mapv *cmapv;
2289 ssize_t nexpected_line; 2355 ssize_t nexpected_line;
2290 unsigned int next_key; 2356 unsigned int next_key;
2357 int cpu;
2291 2358
2292 next_key = ordered_map ? nr_read_elems : atoi(line); 2359 next_key = ordered_map ? nr_read_elems : atoi(line);
2293 set_pprint_mapv(&mapv, next_key); 2360 set_pprint_mapv(mapv, next_key, num_cpus, rounded_value_size);
2294 nexpected_line = snprintf(expected_line, sizeof(expected_line), 2361 cmapv = mapv;
2295 "%u: {%u,0,%d,0x%x,0x%x,0x%x,{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n", 2362
2296 next_key, 2363 for (cpu = 0; cpu < num_cpus; cpu++) {
2297 mapv.ui32, mapv.si32, 2364 if (percpu_map) {
2298 mapv.unused_bits2a, mapv.bits28, mapv.unused_bits2b, 2365 /* for percpu map, the format looks like:
2299 mapv.ui64, 2366 * <key>: {
2300 mapv.ui8a[0], mapv.ui8a[1], mapv.ui8a[2], mapv.ui8a[3], 2367 * cpu0: <value_on_cpu0>
2301 mapv.ui8a[4], mapv.ui8a[5], mapv.ui8a[6], mapv.ui8a[7], 2368 * cpu1: <value_on_cpu1>
2302 pprint_enum_str[mapv.aenum]); 2369 * ...
2303 2370 * cpun: <value_on_cpun>
2304 if (CHECK(nexpected_line == sizeof(expected_line), 2371 * }
2305 "expected_line is too long")) { 2372 *
2306 err = -1; 2373 * let us verify the line containing the key here.
2307 goto done; 2374 */
2375 if (cpu == 0) {
2376 nexpected_line = snprintf(expected_line,
2377 sizeof(expected_line),
2378 "%u: {\n",
2379 next_key);
2380
2381 err = check_line(expected_line, nexpected_line,
2382 sizeof(expected_line), line);
2383 if (err == -1)
2384 goto done;
2385 }
2386
2387 /* read value@cpu */
2388 nread = getline(&line, &line_len, pin_file);
2389 if (nread < 0)
2390 break;
2391 }
2392
2393 nexpected_line = snprintf(expected_line, sizeof(expected_line),
2394 "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
2395 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
2396 percpu_map ? "\tcpu" : "",
2397 percpu_map ? cpu : next_key,
2398 cmapv->ui32, cmapv->si32,
2399 cmapv->unused_bits2a,
2400 cmapv->bits28,
2401 cmapv->unused_bits2b,
2402 cmapv->ui64,
2403 cmapv->ui8a[0], cmapv->ui8a[1],
2404 cmapv->ui8a[2], cmapv->ui8a[3],
2405 cmapv->ui8a[4], cmapv->ui8a[5],
2406 cmapv->ui8a[6], cmapv->ui8a[7],
2407 pprint_enum_str[cmapv->aenum]);
2408
2409 err = check_line(expected_line, nexpected_line,
2410 sizeof(expected_line), line);
2411 if (err == -1)
2412 goto done;
2413
2414 cmapv = (void *)cmapv + rounded_value_size;
2308 } 2415 }
2309 2416
2310 if (strcmp(expected_line, line)) { 2417 if (percpu_map) {
2311 err = -1; 2418 /* skip the last bracket for the percpu map */
2312 fprintf(stderr, "unexpected pprint output\n"); 2419 nread = getline(&line, &line_len, pin_file);
2313 fprintf(stderr, "expected: %s", expected_line); 2420 if (nread < 0)
2314 fprintf(stderr, " read: %s", line); 2421 break;
2315 goto done;
2316 } 2422 }
2317 2423
2318 nread = getline(&line, &line_len, pin_file); 2424 nread = getline(&line, &line_len, pin_file);
@@ -2334,6 +2440,8 @@ static int do_test_pprint(void)
2334 err = 0; 2440 err = 0;
2335 2441
2336done: 2442done:
2443 if (mapv)
2444 free(mapv);
2337 if (!err) 2445 if (!err)
2338 fprintf(stderr, "OK"); 2446 fprintf(stderr, "OK");
2339 if (*btf_log_buf && (err || args.always_log)) 2447 if (*btf_log_buf && (err || args.always_log))
@@ -2361,6 +2469,7 @@ static int test_pprint(void)
2361 pprint_test_template.map_name = pprint_tests_meta[i].map_name; 2469 pprint_test_template.map_name = pprint_tests_meta[i].map_name;
2362 pprint_test_template.ordered_map = pprint_tests_meta[i].ordered_map; 2470 pprint_test_template.ordered_map = pprint_tests_meta[i].ordered_map;
2363 pprint_test_template.lossless_map = pprint_tests_meta[i].lossless_map; 2471 pprint_test_template.lossless_map = pprint_tests_meta[i].lossless_map;
2472 pprint_test_template.percpu_map = pprint_tests_meta[i].percpu_map;
2364 2473
2365 err |= count_result(do_test_pprint()); 2474 err |= count_result(do_test_pprint());
2366 } 2475 }
diff --git a/tools/testing/selftests/bpf/test_cgroup_storage.c b/tools/testing/selftests/bpf/test_cgroup_storage.c
index 4e196e3bfecf..f44834155f25 100644
--- a/tools/testing/selftests/bpf/test_cgroup_storage.c
+++ b/tools/testing/selftests/bpf/test_cgroup_storage.c
@@ -4,6 +4,7 @@
4#include <linux/filter.h> 4#include <linux/filter.h>
5#include <stdio.h> 5#include <stdio.h>
6#include <stdlib.h> 6#include <stdlib.h>
7#include <sys/sysinfo.h>
7 8
8#include "bpf_rlimit.h" 9#include "bpf_rlimit.h"
9#include "cgroup_helpers.h" 10#include "cgroup_helpers.h"
@@ -15,6 +16,14 @@ char bpf_log_buf[BPF_LOG_BUF_SIZE];
15int main(int argc, char **argv) 16int main(int argc, char **argv)
16{ 17{
17 struct bpf_insn prog[] = { 18 struct bpf_insn prog[] = {
19 BPF_LD_MAP_FD(BPF_REG_1, 0), /* percpu map fd */
20 BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */
21 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
22 BPF_FUNC_get_local_storage),
23 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
24 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x1),
25 BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0),
26
18 BPF_LD_MAP_FD(BPF_REG_1, 0), /* map fd */ 27 BPF_LD_MAP_FD(BPF_REG_1, 0), /* map fd */
19 BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */ 28 BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */
20 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 29 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
@@ -28,9 +37,18 @@ int main(int argc, char **argv)
28 }; 37 };
29 size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 38 size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
30 int error = EXIT_FAILURE; 39 int error = EXIT_FAILURE;
31 int map_fd, prog_fd, cgroup_fd; 40 int map_fd, percpu_map_fd, prog_fd, cgroup_fd;
32 struct bpf_cgroup_storage_key key; 41 struct bpf_cgroup_storage_key key;
33 unsigned long long value; 42 unsigned long long value;
43 unsigned long long *percpu_value;
44 int cpu, nproc;
45
46 nproc = get_nprocs_conf();
47 percpu_value = malloc(sizeof(*percpu_value) * nproc);
48 if (!percpu_value) {
49 printf("Not enough memory for per-cpu area (%d cpus)\n", nproc);
50 goto err;
51 }
34 52
35 map_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, sizeof(key), 53 map_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, sizeof(key),
36 sizeof(value), 0, 0); 54 sizeof(value), 0, 0);
@@ -39,7 +57,15 @@ int main(int argc, char **argv)
39 goto out; 57 goto out;
40 } 58 }
41 59
42 prog[0].imm = map_fd; 60 percpu_map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
61 sizeof(key), sizeof(value), 0, 0);
62 if (percpu_map_fd < 0) {
63 printf("Failed to create map: %s\n", strerror(errno));
64 goto out;
65 }
66
67 prog[0].imm = percpu_map_fd;
68 prog[7].imm = map_fd;
43 prog_fd = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, 69 prog_fd = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
44 prog, insns_cnt, "GPL", 0, 70 prog, insns_cnt, "GPL", 0,
45 bpf_log_buf, BPF_LOG_BUF_SIZE); 71 bpf_log_buf, BPF_LOG_BUF_SIZE);
@@ -77,7 +103,15 @@ int main(int argc, char **argv)
77 } 103 }
78 104
79 if (bpf_map_lookup_elem(map_fd, &key, &value)) { 105 if (bpf_map_lookup_elem(map_fd, &key, &value)) {
80 printf("Failed to lookup cgroup storage\n"); 106 printf("Failed to lookup cgroup storage 0\n");
107 goto err;
108 }
109
110 for (cpu = 0; cpu < nproc; cpu++)
111 percpu_value[cpu] = 1000;
112
113 if (bpf_map_update_elem(percpu_map_fd, &key, percpu_value, 0)) {
114 printf("Failed to update the data in the cgroup storage\n");
81 goto err; 115 goto err;
82 } 116 }
83 117
@@ -120,11 +154,31 @@ int main(int argc, char **argv)
120 goto err; 154 goto err;
121 } 155 }
122 156
157 /* Check the final value of the counter in the percpu local storage */
158
159 for (cpu = 0; cpu < nproc; cpu++)
160 percpu_value[cpu] = 0;
161
162 if (bpf_map_lookup_elem(percpu_map_fd, &key, percpu_value)) {
163 printf("Failed to lookup the per-cpu cgroup storage\n");
164 goto err;
165 }
166
167 value = 0;
168 for (cpu = 0; cpu < nproc; cpu++)
169 value += percpu_value[cpu];
170
171 if (value != nproc * 1000 + 6) {
172 printf("Unexpected data in the per-cpu cgroup storage\n");
173 goto err;
174 }
175
123 error = 0; 176 error = 0;
124 printf("test_cgroup_storage:PASS\n"); 177 printf("test_cgroup_storage:PASS\n");
125 178
126err: 179err:
127 cleanup_cgroup_environment(); 180 cleanup_cgroup_environment();
181 free(percpu_value);
128 182
129out: 183out:
130 return error; 184 return error;
diff --git a/tools/testing/selftests/bpf/test_flow_dissector.c b/tools/testing/selftests/bpf/test_flow_dissector.c
new file mode 100644
index 000000000000..12b784afba31
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_flow_dissector.c
@@ -0,0 +1,782 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Inject packets with all sorts of encapsulation into the kernel.
4 *
5 * IPv4/IPv6 outer layer 3
6 * GRE/GUE/BARE outer layer 4, where bare is IPIP/SIT/IPv4-in-IPv6/..
7 * IPv4/IPv6 inner layer 3
8 */
9
10#define _GNU_SOURCE
11
12#include <stddef.h>
13#include <arpa/inet.h>
14#include <asm/byteorder.h>
15#include <error.h>
16#include <errno.h>
17#include <linux/if_packet.h>
18#include <linux/if_ether.h>
19#include <linux/if_packet.h>
20#include <linux/ipv6.h>
21#include <netinet/ip.h>
22#include <netinet/in.h>
23#include <netinet/udp.h>
24#include <poll.h>
25#include <stdbool.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/ioctl.h>
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37#define CFG_PORT_INNER 8000
38
39/* Add some protocol definitions that do not exist in userspace */
40
41struct grehdr {
42 uint16_t unused;
43 uint16_t protocol;
44} __attribute__((packed));
45
46struct guehdr {
47 union {
48 struct {
49#if defined(__LITTLE_ENDIAN_BITFIELD)
50 __u8 hlen:5,
51 control:1,
52 version:2;
53#elif defined (__BIG_ENDIAN_BITFIELD)
54 __u8 version:2,
55 control:1,
56 hlen:5;
57#else
58#error "Please fix <asm/byteorder.h>"
59#endif
60 __u8 proto_ctype;
61 __be16 flags;
62 };
63 __be32 word;
64 };
65};
66
67static uint8_t cfg_dsfield_inner;
68static uint8_t cfg_dsfield_outer;
69static uint8_t cfg_encap_proto;
70static bool cfg_expect_failure = false;
71static int cfg_l3_extra = AF_UNSPEC; /* optional SIT prefix */
72static int cfg_l3_inner = AF_UNSPEC;
73static int cfg_l3_outer = AF_UNSPEC;
74static int cfg_num_pkt = 10;
75static int cfg_num_secs = 0;
76static char cfg_payload_char = 'a';
77static int cfg_payload_len = 100;
78static int cfg_port_gue = 6080;
79static bool cfg_only_rx;
80static bool cfg_only_tx;
81static int cfg_src_port = 9;
82
83static char buf[ETH_DATA_LEN];
84
85#define INIT_ADDR4(name, addr4, port) \
86 static struct sockaddr_in name = { \
87 .sin_family = AF_INET, \
88 .sin_port = __constant_htons(port), \
89 .sin_addr.s_addr = __constant_htonl(addr4), \
90 };
91
92#define INIT_ADDR6(name, addr6, port) \
93 static struct sockaddr_in6 name = { \
94 .sin6_family = AF_INET6, \
95 .sin6_port = __constant_htons(port), \
96 .sin6_addr = addr6, \
97 };
98
99INIT_ADDR4(in_daddr4, INADDR_LOOPBACK, CFG_PORT_INNER)
100INIT_ADDR4(in_saddr4, INADDR_LOOPBACK + 2, 0)
101INIT_ADDR4(out_daddr4, INADDR_LOOPBACK, 0)
102INIT_ADDR4(out_saddr4, INADDR_LOOPBACK + 1, 0)
103INIT_ADDR4(extra_daddr4, INADDR_LOOPBACK, 0)
104INIT_ADDR4(extra_saddr4, INADDR_LOOPBACK + 1, 0)
105
106INIT_ADDR6(in_daddr6, IN6ADDR_LOOPBACK_INIT, CFG_PORT_INNER)
107INIT_ADDR6(in_saddr6, IN6ADDR_LOOPBACK_INIT, 0)
108INIT_ADDR6(out_daddr6, IN6ADDR_LOOPBACK_INIT, 0)
109INIT_ADDR6(out_saddr6, IN6ADDR_LOOPBACK_INIT, 0)
110INIT_ADDR6(extra_daddr6, IN6ADDR_LOOPBACK_INIT, 0)
111INIT_ADDR6(extra_saddr6, IN6ADDR_LOOPBACK_INIT, 0)
112
113static unsigned long util_gettime(void)
114{
115 struct timeval tv;
116
117 gettimeofday(&tv, NULL);
118 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
119}
120
121static void util_printaddr(const char *msg, struct sockaddr *addr)
122{
123 unsigned long off = 0;
124 char nbuf[INET6_ADDRSTRLEN];
125
126 switch (addr->sa_family) {
127 case PF_INET:
128 off = __builtin_offsetof(struct sockaddr_in, sin_addr);
129 break;
130 case PF_INET6:
131 off = __builtin_offsetof(struct sockaddr_in6, sin6_addr);
132 break;
133 default:
134 error(1, 0, "printaddr: unsupported family %u\n",
135 addr->sa_family);
136 }
137
138 if (!inet_ntop(addr->sa_family, ((void *) addr) + off, nbuf,
139 sizeof(nbuf)))
140 error(1, errno, "inet_ntop");
141
142 fprintf(stderr, "%s: %s\n", msg, nbuf);
143}
144
145static unsigned long add_csum_hword(const uint16_t *start, int num_u16)
146{
147 unsigned long sum = 0;
148 int i;
149
150 for (i = 0; i < num_u16; i++)
151 sum += start[i];
152
153 return sum;
154}
155
156static uint16_t build_ip_csum(const uint16_t *start, int num_u16,
157 unsigned long sum)
158{
159 sum += add_csum_hword(start, num_u16);
160
161 while (sum >> 16)
162 sum = (sum & 0xffff) + (sum >> 16);
163
164 return ~sum;
165}
166
167static void build_ipv4_header(void *header, uint8_t proto,
168 uint32_t src, uint32_t dst,
169 int payload_len, uint8_t tos)
170{
171 struct iphdr *iph = header;
172
173 iph->ihl = 5;
174 iph->version = 4;
175 iph->tos = tos;
176 iph->ttl = 8;
177 iph->tot_len = htons(sizeof(*iph) + payload_len);
178 iph->id = htons(1337);
179 iph->protocol = proto;
180 iph->saddr = src;
181 iph->daddr = dst;
182 iph->check = build_ip_csum((void *) iph, iph->ihl << 1, 0);
183}
184
185static void ipv6_set_dsfield(struct ipv6hdr *ip6h, uint8_t dsfield)
186{
187 uint16_t val, *ptr = (uint16_t *)ip6h;
188
189 val = ntohs(*ptr);
190 val &= 0xF00F;
191 val |= ((uint16_t) dsfield) << 4;
192 *ptr = htons(val);
193}
194
195static void build_ipv6_header(void *header, uint8_t proto,
196 struct sockaddr_in6 *src,
197 struct sockaddr_in6 *dst,
198 int payload_len, uint8_t dsfield)
199{
200 struct ipv6hdr *ip6h = header;
201
202 ip6h->version = 6;
203 ip6h->payload_len = htons(payload_len);
204 ip6h->nexthdr = proto;
205 ip6h->hop_limit = 8;
206 ipv6_set_dsfield(ip6h, dsfield);
207
208 memcpy(&ip6h->saddr, &src->sin6_addr, sizeof(ip6h->saddr));
209 memcpy(&ip6h->daddr, &dst->sin6_addr, sizeof(ip6h->daddr));
210}
211
212static uint16_t build_udp_v4_csum(const struct iphdr *iph,
213 const struct udphdr *udph,
214 int num_words)
215{
216 unsigned long pseudo_sum;
217 int num_u16 = sizeof(iph->saddr); /* halfwords: twice byte len */
218
219 pseudo_sum = add_csum_hword((void *) &iph->saddr, num_u16);
220 pseudo_sum += htons(IPPROTO_UDP);
221 pseudo_sum += udph->len;
222 return build_ip_csum((void *) udph, num_words, pseudo_sum);
223}
224
225static uint16_t build_udp_v6_csum(const struct ipv6hdr *ip6h,
226 const struct udphdr *udph,
227 int num_words)
228{
229 unsigned long pseudo_sum;
230 int num_u16 = sizeof(ip6h->saddr); /* halfwords: twice byte len */
231
232 pseudo_sum = add_csum_hword((void *) &ip6h->saddr, num_u16);
233 pseudo_sum += htons(ip6h->nexthdr);
234 pseudo_sum += ip6h->payload_len;
235 return build_ip_csum((void *) udph, num_words, pseudo_sum);
236}
237
238static void build_udp_header(void *header, int payload_len,
239 uint16_t dport, int family)
240{
241 struct udphdr *udph = header;
242 int len = sizeof(*udph) + payload_len;
243
244 udph->source = htons(cfg_src_port);
245 udph->dest = htons(dport);
246 udph->len = htons(len);
247 udph->check = 0;
248 if (family == AF_INET)
249 udph->check = build_udp_v4_csum(header - sizeof(struct iphdr),
250 udph, len >> 1);
251 else
252 udph->check = build_udp_v6_csum(header - sizeof(struct ipv6hdr),
253 udph, len >> 1);
254}
255
256static void build_gue_header(void *header, uint8_t proto)
257{
258 struct guehdr *gueh = header;
259
260 gueh->proto_ctype = proto;
261}
262
263static void build_gre_header(void *header, uint16_t proto)
264{
265 struct grehdr *greh = header;
266
267 greh->protocol = htons(proto);
268}
269
270static int l3_length(int family)
271{
272 if (family == AF_INET)
273 return sizeof(struct iphdr);
274 else
275 return sizeof(struct ipv6hdr);
276}
277
278static int build_packet(void)
279{
280 int ol3_len = 0, ol4_len = 0, il3_len = 0, il4_len = 0;
281 int el3_len = 0;
282
283 if (cfg_l3_extra)
284 el3_len = l3_length(cfg_l3_extra);
285
286 /* calculate header offsets */
287 if (cfg_encap_proto) {
288 ol3_len = l3_length(cfg_l3_outer);
289
290 if (cfg_encap_proto == IPPROTO_GRE)
291 ol4_len = sizeof(struct grehdr);
292 else if (cfg_encap_proto == IPPROTO_UDP)
293 ol4_len = sizeof(struct udphdr) + sizeof(struct guehdr);
294 }
295
296 il3_len = l3_length(cfg_l3_inner);
297 il4_len = sizeof(struct udphdr);
298
299 if (el3_len + ol3_len + ol4_len + il3_len + il4_len + cfg_payload_len >=
300 sizeof(buf))
301 error(1, 0, "packet too large\n");
302
303 /*
304 * Fill packet from inside out, to calculate correct checksums.
305 * But create ip before udp headers, as udp uses ip for pseudo-sum.
306 */
307 memset(buf + el3_len + ol3_len + ol4_len + il3_len + il4_len,
308 cfg_payload_char, cfg_payload_len);
309
310 /* add zero byte for udp csum padding */
311 buf[el3_len + ol3_len + ol4_len + il3_len + il4_len + cfg_payload_len] = 0;
312
313 switch (cfg_l3_inner) {
314 case PF_INET:
315 build_ipv4_header(buf + el3_len + ol3_len + ol4_len,
316 IPPROTO_UDP,
317 in_saddr4.sin_addr.s_addr,
318 in_daddr4.sin_addr.s_addr,
319 il4_len + cfg_payload_len,
320 cfg_dsfield_inner);
321 break;
322 case PF_INET6:
323 build_ipv6_header(buf + el3_len + ol3_len + ol4_len,
324 IPPROTO_UDP,
325 &in_saddr6, &in_daddr6,
326 il4_len + cfg_payload_len,
327 cfg_dsfield_inner);
328 break;
329 }
330
331 build_udp_header(buf + el3_len + ol3_len + ol4_len + il3_len,
332 cfg_payload_len, CFG_PORT_INNER, cfg_l3_inner);
333
334 if (!cfg_encap_proto)
335 return il3_len + il4_len + cfg_payload_len;
336
337 switch (cfg_l3_outer) {
338 case PF_INET:
339 build_ipv4_header(buf + el3_len, cfg_encap_proto,
340 out_saddr4.sin_addr.s_addr,
341 out_daddr4.sin_addr.s_addr,
342 ol4_len + il3_len + il4_len + cfg_payload_len,
343 cfg_dsfield_outer);
344 break;
345 case PF_INET6:
346 build_ipv6_header(buf + el3_len, cfg_encap_proto,
347 &out_saddr6, &out_daddr6,
348 ol4_len + il3_len + il4_len + cfg_payload_len,
349 cfg_dsfield_outer);
350 break;
351 }
352
353 switch (cfg_encap_proto) {
354 case IPPROTO_UDP:
355 build_gue_header(buf + el3_len + ol3_len + ol4_len -
356 sizeof(struct guehdr),
357 cfg_l3_inner == PF_INET ? IPPROTO_IPIP
358 : IPPROTO_IPV6);
359 build_udp_header(buf + el3_len + ol3_len,
360 sizeof(struct guehdr) + il3_len + il4_len +
361 cfg_payload_len,
362 cfg_port_gue, cfg_l3_outer);
363 break;
364 case IPPROTO_GRE:
365 build_gre_header(buf + el3_len + ol3_len,
366 cfg_l3_inner == PF_INET ? ETH_P_IP
367 : ETH_P_IPV6);
368 break;
369 }
370
371 switch (cfg_l3_extra) {
372 case PF_INET:
373 build_ipv4_header(buf,
374 cfg_l3_outer == PF_INET ? IPPROTO_IPIP
375 : IPPROTO_IPV6,
376 extra_saddr4.sin_addr.s_addr,
377 extra_daddr4.sin_addr.s_addr,
378 ol3_len + ol4_len + il3_len + il4_len +
379 cfg_payload_len, 0);
380 break;
381 case PF_INET6:
382 build_ipv6_header(buf,
383 cfg_l3_outer == PF_INET ? IPPROTO_IPIP
384 : IPPROTO_IPV6,
385 &extra_saddr6, &extra_daddr6,
386 ol3_len + ol4_len + il3_len + il4_len +
387 cfg_payload_len, 0);
388 break;
389 }
390
391 return el3_len + ol3_len + ol4_len + il3_len + il4_len +
392 cfg_payload_len;
393}
394
395/* sender transmits encapsulated over RAW or unencap'd over UDP */
396static int setup_tx(void)
397{
398 int family, fd, ret;
399
400 if (cfg_l3_extra)
401 family = cfg_l3_extra;
402 else if (cfg_l3_outer)
403 family = cfg_l3_outer;
404 else
405 family = cfg_l3_inner;
406
407 fd = socket(family, SOCK_RAW, IPPROTO_RAW);
408 if (fd == -1)
409 error(1, errno, "socket tx");
410
411 if (cfg_l3_extra) {
412 if (cfg_l3_extra == PF_INET)
413 ret = connect(fd, (void *) &extra_daddr4,
414 sizeof(extra_daddr4));
415 else
416 ret = connect(fd, (void *) &extra_daddr6,
417 sizeof(extra_daddr6));
418 if (ret)
419 error(1, errno, "connect tx");
420 } else if (cfg_l3_outer) {
421 /* connect to destination if not encapsulated */
422 if (cfg_l3_outer == PF_INET)
423 ret = connect(fd, (void *) &out_daddr4,
424 sizeof(out_daddr4));
425 else
426 ret = connect(fd, (void *) &out_daddr6,
427 sizeof(out_daddr6));
428 if (ret)
429 error(1, errno, "connect tx");
430 } else {
431 /* otherwise using loopback */
432 if (cfg_l3_inner == PF_INET)
433 ret = connect(fd, (void *) &in_daddr4,
434 sizeof(in_daddr4));
435 else
436 ret = connect(fd, (void *) &in_daddr6,
437 sizeof(in_daddr6));
438 if (ret)
439 error(1, errno, "connect tx");
440 }
441
442 return fd;
443}
444
445/* receiver reads unencapsulated UDP */
446static int setup_rx(void)
447{
448 int fd, ret;
449
450 fd = socket(cfg_l3_inner, SOCK_DGRAM, 0);
451 if (fd == -1)
452 error(1, errno, "socket rx");
453
454 if (cfg_l3_inner == PF_INET)
455 ret = bind(fd, (void *) &in_daddr4, sizeof(in_daddr4));
456 else
457 ret = bind(fd, (void *) &in_daddr6, sizeof(in_daddr6));
458 if (ret)
459 error(1, errno, "bind rx");
460
461 return fd;
462}
463
464static int do_tx(int fd, const char *pkt, int len)
465{
466 int ret;
467
468 ret = write(fd, pkt, len);
469 if (ret == -1)
470 error(1, errno, "send");
471 if (ret != len)
472 error(1, errno, "send: len (%d < %d)\n", ret, len);
473
474 return 1;
475}
476
477static int do_poll(int fd, short events, int timeout)
478{
479 struct pollfd pfd;
480 int ret;
481
482 pfd.fd = fd;
483 pfd.events = events;
484
485 ret = poll(&pfd, 1, timeout);
486 if (ret == -1)
487 error(1, errno, "poll");
488 if (ret && !(pfd.revents & POLLIN))
489 error(1, errno, "poll: unexpected event 0x%x\n", pfd.revents);
490
491 return ret;
492}
493
494static int do_rx(int fd)
495{
496 char rbuf;
497 int ret, num = 0;
498
499 while (1) {
500 ret = recv(fd, &rbuf, 1, MSG_DONTWAIT);
501 if (ret == -1 && errno == EAGAIN)
502 break;
503 if (ret == -1)
504 error(1, errno, "recv");
505 if (rbuf != cfg_payload_char)
506 error(1, 0, "recv: payload mismatch");
507 num++;
508 };
509
510 return num;
511}
512
513static int do_main(void)
514{
515 unsigned long tstop, treport, tcur;
516 int fdt = -1, fdr = -1, len, tx = 0, rx = 0;
517
518 if (!cfg_only_tx)
519 fdr = setup_rx();
520 if (!cfg_only_rx)
521 fdt = setup_tx();
522
523 len = build_packet();
524
525 tcur = util_gettime();
526 treport = tcur + 1000;
527 tstop = tcur + (cfg_num_secs * 1000);
528
529 while (1) {
530 if (!cfg_only_rx)
531 tx += do_tx(fdt, buf, len);
532
533 if (!cfg_only_tx)
534 rx += do_rx(fdr);
535
536 if (cfg_num_secs) {
537 tcur = util_gettime();
538 if (tcur >= tstop)
539 break;
540 if (tcur >= treport) {
541 fprintf(stderr, "pkts: tx=%u rx=%u\n", tx, rx);
542 tx = 0;
543 rx = 0;
544 treport = tcur + 1000;
545 }
546 } else {
547 if (tx == cfg_num_pkt)
548 break;
549 }
550 }
551
552 /* read straggler packets, if any */
553 if (rx < tx) {
554 tstop = util_gettime() + 100;
555 while (rx < tx) {
556 tcur = util_gettime();
557 if (tcur >= tstop)
558 break;
559
560 do_poll(fdr, POLLIN, tstop - tcur);
561 rx += do_rx(fdr);
562 }
563 }
564
565 fprintf(stderr, "pkts: tx=%u rx=%u\n", tx, rx);
566
567 if (fdr != -1 && close(fdr))
568 error(1, errno, "close rx");
569 if (fdt != -1 && close(fdt))
570 error(1, errno, "close tx");
571
572 /*
573 * success (== 0) only if received all packets
574 * unless failure is expected, in which case none must arrive.
575 */
576 if (cfg_expect_failure)
577 return rx != 0;
578 else
579 return rx != tx;
580}
581
582
583static void __attribute__((noreturn)) usage(const char *filepath)
584{
585 fprintf(stderr, "Usage: %s [-e gre|gue|bare|none] [-i 4|6] [-l len] "
586 "[-O 4|6] [-o 4|6] [-n num] [-t secs] [-R] [-T] "
587 "[-s <osrc> [-d <odst>] [-S <isrc>] [-D <idst>] "
588 "[-x <otos>] [-X <itos>] [-f <isport>] [-F]\n",
589 filepath);
590 exit(1);
591}
592
593static void parse_addr(int family, void *addr, const char *optarg)
594{
595 int ret;
596
597 ret = inet_pton(family, optarg, addr);
598 if (ret == -1)
599 error(1, errno, "inet_pton");
600 if (ret == 0)
601 error(1, 0, "inet_pton: bad string");
602}
603
604static void parse_addr4(struct sockaddr_in *addr, const char *optarg)
605{
606 parse_addr(AF_INET, &addr->sin_addr, optarg);
607}
608
609static void parse_addr6(struct sockaddr_in6 *addr, const char *optarg)
610{
611 parse_addr(AF_INET6, &addr->sin6_addr, optarg);
612}
613
614static int parse_protocol_family(const char *filepath, const char *optarg)
615{
616 if (!strcmp(optarg, "4"))
617 return PF_INET;
618 if (!strcmp(optarg, "6"))
619 return PF_INET6;
620
621 usage(filepath);
622}
623
624static void parse_opts(int argc, char **argv)
625{
626 int c;
627
628 while ((c = getopt(argc, argv, "d:D:e:f:Fhi:l:n:o:O:Rs:S:t:Tx:X:")) != -1) {
629 switch (c) {
630 case 'd':
631 if (cfg_l3_outer == AF_UNSPEC)
632 error(1, 0, "-d must be preceded by -o");
633 if (cfg_l3_outer == AF_INET)
634 parse_addr4(&out_daddr4, optarg);
635 else
636 parse_addr6(&out_daddr6, optarg);
637 break;
638 case 'D':
639 if (cfg_l3_inner == AF_UNSPEC)
640 error(1, 0, "-D must be preceded by -i");
641 if (cfg_l3_inner == AF_INET)
642 parse_addr4(&in_daddr4, optarg);
643 else
644 parse_addr6(&in_daddr6, optarg);
645 break;
646 case 'e':
647 if (!strcmp(optarg, "gre"))
648 cfg_encap_proto = IPPROTO_GRE;
649 else if (!strcmp(optarg, "gue"))
650 cfg_encap_proto = IPPROTO_UDP;
651 else if (!strcmp(optarg, "bare"))
652 cfg_encap_proto = IPPROTO_IPIP;
653 else if (!strcmp(optarg, "none"))
654 cfg_encap_proto = IPPROTO_IP; /* == 0 */
655 else
656 usage(argv[0]);
657 break;
658 case 'f':
659 cfg_src_port = strtol(optarg, NULL, 0);
660 break;
661 case 'F':
662 cfg_expect_failure = true;
663 break;
664 case 'h':
665 usage(argv[0]);
666 break;
667 case 'i':
668 if (!strcmp(optarg, "4"))
669 cfg_l3_inner = PF_INET;
670 else if (!strcmp(optarg, "6"))
671 cfg_l3_inner = PF_INET6;
672 else
673 usage(argv[0]);
674 break;
675 case 'l':
676 cfg_payload_len = strtol(optarg, NULL, 0);
677 break;
678 case 'n':
679 cfg_num_pkt = strtol(optarg, NULL, 0);
680 break;
681 case 'o':
682 cfg_l3_outer = parse_protocol_family(argv[0], optarg);
683 break;
684 case 'O':
685 cfg_l3_extra = parse_protocol_family(argv[0], optarg);
686 break;
687 case 'R':
688 cfg_only_rx = true;
689 break;
690 case 's':
691 if (cfg_l3_outer == AF_INET)
692 parse_addr4(&out_saddr4, optarg);
693 else
694 parse_addr6(&out_saddr6, optarg);
695 break;
696 case 'S':
697 if (cfg_l3_inner == AF_INET)
698 parse_addr4(&in_saddr4, optarg);
699 else
700 parse_addr6(&in_saddr6, optarg);
701 break;
702 case 't':
703 cfg_num_secs = strtol(optarg, NULL, 0);
704 break;
705 case 'T':
706 cfg_only_tx = true;
707 break;
708 case 'x':
709 cfg_dsfield_outer = strtol(optarg, NULL, 0);
710 break;
711 case 'X':
712 cfg_dsfield_inner = strtol(optarg, NULL, 0);
713 break;
714 }
715 }
716
717 if (cfg_only_rx && cfg_only_tx)
718 error(1, 0, "options: cannot combine rx-only and tx-only");
719
720 if (cfg_encap_proto && cfg_l3_outer == AF_UNSPEC)
721 error(1, 0, "options: must specify outer with encap");
722 else if ((!cfg_encap_proto) && cfg_l3_outer != AF_UNSPEC)
723 error(1, 0, "options: cannot combine no-encap and outer");
724 else if ((!cfg_encap_proto) && cfg_l3_extra != AF_UNSPEC)
725 error(1, 0, "options: cannot combine no-encap and extra");
726
727 if (cfg_l3_inner == AF_UNSPEC)
728 cfg_l3_inner = AF_INET6;
729 if (cfg_l3_inner == AF_INET6 && cfg_encap_proto == IPPROTO_IPIP)
730 cfg_encap_proto = IPPROTO_IPV6;
731
732 /* RFC 6040 4.2:
733 * on decap, if outer encountered congestion (CE == 0x3),
734 * but inner cannot encode ECN (NoECT == 0x0), then drop packet.
735 */
736 if (((cfg_dsfield_outer & 0x3) == 0x3) &&
737 ((cfg_dsfield_inner & 0x3) == 0x0))
738 cfg_expect_failure = true;
739}
740
741static void print_opts(void)
742{
743 if (cfg_l3_inner == PF_INET6) {
744 util_printaddr("inner.dest6", (void *) &in_daddr6);
745 util_printaddr("inner.source6", (void *) &in_saddr6);
746 } else {
747 util_printaddr("inner.dest4", (void *) &in_daddr4);
748 util_printaddr("inner.source4", (void *) &in_saddr4);
749 }
750
751 if (!cfg_l3_outer)
752 return;
753
754 fprintf(stderr, "encap proto: %u\n", cfg_encap_proto);
755
756 if (cfg_l3_outer == PF_INET6) {
757 util_printaddr("outer.dest6", (void *) &out_daddr6);
758 util_printaddr("outer.source6", (void *) &out_saddr6);
759 } else {
760 util_printaddr("outer.dest4", (void *) &out_daddr4);
761 util_printaddr("outer.source4", (void *) &out_saddr4);
762 }
763
764 if (!cfg_l3_extra)
765 return;
766
767 if (cfg_l3_outer == PF_INET6) {
768 util_printaddr("extra.dest6", (void *) &extra_daddr6);
769 util_printaddr("extra.source6", (void *) &extra_saddr6);
770 } else {
771 util_printaddr("extra.dest4", (void *) &extra_daddr4);
772 util_printaddr("extra.source4", (void *) &extra_saddr4);
773 }
774
775}
776
777int main(int argc, char **argv)
778{
779 parse_opts(argc, argv);
780 print_opts();
781 return do_main();
782}
diff --git a/tools/testing/selftests/bpf/test_flow_dissector.sh b/tools/testing/selftests/bpf/test_flow_dissector.sh
new file mode 100755
index 000000000000..c0fb073b5eab
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_flow_dissector.sh
@@ -0,0 +1,115 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Load BPF flow dissector and verify it correctly dissects traffic
5export TESTNAME=test_flow_dissector
6unmount=0
7
8# Kselftest framework requirement - SKIP code is 4.
9ksft_skip=4
10
11msg="skip all tests:"
12if [ $UID != 0 ]; then
13 echo $msg please run this as root >&2
14 exit $ksft_skip
15fi
16
17# This test needs to be run in a network namespace with in_netns.sh. Check if
18# this is the case and run it with in_netns.sh if it is being run in the root
19# namespace.
20if [[ -z $(ip netns identify $$) ]]; then
21 ../net/in_netns.sh "$0" "$@"
22 exit $?
23fi
24
25# Determine selftest success via shell exit code
26exit_handler()
27{
28 if (( $? == 0 )); then
29 echo "selftests: $TESTNAME [PASS]";
30 else
31 echo "selftests: $TESTNAME [FAILED]";
32 fi
33
34 set +e
35
36 # Cleanup
37 tc filter del dev lo ingress pref 1337 2> /dev/null
38 tc qdisc del dev lo ingress 2> /dev/null
39 ./flow_dissector_load -d 2> /dev/null
40 if [ $unmount -ne 0 ]; then
41 umount bpffs 2> /dev/null
42 fi
43}
44
45# Exit script immediately (well catched by trap handler) if any
46# program/thing exits with a non-zero status.
47set -e
48
49# (Use 'trap -l' to list meaning of numbers)
50trap exit_handler 0 2 3 6 9
51
52# Mount BPF file system
53if /bin/mount | grep /sys/fs/bpf > /dev/null; then
54 echo "bpffs already mounted"
55else
56 echo "bpffs not mounted. Mounting..."
57 unmount=1
58 /bin/mount bpffs /sys/fs/bpf -t bpf
59fi
60
61# Attach BPF program
62./flow_dissector_load -p bpf_flow.o -s dissect
63
64# Setup
65tc qdisc add dev lo ingress
66
67echo "Testing IPv4..."
68# Drops all IP/UDP packets coming from port 9
69tc filter add dev lo parent ffff: protocol ip pref 1337 flower ip_proto \
70 udp src_port 9 action drop
71
72# Send 10 IPv4/UDP packets from port 8. Filter should not drop any.
73./test_flow_dissector -i 4 -f 8
74# Send 10 IPv4/UDP packets from port 9. Filter should drop all.
75./test_flow_dissector -i 4 -f 9 -F
76# Send 10 IPv4/UDP packets from port 10. Filter should not drop any.
77./test_flow_dissector -i 4 -f 10
78
79echo "Testing IPIP..."
80# Send 10 IPv4/IPv4/UDP packets from port 8. Filter should not drop any.
81./with_addr.sh ./with_tunnels.sh ./test_flow_dissector -o 4 -e bare -i 4 \
82 -D 192.168.0.1 -S 1.1.1.1 -f 8
83# Send 10 IPv4/IPv4/UDP packets from port 9. Filter should drop all.
84./with_addr.sh ./with_tunnels.sh ./test_flow_dissector -o 4 -e bare -i 4 \
85 -D 192.168.0.1 -S 1.1.1.1 -f 9 -F
86# Send 10 IPv4/IPv4/UDP packets from port 10. Filter should not drop any.
87./with_addr.sh ./with_tunnels.sh ./test_flow_dissector -o 4 -e bare -i 4 \
88 -D 192.168.0.1 -S 1.1.1.1 -f 10
89
90echo "Testing IPv4 + GRE..."
91# Send 10 IPv4/GRE/IPv4/UDP packets from port 8. Filter should not drop any.
92./with_addr.sh ./with_tunnels.sh ./test_flow_dissector -o 4 -e gre -i 4 \
93 -D 192.168.0.1 -S 1.1.1.1 -f 8
94# Send 10 IPv4/GRE/IPv4/UDP packets from port 9. Filter should drop all.
95./with_addr.sh ./with_tunnels.sh ./test_flow_dissector -o 4 -e gre -i 4 \
96 -D 192.168.0.1 -S 1.1.1.1 -f 9 -F
97# Send 10 IPv4/GRE/IPv4/UDP packets from port 10. Filter should not drop any.
98./with_addr.sh ./with_tunnels.sh ./test_flow_dissector -o 4 -e gre -i 4 \
99 -D 192.168.0.1 -S 1.1.1.1 -f 10
100
101tc filter del dev lo ingress pref 1337
102
103echo "Testing IPv6..."
104# Drops all IPv6/UDP packets coming from port 9
105tc filter add dev lo parent ffff: protocol ipv6 pref 1337 flower ip_proto \
106 udp src_port 9 action drop
107
108# Send 10 IPv6/UDP packets from port 8. Filter should not drop any.
109./test_flow_dissector -i 6 -f 8
110# Send 10 IPv6/UDP packets from port 9. Filter should drop all.
111./test_flow_dissector -i 6 -f 9 -F
112# Send 10 IPv6/UDP packets from port 10. Filter should not drop any.
113./test_flow_dissector -i 6 -f 10
114
115exit 0
diff --git a/tools/testing/selftests/bpf/test_libbpf.sh b/tools/testing/selftests/bpf/test_libbpf.sh
index d97dc914cd49..156d89f1edcc 100755
--- a/tools/testing/selftests/bpf/test_libbpf.sh
+++ b/tools/testing/selftests/bpf/test_libbpf.sh
@@ -6,7 +6,7 @@ export TESTNAME=test_libbpf
6# Determine selftest success via shell exit code 6# Determine selftest success via shell exit code
7exit_handler() 7exit_handler()
8{ 8{
9 if (( $? == 0 )); then 9 if [ $? -eq 0 ]; then
10 echo "selftests: $TESTNAME [PASS]"; 10 echo "selftests: $TESTNAME [PASS]";
11 else 11 else
12 echo "$TESTNAME: failed at file $LAST_LOADED" 1>&2 12 echo "$TESTNAME: failed at file $LAST_LOADED" 1>&2
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 9b552c0fc47d..4db2116e52be 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -15,6 +15,7 @@
15#include <string.h> 15#include <string.h>
16#include <assert.h> 16#include <assert.h>
17#include <stdlib.h> 17#include <stdlib.h>
18#include <time.h>
18 19
19#include <sys/wait.h> 20#include <sys/wait.h>
20#include <sys/socket.h> 21#include <sys/socket.h>
@@ -471,6 +472,122 @@ static void test_devmap(int task, void *data)
471 close(fd); 472 close(fd);
472} 473}
473 474
475static void test_queuemap(int task, void *data)
476{
477 const int MAP_SIZE = 32;
478 __u32 vals[MAP_SIZE + MAP_SIZE/2], val;
479 int fd, i;
480
481 /* Fill test values to be used */
482 for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
483 vals[i] = rand();
484
485 /* Invalid key size */
486 fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 4, sizeof(val), MAP_SIZE,
487 map_flags);
488 assert(fd < 0 && errno == EINVAL);
489
490 fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(val), MAP_SIZE,
491 map_flags);
492 /* Queue map does not support BPF_F_NO_PREALLOC */
493 if (map_flags & BPF_F_NO_PREALLOC) {
494 assert(fd < 0 && errno == EINVAL);
495 return;
496 }
497 if (fd < 0) {
498 printf("Failed to create queuemap '%s'!\n", strerror(errno));
499 exit(1);
500 }
501
502 /* Push MAP_SIZE elements */
503 for (i = 0; i < MAP_SIZE; i++)
504 assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
505
506 /* Check that element cannot be pushed due to max_entries limit */
507 assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 &&
508 errno == E2BIG);
509
510 /* Peek element */
511 assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]);
512
513 /* Replace half elements */
514 for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
515 assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
516
517 /* Pop all elements */
518 for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++)
519 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
520 val == vals[i]);
521
522 /* Check that there are not elements left */
523 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 &&
524 errno == ENOENT);
525
526 /* Check that non supported functions set errno to EINVAL */
527 assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
528 assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
529
530 close(fd);
531}
532
533static void test_stackmap(int task, void *data)
534{
535 const int MAP_SIZE = 32;
536 __u32 vals[MAP_SIZE + MAP_SIZE/2], val;
537 int fd, i;
538
539 /* Fill test values to be used */
540 for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
541 vals[i] = rand();
542
543 /* Invalid key size */
544 fd = bpf_create_map(BPF_MAP_TYPE_STACK, 4, sizeof(val), MAP_SIZE,
545 map_flags);
546 assert(fd < 0 && errno == EINVAL);
547
548 fd = bpf_create_map(BPF_MAP_TYPE_STACK, 0, sizeof(val), MAP_SIZE,
549 map_flags);
550 /* Stack map does not support BPF_F_NO_PREALLOC */
551 if (map_flags & BPF_F_NO_PREALLOC) {
552 assert(fd < 0 && errno == EINVAL);
553 return;
554 }
555 if (fd < 0) {
556 printf("Failed to create stackmap '%s'!\n", strerror(errno));
557 exit(1);
558 }
559
560 /* Push MAP_SIZE elements */
561 for (i = 0; i < MAP_SIZE; i++)
562 assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
563
564 /* Check that element cannot be pushed due to max_entries limit */
565 assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 &&
566 errno == E2BIG);
567
568 /* Peek element */
569 assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[i - 1]);
570
571 /* Replace half elements */
572 for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
573 assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
574
575 /* Pop all elements */
576 for (i = MAP_SIZE + MAP_SIZE/2 - 1; i >= MAP_SIZE/2; i--)
577 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
578 val == vals[i]);
579
580 /* Check that there are not elements left */
581 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 &&
582 errno == ENOENT);
583
584 /* Check that non supported functions set errno to EINVAL */
585 assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
586 assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
587
588 close(fd);
589}
590
474#include <sys/socket.h> 591#include <sys/socket.h>
475#include <sys/ioctl.h> 592#include <sys/ioctl.h>
476#include <arpa/inet.h> 593#include <arpa/inet.h>
@@ -1434,10 +1551,15 @@ static void run_all_tests(void)
1434 test_map_wronly(); 1551 test_map_wronly();
1435 1552
1436 test_reuseport_array(); 1553 test_reuseport_array();
1554
1555 test_queuemap(0, NULL);
1556 test_stackmap(0, NULL);
1437} 1557}
1438 1558
1439int main(void) 1559int main(void)
1440{ 1560{
1561 srand(time(NULL));
1562
1441 map_flags = 0; 1563 map_flags = 0;
1442 run_all_tests(); 1564 run_all_tests();
1443 1565
diff --git a/tools/testing/selftests/bpf/test_netcnt.c b/tools/testing/selftests/bpf/test_netcnt.c
new file mode 100644
index 000000000000..7887df693399
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_netcnt.c
@@ -0,0 +1,158 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <errno.h>
6#include <assert.h>
7#include <sys/sysinfo.h>
8#include <sys/time.h>
9
10#include <linux/bpf.h>
11#include <bpf/bpf.h>
12#include <bpf/libbpf.h>
13
14#include "cgroup_helpers.h"
15#include "bpf_rlimit.h"
16#include "netcnt_common.h"
17
18#define BPF_PROG "./netcnt_prog.o"
19#define TEST_CGROUP "/test-network-counters/"
20
21static int bpf_find_map(const char *test, struct bpf_object *obj,
22 const char *name)
23{
24 struct bpf_map *map;
25
26 map = bpf_object__find_map_by_name(obj, name);
27 if (!map) {
28 printf("%s:FAIL:map '%s' not found\n", test, name);
29 return -1;
30 }
31 return bpf_map__fd(map);
32}
33
34int main(int argc, char **argv)
35{
36 struct percpu_net_cnt *percpu_netcnt;
37 struct bpf_cgroup_storage_key key;
38 int map_fd, percpu_map_fd;
39 int error = EXIT_FAILURE;
40 struct net_cnt netcnt;
41 struct bpf_object *obj;
42 int prog_fd, cgroup_fd;
43 unsigned long packets;
44 unsigned long bytes;
45 int cpu, nproc;
46 __u32 prog_cnt;
47
48 nproc = get_nprocs_conf();
49 percpu_netcnt = malloc(sizeof(*percpu_netcnt) * nproc);
50 if (!percpu_netcnt) {
51 printf("Not enough memory for per-cpu area (%d cpus)\n", nproc);
52 goto err;
53 }
54
55 if (bpf_prog_load(BPF_PROG, BPF_PROG_TYPE_CGROUP_SKB,
56 &obj, &prog_fd)) {
57 printf("Failed to load bpf program\n");
58 goto out;
59 }
60
61 if (setup_cgroup_environment()) {
62 printf("Failed to load bpf program\n");
63 goto err;
64 }
65
66 /* Create a cgroup, get fd, and join it */
67 cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
68 if (!cgroup_fd) {
69 printf("Failed to create test cgroup\n");
70 goto err;
71 }
72
73 if (join_cgroup(TEST_CGROUP)) {
74 printf("Failed to join cgroup\n");
75 goto err;
76 }
77
78 /* Attach bpf program */
79 if (bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0)) {
80 printf("Failed to attach bpf program");
81 goto err;
82 }
83
84 assert(system("ping localhost -6 -c 10000 -f -q > /dev/null") == 0);
85
86 if (bpf_prog_query(cgroup_fd, BPF_CGROUP_INET_EGRESS, 0, NULL, NULL,
87 &prog_cnt)) {
88 printf("Failed to query attached programs");
89 goto err;
90 }
91
92 map_fd = bpf_find_map(__func__, obj, "netcnt");
93 if (map_fd < 0) {
94 printf("Failed to find bpf map with net counters");
95 goto err;
96 }
97
98 percpu_map_fd = bpf_find_map(__func__, obj, "percpu_netcnt");
99 if (percpu_map_fd < 0) {
100 printf("Failed to find bpf map with percpu net counters");
101 goto err;
102 }
103
104 if (bpf_map_get_next_key(map_fd, NULL, &key)) {
105 printf("Failed to get key in cgroup storage\n");
106 goto err;
107 }
108
109 if (bpf_map_lookup_elem(map_fd, &key, &netcnt)) {
110 printf("Failed to lookup cgroup storage\n");
111 goto err;
112 }
113
114 if (bpf_map_lookup_elem(percpu_map_fd, &key, &percpu_netcnt[0])) {
115 printf("Failed to lookup percpu cgroup storage\n");
116 goto err;
117 }
118
119 /* Some packets can be still in per-cpu cache, but not more than
120 * MAX_PERCPU_PACKETS.
121 */
122 packets = netcnt.packets;
123 bytes = netcnt.bytes;
124 for (cpu = 0; cpu < nproc; cpu++) {
125 if (percpu_netcnt[cpu].packets > MAX_PERCPU_PACKETS) {
126 printf("Unexpected percpu value: %llu\n",
127 percpu_netcnt[cpu].packets);
128 goto err;
129 }
130
131 packets += percpu_netcnt[cpu].packets;
132 bytes += percpu_netcnt[cpu].bytes;
133 }
134
135 /* No packets should be lost */
136 if (packets != 10000) {
137 printf("Unexpected packet count: %lu\n", packets);
138 goto err;
139 }
140
141 /* Let's check that bytes counter matches the number of packets
142 * multiplied by the size of ipv6 ICMP packet.
143 */
144 if (bytes != packets * 104) {
145 printf("Unexpected bytes count: %lu\n", bytes);
146 goto err;
147 }
148
149 error = 0;
150 printf("test_netcnt:PASS\n");
151
152err:
153 cleanup_cgroup_environment();
154 free(percpu_netcnt);
155
156out:
157 return error;
158}
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 0ef68204c84b..2d3c04f45530 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -112,13 +112,13 @@ static void test_pkt_access(void)
112 112
113 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4), 113 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
114 NULL, NULL, &retval, &duration); 114 NULL, NULL, &retval, &duration);
115 CHECK(err || errno || retval, "ipv4", 115 CHECK(err || retval, "ipv4",
116 "err %d errno %d retval %d duration %d\n", 116 "err %d errno %d retval %d duration %d\n",
117 err, errno, retval, duration); 117 err, errno, retval, duration);
118 118
119 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v6, sizeof(pkt_v6), 119 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v6, sizeof(pkt_v6),
120 NULL, NULL, &retval, &duration); 120 NULL, NULL, &retval, &duration);
121 CHECK(err || errno || retval, "ipv6", 121 CHECK(err || retval, "ipv6",
122 "err %d errno %d retval %d duration %d\n", 122 "err %d errno %d retval %d duration %d\n",
123 err, errno, retval, duration); 123 err, errno, retval, duration);
124 bpf_object__close(obj); 124 bpf_object__close(obj);
@@ -153,14 +153,14 @@ static void test_xdp(void)
153 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 153 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
154 buf, &size, &retval, &duration); 154 buf, &size, &retval, &duration);
155 155
156 CHECK(err || errno || retval != XDP_TX || size != 74 || 156 CHECK(err || retval != XDP_TX || size != 74 ||
157 iph->protocol != IPPROTO_IPIP, "ipv4", 157 iph->protocol != IPPROTO_IPIP, "ipv4",
158 "err %d errno %d retval %d size %d\n", 158 "err %d errno %d retval %d size %d\n",
159 err, errno, retval, size); 159 err, errno, retval, size);
160 160
161 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6), 161 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
162 buf, &size, &retval, &duration); 162 buf, &size, &retval, &duration);
163 CHECK(err || errno || retval != XDP_TX || size != 114 || 163 CHECK(err || retval != XDP_TX || size != 114 ||
164 iph6->nexthdr != IPPROTO_IPV6, "ipv6", 164 iph6->nexthdr != IPPROTO_IPV6, "ipv6",
165 "err %d errno %d retval %d size %d\n", 165 "err %d errno %d retval %d size %d\n",
166 err, errno, retval, size); 166 err, errno, retval, size);
@@ -185,13 +185,13 @@ static void test_xdp_adjust_tail(void)
185 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 185 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
186 buf, &size, &retval, &duration); 186 buf, &size, &retval, &duration);
187 187
188 CHECK(err || errno || retval != XDP_DROP, 188 CHECK(err || retval != XDP_DROP,
189 "ipv4", "err %d errno %d retval %d size %d\n", 189 "ipv4", "err %d errno %d retval %d size %d\n",
190 err, errno, retval, size); 190 err, errno, retval, size);
191 191
192 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6), 192 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
193 buf, &size, &retval, &duration); 193 buf, &size, &retval, &duration);
194 CHECK(err || errno || retval != XDP_TX || size != 54, 194 CHECK(err || retval != XDP_TX || size != 54,
195 "ipv6", "err %d errno %d retval %d size %d\n", 195 "ipv6", "err %d errno %d retval %d size %d\n",
196 err, errno, retval, size); 196 err, errno, retval, size);
197 bpf_object__close(obj); 197 bpf_object__close(obj);
@@ -254,14 +254,14 @@ static void test_l4lb(const char *file)
254 254
255 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4), 255 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
256 buf, &size, &retval, &duration); 256 buf, &size, &retval, &duration);
257 CHECK(err || errno || retval != 7/*TC_ACT_REDIRECT*/ || size != 54 || 257 CHECK(err || retval != 7/*TC_ACT_REDIRECT*/ || size != 54 ||
258 *magic != MAGIC_VAL, "ipv4", 258 *magic != MAGIC_VAL, "ipv4",
259 "err %d errno %d retval %d size %d magic %x\n", 259 "err %d errno %d retval %d size %d magic %x\n",
260 err, errno, retval, size, *magic); 260 err, errno, retval, size, *magic);
261 261
262 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6), 262 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
263 buf, &size, &retval, &duration); 263 buf, &size, &retval, &duration);
264 CHECK(err || errno || retval != 7/*TC_ACT_REDIRECT*/ || size != 74 || 264 CHECK(err || retval != 7/*TC_ACT_REDIRECT*/ || size != 74 ||
265 *magic != MAGIC_VAL, "ipv6", 265 *magic != MAGIC_VAL, "ipv6",
266 "err %d errno %d retval %d size %d magic %x\n", 266 "err %d errno %d retval %d size %d magic %x\n",
267 err, errno, retval, size, *magic); 267 err, errno, retval, size, *magic);
@@ -343,14 +343,14 @@ static void test_xdp_noinline(void)
343 343
344 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4), 344 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
345 buf, &size, &retval, &duration); 345 buf, &size, &retval, &duration);
346 CHECK(err || errno || retval != 1 || size != 54 || 346 CHECK(err || retval != 1 || size != 54 ||
347 *magic != MAGIC_VAL, "ipv4", 347 *magic != MAGIC_VAL, "ipv4",
348 "err %d errno %d retval %d size %d magic %x\n", 348 "err %d errno %d retval %d size %d magic %x\n",
349 err, errno, retval, size, *magic); 349 err, errno, retval, size, *magic);
350 350
351 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6), 351 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
352 buf, &size, &retval, &duration); 352 buf, &size, &retval, &duration);
353 CHECK(err || errno || retval != 1 || size != 74 || 353 CHECK(err || retval != 1 || size != 74 ||
354 *magic != MAGIC_VAL, "ipv6", 354 *magic != MAGIC_VAL, "ipv6",
355 "err %d errno %d retval %d size %d magic %x\n", 355 "err %d errno %d retval %d size %d magic %x\n",
356 err, errno, retval, size, *magic); 356 err, errno, retval, size, *magic);
@@ -1698,8 +1698,142 @@ static void test_task_fd_query_tp(void)
1698 "sys_enter_read"); 1698 "sys_enter_read");
1699} 1699}
1700 1700
1701static void test_reference_tracking()
1702{
1703 const char *file = "./test_sk_lookup_kern.o";
1704 struct bpf_object *obj;
1705 struct bpf_program *prog;
1706 __u32 duration;
1707 int err = 0;
1708
1709 obj = bpf_object__open(file);
1710 if (IS_ERR(obj)) {
1711 error_cnt++;
1712 return;
1713 }
1714
1715 bpf_object__for_each_program(prog, obj) {
1716 const char *title;
1717
1718 /* Ignore .text sections */
1719 title = bpf_program__title(prog, false);
1720 if (strstr(title, ".text") != NULL)
1721 continue;
1722
1723 bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
1724
1725 /* Expect verifier failure if test name has 'fail' */
1726 if (strstr(title, "fail") != NULL) {
1727 libbpf_set_print(NULL, NULL, NULL);
1728 err = !bpf_program__load(prog, "GPL", 0);
1729 libbpf_set_print(printf, printf, NULL);
1730 } else {
1731 err = bpf_program__load(prog, "GPL", 0);
1732 }
1733 CHECK(err, title, "\n");
1734 }
1735 bpf_object__close(obj);
1736}
1737
1738enum {
1739 QUEUE,
1740 STACK,
1741};
1742
1743static void test_queue_stack_map(int type)
1744{
1745 const int MAP_SIZE = 32;
1746 __u32 vals[MAP_SIZE], duration, retval, size, val;
1747 int i, err, prog_fd, map_in_fd, map_out_fd;
1748 char file[32], buf[128];
1749 struct bpf_object *obj;
1750 struct iphdr *iph = (void *)buf + sizeof(struct ethhdr);
1751
1752 /* Fill test values to be used */
1753 for (i = 0; i < MAP_SIZE; i++)
1754 vals[i] = rand();
1755
1756 if (type == QUEUE)
1757 strncpy(file, "./test_queue_map.o", sizeof(file));
1758 else if (type == STACK)
1759 strncpy(file, "./test_stack_map.o", sizeof(file));
1760 else
1761 return;
1762
1763 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
1764 if (err) {
1765 error_cnt++;
1766 return;
1767 }
1768
1769 map_in_fd = bpf_find_map(__func__, obj, "map_in");
1770 if (map_in_fd < 0)
1771 goto out;
1772
1773 map_out_fd = bpf_find_map(__func__, obj, "map_out");
1774 if (map_out_fd < 0)
1775 goto out;
1776
1777 /* Push 32 elements to the input map */
1778 for (i = 0; i < MAP_SIZE; i++) {
1779 err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0);
1780 if (err) {
1781 error_cnt++;
1782 goto out;
1783 }
1784 }
1785
1786 /* The eBPF program pushes iph.saddr in the output map,
1787 * pops the input map and saves this value in iph.daddr
1788 */
1789 for (i = 0; i < MAP_SIZE; i++) {
1790 if (type == QUEUE) {
1791 val = vals[i];
1792 pkt_v4.iph.saddr = vals[i] * 5;
1793 } else if (type == STACK) {
1794 val = vals[MAP_SIZE - 1 - i];
1795 pkt_v4.iph.saddr = vals[MAP_SIZE - 1 - i] * 5;
1796 }
1797
1798 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
1799 buf, &size, &retval, &duration);
1800 if (err || retval || size != sizeof(pkt_v4) ||
1801 iph->daddr != val)
1802 break;
1803 }
1804
1805 CHECK(err || retval || size != sizeof(pkt_v4) || iph->daddr != val,
1806 "bpf_map_pop_elem",
1807 "err %d errno %d retval %d size %d iph->daddr %u\n",
1808 err, errno, retval, size, iph->daddr);
1809
1810 /* Queue is empty, program should return TC_ACT_SHOT */
1811 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
1812 buf, &size, &retval, &duration);
1813 CHECK(err || retval != 2 /* TC_ACT_SHOT */|| size != sizeof(pkt_v4),
1814 "check-queue-stack-map-empty",
1815 "err %d errno %d retval %d size %d\n",
1816 err, errno, retval, size);
1817
1818 /* Check that the program pushed elements correctly */
1819 for (i = 0; i < MAP_SIZE; i++) {
1820 err = bpf_map_lookup_and_delete_elem(map_out_fd, NULL, &val);
1821 if (err || val != vals[i] * 5)
1822 break;
1823 }
1824
1825 CHECK(i != MAP_SIZE && (err || val != vals[i] * 5),
1826 "bpf_map_push_elem", "err %d value %u\n", err, val);
1827
1828out:
1829 pkt_v4.iph.saddr = 0;
1830 bpf_object__close(obj);
1831}
1832
1701int main(void) 1833int main(void)
1702{ 1834{
1835 srand(time(NULL));
1836
1703 jit_enabled = is_jit_enabled(); 1837 jit_enabled = is_jit_enabled();
1704 1838
1705 test_pkt_access(); 1839 test_pkt_access();
@@ -1719,6 +1853,9 @@ int main(void)
1719 test_get_stack_raw_tp(); 1853 test_get_stack_raw_tp();
1720 test_task_fd_query_rawtp(); 1854 test_task_fd_query_rawtp();
1721 test_task_fd_query_tp(); 1855 test_task_fd_query_tp();
1856 test_reference_tracking();
1857 test_queue_stack_map(QUEUE);
1858 test_queue_stack_map(STACK);
1722 1859
1723 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); 1860 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
1724 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 1861 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/tools/testing/selftests/bpf/test_queue_map.c b/tools/testing/selftests/bpf/test_queue_map.c
new file mode 100644
index 000000000000..87db1f9da33d
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_queue_map.c
@@ -0,0 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Politecnico di Torino
3#define MAP_TYPE BPF_MAP_TYPE_QUEUE
4#include "test_queue_stack_map.h"
diff --git a/tools/testing/selftests/bpf/test_queue_stack_map.h b/tools/testing/selftests/bpf/test_queue_stack_map.h
new file mode 100644
index 000000000000..295b9b3bc5c7
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_queue_stack_map.h
@@ -0,0 +1,59 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (c) 2018 Politecnico di Torino
3#include <stddef.h>
4#include <string.h>
5#include <linux/bpf.h>
6#include <linux/if_ether.h>
7#include <linux/ip.h>
8#include <linux/pkt_cls.h>
9#include "bpf_helpers.h"
10
11int _version SEC("version") = 1;
12
13struct bpf_map_def __attribute__ ((section("maps"), used)) map_in = {
14 .type = MAP_TYPE,
15 .key_size = 0,
16 .value_size = sizeof(__u32),
17 .max_entries = 32,
18 .map_flags = 0,
19};
20
21struct bpf_map_def __attribute__ ((section("maps"), used)) map_out = {
22 .type = MAP_TYPE,
23 .key_size = 0,
24 .value_size = sizeof(__u32),
25 .max_entries = 32,
26 .map_flags = 0,
27};
28
29SEC("test")
30int _test(struct __sk_buff *skb)
31{
32 void *data_end = (void *)(long)skb->data_end;
33 void *data = (void *)(long)skb->data;
34 struct ethhdr *eth = (struct ethhdr *)(data);
35 __u32 value;
36 int err;
37
38 if (eth + 1 > data_end)
39 return TC_ACT_SHOT;
40
41 struct iphdr *iph = (struct iphdr *)(eth + 1);
42
43 if (iph + 1 > data_end)
44 return TC_ACT_SHOT;
45
46 err = bpf_map_pop_elem(&map_in, &value);
47 if (err)
48 return TC_ACT_SHOT;
49
50 iph->daddr = value;
51
52 err = bpf_map_push_elem(&map_out, &iph->saddr, 0);
53 if (err)
54 return TC_ACT_SHOT;
55
56 return TC_ACT_OK;
57}
58
59char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_section_names.c b/tools/testing/selftests/bpf/test_section_names.c
new file mode 100644
index 000000000000..7c4f41572b1c
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_section_names.c
@@ -0,0 +1,208 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <err.h>
5#include <bpf/libbpf.h>
6
7#include "bpf_util.h"
8
9struct sec_name_test {
10 const char sec_name[32];
11 struct {
12 int rc;
13 enum bpf_prog_type prog_type;
14 enum bpf_attach_type expected_attach_type;
15 } expected_load;
16 struct {
17 int rc;
18 enum bpf_attach_type attach_type;
19 } expected_attach;
20};
21
22static struct sec_name_test tests[] = {
23 {"InvAliD", {-EINVAL, 0, 0}, {-EINVAL, 0} },
24 {"cgroup", {-EINVAL, 0, 0}, {-EINVAL, 0} },
25 {"socket", {0, BPF_PROG_TYPE_SOCKET_FILTER, 0}, {-EINVAL, 0} },
26 {"kprobe/", {0, BPF_PROG_TYPE_KPROBE, 0}, {-EINVAL, 0} },
27 {"kretprobe/", {0, BPF_PROG_TYPE_KPROBE, 0}, {-EINVAL, 0} },
28 {"classifier", {0, BPF_PROG_TYPE_SCHED_CLS, 0}, {-EINVAL, 0} },
29 {"action", {0, BPF_PROG_TYPE_SCHED_ACT, 0}, {-EINVAL, 0} },
30 {"tracepoint/", {0, BPF_PROG_TYPE_TRACEPOINT, 0}, {-EINVAL, 0} },
31 {
32 "raw_tracepoint/",
33 {0, BPF_PROG_TYPE_RAW_TRACEPOINT, 0},
34 {-EINVAL, 0},
35 },
36 {"xdp", {0, BPF_PROG_TYPE_XDP, 0}, {-EINVAL, 0} },
37 {"perf_event", {0, BPF_PROG_TYPE_PERF_EVENT, 0}, {-EINVAL, 0} },
38 {"lwt_in", {0, BPF_PROG_TYPE_LWT_IN, 0}, {-EINVAL, 0} },
39 {"lwt_out", {0, BPF_PROG_TYPE_LWT_OUT, 0}, {-EINVAL, 0} },
40 {"lwt_xmit", {0, BPF_PROG_TYPE_LWT_XMIT, 0}, {-EINVAL, 0} },
41 {"lwt_seg6local", {0, BPF_PROG_TYPE_LWT_SEG6LOCAL, 0}, {-EINVAL, 0} },
42 {
43 "cgroup_skb/ingress",
44 {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
45 {0, BPF_CGROUP_INET_INGRESS},
46 },
47 {
48 "cgroup_skb/egress",
49 {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
50 {0, BPF_CGROUP_INET_EGRESS},
51 },
52 {"cgroup/skb", {0, BPF_PROG_TYPE_CGROUP_SKB, 0}, {-EINVAL, 0} },
53 {
54 "cgroup/sock",
55 {0, BPF_PROG_TYPE_CGROUP_SOCK, 0},
56 {0, BPF_CGROUP_INET_SOCK_CREATE},
57 },
58 {
59 "cgroup/post_bind4",
60 {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET4_POST_BIND},
61 {0, BPF_CGROUP_INET4_POST_BIND},
62 },
63 {
64 "cgroup/post_bind6",
65 {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET6_POST_BIND},
66 {0, BPF_CGROUP_INET6_POST_BIND},
67 },
68 {
69 "cgroup/dev",
70 {0, BPF_PROG_TYPE_CGROUP_DEVICE, 0},
71 {0, BPF_CGROUP_DEVICE},
72 },
73 {"sockops", {0, BPF_PROG_TYPE_SOCK_OPS, 0}, {0, BPF_CGROUP_SOCK_OPS} },
74 {
75 "sk_skb/stream_parser",
76 {0, BPF_PROG_TYPE_SK_SKB, 0},
77 {0, BPF_SK_SKB_STREAM_PARSER},
78 },
79 {
80 "sk_skb/stream_verdict",
81 {0, BPF_PROG_TYPE_SK_SKB, 0},
82 {0, BPF_SK_SKB_STREAM_VERDICT},
83 },
84 {"sk_skb", {0, BPF_PROG_TYPE_SK_SKB, 0}, {-EINVAL, 0} },
85 {"sk_msg", {0, BPF_PROG_TYPE_SK_MSG, 0}, {0, BPF_SK_MSG_VERDICT} },
86 {"lirc_mode2", {0, BPF_PROG_TYPE_LIRC_MODE2, 0}, {0, BPF_LIRC_MODE2} },
87 {
88 "flow_dissector",
89 {0, BPF_PROG_TYPE_FLOW_DISSECTOR, 0},
90 {0, BPF_FLOW_DISSECTOR},
91 },
92 {
93 "cgroup/bind4",
94 {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND},
95 {0, BPF_CGROUP_INET4_BIND},
96 },
97 {
98 "cgroup/bind6",
99 {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND},
100 {0, BPF_CGROUP_INET6_BIND},
101 },
102 {
103 "cgroup/connect4",
104 {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT},
105 {0, BPF_CGROUP_INET4_CONNECT},
106 },
107 {
108 "cgroup/connect6",
109 {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
110 {0, BPF_CGROUP_INET6_CONNECT},
111 },
112 {
113 "cgroup/sendmsg4",
114 {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG},
115 {0, BPF_CGROUP_UDP4_SENDMSG},
116 },
117 {
118 "cgroup/sendmsg6",
119 {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
120 {0, BPF_CGROUP_UDP6_SENDMSG},
121 },
122};
123
124static int test_prog_type_by_name(const struct sec_name_test *test)
125{
126 enum bpf_attach_type expected_attach_type;
127 enum bpf_prog_type prog_type;
128 int rc;
129
130 rc = libbpf_prog_type_by_name(test->sec_name, &prog_type,
131 &expected_attach_type);
132
133 if (rc != test->expected_load.rc) {
134 warnx("prog: unexpected rc=%d for %s", rc, test->sec_name);
135 return -1;
136 }
137
138 if (rc)
139 return 0;
140
141 if (prog_type != test->expected_load.prog_type) {
142 warnx("prog: unexpected prog_type=%d for %s", prog_type,
143 test->sec_name);
144 return -1;
145 }
146
147 if (expected_attach_type != test->expected_load.expected_attach_type) {
148 warnx("prog: unexpected expected_attach_type=%d for %s",
149 expected_attach_type, test->sec_name);
150 return -1;
151 }
152
153 return 0;
154}
155
156static int test_attach_type_by_name(const struct sec_name_test *test)
157{
158 enum bpf_attach_type attach_type;
159 int rc;
160
161 rc = libbpf_attach_type_by_name(test->sec_name, &attach_type);
162
163 if (rc != test->expected_attach.rc) {
164 warnx("attach: unexpected rc=%d for %s", rc, test->sec_name);
165 return -1;
166 }
167
168 if (rc)
169 return 0;
170
171 if (attach_type != test->expected_attach.attach_type) {
172 warnx("attach: unexpected attach_type=%d for %s", attach_type,
173 test->sec_name);
174 return -1;
175 }
176
177 return 0;
178}
179
180static int run_test_case(const struct sec_name_test *test)
181{
182 if (test_prog_type_by_name(test))
183 return -1;
184 if (test_attach_type_by_name(test))
185 return -1;
186 return 0;
187}
188
189static int run_tests(void)
190{
191 int passes = 0;
192 int fails = 0;
193 int i;
194
195 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
196 if (run_test_case(&tests[i]))
197 ++fails;
198 else
199 ++passes;
200 }
201 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
202 return fails ? -1 : 0;
203}
204
205int main(int argc, char **argv)
206{
207 return run_tests();
208}
diff --git a/tools/testing/selftests/bpf/test_sk_lookup_kern.c b/tools/testing/selftests/bpf/test_sk_lookup_kern.c
new file mode 100644
index 000000000000..b745bdc08c2b
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_sk_lookup_kern.c
@@ -0,0 +1,180 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (c) 2018 Covalent IO, Inc. http://covalent.io
3
4#include <stddef.h>
5#include <stdbool.h>
6#include <string.h>
7#include <linux/bpf.h>
8#include <linux/if_ether.h>
9#include <linux/in.h>
10#include <linux/ip.h>
11#include <linux/ipv6.h>
12#include <linux/pkt_cls.h>
13#include <linux/tcp.h>
14#include <sys/socket.h>
15#include "bpf_helpers.h"
16#include "bpf_endian.h"
17
18int _version SEC("version") = 1;
19char _license[] SEC("license") = "GPL";
20
21/* Fill 'tuple' with L3 info, and attempt to find L4. On fail, return NULL. */
22static struct bpf_sock_tuple *get_tuple(void *data, __u64 nh_off,
23 void *data_end, __u16 eth_proto,
24 bool *ipv4)
25{
26 struct bpf_sock_tuple *result;
27 __u8 proto = 0;
28 __u64 ihl_len;
29
30 if (eth_proto == bpf_htons(ETH_P_IP)) {
31 struct iphdr *iph = (struct iphdr *)(data + nh_off);
32
33 if (iph + 1 > data_end)
34 return NULL;
35 ihl_len = iph->ihl * 4;
36 proto = iph->protocol;
37 *ipv4 = true;
38 result = (struct bpf_sock_tuple *)&iph->saddr;
39 } else if (eth_proto == bpf_htons(ETH_P_IPV6)) {
40 struct ipv6hdr *ip6h = (struct ipv6hdr *)(data + nh_off);
41
42 if (ip6h + 1 > data_end)
43 return NULL;
44 ihl_len = sizeof(*ip6h);
45 proto = ip6h->nexthdr;
46 *ipv4 = true;
47 result = (struct bpf_sock_tuple *)&ip6h->saddr;
48 }
49
50 if (data + nh_off + ihl_len > data_end || proto != IPPROTO_TCP)
51 return NULL;
52
53 return result;
54}
55
56SEC("sk_lookup_success")
57int bpf_sk_lookup_test0(struct __sk_buff *skb)
58{
59 void *data_end = (void *)(long)skb->data_end;
60 void *data = (void *)(long)skb->data;
61 struct ethhdr *eth = (struct ethhdr *)(data);
62 struct bpf_sock_tuple *tuple;
63 struct bpf_sock *sk;
64 size_t tuple_len;
65 bool ipv4;
66
67 if (eth + 1 > data_end)
68 return TC_ACT_SHOT;
69
70 tuple = get_tuple(data, sizeof(*eth), data_end, eth->h_proto, &ipv4);
71 if (!tuple || tuple + sizeof *tuple > data_end)
72 return TC_ACT_SHOT;
73
74 tuple_len = ipv4 ? sizeof(tuple->ipv4) : sizeof(tuple->ipv6);
75 sk = bpf_sk_lookup_tcp(skb, tuple, tuple_len, 0, 0);
76 if (sk)
77 bpf_sk_release(sk);
78 return sk ? TC_ACT_OK : TC_ACT_UNSPEC;
79}
80
81SEC("sk_lookup_success_simple")
82int bpf_sk_lookup_test1(struct __sk_buff *skb)
83{
84 struct bpf_sock_tuple tuple = {};
85 struct bpf_sock *sk;
86
87 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
88 if (sk)
89 bpf_sk_release(sk);
90 return 0;
91}
92
93SEC("fail_use_after_free")
94int bpf_sk_lookup_uaf(struct __sk_buff *skb)
95{
96 struct bpf_sock_tuple tuple = {};
97 struct bpf_sock *sk;
98 __u32 family = 0;
99
100 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
101 if (sk) {
102 bpf_sk_release(sk);
103 family = sk->family;
104 }
105 return family;
106}
107
108SEC("fail_modify_sk_pointer")
109int bpf_sk_lookup_modptr(struct __sk_buff *skb)
110{
111 struct bpf_sock_tuple tuple = {};
112 struct bpf_sock *sk;
113 __u32 family;
114
115 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
116 if (sk) {
117 sk += 1;
118 bpf_sk_release(sk);
119 }
120 return 0;
121}
122
123SEC("fail_modify_sk_or_null_pointer")
124int bpf_sk_lookup_modptr_or_null(struct __sk_buff *skb)
125{
126 struct bpf_sock_tuple tuple = {};
127 struct bpf_sock *sk;
128 __u32 family;
129
130 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
131 sk += 1;
132 if (sk)
133 bpf_sk_release(sk);
134 return 0;
135}
136
137SEC("fail_no_release")
138int bpf_sk_lookup_test2(struct __sk_buff *skb)
139{
140 struct bpf_sock_tuple tuple = {};
141
142 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
143 return 0;
144}
145
146SEC("fail_release_twice")
147int bpf_sk_lookup_test3(struct __sk_buff *skb)
148{
149 struct bpf_sock_tuple tuple = {};
150 struct bpf_sock *sk;
151
152 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
153 bpf_sk_release(sk);
154 bpf_sk_release(sk);
155 return 0;
156}
157
158SEC("fail_release_unchecked")
159int bpf_sk_lookup_test4(struct __sk_buff *skb)
160{
161 struct bpf_sock_tuple tuple = {};
162 struct bpf_sock *sk;
163
164 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
165 bpf_sk_release(sk);
166 return 0;
167}
168
169void lookup_no_release(struct __sk_buff *skb)
170{
171 struct bpf_sock_tuple tuple = {};
172 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), 0, 0);
173}
174
175SEC("fail_no_release_subcall")
176int bpf_sk_lookup_test5(struct __sk_buff *skb)
177{
178 lookup_no_release(skb);
179 return 0;
180}
diff --git a/tools/testing/selftests/bpf/test_socket_cookie.c b/tools/testing/selftests/bpf/test_socket_cookie.c
index 68e108e4687a..b6c2c605d8c0 100644
--- a/tools/testing/selftests/bpf/test_socket_cookie.c
+++ b/tools/testing/selftests/bpf/test_socket_cookie.c
@@ -158,11 +158,7 @@ static int run_test(int cgfd)
158 bpf_object__for_each_program(prog, pobj) { 158 bpf_object__for_each_program(prog, pobj) {
159 prog_name = bpf_program__title(prog, /*needs_copy*/ false); 159 prog_name = bpf_program__title(prog, /*needs_copy*/ false);
160 160
161 if (strcmp(prog_name, "cgroup/connect6") == 0) { 161 if (libbpf_attach_type_by_name(prog_name, &attach_type)) {
162 attach_type = BPF_CGROUP_INET6_CONNECT;
163 } else if (strcmp(prog_name, "sockops") == 0) {
164 attach_type = BPF_CGROUP_SOCK_OPS;
165 } else {
166 log_err("Unexpected prog: %s", prog_name); 162 log_err("Unexpected prog: %s", prog_name);
167 goto err; 163 goto err;
168 } 164 }
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index 0c7d9e556b47..622ade0a0957 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -28,6 +28,7 @@
28#include <linux/sock_diag.h> 28#include <linux/sock_diag.h>
29#include <linux/bpf.h> 29#include <linux/bpf.h>
30#include <linux/if_link.h> 30#include <linux/if_link.h>
31#include <linux/tls.h>
31#include <assert.h> 32#include <assert.h>
32#include <libgen.h> 33#include <libgen.h>
33 34
@@ -43,6 +44,13 @@
43int running; 44int running;
44static void running_handler(int a); 45static void running_handler(int a);
45 46
47#ifndef TCP_ULP
48# define TCP_ULP 31
49#endif
50#ifndef SOL_TLS
51# define SOL_TLS 282
52#endif
53
46/* randomly selected ports for testing on lo */ 54/* randomly selected ports for testing on lo */
47#define S1_PORT 10000 55#define S1_PORT 10000
48#define S2_PORT 10001 56#define S2_PORT 10001
@@ -69,8 +77,12 @@ int txmsg_apply;
69int txmsg_cork; 77int txmsg_cork;
70int txmsg_start; 78int txmsg_start;
71int txmsg_end; 79int txmsg_end;
80int txmsg_start_push;
81int txmsg_end_push;
72int txmsg_ingress; 82int txmsg_ingress;
73int txmsg_skb; 83int txmsg_skb;
84int ktls;
85int peek_flag;
74 86
75static const struct option long_options[] = { 87static const struct option long_options[] = {
76 {"help", no_argument, NULL, 'h' }, 88 {"help", no_argument, NULL, 'h' },
@@ -90,8 +102,12 @@ static const struct option long_options[] = {
90 {"txmsg_cork", required_argument, NULL, 'k'}, 102 {"txmsg_cork", required_argument, NULL, 'k'},
91 {"txmsg_start", required_argument, NULL, 's'}, 103 {"txmsg_start", required_argument, NULL, 's'},
92 {"txmsg_end", required_argument, NULL, 'e'}, 104 {"txmsg_end", required_argument, NULL, 'e'},
105 {"txmsg_start_push", required_argument, NULL, 'p'},
106 {"txmsg_end_push", required_argument, NULL, 'q'},
93 {"txmsg_ingress", no_argument, &txmsg_ingress, 1 }, 107 {"txmsg_ingress", no_argument, &txmsg_ingress, 1 },
94 {"txmsg_skb", no_argument, &txmsg_skb, 1 }, 108 {"txmsg_skb", no_argument, &txmsg_skb, 1 },
109 {"ktls", no_argument, &ktls, 1 },
110 {"peek", no_argument, &peek_flag, 1 },
95 {0, 0, NULL, 0 } 111 {0, 0, NULL, 0 }
96}; 112};
97 113
@@ -112,6 +128,71 @@ static void usage(char *argv[])
112 printf("\n"); 128 printf("\n");
113} 129}
114 130
131char *sock_to_string(int s)
132{
133 if (s == c1)
134 return "client1";
135 else if (s == c2)
136 return "client2";
137 else if (s == s1)
138 return "server1";
139 else if (s == s2)
140 return "server2";
141 else if (s == p1)
142 return "peer1";
143 else if (s == p2)
144 return "peer2";
145 else
146 return "unknown";
147}
148
149static int sockmap_init_ktls(int verbose, int s)
150{
151 struct tls12_crypto_info_aes_gcm_128 tls_tx = {
152 .info = {
153 .version = TLS_1_2_VERSION,
154 .cipher_type = TLS_CIPHER_AES_GCM_128,
155 },
156 };
157 struct tls12_crypto_info_aes_gcm_128 tls_rx = {
158 .info = {
159 .version = TLS_1_2_VERSION,
160 .cipher_type = TLS_CIPHER_AES_GCM_128,
161 },
162 };
163 int so_buf = 6553500;
164 int err;
165
166 err = setsockopt(s, 6, TCP_ULP, "tls", sizeof("tls"));
167 if (err) {
168 fprintf(stderr, "setsockopt: TCP_ULP(%s) failed with error %i\n", sock_to_string(s), err);
169 return -EINVAL;
170 }
171 err = setsockopt(s, SOL_TLS, TLS_TX, (void *)&tls_tx, sizeof(tls_tx));
172 if (err) {
173 fprintf(stderr, "setsockopt: TLS_TX(%s) failed with error %i\n", sock_to_string(s), err);
174 return -EINVAL;
175 }
176 err = setsockopt(s, SOL_TLS, TLS_RX, (void *)&tls_rx, sizeof(tls_rx));
177 if (err) {
178 fprintf(stderr, "setsockopt: TLS_RX(%s) failed with error %i\n", sock_to_string(s), err);
179 return -EINVAL;
180 }
181 err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &so_buf, sizeof(so_buf));
182 if (err) {
183 fprintf(stderr, "setsockopt: (%s) failed sndbuf with error %i\n", sock_to_string(s), err);
184 return -EINVAL;
185 }
186 err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &so_buf, sizeof(so_buf));
187 if (err) {
188 fprintf(stderr, "setsockopt: (%s) failed rcvbuf with error %i\n", sock_to_string(s), err);
189 return -EINVAL;
190 }
191
192 if (verbose)
193 fprintf(stdout, "socket(%s) kTLS enabled\n", sock_to_string(s));
194 return 0;
195}
115static int sockmap_init_sockets(int verbose) 196static int sockmap_init_sockets(int verbose)
116{ 197{
117 int i, err, one = 1; 198 int i, err, one = 1;
@@ -277,33 +358,40 @@ static int msg_loop_sendpage(int fd, int iov_length, int cnt,
277 return 0; 358 return 0;
278} 359}
279 360
280static int msg_loop(int fd, int iov_count, int iov_length, int cnt, 361static void msg_free_iov(struct msghdr *msg)
281 struct msg_stats *s, bool tx,
282 struct sockmap_options *opt)
283{ 362{
284 struct msghdr msg = {0}; 363 int i;
285 int err, i, flags = MSG_NOSIGNAL; 364
365 for (i = 0; i < msg->msg_iovlen; i++)
366 free(msg->msg_iov[i].iov_base);
367 free(msg->msg_iov);
368 msg->msg_iov = NULL;
369 msg->msg_iovlen = 0;
370}
371
372static int msg_alloc_iov(struct msghdr *msg,
373 int iov_count, int iov_length,
374 bool data, bool xmit)
375{
376 unsigned char k = 0;
286 struct iovec *iov; 377 struct iovec *iov;
287 unsigned char k; 378 int i;
288 bool data_test = opt->data_test;
289 bool drop = opt->drop_expected;
290 379
291 iov = calloc(iov_count, sizeof(struct iovec)); 380 iov = calloc(iov_count, sizeof(struct iovec));
292 if (!iov) 381 if (!iov)
293 return errno; 382 return errno;
294 383
295 k = 0;
296 for (i = 0; i < iov_count; i++) { 384 for (i = 0; i < iov_count; i++) {
297 unsigned char *d = calloc(iov_length, sizeof(char)); 385 unsigned char *d = calloc(iov_length, sizeof(char));
298 386
299 if (!d) { 387 if (!d) {
300 fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count); 388 fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
301 goto out_errno; 389 goto unwind_iov;
302 } 390 }
303 iov[i].iov_base = d; 391 iov[i].iov_base = d;
304 iov[i].iov_len = iov_length; 392 iov[i].iov_len = iov_length;
305 393
306 if (data_test && tx) { 394 if (data && xmit) {
307 int j; 395 int j;
308 396
309 for (j = 0; j < iov_length; j++) 397 for (j = 0; j < iov_length; j++)
@@ -311,9 +399,60 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
311 } 399 }
312 } 400 }
313 401
314 msg.msg_iov = iov; 402 msg->msg_iov = iov;
315 msg.msg_iovlen = iov_count; 403 msg->msg_iovlen = iov_count;
316 k = 0; 404
405 return 0;
406unwind_iov:
407 for (i--; i >= 0 ; i--)
408 free(msg->msg_iov[i].iov_base);
409 return -ENOMEM;
410}
411
412static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
413{
414 int i, j, bytes_cnt = 0;
415 unsigned char k = 0;
416
417 for (i = 0; i < msg->msg_iovlen; i++) {
418 unsigned char *d = msg->msg_iov[i].iov_base;
419
420 for (j = 0;
421 j < msg->msg_iov[i].iov_len && size; j++) {
422 if (d[j] != k++) {
423 fprintf(stderr,
424 "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
425 i, j, d[j], k - 1, d[j+1], k);
426 return -EIO;
427 }
428 bytes_cnt++;
429 if (bytes_cnt == chunk_sz) {
430 k = 0;
431 bytes_cnt = 0;
432 }
433 size--;
434 }
435 }
436 return 0;
437}
438
439static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
440 struct msg_stats *s, bool tx,
441 struct sockmap_options *opt)
442{
443 struct msghdr msg = {0}, msg_peek = {0};
444 int err, i, flags = MSG_NOSIGNAL;
445 bool drop = opt->drop_expected;
446 bool data = opt->data_test;
447
448 err = msg_alloc_iov(&msg, iov_count, iov_length, data, tx);
449 if (err)
450 goto out_errno;
451 if (peek_flag) {
452 err = msg_alloc_iov(&msg_peek, iov_count, iov_length, data, tx);
453 if (err)
454 goto out_errno;
455 }
317 456
318 if (tx) { 457 if (tx) {
319 clock_gettime(CLOCK_MONOTONIC, &s->start); 458 clock_gettime(CLOCK_MONOTONIC, &s->start);
@@ -333,19 +472,12 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
333 } 472 }
334 clock_gettime(CLOCK_MONOTONIC, &s->end); 473 clock_gettime(CLOCK_MONOTONIC, &s->end);
335 } else { 474 } else {
336 int slct, recv, max_fd = fd; 475 int slct, recvp = 0, recv, max_fd = fd;
337 int fd_flags = O_NONBLOCK; 476 int fd_flags = O_NONBLOCK;
338 struct timeval timeout; 477 struct timeval timeout;
339 float total_bytes; 478 float total_bytes;
340 int bytes_cnt = 0;
341 int chunk_sz;
342 fd_set w; 479 fd_set w;
343 480
344 if (opt->sendpage)
345 chunk_sz = iov_length * cnt;
346 else
347 chunk_sz = iov_length * iov_count;
348
349 fcntl(fd, fd_flags); 481 fcntl(fd, fd_flags);
350 total_bytes = (float)iov_count * (float)iov_length * (float)cnt; 482 total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
351 err = clock_gettime(CLOCK_MONOTONIC, &s->start); 483 err = clock_gettime(CLOCK_MONOTONIC, &s->start);
@@ -377,6 +509,19 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
377 goto out_errno; 509 goto out_errno;
378 } 510 }
379 511
512 errno = 0;
513 if (peek_flag) {
514 flags |= MSG_PEEK;
515 recvp = recvmsg(fd, &msg_peek, flags);
516 if (recvp < 0) {
517 if (errno != EWOULDBLOCK) {
518 clock_gettime(CLOCK_MONOTONIC, &s->end);
519 goto out_errno;
520 }
521 }
522 flags = 0;
523 }
524
380 recv = recvmsg(fd, &msg, flags); 525 recv = recvmsg(fd, &msg, flags);
381 if (recv < 0) { 526 if (recv < 0) {
382 if (errno != EWOULDBLOCK) { 527 if (errno != EWOULDBLOCK) {
@@ -388,27 +533,23 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
388 533
389 s->bytes_recvd += recv; 534 s->bytes_recvd += recv;
390 535
391 if (data_test) { 536 if (data) {
392 int j; 537 int chunk_sz = opt->sendpage ?
393 538 iov_length * cnt :
394 for (i = 0; i < msg.msg_iovlen; i++) { 539 iov_length * iov_count;
395 unsigned char *d = iov[i].iov_base; 540
396 541 errno = msg_verify_data(&msg, recv, chunk_sz);
397 for (j = 0; 542 if (errno) {
398 j < iov[i].iov_len && recv; j++) { 543 perror("data verify msg failed\n");
399 if (d[j] != k++) { 544 goto out_errno;
400 errno = -EIO; 545 }
401 fprintf(stderr, 546 if (recvp) {
402 "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n", 547 errno = msg_verify_data(&msg_peek,
403 i, j, d[j], k - 1, d[j+1], k); 548 recvp,
404 goto out_errno; 549 chunk_sz);
405 } 550 if (errno) {
406 bytes_cnt++; 551 perror("data verify msg_peek failed\n");
407 if (bytes_cnt == chunk_sz) { 552 goto out_errno;
408 k = 0;
409 bytes_cnt = 0;
410 }
411 recv--;
412 } 553 }
413 } 554 }
414 } 555 }
@@ -416,14 +557,12 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
416 clock_gettime(CLOCK_MONOTONIC, &s->end); 557 clock_gettime(CLOCK_MONOTONIC, &s->end);
417 } 558 }
418 559
419 for (i = 0; i < iov_count; i++) 560 msg_free_iov(&msg);
420 free(iov[i].iov_base); 561 msg_free_iov(&msg_peek);
421 free(iov); 562 return err;
422 return 0;
423out_errno: 563out_errno:
424 for (i = 0; i < iov_count; i++) 564 msg_free_iov(&msg);
425 free(iov[i].iov_base); 565 msg_free_iov(&msg_peek);
426 free(iov);
427 return errno; 566 return errno;
428} 567}
429 568
@@ -456,6 +595,21 @@ static int sendmsg_test(struct sockmap_options *opt)
456 else 595 else
457 rx_fd = p2; 596 rx_fd = p2;
458 597
598 if (ktls) {
599 /* Redirecting into non-TLS socket which sends into a TLS
600 * socket is not a valid test. So in this case lets not
601 * enable kTLS but still run the test.
602 */
603 if (!txmsg_redir || (txmsg_redir && txmsg_ingress)) {
604 err = sockmap_init_ktls(opt->verbose, rx_fd);
605 if (err)
606 return err;
607 }
608 err = sockmap_init_ktls(opt->verbose, c1);
609 if (err)
610 return err;
611 }
612
459 rxpid = fork(); 613 rxpid = fork();
460 if (rxpid == 0) { 614 if (rxpid == 0) {
461 if (opt->drop_expected) 615 if (opt->drop_expected)
@@ -469,17 +623,16 @@ static int sendmsg_test(struct sockmap_options *opt)
469 fprintf(stderr, 623 fprintf(stderr,
470 "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n", 624 "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
471 iov_count, iov_buf, cnt, err); 625 iov_count, iov_buf, cnt, err);
472 shutdown(p2, SHUT_RDWR);
473 shutdown(p1, SHUT_RDWR);
474 if (s.end.tv_sec - s.start.tv_sec) { 626 if (s.end.tv_sec - s.start.tv_sec) {
475 sent_Bps = sentBps(s); 627 sent_Bps = sentBps(s);
476 recvd_Bps = recvdBps(s); 628 recvd_Bps = recvdBps(s);
477 } 629 }
478 if (opt->verbose) 630 if (opt->verbose)
479 fprintf(stdout, 631 fprintf(stdout,
480 "rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s\n", 632 "rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s %s\n",
481 s.bytes_sent, sent_Bps, sent_Bps/giga, 633 s.bytes_sent, sent_Bps, sent_Bps/giga,
482 s.bytes_recvd, recvd_Bps, recvd_Bps/giga); 634 s.bytes_recvd, recvd_Bps, recvd_Bps/giga,
635 peek_flag ? "(peek_msg)" : "");
483 if (err && txmsg_cork) 636 if (err && txmsg_cork)
484 err = 0; 637 err = 0;
485 exit(err ? 1 : 0); 638 exit(err ? 1 : 0);
@@ -500,7 +653,6 @@ static int sendmsg_test(struct sockmap_options *opt)
500 fprintf(stderr, 653 fprintf(stderr,
501 "msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n", 654 "msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n",
502 iov_count, iov_buf, cnt, err); 655 iov_count, iov_buf, cnt, err);
503 shutdown(c1, SHUT_RDWR);
504 if (s.end.tv_sec - s.start.tv_sec) { 656 if (s.end.tv_sec - s.start.tv_sec) {
505 sent_Bps = sentBps(s); 657 sent_Bps = sentBps(s);
506 recvd_Bps = recvdBps(s); 658 recvd_Bps = recvdBps(s);
@@ -755,6 +907,30 @@ run:
755 } 907 }
756 } 908 }
757 909
910 if (txmsg_start_push) {
911 i = 2;
912 err = bpf_map_update_elem(map_fd[5],
913 &i, &txmsg_start_push, BPF_ANY);
914 if (err) {
915 fprintf(stderr,
916 "ERROR: bpf_map_update_elem (txmsg_start_push): %d (%s)\n",
917 err, strerror(errno));
918 goto out;
919 }
920 }
921
922 if (txmsg_end_push) {
923 i = 3;
924 err = bpf_map_update_elem(map_fd[5],
925 &i, &txmsg_end_push, BPF_ANY);
926 if (err) {
927 fprintf(stderr,
928 "ERROR: bpf_map_update_elem %i@%i (txmsg_end_push): %d (%s)\n",
929 txmsg_end_push, i, err, strerror(errno));
930 goto out;
931 }
932 }
933
758 if (txmsg_ingress) { 934 if (txmsg_ingress) {
759 int in = BPF_F_INGRESS; 935 int in = BPF_F_INGRESS;
760 936
@@ -910,6 +1086,10 @@ static void test_options(char *options)
910 strncat(options, "ingress,", OPTSTRING); 1086 strncat(options, "ingress,", OPTSTRING);
911 if (txmsg_skb) 1087 if (txmsg_skb)
912 strncat(options, "skb,", OPTSTRING); 1088 strncat(options, "skb,", OPTSTRING);
1089 if (ktls)
1090 strncat(options, "ktls,", OPTSTRING);
1091 if (peek_flag)
1092 strncat(options, "peek,", OPTSTRING);
913} 1093}
914 1094
915static int __test_exec(int cgrp, int test, struct sockmap_options *opt) 1095static int __test_exec(int cgrp, int test, struct sockmap_options *opt)
@@ -1083,6 +1263,8 @@ static int test_mixed(int cgrp)
1083 txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0; 1263 txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
1084 txmsg_apply = txmsg_cork = 0; 1264 txmsg_apply = txmsg_cork = 0;
1085 txmsg_start = txmsg_end = 0; 1265 txmsg_start = txmsg_end = 0;
1266 txmsg_start_push = txmsg_end_push = 0;
1267
1086 /* Test small and large iov_count values with pass/redir/apply/cork */ 1268 /* Test small and large iov_count values with pass/redir/apply/cork */
1087 txmsg_pass = 1; 1269 txmsg_pass = 1;
1088 txmsg_redir = 0; 1270 txmsg_redir = 0;
@@ -1199,6 +1381,8 @@ static int test_start_end(int cgrp)
1199 /* Test basic start/end with lots of iov_count and iov_lengths */ 1381 /* Test basic start/end with lots of iov_count and iov_lengths */
1200 txmsg_start = 1; 1382 txmsg_start = 1;
1201 txmsg_end = 2; 1383 txmsg_end = 2;
1384 txmsg_start_push = 1;
1385 txmsg_end_push = 2;
1202 err = test_txmsg(cgrp); 1386 err = test_txmsg(cgrp);
1203 if (err) 1387 if (err)
1204 goto out; 1388 goto out;
@@ -1212,6 +1396,8 @@ static int test_start_end(int cgrp)
1212 for (i = 99; i <= 1600; i += 500) { 1396 for (i = 99; i <= 1600; i += 500) {
1213 txmsg_start = 0; 1397 txmsg_start = 0;
1214 txmsg_end = i; 1398 txmsg_end = i;
1399 txmsg_start_push = 0;
1400 txmsg_end_push = i;
1215 err = test_exec(cgrp, &opt); 1401 err = test_exec(cgrp, &opt);
1216 if (err) 1402 if (err)
1217 goto out; 1403 goto out;
@@ -1221,6 +1407,8 @@ static int test_start_end(int cgrp)
1221 for (i = 199; i <= 1600; i += 500) { 1407 for (i = 199; i <= 1600; i += 500) {
1222 txmsg_start = 100; 1408 txmsg_start = 100;
1223 txmsg_end = i; 1409 txmsg_end = i;
1410 txmsg_start_push = 100;
1411 txmsg_end_push = i;
1224 err = test_exec(cgrp, &opt); 1412 err = test_exec(cgrp, &opt);
1225 if (err) 1413 if (err)
1226 goto out; 1414 goto out;
@@ -1229,6 +1417,8 @@ static int test_start_end(int cgrp)
1229 /* Test start/end with cork pulling last sg entry */ 1417 /* Test start/end with cork pulling last sg entry */
1230 txmsg_start = 1500; 1418 txmsg_start = 1500;
1231 txmsg_end = 1600; 1419 txmsg_end = 1600;
1420 txmsg_start_push = 1500;
1421 txmsg_end_push = 1600;
1232 err = test_exec(cgrp, &opt); 1422 err = test_exec(cgrp, &opt);
1233 if (err) 1423 if (err)
1234 goto out; 1424 goto out;
@@ -1236,6 +1426,8 @@ static int test_start_end(int cgrp)
1236 /* Test start/end pull of single byte in last page */ 1426 /* Test start/end pull of single byte in last page */
1237 txmsg_start = 1111; 1427 txmsg_start = 1111;
1238 txmsg_end = 1112; 1428 txmsg_end = 1112;
1429 txmsg_start_push = 1111;
1430 txmsg_end_push = 1112;
1239 err = test_exec(cgrp, &opt); 1431 err = test_exec(cgrp, &opt);
1240 if (err) 1432 if (err)
1241 goto out; 1433 goto out;
@@ -1243,6 +1435,8 @@ static int test_start_end(int cgrp)
1243 /* Test start/end with end < start */ 1435 /* Test start/end with end < start */
1244 txmsg_start = 1111; 1436 txmsg_start = 1111;
1245 txmsg_end = 0; 1437 txmsg_end = 0;
1438 txmsg_start_push = 1111;
1439 txmsg_end_push = 0;
1246 err = test_exec(cgrp, &opt); 1440 err = test_exec(cgrp, &opt);
1247 if (err) 1441 if (err)
1248 goto out; 1442 goto out;
@@ -1250,6 +1444,8 @@ static int test_start_end(int cgrp)
1250 /* Test start/end with end > data */ 1444 /* Test start/end with end > data */
1251 txmsg_start = 0; 1445 txmsg_start = 0;
1252 txmsg_end = 1601; 1446 txmsg_end = 1601;
1447 txmsg_start_push = 0;
1448 txmsg_end_push = 1601;
1253 err = test_exec(cgrp, &opt); 1449 err = test_exec(cgrp, &opt);
1254 if (err) 1450 if (err)
1255 goto out; 1451 goto out;
@@ -1257,6 +1453,8 @@ static int test_start_end(int cgrp)
1257 /* Test start/end with start > data */ 1453 /* Test start/end with start > data */
1258 txmsg_start = 1601; 1454 txmsg_start = 1601;
1259 txmsg_end = 1600; 1455 txmsg_end = 1600;
1456 txmsg_start_push = 1601;
1457 txmsg_end_push = 1600;
1260 err = test_exec(cgrp, &opt); 1458 err = test_exec(cgrp, &opt);
1261 1459
1262out: 1460out:
@@ -1272,7 +1470,7 @@ char *map_names[] = {
1272 "sock_map_redir", 1470 "sock_map_redir",
1273 "sock_apply_bytes", 1471 "sock_apply_bytes",
1274 "sock_cork_bytes", 1472 "sock_cork_bytes",
1275 "sock_pull_bytes", 1473 "sock_bytes",
1276 "sock_redir_flags", 1474 "sock_redir_flags",
1277 "sock_skb_opts", 1475 "sock_skb_opts",
1278}; 1476};
@@ -1348,9 +1546,9 @@ static int populate_progs(char *bpf_file)
1348 return 0; 1546 return 0;
1349} 1547}
1350 1548
1351static int __test_suite(char *bpf_file) 1549static int __test_suite(int cg_fd, char *bpf_file)
1352{ 1550{
1353 int cg_fd, err; 1551 int err, cleanup = cg_fd;
1354 1552
1355 err = populate_progs(bpf_file); 1553 err = populate_progs(bpf_file);
1356 if (err < 0) { 1554 if (err < 0) {
@@ -1358,26 +1556,28 @@ static int __test_suite(char *bpf_file)
1358 return err; 1556 return err;
1359 } 1557 }
1360 1558
1361 if (setup_cgroup_environment()) {
1362 fprintf(stderr, "ERROR: cgroup env failed\n");
1363 return -EINVAL;
1364 }
1365
1366 cg_fd = create_and_get_cgroup(CG_PATH);
1367 if (cg_fd < 0) { 1559 if (cg_fd < 0) {
1368 fprintf(stderr, 1560 if (setup_cgroup_environment()) {
1369 "ERROR: (%i) open cg path failed: %s\n", 1561 fprintf(stderr, "ERROR: cgroup env failed\n");
1370 cg_fd, optarg); 1562 return -EINVAL;
1371 return cg_fd; 1563 }
1372 }
1373 1564
1374 if (join_cgroup(CG_PATH)) { 1565 cg_fd = create_and_get_cgroup(CG_PATH);
1375 fprintf(stderr, "ERROR: failed to join cgroup\n"); 1566 if (cg_fd < 0) {
1376 return -EINVAL; 1567 fprintf(stderr,
1568 "ERROR: (%i) open cg path failed: %s\n",
1569 cg_fd, optarg);
1570 return cg_fd;
1571 }
1572
1573 if (join_cgroup(CG_PATH)) {
1574 fprintf(stderr, "ERROR: failed to join cgroup\n");
1575 return -EINVAL;
1576 }
1377 } 1577 }
1378 1578
1379 /* Tests basic commands and APIs with range of iov values */ 1579 /* Tests basic commands and APIs with range of iov values */
1380 txmsg_start = txmsg_end = 0; 1580 txmsg_start = txmsg_end = txmsg_start_push = txmsg_end_push = 0;
1381 err = test_txmsg(cg_fd); 1581 err = test_txmsg(cg_fd);
1382 if (err) 1582 if (err)
1383 goto out; 1583 goto out;
@@ -1394,20 +1594,24 @@ static int __test_suite(char *bpf_file)
1394 1594
1395out: 1595out:
1396 printf("Summary: %i PASSED %i FAILED\n", passed, failed); 1596 printf("Summary: %i PASSED %i FAILED\n", passed, failed);
1397 cleanup_cgroup_environment(); 1597 if (cleanup < 0) {
1398 close(cg_fd); 1598 cleanup_cgroup_environment();
1599 close(cg_fd);
1600 }
1399 return err; 1601 return err;
1400} 1602}
1401 1603
1402static int test_suite(void) 1604static int test_suite(int cg_fd)
1403{ 1605{
1404 int err; 1606 int err;
1405 1607
1406 err = __test_suite(BPF_SOCKMAP_FILENAME); 1608 err = __test_suite(cg_fd, BPF_SOCKMAP_FILENAME);
1407 if (err) 1609 if (err)
1408 goto out; 1610 goto out;
1409 err = __test_suite(BPF_SOCKHASH_FILENAME); 1611 err = __test_suite(cg_fd, BPF_SOCKHASH_FILENAME);
1410out: 1612out:
1613 if (cg_fd > -1)
1614 close(cg_fd);
1411 return err; 1615 return err;
1412} 1616}
1413 1617
@@ -1420,9 +1624,9 @@ int main(int argc, char **argv)
1420 int test = PING_PONG; 1624 int test = PING_PONG;
1421 1625
1422 if (argc < 2) 1626 if (argc < 2)
1423 return test_suite(); 1627 return test_suite(-1);
1424 1628
1425 while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:", 1629 while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:p:q:",
1426 long_options, &longindex)) != -1) { 1630 long_options, &longindex)) != -1) {
1427 switch (opt) { 1631 switch (opt) {
1428 case 's': 1632 case 's':
@@ -1431,6 +1635,12 @@ int main(int argc, char **argv)
1431 case 'e': 1635 case 'e':
1432 txmsg_end = atoi(optarg); 1636 txmsg_end = atoi(optarg);
1433 break; 1637 break;
1638 case 'p':
1639 txmsg_start_push = atoi(optarg);
1640 break;
1641 case 'q':
1642 txmsg_end_push = atoi(optarg);
1643 break;
1434 case 'a': 1644 case 'a':
1435 txmsg_apply = atoi(optarg); 1645 txmsg_apply = atoi(optarg);
1436 break; 1646 break;
@@ -1486,6 +1696,9 @@ int main(int argc, char **argv)
1486 } 1696 }
1487 } 1697 }
1488 1698
1699 if (argc <= 3 && cg_fd)
1700 return test_suite(cg_fd);
1701
1489 if (!cg_fd) { 1702 if (!cg_fd) {
1490 fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n", 1703 fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n",
1491 argv[0]); 1704 argv[0]);
diff --git a/tools/testing/selftests/bpf/test_sockmap_kern.h b/tools/testing/selftests/bpf/test_sockmap_kern.h
index 8e8e41780bb9..14b8bbac004f 100644
--- a/tools/testing/selftests/bpf/test_sockmap_kern.h
+++ b/tools/testing/selftests/bpf/test_sockmap_kern.h
@@ -70,11 +70,11 @@ struct bpf_map_def SEC("maps") sock_cork_bytes = {
70 .max_entries = 1 70 .max_entries = 1
71}; 71};
72 72
73struct bpf_map_def SEC("maps") sock_pull_bytes = { 73struct bpf_map_def SEC("maps") sock_bytes = {
74 .type = BPF_MAP_TYPE_ARRAY, 74 .type = BPF_MAP_TYPE_ARRAY,
75 .key_size = sizeof(int), 75 .key_size = sizeof(int),
76 .value_size = sizeof(int), 76 .value_size = sizeof(int),
77 .max_entries = 2 77 .max_entries = 4
78}; 78};
79 79
80struct bpf_map_def SEC("maps") sock_redir_flags = { 80struct bpf_map_def SEC("maps") sock_redir_flags = {
@@ -181,8 +181,8 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
181SEC("sk_msg1") 181SEC("sk_msg1")
182int bpf_prog4(struct sk_msg_md *msg) 182int bpf_prog4(struct sk_msg_md *msg)
183{ 183{
184 int *bytes, zero = 0, one = 1; 184 int *bytes, zero = 0, one = 1, two = 2, three = 3;
185 int *start, *end; 185 int *start, *end, *start_push, *end_push;
186 186
187 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); 187 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
188 if (bytes) 188 if (bytes)
@@ -190,18 +190,24 @@ int bpf_prog4(struct sk_msg_md *msg)
190 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); 190 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
191 if (bytes) 191 if (bytes)
192 bpf_msg_cork_bytes(msg, *bytes); 192 bpf_msg_cork_bytes(msg, *bytes);
193 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); 193 start = bpf_map_lookup_elem(&sock_bytes, &zero);
194 end = bpf_map_lookup_elem(&sock_pull_bytes, &one); 194 end = bpf_map_lookup_elem(&sock_bytes, &one);
195 if (start && end) 195 if (start && end)
196 bpf_msg_pull_data(msg, *start, *end, 0); 196 bpf_msg_pull_data(msg, *start, *end, 0);
197 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
198 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
199 if (start_push && end_push)
200 bpf_msg_push_data(msg, *start_push, *end_push, 0);
197 return SK_PASS; 201 return SK_PASS;
198} 202}
199 203
200SEC("sk_msg2") 204SEC("sk_msg2")
201int bpf_prog5(struct sk_msg_md *msg) 205int bpf_prog5(struct sk_msg_md *msg)
202{ 206{
203 int err1 = -1, err2 = -1, zero = 0, one = 1; 207 int zero = 0, one = 1, two = 2, three = 3;
204 int *bytes, *start, *end, len1, len2; 208 int *start, *end, *start_push, *end_push;
209 int *bytes, len1, len2 = 0, len3;
210 int err1 = -1, err2 = -1;
205 211
206 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); 212 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
207 if (bytes) 213 if (bytes)
@@ -210,8 +216,8 @@ int bpf_prog5(struct sk_msg_md *msg)
210 if (bytes) 216 if (bytes)
211 err2 = bpf_msg_cork_bytes(msg, *bytes); 217 err2 = bpf_msg_cork_bytes(msg, *bytes);
212 len1 = (__u64)msg->data_end - (__u64)msg->data; 218 len1 = (__u64)msg->data_end - (__u64)msg->data;
213 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); 219 start = bpf_map_lookup_elem(&sock_bytes, &zero);
214 end = bpf_map_lookup_elem(&sock_pull_bytes, &one); 220 end = bpf_map_lookup_elem(&sock_bytes, &one);
215 if (start && end) { 221 if (start && end) {
216 int err; 222 int err;
217 223
@@ -225,6 +231,23 @@ int bpf_prog5(struct sk_msg_md *msg)
225 bpf_printk("sk_msg2: length update %i->%i\n", 231 bpf_printk("sk_msg2: length update %i->%i\n",
226 len1, len2); 232 len1, len2);
227 } 233 }
234
235 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
236 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
237 if (start_push && end_push) {
238 int err;
239
240 bpf_printk("sk_msg2: push(%i:%i)\n",
241 start_push ? *start_push : 0,
242 end_push ? *end_push : 0);
243 err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
244 if (err)
245 bpf_printk("sk_msg2: push_data err %i\n", err);
246 len3 = (__u64)msg->data_end - (__u64)msg->data;
247 bpf_printk("sk_msg2: length push_update %i->%i\n",
248 len2 ? len2 : len1, len3);
249 }
250
228 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n", 251 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
229 len1, err1, err2); 252 len1, err1, err2);
230 return SK_PASS; 253 return SK_PASS;
@@ -233,8 +256,8 @@ int bpf_prog5(struct sk_msg_md *msg)
233SEC("sk_msg3") 256SEC("sk_msg3")
234int bpf_prog6(struct sk_msg_md *msg) 257int bpf_prog6(struct sk_msg_md *msg)
235{ 258{
236 int *bytes, zero = 0, one = 1, key = 0; 259 int *bytes, *start, *end, *start_push, *end_push, *f;
237 int *start, *end, *f; 260 int zero = 0, one = 1, two = 2, three = 3, key = 0;
238 __u64 flags = 0; 261 __u64 flags = 0;
239 262
240 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); 263 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
@@ -243,10 +266,17 @@ int bpf_prog6(struct sk_msg_md *msg)
243 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); 266 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
244 if (bytes) 267 if (bytes)
245 bpf_msg_cork_bytes(msg, *bytes); 268 bpf_msg_cork_bytes(msg, *bytes);
246 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); 269
247 end = bpf_map_lookup_elem(&sock_pull_bytes, &one); 270 start = bpf_map_lookup_elem(&sock_bytes, &zero);
271 end = bpf_map_lookup_elem(&sock_bytes, &one);
248 if (start && end) 272 if (start && end)
249 bpf_msg_pull_data(msg, *start, *end, 0); 273 bpf_msg_pull_data(msg, *start, *end, 0);
274
275 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
276 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
277 if (start_push && end_push)
278 bpf_msg_push_data(msg, *start_push, *end_push, 0);
279
250 f = bpf_map_lookup_elem(&sock_redir_flags, &zero); 280 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
251 if (f && *f) { 281 if (f && *f) {
252 key = 2; 282 key = 2;
@@ -262,8 +292,9 @@ int bpf_prog6(struct sk_msg_md *msg)
262SEC("sk_msg4") 292SEC("sk_msg4")
263int bpf_prog7(struct sk_msg_md *msg) 293int bpf_prog7(struct sk_msg_md *msg)
264{ 294{
265 int err1 = 0, err2 = 0, zero = 0, one = 1, key = 0; 295 int zero = 0, one = 1, two = 2, three = 3, len1, len2 = 0, len3;
266 int *f, *bytes, *start, *end, len1, len2; 296 int *bytes, *start, *end, *start_push, *end_push, *f;
297 int err1 = 0, err2 = 0, key = 0;
267 __u64 flags = 0; 298 __u64 flags = 0;
268 299
269 int err; 300 int err;
@@ -274,10 +305,10 @@ int bpf_prog7(struct sk_msg_md *msg)
274 if (bytes) 305 if (bytes)
275 err2 = bpf_msg_cork_bytes(msg, *bytes); 306 err2 = bpf_msg_cork_bytes(msg, *bytes);
276 len1 = (__u64)msg->data_end - (__u64)msg->data; 307 len1 = (__u64)msg->data_end - (__u64)msg->data;
277 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
278 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
279 if (start && end) {
280 308
309 start = bpf_map_lookup_elem(&sock_bytes, &zero);
310 end = bpf_map_lookup_elem(&sock_bytes, &one);
311 if (start && end) {
281 bpf_printk("sk_msg2: pull(%i:%i)\n", 312 bpf_printk("sk_msg2: pull(%i:%i)\n",
282 start ? *start : 0, end ? *end : 0); 313 start ? *start : 0, end ? *end : 0);
283 err = bpf_msg_pull_data(msg, *start, *end, 0); 314 err = bpf_msg_pull_data(msg, *start, *end, 0);
@@ -288,6 +319,22 @@ int bpf_prog7(struct sk_msg_md *msg)
288 bpf_printk("sk_msg2: length update %i->%i\n", 319 bpf_printk("sk_msg2: length update %i->%i\n",
289 len1, len2); 320 len1, len2);
290 } 321 }
322
323 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
324 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
325 if (start_push && end_push) {
326 bpf_printk("sk_msg4: push(%i:%i)\n",
327 start_push ? *start_push : 0,
328 end_push ? *end_push : 0);
329 err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
330 if (err)
331 bpf_printk("sk_msg4: push_data err %i\n",
332 err);
333 len3 = (__u64)msg->data_end - (__u64)msg->data;
334 bpf_printk("sk_msg4: length push_update %i->%i\n",
335 len2 ? len2 : len1, len3);
336 }
337
291 f = bpf_map_lookup_elem(&sock_redir_flags, &zero); 338 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
292 if (f && *f) { 339 if (f && *f) {
293 key = 2; 340 key = 2;
@@ -342,8 +389,8 @@ int bpf_prog9(struct sk_msg_md *msg)
342SEC("sk_msg7") 389SEC("sk_msg7")
343int bpf_prog10(struct sk_msg_md *msg) 390int bpf_prog10(struct sk_msg_md *msg)
344{ 391{
345 int *bytes, zero = 0, one = 1; 392 int *bytes, *start, *end, *start_push, *end_push;
346 int *start, *end; 393 int zero = 0, one = 1, two = 2, three = 3;
347 394
348 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); 395 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
349 if (bytes) 396 if (bytes)
@@ -351,10 +398,14 @@ int bpf_prog10(struct sk_msg_md *msg)
351 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); 398 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
352 if (bytes) 399 if (bytes)
353 bpf_msg_cork_bytes(msg, *bytes); 400 bpf_msg_cork_bytes(msg, *bytes);
354 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); 401 start = bpf_map_lookup_elem(&sock_bytes, &zero);
355 end = bpf_map_lookup_elem(&sock_pull_bytes, &one); 402 end = bpf_map_lookup_elem(&sock_bytes, &one);
356 if (start && end) 403 if (start && end)
357 bpf_msg_pull_data(msg, *start, *end, 0); 404 bpf_msg_pull_data(msg, *start, *end, 0);
405 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
406 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
407 if (start_push && end_push)
408 bpf_msg_push_data(msg, *start_push, *end_push, 0);
358 409
359 return SK_DROP; 410 return SK_DROP;
360} 411}
diff --git a/tools/testing/selftests/bpf/test_stack_map.c b/tools/testing/selftests/bpf/test_stack_map.c
new file mode 100644
index 000000000000..31c3880e6da0
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_stack_map.c
@@ -0,0 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Politecnico di Torino
3#define MAP_TYPE BPF_MAP_TYPE_STACK
4#include "test_queue_stack_map.h"
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_kern.c b/tools/testing/selftests/bpf/test_tcpbpf_kern.c
index 4b7fd540cea9..74f73b33a7b0 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_kern.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_kern.c
@@ -5,6 +5,7 @@
5#include <linux/if_ether.h> 5#include <linux/if_ether.h>
6#include <linux/if_packet.h> 6#include <linux/if_packet.h>
7#include <linux/ip.h> 7#include <linux/ip.h>
8#include <linux/ipv6.h>
8#include <linux/types.h> 9#include <linux/types.h>
9#include <linux/socket.h> 10#include <linux/socket.h>
10#include <linux/tcp.h> 11#include <linux/tcp.h>
@@ -17,6 +18,13 @@ struct bpf_map_def SEC("maps") global_map = {
17 .type = BPF_MAP_TYPE_ARRAY, 18 .type = BPF_MAP_TYPE_ARRAY,
18 .key_size = sizeof(__u32), 19 .key_size = sizeof(__u32),
19 .value_size = sizeof(struct tcpbpf_globals), 20 .value_size = sizeof(struct tcpbpf_globals),
21 .max_entries = 4,
22};
23
24struct bpf_map_def SEC("maps") sockopt_results = {
25 .type = BPF_MAP_TYPE_ARRAY,
26 .key_size = sizeof(__u32),
27 .value_size = sizeof(int),
20 .max_entries = 2, 28 .max_entries = 2,
21}; 29};
22 30
@@ -45,11 +53,14 @@ int _version SEC("version") = 1;
45SEC("sockops") 53SEC("sockops")
46int bpf_testcb(struct bpf_sock_ops *skops) 54int bpf_testcb(struct bpf_sock_ops *skops)
47{ 55{
48 int rv = -1; 56 char header[sizeof(struct ipv6hdr) + sizeof(struct tcphdr)];
49 int bad_call_rv = 0; 57 struct tcphdr *thdr;
50 int good_call_rv = 0; 58 int good_call_rv = 0;
51 int op; 59 int bad_call_rv = 0;
60 int save_syn = 1;
61 int rv = -1;
52 int v = 0; 62 int v = 0;
63 int op;
53 64
54 op = (int) skops->op; 65 op = (int) skops->op;
55 66
@@ -82,6 +93,21 @@ int bpf_testcb(struct bpf_sock_ops *skops)
82 v = 0xff; 93 v = 0xff;
83 rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v, 94 rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v,
84 sizeof(v)); 95 sizeof(v));
96 if (skops->family == AF_INET6) {
97 v = bpf_getsockopt(skops, IPPROTO_TCP, TCP_SAVED_SYN,
98 header, (sizeof(struct ipv6hdr) +
99 sizeof(struct tcphdr)));
100 if (!v) {
101 int offset = sizeof(struct ipv6hdr);
102
103 thdr = (struct tcphdr *)(header + offset);
104 v = thdr->syn;
105 __u32 key = 1;
106
107 bpf_map_update_elem(&sockopt_results, &key, &v,
108 BPF_ANY);
109 }
110 }
85 break; 111 break;
86 case BPF_SOCK_OPS_RTO_CB: 112 case BPF_SOCK_OPS_RTO_CB:
87 break; 113 break;
@@ -111,6 +137,12 @@ int bpf_testcb(struct bpf_sock_ops *skops)
111 break; 137 break;
112 case BPF_SOCK_OPS_TCP_LISTEN_CB: 138 case BPF_SOCK_OPS_TCP_LISTEN_CB:
113 bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG); 139 bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
140 v = bpf_setsockopt(skops, IPPROTO_TCP, TCP_SAVE_SYN,
141 &save_syn, sizeof(save_syn));
142 /* Update global map w/ result of setsock opt */
143 __u32 key = 0;
144
145 bpf_map_update_elem(&sockopt_results, &key, &v, BPF_ANY);
114 break; 146 break;
115 default: 147 default:
116 rv = -1; 148 rv = -1;
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c
index a275c2971376..e6eebda7d112 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_user.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c
@@ -54,6 +54,26 @@ err:
54 return -1; 54 return -1;
55} 55}
56 56
57int verify_sockopt_result(int sock_map_fd)
58{
59 __u32 key = 0;
60 int res;
61 int rv;
62
63 /* check setsockopt for SAVE_SYN */
64 rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
65 EXPECT_EQ(0, rv, "d");
66 EXPECT_EQ(0, res, "d");
67 key = 1;
68 /* check getsockopt for SAVED_SYN */
69 rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
70 EXPECT_EQ(0, rv, "d");
71 EXPECT_EQ(1, res, "d");
72 return 0;
73err:
74 return -1;
75}
76
57static int bpf_find_map(const char *test, struct bpf_object *obj, 77static int bpf_find_map(const char *test, struct bpf_object *obj,
58 const char *name) 78 const char *name)
59{ 79{
@@ -70,11 +90,11 @@ static int bpf_find_map(const char *test, struct bpf_object *obj,
70int main(int argc, char **argv) 90int main(int argc, char **argv)
71{ 91{
72 const char *file = "test_tcpbpf_kern.o"; 92 const char *file = "test_tcpbpf_kern.o";
93 int prog_fd, map_fd, sock_map_fd;
73 struct tcpbpf_globals g = {0}; 94 struct tcpbpf_globals g = {0};
74 const char *cg_path = "/foo"; 95 const char *cg_path = "/foo";
75 int error = EXIT_FAILURE; 96 int error = EXIT_FAILURE;
76 struct bpf_object *obj; 97 struct bpf_object *obj;
77 int prog_fd, map_fd;
78 int cg_fd = -1; 98 int cg_fd = -1;
79 __u32 key = 0; 99 __u32 key = 0;
80 int rv; 100 int rv;
@@ -110,6 +130,10 @@ int main(int argc, char **argv)
110 if (map_fd < 0) 130 if (map_fd < 0)
111 goto err; 131 goto err;
112 132
133 sock_map_fd = bpf_find_map(__func__, obj, "sockopt_results");
134 if (sock_map_fd < 0)
135 goto err;
136
113 rv = bpf_map_lookup_elem(map_fd, &key, &g); 137 rv = bpf_map_lookup_elem(map_fd, &key, &g);
114 if (rv != 0) { 138 if (rv != 0) {
115 printf("FAILED: bpf_map_lookup_elem returns %d\n", rv); 139 printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
@@ -121,6 +145,11 @@ int main(int argc, char **argv)
121 goto err; 145 goto err;
122 } 146 }
123 147
148 if (verify_sockopt_result(sock_map_fd)) {
149 printf("FAILED: Wrong sockopt stats\n");
150 goto err;
151 }
152
124 printf("PASSED!\n"); 153 printf("PASSED!\n");
125 error = 0; 154 error = 0;
126err: 155err:
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 67c412d19c09..769d68a48f30 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
5 * Copyright (c) 2017 Facebook 5 * Copyright (c) 2017 Facebook
6 * Copyright (c) 2018 Covalent IO, Inc. http://covalent.io
6 * 7 *
7 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public 9 * modify it under the terms of version 2 of the GNU General Public
@@ -47,7 +48,7 @@
47 48
48#define MAX_INSNS BPF_MAXINSNS 49#define MAX_INSNS BPF_MAXINSNS
49#define MAX_FIXUPS 8 50#define MAX_FIXUPS 8
50#define MAX_NR_MAPS 8 51#define MAX_NR_MAPS 13
51#define POINTER_VALUE 0xcafe4all 52#define POINTER_VALUE 0xcafe4all
52#define TEST_DATA_LEN 64 53#define TEST_DATA_LEN 64
53 54
@@ -60,14 +61,19 @@ static bool unpriv_disabled = false;
60struct bpf_test { 61struct bpf_test {
61 const char *descr; 62 const char *descr;
62 struct bpf_insn insns[MAX_INSNS]; 63 struct bpf_insn insns[MAX_INSNS];
63 int fixup_map1[MAX_FIXUPS]; 64 int fixup_map_hash_8b[MAX_FIXUPS];
64 int fixup_map2[MAX_FIXUPS]; 65 int fixup_map_hash_48b[MAX_FIXUPS];
65 int fixup_map3[MAX_FIXUPS]; 66 int fixup_map_hash_16b[MAX_FIXUPS];
66 int fixup_map4[MAX_FIXUPS]; 67 int fixup_map_array_48b[MAX_FIXUPS];
68 int fixup_map_sockmap[MAX_FIXUPS];
69 int fixup_map_sockhash[MAX_FIXUPS];
70 int fixup_map_xskmap[MAX_FIXUPS];
71 int fixup_map_stacktrace[MAX_FIXUPS];
67 int fixup_prog1[MAX_FIXUPS]; 72 int fixup_prog1[MAX_FIXUPS];
68 int fixup_prog2[MAX_FIXUPS]; 73 int fixup_prog2[MAX_FIXUPS];
69 int fixup_map_in_map[MAX_FIXUPS]; 74 int fixup_map_in_map[MAX_FIXUPS];
70 int fixup_cgroup_storage[MAX_FIXUPS]; 75 int fixup_cgroup_storage[MAX_FIXUPS];
76 int fixup_percpu_cgroup_storage[MAX_FIXUPS];
71 const char *errstr; 77 const char *errstr;
72 const char *errstr_unpriv; 78 const char *errstr_unpriv;
73 uint32_t retval; 79 uint32_t retval;
@@ -177,6 +183,24 @@ static void bpf_fill_rand_ld_dw(struct bpf_test *self)
177 self->retval = (uint32_t)res; 183 self->retval = (uint32_t)res;
178} 184}
179 185
186/* BPF_SK_LOOKUP contains 13 instructions, if you need to fix up maps */
187#define BPF_SK_LOOKUP \
188 /* struct bpf_sock_tuple tuple = {} */ \
189 BPF_MOV64_IMM(BPF_REG_2, 0), \
190 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -8), \
191 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -16), \
192 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -24), \
193 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -32), \
194 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -40), \
195 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -48), \
196 /* sk = sk_lookup_tcp(ctx, &tuple, sizeof tuple, 0, 0) */ \
197 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), \
198 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48), \
199 BPF_MOV64_IMM(BPF_REG_3, sizeof(struct bpf_sock_tuple)), \
200 BPF_MOV64_IMM(BPF_REG_4, 0), \
201 BPF_MOV64_IMM(BPF_REG_5, 0), \
202 BPF_EMIT_CALL(BPF_FUNC_sk_lookup_tcp)
203
180static struct bpf_test tests[] = { 204static struct bpf_test tests[] = {
181 { 205 {
182 "add+sub+mul", 206 "add+sub+mul",
@@ -856,7 +880,7 @@ static struct bpf_test tests[] = {
856 BPF_FUNC_map_lookup_elem), 880 BPF_FUNC_map_lookup_elem),
857 BPF_EXIT_INSN(), 881 BPF_EXIT_INSN(),
858 }, 882 },
859 .fixup_map1 = { 2 }, 883 .fixup_map_hash_8b = { 2 },
860 .errstr = "invalid indirect read from stack", 884 .errstr = "invalid indirect read from stack",
861 .result = REJECT, 885 .result = REJECT,
862 }, 886 },
@@ -1090,7 +1114,7 @@ static struct bpf_test tests[] = {
1090 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 1114 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
1091 BPF_EXIT_INSN(), 1115 BPF_EXIT_INSN(),
1092 }, 1116 },
1093 .fixup_map1 = { 3 }, 1117 .fixup_map_hash_8b = { 3 },
1094 .errstr = "R0 invalid mem access 'map_value_or_null'", 1118 .errstr = "R0 invalid mem access 'map_value_or_null'",
1095 .result = REJECT, 1119 .result = REJECT,
1096 }, 1120 },
@@ -1107,7 +1131,7 @@ static struct bpf_test tests[] = {
1107 BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0), 1131 BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
1108 BPF_EXIT_INSN(), 1132 BPF_EXIT_INSN(),
1109 }, 1133 },
1110 .fixup_map1 = { 3 }, 1134 .fixup_map_hash_8b = { 3 },
1111 .errstr = "misaligned value access", 1135 .errstr = "misaligned value access",
1112 .result = REJECT, 1136 .result = REJECT,
1113 .flags = F_LOAD_WITH_STRICT_ALIGNMENT, 1137 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
@@ -1127,7 +1151,7 @@ static struct bpf_test tests[] = {
1127 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1), 1151 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
1128 BPF_EXIT_INSN(), 1152 BPF_EXIT_INSN(),
1129 }, 1153 },
1130 .fixup_map1 = { 3 }, 1154 .fixup_map_hash_8b = { 3 },
1131 .errstr = "R0 invalid mem access", 1155 .errstr = "R0 invalid mem access",
1132 .errstr_unpriv = "R0 leaks addr", 1156 .errstr_unpriv = "R0 leaks addr",
1133 .result = REJECT, 1157 .result = REJECT,
@@ -1217,7 +1241,7 @@ static struct bpf_test tests[] = {
1217 BPF_FUNC_map_delete_elem), 1241 BPF_FUNC_map_delete_elem),
1218 BPF_EXIT_INSN(), 1242 BPF_EXIT_INSN(),
1219 }, 1243 },
1220 .fixup_map1 = { 24 }, 1244 .fixup_map_hash_8b = { 24 },
1221 .errstr_unpriv = "R1 pointer comparison", 1245 .errstr_unpriv = "R1 pointer comparison",
1222 .result_unpriv = REJECT, 1246 .result_unpriv = REJECT,
1223 .result = ACCEPT, 1247 .result = ACCEPT,
@@ -1371,7 +1395,7 @@ static struct bpf_test tests[] = {
1371 offsetof(struct __sk_buff, pkt_type)), 1395 offsetof(struct __sk_buff, pkt_type)),
1372 BPF_EXIT_INSN(), 1396 BPF_EXIT_INSN(),
1373 }, 1397 },
1374 .fixup_map1 = { 4 }, 1398 .fixup_map_hash_8b = { 4 },
1375 .errstr = "different pointers", 1399 .errstr = "different pointers",
1376 .errstr_unpriv = "R1 pointer comparison", 1400 .errstr_unpriv = "R1 pointer comparison",
1377 .result = REJECT, 1401 .result = REJECT,
@@ -1394,7 +1418,7 @@ static struct bpf_test tests[] = {
1394 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 1418 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
1395 BPF_JMP_IMM(BPF_JA, 0, 0, -12), 1419 BPF_JMP_IMM(BPF_JA, 0, 0, -12),
1396 }, 1420 },
1397 .fixup_map1 = { 6 }, 1421 .fixup_map_hash_8b = { 6 },
1398 .errstr = "different pointers", 1422 .errstr = "different pointers",
1399 .errstr_unpriv = "R1 pointer comparison", 1423 .errstr_unpriv = "R1 pointer comparison",
1400 .result = REJECT, 1424 .result = REJECT,
@@ -1418,7 +1442,7 @@ static struct bpf_test tests[] = {
1418 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 1442 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
1419 BPF_JMP_IMM(BPF_JA, 0, 0, -13), 1443 BPF_JMP_IMM(BPF_JA, 0, 0, -13),
1420 }, 1444 },
1421 .fixup_map1 = { 7 }, 1445 .fixup_map_hash_8b = { 7 },
1422 .errstr = "different pointers", 1446 .errstr = "different pointers",
1423 .errstr_unpriv = "R1 pointer comparison", 1447 .errstr_unpriv = "R1 pointer comparison",
1424 .result = REJECT, 1448 .result = REJECT,
@@ -2555,7 +2579,7 @@ static struct bpf_test tests[] = {
2555 BPF_MOV64_IMM(BPF_REG_0, 0), 2579 BPF_MOV64_IMM(BPF_REG_0, 0),
2556 BPF_EXIT_INSN(), 2580 BPF_EXIT_INSN(),
2557 }, 2581 },
2558 .fixup_map1 = { 3 }, 2582 .fixup_map_hash_8b = { 3 },
2559 .errstr_unpriv = "R4 leaks addr", 2583 .errstr_unpriv = "R4 leaks addr",
2560 .result_unpriv = REJECT, 2584 .result_unpriv = REJECT,
2561 .result = ACCEPT, 2585 .result = ACCEPT,
@@ -2572,7 +2596,7 @@ static struct bpf_test tests[] = {
2572 BPF_MOV64_IMM(BPF_REG_0, 0), 2596 BPF_MOV64_IMM(BPF_REG_0, 0),
2573 BPF_EXIT_INSN(), 2597 BPF_EXIT_INSN(),
2574 }, 2598 },
2575 .fixup_map1 = { 3 }, 2599 .fixup_map_hash_8b = { 3 },
2576 .errstr = "invalid indirect read from stack off -8+0 size 8", 2600 .errstr = "invalid indirect read from stack off -8+0 size 8",
2577 .result = REJECT, 2601 .result = REJECT,
2578 }, 2602 },
@@ -2707,6 +2731,137 @@ static struct bpf_test tests[] = {
2707 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2731 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2708 }, 2732 },
2709 { 2733 {
2734 "unpriv: spill/fill of different pointers stx - ctx and sock",
2735 .insns = {
2736 BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
2737 /* struct bpf_sock *sock = bpf_sock_lookup(...); */
2738 BPF_SK_LOOKUP,
2739 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
2740 /* u64 foo; */
2741 /* void *target = &foo; */
2742 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
2743 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
2744 BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
2745 /* if (skb == NULL) *target = sock; */
2746 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
2747 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
2748 /* else *target = skb; */
2749 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
2750 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
2751 /* struct __sk_buff *skb = *target; */
2752 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
2753 /* skb->mark = 42; */
2754 BPF_MOV64_IMM(BPF_REG_3, 42),
2755 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
2756 offsetof(struct __sk_buff, mark)),
2757 /* if (sk) bpf_sk_release(sk) */
2758 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
2759 BPF_EMIT_CALL(BPF_FUNC_sk_release),
2760 BPF_MOV64_IMM(BPF_REG_0, 0),
2761 BPF_EXIT_INSN(),
2762 },
2763 .result = REJECT,
2764 .errstr = "type=ctx expected=sock",
2765 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2766 },
2767 {
2768 "unpriv: spill/fill of different pointers stx - leak sock",
2769 .insns = {
2770 BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
2771 /* struct bpf_sock *sock = bpf_sock_lookup(...); */
2772 BPF_SK_LOOKUP,
2773 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
2774 /* u64 foo; */
2775 /* void *target = &foo; */
2776 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
2777 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
2778 BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
2779 /* if (skb == NULL) *target = sock; */
2780 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
2781 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
2782 /* else *target = skb; */
2783 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
2784 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
2785 /* struct __sk_buff *skb = *target; */
2786 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
2787 /* skb->mark = 42; */
2788 BPF_MOV64_IMM(BPF_REG_3, 42),
2789 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
2790 offsetof(struct __sk_buff, mark)),
2791 BPF_EXIT_INSN(),
2792 },
2793 .result = REJECT,
2794 //.errstr = "same insn cannot be used with different pointers",
2795 .errstr = "Unreleased reference",
2796 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2797 },
2798 {
2799 "unpriv: spill/fill of different pointers stx - sock and ctx (read)",
2800 .insns = {
2801 BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
2802 /* struct bpf_sock *sock = bpf_sock_lookup(...); */
2803 BPF_SK_LOOKUP,
2804 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
2805 /* u64 foo; */
2806 /* void *target = &foo; */
2807 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
2808 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
2809 BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
2810 /* if (skb) *target = skb */
2811 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
2812 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
2813 /* else *target = sock */
2814 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
2815 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
2816 /* struct bpf_sock *sk = *target; */
2817 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
2818 /* if (sk) u32 foo = sk->mark; bpf_sk_release(sk); */
2819 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
2820 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2821 offsetof(struct bpf_sock, mark)),
2822 BPF_EMIT_CALL(BPF_FUNC_sk_release),
2823 BPF_MOV64_IMM(BPF_REG_0, 0),
2824 BPF_EXIT_INSN(),
2825 },
2826 .result = REJECT,
2827 .errstr = "same insn cannot be used with different pointers",
2828 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2829 },
2830 {
2831 "unpriv: spill/fill of different pointers stx - sock and ctx (write)",
2832 .insns = {
2833 BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
2834 /* struct bpf_sock *sock = bpf_sock_lookup(...); */
2835 BPF_SK_LOOKUP,
2836 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
2837 /* u64 foo; */
2838 /* void *target = &foo; */
2839 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
2840 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
2841 BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
2842 /* if (skb) *target = skb */
2843 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
2844 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
2845 /* else *target = sock */
2846 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
2847 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
2848 /* struct bpf_sock *sk = *target; */
2849 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
2850 /* if (sk) sk->mark = 42; bpf_sk_release(sk); */
2851 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
2852 BPF_MOV64_IMM(BPF_REG_3, 42),
2853 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
2854 offsetof(struct bpf_sock, mark)),
2855 BPF_EMIT_CALL(BPF_FUNC_sk_release),
2856 BPF_MOV64_IMM(BPF_REG_0, 0),
2857 BPF_EXIT_INSN(),
2858 },
2859 .result = REJECT,
2860 //.errstr = "same insn cannot be used with different pointers",
2861 .errstr = "cannot write into socket",
2862 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2863 },
2864 {
2710 "unpriv: spill/fill of different pointers ldx", 2865 "unpriv: spill/fill of different pointers ldx",
2711 .insns = { 2866 .insns = {
2712 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), 2867 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
@@ -2743,7 +2898,7 @@ static struct bpf_test tests[] = {
2743 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 2898 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
2744 BPF_EXIT_INSN(), 2899 BPF_EXIT_INSN(),
2745 }, 2900 },
2746 .fixup_map1 = { 3 }, 2901 .fixup_map_hash_8b = { 3 },
2747 .errstr_unpriv = "R0 leaks addr", 2902 .errstr_unpriv = "R0 leaks addr",
2748 .result_unpriv = REJECT, 2903 .result_unpriv = REJECT,
2749 .result = ACCEPT, 2904 .result = ACCEPT,
@@ -2783,7 +2938,7 @@ static struct bpf_test tests[] = {
2783 BPF_MOV64_IMM(BPF_REG_0, 0), 2938 BPF_MOV64_IMM(BPF_REG_0, 0),
2784 BPF_EXIT_INSN(), 2939 BPF_EXIT_INSN(),
2785 }, 2940 },
2786 .fixup_map1 = { 1 }, 2941 .fixup_map_hash_8b = { 1 },
2787 .errstr_unpriv = "R1 pointer comparison", 2942 .errstr_unpriv = "R1 pointer comparison",
2788 .result_unpriv = REJECT, 2943 .result_unpriv = REJECT,
2789 .result = ACCEPT, 2944 .result = ACCEPT,
@@ -3275,7 +3430,7 @@ static struct bpf_test tests[] = {
3275 BPF_ST_MEM(BPF_DW, BPF_REG_1, offsetof(struct __sk_buff, mark), 0), 3430 BPF_ST_MEM(BPF_DW, BPF_REG_1, offsetof(struct __sk_buff, mark), 0),
3276 BPF_EXIT_INSN(), 3431 BPF_EXIT_INSN(),
3277 }, 3432 },
3278 .errstr = "BPF_ST stores into R1 context is not allowed", 3433 .errstr = "BPF_ST stores into R1 ctx is not allowed",
3279 .result = REJECT, 3434 .result = REJECT,
3280 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3435 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3281 }, 3436 },
@@ -3287,7 +3442,7 @@ static struct bpf_test tests[] = {
3287 BPF_REG_0, offsetof(struct __sk_buff, mark), 0), 3442 BPF_REG_0, offsetof(struct __sk_buff, mark), 0),
3288 BPF_EXIT_INSN(), 3443 BPF_EXIT_INSN(),
3289 }, 3444 },
3290 .errstr = "BPF_XADD stores into R1 context is not allowed", 3445 .errstr = "BPF_XADD stores into R1 ctx is not allowed",
3291 .result = REJECT, 3446 .result = REJECT,
3292 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3447 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3293 }, 3448 },
@@ -3637,7 +3792,7 @@ static struct bpf_test tests[] = {
3637 BPF_MOV64_IMM(BPF_REG_0, 0), 3792 BPF_MOV64_IMM(BPF_REG_0, 0),
3638 BPF_EXIT_INSN(), 3793 BPF_EXIT_INSN(),
3639 }, 3794 },
3640 .errstr = "R3 pointer arithmetic on PTR_TO_PACKET_END", 3795 .errstr = "R3 pointer arithmetic on pkt_end",
3641 .result = REJECT, 3796 .result = REJECT,
3642 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3797 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3643 }, 3798 },
@@ -3922,7 +4077,7 @@ static struct bpf_test tests[] = {
3922 BPF_MOV64_IMM(BPF_REG_0, 0), 4077 BPF_MOV64_IMM(BPF_REG_0, 0),
3923 BPF_EXIT_INSN(), 4078 BPF_EXIT_INSN(),
3924 }, 4079 },
3925 .fixup_map1 = { 5 }, 4080 .fixup_map_hash_8b = { 5 },
3926 .result_unpriv = ACCEPT, 4081 .result_unpriv = ACCEPT,
3927 .result = ACCEPT, 4082 .result = ACCEPT,
3928 .prog_type = BPF_PROG_TYPE_XDP, 4083 .prog_type = BPF_PROG_TYPE_XDP,
@@ -3938,7 +4093,7 @@ static struct bpf_test tests[] = {
3938 BPF_MOV64_IMM(BPF_REG_0, 0), 4093 BPF_MOV64_IMM(BPF_REG_0, 0),
3939 BPF_EXIT_INSN(), 4094 BPF_EXIT_INSN(),
3940 }, 4095 },
3941 .fixup_map1 = { 1 }, 4096 .fixup_map_hash_8b = { 1 },
3942 .result = REJECT, 4097 .result = REJECT,
3943 .errstr = "invalid access to packet", 4098 .errstr = "invalid access to packet",
3944 .prog_type = BPF_PROG_TYPE_XDP, 4099 .prog_type = BPF_PROG_TYPE_XDP,
@@ -3966,7 +4121,7 @@ static struct bpf_test tests[] = {
3966 BPF_MOV64_IMM(BPF_REG_0, 0), 4121 BPF_MOV64_IMM(BPF_REG_0, 0),
3967 BPF_EXIT_INSN(), 4122 BPF_EXIT_INSN(),
3968 }, 4123 },
3969 .fixup_map1 = { 11 }, 4124 .fixup_map_hash_8b = { 11 },
3970 .result = ACCEPT, 4125 .result = ACCEPT,
3971 .prog_type = BPF_PROG_TYPE_XDP, 4126 .prog_type = BPF_PROG_TYPE_XDP,
3972 }, 4127 },
@@ -3988,7 +4143,7 @@ static struct bpf_test tests[] = {
3988 BPF_MOV64_IMM(BPF_REG_0, 0), 4143 BPF_MOV64_IMM(BPF_REG_0, 0),
3989 BPF_EXIT_INSN(), 4144 BPF_EXIT_INSN(),
3990 }, 4145 },
3991 .fixup_map1 = { 7 }, 4146 .fixup_map_hash_8b = { 7 },
3992 .result = REJECT, 4147 .result = REJECT,
3993 .errstr = "invalid access to packet", 4148 .errstr = "invalid access to packet",
3994 .prog_type = BPF_PROG_TYPE_XDP, 4149 .prog_type = BPF_PROG_TYPE_XDP,
@@ -4010,7 +4165,7 @@ static struct bpf_test tests[] = {
4010 BPF_MOV64_IMM(BPF_REG_0, 0), 4165 BPF_MOV64_IMM(BPF_REG_0, 0),
4011 BPF_EXIT_INSN(), 4166 BPF_EXIT_INSN(),
4012 }, 4167 },
4013 .fixup_map1 = { 6 }, 4168 .fixup_map_hash_8b = { 6 },
4014 .result = REJECT, 4169 .result = REJECT,
4015 .errstr = "invalid access to packet", 4170 .errstr = "invalid access to packet",
4016 .prog_type = BPF_PROG_TYPE_XDP, 4171 .prog_type = BPF_PROG_TYPE_XDP,
@@ -4033,7 +4188,7 @@ static struct bpf_test tests[] = {
4033 BPF_MOV64_IMM(BPF_REG_0, 0), 4188 BPF_MOV64_IMM(BPF_REG_0, 0),
4034 BPF_EXIT_INSN(), 4189 BPF_EXIT_INSN(),
4035 }, 4190 },
4036 .fixup_map1 = { 5 }, 4191 .fixup_map_hash_8b = { 5 },
4037 .result = ACCEPT, 4192 .result = ACCEPT,
4038 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 4193 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
4039 }, 4194 },
@@ -4048,7 +4203,7 @@ static struct bpf_test tests[] = {
4048 BPF_MOV64_IMM(BPF_REG_0, 0), 4203 BPF_MOV64_IMM(BPF_REG_0, 0),
4049 BPF_EXIT_INSN(), 4204 BPF_EXIT_INSN(),
4050 }, 4205 },
4051 .fixup_map1 = { 1 }, 4206 .fixup_map_hash_8b = { 1 },
4052 .result = REJECT, 4207 .result = REJECT,
4053 .errstr = "invalid access to packet", 4208 .errstr = "invalid access to packet",
4054 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 4209 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -4076,7 +4231,7 @@ static struct bpf_test tests[] = {
4076 BPF_MOV64_IMM(BPF_REG_0, 0), 4231 BPF_MOV64_IMM(BPF_REG_0, 0),
4077 BPF_EXIT_INSN(), 4232 BPF_EXIT_INSN(),
4078 }, 4233 },
4079 .fixup_map1 = { 11 }, 4234 .fixup_map_hash_8b = { 11 },
4080 .result = ACCEPT, 4235 .result = ACCEPT,
4081 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 4236 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
4082 }, 4237 },
@@ -4098,7 +4253,7 @@ static struct bpf_test tests[] = {
4098 BPF_MOV64_IMM(BPF_REG_0, 0), 4253 BPF_MOV64_IMM(BPF_REG_0, 0),
4099 BPF_EXIT_INSN(), 4254 BPF_EXIT_INSN(),
4100 }, 4255 },
4101 .fixup_map1 = { 7 }, 4256 .fixup_map_hash_8b = { 7 },
4102 .result = REJECT, 4257 .result = REJECT,
4103 .errstr = "invalid access to packet", 4258 .errstr = "invalid access to packet",
4104 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 4259 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -4120,7 +4275,7 @@ static struct bpf_test tests[] = {
4120 BPF_MOV64_IMM(BPF_REG_0, 0), 4275 BPF_MOV64_IMM(BPF_REG_0, 0),
4121 BPF_EXIT_INSN(), 4276 BPF_EXIT_INSN(),
4122 }, 4277 },
4123 .fixup_map1 = { 6 }, 4278 .fixup_map_hash_8b = { 6 },
4124 .result = REJECT, 4279 .result = REJECT,
4125 .errstr = "invalid access to packet", 4280 .errstr = "invalid access to packet",
4126 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 4281 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -4391,6 +4546,85 @@ static struct bpf_test tests[] = {
4391 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 4546 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
4392 }, 4547 },
4393 { 4548 {
4549 "prevent map lookup in sockmap",
4550 .insns = {
4551 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4552 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4553 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4554 BPF_LD_MAP_FD(BPF_REG_1, 0),
4555 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4556 BPF_FUNC_map_lookup_elem),
4557 BPF_EXIT_INSN(),
4558 },
4559 .fixup_map_sockmap = { 3 },
4560 .result = REJECT,
4561 .errstr = "cannot pass map_type 15 into func bpf_map_lookup_elem",
4562 .prog_type = BPF_PROG_TYPE_SOCK_OPS,
4563 },
4564 {
4565 "prevent map lookup in sockhash",
4566 .insns = {
4567 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4568 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4569 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4570 BPF_LD_MAP_FD(BPF_REG_1, 0),
4571 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4572 BPF_FUNC_map_lookup_elem),
4573 BPF_EXIT_INSN(),
4574 },
4575 .fixup_map_sockhash = { 3 },
4576 .result = REJECT,
4577 .errstr = "cannot pass map_type 18 into func bpf_map_lookup_elem",
4578 .prog_type = BPF_PROG_TYPE_SOCK_OPS,
4579 },
4580 {
4581 "prevent map lookup in xskmap",
4582 .insns = {
4583 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4584 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4585 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4586 BPF_LD_MAP_FD(BPF_REG_1, 0),
4587 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4588 BPF_FUNC_map_lookup_elem),
4589 BPF_EXIT_INSN(),
4590 },
4591 .fixup_map_xskmap = { 3 },
4592 .result = REJECT,
4593 .errstr = "cannot pass map_type 17 into func bpf_map_lookup_elem",
4594 .prog_type = BPF_PROG_TYPE_XDP,
4595 },
4596 {
4597 "prevent map lookup in stack trace",
4598 .insns = {
4599 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4600 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4601 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4602 BPF_LD_MAP_FD(BPF_REG_1, 0),
4603 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4604 BPF_FUNC_map_lookup_elem),
4605 BPF_EXIT_INSN(),
4606 },
4607 .fixup_map_stacktrace = { 3 },
4608 .result = REJECT,
4609 .errstr = "cannot pass map_type 7 into func bpf_map_lookup_elem",
4610 .prog_type = BPF_PROG_TYPE_PERF_EVENT,
4611 },
4612 {
4613 "prevent map lookup in prog array",
4614 .insns = {
4615 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4616 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4617 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4618 BPF_LD_MAP_FD(BPF_REG_1, 0),
4619 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4620 BPF_FUNC_map_lookup_elem),
4621 BPF_EXIT_INSN(),
4622 },
4623 .fixup_prog2 = { 3 },
4624 .result = REJECT,
4625 .errstr = "cannot pass map_type 3 into func bpf_map_lookup_elem",
4626 },
4627 {
4394 "valid map access into an array with a constant", 4628 "valid map access into an array with a constant",
4395 .insns = { 4629 .insns = {
4396 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 4630 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
@@ -4404,7 +4638,7 @@ static struct bpf_test tests[] = {
4404 offsetof(struct test_val, foo)), 4638 offsetof(struct test_val, foo)),
4405 BPF_EXIT_INSN(), 4639 BPF_EXIT_INSN(),
4406 }, 4640 },
4407 .fixup_map2 = { 3 }, 4641 .fixup_map_hash_48b = { 3 },
4408 .errstr_unpriv = "R0 leaks addr", 4642 .errstr_unpriv = "R0 leaks addr",
4409 .result_unpriv = REJECT, 4643 .result_unpriv = REJECT,
4410 .result = ACCEPT, 4644 .result = ACCEPT,
@@ -4426,7 +4660,7 @@ static struct bpf_test tests[] = {
4426 offsetof(struct test_val, foo)), 4660 offsetof(struct test_val, foo)),
4427 BPF_EXIT_INSN(), 4661 BPF_EXIT_INSN(),
4428 }, 4662 },
4429 .fixup_map2 = { 3 }, 4663 .fixup_map_hash_48b = { 3 },
4430 .errstr_unpriv = "R0 leaks addr", 4664 .errstr_unpriv = "R0 leaks addr",
4431 .result_unpriv = REJECT, 4665 .result_unpriv = REJECT,
4432 .result = ACCEPT, 4666 .result = ACCEPT,
@@ -4450,7 +4684,7 @@ static struct bpf_test tests[] = {
4450 offsetof(struct test_val, foo)), 4684 offsetof(struct test_val, foo)),
4451 BPF_EXIT_INSN(), 4685 BPF_EXIT_INSN(),
4452 }, 4686 },
4453 .fixup_map2 = { 3 }, 4687 .fixup_map_hash_48b = { 3 },
4454 .errstr_unpriv = "R0 leaks addr", 4688 .errstr_unpriv = "R0 leaks addr",
4455 .result_unpriv = REJECT, 4689 .result_unpriv = REJECT,
4456 .result = ACCEPT, 4690 .result = ACCEPT,
@@ -4478,7 +4712,7 @@ static struct bpf_test tests[] = {
4478 offsetof(struct test_val, foo)), 4712 offsetof(struct test_val, foo)),
4479 BPF_EXIT_INSN(), 4713 BPF_EXIT_INSN(),
4480 }, 4714 },
4481 .fixup_map2 = { 3 }, 4715 .fixup_map_hash_48b = { 3 },
4482 .errstr_unpriv = "R0 leaks addr", 4716 .errstr_unpriv = "R0 leaks addr",
4483 .result_unpriv = REJECT, 4717 .result_unpriv = REJECT,
4484 .result = ACCEPT, 4718 .result = ACCEPT,
@@ -4498,7 +4732,7 @@ static struct bpf_test tests[] = {
4498 offsetof(struct test_val, foo)), 4732 offsetof(struct test_val, foo)),
4499 BPF_EXIT_INSN(), 4733 BPF_EXIT_INSN(),
4500 }, 4734 },
4501 .fixup_map2 = { 3 }, 4735 .fixup_map_hash_48b = { 3 },
4502 .errstr = "invalid access to map value, value_size=48 off=48 size=8", 4736 .errstr = "invalid access to map value, value_size=48 off=48 size=8",
4503 .result = REJECT, 4737 .result = REJECT,
4504 }, 4738 },
@@ -4519,7 +4753,7 @@ static struct bpf_test tests[] = {
4519 offsetof(struct test_val, foo)), 4753 offsetof(struct test_val, foo)),
4520 BPF_EXIT_INSN(), 4754 BPF_EXIT_INSN(),
4521 }, 4755 },
4522 .fixup_map2 = { 3 }, 4756 .fixup_map_hash_48b = { 3 },
4523 .errstr = "R0 min value is outside of the array range", 4757 .errstr = "R0 min value is outside of the array range",
4524 .result = REJECT, 4758 .result = REJECT,
4525 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 4759 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4541,7 +4775,7 @@ static struct bpf_test tests[] = {
4541 offsetof(struct test_val, foo)), 4775 offsetof(struct test_val, foo)),
4542 BPF_EXIT_INSN(), 4776 BPF_EXIT_INSN(),
4543 }, 4777 },
4544 .fixup_map2 = { 3 }, 4778 .fixup_map_hash_48b = { 3 },
4545 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map", 4779 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map",
4546 .result = REJECT, 4780 .result = REJECT,
4547 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 4781 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4566,7 +4800,7 @@ static struct bpf_test tests[] = {
4566 offsetof(struct test_val, foo)), 4800 offsetof(struct test_val, foo)),
4567 BPF_EXIT_INSN(), 4801 BPF_EXIT_INSN(),
4568 }, 4802 },
4569 .fixup_map2 = { 3 }, 4803 .fixup_map_hash_48b = { 3 },
4570 .errstr_unpriv = "R0 leaks addr", 4804 .errstr_unpriv = "R0 leaks addr",
4571 .errstr = "R0 unbounded memory access", 4805 .errstr = "R0 unbounded memory access",
4572 .result_unpriv = REJECT, 4806 .result_unpriv = REJECT,
@@ -4593,7 +4827,7 @@ static struct bpf_test tests[] = {
4593 offsetof(struct test_val, foo)), 4827 offsetof(struct test_val, foo)),
4594 BPF_EXIT_INSN(), 4828 BPF_EXIT_INSN(),
4595 }, 4829 },
4596 .fixup_map2 = { 3 }, 4830 .fixup_map_hash_48b = { 3 },
4597 .errstr_unpriv = "R0 leaks addr", 4831 .errstr_unpriv = "R0 leaks addr",
4598 .errstr = "invalid access to map value, value_size=48 off=44 size=8", 4832 .errstr = "invalid access to map value, value_size=48 off=44 size=8",
4599 .result_unpriv = REJECT, 4833 .result_unpriv = REJECT,
@@ -4623,12 +4857,183 @@ static struct bpf_test tests[] = {
4623 offsetof(struct test_val, foo)), 4857 offsetof(struct test_val, foo)),
4624 BPF_EXIT_INSN(), 4858 BPF_EXIT_INSN(),
4625 }, 4859 },
4626 .fixup_map2 = { 3, 11 }, 4860 .fixup_map_hash_48b = { 3, 11 },
4627 .errstr = "R0 pointer += pointer", 4861 .errstr = "R0 pointer += pointer",
4628 .result = REJECT, 4862 .result = REJECT,
4629 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 4863 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
4630 }, 4864 },
4631 { 4865 {
4866 "direct packet read test#1 for CGROUP_SKB",
4867 .insns = {
4868 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
4869 offsetof(struct __sk_buff, data)),
4870 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
4871 offsetof(struct __sk_buff, data_end)),
4872 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4873 offsetof(struct __sk_buff, len)),
4874 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4875 offsetof(struct __sk_buff, pkt_type)),
4876 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4877 offsetof(struct __sk_buff, mark)),
4878 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
4879 offsetof(struct __sk_buff, mark)),
4880 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4881 offsetof(struct __sk_buff, queue_mapping)),
4882 BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4883 offsetof(struct __sk_buff, protocol)),
4884 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
4885 offsetof(struct __sk_buff, vlan_present)),
4886 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
4887 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
4888 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
4889 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
4890 BPF_MOV64_IMM(BPF_REG_0, 0),
4891 BPF_EXIT_INSN(),
4892 },
4893 .result = ACCEPT,
4894 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4895 },
4896 {
4897 "direct packet read test#2 for CGROUP_SKB",
4898 .insns = {
4899 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4900 offsetof(struct __sk_buff, vlan_tci)),
4901 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4902 offsetof(struct __sk_buff, vlan_proto)),
4903 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4904 offsetof(struct __sk_buff, priority)),
4905 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
4906 offsetof(struct __sk_buff, priority)),
4907 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4908 offsetof(struct __sk_buff,
4909 ingress_ifindex)),
4910 BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4911 offsetof(struct __sk_buff, tc_index)),
4912 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
4913 offsetof(struct __sk_buff, hash)),
4914 BPF_MOV64_IMM(BPF_REG_0, 0),
4915 BPF_EXIT_INSN(),
4916 },
4917 .result = ACCEPT,
4918 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4919 },
4920 {
4921 "direct packet read test#3 for CGROUP_SKB",
4922 .insns = {
4923 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4924 offsetof(struct __sk_buff, cb[0])),
4925 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4926 offsetof(struct __sk_buff, cb[1])),
4927 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4928 offsetof(struct __sk_buff, cb[2])),
4929 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4930 offsetof(struct __sk_buff, cb[3])),
4931 BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4932 offsetof(struct __sk_buff, cb[4])),
4933 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
4934 offsetof(struct __sk_buff, napi_id)),
4935 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_4,
4936 offsetof(struct __sk_buff, cb[0])),
4937 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_5,
4938 offsetof(struct __sk_buff, cb[1])),
4939 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
4940 offsetof(struct __sk_buff, cb[2])),
4941 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_7,
4942 offsetof(struct __sk_buff, cb[3])),
4943 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_8,
4944 offsetof(struct __sk_buff, cb[4])),
4945 BPF_MOV64_IMM(BPF_REG_0, 0),
4946 BPF_EXIT_INSN(),
4947 },
4948 .result = ACCEPT,
4949 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4950 },
4951 {
4952 "direct packet read test#4 for CGROUP_SKB",
4953 .insns = {
4954 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
4955 offsetof(struct __sk_buff, family)),
4956 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
4957 offsetof(struct __sk_buff, remote_ip4)),
4958 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4959 offsetof(struct __sk_buff, local_ip4)),
4960 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4961 offsetof(struct __sk_buff, remote_ip6[0])),
4962 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4963 offsetof(struct __sk_buff, remote_ip6[1])),
4964 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4965 offsetof(struct __sk_buff, remote_ip6[2])),
4966 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4967 offsetof(struct __sk_buff, remote_ip6[3])),
4968 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4969 offsetof(struct __sk_buff, local_ip6[0])),
4970 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4971 offsetof(struct __sk_buff, local_ip6[1])),
4972 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4973 offsetof(struct __sk_buff, local_ip6[2])),
4974 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4975 offsetof(struct __sk_buff, local_ip6[3])),
4976 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4977 offsetof(struct __sk_buff, remote_port)),
4978 BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4979 offsetof(struct __sk_buff, local_port)),
4980 BPF_MOV64_IMM(BPF_REG_0, 0),
4981 BPF_EXIT_INSN(),
4982 },
4983 .result = ACCEPT,
4984 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4985 },
4986 {
4987 "invalid access of tc_classid for CGROUP_SKB",
4988 .insns = {
4989 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
4990 offsetof(struct __sk_buff, tc_classid)),
4991 BPF_MOV64_IMM(BPF_REG_0, 0),
4992 BPF_EXIT_INSN(),
4993 },
4994 .result = REJECT,
4995 .errstr = "invalid bpf_context access",
4996 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4997 },
4998 {
4999 "invalid access of data_meta for CGROUP_SKB",
5000 .insns = {
5001 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5002 offsetof(struct __sk_buff, data_meta)),
5003 BPF_MOV64_IMM(BPF_REG_0, 0),
5004 BPF_EXIT_INSN(),
5005 },
5006 .result = REJECT,
5007 .errstr = "invalid bpf_context access",
5008 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5009 },
5010 {
5011 "invalid access of flow_keys for CGROUP_SKB",
5012 .insns = {
5013 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5014 offsetof(struct __sk_buff, flow_keys)),
5015 BPF_MOV64_IMM(BPF_REG_0, 0),
5016 BPF_EXIT_INSN(),
5017 },
5018 .result = REJECT,
5019 .errstr = "invalid bpf_context access",
5020 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5021 },
5022 {
5023 "invalid write access to napi_id for CGROUP_SKB",
5024 .insns = {
5025 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
5026 offsetof(struct __sk_buff, napi_id)),
5027 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_9,
5028 offsetof(struct __sk_buff, napi_id)),
5029 BPF_MOV64_IMM(BPF_REG_0, 0),
5030 BPF_EXIT_INSN(),
5031 },
5032 .result = REJECT,
5033 .errstr = "invalid bpf_context access",
5034 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5035 },
5036 {
4632 "valid cgroup storage access", 5037 "valid cgroup storage access",
4633 .insns = { 5038 .insns = {
4634 BPF_MOV64_IMM(BPF_REG_2, 0), 5039 BPF_MOV64_IMM(BPF_REG_2, 0),
@@ -4656,7 +5061,7 @@ static struct bpf_test tests[] = {
4656 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1), 5061 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
4657 BPF_EXIT_INSN(), 5062 BPF_EXIT_INSN(),
4658 }, 5063 },
4659 .fixup_map1 = { 1 }, 5064 .fixup_map_hash_8b = { 1 },
4660 .result = REJECT, 5065 .result = REJECT,
4661 .errstr = "cannot pass map_type 1 into func bpf_get_local_storage", 5066 .errstr = "cannot pass map_type 1 into func bpf_get_local_storage",
4662 .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 5067 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
@@ -4676,7 +5081,7 @@ static struct bpf_test tests[] = {
4676 .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 5081 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4677 }, 5082 },
4678 { 5083 {
4679 "invalid per-cgroup storage access 3", 5084 "invalid cgroup storage access 3",
4680 .insns = { 5085 .insns = {
4681 BPF_MOV64_IMM(BPF_REG_2, 0), 5086 BPF_MOV64_IMM(BPF_REG_2, 0),
4682 BPF_LD_MAP_FD(BPF_REG_1, 0), 5087 BPF_LD_MAP_FD(BPF_REG_1, 0),
@@ -4744,6 +5149,121 @@ static struct bpf_test tests[] = {
4744 .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 5149 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4745 }, 5150 },
4746 { 5151 {
5152 "valid per-cpu cgroup storage access",
5153 .insns = {
5154 BPF_MOV64_IMM(BPF_REG_2, 0),
5155 BPF_LD_MAP_FD(BPF_REG_1, 0),
5156 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5157 BPF_FUNC_get_local_storage),
5158 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
5159 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5160 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
5161 BPF_EXIT_INSN(),
5162 },
5163 .fixup_percpu_cgroup_storage = { 1 },
5164 .result = ACCEPT,
5165 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5166 },
5167 {
5168 "invalid per-cpu cgroup storage access 1",
5169 .insns = {
5170 BPF_MOV64_IMM(BPF_REG_2, 0),
5171 BPF_LD_MAP_FD(BPF_REG_1, 0),
5172 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5173 BPF_FUNC_get_local_storage),
5174 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
5175 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5176 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
5177 BPF_EXIT_INSN(),
5178 },
5179 .fixup_map_hash_8b = { 1 },
5180 .result = REJECT,
5181 .errstr = "cannot pass map_type 1 into func bpf_get_local_storage",
5182 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5183 },
5184 {
5185 "invalid per-cpu cgroup storage access 2",
5186 .insns = {
5187 BPF_MOV64_IMM(BPF_REG_2, 0),
5188 BPF_LD_MAP_FD(BPF_REG_1, 1),
5189 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5190 BPF_FUNC_get_local_storage),
5191 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
5192 BPF_EXIT_INSN(),
5193 },
5194 .result = REJECT,
5195 .errstr = "fd 1 is not pointing to valid bpf_map",
5196 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5197 },
5198 {
5199 "invalid per-cpu cgroup storage access 3",
5200 .insns = {
5201 BPF_MOV64_IMM(BPF_REG_2, 0),
5202 BPF_LD_MAP_FD(BPF_REG_1, 0),
5203 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5204 BPF_FUNC_get_local_storage),
5205 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 256),
5206 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
5207 BPF_MOV64_IMM(BPF_REG_0, 0),
5208 BPF_EXIT_INSN(),
5209 },
5210 .fixup_percpu_cgroup_storage = { 1 },
5211 .result = REJECT,
5212 .errstr = "invalid access to map value, value_size=64 off=256 size=4",
5213 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5214 },
5215 {
5216 "invalid per-cpu cgroup storage access 4",
5217 .insns = {
5218 BPF_MOV64_IMM(BPF_REG_2, 0),
5219 BPF_LD_MAP_FD(BPF_REG_1, 0),
5220 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5221 BPF_FUNC_get_local_storage),
5222 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -2),
5223 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5224 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
5225 BPF_EXIT_INSN(),
5226 },
5227 .fixup_cgroup_storage = { 1 },
5228 .result = REJECT,
5229 .errstr = "invalid access to map value, value_size=64 off=-2 size=4",
5230 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5231 },
5232 {
5233 "invalid per-cpu cgroup storage access 5",
5234 .insns = {
5235 BPF_MOV64_IMM(BPF_REG_2, 7),
5236 BPF_LD_MAP_FD(BPF_REG_1, 0),
5237 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5238 BPF_FUNC_get_local_storage),
5239 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
5240 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5241 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
5242 BPF_EXIT_INSN(),
5243 },
5244 .fixup_percpu_cgroup_storage = { 1 },
5245 .result = REJECT,
5246 .errstr = "get_local_storage() doesn't support non-zero flags",
5247 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5248 },
5249 {
5250 "invalid per-cpu cgroup storage access 6",
5251 .insns = {
5252 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
5253 BPF_LD_MAP_FD(BPF_REG_1, 0),
5254 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5255 BPF_FUNC_get_local_storage),
5256 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
5257 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5258 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
5259 BPF_EXIT_INSN(),
5260 },
5261 .fixup_percpu_cgroup_storage = { 1 },
5262 .result = REJECT,
5263 .errstr = "get_local_storage() doesn't support non-zero flags",
5264 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5265 },
5266 {
4747 "multiple registers share map_lookup_elem result", 5267 "multiple registers share map_lookup_elem result",
4748 .insns = { 5268 .insns = {
4749 BPF_MOV64_IMM(BPF_REG_1, 10), 5269 BPF_MOV64_IMM(BPF_REG_1, 10),
@@ -4758,7 +5278,7 @@ static struct bpf_test tests[] = {
4758 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 5278 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
4759 BPF_EXIT_INSN(), 5279 BPF_EXIT_INSN(),
4760 }, 5280 },
4761 .fixup_map1 = { 4 }, 5281 .fixup_map_hash_8b = { 4 },
4762 .result = ACCEPT, 5282 .result = ACCEPT,
4763 .prog_type = BPF_PROG_TYPE_SCHED_CLS 5283 .prog_type = BPF_PROG_TYPE_SCHED_CLS
4764 }, 5284 },
@@ -4779,8 +5299,8 @@ static struct bpf_test tests[] = {
4779 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 5299 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
4780 BPF_EXIT_INSN(), 5300 BPF_EXIT_INSN(),
4781 }, 5301 },
4782 .fixup_map1 = { 4 }, 5302 .fixup_map_hash_8b = { 4 },
4783 .errstr = "R4 pointer arithmetic on PTR_TO_MAP_VALUE_OR_NULL", 5303 .errstr = "R4 pointer arithmetic on map_value_or_null",
4784 .result = REJECT, 5304 .result = REJECT,
4785 .prog_type = BPF_PROG_TYPE_SCHED_CLS 5305 .prog_type = BPF_PROG_TYPE_SCHED_CLS
4786 }, 5306 },
@@ -4800,8 +5320,8 @@ static struct bpf_test tests[] = {
4800 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 5320 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
4801 BPF_EXIT_INSN(), 5321 BPF_EXIT_INSN(),
4802 }, 5322 },
4803 .fixup_map1 = { 4 }, 5323 .fixup_map_hash_8b = { 4 },
4804 .errstr = "R4 pointer arithmetic on PTR_TO_MAP_VALUE_OR_NULL", 5324 .errstr = "R4 pointer arithmetic on map_value_or_null",
4805 .result = REJECT, 5325 .result = REJECT,
4806 .prog_type = BPF_PROG_TYPE_SCHED_CLS 5326 .prog_type = BPF_PROG_TYPE_SCHED_CLS
4807 }, 5327 },
@@ -4821,8 +5341,8 @@ static struct bpf_test tests[] = {
4821 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 5341 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
4822 BPF_EXIT_INSN(), 5342 BPF_EXIT_INSN(),
4823 }, 5343 },
4824 .fixup_map1 = { 4 }, 5344 .fixup_map_hash_8b = { 4 },
4825 .errstr = "R4 pointer arithmetic on PTR_TO_MAP_VALUE_OR_NULL", 5345 .errstr = "R4 pointer arithmetic on map_value_or_null",
4826 .result = REJECT, 5346 .result = REJECT,
4827 .prog_type = BPF_PROG_TYPE_SCHED_CLS 5347 .prog_type = BPF_PROG_TYPE_SCHED_CLS
4828 }, 5348 },
@@ -4847,7 +5367,7 @@ static struct bpf_test tests[] = {
4847 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 5367 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
4848 BPF_EXIT_INSN(), 5368 BPF_EXIT_INSN(),
4849 }, 5369 },
4850 .fixup_map1 = { 4 }, 5370 .fixup_map_hash_8b = { 4 },
4851 .result = REJECT, 5371 .result = REJECT,
4852 .errstr = "R4 !read_ok", 5372 .errstr = "R4 !read_ok",
4853 .prog_type = BPF_PROG_TYPE_SCHED_CLS 5373 .prog_type = BPF_PROG_TYPE_SCHED_CLS
@@ -4875,7 +5395,7 @@ static struct bpf_test tests[] = {
4875 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 5395 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
4876 BPF_EXIT_INSN(), 5396 BPF_EXIT_INSN(),
4877 }, 5397 },
4878 .fixup_map1 = { 4 }, 5398 .fixup_map_hash_8b = { 4 },
4879 .result = ACCEPT, 5399 .result = ACCEPT,
4880 .prog_type = BPF_PROG_TYPE_SCHED_CLS 5400 .prog_type = BPF_PROG_TYPE_SCHED_CLS
4881 }, 5401 },
@@ -4896,7 +5416,7 @@ static struct bpf_test tests[] = {
4896 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), 5416 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
4897 BPF_EXIT_INSN(), 5417 BPF_EXIT_INSN(),
4898 }, 5418 },
4899 .fixup_map2 = { 3 }, 5419 .fixup_map_hash_48b = { 3 },
4900 .errstr = "R0 unbounded memory access", 5420 .errstr = "R0 unbounded memory access",
4901 .result = REJECT, 5421 .result = REJECT,
4902 .errstr_unpriv = "R0 leaks addr", 5422 .errstr_unpriv = "R0 leaks addr",
@@ -5146,11 +5666,11 @@ static struct bpf_test tests[] = {
5146 offsetof(struct __sk_buff, cb[0])), 5666 offsetof(struct __sk_buff, cb[0])),
5147 BPF_EXIT_INSN(), 5667 BPF_EXIT_INSN(),
5148 }, 5668 },
5149 .fixup_map1 = { 2 }, 5669 .fixup_map_hash_8b = { 2 },
5150 .errstr_unpriv = "R2 leaks addr into mem", 5670 .errstr_unpriv = "R2 leaks addr into mem",
5151 .result_unpriv = REJECT, 5671 .result_unpriv = REJECT,
5152 .result = REJECT, 5672 .result = REJECT,
5153 .errstr = "BPF_XADD stores into R1 context is not allowed", 5673 .errstr = "BPF_XADD stores into R1 ctx is not allowed",
5154 }, 5674 },
5155 { 5675 {
5156 "leak pointer into ctx 2", 5676 "leak pointer into ctx 2",
@@ -5165,7 +5685,7 @@ static struct bpf_test tests[] = {
5165 .errstr_unpriv = "R10 leaks addr into mem", 5685 .errstr_unpriv = "R10 leaks addr into mem",
5166 .result_unpriv = REJECT, 5686 .result_unpriv = REJECT,
5167 .result = REJECT, 5687 .result = REJECT,
5168 .errstr = "BPF_XADD stores into R1 context is not allowed", 5688 .errstr = "BPF_XADD stores into R1 ctx is not allowed",
5169 }, 5689 },
5170 { 5690 {
5171 "leak pointer into ctx 3", 5691 "leak pointer into ctx 3",
@@ -5176,7 +5696,7 @@ static struct bpf_test tests[] = {
5176 offsetof(struct __sk_buff, cb[0])), 5696 offsetof(struct __sk_buff, cb[0])),
5177 BPF_EXIT_INSN(), 5697 BPF_EXIT_INSN(),
5178 }, 5698 },
5179 .fixup_map1 = { 1 }, 5699 .fixup_map_hash_8b = { 1 },
5180 .errstr_unpriv = "R2 leaks addr into ctx", 5700 .errstr_unpriv = "R2 leaks addr into ctx",
5181 .result_unpriv = REJECT, 5701 .result_unpriv = REJECT,
5182 .result = ACCEPT, 5702 .result = ACCEPT,
@@ -5198,7 +5718,7 @@ static struct bpf_test tests[] = {
5198 BPF_MOV64_IMM(BPF_REG_0, 0), 5718 BPF_MOV64_IMM(BPF_REG_0, 0),
5199 BPF_EXIT_INSN(), 5719 BPF_EXIT_INSN(),
5200 }, 5720 },
5201 .fixup_map1 = { 4 }, 5721 .fixup_map_hash_8b = { 4 },
5202 .errstr_unpriv = "R6 leaks addr into mem", 5722 .errstr_unpriv = "R6 leaks addr into mem",
5203 .result_unpriv = REJECT, 5723 .result_unpriv = REJECT,
5204 .result = ACCEPT, 5724 .result = ACCEPT,
@@ -5218,7 +5738,7 @@ static struct bpf_test tests[] = {
5218 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5738 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5219 BPF_EXIT_INSN(), 5739 BPF_EXIT_INSN(),
5220 }, 5740 },
5221 .fixup_map2 = { 3 }, 5741 .fixup_map_hash_48b = { 3 },
5222 .result = ACCEPT, 5742 .result = ACCEPT,
5223 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5743 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5224 }, 5744 },
@@ -5237,7 +5757,7 @@ static struct bpf_test tests[] = {
5237 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5757 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5238 BPF_EXIT_INSN(), 5758 BPF_EXIT_INSN(),
5239 }, 5759 },
5240 .fixup_map2 = { 3 }, 5760 .fixup_map_hash_48b = { 3 },
5241 .result = ACCEPT, 5761 .result = ACCEPT,
5242 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5762 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5243 }, 5763 },
@@ -5255,7 +5775,7 @@ static struct bpf_test tests[] = {
5255 BPF_EMIT_CALL(BPF_FUNC_trace_printk), 5775 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
5256 BPF_EXIT_INSN(), 5776 BPF_EXIT_INSN(),
5257 }, 5777 },
5258 .fixup_map2 = { 3 }, 5778 .fixup_map_hash_48b = { 3 },
5259 .errstr = "invalid access to map value, value_size=48 off=0 size=0", 5779 .errstr = "invalid access to map value, value_size=48 off=0 size=0",
5260 .result = REJECT, 5780 .result = REJECT,
5261 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5781 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5275,7 +5795,7 @@ static struct bpf_test tests[] = {
5275 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5795 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5276 BPF_EXIT_INSN(), 5796 BPF_EXIT_INSN(),
5277 }, 5797 },
5278 .fixup_map2 = { 3 }, 5798 .fixup_map_hash_48b = { 3 },
5279 .errstr = "invalid access to map value, value_size=48 off=0 size=56", 5799 .errstr = "invalid access to map value, value_size=48 off=0 size=56",
5280 .result = REJECT, 5800 .result = REJECT,
5281 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5801 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5295,7 +5815,7 @@ static struct bpf_test tests[] = {
5295 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5815 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5296 BPF_EXIT_INSN(), 5816 BPF_EXIT_INSN(),
5297 }, 5817 },
5298 .fixup_map2 = { 3 }, 5818 .fixup_map_hash_48b = { 3 },
5299 .errstr = "R2 min value is negative", 5819 .errstr = "R2 min value is negative",
5300 .result = REJECT, 5820 .result = REJECT,
5301 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5821 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5319,7 +5839,7 @@ static struct bpf_test tests[] = {
5319 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5839 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5320 BPF_EXIT_INSN(), 5840 BPF_EXIT_INSN(),
5321 }, 5841 },
5322 .fixup_map2 = { 3 }, 5842 .fixup_map_hash_48b = { 3 },
5323 .result = ACCEPT, 5843 .result = ACCEPT,
5324 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5844 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5325 }, 5845 },
@@ -5340,7 +5860,7 @@ static struct bpf_test tests[] = {
5340 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5860 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5341 BPF_EXIT_INSN(), 5861 BPF_EXIT_INSN(),
5342 }, 5862 },
5343 .fixup_map2 = { 3 }, 5863 .fixup_map_hash_48b = { 3 },
5344 .result = ACCEPT, 5864 .result = ACCEPT,
5345 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5865 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5346 }, 5866 },
@@ -5360,7 +5880,7 @@ static struct bpf_test tests[] = {
5360 BPF_EMIT_CALL(BPF_FUNC_trace_printk), 5880 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
5361 BPF_EXIT_INSN(), 5881 BPF_EXIT_INSN(),
5362 }, 5882 },
5363 .fixup_map2 = { 3 }, 5883 .fixup_map_hash_48b = { 3 },
5364 .errstr = "invalid access to map value, value_size=48 off=4 size=0", 5884 .errstr = "invalid access to map value, value_size=48 off=4 size=0",
5365 .result = REJECT, 5885 .result = REJECT,
5366 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5886 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5384,7 +5904,7 @@ static struct bpf_test tests[] = {
5384 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5904 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5385 BPF_EXIT_INSN(), 5905 BPF_EXIT_INSN(),
5386 }, 5906 },
5387 .fixup_map2 = { 3 }, 5907 .fixup_map_hash_48b = { 3 },
5388 .errstr = "invalid access to map value, value_size=48 off=4 size=52", 5908 .errstr = "invalid access to map value, value_size=48 off=4 size=52",
5389 .result = REJECT, 5909 .result = REJECT,
5390 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5910 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5406,7 +5926,7 @@ static struct bpf_test tests[] = {
5406 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5926 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5407 BPF_EXIT_INSN(), 5927 BPF_EXIT_INSN(),
5408 }, 5928 },
5409 .fixup_map2 = { 3 }, 5929 .fixup_map_hash_48b = { 3 },
5410 .errstr = "R2 min value is negative", 5930 .errstr = "R2 min value is negative",
5411 .result = REJECT, 5931 .result = REJECT,
5412 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5932 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5428,7 +5948,7 @@ static struct bpf_test tests[] = {
5428 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5948 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5429 BPF_EXIT_INSN(), 5949 BPF_EXIT_INSN(),
5430 }, 5950 },
5431 .fixup_map2 = { 3 }, 5951 .fixup_map_hash_48b = { 3 },
5432 .errstr = "R2 min value is negative", 5952 .errstr = "R2 min value is negative",
5433 .result = REJECT, 5953 .result = REJECT,
5434 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5954 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5453,7 +5973,7 @@ static struct bpf_test tests[] = {
5453 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5973 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5454 BPF_EXIT_INSN(), 5974 BPF_EXIT_INSN(),
5455 }, 5975 },
5456 .fixup_map2 = { 3 }, 5976 .fixup_map_hash_48b = { 3 },
5457 .result = ACCEPT, 5977 .result = ACCEPT,
5458 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5978 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5459 }, 5979 },
@@ -5475,7 +5995,7 @@ static struct bpf_test tests[] = {
5475 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5995 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5476 BPF_EXIT_INSN(), 5996 BPF_EXIT_INSN(),
5477 }, 5997 },
5478 .fixup_map2 = { 3 }, 5998 .fixup_map_hash_48b = { 3 },
5479 .result = ACCEPT, 5999 .result = ACCEPT,
5480 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6000 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5481 }, 6001 },
@@ -5495,7 +6015,7 @@ static struct bpf_test tests[] = {
5495 BPF_EMIT_CALL(BPF_FUNC_trace_printk), 6015 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
5496 BPF_EXIT_INSN(), 6016 BPF_EXIT_INSN(),
5497 }, 6017 },
5498 .fixup_map2 = { 3 }, 6018 .fixup_map_hash_48b = { 3 },
5499 .errstr = "R1 min value is outside of the array range", 6019 .errstr = "R1 min value is outside of the array range",
5500 .result = REJECT, 6020 .result = REJECT,
5501 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6021 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5520,7 +6040,7 @@ static struct bpf_test tests[] = {
5520 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6040 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5521 BPF_EXIT_INSN(), 6041 BPF_EXIT_INSN(),
5522 }, 6042 },
5523 .fixup_map2 = { 3 }, 6043 .fixup_map_hash_48b = { 3 },
5524 .errstr = "invalid access to map value, value_size=48 off=4 size=52", 6044 .errstr = "invalid access to map value, value_size=48 off=4 size=52",
5525 .result = REJECT, 6045 .result = REJECT,
5526 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6046 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5543,7 +6063,7 @@ static struct bpf_test tests[] = {
5543 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6063 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5544 BPF_EXIT_INSN(), 6064 BPF_EXIT_INSN(),
5545 }, 6065 },
5546 .fixup_map2 = { 3 }, 6066 .fixup_map_hash_48b = { 3 },
5547 .errstr = "R2 min value is negative", 6067 .errstr = "R2 min value is negative",
5548 .result = REJECT, 6068 .result = REJECT,
5549 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6069 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5566,7 +6086,7 @@ static struct bpf_test tests[] = {
5566 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6086 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5567 BPF_EXIT_INSN(), 6087 BPF_EXIT_INSN(),
5568 }, 6088 },
5569 .fixup_map2 = { 3 }, 6089 .fixup_map_hash_48b = { 3 },
5570 .errstr = "R2 min value is negative", 6090 .errstr = "R2 min value is negative",
5571 .result = REJECT, 6091 .result = REJECT,
5572 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6092 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5592,7 +6112,7 @@ static struct bpf_test tests[] = {
5592 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6112 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5593 BPF_EXIT_INSN(), 6113 BPF_EXIT_INSN(),
5594 }, 6114 },
5595 .fixup_map2 = { 3 }, 6115 .fixup_map_hash_48b = { 3 },
5596 .result = ACCEPT, 6116 .result = ACCEPT,
5597 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6117 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5598 }, 6118 },
@@ -5615,7 +6135,7 @@ static struct bpf_test tests[] = {
5615 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6135 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5616 BPF_EXIT_INSN(), 6136 BPF_EXIT_INSN(),
5617 }, 6137 },
5618 .fixup_map2 = { 3 }, 6138 .fixup_map_hash_48b = { 3 },
5619 .result = ACCEPT, 6139 .result = ACCEPT,
5620 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6140 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5621 }, 6141 },
@@ -5637,7 +6157,7 @@ static struct bpf_test tests[] = {
5637 BPF_EMIT_CALL(BPF_FUNC_trace_printk), 6157 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
5638 BPF_EXIT_INSN(), 6158 BPF_EXIT_INSN(),
5639 }, 6159 },
5640 .fixup_map2 = { 3 }, 6160 .fixup_map_hash_48b = { 3 },
5641 .errstr = "R1 min value is outside of the array range", 6161 .errstr = "R1 min value is outside of the array range",
5642 .result = REJECT, 6162 .result = REJECT,
5643 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6163 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5659,7 +6179,7 @@ static struct bpf_test tests[] = {
5659 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6179 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5660 BPF_EXIT_INSN(), 6180 BPF_EXIT_INSN(),
5661 }, 6181 },
5662 .fixup_map2 = { 3 }, 6182 .fixup_map_hash_48b = { 3 },
5663 .errstr = "R1 unbounded memory access", 6183 .errstr = "R1 unbounded memory access",
5664 .result = REJECT, 6184 .result = REJECT,
5665 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6185 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5685,7 +6205,7 @@ static struct bpf_test tests[] = {
5685 BPF_EMIT_CALL(BPF_FUNC_probe_read), 6205 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5686 BPF_EXIT_INSN(), 6206 BPF_EXIT_INSN(),
5687 }, 6207 },
5688 .fixup_map2 = { 3 }, 6208 .fixup_map_hash_48b = { 3 },
5689 .errstr = "invalid access to map value, value_size=48 off=4 size=45", 6209 .errstr = "invalid access to map value, value_size=48 off=4 size=45",
5690 .result = REJECT, 6210 .result = REJECT,
5691 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6211 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5709,7 +6229,7 @@ static struct bpf_test tests[] = {
5709 BPF_MOV64_IMM(BPF_REG_0, 0), 6229 BPF_MOV64_IMM(BPF_REG_0, 0),
5710 BPF_EXIT_INSN(), 6230 BPF_EXIT_INSN(),
5711 }, 6231 },
5712 .fixup_map2 = { 3 }, 6232 .fixup_map_hash_48b = { 3 },
5713 .result = ACCEPT, 6233 .result = ACCEPT,
5714 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6234 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5715 }, 6235 },
@@ -5732,7 +6252,7 @@ static struct bpf_test tests[] = {
5732 BPF_MOV64_IMM(BPF_REG_0, 0), 6252 BPF_MOV64_IMM(BPF_REG_0, 0),
5733 BPF_EXIT_INSN(), 6253 BPF_EXIT_INSN(),
5734 }, 6254 },
5735 .fixup_map2 = { 3 }, 6255 .fixup_map_hash_48b = { 3 },
5736 .result = REJECT, 6256 .result = REJECT,
5737 .errstr = "R1 unbounded memory access", 6257 .errstr = "R1 unbounded memory access",
5738 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6258 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5756,7 +6276,7 @@ static struct bpf_test tests[] = {
5756 BPF_MOV64_IMM(BPF_REG_0, 0), 6276 BPF_MOV64_IMM(BPF_REG_0, 0),
5757 BPF_EXIT_INSN(), 6277 BPF_EXIT_INSN(),
5758 }, 6278 },
5759 .fixup_map2 = { 3 }, 6279 .fixup_map_hash_48b = { 3 },
5760 .result = ACCEPT, 6280 .result = ACCEPT,
5761 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6281 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5762 }, 6282 },
@@ -5779,7 +6299,7 @@ static struct bpf_test tests[] = {
5779 BPF_MOV64_IMM(BPF_REG_0, 0), 6299 BPF_MOV64_IMM(BPF_REG_0, 0),
5780 BPF_EXIT_INSN(), 6300 BPF_EXIT_INSN(),
5781 }, 6301 },
5782 .fixup_map2 = { 3 }, 6302 .fixup_map_hash_48b = { 3 },
5783 .result = REJECT, 6303 .result = REJECT,
5784 .errstr = "R1 unbounded memory access", 6304 .errstr = "R1 unbounded memory access",
5785 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6305 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5804,7 +6324,7 @@ static struct bpf_test tests[] = {
5804 BPF_MOV64_IMM(BPF_REG_0, 0), 6324 BPF_MOV64_IMM(BPF_REG_0, 0),
5805 BPF_EXIT_INSN(), 6325 BPF_EXIT_INSN(),
5806 }, 6326 },
5807 .fixup_map2 = { 3 }, 6327 .fixup_map_hash_48b = { 3 },
5808 .result = ACCEPT, 6328 .result = ACCEPT,
5809 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6329 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5810 }, 6330 },
@@ -5828,7 +6348,7 @@ static struct bpf_test tests[] = {
5828 BPF_MOV64_IMM(BPF_REG_0, 0), 6348 BPF_MOV64_IMM(BPF_REG_0, 0),
5829 BPF_EXIT_INSN(), 6349 BPF_EXIT_INSN(),
5830 }, 6350 },
5831 .fixup_map2 = { 3 }, 6351 .fixup_map_hash_48b = { 3 },
5832 .result = ACCEPT, 6352 .result = ACCEPT,
5833 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6353 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5834 }, 6354 },
@@ -5852,7 +6372,7 @@ static struct bpf_test tests[] = {
5852 BPF_MOV64_IMM(BPF_REG_0, 0), 6372 BPF_MOV64_IMM(BPF_REG_0, 0),
5853 BPF_EXIT_INSN(), 6373 BPF_EXIT_INSN(),
5854 }, 6374 },
5855 .fixup_map2 = { 3 }, 6375 .fixup_map_hash_48b = { 3 },
5856 .result = REJECT, 6376 .result = REJECT,
5857 .errstr = "R1 min value is negative", 6377 .errstr = "R1 min value is negative",
5858 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6378 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5877,7 +6397,7 @@ static struct bpf_test tests[] = {
5877 BPF_MOV64_IMM(BPF_REG_0, 0), 6397 BPF_MOV64_IMM(BPF_REG_0, 0),
5878 BPF_EXIT_INSN(), 6398 BPF_EXIT_INSN(),
5879 }, 6399 },
5880 .fixup_map2 = { 3 }, 6400 .fixup_map_hash_48b = { 3 },
5881 .result = ACCEPT, 6401 .result = ACCEPT,
5882 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6402 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5883 }, 6403 },
@@ -5901,7 +6421,7 @@ static struct bpf_test tests[] = {
5901 BPF_MOV64_IMM(BPF_REG_0, 0), 6421 BPF_MOV64_IMM(BPF_REG_0, 0),
5902 BPF_EXIT_INSN(), 6422 BPF_EXIT_INSN(),
5903 }, 6423 },
5904 .fixup_map2 = { 3 }, 6424 .fixup_map_hash_48b = { 3 },
5905 .result = ACCEPT, 6425 .result = ACCEPT,
5906 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6426 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5907 }, 6427 },
@@ -5925,7 +6445,7 @@ static struct bpf_test tests[] = {
5925 BPF_MOV64_IMM(BPF_REG_0, 0), 6445 BPF_MOV64_IMM(BPF_REG_0, 0),
5926 BPF_EXIT_INSN(), 6446 BPF_EXIT_INSN(),
5927 }, 6447 },
5928 .fixup_map2 = { 3 }, 6448 .fixup_map_hash_48b = { 3 },
5929 .result = REJECT, 6449 .result = REJECT,
5930 .errstr = "R1 min value is negative", 6450 .errstr = "R1 min value is negative",
5931 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6451 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -5944,7 +6464,7 @@ static struct bpf_test tests[] = {
5944 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6464 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5945 BPF_EXIT_INSN(), 6465 BPF_EXIT_INSN(),
5946 }, 6466 },
5947 .fixup_map3 = { 3, 8 }, 6467 .fixup_map_hash_16b = { 3, 8 },
5948 .result = ACCEPT, 6468 .result = ACCEPT,
5949 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6469 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5950 }, 6470 },
@@ -5964,7 +6484,7 @@ static struct bpf_test tests[] = {
5964 BPF_EMIT_CALL(BPF_FUNC_map_update_elem), 6484 BPF_EMIT_CALL(BPF_FUNC_map_update_elem),
5965 BPF_EXIT_INSN(), 6485 BPF_EXIT_INSN(),
5966 }, 6486 },
5967 .fixup_map3 = { 3, 10 }, 6487 .fixup_map_hash_16b = { 3, 10 },
5968 .result = ACCEPT, 6488 .result = ACCEPT,
5969 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6489 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5970 }, 6490 },
@@ -5984,8 +6504,8 @@ static struct bpf_test tests[] = {
5984 BPF_EMIT_CALL(BPF_FUNC_map_update_elem), 6504 BPF_EMIT_CALL(BPF_FUNC_map_update_elem),
5985 BPF_EXIT_INSN(), 6505 BPF_EXIT_INSN(),
5986 }, 6506 },
5987 .fixup_map1 = { 3 }, 6507 .fixup_map_hash_8b = { 3 },
5988 .fixup_map3 = { 10 }, 6508 .fixup_map_hash_16b = { 10 },
5989 .result = REJECT, 6509 .result = REJECT,
5990 .errstr = "invalid access to map value, value_size=8 off=0 size=16", 6510 .errstr = "invalid access to map value, value_size=8 off=0 size=16",
5991 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6511 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6006,7 +6526,7 @@ static struct bpf_test tests[] = {
6006 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6526 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6007 BPF_EXIT_INSN(), 6527 BPF_EXIT_INSN(),
6008 }, 6528 },
6009 .fixup_map3 = { 3, 9 }, 6529 .fixup_map_hash_16b = { 3, 9 },
6010 .result = ACCEPT, 6530 .result = ACCEPT,
6011 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6531 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6012 }, 6532 },
@@ -6026,7 +6546,7 @@ static struct bpf_test tests[] = {
6026 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6546 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6027 BPF_EXIT_INSN(), 6547 BPF_EXIT_INSN(),
6028 }, 6548 },
6029 .fixup_map3 = { 3, 9 }, 6549 .fixup_map_hash_16b = { 3, 9 },
6030 .result = REJECT, 6550 .result = REJECT,
6031 .errstr = "invalid access to map value, value_size=16 off=12 size=8", 6551 .errstr = "invalid access to map value, value_size=16 off=12 size=8",
6032 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6552 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6046,7 +6566,7 @@ static struct bpf_test tests[] = {
6046 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6566 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6047 BPF_EXIT_INSN(), 6567 BPF_EXIT_INSN(),
6048 }, 6568 },
6049 .fixup_map3 = { 3, 9 }, 6569 .fixup_map_hash_16b = { 3, 9 },
6050 .result = REJECT, 6570 .result = REJECT,
6051 .errstr = "invalid access to map value, value_size=16 off=-4 size=8", 6571 .errstr = "invalid access to map value, value_size=16 off=-4 size=8",
6052 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6572 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6068,7 +6588,7 @@ static struct bpf_test tests[] = {
6068 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6588 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6069 BPF_EXIT_INSN(), 6589 BPF_EXIT_INSN(),
6070 }, 6590 },
6071 .fixup_map3 = { 3, 10 }, 6591 .fixup_map_hash_16b = { 3, 10 },
6072 .result = ACCEPT, 6592 .result = ACCEPT,
6073 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6593 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6074 }, 6594 },
@@ -6089,7 +6609,7 @@ static struct bpf_test tests[] = {
6089 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6609 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6090 BPF_EXIT_INSN(), 6610 BPF_EXIT_INSN(),
6091 }, 6611 },
6092 .fixup_map3 = { 3, 10 }, 6612 .fixup_map_hash_16b = { 3, 10 },
6093 .result = REJECT, 6613 .result = REJECT,
6094 .errstr = "invalid access to map value, value_size=16 off=12 size=8", 6614 .errstr = "invalid access to map value, value_size=16 off=12 size=8",
6095 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6615 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6110,7 +6630,7 @@ static struct bpf_test tests[] = {
6110 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6630 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6111 BPF_EXIT_INSN(), 6631 BPF_EXIT_INSN(),
6112 }, 6632 },
6113 .fixup_map3 = { 3, 10 }, 6633 .fixup_map_hash_16b = { 3, 10 },
6114 .result = REJECT, 6634 .result = REJECT,
6115 .errstr = "invalid access to map value, value_size=16 off=-4 size=8", 6635 .errstr = "invalid access to map value, value_size=16 off=-4 size=8",
6116 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6636 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6133,7 +6653,7 @@ static struct bpf_test tests[] = {
6133 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6653 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6134 BPF_EXIT_INSN(), 6654 BPF_EXIT_INSN(),
6135 }, 6655 },
6136 .fixup_map3 = { 3, 11 }, 6656 .fixup_map_hash_16b = { 3, 11 },
6137 .result = ACCEPT, 6657 .result = ACCEPT,
6138 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6658 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6139 }, 6659 },
@@ -6153,7 +6673,7 @@ static struct bpf_test tests[] = {
6153 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6673 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6154 BPF_EXIT_INSN(), 6674 BPF_EXIT_INSN(),
6155 }, 6675 },
6156 .fixup_map3 = { 3, 10 }, 6676 .fixup_map_hash_16b = { 3, 10 },
6157 .result = REJECT, 6677 .result = REJECT,
6158 .errstr = "R2 unbounded memory access, make sure to bounds check any array access into a map", 6678 .errstr = "R2 unbounded memory access, make sure to bounds check any array access into a map",
6159 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6679 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6176,7 +6696,7 @@ static struct bpf_test tests[] = {
6176 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 6696 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
6177 BPF_EXIT_INSN(), 6697 BPF_EXIT_INSN(),
6178 }, 6698 },
6179 .fixup_map3 = { 3, 11 }, 6699 .fixup_map_hash_16b = { 3, 11 },
6180 .result = REJECT, 6700 .result = REJECT,
6181 .errstr = "invalid access to map value, value_size=16 off=9 size=8", 6701 .errstr = "invalid access to map value, value_size=16 off=9 size=8",
6182 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6702 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6198,7 +6718,7 @@ static struct bpf_test tests[] = {
6198 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42), 6718 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42),
6199 BPF_EXIT_INSN(), 6719 BPF_EXIT_INSN(),
6200 }, 6720 },
6201 .fixup_map2 = { 3 }, 6721 .fixup_map_hash_48b = { 3 },
6202 .errstr_unpriv = "R0 leaks addr", 6722 .errstr_unpriv = "R0 leaks addr",
6203 .result = ACCEPT, 6723 .result = ACCEPT,
6204 .result_unpriv = REJECT, 6724 .result_unpriv = REJECT,
@@ -6219,7 +6739,7 @@ static struct bpf_test tests[] = {
6219 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42), 6739 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42),
6220 BPF_EXIT_INSN(), 6740 BPF_EXIT_INSN(),
6221 }, 6741 },
6222 .fixup_map2 = { 3 }, 6742 .fixup_map_hash_48b = { 3 },
6223 .errstr_unpriv = "R0 leaks addr", 6743 .errstr_unpriv = "R0 leaks addr",
6224 .result = ACCEPT, 6744 .result = ACCEPT,
6225 .result_unpriv = REJECT, 6745 .result_unpriv = REJECT,
@@ -6236,7 +6756,7 @@ static struct bpf_test tests[] = {
6236 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), 6756 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0),
6237 BPF_EXIT_INSN(), 6757 BPF_EXIT_INSN(),
6238 }, 6758 },
6239 .fixup_map2 = { 3 }, 6759 .fixup_map_hash_48b = { 3 },
6240 .errstr_unpriv = "R1 !read_ok", 6760 .errstr_unpriv = "R1 !read_ok",
6241 .errstr = "R1 !read_ok", 6761 .errstr = "R1 !read_ok",
6242 .result = REJECT, 6762 .result = REJECT,
@@ -6270,7 +6790,7 @@ static struct bpf_test tests[] = {
6270 BPF_ST_MEM(BPF_DW, BPF_REG_7, -4, 24), 6790 BPF_ST_MEM(BPF_DW, BPF_REG_7, -4, 24),
6271 BPF_EXIT_INSN(), 6791 BPF_EXIT_INSN(),
6272 }, 6792 },
6273 .fixup_map2 = { 3 }, 6793 .fixup_map_hash_48b = { 3 },
6274 .errstr_unpriv = "R0 leaks addr", 6794 .errstr_unpriv = "R0 leaks addr",
6275 .result = ACCEPT, 6795 .result = ACCEPT,
6276 .result_unpriv = REJECT, 6796 .result_unpriv = REJECT,
@@ -6298,7 +6818,7 @@ static struct bpf_test tests[] = {
6298 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 4), 6818 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 4),
6299 BPF_EXIT_INSN(), 6819 BPF_EXIT_INSN(),
6300 }, 6820 },
6301 .fixup_map2 = { 3 }, 6821 .fixup_map_hash_48b = { 3 },
6302 .errstr_unpriv = "R0 leaks addr", 6822 .errstr_unpriv = "R0 leaks addr",
6303 .result = ACCEPT, 6823 .result = ACCEPT,
6304 .result_unpriv = REJECT, 6824 .result_unpriv = REJECT,
@@ -6317,7 +6837,7 @@ static struct bpf_test tests[] = {
6317 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22), 6837 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
6318 BPF_EXIT_INSN(), 6838 BPF_EXIT_INSN(),
6319 }, 6839 },
6320 .fixup_map2 = { 3 }, 6840 .fixup_map_hash_48b = { 3 },
6321 .errstr = "R0 bitwise operator &= on pointer", 6841 .errstr = "R0 bitwise operator &= on pointer",
6322 .result = REJECT, 6842 .result = REJECT,
6323 }, 6843 },
@@ -6334,7 +6854,7 @@ static struct bpf_test tests[] = {
6334 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22), 6854 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
6335 BPF_EXIT_INSN(), 6855 BPF_EXIT_INSN(),
6336 }, 6856 },
6337 .fixup_map2 = { 3 }, 6857 .fixup_map_hash_48b = { 3 },
6338 .errstr = "R0 32-bit pointer arithmetic prohibited", 6858 .errstr = "R0 32-bit pointer arithmetic prohibited",
6339 .result = REJECT, 6859 .result = REJECT,
6340 }, 6860 },
@@ -6351,7 +6871,7 @@ static struct bpf_test tests[] = {
6351 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22), 6871 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
6352 BPF_EXIT_INSN(), 6872 BPF_EXIT_INSN(),
6353 }, 6873 },
6354 .fixup_map2 = { 3 }, 6874 .fixup_map_hash_48b = { 3 },
6355 .errstr = "R0 pointer arithmetic with /= operator", 6875 .errstr = "R0 pointer arithmetic with /= operator",
6356 .result = REJECT, 6876 .result = REJECT,
6357 }, 6877 },
@@ -6368,7 +6888,7 @@ static struct bpf_test tests[] = {
6368 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22), 6888 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
6369 BPF_EXIT_INSN(), 6889 BPF_EXIT_INSN(),
6370 }, 6890 },
6371 .fixup_map2 = { 3 }, 6891 .fixup_map_hash_48b = { 3 },
6372 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6892 .errstr_unpriv = "R0 pointer arithmetic prohibited",
6373 .errstr = "invalid mem access 'inv'", 6893 .errstr = "invalid mem access 'inv'",
6374 .result = REJECT, 6894 .result = REJECT,
@@ -6392,7 +6912,7 @@ static struct bpf_test tests[] = {
6392 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22), 6912 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
6393 BPF_EXIT_INSN(), 6913 BPF_EXIT_INSN(),
6394 }, 6914 },
6395 .fixup_map2 = { 3 }, 6915 .fixup_map_hash_48b = { 3 },
6396 .errstr = "R0 invalid mem access 'inv'", 6916 .errstr = "R0 invalid mem access 'inv'",
6397 .result = REJECT, 6917 .result = REJECT,
6398 }, 6918 },
@@ -6415,7 +6935,7 @@ static struct bpf_test tests[] = {
6415 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42), 6935 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42),
6416 BPF_EXIT_INSN(), 6936 BPF_EXIT_INSN(),
6417 }, 6937 },
6418 .fixup_map2 = { 3 }, 6938 .fixup_map_hash_48b = { 3 },
6419 .errstr_unpriv = "R0 leaks addr", 6939 .errstr_unpriv = "R0 leaks addr",
6420 .result = ACCEPT, 6940 .result = ACCEPT,
6421 .result_unpriv = REJECT, 6941 .result_unpriv = REJECT,
@@ -6661,7 +7181,7 @@ static struct bpf_test tests[] = {
6661 BPF_MOV64_IMM(BPF_REG_0, 0), 7181 BPF_MOV64_IMM(BPF_REG_0, 0),
6662 BPF_EXIT_INSN(), 7182 BPF_EXIT_INSN(),
6663 }, 7183 },
6664 .fixup_map2 = { 3 }, 7184 .fixup_map_hash_48b = { 3 },
6665 .result = ACCEPT, 7185 .result = ACCEPT,
6666 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7186 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6667 }, 7187 },
@@ -6687,7 +7207,7 @@ static struct bpf_test tests[] = {
6687 BPF_MOV64_IMM(BPF_REG_0, 0), 7207 BPF_MOV64_IMM(BPF_REG_0, 0),
6688 BPF_EXIT_INSN(), 7208 BPF_EXIT_INSN(),
6689 }, 7209 },
6690 .fixup_map2 = { 3 }, 7210 .fixup_map_hash_48b = { 3 },
6691 .errstr = "invalid access to map value, value_size=48 off=0 size=49", 7211 .errstr = "invalid access to map value, value_size=48 off=0 size=49",
6692 .result = REJECT, 7212 .result = REJECT,
6693 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7213 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6715,7 +7235,7 @@ static struct bpf_test tests[] = {
6715 BPF_MOV64_IMM(BPF_REG_0, 0), 7235 BPF_MOV64_IMM(BPF_REG_0, 0),
6716 BPF_EXIT_INSN(), 7236 BPF_EXIT_INSN(),
6717 }, 7237 },
6718 .fixup_map2 = { 3 }, 7238 .fixup_map_hash_48b = { 3 },
6719 .result = ACCEPT, 7239 .result = ACCEPT,
6720 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7240 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6721 }, 7241 },
@@ -6742,7 +7262,7 @@ static struct bpf_test tests[] = {
6742 BPF_MOV64_IMM(BPF_REG_0, 0), 7262 BPF_MOV64_IMM(BPF_REG_0, 0),
6743 BPF_EXIT_INSN(), 7263 BPF_EXIT_INSN(),
6744 }, 7264 },
6745 .fixup_map2 = { 3 }, 7265 .fixup_map_hash_48b = { 3 },
6746 .errstr = "R1 min value is outside of the array range", 7266 .errstr = "R1 min value is outside of the array range",
6747 .result = REJECT, 7267 .result = REJECT,
6748 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7268 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -6814,7 +7334,7 @@ static struct bpf_test tests[] = {
6814 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 7334 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
6815 BPF_EXIT_INSN(), 7335 BPF_EXIT_INSN(),
6816 }, 7336 },
6817 .fixup_map1 = { 3 }, 7337 .fixup_map_hash_8b = { 3 },
6818 .result = ACCEPT, 7338 .result = ACCEPT,
6819 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 7339 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
6820 }, 7340 },
@@ -6839,7 +7359,7 @@ static struct bpf_test tests[] = {
6839 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 7359 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
6840 BPF_EXIT_INSN(), 7360 BPF_EXIT_INSN(),
6841 }, 7361 },
6842 .fixup_map1 = { 3 }, 7362 .fixup_map_hash_8b = { 3 },
6843 .result = ACCEPT, 7363 .result = ACCEPT,
6844 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 7364 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
6845 }, 7365 },
@@ -6862,7 +7382,7 @@ static struct bpf_test tests[] = {
6862 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 7382 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
6863 BPF_EXIT_INSN(), 7383 BPF_EXIT_INSN(),
6864 }, 7384 },
6865 .fixup_map1 = { 3 }, 7385 .fixup_map_hash_8b = { 3 },
6866 .result = ACCEPT, 7386 .result = ACCEPT,
6867 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 7387 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
6868 }, 7388 },
@@ -6943,7 +7463,7 @@ static struct bpf_test tests[] = {
6943 BPF_EMIT_CALL(BPF_FUNC_probe_read), 7463 BPF_EMIT_CALL(BPF_FUNC_probe_read),
6944 BPF_EXIT_INSN(), 7464 BPF_EXIT_INSN(),
6945 }, 7465 },
6946 .fixup_map1 = { 3 }, 7466 .fixup_map_hash_8b = { 3 },
6947 .result = ACCEPT, 7467 .result = ACCEPT,
6948 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7468 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6949 }, 7469 },
@@ -6964,7 +7484,7 @@ static struct bpf_test tests[] = {
6964 BPF_EMIT_CALL(BPF_FUNC_probe_read), 7484 BPF_EMIT_CALL(BPF_FUNC_probe_read),
6965 BPF_EXIT_INSN(), 7485 BPF_EXIT_INSN(),
6966 }, 7486 },
6967 .fixup_map1 = { 3 }, 7487 .fixup_map_hash_8b = { 3 },
6968 .result = ACCEPT, 7488 .result = ACCEPT,
6969 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7489 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6970 }, 7490 },
@@ -6984,7 +7504,7 @@ static struct bpf_test tests[] = {
6984 BPF_EMIT_CALL(BPF_FUNC_probe_read), 7504 BPF_EMIT_CALL(BPF_FUNC_probe_read),
6985 BPF_EXIT_INSN(), 7505 BPF_EXIT_INSN(),
6986 }, 7506 },
6987 .fixup_map1 = { 3 }, 7507 .fixup_map_hash_8b = { 3 },
6988 .result = ACCEPT, 7508 .result = ACCEPT,
6989 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 7509 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6990 }, 7510 },
@@ -7059,7 +7579,7 @@ static struct bpf_test tests[] = {
7059 offsetof(struct test_val, foo)), 7579 offsetof(struct test_val, foo)),
7060 BPF_EXIT_INSN(), 7580 BPF_EXIT_INSN(),
7061 }, 7581 },
7062 .fixup_map2 = { 3 }, 7582 .fixup_map_hash_48b = { 3 },
7063 .errstr = "R0 max value is outside of the array range", 7583 .errstr = "R0 max value is outside of the array range",
7064 .result = REJECT, 7584 .result = REJECT,
7065 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 7585 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -7089,7 +7609,7 @@ static struct bpf_test tests[] = {
7089 BPF_MOV64_REG(BPF_REG_0, 0), 7609 BPF_MOV64_REG(BPF_REG_0, 0),
7090 BPF_EXIT_INSN(), 7610 BPF_EXIT_INSN(),
7091 }, 7611 },
7092 .fixup_map2 = { 3 }, 7612 .fixup_map_hash_48b = { 3 },
7093 .errstr = "R0 max value is outside of the array range", 7613 .errstr = "R0 max value is outside of the array range",
7094 .result = REJECT, 7614 .result = REJECT,
7095 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 7615 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -7137,7 +7657,7 @@ static struct bpf_test tests[] = {
7137 BPF_EXIT_INSN(), 7657 BPF_EXIT_INSN(),
7138 }, 7658 },
7139 .fixup_map_in_map = { 3 }, 7659 .fixup_map_in_map = { 3 },
7140 .errstr = "R1 pointer arithmetic on CONST_PTR_TO_MAP prohibited", 7660 .errstr = "R1 pointer arithmetic on map_ptr prohibited",
7141 .result = REJECT, 7661 .result = REJECT,
7142 }, 7662 },
7143 { 7663 {
@@ -7442,7 +7962,7 @@ static struct bpf_test tests[] = {
7442 BPF_MOV64_IMM(BPF_REG_0, 0), 7962 BPF_MOV64_IMM(BPF_REG_0, 0),
7443 BPF_EXIT_INSN(), 7963 BPF_EXIT_INSN(),
7444 }, 7964 },
7445 .fixup_map1 = { 3 }, 7965 .fixup_map_hash_8b = { 3 },
7446 .errstr = "unbounded min value", 7966 .errstr = "unbounded min value",
7447 .result = REJECT, 7967 .result = REJECT,
7448 }, 7968 },
@@ -7466,7 +7986,7 @@ static struct bpf_test tests[] = {
7466 BPF_MOV64_IMM(BPF_REG_0, 0), 7986 BPF_MOV64_IMM(BPF_REG_0, 0),
7467 BPF_EXIT_INSN(), 7987 BPF_EXIT_INSN(),
7468 }, 7988 },
7469 .fixup_map1 = { 3 }, 7989 .fixup_map_hash_8b = { 3 },
7470 .errstr = "unbounded min value", 7990 .errstr = "unbounded min value",
7471 .result = REJECT, 7991 .result = REJECT,
7472 }, 7992 },
@@ -7492,7 +8012,7 @@ static struct bpf_test tests[] = {
7492 BPF_MOV64_IMM(BPF_REG_0, 0), 8012 BPF_MOV64_IMM(BPF_REG_0, 0),
7493 BPF_EXIT_INSN(), 8013 BPF_EXIT_INSN(),
7494 }, 8014 },
7495 .fixup_map1 = { 3 }, 8015 .fixup_map_hash_8b = { 3 },
7496 .errstr = "unbounded min value", 8016 .errstr = "unbounded min value",
7497 .result = REJECT, 8017 .result = REJECT,
7498 }, 8018 },
@@ -7517,7 +8037,7 @@ static struct bpf_test tests[] = {
7517 BPF_MOV64_IMM(BPF_REG_0, 0), 8037 BPF_MOV64_IMM(BPF_REG_0, 0),
7518 BPF_EXIT_INSN(), 8038 BPF_EXIT_INSN(),
7519 }, 8039 },
7520 .fixup_map1 = { 3 }, 8040 .fixup_map_hash_8b = { 3 },
7521 .errstr = "unbounded min value", 8041 .errstr = "unbounded min value",
7522 .result = REJECT, 8042 .result = REJECT,
7523 }, 8043 },
@@ -7541,7 +8061,7 @@ static struct bpf_test tests[] = {
7541 BPF_MOV64_IMM(BPF_REG_0, 0), 8061 BPF_MOV64_IMM(BPF_REG_0, 0),
7542 BPF_EXIT_INSN(), 8062 BPF_EXIT_INSN(),
7543 }, 8063 },
7544 .fixup_map1 = { 3 }, 8064 .fixup_map_hash_8b = { 3 },
7545 .result = ACCEPT, 8065 .result = ACCEPT,
7546 }, 8066 },
7547 { 8067 {
@@ -7565,7 +8085,7 @@ static struct bpf_test tests[] = {
7565 BPF_MOV64_IMM(BPF_REG_0, 0), 8085 BPF_MOV64_IMM(BPF_REG_0, 0),
7566 BPF_EXIT_INSN(), 8086 BPF_EXIT_INSN(),
7567 }, 8087 },
7568 .fixup_map1 = { 3 }, 8088 .fixup_map_hash_8b = { 3 },
7569 .errstr = "unbounded min value", 8089 .errstr = "unbounded min value",
7570 .result = REJECT, 8090 .result = REJECT,
7571 }, 8091 },
@@ -7611,7 +8131,7 @@ static struct bpf_test tests[] = {
7611 BPF_MOV64_IMM(BPF_REG_0, 0), 8131 BPF_MOV64_IMM(BPF_REG_0, 0),
7612 BPF_EXIT_INSN(), 8132 BPF_EXIT_INSN(),
7613 }, 8133 },
7614 .fixup_map1 = { 3 }, 8134 .fixup_map_hash_8b = { 3 },
7615 .result = ACCEPT, 8135 .result = ACCEPT,
7616 }, 8136 },
7617 { 8137 {
@@ -7636,7 +8156,7 @@ static struct bpf_test tests[] = {
7636 BPF_MOV64_IMM(BPF_REG_0, 0), 8156 BPF_MOV64_IMM(BPF_REG_0, 0),
7637 BPF_EXIT_INSN(), 8157 BPF_EXIT_INSN(),
7638 }, 8158 },
7639 .fixup_map1 = { 3 }, 8159 .fixup_map_hash_8b = { 3 },
7640 .errstr = "unbounded min value", 8160 .errstr = "unbounded min value",
7641 .result = REJECT, 8161 .result = REJECT,
7642 }, 8162 },
@@ -7662,7 +8182,7 @@ static struct bpf_test tests[] = {
7662 BPF_MOV64_IMM(BPF_REG_0, 0), 8182 BPF_MOV64_IMM(BPF_REG_0, 0),
7663 BPF_EXIT_INSN(), 8183 BPF_EXIT_INSN(),
7664 }, 8184 },
7665 .fixup_map1 = { 3 }, 8185 .fixup_map_hash_8b = { 3 },
7666 .result = ACCEPT, 8186 .result = ACCEPT,
7667 }, 8187 },
7668 { 8188 {
@@ -7687,7 +8207,7 @@ static struct bpf_test tests[] = {
7687 BPF_MOV64_IMM(BPF_REG_0, 0), 8207 BPF_MOV64_IMM(BPF_REG_0, 0),
7688 BPF_EXIT_INSN(), 8208 BPF_EXIT_INSN(),
7689 }, 8209 },
7690 .fixup_map1 = { 3 }, 8210 .fixup_map_hash_8b = { 3 },
7691 .errstr = "unbounded min value", 8211 .errstr = "unbounded min value",
7692 .result = REJECT, 8212 .result = REJECT,
7693 }, 8213 },
@@ -7714,7 +8234,7 @@ static struct bpf_test tests[] = {
7714 BPF_MOV64_IMM(BPF_REG_0, 0), 8234 BPF_MOV64_IMM(BPF_REG_0, 0),
7715 BPF_EXIT_INSN(), 8235 BPF_EXIT_INSN(),
7716 }, 8236 },
7717 .fixup_map1 = { 3 }, 8237 .fixup_map_hash_8b = { 3 },
7718 .errstr = "unbounded min value", 8238 .errstr = "unbounded min value",
7719 .result = REJECT, 8239 .result = REJECT,
7720 }, 8240 },
@@ -7740,7 +8260,7 @@ static struct bpf_test tests[] = {
7740 BPF_MOV64_IMM(BPF_REG_0, 0), 8260 BPF_MOV64_IMM(BPF_REG_0, 0),
7741 BPF_EXIT_INSN(), 8261 BPF_EXIT_INSN(),
7742 }, 8262 },
7743 .fixup_map1 = { 3 }, 8263 .fixup_map_hash_8b = { 3 },
7744 .errstr = "unbounded min value", 8264 .errstr = "unbounded min value",
7745 .result = REJECT, 8265 .result = REJECT,
7746 }, 8266 },
@@ -7769,7 +8289,7 @@ static struct bpf_test tests[] = {
7769 BPF_MOV64_IMM(BPF_REG_0, 0), 8289 BPF_MOV64_IMM(BPF_REG_0, 0),
7770 BPF_EXIT_INSN(), 8290 BPF_EXIT_INSN(),
7771 }, 8291 },
7772 .fixup_map1 = { 3 }, 8292 .fixup_map_hash_8b = { 3 },
7773 .errstr = "unbounded min value", 8293 .errstr = "unbounded min value",
7774 .result = REJECT, 8294 .result = REJECT,
7775 }, 8295 },
@@ -7799,7 +8319,7 @@ static struct bpf_test tests[] = {
7799 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, -3), 8319 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, -3),
7800 BPF_JMP_IMM(BPF_JA, 0, 0, -7), 8320 BPF_JMP_IMM(BPF_JA, 0, 0, -7),
7801 }, 8321 },
7802 .fixup_map1 = { 4 }, 8322 .fixup_map_hash_8b = { 4 },
7803 .errstr = "R0 invalid mem access 'inv'", 8323 .errstr = "R0 invalid mem access 'inv'",
7804 .result = REJECT, 8324 .result = REJECT,
7805 }, 8325 },
@@ -7827,7 +8347,7 @@ static struct bpf_test tests[] = {
7827 BPF_MOV64_IMM(BPF_REG_0, 0), 8347 BPF_MOV64_IMM(BPF_REG_0, 0),
7828 BPF_EXIT_INSN(), 8348 BPF_EXIT_INSN(),
7829 }, 8349 },
7830 .fixup_map1 = { 3 }, 8350 .fixup_map_hash_8b = { 3 },
7831 .errstr = "unbounded min value", 8351 .errstr = "unbounded min value",
7832 .result = REJECT, 8352 .result = REJECT,
7833 .result_unpriv = REJECT, 8353 .result_unpriv = REJECT,
@@ -7854,7 +8374,7 @@ static struct bpf_test tests[] = {
7854 BPF_MOV64_IMM(BPF_REG_0, 0), 8374 BPF_MOV64_IMM(BPF_REG_0, 0),
7855 BPF_EXIT_INSN(), 8375 BPF_EXIT_INSN(),
7856 }, 8376 },
7857 .fixup_map1 = { 3 }, 8377 .fixup_map_hash_8b = { 3 },
7858 .errstr = "R0 max value is outside of the array range", 8378 .errstr = "R0 max value is outside of the array range",
7859 .result = REJECT, 8379 .result = REJECT,
7860 }, 8380 },
@@ -7879,7 +8399,7 @@ static struct bpf_test tests[] = {
7879 BPF_MOV64_IMM(BPF_REG_0, 0), 8399 BPF_MOV64_IMM(BPF_REG_0, 0),
7880 BPF_EXIT_INSN(), 8400 BPF_EXIT_INSN(),
7881 }, 8401 },
7882 .fixup_map1 = { 3 }, 8402 .fixup_map_hash_8b = { 3 },
7883 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 8403 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
7884 .result = REJECT, 8404 .result = REJECT,
7885 }, 8405 },
@@ -7905,7 +8425,7 @@ static struct bpf_test tests[] = {
7905 BPF_MOV64_IMM(BPF_REG_0, 0), 8425 BPF_MOV64_IMM(BPF_REG_0, 0),
7906 BPF_EXIT_INSN(), 8426 BPF_EXIT_INSN(),
7907 }, 8427 },
7908 .fixup_map1 = { 3 }, 8428 .fixup_map_hash_8b = { 3 },
7909 .result = ACCEPT 8429 .result = ACCEPT
7910 }, 8430 },
7911 { 8431 {
@@ -7930,7 +8450,7 @@ static struct bpf_test tests[] = {
7930 BPF_MOV64_IMM(BPF_REG_0, 0), 8450 BPF_MOV64_IMM(BPF_REG_0, 0),
7931 BPF_EXIT_INSN(), 8451 BPF_EXIT_INSN(),
7932 }, 8452 },
7933 .fixup_map1 = { 3 }, 8453 .fixup_map_hash_8b = { 3 },
7934 .errstr = "map_value pointer and 4294967295", 8454 .errstr = "map_value pointer and 4294967295",
7935 .result = REJECT 8455 .result = REJECT
7936 }, 8456 },
@@ -7956,7 +8476,7 @@ static struct bpf_test tests[] = {
7956 BPF_MOV64_IMM(BPF_REG_0, 0), 8476 BPF_MOV64_IMM(BPF_REG_0, 0),
7957 BPF_EXIT_INSN(), 8477 BPF_EXIT_INSN(),
7958 }, 8478 },
7959 .fixup_map1 = { 3 }, 8479 .fixup_map_hash_8b = { 3 },
7960 .errstr = "R0 min value is outside of the array range", 8480 .errstr = "R0 min value is outside of the array range",
7961 .result = REJECT 8481 .result = REJECT
7962 }, 8482 },
@@ -7980,7 +8500,7 @@ static struct bpf_test tests[] = {
7980 BPF_MOV64_IMM(BPF_REG_0, 0), 8500 BPF_MOV64_IMM(BPF_REG_0, 0),
7981 BPF_EXIT_INSN(), 8501 BPF_EXIT_INSN(),
7982 }, 8502 },
7983 .fixup_map1 = { 4 }, 8503 .fixup_map_hash_8b = { 4 },
7984 .errstr = "value_size=8 off=1073741825", 8504 .errstr = "value_size=8 off=1073741825",
7985 .result = REJECT, 8505 .result = REJECT,
7986 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8506 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -8005,7 +8525,7 @@ static struct bpf_test tests[] = {
8005 BPF_MOV64_IMM(BPF_REG_0, 0), 8525 BPF_MOV64_IMM(BPF_REG_0, 0),
8006 BPF_EXIT_INSN(), 8526 BPF_EXIT_INSN(),
8007 }, 8527 },
8008 .fixup_map1 = { 4 }, 8528 .fixup_map_hash_8b = { 4 },
8009 .errstr = "value 1073741823", 8529 .errstr = "value 1073741823",
8010 .result = REJECT, 8530 .result = REJECT,
8011 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8531 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -8041,7 +8561,7 @@ static struct bpf_test tests[] = {
8041 BPF_MOV64_IMM(BPF_REG_0, 0), 8561 BPF_MOV64_IMM(BPF_REG_0, 0),
8042 BPF_EXIT_INSN(), 8562 BPF_EXIT_INSN(),
8043 }, 8563 },
8044 .fixup_map1 = { 3 }, 8564 .fixup_map_hash_8b = { 3 },
8045 .result = ACCEPT 8565 .result = ACCEPT
8046 }, 8566 },
8047 { 8567 {
@@ -8080,7 +8600,7 @@ static struct bpf_test tests[] = {
8080 BPF_MOV64_IMM(BPF_REG_0, 0), 8600 BPF_MOV64_IMM(BPF_REG_0, 0),
8081 BPF_EXIT_INSN(), 8601 BPF_EXIT_INSN(),
8082 }, 8602 },
8083 .fixup_map1 = { 3 }, 8603 .fixup_map_hash_8b = { 3 },
8084 /* not actually fully unbounded, but the bound is very high */ 8604 /* not actually fully unbounded, but the bound is very high */
8085 .errstr = "R0 unbounded memory access", 8605 .errstr = "R0 unbounded memory access",
8086 .result = REJECT 8606 .result = REJECT
@@ -8123,7 +8643,7 @@ static struct bpf_test tests[] = {
8123 BPF_MOV64_IMM(BPF_REG_0, 0), 8643 BPF_MOV64_IMM(BPF_REG_0, 0),
8124 BPF_EXIT_INSN(), 8644 BPF_EXIT_INSN(),
8125 }, 8645 },
8126 .fixup_map1 = { 3 }, 8646 .fixup_map_hash_8b = { 3 },
8127 /* not actually fully unbounded, but the bound is very high */ 8647 /* not actually fully unbounded, but the bound is very high */
8128 .errstr = "R0 unbounded memory access", 8648 .errstr = "R0 unbounded memory access",
8129 .result = REJECT 8649 .result = REJECT
@@ -8152,7 +8672,7 @@ static struct bpf_test tests[] = {
8152 BPF_MOV64_IMM(BPF_REG_0, 0), 8672 BPF_MOV64_IMM(BPF_REG_0, 0),
8153 BPF_EXIT_INSN(), 8673 BPF_EXIT_INSN(),
8154 }, 8674 },
8155 .fixup_map1 = { 3 }, 8675 .fixup_map_hash_8b = { 3 },
8156 .result = ACCEPT 8676 .result = ACCEPT
8157 }, 8677 },
8158 { 8678 {
@@ -8179,7 +8699,7 @@ static struct bpf_test tests[] = {
8179 BPF_MOV64_IMM(BPF_REG_0, 0), 8699 BPF_MOV64_IMM(BPF_REG_0, 0),
8180 BPF_EXIT_INSN(), 8700 BPF_EXIT_INSN(),
8181 }, 8701 },
8182 .fixup_map1 = { 3 }, 8702 .fixup_map_hash_8b = { 3 },
8183 .errstr = "R0 max value is outside of the array range", 8703 .errstr = "R0 max value is outside of the array range",
8184 .result = REJECT 8704 .result = REJECT
8185 }, 8705 },
@@ -8209,7 +8729,7 @@ static struct bpf_test tests[] = {
8209 BPF_MOV64_IMM(BPF_REG_0, 0), 8729 BPF_MOV64_IMM(BPF_REG_0, 0),
8210 BPF_EXIT_INSN(), 8730 BPF_EXIT_INSN(),
8211 }, 8731 },
8212 .fixup_map1 = { 3 }, 8732 .fixup_map_hash_8b = { 3 },
8213 .errstr = "R0 unbounded memory access", 8733 .errstr = "R0 unbounded memory access",
8214 .result = REJECT 8734 .result = REJECT
8215 }, 8735 },
@@ -8229,7 +8749,7 @@ static struct bpf_test tests[] = {
8229 BPF_JMP_A(0), 8749 BPF_JMP_A(0),
8230 BPF_EXIT_INSN(), 8750 BPF_EXIT_INSN(),
8231 }, 8751 },
8232 .fixup_map1 = { 3 }, 8752 .fixup_map_hash_8b = { 3 },
8233 .errstr = "map_value pointer and 2147483646", 8753 .errstr = "map_value pointer and 2147483646",
8234 .result = REJECT 8754 .result = REJECT
8235 }, 8755 },
@@ -8251,7 +8771,7 @@ static struct bpf_test tests[] = {
8251 BPF_JMP_A(0), 8771 BPF_JMP_A(0),
8252 BPF_EXIT_INSN(), 8772 BPF_EXIT_INSN(),
8253 }, 8773 },
8254 .fixup_map1 = { 3 }, 8774 .fixup_map_hash_8b = { 3 },
8255 .errstr = "pointer offset 1073741822", 8775 .errstr = "pointer offset 1073741822",
8256 .result = REJECT 8776 .result = REJECT
8257 }, 8777 },
@@ -8272,7 +8792,7 @@ static struct bpf_test tests[] = {
8272 BPF_JMP_A(0), 8792 BPF_JMP_A(0),
8273 BPF_EXIT_INSN(), 8793 BPF_EXIT_INSN(),
8274 }, 8794 },
8275 .fixup_map1 = { 3 }, 8795 .fixup_map_hash_8b = { 3 },
8276 .errstr = "pointer offset -1073741822", 8796 .errstr = "pointer offset -1073741822",
8277 .result = REJECT 8797 .result = REJECT
8278 }, 8798 },
@@ -8294,7 +8814,7 @@ static struct bpf_test tests[] = {
8294 BPF_JMP_A(0), 8814 BPF_JMP_A(0),
8295 BPF_EXIT_INSN(), 8815 BPF_EXIT_INSN(),
8296 }, 8816 },
8297 .fixup_map1 = { 3 }, 8817 .fixup_map_hash_8b = { 3 },
8298 .errstr = "map_value pointer and 1000000000000", 8818 .errstr = "map_value pointer and 1000000000000",
8299 .result = REJECT 8819 .result = REJECT
8300 }, 8820 },
@@ -8314,7 +8834,7 @@ static struct bpf_test tests[] = {
8314 BPF_JMP_A(0), 8834 BPF_JMP_A(0),
8315 BPF_EXIT_INSN(), 8835 BPF_EXIT_INSN(),
8316 }, 8836 },
8317 .fixup_map1 = { 3 }, 8837 .fixup_map_hash_8b = { 3 },
8318 .result = ACCEPT, 8838 .result = ACCEPT,
8319 .retval = POINTER_VALUE, 8839 .retval = POINTER_VALUE,
8320 .result_unpriv = REJECT, 8840 .result_unpriv = REJECT,
@@ -8335,7 +8855,7 @@ static struct bpf_test tests[] = {
8335 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 8855 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
8336 BPF_EXIT_INSN(), 8856 BPF_EXIT_INSN(),
8337 }, 8857 },
8338 .fixup_map1 = { 3 }, 8858 .fixup_map_hash_8b = { 3 },
8339 .result = ACCEPT, 8859 .result = ACCEPT,
8340 .retval = POINTER_VALUE, 8860 .retval = POINTER_VALUE,
8341 .result_unpriv = REJECT, 8861 .result_unpriv = REJECT,
@@ -8403,7 +8923,7 @@ static struct bpf_test tests[] = {
8403 BPF_MOV64_IMM(BPF_REG_0, 0), 8923 BPF_MOV64_IMM(BPF_REG_0, 0),
8404 BPF_EXIT_INSN(), 8924 BPF_EXIT_INSN(),
8405 }, 8925 },
8406 .fixup_map1 = { 5 }, 8926 .fixup_map_hash_8b = { 5 },
8407 .errstr = "variable stack read R2", 8927 .errstr = "variable stack read R2",
8408 .result = REJECT, 8928 .result = REJECT,
8409 .prog_type = BPF_PROG_TYPE_LWT_IN, 8929 .prog_type = BPF_PROG_TYPE_LWT_IN,
@@ -8484,7 +9004,7 @@ static struct bpf_test tests[] = {
8484 offsetof(struct test_val, foo)), 9004 offsetof(struct test_val, foo)),
8485 BPF_EXIT_INSN(), 9005 BPF_EXIT_INSN(),
8486 }, 9006 },
8487 .fixup_map2 = { 3 }, 9007 .fixup_map_hash_48b = { 3 },
8488 .errstr_unpriv = "R0 leaks addr", 9008 .errstr_unpriv = "R0 leaks addr",
8489 .errstr = "R0 unbounded memory access", 9009 .errstr = "R0 unbounded memory access",
8490 .result_unpriv = REJECT, 9010 .result_unpriv = REJECT,
@@ -8811,7 +9331,7 @@ static struct bpf_test tests[] = {
8811 BPF_MOV64_IMM(BPF_REG_0, 0), 9331 BPF_MOV64_IMM(BPF_REG_0, 0),
8812 BPF_EXIT_INSN(), 9332 BPF_EXIT_INSN(),
8813 }, 9333 },
8814 .errstr = "R3 pointer arithmetic on PTR_TO_PACKET_END", 9334 .errstr = "R3 pointer arithmetic on pkt_end",
8815 .result = REJECT, 9335 .result = REJECT,
8816 .prog_type = BPF_PROG_TYPE_XDP, 9336 .prog_type = BPF_PROG_TYPE_XDP,
8817 }, 9337 },
@@ -8830,7 +9350,7 @@ static struct bpf_test tests[] = {
8830 BPF_MOV64_IMM(BPF_REG_0, 0), 9350 BPF_MOV64_IMM(BPF_REG_0, 0),
8831 BPF_EXIT_INSN(), 9351 BPF_EXIT_INSN(),
8832 }, 9352 },
8833 .errstr = "R3 pointer arithmetic on PTR_TO_PACKET_END", 9353 .errstr = "R3 pointer arithmetic on pkt_end",
8834 .result = REJECT, 9354 .result = REJECT,
8835 .prog_type = BPF_PROG_TYPE_XDP, 9355 .prog_type = BPF_PROG_TYPE_XDP,
8836 }, 9356 },
@@ -10018,7 +10538,7 @@ static struct bpf_test tests[] = {
10018 BPF_EXIT_INSN(), 10538 BPF_EXIT_INSN(),
10019 }, 10539 },
10020 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 10540 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
10021 .fixup_map1 = { 16 }, 10541 .fixup_map_hash_8b = { 16 },
10022 .result = REJECT, 10542 .result = REJECT,
10023 .errstr = "R0 min value is outside of the array range", 10543 .errstr = "R0 min value is outside of the array range",
10024 }, 10544 },
@@ -10969,7 +11489,7 @@ static struct bpf_test tests[] = {
10969 BPF_EXIT_INSN(), /* return 0 */ 11489 BPF_EXIT_INSN(), /* return 0 */
10970 }, 11490 },
10971 .prog_type = BPF_PROG_TYPE_XDP, 11491 .prog_type = BPF_PROG_TYPE_XDP,
10972 .fixup_map1 = { 23 }, 11492 .fixup_map_hash_8b = { 23 },
10973 .result = ACCEPT, 11493 .result = ACCEPT,
10974 }, 11494 },
10975 { 11495 {
@@ -11024,7 +11544,7 @@ static struct bpf_test tests[] = {
11024 BPF_EXIT_INSN(), /* return 1 */ 11544 BPF_EXIT_INSN(), /* return 1 */
11025 }, 11545 },
11026 .prog_type = BPF_PROG_TYPE_XDP, 11546 .prog_type = BPF_PROG_TYPE_XDP,
11027 .fixup_map1 = { 23 }, 11547 .fixup_map_hash_8b = { 23 },
11028 .result = ACCEPT, 11548 .result = ACCEPT,
11029 }, 11549 },
11030 { 11550 {
@@ -11079,7 +11599,7 @@ static struct bpf_test tests[] = {
11079 BPF_EXIT_INSN(), /* return 1 */ 11599 BPF_EXIT_INSN(), /* return 1 */
11080 }, 11600 },
11081 .prog_type = BPF_PROG_TYPE_XDP, 11601 .prog_type = BPF_PROG_TYPE_XDP,
11082 .fixup_map1 = { 23 }, 11602 .fixup_map_hash_8b = { 23 },
11083 .result = REJECT, 11603 .result = REJECT,
11084 .errstr = "invalid read from stack off -16+0 size 8", 11604 .errstr = "invalid read from stack off -16+0 size 8",
11085 }, 11605 },
@@ -11151,7 +11671,7 @@ static struct bpf_test tests[] = {
11151 BPF_EXIT_INSN(), 11671 BPF_EXIT_INSN(),
11152 }, 11672 },
11153 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 11673 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11154 .fixup_map1 = { 12, 22 }, 11674 .fixup_map_hash_8b = { 12, 22 },
11155 .result = REJECT, 11675 .result = REJECT,
11156 .errstr = "invalid access to map value, value_size=8 off=2 size=8", 11676 .errstr = "invalid access to map value, value_size=8 off=2 size=8",
11157 }, 11677 },
@@ -11223,7 +11743,7 @@ static struct bpf_test tests[] = {
11223 BPF_EXIT_INSN(), 11743 BPF_EXIT_INSN(),
11224 }, 11744 },
11225 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 11745 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11226 .fixup_map1 = { 12, 22 }, 11746 .fixup_map_hash_8b = { 12, 22 },
11227 .result = ACCEPT, 11747 .result = ACCEPT,
11228 }, 11748 },
11229 { 11749 {
@@ -11294,7 +11814,7 @@ static struct bpf_test tests[] = {
11294 BPF_JMP_IMM(BPF_JA, 0, 0, -8), 11814 BPF_JMP_IMM(BPF_JA, 0, 0, -8),
11295 }, 11815 },
11296 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 11816 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11297 .fixup_map1 = { 12, 22 }, 11817 .fixup_map_hash_8b = { 12, 22 },
11298 .result = REJECT, 11818 .result = REJECT,
11299 .errstr = "invalid access to map value, value_size=8 off=2 size=8", 11819 .errstr = "invalid access to map value, value_size=8 off=2 size=8",
11300 }, 11820 },
@@ -11366,7 +11886,7 @@ static struct bpf_test tests[] = {
11366 BPF_EXIT_INSN(), 11886 BPF_EXIT_INSN(),
11367 }, 11887 },
11368 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 11888 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11369 .fixup_map1 = { 12, 22 }, 11889 .fixup_map_hash_8b = { 12, 22 },
11370 .result = ACCEPT, 11890 .result = ACCEPT,
11371 }, 11891 },
11372 { 11892 {
@@ -11437,7 +11957,7 @@ static struct bpf_test tests[] = {
11437 BPF_EXIT_INSN(), 11957 BPF_EXIT_INSN(),
11438 }, 11958 },
11439 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 11959 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11440 .fixup_map1 = { 12, 22 }, 11960 .fixup_map_hash_8b = { 12, 22 },
11441 .result = REJECT, 11961 .result = REJECT,
11442 .errstr = "R0 invalid mem access 'inv'", 11962 .errstr = "R0 invalid mem access 'inv'",
11443 }, 11963 },
@@ -11782,7 +12302,7 @@ static struct bpf_test tests[] = {
11782 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 12302 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0),
11783 BPF_EXIT_INSN(), 12303 BPF_EXIT_INSN(),
11784 }, 12304 },
11785 .fixup_map1 = { 13 }, 12305 .fixup_map_hash_8b = { 13 },
11786 .result = ACCEPT, 12306 .result = ACCEPT,
11787 .prog_type = BPF_PROG_TYPE_XDP, 12307 .prog_type = BPF_PROG_TYPE_XDP,
11788 }, 12308 },
@@ -11809,7 +12329,7 @@ static struct bpf_test tests[] = {
11809 BPF_FUNC_map_lookup_elem), 12329 BPF_FUNC_map_lookup_elem),
11810 BPF_EXIT_INSN(), 12330 BPF_EXIT_INSN(),
11811 }, 12331 },
11812 .fixup_map2 = { 6 }, 12332 .fixup_map_hash_48b = { 6 },
11813 .errstr = "invalid indirect read from stack off -8+0 size 8", 12333 .errstr = "invalid indirect read from stack off -8+0 size 8",
11814 .result = REJECT, 12334 .result = REJECT,
11815 .prog_type = BPF_PROG_TYPE_XDP, 12335 .prog_type = BPF_PROG_TYPE_XDP,
@@ -11841,8 +12361,8 @@ static struct bpf_test tests[] = {
11841 BPF_EXIT_INSN(), 12361 BPF_EXIT_INSN(),
11842 }, 12362 },
11843 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 12363 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11844 .fixup_map2 = { 13 }, 12364 .fixup_map_hash_48b = { 13 },
11845 .fixup_map4 = { 16 }, 12365 .fixup_map_array_48b = { 16 },
11846 .result = ACCEPT, 12366 .result = ACCEPT,
11847 .retval = 1, 12367 .retval = 1,
11848 }, 12368 },
@@ -11874,7 +12394,7 @@ static struct bpf_test tests[] = {
11874 }, 12394 },
11875 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 12395 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11876 .fixup_map_in_map = { 16 }, 12396 .fixup_map_in_map = { 16 },
11877 .fixup_map4 = { 13 }, 12397 .fixup_map_array_48b = { 13 },
11878 .result = REJECT, 12398 .result = REJECT,
11879 .errstr = "R0 invalid mem access 'map_ptr'", 12399 .errstr = "R0 invalid mem access 'map_ptr'",
11880 }, 12400 },
@@ -11942,7 +12462,7 @@ static struct bpf_test tests[] = {
11942 BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xdead), 12462 BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xdead),
11943 BPF_EXIT_INSN(), 12463 BPF_EXIT_INSN(),
11944 }, 12464 },
11945 .fixup_map1 = { 3 }, 12465 .fixup_map_hash_8b = { 3 },
11946 .errstr = "R6 invalid mem access 'inv'", 12466 .errstr = "R6 invalid mem access 'inv'",
11947 .result = REJECT, 12467 .result = REJECT,
11948 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 12468 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -11966,7 +12486,7 @@ static struct bpf_test tests[] = {
11966 BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_10, -16), 12486 BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_10, -16),
11967 BPF_EXIT_INSN(), 12487 BPF_EXIT_INSN(),
11968 }, 12488 },
11969 .fixup_map1 = { 3 }, 12489 .fixup_map_hash_8b = { 3 },
11970 .errstr = "invalid read from stack off -16+0 size 8", 12490 .errstr = "invalid read from stack off -16+0 size 8",
11971 .result = REJECT, 12491 .result = REJECT,
11972 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 12492 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -12088,7 +12608,7 @@ static struct bpf_test tests[] = {
12088 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 3), 12608 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 3),
12089 BPF_EXIT_INSN(), 12609 BPF_EXIT_INSN(),
12090 }, 12610 },
12091 .fixup_map1 = { 3 }, 12611 .fixup_map_hash_8b = { 3 },
12092 .result = REJECT, 12612 .result = REJECT,
12093 .errstr = "misaligned value access off", 12613 .errstr = "misaligned value access off",
12094 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 12614 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -12114,7 +12634,7 @@ static struct bpf_test tests[] = {
12114 BPF_EXIT_INSN(), 12634 BPF_EXIT_INSN(),
12115 }, 12635 },
12116 .result = REJECT, 12636 .result = REJECT,
12117 .errstr = "BPF_XADD stores into R2 packet", 12637 .errstr = "BPF_XADD stores into R2 pkt is not allowed",
12118 .prog_type = BPF_PROG_TYPE_XDP, 12638 .prog_type = BPF_PROG_TYPE_XDP,
12119 }, 12639 },
12120 { 12640 {
@@ -12198,7 +12718,7 @@ static struct bpf_test tests[] = {
12198 BPF_EMIT_CALL(BPF_FUNC_get_stack), 12718 BPF_EMIT_CALL(BPF_FUNC_get_stack),
12199 BPF_EXIT_INSN(), 12719 BPF_EXIT_INSN(),
12200 }, 12720 },
12201 .fixup_map2 = { 4 }, 12721 .fixup_map_hash_48b = { 4 },
12202 .result = ACCEPT, 12722 .result = ACCEPT,
12203 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 12723 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
12204 }, 12724 },
@@ -12442,6 +12962,214 @@ static struct bpf_test tests[] = {
12442 .result = ACCEPT, 12962 .result = ACCEPT,
12443 }, 12963 },
12444 { 12964 {
12965 "reference tracking: leak potential reference",
12966 .insns = {
12967 BPF_SK_LOOKUP,
12968 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), /* leak reference */
12969 BPF_EXIT_INSN(),
12970 },
12971 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
12972 .errstr = "Unreleased reference",
12973 .result = REJECT,
12974 },
12975 {
12976 "reference tracking: leak potential reference on stack",
12977 .insns = {
12978 BPF_SK_LOOKUP,
12979 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
12980 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
12981 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
12982 BPF_MOV64_IMM(BPF_REG_0, 0),
12983 BPF_EXIT_INSN(),
12984 },
12985 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
12986 .errstr = "Unreleased reference",
12987 .result = REJECT,
12988 },
12989 {
12990 "reference tracking: leak potential reference on stack 2",
12991 .insns = {
12992 BPF_SK_LOOKUP,
12993 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
12994 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
12995 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
12996 BPF_MOV64_IMM(BPF_REG_0, 0),
12997 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
12998 BPF_EXIT_INSN(),
12999 },
13000 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13001 .errstr = "Unreleased reference",
13002 .result = REJECT,
13003 },
13004 {
13005 "reference tracking: zero potential reference",
13006 .insns = {
13007 BPF_SK_LOOKUP,
13008 BPF_MOV64_IMM(BPF_REG_0, 0), /* leak reference */
13009 BPF_EXIT_INSN(),
13010 },
13011 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13012 .errstr = "Unreleased reference",
13013 .result = REJECT,
13014 },
13015 {
13016 "reference tracking: copy and zero potential references",
13017 .insns = {
13018 BPF_SK_LOOKUP,
13019 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
13020 BPF_MOV64_IMM(BPF_REG_0, 0),
13021 BPF_MOV64_IMM(BPF_REG_7, 0), /* leak reference */
13022 BPF_EXIT_INSN(),
13023 },
13024 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13025 .errstr = "Unreleased reference",
13026 .result = REJECT,
13027 },
13028 {
13029 "reference tracking: release reference without check",
13030 .insns = {
13031 BPF_SK_LOOKUP,
13032 /* reference in r0 may be NULL */
13033 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13034 BPF_MOV64_IMM(BPF_REG_2, 0),
13035 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13036 BPF_EXIT_INSN(),
13037 },
13038 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13039 .errstr = "type=sock_or_null expected=sock",
13040 .result = REJECT,
13041 },
13042 {
13043 "reference tracking: release reference",
13044 .insns = {
13045 BPF_SK_LOOKUP,
13046 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13047 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13048 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13049 BPF_EXIT_INSN(),
13050 },
13051 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13052 .result = ACCEPT,
13053 },
13054 {
13055 "reference tracking: release reference 2",
13056 .insns = {
13057 BPF_SK_LOOKUP,
13058 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13059 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
13060 BPF_EXIT_INSN(),
13061 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13062 BPF_EXIT_INSN(),
13063 },
13064 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13065 .result = ACCEPT,
13066 },
13067 {
13068 "reference tracking: release reference twice",
13069 .insns = {
13070 BPF_SK_LOOKUP,
13071 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13072 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13073 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13074 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13075 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13076 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13077 BPF_EXIT_INSN(),
13078 },
13079 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13080 .errstr = "type=inv expected=sock",
13081 .result = REJECT,
13082 },
13083 {
13084 "reference tracking: release reference twice inside branch",
13085 .insns = {
13086 BPF_SK_LOOKUP,
13087 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13088 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13089 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), /* goto end */
13090 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13091 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13092 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13093 BPF_EXIT_INSN(),
13094 },
13095 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13096 .errstr = "type=inv expected=sock",
13097 .result = REJECT,
13098 },
13099 {
13100 "reference tracking: alloc, check, free in one subbranch",
13101 .insns = {
13102 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
13103 offsetof(struct __sk_buff, data)),
13104 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
13105 offsetof(struct __sk_buff, data_end)),
13106 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
13107 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16),
13108 /* if (offsetof(skb, mark) > data_len) exit; */
13109 BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1),
13110 BPF_EXIT_INSN(),
13111 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2,
13112 offsetof(struct __sk_buff, mark)),
13113 BPF_SK_LOOKUP,
13114 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 1), /* mark == 0? */
13115 /* Leak reference in R0 */
13116 BPF_EXIT_INSN(),
13117 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
13118 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13119 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13120 BPF_EXIT_INSN(),
13121 },
13122 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13123 .errstr = "Unreleased reference",
13124 .result = REJECT,
13125 },
13126 {
13127 "reference tracking: alloc, check, free in both subbranches",
13128 .insns = {
13129 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
13130 offsetof(struct __sk_buff, data)),
13131 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
13132 offsetof(struct __sk_buff, data_end)),
13133 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
13134 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16),
13135 /* if (offsetof(skb, mark) > data_len) exit; */
13136 BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1),
13137 BPF_EXIT_INSN(),
13138 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2,
13139 offsetof(struct __sk_buff, mark)),
13140 BPF_SK_LOOKUP,
13141 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 4), /* mark == 0? */
13142 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
13143 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13144 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13145 BPF_EXIT_INSN(),
13146 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
13147 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13148 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13149 BPF_EXIT_INSN(),
13150 },
13151 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13152 .result = ACCEPT,
13153 },
13154 {
13155 "reference tracking in call: free reference in subprog",
13156 .insns = {
13157 BPF_SK_LOOKUP,
13158 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */
13159 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
13160 BPF_MOV64_IMM(BPF_REG_0, 0),
13161 BPF_EXIT_INSN(),
13162
13163 /* subprog 1 */
13164 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
13165 BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1),
13166 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13167 BPF_EXIT_INSN(),
13168 },
13169 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13170 .result = ACCEPT,
13171 },
13172 {
12445 "pass modified ctx pointer to helper, 1", 13173 "pass modified ctx pointer to helper, 1",
12446 .insns = { 13174 .insns = {
12447 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612), 13175 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
@@ -12511,6 +13239,407 @@ static struct bpf_test tests[] = {
12511 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 13239 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
12512 .result = ACCEPT, 13240 .result = ACCEPT,
12513 }, 13241 },
13242 {
13243 "reference tracking in call: free reference in subprog and outside",
13244 .insns = {
13245 BPF_SK_LOOKUP,
13246 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */
13247 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13248 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3),
13249 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13250 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13251 BPF_EXIT_INSN(),
13252
13253 /* subprog 1 */
13254 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
13255 BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1),
13256 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13257 BPF_EXIT_INSN(),
13258 },
13259 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13260 .errstr = "type=inv expected=sock",
13261 .result = REJECT,
13262 },
13263 {
13264 "reference tracking in call: alloc & leak reference in subprog",
13265 .insns = {
13266 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
13267 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
13268 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3),
13269 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13270 BPF_MOV64_IMM(BPF_REG_0, 0),
13271 BPF_EXIT_INSN(),
13272
13273 /* subprog 1 */
13274 BPF_MOV64_REG(BPF_REG_6, BPF_REG_4),
13275 BPF_SK_LOOKUP,
13276 /* spill unchecked sk_ptr into stack of caller */
13277 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0),
13278 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13279 BPF_EXIT_INSN(),
13280 },
13281 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13282 .errstr = "Unreleased reference",
13283 .result = REJECT,
13284 },
13285 {
13286 "reference tracking in call: alloc in subprog, release outside",
13287 .insns = {
13288 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
13289 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4),
13290 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13291 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13292 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13293 BPF_EXIT_INSN(),
13294
13295 /* subprog 1 */
13296 BPF_SK_LOOKUP,
13297 BPF_EXIT_INSN(), /* return sk */
13298 },
13299 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13300 .retval = POINTER_VALUE,
13301 .result = ACCEPT,
13302 },
13303 {
13304 "reference tracking in call: sk_ptr leak into caller stack",
13305 .insns = {
13306 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
13307 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
13308 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
13309 BPF_MOV64_IMM(BPF_REG_0, 0),
13310 BPF_EXIT_INSN(),
13311
13312 /* subprog 1 */
13313 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
13314 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
13315 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
13316 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5),
13317 /* spill unchecked sk_ptr into stack of caller */
13318 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
13319 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
13320 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
13321 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
13322 BPF_EXIT_INSN(),
13323
13324 /* subprog 2 */
13325 BPF_SK_LOOKUP,
13326 BPF_EXIT_INSN(),
13327 },
13328 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13329 .errstr = "Unreleased reference",
13330 .result = REJECT,
13331 },
13332 {
13333 "reference tracking in call: sk_ptr spill into caller stack",
13334 .insns = {
13335 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
13336 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
13337 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
13338 BPF_MOV64_IMM(BPF_REG_0, 0),
13339 BPF_EXIT_INSN(),
13340
13341 /* subprog 1 */
13342 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
13343 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
13344 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
13345 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 8),
13346 /* spill unchecked sk_ptr into stack of caller */
13347 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
13348 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
13349 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
13350 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
13351 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
13352 /* now the sk_ptr is verified, free the reference */
13353 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_4, 0),
13354 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13355 BPF_EXIT_INSN(),
13356
13357 /* subprog 2 */
13358 BPF_SK_LOOKUP,
13359 BPF_EXIT_INSN(),
13360 },
13361 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13362 .result = ACCEPT,
13363 },
13364 {
13365 "reference tracking: allow LD_ABS",
13366 .insns = {
13367 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
13368 BPF_SK_LOOKUP,
13369 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13370 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13371 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13372 BPF_LD_ABS(BPF_B, 0),
13373 BPF_LD_ABS(BPF_H, 0),
13374 BPF_LD_ABS(BPF_W, 0),
13375 BPF_EXIT_INSN(),
13376 },
13377 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13378 .result = ACCEPT,
13379 },
13380 {
13381 "reference tracking: forbid LD_ABS while holding reference",
13382 .insns = {
13383 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
13384 BPF_SK_LOOKUP,
13385 BPF_LD_ABS(BPF_B, 0),
13386 BPF_LD_ABS(BPF_H, 0),
13387 BPF_LD_ABS(BPF_W, 0),
13388 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13389 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13390 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13391 BPF_EXIT_INSN(),
13392 },
13393 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13394 .errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references",
13395 .result = REJECT,
13396 },
13397 {
13398 "reference tracking: allow LD_IND",
13399 .insns = {
13400 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
13401 BPF_SK_LOOKUP,
13402 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13403 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13404 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13405 BPF_MOV64_IMM(BPF_REG_7, 1),
13406 BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
13407 BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
13408 BPF_EXIT_INSN(),
13409 },
13410 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13411 .result = ACCEPT,
13412 .retval = 1,
13413 },
13414 {
13415 "reference tracking: forbid LD_IND while holding reference",
13416 .insns = {
13417 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
13418 BPF_SK_LOOKUP,
13419 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
13420 BPF_MOV64_IMM(BPF_REG_7, 1),
13421 BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
13422 BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
13423 BPF_MOV64_REG(BPF_REG_1, BPF_REG_4),
13424 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
13425 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13426 BPF_EXIT_INSN(),
13427 },
13428 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13429 .errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references",
13430 .result = REJECT,
13431 },
13432 {
13433 "reference tracking: check reference or tail call",
13434 .insns = {
13435 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
13436 BPF_SK_LOOKUP,
13437 /* if (sk) bpf_sk_release() */
13438 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13439 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7),
13440 /* bpf_tail_call() */
13441 BPF_MOV64_IMM(BPF_REG_3, 2),
13442 BPF_LD_MAP_FD(BPF_REG_2, 0),
13443 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
13444 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
13445 BPF_FUNC_tail_call),
13446 BPF_MOV64_IMM(BPF_REG_0, 0),
13447 BPF_EXIT_INSN(),
13448 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13449 BPF_EXIT_INSN(),
13450 },
13451 .fixup_prog1 = { 17 },
13452 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13453 .result = ACCEPT,
13454 },
13455 {
13456 "reference tracking: release reference then tail call",
13457 .insns = {
13458 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
13459 BPF_SK_LOOKUP,
13460 /* if (sk) bpf_sk_release() */
13461 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13462 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
13463 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13464 /* bpf_tail_call() */
13465 BPF_MOV64_IMM(BPF_REG_3, 2),
13466 BPF_LD_MAP_FD(BPF_REG_2, 0),
13467 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
13468 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
13469 BPF_FUNC_tail_call),
13470 BPF_MOV64_IMM(BPF_REG_0, 0),
13471 BPF_EXIT_INSN(),
13472 },
13473 .fixup_prog1 = { 18 },
13474 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13475 .result = ACCEPT,
13476 },
13477 {
13478 "reference tracking: leak possible reference over tail call",
13479 .insns = {
13480 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
13481 /* Look up socket and store in REG_6 */
13482 BPF_SK_LOOKUP,
13483 /* bpf_tail_call() */
13484 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13485 BPF_MOV64_IMM(BPF_REG_3, 2),
13486 BPF_LD_MAP_FD(BPF_REG_2, 0),
13487 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
13488 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
13489 BPF_FUNC_tail_call),
13490 BPF_MOV64_IMM(BPF_REG_0, 0),
13491 /* if (sk) bpf_sk_release() */
13492 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13493 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
13494 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13495 BPF_EXIT_INSN(),
13496 },
13497 .fixup_prog1 = { 16 },
13498 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13499 .errstr = "tail_call would lead to reference leak",
13500 .result = REJECT,
13501 },
13502 {
13503 "reference tracking: leak checked reference over tail call",
13504 .insns = {
13505 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
13506 /* Look up socket and store in REG_6 */
13507 BPF_SK_LOOKUP,
13508 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13509 /* if (!sk) goto end */
13510 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
13511 /* bpf_tail_call() */
13512 BPF_MOV64_IMM(BPF_REG_3, 0),
13513 BPF_LD_MAP_FD(BPF_REG_2, 0),
13514 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
13515 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
13516 BPF_FUNC_tail_call),
13517 BPF_MOV64_IMM(BPF_REG_0, 0),
13518 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13519 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13520 BPF_EXIT_INSN(),
13521 },
13522 .fixup_prog1 = { 17 },
13523 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13524 .errstr = "tail_call would lead to reference leak",
13525 .result = REJECT,
13526 },
13527 {
13528 "reference tracking: mangle and release sock_or_null",
13529 .insns = {
13530 BPF_SK_LOOKUP,
13531 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13532 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5),
13533 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
13534 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13535 BPF_EXIT_INSN(),
13536 },
13537 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13538 .errstr = "R1 pointer arithmetic on sock_or_null prohibited",
13539 .result = REJECT,
13540 },
13541 {
13542 "reference tracking: mangle and release sock",
13543 .insns = {
13544 BPF_SK_LOOKUP,
13545 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13546 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
13547 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5),
13548 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13549 BPF_EXIT_INSN(),
13550 },
13551 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13552 .errstr = "R1 pointer arithmetic on sock prohibited",
13553 .result = REJECT,
13554 },
13555 {
13556 "reference tracking: access member",
13557 .insns = {
13558 BPF_SK_LOOKUP,
13559 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13560 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
13561 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4),
13562 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13563 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13564 BPF_EXIT_INSN(),
13565 },
13566 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13567 .result = ACCEPT,
13568 },
13569 {
13570 "reference tracking: write to member",
13571 .insns = {
13572 BPF_SK_LOOKUP,
13573 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13574 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
13575 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13576 BPF_LD_IMM64(BPF_REG_2, 42),
13577 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_2,
13578 offsetof(struct bpf_sock, mark)),
13579 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13580 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13581 BPF_LD_IMM64(BPF_REG_0, 0),
13582 BPF_EXIT_INSN(),
13583 },
13584 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13585 .errstr = "cannot write into socket",
13586 .result = REJECT,
13587 },
13588 {
13589 "reference tracking: invalid 64-bit access of member",
13590 .insns = {
13591 BPF_SK_LOOKUP,
13592 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13593 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
13594 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
13595 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13596 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13597 BPF_EXIT_INSN(),
13598 },
13599 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13600 .errstr = "invalid bpf_sock access off=0 size=8",
13601 .result = REJECT,
13602 },
13603 {
13604 "reference tracking: access after release",
13605 .insns = {
13606 BPF_SK_LOOKUP,
13607 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
13608 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
13609 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13610 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
13611 BPF_EXIT_INSN(),
13612 },
13613 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13614 .errstr = "!read_ok",
13615 .result = REJECT,
13616 },
13617 {
13618 "reference tracking: direct access for lookup",
13619 .insns = {
13620 /* Check that the packet is at least 64B long */
13621 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
13622 offsetof(struct __sk_buff, data)),
13623 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
13624 offsetof(struct __sk_buff, data_end)),
13625 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
13626 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 64),
13627 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 9),
13628 /* sk = sk_lookup_tcp(ctx, skb->data, ...) */
13629 BPF_MOV64_IMM(BPF_REG_3, sizeof(struct bpf_sock_tuple)),
13630 BPF_MOV64_IMM(BPF_REG_4, 0),
13631 BPF_MOV64_IMM(BPF_REG_5, 0),
13632 BPF_EMIT_CALL(BPF_FUNC_sk_lookup_tcp),
13633 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
13634 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
13635 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4),
13636 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
13637 BPF_EMIT_CALL(BPF_FUNC_sk_release),
13638 BPF_EXIT_INSN(),
13639 },
13640 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
13641 .result = ACCEPT,
13642 },
12514}; 13643};
12515 13644
12516static int probe_filter_length(const struct bpf_insn *fp) 13645static int probe_filter_length(const struct bpf_insn *fp)
@@ -12536,18 +13665,18 @@ static int create_map(uint32_t type, uint32_t size_key,
12536 return fd; 13665 return fd;
12537} 13666}
12538 13667
12539static int create_prog_dummy1(void) 13668static int create_prog_dummy1(enum bpf_map_type prog_type)
12540{ 13669{
12541 struct bpf_insn prog[] = { 13670 struct bpf_insn prog[] = {
12542 BPF_MOV64_IMM(BPF_REG_0, 42), 13671 BPF_MOV64_IMM(BPF_REG_0, 42),
12543 BPF_EXIT_INSN(), 13672 BPF_EXIT_INSN(),
12544 }; 13673 };
12545 13674
12546 return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, 13675 return bpf_load_program(prog_type, prog,
12547 ARRAY_SIZE(prog), "GPL", 0, NULL, 0); 13676 ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
12548} 13677}
12549 13678
12550static int create_prog_dummy2(int mfd, int idx) 13679static int create_prog_dummy2(enum bpf_map_type prog_type, int mfd, int idx)
12551{ 13680{
12552 struct bpf_insn prog[] = { 13681 struct bpf_insn prog[] = {
12553 BPF_MOV64_IMM(BPF_REG_3, idx), 13682 BPF_MOV64_IMM(BPF_REG_3, idx),
@@ -12558,11 +13687,12 @@ static int create_prog_dummy2(int mfd, int idx)
12558 BPF_EXIT_INSN(), 13687 BPF_EXIT_INSN(),
12559 }; 13688 };
12560 13689
12561 return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, 13690 return bpf_load_program(prog_type, prog,
12562 ARRAY_SIZE(prog), "GPL", 0, NULL, 0); 13691 ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
12563} 13692}
12564 13693
12565static int create_prog_array(uint32_t max_elem, int p1key) 13694static int create_prog_array(enum bpf_map_type prog_type, uint32_t max_elem,
13695 int p1key)
12566{ 13696{
12567 int p2key = 1; 13697 int p2key = 1;
12568 int mfd, p1fd, p2fd; 13698 int mfd, p1fd, p2fd;
@@ -12574,8 +13704,8 @@ static int create_prog_array(uint32_t max_elem, int p1key)
12574 return -1; 13704 return -1;
12575 } 13705 }
12576 13706
12577 p1fd = create_prog_dummy1(); 13707 p1fd = create_prog_dummy1(prog_type);
12578 p2fd = create_prog_dummy2(mfd, p2key); 13708 p2fd = create_prog_dummy2(prog_type, mfd, p2key);
12579 if (p1fd < 0 || p2fd < 0) 13709 if (p1fd < 0 || p2fd < 0)
12580 goto out; 13710 goto out;
12581 if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0) 13711 if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0)
@@ -12615,32 +13745,39 @@ static int create_map_in_map(void)
12615 return outer_map_fd; 13745 return outer_map_fd;
12616} 13746}
12617 13747
12618static int create_cgroup_storage(void) 13748static int create_cgroup_storage(bool percpu)
12619{ 13749{
13750 enum bpf_map_type type = percpu ? BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE :
13751 BPF_MAP_TYPE_CGROUP_STORAGE;
12620 int fd; 13752 int fd;
12621 13753
12622 fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, 13754 fd = bpf_create_map(type, sizeof(struct bpf_cgroup_storage_key),
12623 sizeof(struct bpf_cgroup_storage_key),
12624 TEST_DATA_LEN, 0, 0); 13755 TEST_DATA_LEN, 0, 0);
12625 if (fd < 0) 13756 if (fd < 0)
12626 printf("Failed to create array '%s'!\n", strerror(errno)); 13757 printf("Failed to create cgroup storage '%s'!\n",
13758 strerror(errno));
12627 13759
12628 return fd; 13760 return fd;
12629} 13761}
12630 13762
12631static char bpf_vlog[UINT_MAX >> 8]; 13763static char bpf_vlog[UINT_MAX >> 8];
12632 13764
12633static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog, 13765static void do_test_fixup(struct bpf_test *test, enum bpf_map_type prog_type,
12634 int *map_fds) 13766 struct bpf_insn *prog, int *map_fds)
12635{ 13767{
12636 int *fixup_map1 = test->fixup_map1; 13768 int *fixup_map_hash_8b = test->fixup_map_hash_8b;
12637 int *fixup_map2 = test->fixup_map2; 13769 int *fixup_map_hash_48b = test->fixup_map_hash_48b;
12638 int *fixup_map3 = test->fixup_map3; 13770 int *fixup_map_hash_16b = test->fixup_map_hash_16b;
12639 int *fixup_map4 = test->fixup_map4; 13771 int *fixup_map_array_48b = test->fixup_map_array_48b;
13772 int *fixup_map_sockmap = test->fixup_map_sockmap;
13773 int *fixup_map_sockhash = test->fixup_map_sockhash;
13774 int *fixup_map_xskmap = test->fixup_map_xskmap;
13775 int *fixup_map_stacktrace = test->fixup_map_stacktrace;
12640 int *fixup_prog1 = test->fixup_prog1; 13776 int *fixup_prog1 = test->fixup_prog1;
12641 int *fixup_prog2 = test->fixup_prog2; 13777 int *fixup_prog2 = test->fixup_prog2;
12642 int *fixup_map_in_map = test->fixup_map_in_map; 13778 int *fixup_map_in_map = test->fixup_map_in_map;
12643 int *fixup_cgroup_storage = test->fixup_cgroup_storage; 13779 int *fixup_cgroup_storage = test->fixup_cgroup_storage;
13780 int *fixup_percpu_cgroup_storage = test->fixup_percpu_cgroup_storage;
12644 13781
12645 if (test->fill_helper) 13782 if (test->fill_helper)
12646 test->fill_helper(test); 13783 test->fill_helper(test);
@@ -12649,44 +13786,44 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog,
12649 * for verifier and not do a runtime lookup, so the only thing 13786 * for verifier and not do a runtime lookup, so the only thing
12650 * that really matters is value size in this case. 13787 * that really matters is value size in this case.
12651 */ 13788 */
12652 if (*fixup_map1) { 13789 if (*fixup_map_hash_8b) {
12653 map_fds[0] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long), 13790 map_fds[0] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long),
12654 sizeof(long long), 1); 13791 sizeof(long long), 1);
12655 do { 13792 do {
12656 prog[*fixup_map1].imm = map_fds[0]; 13793 prog[*fixup_map_hash_8b].imm = map_fds[0];
12657 fixup_map1++; 13794 fixup_map_hash_8b++;
12658 } while (*fixup_map1); 13795 } while (*fixup_map_hash_8b);
12659 } 13796 }
12660 13797
12661 if (*fixup_map2) { 13798 if (*fixup_map_hash_48b) {
12662 map_fds[1] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long), 13799 map_fds[1] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long),
12663 sizeof(struct test_val), 1); 13800 sizeof(struct test_val), 1);
12664 do { 13801 do {
12665 prog[*fixup_map2].imm = map_fds[1]; 13802 prog[*fixup_map_hash_48b].imm = map_fds[1];
12666 fixup_map2++; 13803 fixup_map_hash_48b++;
12667 } while (*fixup_map2); 13804 } while (*fixup_map_hash_48b);
12668 } 13805 }
12669 13806
12670 if (*fixup_map3) { 13807 if (*fixup_map_hash_16b) {
12671 map_fds[2] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long), 13808 map_fds[2] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long),
12672 sizeof(struct other_val), 1); 13809 sizeof(struct other_val), 1);
12673 do { 13810 do {
12674 prog[*fixup_map3].imm = map_fds[2]; 13811 prog[*fixup_map_hash_16b].imm = map_fds[2];
12675 fixup_map3++; 13812 fixup_map_hash_16b++;
12676 } while (*fixup_map3); 13813 } while (*fixup_map_hash_16b);
12677 } 13814 }
12678 13815
12679 if (*fixup_map4) { 13816 if (*fixup_map_array_48b) {
12680 map_fds[3] = create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 13817 map_fds[3] = create_map(BPF_MAP_TYPE_ARRAY, sizeof(int),
12681 sizeof(struct test_val), 1); 13818 sizeof(struct test_val), 1);
12682 do { 13819 do {
12683 prog[*fixup_map4].imm = map_fds[3]; 13820 prog[*fixup_map_array_48b].imm = map_fds[3];
12684 fixup_map4++; 13821 fixup_map_array_48b++;
12685 } while (*fixup_map4); 13822 } while (*fixup_map_array_48b);
12686 } 13823 }
12687 13824
12688 if (*fixup_prog1) { 13825 if (*fixup_prog1) {
12689 map_fds[4] = create_prog_array(4, 0); 13826 map_fds[4] = create_prog_array(prog_type, 4, 0);
12690 do { 13827 do {
12691 prog[*fixup_prog1].imm = map_fds[4]; 13828 prog[*fixup_prog1].imm = map_fds[4];
12692 fixup_prog1++; 13829 fixup_prog1++;
@@ -12694,7 +13831,7 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog,
12694 } 13831 }
12695 13832
12696 if (*fixup_prog2) { 13833 if (*fixup_prog2) {
12697 map_fds[5] = create_prog_array(8, 7); 13834 map_fds[5] = create_prog_array(prog_type, 8, 7);
12698 do { 13835 do {
12699 prog[*fixup_prog2].imm = map_fds[5]; 13836 prog[*fixup_prog2].imm = map_fds[5];
12700 fixup_prog2++; 13837 fixup_prog2++;
@@ -12710,12 +13847,52 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog,
12710 } 13847 }
12711 13848
12712 if (*fixup_cgroup_storage) { 13849 if (*fixup_cgroup_storage) {
12713 map_fds[7] = create_cgroup_storage(); 13850 map_fds[7] = create_cgroup_storage(false);
12714 do { 13851 do {
12715 prog[*fixup_cgroup_storage].imm = map_fds[7]; 13852 prog[*fixup_cgroup_storage].imm = map_fds[7];
12716 fixup_cgroup_storage++; 13853 fixup_cgroup_storage++;
12717 } while (*fixup_cgroup_storage); 13854 } while (*fixup_cgroup_storage);
12718 } 13855 }
13856
13857 if (*fixup_percpu_cgroup_storage) {
13858 map_fds[8] = create_cgroup_storage(true);
13859 do {
13860 prog[*fixup_percpu_cgroup_storage].imm = map_fds[8];
13861 fixup_percpu_cgroup_storage++;
13862 } while (*fixup_percpu_cgroup_storage);
13863 }
13864 if (*fixup_map_sockmap) {
13865 map_fds[9] = create_map(BPF_MAP_TYPE_SOCKMAP, sizeof(int),
13866 sizeof(int), 1);
13867 do {
13868 prog[*fixup_map_sockmap].imm = map_fds[9];
13869 fixup_map_sockmap++;
13870 } while (*fixup_map_sockmap);
13871 }
13872 if (*fixup_map_sockhash) {
13873 map_fds[10] = create_map(BPF_MAP_TYPE_SOCKHASH, sizeof(int),
13874 sizeof(int), 1);
13875 do {
13876 prog[*fixup_map_sockhash].imm = map_fds[10];
13877 fixup_map_sockhash++;
13878 } while (*fixup_map_sockhash);
13879 }
13880 if (*fixup_map_xskmap) {
13881 map_fds[11] = create_map(BPF_MAP_TYPE_XSKMAP, sizeof(int),
13882 sizeof(int), 1);
13883 do {
13884 prog[*fixup_map_xskmap].imm = map_fds[11];
13885 fixup_map_xskmap++;
13886 } while (*fixup_map_xskmap);
13887 }
13888 if (*fixup_map_stacktrace) {
13889 map_fds[12] = create_map(BPF_MAP_TYPE_STACK_TRACE, sizeof(u32),
13890 sizeof(u64), 1);
13891 do {
13892 prog[*fixup_map_stacktrace].imm = map_fds[12];
13893 fixup_map_stacktrace++;
13894 } while (fixup_map_stacktrace);
13895 }
12719} 13896}
12720 13897
12721static void do_test_single(struct bpf_test *test, bool unpriv, 13898static void do_test_single(struct bpf_test *test, bool unpriv,
@@ -12732,11 +13909,13 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
12732 for (i = 0; i < MAX_NR_MAPS; i++) 13909 for (i = 0; i < MAX_NR_MAPS; i++)
12733 map_fds[i] = -1; 13910 map_fds[i] = -1;
12734 13911
12735 do_test_fixup(test, prog, map_fds); 13912 if (!prog_type)
13913 prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
13914 do_test_fixup(test, prog_type, prog, map_fds);
12736 prog_len = probe_filter_length(prog); 13915 prog_len = probe_filter_length(prog);
12737 13916
12738 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 13917 fd_prog = bpf_verify_program(prog_type, prog, prog_len,
12739 prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT, 13918 test->flags & F_LOAD_WITH_STRICT_ALIGNMENT,
12740 "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1); 13919 "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1);
12741 13920
12742 expected_ret = unpriv && test->result_unpriv != UNDEF ? 13921 expected_ret = unpriv && test->result_unpriv != UNDEF ?
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan.c b/tools/testing/selftests/bpf/test_xdp_vlan.c
new file mode 100644
index 000000000000..365a7d2d9f5c
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_vlan.c
@@ -0,0 +1,292 @@
1/* SPDX-License-Identifier: GPL-2.0
2 * Copyright(c) 2018 Jesper Dangaard Brouer.
3 *
4 * XDP/TC VLAN manipulation example
5 *
6 * GOTCHA: Remember to disable NIC hardware offloading of VLANs,
7 * else the VLAN tags are NOT inlined in the packet payload:
8 *
9 * # ethtool -K ixgbe2 rxvlan off
10 *
11 * Verify setting:
12 * # ethtool -k ixgbe2 | grep rx-vlan-offload
13 * rx-vlan-offload: off
14 *
15 */
16#include <stddef.h>
17#include <stdbool.h>
18#include <string.h>
19#include <linux/bpf.h>
20#include <linux/if_ether.h>
21#include <linux/if_vlan.h>
22#include <linux/in.h>
23#include <linux/pkt_cls.h>
24
25#include "bpf_helpers.h"
26#include "bpf_endian.h"
27
28/* linux/if_vlan.h have not exposed this as UAPI, thus mirror some here
29 *
30 * struct vlan_hdr - vlan header
31 * @h_vlan_TCI: priority and VLAN ID
32 * @h_vlan_encapsulated_proto: packet type ID or len
33 */
34struct _vlan_hdr {
35 __be16 h_vlan_TCI;
36 __be16 h_vlan_encapsulated_proto;
37};
38#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
39#define VLAN_PRIO_SHIFT 13
40#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */
41#define VLAN_TAG_PRESENT VLAN_CFI_MASK
42#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
43#define VLAN_N_VID 4096
44
45struct parse_pkt {
46 __u16 l3_proto;
47 __u16 l3_offset;
48 __u16 vlan_outer;
49 __u16 vlan_inner;
50 __u8 vlan_outer_offset;
51 __u8 vlan_inner_offset;
52};
53
54char _license[] SEC("license") = "GPL";
55
56static __always_inline
57bool parse_eth_frame(struct ethhdr *eth, void *data_end, struct parse_pkt *pkt)
58{
59 __u16 eth_type;
60 __u8 offset;
61
62 offset = sizeof(*eth);
63 /* Make sure packet is large enough for parsing eth + 2 VLAN headers */
64 if ((void *)eth + offset + (2*sizeof(struct _vlan_hdr)) > data_end)
65 return false;
66
67 eth_type = eth->h_proto;
68
69 /* Handle outer VLAN tag */
70 if (eth_type == bpf_htons(ETH_P_8021Q)
71 || eth_type == bpf_htons(ETH_P_8021AD)) {
72 struct _vlan_hdr *vlan_hdr;
73
74 vlan_hdr = (void *)eth + offset;
75 pkt->vlan_outer_offset = offset;
76 pkt->vlan_outer = bpf_ntohs(vlan_hdr->h_vlan_TCI)
77 & VLAN_VID_MASK;
78 eth_type = vlan_hdr->h_vlan_encapsulated_proto;
79 offset += sizeof(*vlan_hdr);
80 }
81
82 /* Handle inner (double) VLAN tag */
83 if (eth_type == bpf_htons(ETH_P_8021Q)
84 || eth_type == bpf_htons(ETH_P_8021AD)) {
85 struct _vlan_hdr *vlan_hdr;
86
87 vlan_hdr = (void *)eth + offset;
88 pkt->vlan_inner_offset = offset;
89 pkt->vlan_inner = bpf_ntohs(vlan_hdr->h_vlan_TCI)
90 & VLAN_VID_MASK;
91 eth_type = vlan_hdr->h_vlan_encapsulated_proto;
92 offset += sizeof(*vlan_hdr);
93 }
94
95 pkt->l3_proto = bpf_ntohs(eth_type); /* Convert to host-byte-order */
96 pkt->l3_offset = offset;
97
98 return true;
99}
100
101/* Hint, VLANs are choosen to hit network-byte-order issues */
102#define TESTVLAN 4011 /* 0xFAB */
103// #define TO_VLAN 4000 /* 0xFA0 (hint 0xOA0 = 160) */
104
105SEC("xdp_drop_vlan_4011")
106int xdp_prognum0(struct xdp_md *ctx)
107{
108 void *data_end = (void *)(long)ctx->data_end;
109 void *data = (void *)(long)ctx->data;
110 struct parse_pkt pkt = { 0 };
111
112 if (!parse_eth_frame(data, data_end, &pkt))
113 return XDP_ABORTED;
114
115 /* Drop specific VLAN ID example */
116 if (pkt.vlan_outer == TESTVLAN)
117 return XDP_ABORTED;
118 /*
119 * Using XDP_ABORTED makes it possible to record this event,
120 * via tracepoint xdp:xdp_exception like:
121 * # perf record -a -e xdp:xdp_exception
122 * # perf script
123 */
124 return XDP_PASS;
125}
126/*
127Commands to setup VLAN on Linux to test packets gets dropped:
128
129 export ROOTDEV=ixgbe2
130 export VLANID=4011
131 ip link add link $ROOTDEV name $ROOTDEV.$VLANID type vlan id $VLANID
132 ip link set dev $ROOTDEV.$VLANID up
133
134 ip link set dev $ROOTDEV mtu 1508
135 ip addr add 100.64.40.11/24 dev $ROOTDEV.$VLANID
136
137Load prog with ip tool:
138
139 ip link set $ROOTDEV xdp off
140 ip link set $ROOTDEV xdp object xdp_vlan01_kern.o section xdp_drop_vlan_4011
141
142*/
143
144/* Changing VLAN to zero, have same practical effect as removing the VLAN. */
145#define TO_VLAN 0
146
147SEC("xdp_vlan_change")
148int xdp_prognum1(struct xdp_md *ctx)
149{
150 void *data_end = (void *)(long)ctx->data_end;
151 void *data = (void *)(long)ctx->data;
152 struct parse_pkt pkt = { 0 };
153
154 if (!parse_eth_frame(data, data_end, &pkt))
155 return XDP_ABORTED;
156
157 /* Change specific VLAN ID */
158 if (pkt.vlan_outer == TESTVLAN) {
159 struct _vlan_hdr *vlan_hdr = data + pkt.vlan_outer_offset;
160
161 /* Modifying VLAN, preserve top 4 bits */
162 vlan_hdr->h_vlan_TCI =
163 bpf_htons((bpf_ntohs(vlan_hdr->h_vlan_TCI) & 0xf000)
164 | TO_VLAN);
165 }
166
167 return XDP_PASS;
168}
169
170/*
171 * Show XDP+TC can cooperate, on creating a VLAN rewriter.
172 * 1. Create a XDP prog that can "pop"/remove a VLAN header.
173 * 2. Create a TC-bpf prog that egress can add a VLAN header.
174 */
175
176#ifndef ETH_ALEN /* Ethernet MAC address length */
177#define ETH_ALEN 6 /* bytes */
178#endif
179#define VLAN_HDR_SZ 4 /* bytes */
180
181SEC("xdp_vlan_remove_outer")
182int xdp_prognum2(struct xdp_md *ctx)
183{
184 void *data_end = (void *)(long)ctx->data_end;
185 void *data = (void *)(long)ctx->data;
186 struct parse_pkt pkt = { 0 };
187 char *dest;
188
189 if (!parse_eth_frame(data, data_end, &pkt))
190 return XDP_ABORTED;
191
192 /* Skip packet if no outer VLAN was detected */
193 if (pkt.vlan_outer_offset == 0)
194 return XDP_PASS;
195
196 /* Moving Ethernet header, dest overlap with src, memmove handle this */
197 dest = data;
198 dest+= VLAN_HDR_SZ;
199 /*
200 * Notice: Taking over vlan_hdr->h_vlan_encapsulated_proto, by
201 * only moving two MAC addrs (12 bytes), not overwriting last 2 bytes
202 */
203 __builtin_memmove(dest, data, ETH_ALEN * 2);
204 /* Note: LLVM built-in memmove inlining require size to be constant */
205
206 /* Move start of packet header seen by Linux kernel stack */
207 bpf_xdp_adjust_head(ctx, VLAN_HDR_SZ);
208
209 return XDP_PASS;
210}
211
212static __always_inline
213void shift_mac_4bytes_16bit(void *data)
214{
215 __u16 *p = data;
216
217 p[7] = p[5]; /* delete p[7] was vlan_hdr->h_vlan_TCI */
218 p[6] = p[4]; /* delete p[6] was ethhdr->h_proto */
219 p[5] = p[3];
220 p[4] = p[2];
221 p[3] = p[1];
222 p[2] = p[0];
223}
224
225static __always_inline
226void shift_mac_4bytes_32bit(void *data)
227{
228 __u32 *p = data;
229
230 /* Assuming VLAN hdr present. The 4 bytes in p[3] that gets
231 * overwritten, is ethhdr->h_proto and vlan_hdr->h_vlan_TCI.
232 * The vlan_hdr->h_vlan_encapsulated_proto take over role as
233 * ethhdr->h_proto.
234 */
235 p[3] = p[2];
236 p[2] = p[1];
237 p[1] = p[0];
238}
239
240SEC("xdp_vlan_remove_outer2")
241int xdp_prognum3(struct xdp_md *ctx)
242{
243 void *data_end = (void *)(long)ctx->data_end;
244 void *data = (void *)(long)ctx->data;
245 struct ethhdr *orig_eth = data;
246 struct parse_pkt pkt = { 0 };
247
248 if (!parse_eth_frame(orig_eth, data_end, &pkt))
249 return XDP_ABORTED;
250
251 /* Skip packet if no outer VLAN was detected */
252 if (pkt.vlan_outer_offset == 0)
253 return XDP_PASS;
254
255 /* Simply shift down MAC addrs 4 bytes, overwrite h_proto + TCI */
256 shift_mac_4bytes_32bit(data);
257
258 /* Move start of packet header seen by Linux kernel stack */
259 bpf_xdp_adjust_head(ctx, VLAN_HDR_SZ);
260
261 return XDP_PASS;
262}
263
264/*=====================================
265 * BELOW: TC-hook based ebpf programs
266 * ====================================
267 * The TC-clsact eBPF programs (currently) need to be attach via TC commands
268 */
269
270SEC("tc_vlan_push")
271int _tc_progA(struct __sk_buff *ctx)
272{
273 bpf_skb_vlan_push(ctx, bpf_htons(ETH_P_8021Q), TESTVLAN);
274
275 return TC_ACT_OK;
276}
277/*
278Commands to setup TC to use above bpf prog:
279
280export ROOTDEV=ixgbe2
281export FILE=xdp_vlan01_kern.o
282
283# Re-attach clsact to clear/flush existing role
284tc qdisc del dev $ROOTDEV clsact 2> /dev/null ;\
285tc qdisc add dev $ROOTDEV clsact
286
287# Attach BPF prog EGRESS
288tc filter add dev $ROOTDEV egress \
289 prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
290
291tc filter show dev $ROOTDEV egress
292*/
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan.sh b/tools/testing/selftests/bpf/test_xdp_vlan.sh
new file mode 100755
index 000000000000..51a3a31d1aac
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_vlan.sh
@@ -0,0 +1,195 @@
1#!/bin/bash
2
3TESTNAME=xdp_vlan
4
5usage() {
6 echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME"
7 echo ""
8 echo "Usage: $0 [-vfh]"
9 echo " -v | --verbose : Verbose"
10 echo " --flush : Flush before starting (e.g. after --interactive)"
11 echo " --interactive : Keep netns setup running after test-run"
12 echo ""
13}
14
15cleanup()
16{
17 local status=$?
18
19 if [ "$status" = "0" ]; then
20 echo "selftests: $TESTNAME [PASS]";
21 else
22 echo "selftests: $TESTNAME [FAILED]";
23 fi
24
25 if [ -n "$INTERACTIVE" ]; then
26 echo "Namespace setup still active explore with:"
27 echo " ip netns exec ns1 bash"
28 echo " ip netns exec ns2 bash"
29 exit $status
30 fi
31
32 set +e
33 ip link del veth1 2> /dev/null
34 ip netns del ns1 2> /dev/null
35 ip netns del ns2 2> /dev/null
36}
37
38# Using external program "getopt" to get --long-options
39OPTIONS=$(getopt -o hvfi: \
40 --long verbose,flush,help,interactive,debug -- "$@")
41if (( $? != 0 )); then
42 usage
43 echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"
44 exit 2
45fi
46eval set -- "$OPTIONS"
47
48## --- Parse command line arguments / parameters ---
49while true; do
50 case "$1" in
51 -v | --verbose)
52 export VERBOSE=yes
53 shift
54 ;;
55 -i | --interactive | --debug )
56 INTERACTIVE=yes
57 shift
58 ;;
59 -f | --flush )
60 cleanup
61 shift
62 ;;
63 -- )
64 shift
65 break
66 ;;
67 -h | --help )
68 usage;
69 echo "selftests: $TESTNAME [SKIP] usage help info requested"
70 exit 0
71 ;;
72 * )
73 shift
74 break
75 ;;
76 esac
77done
78
79if [ "$EUID" -ne 0 ]; then
80 echo "selftests: $TESTNAME [FAILED] need root privileges"
81 exit 1
82fi
83
84ip link set dev lo xdp off 2>/dev/null > /dev/null
85if [ $? -ne 0 ];then
86 echo "selftests: $TESTNAME [SKIP] need ip xdp support"
87 exit 0
88fi
89
90# Interactive mode likely require us to cleanup netns
91if [ -n "$INTERACTIVE" ]; then
92 ip link del veth1 2> /dev/null
93 ip netns del ns1 2> /dev/null
94 ip netns del ns2 2> /dev/null
95fi
96
97# Exit on failure
98set -e
99
100# Some shell-tools dependencies
101which ip > /dev/null
102which tc > /dev/null
103which ethtool > /dev/null
104
105# Make rest of shell verbose, showing comments as doc/info
106if [ -n "$VERBOSE" ]; then
107 set -v
108fi
109
110# Create two namespaces
111ip netns add ns1
112ip netns add ns2
113
114# Run cleanup if failing or on kill
115trap cleanup 0 2 3 6 9
116
117# Create veth pair
118ip link add veth1 type veth peer name veth2
119
120# Move veth1 and veth2 into the respective namespaces
121ip link set veth1 netns ns1
122ip link set veth2 netns ns2
123
124# NOTICE: XDP require VLAN header inside packet payload
125# - Thus, disable VLAN offloading driver features
126# - For veth REMEMBER TX side VLAN-offload
127#
128# Disable rx-vlan-offload (mostly needed on ns1)
129ip netns exec ns1 ethtool -K veth1 rxvlan off
130ip netns exec ns2 ethtool -K veth2 rxvlan off
131#
132# Disable tx-vlan-offload (mostly needed on ns2)
133ip netns exec ns2 ethtool -K veth2 txvlan off
134ip netns exec ns1 ethtool -K veth1 txvlan off
135
136export IPADDR1=100.64.41.1
137export IPADDR2=100.64.41.2
138
139# In ns1/veth1 add IP-addr on plain net_device
140ip netns exec ns1 ip addr add ${IPADDR1}/24 dev veth1
141ip netns exec ns1 ip link set veth1 up
142
143# In ns2/veth2 create VLAN device
144export VLAN=4011
145export DEVNS2=veth2
146ip netns exec ns2 ip link add link $DEVNS2 name $DEVNS2.$VLAN type vlan id $VLAN
147ip netns exec ns2 ip addr add ${IPADDR2}/24 dev $DEVNS2.$VLAN
148ip netns exec ns2 ip link set $DEVNS2 up
149ip netns exec ns2 ip link set $DEVNS2.$VLAN up
150
151# Bringup lo in netns (to avoids confusing people using --interactive)
152ip netns exec ns1 ip link set lo up
153ip netns exec ns2 ip link set lo up
154
155# At this point, the hosts cannot reach each-other,
156# because ns2 are using VLAN tags on the packets.
157
158ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Okay ping fails"'
159
160
161# Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags
162# ----------------------------------------------------------------------
163# In ns1: ingress use XDP to remove VLAN tags
164export DEVNS1=veth1
165export FILE=test_xdp_vlan.o
166
167# First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
168export XDP_PROG=xdp_vlan_change
169ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
170
171# In ns1: egress use TC to add back VLAN tag 4011
172# (del cmd)
173# tc qdisc del dev $DEVNS1 clsact 2> /dev/null
174#
175ip netns exec ns1 tc qdisc add dev $DEVNS1 clsact
176ip netns exec ns1 tc filter add dev $DEVNS1 egress \
177 prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
178
179# Now the namespaces can reach each-other, test with ping:
180ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
181ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
182
183# Second test: Replace xdp prog, that fully remove vlan header
184#
185# Catch kernel bug for generic-XDP, that does didn't allow us to
186# remove a VLAN header, because skb->protocol still contain VLAN
187# ETH_P_8021Q indication, and this cause overwriting of our changes.
188#
189export XDP_PROG=xdp_vlan_remove_outer2
190ip netns exec ns1 ip link set $DEVNS1 xdp off
191ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
192
193# Now the namespaces should still be able reach each-other, test with ping:
194ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
195ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c
index cabe2a3a3b30..4cdb63bf0521 100644
--- a/tools/testing/selftests/bpf/trace_helpers.c
+++ b/tools/testing/selftests/bpf/trace_helpers.c
@@ -41,6 +41,7 @@ int load_kallsyms(void)
41 syms[i].name = strdup(func); 41 syms[i].name = strdup(func);
42 i++; 42 i++;
43 } 43 }
44 fclose(f);
44 sym_cnt = i; 45 sym_cnt = i;
45 qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp); 46 qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp);
46 return 0; 47 return 0;
@@ -124,10 +125,11 @@ struct perf_event_sample {
124 char data[]; 125 char data[];
125}; 126};
126 127
127static enum bpf_perf_event_ret bpf_perf_event_print(void *event, void *priv) 128static enum bpf_perf_event_ret
129bpf_perf_event_print(struct perf_event_header *hdr, void *private_data)
128{ 130{
129 struct perf_event_sample *e = event; 131 struct perf_event_sample *e = (struct perf_event_sample *)hdr;
130 perf_event_print_fn fn = priv; 132 perf_event_print_fn fn = private_data;
131 int ret; 133 int ret;
132 134
133 if (e->header.type == PERF_RECORD_SAMPLE) { 135 if (e->header.type == PERF_RECORD_SAMPLE) {
diff --git a/tools/testing/selftests/bpf/with_addr.sh b/tools/testing/selftests/bpf/with_addr.sh
new file mode 100755
index 000000000000..ffcd3953f94c
--- /dev/null
+++ b/tools/testing/selftests/bpf/with_addr.sh
@@ -0,0 +1,54 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# add private ipv4 and ipv6 addresses to loopback
5
6readonly V6_INNER='100::a/128'
7readonly V4_INNER='192.168.0.1/32'
8
9if getopts ":s" opt; then
10 readonly SIT_DEV_NAME='sixtofourtest0'
11 readonly V6_SIT='2::/64'
12 readonly V4_SIT='172.17.0.1/32'
13 shift
14fi
15
16fail() {
17 echo "error: $*" 1>&2
18 exit 1
19}
20
21setup() {
22 ip -6 addr add "${V6_INNER}" dev lo || fail 'failed to setup v6 address'
23 ip -4 addr add "${V4_INNER}" dev lo || fail 'failed to setup v4 address'
24
25 if [[ -n "${V6_SIT}" ]]; then
26 ip link add "${SIT_DEV_NAME}" type sit remote any local any \
27 || fail 'failed to add sit'
28 ip link set dev "${SIT_DEV_NAME}" up \
29 || fail 'failed to bring sit device up'
30 ip -6 addr add "${V6_SIT}" dev "${SIT_DEV_NAME}" \
31 || fail 'failed to setup v6 SIT address'
32 ip -4 addr add "${V4_SIT}" dev "${SIT_DEV_NAME}" \
33 || fail 'failed to setup v4 SIT address'
34 fi
35
36 sleep 2 # avoid race causing bind to fail
37}
38
39cleanup() {
40 if [[ -n "${V6_SIT}" ]]; then
41 ip -4 addr del "${V4_SIT}" dev "${SIT_DEV_NAME}"
42 ip -6 addr del "${V6_SIT}" dev "${SIT_DEV_NAME}"
43 ip link del "${SIT_DEV_NAME}"
44 fi
45
46 ip -4 addr del "${V4_INNER}" dev lo
47 ip -6 addr del "${V6_INNER}" dev lo
48}
49
50trap cleanup EXIT
51
52setup
53"$@"
54exit "$?"
diff --git a/tools/testing/selftests/bpf/with_tunnels.sh b/tools/testing/selftests/bpf/with_tunnels.sh
new file mode 100755
index 000000000000..e24949ed3a20
--- /dev/null
+++ b/tools/testing/selftests/bpf/with_tunnels.sh
@@ -0,0 +1,36 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# setup tunnels for flow dissection test
5
6readonly SUFFIX="test_$(mktemp -u XXXX)"
7CONFIG="remote 127.0.0.2 local 127.0.0.1 dev lo"
8
9setup() {
10 ip link add "ipip_${SUFFIX}" type ipip ${CONFIG}
11 ip link add "gre_${SUFFIX}" type gre ${CONFIG}
12 ip link add "sit_${SUFFIX}" type sit ${CONFIG}
13
14 echo "tunnels before test:"
15 ip tunnel show
16
17 ip link set "ipip_${SUFFIX}" up
18 ip link set "gre_${SUFFIX}" up
19 ip link set "sit_${SUFFIX}" up
20}
21
22
23cleanup() {
24 ip tunnel del "ipip_${SUFFIX}"
25 ip tunnel del "gre_${SUFFIX}"
26 ip tunnel del "sit_${SUFFIX}"
27
28 echo "tunnels after test:"
29 ip tunnel show
30}
31
32trap cleanup EXIT
33
34setup
35"$@"
36exit "$?"
diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
new file mode 100755
index 000000000000..0150bb2741eb
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
@@ -0,0 +1,347 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# A test for switch behavior under MC overload. An issue in Spectrum chips
5# causes throughput of UC traffic to drop severely when a switch is under heavy
6# MC load. This issue can be overcome by putting the switch to MC-aware mode.
7# This test verifies that UC performance stays intact even as the switch is
8# under MC flood, and therefore that the MC-aware mode is enabled and correctly
9# configured.
10#
11# Because mlxsw throttles CPU port, the traffic can't actually reach userspace
12# at full speed. That makes it impossible to use iperf3 to simply measure the
13# throughput, because many packets (that reach $h3) don't get to the kernel at
14# all even in UDP mode (the situation is even worse in TCP mode, where one can't
15# hope to see more than a couple Mbps).
16#
17# So instead we send traffic with mausezahn and use RX ethtool counters at $h3.
18# Multicast traffic is untagged, unicast traffic is tagged with PCP 1. Therefore
19# each gets a different priority and we can use per-prio ethtool counters to
20# measure the throughput. In order to avoid prioritizing unicast traffic, prio
21# qdisc is installed on $swp3 and maps all priorities to the same band #7 (and
22# thus TC 0).
23#
24# Mausezahn can't actually saturate the links unless it's using large frames.
25# Thus we set MTU to 10K on all involved interfaces. Then both unicast and
26# multicast traffic uses 8K frames.
27#
28# +-----------------------+ +----------------------------------+
29# | H1 | | H2 |
30# | | | unicast --> + $h2.111 |
31# | | | traffic | 192.0.2.129/28 |
32# | multicast | | | e-qos-map 0:1 |
33# | traffic | | | |
34# | $h1 + <----- | | + $h2 |
35# +-----|-----------------+ +--------------|-------------------+
36# | |
37# +-----|-------------------------------------------------|-------------------+
38# | + $swp1 + $swp2 |
39# | | >1Gbps | >1Gbps |
40# | +---|----------------+ +----------|----------------+ |
41# | | + $swp1.1 | | + $swp2.111 | |
42# | | BR1 | SW | BR111 | |
43# | | + $swp3.1 | | + $swp3.111 | |
44# | +---|----------------+ +----------|----------------+ |
45# | \_________________________________________________/ |
46# | | |
47# | + $swp3 |
48# | | 1Gbps bottleneck |
49# | | prio qdisc: {0..7} -> 7 |
50# +------------------------------------|--------------------------------------+
51# |
52# +--|-----------------+
53# | + $h3 H3 |
54# | | |
55# | + $h3.111 |
56# | 192.0.2.130/28 |
57# +--------------------+
58
59ALL_TESTS="
60 ping_ipv4
61 test_mc_aware
62"
63
64lib_dir=$(dirname $0)/../../../net/forwarding
65
66NUM_NETIFS=6
67source $lib_dir/lib.sh
68
69h1_create()
70{
71 simple_if_init $h1
72 mtu_set $h1 10000
73}
74
75h1_destroy()
76{
77 mtu_restore $h1
78 simple_if_fini $h1
79}
80
81h2_create()
82{
83 simple_if_init $h2
84 mtu_set $h2 10000
85
86 vlan_create $h2 111 v$h2 192.0.2.129/28
87 ip link set dev $h2.111 type vlan egress-qos-map 0:1
88}
89
90h2_destroy()
91{
92 vlan_destroy $h2 111
93
94 mtu_restore $h2
95 simple_if_fini $h2
96}
97
98h3_create()
99{
100 simple_if_init $h3
101 mtu_set $h3 10000
102
103 vlan_create $h3 111 v$h3 192.0.2.130/28
104}
105
106h3_destroy()
107{
108 vlan_destroy $h3 111
109
110 mtu_restore $h3
111 simple_if_fini $h3
112}
113
114switch_create()
115{
116 ip link set dev $swp1 up
117 mtu_set $swp1 10000
118
119 ip link set dev $swp2 up
120 mtu_set $swp2 10000
121
122 ip link set dev $swp3 up
123 mtu_set $swp3 10000
124
125 vlan_create $swp2 111
126 vlan_create $swp3 111
127
128 ethtool -s $swp3 speed 1000 autoneg off
129 tc qdisc replace dev $swp3 root handle 3: \
130 prio bands 8 priomap 7 7 7 7 7 7 7 7
131
132 ip link add name br1 type bridge vlan_filtering 0
133 ip link set dev br1 up
134 ip link set dev $swp1 master br1
135 ip link set dev $swp3 master br1
136
137 ip link add name br111 type bridge vlan_filtering 0
138 ip link set dev br111 up
139 ip link set dev $swp2.111 master br111
140 ip link set dev $swp3.111 master br111
141}
142
143switch_destroy()
144{
145 ip link del dev br111
146 ip link del dev br1
147
148 tc qdisc del dev $swp3 root handle 3:
149 ethtool -s $swp3 autoneg on
150
151 vlan_destroy $swp3 111
152 vlan_destroy $swp2 111
153
154 mtu_restore $swp3
155 ip link set dev $swp3 down
156
157 mtu_restore $swp2
158 ip link set dev $swp2 down
159
160 mtu_restore $swp1
161 ip link set dev $swp1 down
162}
163
164setup_prepare()
165{
166 h1=${NETIFS[p1]}
167 swp1=${NETIFS[p2]}
168
169 swp2=${NETIFS[p3]}
170 h2=${NETIFS[p4]}
171
172 swp3=${NETIFS[p5]}
173 h3=${NETIFS[p6]}
174
175 h3mac=$(mac_get $h3)
176
177 vrf_prepare
178
179 h1_create
180 h2_create
181 h3_create
182 switch_create
183}
184
185cleanup()
186{
187 pre_cleanup
188
189 switch_destroy
190 h3_destroy
191 h2_destroy
192 h1_destroy
193
194 vrf_cleanup
195}
196
197ping_ipv4()
198{
199 ping_test $h2 192.0.2.130
200}
201
202humanize()
203{
204 local speed=$1; shift
205
206 for unit in bps Kbps Mbps Gbps; do
207 if (($(echo "$speed < 1024" | bc))); then
208 break
209 fi
210
211 speed=$(echo "scale=1; $speed / 1024" | bc)
212 done
213
214 echo "$speed${unit}"
215}
216
217rate()
218{
219 local t0=$1; shift
220 local t1=$1; shift
221 local interval=$1; shift
222
223 echo $((8 * (t1 - t0) / interval))
224}
225
226check_rate()
227{
228 local rate=$1; shift
229 local min=$1; shift
230 local what=$1; shift
231
232 if ((rate > min)); then
233 return 0
234 fi
235
236 echo "$what $(humanize $ir) < $(humanize $min_ingress)" > /dev/stderr
237 return 1
238}
239
240measure_uc_rate()
241{
242 local what=$1; shift
243
244 local interval=10
245 local i
246 local ret=0
247
248 # Dips in performance might cause momentary ingress rate to drop below
249 # 1Gbps. That wouldn't saturate egress and MC would thus get through,
250 # seemingly winning bandwidth on account of UC. Demand at least 2Gbps
251 # average ingress rate to somewhat mitigate this.
252 local min_ingress=2147483648
253
254 mausezahn $h2.111 -p 8000 -A 192.0.2.129 -B 192.0.2.130 -c 0 \
255 -a own -b $h3mac -t udp -q &
256 sleep 1
257
258 for i in {5..0}; do
259 local t0=$(ethtool_stats_get $h3 rx_octets_prio_1)
260 local u0=$(ethtool_stats_get $swp2 rx_octets_prio_1)
261 sleep $interval
262 local t1=$(ethtool_stats_get $h3 rx_octets_prio_1)
263 local u1=$(ethtool_stats_get $swp2 rx_octets_prio_1)
264
265 local ir=$(rate $u0 $u1 $interval)
266 local er=$(rate $t0 $t1 $interval)
267
268 if check_rate $ir $min_ingress "$what ingress rate"; then
269 break
270 fi
271
272 # Fail the test if we can't get the throughput.
273 if ((i == 0)); then
274 ret=1
275 fi
276 done
277
278 # Suppress noise from killing mausezahn.
279 { kill %% && wait; } 2>/dev/null
280
281 echo $ir $er
282 exit $ret
283}
284
285test_mc_aware()
286{
287 RET=0
288
289 local -a uc_rate
290 uc_rate=($(measure_uc_rate "UC-only"))
291 check_err $? "Could not get high enough UC-only ingress rate"
292 local ucth1=${uc_rate[1]}
293
294 mausezahn $h1 -p 8000 -c 0 -a own -b bc -t udp -q &
295
296 local d0=$(date +%s)
297 local t0=$(ethtool_stats_get $h3 rx_octets_prio_0)
298 local u0=$(ethtool_stats_get $swp1 rx_octets_prio_0)
299
300 local -a uc_rate_2
301 uc_rate_2=($(measure_uc_rate "UC+MC"))
302 check_err $? "Could not get high enough UC+MC ingress rate"
303 local ucth2=${uc_rate_2[1]}
304
305 local d1=$(date +%s)
306 local t1=$(ethtool_stats_get $h3 rx_octets_prio_0)
307 local u1=$(ethtool_stats_get $swp1 rx_octets_prio_0)
308
309 local deg=$(bc <<< "
310 scale=2
311 ret = 100 * ($ucth1 - $ucth2) / $ucth1
312 if (ret > 0) { ret } else { 0 }
313 ")
314 check_err $(bc <<< "$deg > 10")
315
316 local interval=$((d1 - d0))
317 local mc_ir=$(rate $u0 $u1 $interval)
318 local mc_er=$(rate $t0 $t1 $interval)
319
320 # Suppress noise from killing mausezahn.
321 { kill %% && wait; } 2>/dev/null
322
323 log_test "UC performace under MC overload"
324
325 echo "UC-only throughput $(humanize $ucth1)"
326 echo "UC+MC throughput $(humanize $ucth2)"
327 echo "Degradation $deg %"
328 echo
329 echo "Full report:"
330 echo " UC only:"
331 echo " ingress UC throughput $(humanize ${uc_rate[0]})"
332 echo " egress UC throughput $(humanize ${uc_rate[1]})"
333 echo " UC+MC:"
334 echo " ingress UC throughput $(humanize ${uc_rate_2[0]})"
335 echo " egress UC throughput $(humanize ${uc_rate_2[1]})"
336 echo " ingress MC throughput $(humanize $mc_ir)"
337 echo " egress MC throughput $(humanize $mc_er)"
338}
339
340trap cleanup EXIT
341
342setup_prepare
343setup_wait
344
345tests_run
346
347exit $EXIT_STATUS
diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index 5c34752e1cff..6210ba41c29e 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -1,6 +1,8 @@
1cr4_cpuid_sync_test 1/x86_64/cr4_cpuid_sync_test
2platform_info_test 2/x86_64/evmcs_test
3set_sregs_test 3/x86_64/platform_info_test
4sync_regs_test 4/x86_64/set_sregs_test
5vmx_tsc_adjust_test 5/x86_64/sync_regs_test
6state_test 6/x86_64/vmx_tsc_adjust_test
7/x86_64/state_test
8/dirty_log_test
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index ec32dad3c3f0..01a219229238 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -1,26 +1,30 @@
1all: 1all:
2 2
3top_srcdir = ../../../../ 3top_srcdir = ../../../..
4UNAME_M := $(shell uname -m) 4UNAME_M := $(shell uname -m)
5 5
6LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c 6LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/ucall.c lib/sparsebit.c
7LIBKVM_x86_64 = lib/x86.c lib/vmx.c 7LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c
8 8LIBKVM_aarch64 = lib/aarch64/processor.c
9TEST_GEN_PROGS_x86_64 = platform_info_test 9
10TEST_GEN_PROGS_x86_64 += set_sregs_test 10TEST_GEN_PROGS_x86_64 = x86_64/platform_info_test
11TEST_GEN_PROGS_x86_64 += sync_regs_test 11TEST_GEN_PROGS_x86_64 += x86_64/set_sregs_test
12TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test 12TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test
13TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test 13TEST_GEN_PROGS_x86_64 += x86_64/vmx_tsc_adjust_test
14TEST_GEN_PROGS_x86_64 += state_test 14TEST_GEN_PROGS_x86_64 += x86_64/cr4_cpuid_sync_test
15TEST_GEN_PROGS_x86_64 += x86_64/state_test
16TEST_GEN_PROGS_x86_64 += x86_64/evmcs_test
15TEST_GEN_PROGS_x86_64 += dirty_log_test 17TEST_GEN_PROGS_x86_64 += dirty_log_test
16 18
19TEST_GEN_PROGS_aarch64 += dirty_log_test
20
17TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M)) 21TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M))
18LIBKVM += $(LIBKVM_$(UNAME_M)) 22LIBKVM += $(LIBKVM_$(UNAME_M))
19 23
20INSTALL_HDR_PATH = $(top_srcdir)/usr 24INSTALL_HDR_PATH = $(top_srcdir)/usr
21LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/ 25LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
22LINUX_TOOL_INCLUDE = $(top_srcdir)tools/include 26LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
23CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_TOOL_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I.. 27CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_TOOL_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -Iinclude/$(UNAME_M) -I..
24LDFLAGS += -pthread 28LDFLAGS += -pthread
25 29
26# After inclusion, $(OUTPUT) is defined and 30# After inclusion, $(OUTPUT) is defined and
@@ -29,7 +33,7 @@ include ../lib.mk
29 33
30STATIC_LIBS := $(OUTPUT)/libkvm.a 34STATIC_LIBS := $(OUTPUT)/libkvm.a
31LIBKVM_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM)) 35LIBKVM_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM))
32EXTRA_CLEAN += $(LIBKVM_OBJ) $(STATIC_LIBS) 36EXTRA_CLEAN += $(LIBKVM_OBJ) $(STATIC_LIBS) cscope.*
33 37
34x := $(shell mkdir -p $(sort $(dir $(LIBKVM_OBJ)))) 38x := $(shell mkdir -p $(sort $(dir $(LIBKVM_OBJ))))
35$(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c 39$(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
@@ -41,3 +45,12 @@ $(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
41all: $(STATIC_LIBS) 45all: $(STATIC_LIBS)
42$(TEST_GEN_PROGS): $(STATIC_LIBS) 46$(TEST_GEN_PROGS): $(STATIC_LIBS)
43$(STATIC_LIBS):| khdr 47$(STATIC_LIBS):| khdr
48
49cscope: include_paths = $(LINUX_TOOL_INCLUDE) $(LINUX_HDR_PATH) include lib ..
50cscope:
51 $(RM) cscope.*
52 (find $(include_paths) -name '*.h' \
53 -exec realpath --relative-base=$(PWD) {} \;; \
54 find . -name '*.c' \
55 -exec realpath --relative-base=$(PWD) {} \;) | sort -u > cscope.files
56 cscope -b
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index 0c2cdc105f96..d59820cc2d39 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -5,6 +5,8 @@
5 * Copyright (C) 2018, Red Hat, Inc. 5 * Copyright (C) 2018, Red Hat, Inc.
6 */ 6 */
7 7
8#define _GNU_SOURCE /* for program_invocation_name */
9
8#include <stdio.h> 10#include <stdio.h>
9#include <stdlib.h> 11#include <stdlib.h>
10#include <unistd.h> 12#include <unistd.h>
@@ -15,76 +17,78 @@
15 17
16#include "test_util.h" 18#include "test_util.h"
17#include "kvm_util.h" 19#include "kvm_util.h"
20#include "processor.h"
21
22#define DEBUG printf
18 23
19#define DEBUG printf 24#define VCPU_ID 1
20 25
21#define VCPU_ID 1
22/* The memory slot index to track dirty pages */ 26/* The memory slot index to track dirty pages */
23#define TEST_MEM_SLOT_INDEX 1 27#define TEST_MEM_SLOT_INDEX 1
24/* 28
25 * GPA offset of the testing memory slot. Must be bigger than the 29/* Default guest test memory offset, 1G */
26 * default vm mem slot, which is DEFAULT_GUEST_PHY_PAGES. 30#define DEFAULT_GUEST_TEST_MEM 0x40000000
27 */ 31
28#define TEST_MEM_OFFSET (1ULL << 30) /* 1G */
29/* Size of the testing memory slot */
30#define TEST_MEM_PAGES (1ULL << 18) /* 1G for 4K pages */
31/* How many pages to dirty for each guest loop */ 32/* How many pages to dirty for each guest loop */
32#define TEST_PAGES_PER_LOOP 1024 33#define TEST_PAGES_PER_LOOP 1024
34
33/* How many host loops to run (one KVM_GET_DIRTY_LOG for each loop) */ 35/* How many host loops to run (one KVM_GET_DIRTY_LOG for each loop) */
34#define TEST_HOST_LOOP_N 32 36#define TEST_HOST_LOOP_N 32
37
35/* Interval for each host loop (ms) */ 38/* Interval for each host loop (ms) */
36#define TEST_HOST_LOOP_INTERVAL 10 39#define TEST_HOST_LOOP_INTERVAL 10
40
41/*
42 * Guest/Host shared variables. Ensure addr_gva2hva() and/or
43 * sync_global_to/from_guest() are used when accessing from
44 * the host. READ/WRITE_ONCE() should also be used with anything
45 * that may change.
46 */
47static uint64_t host_page_size;
48static uint64_t guest_page_size;
49static uint64_t guest_num_pages;
50static uint64_t random_array[TEST_PAGES_PER_LOOP];
51static uint64_t iteration;
37 52
38/* 53/*
39 * Guest variables. We use these variables to share data between host 54 * GPA offset of the testing memory slot. Must be bigger than
40 * and guest. There are two copies of the variables, one in host memory 55 * DEFAULT_GUEST_PHY_PAGES.
41 * (which is unused) and one in guest memory. When the host wants to
42 * access these variables, it needs to call addr_gva2hva() to access the
43 * guest copy.
44 */ 56 */
45uint64_t guest_random_array[TEST_PAGES_PER_LOOP]; 57static uint64_t guest_test_mem = DEFAULT_GUEST_TEST_MEM;
46uint64_t guest_iteration;
47uint64_t guest_page_size;
48 58
49/* 59/*
50 * Writes to the first byte of a random page within the testing memory 60 * Continuously write to the first 8 bytes of a random pages within
51 * region continuously. 61 * the testing memory region.
52 */ 62 */
53void guest_code(void) 63static void guest_code(void)
54{ 64{
55 int i = 0; 65 int i;
56 uint64_t volatile *array = guest_random_array;
57 uint64_t volatile *guest_addr;
58 66
59 while (true) { 67 while (true) {
60 for (i = 0; i < TEST_PAGES_PER_LOOP; i++) { 68 for (i = 0; i < TEST_PAGES_PER_LOOP; i++) {
61 /* 69 uint64_t addr = guest_test_mem;
62 * Write to the first 8 bytes of a random page 70 addr += (READ_ONCE(random_array[i]) % guest_num_pages)
63 * on the testing memory region. 71 * guest_page_size;
64 */ 72 addr &= ~(host_page_size - 1);
65 guest_addr = (uint64_t *) 73 *(uint64_t *)addr = READ_ONCE(iteration);
66 (TEST_MEM_OFFSET +
67 (array[i] % TEST_MEM_PAGES) * guest_page_size);
68 *guest_addr = guest_iteration;
69 } 74 }
75
70 /* Tell the host that we need more random numbers */ 76 /* Tell the host that we need more random numbers */
71 GUEST_SYNC(1); 77 GUEST_SYNC(1);
72 } 78 }
73} 79}
74 80
75/* 81/* Host variables */
76 * Host variables. These variables should only be used by the host 82static bool host_quit;
77 * rather than the guest.
78 */
79bool host_quit;
80 83
81/* Points to the test VM memory region on which we track dirty logs */ 84/* Points to the test VM memory region on which we track dirty logs */
82void *host_test_mem; 85static void *host_test_mem;
86static uint64_t host_num_pages;
83 87
84/* For statistics only */ 88/* For statistics only */
85uint64_t host_dirty_count; 89static uint64_t host_dirty_count;
86uint64_t host_clear_count; 90static uint64_t host_clear_count;
87uint64_t host_track_next_count; 91static uint64_t host_track_next_count;
88 92
89/* 93/*
90 * We use this bitmap to track some pages that should have its dirty 94 * We use this bitmap to track some pages that should have its dirty
@@ -93,40 +97,34 @@ uint64_t host_track_next_count;
93 * page bit is cleared in the latest bitmap, then the system must 97 * page bit is cleared in the latest bitmap, then the system must
94 * report that write in the next get dirty log call. 98 * report that write in the next get dirty log call.
95 */ 99 */
96unsigned long *host_bmap_track; 100static unsigned long *host_bmap_track;
97 101
98void generate_random_array(uint64_t *guest_array, uint64_t size) 102static void generate_random_array(uint64_t *guest_array, uint64_t size)
99{ 103{
100 uint64_t i; 104 uint64_t i;
101 105
102 for (i = 0; i < size; i++) { 106 for (i = 0; i < size; i++)
103 guest_array[i] = random(); 107 guest_array[i] = random();
104 }
105} 108}
106 109
107void *vcpu_worker(void *data) 110static void *vcpu_worker(void *data)
108{ 111{
109 int ret; 112 int ret;
110 uint64_t loops, *guest_array, pages_count = 0;
111 struct kvm_vm *vm = data; 113 struct kvm_vm *vm = data;
114 uint64_t *guest_array;
115 uint64_t pages_count = 0;
112 struct kvm_run *run; 116 struct kvm_run *run;
113 struct guest_args args; 117 struct ucall uc;
114 118
115 run = vcpu_state(vm, VCPU_ID); 119 run = vcpu_state(vm, VCPU_ID);
116 120
117 /* Retrieve the guest random array pointer and cache it */ 121 guest_array = addr_gva2hva(vm, (vm_vaddr_t)random_array);
118 guest_array = addr_gva2hva(vm, (vm_vaddr_t)guest_random_array);
119
120 DEBUG("VCPU starts\n");
121
122 generate_random_array(guest_array, TEST_PAGES_PER_LOOP); 122 generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
123 123
124 while (!READ_ONCE(host_quit)) { 124 while (!READ_ONCE(host_quit)) {
125 /* Let the guest to dirty these random pages */ 125 /* Let the guest dirty the random pages */
126 ret = _vcpu_run(vm, VCPU_ID); 126 ret = _vcpu_run(vm, VCPU_ID);
127 guest_args_read(vm, VCPU_ID, &args); 127 if (get_ucall(vm, VCPU_ID, &uc) == UCALL_SYNC) {
128 if (run->exit_reason == KVM_EXIT_IO &&
129 args.port == GUEST_PORT_SYNC) {
130 pages_count += TEST_PAGES_PER_LOOP; 128 pages_count += TEST_PAGES_PER_LOOP;
131 generate_random_array(guest_array, TEST_PAGES_PER_LOOP); 129 generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
132 } else { 130 } else {
@@ -137,18 +135,20 @@ void *vcpu_worker(void *data)
137 } 135 }
138 } 136 }
139 137
140 DEBUG("VCPU exits, dirtied %"PRIu64" pages\n", pages_count); 138 DEBUG("Dirtied %"PRIu64" pages\n", pages_count);
141 139
142 return NULL; 140 return NULL;
143} 141}
144 142
145void vm_dirty_log_verify(unsigned long *bmap, uint64_t iteration) 143static void vm_dirty_log_verify(unsigned long *bmap)
146{ 144{
147 uint64_t page; 145 uint64_t page;
148 uint64_t volatile *value_ptr; 146 uint64_t *value_ptr;
147 uint64_t step = host_page_size >= guest_page_size ? 1 :
148 guest_page_size / host_page_size;
149 149
150 for (page = 0; page < TEST_MEM_PAGES; page++) { 150 for (page = 0; page < host_num_pages; page += step) {
151 value_ptr = host_test_mem + page * getpagesize(); 151 value_ptr = host_test_mem + page * host_page_size;
152 152
153 /* If this is a special page that we were tracking... */ 153 /* If this is a special page that we were tracking... */
154 if (test_and_clear_bit(page, host_bmap_track)) { 154 if (test_and_clear_bit(page, host_bmap_track)) {
@@ -208,88 +208,117 @@ void vm_dirty_log_verify(unsigned long *bmap, uint64_t iteration)
208 } 208 }
209} 209}
210 210
211void help(char *name) 211static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid,
212 uint64_t extra_mem_pages, void *guest_code)
212{ 213{
213 puts(""); 214 struct kvm_vm *vm;
214 printf("usage: %s [-i iterations] [-I interval] [-h]\n", name); 215 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
215 puts(""); 216
216 printf(" -i: specify iteration counts (default: %"PRIu64")\n", 217 vm = vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);
217 TEST_HOST_LOOP_N); 218 kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
218 printf(" -I: specify interval in ms (default: %"PRIu64" ms)\n", 219#ifdef __x86_64__
219 TEST_HOST_LOOP_INTERVAL); 220 vm_create_irqchip(vm);
220 puts(""); 221#endif
221 exit(0); 222 vm_vcpu_add_default(vm, vcpuid, guest_code);
223 return vm;
222} 224}
223 225
224int main(int argc, char *argv[]) 226static void run_test(enum vm_guest_mode mode, unsigned long iterations,
227 unsigned long interval, bool top_offset)
225{ 228{
229 unsigned int guest_pa_bits, guest_page_shift;
226 pthread_t vcpu_thread; 230 pthread_t vcpu_thread;
227 struct kvm_vm *vm; 231 struct kvm_vm *vm;
228 uint64_t volatile *psize, *iteration; 232 uint64_t max_gfn;
229 unsigned long *bmap, iterations = TEST_HOST_LOOP_N, 233 unsigned long *bmap;
230 interval = TEST_HOST_LOOP_INTERVAL; 234
231 int opt; 235 switch (mode) {
232 236 case VM_MODE_P52V48_4K:
233 while ((opt = getopt(argc, argv, "hi:I:")) != -1) { 237 guest_pa_bits = 52;
234 switch (opt) { 238 guest_page_shift = 12;
235 case 'i': 239 break;
236 iterations = strtol(optarg, NULL, 10); 240 case VM_MODE_P52V48_64K:
237 break; 241 guest_pa_bits = 52;
238 case 'I': 242 guest_page_shift = 16;
239 interval = strtol(optarg, NULL, 10); 243 break;
240 break; 244 case VM_MODE_P40V48_4K:
241 case 'h': 245 guest_pa_bits = 40;
242 default: 246 guest_page_shift = 12;
243 help(argv[0]); 247 break;
244 break; 248 case VM_MODE_P40V48_64K:
245 } 249 guest_pa_bits = 40;
250 guest_page_shift = 16;
251 break;
252 default:
253 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
246 } 254 }
247 255
248 TEST_ASSERT(iterations > 2, "Iteration must be bigger than zero\n"); 256 DEBUG("Testing guest mode: %s\n", vm_guest_mode_string(mode));
249 TEST_ASSERT(interval > 0, "Interval must be bigger than zero");
250 257
251 DEBUG("Test iterations: %"PRIu64", interval: %"PRIu64" (ms)\n", 258 max_gfn = (1ul << (guest_pa_bits - guest_page_shift)) - 1;
252 iterations, interval); 259 guest_page_size = (1ul << guest_page_shift);
260 /* 1G of guest page sized pages */
261 guest_num_pages = (1ul << (30 - guest_page_shift));
262 host_page_size = getpagesize();
263 host_num_pages = (guest_num_pages * guest_page_size) / host_page_size +
264 !!((guest_num_pages * guest_page_size) % host_page_size);
253 265
254 srandom(time(0)); 266 if (top_offset) {
267 guest_test_mem = (max_gfn - guest_num_pages) * guest_page_size;
268 guest_test_mem &= ~(host_page_size - 1);
269 }
255 270
256 bmap = bitmap_alloc(TEST_MEM_PAGES); 271 DEBUG("guest test mem offset: 0x%lx\n", guest_test_mem);
257 host_bmap_track = bitmap_alloc(TEST_MEM_PAGES);
258 272
259 vm = vm_create_default(VCPU_ID, TEST_MEM_PAGES, guest_code); 273 bmap = bitmap_alloc(host_num_pages);
274 host_bmap_track = bitmap_alloc(host_num_pages);
275
276 vm = create_vm(mode, VCPU_ID, guest_num_pages, guest_code);
260 277
261 /* Add an extra memory slot for testing dirty logging */ 278 /* Add an extra memory slot for testing dirty logging */
262 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 279 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
263 TEST_MEM_OFFSET, 280 guest_test_mem,
264 TEST_MEM_SLOT_INDEX, 281 TEST_MEM_SLOT_INDEX,
265 TEST_MEM_PAGES, 282 guest_num_pages,
266 KVM_MEM_LOG_DIRTY_PAGES); 283 KVM_MEM_LOG_DIRTY_PAGES);
267 /* Cache the HVA pointer of the region */
268 host_test_mem = addr_gpa2hva(vm, (vm_paddr_t)TEST_MEM_OFFSET);
269 284
270 /* Do 1:1 mapping for the dirty track memory slot */ 285 /* Do 1:1 mapping for the dirty track memory slot */
271 virt_map(vm, TEST_MEM_OFFSET, TEST_MEM_OFFSET, 286 virt_map(vm, guest_test_mem, guest_test_mem,
272 TEST_MEM_PAGES * getpagesize(), 0); 287 guest_num_pages * guest_page_size, 0);
288
289 /* Cache the HVA pointer of the region */
290 host_test_mem = addr_gpa2hva(vm, (vm_paddr_t)guest_test_mem);
273 291
292#ifdef __x86_64__
274 vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); 293 vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
294#endif
295#ifdef __aarch64__
296 ucall_init(vm, UCALL_MMIO, NULL);
297#endif
275 298
276 /* Tell the guest about the page size on the system */ 299 /* Export the shared variables to the guest */
277 psize = addr_gva2hva(vm, (vm_vaddr_t)&guest_page_size); 300 sync_global_to_guest(vm, host_page_size);
278 *psize = getpagesize(); 301 sync_global_to_guest(vm, guest_page_size);
302 sync_global_to_guest(vm, guest_test_mem);
303 sync_global_to_guest(vm, guest_num_pages);
279 304
280 /* Start the iterations */ 305 /* Start the iterations */
281 iteration = addr_gva2hva(vm, (vm_vaddr_t)&guest_iteration); 306 iteration = 1;
282 *iteration = 1; 307 sync_global_to_guest(vm, iteration);
308 host_quit = false;
309 host_dirty_count = 0;
310 host_clear_count = 0;
311 host_track_next_count = 0;
283 312
284 /* Start dirtying pages */
285 pthread_create(&vcpu_thread, NULL, vcpu_worker, vm); 313 pthread_create(&vcpu_thread, NULL, vcpu_worker, vm);
286 314
287 while (*iteration < iterations) { 315 while (iteration < iterations) {
288 /* Give the vcpu thread some time to dirty some pages */ 316 /* Give the vcpu thread some time to dirty some pages */
289 usleep(interval * 1000); 317 usleep(interval * 1000);
290 kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap); 318 kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
291 vm_dirty_log_verify(bmap, *iteration); 319 vm_dirty_log_verify(bmap);
292 (*iteration)++; 320 iteration++;
321 sync_global_to_guest(vm, iteration);
293 } 322 }
294 323
295 /* Tell the vcpu thread to quit */ 324 /* Tell the vcpu thread to quit */
@@ -302,7 +331,118 @@ int main(int argc, char *argv[])
302 331
303 free(bmap); 332 free(bmap);
304 free(host_bmap_track); 333 free(host_bmap_track);
334 ucall_uninit(vm);
305 kvm_vm_free(vm); 335 kvm_vm_free(vm);
336}
337
338static struct vm_guest_modes {
339 enum vm_guest_mode mode;
340 bool supported;
341 bool enabled;
342} vm_guest_modes[NUM_VM_MODES] = {
343#if defined(__x86_64__)
344 { VM_MODE_P52V48_4K, 1, 1, },
345 { VM_MODE_P52V48_64K, 0, 0, },
346 { VM_MODE_P40V48_4K, 0, 0, },
347 { VM_MODE_P40V48_64K, 0, 0, },
348#elif defined(__aarch64__)
349 { VM_MODE_P52V48_4K, 0, 0, },
350 { VM_MODE_P52V48_64K, 0, 0, },
351 { VM_MODE_P40V48_4K, 1, 1, },
352 { VM_MODE_P40V48_64K, 1, 1, },
353#endif
354};
355
356static void help(char *name)
357{
358 int i;
359
360 puts("");
361 printf("usage: %s [-h] [-i iterations] [-I interval] "
362 "[-o offset] [-t] [-m mode]\n", name);
363 puts("");
364 printf(" -i: specify iteration counts (default: %"PRIu64")\n",
365 TEST_HOST_LOOP_N);
366 printf(" -I: specify interval in ms (default: %"PRIu64" ms)\n",
367 TEST_HOST_LOOP_INTERVAL);
368 printf(" -o: guest test memory offset (default: 0x%lx)\n",
369 DEFAULT_GUEST_TEST_MEM);
370 printf(" -t: map guest test memory at the top of the allowed "
371 "physical address range\n");
372 printf(" -m: specify the guest mode ID to test "
373 "(default: test all supported modes)\n"
374 " This option may be used multiple times.\n"
375 " Guest mode IDs:\n");
376 for (i = 0; i < NUM_VM_MODES; ++i) {
377 printf(" %d: %s%s\n",
378 vm_guest_modes[i].mode,
379 vm_guest_mode_string(vm_guest_modes[i].mode),
380 vm_guest_modes[i].supported ? " (supported)" : "");
381 }
382 puts("");
383 exit(0);
384}
385
386int main(int argc, char *argv[])
387{
388 unsigned long iterations = TEST_HOST_LOOP_N;
389 unsigned long interval = TEST_HOST_LOOP_INTERVAL;
390 bool mode_selected = false;
391 bool top_offset = false;
392 unsigned int mode;
393 int opt, i;
394
395 while ((opt = getopt(argc, argv, "hi:I:o:tm:")) != -1) {
396 switch (opt) {
397 case 'i':
398 iterations = strtol(optarg, NULL, 10);
399 break;
400 case 'I':
401 interval = strtol(optarg, NULL, 10);
402 break;
403 case 'o':
404 guest_test_mem = strtoull(optarg, NULL, 0);
405 break;
406 case 't':
407 top_offset = true;
408 break;
409 case 'm':
410 if (!mode_selected) {
411 for (i = 0; i < NUM_VM_MODES; ++i)
412 vm_guest_modes[i].enabled = 0;
413 mode_selected = true;
414 }
415 mode = strtoul(optarg, NULL, 10);
416 TEST_ASSERT(mode < NUM_VM_MODES,
417 "Guest mode ID %d too big", mode);
418 vm_guest_modes[mode].enabled = 1;
419 break;
420 case 'h':
421 default:
422 help(argv[0]);
423 break;
424 }
425 }
426
427 TEST_ASSERT(iterations > 2, "Iterations must be greater than two");
428 TEST_ASSERT(interval > 0, "Interval must be greater than zero");
429 TEST_ASSERT(!top_offset || guest_test_mem == DEFAULT_GUEST_TEST_MEM,
430 "Cannot use both -o [offset] and -t at the same time");
431
432 DEBUG("Test iterations: %"PRIu64", interval: %"PRIu64" (ms)\n",
433 iterations, interval);
434
435 srandom(time(0));
436
437 for (i = 0; i < NUM_VM_MODES; ++i) {
438 if (!vm_guest_modes[i].enabled)
439 continue;
440 TEST_ASSERT(vm_guest_modes[i].supported,
441 "Guest mode ID %d (%s) not supported.",
442 vm_guest_modes[i].mode,
443 vm_guest_mode_string(vm_guest_modes[i].mode));
444 run_test(vm_guest_modes[i].mode, iterations, interval, top_offset);
445 }
306 446
307 return 0; 447 return 0;
308} 448}
diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h
new file mode 100644
index 000000000000..9ef2ab1a0c08
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/aarch64/processor.h
@@ -0,0 +1,55 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * AArch64 processor specific defines
4 *
5 * Copyright (C) 2018, Red Hat, Inc.
6 */
7#ifndef SELFTEST_KVM_PROCESSOR_H
8#define SELFTEST_KVM_PROCESSOR_H
9
10#include "kvm_util.h"
11
12
13#define ARM64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
14 KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
15
16#define CPACR_EL1 3, 0, 1, 0, 2
17#define TCR_EL1 3, 0, 2, 0, 2
18#define MAIR_EL1 3, 0, 10, 2, 0
19#define TTBR0_EL1 3, 0, 2, 0, 0
20#define SCTLR_EL1 3, 0, 1, 0, 0
21
22/*
23 * Default MAIR
24 * index attribute
25 * DEVICE_nGnRnE 0 0000:0000
26 * DEVICE_nGnRE 1 0000:0100
27 * DEVICE_GRE 2 0000:1100
28 * NORMAL_NC 3 0100:0100
29 * NORMAL 4 1111:1111
30 * NORMAL_WT 5 1011:1011
31 */
32#define DEFAULT_MAIR_EL1 ((0x00ul << (0 * 8)) | \
33 (0x04ul << (1 * 8)) | \
34 (0x0cul << (2 * 8)) | \
35 (0x44ul << (3 * 8)) | \
36 (0xfful << (4 * 8)) | \
37 (0xbbul << (5 * 8)))
38
39static inline void get_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t id, uint64_t *addr)
40{
41 struct kvm_one_reg reg;
42 reg.id = id;
43 reg.addr = (uint64_t)addr;
44 vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, &reg);
45}
46
47static inline void set_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t id, uint64_t val)
48{
49 struct kvm_one_reg reg;
50 reg.id = id;
51 reg.addr = (uint64_t)&val;
52 vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, &reg);
53}
54
55#endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/include/evmcs.h b/tools/testing/selftests/kvm/include/evmcs.h
new file mode 100644
index 000000000000..4059014d93ea
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/evmcs.h
@@ -0,0 +1,1098 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * tools/testing/selftests/kvm/include/vmx.h
4 *
5 * Copyright (C) 2018, Red Hat, Inc.
6 *
7 */
8
9#ifndef SELFTEST_KVM_EVMCS_H
10#define SELFTEST_KVM_EVMCS_H
11
12#include <stdint.h>
13#include "vmx.h"
14
15#define u16 uint16_t
16#define u32 uint32_t
17#define u64 uint64_t
18
19extern bool enable_evmcs;
20
21struct hv_vp_assist_page {
22 __u32 apic_assist;
23 __u32 reserved;
24 __u64 vtl_control[2];
25 __u64 nested_enlightenments_control[2];
26 __u32 enlighten_vmentry;
27 __u64 current_nested_vmcs;
28};
29
30struct hv_enlightened_vmcs {
31 u32 revision_id;
32 u32 abort;
33
34 u16 host_es_selector;
35 u16 host_cs_selector;
36 u16 host_ss_selector;
37 u16 host_ds_selector;
38 u16 host_fs_selector;
39 u16 host_gs_selector;
40 u16 host_tr_selector;
41
42 u64 host_ia32_pat;
43 u64 host_ia32_efer;
44
45 u64 host_cr0;
46 u64 host_cr3;
47 u64 host_cr4;
48
49 u64 host_ia32_sysenter_esp;
50 u64 host_ia32_sysenter_eip;
51 u64 host_rip;
52 u32 host_ia32_sysenter_cs;
53
54 u32 pin_based_vm_exec_control;
55 u32 vm_exit_controls;
56 u32 secondary_vm_exec_control;
57
58 u64 io_bitmap_a;
59 u64 io_bitmap_b;
60 u64 msr_bitmap;
61
62 u16 guest_es_selector;
63 u16 guest_cs_selector;
64 u16 guest_ss_selector;
65 u16 guest_ds_selector;
66 u16 guest_fs_selector;
67 u16 guest_gs_selector;
68 u16 guest_ldtr_selector;
69 u16 guest_tr_selector;
70
71 u32 guest_es_limit;
72 u32 guest_cs_limit;
73 u32 guest_ss_limit;
74 u32 guest_ds_limit;
75 u32 guest_fs_limit;
76 u32 guest_gs_limit;
77 u32 guest_ldtr_limit;
78 u32 guest_tr_limit;
79 u32 guest_gdtr_limit;
80 u32 guest_idtr_limit;
81
82 u32 guest_es_ar_bytes;
83 u32 guest_cs_ar_bytes;
84 u32 guest_ss_ar_bytes;
85 u32 guest_ds_ar_bytes;
86 u32 guest_fs_ar_bytes;
87 u32 guest_gs_ar_bytes;
88 u32 guest_ldtr_ar_bytes;
89 u32 guest_tr_ar_bytes;
90
91 u64 guest_es_base;
92 u64 guest_cs_base;
93 u64 guest_ss_base;
94 u64 guest_ds_base;
95 u64 guest_fs_base;
96 u64 guest_gs_base;
97 u64 guest_ldtr_base;
98 u64 guest_tr_base;
99 u64 guest_gdtr_base;
100 u64 guest_idtr_base;
101
102 u64 padding64_1[3];
103
104 u64 vm_exit_msr_store_addr;
105 u64 vm_exit_msr_load_addr;
106 u64 vm_entry_msr_load_addr;
107
108 u64 cr3_target_value0;
109 u64 cr3_target_value1;
110 u64 cr3_target_value2;
111 u64 cr3_target_value3;
112
113 u32 page_fault_error_code_mask;
114 u32 page_fault_error_code_match;
115
116 u32 cr3_target_count;
117 u32 vm_exit_msr_store_count;
118 u32 vm_exit_msr_load_count;
119 u32 vm_entry_msr_load_count;
120
121 u64 tsc_offset;
122 u64 virtual_apic_page_addr;
123 u64 vmcs_link_pointer;
124
125 u64 guest_ia32_debugctl;
126 u64 guest_ia32_pat;
127 u64 guest_ia32_efer;
128
129 u64 guest_pdptr0;
130 u64 guest_pdptr1;
131 u64 guest_pdptr2;
132 u64 guest_pdptr3;
133
134 u64 guest_pending_dbg_exceptions;
135 u64 guest_sysenter_esp;
136 u64 guest_sysenter_eip;
137
138 u32 guest_activity_state;
139 u32 guest_sysenter_cs;
140
141 u64 cr0_guest_host_mask;
142 u64 cr4_guest_host_mask;
143 u64 cr0_read_shadow;
144 u64 cr4_read_shadow;
145 u64 guest_cr0;
146 u64 guest_cr3;
147 u64 guest_cr4;
148 u64 guest_dr7;
149
150 u64 host_fs_base;
151 u64 host_gs_base;
152 u64 host_tr_base;
153 u64 host_gdtr_base;
154 u64 host_idtr_base;
155 u64 host_rsp;
156
157 u64 ept_pointer;
158
159 u16 virtual_processor_id;
160 u16 padding16[3];
161
162 u64 padding64_2[5];
163 u64 guest_physical_address;
164
165 u32 vm_instruction_error;
166 u32 vm_exit_reason;
167 u32 vm_exit_intr_info;
168 u32 vm_exit_intr_error_code;
169 u32 idt_vectoring_info_field;
170 u32 idt_vectoring_error_code;
171 u32 vm_exit_instruction_len;
172 u32 vmx_instruction_info;
173
174 u64 exit_qualification;
175 u64 exit_io_instruction_ecx;
176 u64 exit_io_instruction_esi;
177 u64 exit_io_instruction_edi;
178 u64 exit_io_instruction_eip;
179
180 u64 guest_linear_address;
181 u64 guest_rsp;
182 u64 guest_rflags;
183
184 u32 guest_interruptibility_info;
185 u32 cpu_based_vm_exec_control;
186 u32 exception_bitmap;
187 u32 vm_entry_controls;
188 u32 vm_entry_intr_info_field;
189 u32 vm_entry_exception_error_code;
190 u32 vm_entry_instruction_len;
191 u32 tpr_threshold;
192
193 u64 guest_rip;
194
195 u32 hv_clean_fields;
196 u32 hv_padding_32;
197 u32 hv_synthetic_controls;
198 struct {
199 u32 nested_flush_hypercall:1;
200 u32 msr_bitmap:1;
201 u32 reserved:30;
202 } hv_enlightenments_control;
203 u32 hv_vp_id;
204
205 u64 hv_vm_id;
206 u64 partition_assist_page;
207 u64 padding64_4[4];
208 u64 guest_bndcfgs;
209 u64 padding64_5[7];
210 u64 xss_exit_bitmap;
211 u64 padding64_6[7];
212};
213
214#define HV_X64_MSR_VP_ASSIST_PAGE 0x40000073
215#define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE 0x00000001
216#define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT 12
217#define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK \
218 (~((1ull << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
219
220struct hv_enlightened_vmcs *current_evmcs;
221struct hv_vp_assist_page *current_vp_assist;
222
223static inline int enable_vp_assist(uint64_t vp_assist_pa, void *vp_assist)
224{
225 u64 val = (vp_assist_pa & HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK) |
226 HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
227
228 wrmsr(HV_X64_MSR_VP_ASSIST_PAGE, val);
229
230 current_vp_assist = vp_assist;
231
232 enable_evmcs = true;
233
234 return 0;
235}
236
237static inline int evmcs_vmptrld(uint64_t vmcs_pa, void *vmcs)
238{
239 current_vp_assist->current_nested_vmcs = vmcs_pa;
240 current_vp_assist->enlighten_vmentry = 1;
241
242 current_evmcs = vmcs;
243
244 return 0;
245}
246
247static inline int evmcs_vmptrst(uint64_t *value)
248{
249 *value = current_vp_assist->current_nested_vmcs &
250 ~HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
251
252 return 0;
253}
254
255static inline int evmcs_vmread(uint64_t encoding, uint64_t *value)
256{
257 switch (encoding) {
258 case GUEST_RIP:
259 *value = current_evmcs->guest_rip;
260 break;
261 case GUEST_RSP:
262 *value = current_evmcs->guest_rsp;
263 break;
264 case GUEST_RFLAGS:
265 *value = current_evmcs->guest_rflags;
266 break;
267 case HOST_IA32_PAT:
268 *value = current_evmcs->host_ia32_pat;
269 break;
270 case HOST_IA32_EFER:
271 *value = current_evmcs->host_ia32_efer;
272 break;
273 case HOST_CR0:
274 *value = current_evmcs->host_cr0;
275 break;
276 case HOST_CR3:
277 *value = current_evmcs->host_cr3;
278 break;
279 case HOST_CR4:
280 *value = current_evmcs->host_cr4;
281 break;
282 case HOST_IA32_SYSENTER_ESP:
283 *value = current_evmcs->host_ia32_sysenter_esp;
284 break;
285 case HOST_IA32_SYSENTER_EIP:
286 *value = current_evmcs->host_ia32_sysenter_eip;
287 break;
288 case HOST_RIP:
289 *value = current_evmcs->host_rip;
290 break;
291 case IO_BITMAP_A:
292 *value = current_evmcs->io_bitmap_a;
293 break;
294 case IO_BITMAP_B:
295 *value = current_evmcs->io_bitmap_b;
296 break;
297 case MSR_BITMAP:
298 *value = current_evmcs->msr_bitmap;
299 break;
300 case GUEST_ES_BASE:
301 *value = current_evmcs->guest_es_base;
302 break;
303 case GUEST_CS_BASE:
304 *value = current_evmcs->guest_cs_base;
305 break;
306 case GUEST_SS_BASE:
307 *value = current_evmcs->guest_ss_base;
308 break;
309 case GUEST_DS_BASE:
310 *value = current_evmcs->guest_ds_base;
311 break;
312 case GUEST_FS_BASE:
313 *value = current_evmcs->guest_fs_base;
314 break;
315 case GUEST_GS_BASE:
316 *value = current_evmcs->guest_gs_base;
317 break;
318 case GUEST_LDTR_BASE:
319 *value = current_evmcs->guest_ldtr_base;
320 break;
321 case GUEST_TR_BASE:
322 *value = current_evmcs->guest_tr_base;
323 break;
324 case GUEST_GDTR_BASE:
325 *value = current_evmcs->guest_gdtr_base;
326 break;
327 case GUEST_IDTR_BASE:
328 *value = current_evmcs->guest_idtr_base;
329 break;
330 case TSC_OFFSET:
331 *value = current_evmcs->tsc_offset;
332 break;
333 case VIRTUAL_APIC_PAGE_ADDR:
334 *value = current_evmcs->virtual_apic_page_addr;
335 break;
336 case VMCS_LINK_POINTER:
337 *value = current_evmcs->vmcs_link_pointer;
338 break;
339 case GUEST_IA32_DEBUGCTL:
340 *value = current_evmcs->guest_ia32_debugctl;
341 break;
342 case GUEST_IA32_PAT:
343 *value = current_evmcs->guest_ia32_pat;
344 break;
345 case GUEST_IA32_EFER:
346 *value = current_evmcs->guest_ia32_efer;
347 break;
348 case GUEST_PDPTR0:
349 *value = current_evmcs->guest_pdptr0;
350 break;
351 case GUEST_PDPTR1:
352 *value = current_evmcs->guest_pdptr1;
353 break;
354 case GUEST_PDPTR2:
355 *value = current_evmcs->guest_pdptr2;
356 break;
357 case GUEST_PDPTR3:
358 *value = current_evmcs->guest_pdptr3;
359 break;
360 case GUEST_PENDING_DBG_EXCEPTIONS:
361 *value = current_evmcs->guest_pending_dbg_exceptions;
362 break;
363 case GUEST_SYSENTER_ESP:
364 *value = current_evmcs->guest_sysenter_esp;
365 break;
366 case GUEST_SYSENTER_EIP:
367 *value = current_evmcs->guest_sysenter_eip;
368 break;
369 case CR0_GUEST_HOST_MASK:
370 *value = current_evmcs->cr0_guest_host_mask;
371 break;
372 case CR4_GUEST_HOST_MASK:
373 *value = current_evmcs->cr4_guest_host_mask;
374 break;
375 case CR0_READ_SHADOW:
376 *value = current_evmcs->cr0_read_shadow;
377 break;
378 case CR4_READ_SHADOW:
379 *value = current_evmcs->cr4_read_shadow;
380 break;
381 case GUEST_CR0:
382 *value = current_evmcs->guest_cr0;
383 break;
384 case GUEST_CR3:
385 *value = current_evmcs->guest_cr3;
386 break;
387 case GUEST_CR4:
388 *value = current_evmcs->guest_cr4;
389 break;
390 case GUEST_DR7:
391 *value = current_evmcs->guest_dr7;
392 break;
393 case HOST_FS_BASE:
394 *value = current_evmcs->host_fs_base;
395 break;
396 case HOST_GS_BASE:
397 *value = current_evmcs->host_gs_base;
398 break;
399 case HOST_TR_BASE:
400 *value = current_evmcs->host_tr_base;
401 break;
402 case HOST_GDTR_BASE:
403 *value = current_evmcs->host_gdtr_base;
404 break;
405 case HOST_IDTR_BASE:
406 *value = current_evmcs->host_idtr_base;
407 break;
408 case HOST_RSP:
409 *value = current_evmcs->host_rsp;
410 break;
411 case EPT_POINTER:
412 *value = current_evmcs->ept_pointer;
413 break;
414 case GUEST_BNDCFGS:
415 *value = current_evmcs->guest_bndcfgs;
416 break;
417 case XSS_EXIT_BITMAP:
418 *value = current_evmcs->xss_exit_bitmap;
419 break;
420 case GUEST_PHYSICAL_ADDRESS:
421 *value = current_evmcs->guest_physical_address;
422 break;
423 case EXIT_QUALIFICATION:
424 *value = current_evmcs->exit_qualification;
425 break;
426 case GUEST_LINEAR_ADDRESS:
427 *value = current_evmcs->guest_linear_address;
428 break;
429 case VM_EXIT_MSR_STORE_ADDR:
430 *value = current_evmcs->vm_exit_msr_store_addr;
431 break;
432 case VM_EXIT_MSR_LOAD_ADDR:
433 *value = current_evmcs->vm_exit_msr_load_addr;
434 break;
435 case VM_ENTRY_MSR_LOAD_ADDR:
436 *value = current_evmcs->vm_entry_msr_load_addr;
437 break;
438 case CR3_TARGET_VALUE0:
439 *value = current_evmcs->cr3_target_value0;
440 break;
441 case CR3_TARGET_VALUE1:
442 *value = current_evmcs->cr3_target_value1;
443 break;
444 case CR3_TARGET_VALUE2:
445 *value = current_evmcs->cr3_target_value2;
446 break;
447 case CR3_TARGET_VALUE3:
448 *value = current_evmcs->cr3_target_value3;
449 break;
450 case TPR_THRESHOLD:
451 *value = current_evmcs->tpr_threshold;
452 break;
453 case GUEST_INTERRUPTIBILITY_INFO:
454 *value = current_evmcs->guest_interruptibility_info;
455 break;
456 case CPU_BASED_VM_EXEC_CONTROL:
457 *value = current_evmcs->cpu_based_vm_exec_control;
458 break;
459 case EXCEPTION_BITMAP:
460 *value = current_evmcs->exception_bitmap;
461 break;
462 case VM_ENTRY_CONTROLS:
463 *value = current_evmcs->vm_entry_controls;
464 break;
465 case VM_ENTRY_INTR_INFO_FIELD:
466 *value = current_evmcs->vm_entry_intr_info_field;
467 break;
468 case VM_ENTRY_EXCEPTION_ERROR_CODE:
469 *value = current_evmcs->vm_entry_exception_error_code;
470 break;
471 case VM_ENTRY_INSTRUCTION_LEN:
472 *value = current_evmcs->vm_entry_instruction_len;
473 break;
474 case HOST_IA32_SYSENTER_CS:
475 *value = current_evmcs->host_ia32_sysenter_cs;
476 break;
477 case PIN_BASED_VM_EXEC_CONTROL:
478 *value = current_evmcs->pin_based_vm_exec_control;
479 break;
480 case VM_EXIT_CONTROLS:
481 *value = current_evmcs->vm_exit_controls;
482 break;
483 case SECONDARY_VM_EXEC_CONTROL:
484 *value = current_evmcs->secondary_vm_exec_control;
485 break;
486 case GUEST_ES_LIMIT:
487 *value = current_evmcs->guest_es_limit;
488 break;
489 case GUEST_CS_LIMIT:
490 *value = current_evmcs->guest_cs_limit;
491 break;
492 case GUEST_SS_LIMIT:
493 *value = current_evmcs->guest_ss_limit;
494 break;
495 case GUEST_DS_LIMIT:
496 *value = current_evmcs->guest_ds_limit;
497 break;
498 case GUEST_FS_LIMIT:
499 *value = current_evmcs->guest_fs_limit;
500 break;
501 case GUEST_GS_LIMIT:
502 *value = current_evmcs->guest_gs_limit;
503 break;
504 case GUEST_LDTR_LIMIT:
505 *value = current_evmcs->guest_ldtr_limit;
506 break;
507 case GUEST_TR_LIMIT:
508 *value = current_evmcs->guest_tr_limit;
509 break;
510 case GUEST_GDTR_LIMIT:
511 *value = current_evmcs->guest_gdtr_limit;
512 break;
513 case GUEST_IDTR_LIMIT:
514 *value = current_evmcs->guest_idtr_limit;
515 break;
516 case GUEST_ES_AR_BYTES:
517 *value = current_evmcs->guest_es_ar_bytes;
518 break;
519 case GUEST_CS_AR_BYTES:
520 *value = current_evmcs->guest_cs_ar_bytes;
521 break;
522 case GUEST_SS_AR_BYTES:
523 *value = current_evmcs->guest_ss_ar_bytes;
524 break;
525 case GUEST_DS_AR_BYTES:
526 *value = current_evmcs->guest_ds_ar_bytes;
527 break;
528 case GUEST_FS_AR_BYTES:
529 *value = current_evmcs->guest_fs_ar_bytes;
530 break;
531 case GUEST_GS_AR_BYTES:
532 *value = current_evmcs->guest_gs_ar_bytes;
533 break;
534 case GUEST_LDTR_AR_BYTES:
535 *value = current_evmcs->guest_ldtr_ar_bytes;
536 break;
537 case GUEST_TR_AR_BYTES:
538 *value = current_evmcs->guest_tr_ar_bytes;
539 break;
540 case GUEST_ACTIVITY_STATE:
541 *value = current_evmcs->guest_activity_state;
542 break;
543 case GUEST_SYSENTER_CS:
544 *value = current_evmcs->guest_sysenter_cs;
545 break;
546 case VM_INSTRUCTION_ERROR:
547 *value = current_evmcs->vm_instruction_error;
548 break;
549 case VM_EXIT_REASON:
550 *value = current_evmcs->vm_exit_reason;
551 break;
552 case VM_EXIT_INTR_INFO:
553 *value = current_evmcs->vm_exit_intr_info;
554 break;
555 case VM_EXIT_INTR_ERROR_CODE:
556 *value = current_evmcs->vm_exit_intr_error_code;
557 break;
558 case IDT_VECTORING_INFO_FIELD:
559 *value = current_evmcs->idt_vectoring_info_field;
560 break;
561 case IDT_VECTORING_ERROR_CODE:
562 *value = current_evmcs->idt_vectoring_error_code;
563 break;
564 case VM_EXIT_INSTRUCTION_LEN:
565 *value = current_evmcs->vm_exit_instruction_len;
566 break;
567 case VMX_INSTRUCTION_INFO:
568 *value = current_evmcs->vmx_instruction_info;
569 break;
570 case PAGE_FAULT_ERROR_CODE_MASK:
571 *value = current_evmcs->page_fault_error_code_mask;
572 break;
573 case PAGE_FAULT_ERROR_CODE_MATCH:
574 *value = current_evmcs->page_fault_error_code_match;
575 break;
576 case CR3_TARGET_COUNT:
577 *value = current_evmcs->cr3_target_count;
578 break;
579 case VM_EXIT_MSR_STORE_COUNT:
580 *value = current_evmcs->vm_exit_msr_store_count;
581 break;
582 case VM_EXIT_MSR_LOAD_COUNT:
583 *value = current_evmcs->vm_exit_msr_load_count;
584 break;
585 case VM_ENTRY_MSR_LOAD_COUNT:
586 *value = current_evmcs->vm_entry_msr_load_count;
587 break;
588 case HOST_ES_SELECTOR:
589 *value = current_evmcs->host_es_selector;
590 break;
591 case HOST_CS_SELECTOR:
592 *value = current_evmcs->host_cs_selector;
593 break;
594 case HOST_SS_SELECTOR:
595 *value = current_evmcs->host_ss_selector;
596 break;
597 case HOST_DS_SELECTOR:
598 *value = current_evmcs->host_ds_selector;
599 break;
600 case HOST_FS_SELECTOR:
601 *value = current_evmcs->host_fs_selector;
602 break;
603 case HOST_GS_SELECTOR:
604 *value = current_evmcs->host_gs_selector;
605 break;
606 case HOST_TR_SELECTOR:
607 *value = current_evmcs->host_tr_selector;
608 break;
609 case GUEST_ES_SELECTOR:
610 *value = current_evmcs->guest_es_selector;
611 break;
612 case GUEST_CS_SELECTOR:
613 *value = current_evmcs->guest_cs_selector;
614 break;
615 case GUEST_SS_SELECTOR:
616 *value = current_evmcs->guest_ss_selector;
617 break;
618 case GUEST_DS_SELECTOR:
619 *value = current_evmcs->guest_ds_selector;
620 break;
621 case GUEST_FS_SELECTOR:
622 *value = current_evmcs->guest_fs_selector;
623 break;
624 case GUEST_GS_SELECTOR:
625 *value = current_evmcs->guest_gs_selector;
626 break;
627 case GUEST_LDTR_SELECTOR:
628 *value = current_evmcs->guest_ldtr_selector;
629 break;
630 case GUEST_TR_SELECTOR:
631 *value = current_evmcs->guest_tr_selector;
632 break;
633 case VIRTUAL_PROCESSOR_ID:
634 *value = current_evmcs->virtual_processor_id;
635 break;
636 default: return 1;
637 }
638
639 return 0;
640}
641
642static inline int evmcs_vmwrite(uint64_t encoding, uint64_t value)
643{
644 switch (encoding) {
645 case GUEST_RIP:
646 current_evmcs->guest_rip = value;
647 break;
648 case GUEST_RSP:
649 current_evmcs->guest_rsp = value;
650 break;
651 case GUEST_RFLAGS:
652 current_evmcs->guest_rflags = value;
653 break;
654 case HOST_IA32_PAT:
655 current_evmcs->host_ia32_pat = value;
656 break;
657 case HOST_IA32_EFER:
658 current_evmcs->host_ia32_efer = value;
659 break;
660 case HOST_CR0:
661 current_evmcs->host_cr0 = value;
662 break;
663 case HOST_CR3:
664 current_evmcs->host_cr3 = value;
665 break;
666 case HOST_CR4:
667 current_evmcs->host_cr4 = value;
668 break;
669 case HOST_IA32_SYSENTER_ESP:
670 current_evmcs->host_ia32_sysenter_esp = value;
671 break;
672 case HOST_IA32_SYSENTER_EIP:
673 current_evmcs->host_ia32_sysenter_eip = value;
674 break;
675 case HOST_RIP:
676 current_evmcs->host_rip = value;
677 break;
678 case IO_BITMAP_A:
679 current_evmcs->io_bitmap_a = value;
680 break;
681 case IO_BITMAP_B:
682 current_evmcs->io_bitmap_b = value;
683 break;
684 case MSR_BITMAP:
685 current_evmcs->msr_bitmap = value;
686 break;
687 case GUEST_ES_BASE:
688 current_evmcs->guest_es_base = value;
689 break;
690 case GUEST_CS_BASE:
691 current_evmcs->guest_cs_base = value;
692 break;
693 case GUEST_SS_BASE:
694 current_evmcs->guest_ss_base = value;
695 break;
696 case GUEST_DS_BASE:
697 current_evmcs->guest_ds_base = value;
698 break;
699 case GUEST_FS_BASE:
700 current_evmcs->guest_fs_base = value;
701 break;
702 case GUEST_GS_BASE:
703 current_evmcs->guest_gs_base = value;
704 break;
705 case GUEST_LDTR_BASE:
706 current_evmcs->guest_ldtr_base = value;
707 break;
708 case GUEST_TR_BASE:
709 current_evmcs->guest_tr_base = value;
710 break;
711 case GUEST_GDTR_BASE:
712 current_evmcs->guest_gdtr_base = value;
713 break;
714 case GUEST_IDTR_BASE:
715 current_evmcs->guest_idtr_base = value;
716 break;
717 case TSC_OFFSET:
718 current_evmcs->tsc_offset = value;
719 break;
720 case VIRTUAL_APIC_PAGE_ADDR:
721 current_evmcs->virtual_apic_page_addr = value;
722 break;
723 case VMCS_LINK_POINTER:
724 current_evmcs->vmcs_link_pointer = value;
725 break;
726 case GUEST_IA32_DEBUGCTL:
727 current_evmcs->guest_ia32_debugctl = value;
728 break;
729 case GUEST_IA32_PAT:
730 current_evmcs->guest_ia32_pat = value;
731 break;
732 case GUEST_IA32_EFER:
733 current_evmcs->guest_ia32_efer = value;
734 break;
735 case GUEST_PDPTR0:
736 current_evmcs->guest_pdptr0 = value;
737 break;
738 case GUEST_PDPTR1:
739 current_evmcs->guest_pdptr1 = value;
740 break;
741 case GUEST_PDPTR2:
742 current_evmcs->guest_pdptr2 = value;
743 break;
744 case GUEST_PDPTR3:
745 current_evmcs->guest_pdptr3 = value;
746 break;
747 case GUEST_PENDING_DBG_EXCEPTIONS:
748 current_evmcs->guest_pending_dbg_exceptions = value;
749 break;
750 case GUEST_SYSENTER_ESP:
751 current_evmcs->guest_sysenter_esp = value;
752 break;
753 case GUEST_SYSENTER_EIP:
754 current_evmcs->guest_sysenter_eip = value;
755 break;
756 case CR0_GUEST_HOST_MASK:
757 current_evmcs->cr0_guest_host_mask = value;
758 break;
759 case CR4_GUEST_HOST_MASK:
760 current_evmcs->cr4_guest_host_mask = value;
761 break;
762 case CR0_READ_SHADOW:
763 current_evmcs->cr0_read_shadow = value;
764 break;
765 case CR4_READ_SHADOW:
766 current_evmcs->cr4_read_shadow = value;
767 break;
768 case GUEST_CR0:
769 current_evmcs->guest_cr0 = value;
770 break;
771 case GUEST_CR3:
772 current_evmcs->guest_cr3 = value;
773 break;
774 case GUEST_CR4:
775 current_evmcs->guest_cr4 = value;
776 break;
777 case GUEST_DR7:
778 current_evmcs->guest_dr7 = value;
779 break;
780 case HOST_FS_BASE:
781 current_evmcs->host_fs_base = value;
782 break;
783 case HOST_GS_BASE:
784 current_evmcs->host_gs_base = value;
785 break;
786 case HOST_TR_BASE:
787 current_evmcs->host_tr_base = value;
788 break;
789 case HOST_GDTR_BASE:
790 current_evmcs->host_gdtr_base = value;
791 break;
792 case HOST_IDTR_BASE:
793 current_evmcs->host_idtr_base = value;
794 break;
795 case HOST_RSP:
796 current_evmcs->host_rsp = value;
797 break;
798 case EPT_POINTER:
799 current_evmcs->ept_pointer = value;
800 break;
801 case GUEST_BNDCFGS:
802 current_evmcs->guest_bndcfgs = value;
803 break;
804 case XSS_EXIT_BITMAP:
805 current_evmcs->xss_exit_bitmap = value;
806 break;
807 case GUEST_PHYSICAL_ADDRESS:
808 current_evmcs->guest_physical_address = value;
809 break;
810 case EXIT_QUALIFICATION:
811 current_evmcs->exit_qualification = value;
812 break;
813 case GUEST_LINEAR_ADDRESS:
814 current_evmcs->guest_linear_address = value;
815 break;
816 case VM_EXIT_MSR_STORE_ADDR:
817 current_evmcs->vm_exit_msr_store_addr = value;
818 break;
819 case VM_EXIT_MSR_LOAD_ADDR:
820 current_evmcs->vm_exit_msr_load_addr = value;
821 break;
822 case VM_ENTRY_MSR_LOAD_ADDR:
823 current_evmcs->vm_entry_msr_load_addr = value;
824 break;
825 case CR3_TARGET_VALUE0:
826 current_evmcs->cr3_target_value0 = value;
827 break;
828 case CR3_TARGET_VALUE1:
829 current_evmcs->cr3_target_value1 = value;
830 break;
831 case CR3_TARGET_VALUE2:
832 current_evmcs->cr3_target_value2 = value;
833 break;
834 case CR3_TARGET_VALUE3:
835 current_evmcs->cr3_target_value3 = value;
836 break;
837 case TPR_THRESHOLD:
838 current_evmcs->tpr_threshold = value;
839 break;
840 case GUEST_INTERRUPTIBILITY_INFO:
841 current_evmcs->guest_interruptibility_info = value;
842 break;
843 case CPU_BASED_VM_EXEC_CONTROL:
844 current_evmcs->cpu_based_vm_exec_control = value;
845 break;
846 case EXCEPTION_BITMAP:
847 current_evmcs->exception_bitmap = value;
848 break;
849 case VM_ENTRY_CONTROLS:
850 current_evmcs->vm_entry_controls = value;
851 break;
852 case VM_ENTRY_INTR_INFO_FIELD:
853 current_evmcs->vm_entry_intr_info_field = value;
854 break;
855 case VM_ENTRY_EXCEPTION_ERROR_CODE:
856 current_evmcs->vm_entry_exception_error_code = value;
857 break;
858 case VM_ENTRY_INSTRUCTION_LEN:
859 current_evmcs->vm_entry_instruction_len = value;
860 break;
861 case HOST_IA32_SYSENTER_CS:
862 current_evmcs->host_ia32_sysenter_cs = value;
863 break;
864 case PIN_BASED_VM_EXEC_CONTROL:
865 current_evmcs->pin_based_vm_exec_control = value;
866 break;
867 case VM_EXIT_CONTROLS:
868 current_evmcs->vm_exit_controls = value;
869 break;
870 case SECONDARY_VM_EXEC_CONTROL:
871 current_evmcs->secondary_vm_exec_control = value;
872 break;
873 case GUEST_ES_LIMIT:
874 current_evmcs->guest_es_limit = value;
875 break;
876 case GUEST_CS_LIMIT:
877 current_evmcs->guest_cs_limit = value;
878 break;
879 case GUEST_SS_LIMIT:
880 current_evmcs->guest_ss_limit = value;
881 break;
882 case GUEST_DS_LIMIT:
883 current_evmcs->guest_ds_limit = value;
884 break;
885 case GUEST_FS_LIMIT:
886 current_evmcs->guest_fs_limit = value;
887 break;
888 case GUEST_GS_LIMIT:
889 current_evmcs->guest_gs_limit = value;
890 break;
891 case GUEST_LDTR_LIMIT:
892 current_evmcs->guest_ldtr_limit = value;
893 break;
894 case GUEST_TR_LIMIT:
895 current_evmcs->guest_tr_limit = value;
896 break;
897 case GUEST_GDTR_LIMIT:
898 current_evmcs->guest_gdtr_limit = value;
899 break;
900 case GUEST_IDTR_LIMIT:
901 current_evmcs->guest_idtr_limit = value;
902 break;
903 case GUEST_ES_AR_BYTES:
904 current_evmcs->guest_es_ar_bytes = value;
905 break;
906 case GUEST_CS_AR_BYTES:
907 current_evmcs->guest_cs_ar_bytes = value;
908 break;
909 case GUEST_SS_AR_BYTES:
910 current_evmcs->guest_ss_ar_bytes = value;
911 break;
912 case GUEST_DS_AR_BYTES:
913 current_evmcs->guest_ds_ar_bytes = value;
914 break;
915 case GUEST_FS_AR_BYTES:
916 current_evmcs->guest_fs_ar_bytes = value;
917 break;
918 case GUEST_GS_AR_BYTES:
919 current_evmcs->guest_gs_ar_bytes = value;
920 break;
921 case GUEST_LDTR_AR_BYTES:
922 current_evmcs->guest_ldtr_ar_bytes = value;
923 break;
924 case GUEST_TR_AR_BYTES:
925 current_evmcs->guest_tr_ar_bytes = value;
926 break;
927 case GUEST_ACTIVITY_STATE:
928 current_evmcs->guest_activity_state = value;
929 break;
930 case GUEST_SYSENTER_CS:
931 current_evmcs->guest_sysenter_cs = value;
932 break;
933 case VM_INSTRUCTION_ERROR:
934 current_evmcs->vm_instruction_error = value;
935 break;
936 case VM_EXIT_REASON:
937 current_evmcs->vm_exit_reason = value;
938 break;
939 case VM_EXIT_INTR_INFO:
940 current_evmcs->vm_exit_intr_info = value;
941 break;
942 case VM_EXIT_INTR_ERROR_CODE:
943 current_evmcs->vm_exit_intr_error_code = value;
944 break;
945 case IDT_VECTORING_INFO_FIELD:
946 current_evmcs->idt_vectoring_info_field = value;
947 break;
948 case IDT_VECTORING_ERROR_CODE:
949 current_evmcs->idt_vectoring_error_code = value;
950 break;
951 case VM_EXIT_INSTRUCTION_LEN:
952 current_evmcs->vm_exit_instruction_len = value;
953 break;
954 case VMX_INSTRUCTION_INFO:
955 current_evmcs->vmx_instruction_info = value;
956 break;
957 case PAGE_FAULT_ERROR_CODE_MASK:
958 current_evmcs->page_fault_error_code_mask = value;
959 break;
960 case PAGE_FAULT_ERROR_CODE_MATCH:
961 current_evmcs->page_fault_error_code_match = value;
962 break;
963 case CR3_TARGET_COUNT:
964 current_evmcs->cr3_target_count = value;
965 break;
966 case VM_EXIT_MSR_STORE_COUNT:
967 current_evmcs->vm_exit_msr_store_count = value;
968 break;
969 case VM_EXIT_MSR_LOAD_COUNT:
970 current_evmcs->vm_exit_msr_load_count = value;
971 break;
972 case VM_ENTRY_MSR_LOAD_COUNT:
973 current_evmcs->vm_entry_msr_load_count = value;
974 break;
975 case HOST_ES_SELECTOR:
976 current_evmcs->host_es_selector = value;
977 break;
978 case HOST_CS_SELECTOR:
979 current_evmcs->host_cs_selector = value;
980 break;
981 case HOST_SS_SELECTOR:
982 current_evmcs->host_ss_selector = value;
983 break;
984 case HOST_DS_SELECTOR:
985 current_evmcs->host_ds_selector = value;
986 break;
987 case HOST_FS_SELECTOR:
988 current_evmcs->host_fs_selector = value;
989 break;
990 case HOST_GS_SELECTOR:
991 current_evmcs->host_gs_selector = value;
992 break;
993 case HOST_TR_SELECTOR:
994 current_evmcs->host_tr_selector = value;
995 break;
996 case GUEST_ES_SELECTOR:
997 current_evmcs->guest_es_selector = value;
998 break;
999 case GUEST_CS_SELECTOR:
1000 current_evmcs->guest_cs_selector = value;
1001 break;
1002 case GUEST_SS_SELECTOR:
1003 current_evmcs->guest_ss_selector = value;
1004 break;
1005 case GUEST_DS_SELECTOR:
1006 current_evmcs->guest_ds_selector = value;
1007 break;
1008 case GUEST_FS_SELECTOR:
1009 current_evmcs->guest_fs_selector = value;
1010 break;
1011 case GUEST_GS_SELECTOR:
1012 current_evmcs->guest_gs_selector = value;
1013 break;
1014 case GUEST_LDTR_SELECTOR:
1015 current_evmcs->guest_ldtr_selector = value;
1016 break;
1017 case GUEST_TR_SELECTOR:
1018 current_evmcs->guest_tr_selector = value;
1019 break;
1020 case VIRTUAL_PROCESSOR_ID:
1021 current_evmcs->virtual_processor_id = value;
1022 break;
1023 default: return 1;
1024 }
1025
1026 return 0;
1027}
1028
1029static inline int evmcs_vmlaunch(void)
1030{
1031 int ret;
1032
1033 current_evmcs->hv_clean_fields = 0;
1034
1035 __asm__ __volatile__("push %%rbp;"
1036 "push %%rcx;"
1037 "push %%rdx;"
1038 "push %%rsi;"
1039 "push %%rdi;"
1040 "push $0;"
1041 "mov %%rsp, (%[host_rsp]);"
1042 "lea 1f(%%rip), %%rax;"
1043 "mov %%rax, (%[host_rip]);"
1044 "vmlaunch;"
1045 "incq (%%rsp);"
1046 "1: pop %%rax;"
1047 "pop %%rdi;"
1048 "pop %%rsi;"
1049 "pop %%rdx;"
1050 "pop %%rcx;"
1051 "pop %%rbp;"
1052 : [ret]"=&a"(ret)
1053 : [host_rsp]"r"
1054 ((uint64_t)&current_evmcs->host_rsp),
1055 [host_rip]"r"
1056 ((uint64_t)&current_evmcs->host_rip)
1057 : "memory", "cc", "rbx", "r8", "r9", "r10",
1058 "r11", "r12", "r13", "r14", "r15");
1059 return ret;
1060}
1061
1062/*
1063 * No guest state (e.g. GPRs) is established by this vmresume.
1064 */
1065static inline int evmcs_vmresume(void)
1066{
1067 int ret;
1068
1069 current_evmcs->hv_clean_fields = 0;
1070
1071 __asm__ __volatile__("push %%rbp;"
1072 "push %%rcx;"
1073 "push %%rdx;"
1074 "push %%rsi;"
1075 "push %%rdi;"
1076 "push $0;"
1077 "mov %%rsp, (%[host_rsp]);"
1078 "lea 1f(%%rip), %%rax;"
1079 "mov %%rax, (%[host_rip]);"
1080 "vmresume;"
1081 "incq (%%rsp);"
1082 "1: pop %%rax;"
1083 "pop %%rdi;"
1084 "pop %%rsi;"
1085 "pop %%rdx;"
1086 "pop %%rcx;"
1087 "pop %%rbp;"
1088 : [ret]"=&a"(ret)
1089 : [host_rsp]"r"
1090 ((uint64_t)&current_evmcs->host_rsp),
1091 [host_rip]"r"
1092 ((uint64_t)&current_evmcs->host_rip)
1093 : "memory", "cc", "rbx", "r8", "r9", "r10",
1094 "r11", "r12", "r13", "r14", "r15");
1095 return ret;
1096}
1097
1098#endif /* !SELFTEST_KVM_EVMCS_H */
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 3acf9a91704c..a4e59e3b4826 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -7,7 +7,7 @@
7 * 7 *
8 */ 8 */
9#ifndef SELFTEST_KVM_UTIL_H 9#ifndef SELFTEST_KVM_UTIL_H
10#define SELFTEST_KVM_UTIL_H 1 10#define SELFTEST_KVM_UTIL_H
11 11
12#include "test_util.h" 12#include "test_util.h"
13 13
@@ -17,12 +17,6 @@
17 17
18#include "sparsebit.h" 18#include "sparsebit.h"
19 19
20/*
21 * Memslots can't cover the gfn starting at this gpa otherwise vCPUs can't be
22 * created. Only applies to VMs using EPT.
23 */
24#define KVM_DEFAULT_IDENTITY_MAP_ADDRESS 0xfffbc000ul
25
26 20
27/* Callers of kvm_util only have an incomplete/opaque description of the 21/* Callers of kvm_util only have an incomplete/opaque description of the
28 * structure kvm_util is using to maintain the state of a VM. 22 * structure kvm_util is using to maintain the state of a VM.
@@ -33,16 +27,23 @@ typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
33typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ 27typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
34 28
35/* Minimum allocated guest virtual and physical addresses */ 29/* Minimum allocated guest virtual and physical addresses */
36#define KVM_UTIL_MIN_VADDR 0x2000 30#define KVM_UTIL_MIN_VADDR 0x2000
37 31
38#define DEFAULT_GUEST_PHY_PAGES 512 32#define DEFAULT_GUEST_PHY_PAGES 512
39#define DEFAULT_GUEST_STACK_VADDR_MIN 0xab6000 33#define DEFAULT_GUEST_STACK_VADDR_MIN 0xab6000
40#define DEFAULT_STACK_PGS 5 34#define DEFAULT_STACK_PGS 5
41 35
42enum vm_guest_mode { 36enum vm_guest_mode {
43 VM_MODE_FLAT48PG, 37 VM_MODE_P52V48_4K,
38 VM_MODE_P52V48_64K,
39 VM_MODE_P40V48_4K,
40 VM_MODE_P40V48_64K,
41 NUM_VM_MODES,
44}; 42};
45 43
44#define vm_guest_mode_string(m) vm_guest_mode_string[m]
45extern const char * const vm_guest_mode_string[];
46
46enum vm_mem_backing_src_type { 47enum vm_mem_backing_src_type {
47 VM_MEM_SRC_ANONYMOUS, 48 VM_MEM_SRC_ANONYMOUS,
48 VM_MEM_SRC_ANONYMOUS_THP, 49 VM_MEM_SRC_ANONYMOUS_THP,
@@ -58,15 +59,15 @@ void kvm_vm_restart(struct kvm_vm *vmp, int perm);
58void kvm_vm_release(struct kvm_vm *vmp); 59void kvm_vm_release(struct kvm_vm *vmp);
59void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log); 60void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log);
60 61
61int kvm_memcmp_hva_gva(void *hva, 62int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, const vm_vaddr_t gva,
62 struct kvm_vm *vm, const vm_vaddr_t gva, size_t len); 63 size_t len);
63 64
64void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename, 65void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename,
65 uint32_t data_memslot, uint32_t pgd_memslot); 66 uint32_t data_memslot, uint32_t pgd_memslot);
66 67
67void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent); 68void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
68void vcpu_dump(FILE *stream, struct kvm_vm *vm, 69void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid,
69 uint32_t vcpuid, uint8_t indent); 70 uint8_t indent);
70 71
71void vm_create_irqchip(struct kvm_vm *vm); 72void vm_create_irqchip(struct kvm_vm *vm);
72 73
@@ -75,13 +76,14 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
75 uint64_t guest_paddr, uint32_t slot, uint64_t npages, 76 uint64_t guest_paddr, uint32_t slot, uint64_t npages,
76 uint32_t flags); 77 uint32_t flags);
77 78
78void vcpu_ioctl(struct kvm_vm *vm, 79void vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid, unsigned long ioctl,
79 uint32_t vcpuid, unsigned long ioctl, void *arg); 80 void *arg);
80void vm_ioctl(struct kvm_vm *vm, unsigned long ioctl, void *arg); 81void vm_ioctl(struct kvm_vm *vm, unsigned long ioctl, void *arg);
81void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags); 82void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
82void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_memslot); 83void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot,
84 int gdt_memslot);
83vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, 85vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
84 uint32_t data_memslot, uint32_t pgd_memslot); 86 uint32_t data_memslot, uint32_t pgd_memslot);
85void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, 87void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
86 size_t size, uint32_t pgd_memslot); 88 size_t size, uint32_t pgd_memslot);
87void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa); 89void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa);
@@ -93,56 +95,35 @@ struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid);
93void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid); 95void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid);
94int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid); 96int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid);
95void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid, 97void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
96 struct kvm_mp_state *mp_state); 98 struct kvm_mp_state *mp_state);
97void vcpu_regs_get(struct kvm_vm *vm, 99void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs);
98 uint32_t vcpuid, struct kvm_regs *regs); 100void vcpu_regs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs);
99void vcpu_regs_set(struct kvm_vm *vm,
100 uint32_t vcpuid, struct kvm_regs *regs);
101void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...); 101void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...);
102void vcpu_sregs_get(struct kvm_vm *vm, 102void vcpu_sregs_get(struct kvm_vm *vm, uint32_t vcpuid,
103 uint32_t vcpuid, struct kvm_sregs *sregs); 103 struct kvm_sregs *sregs);
104void vcpu_sregs_set(struct kvm_vm *vm, 104void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid,
105 uint32_t vcpuid, struct kvm_sregs *sregs); 105 struct kvm_sregs *sregs);
106int _vcpu_sregs_set(struct kvm_vm *vm, 106int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid,
107 uint32_t vcpuid, struct kvm_sregs *sregs); 107 struct kvm_sregs *sregs);
108void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid, 108void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
109 struct kvm_vcpu_events *events); 109 struct kvm_vcpu_events *events);
110void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid, 110void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
111 struct kvm_vcpu_events *events); 111 struct kvm_vcpu_events *events);
112uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
113void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
114 uint64_t msr_value);
115 112
116const char *exit_reason_str(unsigned int exit_reason); 113const char *exit_reason_str(unsigned int exit_reason);
117 114
118void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot); 115void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot);
119void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, 116void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
120 uint32_t pgd_memslot); 117 uint32_t pgd_memslot);
121vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, 118vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
122 vm_paddr_t paddr_min, uint32_t memslot); 119 uint32_t memslot);
123 120vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
124struct kvm_cpuid2 *kvm_get_supported_cpuid(void); 121 vm_paddr_t paddr_min, uint32_t memslot);
125void vcpu_set_cpuid(
126 struct kvm_vm *vm, uint32_t vcpuid, struct kvm_cpuid2 *cpuid);
127
128struct kvm_cpuid_entry2 *
129kvm_get_supported_cpuid_index(uint32_t function, uint32_t index);
130
131static inline struct kvm_cpuid_entry2 *
132kvm_get_supported_cpuid_entry(uint32_t function)
133{
134 return kvm_get_supported_cpuid_index(function, 0);
135}
136 122
137struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_size, 123struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_size,
138 void *guest_code); 124 void *guest_code);
139void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code); 125void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code);
140 126
141typedef void (*vmx_guest_code_t)(vm_vaddr_t vmxon_vaddr,
142 vm_paddr_t vmxon_paddr,
143 vm_vaddr_t vmcs_vaddr,
144 vm_paddr_t vmcs_paddr);
145
146struct kvm_userspace_memory_region * 127struct kvm_userspace_memory_region *
147kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start, 128kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
148 uint64_t end); 129 uint64_t end);
@@ -152,43 +133,49 @@ allocate_kvm_dirty_log(struct kvm_userspace_memory_region *region);
152 133
153int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd); 134int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd);
154 135
155#define GUEST_PORT_SYNC 0x1000 136#define sync_global_to_guest(vm, g) ({ \
156#define GUEST_PORT_ABORT 0x1001 137 typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g)); \
157#define GUEST_PORT_DONE 0x1002 138 memcpy(_p, &(g), sizeof(g)); \
158 139})
159static inline void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1) 140
160{ 141#define sync_global_from_guest(vm, g) ({ \
161 __asm__ __volatile__("in %[port], %%al" 142 typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g)); \
162 : 143 memcpy(&(g), _p, sizeof(g)); \
163 : [port]"d"(port), "D"(arg0), "S"(arg1) 144})
164 : "rax"); 145
165} 146/* ucall implementation types */
166 147typedef enum {
167/* 148 UCALL_PIO,
168 * Allows to pass three arguments to the host: port is 16bit wide, 149 UCALL_MMIO,
169 * arg0 & arg1 are 64bit wide 150} ucall_type_t;
170 */ 151
171#define GUEST_SYNC_ARGS(_port, _arg0, _arg1) \ 152/* Common ucalls */
172 __exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1)) 153enum {
173 154 UCALL_NONE,
174#define GUEST_ASSERT(_condition) do { \ 155 UCALL_SYNC,
175 if (!(_condition)) \ 156 UCALL_ABORT,
176 GUEST_SYNC_ARGS(GUEST_PORT_ABORT, \ 157 UCALL_DONE,
177 "Failed guest assert: " \ 158};
178 #_condition, __LINE__); \
179 } while (0)
180
181#define GUEST_SYNC(stage) GUEST_SYNC_ARGS(GUEST_PORT_SYNC, "hello", stage)
182 159
183#define GUEST_DONE() GUEST_SYNC_ARGS(GUEST_PORT_DONE, 0, 0) 160#define UCALL_MAX_ARGS 6
184 161
185struct guest_args { 162struct ucall {
186 uint64_t arg0; 163 uint64_t cmd;
187 uint64_t arg1; 164 uint64_t args[UCALL_MAX_ARGS];
188 uint16_t port; 165};
189} __attribute__ ((packed));
190 166
191void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id, 167void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg);
192 struct guest_args *args); 168void ucall_uninit(struct kvm_vm *vm);
169void ucall(uint64_t cmd, int nargs, ...);
170uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
171
172#define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage)
173#define GUEST_DONE() ucall(UCALL_DONE, 0)
174#define GUEST_ASSERT(_condition) do { \
175 if (!(_condition)) \
176 ucall(UCALL_ABORT, 2, \
177 "Failed guest assert: " \
178 #_condition, __LINE__); \
179} while (0)
193 180
194#endif /* SELFTEST_KVM_UTIL_H */ 181#endif /* SELFTEST_KVM_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/sparsebit.h b/tools/testing/selftests/kvm/include/sparsebit.h
index 54cfeb6568d3..31e030915c1f 100644
--- a/tools/testing/selftests/kvm/include/sparsebit.h
+++ b/tools/testing/selftests/kvm/include/sparsebit.h
@@ -15,8 +15,8 @@
15 * even in the case where most bits are set. 15 * even in the case where most bits are set.
16 */ 16 */
17 17
18#ifndef _TEST_SPARSEBIT_H_ 18#ifndef SELFTEST_KVM_SPARSEBIT_H
19#define _TEST_SPARSEBIT_H_ 19#define SELFTEST_KVM_SPARSEBIT_H
20 20
21#include <stdbool.h> 21#include <stdbool.h>
22#include <stdint.h> 22#include <stdint.h>
@@ -72,4 +72,4 @@ void sparsebit_validate_internal(struct sparsebit *sbit);
72} 72}
73#endif 73#endif
74 74
75#endif /* _TEST_SPARSEBIT_H_ */ 75#endif /* SELFTEST_KVM_SPARSEBIT_H */
diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h
index 73c3933436ec..c7dafe8bd02c 100644
--- a/tools/testing/selftests/kvm/include/test_util.h
+++ b/tools/testing/selftests/kvm/include/test_util.h
@@ -7,8 +7,8 @@
7 * 7 *
8 */ 8 */
9 9
10#ifndef TEST_UTIL_H 10#ifndef SELFTEST_KVM_TEST_UTIL_H
11#define TEST_UTIL_H 1 11#define SELFTEST_KVM_TEST_UTIL_H
12 12
13#include <stdlib.h> 13#include <stdlib.h>
14#include <stdarg.h> 14#include <stdarg.h>
@@ -41,4 +41,4 @@ void test_assert(bool exp, const char *exp_str,
41 #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \ 41 #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \
42} while (0) 42} while (0)
43 43
44#endif /* TEST_UTIL_H */ 44#endif /* SELFTEST_KVM_TEST_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/x86.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
index 42c3596815b8..e2884c2b81ff 100644
--- a/tools/testing/selftests/kvm/include/x86.h
+++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * tools/testing/selftests/kvm/include/x86.h 2 * tools/testing/selftests/kvm/include/x86_64/processor.h
3 * 3 *
4 * Copyright (C) 2018, Google LLC. 4 * Copyright (C) 2018, Google LLC.
5 * 5 *
@@ -7,8 +7,8 @@
7 * 7 *
8 */ 8 */
9 9
10#ifndef SELFTEST_KVM_X86_H 10#ifndef SELFTEST_KVM_PROCESSOR_H
11#define SELFTEST_KVM_X86_H 11#define SELFTEST_KVM_PROCESSOR_H
12 12
13#include <assert.h> 13#include <assert.h>
14#include <stdint.h> 14#include <stdint.h>
@@ -305,7 +305,25 @@ static inline unsigned long get_xmm(int n)
305 305
306struct kvm_x86_state; 306struct kvm_x86_state;
307struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid); 307struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid);
308void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state); 308void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid,
309 struct kvm_x86_state *state);
310
311struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
312void vcpu_set_cpuid(struct kvm_vm *vm, uint32_t vcpuid,
313 struct kvm_cpuid2 *cpuid);
314
315struct kvm_cpuid_entry2 *
316kvm_get_supported_cpuid_index(uint32_t function, uint32_t index);
317
318static inline struct kvm_cpuid_entry2 *
319kvm_get_supported_cpuid_entry(uint32_t function)
320{
321 return kvm_get_supported_cpuid_index(function, 0);
322}
323
324uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
325void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
326 uint64_t msr_value);
309 327
310/* 328/*
311 * Basic CPU control in CR0 329 * Basic CPU control in CR0
@@ -1044,4 +1062,4 @@ void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *s
1044#define MSR_VM_IGNNE 0xc0010115 1062#define MSR_VM_IGNNE 0xc0010115
1045#define MSR_VM_HSAVE_PA 0xc0010117 1063#define MSR_VM_HSAVE_PA 0xc0010117
1046 1064
1047#endif /* !SELFTEST_KVM_X86_H */ 1065#endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/include/vmx.h b/tools/testing/selftests/kvm/include/x86_64/vmx.h
index b9ffe1024d3a..c9bd935b939c 100644
--- a/tools/testing/selftests/kvm/include/vmx.h
+++ b/tools/testing/selftests/kvm/include/x86_64/vmx.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * tools/testing/selftests/kvm/include/vmx.h 2 * tools/testing/selftests/kvm/include/x86_64/vmx.h
3 * 3 *
4 * Copyright (C) 2018, Google LLC. 4 * Copyright (C) 2018, Google LLC.
5 * 5 *
@@ -11,7 +11,7 @@
11#define SELFTEST_KVM_VMX_H 11#define SELFTEST_KVM_VMX_H
12 12
13#include <stdint.h> 13#include <stdint.h>
14#include "x86.h" 14#include "processor.h"
15 15
16#define CPUID_VMX_BIT 5 16#define CPUID_VMX_BIT 5
17 17
@@ -339,6 +339,8 @@ struct vmx_msr_entry {
339 uint64_t value; 339 uint64_t value;
340} __attribute__ ((aligned(16))); 340} __attribute__ ((aligned(16)));
341 341
342#include "evmcs.h"
343
342static inline int vmxon(uint64_t phys) 344static inline int vmxon(uint64_t phys)
343{ 345{
344 uint8_t ret; 346 uint8_t ret;
@@ -372,6 +374,9 @@ static inline int vmptrld(uint64_t vmcs_pa)
372{ 374{
373 uint8_t ret; 375 uint8_t ret;
374 376
377 if (enable_evmcs)
378 return -1;
379
375 __asm__ __volatile__ ("vmptrld %[pa]; setna %[ret]" 380 __asm__ __volatile__ ("vmptrld %[pa]; setna %[ret]"
376 : [ret]"=rm"(ret) 381 : [ret]"=rm"(ret)
377 : [pa]"m"(vmcs_pa) 382 : [pa]"m"(vmcs_pa)
@@ -385,6 +390,9 @@ static inline int vmptrst(uint64_t *value)
385 uint64_t tmp; 390 uint64_t tmp;
386 uint8_t ret; 391 uint8_t ret;
387 392
393 if (enable_evmcs)
394 return evmcs_vmptrst(value);
395
388 __asm__ __volatile__("vmptrst %[value]; setna %[ret]" 396 __asm__ __volatile__("vmptrst %[value]; setna %[ret]"
389 : [value]"=m"(tmp), [ret]"=rm"(ret) 397 : [value]"=m"(tmp), [ret]"=rm"(ret)
390 : : "cc", "memory"); 398 : : "cc", "memory");
@@ -411,6 +419,9 @@ static inline int vmlaunch(void)
411{ 419{
412 int ret; 420 int ret;
413 421
422 if (enable_evmcs)
423 return evmcs_vmlaunch();
424
414 __asm__ __volatile__("push %%rbp;" 425 __asm__ __volatile__("push %%rbp;"
415 "push %%rcx;" 426 "push %%rcx;"
416 "push %%rdx;" 427 "push %%rdx;"
@@ -443,6 +454,9 @@ static inline int vmresume(void)
443{ 454{
444 int ret; 455 int ret;
445 456
457 if (enable_evmcs)
458 return evmcs_vmresume();
459
446 __asm__ __volatile__("push %%rbp;" 460 __asm__ __volatile__("push %%rbp;"
447 "push %%rcx;" 461 "push %%rcx;"
448 "push %%rdx;" 462 "push %%rdx;"
@@ -482,6 +496,9 @@ static inline int vmread(uint64_t encoding, uint64_t *value)
482 uint64_t tmp; 496 uint64_t tmp;
483 uint8_t ret; 497 uint8_t ret;
484 498
499 if (enable_evmcs)
500 return evmcs_vmread(encoding, value);
501
485 __asm__ __volatile__("vmread %[encoding], %[value]; setna %[ret]" 502 __asm__ __volatile__("vmread %[encoding], %[value]; setna %[ret]"
486 : [value]"=rm"(tmp), [ret]"=rm"(ret) 503 : [value]"=rm"(tmp), [ret]"=rm"(ret)
487 : [encoding]"r"(encoding) 504 : [encoding]"r"(encoding)
@@ -506,6 +523,9 @@ static inline int vmwrite(uint64_t encoding, uint64_t value)
506{ 523{
507 uint8_t ret; 524 uint8_t ret;
508 525
526 if (enable_evmcs)
527 return evmcs_vmwrite(encoding, value);
528
509 __asm__ __volatile__ ("vmwrite %[value], %[encoding]; setna %[ret]" 529 __asm__ __volatile__ ("vmwrite %[value], %[encoding]; setna %[ret]"
510 : [ret]"=rm"(ret) 530 : [ret]"=rm"(ret)
511 : [value]"rm"(value), [encoding]"r"(encoding) 531 : [value]"rm"(value), [encoding]"r"(encoding)
@@ -543,10 +563,19 @@ struct vmx_pages {
543 void *vmwrite_hva; 563 void *vmwrite_hva;
544 uint64_t vmwrite_gpa; 564 uint64_t vmwrite_gpa;
545 void *vmwrite; 565 void *vmwrite;
566
567 void *vp_assist_hva;
568 uint64_t vp_assist_gpa;
569 void *vp_assist;
570
571 void *enlightened_vmcs_hva;
572 uint64_t enlightened_vmcs_gpa;
573 void *enlightened_vmcs;
546}; 574};
547 575
548struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva); 576struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva);
549bool prepare_for_vmx_operation(struct vmx_pages *vmx); 577bool prepare_for_vmx_operation(struct vmx_pages *vmx);
550void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp); 578void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp);
579bool load_vmcs(struct vmx_pages *vmx);
551 580
552#endif /* !SELFTEST_KVM_VMX_H */ 581#endif /* SELFTEST_KVM_VMX_H */
diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
new file mode 100644
index 000000000000..b6022e2f116e
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
@@ -0,0 +1,311 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * AArch64 code
4 *
5 * Copyright (C) 2018, Red Hat, Inc.
6 */
7
8#define _GNU_SOURCE /* for program_invocation_name */
9
10#include "kvm_util.h"
11#include "../kvm_util_internal.h"
12#include "processor.h"
13
14#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
15#define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN 0xac0000
16
17static uint64_t page_align(struct kvm_vm *vm, uint64_t v)
18{
19 return (v + vm->page_size) & ~(vm->page_size - 1);
20}
21
22static uint64_t pgd_index(struct kvm_vm *vm, vm_vaddr_t gva)
23{
24 unsigned int shift = (vm->pgtable_levels - 1) * (vm->page_shift - 3) + vm->page_shift;
25 uint64_t mask = (1UL << (vm->va_bits - shift)) - 1;
26
27 return (gva >> shift) & mask;
28}
29
30static uint64_t pud_index(struct kvm_vm *vm, vm_vaddr_t gva)
31{
32 unsigned int shift = 2 * (vm->page_shift - 3) + vm->page_shift;
33 uint64_t mask = (1UL << (vm->page_shift - 3)) - 1;
34
35 TEST_ASSERT(vm->pgtable_levels == 4,
36 "Mode %d does not have 4 page table levels", vm->mode);
37
38 return (gva >> shift) & mask;
39}
40
41static uint64_t pmd_index(struct kvm_vm *vm, vm_vaddr_t gva)
42{
43 unsigned int shift = (vm->page_shift - 3) + vm->page_shift;
44 uint64_t mask = (1UL << (vm->page_shift - 3)) - 1;
45
46 TEST_ASSERT(vm->pgtable_levels >= 3,
47 "Mode %d does not have >= 3 page table levels", vm->mode);
48
49 return (gva >> shift) & mask;
50}
51
52static uint64_t pte_index(struct kvm_vm *vm, vm_vaddr_t gva)
53{
54 uint64_t mask = (1UL << (vm->page_shift - 3)) - 1;
55 return (gva >> vm->page_shift) & mask;
56}
57
58static uint64_t pte_addr(struct kvm_vm *vm, uint64_t entry)
59{
60 uint64_t mask = ((1UL << (vm->va_bits - vm->page_shift)) - 1) << vm->page_shift;
61 return entry & mask;
62}
63
64static uint64_t ptrs_per_pgd(struct kvm_vm *vm)
65{
66 unsigned int shift = (vm->pgtable_levels - 1) * (vm->page_shift - 3) + vm->page_shift;
67 return 1 << (vm->va_bits - shift);
68}
69
70static uint64_t ptrs_per_pte(struct kvm_vm *vm)
71{
72 return 1 << (vm->page_shift - 3);
73}
74
75void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
76{
77 int rc;
78
79 if (!vm->pgd_created) {
80 vm_paddr_t paddr = vm_phy_pages_alloc(vm,
81 page_align(vm, ptrs_per_pgd(vm) * 8) / vm->page_size,
82 KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
83 vm->pgd = paddr;
84 vm->pgd_created = true;
85 }
86}
87
88void _virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
89 uint32_t pgd_memslot, uint64_t flags)
90{
91 uint8_t attr_idx = flags & 7;
92 uint64_t *ptep;
93
94 TEST_ASSERT((vaddr % vm->page_size) == 0,
95 "Virtual address not on page boundary,\n"
96 " vaddr: 0x%lx vm->page_size: 0x%x", vaddr, vm->page_size);
97 TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
98 (vaddr >> vm->page_shift)),
99 "Invalid virtual address, vaddr: 0x%lx", vaddr);
100 TEST_ASSERT((paddr % vm->page_size) == 0,
101 "Physical address not on page boundary,\n"
102 " paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
103 TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
104 "Physical address beyond beyond maximum supported,\n"
105 " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
106 paddr, vm->max_gfn, vm->page_size);
107
108 ptep = addr_gpa2hva(vm, vm->pgd) + pgd_index(vm, vaddr) * 8;
109 if (!*ptep) {
110 *ptep = vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
111 *ptep |= 3;
112 }
113
114 switch (vm->pgtable_levels) {
115 case 4:
116 ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pud_index(vm, vaddr) * 8;
117 if (!*ptep) {
118 *ptep = vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
119 *ptep |= 3;
120 }
121 /* fall through */
122 case 3:
123 ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pmd_index(vm, vaddr) * 8;
124 if (!*ptep) {
125 *ptep = vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
126 *ptep |= 3;
127 }
128 /* fall through */
129 case 2:
130 ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pte_index(vm, vaddr) * 8;
131 break;
132 default:
133 TEST_ASSERT(false, "Page table levels must be 2, 3, or 4");
134 }
135
136 *ptep = paddr | 3;
137 *ptep |= (attr_idx << 2) | (1 << 10) /* Access Flag */;
138}
139
140void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
141 uint32_t pgd_memslot)
142{
143 uint64_t attr_idx = 4; /* NORMAL (See DEFAULT_MAIR_EL1) */
144
145 _virt_pg_map(vm, vaddr, paddr, pgd_memslot, attr_idx);
146}
147
148vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
149{
150 uint64_t *ptep;
151
152 if (!vm->pgd_created)
153 goto unmapped_gva;
154
155 ptep = addr_gpa2hva(vm, vm->pgd) + pgd_index(vm, gva) * 8;
156 if (!ptep)
157 goto unmapped_gva;
158
159 switch (vm->pgtable_levels) {
160 case 4:
161 ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pud_index(vm, gva) * 8;
162 if (!ptep)
163 goto unmapped_gva;
164 /* fall through */
165 case 3:
166 ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pmd_index(vm, gva) * 8;
167 if (!ptep)
168 goto unmapped_gva;
169 /* fall through */
170 case 2:
171 ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pte_index(vm, gva) * 8;
172 if (!ptep)
173 goto unmapped_gva;
174 break;
175 default:
176 TEST_ASSERT(false, "Page table levels must be 2, 3, or 4");
177 }
178
179 return pte_addr(vm, *ptep) + (gva & (vm->page_size - 1));
180
181unmapped_gva:
182 TEST_ASSERT(false, "No mapping for vm virtual address, "
183 "gva: 0x%lx", gva);
184}
185
186static void pte_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent, uint64_t page, int level)
187{
188#ifdef DEBUG_VM
189 static const char * const type[] = { "", "pud", "pmd", "pte" };
190 uint64_t pte, *ptep;
191
192 if (level == 4)
193 return;
194
195 for (pte = page; pte < page + ptrs_per_pte(vm) * 8; pte += 8) {
196 ptep = addr_gpa2hva(vm, pte);
197 if (!*ptep)
198 continue;
199 printf("%*s%s: %lx: %lx at %p\n", indent, "", type[level], pte, *ptep, ptep);
200 pte_dump(stream, vm, indent + 1, pte_addr(vm, *ptep), level + 1);
201 }
202#endif
203}
204
205void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
206{
207 int level = 4 - (vm->pgtable_levels - 1);
208 uint64_t pgd, *ptep;
209
210 if (!vm->pgd_created)
211 return;
212
213 for (pgd = vm->pgd; pgd < vm->pgd + ptrs_per_pgd(vm) * 8; pgd += 8) {
214 ptep = addr_gpa2hva(vm, pgd);
215 if (!*ptep)
216 continue;
217 printf("%*spgd: %lx: %lx at %p\n", indent, "", pgd, *ptep, ptep);
218 pte_dump(stream, vm, indent + 1, pte_addr(vm, *ptep), level);
219 }
220}
221
222struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
223 void *guest_code)
224{
225 uint64_t ptrs_per_4k_pte = 512;
226 uint64_t extra_pg_pages = (extra_mem_pages / ptrs_per_4k_pte) * 2;
227 struct kvm_vm *vm;
228
229 vm = vm_create(VM_MODE_P52V48_4K, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);
230
231 kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
232 vm_vcpu_add_default(vm, vcpuid, guest_code);
233
234 return vm;
235}
236
237void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
238{
239 size_t stack_size = vm->page_size == 4096 ?
240 DEFAULT_STACK_PGS * vm->page_size :
241 vm->page_size;
242 uint64_t stack_vaddr = vm_vaddr_alloc(vm, stack_size,
243 DEFAULT_ARM64_GUEST_STACK_VADDR_MIN, 0, 0);
244
245 vm_vcpu_add(vm, vcpuid, 0, 0);
246
247 set_reg(vm, vcpuid, ARM64_CORE_REG(sp_el1), stack_vaddr + stack_size);
248 set_reg(vm, vcpuid, ARM64_CORE_REG(regs.pc), (uint64_t)guest_code);
249}
250
251void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
252{
253 struct kvm_vcpu_init init;
254 uint64_t sctlr_el1, tcr_el1;
255
256 memset(&init, 0, sizeof(init));
257 init.target = KVM_ARM_TARGET_GENERIC_V8;
258 vcpu_ioctl(vm, vcpuid, KVM_ARM_VCPU_INIT, &init);
259
260 /*
261 * Enable FP/ASIMD to avoid trapping when accessing Q0-Q15
262 * registers, which the variable argument list macros do.
263 */
264 set_reg(vm, vcpuid, ARM64_SYS_REG(CPACR_EL1), 3 << 20);
265
266 get_reg(vm, vcpuid, ARM64_SYS_REG(SCTLR_EL1), &sctlr_el1);
267 get_reg(vm, vcpuid, ARM64_SYS_REG(TCR_EL1), &tcr_el1);
268
269 switch (vm->mode) {
270 case VM_MODE_P52V48_4K:
271 tcr_el1 |= 0ul << 14; /* TG0 = 4KB */
272 tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
273 break;
274 case VM_MODE_P52V48_64K:
275 tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
276 tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
277 break;
278 case VM_MODE_P40V48_4K:
279 tcr_el1 |= 0ul << 14; /* TG0 = 4KB */
280 tcr_el1 |= 2ul << 32; /* IPS = 40 bits */
281 break;
282 case VM_MODE_P40V48_64K:
283 tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
284 tcr_el1 |= 2ul << 32; /* IPS = 40 bits */
285 break;
286 default:
287 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
288 }
289
290 sctlr_el1 |= (1 << 0) | (1 << 2) | (1 << 12) /* M | C | I */;
291 /* TCR_EL1 |= IRGN0:WBWA | ORGN0:WBWA | SH0:Inner-Shareable */;
292 tcr_el1 |= (1 << 8) | (1 << 10) | (3 << 12);
293 tcr_el1 |= (64 - vm->va_bits) /* T0SZ */;
294
295 set_reg(vm, vcpuid, ARM64_SYS_REG(SCTLR_EL1), sctlr_el1);
296 set_reg(vm, vcpuid, ARM64_SYS_REG(TCR_EL1), tcr_el1);
297 set_reg(vm, vcpuid, ARM64_SYS_REG(MAIR_EL1), DEFAULT_MAIR_EL1);
298 set_reg(vm, vcpuid, ARM64_SYS_REG(TTBR0_EL1), vm->pgd);
299}
300
301void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid, uint8_t indent)
302{
303 uint64_t pstate, pc;
304
305 get_reg(vm, vcpuid, ARM64_CORE_REG(regs.pstate), &pstate);
306 get_reg(vm, vcpuid, ARM64_CORE_REG(regs.pc), &pc);
307
308 fprintf(stream, "%*spstate: 0x%.16llx pc: 0x%.16llx\n",
309 indent, "", pstate, pc);
310
311}
diff --git a/tools/testing/selftests/kvm/lib/assert.c b/tools/testing/selftests/kvm/lib/assert.c
index cd01144d27c8..6398efe67885 100644
--- a/tools/testing/selftests/kvm/lib/assert.c
+++ b/tools/testing/selftests/kvm/lib/assert.c
@@ -13,7 +13,7 @@
13#include <execinfo.h> 13#include <execinfo.h>
14#include <sys/syscall.h> 14#include <sys/syscall.h>
15 15
16#include "../../kselftest.h" 16#include "kselftest.h"
17 17
18/* Dumps the current stack trace to stderr. */ 18/* Dumps the current stack trace to stderr. */
19static void __attribute__((noinline)) test_dump_stack(void); 19static void __attribute__((noinline)) test_dump_stack(void);
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 6fd8c089cafc..8c06da4f03db 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -16,10 +16,8 @@
16#include <sys/stat.h> 16#include <sys/stat.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18 18
19#define KVM_DEV_PATH "/dev/kvm"
20
21#define KVM_UTIL_PGS_PER_HUGEPG 512 19#define KVM_UTIL_PGS_PER_HUGEPG 512
22#define KVM_UTIL_MIN_PADDR 0x2000 20#define KVM_UTIL_MIN_PFN 2
23 21
24/* Aligns x up to the next multiple of size. Size must be a power of 2. */ 22/* Aligns x up to the next multiple of size. Size must be a power of 2. */
25static void *align(void *x, size_t size) 23static void *align(void *x, size_t size)
@@ -30,7 +28,8 @@ static void *align(void *x, size_t size)
30 return (void *) (((size_t) x + mask) & ~mask); 28 return (void *) (((size_t) x + mask) & ~mask);
31} 29}
32 30
33/* Capability 31/*
32 * Capability
34 * 33 *
35 * Input Args: 34 * Input Args:
36 * cap - Capability 35 * cap - Capability
@@ -92,16 +91,23 @@ static void vm_open(struct kvm_vm *vm, int perm)
92 if (vm->kvm_fd < 0) 91 if (vm->kvm_fd < 0)
93 exit(KSFT_SKIP); 92 exit(KSFT_SKIP);
94 93
95 /* Create VM. */
96 vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, NULL); 94 vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, NULL);
97 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, " 95 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
98 "rc: %i errno: %i", vm->fd, errno); 96 "rc: %i errno: %i", vm->fd, errno);
99} 97}
100 98
101/* VM Create 99const char * const vm_guest_mode_string[] = {
100 "PA-bits:52, VA-bits:48, 4K pages",
101 "PA-bits:52, VA-bits:48, 64K pages",
102 "PA-bits:40, VA-bits:48, 4K pages",
103 "PA-bits:40, VA-bits:48, 64K pages",
104};
105
106/*
107 * VM Create
102 * 108 *
103 * Input Args: 109 * Input Args:
104 * mode - VM Mode (e.g. VM_MODE_FLAT48PG) 110 * mode - VM Mode (e.g. VM_MODE_P52V48_4K)
105 * phy_pages - Physical memory pages 111 * phy_pages - Physical memory pages
106 * perm - permission 112 * perm - permission
107 * 113 *
@@ -110,7 +116,7 @@ static void vm_open(struct kvm_vm *vm, int perm)
110 * Return: 116 * Return:
111 * Pointer to opaque structure that describes the created VM. 117 * Pointer to opaque structure that describes the created VM.
112 * 118 *
113 * Creates a VM with the mode specified by mode (e.g. VM_MODE_FLAT48PG). 119 * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K).
114 * When phy_pages is non-zero, a memory region of phy_pages physical pages 120 * When phy_pages is non-zero, a memory region of phy_pages physical pages
115 * is created and mapped starting at guest physical address 0. The file 121 * is created and mapped starting at guest physical address 0. The file
116 * descriptor to control the created VM is created with the permissions 122 * descriptor to control the created VM is created with the permissions
@@ -121,7 +127,6 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
121 struct kvm_vm *vm; 127 struct kvm_vm *vm;
122 int kvm_fd; 128 int kvm_fd;
123 129
124 /* Allocate memory. */
125 vm = calloc(1, sizeof(*vm)); 130 vm = calloc(1, sizeof(*vm));
126 TEST_ASSERT(vm != NULL, "Insufficent Memory"); 131 TEST_ASSERT(vm != NULL, "Insufficent Memory");
127 132
@@ -130,26 +135,48 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
130 135
131 /* Setup mode specific traits. */ 136 /* Setup mode specific traits. */
132 switch (vm->mode) { 137 switch (vm->mode) {
133 case VM_MODE_FLAT48PG: 138 case VM_MODE_P52V48_4K:
139 vm->pgtable_levels = 4;
134 vm->page_size = 0x1000; 140 vm->page_size = 0x1000;
135 vm->page_shift = 12; 141 vm->page_shift = 12;
136 142 vm->va_bits = 48;
137 /* Limit to 48-bit canonical virtual addresses. */ 143 break;
138 vm->vpages_valid = sparsebit_alloc(); 144 case VM_MODE_P52V48_64K:
139 sparsebit_set_num(vm->vpages_valid, 145 vm->pgtable_levels = 3;
140 0, (1ULL << (48 - 1)) >> vm->page_shift); 146 vm->pa_bits = 52;
141 sparsebit_set_num(vm->vpages_valid, 147 vm->page_size = 0x10000;
142 (~((1ULL << (48 - 1)) - 1)) >> vm->page_shift, 148 vm->page_shift = 16;
143 (1ULL << (48 - 1)) >> vm->page_shift); 149 vm->va_bits = 48;
144 150 break;
145 /* Limit physical addresses to 52-bits. */ 151 case VM_MODE_P40V48_4K:
146 vm->max_gfn = ((1ULL << 52) >> vm->page_shift) - 1; 152 vm->pgtable_levels = 4;
153 vm->pa_bits = 40;
154 vm->va_bits = 48;
155 vm->page_size = 0x1000;
156 vm->page_shift = 12;
157 break;
158 case VM_MODE_P40V48_64K:
159 vm->pgtable_levels = 3;
160 vm->pa_bits = 40;
161 vm->va_bits = 48;
162 vm->page_size = 0x10000;
163 vm->page_shift = 16;
147 break; 164 break;
148
149 default: 165 default:
150 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode); 166 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
151 } 167 }
152 168
169 /* Limit to VA-bit canonical virtual addresses. */
170 vm->vpages_valid = sparsebit_alloc();
171 sparsebit_set_num(vm->vpages_valid,
172 0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
173 sparsebit_set_num(vm->vpages_valid,
174 (~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
175 (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
176
177 /* Limit physical addresses to PA-bits. */
178 vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1;
179
153 /* Allocate and setup memory for guest. */ 180 /* Allocate and setup memory for guest. */
154 vm->vpages_mapped = sparsebit_alloc(); 181 vm->vpages_mapped = sparsebit_alloc();
155 if (phy_pages != 0) 182 if (phy_pages != 0)
@@ -159,7 +186,8 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
159 return vm; 186 return vm;
160} 187}
161 188
162/* VM Restart 189/*
190 * VM Restart
163 * 191 *
164 * Input Args: 192 * Input Args:
165 * vm - VM that has been released before 193 * vm - VM that has been released before
@@ -186,7 +214,8 @@ void kvm_vm_restart(struct kvm_vm *vmp, int perm)
186 " rc: %i errno: %i\n" 214 " rc: %i errno: %i\n"
187 " slot: %u flags: 0x%x\n" 215 " slot: %u flags: 0x%x\n"
188 " guest_phys_addr: 0x%lx size: 0x%lx", 216 " guest_phys_addr: 0x%lx size: 0x%lx",
189 ret, errno, region->region.slot, region->region.flags, 217 ret, errno, region->region.slot,
218 region->region.flags,
190 region->region.guest_phys_addr, 219 region->region.guest_phys_addr,
191 region->region.memory_size); 220 region->region.memory_size);
192 } 221 }
@@ -202,7 +231,8 @@ void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
202 strerror(-ret)); 231 strerror(-ret));
203} 232}
204 233
205/* Userspace Memory Region Find 234/*
235 * Userspace Memory Region Find
206 * 236 *
207 * Input Args: 237 * Input Args:
208 * vm - Virtual Machine 238 * vm - Virtual Machine
@@ -220,8 +250,8 @@ void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
220 * of the regions is returned. Null is returned only when no overlapping 250 * of the regions is returned. Null is returned only when no overlapping
221 * region exists. 251 * region exists.
222 */ 252 */
223static struct userspace_mem_region *userspace_mem_region_find( 253static struct userspace_mem_region *
224 struct kvm_vm *vm, uint64_t start, uint64_t end) 254userspace_mem_region_find(struct kvm_vm *vm, uint64_t start, uint64_t end)
225{ 255{
226 struct userspace_mem_region *region; 256 struct userspace_mem_region *region;
227 257
@@ -237,7 +267,8 @@ static struct userspace_mem_region *userspace_mem_region_find(
237 return NULL; 267 return NULL;
238} 268}
239 269
240/* KVM Userspace Memory Region Find 270/*
271 * KVM Userspace Memory Region Find
241 * 272 *
242 * Input Args: 273 * Input Args:
243 * vm - Virtual Machine 274 * vm - Virtual Machine
@@ -265,7 +296,8 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
265 return &region->region; 296 return &region->region;
266} 297}
267 298
268/* VCPU Find 299/*
300 * VCPU Find
269 * 301 *
270 * Input Args: 302 * Input Args:
271 * vm - Virtual Machine 303 * vm - Virtual Machine
@@ -280,8 +312,7 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
280 * returns a pointer to it. Returns NULL if the VM doesn't contain a VCPU 312 * returns a pointer to it. Returns NULL if the VM doesn't contain a VCPU
281 * for the specified vcpuid. 313 * for the specified vcpuid.
282 */ 314 */
283struct vcpu *vcpu_find(struct kvm_vm *vm, 315struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid)
284 uint32_t vcpuid)
285{ 316{
286 struct vcpu *vcpup; 317 struct vcpu *vcpup;
287 318
@@ -293,7 +324,8 @@ struct vcpu *vcpu_find(struct kvm_vm *vm,
293 return NULL; 324 return NULL;
294} 325}
295 326
296/* VM VCPU Remove 327/*
328 * VM VCPU Remove
297 * 329 *
298 * Input Args: 330 * Input Args:
299 * vm - Virtual Machine 331 * vm - Virtual Machine
@@ -330,11 +362,9 @@ void kvm_vm_release(struct kvm_vm *vmp)
330{ 362{
331 int ret; 363 int ret;
332 364
333 /* Free VCPUs. */
334 while (vmp->vcpu_head) 365 while (vmp->vcpu_head)
335 vm_vcpu_rm(vmp, vmp->vcpu_head->id); 366 vm_vcpu_rm(vmp, vmp->vcpu_head->id);
336 367
337 /* Close file descriptor for the VM. */
338 ret = close(vmp->fd); 368 ret = close(vmp->fd);
339 TEST_ASSERT(ret == 0, "Close of vm fd failed,\n" 369 TEST_ASSERT(ret == 0, "Close of vm fd failed,\n"
340 " vmp->fd: %i rc: %i errno: %i", vmp->fd, ret, errno); 370 " vmp->fd: %i rc: %i errno: %i", vmp->fd, ret, errno);
@@ -344,7 +374,8 @@ void kvm_vm_release(struct kvm_vm *vmp)
344 " vmp->kvm_fd: %i rc: %i errno: %i", vmp->kvm_fd, ret, errno); 374 " vmp->kvm_fd: %i rc: %i errno: %i", vmp->kvm_fd, ret, errno);
345} 375}
346 376
347/* Destroys and frees the VM pointed to by vmp. 377/*
378 * Destroys and frees the VM pointed to by vmp.
348 */ 379 */
349void kvm_vm_free(struct kvm_vm *vmp) 380void kvm_vm_free(struct kvm_vm *vmp)
350{ 381{
@@ -383,7 +414,8 @@ void kvm_vm_free(struct kvm_vm *vmp)
383 free(vmp); 414 free(vmp);
384} 415}
385 416
386/* Memory Compare, host virtual to guest virtual 417/*
418 * Memory Compare, host virtual to guest virtual
387 * 419 *
388 * Input Args: 420 * Input Args:
389 * hva - Starting host virtual address 421 * hva - Starting host virtual address
@@ -405,23 +437,25 @@ void kvm_vm_free(struct kvm_vm *vmp)
405 * a length of len, to the guest bytes starting at the guest virtual 437 * a length of len, to the guest bytes starting at the guest virtual
406 * address given by gva. 438 * address given by gva.
407 */ 439 */
408int kvm_memcmp_hva_gva(void *hva, 440int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
409 struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
410{ 441{
411 size_t amt; 442 size_t amt;
412 443
413 /* Compare a batch of bytes until either a match is found 444 /*
445 * Compare a batch of bytes until either a match is found
414 * or all the bytes have been compared. 446 * or all the bytes have been compared.
415 */ 447 */
416 for (uintptr_t offset = 0; offset < len; offset += amt) { 448 for (uintptr_t offset = 0; offset < len; offset += amt) {
417 uintptr_t ptr1 = (uintptr_t)hva + offset; 449 uintptr_t ptr1 = (uintptr_t)hva + offset;
418 450
419 /* Determine host address for guest virtual address 451 /*
452 * Determine host address for guest virtual address
420 * at offset. 453 * at offset.
421 */ 454 */
422 uintptr_t ptr2 = (uintptr_t)addr_gva2hva(vm, gva + offset); 455 uintptr_t ptr2 = (uintptr_t)addr_gva2hva(vm, gva + offset);
423 456
424 /* Determine amount to compare on this pass. 457 /*
458 * Determine amount to compare on this pass.
425 * Don't allow the comparsion to cross a page boundary. 459 * Don't allow the comparsion to cross a page boundary.
426 */ 460 */
427 amt = len - offset; 461 amt = len - offset;
@@ -433,7 +467,8 @@ int kvm_memcmp_hva_gva(void *hva,
433 assert((ptr1 >> vm->page_shift) == ((ptr1 + amt - 1) >> vm->page_shift)); 467 assert((ptr1 >> vm->page_shift) == ((ptr1 + amt - 1) >> vm->page_shift));
434 assert((ptr2 >> vm->page_shift) == ((ptr2 + amt - 1) >> vm->page_shift)); 468 assert((ptr2 >> vm->page_shift) == ((ptr2 + amt - 1) >> vm->page_shift));
435 469
436 /* Perform the comparison. If there is a difference 470 /*
471 * Perform the comparison. If there is a difference
437 * return that result to the caller, otherwise need 472 * return that result to the caller, otherwise need
438 * to continue on looking for a mismatch. 473 * to continue on looking for a mismatch.
439 */ 474 */
@@ -442,109 +477,15 @@ int kvm_memcmp_hva_gva(void *hva,
442 return ret; 477 return ret;
443 } 478 }
444 479
445 /* No mismatch found. Let the caller know the two memory 480 /*
481 * No mismatch found. Let the caller know the two memory
446 * areas are equal. 482 * areas are equal.
447 */ 483 */
448 return 0; 484 return 0;
449} 485}
450 486
451/* Allocate an instance of struct kvm_cpuid2 487/*
452 * 488 * VM Userspace Memory Region Add
453 * Input Args: None
454 *
455 * Output Args: None
456 *
457 * Return: A pointer to the allocated struct. The caller is responsible
458 * for freeing this struct.
459 *
460 * Since kvm_cpuid2 uses a 0-length array to allow a the size of the
461 * array to be decided at allocation time, allocation is slightly
462 * complicated. This function uses a reasonable default length for
463 * the array and performs the appropriate allocation.
464 */
465static struct kvm_cpuid2 *allocate_kvm_cpuid2(void)
466{
467 struct kvm_cpuid2 *cpuid;
468 int nent = 100;
469 size_t size;
470
471 size = sizeof(*cpuid);
472 size += nent * sizeof(struct kvm_cpuid_entry2);
473 cpuid = malloc(size);
474 if (!cpuid) {
475 perror("malloc");
476 abort();
477 }
478
479 cpuid->nent = nent;
480
481 return cpuid;
482}
483
484/* KVM Supported CPUID Get
485 *
486 * Input Args: None
487 *
488 * Output Args:
489 *
490 * Return: The supported KVM CPUID
491 *
492 * Get the guest CPUID supported by KVM.
493 */
494struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
495{
496 static struct kvm_cpuid2 *cpuid;
497 int ret;
498 int kvm_fd;
499
500 if (cpuid)
501 return cpuid;
502
503 cpuid = allocate_kvm_cpuid2();
504 kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
505 if (kvm_fd < 0)
506 exit(KSFT_SKIP);
507
508 ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
509 TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n",
510 ret, errno);
511
512 close(kvm_fd);
513 return cpuid;
514}
515
516/* Locate a cpuid entry.
517 *
518 * Input Args:
519 * cpuid: The cpuid.
520 * function: The function of the cpuid entry to find.
521 *
522 * Output Args: None
523 *
524 * Return: A pointer to the cpuid entry. Never returns NULL.
525 */
526struct kvm_cpuid_entry2 *
527kvm_get_supported_cpuid_index(uint32_t function, uint32_t index)
528{
529 struct kvm_cpuid2 *cpuid;
530 struct kvm_cpuid_entry2 *entry = NULL;
531 int i;
532
533 cpuid = kvm_get_supported_cpuid();
534 for (i = 0; i < cpuid->nent; i++) {
535 if (cpuid->entries[i].function == function &&
536 cpuid->entries[i].index == index) {
537 entry = &cpuid->entries[i];
538 break;
539 }
540 }
541
542 TEST_ASSERT(entry, "Guest CPUID entry not found: (EAX=%x, ECX=%x).",
543 function, index);
544 return entry;
545}
546
547/* VM Userspace Memory Region Add
548 * 489 *
549 * Input Args: 490 * Input Args:
550 * vm - Virtual Machine 491 * vm - Virtual Machine
@@ -586,7 +527,8 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
586 " vm->max_gfn: 0x%lx vm->page_size: 0x%x", 527 " vm->max_gfn: 0x%lx vm->page_size: 0x%x",
587 guest_paddr, npages, vm->max_gfn, vm->page_size); 528 guest_paddr, npages, vm->max_gfn, vm->page_size);
588 529
589 /* Confirm a mem region with an overlapping address doesn't 530 /*
531 * Confirm a mem region with an overlapping address doesn't
590 * already exist. 532 * already exist.
591 */ 533 */
592 region = (struct userspace_mem_region *) userspace_mem_region_find( 534 region = (struct userspace_mem_region *) userspace_mem_region_find(
@@ -677,7 +619,8 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
677 vm->userspace_mem_region_head = region; 619 vm->userspace_mem_region_head = region;
678} 620}
679 621
680/* Memslot to region 622/*
623 * Memslot to region
681 * 624 *
682 * Input Args: 625 * Input Args:
683 * vm - Virtual Machine 626 * vm - Virtual Machine
@@ -691,8 +634,8 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
691 * on error (e.g. currently no memory region using memslot as a KVM 634 * on error (e.g. currently no memory region using memslot as a KVM
692 * memory slot ID). 635 * memory slot ID).
693 */ 636 */
694static struct userspace_mem_region *memslot2region(struct kvm_vm *vm, 637static struct userspace_mem_region *
695 uint32_t memslot) 638memslot2region(struct kvm_vm *vm, uint32_t memslot)
696{ 639{
697 struct userspace_mem_region *region; 640 struct userspace_mem_region *region;
698 641
@@ -712,7 +655,8 @@ static struct userspace_mem_region *memslot2region(struct kvm_vm *vm,
712 return region; 655 return region;
713} 656}
714 657
715/* VM Memory Region Flags Set 658/*
659 * VM Memory Region Flags Set
716 * 660 *
717 * Input Args: 661 * Input Args:
718 * vm - Virtual Machine 662 * vm - Virtual Machine
@@ -730,7 +674,6 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags)
730 int ret; 674 int ret;
731 struct userspace_mem_region *region; 675 struct userspace_mem_region *region;
732 676
733 /* Locate memory region. */
734 region = memslot2region(vm, slot); 677 region = memslot2region(vm, slot);
735 678
736 region->region.flags = flags; 679 region->region.flags = flags;
@@ -742,7 +685,8 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags)
742 ret, errno, slot, flags); 685 ret, errno, slot, flags);
743} 686}
744 687
745/* VCPU mmap Size 688/*
689 * VCPU mmap Size
746 * 690 *
747 * Input Args: None 691 * Input Args: None
748 * 692 *
@@ -772,7 +716,8 @@ static int vcpu_mmap_sz(void)
772 return ret; 716 return ret;
773} 717}
774 718
775/* VM VCPU Add 719/*
720 * VM VCPU Add
776 * 721 *
777 * Input Args: 722 * Input Args:
778 * vm - Virtual Machine 723 * vm - Virtual Machine
@@ -785,7 +730,8 @@ static int vcpu_mmap_sz(void)
785 * Creates and adds to the VM specified by vm and virtual CPU with 730 * Creates and adds to the VM specified by vm and virtual CPU with
786 * the ID given by vcpuid. 731 * the ID given by vcpuid.
787 */ 732 */
788void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_memslot) 733void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot,
734 int gdt_memslot)
789{ 735{
790 struct vcpu *vcpu; 736 struct vcpu *vcpu;
791 737
@@ -823,7 +769,8 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_me
823 vcpu_setup(vm, vcpuid, pgd_memslot, gdt_memslot); 769 vcpu_setup(vm, vcpuid, pgd_memslot, gdt_memslot);
824} 770}
825 771
826/* VM Virtual Address Unused Gap 772/*
773 * VM Virtual Address Unused Gap
827 * 774 *
828 * Input Args: 775 * Input Args:
829 * vm - Virtual Machine 776 * vm - Virtual Machine
@@ -843,14 +790,14 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_me
843 * sz unallocated bytes >= vaddr_min is available. 790 * sz unallocated bytes >= vaddr_min is available.
844 */ 791 */
845static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, 792static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz,
846 vm_vaddr_t vaddr_min) 793 vm_vaddr_t vaddr_min)
847{ 794{
848 uint64_t pages = (sz + vm->page_size - 1) >> vm->page_shift; 795 uint64_t pages = (sz + vm->page_size - 1) >> vm->page_shift;
849 796
850 /* Determine lowest permitted virtual page index. */ 797 /* Determine lowest permitted virtual page index. */
851 uint64_t pgidx_start = (vaddr_min + vm->page_size - 1) >> vm->page_shift; 798 uint64_t pgidx_start = (vaddr_min + vm->page_size - 1) >> vm->page_shift;
852 if ((pgidx_start * vm->page_size) < vaddr_min) 799 if ((pgidx_start * vm->page_size) < vaddr_min)
853 goto no_va_found; 800 goto no_va_found;
854 801
855 /* Loop over section with enough valid virtual page indexes. */ 802 /* Loop over section with enough valid virtual page indexes. */
856 if (!sparsebit_is_set_num(vm->vpages_valid, 803 if (!sparsebit_is_set_num(vm->vpages_valid,
@@ -909,7 +856,8 @@ va_found:
909 return pgidx_start * vm->page_size; 856 return pgidx_start * vm->page_size;
910} 857}
911 858
912/* VM Virtual Address Allocate 859/*
860 * VM Virtual Address Allocate
913 * 861 *
914 * Input Args: 862 * Input Args:
915 * vm - Virtual Machine 863 * vm - Virtual Machine
@@ -930,13 +878,14 @@ va_found:
930 * a page. 878 * a page.
931 */ 879 */
932vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, 880vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
933 uint32_t data_memslot, uint32_t pgd_memslot) 881 uint32_t data_memslot, uint32_t pgd_memslot)
934{ 882{
935 uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0); 883 uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
936 884
937 virt_pgd_alloc(vm, pgd_memslot); 885 virt_pgd_alloc(vm, pgd_memslot);
938 886
939 /* Find an unused range of virtual page addresses of at least 887 /*
888 * Find an unused range of virtual page addresses of at least
940 * pages in length. 889 * pages in length.
941 */ 890 */
942 vm_vaddr_t vaddr_start = vm_vaddr_unused_gap(vm, sz, vaddr_min); 891 vm_vaddr_t vaddr_start = vm_vaddr_unused_gap(vm, sz, vaddr_min);
@@ -946,7 +895,8 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
946 pages--, vaddr += vm->page_size) { 895 pages--, vaddr += vm->page_size) {
947 vm_paddr_t paddr; 896 vm_paddr_t paddr;
948 897
949 paddr = vm_phy_page_alloc(vm, KVM_UTIL_MIN_PADDR, data_memslot); 898 paddr = vm_phy_page_alloc(vm,
899 KVM_UTIL_MIN_PFN * vm->page_size, data_memslot);
950 900
951 virt_pg_map(vm, vaddr, paddr, pgd_memslot); 901 virt_pg_map(vm, vaddr, paddr, pgd_memslot);
952 902
@@ -990,7 +940,8 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
990 } 940 }
991} 941}
992 942
993/* Address VM Physical to Host Virtual 943/*
944 * Address VM Physical to Host Virtual
994 * 945 *
995 * Input Args: 946 * Input Args:
996 * vm - Virtual Machine 947 * vm - Virtual Machine
@@ -1022,7 +973,8 @@ void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa)
1022 return NULL; 973 return NULL;
1023} 974}
1024 975
1025/* Address Host Virtual to VM Physical 976/*
977 * Address Host Virtual to VM Physical
1026 * 978 *
1027 * Input Args: 979 * Input Args:
1028 * vm - Virtual Machine 980 * vm - Virtual Machine
@@ -1056,7 +1008,8 @@ vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva)
1056 return -1; 1008 return -1;
1057} 1009}
1058 1010
1059/* VM Create IRQ Chip 1011/*
1012 * VM Create IRQ Chip
1060 * 1013 *
1061 * Input Args: 1014 * Input Args:
1062 * vm - Virtual Machine 1015 * vm - Virtual Machine
@@ -1078,7 +1031,8 @@ void vm_create_irqchip(struct kvm_vm *vm)
1078 vm->has_irqchip = true; 1031 vm->has_irqchip = true;
1079} 1032}
1080 1033
1081/* VM VCPU State 1034/*
1035 * VM VCPU State
1082 * 1036 *
1083 * Input Args: 1037 * Input Args:
1084 * vm - Virtual Machine 1038 * vm - Virtual Machine
@@ -1100,7 +1054,8 @@ struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid)
1100 return vcpu->state; 1054 return vcpu->state;
1101} 1055}
1102 1056
1103/* VM VCPU Run 1057/*
1058 * VM VCPU Run
1104 * 1059 *
1105 * Input Args: 1060 * Input Args:
1106 * vm - Virtual Machine 1061 * vm - Virtual Machine
@@ -1126,13 +1081,14 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
1126 int rc; 1081 int rc;
1127 1082
1128 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1083 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1129 do { 1084 do {
1130 rc = ioctl(vcpu->fd, KVM_RUN, NULL); 1085 rc = ioctl(vcpu->fd, KVM_RUN, NULL);
1131 } while (rc == -1 && errno == EINTR); 1086 } while (rc == -1 && errno == EINTR);
1132 return rc; 1087 return rc;
1133} 1088}
1134 1089
1135/* VM VCPU Set MP State 1090/*
1091 * VM VCPU Set MP State
1136 * 1092 *
1137 * Input Args: 1093 * Input Args:
1138 * vm - Virtual Machine 1094 * vm - Virtual Machine
@@ -1147,7 +1103,7 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
1147 * by mp_state. 1103 * by mp_state.
1148 */ 1104 */
1149void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid, 1105void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
1150 struct kvm_mp_state *mp_state) 1106 struct kvm_mp_state *mp_state)
1151{ 1107{
1152 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1108 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1153 int ret; 1109 int ret;
@@ -1159,7 +1115,8 @@ void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
1159 "rc: %i errno: %i", ret, errno); 1115 "rc: %i errno: %i", ret, errno);
1160} 1116}
1161 1117
1162/* VM VCPU Regs Get 1118/*
1119 * VM VCPU Regs Get
1163 * 1120 *
1164 * Input Args: 1121 * Input Args:
1165 * vm - Virtual Machine 1122 * vm - Virtual Machine
@@ -1173,21 +1130,20 @@ void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
1173 * Obtains the current register state for the VCPU specified by vcpuid 1130 * Obtains the current register state for the VCPU specified by vcpuid
1174 * and stores it at the location given by regs. 1131 * and stores it at the location given by regs.
1175 */ 1132 */
1176void vcpu_regs_get(struct kvm_vm *vm, 1133void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs)
1177 uint32_t vcpuid, struct kvm_regs *regs)
1178{ 1134{
1179 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1135 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1180 int ret; 1136 int ret;
1181 1137
1182 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1138 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1183 1139
1184 /* Get the regs. */
1185 ret = ioctl(vcpu->fd, KVM_GET_REGS, regs); 1140 ret = ioctl(vcpu->fd, KVM_GET_REGS, regs);
1186 TEST_ASSERT(ret == 0, "KVM_GET_REGS failed, rc: %i errno: %i", 1141 TEST_ASSERT(ret == 0, "KVM_GET_REGS failed, rc: %i errno: %i",
1187 ret, errno); 1142 ret, errno);
1188} 1143}
1189 1144
1190/* VM VCPU Regs Set 1145/*
1146 * VM VCPU Regs Set
1191 * 1147 *
1192 * Input Args: 1148 * Input Args:
1193 * vm - Virtual Machine 1149 * vm - Virtual Machine
@@ -1201,165 +1157,46 @@ void vcpu_regs_get(struct kvm_vm *vm,
1201 * Sets the regs of the VCPU specified by vcpuid to the values 1157 * Sets the regs of the VCPU specified by vcpuid to the values
1202 * given by regs. 1158 * given by regs.
1203 */ 1159 */
1204void vcpu_regs_set(struct kvm_vm *vm, 1160void vcpu_regs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs)
1205 uint32_t vcpuid, struct kvm_regs *regs)
1206{ 1161{
1207 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1162 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1208 int ret; 1163 int ret;
1209 1164
1210 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1165 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1211 1166
1212 /* Set the regs. */
1213 ret = ioctl(vcpu->fd, KVM_SET_REGS, regs); 1167 ret = ioctl(vcpu->fd, KVM_SET_REGS, regs);
1214 TEST_ASSERT(ret == 0, "KVM_SET_REGS failed, rc: %i errno: %i", 1168 TEST_ASSERT(ret == 0, "KVM_SET_REGS failed, rc: %i errno: %i",
1215 ret, errno); 1169 ret, errno);
1216} 1170}
1217 1171
1218void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid, 1172void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
1219 struct kvm_vcpu_events *events) 1173 struct kvm_vcpu_events *events)
1220{ 1174{
1221 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1175 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1222 int ret; 1176 int ret;
1223 1177
1224 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1178 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1225 1179
1226 /* Get the regs. */
1227 ret = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, events); 1180 ret = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, events);
1228 TEST_ASSERT(ret == 0, "KVM_GET_VCPU_EVENTS, failed, rc: %i errno: %i", 1181 TEST_ASSERT(ret == 0, "KVM_GET_VCPU_EVENTS, failed, rc: %i errno: %i",
1229 ret, errno); 1182 ret, errno);
1230} 1183}
1231 1184
1232void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid, 1185void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
1233 struct kvm_vcpu_events *events) 1186 struct kvm_vcpu_events *events)
1234{ 1187{
1235 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1188 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1236 int ret; 1189 int ret;
1237 1190
1238 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1191 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1239 1192
1240 /* Set the regs. */
1241 ret = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, events); 1193 ret = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, events);
1242 TEST_ASSERT(ret == 0, "KVM_SET_VCPU_EVENTS, failed, rc: %i errno: %i", 1194 TEST_ASSERT(ret == 0, "KVM_SET_VCPU_EVENTS, failed, rc: %i errno: %i",
1243 ret, errno); 1195 ret, errno);
1244} 1196}
1245 1197
1246/* VCPU Get MSR 1198/*
1247 * 1199 * VM VCPU System Regs Get
1248 * Input Args:
1249 * vm - Virtual Machine
1250 * vcpuid - VCPU ID
1251 * msr_index - Index of MSR
1252 *
1253 * Output Args: None
1254 *
1255 * Return: On success, value of the MSR. On failure a TEST_ASSERT is produced.
1256 *
1257 * Get value of MSR for VCPU.
1258 */
1259uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
1260{
1261 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1262 struct {
1263 struct kvm_msrs header;
1264 struct kvm_msr_entry entry;
1265 } buffer = {};
1266 int r;
1267
1268 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1269 buffer.header.nmsrs = 1;
1270 buffer.entry.index = msr_index;
1271 r = ioctl(vcpu->fd, KVM_GET_MSRS, &buffer.header);
1272 TEST_ASSERT(r == 1, "KVM_GET_MSRS IOCTL failed,\n"
1273 " rc: %i errno: %i", r, errno);
1274
1275 return buffer.entry.data;
1276}
1277
1278/* VCPU Set MSR
1279 *
1280 * Input Args:
1281 * vm - Virtual Machine
1282 * vcpuid - VCPU ID
1283 * msr_index - Index of MSR
1284 * msr_value - New value of MSR
1285 *
1286 * Output Args: None
1287 *
1288 * Return: On success, nothing. On failure a TEST_ASSERT is produced.
1289 *
1290 * Set value of MSR for VCPU.
1291 */
1292void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
1293 uint64_t msr_value)
1294{
1295 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1296 struct {
1297 struct kvm_msrs header;
1298 struct kvm_msr_entry entry;
1299 } buffer = {};
1300 int r;
1301
1302 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1303 memset(&buffer, 0, sizeof(buffer));
1304 buffer.header.nmsrs = 1;
1305 buffer.entry.index = msr_index;
1306 buffer.entry.data = msr_value;
1307 r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
1308 TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
1309 " rc: %i errno: %i", r, errno);
1310}
1311
1312/* VM VCPU Args Set
1313 *
1314 * Input Args:
1315 * vm - Virtual Machine
1316 * vcpuid - VCPU ID
1317 * num - number of arguments
1318 * ... - arguments, each of type uint64_t
1319 *
1320 * Output Args: None
1321 *
1322 * Return: None
1323 *
1324 * Sets the first num function input arguments to the values
1325 * given as variable args. Each of the variable args is expected to
1326 * be of type uint64_t.
1327 */
1328void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
1329{
1330 va_list ap;
1331 struct kvm_regs regs;
1332
1333 TEST_ASSERT(num >= 1 && num <= 6, "Unsupported number of args,\n"
1334 " num: %u\n",
1335 num);
1336
1337 va_start(ap, num);
1338 vcpu_regs_get(vm, vcpuid, &regs);
1339
1340 if (num >= 1)
1341 regs.rdi = va_arg(ap, uint64_t);
1342
1343 if (num >= 2)
1344 regs.rsi = va_arg(ap, uint64_t);
1345
1346 if (num >= 3)
1347 regs.rdx = va_arg(ap, uint64_t);
1348
1349 if (num >= 4)
1350 regs.rcx = va_arg(ap, uint64_t);
1351
1352 if (num >= 5)
1353 regs.r8 = va_arg(ap, uint64_t);
1354
1355 if (num >= 6)
1356 regs.r9 = va_arg(ap, uint64_t);
1357
1358 vcpu_regs_set(vm, vcpuid, &regs);
1359 va_end(ap);
1360}
1361
1362/* VM VCPU System Regs Get
1363 * 1200 *
1364 * Input Args: 1201 * Input Args:
1365 * vm - Virtual Machine 1202 * vm - Virtual Machine
@@ -1373,22 +1210,20 @@ void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
1373 * Obtains the current system register state for the VCPU specified by 1210 * Obtains the current system register state for the VCPU specified by
1374 * vcpuid and stores it at the location given by sregs. 1211 * vcpuid and stores it at the location given by sregs.
1375 */ 1212 */
1376void vcpu_sregs_get(struct kvm_vm *vm, 1213void vcpu_sregs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
1377 uint32_t vcpuid, struct kvm_sregs *sregs)
1378{ 1214{
1379 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1215 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1380 int ret; 1216 int ret;
1381 1217
1382 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1218 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1383 1219
1384 /* Get the regs. */
1385 /* Get the regs. */
1386 ret = ioctl(vcpu->fd, KVM_GET_SREGS, sregs); 1220 ret = ioctl(vcpu->fd, KVM_GET_SREGS, sregs);
1387 TEST_ASSERT(ret == 0, "KVM_GET_SREGS failed, rc: %i errno: %i", 1221 TEST_ASSERT(ret == 0, "KVM_GET_SREGS failed, rc: %i errno: %i",
1388 ret, errno); 1222 ret, errno);
1389} 1223}
1390 1224
1391/* VM VCPU System Regs Set 1225/*
1226 * VM VCPU System Regs Set
1392 * 1227 *
1393 * Input Args: 1228 * Input Args:
1394 * vm - Virtual Machine 1229 * vm - Virtual Machine
@@ -1402,27 +1237,25 @@ void vcpu_sregs_get(struct kvm_vm *vm,
1402 * Sets the system regs of the VCPU specified by vcpuid to the values 1237 * Sets the system regs of the VCPU specified by vcpuid to the values
1403 * given by sregs. 1238 * given by sregs.
1404 */ 1239 */
1405void vcpu_sregs_set(struct kvm_vm *vm, 1240void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
1406 uint32_t vcpuid, struct kvm_sregs *sregs)
1407{ 1241{
1408 int ret = _vcpu_sregs_set(vm, vcpuid, sregs); 1242 int ret = _vcpu_sregs_set(vm, vcpuid, sregs);
1409 TEST_ASSERT(ret == 0, "KVM_RUN IOCTL failed, " 1243 TEST_ASSERT(ret == 0, "KVM_RUN IOCTL failed, "
1410 "rc: %i errno: %i", ret, errno); 1244 "rc: %i errno: %i", ret, errno);
1411} 1245}
1412 1246
1413int _vcpu_sregs_set(struct kvm_vm *vm, 1247int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
1414 uint32_t vcpuid, struct kvm_sregs *sregs)
1415{ 1248{
1416 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1249 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1417 int ret; 1250 int ret;
1418 1251
1419 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); 1252 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1420 1253
1421 /* Get the regs. */
1422 return ioctl(vcpu->fd, KVM_SET_SREGS, sregs); 1254 return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);
1423} 1255}
1424 1256
1425/* VCPU Ioctl 1257/*
1258 * VCPU Ioctl
1426 * 1259 *
1427 * Input Args: 1260 * Input Args:
1428 * vm - Virtual Machine 1261 * vm - Virtual Machine
@@ -1434,8 +1267,8 @@ int _vcpu_sregs_set(struct kvm_vm *vm,
1434 * 1267 *
1435 * Issues an arbitrary ioctl on a VCPU fd. 1268 * Issues an arbitrary ioctl on a VCPU fd.
1436 */ 1269 */
1437void vcpu_ioctl(struct kvm_vm *vm, 1270void vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid,
1438 uint32_t vcpuid, unsigned long cmd, void *arg) 1271 unsigned long cmd, void *arg)
1439{ 1272{
1440 struct vcpu *vcpu = vcpu_find(vm, vcpuid); 1273 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1441 int ret; 1274 int ret;
@@ -1447,7 +1280,8 @@ void vcpu_ioctl(struct kvm_vm *vm,
1447 cmd, ret, errno, strerror(errno)); 1280 cmd, ret, errno, strerror(errno));
1448} 1281}
1449 1282
1450/* VM Ioctl 1283/*
1284 * VM Ioctl
1451 * 1285 *
1452 * Input Args: 1286 * Input Args:
1453 * vm - Virtual Machine 1287 * vm - Virtual Machine
@@ -1467,7 +1301,8 @@ void vm_ioctl(struct kvm_vm *vm, unsigned long cmd, void *arg)
1467 cmd, ret, errno, strerror(errno)); 1301 cmd, ret, errno, strerror(errno));
1468} 1302}
1469 1303
1470/* VM Dump 1304/*
1305 * VM Dump
1471 * 1306 *
1472 * Input Args: 1307 * Input Args:
1473 * vm - Virtual Machine 1308 * vm - Virtual Machine
@@ -1514,38 +1349,6 @@ void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
1514 vcpu_dump(stream, vm, vcpu->id, indent + 2); 1349 vcpu_dump(stream, vm, vcpu->id, indent + 2);
1515} 1350}
1516 1351
1517/* VM VCPU Dump
1518 *
1519 * Input Args:
1520 * vm - Virtual Machine
1521 * vcpuid - VCPU ID
1522 * indent - Left margin indent amount
1523 *
1524 * Output Args:
1525 * stream - Output FILE stream
1526 *
1527 * Return: None
1528 *
1529 * Dumps the current state of the VCPU specified by vcpuid, within the VM
1530 * given by vm, to the FILE stream given by stream.
1531 */
1532void vcpu_dump(FILE *stream, struct kvm_vm *vm,
1533 uint32_t vcpuid, uint8_t indent)
1534{
1535 struct kvm_regs regs;
1536 struct kvm_sregs sregs;
1537
1538 fprintf(stream, "%*scpuid: %u\n", indent, "", vcpuid);
1539
1540 fprintf(stream, "%*sregs:\n", indent + 2, "");
1541 vcpu_regs_get(vm, vcpuid, &regs);
1542 regs_dump(stream, &regs, indent + 4);
1543
1544 fprintf(stream, "%*ssregs:\n", indent + 2, "");
1545 vcpu_sregs_get(vm, vcpuid, &sregs);
1546 sregs_dump(stream, &sregs, indent + 4);
1547}
1548
1549/* Known KVM exit reasons */ 1352/* Known KVM exit reasons */
1550static struct exit_reason { 1353static struct exit_reason {
1551 unsigned int reason; 1354 unsigned int reason;
@@ -1576,7 +1379,8 @@ static struct exit_reason {
1576#endif 1379#endif
1577}; 1380};
1578 1381
1579/* Exit Reason String 1382/*
1383 * Exit Reason String
1580 * 1384 *
1581 * Input Args: 1385 * Input Args:
1582 * exit_reason - Exit reason 1386 * exit_reason - Exit reason
@@ -1602,10 +1406,12 @@ const char *exit_reason_str(unsigned int exit_reason)
1602 return "Unknown"; 1406 return "Unknown";
1603} 1407}
1604 1408
1605/* Physical Page Allocate 1409/*
1410 * Physical Contiguous Page Allocator
1606 * 1411 *
1607 * Input Args: 1412 * Input Args:
1608 * vm - Virtual Machine 1413 * vm - Virtual Machine
1414 * num - number of pages
1609 * paddr_min - Physical address minimum 1415 * paddr_min - Physical address minimum
1610 * memslot - Memory region to allocate page from 1416 * memslot - Memory region to allocate page from
1611 * 1417 *
@@ -1614,47 +1420,59 @@ const char *exit_reason_str(unsigned int exit_reason)
1614 * Return: 1420 * Return:
1615 * Starting physical address 1421 * Starting physical address
1616 * 1422 *
1617 * Within the VM specified by vm, locates an available physical page 1423 * Within the VM specified by vm, locates a range of available physical
1618 * at or above paddr_min. If found, the page is marked as in use 1424 * pages at or above paddr_min. If found, the pages are marked as in use
1619 * and its address is returned. A TEST_ASSERT failure occurs if no 1425 * and thier base address is returned. A TEST_ASSERT failure occurs if
1620 * page is available at or above paddr_min. 1426 * not enough pages are available at or above paddr_min.
1621 */ 1427 */
1622vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, 1428vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
1623 vm_paddr_t paddr_min, uint32_t memslot) 1429 vm_paddr_t paddr_min, uint32_t memslot)
1624{ 1430{
1625 struct userspace_mem_region *region; 1431 struct userspace_mem_region *region;
1626 sparsebit_idx_t pg; 1432 sparsebit_idx_t pg, base;
1433
1434 TEST_ASSERT(num > 0, "Must allocate at least one page");
1627 1435
1628 TEST_ASSERT((paddr_min % vm->page_size) == 0, "Min physical address " 1436 TEST_ASSERT((paddr_min % vm->page_size) == 0, "Min physical address "
1629 "not divisible by page size.\n" 1437 "not divisible by page size.\n"
1630 " paddr_min: 0x%lx page_size: 0x%x", 1438 " paddr_min: 0x%lx page_size: 0x%x",
1631 paddr_min, vm->page_size); 1439 paddr_min, vm->page_size);
1632 1440
1633 /* Locate memory region. */
1634 region = memslot2region(vm, memslot); 1441 region = memslot2region(vm, memslot);
1442 base = pg = paddr_min >> vm->page_shift;
1635 1443
1636 /* Locate next available physical page at or above paddr_min. */ 1444 do {
1637 pg = paddr_min >> vm->page_shift; 1445 for (; pg < base + num; ++pg) {
1638 1446 if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
1639 if (!sparsebit_is_set(region->unused_phy_pages, pg)) { 1447 base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
1640 pg = sparsebit_next_set(region->unused_phy_pages, pg); 1448 break;
1641 if (pg == 0) { 1449 }
1642 fprintf(stderr, "No guest physical page available, "
1643 "paddr_min: 0x%lx page_size: 0x%x memslot: %u",
1644 paddr_min, vm->page_size, memslot);
1645 fputs("---- vm dump ----\n", stderr);
1646 vm_dump(stderr, vm, 2);
1647 abort();
1648 } 1450 }
1451 } while (pg && pg != base + num);
1452
1453 if (pg == 0) {
1454 fprintf(stderr, "No guest physical page available, "
1455 "paddr_min: 0x%lx page_size: 0x%x memslot: %u\n",
1456 paddr_min, vm->page_size, memslot);
1457 fputs("---- vm dump ----\n", stderr);
1458 vm_dump(stderr, vm, 2);
1459 abort();
1649 } 1460 }
1650 1461
1651 /* Specify page as in use and return its address. */ 1462 for (pg = base; pg < base + num; ++pg)
1652 sparsebit_clear(region->unused_phy_pages, pg); 1463 sparsebit_clear(region->unused_phy_pages, pg);
1464
1465 return base * vm->page_size;
1466}
1653 1467
1654 return pg * vm->page_size; 1468vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
1469 uint32_t memslot)
1470{
1471 return vm_phy_pages_alloc(vm, 1, paddr_min, memslot);
1655} 1472}
1656 1473
1657/* Address Guest Virtual to Host Virtual 1474/*
1475 * Address Guest Virtual to Host Virtual
1658 * 1476 *
1659 * Input Args: 1477 * Input Args:
1660 * vm - Virtual Machine 1478 * vm - Virtual Machine
@@ -1669,17 +1487,3 @@ void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva)
1669{ 1487{
1670 return addr_gpa2hva(vm, addr_gva2gpa(vm, gva)); 1488 return addr_gpa2hva(vm, addr_gva2gpa(vm, gva));
1671} 1489}
1672
1673void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id,
1674 struct guest_args *args)
1675{
1676 struct kvm_run *run = vcpu_state(vm, vcpu_id);
1677 struct kvm_regs regs;
1678
1679 memset(&regs, 0, sizeof(regs));
1680 vcpu_regs_get(vm, vcpu_id, &regs);
1681
1682 args->port = run->io.port;
1683 args->arg0 = regs.rdi;
1684 args->arg1 = regs.rsi;
1685}
diff --git a/tools/testing/selftests/kvm/lib/kvm_util_internal.h b/tools/testing/selftests/kvm/lib/kvm_util_internal.h
index 542ed606b338..52701db0f253 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util_internal.h
+++ b/tools/testing/selftests/kvm/lib/kvm_util_internal.h
@@ -1,28 +1,29 @@
1/* 1/*
2 * tools/testing/selftests/kvm/lib/kvm_util.c 2 * tools/testing/selftests/kvm/lib/kvm_util_internal.h
3 * 3 *
4 * Copyright (C) 2018, Google LLC. 4 * Copyright (C) 2018, Google LLC.
5 * 5 *
6 * This work is licensed under the terms of the GNU GPL, version 2. 6 * This work is licensed under the terms of the GNU GPL, version 2.
7 */ 7 */
8 8
9#ifndef KVM_UTIL_INTERNAL_H 9#ifndef SELFTEST_KVM_UTIL_INTERNAL_H
10#define KVM_UTIL_INTERNAL_H 1 10#define SELFTEST_KVM_UTIL_INTERNAL_H
11 11
12#include "sparsebit.h" 12#include "sparsebit.h"
13 13
14#define KVM_DEV_PATH "/dev/kvm"
15
14#ifndef BITS_PER_BYTE 16#ifndef BITS_PER_BYTE
15#define BITS_PER_BYTE 8 17#define BITS_PER_BYTE 8
16#endif 18#endif
17 19
18#ifndef BITS_PER_LONG 20#ifndef BITS_PER_LONG
19#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long)) 21#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
20#endif 22#endif
21 23
22#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 24#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
23#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) 25#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
24 26
25/* Concrete definition of struct kvm_vm. */
26struct userspace_mem_region { 27struct userspace_mem_region {
27 struct userspace_mem_region *next, *prev; 28 struct userspace_mem_region *next, *prev;
28 struct kvm_userspace_memory_region region; 29 struct kvm_userspace_memory_region region;
@@ -45,14 +46,16 @@ struct kvm_vm {
45 int mode; 46 int mode;
46 int kvm_fd; 47 int kvm_fd;
47 int fd; 48 int fd;
49 unsigned int pgtable_levels;
48 unsigned int page_size; 50 unsigned int page_size;
49 unsigned int page_shift; 51 unsigned int page_shift;
52 unsigned int pa_bits;
53 unsigned int va_bits;
50 uint64_t max_gfn; 54 uint64_t max_gfn;
51 struct vcpu *vcpu_head; 55 struct vcpu *vcpu_head;
52 struct userspace_mem_region *userspace_mem_region_head; 56 struct userspace_mem_region *userspace_mem_region_head;
53 struct sparsebit *vpages_valid; 57 struct sparsebit *vpages_valid;
54 struct sparsebit *vpages_mapped; 58 struct sparsebit *vpages_mapped;
55
56 bool has_irqchip; 59 bool has_irqchip;
57 bool pgd_created; 60 bool pgd_created;
58 vm_paddr_t pgd; 61 vm_paddr_t pgd;
@@ -60,13 +63,11 @@ struct kvm_vm {
60 vm_vaddr_t tss; 63 vm_vaddr_t tss;
61}; 64};
62 65
63struct vcpu *vcpu_find(struct kvm_vm *vm, 66struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid);
64 uint32_t vcpuid); 67void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot,
65void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot); 68 int gdt_memslot);
66void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent); 69void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
67void regs_dump(FILE *stream, struct kvm_regs *regs, 70void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent);
68 uint8_t indent); 71void sregs_dump(FILE *stream, struct kvm_sregs *sregs, uint8_t indent);
69void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
70 uint8_t indent);
71 72
72#endif 73#endif /* SELFTEST_KVM_UTIL_INTERNAL_H */
diff --git a/tools/testing/selftests/kvm/lib/ucall.c b/tools/testing/selftests/kvm/lib/ucall.c
new file mode 100644
index 000000000000..4777f9bb5194
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/ucall.c
@@ -0,0 +1,144 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * ucall support. A ucall is a "hypercall to userspace".
4 *
5 * Copyright (C) 2018, Red Hat, Inc.
6 */
7#include "kvm_util.h"
8#include "kvm_util_internal.h"
9
10#define UCALL_PIO_PORT ((uint16_t)0x1000)
11
12static ucall_type_t ucall_type;
13static vm_vaddr_t *ucall_exit_mmio_addr;
14
15static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa)
16{
17 if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1))
18 return false;
19
20 virt_pg_map(vm, gpa, gpa, 0);
21
22 ucall_exit_mmio_addr = (vm_vaddr_t *)gpa;
23 sync_global_to_guest(vm, ucall_exit_mmio_addr);
24
25 return true;
26}
27
28void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg)
29{
30 ucall_type = type;
31 sync_global_to_guest(vm, ucall_type);
32
33 if (type == UCALL_PIO)
34 return;
35
36 if (type == UCALL_MMIO) {
37 vm_paddr_t gpa, start, end, step;
38 bool ret;
39
40 if (arg) {
41 gpa = (vm_paddr_t)arg;
42 ret = ucall_mmio_init(vm, gpa);
43 TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa);
44 return;
45 }
46
47 /*
48 * Find an address within the allowed virtual address space,
49 * that does _not_ have a KVM memory region associated with it.
50 * Identity mapping an address like this allows the guest to
51 * access it, but as KVM doesn't know what to do with it, it
52 * will assume it's something userspace handles and exit with
53 * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64.
54 * Here we start with a guess that the addresses around two
55 * thirds of the VA space are unmapped and then work both down
56 * and up from there in 1/6 VA space sized steps.
57 */
58 start = 1ul << (vm->va_bits * 2 / 3);
59 end = 1ul << vm->va_bits;
60 step = 1ul << (vm->va_bits / 6);
61 for (gpa = start; gpa >= 0; gpa -= step) {
62 if (ucall_mmio_init(vm, gpa & ~(vm->page_size - 1)))
63 return;
64 }
65 for (gpa = start + step; gpa < end; gpa += step) {
66 if (ucall_mmio_init(vm, gpa & ~(vm->page_size - 1)))
67 return;
68 }
69 TEST_ASSERT(false, "Can't find a ucall mmio address");
70 }
71}
72
73void ucall_uninit(struct kvm_vm *vm)
74{
75 ucall_type = 0;
76 sync_global_to_guest(vm, ucall_type);
77 ucall_exit_mmio_addr = 0;
78 sync_global_to_guest(vm, ucall_exit_mmio_addr);
79}
80
81static void ucall_pio_exit(struct ucall *uc)
82{
83#ifdef __x86_64__
84 asm volatile("in %[port], %%al"
85 : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax");
86#endif
87}
88
89static void ucall_mmio_exit(struct ucall *uc)
90{
91 *ucall_exit_mmio_addr = (vm_vaddr_t)uc;
92}
93
94void ucall(uint64_t cmd, int nargs, ...)
95{
96 struct ucall uc = {
97 .cmd = cmd,
98 };
99 va_list va;
100 int i;
101
102 nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS;
103
104 va_start(va, nargs);
105 for (i = 0; i < nargs; ++i)
106 uc.args[i] = va_arg(va, uint64_t);
107 va_end(va);
108
109 switch (ucall_type) {
110 case UCALL_PIO:
111 ucall_pio_exit(&uc);
112 break;
113 case UCALL_MMIO:
114 ucall_mmio_exit(&uc);
115 break;
116 };
117}
118
119uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
120{
121 struct kvm_run *run = vcpu_state(vm, vcpu_id);
122
123 memset(uc, 0, sizeof(*uc));
124
125#ifdef __x86_64__
126 if (ucall_type == UCALL_PIO && run->exit_reason == KVM_EXIT_IO &&
127 run->io.port == UCALL_PIO_PORT) {
128 struct kvm_regs regs;
129 vcpu_regs_get(vm, vcpu_id, &regs);
130 memcpy(uc, addr_gva2hva(vm, (vm_vaddr_t)regs.rdi), sizeof(*uc));
131 return uc->cmd;
132 }
133#endif
134 if (ucall_type == UCALL_MMIO && run->exit_reason == KVM_EXIT_MMIO &&
135 run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) {
136 vm_vaddr_t gva;
137 TEST_ASSERT(run->mmio.is_write && run->mmio.len == 8,
138 "Unexpected ucall exit mmio address access");
139 gva = *(vm_vaddr_t *)run->mmio.data;
140 memcpy(uc, addr_gva2hva(vm, gva), sizeof(*uc));
141 }
142
143 return uc->cmd;
144}
diff --git a/tools/testing/selftests/kvm/lib/x86.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
index a3122f1949a8..f28127f4a3af 100644
--- a/tools/testing/selftests/kvm/lib/x86.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * tools/testing/selftests/kvm/lib/x86.c 2 * tools/testing/selftests/kvm/lib/x86_64/processor.c
3 * 3 *
4 * Copyright (C) 2018, Google LLC. 4 * Copyright (C) 2018, Google LLC.
5 * 5 *
@@ -10,8 +10,8 @@
10 10
11#include "test_util.h" 11#include "test_util.h"
12#include "kvm_util.h" 12#include "kvm_util.h"
13#include "kvm_util_internal.h" 13#include "../kvm_util_internal.h"
14#include "x86.h" 14#include "processor.h"
15 15
16/* Minimum physical address used for virtual translation tables. */ 16/* Minimum physical address used for virtual translation tables. */
17#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000 17#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
@@ -231,7 +231,7 @@ void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
231{ 231{
232 int rc; 232 int rc;
233 233
234 TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use " 234 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use "
235 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 235 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
236 236
237 /* If needed, create page map l4 table. */ 237 /* If needed, create page map l4 table. */
@@ -264,7 +264,7 @@ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
264 uint16_t index[4]; 264 uint16_t index[4];
265 struct pageMapL4Entry *pml4e; 265 struct pageMapL4Entry *pml4e;
266 266
267 TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use " 267 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use "
268 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 268 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
269 269
270 TEST_ASSERT((vaddr % vm->page_size) == 0, 270 TEST_ASSERT((vaddr % vm->page_size) == 0,
@@ -551,7 +551,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
551 struct pageTableEntry *pte; 551 struct pageTableEntry *pte;
552 void *hva; 552 void *hva;
553 553
554 TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use " 554 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use "
555 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 555 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
556 556
557 index[0] = (gva >> 12) & 0x1ffu; 557 index[0] = (gva >> 12) & 0x1ffu;
@@ -624,9 +624,9 @@ void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
624 kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot); 624 kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
625 625
626 switch (vm->mode) { 626 switch (vm->mode) {
627 case VM_MODE_FLAT48PG: 627 case VM_MODE_P52V48_4K:
628 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; 628 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
629 sregs.cr4 |= X86_CR4_PAE; 629 sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
630 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); 630 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
631 631
632 kvm_seg_set_unusable(&sregs.ldt); 632 kvm_seg_set_unusable(&sregs.ldt);
@@ -672,6 +672,102 @@ void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
672 vcpu_set_mp_state(vm, vcpuid, &mp_state); 672 vcpu_set_mp_state(vm, vcpuid, &mp_state);
673} 673}
674 674
675/* Allocate an instance of struct kvm_cpuid2
676 *
677 * Input Args: None
678 *
679 * Output Args: None
680 *
681 * Return: A pointer to the allocated struct. The caller is responsible
682 * for freeing this struct.
683 *
684 * Since kvm_cpuid2 uses a 0-length array to allow a the size of the
685 * array to be decided at allocation time, allocation is slightly
686 * complicated. This function uses a reasonable default length for
687 * the array and performs the appropriate allocation.
688 */
689static struct kvm_cpuid2 *allocate_kvm_cpuid2(void)
690{
691 struct kvm_cpuid2 *cpuid;
692 int nent = 100;
693 size_t size;
694
695 size = sizeof(*cpuid);
696 size += nent * sizeof(struct kvm_cpuid_entry2);
697 cpuid = malloc(size);
698 if (!cpuid) {
699 perror("malloc");
700 abort();
701 }
702
703 cpuid->nent = nent;
704
705 return cpuid;
706}
707
708/* KVM Supported CPUID Get
709 *
710 * Input Args: None
711 *
712 * Output Args:
713 *
714 * Return: The supported KVM CPUID
715 *
716 * Get the guest CPUID supported by KVM.
717 */
718struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
719{
720 static struct kvm_cpuid2 *cpuid;
721 int ret;
722 int kvm_fd;
723
724 if (cpuid)
725 return cpuid;
726
727 cpuid = allocate_kvm_cpuid2();
728 kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
729 if (kvm_fd < 0)
730 exit(KSFT_SKIP);
731
732 ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
733 TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n",
734 ret, errno);
735
736 close(kvm_fd);
737 return cpuid;
738}
739
740/* Locate a cpuid entry.
741 *
742 * Input Args:
743 * cpuid: The cpuid.
744 * function: The function of the cpuid entry to find.
745 *
746 * Output Args: None
747 *
748 * Return: A pointer to the cpuid entry. Never returns NULL.
749 */
750struct kvm_cpuid_entry2 *
751kvm_get_supported_cpuid_index(uint32_t function, uint32_t index)
752{
753 struct kvm_cpuid2 *cpuid;
754 struct kvm_cpuid_entry2 *entry = NULL;
755 int i;
756
757 cpuid = kvm_get_supported_cpuid();
758 for (i = 0; i < cpuid->nent; i++) {
759 if (cpuid->entries[i].function == function &&
760 cpuid->entries[i].index == index) {
761 entry = &cpuid->entries[i];
762 break;
763 }
764 }
765
766 TEST_ASSERT(entry, "Guest CPUID entry not found: (EAX=%x, ECX=%x).",
767 function, index);
768 return entry;
769}
770
675/* VM VCPU CPUID Set 771/* VM VCPU CPUID Set
676 * 772 *
677 * Input Args: 773 * Input Args:
@@ -698,6 +794,7 @@ void vcpu_set_cpuid(struct kvm_vm *vm,
698 rc, errno); 794 rc, errno);
699 795
700} 796}
797
701/* Create a VM with reasonable defaults 798/* Create a VM with reasonable defaults
702 * 799 *
703 * Input Args: 800 * Input Args:
@@ -726,7 +823,7 @@ struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
726 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2; 823 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
727 824
728 /* Create VM */ 825 /* Create VM */
729 vm = vm_create(VM_MODE_FLAT48PG, 826 vm = vm_create(VM_MODE_P52V48_4K,
730 DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, 827 DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
731 O_RDWR); 828 O_RDWR);
732 829
@@ -742,6 +839,154 @@ struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
742 return vm; 839 return vm;
743} 840}
744 841
842/* VCPU Get MSR
843 *
844 * Input Args:
845 * vm - Virtual Machine
846 * vcpuid - VCPU ID
847 * msr_index - Index of MSR
848 *
849 * Output Args: None
850 *
851 * Return: On success, value of the MSR. On failure a TEST_ASSERT is produced.
852 *
853 * Get value of MSR for VCPU.
854 */
855uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
856{
857 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
858 struct {
859 struct kvm_msrs header;
860 struct kvm_msr_entry entry;
861 } buffer = {};
862 int r;
863
864 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
865 buffer.header.nmsrs = 1;
866 buffer.entry.index = msr_index;
867 r = ioctl(vcpu->fd, KVM_GET_MSRS, &buffer.header);
868 TEST_ASSERT(r == 1, "KVM_GET_MSRS IOCTL failed,\n"
869 " rc: %i errno: %i", r, errno);
870
871 return buffer.entry.data;
872}
873
874/* VCPU Set MSR
875 *
876 * Input Args:
877 * vm - Virtual Machine
878 * vcpuid - VCPU ID
879 * msr_index - Index of MSR
880 * msr_value - New value of MSR
881 *
882 * Output Args: None
883 *
884 * Return: On success, nothing. On failure a TEST_ASSERT is produced.
885 *
886 * Set value of MSR for VCPU.
887 */
888void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
889 uint64_t msr_value)
890{
891 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
892 struct {
893 struct kvm_msrs header;
894 struct kvm_msr_entry entry;
895 } buffer = {};
896 int r;
897
898 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
899 memset(&buffer, 0, sizeof(buffer));
900 buffer.header.nmsrs = 1;
901 buffer.entry.index = msr_index;
902 buffer.entry.data = msr_value;
903 r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
904 TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
905 " rc: %i errno: %i", r, errno);
906}
907
908/* VM VCPU Args Set
909 *
910 * Input Args:
911 * vm - Virtual Machine
912 * vcpuid - VCPU ID
913 * num - number of arguments
914 * ... - arguments, each of type uint64_t
915 *
916 * Output Args: None
917 *
918 * Return: None
919 *
920 * Sets the first num function input arguments to the values
921 * given as variable args. Each of the variable args is expected to
922 * be of type uint64_t.
923 */
924void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
925{
926 va_list ap;
927 struct kvm_regs regs;
928
929 TEST_ASSERT(num >= 1 && num <= 6, "Unsupported number of args,\n"
930 " num: %u\n",
931 num);
932
933 va_start(ap, num);
934 vcpu_regs_get(vm, vcpuid, &regs);
935
936 if (num >= 1)
937 regs.rdi = va_arg(ap, uint64_t);
938
939 if (num >= 2)
940 regs.rsi = va_arg(ap, uint64_t);
941
942 if (num >= 3)
943 regs.rdx = va_arg(ap, uint64_t);
944
945 if (num >= 4)
946 regs.rcx = va_arg(ap, uint64_t);
947
948 if (num >= 5)
949 regs.r8 = va_arg(ap, uint64_t);
950
951 if (num >= 6)
952 regs.r9 = va_arg(ap, uint64_t);
953
954 vcpu_regs_set(vm, vcpuid, &regs);
955 va_end(ap);
956}
957
958/*
959 * VM VCPU Dump
960 *
961 * Input Args:
962 * vm - Virtual Machine
963 * vcpuid - VCPU ID
964 * indent - Left margin indent amount
965 *
966 * Output Args:
967 * stream - Output FILE stream
968 *
969 * Return: None
970 *
971 * Dumps the current state of the VCPU specified by vcpuid, within the VM
972 * given by vm, to the FILE stream given by stream.
973 */
974void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid, uint8_t indent)
975{
976 struct kvm_regs regs;
977 struct kvm_sregs sregs;
978
979 fprintf(stream, "%*scpuid: %u\n", indent, "", vcpuid);
980
981 fprintf(stream, "%*sregs:\n", indent + 2, "");
982 vcpu_regs_get(vm, vcpuid, &regs);
983 regs_dump(stream, &regs, indent + 4);
984
985 fprintf(stream, "%*ssregs:\n", indent + 2, "");
986 vcpu_sregs_get(vm, vcpuid, &sregs);
987 sregs_dump(stream, &sregs, indent + 4);
988}
989
745struct kvm_x86_state { 990struct kvm_x86_state {
746 struct kvm_vcpu_events events; 991 struct kvm_vcpu_events events;
747 struct kvm_mp_state mp_state; 992 struct kvm_mp_state mp_state;
diff --git a/tools/testing/selftests/kvm/lib/vmx.c b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
index b987c3c970eb..771ba6bf751c 100644
--- a/tools/testing/selftests/kvm/lib/vmx.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * tools/testing/selftests/kvm/lib/x86.c 2 * tools/testing/selftests/kvm/lib/x86_64/vmx.c
3 * 3 *
4 * Copyright (C) 2018, Google LLC. 4 * Copyright (C) 2018, Google LLC.
5 * 5 *
@@ -10,9 +10,11 @@
10 10
11#include "test_util.h" 11#include "test_util.h"
12#include "kvm_util.h" 12#include "kvm_util.h"
13#include "x86.h" 13#include "processor.h"
14#include "vmx.h" 14#include "vmx.h"
15 15
16bool enable_evmcs;
17
16/* Allocate memory regions for nested VMX tests. 18/* Allocate memory regions for nested VMX tests.
17 * 19 *
18 * Input Args: 20 * Input Args:
@@ -62,6 +64,20 @@ vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva)
62 vmx->vmwrite_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmwrite); 64 vmx->vmwrite_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmwrite);
63 memset(vmx->vmwrite_hva, 0, getpagesize()); 65 memset(vmx->vmwrite_hva, 0, getpagesize());
64 66
67 /* Setup of a region of guest memory for the VP Assist page. */
68 vmx->vp_assist = (void *)vm_vaddr_alloc(vm, getpagesize(),
69 0x10000, 0, 0);
70 vmx->vp_assist_hva = addr_gva2hva(vm, (uintptr_t)vmx->vp_assist);
71 vmx->vp_assist_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vp_assist);
72
73 /* Setup of a region of guest memory for the enlightened VMCS. */
74 vmx->enlightened_vmcs = (void *)vm_vaddr_alloc(vm, getpagesize(),
75 0x10000, 0, 0);
76 vmx->enlightened_vmcs_hva =
77 addr_gva2hva(vm, (uintptr_t)vmx->enlightened_vmcs);
78 vmx->enlightened_vmcs_gpa =
79 addr_gva2gpa(vm, (uintptr_t)vmx->enlightened_vmcs);
80
65 *p_vmx_gva = vmx_gva; 81 *p_vmx_gva = vmx_gva;
66 return vmx; 82 return vmx;
67} 83}
@@ -107,18 +123,31 @@ bool prepare_for_vmx_operation(struct vmx_pages *vmx)
107 if (vmxon(vmx->vmxon_gpa)) 123 if (vmxon(vmx->vmxon_gpa))
108 return false; 124 return false;
109 125
110 /* Load a VMCS. */ 126 return true;
111 *(uint32_t *)(vmx->vmcs) = vmcs_revision(); 127}
112 if (vmclear(vmx->vmcs_gpa))
113 return false;
114
115 if (vmptrld(vmx->vmcs_gpa))
116 return false;
117 128
118 /* Setup shadow VMCS, do not load it yet. */ 129bool load_vmcs(struct vmx_pages *vmx)
119 *(uint32_t *)(vmx->shadow_vmcs) = vmcs_revision() | 0x80000000ul; 130{
120 if (vmclear(vmx->shadow_vmcs_gpa)) 131 if (!enable_evmcs) {
121 return false; 132 /* Load a VMCS. */
133 *(uint32_t *)(vmx->vmcs) = vmcs_revision();
134 if (vmclear(vmx->vmcs_gpa))
135 return false;
136
137 if (vmptrld(vmx->vmcs_gpa))
138 return false;
139
140 /* Setup shadow VMCS, do not load it yet. */
141 *(uint32_t *)(vmx->shadow_vmcs) =
142 vmcs_revision() | 0x80000000ul;
143 if (vmclear(vmx->shadow_vmcs_gpa))
144 return false;
145 } else {
146 if (evmcs_vmptrld(vmx->enlightened_vmcs_gpa,
147 vmx->enlightened_vmcs))
148 return false;
149 current_evmcs->revision_id = vmcs_revision();
150 }
122 151
123 return true; 152 return true;
124} 153}
diff --git a/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c
index 11ec358bf969..d503a51fad30 100644
--- a/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c
+++ b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c
@@ -17,7 +17,7 @@
17#include "test_util.h" 17#include "test_util.h"
18 18
19#include "kvm_util.h" 19#include "kvm_util.h"
20#include "x86.h" 20#include "processor.h"
21 21
22#define X86_FEATURE_XSAVE (1<<26) 22#define X86_FEATURE_XSAVE (1<<26)
23#define X86_FEATURE_OSXSAVE (1<<27) 23#define X86_FEATURE_OSXSAVE (1<<27)
@@ -67,6 +67,7 @@ int main(int argc, char *argv[])
67 struct kvm_vm *vm; 67 struct kvm_vm *vm;
68 struct kvm_sregs sregs; 68 struct kvm_sregs sregs;
69 struct kvm_cpuid_entry2 *entry; 69 struct kvm_cpuid_entry2 *entry;
70 struct ucall uc;
70 int rc; 71 int rc;
71 72
72 entry = kvm_get_supported_cpuid_entry(1); 73 entry = kvm_get_supported_cpuid_entry(1);
@@ -87,21 +88,20 @@ int main(int argc, char *argv[])
87 rc = _vcpu_run(vm, VCPU_ID); 88 rc = _vcpu_run(vm, VCPU_ID);
88 89
89 if (run->exit_reason == KVM_EXIT_IO) { 90 if (run->exit_reason == KVM_EXIT_IO) {
90 switch (run->io.port) { 91 switch (get_ucall(vm, VCPU_ID, &uc)) {
91 case GUEST_PORT_SYNC: 92 case UCALL_SYNC:
92 /* emulate hypervisor clearing CR4.OSXSAVE */ 93 /* emulate hypervisor clearing CR4.OSXSAVE */
93 vcpu_sregs_get(vm, VCPU_ID, &sregs); 94 vcpu_sregs_get(vm, VCPU_ID, &sregs);
94 sregs.cr4 &= ~X86_CR4_OSXSAVE; 95 sregs.cr4 &= ~X86_CR4_OSXSAVE;
95 vcpu_sregs_set(vm, VCPU_ID, &sregs); 96 vcpu_sregs_set(vm, VCPU_ID, &sregs);
96 break; 97 break;
97 case GUEST_PORT_ABORT: 98 case UCALL_ABORT:
98 TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit."); 99 TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
99 break; 100 break;
100 case GUEST_PORT_DONE: 101 case UCALL_DONE:
101 goto done; 102 goto done;
102 default: 103 default:
103 TEST_ASSERT(false, "Unknown port 0x%x.", 104 TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
104 run->io.port);
105 } 105 }
106 } 106 }
107 } 107 }
diff --git a/tools/testing/selftests/kvm/x86_64/evmcs_test.c b/tools/testing/selftests/kvm/x86_64/evmcs_test.c
new file mode 100644
index 000000000000..92c2cfd1b182
--- /dev/null
+++ b/tools/testing/selftests/kvm/x86_64/evmcs_test.c
@@ -0,0 +1,160 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2018, Red Hat, Inc.
4 *
5 * Tests for Enlightened VMCS, including nested guest state.
6 */
7#define _GNU_SOURCE /* for program_invocation_short_name */
8#include <fcntl.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/ioctl.h>
13
14#include "test_util.h"
15
16#include "kvm_util.h"
17
18#include "vmx.h"
19
20#define VCPU_ID 5
21
22static bool have_nested_state;
23
24void l2_guest_code(void)
25{
26 GUEST_SYNC(6);
27
28 GUEST_SYNC(7);
29
30 /* Done, exit to L1 and never come back. */
31 vmcall();
32}
33
34void l1_guest_code(struct vmx_pages *vmx_pages)
35{
36#define L2_GUEST_STACK_SIZE 64
37 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
38
39 enable_vp_assist(vmx_pages->vp_assist_gpa, vmx_pages->vp_assist);
40
41 GUEST_ASSERT(vmx_pages->vmcs_gpa);
42 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
43 GUEST_SYNC(3);
44 GUEST_ASSERT(load_vmcs(vmx_pages));
45 GUEST_ASSERT(vmptrstz() == vmx_pages->enlightened_vmcs_gpa);
46
47 GUEST_SYNC(4);
48 GUEST_ASSERT(vmptrstz() == vmx_pages->enlightened_vmcs_gpa);
49
50 prepare_vmcs(vmx_pages, l2_guest_code,
51 &l2_guest_stack[L2_GUEST_STACK_SIZE]);
52
53 GUEST_SYNC(5);
54 GUEST_ASSERT(vmptrstz() == vmx_pages->enlightened_vmcs_gpa);
55 GUEST_ASSERT(!vmlaunch());
56 GUEST_ASSERT(vmptrstz() == vmx_pages->enlightened_vmcs_gpa);
57 GUEST_SYNC(8);
58 GUEST_ASSERT(!vmresume());
59 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
60 GUEST_SYNC(9);
61}
62
63void guest_code(struct vmx_pages *vmx_pages)
64{
65 GUEST_SYNC(1);
66 GUEST_SYNC(2);
67
68 if (vmx_pages)
69 l1_guest_code(vmx_pages);
70
71 GUEST_DONE();
72}
73
74int main(int argc, char *argv[])
75{
76 struct vmx_pages *vmx_pages = NULL;
77 vm_vaddr_t vmx_pages_gva = 0;
78
79 struct kvm_regs regs1, regs2;
80 struct kvm_vm *vm;
81 struct kvm_run *run;
82 struct kvm_x86_state *state;
83 struct ucall uc;
84 int stage;
85 uint16_t evmcs_ver;
86 struct kvm_enable_cap enable_evmcs_cap = {
87 .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
88 .args[0] = (unsigned long)&evmcs_ver
89 };
90
91 struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
92
93 /* Create VM */
94 vm = vm_create_default(VCPU_ID, 0, guest_code);
95
96 vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
97
98 if (!kvm_check_cap(KVM_CAP_NESTED_STATE) ||
99 !kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
100 printf("capabilities not available, skipping test\n");
101 exit(KSFT_SKIP);
102 }
103
104 vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
105
106 run = vcpu_state(vm, VCPU_ID);
107
108 vcpu_regs_get(vm, VCPU_ID, &regs1);
109
110 vmx_pages = vcpu_alloc_vmx(vm, &vmx_pages_gva);
111 vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_gva);
112
113 for (stage = 1;; stage++) {
114 _vcpu_run(vm, VCPU_ID);
115 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
116 "Unexpected exit reason: %u (%s),\n",
117 run->exit_reason,
118 exit_reason_str(run->exit_reason));
119
120 memset(&regs1, 0, sizeof(regs1));
121 vcpu_regs_get(vm, VCPU_ID, &regs1);
122 switch (get_ucall(vm, VCPU_ID, &uc)) {
123 case UCALL_ABORT:
124 TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0],
125 __FILE__, uc.args[1]);
126 /* NOT REACHED */
127 case UCALL_SYNC:
128 break;
129 case UCALL_DONE:
130 goto done;
131 default:
132 TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
133 }
134
135 /* UCALL_SYNC is handled here. */
136 TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
137 uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx",
138 stage, (ulong)uc.args[1]);
139
140 state = vcpu_save_state(vm, VCPU_ID);
141 kvm_vm_release(vm);
142
143 /* Restore state in a new VM. */
144 kvm_vm_restart(vm, O_RDWR);
145 vm_vcpu_add(vm, VCPU_ID, 0, 0);
146 vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
147 vcpu_load_state(vm, VCPU_ID, state);
148 run = vcpu_state(vm, VCPU_ID);
149 free(state);
150
151 memset(&regs2, 0, sizeof(regs2));
152 vcpu_regs_get(vm, VCPU_ID, &regs2);
153 TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
154 "Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
155 (ulong) regs2.rdi, (ulong) regs2.rsi);
156 }
157
158done:
159 kvm_vm_free(vm);
160}
diff --git a/tools/testing/selftests/kvm/platform_info_test.c b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
index 3764e7121265..eb3e7a838cb4 100644
--- a/tools/testing/selftests/kvm/platform_info_test.c
+++ b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
@@ -19,7 +19,7 @@
19 19
20#include "test_util.h" 20#include "test_util.h"
21#include "kvm_util.h" 21#include "kvm_util.h"
22#include "x86.h" 22#include "processor.h"
23 23
24#define VCPU_ID 0 24#define VCPU_ID 0
25#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00 25#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
@@ -48,7 +48,7 @@ static void set_msr_platform_info_enabled(struct kvm_vm *vm, bool enable)
48static void test_msr_platform_info_enabled(struct kvm_vm *vm) 48static void test_msr_platform_info_enabled(struct kvm_vm *vm)
49{ 49{
50 struct kvm_run *run = vcpu_state(vm, VCPU_ID); 50 struct kvm_run *run = vcpu_state(vm, VCPU_ID);
51 struct guest_args args; 51 struct ucall uc;
52 52
53 set_msr_platform_info_enabled(vm, true); 53 set_msr_platform_info_enabled(vm, true);
54 vcpu_run(vm, VCPU_ID); 54 vcpu_run(vm, VCPU_ID);
@@ -56,11 +56,11 @@ static void test_msr_platform_info_enabled(struct kvm_vm *vm)
56 "Exit_reason other than KVM_EXIT_IO: %u (%s),\n", 56 "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
57 run->exit_reason, 57 run->exit_reason,
58 exit_reason_str(run->exit_reason)); 58 exit_reason_str(run->exit_reason));
59 guest_args_read(vm, VCPU_ID, &args); 59 get_ucall(vm, VCPU_ID, &uc);
60 TEST_ASSERT(args.port == GUEST_PORT_SYNC, 60 TEST_ASSERT(uc.cmd == UCALL_SYNC,
61 "Received IO from port other than PORT_HOST_SYNC: %u\n", 61 "Received ucall other than UCALL_SYNC: %u\n",
62 run->io.port); 62 ucall);
63 TEST_ASSERT((args.arg1 & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) == 63 TEST_ASSERT((uc.args[1] & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
64 MSR_PLATFORM_INFO_MAX_TURBO_RATIO, 64 MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
65 "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.", 65 "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
66 MSR_PLATFORM_INFO_MAX_TURBO_RATIO); 66 MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
diff --git a/tools/testing/selftests/kvm/set_sregs_test.c b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c
index 881419d5746e..35640e8e95bc 100644
--- a/tools/testing/selftests/kvm/set_sregs_test.c
+++ b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c
@@ -22,7 +22,7 @@
22#include "test_util.h" 22#include "test_util.h"
23 23
24#include "kvm_util.h" 24#include "kvm_util.h"
25#include "x86.h" 25#include "processor.h"
26 26
27#define VCPU_ID 5 27#define VCPU_ID 5
28 28
diff --git a/tools/testing/selftests/kvm/state_test.c b/tools/testing/selftests/kvm/x86_64/state_test.c
index 900e3e9dfb9f..03da41f0f736 100644
--- a/tools/testing/selftests/kvm/state_test.c
+++ b/tools/testing/selftests/kvm/x86_64/state_test.c
@@ -17,7 +17,7 @@
17#include "test_util.h" 17#include "test_util.h"
18 18
19#include "kvm_util.h" 19#include "kvm_util.h"
20#include "x86.h" 20#include "processor.h"
21#include "vmx.h" 21#include "vmx.h"
22 22
23#define VCPU_ID 5 23#define VCPU_ID 5
@@ -26,20 +26,20 @@ static bool have_nested_state;
26 26
27void l2_guest_code(void) 27void l2_guest_code(void)
28{ 28{
29 GUEST_SYNC(5); 29 GUEST_SYNC(6);
30 30
31 /* Exit to L1 */ 31 /* Exit to L1 */
32 vmcall(); 32 vmcall();
33 33
34 /* L1 has now set up a shadow VMCS for us. */ 34 /* L1 has now set up a shadow VMCS for us. */
35 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee); 35 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
36 GUEST_SYNC(9); 36 GUEST_SYNC(10);
37 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee); 37 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
38 GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0fffee)); 38 GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0fffee));
39 GUEST_SYNC(10); 39 GUEST_SYNC(11);
40 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0fffee); 40 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0fffee);
41 GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0ffffee)); 41 GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0ffffee));
42 GUEST_SYNC(11); 42 GUEST_SYNC(12);
43 43
44 /* Done, exit to L1 and never come back. */ 44 /* Done, exit to L1 and never come back. */
45 vmcall(); 45 vmcall();
@@ -52,15 +52,17 @@ void l1_guest_code(struct vmx_pages *vmx_pages)
52 52
53 GUEST_ASSERT(vmx_pages->vmcs_gpa); 53 GUEST_ASSERT(vmx_pages->vmcs_gpa);
54 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 54 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
55 GUEST_SYNC(3);
56 GUEST_ASSERT(load_vmcs(vmx_pages));
55 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa); 57 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
56 58
57 GUEST_SYNC(3); 59 GUEST_SYNC(4);
58 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa); 60 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
59 61
60 prepare_vmcs(vmx_pages, l2_guest_code, 62 prepare_vmcs(vmx_pages, l2_guest_code,
61 &l2_guest_stack[L2_GUEST_STACK_SIZE]); 63 &l2_guest_stack[L2_GUEST_STACK_SIZE]);
62 64
63 GUEST_SYNC(4); 65 GUEST_SYNC(5);
64 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa); 66 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
65 GUEST_ASSERT(!vmlaunch()); 67 GUEST_ASSERT(!vmlaunch());
66 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa); 68 GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
@@ -72,7 +74,7 @@ void l1_guest_code(struct vmx_pages *vmx_pages)
72 GUEST_ASSERT(!vmresume()); 74 GUEST_ASSERT(!vmresume());
73 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL); 75 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
74 76
75 GUEST_SYNC(6); 77 GUEST_SYNC(7);
76 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL); 78 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
77 79
78 GUEST_ASSERT(!vmresume()); 80 GUEST_ASSERT(!vmresume());
@@ -85,12 +87,12 @@ void l1_guest_code(struct vmx_pages *vmx_pages)
85 87
86 GUEST_ASSERT(!vmptrld(vmx_pages->shadow_vmcs_gpa)); 88 GUEST_ASSERT(!vmptrld(vmx_pages->shadow_vmcs_gpa));
87 GUEST_ASSERT(vmlaunch()); 89 GUEST_ASSERT(vmlaunch());
88 GUEST_SYNC(7); 90 GUEST_SYNC(8);
89 GUEST_ASSERT(vmlaunch()); 91 GUEST_ASSERT(vmlaunch());
90 GUEST_ASSERT(vmresume()); 92 GUEST_ASSERT(vmresume());
91 93
92 vmwrite(GUEST_RIP, 0xc0ffee); 94 vmwrite(GUEST_RIP, 0xc0ffee);
93 GUEST_SYNC(8); 95 GUEST_SYNC(9);
94 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee); 96 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
95 97
96 GUEST_ASSERT(!vmptrld(vmx_pages->vmcs_gpa)); 98 GUEST_ASSERT(!vmptrld(vmx_pages->vmcs_gpa));
@@ -101,7 +103,7 @@ void l1_guest_code(struct vmx_pages *vmx_pages)
101 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee); 103 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee);
102 GUEST_ASSERT(vmlaunch()); 104 GUEST_ASSERT(vmlaunch());
103 GUEST_ASSERT(vmresume()); 105 GUEST_ASSERT(vmresume());
104 GUEST_SYNC(12); 106 GUEST_SYNC(13);
105 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee); 107 GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee);
106 GUEST_ASSERT(vmlaunch()); 108 GUEST_ASSERT(vmlaunch());
107 GUEST_ASSERT(vmresume()); 109 GUEST_ASSERT(vmresume());
@@ -127,6 +129,7 @@ int main(int argc, char *argv[])
127 struct kvm_vm *vm; 129 struct kvm_vm *vm;
128 struct kvm_run *run; 130 struct kvm_run *run;
129 struct kvm_x86_state *state; 131 struct kvm_x86_state *state;
132 struct ucall uc;
130 int stage; 133 int stage;
131 134
132 struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); 135 struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
@@ -155,23 +158,23 @@ int main(int argc, char *argv[])
155 158
156 memset(&regs1, 0, sizeof(regs1)); 159 memset(&regs1, 0, sizeof(regs1));
157 vcpu_regs_get(vm, VCPU_ID, &regs1); 160 vcpu_regs_get(vm, VCPU_ID, &regs1);
158 switch (run->io.port) { 161 switch (get_ucall(vm, VCPU_ID, &uc)) {
159 case GUEST_PORT_ABORT: 162 case UCALL_ABORT:
160 TEST_ASSERT(false, "%s at %s:%d", (const char *) regs1.rdi, 163 TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0],
161 __FILE__, regs1.rsi); 164 __FILE__, uc.args[1]);
162 /* NOT REACHED */ 165 /* NOT REACHED */
163 case GUEST_PORT_SYNC: 166 case UCALL_SYNC:
164 break; 167 break;
165 case GUEST_PORT_DONE: 168 case UCALL_DONE:
166 goto done; 169 goto done;
167 default: 170 default:
168 TEST_ASSERT(false, "Unknown port 0x%x.", run->io.port); 171 TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
169 } 172 }
170 173
171 /* PORT_SYNC is handled here. */ 174 /* UCALL_SYNC is handled here. */
172 TEST_ASSERT(!strcmp((const char *)regs1.rdi, "hello") && 175 TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
173 regs1.rsi == stage, "Unexpected register values vmexit #%lx, got %lx", 176 uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx",
174 stage, (ulong) regs1.rsi); 177 stage, (ulong)uc.args[1]);
175 178
176 state = vcpu_save_state(vm, VCPU_ID); 179 state = vcpu_save_state(vm, VCPU_ID);
177 kvm_vm_release(vm); 180 kvm_vm_release(vm);
diff --git a/tools/testing/selftests/kvm/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c
index 213343e5dff9..c8478ce9ea77 100644
--- a/tools/testing/selftests/kvm/sync_regs_test.c
+++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c
@@ -19,7 +19,7 @@
19 19
20#include "test_util.h" 20#include "test_util.h"
21#include "kvm_util.h" 21#include "kvm_util.h"
22#include "x86.h" 22#include "processor.h"
23 23
24#define VCPU_ID 5 24#define VCPU_ID 5
25 25
diff --git a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c
index 49bcc68b0235..18fa64db0d7a 100644
--- a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
+++ b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * gtests/tests/vmx_tsc_adjust_test.c 2 * vmx_tsc_adjust_test
3 * 3 *
4 * Copyright (C) 2018, Google LLC. 4 * Copyright (C) 2018, Google LLC.
5 * 5 *
@@ -22,13 +22,13 @@
22 22
23#include "test_util.h" 23#include "test_util.h"
24#include "kvm_util.h" 24#include "kvm_util.h"
25#include "x86.h" 25#include "processor.h"
26#include "vmx.h" 26#include "vmx.h"
27 27
28#include <string.h> 28#include <string.h>
29#include <sys/ioctl.h> 29#include <sys/ioctl.h>
30 30
31#include "../kselftest.h" 31#include "kselftest.h"
32 32
33#ifndef MSR_IA32_TSC_ADJUST 33#ifndef MSR_IA32_TSC_ADJUST
34#define MSR_IA32_TSC_ADJUST 0x3b 34#define MSR_IA32_TSC_ADJUST 0x3b
@@ -94,6 +94,7 @@ static void l1_guest_code(struct vmx_pages *vmx_pages)
94 check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE); 94 check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
95 95
96 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 96 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
97 GUEST_ASSERT(load_vmcs(vmx_pages));
97 98
98 /* Prepare the VMCS for L2 execution. */ 99 /* Prepare the VMCS for L2 execution. */
99 prepare_vmcs(vmx_pages, l2_guest_code, 100 prepare_vmcs(vmx_pages, l2_guest_code,
@@ -146,26 +147,25 @@ int main(int argc, char *argv[])
146 147
147 for (;;) { 148 for (;;) {
148 volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); 149 volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
149 struct guest_args args; 150 struct ucall uc;
150 151
151 vcpu_run(vm, VCPU_ID); 152 vcpu_run(vm, VCPU_ID);
152 guest_args_read(vm, VCPU_ID, &args);
153 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, 153 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
154 "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", 154 "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
155 run->exit_reason, 155 run->exit_reason,
156 exit_reason_str(run->exit_reason)); 156 exit_reason_str(run->exit_reason));
157 157
158 switch (args.port) { 158 switch (get_ucall(vm, VCPU_ID, &uc)) {
159 case GUEST_PORT_ABORT: 159 case UCALL_ABORT:
160 TEST_ASSERT(false, "%s", (const char *) args.arg0); 160 TEST_ASSERT(false, "%s", (const char *)uc.args[0]);
161 /* NOT REACHED */ 161 /* NOT REACHED */
162 case GUEST_PORT_SYNC: 162 case UCALL_SYNC:
163 report(args.arg1); 163 report(uc.args[1]);
164 break; 164 break;
165 case GUEST_PORT_DONE: 165 case UCALL_DONE:
166 goto done; 166 goto done;
167 default: 167 default:
168 TEST_ASSERT(false, "Unknown port 0x%x.", args.port); 168 TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
169 } 169 }
170 } 170 }
171 171
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 78b24cf76f40..8cf22b3c2563 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -14,3 +14,4 @@ udpgso_bench_rx
14udpgso_bench_tx 14udpgso_bench_tx
15tcp_inq 15tcp_inq
16tls 16tls
17ip_defrag
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 919aa2ac00af..256d82d5fa87 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -5,13 +5,13 @@ CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
5CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
6 6
7TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh 7TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
8TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh 8TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh
9TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh 9TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh
10TEST_PROGS_EXTENDED := in_netns.sh 10TEST_PROGS_EXTENDED := in_netns.sh
11TEST_GEN_FILES = socket 11TEST_GEN_FILES = socket
12TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy 12TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
13TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd 13TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd
14TEST_GEN_FILES += udpgso udpgso_bench_tx udpgso_bench_rx 14TEST_GEN_FILES += udpgso udpgso_bench_tx udpgso_bench_rx ip_defrag
15TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa 15TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
16TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls 16TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
17 17
diff --git a/tools/testing/selftests/net/fib-onlink-tests.sh b/tools/testing/selftests/net/fib-onlink-tests.sh
index 3991ad1a368d..864f865eee55 100755
--- a/tools/testing/selftests/net/fib-onlink-tests.sh
+++ b/tools/testing/selftests/net/fib-onlink-tests.sh
@@ -167,8 +167,8 @@ setup()
167 # add vrf table 167 # add vrf table
168 ip li add ${VRF} type vrf table ${VRF_TABLE} 168 ip li add ${VRF} type vrf table ${VRF_TABLE}
169 ip li set ${VRF} up 169 ip li set ${VRF} up
170 ip ro add table ${VRF_TABLE} unreachable default 170 ip ro add table ${VRF_TABLE} unreachable default metric 8192
171 ip -6 ro add table ${VRF_TABLE} unreachable default 171 ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192
172 172
173 # create test interfaces 173 # create test interfaces
174 ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]} 174 ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
@@ -185,20 +185,20 @@ setup()
185 for n in 1 3 5 7; do 185 for n in 1 3 5 7; do
186 ip li set ${NETIFS[p${n}]} up 186 ip li set ${NETIFS[p${n}]} up
187 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]} 187 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
188 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} 188 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
189 done 189 done
190 190
191 # move peer interfaces to namespace and add addresses 191 # move peer interfaces to namespace and add addresses
192 for n in 2 4 6 8; do 192 for n in 2 4 6 8; do
193 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up 193 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
194 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]} 194 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
195 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} 195 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
196 done 196 done
197 197
198 set +e 198 ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
199 ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
199 200
200 # let DAD complete - assume default of 1 probe 201 set +e
201 sleep 1
202} 202}
203 203
204cleanup() 204cleanup()
diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
index 0f45633bd634..802b4af18729 100755
--- a/tools/testing/selftests/net/fib_tests.sh
+++ b/tools/testing/selftests/net/fib_tests.sh
@@ -9,11 +9,11 @@ ret=0
9ksft_skip=4 9ksft_skip=4
10 10
11# all tests in this script. Can be overridden with -t option 11# all tests in this script. Can be overridden with -t option
12TESTS="unregister down carrier nexthop ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric" 12TESTS="unregister down carrier nexthop ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics"
13VERBOSE=0 13VERBOSE=0
14PAUSE_ON_FAIL=no 14PAUSE_ON_FAIL=no
15PAUSE=no 15PAUSE=no
16IP="ip -netns testns" 16IP="ip -netns ns1"
17 17
18log_test() 18log_test()
19{ 19{
@@ -47,8 +47,10 @@ log_test()
47setup() 47setup()
48{ 48{
49 set -e 49 set -e
50 ip netns add testns 50 ip netns add ns1
51 $IP link set dev lo up 51 $IP link set dev lo up
52 ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1
53 ip netns exec ns1 sysctl -qw net.ipv6.conf.all.forwarding=1
52 54
53 $IP link add dummy0 type dummy 55 $IP link add dummy0 type dummy
54 $IP link set dev dummy0 up 56 $IP link set dev dummy0 up
@@ -61,7 +63,8 @@ setup()
61cleanup() 63cleanup()
62{ 64{
63 $IP link del dev dummy0 &> /dev/null 65 $IP link del dev dummy0 &> /dev/null
64 ip netns del testns 66 ip netns del ns1
67 ip netns del ns2 &> /dev/null
65} 68}
66 69
67get_linklocal() 70get_linklocal()
@@ -639,11 +642,14 @@ add_initial_route6()
639 642
640check_route6() 643check_route6()
641{ 644{
642 local pfx="2001:db8:104::/64" 645 local pfx
643 local expected="$1" 646 local expected="$1"
644 local out 647 local out
645 local rc=0 648 local rc=0
646 649
650 set -- $expected
651 pfx=$1
652
647 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//') 653 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
648 [ "${out}" = "${expected}" ] && return 0 654 [ "${out}" = "${expected}" ] && return 0
649 655
@@ -690,28 +696,33 @@ route_setup()
690 [ "${VERBOSE}" = "1" ] && set -x 696 [ "${VERBOSE}" = "1" ] && set -x
691 set -e 697 set -e
692 698
693 $IP li add red up type vrf table 101 699 ip netns add ns2
700 ip -netns ns2 link set dev lo up
701 ip netns exec ns2 sysctl -qw net.ipv4.ip_forward=1
702 ip netns exec ns2 sysctl -qw net.ipv6.conf.all.forwarding=1
703
694 $IP li add veth1 type veth peer name veth2 704 $IP li add veth1 type veth peer name veth2
695 $IP li add veth3 type veth peer name veth4 705 $IP li add veth3 type veth peer name veth4
696 706
697 $IP li set veth1 up 707 $IP li set veth1 up
698 $IP li set veth3 up 708 $IP li set veth3 up
699 $IP li set veth2 vrf red up 709 $IP li set veth2 netns ns2 up
700 $IP li set veth4 vrf red up 710 $IP li set veth4 netns ns2 up
701 $IP li add dummy1 type dummy 711 ip -netns ns2 li add dummy1 type dummy
702 $IP li set dummy1 vrf red up 712 ip -netns ns2 li set dummy1 up
703
704 $IP -6 addr add 2001:db8:101::1/64 dev veth1
705 $IP -6 addr add 2001:db8:101::2/64 dev veth2
706 $IP -6 addr add 2001:db8:103::1/64 dev veth3
707 $IP -6 addr add 2001:db8:103::2/64 dev veth4
708 $IP -6 addr add 2001:db8:104::1/64 dev dummy1
709 713
714 $IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad
715 $IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad
710 $IP addr add 172.16.101.1/24 dev veth1 716 $IP addr add 172.16.101.1/24 dev veth1
711 $IP addr add 172.16.101.2/24 dev veth2
712 $IP addr add 172.16.103.1/24 dev veth3 717 $IP addr add 172.16.103.1/24 dev veth3
713 $IP addr add 172.16.103.2/24 dev veth4 718
714 $IP addr add 172.16.104.1/24 dev dummy1 719 ip -netns ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad
720 ip -netns ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad
721 ip -netns ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad
722
723 ip -netns ns2 addr add 172.16.101.2/24 dev veth2
724 ip -netns ns2 addr add 172.16.103.2/24 dev veth4
725 ip -netns ns2 addr add 172.16.104.1/24 dev dummy1
715 726
716 set +ex 727 set +ex
717} 728}
@@ -944,7 +955,7 @@ ipv6_addr_metric_test()
944 log_test $rc 0 "Modify metric of address" 955 log_test $rc 0 "Modify metric of address"
945 956
946 # verify prefix route removed on down 957 # verify prefix route removed on down
947 run_cmd "ip netns exec testns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1" 958 run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
948 run_cmd "$IP li set dev dummy2 down" 959 run_cmd "$IP li set dev dummy2 down"
949 rc=$? 960 rc=$?
950 if [ $rc -eq 0 ]; then 961 if [ $rc -eq 0 ]; then
@@ -967,6 +978,77 @@ ipv6_addr_metric_test()
967 cleanup 978 cleanup
968} 979}
969 980
981ipv6_route_metrics_test()
982{
983 local rc
984
985 echo
986 echo "IPv6 routes with metrics"
987
988 route_setup
989
990 #
991 # single path with metrics
992 #
993 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
994 rc=$?
995 if [ $rc -eq 0 ]; then
996 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
997 rc=$?
998 fi
999 log_test $rc 0 "Single path route with mtu metric"
1000
1001
1002 #
1003 # multipath via separate routes with metrics
1004 #
1005 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1006 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1007 rc=$?
1008 if [ $rc -eq 0 ]; then
1009 check_route6 "2001:db8:112::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1010 rc=$?
1011 fi
1012 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1013
1014 # second route is coalesced to first to make a multipath route.
1015 # MTU of the second path is hidden from display!
1016 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1017 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1018 rc=$?
1019 if [ $rc -eq 0 ]; then
1020 check_route6 "2001:db8:113::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1021 rc=$?
1022 fi
1023 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1024
1025 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1026 if [ $? -eq 0 ]; then
1027 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1028 log_test $? 0 " MTU of second leg"
1029 fi
1030
1031 #
1032 # multipath with metrics
1033 #
1034 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1035 rc=$?
1036 if [ $rc -eq 0 ]; then
1037 check_route6 "2001:db8:115::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1038 rc=$?
1039 fi
1040 log_test $rc 0 "Multipath route with mtu metric"
1041
1042 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1043 run_cmd "ip netns exec ns1 ping6 -w1 -c1 -s 1500 2001:db8:104::1"
1044 log_test $? 0 "Using route with mtu metric"
1045
1046 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1047 log_test $? 2 "Invalid metric (fails metric_convert)"
1048
1049 route_cleanup
1050}
1051
970# add route for a prefix, flushing any existing routes first 1052# add route for a prefix, flushing any existing routes first
971# expected to be the first step of a test 1053# expected to be the first step of a test
972add_route() 1054add_route()
@@ -1005,11 +1087,15 @@ add_initial_route()
1005 1087
1006check_route() 1088check_route()
1007{ 1089{
1008 local pfx="172.16.104.0/24" 1090 local pfx
1009 local expected="$1" 1091 local expected="$1"
1010 local out 1092 local out
1011 local rc=0 1093 local rc=0
1012 1094
1095 set -- $expected
1096 pfx=$1
1097 [ "${pfx}" = "unreachable" ] && pfx=$2
1098
1013 out=$($IP ro ls match ${pfx}) 1099 out=$($IP ro ls match ${pfx})
1014 [ "${out}" = "${expected}" ] && return 0 1100 [ "${out}" = "${expected}" ] && return 0
1015 1101
@@ -1319,6 +1405,43 @@ ipv4_addr_metric_test()
1319 cleanup 1405 cleanup
1320} 1406}
1321 1407
1408ipv4_route_metrics_test()
1409{
1410 local rc
1411
1412 echo
1413 echo "IPv4 route add / append tests"
1414
1415 route_setup
1416
1417 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1418 rc=$?
1419 if [ $rc -eq 0 ]; then
1420 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1421 rc=$?
1422 fi
1423 log_test $rc 0 "Single path route with mtu metric"
1424
1425
1426 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1427 rc=$?
1428 if [ $rc -eq 0 ]; then
1429 check_route "172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1430 rc=$?
1431 fi
1432 log_test $rc 0 "Multipath route with mtu metric"
1433
1434 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1435 run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1436 log_test $? 0 "Using route with mtu metric"
1437
1438 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1439 log_test $? 2 "Invalid metric (fails metric_convert)"
1440
1441 route_cleanup
1442}
1443
1444
1322################################################################################ 1445################################################################################
1323# usage 1446# usage
1324 1447
@@ -1385,6 +1508,8 @@ do
1385 ipv4_route_test|ipv4_rt) ipv4_route_test;; 1508 ipv4_route_test|ipv4_rt) ipv4_route_test;;
1386 ipv6_addr_metric) ipv6_addr_metric_test;; 1509 ipv6_addr_metric) ipv6_addr_metric_test;;
1387 ipv4_addr_metric) ipv4_addr_metric_test;; 1510 ipv4_addr_metric) ipv4_addr_metric_test;;
1511 ipv6_route_metrics) ipv6_route_metrics_test;;
1512 ipv4_route_metrics) ipv4_route_metrics_test;;
1388 1513
1389 help) echo "Test names: $TESTS"; exit 0;; 1514 help) echo "Test names: $TESTS"; exit 0;;
1390 esac 1515 esac
diff --git a/tools/testing/selftests/net/forwarding/bridge_sticky_fdb.sh b/tools/testing/selftests/net/forwarding/bridge_sticky_fdb.sh
new file mode 100755
index 000000000000..1f8ef0eff862
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/bridge_sticky_fdb.sh
@@ -0,0 +1,69 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="sticky"
5NUM_NETIFS=4
6TEST_MAC=de:ad:be:ef:13:37
7source lib.sh
8
9switch_create()
10{
11 ip link add dev br0 type bridge
12
13 ip link set dev $swp1 master br0
14 ip link set dev $swp2 master br0
15
16 ip link set dev br0 up
17 ip link set dev $h1 up
18 ip link set dev $swp1 up
19 ip link set dev $h2 up
20 ip link set dev $swp2 up
21}
22
23switch_destroy()
24{
25 ip link set dev $swp2 down
26 ip link set dev $h2 down
27 ip link set dev $swp1 down
28 ip link set dev $h1 down
29
30 ip link del dev br0
31}
32
33setup_prepare()
34{
35 h1=${NETIFS[p1]}
36 swp1=${NETIFS[p2]}
37 h2=${NETIFS[p3]}
38 swp2=${NETIFS[p4]}
39
40 switch_create
41}
42
43cleanup()
44{
45 pre_cleanup
46 switch_destroy
47}
48
49sticky()
50{
51 bridge fdb add $TEST_MAC dev $swp1 master static sticky
52 check_err $? "Could not add fdb entry"
53 bridge fdb del $TEST_MAC dev $swp1 vlan 1 master static sticky
54 $MZ $h2 -c 1 -a $TEST_MAC -t arp "request" -q
55 bridge -j fdb show br br0 brport $swp1\
56 | jq -e ".[] | select(.mac == \"$TEST_MAC\")" &> /dev/null
57 check_err $? "Did not find FDB record when should"
58
59 log_test "Sticky fdb entry"
60}
61
62trap cleanup EXIT
63
64setup_prepare
65setup_wait
66
67tests_run
68
69exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index ca53b539aa2d..85d253546684 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -251,7 +251,7 @@ lldpad_app_wait_set()
251{ 251{
252 local dev=$1; shift 252 local dev=$1; shift
253 253
254 while lldptool -t -i $dev -V APP -c app | grep -q pending; do 254 while lldptool -t -i $dev -V APP -c app | grep -Eq "pending|unknown"; do
255 echo "$dev: waiting for lldpad to push pending APP updates" 255 echo "$dev: waiting for lldpad to push pending APP updates"
256 sleep 5 256 sleep 5
257 done 257 done
@@ -494,6 +494,14 @@ tc_rule_stats_get()
494 | jq '.[1].options.actions[].stats.packets' 494 | jq '.[1].options.actions[].stats.packets'
495} 495}
496 496
497ethtool_stats_get()
498{
499 local dev=$1; shift
500 local stat=$1; shift
501
502 ethtool -S $dev | grep "^ *$stat:" | head -n 1 | cut -d: -f2
503}
504
497mac_get() 505mac_get()
498{ 506{
499 local if_name=$1 507 local if_name=$1
@@ -541,6 +549,23 @@ forwarding_restore()
541 sysctl_restore net.ipv4.conf.all.forwarding 549 sysctl_restore net.ipv4.conf.all.forwarding
542} 550}
543 551
552declare -A MTU_ORIG
553mtu_set()
554{
555 local dev=$1; shift
556 local mtu=$1; shift
557
558 MTU_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].mtu')
559 ip link set dev $dev mtu $mtu
560}
561
562mtu_restore()
563{
564 local dev=$1; shift
565
566 ip link set dev $dev mtu ${MTU_ORIG["$dev"]}
567}
568
544tc_offload_check() 569tc_offload_check()
545{ 570{
546 local num_netifs=${1:-$NUM_NETIFS} 571 local num_netifs=${1:-$NUM_NETIFS}
diff --git a/tools/testing/selftests/net/ip_defrag.c b/tools/testing/selftests/net/ip_defrag.c
new file mode 100644
index 000000000000..61ae2782388e
--- /dev/null
+++ b/tools/testing/selftests/net/ip_defrag.c
@@ -0,0 +1,393 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#define _GNU_SOURCE
4
5#include <arpa/inet.h>
6#include <errno.h>
7#include <error.h>
8#include <linux/in.h>
9#include <netinet/ip.h>
10#include <netinet/ip6.h>
11#include <netinet/udp.h>
12#include <stdbool.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <time.h>
17#include <unistd.h>
18
19static bool cfg_do_ipv4;
20static bool cfg_do_ipv6;
21static bool cfg_verbose;
22static bool cfg_overlap;
23static unsigned short cfg_port = 9000;
24
25const struct in_addr addr4 = { .s_addr = __constant_htonl(INADDR_LOOPBACK + 2) };
26const struct in6_addr addr6 = IN6ADDR_LOOPBACK_INIT;
27
28#define IP4_HLEN (sizeof(struct iphdr))
29#define IP6_HLEN (sizeof(struct ip6_hdr))
30#define UDP_HLEN (sizeof(struct udphdr))
31
32/* IPv6 fragment header lenth. */
33#define FRAG_HLEN 8
34
35static int payload_len;
36static int max_frag_len;
37
38#define MSG_LEN_MAX 60000 /* Max UDP payload length. */
39
40#define IP4_MF (1u << 13) /* IPv4 MF flag. */
41#define IP6_MF (1) /* IPv6 MF flag. */
42
43#define CSUM_MANGLED_0 (0xffff)
44
45static uint8_t udp_payload[MSG_LEN_MAX];
46static uint8_t ip_frame[IP_MAXPACKET];
47static uint32_t ip_id = 0xabcd;
48static int msg_counter;
49static int frag_counter;
50static unsigned int seed;
51
52/* Receive a UDP packet. Validate it matches udp_payload. */
53static void recv_validate_udp(int fd_udp)
54{
55 ssize_t ret;
56 static uint8_t recv_buff[MSG_LEN_MAX];
57
58 ret = recv(fd_udp, recv_buff, payload_len, 0);
59 msg_counter++;
60
61 if (cfg_overlap) {
62 if (ret != -1)
63 error(1, 0, "recv: expected timeout; got %d",
64 (int)ret);
65 if (errno != ETIMEDOUT && errno != EAGAIN)
66 error(1, errno, "recv: expected timeout: %d",
67 errno);
68 return; /* OK */
69 }
70
71 if (ret == -1)
72 error(1, errno, "recv: payload_len = %d max_frag_len = %d",
73 payload_len, max_frag_len);
74 if (ret != payload_len)
75 error(1, 0, "recv: wrong size: %d vs %d", (int)ret, payload_len);
76 if (memcmp(udp_payload, recv_buff, payload_len))
77 error(1, 0, "recv: wrong data");
78}
79
80static uint32_t raw_checksum(uint8_t *buf, int len, uint32_t sum)
81{
82 int i;
83
84 for (i = 0; i < (len & ~1U); i += 2) {
85 sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
86 if (sum > 0xffff)
87 sum -= 0xffff;
88 }
89
90 if (i < len) {
91 sum += buf[i] << 8;
92 if (sum > 0xffff)
93 sum -= 0xffff;
94 }
95
96 return sum;
97}
98
99static uint16_t udp_checksum(struct ip *iphdr, struct udphdr *udphdr)
100{
101 uint32_t sum = 0;
102 uint16_t res;
103
104 sum = raw_checksum((uint8_t *)&iphdr->ip_src, 2 * sizeof(iphdr->ip_src),
105 IPPROTO_UDP + (uint32_t)(UDP_HLEN + payload_len));
106 sum = raw_checksum((uint8_t *)udphdr, UDP_HLEN, sum);
107 sum = raw_checksum((uint8_t *)udp_payload, payload_len, sum);
108 res = 0xffff & ~sum;
109 if (res)
110 return htons(res);
111 else
112 return CSUM_MANGLED_0;
113}
114
115static uint16_t udp6_checksum(struct ip6_hdr *iphdr, struct udphdr *udphdr)
116{
117 uint32_t sum = 0;
118 uint16_t res;
119
120 sum = raw_checksum((uint8_t *)&iphdr->ip6_src, 2 * sizeof(iphdr->ip6_src),
121 IPPROTO_UDP);
122 sum = raw_checksum((uint8_t *)&udphdr->len, sizeof(udphdr->len), sum);
123 sum = raw_checksum((uint8_t *)udphdr, UDP_HLEN, sum);
124 sum = raw_checksum((uint8_t *)udp_payload, payload_len, sum);
125 res = 0xffff & ~sum;
126 if (res)
127 return htons(res);
128 else
129 return CSUM_MANGLED_0;
130}
131
132static void send_fragment(int fd_raw, struct sockaddr *addr, socklen_t alen,
133 int offset, bool ipv6)
134{
135 int frag_len;
136 int res;
137 int payload_offset = offset > 0 ? offset - UDP_HLEN : 0;
138 uint8_t *frag_start = ipv6 ? ip_frame + IP6_HLEN + FRAG_HLEN :
139 ip_frame + IP4_HLEN;
140
141 if (offset == 0) {
142 struct udphdr udphdr;
143 udphdr.source = htons(cfg_port + 1);
144 udphdr.dest = htons(cfg_port);
145 udphdr.len = htons(UDP_HLEN + payload_len);
146 udphdr.check = 0;
147 if (ipv6)
148 udphdr.check = udp6_checksum((struct ip6_hdr *)ip_frame, &udphdr);
149 else
150 udphdr.check = udp_checksum((struct ip *)ip_frame, &udphdr);
151 memcpy(frag_start, &udphdr, UDP_HLEN);
152 }
153
154 if (ipv6) {
155 struct ip6_hdr *ip6hdr = (struct ip6_hdr *)ip_frame;
156 struct ip6_frag *fraghdr = (struct ip6_frag *)(ip_frame + IP6_HLEN);
157 if (payload_len - payload_offset <= max_frag_len && offset > 0) {
158 /* This is the last fragment. */
159 frag_len = FRAG_HLEN + payload_len - payload_offset;
160 fraghdr->ip6f_offlg = htons(offset);
161 } else {
162 frag_len = FRAG_HLEN + max_frag_len;
163 fraghdr->ip6f_offlg = htons(offset | IP6_MF);
164 }
165 ip6hdr->ip6_plen = htons(frag_len);
166 if (offset == 0)
167 memcpy(frag_start + UDP_HLEN, udp_payload,
168 frag_len - FRAG_HLEN - UDP_HLEN);
169 else
170 memcpy(frag_start, udp_payload + payload_offset,
171 frag_len - FRAG_HLEN);
172 frag_len += IP6_HLEN;
173 } else {
174 struct ip *iphdr = (struct ip *)ip_frame;
175 if (payload_len - payload_offset <= max_frag_len && offset > 0) {
176 /* This is the last fragment. */
177 frag_len = IP4_HLEN + payload_len - payload_offset;
178 iphdr->ip_off = htons(offset / 8);
179 } else {
180 frag_len = IP4_HLEN + max_frag_len;
181 iphdr->ip_off = htons(offset / 8 | IP4_MF);
182 }
183 iphdr->ip_len = htons(frag_len);
184 if (offset == 0)
185 memcpy(frag_start + UDP_HLEN, udp_payload,
186 frag_len - IP4_HLEN - UDP_HLEN);
187 else
188 memcpy(frag_start, udp_payload + payload_offset,
189 frag_len - IP4_HLEN);
190 }
191
192 res = sendto(fd_raw, ip_frame, frag_len, 0, addr, alen);
193 if (res < 0)
194 error(1, errno, "send_fragment");
195 if (res != frag_len)
196 error(1, 0, "send_fragment: %d vs %d", res, frag_len);
197
198 frag_counter++;
199}
200
201static void send_udp_frags(int fd_raw, struct sockaddr *addr,
202 socklen_t alen, bool ipv6)
203{
204 struct ip *iphdr = (struct ip *)ip_frame;
205 struct ip6_hdr *ip6hdr = (struct ip6_hdr *)ip_frame;
206 int res;
207 int offset;
208 int frag_len;
209
210 /* Send the UDP datagram using raw IP fragments: the 0th fragment
211 * has the UDP header; other fragments are pieces of udp_payload
212 * split in chunks of frag_len size.
213 *
214 * Odd fragments (1st, 3rd, 5th, etc.) are sent out first, then
215 * even fragments (0th, 2nd, etc.) are sent out.
216 */
217 if (ipv6) {
218 struct ip6_frag *fraghdr = (struct ip6_frag *)(ip_frame + IP6_HLEN);
219 ((struct sockaddr_in6 *)addr)->sin6_port = 0;
220 memset(ip6hdr, 0, sizeof(*ip6hdr));
221 ip6hdr->ip6_flow = htonl(6<<28); /* Version. */
222 ip6hdr->ip6_nxt = IPPROTO_FRAGMENT;
223 ip6hdr->ip6_hops = 255;
224 ip6hdr->ip6_src = addr6;
225 ip6hdr->ip6_dst = addr6;
226 fraghdr->ip6f_nxt = IPPROTO_UDP;
227 fraghdr->ip6f_reserved = 0;
228 fraghdr->ip6f_ident = htonl(ip_id++);
229 } else {
230 memset(iphdr, 0, sizeof(*iphdr));
231 iphdr->ip_hl = 5;
232 iphdr->ip_v = 4;
233 iphdr->ip_tos = 0;
234 iphdr->ip_id = htons(ip_id++);
235 iphdr->ip_ttl = 0x40;
236 iphdr->ip_p = IPPROTO_UDP;
237 iphdr->ip_src.s_addr = htonl(INADDR_LOOPBACK);
238 iphdr->ip_dst = addr4;
239 iphdr->ip_sum = 0;
240 }
241
242 /* Odd fragments. */
243 offset = max_frag_len;
244 while (offset < (UDP_HLEN + payload_len)) {
245 send_fragment(fd_raw, addr, alen, offset, ipv6);
246 offset += 2 * max_frag_len;
247 }
248
249 if (cfg_overlap) {
250 /* Send an extra random fragment. */
251 offset = rand() % (UDP_HLEN + payload_len - 1);
252 /* sendto() returns EINVAL if offset + frag_len is too small. */
253 if (ipv6) {
254 struct ip6_frag *fraghdr = (struct ip6_frag *)(ip_frame + IP6_HLEN);
255 frag_len = max_frag_len + rand() % 256;
256 /* In IPv6 if !!(frag_len % 8), the fragment is dropped. */
257 frag_len &= ~0x7;
258 fraghdr->ip6f_offlg = htons(offset / 8 | IP6_MF);
259 ip6hdr->ip6_plen = htons(frag_len);
260 frag_len += IP6_HLEN;
261 } else {
262 frag_len = IP4_HLEN + UDP_HLEN + rand() % 256;
263 iphdr->ip_off = htons(offset / 8 | IP4_MF);
264 iphdr->ip_len = htons(frag_len);
265 }
266 res = sendto(fd_raw, ip_frame, frag_len, 0, addr, alen);
267 if (res < 0)
268 error(1, errno, "sendto overlap");
269 if (res != frag_len)
270 error(1, 0, "sendto overlap: %d vs %d", (int)res, frag_len);
271 frag_counter++;
272 }
273
274 /* Event fragments. */
275 offset = 0;
276 while (offset < (UDP_HLEN + payload_len)) {
277 send_fragment(fd_raw, addr, alen, offset, ipv6);
278 offset += 2 * max_frag_len;
279 }
280}
281
282static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
283{
284 int fd_tx_raw, fd_rx_udp;
285 struct timeval tv = { .tv_sec = 0, .tv_usec = 10 * 1000 };
286 int idx;
287 int min_frag_len = ipv6 ? 1280 : 8;
288
289 /* Initialize the payload. */
290 for (idx = 0; idx < MSG_LEN_MAX; ++idx)
291 udp_payload[idx] = idx % 256;
292
293 /* Open sockets. */
294 fd_tx_raw = socket(addr->sa_family, SOCK_RAW, IPPROTO_RAW);
295 if (fd_tx_raw == -1)
296 error(1, errno, "socket tx_raw");
297
298 fd_rx_udp = socket(addr->sa_family, SOCK_DGRAM, 0);
299 if (fd_rx_udp == -1)
300 error(1, errno, "socket rx_udp");
301 if (bind(fd_rx_udp, addr, alen))
302 error(1, errno, "bind");
303 /* Fail fast. */
304 if (setsockopt(fd_rx_udp, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
305 error(1, errno, "setsockopt rcv timeout");
306
307 for (payload_len = min_frag_len; payload_len < MSG_LEN_MAX;
308 payload_len += (rand() % 4096)) {
309 if (cfg_verbose)
310 printf("payload_len: %d\n", payload_len);
311 max_frag_len = min_frag_len;
312 do {
313 send_udp_frags(fd_tx_raw, addr, alen, ipv6);
314 recv_validate_udp(fd_rx_udp);
315 max_frag_len += 8 * (rand() % 8);
316 } while (max_frag_len < (1500 - FRAG_HLEN) && max_frag_len <= payload_len);
317 }
318
319 /* Cleanup. */
320 if (close(fd_tx_raw))
321 error(1, errno, "close tx_raw");
322 if (close(fd_rx_udp))
323 error(1, errno, "close rx_udp");
324
325 if (cfg_verbose)
326 printf("processed %d messages, %d fragments\n",
327 msg_counter, frag_counter);
328
329 fprintf(stderr, "PASS\n");
330}
331
332
333static void run_test_v4(void)
334{
335 struct sockaddr_in addr = {0};
336
337 addr.sin_family = AF_INET;
338 addr.sin_port = htons(cfg_port);
339 addr.sin_addr = addr4;
340
341 run_test((void *)&addr, sizeof(addr), false /* !ipv6 */);
342}
343
344static void run_test_v6(void)
345{
346 struct sockaddr_in6 addr = {0};
347
348 addr.sin6_family = AF_INET6;
349 addr.sin6_port = htons(cfg_port);
350 addr.sin6_addr = addr6;
351
352 run_test((void *)&addr, sizeof(addr), true /* ipv6 */);
353}
354
355static void parse_opts(int argc, char **argv)
356{
357 int c;
358
359 while ((c = getopt(argc, argv, "46ov")) != -1) {
360 switch (c) {
361 case '4':
362 cfg_do_ipv4 = true;
363 break;
364 case '6':
365 cfg_do_ipv6 = true;
366 break;
367 case 'o':
368 cfg_overlap = true;
369 break;
370 case 'v':
371 cfg_verbose = true;
372 break;
373 default:
374 error(1, 0, "%s: parse error", argv[0]);
375 }
376 }
377}
378
379int main(int argc, char **argv)
380{
381 parse_opts(argc, argv);
382 seed = time(NULL);
383 srand(seed);
384 /* Print the seed to track/reproduce potential failures. */
385 printf("seed = %d\n", seed);
386
387 if (cfg_do_ipv4)
388 run_test_v4();
389 if (cfg_do_ipv6)
390 run_test_v6();
391
392 return 0;
393}
diff --git a/tools/testing/selftests/net/ip_defrag.sh b/tools/testing/selftests/net/ip_defrag.sh
new file mode 100755
index 000000000000..f34672796044
--- /dev/null
+++ b/tools/testing/selftests/net/ip_defrag.sh
@@ -0,0 +1,39 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Run a couple of IP defragmentation tests.
5
6set +x
7set -e
8
9readonly NETNS="ns-$(mktemp -u XXXXXX)"
10
11setup() {
12 ip netns add "${NETNS}"
13 ip -netns "${NETNS}" link set lo up
14 ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_high_thresh=9000000 >/dev/null 2>&1
15 ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_low_thresh=7000000 >/dev/null 2>&1
16 ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_high_thresh=9000000 >/dev/null 2>&1
17 ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_low_thresh=7000000 >/dev/null 2>&1
18}
19
20cleanup() {
21 ip netns del "${NETNS}"
22}
23
24trap cleanup EXIT
25setup
26
27echo "ipv4 defrag"
28ip netns exec "${NETNS}" ./ip_defrag -4
29
30
31echo "ipv4 defrag with overlaps"
32ip netns exec "${NETNS}" ./ip_defrag -4o
33
34echo "ipv6 defrag"
35ip netns exec "${NETNS}" ./ip_defrag -6
36
37echo "ipv6 defrag with overlaps"
38ip netns exec "${NETNS}" ./ip_defrag -6o
39
diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh
index 0ab9423d009f..a369d616b390 100755
--- a/tools/testing/selftests/net/pmtu.sh
+++ b/tools/testing/selftests/net/pmtu.sh
@@ -6,6 +6,26 @@
6# 6#
7# Tests currently implemented: 7# Tests currently implemented:
8# 8#
9# - pmtu_ipv4
10# Set up two namespaces, A and B, with two paths between them over routers
11# R1 and R2 (also implemented with namespaces), with different MTUs:
12#
13# segment a_r1 segment b_r1 a_r1: 2000
14# .--------------R1--------------. a_r2: 1500
15# A B a_r3: 2000
16# '--------------R2--------------' a_r4: 1400
17# segment a_r2 segment b_r2
18#
19# Check that PMTU exceptions with the correct PMTU are created. Then
20# decrease and increase the MTU of the local link for one of the paths,
21# A to R1, checking that route exception PMTU changes accordingly over
22# this path. Also check that locked exceptions are created when an ICMP
23# message advertising a PMTU smaller than net.ipv4.route.min_pmtu is
24# received
25#
26# - pmtu_ipv6
27# Same as pmtu_ipv4, except for locked PMTU tests, using IPv6
28#
9# - pmtu_vti4_exception 29# - pmtu_vti4_exception
10# Set up vti tunnel on top of veth, with xfrm states and policies, in two 30# Set up vti tunnel on top of veth, with xfrm states and policies, in two
11# namespaces with matching endpoints. Check that route exception is not 31# namespaces with matching endpoints. Check that route exception is not
@@ -50,6 +70,8 @@ ksft_skip=4
50which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping) 70which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
51 71
52tests=" 72tests="
73 pmtu_ipv4_exception ipv4: PMTU exceptions
74 pmtu_ipv6_exception ipv6: PMTU exceptions
53 pmtu_vti6_exception vti6: PMTU exceptions 75 pmtu_vti6_exception vti6: PMTU exceptions
54 pmtu_vti4_exception vti4: PMTU exceptions 76 pmtu_vti4_exception vti4: PMTU exceptions
55 pmtu_vti4_default_mtu vti4: default MTU assignment 77 pmtu_vti4_default_mtu vti4: default MTU assignment
@@ -60,8 +82,45 @@ tests="
60 82
61NS_A="ns-$(mktemp -u XXXXXX)" 83NS_A="ns-$(mktemp -u XXXXXX)"
62NS_B="ns-$(mktemp -u XXXXXX)" 84NS_B="ns-$(mktemp -u XXXXXX)"
85NS_R1="ns-$(mktemp -u XXXXXX)"
86NS_R2="ns-$(mktemp -u XXXXXX)"
63ns_a="ip netns exec ${NS_A}" 87ns_a="ip netns exec ${NS_A}"
64ns_b="ip netns exec ${NS_B}" 88ns_b="ip netns exec ${NS_B}"
89ns_r1="ip netns exec ${NS_R1}"
90ns_r2="ip netns exec ${NS_R2}"
91
92# Addressing and routing for tests with routers: four network segments, with
93# index SEGMENT between 1 and 4, a common prefix (PREFIX4 or PREFIX6) and an
94# identifier ID, which is 1 for hosts (A and B), 2 for routers (R1 and R2).
95# Addresses are:
96# - IPv4: PREFIX4.SEGMENT.ID (/24)
97# - IPv6: PREFIX6:SEGMENT::ID (/64)
98prefix4="192.168"
99prefix6="fd00"
100a_r1=1
101a_r2=2
102b_r1=3
103b_r2=4
104# ns peer segment
105routing_addrs="
106 A R1 ${a_r1}
107 A R2 ${a_r2}
108 B R1 ${b_r1}
109 B R2 ${b_r2}
110"
111# Traffic from A to B goes through R1 by default, and through R2, if destined to
112# B's address on the b_r2 segment.
113# Traffic from B to A goes through R1.
114# ns destination gateway
115routes="
116 A default ${prefix4}.${a_r1}.2
117 A ${prefix4}.${b_r2}.1 ${prefix4}.${a_r2}.2
118 B default ${prefix4}.${b_r1}.2
119
120 A default ${prefix6}:${a_r1}::2
121 A ${prefix6}:${b_r2}::1 ${prefix6}:${a_r2}::2
122 B default ${prefix6}:${b_r1}::2
123"
65 124
66veth4_a_addr="192.168.1.1" 125veth4_a_addr="192.168.1.1"
67veth4_b_addr="192.168.1.2" 126veth4_b_addr="192.168.1.2"
@@ -83,6 +142,7 @@ dummy6_mask="64"
83 142
84cleanup_done=1 143cleanup_done=1
85err_buf= 144err_buf=
145tcpdump_pids=
86 146
87err() { 147err() {
88 err_buf="${err_buf}${1} 148 err_buf="${err_buf}${1}
@@ -94,9 +154,15 @@ err_flush() {
94 err_buf= 154 err_buf=
95} 155}
96 156
157# Find the auto-generated name for this namespace
158nsname() {
159 eval echo \$NS_$1
160}
161
97setup_namespaces() { 162setup_namespaces() {
98 ip netns add ${NS_A} || return 1 163 for n in ${NS_A} ${NS_B} ${NS_R1} ${NS_R2}; do
99 ip netns add ${NS_B} 164 ip netns add ${n} || return 1
165 done
100} 166}
101 167
102setup_veth() { 168setup_veth() {
@@ -167,6 +233,49 @@ setup_xfrm6() {
167 setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} 233 setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr}
168} 234}
169 235
236setup_routing() {
237 for i in ${NS_R1} ${NS_R2}; do
238 ip netns exec ${i} sysctl -q net/ipv4/ip_forward=1
239 ip netns exec ${i} sysctl -q net/ipv6/conf/all/forwarding=1
240 done
241
242 for i in ${routing_addrs}; do
243 [ "${ns}" = "" ] && ns="${i}" && continue
244 [ "${peer}" = "" ] && peer="${i}" && continue
245 [ "${segment}" = "" ] && segment="${i}"
246
247 ns_name="$(nsname ${ns})"
248 peer_name="$(nsname ${peer})"
249 if="veth_${ns}-${peer}"
250 ifpeer="veth_${peer}-${ns}"
251
252 # Create veth links
253 ip link add ${if} up netns ${ns_name} type veth peer name ${ifpeer} netns ${peer_name} || return 1
254 ip -n ${peer_name} link set dev ${ifpeer} up
255
256 # Add addresses
257 ip -n ${ns_name} addr add ${prefix4}.${segment}.1/24 dev ${if}
258 ip -n ${ns_name} addr add ${prefix6}:${segment}::1/64 dev ${if}
259
260 ip -n ${peer_name} addr add ${prefix4}.${segment}.2/24 dev ${ifpeer}
261 ip -n ${peer_name} addr add ${prefix6}:${segment}::2/64 dev ${ifpeer}
262
263 ns=""; peer=""; segment=""
264 done
265
266 for i in ${routes}; do
267 [ "${ns}" = "" ] && ns="${i}" && continue
268 [ "${addr}" = "" ] && addr="${i}" && continue
269 [ "${gw}" = "" ] && gw="${i}"
270
271 ns_name="$(nsname ${ns})"
272
273 ip -n ${ns_name} route add ${addr} via ${gw}
274
275 ns=""; addr=""; gw=""
276 done
277}
278
170setup() { 279setup() {
171 [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip 280 [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip
172 281
@@ -176,10 +285,28 @@ setup() {
176 done 285 done
177} 286}
178 287
288trace() {
289 [ $tracing -eq 0 ] && return
290
291 for arg do
292 [ "${ns_cmd}" = "" ] && ns_cmd="${arg}" && continue
293 ${ns_cmd} tcpdump -s 0 -i "${arg}" -w "${name}_${arg}.pcap" 2> /dev/null &
294 tcpdump_pids="${tcpdump_pids} $!"
295 ns_cmd=
296 done
297 sleep 1
298}
299
179cleanup() { 300cleanup() {
301 for pid in ${tcpdump_pids}; do
302 kill ${pid}
303 done
304 tcpdump_pids=
305
180 [ ${cleanup_done} -eq 1 ] && return 306 [ ${cleanup_done} -eq 1 ] && return
181 ip netns del ${NS_A} 2> /dev/null 307 for n in ${NS_A} ${NS_B} ${NS_R1} ${NS_R2}; do
182 ip netns del ${NS_B} 2> /dev/null 308 ip netns del ${n} 2> /dev/null
309 done
183 cleanup_done=1 310 cleanup_done=1
184} 311}
185 312
@@ -196,7 +323,9 @@ mtu_parse() {
196 323
197 next=0 324 next=0
198 for i in ${input}; do 325 for i in ${input}; do
326 [ ${next} -eq 1 -a "${i}" = "lock" ] && next=2 && continue
199 [ ${next} -eq 1 ] && echo "${i}" && return 327 [ ${next} -eq 1 ] && echo "${i}" && return
328 [ ${next} -eq 2 ] && echo "lock ${i}" && return
200 [ "${i}" = "mtu" ] && next=1 329 [ "${i}" = "mtu" ] && next=1
201 done 330 done
202} 331}
@@ -229,8 +358,117 @@ route_get_dst_pmtu_from_exception() {
229 mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})" 358 mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})"
230} 359}
231 360
361check_pmtu_value() {
362 expected="${1}"
363 value="${2}"
364 event="${3}"
365
366 [ "${expected}" = "any" ] && [ -n "${value}" ] && return 0
367 [ "${value}" = "${expected}" ] && return 0
368 [ -z "${value}" ] && err " PMTU exception wasn't created after ${event}" && return 1
369 [ -z "${expected}" ] && err " PMTU exception shouldn't exist after ${event}" && return 1
370 err " found PMTU exception with incorrect MTU ${value}, expected ${expected}, after ${event}"
371 return 1
372}
373
374test_pmtu_ipvX() {
375 family=${1}
376
377 setup namespaces routing || return 2
378 trace "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \
379 "${ns_r1}" veth_R1-B "${ns_b}" veth_B-R1 \
380 "${ns_a}" veth_A-R2 "${ns_r2}" veth_R2-A \
381 "${ns_r2}" veth_R2-B "${ns_b}" veth_B-R2
382
383 if [ ${family} -eq 4 ]; then
384 ping=ping
385 dst1="${prefix4}.${b_r1}.1"
386 dst2="${prefix4}.${b_r2}.1"
387 else
388 ping=${ping6}
389 dst1="${prefix6}:${b_r1}::1"
390 dst2="${prefix6}:${b_r2}::1"
391 fi
392
393 # Set up initial MTU values
394 mtu "${ns_a}" veth_A-R1 2000
395 mtu "${ns_r1}" veth_R1-A 2000
396 mtu "${ns_r1}" veth_R1-B 1400
397 mtu "${ns_b}" veth_B-R1 1400
398
399 mtu "${ns_a}" veth_A-R2 2000
400 mtu "${ns_r2}" veth_R2-A 2000
401 mtu "${ns_r2}" veth_R2-B 1500
402 mtu "${ns_b}" veth_B-R2 1500
403
404 # Create route exceptions
405 ${ns_a} ${ping} -q -M want -i 0.1 -w 2 -s 1800 ${dst1} > /dev/null
406 ${ns_a} ${ping} -q -M want -i 0.1 -w 2 -s 1800 ${dst2} > /dev/null
407
408 # Check that exceptions have been created with the correct PMTU
409 pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
410 check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1
411 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
412 check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1
413
414 # Decrease local MTU below PMTU, check for PMTU decrease in route exception
415 mtu "${ns_a}" veth_A-R1 1300
416 mtu "${ns_r1}" veth_R1-A 1300
417 pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
418 check_pmtu_value "1300" "${pmtu_1}" "decreasing local MTU" || return 1
419 # Second exception shouldn't be modified
420 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
421 check_pmtu_value "1500" "${pmtu_2}" "changing local MTU on a link not on this path" || return 1
422
423 # Increase MTU, check for PMTU increase in route exception
424 mtu "${ns_a}" veth_A-R1 1700
425 mtu "${ns_r1}" veth_R1-A 1700
426 pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
427 check_pmtu_value "1700" "${pmtu_1}" "increasing local MTU" || return 1
428 # Second exception shouldn't be modified
429 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
430 check_pmtu_value "1500" "${pmtu_2}" "changing local MTU on a link not on this path" || return 1
431
432 # Skip PMTU locking tests for IPv6
433 [ $family -eq 6 ] && return 0
434
435 # Decrease remote MTU on path via R2, get new exception
436 mtu "${ns_r2}" veth_R2-B 400
437 mtu "${ns_b}" veth_B-R2 400
438 ${ns_a} ${ping} -q -M want -i 0.1 -w 2 -s 1400 ${dst2} > /dev/null
439 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
440 check_pmtu_value "lock 552" "${pmtu_2}" "exceeding MTU, with MTU < min_pmtu" || return 1
441
442 # Decrease local MTU below PMTU
443 mtu "${ns_a}" veth_A-R2 500
444 mtu "${ns_r2}" veth_R2-A 500
445 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
446 check_pmtu_value "500" "${pmtu_2}" "decreasing local MTU" || return 1
447
448 # Increase local MTU
449 mtu "${ns_a}" veth_A-R2 1500
450 mtu "${ns_r2}" veth_R2-A 1500
451 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
452 check_pmtu_value "1500" "${pmtu_2}" "increasing local MTU" || return 1
453
454 # Get new exception
455 ${ns_a} ${ping} -q -M want -i 0.1 -w 2 -s 1400 ${dst2} > /dev/null
456 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
457 check_pmtu_value "lock 552" "${pmtu_2}" "exceeding MTU, with MTU < min_pmtu" || return 1
458}
459
460test_pmtu_ipv4_exception() {
461 test_pmtu_ipvX 4
462}
463
464test_pmtu_ipv6_exception() {
465 test_pmtu_ipvX 6
466}
467
232test_pmtu_vti4_exception() { 468test_pmtu_vti4_exception() {
233 setup namespaces veth vti4 xfrm4 || return 2 469 setup namespaces veth vti4 xfrm4 || return 2
470 trace "${ns_a}" veth_a "${ns_b}" veth_b \
471 "${ns_a}" vti4_a "${ns_b}" vti4_b
234 472
235 veth_mtu=1500 473 veth_mtu=1500
236 vti_mtu=$((veth_mtu - 20)) 474 vti_mtu=$((veth_mtu - 20))
@@ -248,28 +486,19 @@ test_pmtu_vti4_exception() {
248 # exception is created 486 # exception is created
249 ${ns_a} ping -q -M want -i 0.1 -w 2 -s ${ping_payload} ${vti4_b_addr} > /dev/null 487 ${ns_a} ping -q -M want -i 0.1 -w 2 -s ${ping_payload} ${vti4_b_addr} > /dev/null
250 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})" 488 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})"
251 if [ "${pmtu}" != "" ]; then 489 check_pmtu_value "" "${pmtu}" "sending packet smaller than PMTU (IP payload length ${esp_payload_rfc4106})" || return 1
252 err " unexpected exception created with PMTU ${pmtu} for IP payload length ${esp_payload_rfc4106}"
253 return 1
254 fi
255 490
256 # Now exceed link layer MTU by one byte, check that exception is created 491 # Now exceed link layer MTU by one byte, check that exception is created
492 # with the right PMTU value
257 ${ns_a} ping -q -M want -i 0.1 -w 2 -s $((ping_payload + 1)) ${vti4_b_addr} > /dev/null 493 ${ns_a} ping -q -M want -i 0.1 -w 2 -s $((ping_payload + 1)) ${vti4_b_addr} > /dev/null
258 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})" 494 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})"
259 if [ "${pmtu}" = "" ]; then 495 check_pmtu_value "${esp_payload_rfc4106}" "${pmtu}" "exceeding PMTU (IP payload length $((esp_payload_rfc4106 + 1)))"
260 err " exception not created for IP payload length $((esp_payload_rfc4106 + 1))"
261 return 1
262 fi
263
264 # ...with the right PMTU value
265 if [ ${pmtu} -ne ${esp_payload_rfc4106} ]; then
266 err " wrong PMTU ${pmtu} in exception, expected: ${esp_payload_rfc4106}"
267 return 1
268 fi
269} 496}
270 497
271test_pmtu_vti6_exception() { 498test_pmtu_vti6_exception() {
272 setup namespaces veth vti6 xfrm6 || return 2 499 setup namespaces veth vti6 xfrm6 || return 2
500 trace "${ns_a}" veth_a "${ns_b}" veth_b \
501 "${ns_a}" vti6_a "${ns_b}" vti6_b
273 fail=0 502 fail=0
274 503
275 # Create route exception by exceeding link layer MTU 504 # Create route exception by exceeding link layer MTU
@@ -280,25 +509,18 @@ test_pmtu_vti6_exception() {
280 ${ns_a} ${ping6} -q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev/null 509 ${ns_a} ${ping6} -q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev/null
281 510
282 # Check that exception was created 511 # Check that exception was created
283 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" = "" ]; then 512 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})"
284 err " tunnel exceeding link layer MTU didn't create route exception" 513 check_pmtu_value any "${pmtu}" "creating tunnel exceeding link layer MTU" || return 1
285 return 1
286 fi
287 514
288 # Decrease tunnel MTU, check for PMTU decrease in route exception 515 # Decrease tunnel MTU, check for PMTU decrease in route exception
289 mtu "${ns_a}" vti6_a 3000 516 mtu "${ns_a}" vti6_a 3000
290 517 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})"
291 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 3000 ]; then 518 check_pmtu_value "3000" "${pmtu}" "decreasing tunnel MTU" || fail=1
292 err " decreasing tunnel MTU didn't decrease route exception PMTU"
293 fail=1
294 fi
295 519
296 # Increase tunnel MTU, check for PMTU increase in route exception 520 # Increase tunnel MTU, check for PMTU increase in route exception
297 mtu "${ns_a}" vti6_a 9000 521 mtu "${ns_a}" vti6_a 9000
298 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 9000 ]; then 522 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})"
299 err " increasing tunnel MTU didn't increase route exception PMTU" 523 check_pmtu_value "9000" "${pmtu}" "increasing tunnel MTU" || fail=1
300 fail=1
301 fi
302 524
303 return ${fail} 525 return ${fail}
304} 526}
@@ -445,15 +667,56 @@ test_pmtu_vti6_link_change_mtu() {
445 return ${fail} 667 return ${fail}
446} 668}
447 669
448trap cleanup EXIT 670usage() {
671 echo
672 echo "$0 [OPTIONS] [TEST]..."
673 echo "If no TEST argument is given, all tests will be run."
674 echo
675 echo "Options"
676 echo " --trace: capture traffic to TEST_INTERFACE.pcap"
677 echo
678 echo "Available tests${tests}"
679 exit 1
680}
449 681
450exitcode=0 682exitcode=0
451desc=0 683desc=0
452IFS=" 684IFS="
453" 685"
686
687tracing=0
688for arg do
689 if [ "${arg}" != "${arg#--*}" ]; then
690 opt="${arg#--}"
691 if [ "${opt}" = "trace" ]; then
692 if which tcpdump > /dev/null 2>&1; then
693 tracing=1
694 else
695 echo "=== tcpdump not available, tracing disabled"
696 fi
697 else
698 usage
699 fi
700 else
701 # Check first that all requested tests are available before
702 # running any
703 command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; }
704 fi
705done
706
707trap cleanup EXIT
708
454for t in ${tests}; do 709for t in ${tests}; do
455 [ $desc -eq 0 ] && name="${t}" && desc=1 && continue || desc=0 710 [ $desc -eq 0 ] && name="${t}" && desc=1 && continue || desc=0
456 711
712 run_this=1
713 for arg do
714 [ "${arg}" != "${arg#--*}" ] && continue
715 [ "${arg}" = "${name}" ] && run_this=1 && break
716 run_this=0
717 done
718 [ $run_this -eq 0 ] && continue
719
457 ( 720 (
458 unset IFS 721 unset IFS
459 eval test_${name} 722 eval test_${name}
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 8fdfeafaf8c0..fac68d710f35 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -121,11 +121,11 @@ TEST_F(tls, send_then_sendfile)
121 buf = (char *)malloc(st.st_size); 121 buf = (char *)malloc(st.st_size);
122 122
123 EXPECT_EQ(send(self->fd, test_str, to_send, 0), to_send); 123 EXPECT_EQ(send(self->fd, test_str, to_send, 0), to_send);
124 EXPECT_EQ(recv(self->cfd, recv_buf, to_send, 0), to_send); 124 EXPECT_EQ(recv(self->cfd, recv_buf, to_send, MSG_WAITALL), to_send);
125 EXPECT_EQ(memcmp(test_str, recv_buf, to_send), 0); 125 EXPECT_EQ(memcmp(test_str, recv_buf, to_send), 0);
126 126
127 EXPECT_GE(sendfile(self->fd, filefd, 0, st.st_size), 0); 127 EXPECT_GE(sendfile(self->fd, filefd, 0, st.st_size), 0);
128 EXPECT_EQ(recv(self->cfd, buf, st.st_size, 0), st.st_size); 128 EXPECT_EQ(recv(self->cfd, buf, st.st_size, MSG_WAITALL), st.st_size);
129} 129}
130 130
131TEST_F(tls, recv_max) 131TEST_F(tls, recv_max)
@@ -160,7 +160,7 @@ TEST_F(tls, msg_more)
160 EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len); 160 EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
161 EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_DONTWAIT), -1); 161 EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_DONTWAIT), -1);
162 EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len); 162 EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
163 EXPECT_EQ(recv(self->cfd, buf, send_len * 2, MSG_DONTWAIT), 163 EXPECT_EQ(recv(self->cfd, buf, send_len * 2, MSG_WAITALL),
164 send_len * 2); 164 send_len * 2);
165 EXPECT_EQ(memcmp(buf, test_str, send_len), 0); 165 EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
166} 166}
@@ -180,7 +180,7 @@ TEST_F(tls, sendmsg_single)
180 msg.msg_iov = &vec; 180 msg.msg_iov = &vec;
181 msg.msg_iovlen = 1; 181 msg.msg_iovlen = 1;
182 EXPECT_EQ(sendmsg(self->fd, &msg, 0), send_len); 182 EXPECT_EQ(sendmsg(self->fd, &msg, 0), send_len);
183 EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); 183 EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_WAITALL), send_len);
184 EXPECT_EQ(memcmp(buf, test_str, send_len), 0); 184 EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
185} 185}
186 186
@@ -288,7 +288,7 @@ TEST_F(tls, splice_from_pipe)
288 ASSERT_GE(pipe(p), 0); 288 ASSERT_GE(pipe(p), 0);
289 EXPECT_GE(write(p[1], mem_send, send_len), 0); 289 EXPECT_GE(write(p[1], mem_send, send_len), 0);
290 EXPECT_GE(splice(p[0], NULL, self->fd, NULL, send_len, 0), 0); 290 EXPECT_GE(splice(p[0], NULL, self->fd, NULL, send_len, 0), 0);
291 EXPECT_GE(recv(self->cfd, mem_recv, send_len, 0), 0); 291 EXPECT_EQ(recv(self->cfd, mem_recv, send_len, MSG_WAITALL), send_len);
292 EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); 292 EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
293} 293}
294 294
@@ -306,7 +306,7 @@ TEST_F(tls, splice_from_pipe2)
306 EXPECT_GE(splice(p[0], NULL, self->fd, NULL, 8000, 0), 0); 306 EXPECT_GE(splice(p[0], NULL, self->fd, NULL, 8000, 0), 0);
307 EXPECT_GE(write(p2[1], mem_send + 8000, 8000), 0); 307 EXPECT_GE(write(p2[1], mem_send + 8000, 8000), 0);
308 EXPECT_GE(splice(p2[0], NULL, self->fd, NULL, 8000, 0), 0); 308 EXPECT_GE(splice(p2[0], NULL, self->fd, NULL, 8000, 0), 0);
309 EXPECT_GE(recv(self->cfd, mem_recv, send_len, 0), 0); 309 EXPECT_EQ(recv(self->cfd, mem_recv, send_len, MSG_WAITALL), send_len);
310 EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); 310 EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
311} 311}
312 312
@@ -322,13 +322,13 @@ TEST_F(tls, send_and_splice)
322 322
323 ASSERT_GE(pipe(p), 0); 323 ASSERT_GE(pipe(p), 0);
324 EXPECT_EQ(send(self->fd, test_str, send_len2, 0), send_len2); 324 EXPECT_EQ(send(self->fd, test_str, send_len2, 0), send_len2);
325 EXPECT_NE(recv(self->cfd, buf, send_len2, 0), -1); 325 EXPECT_EQ(recv(self->cfd, buf, send_len2, MSG_WAITALL), send_len2);
326 EXPECT_EQ(memcmp(test_str, buf, send_len2), 0); 326 EXPECT_EQ(memcmp(test_str, buf, send_len2), 0);
327 327
328 EXPECT_GE(write(p[1], mem_send, send_len), send_len); 328 EXPECT_GE(write(p[1], mem_send, send_len), send_len);
329 EXPECT_GE(splice(p[0], NULL, self->fd, NULL, send_len, 0), send_len); 329 EXPECT_GE(splice(p[0], NULL, self->fd, NULL, send_len, 0), send_len);
330 330
331 EXPECT_GE(recv(self->cfd, mem_recv, send_len, 0), 0); 331 EXPECT_EQ(recv(self->cfd, mem_recv, send_len, MSG_WAITALL), send_len);
332 EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); 332 EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
333} 333}
334 334
@@ -436,7 +436,7 @@ TEST_F(tls, multiple_send_single_recv)
436 EXPECT_GE(send(self->fd, send_mem, send_len, 0), 0); 436 EXPECT_GE(send(self->fd, send_mem, send_len, 0), 0);
437 EXPECT_GE(send(self->fd, send_mem, send_len, 0), 0); 437 EXPECT_GE(send(self->fd, send_mem, send_len, 0), 0);
438 memset(recv_mem, 0, total_len); 438 memset(recv_mem, 0, total_len);
439 EXPECT_EQ(recv(self->cfd, recv_mem, total_len, 0), total_len); 439 EXPECT_EQ(recv(self->cfd, recv_mem, total_len, MSG_WAITALL), total_len);
440 440
441 EXPECT_EQ(memcmp(send_mem, recv_mem, send_len), 0); 441 EXPECT_EQ(memcmp(send_mem, recv_mem, send_len), 0);
442 EXPECT_EQ(memcmp(send_mem, recv_mem + send_len, send_len), 0); 442 EXPECT_EQ(memcmp(send_mem, recv_mem + send_len, send_len), 0);
@@ -516,17 +516,17 @@ TEST_F(tls, recv_peek_multiple_records)
516 len = strlen(test_str_second) + 1; 516 len = strlen(test_str_second) + 1;
517 EXPECT_EQ(send(self->fd, test_str_second, len, 0), len); 517 EXPECT_EQ(send(self->fd, test_str_second, len, 0), len);
518 518
519 len = sizeof(buf); 519 len = strlen(test_str_first);
520 memset(buf, 0, len); 520 memset(buf, 0, len);
521 EXPECT_NE(recv(self->cfd, buf, len, MSG_PEEK), -1); 521 EXPECT_EQ(recv(self->cfd, buf, len, MSG_PEEK | MSG_WAITALL), len);
522 522
523 /* MSG_PEEK can only peek into the current record. */ 523 /* MSG_PEEK can only peek into the current record. */
524 len = strlen(test_str_first) + 1; 524 len = strlen(test_str_first);
525 EXPECT_EQ(memcmp(test_str_first, buf, len), 0); 525 EXPECT_EQ(memcmp(test_str_first, buf, len), 0);
526 526
527 len = sizeof(buf); 527 len = strlen(test_str) + 1;
528 memset(buf, 0, len); 528 memset(buf, 0, len);
529 EXPECT_NE(recv(self->cfd, buf, len, 0), -1); 529 EXPECT_EQ(recv(self->cfd, buf, len, MSG_WAITALL), len);
530 530
531 /* Non-MSG_PEEK will advance strparser (and therefore record) 531 /* Non-MSG_PEEK will advance strparser (and therefore record)
532 * however. 532 * however.
@@ -543,6 +543,28 @@ TEST_F(tls, recv_peek_multiple_records)
543 len = strlen(test_str_second) + 1; 543 len = strlen(test_str_second) + 1;
544 EXPECT_EQ(send(self->fd, test_str_second, len, 0), len); 544 EXPECT_EQ(send(self->fd, test_str_second, len, 0), len);
545 545
546 len = strlen(test_str) + 1;
547 memset(buf, 0, len);
548 EXPECT_EQ(recv(self->cfd, buf, len, MSG_PEEK | MSG_WAITALL), len);
549
550 len = strlen(test_str) + 1;
551 EXPECT_EQ(memcmp(test_str, buf, len), 0);
552}
553
554TEST_F(tls, recv_peek_large_buf_mult_recs)
555{
556 char const *test_str = "test_read_peek_mult_recs";
557 char const *test_str_first = "test_read_peek";
558 char const *test_str_second = "_mult_recs";
559 int len;
560 char buf[64];
561
562 len = strlen(test_str_first);
563 EXPECT_EQ(send(self->fd, test_str_first, len, 0), len);
564
565 len = strlen(test_str_second) + 1;
566 EXPECT_EQ(send(self->fd, test_str_second, len, 0), len);
567
546 len = sizeof(buf); 568 len = sizeof(buf);
547 memset(buf, 0, len); 569 memset(buf, 0, len);
548 EXPECT_NE(recv(self->cfd, buf, len, MSG_PEEK), -1); 570 EXPECT_NE(recv(self->cfd, buf, len, MSG_PEEK), -1);
@@ -551,6 +573,7 @@ TEST_F(tls, recv_peek_multiple_records)
551 EXPECT_EQ(memcmp(test_str, buf, len), 0); 573 EXPECT_EQ(memcmp(test_str, buf, len), 0);
552} 574}
553 575
576
554TEST_F(tls, pollin) 577TEST_F(tls, pollin)
555{ 578{
556 char const *test_str = "test_poll"; 579 char const *test_str = "test_poll";
@@ -564,7 +587,7 @@ TEST_F(tls, pollin)
564 587
565 EXPECT_EQ(poll(&fd, 1, 20), 1); 588 EXPECT_EQ(poll(&fd, 1, 20), 1);
566 EXPECT_EQ(fd.revents & POLLIN, 1); 589 EXPECT_EQ(fd.revents & POLLIN, 1);
567 EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); 590 EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_WAITALL), send_len);
568 /* Test timing out */ 591 /* Test timing out */
569 EXPECT_EQ(poll(&fd, 1, 20), 0); 592 EXPECT_EQ(poll(&fd, 1, 20), 0);
570} 593}
@@ -582,7 +605,7 @@ TEST_F(tls, poll_wait)
582 /* Set timeout to inf. secs */ 605 /* Set timeout to inf. secs */
583 EXPECT_EQ(poll(&fd, 1, -1), 1); 606 EXPECT_EQ(poll(&fd, 1, -1), 1);
584 EXPECT_EQ(fd.revents & POLLIN, 1); 607 EXPECT_EQ(fd.revents & POLLIN, 1);
585 EXPECT_EQ(recv(self->cfd, recv_mem, send_len, 0), send_len); 608 EXPECT_EQ(recv(self->cfd, recv_mem, send_len, MSG_WAITALL), send_len);
586} 609}
587 610
588TEST_F(tls, blocking) 611TEST_F(tls, blocking)
@@ -728,7 +751,7 @@ TEST_F(tls, control_msg)
728 EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1); 751 EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1);
729 752
730 vec.iov_base = buf; 753 vec.iov_base = buf;
731 EXPECT_EQ(recvmsg(self->cfd, &msg, 0), send_len); 754 EXPECT_EQ(recvmsg(self->cfd, &msg, MSG_WAITALL), send_len);
732 cmsg = CMSG_FIRSTHDR(&msg); 755 cmsg = CMSG_FIRSTHDR(&msg);
733 EXPECT_NE(cmsg, NULL); 756 EXPECT_NE(cmsg, NULL);
734 EXPECT_EQ(cmsg->cmsg_level, SOL_TLS); 757 EXPECT_EQ(cmsg->cmsg_level, SOL_TLS);
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 201b598558b9..b3ad909aefbc 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -28,7 +28,8 @@ SUB_DIRS = alignment \
28 tm \ 28 tm \
29 vphn \ 29 vphn \
30 math \ 30 math \
31 ptrace 31 ptrace \
32 security
32 33
33endif 34endif
34 35
diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h
index 7f348c059bc2..52b4710469d2 100644
--- a/tools/testing/selftests/powerpc/include/reg.h
+++ b/tools/testing/selftests/powerpc/include/reg.h
@@ -17,6 +17,7 @@
17 : "memory") 17 : "memory")
18 18
19#define mb() asm volatile("sync" : : : "memory"); 19#define mb() asm volatile("sync" : : : "memory");
20#define barrier() asm volatile("" : : : "memory");
20 21
21#define SPRN_MMCR2 769 22#define SPRN_MMCR2 769
22#define SPRN_MMCRA 770 23#define SPRN_MMCRA 770
diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h
index c58c370828b4..49621822d7c3 100644
--- a/tools/testing/selftests/powerpc/include/utils.h
+++ b/tools/testing/selftests/powerpc/include/utils.h
@@ -11,6 +11,7 @@
11#include <stdint.h> 11#include <stdint.h>
12#include <stdbool.h> 12#include <stdbool.h>
13#include <linux/auxvec.h> 13#include <linux/auxvec.h>
14#include <linux/perf_event.h>
14#include "reg.h" 15#include "reg.h"
15 16
16/* Avoid headaches with PRI?64 - just use %ll? always */ 17/* Avoid headaches with PRI?64 - just use %ll? always */
@@ -31,6 +32,15 @@ void *get_auxv_entry(int type);
31 32
32int pick_online_cpu(void); 33int pick_online_cpu(void);
33 34
35int read_debugfs_file(char *debugfs_file, int *result);
36int write_debugfs_file(char *debugfs_file, int result);
37void set_dscr(unsigned long val);
38int perf_event_open_counter(unsigned int type,
39 unsigned long config, int group_fd);
40int perf_event_enable(int fd);
41int perf_event_disable(int fd);
42int perf_event_reset(int fd);
43
34static inline bool have_hwcap(unsigned long ftr) 44static inline bool have_hwcap(unsigned long ftr)
35{ 45{
36 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; 46 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr;
@@ -80,4 +90,12 @@ do { \
80#define PPC_FEATURE2_ARCH_3_00 0x00800000 90#define PPC_FEATURE2_ARCH_3_00 0x00800000
81#endif 91#endif
82 92
93#if defined(__powerpc64__)
94#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP]
95#elif defined(__powerpc__)
96#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
97#else
98#error implement UCONTEXT_NIA
99#endif
100
83#endif /* _SELFTESTS_POWERPC_UTILS_H */ 101#endif /* _SELFTESTS_POWERPC_UTILS_H */
diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore
index 7d7c42ed6de9..ba919308fe30 100644
--- a/tools/testing/selftests/powerpc/mm/.gitignore
+++ b/tools/testing/selftests/powerpc/mm/.gitignore
@@ -2,4 +2,5 @@ hugetlb_vs_thp_test
2subpage_prot 2subpage_prot
3tempfile 3tempfile
4prot_sao 4prot_sao
5segv_errors \ No newline at end of file 5segv_errors
6wild_bctr \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile
index 33ced6e0ad25..43d68420e363 100644
--- a/tools/testing/selftests/powerpc/mm/Makefile
+++ b/tools/testing/selftests/powerpc/mm/Makefile
@@ -2,7 +2,7 @@
2noarg: 2noarg:
3 $(MAKE) -C ../ 3 $(MAKE) -C ../
4 4
5TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors 5TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors wild_bctr
6TEST_GEN_FILES := tempfile 6TEST_GEN_FILES := tempfile
7 7
8top_srcdir = ../../../../.. 8top_srcdir = ../../../../..
@@ -12,6 +12,8 @@ $(TEST_GEN_PROGS): ../harness.c
12 12
13$(OUTPUT)/prot_sao: ../utils.c 13$(OUTPUT)/prot_sao: ../utils.c
14 14
15$(OUTPUT)/wild_bctr: CFLAGS += -m64
16
15$(OUTPUT)/tempfile: 17$(OUTPUT)/tempfile:
16 dd if=/dev/zero of=$@ bs=64k count=1 18 dd if=/dev/zero of=$@ bs=64k count=1
17 19
diff --git a/tools/testing/selftests/powerpc/mm/wild_bctr.c b/tools/testing/selftests/powerpc/mm/wild_bctr.c
new file mode 100644
index 000000000000..1b0e9e9a2ddc
--- /dev/null
+++ b/tools/testing/selftests/powerpc/mm/wild_bctr.c
@@ -0,0 +1,155 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018, Michael Ellerman, IBM Corp.
4 *
5 * Test that an out-of-bounds branch to counter behaves as expected.
6 */
7
8#include <setjmp.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/mman.h>
13#include <sys/types.h>
14#include <sys/wait.h>
15#include <ucontext.h>
16#include <unistd.h>
17
18#include "utils.h"
19
20
21#define BAD_NIP 0x788c545a18000000ull
22
23static struct pt_regs signal_regs;
24static jmp_buf setjmp_env;
25
26static void save_regs(ucontext_t *ctxt)
27{
28 struct pt_regs *regs = ctxt->uc_mcontext.regs;
29
30 memcpy(&signal_regs, regs, sizeof(signal_regs));
31}
32
33static void segv_handler(int signum, siginfo_t *info, void *ctxt_v)
34{
35 save_regs(ctxt_v);
36 longjmp(setjmp_env, 1);
37}
38
39static void usr2_handler(int signum, siginfo_t *info, void *ctxt_v)
40{
41 save_regs(ctxt_v);
42}
43
44static int ok(void)
45{
46 printf("Everything is OK in here.\n");
47 return 0;
48}
49
50#define REG_POISON 0x5a5aUL
51#define POISONED_REG(n) ((REG_POISON << 48) | ((n) << 32) | (REG_POISON << 16) | (n))
52
53static inline void poison_regs(void)
54{
55 #define POISON_REG(n) \
56 "lis " __stringify(n) "," __stringify(REG_POISON) ";" \
57 "addi " __stringify(n) "," __stringify(n) "," __stringify(n) ";" \
58 "sldi " __stringify(n) "," __stringify(n) ", 32 ;" \
59 "oris " __stringify(n) "," __stringify(n) "," __stringify(REG_POISON) ";" \
60 "addi " __stringify(n) "," __stringify(n) "," __stringify(n) ";"
61
62 asm (POISON_REG(15)
63 POISON_REG(16)
64 POISON_REG(17)
65 POISON_REG(18)
66 POISON_REG(19)
67 POISON_REG(20)
68 POISON_REG(21)
69 POISON_REG(22)
70 POISON_REG(23)
71 POISON_REG(24)
72 POISON_REG(25)
73 POISON_REG(26)
74 POISON_REG(27)
75 POISON_REG(28)
76 POISON_REG(29)
77 : // inputs
78 : // outputs
79 : "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25",
80 "26", "27", "28", "29"
81 );
82 #undef POISON_REG
83}
84
85static int check_regs(void)
86{
87 unsigned long i;
88
89 for (i = 15; i <= 29; i++)
90 FAIL_IF(signal_regs.gpr[i] != POISONED_REG(i));
91
92 printf("Regs OK\n");
93 return 0;
94}
95
96static void dump_regs(void)
97{
98 for (int i = 0; i < 32; i += 4) {
99 printf("r%02d 0x%016lx r%02d 0x%016lx " \
100 "r%02d 0x%016lx r%02d 0x%016lx\n",
101 i, signal_regs.gpr[i],
102 i+1, signal_regs.gpr[i+1],
103 i+2, signal_regs.gpr[i+2],
104 i+3, signal_regs.gpr[i+3]);
105 }
106}
107
108int test_wild_bctr(void)
109{
110 int (*func_ptr)(void);
111 struct sigaction segv = {
112 .sa_sigaction = segv_handler,
113 .sa_flags = SA_SIGINFO
114 };
115 struct sigaction usr2 = {
116 .sa_sigaction = usr2_handler,
117 .sa_flags = SA_SIGINFO
118 };
119
120 FAIL_IF(sigaction(SIGSEGV, &segv, NULL));
121 FAIL_IF(sigaction(SIGUSR2, &usr2, NULL));
122
123 bzero(&signal_regs, sizeof(signal_regs));
124
125 if (setjmp(setjmp_env) == 0) {
126 func_ptr = ok;
127 func_ptr();
128
129 kill(getpid(), SIGUSR2);
130 printf("Regs before:\n");
131 dump_regs();
132 bzero(&signal_regs, sizeof(signal_regs));
133
134 poison_regs();
135
136 func_ptr = (int (*)(void))BAD_NIP;
137 func_ptr();
138
139 FAIL_IF(1); /* we didn't segv? */
140 }
141
142 FAIL_IF(signal_regs.nip != BAD_NIP);
143
144 printf("All good - took SEGV as expected branching to 0x%llx\n", BAD_NIP);
145
146 dump_regs();
147 FAIL_IF(check_regs());
148
149 return 0;
150}
151
152int main(void)
153{
154 return test_harness(test_wild_bctr, "wild_bctr");
155}
diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
index ed3239bbfae2..ee1e9ca22f0d 100644
--- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
+++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
@@ -65,14 +65,6 @@ static int unprotect_region(void)
65extern char __start___ex_table[]; 65extern char __start___ex_table[];
66extern char __stop___ex_table[]; 66extern char __stop___ex_table[];
67 67
68#if defined(__powerpc64__)
69#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP]
70#elif defined(__powerpc__)
71#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
72#else
73#error implement UCONTEXT_NIA
74#endif
75
76struct extbl_entry { 68struct extbl_entry {
77 int insn; 69 int insn;
78 int fixup; 70 int fixup;
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index 923d531265f8..9b35ca8e8f13 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -2,7 +2,7 @@
2TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ 2TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
3 ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ 3 ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
4 ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \ 4 ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \
5 perf-hwbreak 5 perf-hwbreak ptrace-syscall
6 6
7top_srcdir = ../../../../.. 7top_srcdir = ../../../../..
8include ../../lib.mk 8include ../../lib.mk
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c b/tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c
new file mode 100644
index 000000000000..3353210dcdbd
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c
@@ -0,0 +1,228 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * A ptrace test for testing PTRACE_SYSEMU, PTRACE_SETREGS and
4 * PTRACE_GETREG. This test basically create a child process that executes
5 * syscalls and the parent process check if it is being traced appropriated.
6 *
7 * This test is heavily based on tools/testing/selftests/x86/ptrace_syscall.c
8 * test, and it was adapted to run on Powerpc by
9 * Breno Leitao <leitao@debian.org>
10 */
11#define _GNU_SOURCE
12
13#include <sys/ptrace.h>
14#include <sys/types.h>
15#include <sys/wait.h>
16#include <sys/syscall.h>
17#include <sys/user.h>
18#include <unistd.h>
19#include <errno.h>
20#include <stddef.h>
21#include <stdio.h>
22#include <err.h>
23#include <string.h>
24#include <sys/auxv.h>
25#include "utils.h"
26
27/* Bitness-agnostic defines for user_regs_struct fields. */
28#define user_syscall_nr gpr[0]
29#define user_arg0 gpr[3]
30#define user_arg1 gpr[4]
31#define user_arg2 gpr[5]
32#define user_arg3 gpr[6]
33#define user_arg4 gpr[7]
34#define user_arg5 gpr[8]
35#define user_ip nip
36
37#define PTRACE_SYSEMU 0x1d
38
39static int nerrs;
40
41static void wait_trap(pid_t chld)
42{
43 siginfo_t si;
44
45 if (waitid(P_PID, chld, &si, WEXITED|WSTOPPED) != 0)
46 err(1, "waitid");
47 if (si.si_pid != chld)
48 errx(1, "got unexpected pid in event\n");
49 if (si.si_code != CLD_TRAPPED)
50 errx(1, "got unexpected event type %d\n", si.si_code);
51}
52
53static void test_ptrace_syscall_restart(void)
54{
55 int status;
56 struct pt_regs regs;
57 pid_t chld;
58
59 printf("[RUN]\tptrace-induced syscall restart\n");
60
61 chld = fork();
62 if (chld < 0)
63 err(1, "fork");
64
65 /*
66 * Child process is running 4 syscalls after ptrace.
67 *
68 * 1) getpid()
69 * 2) gettid()
70 * 3) tgkill() -> Send SIGSTOP
71 * 4) gettid() -> Where the tests will happen essentially
72 */
73 if (chld == 0) {
74 if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0)
75 err(1, "PTRACE_TRACEME");
76
77 pid_t pid = getpid(), tid = syscall(SYS_gettid);
78
79 printf("\tChild will make one syscall\n");
80 syscall(SYS_tgkill, pid, tid, SIGSTOP);
81
82 syscall(SYS_gettid, 10, 11, 12, 13, 14, 15);
83 _exit(0);
84 }
85 /* Parent process below */
86
87 /* Wait for SIGSTOP sent by tgkill above. */
88 if (waitpid(chld, &status, 0) != chld || !WIFSTOPPED(status))
89 err(1, "waitpid");
90
91 printf("[RUN]\tSYSEMU\n");
92 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
93 err(1, "PTRACE_SYSEMU");
94 wait_trap(chld);
95
96 if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
97 err(1, "PTRACE_GETREGS");
98
99 /*
100 * Ptrace trapped prior to executing the syscall, thus r3 still has
101 * the syscall number instead of the sys_gettid() result
102 */
103 if (regs.user_syscall_nr != SYS_gettid ||
104 regs.user_arg0 != 10 || regs.user_arg1 != 11 ||
105 regs.user_arg2 != 12 || regs.user_arg3 != 13 ||
106 regs.user_arg4 != 14 || regs.user_arg5 != 15) {
107 printf("[FAIL]\tInitial args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n",
108 (unsigned long)regs.user_syscall_nr,
109 (unsigned long)regs.user_arg0,
110 (unsigned long)regs.user_arg1,
111 (unsigned long)regs.user_arg2,
112 (unsigned long)regs.user_arg3,
113 (unsigned long)regs.user_arg4,
114 (unsigned long)regs.user_arg5);
115 nerrs++;
116 } else {
117 printf("[OK]\tInitial nr and args are correct\n"); }
118
119 printf("[RUN]\tRestart the syscall (ip = 0x%lx)\n",
120 (unsigned long)regs.user_ip);
121
122 /*
123 * Rewind to retry the same syscall again. This will basically test
124 * the rewind process together with PTRACE_SETREGS and PTRACE_GETREGS.
125 */
126 regs.user_ip -= 4;
127 if (ptrace(PTRACE_SETREGS, chld, 0, &regs) != 0)
128 err(1, "PTRACE_SETREGS");
129
130 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
131 err(1, "PTRACE_SYSEMU");
132 wait_trap(chld);
133
134 if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
135 err(1, "PTRACE_GETREGS");
136
137 if (regs.user_syscall_nr != SYS_gettid ||
138 regs.user_arg0 != 10 || regs.user_arg1 != 11 ||
139 regs.user_arg2 != 12 || regs.user_arg3 != 13 ||
140 regs.user_arg4 != 14 || regs.user_arg5 != 15) {
141 printf("[FAIL]\tRestart nr or args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n",
142 (unsigned long)regs.user_syscall_nr,
143 (unsigned long)regs.user_arg0,
144 (unsigned long)regs.user_arg1,
145 (unsigned long)regs.user_arg2,
146 (unsigned long)regs.user_arg3,
147 (unsigned long)regs.user_arg4,
148 (unsigned long)regs.user_arg5);
149 nerrs++;
150 } else {
151 printf("[OK]\tRestarted nr and args are correct\n");
152 }
153
154 printf("[RUN]\tChange nr and args and restart the syscall (ip = 0x%lx)\n",
155 (unsigned long)regs.user_ip);
156
157 /*
158 * Inject a new syscall (getpid) in the same place the previous
159 * syscall (gettid), rewind and re-execute.
160 */
161 regs.user_syscall_nr = SYS_getpid;
162 regs.user_arg0 = 20;
163 regs.user_arg1 = 21;
164 regs.user_arg2 = 22;
165 regs.user_arg3 = 23;
166 regs.user_arg4 = 24;
167 regs.user_arg5 = 25;
168 regs.user_ip -= 4;
169
170 if (ptrace(PTRACE_SETREGS, chld, 0, &regs) != 0)
171 err(1, "PTRACE_SETREGS");
172
173 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
174 err(1, "PTRACE_SYSEMU");
175 wait_trap(chld);
176
177 if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
178 err(1, "PTRACE_GETREGS");
179
180 /* Check that ptrace stopped at the new syscall that was
181 * injected, and guarantee that it haven't executed, i.e, user_args
182 * contain the arguments and not the syscall return value, for
183 * instance.
184 */
185 if (regs.user_syscall_nr != SYS_getpid
186 || regs.user_arg0 != 20 || regs.user_arg1 != 21
187 || regs.user_arg2 != 22 || regs.user_arg3 != 23
188 || regs.user_arg4 != 24 || regs.user_arg5 != 25) {
189
190 printf("[FAIL]\tRestart nr or args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n",
191 (unsigned long)regs.user_syscall_nr,
192 (unsigned long)regs.user_arg0,
193 (unsigned long)regs.user_arg1,
194 (unsigned long)regs.user_arg2,
195 (unsigned long)regs.user_arg3,
196 (unsigned long)regs.user_arg4,
197 (unsigned long)regs.user_arg5);
198 nerrs++;
199 } else {
200 printf("[OK]\tReplacement nr and args are correct\n");
201 }
202
203 if (ptrace(PTRACE_CONT, chld, 0, 0) != 0)
204 err(1, "PTRACE_CONT");
205
206 if (waitpid(chld, &status, 0) != chld)
207 err(1, "waitpid");
208
209 /* Guarantee that the process executed properly, returning 0 */
210 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
211 printf("[FAIL]\tChild failed\n");
212 nerrs++;
213 } else {
214 printf("[OK]\tChild exited cleanly\n");
215 }
216}
217
218int ptrace_syscall(void)
219{
220 test_ptrace_syscall_restart();
221
222 return nerrs;
223}
224
225int main(void)
226{
227 return test_harness(ptrace_syscall, "ptrace_syscall");
228}
diff --git a/tools/testing/selftests/powerpc/security/Makefile b/tools/testing/selftests/powerpc/security/Makefile
new file mode 100644
index 000000000000..44690f1bb26a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/security/Makefile
@@ -0,0 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0+
2
3TEST_GEN_PROGS := rfi_flush
4
5CFLAGS += -I../../../../../usr/include
6
7include ../../lib.mk
8
9$(TEST_GEN_PROGS): ../harness.c ../utils.c
diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c
new file mode 100644
index 000000000000..564ed45bbf73
--- /dev/null
+++ b/tools/testing/selftests/powerpc/security/rfi_flush.c
@@ -0,0 +1,132 @@
1// SPDX-License-Identifier: GPL-2.0+
2
3/*
4 * Copyright 2018 IBM Corporation.
5 */
6
7#define __SANE_USERSPACE_TYPES__
8
9#include <sys/types.h>
10#include <stdint.h>
11#include <malloc.h>
12#include <unistd.h>
13#include <stdlib.h>
14#include <string.h>
15#include <stdio.h>
16#include "utils.h"
17
18#define CACHELINE_SIZE 128
19
20struct perf_event_read {
21 __u64 nr;
22 __u64 l1d_misses;
23};
24
25static inline __u64 load(void *addr)
26{
27 __u64 tmp;
28
29 asm volatile("ld %0,0(%1)" : "=r"(tmp) : "b"(addr));
30
31 return tmp;
32}
33
34static void syscall_loop(char *p, unsigned long iterations,
35 unsigned long zero_size)
36{
37 for (unsigned long i = 0; i < iterations; i++) {
38 for (unsigned long j = 0; j < zero_size; j += CACHELINE_SIZE)
39 load(p + j);
40 getppid();
41 }
42}
43
44int rfi_flush_test(void)
45{
46 char *p;
47 int repetitions = 10;
48 int fd, passes = 0, iter, rc = 0;
49 struct perf_event_read v;
50 __u64 l1d_misses_total = 0;
51 unsigned long iterations = 100000, zero_size = 24 * 1024;
52 int rfi_flush_org, rfi_flush;
53
54 SKIP_IF(geteuid() != 0);
55
56 if (read_debugfs_file("powerpc/rfi_flush", &rfi_flush_org)) {
57 perror("Unable to read powerpc/rfi_flush debugfs file");
58 SKIP_IF(1);
59 }
60
61 rfi_flush = rfi_flush_org;
62
63 fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1);
64 FAIL_IF(fd < 0);
65
66 p = (char *)memalign(zero_size, CACHELINE_SIZE);
67
68 FAIL_IF(perf_event_enable(fd));
69
70 set_dscr(1);
71
72 iter = repetitions;
73
74again:
75 FAIL_IF(perf_event_reset(fd));
76
77 syscall_loop(p, iterations, zero_size);
78
79 FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v));
80
81 /* Expect at least zero_size/CACHELINE_SIZE misses per iteration */
82 if (v.l1d_misses >= (iterations * zero_size / CACHELINE_SIZE) && rfi_flush)
83 passes++;
84 else if (v.l1d_misses < iterations && !rfi_flush)
85 passes++;
86
87 l1d_misses_total += v.l1d_misses;
88
89 while (--iter)
90 goto again;
91
92 if (passes < repetitions) {
93 printf("FAIL (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d failures]\n",
94 rfi_flush, l1d_misses_total, rfi_flush ? '<' : '>',
95 rfi_flush ? (repetitions * iterations * zero_size / CACHELINE_SIZE) : iterations,
96 repetitions - passes, repetitions);
97 rc = 1;
98 } else
99 printf("PASS (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d pass]\n",
100 rfi_flush, l1d_misses_total, rfi_flush ? '>' : '<',
101 rfi_flush ? (repetitions * iterations * zero_size / CACHELINE_SIZE) : iterations,
102 passes, repetitions);
103
104 if (rfi_flush == rfi_flush_org) {
105 rfi_flush = !rfi_flush_org;
106 if (write_debugfs_file("powerpc/rfi_flush", rfi_flush) < 0) {
107 perror("error writing to powerpc/rfi_flush debugfs file");
108 return 1;
109 }
110 iter = repetitions;
111 l1d_misses_total = 0;
112 passes = 0;
113 goto again;
114 }
115
116 perf_event_disable(fd);
117 close(fd);
118
119 set_dscr(0);
120
121 if (write_debugfs_file("powerpc/rfi_flush", rfi_flush_org) < 0) {
122 perror("unable to restore original value of powerpc/rfi_flush debugfs file");
123 return 1;
124 }
125
126 return rc;
127}
128
129int main(int argc, char *argv[])
130{
131 return test_harness(rfi_flush_test, "rfi_flush_test");
132}
diff --git a/tools/testing/selftests/powerpc/tm/tm-tmspr.c b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
index 2bda81c7bf23..df1d7d4b1c89 100644
--- a/tools/testing/selftests/powerpc/tm/tm-tmspr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
@@ -98,7 +98,7 @@ void texasr(void *in)
98 98
99int test_tmspr() 99int test_tmspr()
100{ 100{
101 pthread_t thread; 101 pthread_t *thread;
102 int thread_num; 102 int thread_num;
103 unsigned long i; 103 unsigned long i;
104 104
@@ -107,21 +107,28 @@ int test_tmspr()
107 /* To cause some context switching */ 107 /* To cause some context switching */
108 thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN); 108 thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
109 109
110 thread = malloc(thread_num * sizeof(pthread_t));
111 if (thread == NULL)
112 return EXIT_FAILURE;
113
110 /* Test TFIAR and TFHAR */ 114 /* Test TFIAR and TFHAR */
111 for (i = 0 ; i < thread_num ; i += 2){ 115 for (i = 0; i < thread_num; i += 2) {
112 if (pthread_create(&thread, NULL, (void*)tfiar_tfhar, (void *)i)) 116 if (pthread_create(&thread[i], NULL, (void *)tfiar_tfhar,
117 (void *)i))
113 return EXIT_FAILURE; 118 return EXIT_FAILURE;
114 } 119 }
115 if (pthread_join(thread, NULL) != 0)
116 return EXIT_FAILURE;
117
118 /* Test TEXASR */ 120 /* Test TEXASR */
119 for (i = 0 ; i < thread_num ; i++){ 121 for (i = 1; i < thread_num; i += 2) {
120 if (pthread_create(&thread, NULL, (void*)texasr, (void *)i)) 122 if (pthread_create(&thread[i], NULL, (void *)texasr, (void *)i))
121 return EXIT_FAILURE; 123 return EXIT_FAILURE;
122 } 124 }
123 if (pthread_join(thread, NULL) != 0) 125
124 return EXIT_FAILURE; 126 for (i = 0; i < thread_num; i++) {
127 if (pthread_join(thread[i], NULL) != 0)
128 return EXIT_FAILURE;
129 }
130
131 free(thread);
125 132
126 if (passed) 133 if (passed)
127 return 0; 134 return 0;
diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
index 156c8e750259..09894f4ff62e 100644
--- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c
+++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
@@ -236,7 +236,8 @@ void *tm_una_ping(void *input)
236 } 236 }
237 237
238 /* Check if we were not expecting a failure and a it occurred. */ 238 /* Check if we were not expecting a failure and a it occurred. */
239 if (!expecting_failure() && is_failure(cr_)) { 239 if (!expecting_failure() && is_failure(cr_) &&
240 !failure_is_reschedule()) {
240 printf("\n\tUnexpected transaction failure 0x%02lx\n\t", 241 printf("\n\tUnexpected transaction failure 0x%02lx\n\t",
241 failure_code()); 242 failure_code());
242 return (void *) -1; 243 return (void *) -1;
@@ -244,9 +245,11 @@ void *tm_una_ping(void *input)
244 245
245 /* 246 /*
246 * Check if TM failed due to the cause we were expecting. 0xda is a 247 * Check if TM failed due to the cause we were expecting. 0xda is a
247 * TM_CAUSE_FAC_UNAV cause, otherwise it's an unexpected cause. 248 * TM_CAUSE_FAC_UNAV cause, otherwise it's an unexpected cause, unless
249 * it was caused by a reschedule.
248 */ 250 */
249 if (is_failure(cr_) && !failure_is_unavailable()) { 251 if (is_failure(cr_) && !failure_is_unavailable() &&
252 !failure_is_reschedule()) {
250 printf("\n\tUnexpected failure cause 0x%02lx\n\t", 253 printf("\n\tUnexpected failure cause 0x%02lx\n\t",
251 failure_code()); 254 failure_code());
252 return (void *) -1; 255 return (void *) -1;
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index df4204247d45..5518b1d4ef8b 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -52,6 +52,15 @@ static inline bool failure_is_unavailable(void)
52 return (failure_code() & TM_CAUSE_FAC_UNAV) == TM_CAUSE_FAC_UNAV; 52 return (failure_code() & TM_CAUSE_FAC_UNAV) == TM_CAUSE_FAC_UNAV;
53} 53}
54 54
55static inline bool failure_is_reschedule(void)
56{
57 if ((failure_code() & TM_CAUSE_RESCHED) == TM_CAUSE_RESCHED ||
58 (failure_code() & TM_CAUSE_KVM_RESCHED) == TM_CAUSE_KVM_RESCHED)
59 return true;
60
61 return false;
62}
63
55static inline bool failure_is_nesting(void) 64static inline bool failure_is_nesting(void)
56{ 65{
57 return (__builtin_get_texasru() & 0x400000); 66 return (__builtin_get_texasru() & 0x400000);
diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c
index aa8fc1e6365b..43c342845be0 100644
--- a/tools/testing/selftests/powerpc/utils.c
+++ b/tools/testing/selftests/powerpc/utils.c
@@ -10,16 +10,22 @@
10#include <fcntl.h> 10#include <fcntl.h>
11#include <link.h> 11#include <link.h>
12#include <sched.h> 12#include <sched.h>
13#include <signal.h>
13#include <stdio.h> 14#include <stdio.h>
15#include <stdlib.h>
14#include <string.h> 16#include <string.h>
17#include <sys/ioctl.h>
15#include <sys/stat.h> 18#include <sys/stat.h>
16#include <sys/types.h> 19#include <sys/types.h>
17#include <sys/utsname.h> 20#include <sys/utsname.h>
18#include <unistd.h> 21#include <unistd.h>
22#include <asm/unistd.h>
23#include <linux/limits.h>
19 24
20#include "utils.h" 25#include "utils.h"
21 26
22static char auxv[4096]; 27static char auxv[4096];
28extern unsigned int dscr_insn[];
23 29
24int read_auxv(char *buf, ssize_t buf_size) 30int read_auxv(char *buf, ssize_t buf_size)
25{ 31{
@@ -121,3 +127,149 @@ bool is_ppc64le(void)
121 127
122 return strcmp(uts.machine, "ppc64le") == 0; 128 return strcmp(uts.machine, "ppc64le") == 0;
123} 129}
130
131int read_debugfs_file(char *debugfs_file, int *result)
132{
133 int rc = -1, fd;
134 char path[PATH_MAX];
135 char value[16];
136
137 strcpy(path, "/sys/kernel/debug/");
138 strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1);
139
140 if ((fd = open(path, O_RDONLY)) < 0)
141 return rc;
142
143 if ((rc = read(fd, value, sizeof(value))) < 0)
144 return rc;
145
146 value[15] = 0;
147 *result = atoi(value);
148 close(fd);
149
150 return 0;
151}
152
153int write_debugfs_file(char *debugfs_file, int result)
154{
155 int rc = -1, fd;
156 char path[PATH_MAX];
157 char value[16];
158
159 strcpy(path, "/sys/kernel/debug/");
160 strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1);
161
162 if ((fd = open(path, O_WRONLY)) < 0)
163 return rc;
164
165 snprintf(value, 16, "%d", result);
166
167 if ((rc = write(fd, value, strlen(value))) < 0)
168 return rc;
169
170 close(fd);
171
172 return 0;
173}
174
175static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
176 int cpu, int group_fd, unsigned long flags)
177{
178 return syscall(__NR_perf_event_open, hw_event, pid, cpu,
179 group_fd, flags);
180}
181
182static void perf_event_attr_init(struct perf_event_attr *event_attr,
183 unsigned int type,
184 unsigned long config)
185{
186 memset(event_attr, 0, sizeof(*event_attr));
187
188 event_attr->type = type;
189 event_attr->size = sizeof(struct perf_event_attr);
190 event_attr->config = config;
191 event_attr->read_format = PERF_FORMAT_GROUP;
192 event_attr->disabled = 1;
193 event_attr->exclude_kernel = 1;
194 event_attr->exclude_hv = 1;
195 event_attr->exclude_guest = 1;
196}
197
198int perf_event_open_counter(unsigned int type,
199 unsigned long config, int group_fd)
200{
201 int fd;
202 struct perf_event_attr event_attr;
203
204 perf_event_attr_init(&event_attr, type, config);
205
206 fd = perf_event_open(&event_attr, 0, -1, group_fd, 0);
207
208 if (fd < 0)
209 perror("perf_event_open() failed");
210
211 return fd;
212}
213
214int perf_event_enable(int fd)
215{
216 if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) {
217 perror("error while enabling perf events");
218 return -1;
219 }
220
221 return 0;
222}
223
224int perf_event_disable(int fd)
225{
226 if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) {
227 perror("error disabling perf events");
228 return -1;
229 }
230
231 return 0;
232}
233
234int perf_event_reset(int fd)
235{
236 if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) {
237 perror("error resetting perf events");
238 return -1;
239 }
240
241 return 0;
242}
243
244static void sigill_handler(int signr, siginfo_t *info, void *unused)
245{
246 static int warned = 0;
247 ucontext_t *ctx = (ucontext_t *)unused;
248 unsigned long *pc = &UCONTEXT_NIA(ctx);
249
250 if (*pc == (unsigned long)&dscr_insn) {
251 if (!warned++)
252 printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n");
253 *pc += 4;
254 } else {
255 printf("SIGILL at %p\n", pc);
256 abort();
257 }
258}
259
260void set_dscr(unsigned long val)
261{
262 static int init = 0;
263 struct sigaction sa;
264
265 if (!init) {
266 memset(&sa, 0, sizeof(sa));
267 sa.sa_sigaction = sigill_handler;
268 sa.sa_flags = SA_SIGINFO;
269 if (sigaction(SIGILL, &sa, NULL))
270 perror("sigill_handler");
271 init = 1;
272 }
273
274 asm volatile("dscr_insn: mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR));
275}
diff --git a/tools/testing/selftests/tc-testing/README b/tools/testing/selftests/tc-testing/README
index 49a6f8c3fdae..f9281e8aa313 100644
--- a/tools/testing/selftests/tc-testing/README
+++ b/tools/testing/selftests/tc-testing/README
@@ -232,6 +232,8 @@ directory:
232 and the other is a test whether the command leaked memory or not. 232 and the other is a test whether the command leaked memory or not.
233 (This one is a preliminary version, it may not work quite right yet, 233 (This one is a preliminary version, it may not work quite right yet,
234 but the overall template is there and it should only need tweaks.) 234 but the overall template is there and it should only need tweaks.)
235 - buildebpfPlugin.py:
236 builds all programs in $EBPFDIR.
235 237
236 238
237ACKNOWLEDGEMENTS 239ACKNOWLEDGEMENTS
diff --git a/tools/testing/selftests/tc-testing/bpf/Makefile b/tools/testing/selftests/tc-testing/bpf/Makefile
new file mode 100644
index 000000000000..dc92eb271d9a
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/bpf/Makefile
@@ -0,0 +1,29 @@
1# SPDX-License-Identifier: GPL-2.0
2
3APIDIR := ../../../../include/uapi
4TEST_GEN_FILES = action.o
5
6top_srcdir = ../../../../..
7include ../../lib.mk
8
9CLANG ?= clang
10LLC ?= llc
11PROBE := $(shell $(LLC) -march=bpf -mcpu=probe -filetype=null /dev/null 2>&1)
12
13ifeq ($(PROBE),)
14 CPU ?= probe
15else
16 CPU ?= generic
17endif
18
19CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \
20 | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
21
22CLANG_FLAGS = -I. -I$(APIDIR) \
23 $(CLANG_SYS_INCLUDES) \
24 -Wno-compare-distinct-pointer-types
25
26$(OUTPUT)/%.o: %.c
27 $(CLANG) $(CLANG_FLAGS) \
28 -O2 -target bpf -emit-llvm -c $< -o - | \
29 $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
diff --git a/tools/testing/selftests/tc-testing/bpf/action.c b/tools/testing/selftests/tc-testing/bpf/action.c
new file mode 100644
index 000000000000..c32b99b80e19
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/bpf/action.c
@@ -0,0 +1,23 @@
1/* SPDX-License-Identifier: GPL-2.0
2 * Copyright (c) 2018 Davide Caratti, Red Hat inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 */
8
9#include <linux/bpf.h>
10#include <linux/pkt_cls.h>
11
12__attribute__((section("action-ok"),used)) int action_ok(struct __sk_buff *s)
13{
14 return TC_ACT_OK;
15}
16
17__attribute__((section("action-ko"),used)) int action_ko(struct __sk_buff *s)
18{
19 s->data = 0x0;
20 return TC_ACT_OK;
21}
22
23char _license[] __attribute__((section("license"),used)) = "GPL";
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/buildebpfPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/buildebpfPlugin.py
new file mode 100644
index 000000000000..9f0ba10c44b4
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/plugin-lib/buildebpfPlugin.py
@@ -0,0 +1,66 @@
1'''
2build ebpf program
3'''
4
5import os
6import signal
7from string import Template
8import subprocess
9import time
10from TdcPlugin import TdcPlugin
11from tdc_config import *
12
13class SubPlugin(TdcPlugin):
14 def __init__(self):
15 self.sub_class = 'buildebpf/SubPlugin'
16 self.tap = ''
17 super().__init__()
18
19 def pre_suite(self, testcount, testidlist):
20 super().pre_suite(testcount, testidlist)
21
22 if self.args.buildebpf:
23 self._ebpf_makeall()
24
25 def post_suite(self, index):
26 super().post_suite(index)
27
28 self._ebpf_makeclean()
29
30 def add_args(self, parser):
31 super().add_args(parser)
32
33 self.argparser_group = self.argparser.add_argument_group(
34 'buildebpf',
35 'options for buildebpfPlugin')
36 self.argparser_group.add_argument(
37 '-B', '--buildebpf', action='store_true',
38 help='build eBPF programs')
39
40 return self.argparser
41
42 def _ebpf_makeall(self):
43 if self.args.buildebpf:
44 self._make('all')
45
46 def _ebpf_makeclean(self):
47 if self.args.buildebpf:
48 self._make('clean')
49
50 def _make(self, target):
51 command = 'make -C {} {}'.format(self.args.NAMES['EBPFDIR'], target)
52 proc = subprocess.Popen(command,
53 shell=True,
54 stdout=subprocess.PIPE,
55 stderr=subprocess.PIPE,
56 env=ENVIR)
57 (rawout, serr) = proc.communicate()
58
59 if proc.returncode != 0 and len(serr) > 0:
60 foutput = serr.decode("utf-8")
61 else:
62 foutput = rawout.decode("utf-8")
63
64 proc.stdout.close()
65 proc.stderr.close()
66 return proc, foutput
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json b/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
index 6f289a49e5ec..5970cee6d05f 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
@@ -55,7 +55,6 @@
55 "bpf" 55 "bpf"
56 ], 56 ],
57 "setup": [ 57 "setup": [
58 "printf '#include <linux/bpf.h>\nchar l[] __attribute__((section(\"license\"),used))=\"GPL\"; __attribute__((section(\"action\"),used)) int m(struct __sk_buff *s) { return 2; }' | clang -O2 -x c -c - -target bpf -o _b.o",
59 [ 58 [
60 "$TC action flush action bpf", 59 "$TC action flush action bpf",
61 0, 60 0,
@@ -63,14 +62,13 @@
63 255 62 255
64 ] 63 ]
65 ], 64 ],
66 "cmdUnderTest": "$TC action add action bpf object-file _b.o index 667", 65 "cmdUnderTest": "$TC action add action bpf object-file $EBPFDIR/action.o section action-ok index 667",
67 "expExitCode": "0", 66 "expExitCode": "0",
68 "verifyCmd": "$TC action get action bpf index 667", 67 "verifyCmd": "$TC action get action bpf index 667",
69 "matchPattern": "action order [0-9]*: bpf _b.o:\\[action\\] id [0-9]* tag 3b185187f1855c4c( jited)? default-action pipe.*index 667 ref", 68 "matchPattern": "action order [0-9]*: bpf action.o:\\[action-ok\\] id [0-9]* tag [0-9a-f]{16}( jited)? default-action pipe.*index 667 ref",
70 "matchCount": "1", 69 "matchCount": "1",
71 "teardown": [ 70 "teardown": [
72 "$TC action flush action bpf", 71 "$TC action flush action bpf"
73 "rm -f _b.o"
74 ] 72 ]
75 }, 73 },
76 { 74 {
@@ -81,7 +79,6 @@
81 "bpf" 79 "bpf"
82 ], 80 ],
83 "setup": [ 81 "setup": [
84 "printf '#include <linux/bpf.h>\nchar l[] __attribute__((section(\"license\"),used))=\"GPL\"; __attribute__((section(\"action\"),used)) int m(struct __sk_buff *s) { s->data = 0x0; return 2; }' | clang -O2 -x c -c - -target bpf -o _c.o",
85 [ 82 [
86 "$TC action flush action bpf", 83 "$TC action flush action bpf",
87 0, 84 0,
@@ -89,10 +86,10 @@
89 255 86 255
90 ] 87 ]
91 ], 88 ],
92 "cmdUnderTest": "$TC action add action bpf object-file _c.o index 667", 89 "cmdUnderTest": "$TC action add action bpf object-file $EBPFDIR/action.o section action-ko index 667",
93 "expExitCode": "255", 90 "expExitCode": "255",
94 "verifyCmd": "$TC action get action bpf index 667", 91 "verifyCmd": "$TC action get action bpf index 667",
95 "matchPattern": "action order [0-9]*: bpf _c.o:\\[action\\] id [0-9].*index 667 ref", 92 "matchPattern": "action order [0-9]*: bpf action.o:\\[action-ko\\] id [0-9].*index 667 ref",
96 "matchCount": "0", 93 "matchCount": "0",
97 "teardown": [ 94 "teardown": [
98 [ 95 [
@@ -100,8 +97,7 @@
100 0, 97 0,
101 1, 98 1,
102 255 99 255
103 ], 100 ]
104 "rm -f _c.o"
105 ] 101 ]
106 }, 102 },
107 { 103 {
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
index 68c91023cdb9..89189a03ce3d 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
@@ -536,5 +536,29 @@
536 "matchPattern": "^[ \t]+index [0-9]+ ref", 536 "matchPattern": "^[ \t]+index [0-9]+ ref",
537 "matchCount": "0", 537 "matchCount": "0",
538 "teardown": [] 538 "teardown": []
539 },
540 {
541 "id": "8e47",
542 "name": "Add gact action with random determ goto chain control action",
543 "category": [
544 "actions",
545 "gact"
546 ],
547 "setup": [
548 [
549 "$TC actions flush action gact",
550 0,
551 1,
552 255
553 ]
554 ],
555 "cmdUnderTest": "$TC actions add action pass random determ goto chain 1 2 index 90",
556 "expExitCode": "255",
557 "verifyCmd": "$TC actions list action gact",
558 "matchPattern": "action order [0-9]*: gact action pass random type determ goto chain 1 val 2.*index 90 ref",
559 "matchCount": "0",
560 "teardown": [
561 "$TC actions flush action gact"
562 ]
539 } 563 }
540] 564]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
index 30f9b54bd666..4086a50a670e 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
@@ -715,5 +715,29 @@
715 "teardown": [ 715 "teardown": [
716 "$TC actions flush action police" 716 "$TC actions flush action police"
717 ] 717 ]
718 },
719 {
720 "id": "b48b",
721 "name": "Add police action with exceed goto chain control action",
722 "category": [
723 "actions",
724 "police"
725 ],
726 "setup": [
727 [
728 "$TC actions flush action police",
729 0,
730 1,
731 255
732 ]
733 ],
734 "cmdUnderTest": "$TC actions add action police rate 1mbit burst 1k conform-exceed pass / goto chain 42",
735 "expExitCode": "255",
736 "verifyCmd": "$TC actions ls action police",
737 "matchPattern": "action order [0-9]*: police 0x1 rate 1Mbit burst 1Kb mtu 2Kb action pass/goto chain 42",
738 "matchCount": "0",
739 "teardown": [
740 "$TC actions flush action police"
741 ]
718 } 742 }
719] 743]
diff --git a/tools/testing/selftests/tc-testing/tdc_config.py b/tools/testing/selftests/tc-testing/tdc_config.py
index a023d0d62b25..d651bc1501bd 100644
--- a/tools/testing/selftests/tc-testing/tdc_config.py
+++ b/tools/testing/selftests/tc-testing/tdc_config.py
@@ -16,7 +16,9 @@ NAMES = {
16 'DEV2': '', 16 'DEV2': '',
17 'BATCH_FILE': './batch.txt', 17 'BATCH_FILE': './batch.txt',
18 # Name of the namespace to use 18 # Name of the namespace to use
19 'NS': 'tcut' 19 'NS': 'tcut',
20 # Directory containing eBPF test programs
21 'EBPFDIR': './bpf'
20 } 22 }
21 23
22 24
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index af5ff83f6d7f..31b3c98b6d34 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -13,3 +13,4 @@ mlock-random-test
13virtual_address_range 13virtual_address_range
14gup_benchmark 14gup_benchmark
15va_128TBswitch 15va_128TBswitch
16map_fixed_noreplace
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index e94b7b14bcb2..6e67e726e5a5 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -12,6 +12,7 @@ TEST_GEN_FILES += gup_benchmark
12TEST_GEN_FILES += hugepage-mmap 12TEST_GEN_FILES += hugepage-mmap
13TEST_GEN_FILES += hugepage-shm 13TEST_GEN_FILES += hugepage-shm
14TEST_GEN_FILES += map_hugetlb 14TEST_GEN_FILES += map_hugetlb
15TEST_GEN_FILES += map_fixed_noreplace
15TEST_GEN_FILES += map_populate 16TEST_GEN_FILES += map_populate
16TEST_GEN_FILES += mlock-random-test 17TEST_GEN_FILES += mlock-random-test
17TEST_GEN_FILES += mlock2-tests 18TEST_GEN_FILES += mlock2-tests
diff --git a/tools/testing/selftests/vm/gup_benchmark.c b/tools/testing/selftests/vm/gup_benchmark.c
index 36df55132036..880b96fc80d4 100644
--- a/tools/testing/selftests/vm/gup_benchmark.c
+++ b/tools/testing/selftests/vm/gup_benchmark.c
@@ -15,9 +15,12 @@
15#define PAGE_SIZE sysconf(_SC_PAGESIZE) 15#define PAGE_SIZE sysconf(_SC_PAGESIZE)
16 16
17#define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark) 17#define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark)
18#define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark)
19#define GUP_BENCHMARK _IOWR('g', 3, struct gup_benchmark)
18 20
19struct gup_benchmark { 21struct gup_benchmark {
20 __u64 delta_usec; 22 __u64 get_delta_usec;
23 __u64 put_delta_usec;
21 __u64 addr; 24 __u64 addr;
22 __u64 size; 25 __u64 size;
23 __u32 nr_pages_per_call; 26 __u32 nr_pages_per_call;
@@ -28,10 +31,12 @@ int main(int argc, char **argv)
28{ 31{
29 struct gup_benchmark gup; 32 struct gup_benchmark gup;
30 unsigned long size = 128 * MB; 33 unsigned long size = 128 * MB;
31 int i, fd, opt, nr_pages = 1, thp = -1, repeats = 1, write = 0; 34 int i, fd, filed, opt, nr_pages = 1, thp = -1, repeats = 1, write = 0;
35 int cmd = GUP_FAST_BENCHMARK, flags = MAP_PRIVATE;
36 char *file = "/dev/zero";
32 char *p; 37 char *p;
33 38
34 while ((opt = getopt(argc, argv, "m:r:n:tT")) != -1) { 39 while ((opt = getopt(argc, argv, "m:r:n:f:tTLUSH")) != -1) {
35 switch (opt) { 40 switch (opt) {
36 case 'm': 41 case 'm':
37 size = atoi(optarg) * MB; 42 size = atoi(optarg) * MB;
@@ -48,13 +53,36 @@ int main(int argc, char **argv)
48 case 'T': 53 case 'T':
49 thp = 0; 54 thp = 0;
50 break; 55 break;
56 case 'L':
57 cmd = GUP_LONGTERM_BENCHMARK;
58 break;
59 case 'U':
60 cmd = GUP_BENCHMARK;
61 break;
51 case 'w': 62 case 'w':
52 write = 1; 63 write = 1;
64 break;
65 case 'f':
66 file = optarg;
67 break;
68 case 'S':
69 flags &= ~MAP_PRIVATE;
70 flags |= MAP_SHARED;
71 break;
72 case 'H':
73 flags |= MAP_HUGETLB;
74 break;
53 default: 75 default:
54 return -1; 76 return -1;
55 } 77 }
56 } 78 }
57 79
80 filed = open(file, O_RDWR|O_CREAT);
81 if (filed < 0) {
82 perror("open");
83 exit(filed);
84 }
85
58 gup.nr_pages_per_call = nr_pages; 86 gup.nr_pages_per_call = nr_pages;
59 gup.flags = write; 87 gup.flags = write;
60 88
@@ -62,8 +90,7 @@ int main(int argc, char **argv)
62 if (fd == -1) 90 if (fd == -1)
63 perror("open"), exit(1); 91 perror("open"), exit(1);
64 92
65 p = mmap(NULL, size, PROT_READ | PROT_WRITE, 93 p = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, filed, 0);
66 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
67 if (p == MAP_FAILED) 94 if (p == MAP_FAILED)
68 perror("mmap"), exit(1); 95 perror("mmap"), exit(1);
69 gup.addr = (unsigned long)p; 96 gup.addr = (unsigned long)p;
@@ -78,10 +105,11 @@ int main(int argc, char **argv)
78 105
79 for (i = 0; i < repeats; i++) { 106 for (i = 0; i < repeats; i++) {
80 gup.size = size; 107 gup.size = size;
81 if (ioctl(fd, GUP_FAST_BENCHMARK, &gup)) 108 if (ioctl(fd, cmd, &gup))
82 perror("ioctl"), exit(1); 109 perror("ioctl"), exit(1);
83 110
84 printf("Time: %lld us", gup.delta_usec); 111 printf("Time: get:%lld put:%lld us", gup.get_delta_usec,
112 gup.put_delta_usec);
85 if (gup.size != size) 113 if (gup.size != size)
86 printf(", truncated (size: %lld)", gup.size); 114 printf(", truncated (size: %lld)", gup.size);
87 printf("\n"); 115 printf("\n");
diff --git a/tools/testing/selftests/vm/map_fixed_noreplace.c b/tools/testing/selftests/vm/map_fixed_noreplace.c
new file mode 100644
index 000000000000..d91bde511268
--- /dev/null
+++ b/tools/testing/selftests/vm/map_fixed_noreplace.c
@@ -0,0 +1,206 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Test that MAP_FIXED_NOREPLACE works.
5 *
6 * Copyright 2018, Jann Horn <jannh@google.com>
7 * Copyright 2018, Michael Ellerman, IBM Corporation.
8 */
9
10#include <sys/mman.h>
11#include <errno.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15
16#ifndef MAP_FIXED_NOREPLACE
17#define MAP_FIXED_NOREPLACE 0x100000
18#endif
19
20#define BASE_ADDRESS (256ul * 1024 * 1024)
21
22
23static void dump_maps(void)
24{
25 char cmd[32];
26
27 snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
28 system(cmd);
29}
30
31int main(void)
32{
33 unsigned long flags, addr, size, page_size;
34 char *p;
35
36 page_size = sysconf(_SC_PAGE_SIZE);
37
38 flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
39
40 // Check we can map all the areas we need below
41 errno = 0;
42 addr = BASE_ADDRESS;
43 size = 5 * page_size;
44 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
45
46 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
47
48 if (p == MAP_FAILED) {
49 dump_maps();
50 printf("Error: couldn't map the space we need for the test\n");
51 return 1;
52 }
53
54 errno = 0;
55 if (munmap((void *)addr, 5 * page_size) != 0) {
56 dump_maps();
57 printf("Error: munmap failed!?\n");
58 return 1;
59 }
60 printf("unmap() successful\n");
61
62 errno = 0;
63 addr = BASE_ADDRESS + page_size;
64 size = 3 * page_size;
65 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
66 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
67
68 if (p == MAP_FAILED) {
69 dump_maps();
70 printf("Error: first mmap() failed unexpectedly\n");
71 return 1;
72 }
73
74 /*
75 * Exact same mapping again:
76 * base | free | new
77 * +1 | mapped | new
78 * +2 | mapped | new
79 * +3 | mapped | new
80 * +4 | free | new
81 */
82 errno = 0;
83 addr = BASE_ADDRESS;
84 size = 5 * page_size;
85 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
86 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
87
88 if (p != MAP_FAILED) {
89 dump_maps();
90 printf("Error:1: mmap() succeeded when it shouldn't have\n");
91 return 1;
92 }
93
94 /*
95 * Second mapping contained within first:
96 *
97 * base | free |
98 * +1 | mapped |
99 * +2 | mapped | new
100 * +3 | mapped |
101 * +4 | free |
102 */
103 errno = 0;
104 addr = BASE_ADDRESS + (2 * page_size);
105 size = page_size;
106 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
107 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
108
109 if (p != MAP_FAILED) {
110 dump_maps();
111 printf("Error:2: mmap() succeeded when it shouldn't have\n");
112 return 1;
113 }
114
115 /*
116 * Overlap end of existing mapping:
117 * base | free |
118 * +1 | mapped |
119 * +2 | mapped |
120 * +3 | mapped | new
121 * +4 | free | new
122 */
123 errno = 0;
124 addr = BASE_ADDRESS + (3 * page_size);
125 size = 2 * page_size;
126 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
127 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
128
129 if (p != MAP_FAILED) {
130 dump_maps();
131 printf("Error:3: mmap() succeeded when it shouldn't have\n");
132 return 1;
133 }
134
135 /*
136 * Overlap start of existing mapping:
137 * base | free | new
138 * +1 | mapped | new
139 * +2 | mapped |
140 * +3 | mapped |
141 * +4 | free |
142 */
143 errno = 0;
144 addr = BASE_ADDRESS;
145 size = 2 * page_size;
146 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
147 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
148
149 if (p != MAP_FAILED) {
150 dump_maps();
151 printf("Error:4: mmap() succeeded when it shouldn't have\n");
152 return 1;
153 }
154
155 /*
156 * Adjacent to start of existing mapping:
157 * base | free | new
158 * +1 | mapped |
159 * +2 | mapped |
160 * +3 | mapped |
161 * +4 | free |
162 */
163 errno = 0;
164 addr = BASE_ADDRESS;
165 size = page_size;
166 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
167 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
168
169 if (p == MAP_FAILED) {
170 dump_maps();
171 printf("Error:5: mmap() failed when it shouldn't have\n");
172 return 1;
173 }
174
175 /*
176 * Adjacent to end of existing mapping:
177 * base | free |
178 * +1 | mapped |
179 * +2 | mapped |
180 * +3 | mapped |
181 * +4 | free | new
182 */
183 errno = 0;
184 addr = BASE_ADDRESS + (4 * page_size);
185 size = page_size;
186 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
187 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
188
189 if (p == MAP_FAILED) {
190 dump_maps();
191 printf("Error:6: mmap() failed when it shouldn't have\n");
192 return 1;
193 }
194
195 addr = BASE_ADDRESS;
196 size = 5 * page_size;
197 if (munmap((void *)addr, size) != 0) {
198 dump_maps();
199 printf("Error: munmap failed!?\n");
200 return 1;
201 }
202 printf("unmap() successful\n");
203
204 printf("OK\n");
205 return 0;
206}
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 7b8171e3128a..5d1db824f73a 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -34,18 +34,6 @@
34 * per-CPU threads 1 by triggering userfaults inside 34 * per-CPU threads 1 by triggering userfaults inside
35 * pthread_mutex_lock will also verify the atomicity of the memory 35 * pthread_mutex_lock will also verify the atomicity of the memory
36 * transfer (UFFDIO_COPY). 36 * transfer (UFFDIO_COPY).
37 *
38 * The program takes two parameters: the amounts of physical memory in
39 * megabytes (MiB) of the area and the number of bounces to execute.
40 *
41 * # 100MiB 99999 bounces
42 * ./userfaultfd 100 99999
43 *
44 * # 1GiB 99 bounces
45 * ./userfaultfd 1000 99
46 *
47 * # 10MiB-~6GiB 999 bounces, continue forever unless an error triggers
48 * while ./userfaultfd $[RANDOM % 6000 + 10] 999; do true; done
49 */ 37 */
50 38
51#define _GNU_SOURCE 39#define _GNU_SOURCE
@@ -115,6 +103,30 @@ pthread_attr_t attr;
115 ~(unsigned long)(sizeof(unsigned long long) \ 103 ~(unsigned long)(sizeof(unsigned long long) \
116 - 1))) 104 - 1)))
117 105
106const char *examples =
107 "# Run anonymous memory test on 100MiB region with 99999 bounces:\n"
108 "./userfaultfd anon 100 99999\n\n"
109 "# Run share memory test on 1GiB region with 99 bounces:\n"
110 "./userfaultfd shmem 1000 99\n\n"
111 "# Run hugetlb memory test on 256MiB region with 50 bounces (using /dev/hugepages/hugefile):\n"
112 "./userfaultfd hugetlb 256 50 /dev/hugepages/hugefile\n\n"
113 "# Run the same hugetlb test but using shmem:\n"
114 "./userfaultfd hugetlb_shared 256 50 /dev/hugepages/hugefile\n\n"
115 "# 10MiB-~6GiB 999 bounces anonymous test, "
116 "continue forever unless an error triggers\n"
117 "while ./userfaultfd anon $[RANDOM % 6000 + 10] 999; do true; done\n\n";
118
119static void usage(void)
120{
121 fprintf(stderr, "\nUsage: ./userfaultfd <test type> <MiB> <bounces> "
122 "[hugetlbfs_file]\n\n");
123 fprintf(stderr, "Supported <test type>: anon, hugetlb, "
124 "hugetlb_shared, shmem\n\n");
125 fprintf(stderr, "Examples:\n\n");
126 fprintf(stderr, examples);
127 exit(1);
128}
129
118static int anon_release_pages(char *rel_area) 130static int anon_release_pages(char *rel_area)
119{ 131{
120 int ret = 0; 132 int ret = 0;
@@ -439,6 +451,43 @@ static int copy_page(int ufd, unsigned long offset)
439 return __copy_page(ufd, offset, false); 451 return __copy_page(ufd, offset, false);
440} 452}
441 453
454static int uffd_read_msg(int ufd, struct uffd_msg *msg)
455{
456 int ret = read(uffd, msg, sizeof(*msg));
457
458 if (ret != sizeof(*msg)) {
459 if (ret < 0) {
460 if (errno == EAGAIN)
461 return 1;
462 else
463 perror("blocking read error"), exit(1);
464 } else {
465 fprintf(stderr, "short read\n"), exit(1);
466 }
467 }
468
469 return 0;
470}
471
472/* Return 1 if page fault handled by us; otherwise 0 */
473static int uffd_handle_page_fault(struct uffd_msg *msg)
474{
475 unsigned long offset;
476
477 if (msg->event != UFFD_EVENT_PAGEFAULT)
478 fprintf(stderr, "unexpected msg event %u\n",
479 msg->event), exit(1);
480
481 if (bounces & BOUNCE_VERIFY &&
482 msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
483 fprintf(stderr, "unexpected write fault\n"), exit(1);
484
485 offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
486 offset &= ~(page_size-1);
487
488 return copy_page(uffd, offset);
489}
490
442static void *uffd_poll_thread(void *arg) 491static void *uffd_poll_thread(void *arg)
443{ 492{
444 unsigned long cpu = (unsigned long) arg; 493 unsigned long cpu = (unsigned long) arg;
@@ -446,7 +495,6 @@ static void *uffd_poll_thread(void *arg)
446 struct uffd_msg msg; 495 struct uffd_msg msg;
447 struct uffdio_register uffd_reg; 496 struct uffdio_register uffd_reg;
448 int ret; 497 int ret;
449 unsigned long offset;
450 char tmp_chr; 498 char tmp_chr;
451 unsigned long userfaults = 0; 499 unsigned long userfaults = 0;
452 500
@@ -470,25 +518,15 @@ static void *uffd_poll_thread(void *arg)
470 if (!(pollfd[0].revents & POLLIN)) 518 if (!(pollfd[0].revents & POLLIN))
471 fprintf(stderr, "pollfd[0].revents %d\n", 519 fprintf(stderr, "pollfd[0].revents %d\n",
472 pollfd[0].revents), exit(1); 520 pollfd[0].revents), exit(1);
473 ret = read(uffd, &msg, sizeof(msg)); 521 if (uffd_read_msg(uffd, &msg))
474 if (ret < 0) { 522 continue;
475 if (errno == EAGAIN)
476 continue;
477 perror("nonblocking read error"), exit(1);
478 }
479 switch (msg.event) { 523 switch (msg.event) {
480 default: 524 default:
481 fprintf(stderr, "unexpected msg event %u\n", 525 fprintf(stderr, "unexpected msg event %u\n",
482 msg.event), exit(1); 526 msg.event), exit(1);
483 break; 527 break;
484 case UFFD_EVENT_PAGEFAULT: 528 case UFFD_EVENT_PAGEFAULT:
485 if (msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE) 529 userfaults += uffd_handle_page_fault(&msg);
486 fprintf(stderr, "unexpected write fault\n"), exit(1);
487 offset = (char *)(unsigned long)msg.arg.pagefault.address -
488 area_dst;
489 offset &= ~(page_size-1);
490 if (copy_page(uffd, offset))
491 userfaults++;
492 break; 530 break;
493 case UFFD_EVENT_FORK: 531 case UFFD_EVENT_FORK:
494 close(uffd); 532 close(uffd);
@@ -516,8 +554,6 @@ static void *uffd_read_thread(void *arg)
516{ 554{
517 unsigned long *this_cpu_userfaults; 555 unsigned long *this_cpu_userfaults;
518 struct uffd_msg msg; 556 struct uffd_msg msg;
519 unsigned long offset;
520 int ret;
521 557
522 this_cpu_userfaults = (unsigned long *) arg; 558 this_cpu_userfaults = (unsigned long *) arg;
523 *this_cpu_userfaults = 0; 559 *this_cpu_userfaults = 0;
@@ -526,24 +562,9 @@ static void *uffd_read_thread(void *arg)
526 /* from here cancellation is ok */ 562 /* from here cancellation is ok */
527 563
528 for (;;) { 564 for (;;) {
529 ret = read(uffd, &msg, sizeof(msg)); 565 if (uffd_read_msg(uffd, &msg))
530 if (ret != sizeof(msg)) { 566 continue;
531 if (ret < 0) 567 (*this_cpu_userfaults) += uffd_handle_page_fault(&msg);
532 perror("blocking read error"), exit(1);
533 else
534 fprintf(stderr, "short read\n"), exit(1);
535 }
536 if (msg.event != UFFD_EVENT_PAGEFAULT)
537 fprintf(stderr, "unexpected msg event %u\n",
538 msg.event), exit(1);
539 if (bounces & BOUNCE_VERIFY &&
540 msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
541 fprintf(stderr, "unexpected write fault\n"), exit(1);
542 offset = (char *)(unsigned long)msg.arg.pagefault.address -
543 area_dst;
544 offset &= ~(page_size-1);
545 if (copy_page(uffd, offset))
546 (*this_cpu_userfaults)++;
547 } 568 }
548 return (void *)NULL; 569 return (void *)NULL;
549} 570}
@@ -605,6 +626,12 @@ static int stress(unsigned long *userfaults)
605 if (uffd_test_ops->release_pages(area_src)) 626 if (uffd_test_ops->release_pages(area_src))
606 return 1; 627 return 1;
607 628
629
630 finished = 1;
631 for (cpu = 0; cpu < nr_cpus; cpu++)
632 if (pthread_join(locking_threads[cpu], NULL))
633 return 1;
634
608 for (cpu = 0; cpu < nr_cpus; cpu++) { 635 for (cpu = 0; cpu < nr_cpus; cpu++) {
609 char c; 636 char c;
610 if (bounces & BOUNCE_POLL) { 637 if (bounces & BOUNCE_POLL) {
@@ -622,11 +649,6 @@ static int stress(unsigned long *userfaults)
622 } 649 }
623 } 650 }
624 651
625 finished = 1;
626 for (cpu = 0; cpu < nr_cpus; cpu++)
627 if (pthread_join(locking_threads[cpu], NULL))
628 return 1;
629
630 return 0; 652 return 0;
631} 653}
632 654
@@ -1272,8 +1294,7 @@ static void sigalrm(int sig)
1272int main(int argc, char **argv) 1294int main(int argc, char **argv)
1273{ 1295{
1274 if (argc < 4) 1296 if (argc < 4)
1275 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"), 1297 usage();
1276 exit(1);
1277 1298
1278 if (signal(SIGALRM, sigalrm) == SIG_ERR) 1299 if (signal(SIGALRM, sigalrm) == SIG_ERR)
1279 fprintf(stderr, "failed to arm SIGALRM"), exit(1); 1300 fprintf(stderr, "failed to arm SIGALRM"), exit(1);
@@ -1286,20 +1307,19 @@ int main(int argc, char **argv)
1286 nr_cpus; 1307 nr_cpus;
1287 if (!nr_pages_per_cpu) { 1308 if (!nr_pages_per_cpu) {
1288 fprintf(stderr, "invalid MiB\n"); 1309 fprintf(stderr, "invalid MiB\n");
1289 fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1); 1310 usage();
1290 } 1311 }
1291 1312
1292 bounces = atoi(argv[3]); 1313 bounces = atoi(argv[3]);
1293 if (bounces <= 0) { 1314 if (bounces <= 0) {
1294 fprintf(stderr, "invalid bounces\n"); 1315 fprintf(stderr, "invalid bounces\n");
1295 fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1); 1316 usage();
1296 } 1317 }
1297 nr_pages = nr_pages_per_cpu * nr_cpus; 1318 nr_pages = nr_pages_per_cpu * nr_cpus;
1298 1319
1299 if (test_type == TEST_HUGETLB) { 1320 if (test_type == TEST_HUGETLB) {
1300 if (argc < 5) 1321 if (argc < 5)
1301 fprintf(stderr, "Usage: hugetlb <MiB> <bounces> <hugetlbfs_file>\n"), 1322 usage();
1302 exit(1);
1303 huge_fd = open(argv[4], O_CREAT | O_RDWR, 0755); 1323 huge_fd = open(argv[4], O_CREAT | O_RDWR, 0755);
1304 if (huge_fd < 0) { 1324 if (huge_fd < 0) {
1305 fprintf(stderr, "Open of %s failed", argv[3]); 1325 fprintf(stderr, "Open of %s failed", argv[3]);
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c
index dc93fadbee96..d79c7581b175 100644
--- a/tools/usb/usbip/libsrc/usbip_host_common.c
+++ b/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -43,7 +43,7 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
43 int size; 43 int size;
44 int fd; 44 int fd;
45 int length; 45 int length;
46 char status; 46 char status[2] = { 0 };
47 int value = 0; 47 int value = 0;
48 48
49 size = snprintf(status_attr_path, sizeof(status_attr_path), 49 size = snprintf(status_attr_path, sizeof(status_attr_path),
@@ -61,14 +61,14 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
61 return -1; 61 return -1;
62 } 62 }
63 63
64 length = read(fd, &status, 1); 64 length = read(fd, status, 1);
65 if (length < 0) { 65 if (length < 0) {
66 err("error reading attribute %s", status_attr_path); 66 err("error reading attribute %s", status_attr_path);
67 close(fd); 67 close(fd);
68 return -1; 68 return -1;
69 } 69 }
70 70
71 value = atoi(&status); 71 value = atoi(status);
72 72
73 return value; 73 return value;
74} 74}
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
index 4204359c9fee..8159fd98680b 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.c
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -150,7 +150,7 @@ static int get_nports(struct udev_device *hc_device)
150 150
151static int vhci_hcd_filter(const struct dirent *dirent) 151static int vhci_hcd_filter(const struct dirent *dirent)
152{ 152{
153 return strcmp(dirent->d_name, "vhci_hcd") >= 0; 153 return !strncmp(dirent->d_name, "vhci_hcd.", 9);
154} 154}
155 155
156static int get_ncontrollers(void) 156static int get_ncontrollers(void)