rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/17] Rust support
@ 2021-07-04 20:27 ojeda
  2021-07-04 20:27 ` [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths) ojeda
                   ` (16 more replies)
  0 siblings, 17 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel, Miguel Ojeda

From: Miguel Ojeda <ojeda@kernel.org>

Rust support

This is the patch series 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:

    rust-for-linux@vger.kernel.org

and take a look at the project itself at:

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

Cheers,
Miguel

--

# Rust support

This cover letter explains the major changes and updates done since
the RFC sent in the previous merge window back in April, plus a few
extra notes and announcements. For the RFC, please see:

    https://lore.kernel.org/lkml/20210414184604.23473-1-ojeda@kernel.org/


## Rust infrastructure updates

There have been several major improvements to the overall Rust
support. The following subsections cover these.


### Removed panicking allocations

We have removed infallible allocations. In order to do so, we have
integrated a subset of the `alloc` standard library crate, with some
additions on top. This allows us to customize things to our needs,
while giving upstream the time they need to evaluate our changes.

Eventually, the goal is to have everything the kernel needs in
upstream `alloc` and drop it from the kernel tree. We have already
started this process and some changes have been already accepted
upstream.

On top of that, `alloc` is now compiled with panicking allocation
methods disabled, thus they cannot be used within the kernel by
mistake either.

Moreover, the documentation for this customized `alloc`  crate (as well
as for `core`) is now generated alongside the rest of the Rust kernel
documentation. Thus kernel developers can now easily browse the subset
that is available within the kernel. Like last time, you can take
a look at a preview of the documentation at:

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

Note that the `compiler_builtins` panicking intrinsics are still
there, but those will be solved by partitioning `core` via feature
gates. The first one, for disabling floating-point functionality,
has just been accepted upstream.


### Beta compiler supported

Up until now, we have been using nightly releases of `rustc` because
we need some of the latest fixes and unstable features.

However, the kernel can now be compiled with beta and stable `rustc`
releases. At the moment, we are using the 1.54-beta1 version as our
reference compiler. At the end of this month, `rustc` 1.54 will be
released, and we will move to that version as our reference.

Note that the kernel still requires unstable features, even if it is
compiled with a stable `rustc` release, thus we cannot guarantee that
future `rustc` versions will work without changes to the kernel tree.

Thus, until all the unstable features we need are stabilized, we will
support a single `rustc` version for each kernel release.


### Testing support

Another big addition has been the support for testing. We now support
the standard Rust `#[test]` attribute to easily write tests, e.g.:

    #[test]
    fn f() {
        let a = 20;
        let b = 22;
        assert_eq!(a + b, 42);
    }

Furthermore, we are now also supporting Rust documentation tests
("doctests"). These allow us to make sure our examples remain up to
date, and also double as tests too, e.g.:

    /// ```
    /// assert_eq!(foo::f(), 42);
    /// ```
    pub fn f() -> i32 {
        42
    }

For the moment, both kinds of tests are run in the host only, but
the goal is to have them running in kernel space, so that we can
test code that depends on kernel features, and to allow any kernel
module to declare and use them.


### Architectures and compiler support

`arm` (i.e. 32-bit) and `riscv` are now also supported.

On compilers, we would like to mention all the work that has been
going in GCC Rust (a GCC frontend for the Rust language) and
`rustc_codegen_gcc` (a `rustc` backend for GCC). The latter now passes
all `core` tests, and the former is now working on traits. We continue
to track their progress as they may become the best way to have
GCC-built kernels with Rust support enabled. Their latest reports
can be found at:

    https://blog.antoyo.xyz/rustc_codegen_gcc-progress-report-1
    https://thephilbert.io/2021/06/28/gcc-rust-weekly-status-report-20/

On top of that, we requested Compiler Explorer to add support to all
the alternative compilers. At the time of writing, they have already
added `mrustc` and GCC Rust; and `rustc_codegen_gcc` is coming soon.
See a live example at:

    https://godbolt.org/z/8o74c57Yj


## Rust abstractions and driver updates

We have developed new Rust abstractions that use the kernel C
implementations: red-black trees, reference-counted objects, file
descriptor creation, tasks, files, io vectors...

Additionally, we have improved driver support: improvements to
`file_operations` (more operations supported, arbitrary state),
reduced boiler-plate code, improved `module!` macro, registration
macros, rudimentary (`probe` and `remove`) platform drivers...

On Binder, there is now support for transferring files descriptors
and LSM hooks; and we are working on preliminary performance numbers.

Moreover, there is ongoing work on a Rust example driver,
`bcm2835-rng`. This is the hardware random-number generator present
on Raspberry Pi Zero(W), Classic, Two, and Three.

There are other small improvements, such as drivers being restricted
on what unstable features they can use.


## Patch series status

Like it was mentioned in the RFC, the Rust support is still to be
considered experimental. However, as noted back in April, support is
good enough that kernel developers can start working on the Rust
abstractions for subsystems and write drivers and other modules.

Please note that the current series have just arrived in `linux-next`,
thus the first run will happen on Tuesday.


## Industry and academia support

We have been in contact with a set of companies and academia members
that would like to use Rust as a second language in the kernel. Some
of them have already started to evaluate Rust for their needs using
the infrastructure we have already in place.

In particular, we have got a few statements from major companies.
In no particular order:

  Microsoft's Linux Systems Group is interested in contributing to
  getting Rust into Linux kernel. Hopefully we will be able to submit
  select Hyper-V drivers written in Rust in the coming months.

  Arm recognises the Rust value proposition and is actively working
  with the Rust community to improve Rust for Arm based systems.
  A good example is Arm’s RFC contribution to the Rust language which
  made Linux on 64-bit Arm systems a Tier-1 Rust supported platform.
  Rustaceans at Arm are excited about the Rust for Linux initiative
  and look forward to assisting in this effort.

  Google supports and contributes directly to the Rust for Linux
  project. Our Android team is evaluating a new Binder implementation
  and considering other drivers where Rust could be adopted.

In addition, IBM contributed the Rust kernel support for PowerPC
which was already included in the RFC.

In addition, from academia, there are already several projects around
Rust for Linux going on. As an example, members of LSE (Systems
Research Laboratory) at EPITA (École pour l'informatique et les
techniques avancées) are developing an SPI Rust driver.

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


## Conferences and talks

We have submitted talk proposals for LPC (Linux Plumbers Conference).

The main one will describe the work we have done so far and ideally
will also serve as an introduction for other kernel developers
interested in using Rust in the kernel. It will cover an introduction
of the language within the context of the kernel, how the overall Rust
support works, how code is documented, how tests are written, a tour
of available tooling, an explanation of coding guidelines, how kernel
driver code looks like, etc.

In addition, we would like to announce that we are organizing a new
conference that focuses on Rust and the Linux kernel. The first
edition will be virtual and will take place before LPC. Details will
be announced soon.


## 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 RFC:

  - bjorn3 for all the input on Rust compiler details and all
    the reviews and suggestions.

  - Arthur Cohen, Esteban Blanc and Martin Schmidt for their ongoing
    work on the SPI abstractions and driver.

  - Dan Robertson for his ongoing work on softdeps in the `module!`
    macro and the addition of a few safety comments.

  - Paul Römer for his ongoing experiment on using `NonNull` as much
    as possible.

  - Sladyn Nunes for his ongoing sorting of error constants.

  - Jonathan Corbet and the LPC organizers for lending us the Linux
    Plumbers Conference infrastructure so that we can have an easy
    time setting up the new conference.

  - John Ericson for quickly implementing the `no_global_oom_handling`
    `cfg` feature in upstream `alloc` to easily disable all
    functionality that relies on panicking allocations.

  - Josh Triplett and John Ericson for their input on `alloc` which
    helped us decide what to do with it (i.e. fully custom vs.
    slightly custom in-tree copy vs. upstream), as well as offering
    to help moving forward some needed features on the Rust side.

  - Mark Rousskov for answering some questions about beta backports
    and scheduling, as well as working on unsticking `1.54.0-beta.1`.

  - Philipp Krones for his input on Clippy lints and discussing
    extensions for developing custom lints.

  - Antoni Boucher for his work on `rustc_codegen_gcc`.

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

  - Marc Poulhiès for his work on Compiler Explorer to add the
    alternative Rust compilers we requested.

  - Many folks that have reported issues, tested the project,
    helped spread the word, joined discussions and contributed in
    other ways! In no particular order: Chenguang Wang, Greg Morenz,
    John Baublitz, Leah Leshchinsky, Caedin Cook, Liam Arzola,
    Fabio Aiuto, Hanqing Zhao, Robin Randhawa, Michal Rostecki,
    Wei Liu...

For additional acknowledgements, please see the RFC from April.

Miguel Ojeda (17):
  kallsyms: support big kernel symbols (2-byte lengths)
  kallsyms: increase maximum kernel symbol length to 512
  Makefile: generate `CLANG_FLAGS` even in GCC builds
  vsprintf: add new `%pA` format specifier
  rust: add C helpers
  rust: add `compiler_builtins` crate
  rust: add `alloc` crate
  rust: add `build_error` crate
  rust: add `macros` crate
  rust: add `kernel` crate
  rust: export generated symbols
  Kbuild: add Rust support
  docs: add Rust documentation
  samples: add Rust examples
  scripts: add `generate_rust_analyzer.py`
  MAINTAINERS: Rust
  Android: Binder IPC in Rust (WIP)

 .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           |   13 +
 Documentation/rust/arch-support.rst         |   35 +
 Documentation/rust/assets/favicon-16x16.png |  Bin 0 -> 798 bytes
 Documentation/rust/assets/favicon-32x32.png |  Bin 0 -> 2076 bytes
 Documentation/rust/assets/rust-logo.png     |  Bin 0 -> 53976 bytes
 Documentation/rust/coding.rst               |   92 +
 Documentation/rust/docs.rst                 |  110 +
 Documentation/rust/index.rst                |   20 +
 Documentation/rust/quick-start.rst          |  222 ++
 MAINTAINERS                                 |   14 +
 Makefile                                    |  176 +-
 arch/arm/rust/target.json                   |   28 +
 arch/arm64/rust/target.json                 |   35 +
 arch/powerpc/rust/target.json               |   30 +
 arch/riscv/Makefile                         |    1 +
 arch/riscv/rust/rv32ima.json                |   37 +
 arch/riscv/rust/rv32imac.json               |   37 +
 arch/riscv/rust/rv64ima.json                |   37 +
 arch/riscv/rust/rv64imac.json               |   37 +
 arch/x86/rust/target.json                   |   37 +
 drivers/android/Kconfig                     |    7 +
 drivers/android/Makefile                    |    2 +
 drivers/android/allocation.rs               |  264 ++
 drivers/android/context.rs                  |   80 +
 drivers/android/defs.rs                     |   99 +
 drivers/android/node.rs                     |  476 +++
 drivers/android/process.rs                  |  972 ++++++
 drivers/android/range_alloc.rs              |  189 ++
 drivers/android/rust_binder.rs              |  114 +
 drivers/android/thread.rs                   |  857 +++++
 drivers/android/transaction.rs              |  328 ++
 include/linux/kallsyms.h                    |    2 +-
 include/linux/spinlock.h                    |   17 +-
 include/uapi/linux/android/binder.h         |   28 +-
 init/Kconfig                                |   28 +
 kernel/kallsyms.c                           |    7 +
 kernel/livepatch/core.c                     |    4 +-
 kernel/printk/printk.c                      |    5 +-
 lib/Kconfig.debug                           |  144 +
 lib/vsprintf.c                              |   12 +
 rust/.gitignore                             |    6 +
 rust/Makefile                               |  316 ++
 rust/alloc/README.md                        |   32 +
 rust/alloc/alloc.rs                         |  425 +++
 rust/alloc/borrow.rs                        |  493 +++
 rust/alloc/boxed.rs                         | 1728 ++++++++++
 rust/alloc/collections/mod.rs               |  116 +
 rust/alloc/fmt.rs                           |  587 ++++
 rust/alloc/lib.rs                           |  197 ++
 rust/alloc/macros.rs                        |  128 +
 rust/alloc/prelude/mod.rs                   |   17 +
 rust/alloc/prelude/v1.rs                    |   16 +
 rust/alloc/raw_vec.rs                       |  612 ++++
 rust/alloc/rc.rs                            | 2539 +++++++++++++++
 rust/alloc/slice.rs                         | 1271 ++++++++
 rust/alloc/str.rs                           |  614 ++++
 rust/alloc/string.rs                        | 2847 ++++++++++++++++
 rust/alloc/sync.rs                          | 2631 +++++++++++++++
 rust/alloc/vec/drain.rs                     |  157 +
 rust/alloc/vec/drain_filter.rs              |  145 +
 rust/alloc/vec/into_iter.rs                 |  296 ++
 rust/alloc/vec/is_zero.rs                   |  106 +
 rust/alloc/vec/mod.rs                       | 3255 +++++++++++++++++++
 rust/alloc/vec/partial_eq.rs                |   49 +
 rust/alloc/vec/set_len_on_drop.rs           |   30 +
 rust/alloc/vec/spec_extend.rs               |  170 +
 rust/bindgen_parameters                     |   13 +
 rust/build_error.rs                         |   33 +
 rust/compiler_builtins.rs                   |  146 +
 rust/exports.c                              |   16 +
 rust/helpers.c                              |  235 ++
 rust/kernel/allocator.rs                    |   63 +
 rust/kernel/bindings.rs                     |   28 +
 rust/kernel/bindings_helper.h               |   24 +
 rust/kernel/buffer.rs                       |   39 +
 rust/kernel/build_assert.rs                 |   80 +
 rust/kernel/c_types.rs                      |  119 +
 rust/kernel/chrdev.rs                       |  212 ++
 rust/kernel/error.rs                        |  272 ++
 rust/kernel/file.rs                         |  130 +
 rust/kernel/file_operations.rs              |  698 ++++
 rust/kernel/io_buffer.rs                    |  153 +
 rust/kernel/iov_iter.rs                     |   95 +
 rust/kernel/lib.rs                          |  220 ++
 rust/kernel/linked_list.rs                  |  245 ++
 rust/kernel/miscdev.rs                      |  113 +
 rust/kernel/module_param.rs                 |  497 +++
 rust/kernel/of.rs                           |  101 +
 rust/kernel/pages.rs                        |  176 +
 rust/kernel/platdev.rs                      |  166 +
 rust/kernel/prelude.rs                      |   28 +
 rust/kernel/print.rs                        |  412 +++
 rust/kernel/random.rs                       |   50 +
 rust/kernel/raw_list.rs                     |  361 ++
 rust/kernel/rbtree.rs                       |  570 ++++
 rust/kernel/security.rs                     |   79 +
 rust/kernel/static_assert.rs                |   39 +
 rust/kernel/str.rs                          |  259 ++
 rust/kernel/sync/arc.rs                     |  227 ++
 rust/kernel/sync/condvar.rs                 |  136 +
 rust/kernel/sync/guard.rs                   |   82 +
 rust/kernel/sync/locked_by.rs               |  112 +
 rust/kernel/sync/mod.rs                     |   84 +
 rust/kernel/sync/mutex.rs                   |  101 +
 rust/kernel/sync/spinlock.rs                |  109 +
 rust/kernel/sysctl.rs                       |  198 ++
 rust/kernel/task.rs                         |  193 ++
 rust/kernel/traits.rs                       |   26 +
 rust/kernel/types.rs                        |  249 ++
 rust/kernel/user_ptr.rs                     |  191 ++
 rust/macros/lib.rs                          |  127 +
 rust/macros/module.rs                       |  754 +++++
 samples/Kconfig                             |    2 +
 samples/Makefile                            |    1 +
 samples/rust/Kconfig                        |  113 +
 samples/rust/Makefile                       |   12 +
 samples/rust/rust_chrdev.rs                 |   51 +
 samples/rust/rust_minimal.rs                |   38 +
 samples/rust/rust_miscdev.rs                |  150 +
 samples/rust/rust_module_parameters.rs      |   72 +
 samples/rust/rust_print.rs                  |   57 +
 samples/rust/rust_random.rs                 |   61 +
 samples/rust/rust_semaphore.rs              |  177 +
 samples/rust/rust_semaphore_c.c             |  212 ++
 samples/rust/rust_stack_probing.rs          |   40 +
 samples/rust/rust_sync.rs                   |   81 +
 scripts/Makefile.build                      |   22 +
 scripts/Makefile.lib                        |   12 +
 scripts/generate_rust_analyzer.py           |  143 +
 scripts/kallsyms.c                          |   33 +-
 scripts/kconfig/confdata.c                  |   67 +-
 scripts/rust-version.sh                     |   31 +
 tools/include/linux/kallsyms.h              |    2 +-
 tools/include/linux/lockdep.h               |    2 +-
 tools/lib/perf/include/perf/event.h         |    2 +-
 tools/lib/symbol/kallsyms.h                 |    2 +-
 141 files changed, 33003 insertions(+), 45 deletions(-)
 create mode 100644 .rustfmt.toml
 create mode 100644 Documentation/rust/arch-support.rst
 create mode 100644 Documentation/rust/assets/favicon-16x16.png
 create mode 100644 Documentation/rust/assets/favicon-32x32.png
 create mode 100644 Documentation/rust/assets/rust-logo.png
 create mode 100644 Documentation/rust/coding.rst
 create mode 100644 Documentation/rust/docs.rst
 create mode 100644 Documentation/rust/index.rst
 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 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/prelude/mod.rs
 create mode 100644 rust/alloc/prelude/v1.rs
 create mode 100644 rust/alloc/raw_vec.rs
 create mode 100644 rust/alloc/rc.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/sync.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/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/error.rs
 create mode 100644 rust/kernel/file.rs
 create mode 100644 rust/kernel/file_operations.rs
 create mode 100644 rust/kernel/io_buffer.rs
 create mode 100644 rust/kernel/iov_iter.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/module_param.rs
 create mode 100644 rust/kernel/of.rs
 create mode 100644 rust/kernel/pages.rs
 create mode 100644 rust/kernel/platdev.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/security.rs
 create mode 100644 rust/kernel/static_assert.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/spinlock.rs
 create mode 100644 rust/kernel/sysctl.rs
 create mode 100644 rust/kernel/task.rs
 create mode 100644 rust/kernel/traits.rs
 create mode 100644 rust/kernel/types.rs
 create mode 100644 rust/kernel/user_ptr.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_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/rust-version.sh

-- 
2.32.0


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:52   ` Linus Torvalds
  2021-07-04 21:04   ` Matthew Wilcox
  2021-07-04 20:27 ` [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512 ojeda
                   ` (15 subsequent siblings)
  16 siblings, 2 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho

From: Miguel Ojeda <ojeda@kernel.org>

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 2-byte lengths to the symbol table. We call
these "big" symbols.

In order to avoid increasing all lengths to 2 bytes (since most
of them only require 1 byte, including many Rust ones), we use
length zero to mark "big" symbols in the table.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 kernel/kallsyms.c  |  7 +++++++
 scripts/kallsyms.c | 31 ++++++++++++++++++++++++++++---
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index c851ca0ed35..9d0c23e1993 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -73,6 +73,13 @@ static unsigned int kallsyms_expand_symbol(unsigned int off,
 	 */
 	off += len + 1;
 
+	/* If zero, it is a "big" symbol, so a two byte length follows. */
+	if (len == 0) {
+		len = (data[0] << 8) | data[1];
+		data += 2;
+		off += len + 2;
+	}
+
 	/*
 	 * For every byte on the compressed symbol data, copy the table
 	 * entry for that byte.
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 54ad86d1378..bcdabee13aa 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -470,12 +470,37 @@ 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 -- we use that
+		 * to mark a "big" symbol (and it doesn't make sense anyway).
+		 */
+		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 bytes are supported. */
+		if (table[i]->len > 0xFFFF) {
+			fprintf(stderr, "kallsyms failure: "
+				"unexpected huge symbol length\n");
+			exit(EXIT_FAILURE);
+		}
+
+		if (table[i]->len <= 0xFF) {
+			/* 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 a zero and then two bytes. */
+			printf("\t.byte 0x00, 0x%02x, 0x%02x",
+				(table[i]->len >> 8) & 0xFF,
+				table[i]->len & 0xFF);
+			off += table[i]->len + 3;
+		}
 		for (k = 0; k < table[i]->len; k++)
 			printf(", 0x%02x", table[i]->sym[k]);
 		printf("\n");
-
-		off += table[i]->len + 1;
 	}
 	printf("\n");
 
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
  2021-07-04 20:27 ` [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths) ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-14 18:20   ` Nick Desaulniers
  2021-07-04 20:27 ` [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds ojeda
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho

From: Miguel Ojeda <ojeda@kernel.org>

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

    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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 include/linux/kallsyms.h            | 2 +-
 kernel/livepatch/core.c             | 4 ++--
 scripts/kallsyms.c                  | 2 +-
 tools/include/linux/kallsyms.h      | 2 +-
 tools/include/linux/lockdep.h       | 2 +-
 tools/lib/perf/include/perf/event.h | 2 +-
 tools/lib/symbol/kallsyms.h         | 2 +-
 7 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 465060acc98..5cdc6903abc 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -14,7 +14,7 @@
 
 #include <asm/sections.h>
 
-#define KSYM_NAME_LEN 128
+#define KSYM_NAME_LEN 512
 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
 			 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
 
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 335d988bd81..73874e5edfd 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -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",
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index bcdabee13aa..9bab5f55ade 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -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;
diff --git a/tools/include/linux/kallsyms.h b/tools/include/linux/kallsyms.h
index efb6c3f5f2a..5a37ccbec54 100644
--- a/tools/include/linux/kallsyms.h
+++ b/tools/include/linux/kallsyms.h
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
-#define KSYM_NAME_LEN 128
+#define KSYM_NAME_LEN 512
 
 struct module;
 
diff --git a/tools/include/linux/lockdep.h b/tools/include/linux/lockdep.h
index e56997288f2..d9c163f3ab2 100644
--- a/tools/include/linux/lockdep.h
+++ b/tools/include/linux/lockdep.h
@@ -47,7 +47,7 @@ static inline int debug_locks_off(void)
 
 #define task_pid_nr(tsk) ((tsk)->pid)
 
-#define KSYM_NAME_LEN 128
+#define KSYM_NAME_LEN 512
 #define printk(...) dprintf(STDOUT_FILENO, __VA_ARGS__)
 #define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
 #define pr_warn pr_err
diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
index 4d0c02ba3f7..095d60144a7 100644
--- a/tools/lib/perf/include/perf/event.h
+++ b/tools/lib/perf/include/perf/event.h
@@ -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 {
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
index 72ab9870454..542f9b059c3 100644
--- a/tools/lib/symbol/kallsyms.h
+++ b/tools/lib/symbol/kallsyms.h
@@ -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)
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
  2021-07-04 20:27 ` [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths) ojeda
  2021-07-04 20:27 ` [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512 ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-14 18:13   ` Nick Desaulniers
  2021-07-04 20:27 ` [PATCH 04/17] vsprintf: add new `%pA` format specifier ojeda
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho

From: Miguel Ojeda <ojeda@kernel.org>

To support Rust under GCC-built kernels, we need to save the flags that
would have been passed if the kernel was being compiled with Clang.

The reason is that `bindgen` -- the tool we use to generate Rust
bindings to the C side of the kernel -- relies on `libclang` to
parse C. Ideally:

  - `bindgen` would support a GCC backend (requested at [1]),

  - or the Clang driver would be perfectly compatible with GCC,
    including plugins. Unlikely, of course, but perhaps a big
    subset of configs may be possible to guarantee to be kept
    compatible nevertheless.

This is also the reason why GCC builds are very experimental and some
configurations may not work (e.g. `GCC_PLUGIN_RANDSTRUCT`). However,
we keep GCC builds working (for some example configs) in the CI
to avoid diverging/regressing further, so that we are better prepared
for the future when a solution might become available.

[1] https://github.com/rust-lang/rust-bindgen/issues/1949

Link: https://github.com/Rust-for-Linux/linux/issues/167
Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 Makefile | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 0565caea036..6e823d8bd64 100644
--- a/Makefile
+++ b/Makefile
@@ -573,18 +573,23 @@ endif
 # and from include/config/auto.conf.cmd to detect the compiler upgrade.
 CC_VERSION_TEXT = $(subst $(pound),,$(shell $(CC) --version 2>/dev/null | head -n 1))
 
-ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
+TENTATIVE_CLANG_FLAGS := -Werror=unknown-warning-option
+
 ifneq ($(CROSS_COMPILE),)
-CLANG_FLAGS	+= --target=$(notdir $(CROSS_COMPILE:%-=%))
+TENTATIVE_CLANG_FLAGS	+= --target=$(notdir $(CROSS_COMPILE:%-=%))
 endif
 ifeq ($(LLVM_IAS),1)
-CLANG_FLAGS	+= -integrated-as
+TENTATIVE_CLANG_FLAGS	+= -integrated-as
 else
-CLANG_FLAGS	+= -no-integrated-as
+TENTATIVE_CLANG_FLAGS	+= -no-integrated-as
 GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
-CLANG_FLAGS	+= --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
+TENTATIVE_CLANG_FLAGS	+= --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
 endif
-CLANG_FLAGS	+= -Werror=unknown-warning-option
+
+export TENTATIVE_CLANG_FLAGS
+
+ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
+CLANG_FLAGS	+= $(TENTATIVE_CLANG_FLAGS)
 KBUILD_CFLAGS	+= $(CLANG_FLAGS)
 KBUILD_AFLAGS	+= $(CLANG_FLAGS)
 export CLANG_FLAGS
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 04/17] vsprintf: add new `%pA` format specifier
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (2 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-07 20:31   ` Nick Desaulniers
  2021-07-04 20:27 ` [PATCH 05/17] rust: add C helpers ojeda
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 lib/vsprintf.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index f0c35d9b65b..e7afe954004 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2182,6 +2182,10 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
 	return widen_string(buf, buf - buf_start, end, spec);
 }
 
+#ifdef CONFIG_RUST
+char *rust_fmt_argument(char* buf, char* end, void *ptr);
+#endif
+
 /* Disable pointer hashing if requested */
 bool no_hash_pointers __ro_after_init;
 EXPORT_SYMBOL_GPL(no_hash_pointers);
@@ -2335,6 +2339,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,
@@ -2407,6 +2415,10 @@ 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);
+#ifdef CONFIG_RUST
+	case 'A':
+		return rust_fmt_argument(buf, end, ptr);
+#endif
 	case 'x':
 		return pointer_string(buf, end, ptr, spec);
 	case 'e':
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 05/17] rust: add C helpers
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (3 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 04/17] vsprintf: add new `%pA` format specifier ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-07 10:19   ` Marco Elver
  2021-07-04 20:27 ` [PATCH 06/17] rust: add `compiler_builtins` crate ojeda
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/helpers.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 235 insertions(+)
 create mode 100644 rust/helpers.c

diff --git a/rust/helpers.c b/rust/helpers.c
new file mode 100644
index 00000000000..a6e98abb13e
--- /dev/null
+++ b/rust/helpers.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bug.h>
+#include <linux/build_bug.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>
+
+void rust_helper_BUG(void)
+{
+	BUG();
+}
+
+unsigned long rust_helper_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	return copy_from_user(to, from, n);
+}
+
+unsigned long rust_helper_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	return copy_to_user(to, from, n);
+}
+
+unsigned long rust_helper_clear_user(void __user *to, unsigned long n)
+{
+	return clear_user(to, n);
+}
+
+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);
+
+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);
+}
+
+void rust_helper_mutex_lock(struct mutex *lock)
+{
+	mutex_lock(lock);
+}
+EXPORT_SYMBOL_GPL(rust_helper_mutex_lock);
+
+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_new(void)
+{
+	return (refcount_t)REFCOUNT_INIT(1);
+}
+EXPORT_SYMBOL_GPL(rust_helper_refcount_new);
+
+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(struct task_struct *mgr)
+{
+	return security_binder_set_context_mgr(mgr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_set_context_mgr);
+
+int rust_helper_security_binder_transaction(struct task_struct *from,
+					    struct task_struct *to)
+{
+	return security_binder_transaction(from, to);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_transaction);
+
+int rust_helper_security_binder_transfer_binder(struct task_struct *from,
+						struct task_struct *to)
+{
+	return security_binder_transfer_binder(from, to);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_binder);
+
+int rust_helper_security_binder_transfer_file(struct task_struct *from,
+					      struct task_struct *to,
+					      struct file *file)
+{
+	return security_binder_transfer_file(from, to, file);
+}
+EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_file);
+
+/* 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"
+);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 06/17] rust: add `compiler_builtins` crate
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (4 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 05/17] rust: add C helpers ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:27 ` [PATCH 08/17] rust: add `build_error` crate ojeda
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/compiler_builtins.rs | 146 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 146 insertions(+)
 create mode 100644 rust/compiler_builtins.rs

diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs
new file mode 100644
index 00000000000..cb4bbf7be4e
--- /dev/null
+++ b/rust/compiler_builtins.rs
@@ -0,0 +1,146 @@
+// 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 floating-point 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!("`f32` should not be used", {
+    __addsf3,
+    __addsf3vfp,
+    __aeabi_fcmpeq,
+    __aeabi_ul2f,
+    __divsf3,
+    __divsf3vfp,
+    __eqsf2,
+    __eqsf2vfp,
+    __fixsfdi,
+    __fixsfsi,
+    __fixsfti,
+    __fixunssfdi,
+    __fixunssfsi,
+    __fixunssfti,
+    __floatdisf,
+    __floatsisf,
+    __floattisf,
+    __floatundisf,
+    __floatunsisf,
+    __floatuntisf,
+    __gesf2,
+    __gesf2vfp,
+    __gtsf2,
+    __gtsf2vfp,
+    __lesf2,
+    __lesf2vfp,
+    __ltsf2,
+    __ltsf2vfp,
+    __mulsf3,
+    __mulsf3vfp,
+    __nesf2,
+    __nesf2vfp,
+    __powisf2,
+    __subsf3,
+    __subsf3vfp,
+    __unordsf2,
+});
+
+define_panicking_intrinsics!("`f64` should not be used", {
+    __adddf3,
+    __adddf3vfp,
+    __aeabi_dcmpeq,
+    __aeabi_ul2d,
+    __divdf3,
+    __divdf3vfp,
+    __eqdf2,
+    __eqdf2vfp,
+    __fixdfdi,
+    __fixdfsi,
+    __fixdfti,
+    __fixunsdfdi,
+    __fixunsdfsi,
+    __fixunsdfti,
+    __floatdidf,
+    __floatsidf,
+    __floattidf,
+    __floatundidf,
+    __floatunsidf,
+    __floatuntidf,
+    __gedf2,
+    __gedf2vfp,
+    __gtdf2,
+    __gtdf2vfp,
+    __ledf2,
+    __ledf2vfp,
+    __ltdf2,
+    __ltdf2vfp,
+    __muldf3,
+    __muldf3vfp,
+    __nedf2,
+    __nedf2vfp,
+    __powidf2,
+    __subdf3,
+    __subdf3vfp,
+    __unorddf2,
+});
+
+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,
+});
+
+extern "C" {
+    fn rust_helper_BUG() -> !;
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo<'_>) -> ! {
+    unsafe {
+        rust_helper_BUG();
+    }
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 08/17] rust: add `build_error` crate
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (5 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 06/17] rust: add `compiler_builtins` crate ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:27 ` [PATCH 09/17] rust: add `macros` crate ojeda
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/build_error.rs | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 rust/build_error.rs

diff --git a/rust/build_error.rs b/rust/build_error.rs
new file mode 100644
index 00000000000..d47fa8393cb
--- /dev/null
+++ b/rust/build_error.rs
@@ -0,0 +1,33 @@
+// 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]
+#![feature(const_panic, core_panic)]
+
+/// 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) -> ! {
+    // Could also be `panic!(msg)` to avoid using unstable feature `core_panic`,
+    // but it is not allowed in Rust 2021, while `panic!("{}", msg)` could not
+    // yet be used in const context.
+    core::panicking::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";
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 09/17] rust: add `macros` crate
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (6 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 08/17] rust: add `build_error` crate ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:27 ` [PATCH 11/17] rust: export generated symbols ojeda
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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",
    }

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/macros/lib.rs    | 127 +++++++
 rust/macros/module.rs | 754 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 881 insertions(+)
 create mode 100644 rust/macros/lib.rs
 create mode 100644 rust/macros/module.rs

diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
new file mode 100644
index 00000000000..cb7a4f12f3b
--- /dev/null
+++ b/rust/macros/lib.rs
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Crate for all kernel procedural macros.
+
+mod module;
+
+use proc_macro::TokenStream;
+
+/// Declares a kernel module.
+///
+/// The `type` argument should be a type which implements the [`KernelModule`]
+/// trait. Also accepts various forms of kernel metadata.
+///
+/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
+///
+/// [`KernelModule`]: ../kernel/trait.KernelModule.html
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::prelude::*;
+///
+/// module!{
+///     type: MyKernelModule,
+///     name: b"my_kernel_module",
+///     author: b"Rust for Linux Contributors",
+///     description: b"My very own kernel module!",
+///     license: b"GPL v2",
+///     params: {
+///        my_i32: i32 {
+///            default: 42,
+///            permissions: 0o000,
+///            description: b"Example of i32",
+///        },
+///        writeable_i32: i32 {
+///            default: 42,
+///            permissions: 0o644,
+///            description: b"Example of i32",
+///        },
+///    },
+/// }
+///
+/// struct MyKernelModule;
+///
+/// impl KernelModule for MyKernelModule {
+///     fn init() -> Result<Self> {
+///         // If the parameter is writeable, then the kparam lock must be
+///         // taken to read the parameter:
+///         {
+///             let lock = THIS_MODULE.kernel_param_lock();
+///             pr_info!("i32 param is:  {}\n", writeable_i32.read(&lock));
+///         }
+///         // If the parameter is read only, it can be read without locking
+///         // the kernel parameters:
+///         pr_info!("i32 param is:  {}\n", my_i32.read());
+///         Ok(MyKernelModule)
+///     }
+/// }
+/// ```
+///
+/// # Supported argument types
+///   - `type`: type which implements the [`KernelModule`] trait (required).
+///   - `name`: byte array of the name of the kernel module (required).
+///   - `author`: byte array of the author of the kernel module.
+///   - `description`: byte array of the description of the kernel module.
+///   - `license`: byte array of the license of the kernel module (required).
+///   - `alias`: byte array of alias name of the kernel module.
+///   - `alias_rtnl_link`: byte array of the `rtnl_link_alias` of the kernel module (mutually exclusive with `alias`).
+///   - `params`: parameters for the kernel module, as described below.
+///
+/// # Supported parameter types
+///
+///   - `bool`: Corresponds to C `bool` param type.
+///   - `i8`: No equivalent C param type.
+///   - `u8`: Corresponds to C `char` param type.
+///   - `i16`: Corresponds to C `short` param type.
+///   - `u16`: Corresponds to C `ushort` param type.
+///   - `i32`: Corresponds to C `int` param type.
+///   - `u32`: Corresponds to C `uint` param type.
+///   - `i64`: No equivalent C param type.
+///   - `u64`: Corresponds to C `ullong` param type.
+///   - `isize`: No equivalent C param type.
+///   - `usize`: No equivalent C param type.
+///   - `str`: Corresponds to C `charp` param type. Reading returns a byte slice.
+///   - `ArrayParam<T,N>`: Corresponds to C parameters created using `module_param_array`. An array
+///     of `T`'s of length at **most** `N`.
+///
+/// `invbool` is unsupported: it was only ever used in a few modules.
+/// Consider using a `bool` and inverting the logic instead.
+#[proc_macro]
+pub fn module(ts: TokenStream) -> TokenStream {
+    module::module(ts)
+}
+
+/// Declares a kernel module that exposes a single misc device.
+///
+/// The `type` argument should be a type which implements the [`FileOpener`] trait. Also accepts
+/// various forms of kernel metadata.
+///
+/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
+///
+/// [`FileOpener`]: ../kernel/file_operations/trait.FileOpener.html
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::prelude::*;
+///
+/// module_misc_device! {
+///     type: MyFile,
+///     name: b"my_miscdev_kernel_module",
+///     author: b"Rust for Linux Contributors",
+///     description: b"My very own misc device kernel module!",
+///     license: b"GPL v2",
+/// }
+///
+/// #[derive(Default)]
+/// struct MyFile;
+///
+/// impl kernel::file_operations::FileOperations for MyFile {
+///     kernel::declare_file_operations!();
+/// }
+/// ```
+#[proc_macro]
+pub fn module_misc_device(ts: TokenStream) -> TokenStream {
+    module::module_misc_device(ts)
+}
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
new file mode 100644
index 00000000000..1389c53aa22
--- /dev/null
+++ b/rust/macros/module.rs
@@ -0,0 +1,754 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use proc_macro::{token_stream, Delimiter, Group, Literal, TokenStream, TokenTree};
+
+fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
+    if let Some(TokenTree::Ident(ident)) = it.next() {
+        Some(ident.to_string())
+    } else {
+        None
+    }
+}
+
+fn try_literal(it: &mut token_stream::IntoIter) -> Option<String> {
+    if let Some(TokenTree::Literal(literal)) = it.next() {
+        Some(literal.to_string())
+    } else {
+        None
+    }
+}
+
+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
+        }
+    })
+}
+
+fn expect_ident(it: &mut token_stream::IntoIter) -> String {
+    try_ident(it).expect("Expected Ident")
+}
+
+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");
+    }
+}
+
+fn expect_literal(it: &mut token_stream::IntoIter) -> String {
+    try_literal(it).expect("Expected Literal")
+}
+
+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");
+    }
+}
+
+fn expect_byte_string(it: &mut token_stream::IntoIter) -> String {
+    try_byte_string(it).expect("Expected byte string")
+}
+
+#[derive(Clone, PartialEq)]
+enum ParamType {
+    Ident(String),
+    Array { vals: String, max_length: usize },
+}
+
+fn expect_array_fields(it: &mut token_stream::IntoIter) -> ParamType {
+    assert_eq!(expect_punct(it), '<');
+    let vals = expect_ident(it);
+    assert_eq!(expect_punct(it), ',');
+    let max_length_str = expect_literal(it);
+    let max_length = max_length_str
+        .parse::<usize>()
+        .expect("Expected usize length");
+    assert_eq!(expect_punct(it), '>');
+    ParamType::Array { vals, max_length }
+}
+
+fn expect_type(it: &mut token_stream::IntoIter) -> ParamType {
+    if let TokenTree::Ident(ident) = it
+        .next()
+        .expect("Reached end of token stream for param type")
+    {
+        match ident.to_string().as_ref() {
+            "ArrayParam" => expect_array_fields(it),
+            _ => ParamType::Ident(ident.to_string()),
+        }
+    } else {
+        panic!("Expected Param Type")
+    }
+}
+
+fn expect_end(it: &mut token_stream::IntoIter) {
+    if it.next().is_some() {
+        panic!("Expected end");
+    }
+}
+
+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
+}
+
+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
+}
+
+struct ModInfoBuilder<'a> {
+    module: &'a str,
+    counter: usize,
+    buffer: String,
+}
+
+impl<'a> ModInfoBuilder<'a> {
+    fn new(module: &'a str) -> Self {
+        ModInfoBuilder {
+            module,
+            counter: 0,
+            buffer: String::new(),
+        }
+    }
+
+    fn emit_base(&mut self, field: &str, content: &str, builtin: bool) {
+        use std::fmt::Write;
+
+        let string = if builtin {
+            // Built-in modules prefix their modinfo strings by `module.`.
+            format!(
+                "{module}.{field}={content}\0",
+                module = self.module,
+                field = field,
+                content = content
+            )
+        } else {
+            // Loadable modules' modinfo strings go as-is.
+            format!("{field}={content}\0", field = field, content = content)
+        };
+
+        write!(
+            &mut self.buffer,
+            "
+                {cfg}
+                #[doc(hidden)]
+                #[link_section = \".modinfo\"]
+                #[used]
+                pub static __{module}_{counter}: [u8; {length}] = *{string};
+            ",
+            cfg = if builtin {
+                "#[cfg(not(MODULE))]"
+            } else {
+                "#[cfg(MODULE)]"
+            },
+            module = self.module,
+            counter = self.counter,
+            length = string.len(),
+            string = Literal::byte_string(string.as_bytes()),
+        )
+        .unwrap();
+
+        self.counter += 1;
+    }
+
+    fn emit_only_builtin(&mut self, field: &str, content: &str) {
+        self.emit_base(field, content, true)
+    }
+
+    fn emit_only_loadable(&mut self, field: &str, content: &str) {
+        self.emit_base(field, content, false)
+    }
+
+    fn emit(&mut self, field: &str, content: &str) {
+        self.emit_only_builtin(field, content);
+        self.emit_only_loadable(field, content);
+    }
+
+    fn emit_param(&mut self, field: &str, param: &str, content: &str) {
+        let content = format!("{param}:{content}", param = param, content = content);
+        self.emit(field, &content);
+    }
+}
+
+fn permissions_are_readonly(perms: &str) -> bool {
+    let (radix, digits) = if let Some(n) = perms.strip_prefix("0x") {
+        (16, n)
+    } else if let Some(n) = perms.strip_prefix("0o") {
+        (8, n)
+    } else if let Some(n) = perms.strip_prefix("0b") {
+        (2, n)
+    } else {
+        (10, perms)
+    };
+    match u32::from_str_radix(digits, radix) {
+        Ok(perms) => perms & 0o222 == 0,
+        Err(_) => false,
+    }
+}
+
+fn param_ops_path(param_type: &str) -> &'static str {
+    match param_type {
+        "bool" => "kernel::module_param::PARAM_OPS_BOOL",
+        "i8" => "kernel::module_param::PARAM_OPS_I8",
+        "u8" => "kernel::module_param::PARAM_OPS_U8",
+        "i16" => "kernel::module_param::PARAM_OPS_I16",
+        "u16" => "kernel::module_param::PARAM_OPS_U16",
+        "i32" => "kernel::module_param::PARAM_OPS_I32",
+        "u32" => "kernel::module_param::PARAM_OPS_U32",
+        "i64" => "kernel::module_param::PARAM_OPS_I64",
+        "u64" => "kernel::module_param::PARAM_OPS_U64",
+        "isize" => "kernel::module_param::PARAM_OPS_ISIZE",
+        "usize" => "kernel::module_param::PARAM_OPS_USIZE",
+        "str" => "kernel::module_param::PARAM_OPS_STR",
+        t => panic!("Unrecognized type {}", t),
+    }
+}
+
+fn try_simple_param_val(
+    param_type: &str,
+) -> Box<dyn Fn(&mut token_stream::IntoIter) -> Option<String>> {
+    match param_type {
+        "bool" => Box::new(|param_it| try_ident(param_it)),
+        "str" => Box::new(|param_it| {
+            try_byte_string(param_it)
+                .map(|s| format!("kernel::module_param::StringParam::Ref(b\"{}\")", s))
+        }),
+        _ => Box::new(|param_it| try_literal(param_it)),
+    }
+}
+
+fn get_default(param_type: &ParamType, param_it: &mut token_stream::IntoIter) -> String {
+    let try_param_val = match param_type {
+        ParamType::Ident(ref param_type)
+        | ParamType::Array {
+            vals: ref param_type,
+            max_length: _,
+        } => try_simple_param_val(param_type),
+    };
+    assert_eq!(expect_ident(param_it), "default");
+    assert_eq!(expect_punct(param_it), ':');
+    let default = match param_type {
+        ParamType::Ident(_) => try_param_val(param_it).expect("Expected default param value"),
+        ParamType::Array {
+            vals: _,
+            max_length: _,
+        } => {
+            let group = expect_group(param_it);
+            assert_eq!(group.delimiter(), Delimiter::Bracket);
+            let mut default_vals = Vec::new();
+            let mut it = group.stream().into_iter();
+
+            while let Some(default_val) = try_param_val(&mut it) {
+                default_vals.push(default_val);
+                match it.next() {
+                    Some(TokenTree::Punct(punct)) => assert_eq!(punct.as_char(), ','),
+                    None => break,
+                    _ => panic!("Expected ',' or end of array default values"),
+                }
+            }
+
+            let mut default_array = "kernel::module_param::ArrayParam::create(&[".to_string();
+            default_array.push_str(
+                &default_vals
+                    .iter()
+                    .map(|val| val.to_string())
+                    .collect::<Vec<String>>()
+                    .join(","),
+            );
+            default_array.push_str("])");
+            default_array
+        }
+    };
+    assert_eq!(expect_punct(param_it), ',');
+    default
+}
+
+fn generated_array_ops_name(vals: &str, max_length: usize) -> String {
+    format!(
+        "__generated_array_ops_{vals}_{max_length}",
+        vals = vals,
+        max_length = max_length
+    )
+}
+
+#[derive(Debug, Default)]
+struct ModuleInfo {
+    type_: String,
+    license: String,
+    name: String,
+    author: Option<String>,
+    description: Option<String>,
+    alias: Option<String>,
+    params: Option<Group>,
+}
+
+impl ModuleInfo {
+    fn parse(it: &mut token_stream::IntoIter) -> Self {
+        let mut info = ModuleInfo::default();
+
+        const EXPECTED_KEYS: &[&str] = &[
+            "type",
+            "name",
+            "author",
+            "description",
+            "license",
+            "alias",
+            "alias_rtnl_link",
+            "params",
+        ];
+        const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
+        let mut seen_keys = Vec::new();
+
+        loop {
+            let key = match it.next() {
+                Some(TokenTree::Ident(ident)) => ident.to_string(),
+                Some(_) => panic!("Expected Ident or end"),
+                None => break,
+            };
+
+            if seen_keys.contains(&key) {
+                panic!(
+                    "Duplicated key \"{}\". Keys can only be specified once.",
+                    key
+                );
+            }
+
+            assert_eq!(expect_punct(it), ':');
+
+            match key.as_str() {
+                "type" => info.type_ = expect_ident(it),
+                "name" => info.name = expect_byte_string(it),
+                "author" => info.author = Some(expect_byte_string(it)),
+                "description" => info.description = Some(expect_byte_string(it)),
+                "license" => info.license = expect_byte_string(it),
+                "alias" => info.alias = Some(expect_byte_string(it)),
+                "alias_rtnl_link" => {
+                    info.alias = Some(format!("rtnl-link-{}", expect_byte_string(it)))
+                }
+                "params" => info.params = Some(expect_group(it)),
+                _ => panic!(
+                    "Unknown key \"{}\". Valid keys are: {:?}.",
+                    key, EXPECTED_KEYS
+                ),
+            }
+
+            assert_eq!(expect_punct(it), ',');
+
+            seen_keys.push(key);
+        }
+
+        expect_end(it);
+
+        for key in REQUIRED_KEYS {
+            if !seen_keys.iter().any(|e| e == key) {
+                panic!("Missing required key \"{}\".", key);
+            }
+        }
+
+        let mut ordered_keys: Vec<&str> = Vec::new();
+        for key in EXPECTED_KEYS {
+            if seen_keys.iter().any(|e| e == key) {
+                ordered_keys.push(key);
+            }
+        }
+
+        if seen_keys != ordered_keys {
+            panic!(
+                "Keys are not ordered as expected. Order them like: {:?}.",
+                ordered_keys
+            );
+        }
+
+        info
+    }
+}
+
+pub fn module(ts: TokenStream) -> TokenStream {
+    let mut it = ts.into_iter();
+
+    let info = ModuleInfo::parse(&mut it);
+
+    let name = info.name.clone();
+
+    let mut modinfo = ModInfoBuilder::new(&name);
+    if let Some(author) = info.author {
+        modinfo.emit("author", &author);
+    }
+    if let Some(description) = info.description {
+        modinfo.emit("description", &description);
+    }
+    modinfo.emit("license", &info.license);
+    if let Some(alias) = info.alias {
+        modinfo.emit("alias", &alias);
+    }
+
+    // Built-in modules also export the `file` modinfo string
+    let file =
+        std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
+    modinfo.emit_only_builtin("file", &file);
+
+    let mut array_types_to_generate = Vec::new();
+    if let Some(params) = info.params {
+        assert_eq!(params.delimiter(), Delimiter::Brace);
+
+        let mut it = params.stream().into_iter();
+
+        loop {
+            let param_name = match it.next() {
+                Some(TokenTree::Ident(ident)) => ident.to_string(),
+                Some(_) => panic!("Expected Ident or end"),
+                None => break,
+            };
+
+            assert_eq!(expect_punct(&mut it), ':');
+            let param_type = expect_type(&mut it);
+            let group = expect_group(&mut it);
+            assert_eq!(expect_punct(&mut it), ',');
+
+            assert_eq!(group.delimiter(), Delimiter::Brace);
+
+            let mut param_it = group.stream().into_iter();
+            let param_default = get_default(&param_type, &mut param_it);
+            let param_permissions = get_literal(&mut param_it, "permissions");
+            let param_description = get_byte_string(&mut param_it, "description");
+            expect_end(&mut param_it);
+
+            // TODO: more primitive types
+            // TODO: other kinds: unsafes, etc.
+            let (param_kernel_type, ops): (String, _) = match param_type {
+                ParamType::Ident(ref param_type) => (
+                    param_type.to_string(),
+                    param_ops_path(param_type).to_string(),
+                ),
+                ParamType::Array {
+                    ref vals,
+                    max_length,
+                } => {
+                    array_types_to_generate.push((vals.clone(), max_length));
+                    (
+                        format!("__rust_array_param_{}_{}", vals, max_length),
+                        generated_array_ops_name(vals, max_length),
+                    )
+                }
+            };
+
+            modinfo.emit_param("parmtype", &param_name, &param_kernel_type);
+            modinfo.emit_param("parm", &param_name, &param_description);
+            let param_type_internal = match param_type {
+                ParamType::Ident(ref param_type) => match param_type.as_ref() {
+                    "str" => "kernel::module_param::StringParam".to_string(),
+                    other => other.to_string(),
+                },
+                ParamType::Array {
+                    ref vals,
+                    max_length,
+                } => format!(
+                    "kernel::module_param::ArrayParam<{vals}, {max_length}>",
+                    vals = vals,
+                    max_length = max_length
+                ),
+            };
+            let read_func = if permissions_are_readonly(&param_permissions) {
+                format!(
+                    "
+                        fn read(&self) -> &<{param_type_internal} as kernel::module_param::ModuleParam>::Value {{
+                            // SAFETY: Parameters do not need to be locked because they are read only or sysfs is not enabled.
+                            unsafe {{ <{param_type_internal} as kernel::module_param::ModuleParam>::value(&__{name}_{param_name}_value) }}
+                        }}
+                    ",
+                    name = name,
+                    param_name = param_name,
+                    param_type_internal = param_type_internal,
+                )
+            } else {
+                format!(
+                    "
+                        fn read<'lck>(&self, lock: &'lck kernel::KParamGuard) -> &'lck <{param_type_internal} as kernel::module_param::ModuleParam>::Value {{
+                            // SAFETY: Parameters are locked by `KParamGuard`.
+                            unsafe {{ <{param_type_internal} as kernel::module_param::ModuleParam>::value(&__{name}_{param_name}_value) }}
+                        }}
+                    ",
+                    name = name,
+                    param_name = param_name,
+                    param_type_internal = param_type_internal,
+                )
+            };
+            let kparam = format!(
+                "
+                    kernel::bindings::kernel_param__bindgen_ty_1 {{
+                        arg: unsafe {{ &__{name}_{param_name}_value }} as *const _ as *mut kernel::c_types::c_void,
+                    }},
+                ",
+                name = name,
+                param_name = param_name,
+            );
+            modinfo.buffer.push_str(
+                &format!(
+                    "
+                    static mut __{name}_{param_name}_value: {param_type_internal} = {param_default};
+
+                    struct __{name}_{param_name};
+
+                    impl __{name}_{param_name} {{ {read_func} }}
+
+                    const {param_name}: __{name}_{param_name} = __{name}_{param_name};
+
+                    // Note: the C macro that generates the static structs for the `__param` section
+                    // asks for them to be `aligned(sizeof(void *))`. However, that was put in place
+                    // in 2003 in commit 38d5b085d2 (\"[PATCH] Fix over-alignment problem on x86-64\")
+                    // to undo GCC over-alignment of static structs of >32 bytes. It seems that is
+                    // not the case anymore, so we simplify to a transparent representation here
+                    // in the expectation that it is not needed anymore.
+                    // TODO: revisit this to confirm the above comment and remove it if it happened
+                    #[repr(transparent)]
+                    struct __{name}_{param_name}_RacyKernelParam(kernel::bindings::kernel_param);
+
+                    unsafe impl Sync for __{name}_{param_name}_RacyKernelParam {{
+                    }}
+
+                    #[cfg(not(MODULE))]
+                    const __{name}_{param_name}_name: *const kernel::c_types::c_char = b\"{name}.{param_name}\\0\" as *const _ as *const kernel::c_types::c_char;
+
+                    #[cfg(MODULE)]
+                    const __{name}_{param_name}_name: *const kernel::c_types::c_char = b\"{param_name}\\0\" as *const _ as *const kernel::c_types::c_char;
+
+                    #[link_section = \"__param\"]
+                    #[used]
+                    static __{name}_{param_name}_struct: __{name}_{param_name}_RacyKernelParam = __{name}_{param_name}_RacyKernelParam(kernel::bindings::kernel_param {{
+                        name: __{name}_{param_name}_name,
+                        // SAFETY: `__this_module` is constructed by the kernel at load time and will not be freed until the module is unloaded.
+                        #[cfg(MODULE)]
+                        mod_: unsafe {{ &kernel::bindings::__this_module as *const _ as *mut _ }},
+                        #[cfg(not(MODULE))]
+                        mod_: core::ptr::null_mut(),
+                        ops: unsafe {{ &{ops} }} as *const kernel::bindings::kernel_param_ops,
+                        perm: {permissions},
+                        level: -1,
+                        flags: 0,
+                        __bindgen_anon_1: {kparam}
+                    }});
+                    ",
+                    name = name,
+                    param_type_internal = param_type_internal,
+                    read_func = read_func,
+                    param_default = param_default,
+                    param_name = param_name,
+                    ops = ops,
+                    permissions = param_permissions,
+                    kparam = kparam,
+                )
+            );
+        }
+    }
+
+    let mut generated_array_types = String::new();
+
+    for (vals, max_length) in array_types_to_generate {
+        let ops_name = generated_array_ops_name(&vals, max_length);
+        generated_array_types.push_str(&format!(
+            "
+                kernel::make_param_ops!(
+                    {ops_name},
+                    kernel::module_param::ArrayParam<{vals}, {{ {max_length} }}>
+                );
+            ",
+            ops_name = ops_name,
+            vals = vals,
+            max_length = max_length,
+        ));
+    }
+
+    format!(
+        "
+            /// The module name.
+            ///
+            /// Used by the printing macros, e.g. [`info!`].
+            const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
+
+            static mut __MOD: Option<{type_}> = None;
+
+            // SAFETY: `__this_module` is constructed by the kernel at load time and will not be freed until the module is unloaded.
+            #[cfg(MODULE)]
+            static THIS_MODULE: kernel::ThisModule = unsafe {{ kernel::ThisModule::from_ptr(&kernel::bindings::__this_module as *const _ as *mut _) }};
+            #[cfg(not(MODULE))]
+            static THIS_MODULE: kernel::ThisModule = unsafe {{ kernel::ThisModule::from_ptr(core::ptr::null_mut()) }};
+
+            // Loadable modules need to export the `{{init,cleanup}}_module` identifiers
+            #[cfg(MODULE)]
+            #[doc(hidden)]
+            #[no_mangle]
+            pub extern \"C\" fn init_module() -> kernel::c_types::c_int {{
+                __init()
+            }}
+
+            #[cfg(MODULE)]
+            #[doc(hidden)]
+            #[no_mangle]
+            pub extern \"C\" fn cleanup_module() {{
+                __exit()
+            }}
+
+            // Built-in modules are initialized through an initcall pointer
+            // and the identifiers need to be unique
+            #[cfg(not(MODULE))]
+            #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
+            #[doc(hidden)]
+            #[link_section = \"{initcall_section}\"]
+            #[used]
+            pub static __{name}_initcall: extern \"C\" fn() -> kernel::c_types::c_int = __{name}_init;
+
+            #[cfg(not(MODULE))]
+            #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
+            global_asm!(
+                r#\".section \"{initcall_section}\", \"a\"
+                __{name}_initcall:
+                    .long   __{name}_init - .
+                    .previous
+                \"#
+            );
+
+            #[cfg(not(MODULE))]
+            #[doc(hidden)]
+            #[no_mangle]
+            pub extern \"C\" fn __{name}_init() -> kernel::c_types::c_int {{
+                __init()
+            }}
+
+            #[cfg(not(MODULE))]
+            #[doc(hidden)]
+            #[no_mangle]
+            pub extern \"C\" fn __{name}_exit() {{
+                __exit()
+            }}
+
+            fn __init() -> kernel::c_types::c_int {{
+                match <{type_} as kernel::KernelModule>::init() {{
+                    Ok(m) => {{
+                        unsafe {{
+                            __MOD = Some(m);
+                        }}
+                        return 0;
+                    }}
+                    Err(e) => {{
+                        return e.to_kernel_errno();
+                    }}
+                }}
+            }}
+
+            fn __exit() {{
+                unsafe {{
+                    // Invokes `drop()` on `__MOD`, which should be used for cleanup.
+                    __MOD = None;
+                }}
+            }}
+
+            {modinfo}
+
+            {generated_array_types}
+        ",
+        type_ = info.type_,
+        name = info.name,
+        modinfo = modinfo.buffer,
+        generated_array_types = generated_array_types,
+        initcall_section = ".initcall6.init"
+    ).parse().expect("Error parsing formatted string into token stream.")
+}
+
+pub fn module_misc_device(ts: TokenStream) -> TokenStream {
+    let mut it = ts.into_iter();
+
+    let info = ModuleInfo::parse(&mut it);
+
+    let module = format!("__internal_ModuleFor{}", info.type_);
+
+    format!(
+        "
+            #[doc(hidden)]
+            struct {module} {{
+                _dev: core::pin::Pin<alloc::boxed::Box<kernel::miscdev::Registration>>,
+            }}
+
+            impl kernel::KernelModule for {module} {{
+                fn init() -> kernel::Result<Self> {{
+                    Ok(Self {{
+                        _dev: kernel::miscdev::Registration::new_pinned::<{type_}>(
+                            kernel::c_str!(\"{name}\"),
+                            None,
+                            (),
+                        )?,
+                    }})
+                }}
+            }}
+
+            kernel::prelude::module! {{
+                type: {module},
+                name: b\"{name}\",
+                {author}
+                {description}
+                license: b\"{license}\",
+                {alias}
+            }}
+        ",
+        module = module,
+        type_ = info.type_,
+        name = info.name,
+        author = info
+            .author
+            .map(|v| format!("author: b\"{}\",", v))
+            .unwrap_or_else(|| "".to_string()),
+        description = info
+            .description
+            .map(|v| format!("description: b\"{}\",", v))
+            .unwrap_or_else(|| "".to_string()),
+        alias = info
+            .alias
+            .map(|v| format!("alias: b\"{}\",", v))
+            .unwrap_or_else(|| "".to_string()),
+        license = info.license
+    )
+    .parse()
+    .expect("Error parsing formatted string into token stream.")
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_permissions_are_readonly() {
+        assert!(permissions_are_readonly("0b000000000"));
+        assert!(permissions_are_readonly("0o000"));
+        assert!(permissions_are_readonly("000"));
+        assert!(permissions_are_readonly("0x000"));
+
+        assert!(!permissions_are_readonly("0b111111111"));
+        assert!(!permissions_are_readonly("0o777"));
+        assert!(!permissions_are_readonly("511"));
+        assert!(!permissions_are_readonly("0x1ff"));
+
+        assert!(permissions_are_readonly("0o014"));
+        assert!(permissions_are_readonly("0o015"));
+
+        assert!(!permissions_are_readonly("0o214"));
+        assert!(!permissions_are_readonly("0o024"));
+        assert!(!permissions_are_readonly("0o012"));
+
+        assert!(!permissions_are_readonly("0o315"));
+        assert!(!permissions_are_readonly("0o065"));
+        assert!(!permissions_are_readonly("0o017"));
+    }
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 11/17] rust: export generated symbols
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (7 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 09/17] rust: add `macros` crate ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:27 ` [PATCH 12/17] Kbuild: add Rust support ojeda
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/exports.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 rust/exports.c

diff --git a/rust/exports.c b/rust/exports.c
new file mode 100644
index 00000000000..d7dff1b3b91
--- /dev/null
+++ b/rust/exports.c
@@ -0,0 +1,16 @@
+// 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).
+
+#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"
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 12/17] Kbuild: add Rust support
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (8 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 11/17] rust: export generated symbols ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:27 ` [PATCH 13/17] docs: add Rust documentation ojeda
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 .gitignore                        |   5 +
 .rustfmt.toml                     |  12 ++
 Documentation/process/changes.rst |  13 ++
 Makefile                          | 159 ++++++++++++++-
 arch/arm/rust/target.json         |  28 +++
 arch/arm64/rust/target.json       |  35 ++++
 arch/powerpc/rust/target.json     |  30 +++
 arch/riscv/Makefile               |   1 +
 arch/riscv/rust/rv32ima.json      |  37 ++++
 arch/riscv/rust/rv32imac.json     |  37 ++++
 arch/riscv/rust/rv64ima.json      |  37 ++++
 arch/riscv/rust/rv64imac.json     |  37 ++++
 arch/x86/rust/target.json         |  37 ++++
 init/Kconfig                      |  28 +++
 lib/Kconfig.debug                 | 144 ++++++++++++++
 rust/.gitignore                   |   6 +
 rust/Makefile                     | 316 ++++++++++++++++++++++++++++++
 rust/bindgen_parameters           |  13 ++
 scripts/Makefile.build            |  22 +++
 scripts/Makefile.lib              |  12 ++
 scripts/kconfig/confdata.c        |  67 ++++++-
 scripts/rust-version.sh           |  31 +++
 22 files changed, 1099 insertions(+), 8 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/rust-version.sh

diff --git a/.gitignore b/.gitignore
index 7afd412dadd..48c68948f47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/.rustfmt.toml b/.rustfmt.toml
new file mode 100644
index 00000000000..4fea7c464f0
--- /dev/null
+++ b/.rustfmt.toml
@@ -0,0 +1,12 @@
+edition = "2018"
+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
diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
index d3a8557b66a..7654a7105dc 100644
--- a/Documentation/process/changes.rst
+++ b/Documentation/process/changes.rst
@@ -26,11 +26,18 @@ running a Linux kernel.  Also, not all tools are necessary on all
 systems; obviously, if you don't have any PC Card hardware, for example,
 you probably needn't concern yourself with pcmciautils.
 
+Furthermore, note that newer versions of the Rust toolchain may or may not work
+because, for the moment, we depend on some unstable features. Thus, unless you
+know what you are doing, use the exact version listed here. Please see
+:ref:`Documentation/rust/quick-start.rst <rust_quick_start>` for details.
+
 ====================== ===============  ========================================
         Program        Minimal version       Command to check the version
 ====================== ===============  ========================================
 GNU C                  4.9              gcc --version
 Clang/LLVM (optional)  10.0.1           clang --version
+rustc (optional)       1.54.0-beta.1    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
@@ -329,6 +336,12 @@ 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 Rust documentation. Please see
+:ref:`Documentation/rust/docs.rst <rust_docs>` for more information.
+
 Getting updated software
 ========================
 
diff --git a/Makefile b/Makefile
index 6e823d8bd64..c814b209b6c 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,13 @@ endif
 
 export KBUILD_CHECKSRC
 
+# Enable "clippy" (a linter) as part of the Rust compilation.
+#
+# Use 'make CLIPPY=1' to enable it.
+ifeq ("$(origin CLIPPY)", "command line")
+  KBUILD_CLIPPY := $(CLIPPY)
+endif
+
 # Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the
 # directory of external module to build. Setting M= takes precedence.
 ifeq ("$(origin M)", "command line")
@@ -263,7 +270,7 @@ no-dot-config-targets := $(clean-targets) \
 			 cscope gtags TAGS tags help% %docs check% coccicheck \
 			 $(version_h) headers headers_% archheaders archscripts \
 			 %asm-generic kernelversion %src-pkg dt_binding_check \
-			 outputmakefile
+			 outputmakefile rustfmt rustfmtcheck
 # Installation targets should not require compiler. Unfortunately, vdso_install
 # is an exception where build artifacts may be updated. This must be fixed.
 no-compiler-targets := $(no-dot-config-targets) install dtbs_install \
@@ -452,6 +459,12 @@ OBJDUMP		= $(CROSS_COMPILE)objdump
 READELF		= $(CROSS_COMPILE)readelf
 STRIP		= $(CROSS_COMPILE)strip
 endif
+RUSTC		= rustc
+RUSTDOC		= rustdoc
+RUSTFMT		= rustfmt
+CLIPPY_DRIVER	= clippy-driver
+BINDGEN		= bindgen
+CARGO		= cargo
 PAHOLE		= pahole
 RESOLVE_BTFIDS	= $(objtree)/tools/bpf/resolve_btfids/resolve_btfids
 LEX		= flex
@@ -475,9 +488,11 @@ CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
 		  -Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
 NOSTDINC_FLAGS :=
 CFLAGS_MODULE   =
+RUSTFLAGS_MODULE =
 AFLAGS_MODULE   =
 LDFLAGS_MODULE  =
 CFLAGS_KERNEL	=
+RUSTFLAGS_KERNEL =
 AFLAGS_KERNEL	=
 LDFLAGS_vmlinux =
 
@@ -506,15 +521,41 @@ KBUILD_CFLAGS   := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
 		   -Werror=return-type -Wno-format-security \
 		   -std=gnu89
 KBUILD_CPPFLAGS := -D__KERNEL__
+KBUILD_RUST_TARGET := $(srctree)/arch/$(SRCARCH)/rust/target.json
+KBUILD_RUSTFLAGS := --emit=dep-info,obj,metadata --edition=2018 \
+		     -Cpanic=abort -Cembed-bitcode=n -Clto=n -Crpath=n \
+		     -Cforce-unwind-tables=n -Ccodegen-units=1 \
+		     -Zbinary_dep_depinfo=y -Zsymbol-mangling-version=v0 \
+		     -Dunsafe_op_in_unsafe_fn -Drust_2018_idioms \
+		     -Wmissing_docs
+KBUILD_CLIPPYFLAGS := -Dclippy::correctness -Dclippy::style \
+		      -Dclippy::complexity -Dclippy::perf -Dclippy::float_arithmetic
 KBUILD_AFLAGS_KERNEL :=
 KBUILD_CFLAGS_KERNEL :=
+KBUILD_RUSTFLAGS_KERNEL :=
 KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
+KBUILD_RUSTFLAGS_MODULE := --cfg MODULE
 KBUILD_LDFLAGS_MODULE :=
 KBUILD_LDFLAGS :=
 CLANG_FLAGS :=
 
+ifeq ($(KBUILD_CLIPPY),1)
+	RUSTC_OR_CLIPPY_QUIET := CLIPPY
+	RUSTC_OR_CLIPPY = $(CLIPPY_DRIVER) $(KBUILD_CLIPPYFLAGS)
+else
+	RUSTC_OR_CLIPPY_QUIET := RUSTC
+	RUSTC_OR_CLIPPY = $(RUSTC)
+endif
+
+ifdef RUST_LIB_SRC
+	export RUST_LIB_SRC
+endif
+
+export RUSTC_BOOTSTRAP := 1
+
 export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
+export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN CARGO
 export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
 export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
 export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
@@ -522,9 +563,10 @@ export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
 
 export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
+export KBUILD_RUST_TARGET KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE
 export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
-export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
-export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
+export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_RUSTFLAGS_MODULE KBUILD_LDFLAGS_MODULE
+export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
 
 # Files to ignore in find ... statements
 
@@ -724,7 +766,7 @@ $(KCONFIG_CONFIG):
 quiet_cmd_syncconfig = SYNC    $@
       cmd_syncconfig = $(MAKE) -f $(srctree)/Makefile syncconfig
 
-%/config/auto.conf %/config/auto.conf.cmd %/generated/autoconf.h: $(KCONFIG_CONFIG)
+%/config/auto.conf %/config/auto.conf.cmd %/generated/autoconf.h %/generated/rustc_cfg: $(KCONFIG_CONFIG)
 	+$(call cmd,syncconfig)
 else # !may-sync-config
 # External modules and some install targets need include/generated/autoconf.h
@@ -750,12 +792,43 @@ KBUILD_CFLAGS	+= $(call cc-disable-warning, format-truncation)
 KBUILD_CFLAGS	+= $(call cc-disable-warning, format-overflow)
 KBUILD_CFLAGS	+= $(call cc-disable-warning, address-of-packed-member)
 
+ifdef CONFIG_RUST_DEBUG_ASSERTIONS
+KBUILD_RUSTFLAGS += -Cdebug-assertions=y
+else
+KBUILD_RUSTFLAGS += -Cdebug-assertions=n
+endif
+
+ifdef CONFIG_RUST_OVERFLOW_CHECKS
+KBUILD_RUSTFLAGS += -Coverflow-checks=y
+else
+KBUILD_RUSTFLAGS += -Coverflow-checks=n
+endif
+
 ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
 KBUILD_CFLAGS += -O2
+KBUILD_RUSTFLAGS_OPT_LEVEL_MAP := 2
 else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
 KBUILD_CFLAGS += -O3
+KBUILD_RUSTFLAGS_OPT_LEVEL_MAP := 3
 else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 KBUILD_CFLAGS += -Os
+KBUILD_RUSTFLAGS_OPT_LEVEL_MAP := z
+endif
+
+ifdef CONFIG_RUST_OPT_LEVEL_SIMILAR_AS_CHOSEN_FOR_C
+KBUILD_RUSTFLAGS += -Copt-level=$(KBUILD_RUSTFLAGS_OPT_LEVEL_MAP)
+else ifdef CONFIG_RUST_OPT_LEVEL_0
+KBUILD_RUSTFLAGS += -Copt-level=0
+else ifdef CONFIG_RUST_OPT_LEVEL_1
+KBUILD_RUSTFLAGS += -Copt-level=1
+else ifdef CONFIG_RUST_OPT_LEVEL_2
+KBUILD_RUSTFLAGS += -Copt-level=2
+else ifdef CONFIG_RUST_OPT_LEVEL_3
+KBUILD_RUSTFLAGS += -Copt-level=3
+else ifdef CONFIG_RUST_OPT_LEVEL_S
+KBUILD_RUSTFLAGS += -Copt-level=s
+else ifdef CONFIG_RUST_OPT_LEVEL_Z
+KBUILD_RUSTFLAGS += -Copt-level=z
 endif
 
 # Tell gcc to never replace conditional load with a non-conditional one
@@ -805,6 +878,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
 ifdef CONFIG_FRAME_POINTER
 KBUILD_CFLAGS	+= -fno-omit-frame-pointer -fno-optimize-sibling-calls
+KBUILD_RUSTFLAGS += -Cforce-frame-pointers=y
 else
 # Some targets (ARM with Thumb2, for example), can't be built with frame
 # pointers.  For those, we don't have FUNCTION_TRACER automatically
@@ -842,6 +916,8 @@ ifdef CONFIG_CC_IS_GCC
 DEBUG_CFLAGS	+= $(call cc-ifversion, -lt, 0500, $(call cc-option, -fno-var-tracking-assignments))
 endif
 
+DEBUG_RUSTFLAGS :=
+
 ifdef CONFIG_DEBUG_INFO
 
 ifdef CONFIG_DEBUG_INFO_SPLIT
@@ -852,6 +928,11 @@ endif
 
 ifneq ($(LLVM_IAS),1)
 KBUILD_AFLAGS	+= -Wa,-gdwarf-2
+ifdef CONFIG_DEBUG_INFO_REDUCED
+DEBUG_RUSTFLAGS += -Cdebuginfo=1
+else
+DEBUG_RUSTFLAGS += -Cdebuginfo=2
+endif
 endif
 
 ifndef CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
@@ -876,6 +957,9 @@ endif # CONFIG_DEBUG_INFO
 KBUILD_CFLAGS += $(DEBUG_CFLAGS)
 export DEBUG_CFLAGS
 
+KBUILD_RUSTFLAGS += $(DEBUG_RUSTFLAGS)
+export DEBUG_RUSTFLAGS
+
 ifdef CONFIG_FUNCTION_TRACER
 ifdef CONFIG_FTRACE_MCOUNT_USE_CC
   CC_FLAGS_FTRACE	+= -mrecord-mcount
@@ -1031,10 +1115,11 @@ include $(addprefix $(srctree)/, $(include-y))
 # Do not add $(call cc-option,...) below this line. When you build the kernel
 # from the clean source tree, the GCC plugins do not exist at this point.
 
-# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
+# Add user supplied CPPFLAGS, AFLAGS, CFLAGS and RUSTFLAGS as the last assignments
 KBUILD_CPPFLAGS += $(KCPPFLAGS)
 KBUILD_AFLAGS   += $(KAFLAGS)
 KBUILD_CFLAGS   += $(KCFLAGS)
+KBUILD_RUSTFLAGS += $(KRUSTFLAGS)
 
 KBUILD_LDFLAGS_MODULE += --build-id=sha1
 LDFLAGS_vmlinux += --build-id=sha1
@@ -1138,6 +1223,10 @@ export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
 ifeq ($(KBUILD_EXTMOD),)
 core-y		+= kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
 
+ifdef CONFIG_RUST
+core-y		+= rust/
+endif
+
 vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, \
 		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
 		     $(libs-y) $(libs-m)))
@@ -1238,6 +1327,9 @@ archprepare: outputmakefile archheaders archscripts scripts include/config/kerne
 prepare0: archprepare
 	$(Q)$(MAKE) $(build)=scripts/mod
 	$(Q)$(MAKE) $(build)=.
+ifdef CONFIG_RUST
+	$(Q)$(MAKE) $(build)=rust
+endif
 
 # All the preparing..
 prepare: prepare0 prepare-objtool prepare-resolve_btfids
@@ -1511,7 +1603,7 @@ endif # CONFIG_MODULES
 # Directories & files removed with 'make clean'
 CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \
 	       modules.builtin modules.builtin.modinfo modules.nsdeps \
-	       compile_commands.json .thinlto-cache
+	       compile_commands.json .thinlto-cache rust/test rust/doc
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_FILES += include/config include/generated          \
@@ -1522,7 +1614,8 @@ MRPROPER_FILES += include/config include/generated          \
 		  certs/signing_key.pem certs/signing_key.x509 \
 		  certs/x509.genkey \
 		  vmlinux-gdb.py \
-		  *.spec
+		  *.spec \
+		  rust/*_generated.h rust/*_generated.rs rust/libmacros.so
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1634,6 +1727,17 @@ help:
 	@echo  '  kselftest-merge   - Merge all the config dependencies of'
 	@echo  '		      kselftest to existing .config.'
 	@echo  ''
+	@echo  'Rust targets:'
+	@echo  '  rustfmt	  - Reformat all the Rust code in the kernel'
+	@echo  '  rustfmtcheck	  - Checks if all the Rust code in the kernel'
+	@echo  '		    is formatted, printing a diff otherwise.'
+	@echo  '  rustdoc	  - Generate Rust documentation'
+	@echo  '		    (requires kernel .config)'
+	@echo  '  rusttest        - Runs the Rust tests'
+	@echo  '                    (requires kernel .config; downloads external repos)'
+	@echo  '  rust-analyzer	  - Generate rust-project.json rust-analyzer support file'
+	@echo  '		    (requires kernel .config)'
+	@echo  ''
 	@$(if $(dtstree), \
 		echo 'Devicetree:'; \
 		echo '* dtbs             - Build device tree blobs for enabled boards'; \
@@ -1705,6 +1809,46 @@ PHONY += $(DOC_TARGETS)
 $(DOC_TARGETS):
 	$(Q)$(MAKE) $(build)=Documentation $@
 
+
+# Rust targets
+# ---------------------------------------------------------------------------
+
+# Documentation target
+#
+# Using the singular to avoid running afoul of `no-dot-config-targets`.
+PHONY += rustdoc
+rustdoc: prepare0
+	$(Q)$(MAKE) $(build)=rust $@
+
+# Testing target
+PHONY += rusttest
+rusttest: prepare0
+	$(Q)$(MAKE) $(build)=rust $@
+
+# Formatting targets
+PHONY += rustfmt rustfmtcheck
+
+# We skip `rust/alloc` since we want to minimize the diff w.r.t. upstream.
+#
+# We match using absolute paths since `find` does not resolve them
+# when matching, which is a problem when e.g. `srctree` is `..`.
+# We `grep` afterwards in order to remove the directory entry itself.
+rustfmt:
+	$(Q)find $(abs_srctree) -type f -name '*.rs' \
+		-o -path $(abs_srctree)/rust/alloc -prune \
+		-o -path $(abs_objtree)/rust/test -prune \
+		| grep -Fv $(abs_srctree)/rust/alloc \
+		| grep -Fv $(abs_objtree)/rust/test \
+		| xargs $(RUSTFMT) $(rustfmt_flags)
+
+rustfmtcheck: rustfmt_flags = --check
+rustfmtcheck: rustfmt
+
+# IDE support targets
+PHONY += rust-analyzer
+rust-analyzer: prepare0
+	$(Q)$(MAKE) $(build)=rust $@
+
 # Misc
 # ---------------------------------------------------------------------------
 
@@ -1862,6 +2006,7 @@ clean: $(clean-dirs)
 	$(call cmd,rmfiles)
 	@find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
 		\( -name '*.[aios]' -o -name '*.ko' -o -name '.*.cmd' \
+		-o -name '*.rmeta' \
 		-o -name '*.ko.*' \
 		-o -name '*.dtb' -o -name '*.dtbo' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
 		-o -name '*.dwo' -o -name '*.lst' \
diff --git a/arch/arm/rust/target.json b/arch/arm/rust/target.json
new file mode 100644
index 00000000000..37710eb727b
--- /dev/null
+++ b/arch/arm/rust/target.json
@@ -0,0 +1,28 @@
+{
+  "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,
+  "is-builtin": 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"
+}
diff --git a/arch/arm64/rust/target.json b/arch/arm64/rust/target.json
new file mode 100644
index 00000000000..9ea86ed6c73
--- /dev/null
+++ b/arch/arm64/rust/target.json
@@ -0,0 +1,35 @@
+{
+  "arch": "aarch64",
+  "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
+  "disable-redzone": true,
+  "eliminate-frame-pointer": false,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+strict-align,+neon,+fp-armv8",
+  "function-sections": false,
+  "is-builtin": true,
+  "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": ""
+}
diff --git a/arch/powerpc/rust/target.json b/arch/powerpc/rust/target.json
new file mode 100644
index 00000000000..1e53f830809
--- /dev/null
+++ b/arch/powerpc/rust/target.json
@@ -0,0 +1,30 @@
+{
+  "arch": "powerpc64",
+  "code-mode": "kernel",
+  "cpu": "ppc64le",
+  "data-layout": "e-m:e-i64:64-n32:64",
+  "env": "gnu",
+  "features": "-altivec,-vsx,-hard-float",
+  "function-sections": false,
+  "is-builtin": true,
+  "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"
+}
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 99ecd8bcfd7..2a476eb5da5 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -54,6 +54,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)
diff --git a/arch/riscv/rust/rv32ima.json b/arch/riscv/rust/rv32ima.json
new file mode 100644
index 00000000000..8e9b46011e7
--- /dev/null
+++ b/arch/riscv/rust/rv32ima.json
@@ -0,0 +1,37 @@
+{
+  "arch": "riscv32",
+  "code-model": "medium",
+  "cpu": "generic-rv32",
+  "data-layout": "e-m:e-p:32:32-i64:64-n32-S128",
+  "disable-redzone": true,
+  "eliminate-frame-pointer": false,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a",
+  "function-sections": false,
+  "is-builtin": true,
+  "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": ""
+}
diff --git a/arch/riscv/rust/rv32imac.json b/arch/riscv/rust/rv32imac.json
new file mode 100644
index 00000000000..2b3a139da99
--- /dev/null
+++ b/arch/riscv/rust/rv32imac.json
@@ -0,0 +1,37 @@
+{
+  "arch": "riscv32",
+  "code-model": "medium",
+  "cpu": "generic-rv32",
+  "data-layout": "e-m:e-p:32:32-i64:64-n32-S128",
+  "disable-redzone": true,
+  "eliminate-frame-pointer": false,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a,+c",
+  "function-sections": false,
+  "is-builtin": true,
+  "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": ""
+}
diff --git a/arch/riscv/rust/rv64ima.json b/arch/riscv/rust/rv64ima.json
new file mode 100644
index 00000000000..091da50069a
--- /dev/null
+++ b/arch/riscv/rust/rv64ima.json
@@ -0,0 +1,37 @@
+{
+  "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,
+  "eliminate-frame-pointer": false,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a",
+  "function-sections": false,
+  "is-builtin": true,
+  "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": ""
+}
diff --git a/arch/riscv/rust/rv64imac.json b/arch/riscv/rust/rv64imac.json
new file mode 100644
index 00000000000..aa5a8f4549f
--- /dev/null
+++ b/arch/riscv/rust/rv64imac.json
@@ -0,0 +1,37 @@
+{
+  "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,
+  "eliminate-frame-pointer": false,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "+m,+a,+c",
+  "function-sections": false,
+  "is-builtin": true,
+  "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": ""
+}
diff --git a/arch/x86/rust/target.json b/arch/x86/rust/target.json
new file mode 100644
index 00000000000..76ac800d38e
--- /dev/null
+++ b/arch/x86/rust/target.json
@@ -0,0 +1,37 @@
+{
+  "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,
+  "eliminate-frame-pointer": false,
+  "emit-debug-gdb-scripts": false,
+  "env": "gnu",
+  "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
+  "function-sections": false,
+  "is-builtin": true,
+  "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"
+}
diff --git a/init/Kconfig b/init/Kconfig
index a61c92066c2..5318f209a3b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -60,6 +60,15 @@ config LLD_VERSION
 	default $(ld-version) if LD_IS_LLD
 	default 0
 
+config HAS_RUST
+	depends on ARM64 || CPU_32v6 || CPU_32v6K || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || RISCV
+	def_bool $(success,$(RUSTC) --version)
+
+config RUSTC_VERSION
+	depends on HAS_RUST
+	int
+	default $(shell,$(srctree)/scripts/rust-version.sh $(RUSTC))
+
 config CC_CAN_LINK
 	bool
 	default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(m64-flag)) if 64BIT
@@ -2011,6 +2020,25 @@ config PROFILING
 	  Say Y here to enable the extended profiling support mechanisms used
 	  by profilers.
 
+config RUST
+	bool "Rust support"
+	depends on HAS_RUST
+	depends on !COMPILE_TEST
+	depends on !MODVERSIONS
+	default n
+	help
+	  Enables Rust support in the kernel.
+
+	  This allows other Rust-related options, like drivers written in Rust,
+	  to be selected.
+
+	  It is also required to be able to load external kernel modules
+	  written in Rust.
+
+	  See Documentation/rust/ for more information.
+
+	  If unsure, say N.
+
 #
 # Place an empty function call at each tracepoint site. Can be
 # dynamically changed for a probe function.
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 678c1396758..30b705709c2 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2602,6 +2602,150 @@ config HYPERV_TESTING
 
 endmenu # "Kernel Testing and Coverage"
 
+menu "Rust hacking"
+
+config RUST_DEBUG_ASSERTIONS
+	bool "Debug assertions"
+	default n
+	depends on RUST
+	help
+	  Enables rustc's `-Cdebug-assertions` codegen option.
+
+	  This flag lets you turn `cfg(debug_assertions)` conditional
+	  compilation on or off. This can be used to enable extra debugging
+	  code in development but not in production. For example, it controls
+	  the behavior of the standard library's `debug_assert!` macro.
+
+	  Note that this will apply to all Rust code, including `core`.
+
+	  If unsure, say N.
+
+config RUST_OVERFLOW_CHECKS
+	bool "Overflow checks"
+	default y
+	depends on RUST
+	help
+	  Enables rustc's `-Coverflow-checks` codegen option.
+
+	  This flag allows you to control the behavior of runtime integer
+	  overflow. When overflow-checks are enabled, a panic will occur
+	  on overflow.
+
+	  Note that this will apply to all Rust code, including `core`.
+
+	  If unsure, say Y.
+
+choice
+	prompt "Optimization level"
+	default RUST_OPT_LEVEL_SIMILAR_AS_CHOSEN_FOR_C
+	depends on RUST
+	help
+	  Controls rustc's `-Copt-level` codegen option.
+
+	  This flag controls the optimization level.
+
+	  If unsure, say "Similar as chosen for C".
+
+config RUST_OPT_LEVEL_SIMILAR_AS_CHOSEN_FOR_C
+	bool "Similar as chosen for C"
+	help
+	  This choice will pick a similar optimization level as chosen in
+	  the "Compiler optimization level" for C:
+
+	      -O2 is currently mapped to -Copt-level=2
+	      -O3 is currently mapped to -Copt-level=3
+	      -Os is currently mapped to -Copt-level=z
+
+	  The mapping may change over time to follow the intended semantics
+	  of the choice for C as sensibly as possible.
+
+	  This is the default.
+
+config RUST_OPT_LEVEL_0
+	bool "No optimizations (-Copt-level=0)"
+	help
+	  Not recommended for most purposes. It may come in handy for debugging
+	  suspected optimizer bugs, unexpected undefined behavior, etc.
+
+	  Note that this level will *not* enable debug assertions nor overflow
+	  checks on its own (like it happens when interacting with rustc
+	  directly). Use the corresponding configuration options to control
+	  that instead, orthogonally.
+
+	  Note this level may cause excessive stack usage, which can lead to stack
+	  overflow and subsequent crashes.
+
+config RUST_OPT_LEVEL_1
+	bool "Basic optimizations (-Copt-level=1)"
+	help
+	  Useful for debugging without getting too lost, but without
+	  the overhead and boilerplate of no optimizations at all.
+
+	  Note this level may cause excessive stack usage, which can lead to stack
+	  overflow and subsequent crashes.
+
+config RUST_OPT_LEVEL_2
+	bool "Some optimizations (-Copt-level=2)"
+	help
+	  The sensible choice in most cases.
+
+config RUST_OPT_LEVEL_3
+	bool "All optimizations (-Copt-level=3)"
+	help
+	  Yet more performance (hopefully).
+
+config RUST_OPT_LEVEL_S
+	bool "Optimize for size (-Copt-level=s)"
+	help
+	  Smaller kernel, ideally without too much performance loss.
+
+config RUST_OPT_LEVEL_Z
+	bool "Optimize for size, no loop vectorization (-Copt-level=z)"
+	help
+	  Like the previous level, but also turn off loop vectorization.
+
+endchoice
+
+choice
+	prompt "Build-time assertions"
+	default RUST_BUILD_ASSERT_ALLOW if RUST_OPT_LEVEL_0
+	default RUST_BUILD_ASSERT_DENY if !RUST_OPT_LEVEL_0
+	depends on RUST
+	help
+	  Controls how are `build_error!` and `build_assert!` handled during build.
+
+	  If calls to them exist in the binary, it may indicate a violated invariant
+	  or that the optimizer failed to verify the invariant during compilation.
+	  You can choose to abort compilation or ignore them during build and let the
+	  check be carried to runtime.
+
+	  If optimizations are turned off, you cannot select "Deny".
+
+	  If unsure, say "Deny".
+
+config RUST_BUILD_ASSERT_ALLOW
+	bool "Allow"
+	help
+	  Unoptimized calls to `build_error!` will be converted to `panic!`
+	  and checked at runtime.
+
+config RUST_BUILD_ASSERT_WARN
+	bool "Warn"
+	help
+	  Unoptimized calls to `build_error!` will be converted to `panic!`
+	  and checked at runtime, but warnings will be generated when building.
+
+config RUST_BUILD_ASSERT_DENY
+	bool "Deny"
+	depends on !RUST_OPT_LEVEL_0
+	help
+	  Unoptimized calls to `build_error!` will abort compilation.
+
+endchoice
+
+
+endmenu # "Rust"
+
 source "Documentation/Kconfig"
 
 endmenu # Kernel hacking
diff --git a/rust/.gitignore b/rust/.gitignore
new file mode 100644
index 00000000000..c6186b71e1c
--- /dev/null
+++ b/rust/.gitignore
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+bindings_generated.rs
+exports_*_generated.h
+doc/
+test/
diff --git a/rust/Makefile b/rust/Makefile
new file mode 100644
index 00000000000..233b8f36548
--- /dev/null
+++ b/rust/Makefile
@@ -0,0 +1,316 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_RUST) += core.o compiler_builtins.o helpers.o
+extra-$(CONFIG_RUST) += exports_core_generated.h
+
+extra-$(CONFIG_RUST) += libmacros.so
+
+extra-$(CONFIG_RUST) += bindings_generated.rs
+obj-$(CONFIG_RUST) += alloc.o kernel.o
+extra-$(CONFIG_RUST) += exports_alloc_generated.h exports_kernel_generated.h
+
+ifdef CONFIG_RUST_BUILD_ASSERT_DENY
+extra-$(CONFIG_RUST) += build_error.o
+else
+obj-$(CONFIG_RUST) += build_error.o
+endif
+
+obj-$(CONFIG_RUST) += exports.o
+
+ifeq ($(quiet),silent_)
+cargo_quiet=-q
+rust_test_quiet=-q
+rustdoc_test_quiet=--test-args -q
+else ifeq ($(quiet),quiet_)
+rust_test_quiet=-q
+rustdoc_test_quiet=--test-args -q
+else
+cargo_quiet=--verbose
+endif
+
+quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
+      cmd_rustdoc = \
+	RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
+	$(RUSTDOC) $(if $(rustdoc_host),,$(rust_cross_flags)) \
+		$(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags))) \
+		$(rustc_target_flags) -L $(objtree)/rust \
+		--output $(objtree)/rust/doc --crate-name $(subst rustdoc-,,$@) \
+		@$(objtree)/include/generated/rustc_cfg $<
+
+# This is a temporary fix for the CSS, visible on `type`s (`Result`).
+# It is already fixed in nightly.
+RUSTDOC_FIX_BEFORE := .impl,.method,.type:not(.container-rustdoc),.associatedconstant,.associatedtype
+RUSTDOC_FIX_AFTER := .impl,.impl-items .method,.methods .method,.impl-items \
+	.type,.methods .type,.impl-items .associatedconstant,.methods \
+	.associatedconstant,.impl-items .associatedtype,.methods .associatedtype
+
+rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins rustdoc-alloc rustdoc-kernel
+	$(Q)cp $(srctree)/Documentation/rust/assets/* $(objtree)/rust/doc
+	$(Q)sed -i "s/$(RUSTDOC_FIX_BEFORE)/$(RUSTDOC_FIX_AFTER)/" \
+		$(objtree)/rust/doc/rustdoc.css
+
+rustdoc-macros: private rustdoc_host = yes
+rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \
+    --extern proc_macro
+rustdoc-macros: $(srctree)/rust/macros/lib.rs FORCE
+	$(call if_changed,rustdoc)
+
+rustdoc-compiler_builtins: $(srctree)/rust/compiler_builtins.rs rustdoc-core FORCE
+	$(call if_changed,rustdoc)
+
+# We need to allow `broken_intra_doc_links` because some
+# `no_global_oom_handling` functions refer to non-`no_global_oom_handling`
+# functions. Ideally `rustdoc` would have a way to distinguish broken links
+# due to things that are "configured out" vs. entirely non-existing ones.
+rustdoc-alloc: private rustc_target_flags = --cfg no_global_oom_handling \
+    -Abroken_intra_doc_links
+rustdoc-alloc: $(srctree)/rust/alloc/lib.rs rustdoc-core \
+    rustdoc-compiler_builtins FORCE
+	$(call if_changed,rustdoc)
+
+rustdoc-kernel: private rustc_target_flags = --extern alloc \
+    --extern build_error \
+    --extern macros=$(objtree)/rust/libmacros.so
+rustdoc-kernel: $(srctree)/rust/kernel/lib.rs rustdoc-core \
+    rustdoc-macros rustdoc-compiler_builtins rustdoc-alloc \
+    $(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs FORCE
+	$(call if_changed,rustdoc)
+
+quiet_cmd_rustc_test_library = RUSTC TL $<
+      cmd_rustc_test_library = \
+	RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
+	$(RUSTC) $(filter-out --sysroot=%, $(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags)))) \
+		$(rustc_target_flags) --crate-type $(if $(rustc_test_library_proc),proc-macro,rlib) \
+		--out-dir $(objtree)/rust/test/ --cfg testlib \
+		--sysroot $(objtree)/rust/test/sysroot \
+		-L $(objtree)/rust/test/ --crate-name $(subst rusttest-,,$(subst rusttestlib-,,$@)) $<
+
+rusttestlib-build_error: $(srctree)/rust/build_error.rs rusttest-prepare FORCE
+	$(call if_changed,rustc_test_library)
+
+rusttestlib-macros: private rustc_target_flags = --extern proc_macro
+rusttestlib-macros: private rustc_test_library_proc = yes
+rusttestlib-macros: $(srctree)/rust/macros/lib.rs rusttest-prepare FORCE
+	$(call if_changed,rustc_test_library)
+
+quiet_cmd_rustdoc_test = RUSTDOC T $<
+      cmd_rustdoc_test = \
+	RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
+	$(RUSTDOC) --test $(filter-out --sysroot=%, $(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags)))) \
+		$(rustc_target_flags) $(rustdoc_test_target_flags) \
+		--sysroot $(objtree)/rust/test/sysroot $(rustdoc_test_quiet) \
+		-L $(objtree)/rust/test \
+		--output $(objtree)/rust/doc --crate-name $(subst rusttest-,,$@) \
+		@$(objtree)/include/generated/rustc_cfg $<
+
+# We cannot use `-Zpanic-abort-tests` because some tests are dynamic,
+# so for the moment we skip `-Cpanic=abort`.
+quiet_cmd_rustc_test = RUSTC T  $<
+      cmd_rustc_test = \
+	RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
+	$(RUSTC) --test $(filter-out --sysroot=%, $(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags)))) \
+		$(rustc_target_flags) --out-dir $(objtree)/rust/test \
+		--sysroot $(objtree)/rust/test/sysroot \
+		-L $(objtree)/rust/test/ --crate-name $(subst rusttest-,,$@) $<; \
+	$(objtree)/rust/test/$(subst rusttest-,,$@) $(rust_test_quiet) \
+		$(rustc_test_run_flags)
+
+rusttest: rusttest-macros rusttest-kernel
+
+# This prepares a custom sysroot with our custom `alloc` instead of
+# the standard one.
+#
+# This requires several hacks:
+#   - Unlike `core` and `alloc`, `std` depends on more than a dozen crates,
+#     including third-party crates that need to be downloaded, plus custom
+#     `build.rs` steps. Thus hardcoding things here is not maintainable.
+#   - `cargo` knows how to build the standard library, but it is an unstable
+#     feature so far (`-Zbuild-std`).
+#   - `cargo` only considers the use case of building the standard library
+#     to use it in a given package. Thus we need to create a dummy package
+#     and pick the generated libraries from there.
+#   - Since we only keep a subset of upstream `alloc` in-tree, we need
+#     to recreate it on the fly by putting our sources on top.
+#   - The usual ways of modifying the dependency graph in `cargo` do not seem
+#     to apply for the `-Zbuild-std` steps, thus we have to mislead it
+#     by modifying the sources in the sysroot.
+#   - To avoid messing with the user's Rust installation, we create a clone
+#     of the sysroot. However, `cargo` ignores `RUSTFLAGS` in the `-Zbuild-std`
+#     steps, thus we use a wrapper binary passed via `RUSTC` to pass the flag.
+#
+# In the future, we hope to avoid the whole ordeal by either:
+#   - Making the `test` crate not depend on `std` (either improving upstream
+#     or having our own custom crate).
+#   - Making the tests run in kernel space (requires the previous point).
+#   - Making `std` and friends be more like a "normal" crate, so that
+#     `-Zbuild-std` and related hacks are not needed.
+quiet_cmd_rustsysroot = RUSTSYSROOT
+      cmd_rustsysroot = \
+	rm -rf $(objtree)/rust/test; \
+	mkdir -p $(objtree)/rust/test; \
+	cp -a $(rustc_sysroot) $(objtree)/rust/test/sysroot; \
+	cp -r $(srctree)/rust/alloc/* \
+		$(objtree)/rust/test/sysroot/lib/rustlib/src/rust/library/alloc/src; \
+	echo '\#!/bin/sh' > $(objtree)/rust/test/rustc_sysroot; \
+	echo "$(RUSTC) --sysroot=$(abspath $(objtree)/rust/test/sysroot) \"\$$@\"" \
+		>> $(objtree)/rust/test/rustc_sysroot; \
+	chmod u+x $(objtree)/rust/test/rustc_sysroot; \
+	$(CARGO) -q new $(objtree)/rust/test/dummy; \
+	RUSTC=$(objtree)/rust/test/rustc_sysroot $(CARGO) $(cargo_quiet) \
+		test -Zbuild-std --target $(rustc_host_target) \
+		--manifest-path $(objtree)/rust/test/dummy/Cargo.toml; \
+	rm $(objtree)/rust/test/sysroot/lib/rustlib/$(rustc_host_target)/lib/*; \
+	cp $(objtree)/rust/test/dummy/target/$(rustc_host_target)/debug/deps/* \
+		$(objtree)/rust/test/sysroot/lib/rustlib/$(rustc_host_target)/lib
+
+rusttest-prepare: FORCE
+	$(call if_changed,rustsysroot)
+
+rusttest-macros: private rustc_target_flags = --extern proc_macro
+rusttest-macros: private rustdoc_test_target_flags = --crate-type proc-macro
+rusttest-macros: $(srctree)/rust/macros/lib.rs rusttest-prepare FORCE
+	$(call if_changed,rustc_test)
+	$(call if_changed,rustdoc_test)
+
+rusttest-kernel: private rustc_target_flags = --extern alloc \
+    --extern build_error --extern macros
+rusttest-kernel: private rustc_test_run_flags = \
+    --skip bindgen_test_layout_
+rusttest-kernel: $(srctree)/rust/kernel/lib.rs rusttest-prepare \
+    rusttestlib-build_error rusttestlib-macros FORCE
+	$(call if_changed,rustc_test)
+	$(call if_changed,rustc_test_library)
+	$(call if_changed,rustdoc_test)
+
+ifdef CONFIG_CC_IS_CLANG
+bindgen_c_flags = $(c_flags)
+else
+# bindgen relies on libclang to parse C. Ideally, bindgen would support a GCC
+# plugin backend and/or the Clang driver would be perfectly compatible with GCC.
+#
+# For the moment, here we are tweaking the flags on the fly. Some config
+# options may not work (e.g. `GCC_PLUGIN_RANDSTRUCT` if we end up using one
+# of those structs). We might want to redo how Clang flags are kept track of
+# in the general `Makefile` even for GCC builds, similar to what we did with
+# `TENTATIVE_CLANG_FLAGS`.
+bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
+	-mskip-rax-setup -mgeneral-regs-only -msign-return-address=% \
+	-mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount \
+	-mabi=lp64 -mstack-protector-guard% -fconserve-stack -falign-jumps=% \
+	-falign-loops=% -fno-ipa-cp-clone -fno-partial-inlining \
+	-fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \
+	-Wno-packed-not-aligned -Wno-format-truncation -Wno-format-overflow \
+	-Wno-stringop-truncation -Wno-unused-but-set-variable \
+	-Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized \
+	-Werror=designated-init -Wno-zero-length-bounds \
+	--param=% --param asan-%
+
+# PowerPC
+bindgen_skip_c_flags += -mtraceback=no -mno-pointers-to-nested-functions \
+	-mno-string -mno-strict-align
+
+bindgen_extra_c_flags = $(TENTATIVE_CLANG_FLAGS) -Wno-address-of-packed-member
+bindgen_c_flags = $(filter-out $(bindgen_skip_c_flags), $(c_flags)) \
+	$(bindgen_extra_c_flags)
+endif
+
+# To avoid several recompilations in PowerPC, which inserts `-D_TASK_CPU`
+bindgen_c_flags_final = $(filter-out -D_TASK_CPU=%, $(bindgen_c_flags))
+
+quiet_cmd_bindgen = BINDGEN $@
+      cmd_bindgen = \
+	$(BINDGEN) $< $(shell grep -v '^\#\|^$$' $(srctree)/rust/bindgen_parameters) \
+		--use-core --with-derive-default --ctypes-prefix c_types \
+		--no-debug '.*' \
+		--size_t-is-usize -o $@ -- $(bindgen_c_flags_final) -DMODULE
+
+$(objtree)/rust/bindings_generated.rs: $(srctree)/rust/kernel/bindings_helper.h \
+	$(srctree)/rust/bindgen_parameters FORCE
+	$(call if_changed_dep,bindgen)
+
+quiet_cmd_exports = EXPORTS $@
+      cmd_exports = \
+	$(NM) -p --defined-only $< \
+		| grep -E ' (T|R|D) ' | cut -d ' ' -f 3 \
+		| xargs -Isymbol \
+		echo 'EXPORT_SYMBOL_RUST_GPL(symbol);' > $@
+
+$(objtree)/rust/exports_core_generated.h: $(objtree)/rust/core.o FORCE
+	$(call if_changed,exports)
+
+$(objtree)/rust/exports_alloc_generated.h: $(objtree)/rust/alloc.o FORCE
+	$(call if_changed,exports)
+
+$(objtree)/rust/exports_kernel_generated.h: $(objtree)/rust/kernel.o FORCE
+	$(call if_changed,exports)
+
+# `-Cpanic=unwind -Cforce-unwind-tables=y` overrides `rust_flags` in order to
+# avoid the https://github.com/rust-lang/rust/issues/82320 rustc crash.
+quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
+      cmd_rustc_procmacro = \
+	$(RUSTC_OR_CLIPPY) $(rust_flags) \
+		--emit=dep-info,link --extern proc_macro \
+		-Cpanic=unwind -Cforce-unwind-tables=y \
+		--crate-type proc-macro --out-dir $(objtree)/rust/ \
+		--crate-name $(patsubst lib%.so,%,$(notdir $@)) $<; \
+	mv $(objtree)/rust/$(patsubst lib%.so,%,$(notdir $@)).d $(depfile); \
+	sed -i '/^\#/d' $(depfile)
+
+# Procedural macros can only be used with the `rustc` that compiled it.
+# Therefore, to get `libmacros.so` automatically recompiled when the compiler
+# version changes, we add `core.o` as a dependency (even if it is not needed).
+$(objtree)/rust/libmacros.so: $(srctree)/rust/macros/lib.rs \
+	$(objtree)/rust/core.o FORCE
+	$(call if_changed_dep,rustc_procmacro)
+
+quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
+      cmd_rustc_library = \
+	RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
+	$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
+		$(rust_flags) $(rust_cross_flags) $(rustc_target_flags) \
+		--crate-type rlib --out-dir $(objtree)/rust/ -L $(objtree)/rust/ \
+		--crate-name $(patsubst %.o,%,$(notdir $@)) $<; \
+	mv $(objtree)/rust/$(patsubst %.o,%,$(notdir $@)).d $(depfile); \
+	sed -i '/^\#/d' $(depfile) \
+	$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@)
+
+# `$(rust_flags)` is passed in case the user added `--sysroot`.
+rustc_sysroot = $(shell $(RUSTC) $(rust_flags) --print sysroot)
+rustc_host_target = $(shell $(RUSTC) --version --verbose | grep -F 'host: ' | cut -d' ' -f2)
+RUST_LIB_SRC ?= $(rustc_sysroot)/lib/rustlib/src/rust/library
+
+rust-analyzer:
+	$(Q)$(srctree)/scripts/generate_rust_analyzer.py $(srctree) $(objtree) $(RUST_LIB_SRC) $(objtree)/rust/bindings_generated.rs > $(objtree)/rust-project.json
+
+$(objtree)/rust/compiler_builtins.o: private rustc_objcopy = -w -W '__*'
+$(objtree)/rust/compiler_builtins.o: $(srctree)/rust/compiler_builtins.rs \
+    $(objtree)/rust/core.o FORCE
+	$(call if_changed_dep,rustc_library)
+
+$(objtree)/rust/alloc.o: private skip_clippy = 1
+$(objtree)/rust/alloc.o: private rustc_target_flags = --cfg no_global_oom_handling
+$(objtree)/rust/alloc.o: $(srctree)/rust/alloc/lib.rs \
+    $(objtree)/rust/compiler_builtins.o FORCE
+	$(call if_changed_dep,rustc_library)
+
+$(objtree)/rust/build_error.o: $(srctree)/rust/build_error.rs \
+    $(objtree)/rust/compiler_builtins.o FORCE
+	$(call if_changed_dep,rustc_library)
+
+# ICE on `--extern macros`: https://github.com/rust-lang/rust/issues/56935
+$(objtree)/rust/kernel.o: private rustc_target_flags = --extern alloc \
+    --extern build_error \
+    --extern macros=$(objtree)/rust/libmacros.so
+$(objtree)/rust/kernel.o: $(srctree)/rust/kernel/lib.rs $(objtree)/rust/alloc.o \
+    $(objtree)/rust/build_error.o \
+    $(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs FORCE
+	$(call if_changed_dep,rustc_library)
+
+# Targets that need to expand twice
+.SECONDEXPANSION:
+$(objtree)/rust/core.o: private skip_clippy = 1
+$(objtree)/rust/core.o: $$(RUST_LIB_SRC)/core/src/lib.rs FORCE
+	$(call if_changed_dep,rustc_library)
+
+rustdoc-core: $$(RUST_LIB_SRC)/core/src/lib.rs FORCE
+	$(call if_changed,rustdoc)
diff --git a/rust/bindgen_parameters b/rust/bindgen_parameters
new file mode 100644
index 00000000000..c2cc4a88234
--- /dev/null
+++ b/rust/bindgen_parameters
@@ -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
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 949f723efe5..bb22acf8415 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -26,6 +26,7 @@ EXTRA_CPPFLAGS :=
 EXTRA_LDFLAGS  :=
 asflags-y  :=
 ccflags-y  :=
+rustflags-y :=
 cppflags-y :=
 ldflags-y  :=
 
@@ -288,6 +289,27 @@ quiet_cmd_cc_lst_c = MKLST   $@
 $(obj)/%.lst: $(src)/%.c FORCE
 	$(call if_changed_dep,cc_lst_c)
 
+# Compile Rust sources (.rs)
+# ---------------------------------------------------------------------------
+
+# Need to use absolute path here and have symbolic links resolved;
+# otherwise rustdoc and rustc compute different hashes for the target.
+rust_cross_flags := --target=$(realpath $(KBUILD_RUST_TARGET))
+
+quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
+      cmd_rustc_o_rs = \
+	RUST_MODFILE=$(modfile) \
+	$(RUSTC_OR_CLIPPY) $(rust_flags) $(rust_cross_flags) \
+		-Zallow-features=allocator_api,bench_black_box,concat_idents,global_asm,try_reserve \
+		--extern alloc --extern kernel \
+		--crate-type rlib --out-dir $(obj) -L $(objtree)/rust/ \
+		--crate-name $(patsubst %.o,%,$(notdir $@)) $<; \
+	mv $(obj)/$(subst .o,,$(notdir $@)).d $(depfile); \
+	sed -i '/^\#/d' $(depfile)
+
+$(obj)/%.o: $(src)/%.rs FORCE
+	$(call if_changed_dep,rustc_o_rs)
+
 # Compile assembler sources (.S)
 # ---------------------------------------------------------------------------
 
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 10950559b22..cee5af32c65 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -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)) \
@@ -202,6 +207,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))
@@ -211,6 +221,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)
 
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index cf72680cd76..d9fc638dfa8 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -651,6 +651,56 @@ static struct conf_printer kconfig_printer_cb =
 	.print_comment = kconfig_print_comment,
 };
 
+/*
+ * rustc cfg printer
+ *
+ * This printer is used when generating the resulting rustc configuration
+ * after kconfig invocation and `defconfig` files.
+ */
+static void rustc_cfg_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+	const char *str;
+
+	switch (sym->type) {
+	case S_INT:
+	case S_HEX:
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		str = sym_escape_string_value(value);
+
+		/*
+		 * We don't care about disabled ones, i.e. no need for
+		 * what otherwise are "comments" in other printers.
+		 */
+		if (*value == 'n')
+			return;
+
+		/*
+		 * To have similar functionality to the C macro `IS_ENABLED()`
+		 * we provide an empty `--cfg CONFIG_X` here in both `y`
+		 * and `m` cases.
+		 *
+		 * Then, the common `fprintf()` below will also give us
+		 * a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can
+		 * be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`.
+		 */
+		if (*value == 'y' || *value == 'm')
+			fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name);
+
+		break;
+	default:
+		str = value;
+		break;
+	}
+
+	fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, str);
+}
+
+static struct conf_printer rustc_cfg_printer_cb =
+{
+	.print_symbol = rustc_cfg_print_symbol,
+};
+
 /*
  * Header printer
  *
@@ -1058,7 +1108,7 @@ int conf_write_autoconf(int overwrite)
 	struct symbol *sym;
 	const char *name;
 	const char *autoconf_name = conf_get_autoconfig_name();
-	FILE *out, *out_h;
+	FILE *out, *out_h, *out_rustc_cfg;
 	int i;
 
 	if (!overwrite && is_present(autoconf_name))
@@ -1079,6 +1129,13 @@ int conf_write_autoconf(int overwrite)
 		return 1;
 	}
 
+	out_rustc_cfg = fopen(".tmp_rustc_cfg", "w");
+	if (!out_rustc_cfg) {
+		fclose(out);
+		fclose(out_h);
+		return 1;
+	}
+
 	conf_write_heading(out, &kconfig_printer_cb, NULL);
 	conf_write_heading(out_h, &header_printer_cb, NULL);
 
@@ -1090,9 +1147,11 @@ int conf_write_autoconf(int overwrite)
 		/* write symbols to auto.conf and autoconf.h */
 		conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
 		conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
+		conf_write_symbol(out_rustc_cfg, sym, &rustc_cfg_printer_cb, NULL);
 	}
 	fclose(out);
 	fclose(out_h);
+	fclose(out_rustc_cfg);
 
 	name = getenv("KCONFIG_AUTOHEADER");
 	if (!name)
@@ -1111,6 +1170,12 @@ int conf_write_autoconf(int overwrite)
 	if (rename(".tmpconfig", autoconf_name))
 		return 1;
 
+	name = "include/generated/rustc_cfg";
+	if (make_parent_dir(name))
+		return 1;
+	if (rename(".tmp_rustc_cfg", name))
+		return 1;
+
 	return 0;
 }
 
diff --git a/scripts/rust-version.sh b/scripts/rust-version.sh
new file mode 100755
index 00000000000..67b6d31688e
--- /dev/null
+++ b/scripts/rust-version.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# rust-version rust-command
+#
+# Print the compiler version of `rust-command' in a 5 or 6-digit form
+# such as `14502' for rustc-1.45.2 etc.
+#
+# Returns 0 if not found (so that Kconfig does not complain)
+compiler="$*"
+
+if [ ${#compiler} -eq 0 ]; then
+	echo "Error: No compiler specified." >&2
+	printf "Usage:\n\t$0 <rust-command>\n" >&2
+	exit 1
+fi
+
+if ! command -v $compiler >/dev/null 2>&1; then
+	echo 0
+	exit 0
+fi
+
+VERSION=$($compiler --version | cut -f2 -d' ')
+
+# Cut suffix if any (e.g. `-dev`)
+VERSION=$(echo $VERSION | cut -f1 -d'-')
+
+MAJOR=$(echo $VERSION | cut -f1 -d'.')
+MINOR=$(echo $VERSION | cut -f2 -d'.')
+PATCHLEVEL=$(echo $VERSION | cut -f3 -d'.')
+printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 13/17] docs: add Rust documentation
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (9 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 12/17] Kbuild: add Rust support ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-05  5:02   ` Willy Tarreau
  2021-07-14 18:37   ` Nick Desaulniers
  2021-07-04 20:27 ` [PATCH 14/17] samples: add Rust examples ojeda
                   ` (5 subsequent siblings)
  16 siblings, 2 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

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

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 Documentation/doc-guide/kernel-doc.rst      |   3 +
 Documentation/index.rst                     |   1 +
 Documentation/kbuild/kbuild.rst             |   4 +
 Documentation/rust/arch-support.rst         |  35 +++
 Documentation/rust/assets/favicon-16x16.png | Bin 0 -> 798 bytes
 Documentation/rust/assets/favicon-32x32.png | Bin 0 -> 2076 bytes
 Documentation/rust/assets/rust-logo.png     | Bin 0 -> 53976 bytes
 Documentation/rust/coding.rst               |  92 ++++++++
 Documentation/rust/docs.rst                 | 110 ++++++++++
 Documentation/rust/index.rst                |  20 ++
 Documentation/rust/quick-start.rst          | 222 ++++++++++++++++++++
 11 files changed, 487 insertions(+)
 create mode 100644 Documentation/rust/arch-support.rst
 create mode 100644 Documentation/rust/assets/favicon-16x16.png
 create mode 100644 Documentation/rust/assets/favicon-32x32.png
 create mode 100644 Documentation/rust/assets/rust-logo.png
 create mode 100644 Documentation/rust/coding.rst
 create mode 100644 Documentation/rust/docs.rst
 create mode 100644 Documentation/rust/index.rst
 create mode 100644 Documentation/rust/quick-start.rst

diff --git a/Documentation/doc-guide/kernel-doc.rst b/Documentation/doc-guide/kernel-doc.rst
index 79aaa55d6bc..724e2ffddff 100644
--- a/Documentation/doc-guide/kernel-doc.rst
+++ b/Documentation/doc-guide/kernel-doc.rst
@@ -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
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 54ce34fd6fb..1b13c2445e8 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -82,6 +82,7 @@ merged much easier.
    maintainer/index
    fault-injection/index
    livepatch/index
+   rust/index
 
 
 Kernel API documentation
diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst
index 2d1fc03d346..468a0d216c2 100644
--- a/Documentation/kbuild/kbuild.rst
+++ b/Documentation/kbuild/kbuild.rst
@@ -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.
diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst
new file mode 100644
index 00000000000..0dd603d3781
--- /dev/null
+++ b/Documentation/rust/arch-support.rst
@@ -0,0 +1,35 @@
+.. _rust_arch_support:
+
+Arch Support
+============
+
+Currently, the Rust compiler (``rustc``) uses LLVM for code generation,
+which limits the supported architectures we can target. In addition, support
+for building the kernel with LLVM/Clang varies (see :ref:`kbuild_llvm`),
+which ``bindgen`` relies on through ``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
diff --git a/Documentation/rust/assets/favicon-16x16.png b/Documentation/rust/assets/favicon-16x16.png
new file mode 100644
index 0000000000000000000000000000000000000000..d93115e8f47a939635b73ad3b3226837f83f7584
GIT binary patch
literal 798
zcmV+(1L6FMP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0RI60
z0RN!9r;`8x0@F!EK~y-6ZIMf8lxGx%pYwg+WHOhSacUA1ouC<$$uN<cj8>60Bw|2Q
zLBXm~u^5_#D=(`S=^_iY%Mx4&QgPv>=t9NnMoV2tLKM_ms)9Af%fw5(#7W1=T>klg
z7yT{L`Yg|R59hq^5&lmV5CyuFQk4L<ZKr{YzzFc-BQyWf4h#T~L1jdAp|Ubm@cI0i
ze`*Z4nvb#$xC~@P<Z37s&iecn&b)a|P9P900Dk~kSF`T@kp5uvZlDd=6Ao7&{jz)6
z>O^dYzb*M0snm08V&e67;5T5iYw;fNPy^F}ZNPfK0%jMB`BiI{q-%F<$tb^i%%!2%
z=H<jxHE;sB4fFvS;EDobzzVl94m6ZXcFfXsX7W`fb+up6)VzT5a$g6q4@d#O1KmJO
z1K$8i;8)-R5Q#>kHQ)9hU`E4w8WwDzSQ5^j{RP{$p90T-9FPFg3J3zVz#ZUcfX>bi
z7A;yxeM1~$49R3G@pv=Fc*1TDf4T3TrT_sPU=(;8iPWo&8+$OuAOc!zT3TA@?cGW+
z7>p@pRs+p|0vrRR0UOu~e4a?mpOs7|DU~ch5D~QY(Ae0Bhyc<DgxtU<jqAG)_$pc_
zEN=0lly(n$PmxmY2_ixuP!`GjUBrP$zy%Fty&kGJEjLU0d&_8@Gsc-qX`-<t!C(Lp
zMK+ycZ1{WbjigxH;p5i*JW~bdFmPG}xw$iO26lQoTbs?a=|PL@*KaT>t;FLAM1-5y
z2Kgj+hMr}b_BJnN;yk!=JO5*`#Ge}A_;>#7>}u)p7^<{}rih2JH?=%?W^?ZRc@FOX
zfv!*AP*de$e7x{#Zj~JBuFoDhc9oI<oZN-4W>(osf4OvsN0v@aIZeBNvb@80Jz^D$
z%nUi!p0EA+aD^Hjx|7=*m|r;E-;d3Ik^-QoorqB;acbCFn$6(@P>M`f!VHEg^yrD9
c{K$v;cZ2KTr4Y@#wEzGB07*qoM6N<$f+87m)&Kwi

literal 0
HcmV?d00001

diff --git a/Documentation/rust/assets/favicon-32x32.png b/Documentation/rust/assets/favicon-32x32.png
new file mode 100644
index 0000000000000000000000000000000000000000..655ccbcfc8cddde1e9c7d826a3f44c1e056b1dc8
GIT binary patch
literal 2076
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
GLSTYjg4{d+

literal 0
HcmV?d00001

diff --git a/Documentation/rust/assets/rust-logo.png b/Documentation/rust/assets/rust-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..081ae80c193ba259ffc5c506ccefc4cedd915c4b
GIT binary patch
literal 53976
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
WKU7`}H-hE>0000<MNUMnLSTZyHLE88

literal 0
HcmV?d00001

diff --git a/Documentation/rust/coding.rst b/Documentation/rust/coding.rst
new file mode 100644
index 00000000000..5cbe132f461
--- /dev/null
+++ b/Documentation/rust/coding.rst
@@ -0,0 +1,92 @@
+.. _rust_coding:
+
+Coding
+======
+
+This document describes how to write Rust code in the kernel.
+
+
+Coding style
+------------
+
+The code is automatically formatted using the ``rustfmt`` tool. This is very
+good news!
+
+- If you contribute from time to time to the kernel, you do not need to learn
+  and remember one more style guide. You will also need less patch roundtrips
+  to land a change.
+
+- If you are a reviewer or a maintainer, you will not need to spend time on
+  pointing out style issues anymore.
+
+.. note:: Conventions on comments and documentation are not checked by
+  ``rustfmt``. Thus we still need to take care of those: please see
+  :ref:`Documentation/rust/docs.rst <rust_docs>`.
+
+We use the tool's default settings. This means we are following the idiomatic
+Rust style. For instance, we use 4 spaces for indentation rather than tabs.
+
+Typically, you will want to instruct your editor/IDE to format while you type,
+when you save or at commit time. However, if for some reason you want
+to reformat the entire kernel Rust sources at some point, you may run::
+
+	make LLVM=1 rustfmt
+
+To check if everything is formatted (printing a diff otherwise), e.g. if you
+have configured a CI for a tree as a maintainer, you may run::
+
+	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.
+
+
+Extra lints
+-----------
+
+While ``rustc`` is a very helpful compiler, some extra lints and analysis are
+available via ``clippy``, a Rust linter. To enable it, pass ``CLIPPY=1`` to
+the same invocation you use for compilation, e.g.::
+
+	make LLVM=1 CLIPPY=1
+
+At the moment, we do not enforce a "clippy-free" compilation, so you can treat
+the output the same way as the extra warning levels for C, e.g. like ``W=2``.
+Still, we use the default configuration, which is relatively conservative, so
+it is a good idea to read any output it may produce from time to time and fix
+the pointed out issues. The list of enabled lists will be likely tweaked over
+time, and extra levels may end up being introduced, e.g. ``CLIPPY=2``.
+
+
+Abstractions vs. bindings
+-------------------------
+
+We don't have abstractions for all the kernel internal APIs and concepts,
+but we would like to expand coverage as time goes on. Unless there is
+a good reason not to, always use the abstractions instead of calling
+the C bindings directly.
+
+If you are writing some code that requires a call to an internal kernel API
+or concept that isn't abstracted yet, consider providing an (ideally safe)
+abstraction for everyone to use.
+
+
+Conditional compilation
+-----------------------
+
+Rust code has access to conditional compilation based on the kernel
+configuration:
+
+.. code-block:: rust
+
+	#[cfg(CONFIG_X)]      // `CONFIG_X` is enabled (`y` or `m`)
+	#[cfg(CONFIG_X="y")]  // `CONFIG_X` is enabled as a built-in (`y`)
+	#[cfg(CONFIG_X="m")]  // `CONFIG_X` is enabled as a module   (`m`)
+	#[cfg(not(CONFIG_X))] // `CONFIG_X` is disabled
+
+
+Documentation
+-------------
+
+Please see :ref:`Documentation/rust/docs.rst <rust_docs>`.
diff --git a/Documentation/rust/docs.rst b/Documentation/rust/docs.rst
new file mode 100644
index 00000000000..ab29d8b6a00
--- /dev/null
+++ b/Documentation/rust/docs.rst
@@ -0,0 +1,110 @@
+.. _rust_docs:
+
+Docs
+====
+
+Rust kernel code is not documented like C kernel code (i.e. via kernel-doc).
+Instead, we use the usual system for documenting Rust code: the ``rustdoc``
+tool, which uses Markdown (a *very* lightweight markup language).
+
+This document describes how to make the most out of the kernel documentation
+for Rust.
+
+
+Reading the docs
+----------------
+
+An advantage of using Markdown is that it attempts to make text look almost as
+you would have written it in plain text. This makes the documentation quite
+pleasant to read even in its source form.
+
+However, the generated HTML docs produced by ``rustdoc`` provide a *very* nice
+experience, including integrated instant search, clickable items (types,
+functions, constants, etc. -- including to all the standard Rust library ones
+that we use in the kernel, e.g. ``core``), categorization, links to the source
+code, etc.
+
+Like for the rest of the kernel documentation, pregenerated HTML docs for
+the libraries (crates) inside ``rust/`` that are used by the rest of the kernel
+are available at `kernel.org`_ (TODO: link when in mainline and generated
+alongside the rest of the documentation).
+
+.. _kernel.org: http://kernel.org/
+
+Otherwise, you can generate them locally. This is quite fast (same order as
+compiling the code itself) and you do not need any special tools or environment.
+This has the added advantage that they will be tailored to your particular
+kernel configuration. To generate them, simply use the ``rustdoc`` target with
+the same invocation you use for compilation, e.g.::
+
+	make LLVM=1 rustdoc
+
+
+Writing the docs
+----------------
+
+If you already know Markdown, learning how to write Rust documentation will be
+a breeze. If not, understanding the basics is a matter of minutes reading other
+code. There are also many guides available out there, a particularly nice one
+is at `GitHub`_.
+
+.. _GitHub: https://guides.github.com/features/mastering-markdown/#syntax
+
+This is how a well-documented Rust function may look like (derived from the Rust
+standard library)::
+
+	/// 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 common conventions
+(that we also follow 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 the preconditions needed for a call to be
+  safe 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, you should use a fallible approach, 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...) will be automatically linked
+  (``rustdoc`` will find out the URL for you).
+
+* Following the Rust standard library conventions, 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 also 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
diff --git a/Documentation/rust/index.rst b/Documentation/rust/index.rst
new file mode 100644
index 00000000000..257cf2b200b
--- /dev/null
+++ b/Documentation/rust/index.rst
@@ -0,0 +1,20 @@
+Rust
+====
+
+Documentation related to Rust within the kernel. If you are starting out,
+read the :ref:`Documentation/rust/quick-start.rst <rust_quick_start>` guide.
+
+.. toctree::
+    :maxdepth: 1
+
+    quick-start
+    coding
+    docs
+    arch-support
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst
new file mode 100644
index 00000000000..3f5df2888e0
--- /dev/null
+++ b/Documentation/rust/quick-start.rst
@@ -0,0 +1,222 @@
+.. _rust_quick_start:
+
+Quick Start
+===========
+
+This document describes how to get started with kernel development in Rust.
+If you have worked previously with Rust, this will only take a moment.
+
+Please note that, at the moment, a very restricted subset of architectures
+is supported, see :doc:`/rust/arch-support`.
+
+
+Requirements: Building
+----------------------
+
+This section explains how to fetch the tools needed for building.
+
+Some of these requirements might be available from your Linux distribution
+under names like ``rustc``, ``rust-src``, ``rust-bindgen``, etc. However,
+at the time of writing, they are likely to not be recent enough.
+
+
+rustc
+*****
+
+A particular version (`1.54.0-beta.1`) of the Rust compiler is required.
+Newer versions may or may not work because, for the moment, we depend on
+some unstable Rust features.
+
+If you are using ``rustup``, run::
+
+    rustup default beta-2021-06-23
+
+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 you are using ``rustup``, run::
+
+    rustup component add rust-src
+
+Otherwise, if you used a standalone installer, you can clone the Rust
+repository into the installation folder of your nightly toolchain::
+
+    git clone --recurse-submodules https://github.com/rust-lang/rust $(rustc --print sysroot)/lib/rustlib/src/rust
+
+
+libclang
+********
+
+``libclang`` (part of LLVM) is used by ``bindgen`` to understand the C code
+in the kernel, which means you will need an LLVM installed; like when
+you compile the kernel with ``CC=clang`` or ``LLVM=1``.
+
+Your Linux distribution is likely to have a suitable one available, so it is
+best if you check that first.
+
+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 Documentation/kbuild/llvm.rst for more information and 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. The version we currently support is ``0.56.0``.
+
+Install it via (this will build the tool from source)::
+
+    cargo install --locked --version 0.56.0 bindgen
+
+
+Requirements: Developing
+------------------------
+
+This section explains how to fetch the tools needed for developing. That is,
+if you only want to build the kernel, you do not need them.
+
+
+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.rst <rust_coding>`).
+
+If you are using ``rustup``, its ``default`` profile already installs the tool,
+so you should be good to go. If you are using another profile, you can install
+the component manually::
+
+    rustup component add rustfmt
+
+The standalone installers also come with ``rustfmt``.
+
+
+clippy
+******
+
+``clippy`` is a Rust linter. Installing it allows you to get extra warnings
+for Rust code passing ``CLIPPY=1`` to ``make`` (for details, please see
+:ref:`Documentation/rust/coding.rst <rust_coding>`).
+
+If you are using ``rustup``, its ``default`` profile already installs the tool,
+so you should be good to go. If you are using another profile, you can install
+the component 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 (``rusttest`` target) since we use it to build a custom standard
+library that contains the facilities provided by our custom ``alloc``.
+
+If you are using ``rustup``, all the profiles already install the tool,
+so you should be good to go. The standalone installers also include ``cargo``.
+
+
+rustdoc
+*******
+
+``rustdoc`` is the documentation tool for Rust. It generates pretty HTML
+documentation for Rust code (for details, please see
+:ref:`Documentation/rust/docs.rst <rust_docs>`.
+
+``rustdoc`` is also able to test the examples provided in documented Rust code
+(called doctests or documentation tests). We use this feature, thus ``rustdoc``
+is required to run the tests (``rusttest`` target).
+
+If you are using ``rustup``, all the profiles already install the tool,
+so you should be good to go. The standalone installers also include ``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`` will need to be
+`configured <https://rust-analyzer.github.io/manual.html#non-cargo-based-projects>`_
+to work with the kernel by adding a ``rust-project.json`` file in the root folder.
+A ``rust-project.json`` can be generated by building the Make target ``rust-analyzer``,
+which will create a ``rust-project.json`` in the root of the output directory.
+
+
+Configuration
+-------------
+
+``Rust support`` (``CONFIG_RUST``) needs to be enabled in the ``General setup``
+menu. The option is only shown if the build system can locate ``rustc``.
+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
+-------
+
+If you want 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 you use GDB/Binutils and Rust symbols aren't getting demangled, the reason
+is your toolchain doesn't support Rust's new v0 mangling scheme yet. There are
+a few ways out:
+
+  - If you don't mind building your own tools, we provide the following fork
+    with the support cherry-picked from GCC:
+
+        https://github.com/Rust-for-Linux/binutils-gdb/releases/tag/gdb-10.1-release-rust
+        https://github.com/Rust-for-Linux/binutils-gdb/releases/tag/binutils-2_35_1-rust
+
+  - If you only need GDB and can enable ``CONFIG_DEBUG_INFO``, do so:
+    some versions of GDB (e.g. vanilla GDB 10.1) are able to use
+    the pre-demangled names embedded in the debug info.
+
+  - If you don't need loadable module support, you may compile without
+    the ``-Zsymbol-mangling-version=v0`` flag. However, we don't maintain
+    support for that, so avoid it unless you are in a hurry.
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 14/17] samples: add Rust examples
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (10 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 13/17] docs: add Rust documentation ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-04 20:27 ` [PATCH 15/17] scripts: add `generate_rust_analyzer.py` ojeda
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 samples/Kconfig                        |   2 +
 samples/Makefile                       |   1 +
 samples/rust/Kconfig                   | 113 +++++++++++++
 samples/rust/Makefile                  |  12 ++
 samples/rust/rust_chrdev.rs            |  51 ++++++
 samples/rust/rust_minimal.rs           |  38 +++++
 samples/rust/rust_miscdev.rs           | 150 +++++++++++++++++
 samples/rust/rust_module_parameters.rs |  72 +++++++++
 samples/rust/rust_print.rs             |  57 +++++++
 samples/rust/rust_random.rs            |  61 +++++++
 samples/rust/rust_semaphore.rs         | 177 +++++++++++++++++++++
 samples/rust/rust_semaphore_c.c        | 212 +++++++++++++++++++++++++
 samples/rust/rust_stack_probing.rs     |  40 +++++
 samples/rust/rust_sync.rs              |  81 ++++++++++
 14 files changed, 1067 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_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

diff --git a/samples/Kconfig b/samples/Kconfig
index b5a1a7aa7e2..eaa06c05d37 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -223,4 +223,6 @@ config SAMPLE_WATCH_QUEUE
 	  Build example userspace program to use the new mount_notify(),
 	  sb_notify() syscalls and the KEYCTL_WATCH_KEY keyctl() function.
 
+source "samples/rust/Kconfig"
+
 endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 087e0988ccc..291663e56a3 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SAMPLE_INTEL_MEI)		+= mei/
 subdir-$(CONFIG_SAMPLE_WATCHDOG)	+= watchdog
 subdir-$(CONFIG_SAMPLE_WATCH_QUEUE)	+= watch_queue
 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST)	+= kmemleak/
+obj-$(CONFIG_SAMPLES_RUST)		+= rust/
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
new file mode 100644
index 00000000000..183a3c4dc80
--- /dev/null
+++ b/samples/rust/Kconfig
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menuconfig SAMPLES_RUST
+	bool "Rust samples"
+	depends on RUST
+	help
+	  You can build sample Rust kernel code here.
+
+	  If unsure, say N.
+
+if SAMPLES_RUST
+
+config SAMPLE_RUST_MINIMAL
+	tristate "Minimal"
+	help
+	  This option builds the Rust minimal module sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_minimal.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_PRINT
+	tristate "Printing macros"
+	help
+	  This option builds the Rust printing macros sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_print.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_MODULE_PARAMETERS
+	tristate "Module parameters"
+	help
+	  This option builds the Rust module parameters sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_module_parameters.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_SYNC
+	tristate "Synchronisation primitives"
+	help
+	  This option builds the Rust synchronisation primitives sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_sync.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_CHRDEV
+	tristate "Character device"
+	help
+	  This option builds the Rust character device sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_chrdev.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_MISCDEV
+	tristate "Miscellaneous device"
+	help
+	  This option builds the Rust miscellaneous device sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_miscdev.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_STACK_PROBING
+	tristate "Stack probing"
+	help
+	  This option builds the Rust stack probing sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_stack_probing.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_SEMAPHORE
+	tristate "Semaphore"
+	help
+	  This option builds the Rust semaphore sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_semaphore.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_SEMAPHORE_C
+	tristate "Semaphore (in C, for comparison)"
+	help
+	  This option builds the Rust semaphore sample (in C, for comparison).
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_semaphore_c.
+
+	  If unsure, say N.
+
+config SAMPLE_RUST_RANDOM
+	tristate "Random"
+	help
+	  This option builds the Rust random sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_random.
+
+	  If unsure, say N.
+
+endif # SAMPLES_RUST
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
new file mode 100644
index 00000000000..48bc871ea1f
--- /dev/null
+++ b/samples/rust/Makefile
@@ -0,0 +1,12 @@
+# 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
diff --git a/samples/rust/rust_chrdev.rs b/samples/rust/rust_chrdev.rs
new file mode 100644
index 00000000000..ccdfb2da785
--- /dev/null
+++ b/samples/rust/rust_chrdev.rs
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust character device sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use kernel::prelude::*;
+use kernel::{c_str, chrdev, file_operations::FileOperations};
+
+module! {
+    type: RustChrdev,
+    name: b"rust_chrdev",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust character device sample",
+    license: b"GPL v2",
+}
+
+#[derive(Default)]
+struct RustFile;
+
+impl FileOperations for RustFile {
+    kernel::declare_file_operations!();
+}
+
+struct RustChrdev {
+    _dev: Pin<Box<chrdev::Registration<2>>>,
+}
+
+impl KernelModule for RustChrdev {
+    fn init() -> Result<Self> {
+        pr_info!("Rust character device sample (init)\n");
+
+        let mut chrdev_reg =
+            chrdev::Registration::new_pinned(c_str!("rust_chrdev"), 0, &THIS_MODULE)?;
+
+        // Register the same kind of device twice, we're just demonstrating
+        // that you can use multiple minors. There are two minors in this case
+        // because its type is `chrdev::Registration<2>`
+        chrdev_reg.as_mut().register::<RustFile>()?;
+        chrdev_reg.as_mut().register::<RustFile>()?;
+
+        Ok(RustChrdev { _dev: chrdev_reg })
+    }
+}
+
+impl Drop for RustChrdev {
+    fn drop(&mut self) {
+        pr_info!("Rust character device sample (exit)\n");
+    }
+}
diff --git a/samples/rust/rust_minimal.rs b/samples/rust/rust_minimal.rs
new file mode 100644
index 00000000000..49cfd8cf3aa
--- /dev/null
+++ b/samples/rust/rust_minimal.rs
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust minimal sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+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() -> 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");
+    }
+}
diff --git a/samples/rust/rust_miscdev.rs b/samples/rust/rust_miscdev.rs
new file mode 100644
index 00000000000..df8681af9cc
--- /dev/null
+++ b/samples/rust/rust_miscdev.rs
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust miscellaneous device sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use kernel::prelude::*;
+use kernel::{
+    c_str,
+    file::File,
+    file_operations::{FileOpener, FileOperations},
+    io_buffer::{IoBufferReader, IoBufferWriter},
+    miscdev,
+    sync::{CondVar, Mutex, Ref},
+};
+
+module! {
+    type: RustMiscdev,
+    name: b"rust_miscdev",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust miscellaneous device sample",
+    license: b"GPL v2",
+}
+
+const MAX_TOKENS: usize = 3;
+
+struct SharedStateInner {
+    token_count: usize,
+}
+
+struct SharedState {
+    state_changed: CondVar,
+    inner: Mutex<SharedStateInner>,
+}
+
+impl SharedState {
+    fn try_new() -> Result<Pin<Ref<Self>>> {
+        Ok(Ref::pinned(Ref::try_new_and_init(
+            Self {
+                // SAFETY: `condvar_init!` is called below.
+                state_changed: unsafe { CondVar::new() },
+                // SAFETY: `mutex_init!` is called below.
+                inner: unsafe { Mutex::new(SharedStateInner { token_count: 0 }) },
+            },
+            |mut state| {
+                // SAFETY: `state_changed` is pinned when `state` is.
+                let pinned = unsafe { state.as_mut().map_unchecked_mut(|s| &mut s.state_changed) };
+                kernel::condvar_init!(pinned, "SharedState::state_changed");
+                // SAFETY: `inner` is pinned when `state` is.
+                let pinned = unsafe { state.as_mut().map_unchecked_mut(|s| &mut s.inner) };
+                kernel::mutex_init!(pinned, "SharedState::inner");
+            },
+        )?))
+    }
+}
+
+struct Token;
+
+impl FileOpener<Pin<Ref<SharedState>>> for Token {
+    fn open(shared: &Pin<Ref<SharedState>>) -> Result<Self::Wrapper> {
+        Ok(shared.clone())
+    }
+}
+
+impl FileOperations for Token {
+    type Wrapper = Pin<Ref<SharedState>>;
+
+    kernel::declare_file_operations!(read, write);
+
+    fn read<T: IoBufferWriter>(
+        shared: &Ref<SharedState>,
+        _: &File,
+        data: &mut T,
+        offset: u64,
+    ) -> Result<usize> {
+        // Succeed if the caller doesn't provide a buffer or if not at the start.
+        if data.is_empty() || offset != 0 {
+            return Ok(0);
+        }
+
+        {
+            let mut inner = shared.inner.lock();
+
+            // Wait until we are allowed to decrement the token count or a signal arrives.
+            while inner.token_count == 0 {
+                if shared.state_changed.wait(&mut inner) {
+                    return Err(Error::EINTR);
+                }
+            }
+
+            // Consume a token.
+            inner.token_count -= 1;
+        }
+
+        // Notify a possible writer waiting.
+        shared.state_changed.notify_all();
+
+        // Write a one-byte 1 to the reader.
+        data.write_slice(&[1u8; 1])?;
+        Ok(1)
+    }
+
+    fn write<T: IoBufferReader>(
+        shared: &Ref<SharedState>,
+        _: &File,
+        data: &mut T,
+        _offset: u64,
+    ) -> Result<usize> {
+        {
+            let mut inner = shared.inner.lock();
+
+            // Wait until we are allowed to increment the token count or a signal arrives.
+            while inner.token_count == MAX_TOKENS {
+                if shared.state_changed.wait(&mut inner) {
+                    return Err(Error::EINTR);
+                }
+            }
+
+            // Increment the number of token so that a reader can be released.
+            inner.token_count += 1;
+        }
+
+        // Notify a possible reader waiting.
+        shared.state_changed.notify_all();
+        Ok(data.len())
+    }
+}
+
+struct RustMiscdev {
+    _dev: Pin<Box<miscdev::Registration<Pin<Ref<SharedState>>>>>,
+}
+
+impl KernelModule for RustMiscdev {
+    fn init() -> Result<Self> {
+        pr_info!("Rust miscellaneous device sample (init)\n");
+
+        let state = SharedState::try_new()?;
+
+        Ok(RustMiscdev {
+            _dev: miscdev::Registration::new_pinned::<Token>(c_str!("rust_miscdev"), None, state)?,
+        })
+    }
+}
+
+impl Drop for RustMiscdev {
+    fn drop(&mut self) {
+        pr_info!("Rust miscellaneous device sample (exit)\n");
+    }
+}
diff --git a/samples/rust/rust_module_parameters.rs b/samples/rust/rust_module_parameters.rs
new file mode 100644
index 00000000000..57e59e80502
--- /dev/null
+++ b/samples/rust/rust_module_parameters.rs
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust module parameters sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use kernel::prelude::*;
+
+module! {
+    type: RustModuleParameters,
+    name: b"rust_module_parameters",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust module parameters sample",
+    license: b"GPL v2",
+    params: {
+        my_bool: bool {
+            default: true,
+            permissions: 0,
+            description: b"Example of bool",
+        },
+        my_i32: i32 {
+            default: 42,
+            permissions: 0o644,
+            description: b"Example of i32",
+        },
+        my_str: str {
+            default: b"default str val",
+            permissions: 0o644,
+            description: b"Example of a string param",
+        },
+        my_usize: usize {
+            default: 42,
+            permissions: 0o644,
+            description: b"Example of usize",
+        },
+        my_array: ArrayParam<i32, 3> {
+            default: [0, 1],
+            permissions: 0,
+            description: b"Example of array",
+        },
+    },
+}
+
+struct RustModuleParameters;
+
+impl KernelModule for RustModuleParameters {
+    fn init() -> Result<Self> {
+        pr_info!("Rust module parameters sample (init)\n");
+
+        {
+            let lock = THIS_MODULE.kernel_param_lock();
+            pr_info!("Parameters:\n");
+            pr_info!("  my_bool:    {}\n", my_bool.read());
+            pr_info!("  my_i32:     {}\n", my_i32.read(&lock));
+            pr_info!(
+                "  my_str:     {}\n",
+                core::str::from_utf8(my_str.read(&lock))?
+            );
+            pr_info!("  my_usize:   {}\n", my_usize.read(&lock));
+            pr_info!("  my_array:   {:?}\n", my_array.read());
+        }
+
+        Ok(RustModuleParameters)
+    }
+}
+
+impl Drop for RustModuleParameters {
+    fn drop(&mut self) {
+        pr_info!("Rust module parameters sample (exit)\n");
+    }
+}
diff --git a/samples/rust/rust_print.rs b/samples/rust/rust_print.rs
new file mode 100644
index 00000000000..c43338fca50
--- /dev/null
+++ b/samples/rust/rust_print.rs
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust printing macros sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use kernel::pr_cont;
+use kernel::prelude::*;
+
+module! {
+    type: RustPrint,
+    name: b"rust_print",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust printing macros sample",
+    license: b"GPL v2",
+}
+
+struct RustPrint;
+
+impl KernelModule for RustPrint {
+    fn init() -> Result<Self> {
+        pr_info!("Rust printing macros sample (init)\n");
+
+        pr_emerg!("Emergency message (level 0) without args\n");
+        pr_alert!("Alert message (level 1) without args\n");
+        pr_crit!("Critical message (level 2) without args\n");
+        pr_err!("Error message (level 3) without args\n");
+        pr_warn!("Warning message (level 4) without args\n");
+        pr_notice!("Notice message (level 5) without args\n");
+        pr_info!("Info message (level 6) without args\n");
+
+        pr_info!("A line that");
+        pr_cont!(" is continued");
+        pr_cont!(" without args\n");
+
+        pr_emerg!("{} message (level {}) with args\n", "Emergency", 0);
+        pr_alert!("{} message (level {}) with args\n", "Alert", 1);
+        pr_crit!("{} message (level {}) with args\n", "Critical", 2);
+        pr_err!("{} message (level {}) with args\n", "Error", 3);
+        pr_warn!("{} message (level {}) with args\n", "Warning", 4);
+        pr_notice!("{} message (level {}) with args\n", "Notice", 5);
+        pr_info!("{} message (level {}) with args\n", "Info", 6);
+
+        pr_info!("A {} that", "line");
+        pr_cont!(" is {}", "continued");
+        pr_cont!(" with {}\n", "args");
+
+        Ok(RustPrint)
+    }
+}
+
+impl Drop for RustPrint {
+    fn drop(&mut self) {
+        pr_info!("Rust printing macros sample (exit)\n");
+    }
+}
diff --git a/samples/rust/rust_random.rs b/samples/rust/rust_random.rs
new file mode 100644
index 00000000000..135325b6ca0
--- /dev/null
+++ b/samples/rust/rust_random.rs
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust random device
+//!
+//! Adapted from Alex Gaynor's original available at
+//! <https://github.com/alex/just-use/blob/master/src/lib.rs>.
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use kernel::{
+    file::File,
+    file_operations::FileOperations,
+    io_buffer::{IoBufferReader, IoBufferWriter},
+    prelude::*,
+};
+
+#[derive(Default)]
+struct RandomFile;
+
+impl FileOperations for RandomFile {
+    kernel::declare_file_operations!(read, write, read_iter, write_iter);
+
+    fn read<T: IoBufferWriter>(_this: &Self, file: &File, buf: &mut T, _: u64) -> Result<usize> {
+        let total_len = buf.len();
+        let mut chunkbuf = [0; 256];
+
+        while !buf.is_empty() {
+            let len = chunkbuf.len().min(buf.len());
+            let chunk = &mut chunkbuf[0..len];
+
+            if file.is_blocking() {
+                kernel::random::getrandom(chunk)?;
+            } else {
+                kernel::random::getrandom_nonblock(chunk)?;
+            }
+            buf.write_slice(chunk)?;
+        }
+        Ok(total_len)
+    }
+
+    fn write<T: IoBufferReader>(_this: &Self, _file: &File, buf: &mut T, _: u64) -> Result<usize> {
+        let total_len = buf.len();
+        let mut chunkbuf = [0; 256];
+        while !buf.is_empty() {
+            let len = chunkbuf.len().min(buf.len());
+            let chunk = &mut chunkbuf[0..len];
+            buf.read_slice(chunk)?;
+            kernel::random::add_randomness(chunk);
+        }
+        Ok(total_len)
+    }
+}
+
+module_misc_device! {
+    type: RandomFile,
+    name: b"rust_random",
+    author: b"Rust for Linux Contributors",
+    description: b"Just use /dev/urandom: Now with early-boot safety",
+    license: b"GPL v2",
+}
diff --git a/samples/rust/rust_semaphore.rs b/samples/rust/rust_semaphore.rs
new file mode 100644
index 00000000000..1408d5095b8
--- /dev/null
+++ b/samples/rust/rust_semaphore.rs
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust semaphore sample
+//!
+//! A counting semaphore that can be used by userspace.
+//!
+//! The count is incremented by writes to the device. A write of `n` bytes results in an increment
+//! of `n`. It is decremented by reads; each read results in the count being decremented by 1. If
+//! the count is already zero, a read will block until another write increments it.
+//!
+//! This can be used in user space from the shell for example  as follows (assuming a node called
+//! `semaphore`): `cat semaphore` decrements the count by 1 (waiting for it to become non-zero
+//! before decrementing); `echo -n 123 > semaphore` increments the semaphore by 3, potentially
+//! unblocking up to 3 blocked readers.
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use core::sync::atomic::{AtomicU64, Ordering};
+use kernel::{
+    c_str, condvar_init, declare_file_operations,
+    file::File,
+    file_operations::{FileOpener, FileOperations, IoctlCommand, IoctlHandler},
+    io_buffer::{IoBufferReader, IoBufferWriter},
+    miscdev::Registration,
+    mutex_init,
+    prelude::*,
+    sync::{CondVar, Mutex, Ref},
+    user_ptr::{UserSlicePtrReader, UserSlicePtrWriter},
+};
+
+module! {
+    type: RustSemaphore,
+    name: b"rust_semaphore",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust semaphore sample",
+    license: b"GPL v2",
+}
+
+struct SemaphoreInner {
+    count: usize,
+    max_seen: usize,
+}
+
+struct Semaphore {
+    changed: CondVar,
+    inner: Mutex<SemaphoreInner>,
+}
+
+struct FileState {
+    read_count: AtomicU64,
+    shared: Ref<Semaphore>,
+}
+
+impl FileState {
+    fn consume(&self) -> Result {
+        let mut inner = self.shared.inner.lock();
+        while inner.count == 0 {
+            if self.shared.changed.wait(&mut inner) {
+                return Err(Error::EINTR);
+            }
+        }
+        inner.count -= 1;
+        Ok(())
+    }
+}
+
+impl FileOpener<Ref<Semaphore>> for FileState {
+    fn open(shared: &Ref<Semaphore>) -> Result<Box<Self>> {
+        Ok(Box::try_new(Self {
+            read_count: AtomicU64::new(0),
+            shared: shared.clone(),
+        })?)
+    }
+}
+
+impl FileOperations for FileState {
+    declare_file_operations!(read, write, ioctl);
+
+    fn read<T: IoBufferWriter>(this: &Self, _: &File, data: &mut T, offset: u64) -> Result<usize> {
+        if data.is_empty() || offset > 0 {
+            return Ok(0);
+        }
+        this.consume()?;
+        data.write_slice(&[0u8; 1])?;
+        this.read_count.fetch_add(1, Ordering::Relaxed);
+        Ok(1)
+    }
+
+    fn write<T: IoBufferReader>(this: &Self, _: &File, data: &mut T, _offs: u64) -> Result<usize> {
+        {
+            let mut inner = this.shared.inner.lock();
+            inner.count = inner.count.saturating_add(data.len());
+            if inner.count > inner.max_seen {
+                inner.max_seen = inner.count;
+            }
+        }
+
+        this.shared.changed.notify_all();
+        Ok(data.len())
+    }
+
+    fn ioctl(this: &Self, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
+        cmd.dispatch::<Self>(this, file)
+    }
+}
+
+struct RustSemaphore {
+    _dev: Pin<Box<Registration<Ref<Semaphore>>>>,
+}
+
+impl KernelModule for RustSemaphore {
+    fn init() -> Result<Self> {
+        pr_info!("Rust semaphore sample (init)\n");
+
+        let sema = Ref::try_new_and_init(
+            Semaphore {
+                // SAFETY: `condvar_init!` is called below.
+                changed: unsafe { CondVar::new() },
+
+                // SAFETY: `mutex_init!` is called below.
+                inner: unsafe {
+                    Mutex::new(SemaphoreInner {
+                        count: 0,
+                        max_seen: 0,
+                    })
+                },
+            },
+            |mut sema| {
+                // SAFETY: `changed` is pinned when `sema` is.
+                let pinned = unsafe { sema.as_mut().map_unchecked_mut(|s| &mut s.changed) };
+                condvar_init!(pinned, "Semaphore::changed");
+
+                // SAFETY: `inner` is pinned when `sema` is.
+                let pinned = unsafe { sema.as_mut().map_unchecked_mut(|s| &mut s.inner) };
+                mutex_init!(pinned, "Semaphore::inner");
+            },
+        )?;
+
+        Ok(Self {
+            _dev: Registration::new_pinned::<FileState>(c_str!("rust_semaphore"), None, sema)?,
+        })
+    }
+}
+
+impl Drop for RustSemaphore {
+    fn drop(&mut self) {
+        pr_info!("Rust semaphore sample (exit)\n");
+    }
+}
+
+const IOCTL_GET_READ_COUNT: u32 = 0x80086301;
+const IOCTL_SET_READ_COUNT: u32 = 0x40086301;
+
+impl IoctlHandler for FileState {
+    type Target = Self;
+
+    fn read(this: &Self, _: &File, cmd: u32, writer: &mut UserSlicePtrWriter) -> Result<i32> {
+        match cmd {
+            IOCTL_GET_READ_COUNT => {
+                writer.write(&this.read_count.load(Ordering::Relaxed))?;
+                Ok(0)
+            }
+            _ => Err(Error::EINVAL),
+        }
+    }
+
+    fn write(this: &Self, _: &File, cmd: u32, reader: &mut UserSlicePtrReader) -> Result<i32> {
+        match cmd {
+            IOCTL_SET_READ_COUNT => {
+                this.read_count.store(reader.read()?, Ordering::Relaxed);
+                Ok(0)
+            }
+            _ => Err(Error::EINVAL),
+        }
+    }
+}
diff --git a/samples/rust/rust_semaphore_c.c b/samples/rust/rust_semaphore_c.c
new file mode 100644
index 00000000000..cdc121d4030
--- /dev/null
+++ b/samples/rust/rust_semaphore_c.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rust semaphore sample (in C, for comparison)
+ *
+ * This is a C implementation of `rust_semaphore.rs`. Refer to the description
+ * in that file for details on the device.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/refcount.h>
+#include <linux/wait.h>
+
+#define IOCTL_GET_READ_COUNT _IOR('c', 1, u64)
+#define IOCTL_SET_READ_COUNT _IOW('c', 1, u64)
+
+struct semaphore_state {
+	struct kref ref;
+	struct miscdevice miscdev;
+	wait_queue_head_t changed;
+	struct mutex mutex;
+	size_t count;
+	size_t max_seen;
+};
+
+struct file_state {
+	atomic64_t read_count;
+	struct semaphore_state *shared;
+};
+
+static int semaphore_consume(struct semaphore_state *state)
+{
+	DEFINE_WAIT(wait);
+
+	mutex_lock(&state->mutex);
+	while (state->count == 0) {
+		prepare_to_wait(&state->changed, &wait, TASK_INTERRUPTIBLE);
+		mutex_unlock(&state->mutex);
+		schedule();
+		finish_wait(&state->changed, &wait);
+		if (signal_pending(current))
+			return -EINTR;
+		mutex_lock(&state->mutex);
+	}
+
+	state->count--;
+	mutex_unlock(&state->mutex);
+
+	return 0;
+}
+
+static int semaphore_open(struct inode *nodp, struct file *filp)
+{
+	struct semaphore_state *shared =
+		container_of(filp->private_data, struct semaphore_state, miscdev);
+	struct file_state *state;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	kref_get(&shared->ref);
+	state->shared = shared;
+	atomic64_set(&state->read_count, 0);
+
+	filp->private_data = state;
+
+	return 0;
+}
+
+static ssize_t semaphore_write(struct file *filp, const char __user *buffer, size_t count,
+			       loff_t *ppos)
+{
+	struct file_state *state = filp->private_data;
+	struct semaphore_state *shared = state->shared;
+
+	mutex_lock(&shared->mutex);
+
+	shared->count += count;
+	if (shared->count < count)
+		shared->count = SIZE_MAX;
+
+	if (shared->count > shared->max_seen)
+		shared->max_seen = shared->count;
+
+	mutex_unlock(&shared->mutex);
+
+	wake_up_all(&shared->changed);
+
+	return count;
+}
+
+static ssize_t semaphore_read(struct file *filp, char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+	struct file_state *state = filp->private_data;
+	char c = 0;
+	int ret;
+
+	if (count == 0 || *ppos > 0)
+		return 0;
+
+	ret = semaphore_consume(state->shared);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(buffer, &c, sizeof(c)))
+		return -EFAULT;
+
+	atomic64_add(1, &state->read_count);
+	*ppos += 1;
+	return 1;
+}
+
+static long semaphore_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct file_state *state = filp->private_data;
+	void __user *buffer = (void __user *)arg;
+	u64 value;
+
+	switch (cmd) {
+	case IOCTL_GET_READ_COUNT:
+		value = atomic64_read(&state->read_count);
+		if (copy_to_user(buffer, &value, sizeof(value)))
+			return -EFAULT;
+		return 0;
+	case IOCTL_SET_READ_COUNT:
+		if (copy_from_user(&value, buffer, sizeof(value)))
+			return -EFAULT;
+		atomic64_set(&state->read_count, value);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static void semaphore_free(struct kref *kref)
+{
+	struct semaphore_state *device;
+
+	device = container_of(kref, struct semaphore_state, ref);
+	kfree(device);
+}
+
+static int semaphore_release(struct inode *nodp, struct file *filp)
+{
+	struct file_state *state = filp->private_data;
+
+	kref_put(&state->shared->ref, semaphore_free);
+	kfree(state);
+	return 0;
+}
+
+static const struct file_operations semaphore_fops = {
+	.owner = THIS_MODULE,
+	.open = semaphore_open,
+	.read = semaphore_read,
+	.write = semaphore_write,
+	.compat_ioctl = semaphore_ioctl,
+	.release = semaphore_release,
+};
+
+static struct semaphore_state *device;
+
+static int __init semaphore_init(void)
+{
+	int ret;
+	struct semaphore_state *state;
+
+	pr_info("Rust semaphore sample (in C, for comparison) (init)\n");
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	mutex_init(&state->mutex);
+	kref_init(&state->ref);
+	init_waitqueue_head(&state->changed);
+
+	state->miscdev.fops = &semaphore_fops;
+	state->miscdev.minor = MISC_DYNAMIC_MINOR;
+	state->miscdev.name = "semaphore";
+
+	ret = misc_register(&state->miscdev);
+	if (ret < 0) {
+		kfree(state);
+		return ret;
+	}
+
+	device = state;
+
+	return 0;
+}
+
+static void __exit semaphore_exit(void)
+{
+	pr_info("Rust semaphore sample (in C, for comparison) (exit)\n");
+
+	misc_deregister(&device->miscdev);
+	kref_put(&device->ref, semaphore_free);
+}
+
+module_init(semaphore_init);
+module_exit(semaphore_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Rust for Linux Contributors");
+MODULE_DESCRIPTION("Rust semaphore sample (in C, for comparison)");
diff --git a/samples/rust/rust_stack_probing.rs b/samples/rust/rust_stack_probing.rs
new file mode 100644
index 00000000000..fcb87a53ce7
--- /dev/null
+++ b/samples/rust/rust_stack_probing.rs
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust stack probing sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+#![feature(bench_black_box)]
+
+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() -> 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");
+    }
+}
diff --git a/samples/rust/rust_sync.rs b/samples/rust/rust_sync.rs
new file mode 100644
index 00000000000..40bbfec9ad2
--- /dev/null
+++ b/samples/rust/rust_sync.rs
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust synchronisation primitives sample
+
+#![no_std]
+#![feature(allocator_api, global_asm)]
+
+use kernel::prelude::*;
+use kernel::{
+    condvar_init, mutex_init, spinlock_init,
+    sync::{CondVar, Mutex, SpinLock},
+};
+
+module! {
+    type: RustSync,
+    name: b"rust_sync",
+    author: b"Rust for Linux Contributors",
+    description: b"Rust synchronisation primitives sample",
+    license: b"GPL v2",
+}
+
+struct RustSync;
+
+impl KernelModule for RustSync {
+    fn init() -> Result<Self> {
+        pr_info!("Rust synchronisation primitives sample (init)\n");
+
+        // Test mutexes.
+        {
+            // SAFETY: `init` is called below.
+            let mut data = Pin::from(Box::try_new(unsafe { Mutex::new(0) })?);
+            mutex_init!(data.as_mut(), "RustSync::init::data1");
+            *data.lock() = 10;
+            pr_info!("Value: {}\n", *data.lock());
+
+            // SAFETY: `init` is called below.
+            let mut cv = Pin::from(Box::try_new(unsafe { CondVar::new() })?);
+            condvar_init!(cv.as_mut(), "RustSync::init::cv1");
+
+            {
+                let mut guard = data.lock();
+                while *guard != 10 {
+                    let _ = cv.wait(&mut guard);
+                }
+            }
+            cv.notify_one();
+            cv.notify_all();
+            cv.free_waiters();
+        }
+
+        // Test spinlocks.
+        {
+            // SAFETY: `init` is called below.
+            let mut data = Pin::from(Box::try_new(unsafe { SpinLock::new(0) })?);
+            spinlock_init!(data.as_mut(), "RustSync::init::data2");
+            *data.lock() = 10;
+            pr_info!("Value: {}\n", *data.lock());
+
+            // SAFETY: `init` is called below.
+            let mut cv = Pin::from(Box::try_new(unsafe { CondVar::new() })?);
+            condvar_init!(cv.as_mut(), "RustSync::init::cv2");
+            {
+                let mut guard = data.lock();
+                while *guard != 10 {
+                    let _ = cv.wait(&mut guard);
+                }
+            }
+            cv.notify_one();
+            cv.notify_all();
+            cv.free_waiters();
+        }
+
+        Ok(RustSync)
+    }
+}
+
+impl Drop for RustSync {
+    fn drop(&mut self) {
+        pr_info!("Rust synchronisation primitives sample (exit)\n");
+    }
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 15/17] scripts: add `generate_rust_analyzer.py`
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (11 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 14/17] samples: add Rust examples ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-05  5:05   ` Willy Tarreau
  2021-07-04 20:27 ` [PATCH 16/17] MAINTAINERS: Rust ojeda
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Wedson Almeida Filho, Boqun Feng,
	Sumera Priyadarsini, Michael Ellerman, Sven Van Asbroeck,
	Gary Guo, Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi,
	Douglas Su, Yuki Okushi

From: Miguel Ojeda <ojeda@kernel.org>

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.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
Co-developed-by: Douglas Su <d0u9.su@outlook.com>
Signed-off-by: Douglas Su <d0u9.su@outlook.com>
Co-developed-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 scripts/generate_rust_analyzer.py | 143 ++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100755 scripts/generate_rust_analyzer.py

diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
new file mode 100755
index 00000000000..72c453e1aea
--- /dev/null
+++ b/scripts/generate_rust_analyzer.py
@@ -0,0 +1,143 @@
+#!/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, bindings_file):
+    # 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, is_workspace_member, deps, cfg):
+        crates_indexes[display_name] = len(crates)
+        crates.append({
+            "display_name": display_name,
+            "root_module": str(root_module),
+            "is_workspace_member": is_workspace_member,
+            "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps],
+            "cfg": cfg,
+            "edition": "2018",
+            "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",
+        False,
+        [],
+        [],
+    )
+
+    append_crate(
+        "compiler_builtins",
+        srctree / "rust" / "compiler_builtins.rs",
+        True,
+        [],
+        [],
+    )
+
+    append_crate(
+        "alloc",
+        srctree / "rust" / "alloc" / "lib.rs",
+        True,
+        ["core", "compiler_builtins"],
+        [],
+    )
+
+    append_crate(
+        "macros",
+        srctree / "rust" / "macros" / "lib.rs",
+        True,
+        [],
+        [],
+    )
+    crates[-1]["proc_macro_dylib_path"] = "rust/libmacros.so"
+
+    append_crate(
+        "build_error",
+        srctree / "rust" / "build_error.rs",
+        True,
+        ["core", "compiler_builtins"],
+        [],
+    )
+
+    append_crate(
+        "kernel",
+        srctree / "rust" / "kernel" / "lib.rs",
+        True,
+        ["core", "alloc", "macros", "build_error"],
+        cfg,
+    )
+    crates[-1]["env"]["RUST_BINDINGS_FILE"] = str(bindings_file.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,
+                True,
+                ["core", "alloc", "kernel"],
+                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)
+    parser.add_argument("bindings_file", 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, args.bindings_file),
+        "sysroot_src": str(args.sysroot_src),
+    }
+
+    json.dump(rust_project, sys.stdout, sort_keys=True, indent=4)
+
+if __name__ == "__main__":
+    main()
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 16/17] MAINTAINERS: Rust
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (12 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 15/17] scripts: add `generate_rust_analyzer.py` ojeda
@ 2021-07-04 20:27 ` ojeda
  2021-07-06  0:26   ` Pedro Tammela
  2021-07-04 23:11 ` [PATCH 00/17] Rust support Miguel Ojeda
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: ojeda @ 2021-07-04 20:27 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho

From: Miguel Ojeda <ojeda@kernel.org>

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

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 MAINTAINERS | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0cce91cd562..a439204d9be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15894,6 +15894,20 @@ L:	linux-rdma@vger.kernel.org
 S:	Maintained
 F:	drivers/infiniband/ulp/rtrs/
 
+RUST
+M:	Miguel Ojeda <ojeda@kernel.org>
+M:	Alex Gaynor <alex.gaynor@gmail.com>
+M:	Wedson Almeida Filho <wedsonaf@google.com>
+L:	rust-for-linux@vger.kernel.org
+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/
+K:	\b(?i:rust)\b
+
 RXRPC SOCKETS (AF_RXRPC)
 M:	David Howells <dhowells@redhat.com>
 M:	Marc Dionne <marc.dionne@auristor.com>
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 20:27 ` [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths) ojeda
@ 2021-07-04 20:52   ` Linus Torvalds
  2021-07-04 21:15     ` Miguel Ojeda
  2021-07-04 21:04   ` Matthew Wilcox
  1 sibling, 1 reply; 70+ messages in thread
From: Linus Torvalds @ 2021-07-04 20:52 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Greg Kroah-Hartman, rust-for-linux, Linux Kbuild mailing list,
	open list:DOCUMENTATION, Linux Kernel Mailing List, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 4, 2021 at 1:28 PM <ojeda@kernel.org> wrote:
>
>
> +       /* If zero, it is a "big" symbol, so a two byte length follows. */
> +       if (len == 0) {
> +               len = (data[0] << 8) | data[1];
> +               data += 2;
> +               off += len + 2;
> +       }

Side note: it might be a good idea at this point to verify that "len" is >255.

Also, why is this in big-endian order?

Let's just try to kill big-endian data, it's disgusting and should
just die already.

BE is practically dead anyway, we shouldn't add new cases. Networking
has legacy reasons from the bad old days when byte order wars were
still a thing, but those days are gone.

           Linus

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 20:27 ` [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths) ojeda
  2021-07-04 20:52   ` Linus Torvalds
@ 2021-07-04 21:04   ` Matthew Wilcox
  2021-07-04 21:17     ` Miguel Ojeda
  2021-07-04 21:20     ` Gary Guo
  1 sibling, 2 replies; 70+ messages in thread
From: Matthew Wilcox @ 2021-07-04 21:04 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho

On Sun, Jul 04, 2021 at 10:27:40PM +0200, ojeda@kernel.org wrote:
> From: Miguel Ojeda <ojeda@kernel.org>
> 
> 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 2-byte lengths to the symbol table. We call
> these "big" symbols.
> 
> In order to avoid increasing all lengths to 2 bytes (since most
> of them only require 1 byte, including many Rust ones), we use
> length zero to mark "big" symbols in the table.

What happened to my suggestion from last time of encoding symbols < 128
as 0-127 and symbols larger than that as (data[0] - 128) * 256 +
data[1]) ?

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 20:52   ` Linus Torvalds
@ 2021-07-04 21:15     ` Miguel Ojeda
  2021-07-04 21:28       ` Linus Torvalds
  0 siblings, 1 reply; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-04 21:15 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Miguel Ojeda, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, open list:DOCUMENTATION,
	Linux Kernel Mailing List, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho

On Sun, Jul 4, 2021 at 10:52 PM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> Also, why is this in big-endian order?

No particular reason. It makes sense to use LE -- I will change it.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:04   ` Matthew Wilcox
@ 2021-07-04 21:17     ` Miguel Ojeda
  2021-07-04 21:33       ` Matthew Wilcox
  2021-07-04 21:20     ` Gary Guo
  1 sibling, 1 reply; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-04 21:17 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 4, 2021 at 11:05 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> What happened to my suggestion from last time of encoding symbols < 128
> as 0-127 and symbols larger than that as (data[0] - 128) * 256 +
> data[1]) ?

Nothing, sorry, we focused on other parts (e.g. the allocation panics)
during this iteration. I can take a look for v2.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:04   ` Matthew Wilcox
  2021-07-04 21:17     ` Miguel Ojeda
@ 2021-07-04 21:20     ` Gary Guo
  2021-07-05  4:35       ` Willy Tarreau
  1 sibling, 1 reply; 70+ messages in thread
From: Gary Guo @ 2021-07-04 21:20 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	linux-kbuild, linux-doc, linux-kernel, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, 4 Jul 2021 22:04:49 +0100
Matthew Wilcox <willy@infradead.org> wrote:

> On Sun, Jul 04, 2021 at 10:27:40PM +0200, ojeda@kernel.org wrote:
> > From: Miguel Ojeda <ojeda@kernel.org>
> > 
> > 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 2-byte lengths to the symbol table. We call
> > these "big" symbols.
> > 
> > In order to avoid increasing all lengths to 2 bytes (since most
> > of them only require 1 byte, including many Rust ones), we use
> > length zero to mark "big" symbols in the table.  
> 
> What happened to my suggestion from last time of encoding symbols <
> 128 as 0-127 and symbols larger than that as (data[0] - 128) * 256 +
> data[1]) ?

Yeah, I agree ULEB128 or similar encoding scheme would be better than
using 0 as an escape byte. If ULEB128 is used and we restrict number of
bytes to 2, it will encode numbers up to 2**14 instead of 2**16 like the
current scheme, but that should be sufficient anyway.

- Gary

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:15     ` Miguel Ojeda
@ 2021-07-04 21:28       ` Linus Torvalds
  0 siblings, 0 replies; 70+ messages in thread
From: Linus Torvalds @ 2021-07-04 21:28 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Miguel Ojeda, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, open list:DOCUMENTATION,
	Linux Kernel Mailing List, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho

On Sun, Jul 4, 2021 at 2:15 PM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> No particular reason. It makes sense to use LE -- I will change it.

Matthew's suggestion is denser, which is nice.

At that point, it would be neither BE nor LE. But the "LE-like" version would be

   len = data[0];
   if (len & 128)
        len += data[1] << 7;

which ends up having a tiny bit more range (it goes to 11^H32895).

Of course, if the range is expected to be just 0-300, I guess that
matters not one whit.

                Linus

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:17     ` Miguel Ojeda
@ 2021-07-04 21:33       ` Matthew Wilcox
  2021-07-04 21:49         ` Matthew Wilcox
  2021-07-04 22:20         ` Gary Guo
  0 siblings, 2 replies; 70+ messages in thread
From: Matthew Wilcox @ 2021-07-04 21:33 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 04, 2021 at 11:17:50PM +0200, Miguel Ojeda wrote:
> On Sun, Jul 4, 2021 at 11:05 PM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > What happened to my suggestion from last time of encoding symbols < 128
> > as 0-127 and symbols larger than that as (data[0] - 128) * 256 +
> > data[1]) ?
> 
> Nothing, sorry, we focused on other parts (e.g. the allocation panics)
> during this iteration. I can take a look for v2.

Here's what I have.  Build testing now.


diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index c851ca0ed357..0d45a6e5fdc3 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -67,6 +67,14 @@ static unsigned int kallsyms_expand_symbol(unsigned int off,
 	len = *data;
 	data++;
 
+	/* lengths larger than 128 are encoded as two bytes */
+	if (len >= 128) {
+		len -= 128;
+		len *= 256;
+		len += *data;
+		data++;
+	}
+
 	/*
 	 * Update the offset to return the offset for the next symbol on
 	 * the compressed stream.
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 54ad86d13784..701566e01a1d 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -467,10 +467,16 @@ static void write_src(void)
 	output_label("kallsyms_names");
 	off = 0;
 	for (i = 0; i < table_cnt; i++) {
+		int len = table[i]->len;
 		if ((i & 0xFF) == 0)
 			markers[i >> 8] = off;
 
-		printf("\t.byte 0x%02x", table[i]->len);
+		if (len >= 128) {
+			printf("\t.byte 0x%02x\n", len / 256 + 128);
+			len %= 256;
+			off++;
+		}
+		printf("\t.byte 0x%02x", len);
 		for (k = 0; k < table[i]->len; k++)
 			printf(", 0x%02x", table[i]->sym[k]);
 		printf("\n");

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:33       ` Matthew Wilcox
@ 2021-07-04 21:49         ` Matthew Wilcox
  2021-07-04 22:07           ` Miguel Ojeda
  2021-07-04 22:20         ` Gary Guo
  1 sibling, 1 reply; 70+ messages in thread
From: Matthew Wilcox @ 2021-07-04 21:49 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 04, 2021 at 10:33:39PM +0100, Matthew Wilcox wrote:
> On Sun, Jul 04, 2021 at 11:17:50PM +0200, Miguel Ojeda wrote:
> > On Sun, Jul 4, 2021 at 11:05 PM Matthew Wilcox <willy@infradead.org> wrote:
> > >
> > > What happened to my suggestion from last time of encoding symbols < 128
> > > as 0-127 and symbols larger than that as (data[0] - 128) * 256 +
> > > data[1]) ?
> > 
> > Nothing, sorry, we focused on other parts (e.g. the allocation panics)
> > during this iteration. I can take a look for v2.
> 
> Here's what I have.  Build testing now.

It seems to work.  Sample output from kallsyms with the test forced to
'true':

        .byte 0x80
        .byte 0x0a, 0x41, 0xff, 0x70, 0xf3, 0xd0, 0xb0, 0xf2, 0xfc, 0x72, 0x74

under normal circumstances, it omits that first line.

I'm unfortunately in the middle of ripping apart and fixing up my test
infrastructure, so I can't claim to have really tested it, and I don't
have a module with a really large symbol anyway.  But I'll submit this
to you as a proper patch with changelog if that's enough testing for you.

(now that i look at kallsyms, why on earth is it ripping the string
apart and turning it into .byte instead of just using .ascii?)

> 
> diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
> index c851ca0ed357..0d45a6e5fdc3 100644
> --- a/kernel/kallsyms.c
> +++ b/kernel/kallsyms.c
> @@ -67,6 +67,14 @@ static unsigned int kallsyms_expand_symbol(unsigned int off,
>  	len = *data;
>  	data++;
>  
> +	/* lengths larger than 128 are encoded as two bytes */
> +	if (len >= 128) {
> +		len -= 128;
> +		len *= 256;
> +		len += *data;
> +		data++;
> +	}
> +
>  	/*
>  	 * Update the offset to return the offset for the next symbol on
>  	 * the compressed stream.
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 54ad86d13784..701566e01a1d 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -467,10 +467,16 @@ static void write_src(void)
>  	output_label("kallsyms_names");
>  	off = 0;
>  	for (i = 0; i < table_cnt; i++) {
> +		int len = table[i]->len;
>  		if ((i & 0xFF) == 0)
>  			markers[i >> 8] = off;
>  
> -		printf("\t.byte 0x%02x", table[i]->len);
> +		if (len >= 128) {
> +			printf("\t.byte 0x%02x\n", len / 256 + 128);
> +			len %= 256;
> +			off++;
> +		}
> +		printf("\t.byte 0x%02x", len);
>  		for (k = 0; k < table[i]->len; k++)
>  			printf(", 0x%02x", table[i]->sym[k]);
>  		printf("\n");

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:49         ` Matthew Wilcox
@ 2021-07-04 22:07           ` Miguel Ojeda
  0 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-04 22:07 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 4, 2021 at 11:49 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> I'm unfortunately in the middle of ripping apart and fixing up my test
> infrastructure, so I can't claim to have really tested it, and I don't
> have a module with a really large symbol anyway.  But I'll submit this
> to you as a proper patch with changelog if that's enough testing for you.

Sure, and thanks! I can give it a spin with our tests.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:33       ` Matthew Wilcox
  2021-07-04 21:49         ` Matthew Wilcox
@ 2021-07-04 22:20         ` Gary Guo
  2021-07-04 22:42           ` Matthew Wilcox
  1 sibling, 1 reply; 70+ messages in thread
From: Gary Guo @ 2021-07-04 22:20 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Miguel Ojeda, Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	Linux Doc Mailing List, linux-kernel, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, 4 Jul 2021 22:33:39 +0100
Matthew Wilcox <willy@infradead.org> wrote:

> On Sun, Jul 04, 2021 at 11:17:50PM +0200, Miguel Ojeda wrote:
> > On Sun, Jul 4, 2021 at 11:05 PM Matthew Wilcox
> > <willy@infradead.org> wrote:  
> > >
> > > What happened to my suggestion from last time of encoding symbols
> > > < 128 as 0-127 and symbols larger than that as (data[0] - 128) *
> > > 256 + data[1]) ?  
> > 
> > Nothing, sorry, we focused on other parts (e.g. the allocation
> > panics) during this iteration. I can take a look for v2.  
> 
> Here's what I have.  Build testing now.
> 
> 
> diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
> index c851ca0ed357..0d45a6e5fdc3 100644
> --- a/kernel/kallsyms.c
> +++ b/kernel/kallsyms.c
> @@ -67,6 +67,14 @@ static unsigned int
> kallsyms_expand_symbol(unsigned int off, len = *data;
>  	data++;
>  
> +	/* lengths larger than 128 are encoded as two bytes */
> +	if (len >= 128) {
> +		len -= 128;
> +		len *= 256;
> +		len += *data;
> +		data++;
> +	}
> +
>  	/*
>  	 * Update the offset to return the offset for the next
> symbol on
>  	 * the compressed stream.
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 54ad86d13784..701566e01a1d 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -467,10 +467,16 @@ static void write_src(void)
>  	output_label("kallsyms_names");
>  	off = 0;
>  	for (i = 0; i < table_cnt; i++) {
> +		int len = table[i]->len;
>  		if ((i & 0xFF) == 0)
>  			markers[i >> 8] = off;
>  
> -		printf("\t.byte 0x%02x", table[i]->len);
> +		if (len >= 128) {
> +			printf("\t.byte 0x%02x\n", len / 256 + 128);
> +			len %= 256;
> +			off++;
> +		}
> +		printf("\t.byte 0x%02x", len);
>  		for (k = 0; k < table[i]->len; k++)
>  			printf(", 0x%02x", table[i]->sym[k]);
>  		printf("\n");

This is big endian.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 22:20         ` Gary Guo
@ 2021-07-04 22:42           ` Matthew Wilcox
  2021-07-04 23:14             ` Gary Guo
  2021-07-13 18:02             ` Kent Overstreet
  0 siblings, 2 replies; 70+ messages in thread
From: Matthew Wilcox @ 2021-07-04 22:42 UTC (permalink / raw)
  To: Gary Guo
  Cc: Miguel Ojeda, Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	Linux Doc Mailing List, linux-kernel, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 04, 2021 at 11:20:07PM +0100, Gary Guo wrote:
> This is big endian.

Fundamentally, it doesn't matter whether it's encoded as top-7 +
bottom-8 or bottom-7 + top-8.  It could just as well be:

        if (len >= 128) {
                len -= 128;
                len += *data * 256;
                data++;
        }

It doesn't matter whether it's compatible with some other encoding.
This encoding has one producer and one consumer.  As long as they agree,
it's fine.  If you want to make an argument about extensibiity, then
I'm going to suggest that wanting a symbol name more than 32kB in size
is a sign you've done something else very, very wrong.

At that point, you should probably switch to comparing hashes of the
symbol instead of the symbol.  Indeed, I think we're already there at
300 byte symbols; we should probably SipHash the full, unmangled symbol
[1].  At 33k symbols in the current kernel, the risk of a collision of
a 64-bit value is negligible, and almost every kernel symbol is longer
than 7 bytes (thankfully).

[1] ie SipHash("void unlock_page(struct page *)")

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (13 preceding siblings ...)
  2021-07-04 20:27 ` [PATCH 16/17] MAINTAINERS: Rust ojeda
@ 2021-07-04 23:11 ` Miguel Ojeda
  2021-07-07  6:43 ` Christoph Hellwig
  2021-07-07 10:51 ` Marco Elver
  16 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-04 23:11 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Sun, Jul 4, 2021 at 10:28 PM <ojeda@kernel.org> wrote:
>
> This is the patch series to add support for Rust as a second language
> to the Linux kernel.

In case somebody wonders: patch 07 was particularly big and lore does
not seem to be showing it.

Let me know if you want me to split it; otherwise I will ask
Konstantin when he is back from holidays.

>   - Many folks that have reported issues, tested the project,
>     helped spread the word, joined discussions and contributed in
>     other ways! In no particular order: Chenguang Wang, Greg Morenz,
>     John Baublitz, Leah Leshchinsky, Caedin Cook, Liam Arzola,
>     Fabio Aiuto, Hanqing Zhao, Robin Randhawa, Michal Rostecki,
>     Wei Liu...

I forgot to mention Samantha Miller, Santosh Sivaraj, Vegard Nossum
and Leandro Coutinho.

My apologies!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 22:42           ` Matthew Wilcox
@ 2021-07-04 23:14             ` Gary Guo
  2021-07-13 18:02             ` Kent Overstreet
  1 sibling, 0 replies; 70+ messages in thread
From: Gary Guo @ 2021-07-04 23:14 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Miguel Ojeda, Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	Linux Doc Mailing List, linux-kernel, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, 4 Jul 2021 23:42:03 +0100
Matthew Wilcox <willy@infradead.org> wrote:

> On Sun, Jul 04, 2021 at 11:20:07PM +0100, Gary Guo wrote:
> > This is big endian.  
> 
> Fundamentally, it doesn't matter whether it's encoded as top-7 +
> bottom-8 or bottom-7 + top-8.  It could just as well be:
> 
>         if (len >= 128) {
>                 len -= 128;
>                 len += *data * 256;

Do you mean `*data * 128`?

>                 data++;
>         }
> 
> It doesn't matter whether it's compatible with some other encoding.
> This encoding has one producer and one consumer.  As long as they
> agree, it's fine.

I am aware that this is only for internal tooling so it doesn't
really matter. I mentioned that it's big endian to do top-7 +
bottom-8 because Linus suggests that big-endian shouldn't be
used.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 21:20     ` Gary Guo
@ 2021-07-05  4:35       ` Willy Tarreau
  0 siblings, 0 replies; 70+ messages in thread
From: Willy Tarreau @ 2021-07-05  4:35 UTC (permalink / raw)
  To: Gary Guo
  Cc: Matthew Wilcox, ojeda, Linus Torvalds, Greg Kroah-Hartman,
	rust-for-linux, linux-kbuild, linux-doc, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 04, 2021 at 10:20:43PM +0100, Gary Guo wrote:
> On Sun, 4 Jul 2021 22:04:49 +0100
> Matthew Wilcox <willy@infradead.org> wrote:
> 
> > On Sun, Jul 04, 2021 at 10:27:40PM +0200, ojeda@kernel.org wrote:
> > > From: Miguel Ojeda <ojeda@kernel.org>
> > > 
> > > 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 2-byte lengths to the symbol table. We call
> > > these "big" symbols.
> > > 
> > > In order to avoid increasing all lengths to 2 bytes (since most
> > > of them only require 1 byte, including many Rust ones), we use
> > > length zero to mark "big" symbols in the table.  
> > 
> > What happened to my suggestion from last time of encoding symbols <
> > 128 as 0-127 and symbols larger than that as (data[0] - 128) * 256 +
> > data[1]) ?
> 
> Yeah, I agree ULEB128 or similar encoding scheme would be better than
> using 0 as an escape byte. If ULEB128 is used and we restrict number of
> bytes to 2, it will encode numbers up to 2**14 instead of 2**16 like the
> current scheme, but that should be sufficient anyway.

Actually plenty of variants of such encodings exist. You can split the
first byte on 192 to keep 6 upper bits, 224 for 5, 240 for 4, etc. It
all depends how long the maximum string is expected to be and how often
we expect to see large strings. For example when splitting around 240,
all sizes from 0 to 239 take one byte, and sizes from 240 to 4335 take
two bytes.

But if strings >128 are already extremely rare we don't really care
about the extra byte needed to encode them.

Willy

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/17] docs: add Rust documentation
  2021-07-04 20:27 ` [PATCH 13/17] docs: add Rust documentation ojeda
@ 2021-07-05  5:02   ` Willy Tarreau
  2021-07-06  0:06     ` Miguel Ojeda
  2021-07-14 18:37   ` Nick Desaulniers
  1 sibling, 1 reply; 70+ messages in thread
From: Willy Tarreau @ 2021-07-05  5:02 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	Boqun Feng, Sumera Priyadarsini, Michael Ellerman,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Fox Chen,
	Ayaan Zaidi, Douglas Su, Yuki Okushi

On Sun, Jul 04, 2021 at 10:27:52PM +0200, ojeda@kernel.org wrote:
> From: Miguel Ojeda <ojeda@kernel.org>
> 
> 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.
(...)
> diff --git a/Documentation/rust/coding.rst b/Documentation/rust/coding.rst
> new file mode 100644
> index 00000000000..5cbe132f461
> --- /dev/null
> +++ b/Documentation/rust/coding.rst
> @@ -0,0 +1,92 @@
> +.. _rust_coding:
> +
> +Coding
> +======
> +
> +This document describes how to write Rust code in the kernel.
> +
> +
> +Coding style
> +------------
> +
> +The code is automatically formatted using the ``rustfmt`` tool. This is very
> +good news!

Miguel, the wording and style in this file is not much welcome, it looks
like a copy-paste of an e-mail in the doc. The exclamation above "this is
a very good news" doesn't really belong to a doc, and for readers who don't
understand why it appears as a good news to the writer, it probably is an
even less good news.

> +- If you contribute from time to time to the kernel, you do not need to learn
> +  and remember one more style guide. You will also need less patch roundtrips
> +  to land a change.
> +
> +- If you are a reviewer or a maintainer, you will not need to spend time on
> +  pointing out style issues anymore.
> +
> +.. note:: Conventions on comments and documentation are not checked by
> +  ``rustfmt``. Thus we still need to take care of those: please see
> +  :ref:`Documentation/rust/docs.rst <rust_docs>`.
> +
> +We use the tool's default settings. This means we are following the idiomatic
> +Rust style. For instance, we use 4 spaces for indentation rather than tabs.
> +
> +Typically, you will want to instruct your editor/IDE to format while you type,

In general you should avoid "we" and "you" when writing documentation.
Prefer passive forms instead, which do not place a barrier between those
who teach and those who learn. It's generally considered more inclusive
in that it makes the reader not feel outside of the team who wrote it.

For example the last sentences above could be reworded like this:

  The tool's default settings are used, which means the idiomatic Rust
  style is followed. For instance, 4 spaces are used for indentation
  rather than tabs.

  Typically editors/IDE will have to be instructed to format while typing.
  (...)

An additional note is that if the language imposes such unusual constraints
on the editor, you should probably point to various known settins for most
well-known editors.

> +when you save or at commit time. However, if for some reason you want
> +to reformat the entire kernel Rust sources at some point, you may run::
> +
> +	make LLVM=1 rustfmt
> +
> +To check if everything is formatted (printing a diff otherwise), e.g. if you
> +have configured a CI for a tree as a maintainer, you may run::
> +
> +	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.

You should also clearly indicate how to recheck (or adjust) individual
files, not just say that the command supports it.

Regards,
Willy

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 15/17] scripts: add `generate_rust_analyzer.py`
  2021-07-04 20:27 ` [PATCH 15/17] scripts: add `generate_rust_analyzer.py` ojeda
@ 2021-07-05  5:05   ` Willy Tarreau
  2021-07-05 23:41     ` Miguel Ojeda
  0 siblings, 1 reply; 70+ messages in thread
From: Willy Tarreau @ 2021-07-05  5:05 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	Boqun Feng, Sumera Priyadarsini, Michael Ellerman,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Fox Chen,
	Ayaan Zaidi, Douglas Su, Yuki Okushi

On Sun, Jul 04, 2021 at 10:27:54PM +0200, ojeda@kernel.org wrote:
> From: Miguel Ojeda <ojeda@kernel.org>
> 
> 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.

You should probably add some doc about this, as I have no idea how
I'm supposed to use this from my editor.

Willy

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 15/17] scripts: add `generate_rust_analyzer.py`
  2021-07-05  5:05   ` Willy Tarreau
@ 2021-07-05 23:41     ` Miguel Ojeda
  0 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-05 23:41 UTC (permalink / raw)
  To: Willy Tarreau
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, Boqun Feng, Sumera Priyadarsini,
	Michael Ellerman, Sven Van Asbroeck, Gary Guo,
	Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi, Douglas Su,
	Yuki Okushi

On Mon, Jul 5, 2021 at 7:05 AM Willy Tarreau <w@1wt.eu> wrote:
>
> You should probably add some doc about this, as I have no idea how
> I'm supposed to use this from my editor.

Yeah, I can add a link to rust-analyzer's docs and/or the Language
Server Protocol site, and perhaps a couple steps on how to set it up;
but I would try to avoid repeating their documentation.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/17] docs: add Rust documentation
  2021-07-05  5:02   ` Willy Tarreau
@ 2021-07-06  0:06     ` Miguel Ojeda
  2021-07-06  2:09       ` Willy Tarreau
  0 siblings, 1 reply; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-06  0:06 UTC (permalink / raw)
  To: Willy Tarreau
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, Boqun Feng, Sumera Priyadarsini,
	Michael Ellerman, Sven Van Asbroeck, Gary Guo,
	Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi, Douglas Su,
	Yuki Okushi

On Mon, Jul 5, 2021 at 7:02 AM Willy Tarreau <w@1wt.eu> wrote:
>
> Miguel, the wording and style in this file is not much welcome, it looks
> like a copy-paste of an e-mail in the doc. The exclamation above "this is
> a very good news" doesn't really belong to a doc, and for readers who don't
> understand why it appears as a good news to the writer, it probably is an
> even less good news.

Yes, I can definitely be more formal here.

> In general you should avoid "we" and "you" when writing documentation.
> Prefer passive forms instead, which do not place a barrier between those
> who teach and those who learn. It's generally considered more inclusive
> in that it makes the reader not feel outside of the team who wrote it.

When I was writing this, I wondered the same thing, because in Spanish
this does look quite bad (in the sense of being too informal), and we
use the passive forms a lot more for things like this. So I am fine
rewriting this. Also, mixing we/you is not ideal either.

Having said that, I am not sure about English and whether people
prefer to read text with the passive form or not. In `Documentation/`
there seems to be a lot of "we"s and "you"s, but they could be wrong
too, of course.

> An additional note is that if the language imposes such unusual constraints
> on the editor, you should probably point to various known settins for most
> well-known editors.

Are you referring about style? If yes, it is possible to write the
code with a text editor with no extra features and then format it, so
that should not be a problem.

> You should also clearly indicate how to recheck (or adjust) individual
> files, not just say that the command supports it.

Sounds good -- I will do that.

Thanks a lot for reviewing the docs!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 16/17] MAINTAINERS: Rust
  2021-07-04 20:27 ` [PATCH 16/17] MAINTAINERS: Rust ojeda
@ 2021-07-06  0:26   ` Pedro Tammela
  2021-07-06 22:14     ` Miguel Ojeda
  0 siblings, 1 reply; 70+ messages in thread
From: Pedro Tammela @ 2021-07-06  0:26 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, open list, Alex Gaynor, Wedson Almeida Filho

> ---
>  MAINTAINERS | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0cce91cd562..a439204d9be 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -15894,6 +15894,20 @@ L:     linux-rdma@vger.kernel.org
>  S:     Maintained
>  F:     drivers/infiniband/ulp/rtrs/
>
> +RUST
> +M:     Miguel Ojeda <ojeda@kernel.org>
> +M:     Alex Gaynor <alex.gaynor@gmail.com>
> +M:     Wedson Almeida Filho <wedsonaf@google.com>
> +L:     rust-for-linux@vger.kernel.org
> +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/
> +K:     \b(?i:rust)\b
> +

Does this mean that development will be done exclusively on GitHub?
If affirmative, is there a bot that will replicate the messages in the
mailing list?

>  RXRPC SOCKETS (AF_RXRPC)
>  M:     David Howells <dhowells@redhat.com>
>  M:     Marc Dionne <marc.dionne@auristor.com>
> --
> 2.32.0
>

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/17] docs: add Rust documentation
  2021-07-06  0:06     ` Miguel Ojeda
@ 2021-07-06  2:09       ` Willy Tarreau
  0 siblings, 0 replies; 70+ messages in thread
From: Willy Tarreau @ 2021-07-06  2:09 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, Boqun Feng, Sumera Priyadarsini,
	Michael Ellerman, Sven Van Asbroeck, Gary Guo,
	Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi, Douglas Su,
	Yuki Okushi

On Tue, Jul 06, 2021 at 02:06:52AM +0200, Miguel Ojeda wrote:
> > In general you should avoid "we" and "you" when writing documentation.
> > Prefer passive forms instead, which do not place a barrier between those
> > who teach and those who learn. It's generally considered more inclusive
> > in that it makes the reader not feel outside of the team who wrote it.
> 
> When I was writing this, I wondered the same thing, because in Spanish
> this does look quite bad (in the sense of being too informal), and we
> use the passive forms a lot more for things like this. So I am fine
> rewriting this. Also, mixing we/you is not ideal either.

Indeed, I can imagine how informal it could sound in Spanish.

> Having said that, I am not sure about English and whether people
> prefer to read text with the passive form or not. In `Documentation/`
> there seems to be a lot of "we"s and "you"s, but they could be wrong
> too, of course.

It's possible. While I've seen it used a lot in training or step-by-step
instructions which aim to guide the reader through a procedure, it's not
commonly found in documentation. One principle to keep in mind is to only
focus on the subject. If your documentation describes a component or
process and does not involve a human, there's no reason for introducing
this human there. If it explicitly aims at the human (e.g. instructions),
of course it makes sense. But anything that can end up in a script does
not require a human and should avoid we/you.

> > An additional note is that if the language imposes such unusual constraints
> > on the editor, you should probably point to various known settins for most
> > well-known editors.
> 
> Are you referring about style? If yes, it is possible to write the
> code with a text editor with no extra features and then format it, so
> that should not be a problem.

Yes that's my point, it will likely be the first experience for most
casual visitors who have no idea how to reconfigure their editor or
who don't want to risk to break their existing config.

> > You should also clearly indicate how to recheck (or adjust) individual
> > files, not just say that the command supports it.
> 
> Sounds good -- I will do that.
> 
> Thanks a lot for reviewing the docs!

You're welcome.

Willy

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 16/17] MAINTAINERS: Rust
  2021-07-06  0:26   ` Pedro Tammela
@ 2021-07-06 22:14     ` Miguel Ojeda
  0 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-06 22:14 UTC (permalink / raw)
  To: Pedro Tammela
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, open list,
	Alex Gaynor, Wedson Almeida Filho

On Tue, Jul 6, 2021 at 2:26 AM Pedro Tammela <pctammela@gmail.com> wrote:
>
> Does this mean that development will be done exclusively on GitHub?
> If affirmative, is there a bot that will replicate the messages in the
> mailing list?

Development has happened mainly in GitHub so far, but we have accepted
patches from the ML and we can do their reviews there too.

We do not have a bot to replicate reviews into the mailing list nor
any fancy bidirectional sync, though.

If this is deemed unacceptable by Linus et. al., we can do development
in the ML as usual -- we do not really mind one way or the other (and,
in fact, we discussed moving things to a git.kernel.org tree too).

The main point of GitHub/GitLab/etc. for us so far is having an issue
tracker and some kind of CI.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (14 preceding siblings ...)
  2021-07-04 23:11 ` [PATCH 00/17] Rust support Miguel Ojeda
@ 2021-07-07  6:43 ` Christoph Hellwig
  2021-07-07 12:33   ` Miguel Ojeda
  2021-07-07 10:51 ` Marco Elver
  16 siblings, 1 reply; 70+ messages in thread
From: Christoph Hellwig @ 2021-07-07  6:43 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel

Not sure if this is just a state of the union post or if you actually
want to submit it.  If the later I strongly disagree with merging it,
as you should refined it and prove it actually is useful first.  Where
useful would be a real-life driver like say nvme or a usb host
controller driver that actually works and shows benefits over the
existing one.  Until it shows such usefulness it will just drag
everyone else down.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 05/17] rust: add C helpers
  2021-07-04 20:27 ` [PATCH 05/17] rust: add C helpers ojeda
@ 2021-07-07 10:19   ` Marco Elver
  2021-07-09 10:31     ` Marco Elver
  2021-07-09 14:32     ` Miguel Ojeda
  0 siblings, 2 replies; 70+ messages in thread
From: Marco Elver @ 2021-07-07 10:19 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	Boqun Feng, Sumera Priyadarsini, Michael Ellerman,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Fox Chen,
	Ayaan Zaidi, Douglas Su, Yuki Okushi, clang-built-linux

On Sun, Jul 04, 2021 at 10:27PM +0200, ojeda@kernel.org wrote:
> From: Miguel Ojeda <ojeda@kernel.org>
> 
> This source file contains forwarders to C macros and inlined
> functions.

What is the story with Rust and LTO? Intuitively, I would expect Rust
code to only perform optimally if the kernel is built with LTO
(currently only supported via Clang).

Because if calls to every one of these helpers are real calls, I would
expect performance to be pretty poor. There's probably a reason these
are macros or inlinable functions.

I would almost go so far and suggest that CONFIG_RUST be modified as
follows:

--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2028,6 +2028,7 @@ config RUST
 	depends on HAS_RUST
 	depends on !COMPILE_TEST
 	depends on !MODVERSIONS
+	depends on LTO || EXPERT
 	default n
 	help
 	  Enables Rust support in the kernel.

[ I'm sure there are configs that don't yet work with LTO, but could be
  useful to enable for debugging or testing purposes, and therefore would
  make it conditional on CONFIG_EXPERT as well. ]

[...]
> +unsigned long rust_helper_copy_from_user(void *to, const void __user *from, unsigned long n)
> +{
> +	return copy_from_user(to, from, n);
> +}
> +
[...]

From some local tests, it looks like simply attaching
__attribute__((always_inline)) will do what one would expect when
compiling with Clang LTO (I checked -flto=thin).

If you confirm this also works across C and Rust TUs when enabling LTO,
I would then suggested adding __attribute__((always_inline)) to all
these helpers.

Thanks,
-- Marco

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
                   ` (15 preceding siblings ...)
  2021-07-07  6:43 ` Christoph Hellwig
@ 2021-07-07 10:51 ` Marco Elver
  2021-07-07 11:28   ` Miguel Ojeda
  16 siblings, 1 reply; 70+ messages in thread
From: Marco Elver @ 2021-07-07 10:51 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel

On Sun, Jul 04, 2021 at 10:27PM +0200, ojeda@kernel.org wrote:
[...]
>   rust: add `alloc` crate
[...]

I think this patch never made it to the mailing list. b4 also doesn't
find it:

	ERROR: missing [7/17]

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 10:51 ` Marco Elver
@ 2021-07-07 11:28   ` Miguel Ojeda
  0 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-07 11:28 UTC (permalink / raw)
  To: Marco Elver
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Wed, Jul 7, 2021 at 12:51 PM Marco Elver <elver@google.com> wrote:
>
> I think this patch never made it to the mailing list. b4 also doesn't
> find it:
>
>         ERROR: missing [7/17]

Yeah, thanks -- I mentioned in my reply above:

    https://lore.kernel.org/lkml/CANiq72nQq8Y8v9Pyf7JFq6Kf-+doNP+mHAFNzj_cSFBa3KwS5w@mail.gmail.com/

If you want to try the patches, you can pick them from this tree (the
one in linux-next):

    https://github.com/Rust-for-Linux/linux/tree/rust-next

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07  6:43 ` Christoph Hellwig
@ 2021-07-07 12:33   ` Miguel Ojeda
  2021-07-07 12:50     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-07 12:33 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Wed, Jul 7, 2021 at 8:44 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> Not sure if this is just a state of the union post or if you actually
> want to submit it.  If the later I strongly disagree with merging it,

We are submitting it.

> as you should refined it and prove it actually is useful first.  Where
> useful would be a real-life driver like say nvme or a usb host
> controller driver that actually works and shows benefits over the
> existing one.  Until it shows such usefulness it will just drag
> everyone else down.

It is "proven" in the sense we are already starting to get users
downstream and other interested parties have shown support.

However, others are more conservative and will only start investing
into it if we are in mainline, i.e. if the decision of having Rust or
not is already taken.

But it is fair to ask for a hardware driver to see how it looks like,
which is why the cover letter mentions we are working on one.

Now, if you are OK with non-hardware modules, you can take a look at
Rust Binder (last patch in the series) which is a non-trivial module
and it is already working.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 12:33   ` Miguel Ojeda
@ 2021-07-07 12:50     ` Greg Kroah-Hartman
  2021-07-07 14:07       ` Wedson Almeida Filho
  0 siblings, 1 reply; 70+ messages in thread
From: Greg Kroah-Hartman @ 2021-07-07 12:50 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Christoph Hellwig, Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Wed, Jul 07, 2021 at 02:33:57PM +0200, Miguel Ojeda wrote:
> Now, if you are OK with non-hardware modules, you can take a look at
> Rust Binder (last patch in the series) which is a non-trivial module
> and it is already working.

Cool, does it actually pass the binder self-tests that the Android
systems have for the codebase?  Last I looked at this thing, it was not
feature-complete compared to the in-kernel binder code, has that been
resolved and the needed filesystem changes added?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 12:50     ` Greg Kroah-Hartman
@ 2021-07-07 14:07       ` Wedson Almeida Filho
  2021-07-07 14:12         ` Christoph Hellwig
  2021-07-07 15:02         ` Greg Kroah-Hartman
  0 siblings, 2 replies; 70+ messages in thread
From: Wedson Almeida Filho @ 2021-07-07 14:07 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Miguel Ojeda, Christoph Hellwig, Miguel Ojeda, Linus Torvalds,
	rust-for-linux, Linux Kbuild mailing list,
	Linux Doc Mailing List, linux-kernel

On Wed, Jul 07, 2021 at 02:50:54PM +0200, Greg Kroah-Hartman wrote:
> On Wed, Jul 07, 2021 at 02:33:57PM +0200, Miguel Ojeda wrote:
> > Now, if you are OK with non-hardware modules, you can take a look at
> > Rust Binder (last patch in the series) which is a non-trivial module
> > and it is already working.
> 
> Cool, does it actually pass the binder self-tests that the Android
> systems have for the codebase?

We haven't run the Android tests yet because they depend on an Android-specific
service (servicemanager) running and other Android-specific libraries. What we
are doing instead is adding binder tests that don't depend on anything
Android-specific; in fact, we are putting them in tools/testing/selftests/binder
so that they can run on any vanilla system.

The commit is available here:
https://github.com/wedsonaf/linux/commit/f90ec49be9207fa765f07ad1071210ad871712ac

The tests are written in C and run successfully against both C and Rust drivers.
I still have another ~20 tests that I wrote in another harness that I will
convert to selftests soon, but the two together I believe have more coverage
than the ones in Android.

We also have a trivial latency benchmark (ping with no payload) where the Rust
version performs better than the C one.

The benchmark is available here: https://github.com/wedsonaf/linux/commits/ping

> Last I looked at this thing, it was not
> feature-complete compared to the in-kernel binder code, has that been
> resolved and the needed filesystem changes added?

It is not feature-complete in comparison to the C one just yet, it is missing a
few things but not for any fundamental reason -- we were mostly focusing on the
kernel crate and tests.

Miguel's point is that it does implement the vast majority of binder features
and is non-trivial, so it could be used as evidence that useful kernel drivers
can be built with Rust; not just "transpiled" from C, but written with the Rust
safety guarantees.

Cheers,
-Wedson

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 14:07       ` Wedson Almeida Filho
@ 2021-07-07 14:12         ` Christoph Hellwig
  2021-07-07 15:02         ` Greg Kroah-Hartman
  1 sibling, 0 replies; 70+ messages in thread
From: Christoph Hellwig @ 2021-07-07 14:12 UTC (permalink / raw)
  To: Wedson Almeida Filho
  Cc: Greg Kroah-Hartman, Miguel Ojeda, Christoph Hellwig,
	Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Wed, Jul 07, 2021 at 03:07:50PM +0100, Wedson Almeida Filho wrote:
> Miguel's point is that it does implement the vast majority of binder features
> and is non-trivial, so it could be used as evidence that useful kernel drivers
> can be built with Rust; not just "transpiled" from C, but written with the Rust
> safety guarantees.

binder is not a kernel driver.  It is a ill design IPC mechanism
absolutely no representative for other kernel code.

Please write an actual real driver dealing with real (and common) hardware
and come back with the results.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 14:07       ` Wedson Almeida Filho
  2021-07-07 14:12         ` Christoph Hellwig
@ 2021-07-07 15:02         ` Greg Kroah-Hartman
  2021-07-07 20:56           ` Finn Behrens
  1 sibling, 1 reply; 70+ messages in thread
From: Greg Kroah-Hartman @ 2021-07-07 15:02 UTC (permalink / raw)
  To: Wedson Almeida Filho
  Cc: Miguel Ojeda, Christoph Hellwig, Miguel Ojeda, Linus Torvalds,
	rust-for-linux, Linux Kbuild mailing list,
	Linux Doc Mailing List, linux-kernel

On Wed, Jul 07, 2021 at 03:07:50PM +0100, Wedson Almeida Filho wrote:
> > Last I looked at this thing, it was not
> > feature-complete compared to the in-kernel binder code, has that been
> > resolved and the needed filesystem changes added?
> 
> It is not feature-complete in comparison to the C one just yet, it is missing a
> few things but not for any fundamental reason -- we were mostly focusing on the
> kernel crate and tests.

I love it how you call "binderfs is missing" a "few things" :)

> Miguel's point is that it does implement the vast majority of binder features
> and is non-trivial, so it could be used as evidence that useful kernel drivers
> can be built with Rust; not just "transpiled" from C, but written with the Rust
> safety guarantees.

As Christoph said, and I and others have said before, binder is in no
way shape or form anything that resembles any sort of "driver" at all.
It is a crazy IPC mechanism that is tacked onto the side of the kernel.
Not to say that it doesn't have its usages, but the interactions between
binder and the rest of the kernel are very small and specific.
Something that almost no one else will ever write again.

Please work on a real driver to help prove, or disprove, that this all
is going to be able to work properly.  There are huge unanswered
questions that need to be resolved that you will run into when you do
such a thing.

Good luck!

greg k-h

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 04/17] vsprintf: add new `%pA` format specifier
  2021-07-04 20:27 ` [PATCH 04/17] vsprintf: add new `%pA` format specifier ojeda
@ 2021-07-07 20:31   ` Nick Desaulniers
  2021-07-07 22:33     ` Miguel Ojeda
  0 siblings, 1 reply; 70+ messages in thread
From: Nick Desaulniers @ 2021-07-07 20:31 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	Boqun Feng, Sumera Priyadarsini, Michael Ellerman,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Fox Chen,
	Ayaan Zaidi, Douglas Su, Yuki Okushi

On Sun, Jul 4, 2021 at 1:29 PM <ojeda@kernel.org> wrote:
>
> From: Miguel Ojeda <ojeda@kernel.org>
>
> 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.
>
> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
> Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
> Co-developed-by: Finn Behrens <me@kloenk.de>
> Signed-off-by: Finn Behrens <me@kloenk.de>
> Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
> Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
> Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
> Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
> Co-developed-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
> Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
> Co-developed-by: Fox Chen <foxhlchen@gmail.com>
> Signed-off-by: Fox Chen <foxhlchen@gmail.com>
> Co-developed-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
> Signed-off-by: Ayaan Zaidi <zaidi.ayaan@gmail.com>
> Co-developed-by: Douglas Su <d0u9.su@outlook.com>
> Signed-off-by: Douglas Su <d0u9.su@outlook.com>
> Co-developed-by: Yuki Okushi <jtitor@2k36.org>
> Signed-off-by: Yuki Okushi <jtitor@2k36.org>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
>  lib/vsprintf.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index f0c35d9b65b..e7afe954004 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -2182,6 +2182,10 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
>         return widen_string(buf, buf - buf_start, end, spec);
>  }
>
> +#ifdef CONFIG_RUST
> +char *rust_fmt_argument(char* buf, char* end, void *ptr);

Which patch in the series adds the definition of rust_fmt_argument?
Sorry, I haven't looked through the entire series yet, but I don't
think it was an earlier patch in the series.  If it's later in the
series, you may want to rebase this to be after (or combine it with
the patch that provides the definition).  For instance, let's say the
first half of this series was accepted/merged, but not the latter
half. It would be weird to provide such definitions/calls to undefined
symbols.

> +#endif
> +
>  /* Disable pointer hashing if requested */
>  bool no_hash_pointers __ro_after_init;
>  EXPORT_SYMBOL_GPL(no_hash_pointers);
> @@ -2335,6 +2339,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,
> @@ -2407,6 +2415,10 @@ 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);
> +#ifdef CONFIG_RUST
> +       case 'A':
> +               return rust_fmt_argument(buf, end, ptr);
> +#endif
>         case 'x':
>                 return pointer_string(buf, end, ptr, spec);
>         case 'e':
> --
> 2.32.0
>


--
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 15:02         ` Greg Kroah-Hartman
@ 2021-07-07 20:56           ` Finn Behrens
  2021-07-08  0:58             ` Matthew Wilcox
  0 siblings, 1 reply; 70+ messages in thread
From: Finn Behrens @ 2021-07-07 20:56 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Wedson Almeida Filho, Miguel Ojeda, Christoph Hellwig,
	Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel



> On 7. Jul 2021, at 17:02, Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> 
> On Wed, Jul 07, 2021 at 03:07:50PM +0100, Wedson Almeida Filho wrote:
>>> Last I looked at this thing, it was not
>>> feature-complete compared to the in-kernel binder code, has that been
>>> resolved and the needed filesystem changes added?
>> 
>> It is not feature-complete in comparison to the C one just yet, it is missing a
>> few things but not for any fundamental reason -- we were mostly focusing on the
>> kernel crate and tests.
> 
> I love it how you call "binderfs is missing" a "few things" :)
> 
>> Miguel's point is that it does implement the vast majority of binder features
>> and is non-trivial, so it could be used as evidence that useful kernel drivers
>> can be built with Rust; not just "transpiled" from C, but written with the Rust
>> safety guarantees.
> 
> As Christoph said, and I and others have said before, binder is in no
> way shape or form anything that resembles any sort of "driver" at all.
> It is a crazy IPC mechanism that is tacked onto the side of the kernel.
> Not to say that it doesn't have its usages, but the interactions between
> binder and the rest of the kernel are very small and specific.
> Something that almost no one else will ever write again.
> 
> Please work on a real driver to help prove, or disprove, that this all
> is going to be able to work properly.  There are huge unanswered
> questions that need to be resolved that you will run into when you do
> such a thing.
> 

There is a more general use driver (network dummy) still in the making, It is fully operational, just the documentation of the rust bindings are not finished yet, so it is not merged into the rust tree yet, also I have to rebase it.
I testet the network dummy (dummyrs) driver and for stupid tests like Iperf3 or ping it performed slightly better that the C version. See https://github.com/Kloenk/linux/blob/rust-netdevice/drivers/net/dummy_rs.rs for the actually driver.

Yes this driver is still only virtually, but the network apis are probably more general usage than the binder apis.

> Good luck!
> 
> greg k-h

CU,
Finn


^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 04/17] vsprintf: add new `%pA` format specifier
  2021-07-07 20:31   ` Nick Desaulniers
@ 2021-07-07 22:33     ` Miguel Ojeda
  0 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-07 22:33 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, Boqun Feng, Sumera Priyadarsini,
	Michael Ellerman, Sven Van Asbroeck, Gary Guo,
	Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi, Douglas Su,
	Yuki Okushi

On Wed, Jul 7, 2021 at 10:31 PM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> Which patch in the series adds the definition of rust_fmt_argument?
> Sorry, I haven't looked through the entire series yet, but I don't
> think it was an earlier patch in the series.  If it's later in the
> series, you may want to rebase this to be after (or combine it with
> the patch that provides the definition).  For instance, let's say the
> first half of this series was accepted/merged, but not the latter
> half. It would be weird to provide such definitions/calls to undefined
> symbols.

It is in https://lore.kernel.org/lkml/20210704202756.29107-11-ojeda@kernel.org/#Z30rust:kernel:print.rs

Yeah, perhaps it would have been better to put it in the `kernel`
crate commit alongside `include/linux/spinlock.h` and
`kernel/printk/printk.c`.

On the other hand, having C changes on other commits may be easier to
read and explain (note that compilation still works, given things are
only enabled near the end in the Kbuild commit).

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-07 20:56           ` Finn Behrens
@ 2021-07-08  0:58             ` Matthew Wilcox
  2021-07-08  6:39               ` [PATCH 00/17] Rust support, NVMe Geert Stappers
  2021-07-22 22:55               ` [PATCH 00/17] Rust support Wedson Almeida Filho
  0 siblings, 2 replies; 70+ messages in thread
From: Matthew Wilcox @ 2021-07-08  0:58 UTC (permalink / raw)
  To: Finn Behrens
  Cc: Greg Kroah-Hartman, Wedson Almeida Filho, Miguel Ojeda,
	Christoph Hellwig, Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Wed, Jul 07, 2021 at 10:56:57PM +0200, Finn Behrens wrote:
> There is a more general use driver (network dummy) still in the making, It is fully operational, just the documentation of the rust bindings are not finished yet, so it is not merged into the rust tree yet, also I have to rebase it.

Why are you so resistant to writing a real driver that deals with actual
hardware?  A simple NVMe driver is less than a thousand lines of C.
I know the one in the kernel now is ridiculously complicated and has
been thoroughly messed up with abstractions to support NVMeoF instead
of having a separate driver, but it's really a simple interface at heart.


^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support, NVMe
  2021-07-08  0:58             ` Matthew Wilcox
@ 2021-07-08  6:39               ` Geert Stappers
  2021-07-08  8:29                 ` Finn Behrens
  2021-07-22 22:55               ` [PATCH 00/17] Rust support Wedson Almeida Filho
  1 sibling, 1 reply; 70+ messages in thread
From: Geert Stappers @ 2021-07-08  6:39 UTC (permalink / raw)
  To: Matthew Wilcox, rust-for-linux, linux-kernel

On Thu, Jul 08, 2021 at 01:58:32AM +0100, Matthew Wilcox wrote:
> On Wed, Jul 07, 2021 at 10:56:57PM +0200, Finn Behrens wrote:
> > There is a more general use driver (network dummy) still in the
> > making, It is fully operational, just the documentation of the rust
> > bindings are not finished yet, so it is not merged into the rust
> > tree yet, also I have to rebase it.
> 
> Why are you so resistant to writing a real driver that deals with actual hardware?

} Why are we so resistant to writing a real driver that deals with actual hardware?

It is not dodging hardware, it is universal available.


> A simple NVMe driver is less than a thousand lines of C.
> I know the one in the kernel now is ridiculously complicated and has
> been thoroughly messed up with abstractions to support NVMeoF instead
> of having a separate driver, but it's really a simple interface at heart.

Summary of https://qemu.readthedocs.io/en/latest/system/nvme.html

  NVMe hardware is universal available.


 

Groeten
Geert Stappers
-- 
Silence is hard to parse

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support, NVMe
  2021-07-08  6:39               ` [PATCH 00/17] Rust support, NVMe Geert Stappers
@ 2021-07-08  8:29                 ` Finn Behrens
  0 siblings, 0 replies; 70+ messages in thread
From: Finn Behrens @ 2021-07-08  8:29 UTC (permalink / raw)
  To: Geert Stappers; +Cc: Matthew Wilcox, rust-for-linux, linux-kernel



> On 8. Jul 2021, at 08:39, Geert Stappers <stappers@stappers.nl> wrote:
> 
> On Thu, Jul 08, 2021 at 01:58:32AM +0100, Matthew Wilcox wrote:
>> On Wed, Jul 07, 2021 at 10:56:57PM +0200, Finn Behrens wrote:
>>> There is a more general use driver (network dummy) still in the
>>> making, It is fully operational, just the documentation of the rust
>>> bindings are not finished yet, so it is not merged into the rust
>>> tree yet, also I have to rebase it.
>> 
>> Why are you so resistant to writing a real driver that deals with actual hardware?
> 
> } Why are we so resistant to writing a real driver that deals with actual hardware?
> 
> It is not dodging hardware, it is universal available.
> 
> 
>> A simple NVMe driver is less than a thousand lines of C.
>> I know the one in the kernel now is ridiculously complicated and has
>> been thoroughly messed up with abstractions to support NVMeoF instead
>> of having a separate driver, but it's really a simple interface at heart.
> 
> Summary of https://qemu.readthedocs.io/en/latest/system/nvme.html
> 
>  NVMe hardware is universal available.
> 

I actually don’t have a clue how nvme works, that is my reason to not write a nvme driver. But, I’m currently writing a rust version of e1000. This is also available in qemu and is real hardware. This is sadly taking quite some time, as I don’t have a good linux kernel development setup currently.

> 
> 
> 
> Groeten
> Geert Stappers
> -- 
> Silence is hard to parse

CU,
Finn


^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 05/17] rust: add C helpers
  2021-07-07 10:19   ` Marco Elver
@ 2021-07-09 10:31     ` Marco Elver
  2021-07-09 14:32     ` Miguel Ojeda
  1 sibling, 0 replies; 70+ messages in thread
From: Marco Elver @ 2021-07-09 10:31 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	Boqun Feng, Sumera Priyadarsini, Michael Ellerman,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Fox Chen,
	Ayaan Zaidi, Douglas Su, Yuki Okushi, clang-built-linux

On Wed, 7 Jul 2021 at 12:19, Marco Elver <elver@google.com> wrote:
> On Sun, Jul 04, 2021 at 10:27PM +0200, ojeda@kernel.org wrote:
> > From: Miguel Ojeda <ojeda@kernel.org>
> >
> > This source file contains forwarders to C macros and inlined
> > functions.
>
> What is the story with Rust and LTO? Intuitively, I would expect Rust
> code to only perform optimally if the kernel is built with LTO
> (currently only supported via Clang).

I'll answer my own question: it looks like Linux Rust code currently
does _not_ generate LLVM-LTO compatible object files, but only native
object files (which still link fine if LTO is enabled, but doesn't
permit the optimizations below we'd want).

rustc already supports playing nicely with LLVM LTO via `-C
linker-plugin-lto`:
https://doc.rust-lang.org/rustc/linker-plugin-lto.html

So, hopefully it should only require kernel work to make it play
nicely with CONFIG_LTO_CLANG.

> Because if calls to every one of these helpers are real calls, I would
> expect performance to be pretty poor. There's probably a reason these
> are macros or inlinable functions.
>
> I would almost go so far and suggest that CONFIG_RUST be modified as
> follows:
>
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -2028,6 +2028,7 @@ config RUST
>         depends on HAS_RUST
>         depends on !COMPILE_TEST
>         depends on !MODVERSIONS
> +       depends on LTO || EXPERT
>         default n
>         help
>           Enables Rust support in the kernel.
>
> [ I'm sure there are configs that don't yet work with LTO, but could be
>   useful to enable for debugging or testing purposes, and therefore would
>   make it conditional on CONFIG_EXPERT as well. ]
>
> [...]
> > +unsigned long rust_helper_copy_from_user(void *to, const void __user *from, unsigned long n)
> > +{
> > +     return copy_from_user(to, from, n);
> > +}
> > +
> [...]
>
> From some local tests, it looks like simply attaching
> __attribute__((always_inline)) will do what one would expect when
> compiling with Clang LTO (I checked -flto=thin).
>
> If you confirm this also works across C and Rust TUs when enabling LTO,
> I would then suggested adding __attribute__((always_inline)) to all
> these helpers.
>
> Thanks,
> -- Marco

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 05/17] rust: add C helpers
  2021-07-07 10:19   ` Marco Elver
  2021-07-09 10:31     ` Marco Elver
@ 2021-07-09 14:32     ` Miguel Ojeda
  1 sibling, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-09 14:32 UTC (permalink / raw)
  To: Marco Elver
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, Boqun Feng, Sumera Priyadarsini,
	Michael Ellerman, Sven Van Asbroeck, Gary Guo,
	Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi, Douglas Su,
	Yuki Okushi, clang-built-linux

On Wed, Jul 7, 2021 at 12:19 PM 'Marco Elver' via Clang Built Linux
<clang-built-linux@googlegroups.com> wrote:
>
> What is the story with Rust and LTO? Intuitively, I would expect Rust
> code to only perform optimally if the kernel is built with LTO
> (currently only supported via Clang).

Cross-language LTO is possible and is used in other major projects.
For instance, Firefox seems to use it:

    https://bugzilla.mozilla.org/show_bug.cgi?id=1486042

However, we have not taken a look at it yet for the kernel.

> Because if calls to every one of these helpers are real calls, I would
> expect performance to be pretty poor. There's probably a reason these
> are macros or inlinable functions.

Maybe -- we need to measure.

> I would almost go so far and suggest that CONFIG_RUST be modified as
> follows:

Even if the performance was unacceptable, there are other ways than
LTO to solve this, such as implementing the equivalent macro/function
on Rust's side.

Furthermore, we need to consider GCC too.

Thus I would not be premature in making it depend on LTO.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths)
  2021-07-04 22:42           ` Matthew Wilcox
  2021-07-04 23:14             ` Gary Guo
@ 2021-07-13 18:02             ` Kent Overstreet
  1 sibling, 0 replies; 70+ messages in thread
From: Kent Overstreet @ 2021-07-13 18:02 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Gary Guo, Miguel Ojeda, Miguel Ojeda, Linus Torvalds,
	Greg Kroah-Hartman, rust-for-linux, Linux Kbuild mailing list,
	Linux Doc Mailing List, linux-kernel, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Sun, Jul 04, 2021 at 11:42:03PM +0100, Matthew Wilcox wrote:
> On Sun, Jul 04, 2021 at 11:20:07PM +0100, Gary Guo wrote:
> > This is big endian.
> 
> Fundamentally, it doesn't matter whether it's encoded as top-7 +
> bottom-8 or bottom-7 + top-8.  It could just as well be:
> 
>         if (len >= 128) {
>                 len -= 128;
>                 len += *data * 256;
>                 data++;
>         }
> 
> It doesn't matter whether it's compatible with some other encoding.
> This encoding has one producer and one consumer.  As long as they agree,
> it's fine.  If you want to make an argument about extensibiity, then
> I'm going to suggest that wanting a symbol name more than 32kB in size
> is a sign you've done something else very, very wrong.
> 
> At that point, you should probably switch to comparing hashes of the
> symbol instead of the symbol.  Indeed, I think we're already there at
> 300 byte symbols; we should probably SipHash the full, unmangled symbol
> [1].  At 33k symbols in the current kernel, the risk of a collision of
> a 64-bit value is negligible, and almost every kernel symbol is longer
> than 7 bytes (thankfully).

We really should have a better standard varint encoding - open coding varint
encodings in 2021 is offensive, and LEB128 is retarded due to using the high bit
of _every_ byte. Here's the encoding I did for bcachefs, which I nominate for a
standard varint encoding, unless someone knows of a way to do better:

https://evilpiepirate.org/git/bcachefs.git/tree/fs/bcachefs/varint.c

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds
  2021-07-04 20:27 ` [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds ojeda
@ 2021-07-14 18:13   ` Nick Desaulniers
  2021-07-14 18:16     ` Nick Desaulniers
  2021-07-14 20:31     ` Miguel Ojeda
  0 siblings, 2 replies; 70+ messages in thread
From: Nick Desaulniers @ 2021-07-14 18:13 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	clang-built-linux, Nathan Chancellor

On Sun, Jul 4, 2021 at 1:28 PM <ojeda@kernel.org> wrote:
>
> From: Miguel Ojeda <ojeda@kernel.org>
>
> To support Rust under GCC-built kernels, we need to save the flags that
> would have been passed if the kernel was being compiled with Clang.
>
> The reason is that `bindgen` -- the tool we use to generate Rust
> bindings to the C side of the kernel -- relies on `libclang` to
> parse C. Ideally:
>
>   - `bindgen` would support a GCC backend (requested at [1]),
>
>   - or the Clang driver would be perfectly compatible with GCC,
>     including plugins. Unlikely, of course, but perhaps a big
>     subset of configs may be possible to guarantee to be kept
>     compatible nevertheless.
>
> This is also the reason why GCC builds are very experimental and some
> configurations may not work (e.g. `GCC_PLUGIN_RANDSTRUCT`). However,
> we keep GCC builds working (for some example configs) in the CI
> to avoid diverging/regressing further, so that we are better prepared
> for the future when a solution might become available.
>
> [1] https://github.com/rust-lang/rust-bindgen/issues/1949
>
> Link: https://github.com/Rust-for-Linux/linux/issues/167
> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
> Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
> Co-developed-by: Finn Behrens <me@kloenk.de>
> Signed-off-by: Finn Behrens <me@kloenk.de>
> Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

Patch LGTM; please keep an eye on the series:
https://lore.kernel.org/lkml/20210707224310.1403944-2-ndesaulniers@google.com/

If that lands in kbuild before this, this patch will need to be
rebased to avoid a conflict in linux-next.

So (tentatively :-P):
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>

If the patch needs to be rebased on the series linked above, please
drop my reviewed by tag and I will re-review. Perhaps putting me
explicitly on Cc: in the commit message will help notify me if there
are successive versions?

> ---
>  Makefile | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 0565caea036..6e823d8bd64 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -573,18 +573,23 @@ endif
>  # and from include/config/auto.conf.cmd to detect the compiler upgrade.
>  CC_VERSION_TEXT = $(subst $(pound),,$(shell $(CC) --version 2>/dev/null | head -n 1))
>
> -ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
> +TENTATIVE_CLANG_FLAGS := -Werror=unknown-warning-option
> +
>  ifneq ($(CROSS_COMPILE),)
> -CLANG_FLAGS    += --target=$(notdir $(CROSS_COMPILE:%-=%))
> +TENTATIVE_CLANG_FLAGS  += --target=$(notdir $(CROSS_COMPILE:%-=%))
>  endif
>  ifeq ($(LLVM_IAS),1)
> -CLANG_FLAGS    += -integrated-as
> +TENTATIVE_CLANG_FLAGS  += -integrated-as
>  else
> -CLANG_FLAGS    += -no-integrated-as
> +TENTATIVE_CLANG_FLAGS  += -no-integrated-as
>  GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
> -CLANG_FLAGS    += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
> +TENTATIVE_CLANG_FLAGS  += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
>  endif
> -CLANG_FLAGS    += -Werror=unknown-warning-option
> +
> +export TENTATIVE_CLANG_FLAGS
> +
> +ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
> +CLANG_FLAGS    += $(TENTATIVE_CLANG_FLAGS)
>  KBUILD_CFLAGS  += $(CLANG_FLAGS)
>  KBUILD_AFLAGS  += $(CLANG_FLAGS)
>  export CLANG_FLAGS
> --
> 2.32.0
>


-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds
  2021-07-14 18:13   ` Nick Desaulniers
@ 2021-07-14 18:16     ` Nick Desaulniers
  2021-07-14 20:31     ` Miguel Ojeda
  1 sibling, 0 replies; 70+ messages in thread
From: Nick Desaulniers @ 2021-07-14 18:16 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	clang-built-linux, Nathan Chancellor

On Wed, Jul 14, 2021 at 11:13 AM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> On Sun, Jul 4, 2021 at 1:28 PM <ojeda@kernel.org> wrote:
> >
> > From: Miguel Ojeda <ojeda@kernel.org>
> >
> > To support Rust under GCC-built kernels, we need to save the flags that
> > would have been passed if the kernel was being compiled with Clang.
> >
> > The reason is that `bindgen` -- the tool we use to generate Rust
> > bindings to the C side of the kernel -- relies on `libclang` to
> > parse C. Ideally:
> >
> >   - `bindgen` would support a GCC backend (requested at [1]),
> >
> >   - or the Clang driver would be perfectly compatible with GCC,
> >     including plugins. Unlikely, of course, but perhaps a big
> >     subset of configs may be possible to guarantee to be kept
> >     compatible nevertheless.
> >
> > This is also the reason why GCC builds are very experimental and some
> > configurations may not work (e.g. `GCC_PLUGIN_RANDSTRUCT`). However,
> > we keep GCC builds working (for some example configs) in the CI
> > to avoid diverging/regressing further, so that we are better prepared
> > for the future when a solution might become available.
> >
> > [1] https://github.com/rust-lang/rust-bindgen/issues/1949
> >
> > Link: https://github.com/Rust-for-Linux/linux/issues/167
> > Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> > Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> > Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
> > Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
> > Co-developed-by: Finn Behrens <me@kloenk.de>
> > Signed-off-by: Finn Behrens <me@kloenk.de>
> > Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> > Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> > Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
> > Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> > Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
>
> Patch LGTM; please keep an eye on the series:
> https://lore.kernel.org/lkml/20210707224310.1403944-2-ndesaulniers@google.com/
>
> If that lands in kbuild before this, this patch will need to be
> rebased to avoid a conflict in linux-next.
>
> So (tentatively :-P):
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
>
> If the patch needs to be rebased on the series linked above, please
> drop my reviewed by tag and I will re-review. Perhaps putting me
> explicitly on Cc: in the commit message will help notify me if there
> are successive versions?
>
> > ---
> >  Makefile | 17 +++++++++++------
> >  1 file changed, 11 insertions(+), 6 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index 0565caea036..6e823d8bd64 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -573,18 +573,23 @@ endif
> >  # and from include/config/auto.conf.cmd to detect the compiler upgrade.
> >  CC_VERSION_TEXT = $(subst $(pound),,$(shell $(CC) --version 2>/dev/null | head -n 1))
> >
> > -ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
> > +TENTATIVE_CLANG_FLAGS := -Werror=unknown-warning-option

Also, consider whether `BINDGEN_FLAGS` would be more descriptive (and
less verbose) than `TENTATIVE_CLANG_FLAGS`.

> > +
> >  ifneq ($(CROSS_COMPILE),)
> > -CLANG_FLAGS    += --target=$(notdir $(CROSS_COMPILE:%-=%))
> > +TENTATIVE_CLANG_FLAGS  += --target=$(notdir $(CROSS_COMPILE:%-=%))
> >  endif
> >  ifeq ($(LLVM_IAS),1)
> > -CLANG_FLAGS    += -integrated-as
> > +TENTATIVE_CLANG_FLAGS  += -integrated-as
> >  else
> > -CLANG_FLAGS    += -no-integrated-as
> > +TENTATIVE_CLANG_FLAGS  += -no-integrated-as
> >  GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
> > -CLANG_FLAGS    += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
> > +TENTATIVE_CLANG_FLAGS  += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
> >  endif
> > -CLANG_FLAGS    += -Werror=unknown-warning-option
> > +
> > +export TENTATIVE_CLANG_FLAGS
> > +
> > +ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
> > +CLANG_FLAGS    += $(TENTATIVE_CLANG_FLAGS)
> >  KBUILD_CFLAGS  += $(CLANG_FLAGS)
> >  KBUILD_AFLAGS  += $(CLANG_FLAGS)
> >  export CLANG_FLAGS
> > --
> > 2.32.0
> >
>
>
> --
> Thanks,
> ~Nick Desaulniers



-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-04 20:27 ` [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512 ojeda
@ 2021-07-14 18:20   ` Nick Desaulniers
  2021-07-14 19:04     ` Linus Torvalds
  2021-07-14 20:19     ` Miguel Ojeda
  0 siblings, 2 replies; 70+ messages in thread
From: Nick Desaulniers @ 2021-07-14 18:20 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho

On Sun, Jul 4, 2021 at 1:28 PM <ojeda@kernel.org> wrote:
>
> From: Miguel Ojeda <ojeda@kernel.org>
>
> Rust symbols can become quite long due to namespacing introduced
> by modules, types, traits, generics, etc. For instance, for:
>
>     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

For C++ demangling, we have c++filt.

A quick search turned up: https://github.com/luser/rustfilt

but if the v0 mangling scheme is upcoming, I doubt a repo that hasn't
been updated supports an upcoming scheme.  Is there a more official
equivalent?

Do we demangle rust symbols when printing a trace from a warn/panic?
That would be nice.

>
> 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.
>
> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
> Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
> Co-developed-by: Finn Behrens <me@kloenk.de>
> Signed-off-by: Finn Behrens <me@kloenk.de>
> Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
>  include/linux/kallsyms.h            | 2 +-
>  kernel/livepatch/core.c             | 4 ++--
>  scripts/kallsyms.c                  | 2 +-
>  tools/include/linux/kallsyms.h      | 2 +-
>  tools/include/linux/lockdep.h       | 2 +-
>  tools/lib/perf/include/perf/event.h | 2 +-
>  tools/lib/symbol/kallsyms.h         | 2 +-
>  7 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
> index 465060acc98..5cdc6903abc 100644
> --- a/include/linux/kallsyms.h
> +++ b/include/linux/kallsyms.h
> @@ -14,7 +14,7 @@
>
>  #include <asm/sections.h>
>
> -#define KSYM_NAME_LEN 128
> +#define KSYM_NAME_LEN 512
>  #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
>                          2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
>
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 335d988bd81..73874e5edfd 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -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",
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index bcdabee13aa..9bab5f55ade 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -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;
> diff --git a/tools/include/linux/kallsyms.h b/tools/include/linux/kallsyms.h
> index efb6c3f5f2a..5a37ccbec54 100644
> --- a/tools/include/linux/kallsyms.h
> +++ b/tools/include/linux/kallsyms.h
> @@ -6,7 +6,7 @@
>  #include <stdio.h>
>  #include <unistd.h>
>
> -#define KSYM_NAME_LEN 128
> +#define KSYM_NAME_LEN 512
>
>  struct module;
>
> diff --git a/tools/include/linux/lockdep.h b/tools/include/linux/lockdep.h
> index e56997288f2..d9c163f3ab2 100644
> --- a/tools/include/linux/lockdep.h
> +++ b/tools/include/linux/lockdep.h
> @@ -47,7 +47,7 @@ static inline int debug_locks_off(void)
>
>  #define task_pid_nr(tsk) ((tsk)->pid)
>
> -#define KSYM_NAME_LEN 128
> +#define KSYM_NAME_LEN 512
>  #define printk(...) dprintf(STDOUT_FILENO, __VA_ARGS__)
>  #define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
>  #define pr_warn pr_err
> diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
> index 4d0c02ba3f7..095d60144a7 100644
> --- a/tools/lib/perf/include/perf/event.h
> +++ b/tools/lib/perf/include/perf/event.h
> @@ -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 {
> diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
> index 72ab9870454..542f9b059c3 100644
> --- a/tools/lib/symbol/kallsyms.h
> +++ b/tools/lib/symbol/kallsyms.h
> @@ -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)
> --
> 2.32.0
>


-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/17] docs: add Rust documentation
  2021-07-04 20:27 ` [PATCH 13/17] docs: add Rust documentation ojeda
  2021-07-05  5:02   ` Willy Tarreau
@ 2021-07-14 18:37   ` Nick Desaulniers
  2021-07-14 19:55     ` Miguel Ojeda
  1 sibling, 1 reply; 70+ messages in thread
From: Nick Desaulniers @ 2021-07-14 18:37 UTC (permalink / raw)
  To: ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kbuild,
	linux-doc, linux-kernel, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho,
	Boqun Feng, Sumera Priyadarsini, Michael Ellerman,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Fox Chen,
	Ayaan Zaidi, Douglas Su, Yuki Okushi

On Sun, Jul 4, 2021 at 1:29 PM <ojeda@kernel.org> wrote:
>
> From: Miguel Ojeda <ojeda@kernel.org>
>
> 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.
>
> These documents contain general information that does not fit
> particularly well in the source code, like the Quick Start guide.
>
... snip ...
> +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`` will need to be
> +`configured <https://rust-analyzer.github.io/manual.html#non-cargo-based-projects>`_
> +to work with the kernel by adding a ``rust-project.json`` file in the root folder.
> +A ``rust-project.json`` can be generated by building the Make target ``rust-analyzer``,
> +which will create a ``rust-project.json`` in the root of the output directory.

Is rust-analyzer necessary to talk about? I think most kernel
developers aren't using LSP clients, so it doesn't seem necessary to
talk about for kernel development IMO.  If a developer would like to
use an LSP client, they should refer to the documentation of their LSP
client.



Should Documentation/process/changes.rst be updated to note which
versions of all of these tools are currently supported?


> +     - ``armv6`` and compatible only, ``RUST_OPT_LEVEL >= 2``

For the compat table, for 32b ARM, why is v6 supported but not v7? Why
only when optimizations are enabled?

> +Currently, the Rust compiler (``rustc``) uses LLVM for code generation,
> +which limits the supported architectures we can target. In addition, support
> +for building the kernel with LLVM/Clang varies (see :ref:`kbuild_llvm`),
> +which ``bindgen`` relies on through ``libclang``.

Doesn't this also depend on rustc having support for a given target
triple? Just because LLVM has a backend for a given architecture
doesn't mean rustc can target it, right?
-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-14 18:20   ` Nick Desaulniers
@ 2021-07-14 19:04     ` Linus Torvalds
  2021-07-14 20:09       ` Eric W. Biederman
  2021-07-14 20:19     ` Miguel Ojeda
  1 sibling, 1 reply; 70+ messages in thread
From: Linus Torvalds @ 2021-07-14 19:04 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Miguel Ojeda, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, open list:DOCUMENTATION,
	Linux Kernel Mailing List, Alex Gaynor, Geoffrey Thomas,
	Finn Behrens, Adam Bratschi-Kaye, Wedson Almeida Filho

On Wed, Jul 14, 2021 at 11:20 AM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> Do we demangle rust symbols when printing a trace from a warn/panic?
> That would be nice.

I think it would be pretty much required. Otherwise stack traces are
going to be very very painful.

In fact, I'm starting to think that Willy is right: we should use
hashes for the "real" symbol name, and have demangled names for
printing, and at no point would the kernel actually want or need to
have the nasty mangled names.

(This wouldn't be rust-specific - using hashes for module linking
sounds like a good diea for C code as well, even if the de-mangled
names for printing are then the regular ones)

Anybody interested in looking into that? It would make this "big
kernel symbols" patch immaterial.

             Linus

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/17] docs: add Rust documentation
  2021-07-14 18:37   ` Nick Desaulniers
@ 2021-07-14 19:55     ` Miguel Ojeda
  0 siblings, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-14 19:55 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, Boqun Feng, Sumera Priyadarsini,
	Michael Ellerman, Sven Van Asbroeck, Gary Guo,
	Boris-Chengbiao Zhou, Fox Chen, Ayaan Zaidi, Douglas Su,
	Yuki Okushi

On Wed, Jul 14, 2021 at 8:38 PM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> Is rust-analyzer necessary to talk about? I think most kernel
> developers aren't using LSP clients, so it doesn't seem necessary to
> talk about for kernel development IMO.  If a developer would like to
> use an LSP client, they should refer to the documentation of their LSP
> client.

I think it is fair to advertise it given we have support for
generating its configuration.

Otherwise, people might miss the script and spend time generating a
configuration by hand (which takes quite some time and would not carry
the `CONFIG_*` settings etc.).

And they may start using it if they did not hear about it! :)

> Should Documentation/process/changes.rst be updated to note which
> versions of all of these tools are currently supported?

For the ones required for building, they are already there (i.e.
`rustc` and `bindgen`).

For the rest, most come with the Rust toolchain, so I think there is
no need to list them explicitly. For `rust-analyzer`, it is "rolling",
so it does not make much sense to put it in any case.

> For the compat table, for 32b ARM, why is v6 supported but not v7? Why
> only when optimizations are enabled?

For arch support, we only have a few fixed Rust target files for the
moment as examples (thus we picked v6) -- we will generate those with
a script later on.

For particular restrictions (such as the optimization level), we will
look into solving those bits later on. In any case, it is not a
priority, since less than `-O2` is intended only for kernel hacking.

> Doesn't this also depend on rustc having support for a given target
> triple? Just because LLVM has a backend for a given architecture
> doesn't mean rustc can target it, right?

No -- currently we use custom target files instead of particular
triples (see previous point), which are basically the settings `rustc`
forwards to LLVM for codegen.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-14 19:04     ` Linus Torvalds
@ 2021-07-14 20:09       ` Eric W. Biederman
  2021-07-14 20:21         ` Linus Torvalds
  0 siblings, 1 reply; 70+ messages in thread
From: Eric W. Biederman @ 2021-07-14 20:09 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Nick Desaulniers, Miguel Ojeda, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	open list:DOCUMENTATION, Linux Kernel Mailing List, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

Linus Torvalds <torvalds@linux-foundation.org> writes:

> On Wed, Jul 14, 2021 at 11:20 AM Nick Desaulniers
> <ndesaulniers@google.com> wrote:
>>
>> Do we demangle rust symbols when printing a trace from a warn/panic?
>> That would be nice.
>
> I think it would be pretty much required. Otherwise stack traces are
> going to be very very painful.
>
> In fact, I'm starting to think that Willy is right: we should use
> hashes for the "real" symbol name, and have demangled names for
> printing, and at no point would the kernel actually want or need to
> have the nasty mangled names.
>
> (This wouldn't be rust-specific - using hashes for module linking
> sounds like a good diea for C code as well, even if the de-mangled
> names for printing are then the regular ones)
>
> Anybody interested in looking into that? It would make this "big
> kernel symbols" patch immaterial.

Are you thinking the hashed kernel symbols need to have their types
included in the hash?  Or is this just a hash to make the names a
managable size?

Eric

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-14 18:20   ` Nick Desaulniers
  2021-07-14 19:04     ` Linus Torvalds
@ 2021-07-14 20:19     ` Miguel Ojeda
  1 sibling, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-14 20:19 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Wed, Jul 14, 2021 at 8:20 PM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> For C++ demangling, we have c++filt.
>
> A quick search turned up: https://github.com/luser/rustfilt
>
> but if the v0 mangling scheme is upcoming, I doubt a repo that hasn't
> been updated supports an upcoming scheme.  Is there a more official
> equivalent?

Demangling v0 is already supported by the latest releases of binutils
(2.36) / gdb (10.2), e.g.:

    echo _RNvXNtCshGpAVYOtgW1_7example9my_moduleINtB2_13MyGenericTypeNtB2_6MyTypeENtB2_7MyTrait9my_method
| c++filt -i
    <example::my_module::MyGenericType<example::my_module::MyType> as
example::my_module::MyTrait>::my_method

See the current status at https://github.com/rust-lang/rust/issues/60705.

(which reminds me I have to update the "Hacking" section in the Quick
Start guide, because now the releases I backported the support into
are not needed anymore)

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-14 20:09       ` Eric W. Biederman
@ 2021-07-14 20:21         ` Linus Torvalds
  2021-07-14 20:48           ` Eric W. Biederman
  0 siblings, 1 reply; 70+ messages in thread
From: Linus Torvalds @ 2021-07-14 20:21 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Nick Desaulniers, Miguel Ojeda, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	open list:DOCUMENTATION, Linux Kernel Mailing List, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Wed, Jul 14, 2021 at 1:09 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Are you thinking the hashed kernel symbols need to have their types
> included in the hash?

I think the hash should be the whole mangled name. So yes, for Rust
symbols they'd have the the type information.

>  Or is this just a hash to make the names a managable size?

No, if that was the only point of it, the "just use two bytes for
length" would be simpler.

But I don't think we want to do run-time de-mangling of names in the
kernel when doing stack traces, which implies that the kallsym
information in the kernel should be the de-mangled names.

That makes the names nice and readable, and also makes this "maximum
symbol length" thing a non-issue.

BUT.

It also means that you can't use those names for linking purposes, so
you'd then need to have a "full version" for that. But as Willy
pointed out elsewhere, you might as well just use a constant-sized
hash for that, rather than have both a manged and a de-mangled name.

                   Linus

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds
  2021-07-14 18:13   ` Nick Desaulniers
  2021-07-14 18:16     ` Nick Desaulniers
@ 2021-07-14 20:31     ` Miguel Ojeda
  1 sibling, 0 replies; 70+ messages in thread
From: Miguel Ojeda @ 2021-07-14 20:31 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Miguel Ojeda, Linus Torvalds, Greg Kroah-Hartman, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel,
	Alex Gaynor, Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho, clang-built-linux, Nathan Chancellor

On Wed, Jul 14, 2021 at 8:14 PM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> Patch LGTM; please keep an eye on the series:
> https://lore.kernel.org/lkml/20210707224310.1403944-2-ndesaulniers@google.com/
>
> If that lands in kbuild before this, this patch will need to be
> rebased to avoid a conflict in linux-next.
>
> So (tentatively :-P):
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>

Thanks for the heads up!

Given how fast `rustc_codegen_gcc` is progressing, we may need to
prioritize getting
https://github.com/rust-lang/rust-bindgen/issues/1949 fixed so that we
can drop this hack altogether and go for proper, full GCC support.

> If the patch needs to be rebased on the series linked above, please
> drop my reviewed by tag and I will re-review. Perhaps putting me
> explicitly on Cc: in the commit message will help notify me if there
> are successive versions?

Ack -- will do that.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-14 20:21         ` Linus Torvalds
@ 2021-07-14 20:48           ` Eric W. Biederman
  2021-07-14 22:40             ` Linus Torvalds
  0 siblings, 1 reply; 70+ messages in thread
From: Eric W. Biederman @ 2021-07-14 20:48 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Nick Desaulniers, Miguel Ojeda, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	open list:DOCUMENTATION, Linux Kernel Mailing List, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

Linus Torvalds <torvalds@linux-foundation.org> writes:

> On Wed, Jul 14, 2021 at 1:09 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Are you thinking the hashed kernel symbols need to have their types
>> included in the hash?
>
> I think the hash should be the whole mangled name. So yes, for Rust
> symbols they'd have the the type information.

Sorry I was meaning to ask should the C symbols that get hashed
include their types in the hash as well?  Because if everything
is going to be hashed we need to clear definition of what we do
with good old C symbols as well.

>>  Or is this just a hash to make the names a managable size?
>
> No, if that was the only point of it, the "just use two bytes for
> length" would be simpler.
>
> But I don't think we want to do run-time de-mangling of names in the
> kernel when doing stack traces, which implies that the kallsym
> information in the kernel should be the de-mangled names.
>
> That makes the names nice and readable, and also makes this "maximum
> symbol length" thing a non-issue.
>
> BUT.
>
> It also means that you can't use those names for linking purposes, so
> you'd then need to have a "full version" for that. But as Willy
> pointed out elsewhere, you might as well just use a constant-sized
> hash for that, rather than have both a manged and a de-mangled name.

Just to clarify.  We want this for the C symbols as well?

Eric


^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512
  2021-07-14 20:48           ` Eric W. Biederman
@ 2021-07-14 22:40             ` Linus Torvalds
  0 siblings, 0 replies; 70+ messages in thread
From: Linus Torvalds @ 2021-07-14 22:40 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Nick Desaulniers, Miguel Ojeda, Greg Kroah-Hartman,
	rust-for-linux, Linux Kbuild mailing list,
	open list:DOCUMENTATION, Linux Kernel Mailing List, Alex Gaynor,
	Geoffrey Thomas, Finn Behrens, Adam Bratschi-Kaye,
	Wedson Almeida Filho

On Wed, Jul 14, 2021 at 1:49 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Sorry I was meaning to ask should the C symbols that get hashed
> include their types in the hash as well?  Because if everything
> is going to be hashed we need to clear definition of what we do
> with good old C symbols as well.

Oh, I guess if we wanted to be fancy, we could make the modversion
information be part of the hash.

Because we already have that, and that's kind of what it is. But I
wasn't actually thinking that fancy - I'd leave the C hash as just the
name hash with no type info.

Unless somebody really wants to do that modversions thing. It *would*
be a very natural thing to do in that "link using hashes" world view..

                Linus

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-08  0:58             ` Matthew Wilcox
  2021-07-08  6:39               ` [PATCH 00/17] Rust support, NVMe Geert Stappers
@ 2021-07-22 22:55               ` Wedson Almeida Filho
  2021-07-23  1:17                 ` Matthew Wilcox
  2021-07-23 15:08                 ` [PATCH 00/17] Rust support Keith Busch
  1 sibling, 2 replies; 70+ messages in thread
From: Wedson Almeida Filho @ 2021-07-22 22:55 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Finn Behrens, Greg Kroah-Hartman, Miguel Ojeda,
	Christoph Hellwig, Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

Hey Matthew,

On Thu, Jul 08, 2021 at 01:58:32AM +0100, Matthew Wilcox wrote:
> Why are you so resistant to writing a real driver that deals with actual
> hardware?  

I don't think it was so much resistance but rather a prioritisation thing. Have
you by any chance seen the gpio driver I posted a couple of days ago?

> A simple NVMe driver is less than a thousand lines of C.
> I know the one in the kernel now is ridiculously complicated and has
> been thoroughly messed up with abstractions to support NVMeoF instead
> of having a separate driver, but it's really a simple interface at heart.

The latest NVMe spec is 452 pages long, which seems to contradict your claim
that it's simple. In any case, translating less than 1K lines of C shouldn't be
too hard (after I've built the abstractions, of course). Would you mind sharing
the simple driver you mention above?

Thanks,
-Wedson

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-22 22:55               ` [PATCH 00/17] Rust support Wedson Almeida Filho
@ 2021-07-23  1:17                 ` Matthew Wilcox
  2021-07-23 11:33                   ` [PATCH 00/17] Rust support, GPIO driver Geert Stappers
  2021-07-23 15:08                 ` [PATCH 00/17] Rust support Keith Busch
  1 sibling, 1 reply; 70+ messages in thread
From: Matthew Wilcox @ 2021-07-23  1:17 UTC (permalink / raw)
  To: Wedson Almeida Filho
  Cc: Finn Behrens, Greg Kroah-Hartman, Miguel Ojeda,
	Christoph Hellwig, Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Thu, Jul 22, 2021 at 11:55:58PM +0100, Wedson Almeida Filho wrote:
> Hey Matthew,
> 
> On Thu, Jul 08, 2021 at 01:58:32AM +0100, Matthew Wilcox wrote:
> > Why are you so resistant to writing a real driver that deals with actual
> > hardware?  
> 
> I don't think it was so much resistance but rather a prioritisation thing. Have
> you by any chance seen the gpio driver I posted a couple of days ago?

I haven't seen it, no ...

> > A simple NVMe driver is less than a thousand lines of C.
> > I know the one in the kernel now is ridiculously complicated and has
> > been thoroughly messed up with abstractions to support NVMeoF instead
> > of having a separate driver, but it's really a simple interface at heart.
> 
> The latest NVMe spec is 452 pages long, which seems to contradict your claim
> that it's simple.

As I said, they've put all kinds of crap into NVMe these days.
If you look at the 1.0e spec, it's 127 pages.

> In any case, translating less than 1K lines of C shouldn't be
> too hard (after I've built the abstractions, of course). Would you mind sharing
> the simple driver you mention above?

Unfortunately, most of the early versions were lost during the
kernel.org breakin.  If you check out commit 5da273fe3fd1 and look at
drivers/block/nvme.c, you'll see a driver that's about 2000 lines.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support, GPIO driver
  2021-07-23  1:17                 ` Matthew Wilcox
@ 2021-07-23 11:33                   ` Geert Stappers
  0 siblings, 0 replies; 70+ messages in thread
From: Geert Stappers @ 2021-07-23 11:33 UTC (permalink / raw)
  To: Matthew Wilcox, Wedson Almeida Filho, rust-for-linux,
	Linux Doc Mailing List, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 649 bytes --]

On Fri, Jul 23, 2021 at 02:17:58AM +0100, Matthew Wilcox wrote:
> On Thu, Jul 22, 2021 at 11:55:58PM +0100, Wedson Almeida Filho wrote:
> > Hey Matthew,
> > 
> > On Thu, Jul 08, 2021 at 01:58:32AM +0100, Matthew Wilcox wrote:
> > > Why are you so resistant to writing a real driver that deals with actual
> > > hardware?  
> > 
> > I don't think it was so much resistance but rather a prioritisation thing. Have
> > you by any chance seen the gpio driver I posted a couple of days ago?
> 
> I haven't seen it, no ...

Most likely it is https://lwn.net/Articles/863459/

 

 
Groeten
Geert Stappers
-- 
Silence is hard to parse

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 00/17] Rust support
  2021-07-22 22:55               ` [PATCH 00/17] Rust support Wedson Almeida Filho
  2021-07-23  1:17                 ` Matthew Wilcox
@ 2021-07-23 15:08                 ` Keith Busch
  1 sibling, 0 replies; 70+ messages in thread
From: Keith Busch @ 2021-07-23 15:08 UTC (permalink / raw)
  To: Wedson Almeida Filho
  Cc: Matthew Wilcox, Finn Behrens, Greg Kroah-Hartman, Miguel Ojeda,
	Christoph Hellwig, Miguel Ojeda, Linus Torvalds, rust-for-linux,
	Linux Kbuild mailing list, Linux Doc Mailing List, linux-kernel

On Thu, Jul 22, 2021 at 11:55:58PM +0100, Wedson Almeida Filho wrote:
> On Thu, Jul 08, 2021 at 01:58:32AM +0100, Matthew Wilcox wrote:
> > A simple NVMe driver is less than a thousand lines of C.
> > I know the one in the kernel now is ridiculously complicated and has
> > been thoroughly messed up with abstractions to support NVMeoF instead
> > of having a separate driver, but it's really a simple interface at heart.
> 
> The latest NVMe spec is 452 pages long, which seems to contradict your claim
> that it's simple. In any case, translating less than 1K lines of C shouldn't be
> too hard (after I've built the abstractions, of course). Would you mind sharing
> the simple driver you mention above?

You can use the 1.0 spec, which is much shorter. A 1.0 capable driver
should be forward compatible with newer devices, too.

The current nvme driver became less simple since blk-mq integration and
has only gotten more complicated since then with other transports and
more advanced features. For a simpler example, you can reference an in
kernel version <= 3.16, and ignore the "nvme-scsi" parts.

^ permalink raw reply	[flat|nested] 70+ messages in thread

end of thread, other threads:[~2021-07-23 15:08 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-04 20:27 [PATCH 00/17] Rust support ojeda
2021-07-04 20:27 ` [PATCH 01/17] kallsyms: support big kernel symbols (2-byte lengths) ojeda
2021-07-04 20:52   ` Linus Torvalds
2021-07-04 21:15     ` Miguel Ojeda
2021-07-04 21:28       ` Linus Torvalds
2021-07-04 21:04   ` Matthew Wilcox
2021-07-04 21:17     ` Miguel Ojeda
2021-07-04 21:33       ` Matthew Wilcox
2021-07-04 21:49         ` Matthew Wilcox
2021-07-04 22:07           ` Miguel Ojeda
2021-07-04 22:20         ` Gary Guo
2021-07-04 22:42           ` Matthew Wilcox
2021-07-04 23:14             ` Gary Guo
2021-07-13 18:02             ` Kent Overstreet
2021-07-04 21:20     ` Gary Guo
2021-07-05  4:35       ` Willy Tarreau
2021-07-04 20:27 ` [PATCH 02/17] kallsyms: increase maximum kernel symbol length to 512 ojeda
2021-07-14 18:20   ` Nick Desaulniers
2021-07-14 19:04     ` Linus Torvalds
2021-07-14 20:09       ` Eric W. Biederman
2021-07-14 20:21         ` Linus Torvalds
2021-07-14 20:48           ` Eric W. Biederman
2021-07-14 22:40             ` Linus Torvalds
2021-07-14 20:19     ` Miguel Ojeda
2021-07-04 20:27 ` [PATCH 03/17] Makefile: generate `CLANG_FLAGS` even in GCC builds ojeda
2021-07-14 18:13   ` Nick Desaulniers
2021-07-14 18:16     ` Nick Desaulniers
2021-07-14 20:31     ` Miguel Ojeda
2021-07-04 20:27 ` [PATCH 04/17] vsprintf: add new `%pA` format specifier ojeda
2021-07-07 20:31   ` Nick Desaulniers
2021-07-07 22:33     ` Miguel Ojeda
2021-07-04 20:27 ` [PATCH 05/17] rust: add C helpers ojeda
2021-07-07 10:19   ` Marco Elver
2021-07-09 10:31     ` Marco Elver
2021-07-09 14:32     ` Miguel Ojeda
2021-07-04 20:27 ` [PATCH 06/17] rust: add `compiler_builtins` crate ojeda
2021-07-04 20:27 ` [PATCH 08/17] rust: add `build_error` crate ojeda
2021-07-04 20:27 ` [PATCH 09/17] rust: add `macros` crate ojeda
2021-07-04 20:27 ` [PATCH 11/17] rust: export generated symbols ojeda
2021-07-04 20:27 ` [PATCH 12/17] Kbuild: add Rust support ojeda
2021-07-04 20:27 ` [PATCH 13/17] docs: add Rust documentation ojeda
2021-07-05  5:02   ` Willy Tarreau
2021-07-06  0:06     ` Miguel Ojeda
2021-07-06  2:09       ` Willy Tarreau
2021-07-14 18:37   ` Nick Desaulniers
2021-07-14 19:55     ` Miguel Ojeda
2021-07-04 20:27 ` [PATCH 14/17] samples: add Rust examples ojeda
2021-07-04 20:27 ` [PATCH 15/17] scripts: add `generate_rust_analyzer.py` ojeda
2021-07-05  5:05   ` Willy Tarreau
2021-07-05 23:41     ` Miguel Ojeda
2021-07-04 20:27 ` [PATCH 16/17] MAINTAINERS: Rust ojeda
2021-07-06  0:26   ` Pedro Tammela
2021-07-06 22:14     ` Miguel Ojeda
2021-07-04 23:11 ` [PATCH 00/17] Rust support Miguel Ojeda
2021-07-07  6:43 ` Christoph Hellwig
2021-07-07 12:33   ` Miguel Ojeda
2021-07-07 12:50     ` Greg Kroah-Hartman
2021-07-07 14:07       ` Wedson Almeida Filho
2021-07-07 14:12         ` Christoph Hellwig
2021-07-07 15:02         ` Greg Kroah-Hartman
2021-07-07 20:56           ` Finn Behrens
2021-07-08  0:58             ` Matthew Wilcox
2021-07-08  6:39               ` [PATCH 00/17] Rust support, NVMe Geert Stappers
2021-07-08  8:29                 ` Finn Behrens
2021-07-22 22:55               ` [PATCH 00/17] Rust support Wedson Almeida Filho
2021-07-23  1:17                 ` Matthew Wilcox
2021-07-23 11:33                   ` [PATCH 00/17] Rust support, GPIO driver Geert Stappers
2021-07-23 15:08                 ` [PATCH 00/17] Rust support Keith Busch
2021-07-07 10:51 ` Marco Elver
2021-07-07 11:28   ` Miguel Ojeda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).