Context |
Check |
Description |
bpf/vmtest-bpf-next-PR |
success
|
PR summary
|
bpf/vmtest-bpf-next-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-next-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-next-VM_Test-2 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-next-VM_Test-3 |
success
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-4 |
success
|
Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-6 |
success
|
Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-7 |
success
|
Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-8 |
success
|
Logs for aarch64-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-9 |
pending
|
Logs for s390x-gcc / build / build for s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-10 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-next-VM_Test-11 |
success
|
Logs for x86_64-gcc / build / build for x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-12 |
success
|
Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-13 |
success
|
Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-14 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-16 |
success
|
Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-15 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-18 |
success
|
Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-17 |
success
|
Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-20 |
success
|
Logs for x86_64-llvm-16 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-19 |
success
|
Logs for x86_64-llvm-16 / build / build for x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-21 |
success
|
Logs for x86_64-llvm-16 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-22 |
success
|
Logs for x86_64-llvm-16 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-23 |
success
|
Logs for x86_64-llvm-16 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-24 |
success
|
Logs for x86_64-llvm-16 / veristat
|
bpf/vmtest-bpf-next-VM_Test-5 |
fail
|
Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
|
netdev/series_format |
success
|
Posting correctly formatted
|
netdev/tree_selection |
success
|
Clearly marked for bpf-next
|
netdev/fixes_present |
success
|
Fixes tag not required for -next series
|
netdev/header_inline |
success
|
No static functions without inline keyword in header files
|
netdev/build_32bit |
success
|
Errors and warnings before: 1350 this patch: 1350
|
netdev/cc_maintainers |
warning
|
9 maintainers not CCed: haoluo@google.com song@kernel.org linux-kselftest@vger.kernel.org shuah@kernel.org martin.lau@linux.dev kpsingh@kernel.org jolsa@kernel.org sdf@google.com mykolal@fb.com
|
netdev/build_clang |
success
|
Errors and warnings before: 1378 this patch: 1378
|
netdev/verify_signedoff |
success
|
Signed-off-by tag matches author and committer
|
netdev/deprecated_api |
success
|
None detected
|
netdev/check_selftest |
success
|
No net selftest shell script
|
netdev/verify_fixes |
success
|
No Fixes tag
|
netdev/build_allmodconfig_warn |
success
|
Errors and warnings before: 1378 this patch: 1378
|
netdev/checkpatch |
fail
|
ERROR: open brace '{' following function definitions go on the next line
WARNING: 'assum' may be misspelled - perhaps 'assume'?
WARNING: 'inital' may be misspelled - perhaps 'initial'?
WARNING: Missing or malformed SPDX-License-Identifier tag in line 2
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
|
netdev/build_clang_rust |
success
|
No Rust files in patch. Skipping build
|
netdev/kdoc |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/source_inline |
success
|
Was 0 now: 0
|
new file mode 100644
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _LINUX_WRANGE_H
+#define _LINUX_WRANGE_H
+
+#include <linux/types.h>
+
+struct wrange32 {
+ /* Start with a usual u32 min/max.
+ *
+ * Requiring umin/start <= umax/end, and cannot be use to track s32
+ * range.
+ */
+ u32 start; /* umin */
+ u32 end; /* umax */
+};
+
+/* Helper functions that will be required later */
+static inline u32 wrange32_umin(struct wrange32 a) {
+ return a.start;
+}
+
+static inline u32 wrange32_umax(struct wrange32 a) {
+ return a.end;
+}
+
+#endif /* _LINUX_WRANGE_H */
new file mode 100755
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+import abc
+from z3 import *
+
+
+# Helpers
+BitVec32 = lambda n: BitVec(n, bv=32)
+BitVecVal32 = lambda v: BitVecVal(v, bv=32)
+
+class Wrange(abc.ABC):
+ SIZE = None # Bitwidth, this will be defined in the subclass
+ name: str
+ start: BitVecRef
+ end: BitVecRef
+
+ def __init__(self, name, start=None, end=None):
+ self.name = name
+ self.start = BitVec(f'Wrange32-{name}-start', bv=self.SIZE) if start is None else start
+ assert(self.start.size() == self.SIZE)
+ self.end = BitVec(f'Wrange32-{name}-end', bv=self.SIZE) if end is None else end
+ assert(self.end.size() == self.SIZE)
+
+ def wellformed(self):
+ # start <= end
+ return ULE(self.start, self.end)
+
+ @property
+ def umin(self):
+ return self.start
+
+ @property
+ def umax(self):
+ return self.end
+
+ # Not used in wrange.c, but helps with checking later
+ def contains(self, val: BitVecRef):
+ assert(val.size() == self.SIZE)
+ # umin <= val <= umax
+ return And(ULE(self.umin, val), ULE(val, self.umax))
+
+
+class Wrange32(Wrange):
+ SIZE = 32 # Working with 32-bit integers
+
+
+__all__ = [
+ 'Wrange',
+ 'Wrange32',
+ 'BitVec32',
+ 'BitVecVal32',
+]
+
+
+def main():
+ # A random 32-bit integer called x, that can be of any possible value
+ # unless constrained
+ x = BitVec32('x')
+
+ w1 = Wrange32('w1', start=BitVecVal32(1), end=BitVecVal32(1))
+ print(f'Given w1 start={w1.start} end={w1.end}')
+ print('\nChecking w1 is wellformed')
+ prove(
+ w1.wellformed(),
+ )
+ print('\nChecking w1.umin is 1')
+ prove(
+ w1.umin == BitVecVal32(1),
+ )
+ print('\nChecking w1.umax is 1')
+ prove(
+ w1.umax == BitVecVal32(1),
+ )
+ print('\nChecking that w1 contains 1')
+ prove(
+ w1.contains(BitVecVal32(1)),
+ )
+ print('\nChecking that w1 is a set of {1}, with only one element')
+ prove(
+ w1.contains(x) == (x == BitVecVal32(1)),
+ )
+
+ w2 = Wrange32('w2', start=BitVecVal32(2), end=BitVecVal32(2**32 - 1))
+ print(f'\nGiven w2 start={w2.start} end={w2.end}')
+ print('\nChecking w2 is wellformed')
+ prove(
+ w2.wellformed(),
+ )
+ print('\nChecking w2.umin is 2')
+ prove(
+ w2.umin == BitVecVal32(2),
+ )
+ print('\nChecking w2.umax is 2**32-1')
+ prove(
+ w2.umax == BitVecVal32(2**32 - 1),
+ )
+ print('\nChecking that w2 contains 2**32 - 1')
+ prove(
+ w2.contains(BitVecVal32(2**32 - 1)),
+ )
+ print('\nChecking that w2 does NOT contains 1')
+ prove(
+ Not(w2.contains(BitVecVal32(1))),
+ )
+ print('\nChecking that w2 is a set of {2..2**32-1}')
+ prove(
+ # Contrain x such that 2 <= x <= 2**32-1 and check that if x between 2
+ # and 2**32-1 (inclusive), then w2.contains(x) will return true.
+ #
+ # In addition to that, check that the reverse is also true. That is if
+ # x it _not_ a value between 2 and 2**32-1, then w2.contains(x) will
+ # return false.
+ w2.contains(x) == And(ULE(BitVecVal32(2), x), ULE(x, BitVecVal32(2**32-1))),
+ )
+
+ # Right now our semantic doesn't allow umax/end < umin/start
+ w3 = Wrange32('w3', start=BitVecVal32(2), end=BitVecVal32(0))
+ print(f'\nGiven w3 start={w3.start} end={w3.end}')
+ print('\nChecking w3 is NOT wellformed')
+ prove(
+ Not(w3.wellformed()),
+ )
+
+ # General checks that does not assum the value of start/end, except that it
+ # meets the requirement that start <= end.
+ w = Wrange32('w') # Given a Wrange32 called w
+ x = BitVec32('x') # And an 32-bit integer x (redeclared for clarity)
+ print(f'\nGiven any possible Wrange32 called w, and any possible 32-bit integer called x')
+ print('\nChecking if w.contains(x) == True, then w.umin <= (u32)x is also true')
+ prove(
+ Implies(
+ And(
+ w.wellformed(),
+ w.contains(x),
+ ),
+ ULE(w.umin, x),
+ )
+ )
+ print('\nChecking if w.contains(x) == True, then (u32)x <= w.umax is also true')
+ prove(
+ Implies(
+ And(
+ w.wellformed(),
+ w.contains(x),
+ ),
+ ULE(x, w.umax),
+ )
+ )
+
+if __name__ == '__main__':
+ main()
Add struct wrange32 (short for "32-bit wrapped range") and umin/umax helpers, the latter simply return start/end at the moment. We call the fields start and end instead of umin and umax, because later patch will lift the umin <= umax requirement, so we can have cases where umax < umin; and continuing to call them umin/umax would be confusing. A struct wrange32 modeled with z3Py is also attached to show that wrange32 in its current form work as intended. Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com> --- include/linux/wrange.h | 26 ++++ tools/testing/selftests/bpf/formal/wrange.py | 150 +++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 include/linux/wrange.h create mode 100755 tools/testing/selftests/bpf/formal/wrange.py