Skip to content

Commit b456005

Browse files
committed
Merge branch 'bpf-volatile-compare'
Alexei Starovoitov says: ==================== bpf: volatile compare From: Alexei Starovoitov <[email protected]> v2->v3: Debugged profiler.c regression. It was caused by basic block layout. Introduce bpf_cmp_likely() and bpf_cmp_unlikely() macros. Debugged redundant <<=32, >>=32 with u32 variables. Added cast workaround. v1->v2: Fixed issues pointed out by Daniel, added more tests, attempted to convert profiler.c, but barrier_var() wins vs bpf_cmp(). To be investigated. Patches 1-4 are good to go, but 5 needs more work. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Andrii Nakryiko <[email protected]>
2 parents a640de4 + 7e3811c commit b456005

29 files changed

+171
-275
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
383383
BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
384384
-I$(INCLUDE_DIR) -I$(CURDIR) -I$(APIDIR) \
385385
-I$(abspath $(OUTPUT)/../usr/include)
386+
# TODO: enable me -Wsign-compare
386387

387388
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
388389
-Wno-compare-distinct-pointer-types

tools/testing/selftests/bpf/bpf_experimental.h

Lines changed: 72 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -254,173 +254,97 @@ extern void bpf_throw(u64 cookie) __ksym;
254254
} \
255255
})
256256

257-
/* Description
258-
* Assert that a conditional expression is true.
259-
* Returns
260-
* Void.
261-
* Throws
262-
* An exception with the value zero when the assertion fails.
263-
*/
264-
#define bpf_assert(cond) if (!(cond)) bpf_throw(0);
265-
266-
/* Description
267-
* Assert that a conditional expression is true.
268-
* Returns
269-
* Void.
270-
* Throws
271-
* An exception with the specified value when the assertion fails.
272-
*/
273-
#define bpf_assert_with(cond, value) if (!(cond)) bpf_throw(value);
274-
275-
/* Description
276-
* Assert that LHS is equal to RHS. This statement updates the known value
277-
* of LHS during verification. Note that RHS must be a constant value, and
278-
* must fit within the data type of LHS.
279-
* Returns
280-
* Void.
281-
* Throws
282-
* An exception with the value zero when the assertion fails.
283-
*/
284-
#define bpf_assert_eq(LHS, RHS) \
285-
({ \
286-
barrier_var(LHS); \
287-
__bpf_assert_op(LHS, ==, RHS, 0, true); \
288-
})
289-
290-
/* Description
291-
* Assert that LHS is equal to RHS. This statement updates the known value
292-
* of LHS during verification. Note that RHS must be a constant value, and
293-
* must fit within the data type of LHS.
294-
* Returns
295-
* Void.
296-
* Throws
297-
* An exception with the specified value when the assertion fails.
298-
*/
299-
#define bpf_assert_eq_with(LHS, RHS, value) \
300-
({ \
301-
barrier_var(LHS); \
302-
__bpf_assert_op(LHS, ==, RHS, value, true); \
303-
})
304-
305-
/* Description
306-
* Assert that LHS is less than RHS. This statement updates the known
307-
* bounds of LHS during verification. Note that RHS must be a constant
308-
* value, and must fit within the data type of LHS.
309-
* Returns
310-
* Void.
311-
* Throws
312-
* An exception with the value zero when the assertion fails.
313-
*/
314-
#define bpf_assert_lt(LHS, RHS) \
315-
({ \
316-
barrier_var(LHS); \
317-
__bpf_assert_op(LHS, <, RHS, 0, false); \
318-
})
319-
320-
/* Description
321-
* Assert that LHS is less than RHS. This statement updates the known
322-
* bounds of LHS during verification. Note that RHS must be a constant
323-
* value, and must fit within the data type of LHS.
324-
* Returns
325-
* Void.
326-
* Throws
327-
* An exception with the specified value when the assertion fails.
328-
*/
329-
#define bpf_assert_lt_with(LHS, RHS, value) \
330-
({ \
331-
barrier_var(LHS); \
332-
__bpf_assert_op(LHS, <, RHS, value, false); \
333-
})
257+
#define __cmp_cannot_be_signed(x) \
258+
__builtin_strcmp(#x, "==") == 0 || __builtin_strcmp(#x, "!=") == 0 || \
259+
__builtin_strcmp(#x, "&") == 0
334260

335-
/* Description
336-
* Assert that LHS is greater than RHS. This statement updates the known
337-
* bounds of LHS during verification. Note that RHS must be a constant
338-
* value, and must fit within the data type of LHS.
339-
* Returns
340-
* Void.
341-
* Throws
342-
* An exception with the value zero when the assertion fails.
343-
*/
344-
#define bpf_assert_gt(LHS, RHS) \
345-
({ \
346-
barrier_var(LHS); \
347-
__bpf_assert_op(LHS, >, RHS, 0, false); \
348-
})
261+
#define __is_signed_type(type) (((type)(-1)) < (type)1)
349262

350-
/* Description
351-
* Assert that LHS is greater than RHS. This statement updates the known
352-
* bounds of LHS during verification. Note that RHS must be a constant
353-
* value, and must fit within the data type of LHS.
354-
* Returns
355-
* Void.
356-
* Throws
357-
* An exception with the specified value when the assertion fails.
263+
#define __bpf_cmp(LHS, OP, SIGN, PRED, RHS, DEFAULT) \
264+
({ \
265+
__label__ l_true; \
266+
bool ret = DEFAULT; \
267+
asm volatile goto("if %[lhs] " SIGN #OP " %[rhs] goto %l[l_true]" \
268+
:: [lhs] "r"((short)LHS), [rhs] PRED (RHS) :: l_true); \
269+
ret = !DEFAULT; \
270+
l_true: \
271+
ret; \
272+
})
273+
274+
/* C type conversions coupled with comparison operator are tricky.
275+
* Make sure BPF program is compiled with -Wsign-compare then
276+
* __lhs OP __rhs below will catch the mistake.
277+
* Be aware that we check only __lhs to figure out the sign of compare.
358278
*/
359-
#define bpf_assert_gt_with(LHS, RHS, value) \
360-
({ \
361-
barrier_var(LHS); \
362-
__bpf_assert_op(LHS, >, RHS, value, false); \
363-
})
279+
#define _bpf_cmp(LHS, OP, RHS, NOFLIP) \
280+
({ \
281+
typeof(LHS) __lhs = (LHS); \
282+
typeof(RHS) __rhs = (RHS); \
283+
bool ret; \
284+
_Static_assert(sizeof(&(LHS)), "1st argument must be an lvalue expression"); \
285+
(void)(__lhs OP __rhs); \
286+
if (__cmp_cannot_be_signed(OP) || !__is_signed_type(typeof(__lhs))) { \
287+
if (sizeof(__rhs) == 8) \
288+
ret = __bpf_cmp(__lhs, OP, "", "r", __rhs, NOFLIP); \
289+
else \
290+
ret = __bpf_cmp(__lhs, OP, "", "i", __rhs, NOFLIP); \
291+
} else { \
292+
if (sizeof(__rhs) == 8) \
293+
ret = __bpf_cmp(__lhs, OP, "s", "r", __rhs, NOFLIP); \
294+
else \
295+
ret = __bpf_cmp(__lhs, OP, "s", "i", __rhs, NOFLIP); \
296+
} \
297+
ret; \
298+
})
299+
300+
#ifndef bpf_cmp_unlikely
301+
#define bpf_cmp_unlikely(LHS, OP, RHS) _bpf_cmp(LHS, OP, RHS, true)
302+
#endif
364303

365-
/* Description
366-
* Assert that LHS is less than or equal to RHS. This statement updates the
367-
* known bounds of LHS during verification. Note that RHS must be a
368-
* constant value, and must fit within the data type of LHS.
369-
* Returns
370-
* Void.
371-
* Throws
372-
* An exception with the value zero when the assertion fails.
373-
*/
374-
#define bpf_assert_le(LHS, RHS) \
375-
({ \
376-
barrier_var(LHS); \
377-
__bpf_assert_op(LHS, <=, RHS, 0, false); \
378-
})
304+
#ifndef bpf_cmp_likely
305+
#define bpf_cmp_likely(LHS, OP, RHS) \
306+
({ \
307+
bool ret; \
308+
if (__builtin_strcmp(#OP, "==") == 0) \
309+
ret = _bpf_cmp(LHS, !=, RHS, false); \
310+
else if (__builtin_strcmp(#OP, "!=") == 0) \
311+
ret = _bpf_cmp(LHS, ==, RHS, false); \
312+
else if (__builtin_strcmp(#OP, "<=") == 0) \
313+
ret = _bpf_cmp(LHS, >, RHS, false); \
314+
else if (__builtin_strcmp(#OP, "<") == 0) \
315+
ret = _bpf_cmp(LHS, >=, RHS, false); \
316+
else if (__builtin_strcmp(#OP, ">") == 0) \
317+
ret = _bpf_cmp(LHS, <=, RHS, false); \
318+
else if (__builtin_strcmp(#OP, ">=") == 0) \
319+
ret = _bpf_cmp(LHS, <, RHS, false); \
320+
else \
321+
(void) "bug"; \
322+
ret; \
323+
})
324+
#endif
379325

380-
/* Description
381-
* Assert that LHS is less than or equal to RHS. This statement updates the
382-
* known bounds of LHS during verification. Note that RHS must be a
383-
* constant value, and must fit within the data type of LHS.
384-
* Returns
385-
* Void.
386-
* Throws
387-
* An exception with the specified value when the assertion fails.
388-
*/
389-
#define bpf_assert_le_with(LHS, RHS, value) \
390-
({ \
391-
barrier_var(LHS); \
392-
__bpf_assert_op(LHS, <=, RHS, value, false); \
393-
})
326+
#ifndef bpf_nop_mov
327+
#define bpf_nop_mov(var) \
328+
asm volatile("%[reg]=%[reg]"::[reg]"r"((short)var))
329+
#endif
394330

395331
/* Description
396-
* Assert that LHS is greater than or equal to RHS. This statement updates
397-
* the known bounds of LHS during verification. Note that RHS must be a
398-
* constant value, and must fit within the data type of LHS.
332+
* Assert that a conditional expression is true.
399333
* Returns
400334
* Void.
401335
* Throws
402336
* An exception with the value zero when the assertion fails.
403337
*/
404-
#define bpf_assert_ge(LHS, RHS) \
405-
({ \
406-
barrier_var(LHS); \
407-
__bpf_assert_op(LHS, >=, RHS, 0, false); \
408-
})
338+
#define bpf_assert(cond) if (!(cond)) bpf_throw(0);
409339

410340
/* Description
411-
* Assert that LHS is greater than or equal to RHS. This statement updates
412-
* the known bounds of LHS during verification. Note that RHS must be a
413-
* constant value, and must fit within the data type of LHS.
341+
* Assert that a conditional expression is true.
414342
* Returns
415343
* Void.
416344
* Throws
417345
* An exception with the specified value when the assertion fails.
418346
*/
419-
#define bpf_assert_ge_with(LHS, RHS, value) \
420-
({ \
421-
barrier_var(LHS); \
422-
__bpf_assert_op(LHS, >=, RHS, value, false); \
423-
})
347+
#define bpf_assert_with(cond, value) if (!(cond)) bpf_throw(value);
424348

425349
/* Description
426350
* Assert that LHS is in the range [BEG, END] (inclusive of both). This

tools/testing/selftests/bpf/progs/bpf_iter_bpf_percpu_hash_map.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ struct {
2020
} hashmap1 SEC(".maps");
2121

2222
/* will set before prog run */
23-
volatile const __u32 num_cpus = 0;
23+
volatile const __s32 num_cpus = 0;
2424

2525
/* will collect results during prog run */
2626
__u32 key_sum_a = 0, key_sum_b = 0, key_sum_c = 0;

tools/testing/selftests/bpf/progs/bpf_iter_task_vmas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ SEC("iter/task_vma") int proc_maps(struct bpf_iter__task_vma *ctx)
3535
return 0;
3636

3737
file = vma->vm_file;
38-
if (task->tgid != pid) {
38+
if (task->tgid != (pid_t)pid) {
3939
if (one_task)
4040
one_task_error = 1;
4141
return 0;

tools/testing/selftests/bpf/progs/bpf_iter_tasks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ int dump_task(struct bpf_iter__task *ctx)
2222
return 0;
2323
}
2424

25-
if (task->pid != tid)
25+
if (task->pid != (pid_t)tid)
2626
num_unknown_tid++;
2727
else
2828
num_known_tid++;

tools/testing/selftests/bpf/progs/bpf_iter_test_kern4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ int dump_bpf_map(struct bpf_iter__bpf_map *ctx)
4545
}
4646

4747
/* fill seq_file buffer */
48-
for (i = 0; i < print_len; i++)
48+
for (i = 0; i < (int)print_len; i++)
4949
bpf_seq_write(seq, &seq_num, sizeof(seq_num));
5050

5151
return ret;

tools/testing/selftests/bpf/progs/cgroup_getset_retval_setsockopt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
__u32 invocations = 0;
1212
__u32 assertion_error = 0;
1313
__u32 retval_value = 0;
14-
__u32 page_size = 0;
14+
__s32 page_size = 0;
1515

1616
SEC("cgroup/setsockopt")
1717
int get_retval(struct bpf_sockopt *ctx)

tools/testing/selftests/bpf/progs/cgrp_ls_sleepable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct {
1515
__type(value, long);
1616
} map_a SEC(".maps");
1717

18-
__u32 target_pid;
18+
__s32 target_pid;
1919
__u64 cgroup_id;
2020
int target_hid;
2121
bool is_cgroup1;

tools/testing/selftests/bpf/progs/cpumask_success.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ SEC("tp_btf/task_newtask")
332332
int BPF_PROG(test_copy_any_anyand, struct task_struct *task, u64 clone_flags)
333333
{
334334
struct bpf_cpumask *mask1, *mask2, *dst1, *dst2;
335-
u32 cpu;
335+
int cpu;
336336

337337
if (!is_test_task())
338338
return 0;

0 commit comments

Comments
 (0)