Add Rust support for trace events:

- 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.
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQRRSw7ePDh/lE+zeZMp5XQQmuv6qgUCZ0DjqhQccm9zdGVkdEBn
 b29kbWlzLm9yZwAKCRAp5XQQmuv6qrLlAPsF6t/c1nHSGTKDv9FJDJe4JHdP7e+U
 7X0S8BmSTKFNAQD+K2TEd0bjVP7ug8dQZBT+fveiFr+ARYxAwJ3JnEFjUwg=
 =Ab+T
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2024-11-25 15:44:29 -08:00
commit 7f4f3b14e8
22 changed files with 375 additions and 64 deletions

View File

@ -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*

View File

@ -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;

View File

@ -19,10 +19,14 @@
#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)
@ -30,8 +34,8 @@ static __always_inline bool arch_static_branch(struct static_key * const key,
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;
@ -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:

View File

@ -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;
@ -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;

View File

@ -16,21 +16,28 @@
#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;
@ -38,21 +45,20 @@ static __always_inline bool arch_static_branch(struct static_key * const key,
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;

View File

@ -12,35 +12,28 @@
#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;
@ -48,13 +41,11 @@ static __always_inline bool arch_static_branch(struct static_key * const key, co
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;

View File

@ -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
@ -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) \
{ \
@ -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)) \
@ -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(); \
@ -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 = { \

View File

@ -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
@ -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

View File

@ -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>

View File

@ -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
@ -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

View File

@ -17,6 +17,7 @@
#include <linux/firmware.h>
#include <linux/fs.h>
#include <linux/jiffies.h>
#include <linux/jump_label.h>
#include <linux/mdio.h>
#include <linux/phy.h>
#include <linux/pid_namespace.h>
@ -25,8 +26,10 @@
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/slab.h>
#include <linux/tracepoint.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <trace/events/rust_sample.h>
/* `bindgen` gets confused at certain things. */
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;

View File

@ -14,6 +14,7 @@
#include "cred.c"
#include "err.c"
#include "fs.c"
#include "jump_label.c"
#include "kunit.c"
#include "mutex.c"
#include "page.c"

14
rust/helpers/jump_label.c Normal file
View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2024 Google LLC.
*/
#include <linux/jump_label.h>
#ifndef CONFIG_JUMP_LABEL
int rust_helper_static_key_count(struct static_key *key)
{
return static_key_count(key);
}
#endif

3
rust/kernel/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
/generated_arch_static_branch_asm.rs

View File

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/jump_label.h>
// Cut here.
::kernel::concat_literals!(ARCH_STATIC_BRANCH_ASM("{symb} + {off} + {branch}", "{l_yes}"))

74
rust/kernel/jump_label.rs Normal file
View File

@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2024 Google LLC.
//! Logic for static keys.
//!
//! C header: [`include/linux/jump_label.h`](srctree/include/linux/jump_label.h).
/// Branch based on a static key.
///
/// Takes three arguments:
///
/// * `key` - the path to the static variable containing the `static_key`.
/// * `keytyp` - the type of `key`.
/// * `field` - the name of the field of `key` that contains the `static_key`.
///
/// # Safety
///
/// The macro must be used with a real static key defined by C.
#[macro_export]
macro_rules! static_branch_unlikely {
($key:path, $keytyp:ty, $field:ident) => {{
let _key: *const $keytyp = ::core::ptr::addr_of!($key);
let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field);
let _key: *const $crate::bindings::static_key = _key.cast();
#[cfg(not(CONFIG_JUMP_LABEL))]
{
$crate::bindings::static_key_count(_key.cast_mut()) > 0
}
#[cfg(CONFIG_JUMP_LABEL)]
$crate::jump_label::arch_static_branch! { $key, $keytyp, $field, false }
}};
}
pub use static_branch_unlikely;
/// Assert that the assembly block evaluates to a string literal.
#[cfg(CONFIG_JUMP_LABEL)]
const _: &str = include!(concat!(
env!("OBJTREE"),
"/rust/kernel/generated_arch_static_branch_asm.rs"
));
#[macro_export]
#[doc(hidden)]
#[cfg(CONFIG_JUMP_LABEL)]
macro_rules! arch_static_branch {
($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
$crate::asm!(
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_static_branch_asm.rs"));
l_yes = label {
break 'my_label true;
},
symb = sym $key,
off = const ::core::mem::offset_of!($keytyp, $field),
branch = const $crate::jump_label::bool_to_int($branch),
);
break 'my_label false;
}};
}
#[cfg(CONFIG_JUMP_LABEL)]
pub use arch_static_branch;
/// A helper used by inline assembly to pass a boolean to as a `const` parameter.
///
/// Using this function instead of a cast lets you assert that the input is a boolean, and not some
/// other type that can also be cast to an integer.
#[doc(hidden)]
pub const fn bool_to_int(b: bool) -> i32 {
b as i32
}

View File

@ -38,6 +38,7 @@
pub mod fs;
pub mod init;
pub mod ioctl;
pub mod jump_label;
#[cfg(CONFIG_KUNIT)]
pub mod kunit;
pub mod list;
@ -57,6 +58,7 @@
pub mod sync;
pub mod task;
pub mod time;
pub mod tracepoint;
pub mod types;
pub mod uaccess;
pub mod workqueue;
@ -150,3 +152,38 @@ macro_rules! container_of {
ptr.sub(offset) as *const $type
}}
}
/// Helper for `.rs.S` files.
#[doc(hidden)]
#[macro_export]
macro_rules! concat_literals {
($( $asm:literal )* ) => {
::core::concat!($($asm),*)
};
}
/// Wrapper around `asm!` configured for use in the kernel.
///
/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
/// syntax.
// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[macro_export]
macro_rules! asm {
($($asm:expr),* ; $($rest:tt)*) => {
::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* )
};
}
/// Wrapper around `asm!` configured for use in the kernel.
///
/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
/// syntax.
// For non-x86 arches we just pass through to `asm!`.
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
#[macro_export]
macro_rules! asm {
($($asm:expr),* ; $($rest:tt)*) => {
::core::arch::asm!( $($asm)*, $($rest)* )
};
}

49
rust/kernel/tracepoint.rs Normal file
View File

@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2024 Google LLC.
//! Logic for tracepoints.
/// Declare the Rust entry point for a tracepoint.
///
/// This macro generates an unsafe function that calls into C, and its safety requirements will be
/// whatever the relevant C code requires. To document these safety requirements, you may add
/// doc-comments when invoking the macro.
#[macro_export]
macro_rules! declare_trace {
($($(#[$attr:meta])* $pub:vis unsafe fn $name:ident($($argname:ident : $argtyp:ty),* $(,)?);)*) => {$(
$( #[$attr] )*
#[inline(always)]
$pub unsafe fn $name($($argname : $argtyp),*) {
#[cfg(CONFIG_TRACEPOINTS)]
{
// SAFETY: It's always okay to query the static key for a tracepoint.
let should_trace = unsafe {
$crate::macros::paste! {
$crate::jump_label::static_branch_unlikely!(
$crate::bindings::[< __tracepoint_ $name >],
$crate::bindings::tracepoint,
key
)
}
};
if should_trace {
$crate::macros::paste! {
// SAFETY: The caller guarantees that it is okay to call this tracepoint.
unsafe { $crate::bindings::[< rust_do_trace_ $name >]($($argname),*) };
}
}
}
#[cfg(not(CONFIG_TRACEPOINTS))]
{
// If tracepoints are disabled, insert a trivial use of each argument
// to avoid unused argument warnings.
$( let _unused = $argname; )*
}
}
)*}
}
pub use declare_trace;

View File

@ -1,6 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
ccflags-y += -I$(src) # needed for trace events
obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o
obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
rust_print-y := rust_print_main.o rust_print_events.o
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs

View File

@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2024 Google LLC
*/
#define CREATE_TRACE_POINTS
#define CREATE_RUST_TRACE_POINTS
#include <trace/events/rust_sample.h>

View File

@ -69,6 +69,8 @@ fn init(_module: &'static ThisModule) -> Result<Self> {
arc_print()?;
trace::trace_rust_sample_loaded(42);
Ok(RustPrint)
}
}
@ -78,3 +80,19 @@ fn drop(&mut self) {
pr_info!("Rust printing macros sample (exit)\n");
}
}
mod trace {
use core::ffi::c_int;
kernel::declare_trace! {
/// # Safety
///
/// Always safe to call.
unsafe fn rust_sample_loaded(magic: c_int);
}
pub(crate) fn trace_rust_sample_loaded(magic: i32) {
// SAFETY: Always safe to call.
unsafe { rust_sample_loaded(magic as c_int) }
}
}

View File

@ -248,12 +248,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE
# Compile Rust sources (.rs)
# ---------------------------------------------------------------------------
rust_allowed_features := new_uninit
rust_allowed_features := asm_const,asm_goto,new_uninit
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
# current working directory, which may be not accessible in the out-of-tree
# modules case.
rust_common_cmd = \
OBJTREE=$(abspath $(objtree)) \
RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \
-Zallow-features=$(rust_allowed_features) \
-Zcrate-attr=no_std \
@ -303,6 +304,12 @@ quiet_cmd_rustc_ll_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
$(obj)/%.ll: $(obj)/%.rs FORCE
+$(call if_changed_dep,rustc_ll_rs)
quiet_cmd_rustc_rs_rs_S = RSCPP $(quiet_modtag) $@
cmd_rustc_rs_rs_S = $(CPP) $(c_flags) -xc -C -P $< | sed '1,/^\/\/ Cut here.$$/d' >$@
$(obj)/%.rs: $(obj)/%.rs.S FORCE
+$(call if_changed_dep,rustc_rs_rs_S)
# Compile assembler sources (.S)
# ---------------------------------------------------------------------------