Skip to content

Commit

Permalink
Merge tag 'trace-rust-v6.13' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/trace/linux-trace

Pull rust trace event support from Steven Rostedt:
 "Allow Rust code to have trace events

  Trace events is a popular way to debug what is happening inside the
  kernel or just to find out what is happening. Rust code is being added
  to the Linux kernel but it currently does not support the tracing
  infrastructure. Add support of trace events inside Rust code"

* tag 'trace-rust-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  rust: jump_label: skip formatting generated file
  jump_label: rust: pass a mut ptr to `static_key_count`
  samples: rust: fix `rust_print` build making it a combined module
  rust: add arch_static_branch
  jump_label: adjust inline asm to be consistent
  rust: samples: add tracepoint to Rust sample
  rust: add tracepoint support
  rust: add static_branch_unlikely for static_key_false
  • Loading branch information
Linus Torvalds committed Nov 25, 2024
2 parents 36843bf + 8af7a50 commit 7f4f3b1
Show file tree
Hide file tree
Showing 22 changed files with 375 additions and 64 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -20348,6 +20348,7 @@ C: zulip://rust-for-linux.zulipchat.com
P: https://rust-for-linux.com/contributing
T: git https://github.com/Rust-for-Linux/linux.git rust-next
F: Documentation/rust/
F: include/trace/events/rust_sample.h
F: rust/
F: samples/rust/
F: scripts/*rust*
Expand Down
14 changes: 9 additions & 5 deletions arch/arm/include/asm/jump_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@

#define JUMP_LABEL_NOP_SIZE 4

/* This macro is also expanded on the Rust side. */
#define ARCH_STATIC_BRANCH_ASM(key, label) \
"1:\n\t" \
WASM(nop) "\n\t" \
".pushsection __jump_table, \"aw\"\n\t" \
".word 1b, " label ", " key "\n\t" \
".popsection\n\t" \

static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
asm goto("1:\n\t"
WASM(nop) "\n\t"
".pushsection __jump_table, \"aw\"\n\t"
".word 1b, %l[l_yes], %c0\n\t"
".popsection\n\t"
asm goto(ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
: : "i" (&((char *)key)[branch]) : : l_yes);

return false;
Expand Down
20 changes: 13 additions & 7 deletions arch/arm64/include/asm/jump_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,23 @@
#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\"\n\t" \
".align 3\n\t" \
".long 1b - ., %l["#label"] - .\n\t" \
".quad %c0 - .\n\t" \
".popsection\n\t" \
: : "i"(key) : : label
".long 1b - ., " label " - .\n\t" \
".quad " key " - .\n\t" \
".popsection\n\t"

/* This macro is also expanded on the Rust side. */
#define ARCH_STATIC_BRANCH_ASM(key, label) \
"1: nop\n\t" \
JUMP_TABLE_ENTRY(key, label)

static __always_inline bool arch_static_branch(struct static_key * const key,
const bool branch)
{
char *k = &((char *)key)[branch];

asm goto(
"1: nop \n\t"
JUMP_TABLE_ENTRY(k, l_yes)
ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
: : "i"(k) : : l_yes
);

return false;
Expand All @@ -43,9 +47,11 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke
const bool branch)
{
char *k = &((char *)key)[branch];

asm goto(
"1: b %l[l_yes] \n\t"
JUMP_TABLE_ENTRY(k, l_yes)
JUMP_TABLE_ENTRY("%c0", "%l[l_yes]")
: : "i"(k) : : l_yes
);
return false;
l_yes:
Expand Down
16 changes: 10 additions & 6 deletions arch/loongarch/include/asm/jump_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,22 @@

#define JUMP_LABEL_NOP_SIZE 4

#define JUMP_TABLE_ENTRY \
/* This macro is also expanded on the Rust side. */
#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
".align 3 \n\t" \
".long 1b - ., %l[l_yes] - . \n\t" \
".quad %0 - . \n\t" \
".long 1b - ., " label " - . \n\t" \
".quad " key " - . \n\t" \
".popsection \n\t"

#define ARCH_STATIC_BRANCH_ASM(key, label) \
"1: nop \n\t" \
JUMP_TABLE_ENTRY(key, label)

static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
{
asm goto(
"1: nop \n\t"
JUMP_TABLE_ENTRY
ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
: : "i"(&((char *)key)[branch]) : : l_yes);

return false;
Expand All @@ -37,7 +41,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke
{
asm goto(
"1: b %l[l_yes] \n\t"
JUMP_TABLE_ENTRY
JUMP_TABLE_ENTRY("%0", "%l[l_yes]")
: : "i"(&((char *)key)[branch]) : : l_yes);

return false;
Expand Down
50 changes: 28 additions & 22 deletions arch/riscv/include/asm/jump_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,49 @@

#define JUMP_LABEL_NOP_SIZE 4

#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
".align " RISCV_LGPTR " \n\t" \
".long 1b - ., " label " - . \n\t" \
"" RISCV_PTR " " key " - . \n\t" \
".popsection \n\t"

/* This macro is also expanded on the Rust side. */
#define ARCH_STATIC_BRANCH_ASM(key, label) \
" .align 2 \n\t" \
" .option push \n\t" \
" .option norelax \n\t" \
" .option norvc \n\t" \
"1: nop \n\t" \
" .option pop \n\t" \
JUMP_TABLE_ENTRY(key, label)

static __always_inline bool arch_static_branch(struct static_key * const key,
const bool branch)
{
asm goto(
" .align 2 \n\t"
" .option push \n\t"
" .option norelax \n\t"
" .option norvc \n\t"
"1: nop \n\t"
" .option pop \n\t"
" .pushsection __jump_table, \"aw\" \n\t"
" .align " RISCV_LGPTR " \n\t"
" .long 1b - ., %l[label] - . \n\t"
" " RISCV_PTR " %0 - . \n\t"
" .popsection \n\t"
ARCH_STATIC_BRANCH_ASM("%0", "%l[label]")
: : "i"(&((char *)key)[branch]) : : label);

return false;
label:
return true;
}

#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \
" .align 2 \n\t" \
" .option push \n\t" \
" .option norelax \n\t" \
" .option norvc \n\t" \
"1: j " label " \n\t" \
" .option pop \n\t" \
JUMP_TABLE_ENTRY(key, label)

static __always_inline bool arch_static_branch_jump(struct static_key * const key,
const bool branch)
{
asm goto(
" .align 2 \n\t"
" .option push \n\t"
" .option norelax \n\t"
" .option norvc \n\t"
"1: j %l[label] \n\t"
" .option pop \n\t"
" .pushsection __jump_table, \"aw\" \n\t"
" .align " RISCV_LGPTR " \n\t"
" .long 1b - ., %l[label] - . \n\t"
" " RISCV_PTR " %0 - . \n\t"
" .popsection \n\t"
ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[label]")
: : "i"(&((char *)key)[branch]) : : label);

return false;
Expand Down
35 changes: 13 additions & 22 deletions arch/x86/include/asm/jump_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,49 +12,40 @@
#include <linux/stringify.h>
#include <linux/types.h>

#define JUMP_TABLE_ENTRY \
#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
_ASM_ALIGN "\n\t" \
".long 1b - . \n\t" \
".long %l[l_yes] - . \n\t" \
_ASM_PTR "%c0 + %c1 - .\n\t" \
".long " label " - . \n\t" \
_ASM_PTR " " key " - . \n\t" \
".popsection \n\t"

/* This macro is also expanded on the Rust side. */
#ifdef CONFIG_HAVE_JUMP_LABEL_HACK

static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
asm goto("1:"
"jmp %l[l_yes] # objtool NOPs this \n\t"
JUMP_TABLE_ENTRY
: : "i" (key), "i" (2 | branch) : : l_yes);

return false;
l_yes:
return true;
}

#define ARCH_STATIC_BRANCH_ASM(key, label) \
"1: jmp " label " # objtool NOPs this \n\t" \
JUMP_TABLE_ENTRY(key " + 2", label)
#else /* !CONFIG_HAVE_JUMP_LABEL_HACK */
#define ARCH_STATIC_BRANCH_ASM(key, label) \
"1: .byte " __stringify(BYTES_NOP5) "\n\t" \
JUMP_TABLE_ENTRY(key, label)
#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */

static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
{
asm goto("1:"
".byte " __stringify(BYTES_NOP5) "\n\t"
JUMP_TABLE_ENTRY
asm goto(ARCH_STATIC_BRANCH_ASM("%c0 + %c1", "%l[l_yes]")
: : "i" (key), "i" (branch) : : l_yes);

return false;
l_yes:
return true;
}

#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */

static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
{
asm goto("1:"
"jmp %l[l_yes]\n\t"
JUMP_TABLE_ENTRY
JUMP_TABLE_ENTRY("%c0 + %c1", "%l[l_yes]")
: : "i" (key), "i" (branch) : : l_yes);

return false;
Expand Down
28 changes: 27 additions & 1 deletion include/linux/tracepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
preempt_enable_notrace(); \
} while (0)

/*
* Declare an exported function that Rust code can call to trigger this
* tracepoint. This function does not include the static branch; that is done
* in Rust to avoid a function call when the tracepoint is disabled.
*/
#define DEFINE_RUST_DO_TRACE(name, proto, args)
#define __DEFINE_RUST_DO_TRACE(name, proto, args) \
notrace void rust_do_trace_##name(proto) \
{ \
__rust_do_trace_##name(args); \
}

/*
* Make sure the alignment of the structure in the __tracepoints section will
* not add unwanted padding between the beginning of the section and the
Expand All @@ -254,6 +266,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
extern int __traceiter_##name(data_proto); \
DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
extern struct tracepoint __tracepoint_##name; \
extern void rust_do_trace_##name(proto); \
static inline int \
register_trace_##name(void (*probe)(data_proto), void *data) \
{ \
Expand Down Expand Up @@ -285,6 +298,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)

#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
static inline void __rust_do_trace_##name(proto) \
{ \
__DO_TRACE(name, \
TP_ARGS(args), \
TP_CONDITION(cond), 0); \
} \
static inline void trace_##name(proto) \
{ \
if (static_branch_unlikely(&__tracepoint_##name.key)) \
Expand All @@ -299,6 +318,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)

#define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
static inline void __rust_do_trace_##name(proto) \
{ \
__DO_TRACE(name, \
TP_ARGS(args), \
TP_CONDITION(cond), 1); \
} \
static inline void trace_##name(proto) \
{ \
might_fault(); \
Expand Down Expand Up @@ -354,7 +379,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
void __probestub_##_name(void *__data, proto) \
{ \
} \
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \
DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args))

#define DEFINE_TRACE_FN(_name, _reg, _unreg, _proto, _args) \
static struct tracepoint_ext __tracepoint_ext_##_name = { \
Expand Down
12 changes: 12 additions & 0 deletions include/trace/define_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@
#define DECLARE_TRACE(name, proto, args) \
DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))

/* If requested, create helpers for calling these tracepoints from Rust. */
#ifdef CREATE_RUST_TRACE_POINTS
#undef DEFINE_RUST_DO_TRACE
#define DEFINE_RUST_DO_TRACE(name, proto, args) \
__DEFINE_RUST_DO_TRACE(name, PARAMS(proto), PARAMS(args))
#endif

#undef TRACE_INCLUDE
#undef __TRACE_INCLUDE

Expand Down Expand Up @@ -134,6 +141,11 @@
# undef UNDEF_TRACE_INCLUDE_PATH
#endif

#ifdef CREATE_RUST_TRACE_POINTS
# undef DEFINE_RUST_DO_TRACE
# define DEFINE_RUST_DO_TRACE(name, proto, args)
#endif

/* We may be processing more files */
#define CREATE_TRACE_POINTS

Expand Down
31 changes: 31 additions & 0 deletions include/trace/events/rust_sample.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Tracepoints for `samples/rust/rust_print.rs`.
*
* Copyright (C) 2024 Google, Inc.
*/

#undef TRACE_SYSTEM
#define TRACE_SYSTEM rust_sample

#if !defined(_RUST_SAMPLE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _RUST_SAMPLE_TRACE_H

#include <linux/tracepoint.h>

TRACE_EVENT(rust_sample_loaded,
TP_PROTO(int magic_number),
TP_ARGS(magic_number),
TP_STRUCT__entry(
__field(int, magic_number)
),
TP_fast_assign(
__entry->magic_number = magic_number;
),
TP_printk("magic=%d", __entry->magic_number)
);

#endif /* _RUST_SAMPLE_TRACE_H */

/* This part must be outside protection */
#include <trace/define_trace.h>
6 changes: 6 additions & 0 deletions rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c
obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o
obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o

always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs

# Avoids running `$(RUSTC)` for the sysroot when it may not be available.
ifdef CONFIG_RUST

Expand Down Expand Up @@ -424,4 +426,8 @@ $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \
$(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE
+$(call if_changed_rule,rustc_library)

ifdef CONFIG_JUMP_LABEL
$(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs
endif

endif # CONFIG_RUST
Loading

0 comments on commit 7f4f3b1

Please sign in to comment.