Skip to content

Commit 7f4f3b1

Browse files
committedNov 25, 2024
Merge tag 'trace-rust-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents 36843bf + 8af7a50 commit 7f4f3b1

File tree

22 files changed

+375
-64
lines changed

22 files changed

+375
-64
lines changed
 

‎MAINTAINERS

+1
Original file line numberDiff line numberDiff line change
@@ -20348,6 +20348,7 @@ C: zulip://rust-for-linux.zulipchat.com
2034820348
P: https://rust-for-linux.com/contributing
2034920349
T: git https://github.com/Rust-for-Linux/linux.git rust-next
2035020350
F: Documentation/rust/
20351+
F: include/trace/events/rust_sample.h
2035120352
F: rust/
2035220353
F: samples/rust/
2035320354
F: scripts/*rust*

‎arch/arm/include/asm/jump_label.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99

1010
#define JUMP_LABEL_NOP_SIZE 4
1111

12+
/* This macro is also expanded on the Rust side. */
13+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
14+
"1:\n\t" \
15+
WASM(nop) "\n\t" \
16+
".pushsection __jump_table, \"aw\"\n\t" \
17+
".word 1b, " label ", " key "\n\t" \
18+
".popsection\n\t" \
19+
1220
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
1321
{
14-
asm goto("1:\n\t"
15-
WASM(nop) "\n\t"
16-
".pushsection __jump_table, \"aw\"\n\t"
17-
".word 1b, %l[l_yes], %c0\n\t"
18-
".popsection\n\t"
22+
asm goto(ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
1923
: : "i" (&((char *)key)[branch]) : : l_yes);
2024

2125
return false;

‎arch/arm64/include/asm/jump_label.h

+13-7
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,23 @@
1919
#define JUMP_TABLE_ENTRY(key, label) \
2020
".pushsection __jump_table, \"aw\"\n\t" \
2121
".align 3\n\t" \
22-
".long 1b - ., %l["#label"] - .\n\t" \
23-
".quad %c0 - .\n\t" \
24-
".popsection\n\t" \
25-
: : "i"(key) : : label
22+
".long 1b - ., " label " - .\n\t" \
23+
".quad " key " - .\n\t" \
24+
".popsection\n\t"
25+
26+
/* This macro is also expanded on the Rust side. */
27+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
28+
"1: nop\n\t" \
29+
JUMP_TABLE_ENTRY(key, label)
2630

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

3236
asm goto(
33-
"1: nop \n\t"
34-
JUMP_TABLE_ENTRY(k, l_yes)
37+
ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
38+
: : "i"(k) : : l_yes
3539
);
3640

3741
return false;
@@ -43,9 +47,11 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke
4347
const bool branch)
4448
{
4549
char *k = &((char *)key)[branch];
50+
4651
asm goto(
4752
"1: b %l[l_yes] \n\t"
48-
JUMP_TABLE_ENTRY(k, l_yes)
53+
JUMP_TABLE_ENTRY("%c0", "%l[l_yes]")
54+
: : "i"(k) : : l_yes
4955
);
5056
return false;
5157
l_yes:

‎arch/loongarch/include/asm/jump_label.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@
1313

1414
#define JUMP_LABEL_NOP_SIZE 4
1515

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

24+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
25+
"1: nop \n\t" \
26+
JUMP_TABLE_ENTRY(key, label)
27+
2328
static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
2429
{
2530
asm goto(
26-
"1: nop \n\t"
27-
JUMP_TABLE_ENTRY
31+
ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
2832
: : "i"(&((char *)key)[branch]) : : l_yes);
2933

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

4347
return false;

‎arch/riscv/include/asm/jump_label.h

+28-22
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,49 @@
1616

1717
#define JUMP_LABEL_NOP_SIZE 4
1818

19+
#define JUMP_TABLE_ENTRY(key, label) \
20+
".pushsection __jump_table, \"aw\" \n\t" \
21+
".align " RISCV_LGPTR " \n\t" \
22+
".long 1b - ., " label " - . \n\t" \
23+
"" RISCV_PTR " " key " - . \n\t" \
24+
".popsection \n\t"
25+
26+
/* This macro is also expanded on the Rust side. */
27+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
28+
" .align 2 \n\t" \
29+
" .option push \n\t" \
30+
" .option norelax \n\t" \
31+
" .option norvc \n\t" \
32+
"1: nop \n\t" \
33+
" .option pop \n\t" \
34+
JUMP_TABLE_ENTRY(key, label)
35+
1936
static __always_inline bool arch_static_branch(struct static_key * const key,
2037
const bool branch)
2138
{
2239
asm goto(
23-
" .align 2 \n\t"
24-
" .option push \n\t"
25-
" .option norelax \n\t"
26-
" .option norvc \n\t"
27-
"1: nop \n\t"
28-
" .option pop \n\t"
29-
" .pushsection __jump_table, \"aw\" \n\t"
30-
" .align " RISCV_LGPTR " \n\t"
31-
" .long 1b - ., %l[label] - . \n\t"
32-
" " RISCV_PTR " %0 - . \n\t"
33-
" .popsection \n\t"
40+
ARCH_STATIC_BRANCH_ASM("%0", "%l[label]")
3441
: : "i"(&((char *)key)[branch]) : : label);
3542

3643
return false;
3744
label:
3845
return true;
3946
}
4047

48+
#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \
49+
" .align 2 \n\t" \
50+
" .option push \n\t" \
51+
" .option norelax \n\t" \
52+
" .option norvc \n\t" \
53+
"1: j " label " \n\t" \
54+
" .option pop \n\t" \
55+
JUMP_TABLE_ENTRY(key, label)
56+
4157
static __always_inline bool arch_static_branch_jump(struct static_key * const key,
4258
const bool branch)
4359
{
4460
asm goto(
45-
" .align 2 \n\t"
46-
" .option push \n\t"
47-
" .option norelax \n\t"
48-
" .option norvc \n\t"
49-
"1: j %l[label] \n\t"
50-
" .option pop \n\t"
51-
" .pushsection __jump_table, \"aw\" \n\t"
52-
" .align " RISCV_LGPTR " \n\t"
53-
" .long 1b - ., %l[label] - . \n\t"
54-
" " RISCV_PTR " %0 - . \n\t"
55-
" .popsection \n\t"
61+
ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[label]")
5662
: : "i"(&((char *)key)[branch]) : : label);
5763

5864
return false;

‎arch/x86/include/asm/jump_label.h

+13-22
Original file line numberDiff line numberDiff line change
@@ -12,49 +12,40 @@
1212
#include <linux/stringify.h>
1313
#include <linux/types.h>
1414

15-
#define JUMP_TABLE_ENTRY \
15+
#define JUMP_TABLE_ENTRY(key, label) \
1616
".pushsection __jump_table, \"aw\" \n\t" \
1717
_ASM_ALIGN "\n\t" \
1818
".long 1b - . \n\t" \
19-
".long %l[l_yes] - . \n\t" \
20-
_ASM_PTR "%c0 + %c1 - .\n\t" \
19+
".long " label " - . \n\t" \
20+
_ASM_PTR " " key " - . \n\t" \
2121
".popsection \n\t"
2222

23+
/* This macro is also expanded on the Rust side. */
2324
#ifdef CONFIG_HAVE_JUMP_LABEL_HACK
24-
25-
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
26-
{
27-
asm goto("1:"
28-
"jmp %l[l_yes] # objtool NOPs this \n\t"
29-
JUMP_TABLE_ENTRY
30-
: : "i" (key), "i" (2 | branch) : : l_yes);
31-
32-
return false;
33-
l_yes:
34-
return true;
35-
}
36-
25+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
26+
"1: jmp " label " # objtool NOPs this \n\t" \
27+
JUMP_TABLE_ENTRY(key " + 2", label)
3728
#else /* !CONFIG_HAVE_JUMP_LABEL_HACK */
29+
#define ARCH_STATIC_BRANCH_ASM(key, label) \
30+
"1: .byte " __stringify(BYTES_NOP5) "\n\t" \
31+
JUMP_TABLE_ENTRY(key, label)
32+
#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
3833

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

4639
return false;
4740
l_yes:
4841
return true;
4942
}
5043

51-
#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
52-
5344
static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
5445
{
5546
asm goto("1:"
5647
"jmp %l[l_yes]\n\t"
57-
JUMP_TABLE_ENTRY
48+
JUMP_TABLE_ENTRY("%c0 + %c1", "%l[l_yes]")
5849
: : "i" (key), "i" (branch) : : l_yes);
5950

6051
return false;

‎include/linux/tracepoint.h

+27-1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,18 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
239239
preempt_enable_notrace(); \
240240
} while (0)
241241

242+
/*
243+
* Declare an exported function that Rust code can call to trigger this
244+
* tracepoint. This function does not include the static branch; that is done
245+
* in Rust to avoid a function call when the tracepoint is disabled.
246+
*/
247+
#define DEFINE_RUST_DO_TRACE(name, proto, args)
248+
#define __DEFINE_RUST_DO_TRACE(name, proto, args) \
249+
notrace void rust_do_trace_##name(proto) \
250+
{ \
251+
__rust_do_trace_##name(args); \
252+
}
253+
242254
/*
243255
* Make sure the alignment of the structure in the __tracepoints section will
244256
* not add unwanted padding between the beginning of the section and the
@@ -254,6 +266,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
254266
extern int __traceiter_##name(data_proto); \
255267
DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
256268
extern struct tracepoint __tracepoint_##name; \
269+
extern void rust_do_trace_##name(proto); \
257270
static inline int \
258271
register_trace_##name(void (*probe)(data_proto), void *data) \
259272
{ \
@@ -285,6 +298,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
285298

286299
#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
287300
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
301+
static inline void __rust_do_trace_##name(proto) \
302+
{ \
303+
__DO_TRACE(name, \
304+
TP_ARGS(args), \
305+
TP_CONDITION(cond), 0); \
306+
} \
288307
static inline void trace_##name(proto) \
289308
{ \
290309
if (static_branch_unlikely(&__tracepoint_##name.key)) \
@@ -299,6 +318,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
299318

300319
#define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \
301320
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
321+
static inline void __rust_do_trace_##name(proto) \
322+
{ \
323+
__DO_TRACE(name, \
324+
TP_ARGS(args), \
325+
TP_CONDITION(cond), 1); \
326+
} \
302327
static inline void trace_##name(proto) \
303328
{ \
304329
might_fault(); \
@@ -354,7 +379,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
354379
void __probestub_##_name(void *__data, proto) \
355380
{ \
356381
} \
357-
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
382+
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \
383+
DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args))
358384

359385
#define DEFINE_TRACE_FN(_name, _reg, _unreg, _proto, _args) \
360386
static struct tracepoint_ext __tracepoint_ext_##_name = { \

‎include/trace/define_trace.h

+12
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@
7676
#define DECLARE_TRACE(name, proto, args) \
7777
DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
7878

79+
/* If requested, create helpers for calling these tracepoints from Rust. */
80+
#ifdef CREATE_RUST_TRACE_POINTS
81+
#undef DEFINE_RUST_DO_TRACE
82+
#define DEFINE_RUST_DO_TRACE(name, proto, args) \
83+
__DEFINE_RUST_DO_TRACE(name, PARAMS(proto), PARAMS(args))
84+
#endif
85+
7986
#undef TRACE_INCLUDE
8087
#undef __TRACE_INCLUDE
8188

@@ -134,6 +141,11 @@
134141
# undef UNDEF_TRACE_INCLUDE_PATH
135142
#endif
136143

144+
#ifdef CREATE_RUST_TRACE_POINTS
145+
# undef DEFINE_RUST_DO_TRACE
146+
# define DEFINE_RUST_DO_TRACE(name, proto, args)
147+
#endif
148+
137149
/* We may be processing more files */
138150
#define CREATE_TRACE_POINTS
139151

‎include/trace/events/rust_sample.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Tracepoints for `samples/rust/rust_print.rs`.
4+
*
5+
* Copyright (C) 2024 Google, Inc.
6+
*/
7+
8+
#undef TRACE_SYSTEM
9+
#define TRACE_SYSTEM rust_sample
10+
11+
#if !defined(_RUST_SAMPLE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
12+
#define _RUST_SAMPLE_TRACE_H
13+
14+
#include <linux/tracepoint.h>
15+
16+
TRACE_EVENT(rust_sample_loaded,
17+
TP_PROTO(int magic_number),
18+
TP_ARGS(magic_number),
19+
TP_STRUCT__entry(
20+
__field(int, magic_number)
21+
),
22+
TP_fast_assign(
23+
__entry->magic_number = magic_number;
24+
),
25+
TP_printk("magic=%d", __entry->magic_number)
26+
);
27+
28+
#endif /* _RUST_SAMPLE_TRACE_H */
29+
30+
/* This part must be outside protection */
31+
#include <trace/define_trace.h>

‎rust/Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c
3636
obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o
3737
obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o
3838

39+
always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs
40+
3941
# Avoids running `$(RUSTC)` for the sysroot when it may not be available.
4042
ifdef CONFIG_RUST
4143

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

429+
ifdef CONFIG_JUMP_LABEL
430+
$(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs
431+
endif
432+
427433
endif # CONFIG_RUST

‎rust/bindings/bindings_helper.h

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/firmware.h>
1818
#include <linux/fs.h>
1919
#include <linux/jiffies.h>
20+
#include <linux/jump_label.h>
2021
#include <linux/mdio.h>
2122
#include <linux/phy.h>
2223
#include <linux/pid_namespace.h>
@@ -25,8 +26,10 @@
2526
#include <linux/sched.h>
2627
#include <linux/security.h>
2728
#include <linux/slab.h>
29+
#include <linux/tracepoint.h>
2830
#include <linux/wait.h>
2931
#include <linux/workqueue.h>
32+
#include <trace/events/rust_sample.h>
3033

3134
/* `bindgen` gets confused at certain things. */
3235
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;

‎rust/helpers/helpers.c

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "cred.c"
1515
#include "err.c"
1616
#include "fs.c"
17+
#include "jump_label.c"
1718
#include "kunit.c"
1819
#include "mutex.c"
1920
#include "page.c"

‎rust/helpers/jump_label.c

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2024 Google LLC.
5+
*/
6+
7+
#include <linux/jump_label.h>
8+
9+
#ifndef CONFIG_JUMP_LABEL
10+
int rust_helper_static_key_count(struct static_key *key)
11+
{
12+
return static_key_count(key);
13+
}
14+
#endif

‎rust/kernel/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
/generated_arch_static_branch_asm.rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#include <linux/jump_label.h>
4+
5+
// Cut here.
6+
7+
::kernel::concat_literals!(ARCH_STATIC_BRANCH_ASM("{symb} + {off} + {branch}", "{l_yes}"))

‎rust/kernel/jump_label.rs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
// Copyright (C) 2024 Google LLC.
4+
5+
//! Logic for static keys.
6+
//!
7+
//! C header: [`include/linux/jump_label.h`](srctree/include/linux/jump_label.h).
8+
9+
/// Branch based on a static key.
10+
///
11+
/// Takes three arguments:
12+
///
13+
/// * `key` - the path to the static variable containing the `static_key`.
14+
/// * `keytyp` - the type of `key`.
15+
/// * `field` - the name of the field of `key` that contains the `static_key`.
16+
///
17+
/// # Safety
18+
///
19+
/// The macro must be used with a real static key defined by C.
20+
#[macro_export]
21+
macro_rules! static_branch_unlikely {
22+
($key:path, $keytyp:ty, $field:ident) => {{
23+
let _key: *const $keytyp = ::core::ptr::addr_of!($key);
24+
let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field);
25+
let _key: *const $crate::bindings::static_key = _key.cast();
26+
27+
#[cfg(not(CONFIG_JUMP_LABEL))]
28+
{
29+
$crate::bindings::static_key_count(_key.cast_mut()) > 0
30+
}
31+
32+
#[cfg(CONFIG_JUMP_LABEL)]
33+
$crate::jump_label::arch_static_branch! { $key, $keytyp, $field, false }
34+
}};
35+
}
36+
pub use static_branch_unlikely;
37+
38+
/// Assert that the assembly block evaluates to a string literal.
39+
#[cfg(CONFIG_JUMP_LABEL)]
40+
const _: &str = include!(concat!(
41+
env!("OBJTREE"),
42+
"/rust/kernel/generated_arch_static_branch_asm.rs"
43+
));
44+
45+
#[macro_export]
46+
#[doc(hidden)]
47+
#[cfg(CONFIG_JUMP_LABEL)]
48+
macro_rules! arch_static_branch {
49+
($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
50+
$crate::asm!(
51+
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_static_branch_asm.rs"));
52+
l_yes = label {
53+
break 'my_label true;
54+
},
55+
symb = sym $key,
56+
off = const ::core::mem::offset_of!($keytyp, $field),
57+
branch = const $crate::jump_label::bool_to_int($branch),
58+
);
59+
60+
break 'my_label false;
61+
}};
62+
}
63+
64+
#[cfg(CONFIG_JUMP_LABEL)]
65+
pub use arch_static_branch;
66+
67+
/// A helper used by inline assembly to pass a boolean to as a `const` parameter.
68+
///
69+
/// Using this function instead of a cast lets you assert that the input is a boolean, and not some
70+
/// other type that can also be cast to an integer.
71+
#[doc(hidden)]
72+
pub const fn bool_to_int(b: bool) -> i32 {
73+
b as i32
74+
}

‎rust/kernel/lib.rs

+37
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub mod firmware;
3838
pub mod fs;
3939
pub mod init;
4040
pub mod ioctl;
41+
pub mod jump_label;
4142
#[cfg(CONFIG_KUNIT)]
4243
pub mod kunit;
4344
pub mod list;
@@ -57,6 +58,7 @@ pub mod str;
5758
pub mod sync;
5859
pub mod task;
5960
pub mod time;
61+
pub mod tracepoint;
6062
pub mod types;
6163
pub mod uaccess;
6264
pub mod workqueue;
@@ -150,3 +152,38 @@ macro_rules! container_of {
150152
ptr.sub(offset) as *const $type
151153
}}
152154
}
155+
156+
/// Helper for `.rs.S` files.
157+
#[doc(hidden)]
158+
#[macro_export]
159+
macro_rules! concat_literals {
160+
($( $asm:literal )* ) => {
161+
::core::concat!($($asm),*)
162+
};
163+
}
164+
165+
/// Wrapper around `asm!` configured for use in the kernel.
166+
///
167+
/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
168+
/// syntax.
169+
// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel.
170+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
171+
#[macro_export]
172+
macro_rules! asm {
173+
($($asm:expr),* ; $($rest:tt)*) => {
174+
::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* )
175+
};
176+
}
177+
178+
/// Wrapper around `asm!` configured for use in the kernel.
179+
///
180+
/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
181+
/// syntax.
182+
// For non-x86 arches we just pass through to `asm!`.
183+
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
184+
#[macro_export]
185+
macro_rules! asm {
186+
($($asm:expr),* ; $($rest:tt)*) => {
187+
::core::arch::asm!( $($asm)*, $($rest)* )
188+
};
189+
}

‎rust/kernel/tracepoint.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
// Copyright (C) 2024 Google LLC.
4+
5+
//! Logic for tracepoints.
6+
7+
/// Declare the Rust entry point for a tracepoint.
8+
///
9+
/// This macro generates an unsafe function that calls into C, and its safety requirements will be
10+
/// whatever the relevant C code requires. To document these safety requirements, you may add
11+
/// doc-comments when invoking the macro.
12+
#[macro_export]
13+
macro_rules! declare_trace {
14+
($($(#[$attr:meta])* $pub:vis unsafe fn $name:ident($($argname:ident : $argtyp:ty),* $(,)?);)*) => {$(
15+
$( #[$attr] )*
16+
#[inline(always)]
17+
$pub unsafe fn $name($($argname : $argtyp),*) {
18+
#[cfg(CONFIG_TRACEPOINTS)]
19+
{
20+
// SAFETY: It's always okay to query the static key for a tracepoint.
21+
let should_trace = unsafe {
22+
$crate::macros::paste! {
23+
$crate::jump_label::static_branch_unlikely!(
24+
$crate::bindings::[< __tracepoint_ $name >],
25+
$crate::bindings::tracepoint,
26+
key
27+
)
28+
}
29+
};
30+
31+
if should_trace {
32+
$crate::macros::paste! {
33+
// SAFETY: The caller guarantees that it is okay to call this tracepoint.
34+
unsafe { $crate::bindings::[< rust_do_trace_ $name >]($($argname),*) };
35+
}
36+
}
37+
}
38+
39+
#[cfg(not(CONFIG_TRACEPOINTS))]
40+
{
41+
// If tracepoints are disabled, insert a trivial use of each argument
42+
// to avoid unused argument warnings.
43+
$( let _unused = $argname; )*
44+
}
45+
}
46+
)*}
47+
}
48+
49+
pub use declare_trace;

‎samples/rust/Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# SPDX-License-Identifier: GPL-2.0
2+
ccflags-y += -I$(src) # needed for trace events
23

34
obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o
45
obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
56

7+
rust_print-y := rust_print_main.o rust_print_events.o
8+
69
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs

‎samples/rust/rust_print_events.c

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright 2024 Google LLC
4+
*/
5+
6+
#define CREATE_TRACE_POINTS
7+
#define CREATE_RUST_TRACE_POINTS
8+
#include <trace/events/rust_sample.h>

‎samples/rust/rust_print.rs ‎samples/rust/rust_print_main.rs

+18
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ impl kernel::Module for RustPrint {
6969

7070
arc_print()?;
7171

72+
trace::trace_rust_sample_loaded(42);
73+
7274
Ok(RustPrint)
7375
}
7476
}
@@ -78,3 +80,19 @@ impl Drop for RustPrint {
7880
pr_info!("Rust printing macros sample (exit)\n");
7981
}
8082
}
83+
84+
mod trace {
85+
use core::ffi::c_int;
86+
87+
kernel::declare_trace! {
88+
/// # Safety
89+
///
90+
/// Always safe to call.
91+
unsafe fn rust_sample_loaded(magic: c_int);
92+
}
93+
94+
pub(crate) fn trace_rust_sample_loaded(magic: i32) {
95+
// SAFETY: Always safe to call.
96+
unsafe { rust_sample_loaded(magic as c_int) }
97+
}
98+
}

‎scripts/Makefile.build

+8-1
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE
248248
# Compile Rust sources (.rs)
249249
# ---------------------------------------------------------------------------
250250

251-
rust_allowed_features := new_uninit
251+
rust_allowed_features := asm_const,asm_goto,new_uninit
252252

253253
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
254254
# current working directory, which may be not accessible in the out-of-tree
255255
# modules case.
256256
rust_common_cmd = \
257+
OBJTREE=$(abspath $(objtree)) \
257258
RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \
258259
-Zallow-features=$(rust_allowed_features) \
259260
-Zcrate-attr=no_std \
@@ -303,6 +304,12 @@ quiet_cmd_rustc_ll_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
303304
$(obj)/%.ll: $(obj)/%.rs FORCE
304305
+$(call if_changed_dep,rustc_ll_rs)
305306

307+
quiet_cmd_rustc_rs_rs_S = RSCPP $(quiet_modtag) $@
308+
cmd_rustc_rs_rs_S = $(CPP) $(c_flags) -xc -C -P $< | sed '1,/^\/\/ Cut here.$$/d' >$@
309+
310+
$(obj)/%.rs: $(obj)/%.rs.S FORCE
311+
+$(call if_changed_dep,rustc_rs_rs_S)
312+
306313
# Compile assembler sources (.S)
307314
# ---------------------------------------------------------------------------
308315

0 commit comments

Comments
 (0)
Please sign in to comment.