[DTrace-devel] [PATCH 1/4] bpf: introduce atomic_add()
Kris Van Hees
kris.van.hees at oracle.com
Tue May 9 07:16:46 UTC 2023
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 aotmic_add() macro emits a raw xadd instruction that works on
all kernels.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
bpf/speculation.c | 9 +++------
include/bpf-lib.h | 27 ++++++++++++++++++++++++++-
2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/bpf/speculation.c b/bpf/speculation.c
index 90433753..0a19ac33 100644
--- a/bpf/speculation.c
+++ b/bpf/speculation.c
@@ -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>
@@ -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;
}
diff --git a/include/bpf-lib.h b/include/bpf-lib.h
index d7078da5..fc3fe4fa 100644
--- a/include/bpf-lib.h
+++ b/include/bpf-lib.h
@@ -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.
*/
@@ -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 */
--
2.40.1
More information about the DTrace-devel
mailing list