Skip to contentSkip to conversation

Rust support

PATCH Superseded Miguel Ojeda 12 participants 57 messages Feb 12, 2022 – Mar 18, 2022

Subsystems (28)

v4 of 10 Superseded Latest is v10 →

lore
Share & tools
lore

Miguel Ojeda

author maintainer
#0 lore raw

v4 cover Rust support

Rust support

This is the patch series (v4) to add support for Rust as a second language to the Linux kernel.

If you are interested in following this effort, please join us in the mailing list at:

[email protected]

and take a look at the project itself at:

https://github.com/Rust-for-Linux

As usual, special thanks go to ISRG (Internet Security Research Group) and Google for their financial support on this endeavor.

Cheers,
Miguel

--

# Rust support

This cover letter explains the major changes and updates done since the previous ones. For those, please see:

    RFC: https://lore.kernel.org/lkml/[email protected]/
    v1:  https://lore.kernel.org/lkml/[email protected]/
    v2:  https://lore.kernel.org/lkml/[email protected]/
    v3:  https://lore.kernel.org/lkml/[email protected]/

## Infrastructure updates

There have been several improvements to the overall Rust support:

- The Intel 0DAY/LKP kernel test robot is setting up Rust in their CI -- we already got the first reports from the bot which we could act upon, very useful!

- KernelCI is also looking forward to enabling Rust in their runs.

- The GitHub CI we use for quick pre-merge testing has been moved to use containers.

- Kernel modules do not need to write the crate attributes

    `#![no_std]` and `#![feature(...)]` anymore, removing boilerplate.

- Added single target support, including .o, .s, .ll and .i (i.e. macro expanded, similar to C preprocessed sources).

- Explanation of the helpers.c file and licensing for helpers and exports.

- The documentation logo is now vector based (SVG). In addition, a vector version of Tux has been proposed for upstream, and an RFC for improved custom logo support has been submitted to upstream Rust.

- Added coding guidelines on comments (//) and code documentation

    (`///`).

- is_rust_module.sh rework.

- Generation of .rmeta for leaf modules is skipped now.

- Other cleanups, fixes and improvements.

## Abstractions and driver updates

Some of the improvements to the abstractions and example drivers are:

- Added support for static (global shared variables) synchronization primitives. CONFIG_CONSTRUCTORS are used for the implementation.

- Simplification of the lock guards by using marker types, i.e. Guard and GuardMut are unified into a single parametrized type. If the marker is WriteLock, then Guard implements DerefMut (only implemented by GuardMut previously).

- Optional parameters added to the registration of misc devices,

    following the builder pattern., e.g.

        miscdev::Options::new()
            .mode(0o600)
            .minor(10)
            .parent(parent)
            .register(reg, c_str!("sample"), ())

- Added RwSemaphore abstraction that wraps the C side struct rw_semaphore.

- New mm module and VMA abstraction (wrapping the C side struct vm_area_struct) for use with mmap.

- GPIO PL061 now uses the recently added dev_*! Rust macros.

- Support the !CONFIG_PRINTK case.

- Other cleanups, fixes and improvements.

## Patch series status

The Rust support is still to be considered experimental. However, support is good enough that kernel developers can start working on the Rust abstractions for subsystems and write drivers and other modules.

The current series has just arrived in linux-next, as usual. Similarly, the preview docs for this series can be seen at:

https://rust-for-linux.github.io/docs/kernel/

As usual, please see the following link for the
live list of unstable Rust features we are using:

https://github.com/Rust-for-Linux/linux/issues/2

## Acknowledgements

The signatures in the main commits correspond to the people that wrote code that has ended up in them at the present time. For details on contributions to code and discussions, please see our repository:

https://github.com/Rust-for-Linux/linux

However, we would like to give credit to everyone that has contributed in one way or another to the Rust for Linux project. Since the previous cover letter:

- Philip Li, Yujie Liu et. al. for setting the Intel 0DAY/LKP kernel test robot with Rust support.

- Maciej Falkowski for continuing his work on the Hardware Random Number Generator subsystem, Samsung Exynos true random number generator, clock subsystem, etc.

- bjorn3 for an extensive re-review of the previous round.

- Jonathan Corbet for his feedback on the previous round.

- Garrett LeSage and IFo Hancroft for agreeing to the usage of their vector version of Tux within the kernel tree with the same license as the existing one from Larry Ewing.

- Nathan Chancellor for noticing a case where a C module was being identified as a Rust one for purposes of skipping BTF generation and suggesting a few improvements around is_rust_module.sh.

- Wei Liu for exporting the remaining helpers and triggering a useful discussion around it.

- Miguel Cano for fixing an issue with compilers containing a full, 3-part version in the suffix part (e.g. Ubuntu Clang).

- Abhik Jain for working on adding missing // SAFETY comments and # Safety sections to the code generated by the module! macro.

- Jiapeng Chong and the Abaci Robot for reporting and fixing an unneeded header #include.

- Finn Behrens for resuming his work on building Rust for Linux on Nix and spotting and fixing usability issues.

- As usual, Gary Guo and bjorn3 for all the input on Rust compiler details and all the reviews and suggestions.

- John Ericson, TennyZhuang and Xuanwo for their ongoing work on adding more fallible allocation methods (try_*) to the Rust standard library.

- Stephan Sokolow and Mark Rousskov for their feedback on the custom documentation logo RFC.

- Philip Herrons (and his supporters Open Source Security and Embecosm) et. al. for their ongoing work on GCC Rust.

- Antoni Boucher (and his supporters) et. al. for their ongoing work on rustc_codegen_gcc.

- Mats Larsen, Marc Poulhiès et. al. for their ongoing work on improving Rust support in Compiler Explorer.

- Many folks that have reported issues, tested the project, helped spread the word, joined discussions and contributed in other ways!

Please see also the acknowledgements on the previous cover letters.

Boqun Feng (1):
kallsyms: use the correct buffer size for symbols

Gary Guo (2):
rust: add build_error crate
vsprintf: add new %pA format specifier

Miguel Ojeda (13):
kallsyms: support "big" kernel symbols
kallsyms: increase maximum kernel symbol length to 512
rust: add C helpers
rust: add compiler_builtins crate
rust: add alloc crate
rust: add macros crate
rust: export generated symbols
scripts: add generate_rust_analyzer.py
scripts: decode_stacktrace: demangle Rust symbols
docs: add Rust documentation
Kbuild: add Rust support
samples: add Rust examples
MAINTAINERS: Rust

Wedson Almeida Filho (4):
rust: add kernel crate's sync module
rust: add kernel crate
[RFC] drivers: gpio: PrimeCell PL061 in Rust
[RFC] drivers: android: Binder IPC in Rust

 .gitignore                                   |    5 +
 .rustfmt.toml                                |   12 +
 Documentation/doc-guide/kernel-doc.rst       |    3 +
 Documentation/index.rst                      |    1 +
 Documentation/kbuild/kbuild.rst              |    4 +
 Documentation/process/changes.rst            |   42 +
 Documentation/rust/arch-support.rst          |   35 +
 Documentation/rust/coding-guidelines.rst     |  153 +
 Documentation/rust/general-information.rst   |   80 +
 Documentation/rust/index.rst                 |   21 +
 Documentation/rust/logo.svg                  |  357 ++
 Documentation/rust/quick-start.rst           |  231 ++
 MAINTAINERS                                  |   16 +
 Makefile                                     |  154 +-
 arch/arm/rust/target.json                    |   27 +
 arch/arm64/rust/target.json                  |   34 +
 arch/powerpc/rust/target.json                |   29 +
 arch/riscv/Makefile                          |    1 +
 arch/riscv/rust/rv32ima.json                 |   36 +
 arch/riscv/rust/rv32imac.json                |   36 +
 arch/riscv/rust/rv64ima.json                 |   36 +
 arch/riscv/rust/rv64imac.json                |   36 +
 arch/x86/rust/target.json                    |   36 +
 drivers/android/Kconfig                      |    7 +
 drivers/android/Makefile                     |    2 +
 drivers/android/allocation.rs                |  266 ++
 drivers/android/context.rs                   |   80 +
 drivers/android/defs.rs                      |   99 +
 drivers/android/node.rs                      |  476 +++
 drivers/android/process.rs                   |  961 +++++
 drivers/android/range_alloc.rs               |  189 +
 drivers/android/rust_binder.rs               |  111 +
 drivers/android/thread.rs                    |  871 +++++
 drivers/android/transaction.rs               |  326 ++
 drivers/gpio/Kconfig                         |    8 +
 drivers/gpio/Makefile                        |    1 +
 drivers/gpio/gpio_pl061_rust.rs              |  370 ++
 include/linux/kallsyms.h                     |    2 +-
 include/linux/spinlock.h                     |   17 +-
 include/uapi/linux/android/binder.h          |   28 +-
 init/Kconfig                                 |   45 +-
 kernel/kallsyms.c                            |   26 +-
 kernel/livepatch/core.c                      |    4 +-
 kernel/printk/printk.c                       |    5 +-
 lib/Kconfig.debug                            |  144 +
 lib/rust.h                                   |   14 +
 lib/vsprintf.c                               |    7 +
 rust/.gitignore                              |    7 +
 rust/Makefile                                |  374 ++
 rust/alloc/README.md                         |   32 +
 rust/alloc/alloc.rs                          |  427 +++
 rust/alloc/borrow.rs                         |  498 +++
 rust/alloc/boxed.rs                          | 1847 ++++++++++
 rust/alloc/collections/mod.rs                |  156 +
 rust/alloc/fmt.rs                            |  601 ++++
 rust/alloc/lib.rs                            |  217 ++
 rust/alloc/macros.rs                         |  126 +
 rust/alloc/raw_vec.rs                        |  549 +++
 rust/alloc/slice.rs                          | 1279 +++++++
 rust/alloc/str.rs                            |  624 ++++
 rust/alloc/string.rs                         | 2864 +++++++++++++++
 rust/alloc/vec/drain.rs                      |  159 +
 rust/alloc/vec/drain_filter.rs               |  145 +
 rust/alloc/vec/into_iter.rs                  |  356 ++
 rust/alloc/vec/is_zero.rs                    |  106 +
 rust/alloc/vec/mod.rs                        | 3359 ++++++++++++++++++
 rust/alloc/vec/partial_eq.rs                 |   49 +
 rust/alloc/vec/set_len_on_drop.rs            |   30 +
 rust/alloc/vec/spec_extend.rs                |  172 +
 rust/bindgen_parameters                      |   13 +
 rust/build_error.rs                          |   29 +
 rust/compiler_builtins.rs                    |   57 +
 rust/exports.c                               |   19 +
 rust/helpers.c                               |  529 +++
 rust/kernel/allocator.rs                     |   65 +
 rust/kernel/amba.rs                          |  259 ++
 rust/kernel/bindings.rs                      |   47 +
 rust/kernel/bindings_helper.h                |   30 +
 rust/kernel/buffer.rs                        |   52 +
 rust/kernel/build_assert.rs                  |   80 +
 rust/kernel/c_types.rs                       |  119 +
 rust/kernel/chrdev.rs                        |  209 ++
 rust/kernel/clk.rs                           |   75 +
 rust/kernel/cred.rs                          |   73 +
 rust/kernel/device.rs                        |  554 +++
 rust/kernel/driver.rs                        |  440 +++
 rust/kernel/error.rs                         |  542 +++
 rust/kernel/file.rs                          |  147 +
 rust/kernel/file_operations.rs               |  734 ++++
 rust/kernel/gpio.rs                          |  477 +++
 rust/kernel/io_buffer.rs                     |  153 +
 rust/kernel/io_mem.rs                        |  227 ++
 rust/kernel/iov_iter.rs                      |   81 +
 rust/kernel/irq.rs                           |  409 +++
 rust/kernel/lib.rs                           |  261 ++
 rust/kernel/linked_list.rs                   |  247 ++
 rust/kernel/miscdev.rs                       |  281 ++
 rust/kernel/mm.rs                            |  149 +
 rust/kernel/module_param.rs                  |  497 +++
 rust/kernel/of.rs                            |   63 +
 rust/kernel/pages.rs                         |  144 +
 rust/kernel/platform.rs                      |  224 ++
 rust/kernel/power.rs                         |  118 +
 rust/kernel/prelude.rs                       |   36 +
 rust/kernel/print.rs                         |  417 +++
 rust/kernel/random.rs                        |   50 +
 rust/kernel/raw_list.rs                      |  361 ++
 rust/kernel/rbtree.rs                        |  562 +++
 rust/kernel/revocable.rs                     |  163 +
 rust/kernel/security.rs                      |   36 +
 rust/kernel/static_assert.rs                 |   39 +
 rust/kernel/std_vendor.rs                    |  150 +
 rust/kernel/str.rs                           |  401 +++
 rust/kernel/sync/arc.rs                      |  500 +++
 rust/kernel/sync/condvar.rs                  |  138 +
 rust/kernel/sync/guard.rs                    |  150 +
 rust/kernel/sync/locked_by.rs                |  112 +
 rust/kernel/sync/mod.rs                      |  157 +
 rust/kernel/sync/mutex.rs                    |  112 +
 rust/kernel/sync/revocable_mutex.rs          |  184 +
 rust/kernel/sync/rwsem.rs                    |  147 +
 rust/kernel/sync/seqlock.rs                  |  202 ++
 rust/kernel/sync/spinlock.rs                 |  180 +
 rust/kernel/sysctl.rs                        |  197 +
 rust/kernel/task.rs                          |  182 +
 rust/kernel/types.rs                         |  486 +++
 rust/kernel/user_ptr.rs                      |  175 +
 rust/macros/helpers.rs                       |   79 +
 rust/macros/lib.rs                           |   94 +
 rust/macros/module.rs                        |  631 ++++
 samples/Kconfig                              |    2 +
 samples/Makefile                             |    1 +
 samples/rust/Kconfig                         |  123 +
 samples/rust/Makefile                        |   13 +
 samples/rust/rust_chrdev.rs                  |   50 +
 samples/rust/rust_minimal.rs                 |   35 +
 samples/rust/rust_miscdev.rs                 |  144 +
 samples/rust/rust_module_parameters.rs       |   69 +
 samples/rust/rust_platform.rs                |   22 +
 samples/rust/rust_print.rs                   |   54 +
 samples/rust/rust_random.rs                  |   61 +
 samples/rust/rust_semaphore.rs               |  172 +
 samples/rust/rust_semaphore_c.c              |  212 ++
 samples/rust/rust_stack_probing.rs           |   36 +
 samples/rust/rust_sync.rs                    |   78 +
 scripts/Kconfig.include                      |    6 +-
 scripts/Makefile.build                       |   65 +
 scripts/Makefile.debug                       |   10 +
 scripts/Makefile.lib                         |   12 +
 scripts/Makefile.modfinal                    |    8 +-
 scripts/cc-version.sh                        |   12 +-
 scripts/decode_stacktrace.sh                 |   14 +
 scripts/generate_rust_analyzer.py            |  133 +
 scripts/is_rust_module.sh                    |   13 +
 scripts/kallsyms.c                           |   40 +-
 scripts/kconfig/confdata.c                   |   75 +
 scripts/min-tool-version.sh                  |    6 +
 scripts/rust-is-available-bindgen-libclang.h |    2 +
 scripts/rust-is-available.sh                 |  158 +
 tools/include/linux/kallsyms.h               |    2 +-
 tools/lib/perf/include/perf/event.h          |    2 +-
 tools/lib/symbol/kallsyms.h                  |    2 +-
 162 files changed, 34341 insertions(+), 57 deletions(-)
 create mode 100644 .rustfmt.toml
 create mode 100644 Documentation/rust/arch-support.rst
 create mode 100644 Documentation/rust/coding-guidelines.rst
 create mode 100644 Documentation/rust/general-information.rst
 create mode 100644 Documentation/rust/index.rst
 create mode 100644 Documentation/rust/logo.svg
 create mode 100644 Documentation/rust/quick-start.rst
 create mode 100644 arch/arm/rust/target.json
 create mode 100644 arch/arm64/rust/target.json
 create mode 100644 arch/powerpc/rust/target.json
 create mode 100644 arch/riscv/rust/rv32ima.json
 create mode 100644 arch/riscv/rust/rv32imac.json
 create mode 100644 arch/riscv/rust/rv64ima.json
 create mode 100644 arch/riscv/rust/rv64imac.json
 create mode 100644 arch/x86/rust/target.json
 create mode 100644 drivers/android/allocation.rs
 create mode 100644 drivers/android/context.rs
 create mode 100644 drivers/android/defs.rs
 create mode 100644 drivers/android/node.rs
 create mode 100644 drivers/android/process.rs
 create mode 100644 drivers/android/range_alloc.rs
 create mode 100644 drivers/android/rust_binder.rs
 create mode 100644 drivers/android/thread.rs
 create mode 100644 drivers/android/transaction.rs
 create mode 100644 drivers/gpio/gpio_pl061_rust.rs
 create mode 100644 lib/rust.h
 create mode 100644 rust/.gitignore
 create mode 100644 rust/Makefile
 create mode 100644 rust/alloc/README.md
 create mode 100644 rust/alloc/alloc.rs
 create mode 100644 rust/alloc/borrow.rs
 create mode 100644 rust/alloc/boxed.rs
 create mode 100644 rust/alloc/collections/mod.rs
 create mode 100644 rust/alloc/fmt.rs
 create mode 100644 rust/alloc/lib.rs
 create mode 100644 rust/alloc/macros.rs
 create mode 100644 rust/alloc/raw_vec.rs
 create mode 100644 rust/alloc/slice.rs
 create mode 100644 rust/alloc/str.rs
 create mode 100644 rust/alloc/string.rs
 create mode 100644 rust/alloc/vec/drain.rs
 create mode 100644 rust/alloc/vec/drain_filter.rs
 create mode 100644 rust/alloc/vec/into_iter.rs
 create mode 100644 rust/alloc/vec/is_zero.rs
 create mode 100644 rust/alloc/vec/mod.rs
 create mode 100644 rust/alloc/vec/partial_eq.rs
 create mode 100644 rust/alloc/vec/set_len_on_drop.rs
 create mode 100644 rust/alloc/vec/spec_extend.rs
 create mode 100644 rust/bindgen_parameters
 create mode 100644 rust/build_error.rs
 create mode 100644 rust/compiler_builtins.rs
 create mode 100644 rust/exports.c
 create mode 100644 rust/helpers.c
 create mode 100644 rust/kernel/allocator.rs
 create mode 100644 rust/kernel/amba.rs
 create mode 100644 rust/kernel/bindings.rs
 create mode 100644 rust/kernel/bindings_helper.h
 create mode 100644 rust/kernel/buffer.rs
 create mode 100644 rust/kernel/build_assert.rs
 create mode 100644 rust/kernel/c_types.rs
 create mode 100644 rust/kernel/chrdev.rs
 create mode 100644 rust/kernel/clk.rs
 create mode 100644 rust/kernel/cred.rs
 create mode 100644 rust/kernel/device.rs
 create mode 100644 rust/kernel/driver.rs
 create mode 100644 rust/kernel/error.rs
 create mode 100644 rust/kernel/file.rs
 create mode 100644 rust/kernel/file_operations.rs
 create mode 100644 rust/kernel/gpio.rs
 create mode 100644 rust/kernel/io_buffer.rs
 create mode 100644 rust/kernel/io_mem.rs
 create mode 100644 rust/kernel/iov_iter.rs
 create mode 100644 rust/kernel/irq.rs
 create mode 100644 rust/kernel/lib.rs
 create mode 100644 rust/kernel/linked_list.rs
 create mode 100644 rust/kernel/miscdev.rs
 create mode 100644 rust/kernel/mm.rs
 create mode 100644 rust/kernel/module_param.rs
 create mode 100644 rust/kernel/of.rs
 create mode 100644 rust/kernel/pages.rs
 create mode 100644 rust/kernel/platform.rs
 create mode 100644 rust/kernel/power.rs
 create mode 100644 rust/kernel/prelude.rs
 create mode 100644 rust/kernel/print.rs
 create mode 100644 rust/kernel/random.rs
 create mode 100644 rust/kernel/raw_list.rs
 create mode 100644 rust/kernel/rbtree.rs
 create mode 100644 rust/kernel/revocable.rs
 create mode 100644 rust/kernel/security.rs
 create mode 100644 rust/kernel/static_assert.rs
 create mode 100644 rust/kernel/std_vendor.rs
 create mode 100644 rust/kernel/str.rs
 create mode 100644 rust/kernel/sync/arc.rs
 create mode 100644 rust/kernel/sync/condvar.rs
 create mode 100644 rust/kernel/sync/guard.rs
 create mode 100644 rust/kernel/sync/locked_by.rs
 create mode 100644 rust/kernel/sync/mod.rs
 create mode 100644 rust/kernel/sync/mutex.rs
 create mode 100644 rust/kernel/sync/revocable_mutex.rs
 create mode 100644 rust/kernel/sync/rwsem.rs
 create mode 100644 rust/kernel/sync/seqlock.rs
 create mode 100644 rust/kernel/sync/spinlock.rs
 create mode 100644 rust/kernel/sysctl.rs
 create mode 100644 rust/kernel/task.rs
 create mode 100644 rust/kernel/types.rs
 create mode 100644 rust/kernel/user_ptr.rs
 create mode 100644 rust/macros/helpers.rs
 create mode 100644 rust/macros/lib.rs
 create mode 100644 rust/macros/module.rs
 create mode 100644 samples/rust/Kconfig
 create mode 100644 samples/rust/Makefile
 create mode 100644 samples/rust/rust_chrdev.rs
 create mode 100644 samples/rust/rust_minimal.rs
 create mode 100644 samples/rust/rust_miscdev.rs
 create mode 100644 samples/rust/rust_module_parameters.rs
 create mode 100644 samples/rust/rust_platform.rs
 create mode 100644 samples/rust/rust_print.rs
 create mode 100644 samples/rust/rust_random.rs
 create mode 100644 samples/rust/rust_semaphore.rs
 create mode 100644 samples/rust/rust_semaphore_c.c
 create mode 100644 samples/rust/rust_stack_probing.rs
 create mode 100644 samples/rust/rust_sync.rs
 create mode 100755 scripts/generate_rust_analyzer.py
 create mode 100755 scripts/is_rust_module.sh
 create mode 100644 scripts/rust-is-available-bindgen-libclang.h
 create mode 100755 scripts/rust-is-available.sh

base-commit: dfd42facf1e4ada021b939b4e19c935dcdd55566

Signature · 1 line
2.35.1
author maintainer
#1 lore raw

PATCH v4 1/20 kallsyms: support "big" kernel symbols

Rust symbols can become quite long due to namespacing introduced by modules, types, traits, generics, etc.

Increasing to 255 is not enough in some cases, and therefore we need to introduce longer lengths to the symbol table.

In order to avoid increasing all lengths to 2 bytes (since most of them are small, including many Rust ones), we use ULEB128 to keep smaller symbols in 1 byte, with the rest in 2 bytes.

---
 kernel/kallsyms.c  | 26 ++++++++++++++++++++++----
 scripts/kallsyms.c | 29 ++++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 7 deletions(-)
kernel/kallsyms.c +22 -4
index 951c93216fc4..57213e1d2349 100644
@@ -69,12 +69,20 @@ static unsigned int kallsyms_expand_symbol(unsigned int off,
 	data = &kallsyms_names[off];
 	len = *data;
 	data++;
+	off++;
+
+	/* If MSB is 1, it is a "big" symbol, so needs an additional byte. */
+	if ((len & 0x80) != 0) {
+		len = (len & 0x7F) | (*data << 7);
+		data++;
+		off++;
+	}
 
 	/*
 	 * Update the offset to return the offset for the next symbol on
 	 * the compressed stream.
 	 */
-	off += len + 1;
+	off += len;
 
 	/*
 	 * For every byte on the compressed symbol data, copy the table
@@ -127,7 +135,7 @@ static char kallsyms_get_symbol_type(unsigned int off)
 static unsigned int get_symbol_offset(unsigned long pos)
 {
 	const u8 *name;
-	int i;
+	int i, len;
 
 	/*
 	 * Use the closest marker we have. We have markers every 256 positions,
@@ -141,8 +149,18 @@ static unsigned int get_symbol_offset(unsigned long pos)
 	 * so we just need to add the len to the current pointer for every
 	 * symbol we wish to skip.
 	 */
-	for (i = 0; i < (pos & 0xFF); i++)
-		name = name + (*name) + 1;
+	for (i = 0; i < (pos & 0xFF); i++) {
+		len = *name;
+
+		/*
+		 * If MSB is 1, it is a "big" symbol, so we need to look into
+		 * the next byte (and skip it, too).
+		 */
+		if ((len & 0x80) != 0)
+			len = ((len & 0x7F) | (name[1] << 7)) + 1;
+
+		name = name + len + 1;
+	}
 
 	return name - kallsyms_names;
 }
scripts/kallsyms.c +26 -3
index 54ad86d13784..79b11bb7f07d 100644
@@ -470,12 +470,35 @@ static void write_src(void)
 		if ((i & 0xFF) == 0)
 			markers[i >> 8] = off;
 
-		printf("\t.byte 0x%02x", table[i]->len);
+		/* There cannot be any symbol of length zero. */
+		if (table[i]->len == 0) {
+			fprintf(stderr, "kallsyms failure: "
+				"unexpected zero symbol length\n");
+			exit(EXIT_FAILURE);
+		}
+
+		/* Only lengths that fit in up-to-two-byte ULEB128 are supported. */
+		if (table[i]->len > 0x3FFF) {
+			fprintf(stderr, "kallsyms failure: "
+				"unexpected huge symbol length\n");
+			exit(EXIT_FAILURE);
+		}
+
+		/* Encode length with ULEB128. */
+		if (table[i]->len <= 0x7F) {
+			/* Most symbols use a single byte for the length. */
+			printf("\t.byte 0x%02x", table[i]->len);
+			off += table[i]->len + 1;
+		} else {
+			/* "Big" symbols use two bytes. */
+			printf("\t.byte 0x%02x, 0x%02x",
+				(table[i]->len & 0x7F) | 0x80,
+				(table[i]->len >> 7) & 0x7F);
+			off += table[i]->len + 2;
+		}
 		for (k = 0; k < table[i]->len; k++)
 			printf(", 0x%02x", table[i]->sym[k]);
 		printf("\n");
-
-		off += table[i]->len + 1;
 	}
 	printf("\n");
 
Signature · 1 line
2.35.1
author maintainer
#2 lore raw

PATCH v4 2/20 kallsyms: increase maximum kernel symbol length to 512

In reply to Miguel Ojeda

Rust symbols can become quite long due to namespacing introduced by modules, types, traits, generics, etc. For instance, the following code:

    pub mod my_module {
        pub struct MyType;
        pub struct MyGenericType<T>(T);

        pub trait MyTrait {
            fn my_method() -> u32;
        }

        impl MyTrait for MyGenericType<MyType> {
            fn my_method() -> u32 {
                42
            }
        }
    }

generates a symbol of length 96 when using the upcoming v0 mangling scheme:

_RNvXNtCshGpAVYOtgW1_7example9my_moduleINtB2_13MyGenericTypeNtB2_6MyTypeENtB2_7MyTrait9my_method

At the moment, Rust symbols may reach up to 300 in length. Setting 512 as the maximum seems like a reasonable choice to keep some headroom.

---
 include/linux/kallsyms.h            | 2 +-
 kernel/livepatch/core.c             | 4 ++--
 scripts/kallsyms.c                  | 2 +-
 tools/include/linux/kallsyms.h      | 2 +-
 tools/lib/perf/include/perf/event.h | 2 +-
 tools/lib/symbol/kallsyms.h         | 2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)
include/linux/kallsyms.h +1 -1
index 4176c7eca7b5..5fb17dd4b6fa 100644
@@ -15,7 +15,7 @@
 
 #include <asm/sections.h>
 
-#define KSYM_NAME_LEN 128
+#define KSYM_NAME_LEN 512
 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
 			(KSYM_NAME_LEN - 1) + \
 			2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
kernel/livepatch/core.c +2 -2
index 585494ec464f..01bfab7fe7c0 100644
@@ -213,7 +213,7 @@ static int klp_resolve_symbols(Elf64_Shdr *sechdrs, const char *strtab,
 	 * we use the smallest/strictest upper bound possible (56, based on
 	 * the current definition of MODULE_NAME_LEN) to prevent overflows.
 	 */
-	BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128);
+	BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 512);
 
 	relas = (Elf_Rela *) relasec->sh_addr;
 	/* For each rela in this klp relocation section */
@@ -227,7 +227,7 @@ static int klp_resolve_symbols(Elf64_Shdr *sechdrs, const char *strtab,
 
 		/* Format: .klp.sym.sym_objname.sym_name,sympos */
 		cnt = sscanf(strtab + sym->st_name,
-			     ".klp.sym.%55[^.].%127[^,],%lu",
+			     ".klp.sym.%55[^.].%511[^,],%lu",
 			     sym_objname, sym_name, &sympos);
 		if (cnt != 3) {
 			pr_err("symbol %s has an incorrectly formatted name\n",
scripts/kallsyms.c +1 -1
index 79b11bb7f07d..72ba0fe4e43b 100644
@@ -27,7 +27,7 @@
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
-#define KSYM_NAME_LEN		128
+#define KSYM_NAME_LEN		512
 
 struct sym_entry {
 	unsigned long long addr;
tools/include/linux/kallsyms.h +1 -1
index efb6c3f5f2a9..5a37ccbec54f 100644
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
-#define KSYM_NAME_LEN 128
+#define KSYM_NAME_LEN 512
 
 struct module;
 
tools/lib/perf/include/perf/event.h +1 -1
index 75ee385fb078..acc4fa065ec7 100644
@@ -95,7 +95,7 @@ struct perf_record_throttle {
 };
 
 #ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 256
+#define KSYM_NAME_LEN 512
 #endif
 
 struct perf_record_ksymbol {
tools/lib/symbol/kallsyms.h +1 -1
index 72ab9870454b..542f9b059c3b 100644
@@ -7,7 +7,7 @@
 #include <linux/types.h>
 
 #ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 256
+#define KSYM_NAME_LEN 512
 #endif
 
 static inline u8 kallsyms2elf_binding(char type)
Signature · 1 line
2.35.1
maintainer Tested-by Acked-by on v4 2/20
#3 lore raw

Re: [PATCH v4 02/20] kallsyms: increase maximum kernel symbol length to 512

Quoted 27 lines · Miguel Ojeda

Rust symbols can become quite long due to namespacing introduced by modules, types, traits, generics, etc. For instance, the following code:

    pub mod my_module {
        pub struct MyType;
        pub struct MyGenericType<T>(T);

        pub trait MyTrait {
            fn my_method() -> u32;
        }

        impl MyTrait for MyGenericType<MyType> {
            fn my_method() -> u32 {
                42
            }
        }
    }

generates a symbol of length 96 when using the upcoming v0 mangling scheme:

_RNvXNtCshGpAVYOtgW1_7example9my_moduleINtB2_13MyGenericTypeNtB2_6MyTypeENtB2_7MyTrait9my_method

At the moment, Rust symbols may reach up to 300 in length. Setting 512 as the maximum seems like a reasonable choice to keep some headroom.

Quoted 9 lines

The livepatch selftest still pass. Feel free to add:

Best Regards,
Petr

author maintainer
#5 lore raw

PATCH v4 3/20 kallsyms: use the correct buffer size for symbols

In reply to Miguel Ojeda

From: Boqun Feng <[email protected]>

The buffered name size should be larger than KSYM_NAME_LEN, otherwise we cannot tell whether the size of a symbol name is too long.

---
 scripts/kallsyms.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
scripts/kallsyms.c +6 -3
index 72ba0fe4e43b..0e37c19d84af 100644
@@ -27,6 +27,9 @@
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
+#define _stringify_1(x)	#x
+#define _stringify(x)	_stringify_1(x)
+
 #define KSYM_NAME_LEN		512
 
 struct sym_entry {
@@ -197,15 +200,15 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
 
 static struct sym_entry *read_symbol(FILE *in)
 {
-	char name[500], type;
+	char name[KSYM_NAME_LEN+1], type;
 	unsigned long long addr;
 	unsigned int len;
 	struct sym_entry *sym;
 	int rc;
 
-	rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name);
+	rc = fscanf(in, "%llx %c %" _stringify(KSYM_NAME_LEN) "s\n", &addr, &type, name);
 	if (rc != 3) {
-		if (rc != EOF && fgets(name, 500, in) == NULL)
+		if (rc != EOF && fgets(name, KSYM_NAME_LEN + 1, in) == NULL)
 			fprintf(stderr, "Read error or end of file.\n");
 		return NULL;
 	}
Signature · 1 line
2.35.1
author maintainer
#6 lore raw

PATCH v4 4/20 rust: add C helpers

In reply to Miguel Ojeda

This source file contains forwarders to C macros and inlined functions.

---
 rust/helpers.c | 529 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 529 insertions(+)
 create mode 100644 rust/helpers.c
rust/helpers.c new file +529 -0
new file mode 100644
index 000000000000..0b6329797430
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Non-trivial C macros cannot be used in Rust. Similarly, inlined C functions
+// cannot be called either. This file explicitly creates functions ("helpers")
+// that wrap those so that they can be called from Rust.
+//
+// Even though Rust kernel modules should never use directly the bindings, some
+// of these helpers need to be exported because Rust generics and inlined
+// functions may not get their code generated in the crate where they are
+// defined. Other helpers, called from non-inline functions, may not be
+// exported, in principle. However, in general, the Rust compiler does not
+// guarantee codegen will be performed for a non-inline function either.
+// Therefore, this file exports all the helpers. In the future, this may be
+// revisited to reduce the number of exports after the compiler is informed
+// about the places codegen is required.
+//
+// All symbols are exported as GPL-only to guarantee no GPL-only feature is
+// accidentally exposed.
+
+#include <linux/bug.h>
+#include <linux/build_bug.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/sched/signal.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+#include <linux/uio.h>
+#include <linux/errname.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/security.h>
+#include <asm/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/amba/bus.h>
+#include <linux/of_device.h>
+
+__noreturn void rust_helper_BUG(void)
+{
+	BUG();
+}
+EXPORT_SYMBOL_GPL(rust_helper_BUG);
+
+void rust_helper_clk_disable_unprepare(struct clk *clk)
+{
+	return clk_disable_unprepare(clk);
+}
+EXPORT_SYMBOL_GPL(rust_helper_clk_disable_unprepare);
+
+int rust_helper_clk_prepare_enable(struct clk *clk)
+{
+	return clk_prepare_enable(clk);
+}
+EXPORT_SYMBOL_GPL(rust_helper_clk_prepare_enable);
+
+unsigned long rust_helper_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	return copy_from_user(to, from, n);
+}
+EXPORT_SYMBOL_GPL(rust_helper_copy_from_user);
+
+unsigned long rust_helper_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	return copy_to_user(to, from, n);
+}
+EXPORT_SYMBOL_GPL(rust_helper_copy_to_user);
+
+unsigned long rust_helper_clear_user(void __user *to, unsigned long n)
+{
+	return clear_user(to, n);
+}
+EXPORT_SYMBOL_GPL(rust_helper_clear_user);
+
+void __iomem *rust_helper_ioremap(resource_size_t offset, unsigned long size)
+{
+	return ioremap(offset, size);
+}
+EXPORT_SYMBOL_GPL(rust_helper_ioremap);
+
+u8 rust_helper_readb(const volatile void __iomem *addr)
+{
+	return readb(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readb);
+
+u16 rust_helper_readw(const volatile void __iomem *addr)
+{
+	return readw(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readw);
+
+u32 rust_helper_readl(const volatile void __iomem *addr)
+{
+	return readl(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readl);
+
+#ifdef CONFIG_64BIT
+u64 rust_helper_readq(const volatile void __iomem *addr)
+{
+	return readq(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readq);
+#endif
+
+void rust_helper_writeb(u8 value, volatile void __iomem *addr)
+{
+	writeb(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writeb);
+
+void rust_helper_writew(u16 value, volatile void __iomem *addr)
+{
+	writew(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writew);
+
+void rust_helper_writel(u32 value, volatile void __iomem *addr)
+{
+	writel(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writel);
+
+#ifdef CONFIG_64BIT
+void rust_helper_writeq(u64 value, volatile void __iomem *addr)
+{
+	writeq(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writeq);
+#endif
+
+u8 rust_helper_readb_relaxed(const volatile void __iomem *addr)
+{
+	return readb_relaxed(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readb_relaxed);
+
+u16 rust_helper_readw_relaxed(const volatile void __iomem *addr)
+{
+	return readw_relaxed(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readw_relaxed);
+
+u32 rust_helper_readl_relaxed(const volatile void __iomem *addr)
+{
+	return readl_relaxed(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readl_relaxed);
+
+#ifdef CONFIG_64BIT
+u64 rust_helper_readq_relaxed(const volatile void __iomem *addr)
+{
+	return readq_relaxed(addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_readq_relaxed);
+#endif
+
+void rust_helper_writeb_relaxed(u8 value, volatile void __iomem *addr)
+{
+        writeb_relaxed(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writeb_relaxed);
+
+void rust_helper_writew_relaxed(u16 value, volatile void __iomem *addr)
+{
+        writew_relaxed(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writew_relaxed);
+
+void rust_helper_writel_relaxed(u32 value, volatile void __iomem *addr)
+{
+        writel_relaxed(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writel_relaxed);
+
+#ifdef CONFIG_64BIT
+void rust_helper_writeq_relaxed(u64 value, volatile void __iomem *addr)
+{
+        writeq_relaxed(value, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writeq_relaxed);
+#endif
+void rust_helper___spin_lock_init(spinlock_t *lock, const char *name,
+				  struct lock_class_key *key)
+{
+#ifdef CONFIG_DEBUG_SPINLOCK
+	__spin_lock_init(lock, name, key);
+#else
+	spin_lock_init(lock);
+#endif
+}
+EXPORT_SYMBOL_GPL(rust_helper___spin_lock_init);
+
+void rust_helper_spin_lock(spinlock_t *lock)
+{
+	spin_lock(lock);
+}
+EXPORT_SYMBOL_GPL(rust_helper_spin_lock);
+
+void rust_helper_spin_unlock(spinlock_t *lock)
+{
+	spin_unlock(lock);
+}
+EXPORT_SYMBOL_GPL(rust_helper_spin_unlock);
+
+unsigned long rust_helper_spin_lock_irqsave(spinlock_t *lock)
+{
+	unsigned long flags;
+	spin_lock_irqsave(lock, flags);
+	return flags;
+}
+EXPORT_SYMBOL_GPL(rust_helper_spin_lock_irqsave);
+
+void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+	spin_unlock_irqrestore(lock, flags);
+}
+EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore);
+
+void rust_helper_init_wait(struct wait_queue_entry *wq_entry)
+{
+	init_wait(wq_entry);
+}
+EXPORT_SYMBOL_GPL(rust_helper_init_wait);
+
+int rust_helper_signal_pending(struct task_struct *t)
+{
+	return signal_pending(t);
+}
+EXPORT_SYMBOL_GPL(rust_helper_signal_pending);
+
+struct page *rust_helper_alloc_pages(gfp_t gfp_mask, unsigned int order)
+{
+	return alloc_pages(gfp_mask, order);
+}
+EXPORT_SYMBOL_GPL(rust_helper_alloc_pages);
+
+void *rust_helper_kmap(struct page *page)
+{
+	return kmap(page);
+}
+EXPORT_SYMBOL_GPL(rust_helper_kmap);
+
+void rust_helper_kunmap(struct page *page)
+{
+	return kunmap(page);
+}
+EXPORT_SYMBOL_GPL(rust_helper_kunmap);
+
+int rust_helper_cond_resched(void)
+{
+	return cond_resched();
+}
+EXPORT_SYMBOL_GPL(rust_helper_cond_resched);
+
+size_t rust_helper_copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
+{
+	return copy_from_iter(addr, bytes, i);
+}
+EXPORT_SYMBOL_GPL(rust_helper_copy_from_iter);
+
+size_t rust_helper_copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
+{
+	return copy_to_iter(addr, bytes, i);
+}
+EXPORT_SYMBOL_GPL(rust_helper_copy_to_iter);
+
+bool rust_helper_IS_ERR(__force const void *ptr)
+{
+	return IS_ERR(ptr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_IS_ERR);
+
+long rust_helper_PTR_ERR(__force const void *ptr)
+{
+	return PTR_ERR(ptr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR);
+
+const char *rust_helper_errname(int err)
+{
+	return errname(err);
+}
+EXPORT_SYMBOL_GPL(rust_helper_errname);
+
+void rust_helper_mutex_lock(struct mutex *lock)
+{
+	mutex_lock(lock);
+}
+EXPORT_SYMBOL_GPL(rust_helper_mutex_lock);
+
+void rust_helper_amba_set_drvdata(struct amba_device *dev, void *data)
+{
+	amba_set_drvdata(dev, data);
+}
+EXPORT_SYMBOL_GPL(rust_helper_amba_set_drvdata);
+
+void *rust_helper_amba_get_drvdata(struct amba_device *dev)
+{
+	return amba_get_drvdata(dev);
+}
+EXPORT_SYMBOL_GPL(rust_helper_amba_get_drvdata);
+
+void *
+rust_helper_platform_get_drvdata(const struct platform_device *pdev)
+{
+	return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL_GPL(rust_helper_platform_get_drvdata);
+
+void
+rust_helper_platform_set_drvdata(struct platform_device *pdev,
+				 void *data)
+{
+	return platform_set_drvdata(pdev, data);
+}
+EXPORT_SYMBOL_GPL(rust_helper_platform_set_drvdata);
+
+refcount_t rust_helper_REFCOUNT_INIT(int n)
+{
+	return (refcount_t)REFCOUNT_INIT(n);
+}
+EXPORT_SYMBOL_GPL(rust_helper_REFCOUNT_INIT);
+
+void rust_helper_refcount_inc(refcount_t *r)
+{
+	refcount_inc(r);
+}
+EXPORT_SYMBOL_GPL(rust_helper_refcount_inc);
+
+bool rust_helper_refcount_dec_and_test(refcount_t *r)
+{
+	return refcount_dec_and_test(r);
+}
+EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test);
+
+void rust_helper_rb_link_node(struct rb_node *node, struct rb_node *parent,
+			      struct rb_node **rb_link)
+{
+	rb_link_node(node, parent, rb_link);
+}
+EXPORT_SYMBOL_GPL(rust_helper_rb_link_node);
+
+struct task_struct *rust_helper_get_current(void)
+{
+	return current;
+}
+EXPORT_SYMBOL_GPL(rust_helper_get_current);
+
+void rust_helper_get_task_struct(struct task_struct * t)
+{
+	get_task_struct(t);
+}
+EXPORT_SYMBOL_GPL(rust_helper_get_task_struct);
+
+void rust_helper_put_task_struct(struct task_struct * t)
+{
+	put_task_struct(t);
+}
+EXPORT_SYMBOL_GPL(rust_helper_put_task_struct);
+
+int rust_helper_security_binder_set_context_mgr(const struct cred *mgr)
+{
+	return security_binder_set_context_mgr(mgr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_set_context_mgr);
+
+int rust_helper_security_binder_transaction(const struct cred *from,
+					    const struct cred *to)
+{
+	return security_binder_transaction(from, to);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_transaction);
+
+int rust_helper_security_binder_transfer_binder(const struct cred *from,
+						const struct cred *to)
+{
+	return security_binder_transfer_binder(from, to);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_binder);
+
+int rust_helper_security_binder_transfer_file(const struct cred *from,
+					      const struct cred *to,
+					      struct file *file)
+{
+	return security_binder_transfer_file(from, to, file);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_file);
+
+void rust_helper_rcu_read_lock(void)
+{
+	rcu_read_lock();
+}
+EXPORT_SYMBOL_GPL(rust_helper_rcu_read_lock);
+
+void rust_helper_rcu_read_unlock(void)
+{
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(rust_helper_rcu_read_unlock);
+
+void rust_helper_synchronize_rcu(void)
+{
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(rust_helper_synchronize_rcu);
+
+void *rust_helper_dev_get_drvdata(struct device *dev)
+{
+	return dev_get_drvdata(dev);
+}
+EXPORT_SYMBOL_GPL(rust_helper_dev_get_drvdata);
+
+const char *rust_helper_dev_name(const struct device *dev)
+{
+	return dev_name(dev);
+}
+EXPORT_SYMBOL_GPL(rust_helper_dev_name);
+
+void rust_helper___seqcount_init(seqcount_t *s, const char *name,
+				 struct lock_class_key *key)
+{
+	__seqcount_init(s, name, key);
+}
+EXPORT_SYMBOL_GPL(rust_helper___seqcount_init);
+
+unsigned rust_helper_read_seqcount_begin(seqcount_t *s)
+{
+	return read_seqcount_begin(s);
+}
+EXPORT_SYMBOL_GPL(rust_helper_read_seqcount_begin);
+
+int rust_helper_read_seqcount_retry(seqcount_t *s, unsigned start)
+{
+	return read_seqcount_retry(s, start);
+}
+EXPORT_SYMBOL_GPL(rust_helper_read_seqcount_retry);
+
+void rust_helper_write_seqcount_begin(seqcount_t *s)
+{
+	do_write_seqcount_begin(s);
+}
+EXPORT_SYMBOL_GPL(rust_helper_write_seqcount_begin);
+
+void rust_helper_write_seqcount_end(seqcount_t *s)
+{
+	do_write_seqcount_end(s);
+}
+EXPORT_SYMBOL_GPL(rust_helper_write_seqcount_end);
+
+void rust_helper_irq_set_handler_locked(struct irq_data *data,
+					irq_flow_handler_t handler)
+{
+	irq_set_handler_locked(data, handler);
+}
+EXPORT_SYMBOL_GPL(rust_helper_irq_set_handler_locked);
+
+void *rust_helper_irq_data_get_irq_chip_data(struct irq_data *d)
+{
+	return irq_data_get_irq_chip_data(d);
+}
+EXPORT_SYMBOL_GPL(rust_helper_irq_data_get_irq_chip_data);
+
+struct irq_chip *rust_helper_irq_desc_get_chip(struct irq_desc *desc)
+{
+	return irq_desc_get_chip(desc);
+}
+EXPORT_SYMBOL_GPL(rust_helper_irq_desc_get_chip);
+
+void *rust_helper_irq_desc_get_handler_data(struct irq_desc *desc)
+{
+	return irq_desc_get_handler_data(desc);
+}
+EXPORT_SYMBOL_GPL(rust_helper_irq_desc_get_handler_data);
+
+void rust_helper_chained_irq_enter(struct irq_chip *chip,
+				   struct irq_desc *desc)
+{
+	chained_irq_enter(chip, desc);
+}
+EXPORT_SYMBOL_GPL(rust_helper_chained_irq_enter);
+
+void rust_helper_chained_irq_exit(struct irq_chip *chip,
+				   struct irq_desc *desc)
+{
+	chained_irq_exit(chip, desc);
+}
+EXPORT_SYMBOL_GPL(rust_helper_chained_irq_exit);
+
+const struct cred *rust_helper_get_cred(const struct cred *cred)
+{
+	return get_cred(cred);
+}
+EXPORT_SYMBOL_GPL(rust_helper_get_cred);
+
+void rust_helper_put_cred(const struct cred *cred) {
+	put_cred(cred);
+}
+EXPORT_SYMBOL_GPL(rust_helper_put_cred);
+
+const struct of_device_id *rust_helper_of_match_device(
+		const struct of_device_id *matches, const struct device *dev)
+{
+	return of_match_device(matches, dev);
+}
+EXPORT_SYMBOL_GPL(rust_helper_of_match_device);
+
+/* We use bindgen's --size_t-is-usize option to bind the C size_t type
+ * as the Rust usize type, so we can use it in contexts where Rust
+ * expects a usize like slice (array) indices. usize is defined to be
+ * the same as C's uintptr_t type (can hold any pointer) but not
+ * necessarily the same as size_t (can hold the size of any single
+ * object). Most modern platforms use the same concrete integer type for
+ * both of them, but in case we find ourselves on a platform where
+ * that's not true, fail early instead of risking ABI or
+ * integer-overflow issues.
+ *
+ * If your platform fails this assertion, it means that you are in
+ * danger of integer-overflow bugs (even if you attempt to remove
+ * --size_t-is-usize). It may be easiest to change the kernel ABI on
+ * your platform such that size_t matches uintptr_t (i.e., to increase
+ * size_t, because uintptr_t has to be at least as big as size_t).
+*/
+static_assert(
+	sizeof(size_t) == sizeof(uintptr_t) &&
+	__alignof__(size_t) == __alignof__(uintptr_t),
+	"Rust code expects C size_t to match Rust usize"
+);
Signature · 1 line
2.35.1
author maintainer
#7 lore raw

PATCH v4 5/20 rust: add `compiler_builtins` crate

In reply to Miguel Ojeda

Rust provides compiler_builtins as a port of LLVM's compiler-rt. Since we do not need the vast majority of them, we avoid the dependency by providing our own crate.

---
 rust/compiler_builtins.rs | 57 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 rust/compiler_builtins.rs
rust/compiler_builtins.rs new file +57 -0
new file mode 100644
index 000000000000..80ca4c0dcd24
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Our own `compiler_builtins`.
+//!
+//! Rust provides [`compiler_builtins`] as a port of LLVM's [`compiler-rt`].
+//! Since we do not need the vast majority of them, we avoid the dependency
+//! by providing this file.
+//!
+//! At the moment, some builtins are required that should not be. For instance,
+//! [`core`] has 128-bit integers functionality which we should not be compiling
+//! in. We will work with upstream [`core`] to provide feature flags to disable
+//! the parts we do not need. For the moment, we define them to [`panic!`] at
+//! runtime for simplicity to catch mistakes, instead of performing surgery
+//! on `core.o`.
+//!
+//! In any case, all these symbols are weakened to ensure we do not override
+//! those that may be provided by the rest of the kernel.
+//!
+//! [`compiler_builtins`]: https://github.com/rust-lang/compiler-builtins
+//! [`compiler-rt`]: https://compiler-rt.llvm.org/
+
+#![feature(compiler_builtins)]
+#![compiler_builtins]
+#![no_builtins]
+#![no_std]
+
+macro_rules! define_panicking_intrinsics(
+    ($reason: tt, { $($ident: ident, )* }) => {
+        $(
+            #[doc(hidden)]
+            #[no_mangle]
+            pub extern "C" fn $ident() {
+                panic!($reason);
+            }
+        )*
+    }
+);
+
+define_panicking_intrinsics!("`i128` should not be used", {
+    __ashrti3,
+    __muloti4,
+    __multi3,
+});
+
+define_panicking_intrinsics!("`u128` should not be used", {
+    __ashlti3,
+    __lshrti3,
+    __udivmodti4,
+    __udivti3,
+    __umodti3,
+});
+
+#[cfg(target_arch = "arm")]
+define_panicking_intrinsics!("`u64` division/modulo should not be used", {
+    __aeabi_uldivmod,
+    __mulodi4,
+});
Signature · 1 line
2.35.1
author maintainer
#8 lore raw

PATCH v4 6/20 rust: add `alloc` crate

In reply to Miguel Ojeda

This crate is a subset of the Rust standard library alloc, with some additions on top.

This is needed because upstream support for fallible allocations is a work in progress (i.e. the try_* versions of methods which return a Result instead of panicking).

Having the library in-tree also gives us a bit more freedom to experiment with new interfaces and allows us to iterate quickly.

Eventually, the goal is to have everything the kernel needs in upstream alloc and drop it from the kernel tree.

---
 rust/alloc/README.md              |   32 +
 rust/alloc/alloc.rs               |  427 ++++
 rust/alloc/borrow.rs              |  498 +++++
 rust/alloc/boxed.rs               | 1847 ++++++++++++++++
 rust/alloc/collections/mod.rs     |  156 ++
 rust/alloc/fmt.rs                 |  601 ++++++
 rust/alloc/lib.rs                 |  217 ++
 rust/alloc/macros.rs              |  126 ++
 rust/alloc/raw_vec.rs             |  549 +++++
 rust/alloc/slice.rs               | 1279 +++++++++++
 rust/alloc/str.rs                 |  624 ++++++
 rust/alloc/string.rs              | 2864 ++++++++++++++++++++++++
 rust/alloc/vec/drain.rs           |  159 ++
 rust/alloc/vec/drain_filter.rs    |  145 ++
 rust/alloc/vec/into_iter.rs       |  356 +++
 rust/alloc/vec/is_zero.rs         |  106 +
 rust/alloc/vec/mod.rs             | 3359 +++++++++++++++++++++++++++++
 rust/alloc/vec/partial_eq.rs      |   49 +
 rust/alloc/vec/set_len_on_drop.rs |   30 +
 rust/alloc/vec/spec_extend.rs     |  172 ++
 20 files changed, 13596 insertions(+)
 create mode 100644 rust/alloc/README.md
 create mode 100644 rust/alloc/alloc.rs
 create mode 100644 rust/alloc/borrow.rs
 create mode 100644 rust/alloc/boxed.rs
 create mode 100644 rust/alloc/collections/mod.rs
 create mode 100644 rust/alloc/fmt.rs
 create mode 100644 rust/alloc/lib.rs
 create mode 100644 rust/alloc/macros.rs
 create mode 100644 rust/alloc/raw_vec.rs
 create mode 100644 rust/alloc/slice.rs
 create mode 100644 rust/alloc/str.rs
 create mode 100644 rust/alloc/string.rs
 create mode 100644 rust/alloc/vec/drain.rs
 create mode 100644 rust/alloc/vec/drain_filter.rs
 create mode 100644 rust/alloc/vec/into_iter.rs
 create mode 100644 rust/alloc/vec/is_zero.rs
 create mode 100644 rust/alloc/vec/mod.rs
 create mode 100644 rust/alloc/vec/partial_eq.rs
 create mode 100644 rust/alloc/vec/set_len_on_drop.rs
 create mode 100644 rust/alloc/vec/spec_extend.rs
rust/alloc/README.md new file +32 -0
new file mode 100644
index 000000000000..a1bcc2cef0e6
@@ -0,0 +1,32 @@
+# `alloc`
+
+These source files come from the Rust standard library, hosted in
+the https://github.com/rust-lang/rust repository. For copyright
+details, see https://github.com/rust-lang/rust/blob/master/COPYRIGHT.
+
+Please note that these files should be kept as close as possible to
+upstream. In general, only additions should be performed (e.g. new
+methods). Eventually, changes should make it into upstream so that,
+at some point, this fork can be dropped from the kernel tree.
+
+
+## Rationale
+
+On one hand, kernel folks wanted to keep `alloc` in-tree to have more
+freedom in both workflow and actual features if actually needed
+(e.g. receiver types if we ended up using them), which is reasonable.
+
+On the other hand, Rust folks wanted to keep `alloc` as close as
+upstream as possible and avoid as much divergence as possible, which
+is also reasonable.
+
+We agreed on a middle-ground: we would keep a subset of `alloc`
+in-tree that would be as small and as close as possible to upstream.
+Then, upstream can start adding the functions that we add to `alloc`
+etc., until we reach a point where the kernel already knows exactly
+what it needs in `alloc` and all the new methods are merged into
+upstream, so that we can drop `alloc` from the kernel tree and go back
+to using the upstream one.
+
+By doing this, the kernel can go a bit faster now, and Rust can
+slowly incorporate and discuss the changes as needed.
rust/alloc/alloc.rs new file +427 -0

427 lines not on this page · raw message

rust/alloc/borrow.rs new file +498 -0

498 lines not on this page · raw message

rust/alloc/boxed.rs new file +1847 -0

1,847 lines not on this page · raw message

rust/alloc/collections/mod.rs new file +156 -0

156 lines not on this page · raw message

rust/alloc/fmt.rs new file +601 -0

40 lines not on this page · raw message

rust/alloc/lib.rs new file +217 -0

217 lines not on this page · raw message

rust/alloc/macros.rs new file +126 -0

126 lines not on this page · raw message

rust/alloc/raw_vec.rs new file +549 -0

549 lines not on this page · raw message

rust/alloc/slice.rs new file +1279 -0

1,279 lines not on this page · raw message

rust/alloc/str.rs new file +624 -0

624 lines not on this page · raw message

rust/alloc/string.rs new file +2864 -0

2,864 lines not on this page · raw message

rust/alloc/vec/drain.rs new file +159 -0

159 lines not on this page · raw message

rust/alloc/vec/drain_filter.rs new file +145 -0

145 lines not on this page · raw message

rust/alloc/vec/into_iter.rs new file +356 -0

356 lines not on this page · raw message

rust/alloc/vec/is_zero.rs new file +106 -0

106 lines not on this page · raw message

rust/alloc/vec/mod.rs new file +3359 -0

3,359 lines not on this page · raw message

rust/alloc/vec/partial_eq.rs new file +49 -0

49 lines not on this page · raw message

rust/alloc/vec/set_len_on_drop.rs new file +30 -0
new file mode 100644
index 000000000000..448bf5076a0b

Lines of this file are not shown. View the raw message.

rust/alloc/vec/spec_extend.rs new file +172 -0

172 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.35.1

Part of the diff is not shown here. View the raw message.

author maintainer
#9 lore raw

PATCH v4 7/20 rust: add `build_error` crate

In reply to Miguel Ojeda

From: Gary Guo <[email protected]>

The build_error crate provides the build_error function which is then used to provide the build_error! and the build_assert! macros.

build_assert! is intended to be used when static_assert! cannot be used, e.g. when the condition refers to generic parameters or parameters of an inline function.

---
 rust/build_error.rs | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 rust/build_error.rs
rust/build_error.rs new file +29 -0
new file mode 100644
index 000000000000..34e589149d3e
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Build-time error.
+//!
+//! This crate provides a function `build_error`, which will panic in
+//! compile-time if executed in const context, and will cause a build error
+//! if not executed at compile time and the optimizer does not optimise away the
+//! call.
+//!
+//! It is used by `build_assert!` in the kernel crate, allowing checking of
+//! conditions that could be checked statically, but could not be enforced in
+//! Rust yet (e.g. perform some checks in const functions, but those
+//! functions could still be called in the runtime).
+
+#![no_std]
+
+/// Panics if executed in const context, or triggers a build error if not.
+#[inline(never)]
+#[cold]
+#[no_mangle]
+#[track_caller]
+pub const fn build_error(msg: &'static str) -> ! {
+    panic!("{}", msg);
+}
+
+#[cfg(CONFIG_RUST_BUILD_ASSERT_WARN)]
+#[link_section = ".gnu.warning.build_error"]
+#[used]
+static BUILD_ERROR_WARNING: [u8; 45] = *b"call to build_error present after compilation";
Signature · 1 line
2.35.1
author maintainer
#10 lore raw

PATCH v4 8/20 rust: add `macros` crate

In reply to Miguel Ojeda

This crate contains all the procedural macros ("proc macros") shared by all the kernel.

Procedural macros allow to create syntax extensions. They run at compile-time and can consume as well as produce Rust syntax.

For instance, the module! macro that is used by Rust modules is implemented here. It allows to easily declare the equivalent information to the MODULE_* macros in C modules, e.g.:

    module! {
        type: RustMinimal,
        name: b"rust_minimal",
        author: b"Rust for Linux Contributors",
        description: b"Rust minimal sample",
        license: b"GPL v2",
    }
---
 rust/macros/helpers.rs |  79 ++++++
 rust/macros/lib.rs     |  94 ++++++
 rust/macros/module.rs  | 631 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 804 insertions(+)
 create mode 100644 rust/macros/helpers.rs
 create mode 100644 rust/macros/lib.rs
 create mode 100644 rust/macros/module.rs
rust/macros/helpers.rs new file +79 -0
new file mode 100644
index 000000000000..ad210563e5a6
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use proc_macro::{token_stream, Group, TokenTree};
+
+pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
+    if let Some(TokenTree::Ident(ident)) = it.next() {
+        Some(ident.to_string())
+    } else {
+        None
+    }
+}
+
+pub(crate) fn try_literal(it: &mut token_stream::IntoIter) -> Option<String> {
+    if let Some(TokenTree::Literal(literal)) = it.next() {
+        Some(literal.to_string())
+    } else {
+        None
+    }
+}
+
+pub(crate) fn try_byte_string(it: &mut token_stream::IntoIter) -> Option<String> {
+    try_literal(it).and_then(|byte_string| {
+        if byte_string.starts_with("b\"") && byte_string.ends_with('\"') {
+            Some(byte_string[2..byte_string.len() - 1].to_string())
+        } else {
+            None
+        }
+    })
+}
+
+pub(crate) fn expect_ident(it: &mut token_stream::IntoIter) -> String {
+    try_ident(it).expect("Expected Ident")
+}
+
+pub(crate) fn expect_punct(it: &mut token_stream::IntoIter) -> char {
+    if let TokenTree::Punct(punct) = it.next().expect("Reached end of token stream for Punct") {
+        punct.as_char()
+    } else {
+        panic!("Expected Punct");
+    }
+}
+
+pub(crate) fn expect_literal(it: &mut token_stream::IntoIter) -> String {
+    try_literal(it).expect("Expected Literal")
+}
+
+pub(crate) fn expect_group(it: &mut token_stream::IntoIter) -> Group {
+    if let TokenTree::Group(group) = it.next().expect("Reached end of token stream for Group") {
+        group
+    } else {
+        panic!("Expected Group");
+    }
+}
+
+pub(crate) fn expect_byte_string(it: &mut token_stream::IntoIter) -> String {
+    try_byte_string(it).expect("Expected byte string")
+}
+
+pub(crate) fn expect_end(it: &mut token_stream::IntoIter) {
+    if it.next().is_some() {
+        panic!("Expected end");
+    }
+}
+
+pub(crate) fn get_literal(it: &mut token_stream::IntoIter, expected_name: &str) -> String {
+    assert_eq!(expect_ident(it), expected_name);
+    assert_eq!(expect_punct(it), ':');
+    let literal = expect_literal(it);
+    assert_eq!(expect_punct(it), ',');
+    literal
+}
+
+pub(crate) fn get_byte_string(it: &mut token_stream::IntoIter, expected_name: &str) -> String {
+    assert_eq!(expect_ident(it), expected_name);
+    assert_eq!(expect_punct(it), ':');
+    let byte_string = expect_byte_string(it);
+    assert_eq!(expect_punct(it), ',');
+    byte_string
+}
rust/macros/lib.rs new file +94 -0

94 lines not on this page · raw message

rust/macros/module.rs new file +631 -0

631 lines not on this page · raw message

Signature · 1 line
2.35.1
author maintainer
#11 lore raw

PATCH v4 9/20 rust: add `kernel` crate's `sync` module

In reply to Miguel Ojeda

From: Wedson Almeida Filho <[email protected]>

This module contains the kernel APIs related to synchronisation that have been ported or wrapped for usage by Rust code in the kernel and is shared by all of them.

---
 include/linux/spinlock.h            |  17 +-
 rust/kernel/sync/arc.rs             | 500 ++++++++++++++++++++++++++++
 rust/kernel/sync/condvar.rs         | 138 ++++++++
 rust/kernel/sync/guard.rs           | 150 +++++++++
 rust/kernel/sync/locked_by.rs       | 112 +++++++
 rust/kernel/sync/mod.rs             | 157 +++++++++
 rust/kernel/sync/mutex.rs           | 112 +++++++
 rust/kernel/sync/revocable_mutex.rs | 184 ++++++++++
 rust/kernel/sync/rwsem.rs           | 147 ++++++++
 rust/kernel/sync/seqlock.rs         | 202 +++++++++++
 rust/kernel/sync/spinlock.rs        | 180 ++++++++++
 11 files changed, 1893 insertions(+), 6 deletions(-)
 create mode 100644 rust/kernel/sync/arc.rs
 create mode 100644 rust/kernel/sync/condvar.rs
 create mode 100644 rust/kernel/sync/guard.rs
 create mode 100644 rust/kernel/sync/locked_by.rs
 create mode 100644 rust/kernel/sync/mod.rs
 create mode 100644 rust/kernel/sync/mutex.rs
 create mode 100644 rust/kernel/sync/revocable_mutex.rs
 create mode 100644 rust/kernel/sync/rwsem.rs
 create mode 100644 rust/kernel/sync/seqlock.rs
 create mode 100644 rust/kernel/sync/spinlock.rs
include/linux/spinlock.h +11 -6
index 5c0c5174155d..a732d62dbe35 100644
@@ -326,12 +326,17 @@ static __always_inline raw_spinlock_t *spinlock_check(spinlock_t *lock)
 
 #ifdef CONFIG_DEBUG_SPINLOCK
 
-# define spin_lock_init(lock)					\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__raw_spin_lock_init(spinlock_check(lock),		\
-			     #lock, &__key, LD_WAIT_CONFIG);	\
+static inline void __spin_lock_init(spinlock_t *lock, const char *name,
+				    struct lock_class_key *key)
+{
+	__raw_spin_lock_init(spinlock_check(lock), name, key, LD_WAIT_CONFIG);
+}
+
+# define spin_lock_init(lock)			\
+do {						\
+	static struct lock_class_key __key;	\
+						\
+	__spin_lock_init(lock, #lock, &__key);	\
 } while (0)
 
 #else
rust/kernel/sync/arc.rs new file +500 -0

500 lines not on this page · raw message

rust/kernel/sync/condvar.rs new file +138 -0

138 lines not on this page · raw message

rust/kernel/sync/guard.rs new file +150 -0

150 lines not on this page · raw message

rust/kernel/sync/locked_by.rs new file +112 -0

112 lines not on this page · raw message

rust/kernel/sync/mod.rs new file +157 -0

157 lines not on this page · raw message

rust/kernel/sync/mutex.rs new file +112 -0

112 lines not on this page · raw message

rust/kernel/sync/revocable_mutex.rs new file +184 -0

184 lines not on this page · raw message

rust/kernel/sync/rwsem.rs new file +147 -0

147 lines not on this page · raw message

rust/kernel/sync/seqlock.rs new file +202 -0

202 lines not on this page · raw message

rust/kernel/sync/spinlock.rs new file +180 -0

180 lines not on this page · raw message

Signature · 1 line
2.35.1
author maintainer
#12 lore raw

PATCH v4 10/20 rust: add `kernel` crate

In reply to Miguel Ojeda

From: Wedson Almeida Filho <[email protected]>

The kernel crate currently includes all the abstractions that wrap kernel features written in C.

These abstractions call the C side of the kernel via the generated bindings with the bindgen tool. Modules developed in Rust should never call the bindings themselves.

In the future, as the abstractions grow in number, we may need to split this crate into several, possibly following a similar subdivision in subsystems as the kernel itself and/or moving the code to the actual subsystems.

---
 kernel/printk/printk.c         |   5 +-
 rust/kernel/allocator.rs       |  65 +++
 rust/kernel/amba.rs            | 259 ++++++++++++
 rust/kernel/bindings.rs        |  47 +++
 rust/kernel/bindings_helper.h  |  30 ++
 rust/kernel/buffer.rs          |  52 +++
 rust/kernel/build_assert.rs    |  80 ++++
 rust/kernel/c_types.rs         | 119 ++++++
 rust/kernel/chrdev.rs          | 209 ++++++++++
 rust/kernel/clk.rs             |  75 ++++
 rust/kernel/cred.rs            |  73 ++++
 rust/kernel/device.rs          | 554 +++++++++++++++++++++++++
 rust/kernel/driver.rs          | 440 ++++++++++++++++++++
 rust/kernel/error.rs           | 542 ++++++++++++++++++++++++
 rust/kernel/file.rs            | 147 +++++++
 rust/kernel/file_operations.rs | 734 +++++++++++++++++++++++++++++++++
 rust/kernel/gpio.rs            | 477 +++++++++++++++++++++
 rust/kernel/io_buffer.rs       | 153 +++++++
 rust/kernel/io_mem.rs          | 227 ++++++++++
 rust/kernel/iov_iter.rs        |  81 ++++
 rust/kernel/irq.rs             | 409 ++++++++++++++++++
 rust/kernel/lib.rs             | 261 ++++++++++++
 rust/kernel/linked_list.rs     | 247 +++++++++++
 rust/kernel/miscdev.rs         | 281 +++++++++++++
 rust/kernel/mm.rs              | 149 +++++++
 rust/kernel/module_param.rs    | 497 ++++++++++++++++++++++
 rust/kernel/of.rs              |  63 +++
 rust/kernel/pages.rs           | 144 +++++++
 rust/kernel/platform.rs        | 224 ++++++++++
 rust/kernel/power.rs           | 118 ++++++
 rust/kernel/prelude.rs         |  36 ++
 rust/kernel/print.rs           | 417 +++++++++++++++++++
 rust/kernel/random.rs          |  50 +++
 rust/kernel/raw_list.rs        | 361 ++++++++++++++++
 rust/kernel/rbtree.rs          | 562 +++++++++++++++++++++++++
 rust/kernel/revocable.rs       | 163 ++++++++
 rust/kernel/security.rs        |  36 ++
 rust/kernel/static_assert.rs   |  39 ++
 rust/kernel/std_vendor.rs      | 150 +++++++
 rust/kernel/str.rs             | 401 ++++++++++++++++++
 rust/kernel/sysctl.rs          | 197 +++++++++
 rust/kernel/task.rs            | 182 ++++++++
 rust/kernel/types.rs           | 486 ++++++++++++++++++++++
 rust/kernel/user_ptr.rs        | 175 ++++++++
 44 files changed, 10016 insertions(+), 1 deletion(-)
 create mode 100644 rust/kernel/allocator.rs
 create mode 100644 rust/kernel/amba.rs
 create mode 100644 rust/kernel/bindings.rs
 create mode 100644 rust/kernel/bindings_helper.h
 create mode 100644 rust/kernel/buffer.rs
 create mode 100644 rust/kernel/build_assert.rs
 create mode 100644 rust/kernel/c_types.rs
 create mode 100644 rust/kernel/chrdev.rs
 create mode 100644 rust/kernel/clk.rs
 create mode 100644 rust/kernel/cred.rs
 create mode 100644 rust/kernel/device.rs
 create mode 100644 rust/kernel/driver.rs
 create mode 100644 rust/kernel/error.rs
 create mode 100644 rust/kernel/file.rs
 create mode 100644 rust/kernel/file_operations.rs
 create mode 100644 rust/kernel/gpio.rs
 create mode 100644 rust/kernel/io_buffer.rs
 create mode 100644 rust/kernel/io_mem.rs
 create mode 100644 rust/kernel/iov_iter.rs
 create mode 100644 rust/kernel/irq.rs
 create mode 100644 rust/kernel/lib.rs
 create mode 100644 rust/kernel/linked_list.rs
 create mode 100644 rust/kernel/miscdev.rs
 create mode 100644 rust/kernel/mm.rs
 create mode 100644 rust/kernel/module_param.rs
 create mode 100644 rust/kernel/of.rs
 create mode 100644 rust/kernel/pages.rs
 create mode 100644 rust/kernel/platform.rs
 create mode 100644 rust/kernel/power.rs
 create mode 100644 rust/kernel/prelude.rs
 create mode 100644 rust/kernel/print.rs
 create mode 100644 rust/kernel/random.rs
 create mode 100644 rust/kernel/raw_list.rs
 create mode 100644 rust/kernel/rbtree.rs
 create mode 100644 rust/kernel/revocable.rs
 create mode 100644 rust/kernel/security.rs
 create mode 100644 rust/kernel/static_assert.rs
 create mode 100644 rust/kernel/std_vendor.rs
 create mode 100644 rust/kernel/str.rs
 create mode 100644 rust/kernel/sysctl.rs
 create mode 100644 rust/kernel/task.rs
 create mode 100644 rust/kernel/types.rs
 create mode 100644 rust/kernel/user_ptr.rs
kernel/printk/printk.c +4 -1
index 82abfaf3c2aa..c042386667f2 100644
@@ -392,7 +392,10 @@ static struct latched_seq clear_seq = {
 /* the maximum size of a formatted record (i.e. with prefix added per line) */
 #define CONSOLE_LOG_MAX		1024
 
-/* the maximum size allowed to be reserved for a record */
+/*
+ * The maximum size allowed to be reserved for a record.
+ * Keep in sync with rust/kernel/print.rs.
+ */
 #define LOG_LINE_MAX		(CONSOLE_LOG_MAX - PREFIX_MAX)
 
 #define LOG_LEVEL(v)		((v) & 0x07)
rust/kernel/allocator.rs new file +65 -0

65 lines not on this page · raw message

rust/kernel/amba.rs new file +259 -0

259 lines not on this page · raw message

rust/kernel/bindings.rs new file +47 -0

47 lines not on this page · raw message

rust/kernel/bindings_helper.h new file +30 -0
new file mode 100644
index 000000000000..a79f3f398b93
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/cdev.h>
+#include <linux/clk.h>
+#include <linux/errname.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/uaccess.h>
+#include <linux/uio.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <uapi/linux/android/binder.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/security.h>
+#include <asm/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/amba/bus.h>
+#include <linux/gpio/driver.h>
+
+// `bindgen` gets confused at certain things
+const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
+const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
rust/kernel/buffer.rs new file +52 -0

52 lines not on this page · raw message

rust/kernel/build_assert.rs new file +80 -0

80 lines not on this page · raw message

rust/kernel/c_types.rs new file +119 -0

119 lines not on this page · raw message

rust/kernel/chrdev.rs new file +209 -0

209 lines not on this page · raw message

rust/kernel/clk.rs new file +75 -0

75 lines not on this page · raw message

rust/kernel/cred.rs new file +73 -0

73 lines not on this page · raw message

rust/kernel/device.rs new file +554 -0

554 lines not on this page · raw message

rust/kernel/driver.rs new file +440 -0

440 lines not on this page · raw message

rust/kernel/error.rs new file +542 -0

542 lines not on this page · raw message

rust/kernel/file.rs new file +147 -0

147 lines not on this page · raw message

rust/kernel/file_operations.rs new file +734 -0

297 lines not on this page · raw message

rust/kernel/gpio.rs new file +477 -0

477 lines not on this page · raw message

rust/kernel/io_buffer.rs new file +153 -0

153 lines not on this page · raw message

rust/kernel/io_mem.rs new file +227 -0

227 lines not on this page · raw message

rust/kernel/iov_iter.rs new file +81 -0

81 lines not on this page · raw message

rust/kernel/irq.rs new file +409 -0

409 lines not on this page · raw message

rust/kernel/lib.rs new file +261 -0

261 lines not on this page · raw message

rust/kernel/linked_list.rs new file +247 -0

247 lines not on this page · raw message

rust/kernel/miscdev.rs new file +281 -0

281 lines not on this page · raw message

rust/kernel/mm.rs new file +149 -0

149 lines not on this page · raw message

rust/kernel/module_param.rs new file +497 -0

497 lines not on this page · raw message

rust/kernel/of.rs new file +63 -0

63 lines not on this page · raw message

rust/kernel/pages.rs new file +144 -0

144 lines not on this page · raw message

rust/kernel/platform.rs new file +224 -0

224 lines not on this page · raw message

rust/kernel/power.rs new file +118 -0

118 lines not on this page · raw message

rust/kernel/prelude.rs new file +36 -0
new file mode 100644
index 000000000000..ad9e91307028

Lines of this file are not shown. View the raw message.

rust/kernel/print.rs new file +417 -0

417 lines not on this page · raw message

rust/kernel/random.rs new file +50 -0

50 lines not on this page · raw message

rust/kernel/raw_list.rs new file +361 -0

361 lines not on this page · raw message

rust/kernel/rbtree.rs new file +562 -0

562 lines not on this page · raw message

rust/kernel/revocable.rs new file +163 -0

163 lines not on this page · raw message

rust/kernel/security.rs new file +36 -0
new file mode 100644
index 000000000000..2004d01233f4

Lines of this file are not shown. View the raw message.

rust/kernel/static_assert.rs new file +39 -0
new file mode 100644
index 000000000000..a80d8ab57564

Lines of this file are not shown. View the raw message.

rust/kernel/std_vendor.rs new file +150 -0

150 lines not on this page · raw message

rust/kernel/str.rs new file +401 -0

401 lines not on this page · raw message

rust/kernel/sysctl.rs new file +197 -0

197 lines not on this page · raw message

rust/kernel/task.rs new file +182 -0

182 lines not on this page · raw message

rust/kernel/types.rs new file +486 -0

486 lines not on this page · raw message

rust/kernel/user_ptr.rs new file +175 -0

175 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.35.1

Part of the diff is not shown here. View the raw message.

#13 lore raw

Re: [PATCH v4 10/20] rust: add `kernel` crate

On (22/02/12 14:03), Miguel Ojeda wrote:
[..]

Quoted 5 lines
rust/kernel/allocator.rs new file +5 -0
+unsafe impl GlobalAlloc for KernelAllocator {
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        // `krealloc()` is used instead of `kmalloc()` because the latter is
+        // an inline function and cannot be bound to as a result.
+        unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 }

[..]

rust/kernel/pages.rs line 35

Quoted 11 lines
rust/kernel/pages.rs new file +11 -0
+impl<const ORDER: u32> Pages<ORDER> {
+    /// Allocates a new set of contiguous pages.
+    pub fn new() -> Result<Self> {
+        // TODO: Consider whether we want to allow callers to specify flags.
+        // SAFETY: This only allocates pages. We check that it succeeds in the next statement.
+        let pages = unsafe {
+            bindings::alloc_pages(
+                bindings::GFP_KERNEL | bindings::__GFP_ZERO | bindings::__GFP_HIGHMEM,
+                ORDER,
+            )
+        };

[..]

Is this flexible enough? Why not let user pass bindings::GFP_* bitmask, just like what the underlying kernel API does.

#14 lore raw

Re: [PATCH v4 10/20] rust: add `kernel` crate

Hi Sergey,

Quoted 3 lines · Sergey Senozhatsky

Is this flexible enough? Why not let user pass bindings::GFP_* bitmask, just like what the underlying kernel API does.

For particular kernel abstractions, they may know what they need; but in general, yeah, we may need to allow for flexibility where needed (see the TODO comment in the quoted code).

For collections that need to allocate, it is an open question how Rust will handle it upstream, as there are several approaches (if you want to take a look, see the allocator_api feature and the working group at https://github.com/rust-lang/wg-allocators). But in order to be able to experiment and see what is best for the kernel, we have an in-tree fork of the alloc standard library crate (see rust/alloc/README.md).

Cheers,
Miguel

maintainer
#15 lore raw

Re: [PATCH v4 10/20] rust: add `kernel` crate

In reply to Miguel Ojeda
Quoted 19 lines · Miguel Ojeda

From: Wedson Almeida Filho <[email protected]>

The kernel crate currently includes all the abstractions that wrap kernel features written in C.

These abstractions call the C side of the kernel via the generated bindings with the bindgen tool. Modules developed in Rust should never call the bindings themselves.

In the future, as the abstractions grow in number, we may need to split this crate into several, possibly following a similar subdivision in subsystems as the kernel itself and/or moving the code to the actual subsystems.

kernel/printk/printk.c +0 -0
index 82abfaf3c2aa..c042386667f2 100644

kernel/printk/printk.c static struct latched_seq clear_seq = { · line 399

Quoted 9 lines
kernel/printk/printk.c +4 -1
@@ -392,7 +392,10 @@ static struct latched_seq clear_seq = {
 /* the maximum size of a formatted record (i.e. with prefix added per line) */
 #define CONSOLE_LOG_MAX		1024
 
-/* the maximum size allowed to be reserved for a record */
+/*
+ * The maximum size allowed to be reserved for a record.
+ * Keep in sync with rust/kernel/print.rs.
+ */
 #define LOG_LINE_MAX		(CONSOLE_LOG_MAX - PREFIX_MAX)

What exactly should we keep in sync, please?

I see only handling of KERN_* prefix in print.rs. I do not see there any counter part of LOG_LINE_MAX, CONSOLE_LOG_MAX, or PREFIX_MAX.

Also note that PREFIX_MAX is the maximal lenght of the prefix printed on console. It is log level + time stamp + caller id. For example:

<12>[  123.632345][ T3260]

It seems that print.rs defines max size of the prefix in the printk format where the log level is defined using KERN_* pair of characters.

Quoted 10 lines
kernel/printk/printk.c +0 -0
 #define LOG_LEVEL(v)		((v) & 0x07)
rust/kernel/print.rs new file +2 -0
new file mode 100644
index 000000000000..dba4ef10c722
@@ -0,0 +1,417 @@
+/// Format strings.
+///

rust/kernel/print.rs line 12

Quoted 10 lines
rust/kernel/print.rs new file +10 -0
+/// Public but hidden since it should only be used from public macros.
+#[doc(hidden)]
+pub mod format_strings {
+    use crate::bindings;
+
+    /// The length we copy from the `KERN_*` kernel prefixes.
+    const LENGTH_PREFIX: usize = 2;
+
+    /// The length of the fixed format strings.
+    pub const LENGTH: usize = 10;

I am sorry but I am not familiar with rust. What are these limits 2 and 10 used for, please?

I guess that 2 is the size of a single KERN_* identifier. But what is 10?

Note that printk() format prefix is typically just a single KERN_* identifier. But there might be more. Well, in practice only the following combination makes sense: KERN_CONT + KERN_<LEVEL>.

Quoted 17 lines
rust/kernel/print.rs new file +17 -0
+    /// Generates a fixed format string for the kernel's [`_printk`].
+    ///
+    /// The format string is always the same for a given level, i.e. for a
+    /// given `prefix`, which are the kernel's `KERN_*` constants.
+    ///
+    /// [`_printk`]: ../../../../include/linux/printk.h
+    const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] {
+        // Ensure the `KERN_*` macros are what we expect.
+        assert!(prefix[0] == b'\x01');
+        if is_cont {
+            assert!(prefix[1] == b'c');
+        } else {
+            assert!(prefix[1] >= b'0' && prefix[1] <= b'7');
+        }
+        assert!(prefix[2] == b'\x00');
+
+        let suffix: &[u8; LENGTH - LENGTH_PREFIX] = if is_cont {

rust/kernel/print.rs line 71

Quoted 10 lines
rust/kernel/print.rs new file +10 -0
+            b"%pA\0\0\0\0\0"
+        } else {
+            b"%s: %pA\0"
+        };
+
+        [
+            prefix[0], prefix[1], suffix[0], suffix[1], suffix[2], suffix[3], suffix[4], suffix[5],
+            suffix[6], suffix[7],
+        ]
+    }

Finally, is there any way to test whether any change in the printk code breaks the rust support?

Best Regards,
Petr

#16 lore raw

Re: [PATCH v4 10/20] rust: add `kernel` crate

Hi Petr,

Quoted 5 lines · Petr Mladek

What exactly should we keep in sync, please?

I see only handling of KERN_* prefix in print.rs. I do not see there any counter part of LOG_LINE_MAX, CONSOLE_LOG_MAX, or PREFIX_MAX.

Good catch! We had a buffer on the Rust side in the past, but that is not the case anymore since commit 9e8bd679ecf2 ("Support Rust core::fmt::Argument in vsprintf") on our side, so we will remove the comment.

Quoted 9 lines

I am sorry but I am not familiar with rust. What are these limits 2 and 10 used for, please?

I guess that 2 is the size of a single KERN_* identifier. But what is 10?

Note that printk() format prefix is typically just a single KERN_* identifier. But there might be more. Well, in practice only the following combination makes sense: KERN_CONT + KERN_<LEVEL>.

What we are doing here is generating compile-time format strings that are then used by the pr_*! macros (which call the C side printk() with one of the strings).

In other words, this is not parsing arbitrary printk() format strings (which I am guessing something like that is your concern -- please let me know if I got it wrong).

To clarify a bit what the code does and what the constants are:

- generate() is called at compile-time.

- The size of these generated strings is always 10.

- We compose those strings by using the first 2 bytes of KERN_*.
However, we also take the chance to check (at compile-time) they have the contents we expect, including the third zero byte.

- Then other 8 bytes are used to complete the 10: either "%pA" plus
0 padding (CONT level) or "%s: %pA" (otherwise).

Quoted 2 lines

Finally, is there any way to test whether any change in the printk code breaks the rust support?

One way is to compile the code, e.g. the assert!s in the generate function run at compile-time, thus they provide a first layer of defense.

Another way is to use samples/rust/print.rs which we run in the CI as a black box test.

Is that what you had in mind? Or something like unit tests or self tests?

Thanks for taking a look!

Cheers,
Miguel

maintainer
#17 lore raw

Re: [PATCH v4 10/20] rust: add `kernel` crate

Quoted 6 lines · Miguel Ojeda

Hi Petr,

Quoted 3 lines · Petr Mladek

What exactly should we keep in sync, please?

Quoted 7 lines
Quoted 2 lines

I see only handling of KERN_* prefix in print.rs. I do not see there any counter part of LOG_LINE_MAX, CONSOLE_LOG_MAX, or PREFIX_MAX.

Good catch! We had a buffer on the Rust side in the past, but that is not the case anymore since commit 9e8bd679ecf2 ("Support Rust core::fmt::Argument in vsprintf") on our side, so we will remove the comment.

Great :-)

Quoted 6 lines
Quoted 6 lines

I am sorry but I am not familiar with rust. What are these limits 2 and 10 used for, please?

I guess that 2 is the size of a single KERN_* identifier. But what is 10?

Quoted 7 lines
Quoted 3 lines

Note that printk() format prefix is typically just a single KERN_* identifier. But there might be more. Well, in practice only the following combination makes sense: KERN_CONT + KERN_<LEVEL>.

What we are doing here is generating compile-time format strings that are then used by the pr_*! macros (which call the C side printk() with one of the strings).

I see. We are on the safe side then.

Quoted 3 lines

In other words, this is not parsing arbitrary printk() format strings (which I am guessing something like that is your concern -- please let me know if I got it wrong).

Yes, this was my concern.

Quoted 11 lines
Quoted 2 lines

Finally, is there any way to test whether any change in the printk code breaks the rust support?

One way is to compile the code, e.g. the assert!s in the generate function run at compile-time, thus they provide a first layer of defense.

Another way is to use samples/rust/print.rs which we run in the CI as a black box test.

Is that what you had in mind? Or something like unit tests or self tests?

I had in mind any tests that I might run [*] to be sure that changes in the native printk code does not break Rust support.

The compile test and samples/rust/print.rs do some basic tests and might enough for now.

[*] To make it clear. I am not going to run the tests at this stage.
But I might be useful once this patchset is accepted upstream. But it also might be enough to wait for results from your CI. I hope that we will not break it that often.

Best Regards,
Petr

author maintainer
#18 lore raw

PATCH v4 11/20 rust: export generated symbols

In reply to Miguel Ojeda

All symbols are reexported reusing the EXPORT_SYMBOL_GPL macro from C. The lists of symbols are generated on the fly.

There are three main sets of symbols to distinguish:

- The ones from the core and alloc crates (from the Rust standard library). The code is licensed as Apache/MIT.

- The ones from our abstractions in the kernel crate.

- The helpers (already exported since they are not generated).

We export everything as GPL. This ensures we do not mistakenly expose GPL kernel symbols/features as non-GPL, even indirectly.

---
 rust/exports.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 rust/exports.c
rust/exports.c new file +19 -0
new file mode 100644
index 000000000000..a9aec51eed8a
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// A hack to export Rust symbols for loadable modules without having to redo
+// the entire `include/linux/export.h` logic in Rust.
+//
+// This requires the Rust's new/future `v0` mangling scheme because the default
+// one ("legacy") uses invalid characters for C identifiers (thus we cannot use
+// the `EXPORT_SYMBOL_*` macros).
+//
+// All symbols are exported as GPL-only to guarantee no GPL-only feature is
+// accidentally exposed.
+
+#include <linux/module.h>
+
+#define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym);
+
+#include "exports_core_generated.h"
+#include "exports_alloc_generated.h"
+#include "exports_kernel_generated.h"
Signature · 1 line
2.35.1
author maintainer
#19 lore raw

PATCH v4 12/20 vsprintf: add new `%pA` format specifier

In reply to Miguel Ojeda

From: Gary Guo <[email protected]>

This patch adds a format specifier %pA to vsprintf which formats a pointer as core::fmt::Arguments. Doing so allows us to directly format to the internal buffer of printf, so we do not have to use a temporary buffer on the stack to pre-assemble the message on the Rust side.

This specifier is intended only to be used from Rust and not for C, so checkpatch.pl is intentionally unchanged to catch any misuse.

---
 lib/rust.h     | 14 ++++++++++++++
 lib/vsprintf.c |  7 +++++++
 2 files changed, 21 insertions(+)
 create mode 100644 lib/rust.h
lib/rust.h new file +14 -0
new file mode 100644
index 000000000000..9cf0b102b496
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LIB_RUST_H
+#define _LIB_RUST_H
+
+#ifdef CONFIG_RUST
+char *rust_fmt_argument(char* buf, char* end, void *ptr);
+#else
+static inline char *rust_fmt_argument(char* buf, char* end, void *ptr)
+{
+	return NULL;
+}
+#endif
+
+#endif /* _LIB_RUST_H */
lib/vsprintf.c +7 -0
index 3b8129dd374c..61528094ec87 100644
@@ -52,6 +52,7 @@
 
 #include <linux/string_helpers.h>
 #include "kstrtox.h"
+#include "rust.h"
 
 static noinline unsigned long long simple_strntoull(const char *startp, size_t max_chars, char **endp, unsigned int base)
 {
@@ -2378,6 +2379,10 @@ early_param("no_hash_pointers", no_hash_pointers_enable);
  *
  * Note: The default behaviour (unadorned %p) is to hash the address,
  * rendering it useful as a unique identifier.
+ *
+ * There is also a '%pA' format specifier, but it is only intended to be used
+ * from Rust code to format core::fmt::Arguments. Do *not* use it from C.
+ * See rust/kernel/print.rs for details.
  */
 static noinline_for_stack
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
@@ -2450,6 +2455,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		return device_node_string(buf, end, ptr, spec, fmt + 1);
 	case 'f':
 		return fwnode_string(buf, end, ptr, spec, fmt + 1);
+	case 'A':
+		return rust_fmt_argument(buf, end, ptr);
 	case 'x':
 		return pointer_string(buf, end, ptr, spec);
 	case 'e':
Signature · 1 line
2.35.1
#20 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 1 line · Miguel Ojeda

From: Gary Guo <[email protected]>

Not sure I understand this...

Quoted 9 lines

This patch adds a format specifier %pA to vsprintf which formats a pointer as core::fmt::Arguments. Doing so allows us to directly format to the internal buffer of printf, so we do not have to use a temporary buffer on the stack to pre-assemble the message on the Rust side.

This specifier is intended only to be used from Rust and not for C, so checkpatch.pl is intentionally unchanged to catch any misuse.

Quoted 6 lines

...together with this in the current SoB chain.

Quoted 2 lines

I'm wondering if you considered to use %pV.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#21 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 20 lines · Andy Shevchenko
Quoted 1 line · Miguel Ojeda

From: Gary Guo <[email protected]>

Not sure I understand this...

Quoted 13 lines

This patch adds a format specifier %pA to vsprintf which formats a pointer as core::fmt::Arguments. Doing so allows us to directly format to the internal buffer of printf, so we do not have to use a temporary buffer on the stack to pre-assemble the message on the Rust side.

This specifier is intended only to be used from Rust and not for C, so checkpatch.pl is intentionally unchanged to catch any misuse.

Quoted 9 lines
Quoted 1 line

...together with this in the current SoB chain.

Quoted 2 lines

I'm wondering if you considered to use %pV.

I think the point is for vsnprintf() to call (back) into Rust code.

That said, I don't like the !CONFIG_RUST version to return NULL, that will surely crash moments later.

So I prefer something like

[rust.h]
// no CONFIG_RUST conditional
+char *rust_fmt_argument(char* buf, char* end, void *ptr);

[vsprintf.c]
+ case 'A':
+ if (IS_ENABLED(CONFIG_RUST))
+ return rust_fmt_argument(buf, end, ptr);
+ else
+ return string_nocheck(buf, end, "[%pA in non-Rust
code?!]", default_str_spec);

Rasmus

#22 lore raw

RE: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

From: Rasmus Villemoes

Quoted 27 lines

Sent: 14 February 2022 10:53

Quoted 24 lines · Andy Shevchenko
Quoted 1 line · Miguel Ojeda

From: Gary Guo <[email protected]>

Not sure I understand this...

Quoted 9 lines

This patch adds a format specifier %pA to vsprintf which formats a pointer as core::fmt::Arguments. Doing so allows us to directly format to the internal buffer of printf, so we do not have to use a temporary buffer on the stack to pre-assemble the message on the Rust side.

This specifier is intended only to be used from Rust and not for C, so checkpatch.pl is intentionally unchanged to catch any misuse.

Quoted 6 lines

...together with this in the current SoB chain.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

I'm wondering if you considered to use %pV.

I think the point is for vsnprintf() to call (back) into Rust code.

Doesn't that stand a reasonable chance of blowing the kernel stack?

vsnprintf() is likely to be on the 'worst case' stack path anyway. Anything vaguely like a recursive call, or anything 'stack expensive' inside vsnprintf() stands a real chance of overflowing the stack.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

#23 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 6 lines · David Laight

Doesn't that stand a reasonable chance of blowing the kernel stack?

vsnprintf() is likely to be on the 'worst case' stack path anyway. Anything vaguely like a recursive call, or anything 'stack expensive' inside vsnprintf() stands a real chance of overflowing the stack.

There should be no recursion going on, but stack usage could be a concern depending on what the formatted types attempt to do (thus we need to be mindful when implementing Display) and what the compiler could possibly generate on a worst case (Gary, bjorn3 et. al. may want to give details about this).

Cheers,
Miguel

#24 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

In reply to Rasmus Villemoes
Quoted 2 lines · Rasmus Villemoes

I think the point is for vsnprintf() to call (back) into Rust code.

Indeed, this is the case.

Quoted 15 lines

That said, I don't like the !CONFIG_RUST version to return NULL, that will surely crash moments later.

So I prefer something like

[rust.h]
// no CONFIG_RUST conditional
+char *rust_fmt_argument(char* buf, char* end, void *ptr);

[vsprintf.c]

(quoted diff) +5 -0
+       case 'A':
+               if (IS_ENABLED(CONFIG_RUST))
+                   return rust_fmt_argument(buf, end, ptr);
+               else
+                   return string_nocheck(buf, end, "[%pA in non-Rust
Quoted 1 line

code?!]", default_str_spec);

Sounds good. Or perhaps simply break and let it print the pointer (to be consistent with g case and non-error e case).

Cheers,
Miguel

maintainer
#25 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 23 lines · Miguel Ojeda
Quoted 2 lines · Rasmus Villemoes

I think the point is for vsnprintf() to call (back) into Rust code.

Indeed, this is the case.

Quoted 16 lines

That said, I don't like the !CONFIG_RUST version to return NULL, that will surely crash moments later.

So I prefer something like

[rust.h]
// no CONFIG_RUST conditional
+char *rust_fmt_argument(char* buf, char* end, void *ptr);

[vsprintf.c]

(quoted diff) +5 -0
+       case 'A':
+               if (IS_ENABLED(CONFIG_RUST))
+                   return rust_fmt_argument(buf, end, ptr);
+               else
+                   return string_nocheck(buf, end, "[%pA in non-Rust

code?!]", default_str_spec);

Any long message might cause buffer overflow when the caller expects fixed short string.

Quoted 2 lines

Sounds good. Or perhaps simply break and let it print the pointer (to be consistent with g case and non-error e case).

Also this might cause buffer overflow.

The most safe solution would be to use WARN_ONCE(). The only drawback is that it might cause panic() when using "panic_on_warn" kernel parameter. But it will not open security hole.

Best Regards,
Petr

#26 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 25 lines · Petr Mladek
Quoted 23 lines · Miguel Ojeda
Quoted 2 lines · Rasmus Villemoes

I think the point is for vsnprintf() to call (back) into Rust code.

Indeed, this is the case.

Quoted 16 lines

That said, I don't like the !CONFIG_RUST version to return NULL, that will surely crash moments later.

So I prefer something like

[rust.h]
// no CONFIG_RUST conditional
+char *rust_fmt_argument(char* buf, char* end, void *ptr);

[vsprintf.c]

(quoted diff) +5 -0
+       case 'A':
+               if (IS_ENABLED(CONFIG_RUST))
+                   return rust_fmt_argument(buf, end, ptr);
+               else
+                   return string_nocheck(buf, end, "[%pA in non-Rust

code?!]", default_str_spec);

Quoted 2 lines

Any long message might cause buffer overflow when the caller expects fixed short string.

If the caller (1) uses a %p extension from C code which should only be used from Rust and (2) uses sprintf() or another variant where he doesn't provide the real buffer bounds, well, then he certainly gets to keep the pieces.

It is a much worse problem that if CONFIG_RUST is enabled, we can't know that we were actually called from Rust (but when !CONFIG_RUST, we certainly know that we weren't), so we could call into rust_fmt_argument with a pointer which certainly doesn't point to the/a data structure which that Rust code expects. But we can't do anything about it, we will just have to rely on static analysis to flag any use of %pA in C code.

Quoted 1 line

The most safe solution would be to use WARN_ONCE().

Preferably no, we shouldn't call into the printk machinery from within vsnprintf(). I know I've added a few myself (AFAIR for use of %n or other unsupported specifiers, and for overflow of precision/field width), and I've often thought about a way to get rid of them while still making sure some message eventually gets logged (once).

Rasmus

maintainer
#27 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 34 lines · Rasmus Villemoes
Quoted 25 lines · Petr Mladek
Quoted 23 lines · Miguel Ojeda
Quoted 2 lines · Rasmus Villemoes

I think the point is for vsnprintf() to call (back) into Rust code.

Indeed, this is the case.

Quoted 16 lines

That said, I don't like the !CONFIG_RUST version to return NULL, that will surely crash moments later.

So I prefer something like

[rust.h]
// no CONFIG_RUST conditional
+char *rust_fmt_argument(char* buf, char* end, void *ptr);

[vsprintf.c]

(quoted diff) +5 -0
+       case 'A':
+               if (IS_ENABLED(CONFIG_RUST))
+                   return rust_fmt_argument(buf, end, ptr);
+               else
+                   return string_nocheck(buf, end, "[%pA in non-Rust

code?!]", default_str_spec);

Quoted 2 lines

Any long message might cause buffer overflow when the caller expects fixed short string.

If the caller (1) uses a %p extension from C code which should only be used from Rust and (2) uses sprintf() or another variant where he doesn't provide the real buffer bounds, well, then he certainly gets to keep the pieces.

Quoted 6 lines

It is a much worse problem that if CONFIG_RUST is enabled, we can't know that we were actually called from Rust (but when !CONFIG_RUST, we certainly know that we weren't), so we could call into rust_fmt_argument with a pointer which certainly doesn't point to the/a data structure which that Rust code expects. But we can't do anything about it, we will just have to rely on static analysis to flag any use of %pA in C code.

Yeah. !CONFIG_RUST would trigger the warning and help to find the sinners but it is not reliable. Static analysic might be better...

Quoted 7 lines
Quoted 1 line

The most safe solution would be to use WARN_ONCE().

Preferably no, we shouldn't call into the printk machinery from within vsnprintf(). I know I've added a few myself (AFAIR for use of %n or other unsupported specifiers, and for overflow of precision/field width), and I've often thought about a way to get rid of them while still making sure some message eventually gets logged (once).

WARN_ONCE() in vsprintf() code is much more acceptable these days with the lockless ringbuffer.

Best Regards,
Petr

#28 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

In reply to Andy Shevchenko

Hi Andy,

Quoted 4 lines · Andy Shevchenko

Not sure I understand this...

...together with this in the current SoB chain.

From my reading of Documentation/process/submitting-patches.rst, this is the case I have to use:

```
Example of a patch submitted by a Co-developed-by: author::

    From: From Author <[email protected]>

    <changelog>

    Co-developed-by: Random Co-Author <[email protected]>
    Signed-off-by: Random Co-Author <[email protected]>
    Signed-off-by: From Author <[email protected]>
    Co-developed-by: Submitting Co-Author <[email protected]>
    Signed-off-by: Submitting Co-Author <[email protected]>
```

Do you think another case applies?

Quoted 1 line

I'm wondering if you considered to use %pV.

Please see Rasmus' reply, i.e. we are using Rust's own formatting machinery (the compiler validates the format string and creates an object that represents the formatting to be done).

Thanks for taking a look!

Cheers,
Miguel

#29 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 24 lines · Miguel Ojeda
Quoted 4 lines · Andy Shevchenko

Not sure I understand this...

...together with this in the current SoB chain.

From my reading of Documentation/process/submitting-patches.rst, this is the case I have to use:

```
Example of a patch submitted by a Co-developed-by: author::

    From: From Author <[email protected]>

    <changelog>

    Co-developed-by: Random Co-Author <[email protected]>
    Signed-off-by: Random Co-Author <[email protected]>
    Signed-off-by: From Author <[email protected]>
    Co-developed-by: Submitting Co-Author <[email protected]>
    Signed-off-by: Submitting Co-Author <[email protected]>
```
Quoted 1 line

Do you think another case applies?

I see, thanks for elaboration!

...

Quoted 5 lines
Quoted 1 line

I'm wondering if you considered to use %pV.

Please see Rasmus' reply, i.e. we are using Rust's own formatting machinery (the compiler validates the format string and creates an object that represents the formatting to be done).

Yes, I read that.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#30 lore raw

Re: [PATCH v4 12/20] vsprintf: add new `%pA` format specifier

Quoted 2 lines · Andy Shevchenko

I see, thanks for elaboration!

Anytime!

Cheers,
Miguel

author maintainer
#31 lore raw

PATCH v4 13/20 scripts: add `generate_rust_analyzer.py`

In reply to Miguel Ojeda

The generate_rust_analyzer.py script generates the configuration file (rust-project.json) for rust-analyzer.

rust-analyzer is a modular compiler frontend for the Rust language. It provides an LSP server which can be used in editors such as VS Code, Emacs or Vim.

---
 scripts/generate_rust_analyzer.py | 133 ++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)
 create mode 100755 scripts/generate_rust_analyzer.py
scripts/generate_rust_analyzer.py new file +133 -0
new file mode 100755
index 000000000000..024f8b884c1b
@@ -0,0 +1,133 @@
+#!/usr/bin/env python3
+"""generate_rust_analyzer - Generates the `rust-project.json` file for `rust-analyzer`.
+"""
+
+import argparse
+import json
+import logging
+import pathlib
+import sys
+
+def generate_crates(srctree, objtree, sysroot_src):
+    # Generate the configuration list.
+    cfg = []
+    with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
+        for line in fd:
+            line = line.replace("--cfg=", "")
+            line = line.replace("\n", "")
+            cfg.append(line)
+
+    # Now fill the crates list -- dependencies need to come first.
+    #
+    # Avoid O(n^2) iterations by keeping a map of indexes.
+    crates = []
+    crates_indexes = {}
+
+    def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False):
+        crates_indexes[display_name] = len(crates)
+        crates.append({
+            "display_name": display_name,
+            "root_module": str(root_module),
+            "is_workspace_member": is_workspace_member,
+            "is_proc_macro": is_proc_macro,
+            "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps],
+            "cfg": cfg,
+            "edition": "2021",
+            "env": {
+                "RUST_MODFILE": "This is only for rust-analyzer"
+            }
+        })
+
+    # First, the ones in `rust/` since they are a bit special.
+    append_crate(
+        "core",
+        sysroot_src / "core" / "src" / "lib.rs",
+        [],
+        is_workspace_member=False,
+    )
+
+    append_crate(
+        "compiler_builtins",
+        srctree / "rust" / "compiler_builtins.rs",
+        [],
+    )
+
+    append_crate(
+        "alloc",
+        srctree / "rust" / "alloc" / "lib.rs",
+        ["core", "compiler_builtins"],
+    )
+
+    append_crate(
+        "macros",
+        srctree / "rust" / "macros" / "lib.rs",
+        [],
+        is_proc_macro=True,
+    )
+    crates[-1]["proc_macro_dylib_path"] = "rust/libmacros.so"
+
+    append_crate(
+        "build_error",
+        srctree / "rust" / "build_error.rs",
+        ["core", "compiler_builtins"],
+    )
+
+    append_crate(
+        "kernel",
+        srctree / "rust" / "kernel" / "lib.rs",
+        ["core", "alloc", "macros", "build_error"],
+        cfg=cfg,
+    )
+    crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
+    crates[-1]["source"] = {
+        "include_dirs": [
+            str(srctree / "rust" / "kernel"),
+            str(objtree / "rust")
+        ],
+        "exclude_dirs": [],
+    }
+
+    # Then, the rest outside of `rust/`.
+    #
+    # We explicitly mention the top-level folders we want to cover.
+    for folder in ("samples", "drivers"):
+        for path in (srctree / folder).rglob("*.rs"):
+            logging.info("Checking %s", path)
+            name = path.name.replace(".rs", "")
+
+            # Skip those that are not crate roots.
+            if f"{name}.o" not in open(path.parent / "Makefile").read():
+                continue
+
+            logging.info("Adding %s", name)
+            append_crate(
+                name,
+                path,
+                ["core", "alloc", "kernel"],
+                cfg=cfg,
+            )
+
+    return crates
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--verbose', '-v', action='store_true')
+    parser.add_argument("srctree", type=pathlib.Path)
+    parser.add_argument("objtree", type=pathlib.Path)
+    parser.add_argument("sysroot_src", type=pathlib.Path)
+    args = parser.parse_args()
+
+    logging.basicConfig(
+        format="[%(asctime)s] [%(levelname)s] %(message)s",
+        level=logging.INFO if args.verbose else logging.WARNING
+    )
+
+    rust_project = {
+        "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src),
+        "sysroot_src": str(args.sysroot_src),
+    }
+
+    json.dump(rust_project, sys.stdout, sort_keys=True, indent=4)
+
+if __name__ == "__main__":
+    main()
Signature · 1 line
2.35.1
author maintainer
#32 lore raw

PATCH v4 14/20 scripts: decode_stacktrace: demangle Rust symbols

In reply to Miguel Ojeda

Recent versions of both Binutils (c++filt) and LLVM (llvm-cxxfilt) provide Rust v0 mangling support.

---
I would like to use this patch for discussing the demangling topic.

The following discusses the different approaches we could take.

# Leave demangling to userspace

This is the easiest and less invasive approach, the one implemented by this patch.

The decode_stacktrace.sh script is already needed to map the offsets to the source code. Therefore, we could also take the chance to demangle the symbols here.

With this approach, we do not need to introduce any change in the vsprintf machinery and we minimize the risk of breaking user tools.

Note that, if we take this approach, it is likely we want to ask for a minimum version of either of the tools (since there may be users of the script that do not have recent enough toolchains).

# Demangling in kernelspace on-the-fly

That is, at backtrace print time, we demangle the Rust symbols.

The size of the code that would be needed is fairly small; around 5 KiB using the "official" library (written in Rust), e.g.:

    text    data    bss     dec      hex    filename
    7799976 1689820 2129920 11619716 b14d84 vmlinux
    7801111 1693916 2129920 11624947 b161f3 vmlinux + demangling

We can remove a few bits from the official library, e.g. punycode support that we do not need (all our identifiers will be ASCII), but it does not make a substantial difference.

The official library performs the demangling without requiring allocations. However, of course, it will increased our stack usage and complexity, specially considering a stack dump may be requested in not ideal conditions.

Furthermore, this approach (and the ones below) likely require adding a new %p specifier (or a new modifier to existing ones) if we do not want to affect non-backtrace uses of the B/S ones. Also, it is unclear whether we should write the demangled versions in an extra, different line or replace the real symbol -- we could be breaking user tools relying on parsing backtraces (e.g. our own decode_stacktrace.sh). For instance, they could be relying on having real symbols there, or may break due to e.g. spaces.

# Demangling at compile-time

This implies having kallsyms demangle all the Rust symbols.

The size of this data is around the same order of magnitude of the non-demangled ones. However, this is notably more than the demangling code (see previous point), e.g. 120 KiB (uncompressed) in a small kernel.

This approach also brings the same concerns regarding modifying the backtrace printing (see previous point).

# Demangling at compile-time and substituting symbols by hashes

One variation of the previous alternative is avoiding the mangled names inside the kernel, by hashing them. This would avoid having to support "big symbols" and would also reduce the size of the kallsyms tables, while still allowing to link modules.

However, if we do not have the real symbols around, then we do not have the possibility of providing both the mangled and demangled versions in the backtrace, which brings us back to the issues related to breaking userspace tools. There are also other places other than backtraces using "real" symbols that users may be relying on, such as /proc/*/stack.

 scripts/decode_stacktrace.sh | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
scripts/decode_stacktrace.sh +14 -0
index 5fbad61fe490..f3c7b506d440 100755
@@ -8,6 +8,14 @@ usage() {
 	echo "	$0 -r <release> | <vmlinux> [<base path>|auto] [<modules path>]"
 }
 
+# Try to find a Rust demangler
+if type llvm-cxxfilt >/dev/null 2>&1 ; then
+	cppfilt=llvm-cxxfilt
+elif type c++filt >/dev/null 2>&1 ; then
+	cppfilt=c++filt
+	cppfilt_opts=-i
+fi
+
 if [[ $1 == "-r" ]] ; then
 	vmlinux=""
 	basepath="auto"
@@ -169,6 +177,12 @@ parse_symbol() {
 	# In the case of inlines, move everything to same line
 	code=${code//$'\n'/' '}
 
+	# Demangle if the name looks like a Rust symbol and if
+	# we got a Rust demangler
+	if [[ $name =~ ^_R && $cppfilt != "" ]] ; then
+		name=$("$cppfilt" "$cppfilt_opts" "$name")
+	fi
+
 	# Replace old address with pretty line numbers
 	symbol="$segment$name ($code)"
 }
Signature · 1 line
2.35.1
author maintainer
#33 lore raw

PATCH v4 15/20 docs: add Rust documentation

In reply to Miguel Ojeda

Most of the documentation for Rust is written within the source code itself, as it is idiomatic for Rust projects. This applies to both the shared infrastructure at rust/ as well as any other Rust module (e.g. drivers) written across the kernel.

However, these documents contain general information that does not fit particularly well in the source code, like the Quick Start guide.

It also contains an asset (SVG logo) used for the rustdoc target and a few other small changes elsewhere in the documentation folder.

---
 Documentation/doc-guide/kernel-doc.rst     |   3 +
 Documentation/index.rst                    |   1 +
 Documentation/kbuild/kbuild.rst            |   4 +
 Documentation/process/changes.rst          |  42 +++
 Documentation/rust/arch-support.rst        |  35 ++
 Documentation/rust/coding-guidelines.rst   | 153 +++++++++
 Documentation/rust/general-information.rst |  80 +++++
 Documentation/rust/index.rst               |  21 ++
 Documentation/rust/logo.svg                | 357 +++++++++++++++++++++
 Documentation/rust/quick-start.rst         | 231 +++++++++++++
 10 files changed, 927 insertions(+)
 create mode 100644 Documentation/rust/arch-support.rst
 create mode 100644 Documentation/rust/coding-guidelines.rst
 create mode 100644 Documentation/rust/general-information.rst
 create mode 100644 Documentation/rust/index.rst
 create mode 100644 Documentation/rust/logo.svg
 create mode 100644 Documentation/rust/quick-start.rst
Documentation/doc-guide/kernel-doc.rst +3 -0
index 79aaa55d6bcf..724e2ffddff1 100644
@@ -11,6 +11,9 @@ when it is embedded in source files.
    reasons. The kernel source contains tens of thousands of kernel-doc
    comments. Please stick to the style described here.
 
+.. note:: kernel-doc does not cover Rust code: please see
+   Documentation/rust/docs.rst instead.
+
 The kernel-doc structure is extracted from the comments, and proper
 `Sphinx C Domain`_ function and type descriptions with anchors are
 generated from them. The descriptions are filtered for special kernel-doc
Documentation/index.rst +1 -0
index b58692d687f6..ca9ff1adbe0b 100644
@@ -82,6 +82,7 @@ merged much easier.
    maintainer/index
    fault-injection/index
    livepatch/index
+   rust/index
 
 
 Kernel API documentation
Documentation/kbuild/kbuild.rst +4 -0
index 2d1fc03d346e..468a0d216c29 100644
@@ -57,6 +57,10 @@ CFLAGS_MODULE
 -------------
 Additional module specific options to use for $(CC).
 
+KRUSTFLAGS
+----------
+Additional options to the Rust compiler (for built-in and modules).
+
 LDFLAGS_MODULE
 --------------
 Additional options used for $(LD) when linking modules.
Documentation/process/changes.rst +42 -0

66 lines not on this page · raw message

Documentation/rust/arch-support.rst new file +35 -0
new file mode 100644
index 000000000000..fdcce6452623
@@ -0,0 +1,35 @@
+.. _rust_arch_support:
+
+Arch Support
+============
+
+Currently, the Rust compiler (``rustc``) uses LLVM for code generation,
+which limits the supported architectures that can be targeted. In addition,
+support for building the kernel with LLVM/Clang varies (see :ref:`kbuild_llvm`).
+This support is needed for ``bindgen`` which uses ``libclang``.
+
+Below is a general summary of architectures that currently work. Level of
+support corresponds to ``S`` values in the ``MAINTAINERS`` file.
+
+.. list-table::
+   :widths: 10 10 10
+   :header-rows: 1
+
+   * - Architecture
+     - Level of support
+     - Constraints
+   * - ``arm``
+     - Maintained
+     - ``armv6`` and compatible only, ``RUST_OPT_LEVEL >= 2``
+   * - ``arm64``
+     - Maintained
+     - None
+   * - ``powerpc``
+     - Maintained
+     - ``ppc64le`` only, ``RUST_OPT_LEVEL < 2`` requires ``CONFIG_THREAD_SHIFT=15``
+   * - ``riscv``
+     - Maintained
+     - ``riscv64`` only
+   * - ``x86``
+     - Maintained
+     - ``x86_64`` only
Documentation/rust/coding-guidelines.rst new file +153 -0

153 lines not on this page · raw message

Documentation/rust/general-information.rst new file +80 -0

80 lines not on this page · raw message

Documentation/rust/index.rst new file +21 -0
new file mode 100644
index 000000000000..6e20af5b723a
@@ -0,0 +1,21 @@
+Rust
+====
+
+Documentation related to Rust within the kernel. To start using Rust
+in the kernel, please read the
+:ref:`Documentation/rust/quick-start.rst <rust_quick_start>` guide.
+
+.. toctree::
+    :maxdepth: 1
+
+    quick-start
+    general-information
+    coding-guidelines
+    arch-support
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
Documentation/rust/logo.svg new file +357 -0

357 lines not on this page · raw message

Documentation/rust/quick-start.rst new file +231 -0

231 lines not on this page · raw message

Signature · 1 line
2.35.1
#34 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

Hi,

Please find inline comments WRT ReST-in-kereneldoc.

Jon, if I'm missing something, please enlighten me.

Quoted 116 lines · Miguel Ojeda

Most of the documentation for Rust is written within the source code itself, as it is idiomatic for Rust projects. This applies to both the shared infrastructure at rust/ as well as any other Rust module (e.g. drivers) written across the kernel.

However, these documents contain general information that does not fit particularly well in the source code, like the Quick Start guide.

It also contains an asset (SVG logo) used for the rustdoc target and a few other small changes elsewhere in the documentation folder.

---
 Documentation/doc-guide/kernel-doc.rst     |   3 +
 Documentation/index.rst                    |   1 +
 Documentation/kbuild/kbuild.rst            |   4 +
 Documentation/process/changes.rst          |  42 +++
 Documentation/rust/arch-support.rst        |  35 ++
 Documentation/rust/coding-guidelines.rst   | 153 +++++++++
 Documentation/rust/general-information.rst |  80 +++++
 Documentation/rust/index.rst               |  21 ++
 Documentation/rust/logo.svg                | 357 +++++++++++++++++++++
 Documentation/rust/quick-start.rst         | 231 +++++++++++++
 10 files changed, 927 insertions(+)
 create mode 100644 Documentation/rust/arch-support.rst
 create mode 100644 Documentation/rust/coding-guidelines.rst
 create mode 100644 Documentation/rust/general-information.rst
 create mode 100644 Documentation/rust/index.rst
 create mode 100644 Documentation/rust/logo.svg
 create mode 100644 Documentation/rust/quick-start.rst
Documentation/doc-guide/kernel-doc.rst +3 -0
index 79aaa55d6bcf..724e2ffddff1 100644
@@ -11,6 +11,9 @@ when it is embedded in source files.
    reasons. The kernel source contains tens of thousands of kernel-doc
    comments. Please stick to the style described here.
 
+.. note:: kernel-doc does not cover Rust code: please see
+   Documentation/rust/docs.rst instead.
+
 The kernel-doc structure is extracted from the comments, and proper
 `Sphinx C Domain`_ function and type descriptions with anchors are
 generated from them. The descriptions are filtered for special kernel-doc
Documentation/index.rst +1 -0
index b58692d687f6..ca9ff1adbe0b 100644
@@ -82,6 +82,7 @@ merged much easier.
    maintainer/index
    fault-injection/index
    livepatch/index
+   rust/index
 
 
 Kernel API documentation
Documentation/kbuild/kbuild.rst +4 -0
index 2d1fc03d346e..468a0d216c29 100644
@@ -57,6 +57,10 @@ CFLAGS_MODULE
 -------------
 Additional module specific options to use for $(CC).
 
+KRUSTFLAGS
+----------
+Additional options to the Rust compiler (for built-in and modules).
+
 LDFLAGS_MODULE
 --------------
 Additional options used for $(LD) when linking modules.
Documentation/process/changes.rst +5 -0
index a337e8eabfe1..4ec918da321f 100644
@@ -31,6 +31,8 @@ you probably needn't concern yourself with pcmciautils.
 ====================== ===============  ========================================
 GNU C                  5.1              gcc --version
 Clang/LLVM (optional)  11.0.0           clang --version
+Rust (optional)        1.58.0           rustc --version
+bindgen (optional)     0.56.0           bindgen --version
 GNU make               3.81             make --version
 binutils               2.23             ld -v
 flex                   2.5.35           flex --version
@@ -78,6 +80,29 @@ kernels. Older releases aren't guaranteed to work, and we may drop workarounds
 from the kernel that were used to support older versions. Please see additional
 docs on :ref:`Building Linux with Clang/LLVM <kbuild_llvm>`.
 
+Rust (optional)
+---------------
+

Documentation/process/changes.rst kernels. Older releases aren't guaranteed to work, and we may drop workarounds · line 95

Quoted 10 lines
Documentation/process/changes.rst +10 -0
+A particular version of the Rust toolchain is required. Newer versions may or
+may not work because the kernel depends on some unstable Rust features, for
+the moment.
+
+Each Rust toolchain comes with several "components", some of which are required
+(like ``rustc``) and some that are optional. The ``rust-src`` component (which
+is optional) needs to be installed to build the kernel. Other components are
+useful for developing.
+
+Please see :ref:`Documentation/rust/quick-start.rst <rust_quick_start>` for

Documentation/rust/quick-start.rst for

On document cross-referencing, see:
https://www.kernel.org/doc/html/latest/doc-guide/sphinx.html#cross-referencing

Documentation/process/changes.rst kernels. Older releases aren't guaranteed to work, and we may drop workarounds · line 96

Quoted 1 line
Documentation/process/changes.rst +1 -0
+instructions on how to satify the build requirements of Rust support. In

satisfy

Quoted 13 lines
Documentation/process/changes.rst +9 -0
+particular, the Makefile target 'rustavailable' is useful to check why the Rust
+toolchain may not be detected.
+
+bindgen (optional)
+------------------
+
+``bindgen`` is used to generate the Rust bindings to the C side of the kernel.
+It depends on ``libclang``.
+
 Make
 ----
 

Documentation/process/changes.rst Sphinx · line 372

Quoted 8 lines
Documentation/process/changes.rst +5 -0
@@ -340,6 +365,13 @@ Sphinx
 Please see :ref:`sphinx_install` in :ref:`Documentation/doc-guide/sphinx.rst <sphinxdoc>`
 for details about Sphinx requirements.
 
+rustdoc
+-------
+
+``rustdoc`` is used to generate the documentation for Rust code. Please see
+:ref:`Documentation/rust/general-information.rst <rust_general_information>`

Documentation/rust/general-information.rst

Documentation/process/changes.rst Clang/LLVM · line 394

Quoted 13 lines
Documentation/process/changes.rst +6 -0
+for more information.
+
 Getting updated software
 ========================
 
@@ -356,6 +388,16 @@ Clang/LLVM
 
 - :ref:`Getting LLVM <getting_llvm>`.
 
+Rust
+----
+
+- :ref:`Documentation/rust/quick-start.rst <rust_quick_start>`.

- Documentation/rust/quick-start.rst.

Documentation/process/changes.rst Clang/LLVM · line 399

Quoted 5 lines
Documentation/process/changes.rst +5 -0
+
+bindgen
+-------
+
+- :ref:`Documentation/rust/quick-start.rst <rust_quick_start>`.

- Documentation/rust/quick-start.rst.

Documentation/rust/arch-support.rst line 1

Quoted 11 lines
Documentation/process/changes.rst +1 -0
+
 Make
 ----
 
Documentation/rust/arch-support.rst new file +1 -0
new file mode 100644
index 000000000000..fdcce6452623
@@ -0,0 +1,35 @@
+.. _rust_arch_support:

This tag is not necessary.

Documentation/rust/arch-support.rst line 8

Quoted 7 lines
Documentation/rust/arch-support.rst new file +7 -0
+
+Arch Support
+============
+
+Currently, the Rust compiler (``rustc``) uses LLVM for code generation,
+which limits the supported architectures that can be targeted. In addition,
+support for building the kernel with LLVM/Clang varies (see :ref:`kbuild_llvm`).

support for building the kernel with LLVM/Clang varies (see Documentation/kbuild/llvm.rst).

Documentation/rust/arch-support.rst line 14

Quoted 6 lines
Documentation/rust/arch-support.rst new file +6 -0
+This support is needed for ``bindgen`` which uses ``libclang``.
+
+Below is a general summary of architectures that currently work. Level of
+support corresponds to ``S`` values in the ``MAINTAINERS`` file.
+
+.. list-table::

FYI, use of list-table is discouraged. (See commit db67eb748e7a ("docs: discourage use of list tables").)

Documentation/rust/arch-support.rst line 15

Quoted 1 line
Documentation/rust/arch-support.rst new file +1 -0
+   :widths: 10 10 10

:widths: 8 12 30 <- This table looks better in html with these widths.

Quoted 25 lines
Documentation/rust/arch-support.rst new file +19 -0
+   :header-rows: 1
+> +   * - Architecture
+     - Level of support
+     - Constraints
+   * - ``arm``
+     - Maintained
+     - ``armv6`` and compatible only, ``RUST_OPT_LEVEL >= 2``
+   * - ``arm64``
+     - Maintained
+     - None
+   * - ``powerpc``
+     - Maintained
+     - ``ppc64le`` only, ``RUST_OPT_LEVEL < 2`` requires ``CONFIG_THREAD_SHIFT=15``
+   * - ``riscv``
+     - Maintained
+     - ``riscv64`` only
+   * - ``x86``
+     - Maintained
+     - ``x86_64`` only
Documentation/rust/coding-guidelines.rst new file +0 -0
new file mode 100644
index 000000000000..9181dcbc2140

Documentation/rust/coding-guidelines.rst line 1

Quoted 1 line
Documentation/rust/coding-guidelines.rst new file +1 -0
@@ -0,0 +1,153 @@
+.. _rust_coding_guidelines:

Unnecessary tag.

Quoted 158 lines
Documentation/rust/coding-guidelines.rst new file +152 -0
+
+Coding Guidelines
+=================
+
+This document describes how to write Rust code in the kernel.
+
+
+Style & formatting
+------------------
+
+The code should be formatted using ``rustfmt``. In this way, a person
+contributing from time to time to the kernel does not need to learn and
+remember one more style guide. More importantly, reviewers and maintainers
+do not need to spend time pointing out style issues anymore, and thus
+less patch roundtrips may be needed to land a change.
+
+.. note:: Conventions on comments and documentation are not checked by
+  ``rustfmt``. Thus those are still needed to be taken care of.
+
+The default settings of ``rustfmt`` are used. This means the idiomatic Rust
+style is followed. For instance, 4 spaces are used for indentation rather
+than tabs.
+
+It is convenient to instruct editors/IDEs to format while typing,
+when saving or at commit time. However, if for some reason reformatting
+the entire kernel Rust sources is needed at some point, the following can be
+run::
+
+	make LLVM=1 rustfmt
+
+It is also possible to check if everything is formatted (printing a diff
+otherwise), for instance for a CI, with::
+
+	make LLVM=1 rustfmtcheck
+
+Like ``clang-format`` for the rest of the kernel, ``rustfmt`` works on
+individual files, and does not require a kernel configuration. Sometimes it may
+even work with broken code.
+
+
+Code documentation
+------------------
+
+Rust kernel code is not documented like C kernel code (i.e. via kernel-doc).
+Instead, the usual system for documenting Rust code is used: the ``rustdoc``
+tool, which uses Markdown (a lightweight markup language).
+
+To learn Markdown, there are many guides available out there. For instance,
+the one at:
+
+	https://commonmark.org/help/
+
+This is how a well-documented Rust function may look like:
+
+.. code-block:: rust
+
+	/// Returns the contained [`Some`] value, consuming the `self` value,
+	/// without checking that the value is not [`None`].
+	///
+	/// # Safety
+	///
+	/// Calling this method on [`None`] is *[undefined behavior]*.
+	///
+	/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+	///
+	/// # Examples
+	///
+	/// ```
+	/// let x = Some("air");
+	/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
+	/// ```
+	pub unsafe fn unwrap_unchecked(self) -> T {
+		match self {
+			Some(val) => val,
+
+			// SAFETY: The safety contract must be upheld by the caller.
+			None => unsafe { hint::unreachable_unchecked() },
+		}
+	}
+
+This example showcases a few ``rustdoc`` features and some conventions followed
+in the kernel:
+
+  - The first paragraph must be a single sentence briefly describing what
+    the documented item does. Further explanations must go in extra paragraphs.
+
+  - Unsafe functions must document their safety preconditions under
+    a ``# Safety`` section.
+
+  - While not shown here, if a function may panic, the conditions under which
+    that happens must be described under a ``# Panics`` section.
+
+    Please note that panicking should be very rare and used only with a good
+    reason. In almost all cases, a fallible approach should be used, typically
+    returning a ``Result``.
+
+  - If providing examples of usage would help readers, they must be written in
+    a section called ``# Examples``.
+
+  - Rust items (functions, types, constants...) must be linked appropriately
+    (``rustdoc`` will create a link automatically).
+
+  - Any ``unsafe`` block must be preceded by a ``// SAFETY:`` comment
+    describing why the code inside is sound.
+
+    While sometimes the reason might look trivial and therefore unneeded, writing
+    these comments is not just a good way of documenting what has been taken into
+    account, but most importantly, it provides a way to know that there are
+    no *extra* implicit constraints.
+
+To learn more about how to write documentation for Rust and extra features,
+please take a look at the ``rustdoc`` `book`_.
+
+.. _book: https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
+
+
+Naming
+------
+
+Rust kernel code follows the usual Rust naming conventions:
+
+	https://rust-lang.github.io/api-guidelines/naming.html
+
+When existing C concepts (e.g. macros, functions, objects...) are wrapped into
+a Rust abstraction, a name as close as reasonably possible to the C side should
+be used in order to avoid confusion and to improve readability when switching
+back and forth between the C and Rust sides. For instance, macros such as
+``pr_info`` from C are named the same in the Rust side.
+
+Having said that, casing should be adjusted to follow the Rust naming
+conventions, and namespacing introduced by modules and types should not be
+repeated in the item names. For instance, when wrapping constants like:
+
+.. code-block:: c
+
+	#define GPIO_LINE_DIRECTION_IN	0
+	#define GPIO_LINE_DIRECTION_OUT	1
+
+The equivalent in Rust may look like (ignoring documentation):
+
+.. code-block:: rust
+
+	pub mod gpio {
+	    pub enum LineDirection {
+	        In = bindings::GPIO_LINE_DIRECTION_IN as _,
+	        Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
+	    }
+	}
+
+That is, the equivalent of ``GPIO_LINE_DIRECTION_IN`` would be referred to as
+``gpio::LineDirection::In``. In particular, it should not be named
+``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN``.
Documentation/rust/general-information.rst new file +0 -0
new file mode 100644
index 000000000000..9ee4c6994d08

Documentation/rust/general-information.rst line 1

Quoted 1 line
Documentation/rust/general-information.rst new file +1 -0
@@ -0,0 +1,80 @@
+.. _rust_general_information:

Unnecessary tag.

Quoted 24 lines
Documentation/rust/general-information.rst new file +24 -0
+
+General Information
+===================
+
+This document contains useful information to know when working with
+the Rust support in the kernel.
+
+
+Code documentation
+------------------
+
+Rust kernel code is documented using ``rustdoc``, its built-in documentation
+generator.
+
+The generated HTML docs include integrated search, linked items (e.g. types,
+functions, constants), source code, etc. They may be read at (TODO: link when
+in mainline and generated alongside the rest of the documentation):
+
+	http://kernel.org/
+
+The docs can also be easily generated and read locally. This is quite fast
+(same order as compiling the code itself) and no special tools or environment
+are needed. This has the added advantage that they will be tailored to
+the particular kernel configuration used. To generate them, use the ``rustdoc``

Documentation/rust/general-information.rst line 35

Quoted 10 lines
Documentation/rust/general-information.rst new file +10 -0
+target with the same invocation used for compilation, e.g.::
+
+	make LLVM=1 rustdoc
+
+To read the docs locally in your web browser, run e.g.::
+
+	xdg-open rust/doc/kernel/index.html
+
+To learn about how to write the documentation, please see the coding guidelines
+at :ref:`Documentation/rust/coding-guidelines.rst <rust_coding_guidelines>`.

at Documentation/rust/coding-guidelines.rst.

Quoted 51 lines
Documentation/rust/general-information.rst new file +45 -0
+
+
+Extra lints
+-----------
+
+While ``rustc`` is a very helpful compiler, some extra lints and analyses are
+available via ``clippy``, a Rust linter. To enable it, pass ``CLIPPY=1`` to
+the same invocation used for compilation, e.g.::
+
+	make LLVM=1 CLIPPY=1
+
+Please note that Clippy may change code generation, thus it should not be
+enabled while building a production kernel.
+
+
+Abstractions vs. bindings
+-------------------------
+
+Abstractions are Rust code wrapping kernel functionality from the C side.
+
+In order to use functions and types from the C side, bindings are created.
+Bindings are the declarations for Rust of those functions and types from
+the C side.
+
+For instance, one may write a ``Mutex`` abstraction in Rust which wraps
+a ``struct mutex`` from the C side and calls its functions through the bindings.
+
+Abstractions are not available for all the kernel internal APIs and concepts,
+but it is intended that coverage is expanded as time goes on. "Leaf" modules
+(e.g. drivers) should not use the C bindings directly. Instead, subsystems
+should provide as-safe-as-possible abstractions as needed.
+
+
+Conditional compilation
+-----------------------
+
+Rust code has access to conditional compilation based on the kernel
+configuration:
+
+.. code-block:: rust
+
+	#[cfg(CONFIG_X)]       // Enabled               (`y` or `m`)
+	#[cfg(CONFIG_X="y")]   // Enabled as a built-in (`y`)
+	#[cfg(CONFIG_X="m")]   // Enabled as a module   (`m`)
+	#[cfg(not(CONFIG_X))]  // Disabled
Documentation/rust/index.rst new file +0 -0
new file mode 100644
index 000000000000..6e20af5b723a

Documentation/rust/index.rst line 6

Quoted 6 lines
Documentation/rust/index.rst new file +6 -0
@@ -0,0 +1,21 @@
+Rust
+====
+
+Documentation related to Rust within the kernel. To start using Rust
+in the kernel, please read the
+:ref:`Documentation/rust/quick-start.rst <rust_quick_start>` guide.

in the kernel, please read the guide in Documentation/rust/quick-start.rst.

Quoted 18 lines
Documentation/rust/index.rst new file +15 -0
+
+.. toctree::
+    :maxdepth: 1
+
+    quick-start
+    general-information
+    coding-guidelines
+    arch-support
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
Documentation/rust/logo.svg new file +0 -0
new file mode 100644
index 000000000000..65be792a5abe

Documentation/rust/logo.svg

Quoted 1 line
Documentation/rust/logo.svg new file +0 -1
--- /dev/null

How about adding a suitable license identifier in a comment?
For example, Documentation/userspace-api/media/v4l/selection.svg carries this:

<?xml version="1.0" encoding="UTF-8"?>
<!-- SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later -->

[hunk of SVG omitted]

Documentation/rust/quick-start.rst line 1

Quoted 7 lines
Documentation/rust/quick-start.rst new file +1 -0
new file mode 100644
index 000000000000..260393c48379
@@ -0,0 +1,231 @@
+.. _rust_quick_start:

Unnecessary tag.

Quoted 78 lines
Documentation/rust/quick-start.rst new file +78 -0
+
+Quick Start
+===========
+
+This document describes how to get started with kernel development in Rust.
+
+
+Requirements: Building
+----------------------
+
+This section explains how to fetch the tools needed for building.
+
+Some of these requirements might be available from Linux distributions
+under names like ``rustc``, ``rust-src``, ``rust-bindgen``, etc. However,
+at the time of writing, they are likely not to be recent enough unless
+the distribution tracks the latest releases.
+
+To easily check whether the requirements are met, the following target
+can be used::
+
+	make LLVM=1 rustavailable
+
+This triggers the same logic used by Kconfig to determine whether
+``RUST_IS_AVAILABLE`` should be enabled; but it also explains why not
+if that is the case.
+
+
+rustc
+*****
+
+A particular version of the Rust compiler is required. Newer versions may or
+may not work because, for the moment, the kernel depends on some unstable
+Rust features.
+
+If ``rustup`` is being used, enter the checked out source code directory
+and run::
+
+	rustup override set $(scripts/min-tool-version.sh rustc)
+
+Otherwise, fetch a standalone installer or install ``rustup`` from:
+
+	https://www.rust-lang.org
+
+
+Rust standard library source
+****************************
+
+The Rust standard library source is required because the build system will
+cross-compile ``core`` and ``alloc``.
+
+If ``rustup`` is being used, run::
+
+	rustup component add rust-src
+
+The components are installed per toolchain, thus upgrading the Rust compiler
+version later on requires re-adding the component.
+
+Otherwise, if a standalone installer is used, the Rust repository may be cloned
+into the installation folder of the toolchain::
+
+	git clone --recurse-submodules \
+		--branch $(scripts/min-tool-version.sh rustc) \
+		https://github.com/rust-lang/rust \
+		$(rustc --print sysroot)/lib/rustlib/src/rust
+
+In this case, upgrading the Rust compiler version later on requires manually
+updating this clone.
+
+
+libclang
+********
+
+``libclang`` (part of LLVM) is used by ``bindgen`` to understand the C code
+in the kernel, which means LLVM needs to be installed; like when the kernel
+is compiled with ``CC=clang`` or ``LLVM=1``.
+
+Linux distributions are likely to have a suitable one available, so it is
+best to check that first.

Documentation/rust/quick-start.rst line 89

Quoted 10 lines
Documentation/rust/quick-start.rst new file +10 -0
+
+There are also some binaries for several systems and architectures uploaded at:
+
+	https://releases.llvm.org/download.html
+
+Otherwise, building LLVM takes quite a while, but it is not a complex process:
+
+	https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm
+
+See :ref:`Documentation/kbuild/llvm.rst <kbuild_llvm>` for more information and

See Documentation/kbuild/llvm.rst for more information and

Quoted 17 lines
Documentation/rust/quick-start.rst new file +17 -0
+further ways to fetch pre-built releases and distribution packages.
+
+
+bindgen
+*******
+
+The bindings to the C side of the kernel are generated at build time using
+the ``bindgen`` tool. A particular version is required.
+
+Install it via (note that this will download and build the tool from source)::
+
+	cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen
+
+
+Requirements: Developing
+------------------------
+

Documentation/rust/quick-start.rst line 116

Quoted 10 lines
Documentation/rust/quick-start.rst new file +10 -0
+This section explains how to fetch the tools needed for developing. That is,
+they are not needed when just building the kernel.
+
+
+rustfmt
+*******
+
+The ``rustfmt`` tool is used to automatically format all the Rust kernel code,
+including the generated C bindings (for details, please see
+:ref:`Documentation/rust/coding-guidelines.rst <rust_coding_guidelines>`).

Documentation/rust/coding-guidelines.rst).

Quoted 6 lines
Documentation/rust/quick-start.rst new file +6 -0
+
+If ``rustup`` is being used, its ``default`` profile already installs the tool,
+thus nothing needs to be done. If another profile is being used, the component
+can be installed manually::
+
+	rustup component add rustfmt

Documentation/rust/quick-start.rst line 132

Quoted 10 lines
Documentation/rust/quick-start.rst new file +10 -0
+
+The standalone installers also come with ``rustfmt``.
+
+
+clippy
+******
+
+``clippy`` is a Rust linter. Running it provides extra warnings for Rust code.
+It can be run by passing ``CLIPPY=1`` to ``make`` (for details, please see
+:ref:`Documentation/rust/general-information.rst <rust_general_information>`).

Documentation/rust/general-information.rst).

Quoted 20 lines
Documentation/rust/quick-start.rst new file +20 -0
+
+If ``rustup`` is being used, its ``default`` profile already installs the tool,
+thus nothing needs to be done. If another profile is being used, the component
+can be installed manually::
+
+	rustup component add clippy
+
+The standalone installers also come with ``clippy``.
+
+
+cargo
+*****
+
+``cargo`` is the Rust native build system. It is currently required to run
+the tests since it is used to build a custom standard library that contains
+the facilities provided by the custom ``alloc`` in the kernel. The tests can
+be run using the ``rusttest`` Make target.
+
+If ``rustup`` is being used, all the profiles already install the tool,
+thus nothing needs to be done.

Documentation/rust/quick-start.rst line 162

Quoted 10 lines
Documentation/rust/quick-start.rst new file +10 -0
+
+The standalone installers also come with ``cargo``.
+
+
+rustdoc
+*******
+
+``rustdoc`` is the documentation tool for Rust. It generates pretty HTML
+documentation for Rust code (for details, please see
+:ref:`Documentation/rust/general-information.rst <rust_general_information>`).

Documentation/rust/general-information.rst).

Quoted 72 lines
Documentation/rust/quick-start.rst new file +69 -0
+
+``rustdoc`` is also used to test the examples provided in documented Rust code
+(called doctests or documentation tests). The ``rusttest`` Make target uses
+this feature.
+
+If ``rustup`` is being used, all the profiles already install the tool,
+thus nothing needs to be done.
+
+The standalone installers also come with ``rustdoc``.
+
+
+rust-analyzer
+*************
+
+The `rust-analyzer <https://rust-analyzer.github.io/>`_ language server can
+be used with many editors to enable syntax highlighting, completion, go to
+definition, and other features.
+
+``rust-analyzer`` needs a configuration file, ``rust-project.json``, which
+can be generated by the ``rust-analyzer`` Make target.
+
+
+Configuration
+-------------
+
+``Rust support`` (``CONFIG_RUST``) needs to be enabled in the ``General setup``
+menu. The option is only shown if a suitable Rust toolchain is found (see
+above). In turn, this will make visible the rest of options that depend on Rust.
+
+Afterwards, go to::
+
+	Kernel hacking
+	    -> Sample kernel code
+	        -> Rust samples
+
+And enable some sample modules either as built-in or as loadable.
+
+
+Building
+--------
+
+Building a kernel with a complete LLVM toolchain is the best supported setup
+at the moment. That is::
+
+	make LLVM=1
+
+For architectures that do not support a full LLVM toolchain, use::
+
+	make CC=clang
+
+Using GCC also works for some configurations, but it is very experimental at
+the moment.
+
+
+Hacking
+-------
+
+To dive deeper, take a look at the source code of the samples
+at ``samples/rust/``, the Rust support code under ``rust/`` and
+the ``Rust hacking`` menu under ``Kernel hacking``.
+
+If GDB/Binutils is used and Rust symbols are not getting demangled, the reason
+is the toolchain does not support Rust's new v0 mangling scheme yet.
+There are a few ways out:
+
+  - Install a newer release (GDB >= 10.2, Binutils >= 2.36).
+
+  - Some versions of GDB (e.g. vanilla GDB 10.1) are able to use
+    the pre-demangled names embedded in the debug info (``CONFIG_DEBUG_INFO``).
Signature · 1 line
2.35.1

Notes:

Those cross-references of plain path such as

Documentation/rust/general-information.rst

are recognized when you build by the top level "make htmldocs". If you specify a subdirectory by "make SPHINXDIRS=rust htmldocs", current build script can't recognize them. This is one of (not widely recognized) issues in subdirectory handling of automarkup.py. Hopefully, they can be resolved soon.

Tags at the top of .rst files are redundant and should be avoided. Existing ones can be removed after referencing sites are updated.

Thanks, Akira

#35 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

Hi Akira,

Quoted 2 lines · Akira Yokosawa

Please find inline comments WRT ReST-in-kereneldoc.

Thanks a lot for the detailed review & references. I will apply the suggestions.

Cheers,
Miguel

#36 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

In reply to Akira Yokosawa

[Dropped most CCs]

Hi Miguel.
I have a follow-up hint on cross referencing for you. See below.

Quoted 8 lines · Akira Yokosawa

Hi,

Please find inline comments WRT ReST-in-kereneldoc.

Jon, if I'm missing something, please enlighten me.

On Sat, 12 Feb 2022 14:03:41 +0100,
Miguel Ojeda <[email protected]> wrote:

[...]

Quoted 36 lines

Documentation/rust/general-information.rst line 1

Quoted 7 lines
Documentation/rust/general-information.rst new file +1 -0
new file mode 100644
index 000000000000..9ee4c6994d08
@@ -0,0 +1,80 @@
+.. _rust_general_information:

Unnecessary tag.

Quoted 27 lines
Documentation/rust/general-information.rst new file +27 -0
+
+General Information
+===================
+
+This document contains useful information to know when working with
+the Rust support in the kernel.
+
+
+Code documentation
+------------------
+
+Rust kernel code is documented using ``rustdoc``, its built-in documentation
+generator.
+
+The generated HTML docs include integrated search, linked items (e.g. types,
+functions, constants), source code, etc. They may be read at (TODO: link when
+in mainline and generated alongside the rest of the documentation):
+
+	http://kernel.org/
+
+The docs can also be easily generated and read locally. This is quite fast
+(same order as compiling the code itself) and no special tools or environment
+are needed. This has the added advantage that they will be tailored to
+the particular kernel configuration used. To generate them, use the ``rustdoc``
+target with the same invocation used for compilation, e.g.::
+
+	make LLVM=1 rustdoc
Quoted 8 lines

Documentation/rust/general-information.rst line 35

Quoted 7 lines
Documentation/rust/general-information.rst new file +7 -0
+
+To read the docs locally in your web browser, run e.g.::
+
+	xdg-open rust/doc/kernel/index.html
+
+To learn about how to write the documentation, please see the coding guidelines
+at :ref:`Documentation/rust/coding-guidelines.rst <rust_coding_guidelines>`.

at Documentation/rust/coding-guidelines.rst.

Here, the cross reference is internal to Documentation/rust/.
In this case, a relative path works for both top and subdirectory level build. So you can say:

at coding-guidelines.rst.

Quoted 51 lines
Quoted 51 lines
Documentation/rust/general-information.rst new file +45 -0
+
+
+Extra lints
+-----------
+
+While ``rustc`` is a very helpful compiler, some extra lints and analyses are
+available via ``clippy``, a Rust linter. To enable it, pass ``CLIPPY=1`` to
+the same invocation used for compilation, e.g.::
+
+	make LLVM=1 CLIPPY=1
+
+Please note that Clippy may change code generation, thus it should not be
+enabled while building a production kernel.
+
+
+Abstractions vs. bindings
+-------------------------
+
+Abstractions are Rust code wrapping kernel functionality from the C side.
+
+In order to use functions and types from the C side, bindings are created.
+Bindings are the declarations for Rust of those functions and types from
+the C side.
+
+For instance, one may write a ``Mutex`` abstraction in Rust which wraps
+a ``struct mutex`` from the C side and calls its functions through the bindings.
+
+Abstractions are not available for all the kernel internal APIs and concepts,
+but it is intended that coverage is expanded as time goes on. "Leaf" modules
+(e.g. drivers) should not use the C bindings directly. Instead, subsystems
+should provide as-safe-as-possible abstractions as needed.
+
+
+Conditional compilation
+-----------------------
+
+Rust code has access to conditional compilation based on the kernel
+configuration:
+
+.. code-block:: rust
+
+	#[cfg(CONFIG_X)]       // Enabled               (`y` or `m`)
+	#[cfg(CONFIG_X="y")]   // Enabled as a built-in (`y`)
+	#[cfg(CONFIG_X="m")]   // Enabled as a module   (`m`)
+	#[cfg(not(CONFIG_X))]  // Disabled
Documentation/rust/index.rst new file +0 -0
new file mode 100644
index 000000000000..6e20af5b723a
Quoted 8 lines

Documentation/rust/index.rst line 6

Quoted 7 lines
Documentation/rust/index.rst new file +6 -0
@@ -0,0 +1,21 @@
+Rust
+====
+
+Documentation related to Rust within the kernel. To start using Rust
+in the kernel, please read the
+:ref:`Documentation/rust/quick-start.rst <rust_quick_start>` guide.

in the kernel, please read the guide in Documentation/rust/quick-start.rst.

in the kernel, please read the guide in quick-start.rst.

, and so on.

Thanks, Akira

[...]

Quoted 18 lines

Notes:

Those cross-references of plain path such as

Documentation/rust/general-information.rst

are recognized when you build by the top level "make htmldocs". If you specify a subdirectory by "make SPHINXDIRS=rust htmldocs", current build script can't recognize them. This is one of (not widely recognized) issues in subdirectory handling of automarkup.py. Hopefully, they can be resolved soon.

Tags at the top of .rst files are redundant and should be avoided. Existing ones can be removed after referencing sites are updated.

Thanks, Akira

#37 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

Hi Akira,

Quoted 6 lines · Akira Yokosawa

Here, the cross reference is internal to Documentation/rust/.
In this case, a relative path works for both top and subdirectory level build. So you can say:

at coding-guidelines.rst.

That is quite neat -- thanks! Will definitely do.

Cheers,
Miguel

#38 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

In reply to Akira Yokosawa

Hi Akira,

Quoted 7 lines · Akira Yokosawa

Documentation/rust/logo.svg

Quoted 5 lines
Documentation/rust/logo.svg new file +0 -1
new file mode 100644
index 000000000000..65be792a5abe
--- /dev/null

How about adding a suitable license identifier in a comment?

For the next round, I did not apply this suggestion, because it is unclear which license identifier to use: it would be probably be the same as the COPYING-logo one (which would be used also for the Tux SVG, if it gets merged -- it was sent a while ago).

Cheers,
Miguel

#39 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

Hi Miguel,

Quoted 11 lines · Miguel Ojeda

Hi Akira,

Quoted 7 lines · Akira Yokosawa

Documentation/rust/logo.svg

Quoted 5 lines
Documentation/rust/logo.svg new file +0 -1
new file mode 100644
index 000000000000..65be792a5abe
--- /dev/null

How about adding a suitable license identifier in a comment?

Quoted 4 lines

For the next round, I did not apply this suggestion, because it is unclear which license identifier to use: it would be probably be the same as the COPYING-logo one (which would be used also for the Tux SVG, if it gets merged -- it was sent a while ago).

I see.

As I see v2 15/20, the SVG figure is among other documentation updates. IIUC, this figure/logo was in PNG at first, but Jon suggested vector graphics. If this is the case, it deserves an individual patch with a changelog explaining why it is in SVG, where the Tux figure came from, what was the original PNG logo, who contributed the SVG conversion, etc.

I understand you did all the SVG work, didn't you?
I don't think those many Co-developed-by tags apply to this figure.

I'm saying this because this figure/logo can be reused in other open- source projects on its own. It would be worth clarifying its origin in the Git history as well as in COPYING-logo.

Thanks, Akira

Quoted 3 lines

Cheers,
Miguel

#40 lore raw

Re: [PATCH v4 15/20] docs: add Rust documentation

Hi Akira,

Quoted 6 lines · Akira Yokosawa

As I see v2 15/20, the SVG figure is among other documentation updates. IIUC, this figure/logo was in PNG at first, but Jon suggested vector graphics. If this is the case, it deserves an individual patch with a changelog explaining why it is in SVG, where the Tux figure came from, what was the original PNG logo, who contributed the SVG conversion, etc.

Yeah, I can split the figure into another patch for the next round. Though one could argue the same for other files -- do you prefer to have more granular patches in general?

Quoted 2 lines

I understand you did all the SVG work, didn't you?
I don't think those many Co-developed-by tags apply to this figure.

Yeah, I made the logo, but I reused the SVG forms of both the Rust and the Tux logos.

The Tux SVG conversion (from Larry Ewing's one) was done by Garrett LeSage and IFo Hancroft, please see
https://lore.kernel.org/lkml/[email protected]/ for details on that one.

I will add these details to the split patch.

Quoted 3 lines

I'm saying this because this figure/logo can be reused in other open- source projects on its own. It would be worth clarifying its origin in the Git history as well as in COPYING-logo.

I think the Tux SVG logo would be the most useful for other projects, which is why I submitted it to be added to the tree with the permission of Garrett and IFo (see link above). I am not sure if other open-source projects would need the Rust for Linux one, though, so it sounds like a good idea. I am happy to split the patch, clarify the origin and to add a COPYING-logo to the Documentation/rust folder too (pointing to the main one at Documentation/ maybe).

Cheers,
Miguel

author maintainer
#41 lore raw

PATCH v4 16/20 Kbuild: add Rust support

In reply to Miguel Ojeda

Having all the new files in place, we now enable Rust support in the build system, including Kconfig entries related to Rust, the Rust configuration printer, the target definition files, the version detection script and a few other bits.

In the future, we will likely want to generate the target files on the fly via a script.

---
 .gitignore                                   |   5 +
 .rustfmt.toml                                |  12 +
 Makefile                                     | 154 +++++++-
 arch/arm/rust/target.json                    |  27 ++
 arch/arm64/rust/target.json                  |  34 ++
 arch/powerpc/rust/target.json                |  29 ++
 arch/riscv/Makefile                          |   1 +
 arch/riscv/rust/rv32ima.json                 |  36 ++
 arch/riscv/rust/rv32imac.json                |  36 ++
 arch/riscv/rust/rv64ima.json                 |  36 ++
 arch/riscv/rust/rv64imac.json                |  36 ++
 arch/x86/rust/target.json                    |  36 ++
 init/Kconfig                                 |  45 ++-
 lib/Kconfig.debug                            | 144 +++++++
 rust/.gitignore                              |   7 +
 rust/Makefile                                | 374 +++++++++++++++++++
 rust/bindgen_parameters                      |  13 +
 scripts/Kconfig.include                      |   6 +-
 scripts/Makefile.build                       |  65 ++++
 scripts/Makefile.debug                       |  10 +
 scripts/Makefile.lib                         |  12 +
 scripts/Makefile.modfinal                    |   8 +-
 scripts/cc-version.sh                        |  12 +-
 scripts/is_rust_module.sh                    |  13 +
 scripts/kconfig/confdata.c                   |  75 ++++
 scripts/min-tool-version.sh                  |   6 +
 scripts/rust-is-available-bindgen-libclang.h |   2 +
 scripts/rust-is-available.sh                 | 158 ++++++++
 28 files changed, 1372 insertions(+), 20 deletions(-)
 create mode 100644 .rustfmt.toml
 create mode 100644 arch/arm/rust/target.json
 create mode 100644 arch/arm64/rust/target.json
 create mode 100644 arch/powerpc/rust/target.json
 create mode 100644 arch/riscv/rust/rv32ima.json
 create mode 100644 arch/riscv/rust/rv32imac.json
 create mode 100644 arch/riscv/rust/rv64ima.json
 create mode 100644 arch/riscv/rust/rv64imac.json
 create mode 100644 arch/x86/rust/target.json
 create mode 100644 rust/.gitignore
 create mode 100644 rust/Makefile
 create mode 100644 rust/bindgen_parameters
 create mode 100755 scripts/is_rust_module.sh
 create mode 100644 scripts/rust-is-available-bindgen-libclang.h
 create mode 100755 scripts/rust-is-available.sh
.gitignore +5 -0
index 7afd412dadd2..48c68948f476 100644
@@ -37,6 +37,7 @@
 *.o
 *.o.*
 *.patch
+*.rmeta
 *.s
 *.so
 *.so.dbg
@@ -96,6 +97,7 @@ modules.order
 !.gitattributes
 !.gitignore
 !.mailmap
+!.rustfmt.toml
 
 #
 # Generated include files
@@ -161,3 +163,6 @@ x509.genkey
 
 # Documentation toolchain
 sphinx_*/
+
+# Rust analyzer configuration
+/rust-project.json
.rustfmt.toml new file +12 -0
new file mode 100644
index 000000000000..3de5cc497465
@@ -0,0 +1,12 @@
+edition = "2021"
+newline_style = "Unix"
+
+# Unstable options that help catching some mistakes in formatting and that we may want to enable
+# when they become stable.
+#
+# They are kept here since they are useful to run from time to time.
+#format_code_in_doc_comments = true
+#reorder_impl_items = true
+#comment_width = 100
+#wrap_comments = true
+#normalize_comments = true
Makefile +147 -7

284 lines not on this page · raw message

arch/arm/rust/target.json new file +27 -0
new file mode 100644
index 000000000000..3f845b8221dc
@@ -0,0 +1,27 @@
+{
+  "arch": "arm",
+  "crt-static-respected": true,
+  "data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
+  "dynamic-linking": true,
+  "env": "gnu",
+  "executables": true,
+  "features": "+strict-align,+v6",
+  "function-sections": false,
+  "has-elf-tls": true,
+  "has-rpath": true,
+  "linker-is-gnu": true,
+  "llvm-target": "arm-unknown-linux-gnueabi",
+  "max-atomic-width": 64,
+  "os": "linux",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack"
+    ]
+  },
+  "relocation-model": "static",
+  "target-family": "unix",
+  "target-mcount": "\u0001__gnu_mcount_nc",
+  "target-pointer-width": "32"
+}
arch/arm64/rust/target.json new file +34 -0
new file mode 100644
index 000000000000..09a264df26c7
@@ -0,0 +1,34 @@
+{
+  "arch": "aarch64",
+  "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
+  "disable-redzone": true,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+strict-align,+neon,+fp-armv8",
+  "frame-pointer": "always",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "aarch64-unknown-none",
+  "max-atomic-width": 128,
+  "needs-plt": true,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m64"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "stack-probes": {
+    "kind": "none"
+  },
+  "target-c-int-width": "32",
+  "target-endian": "little",
+  "target-pointer-width": "64",
+  "vendor": ""
+}
arch/powerpc/rust/target.json new file +29 -0
new file mode 100644
index 000000000000..2420c8e6a520
@@ -0,0 +1,29 @@
+{
+  "arch": "powerpc64",
+  "code-model": "large",
+  "cpu": "ppc64le",
+  "data-layout": "e-m:e-i64:64-n32:64",
+  "env": "gnu",
+  "features": "-altivec,-vsx,-hard-float",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "powerpc64le-elf",
+  "max-atomic-width": 64,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m64"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "target-family": "unix",
+  "target-mcount": "_mcount",
+  "target-endian": "little",
+  "target-pointer-width": "64"
+}
arch/riscv/Makefile +1 -0
index 8a107ed18b0d..0487db1e54c6 100644
@@ -52,6 +52,7 @@ riscv-march-$(CONFIG_FPU)		:= $(riscv-march-y)fd
 riscv-march-$(CONFIG_RISCV_ISA_C)	:= $(riscv-march-y)c
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
+KBUILD_RUST_TARGET := $(srctree)/arch/riscv/rust/$(subst fd,,$(riscv-march-y)).json
 
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
arch/riscv/rust/rv32ima.json new file +36 -0
new file mode 100644
index 000000000000..bcdda88c1604
@@ -0,0 +1,36 @@
+{
+  "arch": "riscv32",
+  "code-model": "medium",
+  "cpu": "generic-rv32",
+  "data-layout": "e-m:e-p:32:32-i64:64-n32-S128",
+  "disable-redzone": true,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a",
+  "frame-pointer": "always",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "riscv32",
+  "max-atomic-width": 32,
+  "needs-plt": true,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m32"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "stack-probes": {
+    "kind": "none"
+  },
+  "target-c-int-width": "32",
+  "target-endian": "little",
+  "target-pointer-width": "32",
+  "vendor": ""
+}
arch/riscv/rust/rv32imac.json new file +36 -0
new file mode 100644
index 000000000000..45873c10a5c3
@@ -0,0 +1,36 @@
+{
+  "arch": "riscv32",
+  "code-model": "medium",
+  "cpu": "generic-rv32",
+  "data-layout": "e-m:e-p:32:32-i64:64-n32-S128",
+  "disable-redzone": true,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a,+c",
+  "frame-pointer": "always",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "riscv32",
+  "max-atomic-width": 32,
+  "needs-plt": true,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m32"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "stack-probes": {
+    "kind": "none"
+  },
+  "target-c-int-width": "32",
+  "target-endian": "little",
+  "target-pointer-width": "32",
+  "vendor": ""
+}
arch/riscv/rust/rv64ima.json new file +36 -0
new file mode 100644
index 000000000000..853d758c5461
@@ -0,0 +1,36 @@
+{
+  "arch": "riscv64",
+  "code-model": "medium",
+  "cpu": "generic-rv64",
+  "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
+  "disable-redzone": true,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a",
+  "frame-pointer": "always",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "riscv64",
+  "max-atomic-width": 64,
+  "needs-plt": true,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m64"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "stack-probes": {
+    "kind": "none"
+  },
+  "target-c-int-width": "32",
+  "target-endian": "little",
+  "target-pointer-width": "64",
+  "vendor": ""
+}
arch/riscv/rust/rv64imac.json new file +36 -0
new file mode 100644
index 000000000000..ce50ee8e8c93
@@ -0,0 +1,36 @@
+{
+  "arch": "riscv64",
+  "code-model": "medium",
+  "cpu": "generic-rv64",
+  "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
+  "disable-redzone": true,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a,+c",
+  "frame-pointer": "always",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "riscv64",
+  "max-atomic-width": 64,
+  "needs-plt": true,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m64"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "stack-probes": {
+    "kind": "none"
+  },
+  "target-c-int-width": "32",
+  "target-endian": "little",
+  "target-pointer-width": "64",
+  "vendor": ""
+}
arch/x86/rust/target.json new file +36 -0
new file mode 100644
index 000000000000..379cf39e8941
@@ -0,0 +1,36 @@
+{
+  "arch": "x86_64",
+  "code-model": "kernel",
+  "cpu": "x86-64",
+  "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
+  "disable-redzone": true,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
+  "frame-pointer": "always",
+  "function-sections": false,
+  "linker-flavor": "gcc",
+  "linker-is-gnu": true,
+  "llvm-target": "x86_64-elf",
+  "max-atomic-width": 64,
+  "needs-plt": true,
+  "os": "none",
+  "panic-strategy": "abort",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-Wl,--as-needed",
+      "-Wl,-z,noexecstack",
+      "-m64"
+    ]
+  },
+  "relocation-model": "static",
+  "relro-level": "full",
+  "stack-probes": {
+    "kind": "none"
+  },
+  "target-c-int-width": "32",
+  "target-endian": "little",
+  "target-pointer-width": "64",
+  "vendor": "unknown"
+}
init/Kconfig +44 -1

63 lines not on this page · raw message

lib/Kconfig.debug +144 -0

150 lines not on this page · raw message

rust/.gitignore new file +7 -0
new file mode 100644
index 000000000000..168cb26a31b9
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+bindings_generated.rs
+bindings_helpers_generated.rs
+exports_*_generated.h
+doc/
+test/
rust/Makefile new file +374 -0

374 lines not on this page · raw message

rust/bindgen_parameters new file +13 -0
new file mode 100644
index 000000000000..c2cc4a88234e
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+--opaque-type xregs_state
+--opaque-type desc_struct
+--opaque-type arch_lbr_state
+--opaque-type local_apic
+
+# If SMP is disabled, `arch_spinlock_t` is defined as a ZST which triggers a Rust
+# warning. We don't need to peek into it anyway.
+--opaque-type spinlock
+
+# `seccomp`'s comment gets understood as a doctest
+--no-doc-comments
scripts/Kconfig.include +3 -3
index 0496efd6e117..83e850321eb6 100644
@@ -36,12 +36,12 @@ ld-option = $(success,$(LD) -v $(1))
 as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler -o /dev/null -)
 
 # check if $(CC) and $(LD) exist
-$(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found)
+$(error-if,$(failure,command -v $(CC)),C compiler '$(CC)' not found)
 $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found)
 
-# Get the compiler name, version, and error out if it is not supported.
+# Get the C compiler name, version, and error out if it is not supported.
 cc-info := $(shell,$(srctree)/scripts/cc-version.sh $(CC))
-$(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this compiler is not supported.)
+$(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this C compiler is not supported.)
 cc-name := $(shell,set -- $(cc-info) && echo $1)
 cc-version := $(shell,set -- $(cc-info) && echo $2)
 
scripts/Makefile.build +65 -0

77 lines not on this page · raw message

scripts/Makefile.debug +10 -0
index 9f39b0130551..fe87389d52c0 100644
@@ -1,4 +1,5 @@
 DEBUG_CFLAGS	:=
+DEBUG_RUSTFLAGS	:=
 
 ifdef CONFIG_DEBUG_INFO_SPLIT
 DEBUG_CFLAGS	+= -gsplit-dwarf
@@ -10,6 +11,12 @@ ifndef CONFIG_AS_IS_LLVM
 KBUILD_AFLAGS	+= -Wa,-gdwarf-2
 endif
 
+ifdef CONFIG_DEBUG_INFO_REDUCED
+DEBUG_RUSTFLAGS += -Cdebuginfo=1
+else
+DEBUG_RUSTFLAGS += -Cdebuginfo=2
+endif
+
 ifndef CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
 dwarf-version-$(CONFIG_DEBUG_INFO_DWARF4) := 4
 dwarf-version-$(CONFIG_DEBUG_INFO_DWARF5) := 5
@@ -31,3 +38,6 @@ endif
 
 KBUILD_CFLAGS += $(DEBUG_CFLAGS)
 export DEBUG_CFLAGS
+
+KBUILD_RUSTFLAGS += $(DEBUG_RUSTFLAGS)
+export DEBUG_RUSTFLAGS
scripts/Makefile.lib +12 -0
index 79be57fdd32a..6ac8ae2fc3b6 100644
@@ -8,6 +8,7 @@ ldflags-y  += $(EXTRA_LDFLAGS)
 # flags that take effect in current and sub directories
 KBUILD_AFLAGS += $(subdir-asflags-y)
 KBUILD_CFLAGS += $(subdir-ccflags-y)
+KBUILD_RUSTFLAGS += $(subdir-rustflags-y)
 
 # Figure out what we need to build from the various variables
 # ===========================================================================
@@ -133,6 +134,10 @@ _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), \
                      $(filter-out $(ccflags-remove-y), \
                          $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(ccflags-y)) \
                      $(CFLAGS_$(target-stem).o))
+_rust_flags    = $(filter-out $(RUSTFLAGS_REMOVE_$(target-stem).o), \
+                     $(filter-out $(rustflags-remove-y), \
+                         $(KBUILD_RUSTFLAGS) $(rustflags-y)) \
+                     $(RUSTFLAGS_$(target-stem).o))
 _a_flags       = $(filter-out $(AFLAGS_REMOVE_$(target-stem).o), \
                      $(filter-out $(asflags-remove-y), \
                          $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(asflags-y)) \
@@ -207,6 +212,11 @@ modkern_cflags =                                          \
 		$(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
 		$(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL) $(modfile_flags))
 
+modkern_rustflags =                                              \
+	$(if $(part-of-module),                                   \
+		$(KBUILD_RUSTFLAGS_MODULE) $(RUSTFLAGS_MODULE), \
+		$(KBUILD_RUSTFLAGS_KERNEL) $(RUSTFLAGS_KERNEL))
+
 modkern_aflags = $(if $(part-of-module),				\
 			$(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE),	\
 			$(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL))
@@ -216,6 +226,8 @@ c_flags        = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
 		 $(_c_flags) $(modkern_cflags)                           \
 		 $(basename_flags) $(modname_flags)
 
+rust_flags     = $(_rust_flags) $(modkern_rustflags) @$(objtree)/include/generated/rustc_cfg
+
 a_flags        = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
 		 $(_a_flags) $(modkern_aflags)
 
scripts/Makefile.modfinal +5 -3
index 7f39599e9fae..670d7997a38b 100644
@@ -39,11 +39,13 @@ quiet_cmd_ld_ko_o = LD [M]  $@
 
 quiet_cmd_btf_ko = BTF [M] $@
       cmd_btf_ko = 							\
-	if [ -f vmlinux ]; then						\
+	if [ ! -f vmlinux ]; then					\
+		printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
+	elif [ -n "$(CONFIG_RUST)" ] && $(srctree)/scripts/is_rust_module.sh $@; then 		\
+		printf "Skipping BTF generation for %s because it's a Rust module\n" $@ 1>&2; \
+	else								\
 		LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) --btf_base vmlinux $@; \
 		$(RESOLVE_BTFIDS) -b vmlinux $@; 			\
-	else								\
-		printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
 	fi;
 
 # Same as newer-prereqs, but allows to exclude specified extra dependencies
scripts/cc-version.sh +6 -6
index f1952c522466..2401c86fcf53 100755
@@ -1,13 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 #
-# Print the compiler name and its version in a 5 or 6-digit form.
+# Print the C compiler name and its version in a 5 or 6-digit form.
 # Also, perform the minimum version check.
 
 set -e
 
-# Print the compiler name and some version components.
-get_compiler_info()
+# Print the C compiler name and some version components.
+get_c_compiler_info()
 {
 	cat <<- EOF | "$@" -E -P -x c - 2>/dev/null
 	#if defined(__clang__)
@@ -32,7 +32,7 @@ get_canonical_version()
 
 # $@ instead of $1 because multiple words might be given, e.g. CC="ccache gcc".
 orig_args="$@"
-set -- $(get_compiler_info "$@")
+set -- $(get_c_compiler_info "$@")
 
 name=$1
 
@@ -52,7 +52,7 @@ ICC)
 	min_version=$($min_tool_version icc)
 	;;
 *)
-	echo "$orig_args: unknown compiler" >&2
+	echo "$orig_args: unknown C compiler" >&2
 	exit 1
 	;;
 esac
@@ -62,7 +62,7 @@ min_cversion=$(get_canonical_version $min_version)
 
 if [ "$cversion" -lt "$min_cversion" ]; then
 	echo >&2 "***"
-	echo >&2 "*** Compiler is too old."
+	echo >&2 "*** C compiler is too old."
 	echo >&2 "***   Your $name version:    $version"
 	echo >&2 "***   Minimum $name version: $min_version"
 	echo >&2 "***"
scripts/is_rust_module.sh new file +13 -0
new file mode 100755
index 000000000000..277a64d07f22
@@ -0,0 +1,13 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# is_rust_module.sh module.ko
+#
+# Returns `0` if `module.ko` is a Rust module, `1` otherwise.
+
+set -e
+
+# Using the `16_` prefix ensures other symbols with the same substring
+# are not picked up (even if it would be unlikely). The last part is
+# used just in case LLVM decides to use the `.` suffix.
+${NM} "$*" | grep -qE '^[0-9a-fA-F]+ r _R[^[:space:]]+16___IS_RUST_MODULE[^[:space:]]*$'
scripts/kconfig/confdata.c +75 -0

99 lines not on this page · raw message

scripts/min-tool-version.sh +6 -0
index 7c20252a90c6..117797d7e0c7 100755
@@ -31,6 +31,12 @@ llvm)
 		echo 11.0.0
 	fi
 	;;
+rustc)
+	echo 1.58.0
+	;;
+bindgen)
+	echo 0.56.0
+	;;
 *)
 	echo "$1: unknown tool" >&2
 	exit 1
scripts/rust-is-available-bindgen-libclang.h new file +2 -0
new file mode 100644
index 000000000000..0ef6db10d674
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#pragma message("clang version " __clang_version__)
scripts/rust-is-available.sh new file +158 -0

158 lines not on this page · raw message

Signature · 7 lines
2.35.1


_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
#42 lore raw

Re: [PATCH v4 16/20] Kbuild: add Rust support

init/Kconfig config PROFILING · line 2059

Quoted 4 lines · Miguel Ojeda
init/Kconfig +4 -0
+config RUST
+	bool "Rust support"
+	depends on RUST_IS_AVAILABLE
+	depends on ARM64 || CPU_32v6 || CPU_32v6K || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || RISCV

Please don't use CPU_32v6* here.

It probably makes more sense to add a symbol "HAVE_RUST" and have the appropriate architecture Kconfig files select HAVE_RUST.

Does Rust support Thumb on ARMv6 and ARMv7 architectures?

init/Kconfig config PROFILING · line 2063

Quoted 4 lines
init/Kconfig +4 -0
+	depends on !MODVERSIONS
+	depends on !GCC_PLUGIN_RANDSTRUCT
+	select CONSTRUCTORS
+	default n

Please remove every utterance of "default n" from your patch; n is the default default which default defaults to, so you don't need to specify default n to make the option default to n. It will default to n purely because n is the default when no default is specified.

init/Kconfig config PROFILING · line 2068

Quoted 5 lines
init/Kconfig +5 -0
+	help
+	  Enables Rust support in the kernel.
+
+	  This allows other Rust-related options, like drivers written in Rust,
+	  to be selected.

As Rust doesn't support all the architectures that the kernel supports, Rust must not be used for core infrastructure.

Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
#43 lore raw

Re: [PATCH v4 16/20] Kbuild: add Rust support

Hi Russell,

Quoted 5 lines · Russell King (Oracle)

Please don't use CPU_32v6* here.

It probably makes more sense to add a symbol "HAVE_RUST" and have the appropriate architecture Kconfig files select HAVE_RUST.

We can do it whatever way arch maintainers prefer, of course. Why would you prefer one over the other?

Quoted 1 line

Does Rust support Thumb on ARMv6 and ARMv7 architectures?

Yes, the main backend is LLVM. Some built-in targets and their support level are listed here, if you want to take a look:

https://doc.rust-lang.org/nightly/rustc/platform-support.html

There is also a GCC backend in rustc [1], which is making good progress and may eventually give us access to architectures supported by GCC. Furthermore, a from-scratch Rust frontend for GCC [2] is being worked on, though this effort will likely take more time to reach a point where it may be used for the kernel.

[1] https://github.com/rust-lang/rust/tree/master/compiler/rustc_codegen_gcc
[2] https://github.com/Rust-GCC/gccrs

Quoted 4 lines

Please remove every utterance of "default n" from your patch; n is the default default which default defaults to, so you don't need to specify default n to make the option default to n. It will default to n purely because n is the default when no default is specified.

Certainly. I am curious, though: is there a reason for most of the other 500+ instances in the kernel tree?

Quoted 2 lines

As Rust doesn't support all the architectures that the kernel supports, Rust must not be used for core infrastructure.

Yeah, although I am not sure I understand what you are getting at here.

Cheers,
Miguel

#44 lore raw

Re: [PATCH v4 16/20] Kbuild: add Rust support

Quoted 5 lines · Miguel Ojeda

Hi Russell,

Quoted 1 line · Russell King (Oracle)
Quoted 7 lines
Quoted 4 lines

Please don't use CPU_32v6* here.

It probably makes more sense to add a symbol "HAVE_RUST" and have the appropriate architecture Kconfig files select HAVE_RUST.

We can do it whatever way arch maintainers prefer, of course. Why would you prefer one over the other?

It would be cleaner, rather than the "depends" line getting longer and longer over time - and if different architecture maintainers change it, it will lead to conflicts.

Quoted 4 lines
Quoted 1 line

Does Rust support Thumb on ARMv6 and ARMv7 architectures?

Yes, the main backend is LLVM. Some built-in targets and their support level are listed here, if you want to take a look:

Right, so why made it dependent on CPU_32v6 || CPU_32v6K if ARMv7 is supported? What about CPU_32v7? What about CPU_32v7M?

I think it would be saner to use the CPU_V6, CPU_V6K, CPU_V7 and maybe CPU_V7M here - even bettern to select "HAVE_RUST" from these symbols, since I'm sure you'd start to see the issue behind my "HAVE_RUST" suggestion as it means having four symbols just for 32-bit ARM on your dependency line.

Quoted 1 line

https://doc.rust-lang.org/nightly/rustc/platform-support.html

Interestingly, it does not list arm-unknown-linux-gnueabihf, which is the "tuple" commonly used to build 32-bit ARM kernels.

Quoted 7 lines
Quoted 4 lines

Please remove every utterance of "default n" from your patch; n is the default default which default defaults to, so you don't need to specify default n to make the option default to n. It will default to n purely because n is the default when no default is specified.

Certainly. I am curious, though: is there a reason for most of the other 500+ instances in the kernel tree?

Probably because people incorrectly think it's required or some other minor reason. As I say:

config FOO
bool/tristate ...

always defaults to 'n' without needing "default n" to be specified.

Let's do some proper research on this. There are 19148 "config" statements in the kernel tree, 521 "default n" and 4818 that specify any kind of "default". That means there are about 14330 config statements that do not specify any kind of default.

So, there are about 27 times more config statements that specify no default than those that specify "default n", so using the argument that there are "500+ instances" and therefore should be seen as correct is completely misguided.

Quoted 4 lines
Quoted 2 lines

As Rust doesn't support all the architectures that the kernel supports, Rust must not be used for core infrastructure.

Yeah, although I am not sure I understand what you are getting at here.

I mean, if we end up with, e.g. a filesystem coded in Rust, that filesystem will not be available on architectures that the kernel supports until either (a) Rust gains support for that architecture or (b) someone re-codes the filesystem in C - at which point, what is the point of having Rust in the kernel?

Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
#45 lore raw

Re: [PATCH v4 16/20] Kbuild: add Rust support

Quoted 9 lines · Russell King (Oracle)

Right, so why made it dependent on CPU_32v6 || CPU_32v6K if ARMv7 is supported? What about CPU_32v7? What about CPU_32v7M?

I think it would be saner to use the CPU_V6, CPU_V6K, CPU_V7 and maybe CPU_V7M here - even bettern to select "HAVE_RUST" from these symbols, since I'm sure you'd start to see the issue behind my "HAVE_RUST" suggestion as it means having four symbols just for 32-bit ARM on your dependency line.

To support arch variations properly we also have to configure the compiler via filling a target spec on the fly, but so far we only have a few static variations as an example. This is one of the missing parts of the arch support. I will let you know when we have something ready.

Quoted 2 lines

Interestingly, it does not list arm-unknown-linux-gnueabihf, which is the "tuple" commonly used to build 32-bit ARM kernels.

I see it there (Tier 2).

Quoted 2 lines

Probably because people incorrectly think it's required or some other minor reason. As I say:

In that case, we should remove them and warn about those instances, assuming the preferred style is to not have it.

Quoted 3 lines

so using the argument
that there are "500+ instances" and therefore should be seen as correct is completely misguided.

I did not use any such argument.

Quoted 2 lines

I mean, if we end up with, e.g. a filesystem coded in Rust, that filesystem will not be available on architectures that the kernel

As long as that filesystem is an optional feature (or as long as there is a C version), it should be fine.

Quoted 1 line

supports until either (a) Rust gains support for that architecture

For this, it would be ideal if entities behind some of the architectures could support LLVM & ClangBuiltLinux, or the GCC Rust frontend, or the GCC backend for rustc.

For instance, Arm is supporting both LLVM and the Rust project.

Quoted 2 lines

or (b) someone re-codes the filesystem in C - at which point, what is the point of having Rust in the kernel?

Having a C version of some system does not mean a Rust version would not offer advantages. In fact, we are adding Rust precisely because we believe it offers some advantages over C, for both end users and maintainers.

(Please see the RFC [1], previous discussions, etc.)

[1] https://lore.kernel.org/lkml/[email protected]/

Cheers,
Miguel

#46 lore raw

Re: [PATCH v4 16/20] Kbuild: add Rust support

In reply to Miguel Ojeda

Hi!

init/Kconfig config PROFILING · line 2059

Quoted 4 lines · Miguel Ojeda
init/Kconfig +4 -0
+config RUST
+	bool "Rust support"
+	depends on RUST_IS_AVAILABLE
+	depends on ARM64 || CPU_32v6 || CPU_32v6K || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || RISCV

Is there any particular reason why this list excludes MIPS*, i386, big-endian PowerPC and SPARC targets which are already supported by the Rust programming language?

Are the arch/$ARCH/rust/target.json files everything that's needed for supporting the other targets?

Thanks,
Adrian

Signature · 10 lines
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - [email protected]
`. `'   Freie Universitaet Berlin - [email protected]
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913


_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
#47 lore raw

Re: [PATCH v4 16/20] Kbuild: add Rust support

Hi John Paul,

Quoted 4 lines · John Paul Adrian Glaubitz

Is there any particular reason why this list excludes MIPS*, i386, big-endian PowerPC and SPARC targets which are already supported by the Rust programming language?

The variations we have so far were intended to showcase the Rust support in several major architectures, rather than cover everything. But as long as LLVM (& the kernel, i.e. ClangBuiltLinux) supports the target (and as long there are no compiler/toolchain issues), you should be able to try it.

Quoted 2 lines

Are the arch/$ARCH/rust/target.json files everything that's needed for supporting the other targets?

Mostly -- there is also rust/kernel/c_types.rs and you may need to tweak rust/compiler_builtins.rs, but not much more.

Note that for the target spec files, the short-term plan is to generate dynamically the target spec file according to what the architecture requests, instead of using these static files. Longer term, we need a Rust-stable way to setup custom targets from upstream rustc (though it is not clear yet how it will look, e.g. it could be via command-line flags).

Cheers,
Miguel

author maintainer
#48 lore raw

PATCH v4 17/20 samples: add Rust examples

In reply to Miguel Ojeda

A set of Rust modules that showcase how Rust modules look like and how to use the abstracted kernel features.

These samples also double as tests in the CI.

The semaphore sample comes with a C version for comparison.

---
 samples/Kconfig                        |   2 +
 samples/Makefile                       |   1 +
 samples/rust/Kconfig                   | 123 ++++++++++++++
 samples/rust/Makefile                  |  13 ++
 samples/rust/rust_chrdev.rs            |  50 ++++++
 samples/rust/rust_minimal.rs           |  35 ++++
 samples/rust/rust_miscdev.rs           | 144 +++++++++++++++++
 samples/rust/rust_module_parameters.rs |  69 ++++++++
 samples/rust/rust_platform.rs          |  22 +++
 samples/rust/rust_print.rs             |  54 +++++++
 samples/rust/rust_random.rs            |  61 +++++++
 samples/rust/rust_semaphore.rs         | 172 ++++++++++++++++++++
 samples/rust/rust_semaphore_c.c        | 212 +++++++++++++++++++++++++
 samples/rust/rust_stack_probing.rs     |  36 +++++
 samples/rust/rust_sync.rs              |  78 +++++++++
 15 files changed, 1072 insertions(+)
 create mode 100644 samples/rust/Kconfig
 create mode 100644 samples/rust/Makefile
 create mode 100644 samples/rust/rust_chrdev.rs
 create mode 100644 samples/rust/rust_minimal.rs
 create mode 100644 samples/rust/rust_miscdev.rs
 create mode 100644 samples/rust/rust_module_parameters.rs
 create mode 100644 samples/rust/rust_platform.rs
 create mode 100644 samples/rust/rust_print.rs
 create mode 100644 samples/rust/rust_random.rs
 create mode 100644 samples/rust/rust_semaphore.rs
 create mode 100644 samples/rust/rust_semaphore_c.c
 create mode 100644 samples/rust/rust_stack_probing.rs
 create mode 100644 samples/rust/rust_sync.rs
samples/Kconfig +2 -0
index 22cc921ae291..9a82039aae49 100644
@@ -250,6 +250,8 @@ config SAMPLE_CORESIGHT_SYSCFG
 	  This demonstrates how a user may create their own CoreSight
 	  configurations and easily load them into the system at runtime.
 
+source "samples/rust/Kconfig"
+
 endif # SAMPLES
 
 config HAVE_SAMPLE_FTRACE_DIRECT
samples/Makefile +1 -0
index 1ae4de99c983..fc5e9760ea32 100644
@@ -33,3 +33,4 @@ subdir-$(CONFIG_SAMPLE_WATCHDOG)	+= watchdog
 subdir-$(CONFIG_SAMPLE_WATCH_QUEUE)	+= watch_queue
 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST)	+= kmemleak/
 obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG)	+= coresight/
+obj-$(CONFIG_SAMPLES_RUST)		+= rust/
samples/rust/Kconfig new file +123 -0

123 lines not on this page · raw message

samples/rust/Makefile new file +13 -0
new file mode 100644
index 000000000000..96ffeb7d334a
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SAMPLE_RUST_MINIMAL)		+= rust_minimal.o
+obj-$(CONFIG_SAMPLE_RUST_PRINT)			+= rust_print.o
+obj-$(CONFIG_SAMPLE_RUST_MODULE_PARAMETERS)	+= rust_module_parameters.o
+obj-$(CONFIG_SAMPLE_RUST_SYNC)			+= rust_sync.o
+obj-$(CONFIG_SAMPLE_RUST_CHRDEV)		+= rust_chrdev.o
+obj-$(CONFIG_SAMPLE_RUST_MISCDEV)		+= rust_miscdev.o
+obj-$(CONFIG_SAMPLE_RUST_STACK_PROBING)		+= rust_stack_probing.o
+obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE)		+= rust_semaphore.o
+obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE_C)		+= rust_semaphore_c.o
+obj-$(CONFIG_SAMPLE_RUST_RANDOM)		+= rust_random.o
+obj-$(CONFIG_SAMPLE_RUST_PLATFORM)		+= rust_platform.o
samples/rust/rust_chrdev.rs new file +50 -0

50 lines not on this page · raw message

samples/rust/rust_minimal.rs new file +35 -0
new file mode 100644
index 000000000000..f0488262bcc9
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust minimal sample.
+
+use kernel::prelude::*;
+
+module! {
+    type: RustMinimal,
+    name: b"rust_minimal",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust minimal sample",
+    license: b"GPL v2",
+}
+
+struct RustMinimal {
+    message: String,
+}
+
+impl KernelModule for RustMinimal {
+    fn init(_name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
+        pr_info!("Rust minimal sample (init)\n");
+        pr_info!("Am I built-in? {}\n", !cfg!(MODULE));
+
+        Ok(RustMinimal {
+            message: "on the heap!".try_to_owned()?,
+        })
+    }
+}
+
+impl Drop for RustMinimal {
+    fn drop(&mut self) {
+        pr_info!("My message is {}\n", self.message);
+        pr_info!("Rust minimal sample (exit)\n");
+    }
+}
samples/rust/rust_miscdev.rs new file +144 -0

144 lines not on this page · raw message

samples/rust/rust_module_parameters.rs new file +69 -0

69 lines not on this page · raw message

samples/rust/rust_platform.rs new file +22 -0
new file mode 100644
index 000000000000..c0b740094c59
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust platform device driver sample.
+
+use kernel::{module_platform_driver, of, platform, prelude::*};
+
+module_platform_driver! {
+    type: Driver,
+    name: b"rust_platform",
+    license: b"GPL v2",
+}
+
+struct Driver;
+impl platform::Driver for Driver {
+    kernel::define_of_id_table! {(), [
+        (of::DeviceId::Compatible(b"rust,sample"), None),
+    ]}
+
+    fn probe(_dev: &mut platform::Device, _id_info: Option<&Self::IdInfo>) -> Result {
+        Ok(())
+    }
+}
samples/rust/rust_print.rs new file +54 -0

54 lines not on this page · raw message

samples/rust/rust_random.rs new file +61 -0

61 lines not on this page · raw message

samples/rust/rust_semaphore.rs new file +172 -0

172 lines not on this page · raw message

samples/rust/rust_semaphore_c.c new file +212 -0

212 lines not on this page · raw message

samples/rust/rust_stack_probing.rs new file +36 -0
new file mode 100644
index 000000000000..214d4d1f6528
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust stack probing sample.
+
+use kernel::prelude::*;
+
+module! {
+    type: RustStackProbing,
+    name: b"rust_stack_probing",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust stack probing sample",
+    license: b"GPL v2",
+}
+
+struct RustStackProbing;
+
+impl KernelModule for RustStackProbing {
+    fn init(_name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
+        pr_info!("Rust stack probing sample (init)\n");
+
+        // Including this large variable on the stack will trigger
+        // stack probing on the supported archs.
+        // This will verify that stack probing does not lead to
+        // any errors if we need to link `__rust_probestack`.
+        let x: [u64; 514] = core::hint::black_box([5; 514]);
+        pr_info!("Large array has length: {}\n", x.len());
+
+        Ok(RustStackProbing)
+    }
+}
+
+impl Drop for RustStackProbing {
+    fn drop(&mut self) {
+        pr_info!("Rust stack probing sample (exit)\n");
+    }
+}
samples/rust/rust_sync.rs new file +78 -0

78 lines not on this page · raw message

Signature · 1 line
2.35.1
author maintainer
#49 lore raw

PATCH v4 18/20 MAINTAINERS: Rust

In reply to Miguel Ojeda

Miguel, Alex and Wedson will be maintaining the Rust support.

---
 MAINTAINERS | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
MAINTAINERS +16 -0
index 69a2935daf6c..17215393ff58 100644
@@ -16795,6 +16795,22 @@ L:	[email protected]
 S:	Maintained
 F:	drivers/infiniband/ulp/rtrs/
 
+RUST
+M:	Miguel Ojeda <[email protected]>
+M:	Alex Gaynor <[email protected]>
+M:	Wedson Almeida Filho <[email protected]>
+L:	[email protected]
+S:	Supported
+W:	https://github.com/Rust-for-Linux/linux
+B:	https://github.com/Rust-for-Linux/linux/issues
+T:	git https://github.com/Rust-for-Linux/linux.git rust-next
+F:	rust/
+F:	samples/rust/
+F:	Documentation/rust/
+F:	lib/rust.h
+F:	scripts/*rust*
+K:	\b(?i:rust)\b
+
 RXRPC SOCKETS (AF_RXRPC)
 M:	David Howells <[email protected]>
 M:	Marc Dionne <[email protected]>
Signature · 1 line
2.35.1
author maintainer
#50 lore raw

RFC PATCH v4 19/20 drivers: gpio: PrimeCell PL061 in Rust

In reply to Miguel Ojeda

From: Wedson Almeida Filho <[email protected]>

A port to Rust of the PrimeCell PL061 GPIO driver.

This module is a work in progress and will be sent for review later on, as well as separately from the Rust support.

However, it is included to show how an actual working module written in Rust may look like.

---
 drivers/gpio/Kconfig            |   8 +
 drivers/gpio/Makefile           |   1 +
 drivers/gpio/gpio_pl061_rust.rs | 370 ++++++++++++++++++++++++++++++++
 3 files changed, 379 insertions(+)
 create mode 100644 drivers/gpio/gpio_pl061_rust.rs
drivers/gpio/Kconfig +8 -0
index 1c211b4c63be..172295770c3d 100644
@@ -471,6 +471,14 @@ config GPIO_PL061
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device.
 
+config GPIO_PL061_RUST
+	tristate "PrimeCell PL061 GPIO support written in Rust"
+	depends on ARM_AMBA && RUST
+	select IRQ_DOMAIN
+	select GPIOLIB_IRQCHIP
+	help
+	  Say yes here to support the PrimeCell PL061 GPIO device
+
 config GPIO_PMIC_EIC_SPRD
 	tristate "Spreadtrum PMIC EIC support"
 	depends on MFD_SC27XX_PMIC || COMPILE_TEST
drivers/gpio/Makefile +1 -0
index edbaa3cb343c..7dc334df9c3f 100644
@@ -117,6 +117,7 @@ obj-$(CONFIG_GPIO_PCIE_IDIO_24)		+= gpio-pcie-idio-24.o
 obj-$(CONFIG_GPIO_PCI_IDIO_16)		+= gpio-pci-idio-16.o
 obj-$(CONFIG_GPIO_PISOSR)		+= gpio-pisosr.o
 obj-$(CONFIG_GPIO_PL061)		+= gpio-pl061.o
+obj-$(CONFIG_GPIO_PL061_RUST)		+= gpio_pl061_rust.o
 obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio-pmic-eic-sprd.o
 obj-$(CONFIG_GPIO_PXA)			+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RASPBERRYPI_EXP)	+= gpio-raspberrypi-exp.o
drivers/gpio/gpio_pl061_rust.rs new file +370 -0

370 lines not on this page · raw message

Signature · 1 line
2.35.1
author maintainer
#51 lore raw

RFC PATCH v4 20/20 drivers: android: Binder IPC in Rust

In reply to Miguel Ojeda

From: Wedson Almeida Filho <[email protected]>

A port to Rust of the Android Binder IPC mechanism.

This module is a work in progress and will be sent for review later on, as well as separately from the Rust support.

However, it is included to show how an actual working module written in Rust may look like.

---
 drivers/android/Kconfig             |   7 +
 drivers/android/Makefile            |   2 +
 drivers/android/allocation.rs       | 266 ++++++++
 drivers/android/context.rs          |  80 +++
 drivers/android/defs.rs             |  99 +++
 drivers/android/node.rs             | 476 ++++++++++++++
 drivers/android/process.rs          | 961 ++++++++++++++++++++++++++++
 drivers/android/range_alloc.rs      | 189 ++++++
 drivers/android/rust_binder.rs      | 111 ++++
 drivers/android/thread.rs           | 871 +++++++++++++++++++++++++
 drivers/android/transaction.rs      | 326 ++++++++++
 include/uapi/linux/android/binder.h |  28 +-
 12 files changed, 3403 insertions(+), 13 deletions(-)
 create mode 100644 drivers/android/allocation.rs
 create mode 100644 drivers/android/context.rs
 create mode 100644 drivers/android/defs.rs
 create mode 100644 drivers/android/node.rs
 create mode 100644 drivers/android/process.rs
 create mode 100644 drivers/android/range_alloc.rs
 create mode 100644 drivers/android/rust_binder.rs
 create mode 100644 drivers/android/thread.rs
 create mode 100644 drivers/android/transaction.rs
drivers/android/Kconfig +7 -0
index 53b22e26266c..7aef7f38f988 100644
@@ -20,6 +20,13 @@ config ANDROID_BINDER_IPC
 	  Android process, using Binder to identify, invoke and pass arguments
 	  between said processes.
 
+config ANDROID_BINDER_IPC_RUST
+	bool "Android Binder IPC Driver in Rust"
+	depends on MMU && RUST
+	default n
+	help
+	  Implementation of the Binder IPC in Rust.
+
 config ANDROID_BINDERFS
 	bool "Android Binderfs filesystem"
 	depends on ANDROID_BINDER_IPC
drivers/android/Makefile +2 -0
index c9d3d0c99c25..c428f2ce2f05 100644
@@ -4,3 +4,5 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+
+obj-$(CONFIG_ANDROID_BINDER_IPC_RUST) += rust_binder.o
drivers/android/allocation.rs new file +266 -0

266 lines not on this page · raw message

drivers/android/context.rs new file +80 -0

80 lines not on this page · raw message

drivers/android/defs.rs new file +99 -0

99 lines not on this page · raw message

drivers/android/node.rs new file +476 -0

476 lines not on this page · raw message

drivers/android/process.rs new file +961 -0

961 lines not on this page · raw message

drivers/android/range_alloc.rs new file +189 -0

189 lines not on this page · raw message

drivers/android/rust_binder.rs new file +111 -0

111 lines not on this page · raw message

drivers/android/thread.rs new file +871 -0

800 lines not on this page · raw message

drivers/android/transaction.rs new file +326 -0

326 lines not on this page · raw message

include/uapi/linux/android/binder.h +15 -13
index 3246f2c74696..ad619623571e 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.35.1

Part of the diff is not shown here. View the raw message.

#52 lore raw

Re: [PATCH v4 00/20] Rust support, nn/nn

In reply to Miguel Ojeda
Quoted 5 lines · Miguel Ojeda

Rust support

This is the patch series (v4) to add support for Rust as a second language to the Linux kernel.
...

Where is patch 20/20?

Long:

I'm missing patch 20/20. With the v3 series I did mis patch 21/21.

In other projects I see,
patches 01/nn up to nn/nn and cover letter 00/nn.

At https://www.spinics.net/lists/linux-serial/ you find

[PATCH v2 0/2] serial: 8250: Correct basic issues with the PCI blacklist, Maciej W. Rozycki [PATCH v2 2/2] serial: 8250: Report which option to enable for blacklisted PCI devices, Maciej W. Rozycki [PATCH v2 1/2] serial: 8250: Correct Kconfig help text for blacklisted PCI devices, Maciej W. Rozycki

[PATCH v3 0/2] serial: 8250: Fixes for Oxford Semiconductor 950 UARTs, Maciej W. Rozycki [PATCH v3 1/2] serial: 8250: Fold EndRun device support into OxSemi Tornado code, Maciej W. Rozycki [PATCH v3 2/2] serial: 8250: Add proper clock handling for OxSemi PCIe devices, Maciej W. Rozycki

[PATCH 0/2] serial: 8250: Correct basic issues with the PCI blacklist, Maciej W. Rozycki [PATCH 1/2] serial: 8250: Correct Kconfig help text for blacklisted PCI devices, Maciej W. Rozycki [PATCH 2/2] serial: 8250: Report which option to enable for blacklisted PCI devices, Maciej W. Rozycki

[PATCH v8 0/6] serial: mvebu-uart: Support for higher baudrates, Marek Behún
` [PATCH v8 1/6] math64: New DIV_U64_ROUND_CLOSEST helper, Marek Behún
[PATCH v8 2/6] dt-bindings: mvebu-uart: document DT bindings for marvell,armada-3700-uart-clock, Marek Behún [PATCH v8 3/6] serial: mvebu-uart: implement UART clock driver for configuring UART base clock, Marek Behún ` [PATCH v8 4/6] dt-bindings: mvebu-uart: update information about UART clock, Marek Behún
[PATCH v8 5/6] arm64: dts: marvell: armada-37xx: add device node for UART clock and use it, Marek Behún [PATCH v8 6/6] serial: mvebu-uart: implement support for baudrates higher than 230400 Bd, Marek Behún

At https://lore.kernel.org/rust-for-linux/ you find

[PATCH v4 00/20] Rust support
` [PATCH v4 01/20] kallsyms: support "big" kernel symbols
[PATCH v4 02/20] kallsyms: increase maximum kernel symbol length to 512 [PATCH v4 03/20] kallsyms: use the correct buffer size for symbols ` [PATCH v4 04/20] rust: add C helpers
[PATCH v4 05/20] rust: add compiler_builtins` crate
[PATCH v4 07/20] rust: add build_error` crate
[PATCH v4 08/20] rust: add macros` crate
[PATCH v4 09/20] rust: add kernel crate's sync` module
` [PATCH v4 11/20] rust: export generated symbols
[PATCH v4 12/20] vsprintf: add new %pA` format specifier
[PATCH v4 13/20] scripts: add generate_rust_analyzer.py`
[PATCH v4 14/20] scripts: decode_stacktrace: demangle Rust symbols [PATCH v4 16/20] Kbuild: add Rust support
` [PATCH v4 17/20] samples: add Rust examples
` [PATCH v4 18/20] MAINTAINERS: Rust
` [PATCH v4 19/20] [RFC] drivers: gpio: PrimeCell PL061 in Rust

Hench my question: Where is patch 20/20?

Groeten
Geert Stappers

Signature · 1 line
Silence is hard to parse
maintainer
#53 lore raw

Re: [PATCH v4 00/20] Rust support, nn/nn

Quoted 9 lines · Geert Stappers
Quoted 5 lines · Miguel Ojeda

Rust support

This is the patch series (v4) to add support for Rust as a second language to the Linux kernel.
...

Where is patch 20/20?

https://lore.kernel.org/r/[email protected]

#54 lore raw

Re: [PATCH v4 00/20] Rust support, nn/nn

Quoted 4 lines · Greg KH
Quoted 3 lines · Geert Stappers
Quoted 2 lines · Miguel Ojeda

Rust support

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines

This is the patch series (v4) to add support for Rust as a second language to the Linux kernel.
...

Where is patch 20/20?

https://lore.kernel.org/r/[email protected]

Ah, Subject: [PATCH v4 20/20] [RFC] drivers: android: Binder IPC in Rust Thanks. So 20/20 does exist. That it is
NOT at https://lore.kernel.org/rust-for-linux/ remains odd.

Groeten
Geert Stappers

Signature · 1 line
Silence is hard to parse
#55 lore raw

Re: [PATCH v4 00/20] Rust support, nn/nn

Quoted 4 lines · Geert Stappers

Ah, Subject: [PATCH v4 20/20] [RFC] drivers: android: Binder IPC in Rust Thanks. So 20/20 does exist. That it is
NOT at https://lore.kernel.org/rust-for-linux/ remains odd.

Sorry about that, some patches bounced since they were too long (number 6, 10, 15 and 20 in rust-for-linux and number 15 in linux-doc and linux-kbuild).

Cheers,
Miguel

#56 lore raw

Re: [PATCH v4 00/20] Rust support, nn/nn

Quoted 1 line · Miguel Ojeda

On Mon, Feb 14, 2022 at 2:57 PM Geert Stappers wrote:

} } Greg KH told:
} } } Geert Stappers asked:
} } } } Where is patch 20/20
} } } In the archive

Quoted 5 lines
Quoted 3 lines

Ah, Subject: [PATCH v4 20/20] [RFC] drivers: android: Binder IPC in Rust Thanks. So 20/20 does exist. That it is
NOT at https://lore.kernel.org/rust-for-linux/ remains odd.

Sorry about that, some patches bounced since they were too long

Ah, too long, that explains it.

Quoted 2 lines

(number 6, 10, 15 and 20 in rust-for-linux and number 15 in linux-doc and linux-kbuild).

Oops, I didn't miss other patches. I hope they (patch 6, 10, 15 and 20) get the review attention to get accepted.

These are URLs of them: (patchnumber plus one due the cover letter)

https://lore.kernel.org/r/[email protected]
https://lore.kernel.org/r/[email protected]
https://lore.kernel.org/r/[email protected]
https://lore.kernel.org/r/[email protected]

Groeten
Geert Stappers

Signature · 1 line
Silence is hard to parse