Skip to content

Commit

Permalink
bpf: introduce atomic_add()
Browse files Browse the repository at this point in the history
The GCC BPF support does not provide a way to emit an atomic add
instruction (BPF xadd) without the fetch-flag.  But since older
kernels do not support xadd with the fetch flag, the generated
BPF programs are rejected by the BPF verifier.

The atomic_add() macro emits a raw xadd instruction that works on
all kernels.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed May 24, 2023
1 parent 713e3bf commit 394de56
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
9 changes: 3 additions & 6 deletions bpf/speculation.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
*/
#include <linux/bpf.h>
#include <stdint.h>
#include <bpf-helpers.h>
#include <bpf-lib.h>
#include <dt_bpf_maps.h>

#include <dtrace/faults_defines.h>
Expand Down Expand Up @@ -96,11 +97,7 @@ dt_speculation_speculate(uint32_t id)
if (spec->draining)
return -1;

spec->written++;
/* Use atomics once GCC/binutils can emit them in forms that older
* kernels support:
* __atomic_add_fetch(&spec->written, 1, __ATOMIC_RELAXED);
*/
atomic_add(&spec->written, 1);
return 0;
}

Expand Down
27 changes: 26 additions & 1 deletion include/bpf-lib.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
Expand Down Expand Up @@ -61,5 +61,30 @@
: /* no clobbers */ \
);

/*
* Explicit inline assembler to implement atomic add:
*
* *ptr += val;
*/
#define atomic_add(valp, val) \
do { \
register uint64_t *ptr asm("%r0") = (valp); \
register uint64_t tmp asm("%r1") = (val); \
asm (".byte 0xdb, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00" \
: /* no outputs */ \
: "r" (ptr), "r" (tmp) \
: "memory" \
); \
} while (0)
#define atomic_add32(valp, val) \
do { \
register uint32_t *ptr asm("%r0") = (valp); \
register uint32_t tmp asm("%r1") = (val); \
asm (".byte 0xc3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00" \
: /* no outputs */ \
: "r" (ptr), "r" (tmp) \
: "memory" \
); \
} while (0)

#endif /* BPF_LIB_H */

0 comments on commit 394de56

Please sign in to comment.