Re: [PATCH 00/13] [RFC] Rust support

2021-04-20 Thread Willy Tarreau
On Tue, Apr 20, 2021 at 07:56:18AM +0200, Greg Kroah-Hartman wrote:
> I would LOVE it if some "executives" would see the above presentations,
> because then they would maybe actually fund developers to fix bugs and
> maintain the kernel code, instead of only allowing them to add new
> features.
> 
> Seriously, that's the real problem, that Dmitry's work has exposed, the
> lack of people allowed to do this type of bugfixing and maintenance on
> company time, for something that the company relies on, is a huge issue.
> "executives" feel that they are willing to fund the initial work and
> then "throw it over the wall to the community" once it is merged, and
> then they can forget about it as "the community" will maintain it for
> them for free.  And that's a lie, as Dmitry's work shows.

That's sadly the eternal situation, and I'm suspecting that software
development and maintenance is not identified as a requirement for a
large number of hardware vendors, especially on the consumer side where
margins are lower. A contractor is paid to develop a driver, *sometimes*
to try to mainline it (and the later they engage with the community, the
longer it takes in round trips), and once the code finally gets merged,
all the initial budget is depleted and no more software work will be
done.

Worse, we could imagine kicking unmaintained drivers faster off the
tree, but that would actually help these unscrupulous vendors by
forcing their customers to switch to the new model :-/  And most of
them wouldn't care either if their contributions were refused based
on their track record of not maintaining their code, since they often
see this as a convenience to please their customers and not something
they need (after all, relying on a bogus and vulnerable BSP has never
prevented from selling a device, quite the opposite).

In short, there is a parallel universe where running highly bogus and
vulnerable out-of-tree code seems like the norm and where there is no
sort of care for what is mainlined as it's possibly just made to look
"cool".

We also need to recognize that it's expectable that some vendors are
not willing to engage on supporting a driver for a decade if they
expect their device to last 5 years only, and maybe we should make
some rules clear about mainlining drivers and what to expect for
users (in which case the end of support would be clear and nobody
would be surprised if the driver is removed at the end of its
maintenance, barring a switch to a community maintainer).

Just my two cents,
Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Greg Kroah-Hartman
On Mon, Apr 19, 2021 at 05:24:33PM -0700, Nick Desaulniers wrote:
> On Fri, Apr 16, 2021 at 10:39 AM Willy Tarreau  wrote:
> >
> > resources usage, I'm really not convinced at all it's suited for
> > low-level development. I understand the interest of the experiment
> > to help the language evolve into that direction, but I fear that
> > the kernel will soon be as bloated and insecure as a browser, and
> > that's really not to please me.
> 
> Dunno, I don't think the introduction of Rust made Firefox _more_ insecure.
> https://wiki.mozilla.org/Oxidation#Within_Firefox
> 
> I pray no executives ever see Dmitry Vyukov's 2019 Linux Plumbers Conf
> talk "Reflections on kernel quality, development process and testing."
> https://www.youtube.com/watch?v=iAfrrNdl2f4
> or his 2018 Linux Security Summit talk "Syzbot and the Tale of
> Thousand Kernel Bugs" https://www.youtube.com/watch?v=qrBVXxZDVQY
> (and they're just fuzzing the syscall interface and USB devices.
> Imagine once folks can more easily craft malformed bluetooth and wifi
> packets.)
> 
> I'd imagine the first term that comes to mind for them might be
> "liability."  They are quite sensitive to these vulnerabilities with
> silly names, logos, and websites.  There are many of us that believe
> an incremental approach of introducing a memory safe language to our
> existing infrastructure at the very least to attempt to improve the
> quality of drivers for those that choose to use such tools is a better
> approach.

I would LOVE it if some "executives" would see the above presentations,
because then they would maybe actually fund developers to fix bugs and
maintain the kernel code, instead of only allowing them to add new
features.

Seriously, that's the real problem, that Dmitry's work has exposed, the
lack of people allowed to do this type of bugfixing and maintenance on
company time, for something that the company relies on, is a huge issue.
"executives" feel that they are willing to fund the initial work and
then "throw it over the wall to the community" once it is merged, and
then they can forget about it as "the community" will maintain it for
them for free.  And that's a lie, as Dmitry's work shows.

The world creates new use cases and testing ability all the time, which
exposes bugs that have been around in old code.  Once the bugs are fixed
in that layer of code, the next layer down can finally be tested and
then look, more corner cases of issues.

Rewriting the kernel in another language is not going to fix the
majority of the issues that fuzzing finds here automagically, as that
work has exposed us to things like fault-injection and malicious USB
packets that no language would have saved us from "automatically".  All
of those code paths deal with "unsafe" data that doesn't magically
become "safe" because we switch languages.

And over time, what we have determined is "safe" has changed!  People
forget that only a few years ago have we decided that the kernel now has
to protect userspace programs from malicious hardware.  That's a major
shift in thinking, now data that we used to blindly trust can not be
trusted at all.  And "executives" want us to fix all of those issues for
free, when really it's a major design shift for loads of kernel
subsystems to handle this new threat model.

So yes, please spread that talk around.  Maybe then will we actually get
funding and support to FIX the bugs that those tools test.  Right now,
the primary fixer of those findings are _INTERNS_ as that's all
companies are willing to fund to fix this type of thing.

And don't get me started on the inability for "executives" to fund other
parts of Linux that they rely on, because they want "other companies" to
do it instead.  The tragedy-of-the-commons is a real threat to Linux,
and always has been...

thanks,

greg k-h


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Willy Tarreau
Hi Nick,

On Mon, Apr 19, 2021 at 05:24:33PM -0700, Nick Desaulniers wrote:
> I don't think the introduction of Rust made Firefox _more_ insecure.
> https://wiki.mozilla.org/Oxidation#Within_Firefox

Browsers are human interfaces and do not fundamentally require low
level access to memory/hardware/whatever. They can be written in
about any language, only the resource usage and performance will
make a difference. As such, some were even written in Java or JS
for example.

Operating systems, and particularly drivers *do* require low-level
accesses, and stuff that can hardly be abstracted or understood by
a compiler. You may have to perform two 16-bit reads/writes on a
32-bit MMIO address to perform an operation and the compiler does
not have to know it, just to obey.

> Really, a key point is that a lot of common mistakes in C are compile
> time errors in Rust. I know no "true" kernel dev would make such
> mistakes in C,

Everyone makes mistakes, the level of attention varies over time and
the focus often changes when dealing with build errors. How many time
some of us facing a bug remembered having changed the code very late
after a build error, and being less careful from this point when the
goal changed from "let's do it right" to "let's get this to build" ?

> but is there nothing we can do to help our peers
> writing drivers?  The point is to transfer cost from runtime to
> compile time to avoid costs at runtime; like all of the memory safety
> bugs which are costing our industry.

And do we have stats on the number of logical bugs, some of which are
caused by developers trying to work around compilers' stubbornness ?
For me, personally speaking, they have *increased* over time, usually
trying to avoid some annoying modern gcc warnings, resulting in integer
casts being placed close to string formats, or returns being placed in
switch/case to avoid the fall-through warning, etc. Thus I'm worried that
a non-negligible part of the 70% of bugs caused by memory safety issues
could be replaced with logic bugs to get to the point where the rust
compiler finally accepts to compile the code. It makes me think about
researchers trying to reduce the causes of certain deaths and claiming
to "save lives" while in the end the people they "save" will simply die
from something else.

And I'm not particularly trying to blindly defend C here. I'm complaining
every single day about some of its shortcomings like the vast amount of
UB, stupid type promotion, counter-intuitive operators precedence when
combining bit-ops with arithmetic, limited size of enums, lack of rotate
operator, strict aliasing, or the recourse to asm() statements every 10
lines to do stuff that can hardly be expressed in a way understandable
by a compiler. I'm just seeing that a lot of the griefs I'm having
against C come from the compiler trying to be too smart or too stubborn,
so giving even more of the handle to a compiler doesn't appeal me at all.

In addition, we all know how painful it is to work around compiler bugs
by writing complex code that carefully avoids certain constructs. I'm
wondering if we'll still have that luxury with a stricter compiler, or
if the only response will have to be between "let's disable this driver
that does not compile" or "please force distros to upgrade their
compilers".

But we'll see :-/

Regards,
Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Nick Desaulniers
On Fri, Apr 16, 2021 at 10:39 AM Willy Tarreau  wrote:
>
> resources usage, I'm really not convinced at all it's suited for
> low-level development. I understand the interest of the experiment
> to help the language evolve into that direction, but I fear that
> the kernel will soon be as bloated and insecure as a browser, and
> that's really not to please me.

Dunno, I don't think the introduction of Rust made Firefox _more_ insecure.
https://wiki.mozilla.org/Oxidation#Within_Firefox

I pray no executives ever see Dmitry Vyukov's 2019 Linux Plumbers Conf
talk "Reflections on kernel quality, development process and testing."
https://www.youtube.com/watch?v=iAfrrNdl2f4
or his 2018 Linux Security Summit talk "Syzbot and the Tale of
Thousand Kernel Bugs" https://www.youtube.com/watch?v=qrBVXxZDVQY
(and they're just fuzzing the syscall interface and USB devices.
Imagine once folks can more easily craft malformed bluetooth and wifi
packets.)

I'd imagine the first term that comes to mind for them might be
"liability."  They are quite sensitive to these vulnerabilities with
silly names, logos, and websites.  There are many of us that believe
an incremental approach of introducing a memory safe language to our
existing infrastructure at the very least to attempt to improve the
quality of drivers for those that choose to use such tools is a better
approach.

I think a lot of the current discussion picking nits in syntax, format
of docs, ease of installation, or theoretical memory models for which
no language (not even the one the kernel is implemented in) provides
all rightly should still be added to a revised RFC under "Why not
[Rust]?" but perhaps are severely overlooking the benefits.  A
tradeoff for sure though.

Really, a key point is that a lot of common mistakes in C are compile
time errors in Rust. I know no "true" kernel dev would make such
mistakes in C, but is there nothing we can do to help our peers
writing drivers?  The point is to transfer cost from runtime to
compile time to avoid costs at runtime; like all of the memory safety
bugs which are costing our industry.

Curiously recurring statistics:
https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/
"Microsoft security engineer Matt Miller said that over the last 12
years, around 70 percent of all Microsoft patches were fixes for
memory safety bugs."

https://www.chromium.org/Home/chromium-security/memory-safety
"The Chromium project finds that around 70% of our serious security
bugs are memory safety problems."

https://security.googleblog.com/2021/01/data-driven-security-hardening-in.html
(59% of Critical and High severity vulnerabilities fixed in Android
Security Bulletins in 2019 are classified as "Memory," FWIW)

https://hacks.mozilla.org/2019/02/rewriting-a-browser-component-in-rust/
"If we’d had a time machine and could have written this component in
Rust from the start, 51 (73.9%) of these bugs would not have been
possible."
--
Thanks,
~Nick Desaulniers


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Miguel Ojeda
Hi Nick,

On Mon, Apr 19, 2021 at 10:36 PM Nick Desaulniers
 wrote:
>
> This is a much different process than drafts thrown over the wall.
> What hope do any kernel contributors have to participate in the ISO
> WGs, other than hoping their contributions to a draft foresee/address
> any concerns members of the committee might have?  How do members of
> the ISO WG communicate with folks interested in the outcomes of their
> decisions?

For WG21, several folks write trip reports of each meeting, and you
can check the status of papers in GitHub at
https://github.com/cplusplus/papers/issues.

For WG14, there are way less papers going on. It is more or  less easy
to follow by reading the list of latest additions in the first pages
of the draft, as well as the Editor's Report.

> The two processes are quite different; one doesn't require "joining a
> national body" (which I assume involves some monetary transaction, if
> not for the individual participant, for their employer) for instance.
> (http://www.open-std.org/jtc1/sc22/wg14/www/contributing which links
> to https://www.iso.org/members.html; I wonder if we have kernel
> contributors in those grayed out countries?)

They are indeed very different processes. Being an ISO standard has
advantages and disadvantages.

In any case, I should note that not everyone that goes to the meetings
pays, e.g. some go as guests, some are funded by their country (or the
EU or other organizations), etc.

In fact, the bigger costs, in my experience, are the time commitment
(a week several times a year) and the costs of traveling (before the
pandemic, that is).

Furthermore, contributing proposals does not actually require
attending the meetings nor joining the committee -- some people
contribute to the standards via proxy, i.e. somebody else presents
their proposals in the committee.

> It was always very ironic to me that the most important body of free
> software was subject to decisions made by ISO, for better or for
> worse.  I would think Rust's RFC process would be more accessible to
> kernel developers, modulo the anti-github crowd, but with the Rust's
> community's values in inclusion I'm sure they'd be happy to accomodate
> folks for the RFC process without requiring github.  I'm not sure ISO
> can be as flexible for non-members.

Well, the kernel already ignores the C standard here and there. ;-) In
the end, it is "just" a standard -- the kernel and compilers can do
something else when they need.

> Either way, I think Rust's RFC process is something worth adding to
> the list of benefits under the heading "Why Rust?" in this proposed
> RFC.

The Rust RFC process has indeed upsides. It is very dynamic and easy
to participate, and allows for anybody to easily comment on proposals,
even anonymously. But, for better or worse, does not lead to an ISO
standard (which some people & companies really value, e.g. as
requirements in contracts etc.).

In the end, writing an RFC is similar to writing a paper for ISO. The
bigger differences, as mentioned above, are on the requirements if you
actually want to go there and present the paper yourself and/or if you
want to have voting rights etc.

Personally, I think some ISO policies could be improved for some types
of standards (or at least let WGs relax them to some degree), but...

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Paul E. McKenney
On Mon, Apr 19, 2021 at 01:35:56PM -0700, Nick Desaulniers wrote:
> On Fri, Apr 16, 2021 at 11:47 AM Paul E. McKenney  wrote:
> >
> > On Thu, Apr 15, 2021 at 11:04:37PM -0700, Nick Desaulniers wrote:
> > > On Thu, Apr 15, 2021 at 9:27 PM Boqun Feng  wrote:
> > > >
> > > > But I think the Rust Community still wants to have a good memory model,
> > > > and they are open to any kind of suggestion and input. I think we (LKMM
> > > > people) should really get involved, because the recent discussion on
> > > > RISC-V's atomics shows that if we didn't people might get a "broken"
> > > > design because they thought C11 memory model is good enough:
> > > >
> > > > https://lore.kernel.org/lkml/YGyZPCxJYGOvqYZQ@boqun-archlinux/
> > > >
> > > > And the benefits are mutual: a) Linux Kernel Memory Model (LKMM) is
> > > > defined by combining the requirements of developers and the behavior of
> > > > hardwares, it's pratical and can be a very good input for memory model
> > > > designing in Rust; b) Once Rust has a better memory model, the compiler
> > > > technologies whatever Rust compilers use to suppor the memory model can
> > > > be adopted to C compilers and we can get that part for free.
> > >
> > > Yes, I agree; I think that's a very good approach.  Avoiding the ISO
> > > WG14 is interesting; at least the merits could be debated in the
> > > public and not behind closed doors.
> >
> > WG14 (C) and WG21 (C++) are at least somewhat open.  Here are some of
> > the proposals a few of us have in flight:
> 
> Wow, the working groups have been busy.  Thank you Paul and Boqun (and
> anyone else on thread) for authoring many of the proposals listed
> below.  Looks like I have a lot of reading to do to catch up.

And this is only the proposals relating to low-level concurrency.
There are way more proposals relating to vector processing, GPGPUs,
task-based concurrency, and so on.  Here is the list of papers submitted
thus far this year:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/

> Have any of those been accepted yet, or led to amendments to either
> language's specs?  Where's the best place to track that?

None of them have yet to be accepted.  P1121R2 has been recommended for
Concurrency Technical Specification 2, which is a stepping stone to the
International Standard.  I hope that P1122R2 will follow soon.

> My point has more to do with _participation_.  Rust's RFC process is
> well documented (https://rust-lang.github.io/rfcs/introduction.html)
> and is done via github pull requests[0].
> 
> This is a much different process than drafts thrown over the wall.
> What hope do any kernel contributors have to participate in the ISO
> WGs, other than hoping their contributions to a draft foresee/address
> any concerns members of the committee might have?  How do members of
> the ISO WG communicate with folks interested in the outcomes of their
> decisions?

I participate in ISO SC22 WG21 (C++) and to a lesser extent WG14 (C).
Participation is key.  The various US National Laboratories send quite a
few people, which has a lot to do with these two standards accommodating
their wishes.

> The two processes are quite different; one doesn't require "joining a
> national body" (which I assume involves some monetary transaction, if
> not for the individual participant, for their employer) for instance.
> (http://www.open-std.org/jtc1/sc22/wg14/www/contributing which links
> to https://www.iso.org/members.html; I wonder if we have kernel
> contributors in those grayed out countries?)

Your employer is already a member of WG21 (C++), so there is no ISO
obstacle to participation by you or by your colleagues.  If you contact
me offlist, I would be happy to connect you to your employer's WG21
representative.

> It was always very ironic to me that the most important body of free
> software was subject to decisions made by ISO, for better or for
> worse.  I would think Rust's RFC process would be more accessible to
> kernel developers, modulo the anti-github crowd, but with the Rust's
> community's values in inclusion I'm sure they'd be happy to accomodate
> folks for the RFC process without requiring github.  I'm not sure ISO
> can be as flexible for non-members.

Being a member is not all that necessary.  Yes, at the end of the day,
only national bodies can formally vote, but I have not come across a
case of anyone being barred from discussions, paper submissions, or straw
polls (informal votes used to set direction) due to not being a member.
Given that the national bodies are only permitted to comment on and vote
on finished proposals, you can argue that individuals have more influence.

Similarly, it is not necessary to be personally acquainted with me in
order to get patches into Linux-kernel RCU.

> Either way, I think Rust's RFC process is something worth adding to
> the list of benefits under the heading "Why Rust?" in this proposed
> RFC.

Comparing Rust's process to that of the C or C++ standard 

Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Nick Desaulniers
On Fri, Apr 16, 2021 at 11:47 AM Paul E. McKenney  wrote:
>
> On Thu, Apr 15, 2021 at 11:04:37PM -0700, Nick Desaulniers wrote:
> > On Thu, Apr 15, 2021 at 9:27 PM Boqun Feng  wrote:
> > >
> > > But I think the Rust Community still wants to have a good memory model,
> > > and they are open to any kind of suggestion and input. I think we (LKMM
> > > people) should really get involved, because the recent discussion on
> > > RISC-V's atomics shows that if we didn't people might get a "broken"
> > > design because they thought C11 memory model is good enough:
> > >
> > > https://lore.kernel.org/lkml/YGyZPCxJYGOvqYZQ@boqun-archlinux/
> > >
> > > And the benefits are mutual: a) Linux Kernel Memory Model (LKMM) is
> > > defined by combining the requirements of developers and the behavior of
> > > hardwares, it's pratical and can be a very good input for memory model
> > > designing in Rust; b) Once Rust has a better memory model, the compiler
> > > technologies whatever Rust compilers use to suppor the memory model can
> > > be adopted to C compilers and we can get that part for free.
> >
> > Yes, I agree; I think that's a very good approach.  Avoiding the ISO
> > WG14 is interesting; at least the merits could be debated in the
> > public and not behind closed doors.
>
> WG14 (C) and WG21 (C++) are at least somewhat open.  Here are some of
> the proposals a few of us have in flight:

Wow, the working groups have been busy.  Thank you Paul and Boqun (and
anyone else on thread) for authoring many of the proposals listed
below.  Looks like I have a lot of reading to do to catch up.

Have any of those been accepted yet, or led to amendments to either
language's specs?  Where's the best place to track that?

My point has more to do with _participation_.  Rust's RFC process is
well documented (https://rust-lang.github.io/rfcs/introduction.html)
and is done via github pull requests[0].

This is a much different process than drafts thrown over the wall.
What hope do any kernel contributors have to participate in the ISO
WGs, other than hoping their contributions to a draft foresee/address
any concerns members of the committee might have?  How do members of
the ISO WG communicate with folks interested in the outcomes of their
decisions?

The two processes are quite different; one doesn't require "joining a
national body" (which I assume involves some monetary transaction, if
not for the individual participant, for their employer) for instance.
(http://www.open-std.org/jtc1/sc22/wg14/www/contributing which links
to https://www.iso.org/members.html; I wonder if we have kernel
contributors in those grayed out countries?)

It was always very ironic to me that the most important body of free
software was subject to decisions made by ISO, for better or for
worse.  I would think Rust's RFC process would be more accessible to
kernel developers, modulo the anti-github crowd, but with the Rust's
community's values in inclusion I'm sure they'd be happy to accomodate
folks for the RFC process without requiring github.  I'm not sure ISO
can be as flexible for non-members.

Either way, I think Rust's RFC process is something worth adding to
the list of benefits under the heading "Why Rust?" in this proposed
RFC.

>
> P2055R0 A Relaxed Guide to memory_order_relaxed
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2055r0.pdf
> P0124R7 Linux-Kernel Memory Model (vs. that of C/C++)
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0124r7.html
> P1726R4 Pointer lifetime-end zap
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1726r4.pdf
> 
> https://docs.google.com/document/d/1MfagxTa6H0rTxtq9Oxyh4X53NzKqOt7y3hZBVzO_LMk/edit?usp=sharing
> P1121R2 Hazard Pointers: Proposed Interface and Wording for Concurrency TS 2
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1121r2.pdf
> P1382R1 volatile_load and volatile_store
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1382r1.pdf
> P1122R2 Proposed Wording for Concurrent Data Structures: Read-Copy-Update 
> (RCU)
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1122r2.pdf
> 
> https://docs.google.com/document/d/1MfagxTa6H0rTxtq9Oxyh4X53NzKqOt7y3hZBVzO_LMk/edit?usp=sharing
> P0190R4 Proposal for New memory order consume Definition
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf
> P0750R1 Consume
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0750r1.html

Does wg14 not participate in these discussions? (Or, is there a lot of
overlap between participants in both?)
http://93.90.116.65/JTC1/SC22/WG14/www/docs/ seems like a list of
proposals and meeting minutes, but all of the above links look like
WG21.  The model of decisions being made for C++ then trickling down
to C is definitely curious.  Though perhaps for the topics of memory
orderings there's enough overlap between the two languages for it not
to matter.

>
> 

Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Linus Torvalds
On Mon, Apr 19, 2021 at 11:38 AM Paolo Bonzini  wrote:
>
> It changes it for the worse, in that access to fields that are shared
> across threads *must* either use atomic types

Well, we won't be using those broken types in the core kernel, so that
would all be entirely on the Rust side.

And I don't expect the Rust side to do a lot of non-locked accesses,
which presumably shouldn't need any of this anyway.

If Rust code ends up accessing actual real kernel data structures with
memory ordering, then that will be to types that do *not* follow the
useless C++ atomics, and that in turn presumably means that it will be
done as "unsafe" helpers that do what the LKMM does (ie READ_ONCE()
and all the rest of it).

 Linus


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Paolo Bonzini

On 19/04/21 19:14, Linus Torvalds wrote:

On Mon, Apr 19, 2021 at 2:36 AM Peter Zijlstra  wrote:


I also don't see how this is better than seq_cst.

But yes, not broken, but also very much not optimal.


I continue to feel like kernel people should just entirely ignore the
C++ memory ordering standard.

It's inferior to what we already have, and simply not helpful. It
doesn't actually solve any problems as far as the kernel is concerned,
and it generates its own set of issues (ie assuming that the compiler
supports it, and assuming the compiler gets it right).

The really subtle cases that it could have been helpful for (eg RCU,
or the load-store control dependencies) were _too_ subtle for the
standard.

And I do not believe Rust changes _any_ of that.


It changes it for the worse, in that access to fields that are shared 
across threads *must* either use atomic types (which boil down to the 
same compiler intrinsics as the C/C++ memory model) or synchronization 
primitives.  LKMM operates in the grey area between the C standard and 
what gcc/clang actually implement, but there's no such grey area in Rust 
unless somebody wants to rewrite arch/*/asm atomic access primitives and 
memory barriers in Rust.


Of course it's possible to say Rust code just uses the C/C++/Rust model 
and C code follows the LKMM, but that really only delays the inevitable 
until a driver is written part in C part in Rust, and needs to perform 
accesses outside synchronization primitives.


Paolo


Any kernel Rust code will simply have to follow the LKMM rules, and
use the kernel model for the interfaces. Things like the C++ memory
model is simply not _relevant_ to the kernel.




Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Linus Torvalds
On Mon, Apr 19, 2021 at 2:36 AM Peter Zijlstra  wrote:
>
> I also don't see how this is better than seq_cst.
>
> But yes, not broken, but also very much not optimal.

I continue to feel like kernel people should just entirely ignore the
C++ memory ordering standard.

It's inferior to what we already have, and simply not helpful. It
doesn't actually solve any problems as far as the kernel is concerned,
and it generates its own set of issues (ie assuming that the compiler
supports it, and assuming the compiler gets it right).

The really subtle cases that it could have been helpful for (eg RCU,
or the load-store control dependencies) were _too_ subtle for the
standard.

And I do not believe Rust changes _any_ of that.

Any kernel Rust code will simply have to follow the LKMM rules, and
use the kernel model for the interfaces. Things like the C++ memory
model is simply not _relevant_ to the kernel.

 Linus


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Will Deacon
On Mon, Apr 19, 2021 at 11:40:54AM +0200, Paolo Bonzini wrote:
> On 19/04/21 11:36, Peter Zijlstra wrote:
> > On Mon, Apr 19, 2021 at 11:02:12AM +0200, Paolo Bonzini wrote:
> > > > void writer(void)
> > > > {
> > > >   atomic_store_explicit(, seq+1, memory_order_relaxed);
> > > >   atomic_thread_fence(memory_order_acquire);
> > > 
> > > This needs to be memory_order_release.  The only change in the resulting
> > > assembly is that "dmb ishld" becomes "dmb ish", which is not as good as 
> > > the
> > > "dmb ishst" you get from smp_wmb() but not buggy either.
> > 
> > Yuck! And that is what requires the insides to be
> > atomic_store_explicit(), otherwise this fence doesn't have to affect
> > them.
> 
> Not just that, even the write needs to be atomic_store_explicit in order to
> avoid a data race.atomic_store_explicit

https://wg21.link/P0690

was an attempt to address this, but I don't know if any of the ideas got
adopted in the end.

Will


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Paolo Bonzini

On 19/04/21 11:36, Peter Zijlstra wrote:

On Mon, Apr 19, 2021 at 11:02:12AM +0200, Paolo Bonzini wrote:

void writer(void)
{
  atomic_store_explicit(, seq+1, memory_order_relaxed);
  atomic_thread_fence(memory_order_acquire);


This needs to be memory_order_release.  The only change in the resulting
assembly is that "dmb ishld" becomes "dmb ish", which is not as good as the
"dmb ishst" you get from smp_wmb() but not buggy either.


Yuck! And that is what requires the insides to be
atomic_store_explicit(), otherwise this fence doesn't have to affect
them.


Not just that, even the write needs to be atomic_store_explicit in order 
to avoid a data race.atomic_store_explicit



I also don't see how this is better than seq_cst.


It is better than seq_cst on TSO architectures.  Another possibility is 
to use release stores for everything (both increments and the stores 
between them).



But yes, not broken, but also very much not optimal.


Agreed on that, just like RCU/memory_order_consume.

Paolo



Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Peter Zijlstra
On Mon, Apr 19, 2021 at 11:02:12AM +0200, Paolo Bonzini wrote:
> > void writer(void)
> > {
> >  atomic_store_explicit(, seq+1, memory_order_relaxed);
> >  atomic_thread_fence(memory_order_acquire);
> 
> This needs to be memory_order_release.  The only change in the resulting
> assembly is that "dmb ishld" becomes "dmb ish", which is not as good as the
> "dmb ishst" you get from smp_wmb() but not buggy either.

Yuck! And that is what requires the insides to be
atomic_store_explicit(), otherwise this fence doesn't have to affect
them.

I also don't see how this is better than seq_cst.

But yes, not broken, but also very much not optimal.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Paolo Bonzini

On 19/04/21 10:26, Peter Zijlstra wrote:

On Mon, Apr 19, 2021 at 09:53:06AM +0200, Paolo Bonzini wrote:

On 19/04/21 09:32, Peter Zijlstra wrote:

On Sat, Apr 17, 2021 at 04:51:58PM +0200, Paolo Bonzini wrote:

On 16/04/21 09:09, Peter Zijlstra wrote:

Well, the obvious example would be seqlocks. C11 can't do them


Sure it can.  C11 requires annotating with (the equivalent of) READ_ONCE all
reads of seqlock-protected fields, but the memory model supports seqlocks
just fine.


How does that help?

IIRC there's two problems, one on each side the lock. On the write side
we have:

seq++;
smp_wmb();
X = r;
Y = r;
smp_wmb();
seq++;

Which C11 simply cannot do right because it does't have wmb.


It has atomic_thread_fence(memory_order_release), and
atomic_thread_fence(memory_order_acquire) on the read side.


https://godbolt.org/z/85xoPxeE5

void writer(void)
{
 atomic_store_explicit(, seq+1, memory_order_relaxed);
 atomic_thread_fence(memory_order_acquire);


This needs to be memory_order_release.  The only change in the resulting 
assembly is that "dmb ishld" becomes "dmb ish", which is not as good as 
the "dmb ishst" you get from smp_wmb() but not buggy either.


The read side can use "dmb ishld" so it gets the same code as Linux.

LWN needs a "C11 memory model for kernel folks" article.  In the 
meanwhile there is 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0124r4.html 
which is the opposite (Linux kernel memory model for C11 folks).


Paolo



 X = 1;
 Y = 2;

 atomic_store_explicit(, seq+1, memory_order_release);
}

gives:

writer:
 adrpx1, .LANCHOR0
 add x0, x1, :lo12:.LANCHOR0
 ldr w2, [x1, #:lo12:.LANCHOR0]
 add w2, w2, 1
 str w2, [x0]
 dmb ishld
 ldr w1, [x1, #:lo12:.LANCHOR0]
 mov w3, 1
 mov w2, 2
 stp w3, w2, [x0, 4]
 add w1, w1, w3
 stlrw1, [x0]
 ret

Which, afaict, is completely buggered. What it seems to be doing is
turning the seq load into a load-acquire, but what we really need is to
make sure the seq store (increment) is ordered before the other stores.






Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Peter Zijlstra
On Mon, Apr 19, 2021 at 10:26:57AM +0200, Peter Zijlstra wrote:

> https://godbolt.org/z/85xoPxeE5

That wants _Atomic on the seq definition for clang.

> void writer(void)
> {
> atomic_store_explicit(, seq+1, memory_order_relaxed);
> atomic_thread_fence(memory_order_acquire);
> 
> X = 1;
> Y = 2;
> 
> atomic_store_explicit(, seq+1, memory_order_release);
> }
> 
> gives:
> 
> writer:
> adrpx1, .LANCHOR0
> add x0, x1, :lo12:.LANCHOR0
> ldr w2, [x1, #:lo12:.LANCHOR0]
> add w2, w2, 1
> str w2, [x0]
> dmb ishld
> ldr w1, [x1, #:lo12:.LANCHOR0]
> mov w3, 1
> mov w2, 2
> stp w3, w2, [x0, 4]
> add w1, w1, w3
> stlrw1, [x0]
> ret
> 
> Which, afaict, is completely buggered. What it seems to be doing is
> turning the seq load into a load-acquire, but what we really need is to
> make sure the seq store (increment) is ordered before the other stores.

Put differently, what you seem to want is store-acquire, but there ain't
no such thing.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Peter Zijlstra
On Mon, Apr 19, 2021 at 09:53:06AM +0200, Paolo Bonzini wrote:
> On 19/04/21 09:32, Peter Zijlstra wrote:
> > On Sat, Apr 17, 2021 at 04:51:58PM +0200, Paolo Bonzini wrote:
> > > On 16/04/21 09:09, Peter Zijlstra wrote:
> > > > Well, the obvious example would be seqlocks. C11 can't do them
> > > 
> > > Sure it can.  C11 requires annotating with (the equivalent of) READ_ONCE 
> > > all
> > > reads of seqlock-protected fields, but the memory model supports seqlocks
> > > just fine.
> > 
> > How does that help?
> > 
> > IIRC there's two problems, one on each side the lock. On the write side
> > we have:
> > 
> > seq++;
> > smp_wmb();
> > X = r;
> > Y = r;
> > smp_wmb();
> > seq++;
> > 
> > Which C11 simply cannot do right because it does't have wmb.
> 
> It has atomic_thread_fence(memory_order_release), and
> atomic_thread_fence(memory_order_acquire) on the read side.

https://godbolt.org/z/85xoPxeE5

void writer(void)
{
atomic_store_explicit(, seq+1, memory_order_relaxed);
atomic_thread_fence(memory_order_acquire);

X = 1;
Y = 2;

atomic_store_explicit(, seq+1, memory_order_release);
}

gives:

writer:
adrpx1, .LANCHOR0
add x0, x1, :lo12:.LANCHOR0
ldr w2, [x1, #:lo12:.LANCHOR0]
add w2, w2, 1
str w2, [x0]
dmb ishld
ldr w1, [x1, #:lo12:.LANCHOR0]
mov w3, 1
mov w2, 2
stp w3, w2, [x0, 4]
add w1, w1, w3
stlrw1, [x0]
ret

Which, afaict, is completely buggered. What it seems to be doing is
turning the seq load into a load-acquire, but what we really need is to
make sure the seq store (increment) is ordered before the other stores.




Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Paolo Bonzini

On 19/04/21 09:32, Peter Zijlstra wrote:

On Sat, Apr 17, 2021 at 04:51:58PM +0200, Paolo Bonzini wrote:

On 16/04/21 09:09, Peter Zijlstra wrote:

Well, the obvious example would be seqlocks. C11 can't do them


Sure it can.  C11 requires annotating with (the equivalent of) READ_ONCE all
reads of seqlock-protected fields, but the memory model supports seqlocks
just fine.


How does that help?

IIRC there's two problems, one on each side the lock. On the write side
we have:

seq++;
smp_wmb();
X = r;
Y = r;
smp_wmb();
seq++;

Which C11 simply cannot do right because it does't have wmb.


It has atomic_thread_fence(memory_order_release), and 
atomic_thread_fence(memory_order_acquire) on the read side.



You end up
having to use seq_cst for the first wmb or make both X and Y (on top of
the last seq) a store-release, both options are sub-optimal.


seq_cst (except for the fence which is just smp_mb) is a pile of manure, 
no doubt about that. :)


Paolo



Re: [PATCH 00/13] [RFC] Rust support

2021-04-19 Thread Peter Zijlstra
On Sat, Apr 17, 2021 at 04:51:58PM +0200, Paolo Bonzini wrote:
> On 16/04/21 09:09, Peter Zijlstra wrote:
> > Well, the obvious example would be seqlocks. C11 can't do them
> 
> Sure it can.  C11 requires annotating with (the equivalent of) READ_ONCE all
> reads of seqlock-protected fields, but the memory model supports seqlocks
> just fine.

How does that help?

IIRC there's two problems, one on each side the lock. On the write side
we have:

seq++;
smp_wmb();
X = r;
Y = r;
smp_wmb();
seq++;

Which C11 simply cannot do right because it does't have wmb. You end up
having to use seq_cst for the first wmb or make both X and Y (on top of
the last seq) a store-release, both options are sub-optimal.

On the read side you get:

do {
  s = seq;
  smp_rmb();
  r1 = X;
  r2 = Y;
  smp_rmb();
} while ((s&1) || seq != s);

And then you get into trouble the last barrier, so the first seq load
can be load-acquire, after which the loads of X, Y come after, but you
need then to happen before the second seq load, for which you then need
seq_cst, or make X and Y load-acquire. Again, not optimal.

I have also seen *many* broken variants of it on the web. Some work on
x86 but are totally broken when you build them on LL/SC ARM64.



Re: [PATCH 00/13] [RFC] Rust support

2021-04-18 Thread Wedson Almeida Filho
On Sat, Apr 17, 2021 at 04:21:27PM +0200, Willy Tarreau wrote:
> Well, I can't express how much I hate abstractions because I constantly
> need to know what it's doing under the hood, and I spend my time reading
> the output asm code because I always want to confirm my assumptions about
> the compiler not cheating on me (and not hitting one of its bugs),
> especially after C compilers have become so smart that they completely
> replace your code with what they think is better for you, (including
> nothing),

I understand the feeling. One thing I can say about the abstractions we've been
talking about is that they're zero-cost. So you'd still have the ability to
inspect generated code and relate that to source, although it would still be
subject to optimisations like C (or perhaps more optimisations as the compiler
knows more about the code).

> so I guess all of this is really not for someone like me.

This may indeed be the case. But I'd invite you to try it out for yourself
anyway before discounting it. I used to hate destructors in C++ because they
were called implicitly: C was king because I had full control. Now I find myself
publicly backing Rust. I feel the advantages outweigh the cost.

> However while I'm pretty sure that based on our respective experiences
> we'd probably disagree forever on a wide number of approaches when it
> comes to deciding whether the developer or the compiler should have the
> last say, I sincerely appreciate that you take the time to calmly explain
> your differing views and the rationale behind, so many thanks for this!

Thank you. I also appreciate your willingness to engage with us.

Cheers,
-Wedson


Re: [PATCH 00/13] [RFC] Rust support

2021-04-18 Thread Wedson Almeida Filho
On Wed, Apr 14, 2021 at 09:09:53PM +0100, Matthew Wilcox wrote:
> By the way, I don't think that Rust necessarily has to conform to the
> current way that Linux works.  If this prompted us to track the current
> context (inside spinlock, handling interrupt, performing writeback, etc)
> and do away with (some) GFP flags, that's not the end of the world.
> We're already moving in that direction to a certain extent with the
> scoped memory allocation APIs to replace GFP_NOFS / GFP_NOIO.

I hadn't myself considered this option but it looks enticing to me. Do you have
a sense of which GFP flags we wouldn't be able to obviate even if we did track
state?


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Richard Weinberger
On Thu, Apr 15, 2021 at 2:41 AM  wrote:
> Regarding compilers, we support Clang-built kernels as well as
> `LLVM=1` builds where possible (i.e. as long as supported by
> the ClangBuiltLinux project). We also maintain some configurations
> of GCC-built kernels working, but they are not intended to be used
> at the present time. Having a `bindgen` backend for GCC would be
> ideal to improve support for those builds.

Sp this effectively means gcc is a second class citizen and even if
gcc is supported
at some point one needs a super recent gcc *and* rust toolchain to build
a rust-enabeled kernel?
I understand that this is right now not a big deal, but as soon a
non-trival subsystem
is rust-only people are forced to upgrade.

Don't get me wrong, I'm all for having rust support in Linux.
But I'm a bit worried about new dependencies on compiler toolchains.
As someone who works a lot with long supported embedded systems I learned that
as soon an application gains a hard dependency on clang or rust I'm in trouble.

-- 
Thanks,
//richard


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Miguel Ojeda
On Sat, Apr 17, 2021 at 4:21 PM Willy Tarreau  wrote:
>
> Well, I can't express how much I hate abstractions because I constantly
> need to know what it's doing under the hood, and I spend my time reading
> the output asm code because I always want to confirm my assumptions about
> the compiler not cheating on me (and not hitting one of its bugs),
> especially after C compilers have become so smart that they completely
> replace your code with what they think is better for you, (including
> nothing), so I guess all of this is really not for someone like me.

Concerning compiler bugs etc.: as you mention, nowadays that applies
to both C and Rust.

Manually inspecting the output asm does not really scale anymore
because we need to worry about all compiler versions out there,
including future ones, for both GCC and Clang.

So we would need to disable optimizations, or reduce the set of
supported compiler versions, or automatically check the generated asm
(like in the compiler's own test suites), or keep binary blobs after
checking (like in some safety-critical domains), etc.

Since none of those are really doable for us (except perhaps for small
subsets of code or unit tests), we need other ways to help with this.
Rust provides several here. For instance, the UB-less subset means
less surprises and less double-checking if some particular construct
is UB and may give problems later on.

Similarly, Rust is actually more explicit in many cases than C, to
reduce surprises further. For instance, regarding implicit type
conversions, none of these compile:

fn f1(n: i32) -> i64 { n }
fn f2(n: i32, m: i64) { n + m; }
fn f3(b: bool) -> i32 { b }
fn f4(n: i32) -> bool { n }
fn f5(n: i32) -> i32 { if n { 42 } else { 53 } }

Building abstractions also helps to ensure you get the semantics you
want in the face of smart optimizers -- rather than the opposite. For
instance, continuing with the integer examples, you may use a
`NonZeroU32`. Or a `Wrapping` for intentional wrapping integer
arithmetic, etc.

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Paolo Bonzini

On 16/04/21 17:58, Theodore Ts'o wrote:

Another fairly common use case is a lockless, racy test of a
particular field, as an optimization before we take the lock before we
test it for realsies.  In this particular case, we can't allocate
memory while holding a spinlock, so we check to see without taking the
spinlock to see whether we should allocate memory (which is expensive,
and unnecessasry most of the time):

alloc_transaction:
/*
 * This check is racy but it is just an optimization of allocating new
 * transaction early if there are high chances we'll need it. If we
 * guess wrong, we'll retry or free the unused transaction.
 */
if (!data_race(journal->j_running_transaction)) {
/*
 * If __GFP_FS is not present, then we may be being called from
 * inside the fs writeback layer, so we MUST NOT fail.
 */
if ((gfp_mask & __GFP_FS) == 0)
gfp_mask |= __GFP_NOFAIL;
new_transaction = kmem_cache_zalloc(transaction_cache,
gfp_mask);
if (!new_transaction)
return -ENOMEM;
}


From my limited experience with Rust, things like these are a bit 
annoying indeed, sooner or later Mutex<> just doesn't cut it and you 
have to deal with its limitations.


In this particular case you would use an AtomicBool field, place it 
outside the Mutex-protected struct, and make sure that is only accessed 
under the lock just like in C.
One easy way out is to make the Mutex protect (officially) nothing, i.e. 
Mutex<()>, and handle the mutable fields yourself using RefCell (which 
gives you run-time checking but has some some space cost) or UnsafeCell 
(which is unsafe as the name says).  Rust makes it pretty easy to write 
smart pointers (Mutex<>'s lock guard itself is a smart pointer) so you 
also have the possibility of writing a safe wrapper for the combination 
of Mutex<()> and UnsafeCell.


Another example is when yu have a list of XYZ objects and use the same 
mutex for both the list of XYZ and a field in struct XYZ.  You could 
place that field in an UnsafeCell and write a function that receives a 
guard for the list lock and returns the field, or something like that. 
It *is* quite ugly though.


As an aside, from a teaching standpoint associating a Mutex with a 
specific data structure is bad IMNSHO, because it encourages too 
fine-grained locking.  Sometimes the easiest path to scalability is to 
use a more coarse lock and ensure that contention is extremely rare. 
But it does work for most simple use cases (and device drivers would 
qualify as simple more often than not).


Paolo



Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Paolo Bonzini

On 16/04/21 09:09, Peter Zijlstra wrote:

Well, the obvious example would be seqlocks. C11 can't do them


Sure it can.  C11 requires annotating with (the equivalent of) READ_ONCE 
all reads of seqlock-protected fields, but the memory model supports 
seqlocks just fine.



Simlar thing for RCU; C11 can't optimally do that


Technically if you know what you're doing (i.e. that you're not on 
Alpha) you can do RCU using a relaxed load followed by an 
atomic_signal_fence(memory_order_consume).  Which I agree is horrible 
and not entirely within the standard, but it works in practice.  The 
Linux implementation of memory barriers, atomic RMW primitives, 
load-acquire/store-release etc. is also completely outside the standard, 
so it's not much different and more portable.


The only thing that I really, really miss when programming with C11 
atomics is smp_mb__{before,after}_atomic().


Paolo



Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Willy Tarreau
On Sat, Apr 17, 2021 at 04:24:43PM +0200, Peter Zijlstra wrote:
> On Sat, Apr 17, 2021 at 01:46:23PM +0200, Willy Tarreau wrote:
> > For me the old trick of casting one side as long long still works:
> > 
> >   unsigned long long mul3264(unsigned int a, unsigned int b)
> >   {
> > return (unsigned long long)a * b;
> >   }
> > 
> > i386:
> >    :
> >  0: 8b 44 24 08   mov0x8(%esp),%eax
> >  4: f7 64 24 04   mull   0x4(%esp)
> >  8: c3ret
> > 
> > x86_64:
> >    :
> >  0: 89 f8 mov%edi,%eax
> >  2: 89 f7 mov%esi,%edi
> >  4: 48 0f af c7   imul   %rdi,%rax
> >  8: c3retq   
> > 
> > Or maybe you had something else in mind ?
> 
> Last time I tried it, the thing refused :/ which is how we ended up with
> mul_u32_u32() in asm.

Oh I trust you, I do remember having noticed it on one gcc version as
well (maybe 4.5). But I've been successfully using this since 2.95, and
could quickly recheck that 4.7, 4.8, 5.4, 6.5, 7.4, 9.3 and 11-trunk do
produce the code above, which is reassuring, as we all prefer to limit
the amount of asm statements.

Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Peter Zijlstra
On Sat, Apr 17, 2021 at 01:46:23PM +0200, Willy Tarreau wrote:
> For me the old trick of casting one side as long long still works:
> 
>   unsigned long long mul3264(unsigned int a, unsigned int b)
>   {
> return (unsigned long long)a * b;
>   }
> 
> i386:
>    :
>  0: 8b 44 24 08   mov0x8(%esp),%eax
>  4: f7 64 24 04   mull   0x4(%esp)
>  8: c3ret
> 
> x86_64:
>    :
>  0: 89 f8 mov%edi,%eax
>  2: 89 f7 mov%esi,%edi
>  4: 48 0f af c7   imul   %rdi,%rax
>  8: c3retq   
> 
> Or maybe you had something else in mind ?

Last time I tried it, the thing refused :/ which is how we ended up with
mul_u32_u32() in asm.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Willy Tarreau
On Sat, Apr 17, 2021 at 02:53:10PM +0100, Wedson Almeida Filho wrote:
> > > Note that this is
> > > another area where Rust offers advantages: read-only guards (in C, if you 
> > > take a
> > > read lock, nothing prevents you from making changes to fields you should 
> > > only be
> > > allowed to read);
> > 
> > But I'm happily doing that when I know what I'm doing. What you call a
> > read lock usually is in fact a shared lock as opposed to an exclusive
> > lock (generally used for writes). For me it's perfectly valid to perform
> > atomic writes under a read lock instead of forcing everyone to wait by
> > taking a write lock. You may for example take a read lock on a structure
> > to make sure that a field you're accessing in it points to stable memory
> > that is only modified under the write lock, but the pointer itself is
> > atomically accessed and swapped under the read lock.
> 
> Yes, this is a great example. Also easily expressible in Rust: they have this
> concept of interior mutability where certain types allow their contents to be
> modified even when shared immutably. Atomics offer such interior mutability, 
> so
> the scenario you describe is fine.
> 
> Rust in fact has an extra enforcement here that C doesn't: it requires 
> interior
> mutability for this scenario to be allowed, so you can't do it with a plain
> naked type (say u64) -- you'd need to use something like an atomic64_t, where
> you're required to specify memory ordering when accessing them.
> 
> In C we of course have atomics but the compiler never alerts us for when we 
> need
> them.

OK thanks for explaining.

> > > In fact, this is also an advantage of Rust. It would *force* developers to
> > > lock/unlock the RCU lock before they can access the protected data.
> > 
> > I'm really afraid by languages which force developers to do this or that.
> 
> When I say that Rust forces developers to do certain things, it's to provide 
> the
> compile-time safety guarantees. Some of these requirements are imposed by our
> own abstractions -- we can always revisit and try to improve them. In cases 
> when
> the abstractions cannot be further refined, developers always have the escape
> hatch of unsafety, where they're allowed to do pretty much everything as in C,
> but then they also give up the compile-time guarantees for those parts.

Well, I can't express how much I hate abstractions because I constantly
need to know what it's doing under the hood, and I spend my time reading
the output asm code because I always want to confirm my assumptions about
the compiler not cheating on me (and not hitting one of its bugs),
especially after C compilers have become so smart that they completely
replace your code with what they think is better for you, (including
nothing), so I guess all of this is really not for someone like me.

However while I'm pretty sure that based on our respective experiences
we'd probably disagree forever on a wide number of approaches when it
comes to deciding whether the developer or the compiler should have the
last say, I sincerely appreciate that you take the time to calmly explain
your differing views and the rationale behind, so many thanks for this!

Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Wedson Almeida Filho
On Fri, Apr 16, 2021 at 06:14:44PM +0200, Willy Tarreau wrote:

> But will this remain syntactically readable/writable by mere humans ?

I would certainly hope so.

> > Note that this is
> > another area where Rust offers advantages: read-only guards (in C, if you 
> > take a
> > read lock, nothing prevents you from making changes to fields you should 
> > only be
> > allowed to read);
> 
> But I'm happily doing that when I know what I'm doing. What you call a
> read lock usually is in fact a shared lock as opposed to an exclusive
> lock (generally used for writes). For me it's perfectly valid to perform
> atomic writes under a read lock instead of forcing everyone to wait by
> taking a write lock. You may for example take a read lock on a structure
> to make sure that a field you're accessing in it points to stable memory
> that is only modified under the write lock, but the pointer itself is
> atomically accessed and swapped under the read lock.

Yes, this is a great example. Also easily expressible in Rust: they have this
concept of interior mutability where certain types allow their contents to be
modified even when shared immutably. Atomics offer such interior mutability, so
the scenario you describe is fine.

Rust in fact has an extra enforcement here that C doesn't: it requires interior
mutability for this scenario to be allowed, so you can't do it with a plain
naked type (say u64) -- you'd need to use something like an atomic64_t, where
you're required to specify memory ordering when accessing them.

In C we of course have atomics but the compiler never alerts us for when we need
them.

> > In fact, this is also an advantage of Rust. It would *force* developers to
> > lock/unlock the RCU lock before they can access the protected data.
> 
> I'm really afraid by languages which force developers to do this or that.

When I say that Rust forces developers to do certain things, it's to provide the
compile-time safety guarantees. Some of these requirements are imposed by our
own abstractions -- we can always revisit and try to improve them. In cases when
the abstractions cannot be further refined, developers always have the escape
hatch of unsafety, where they're allowed to do pretty much everything as in C,
but then they also give up the compile-time guarantees for those parts.


RE: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread David Laight
From: Peter Zijlstra
> Sent: 17 April 2021 12:17
...
> > (i'd argue this is C being broken; promoting only as far as int, when
> > assigning to an unsigned long is Bad, but until/unless either GCC fixes
> > that or the language committee realises that being stuck in the 1970s
> > is Bad, people are going to keep making this kind of mistake)
> 
> Well, I think the rules actually make sense, at the point in the syntax
> tree where + happens, we have 'unsigned char' and 'int', so at that
> point we promote to 'int'. Subsequently 'int' gets shifted and bad
> things happen.

The 1970s were fine.
K C was sign preserving - so 'unsigned char' promoted to 'unsigned int'.
The ANSI C committee broke things by changing it to value preserving
with the strong preference for signed types.

Even with ANSI C the type of ((unsigned char)x + 1) can be unsigned!
All it needs as an architecture where sizeof (int) == 1.
(sizeof (char) has to be 1 - even though that isn't directly explicit.)

Of course, having 32-bit 'char' and 'int' does give problems with
the value for EOF.

David

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



Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Wedson Almeida Filho
On Fri, Apr 16, 2021 at 04:03:07PM +0100, Matthew Wilcox wrote:
> Well, we could do that in C too.
> 
> struct unlocked_inode {
>   spinlock_t i_lock;
> };
> 
> struct locked_inode {
>   spinlock_t i_lock;
>   unsigned short i_bytes;
>   blkcnt_t i_blocks;
> };
> 
> struct locked_inode *lock_inode(struct unlocked_inode *inode)
> {
>   spin_lock(>i_lock);
>   return (struct locked_inode *)inode;
> }

Indeed you can do this kind of thing in C, but as I said before (apologies if
I'm too repetitive on this) Rust forces you to do it the right way, whereas the
lack of enforcement in C leaves room for mistakes.

If you do add extensions to C to add some of these restrictions (and I encourage
you to pursue such extensions as we all benefit from better C), it is likely not
sufficient to reach the level of compile-time guarantee that Rust offers because
you need a whole slew of restrictions/enforcements.

I also note that academics have a formalisation of [a subset of] Rust that show
the soundness of these guarantees and the requirements on unsafe to compose
safely. So we're not talking about guesswork, there are formal machine-checked
proofs published about this (see for example
https://people.mpi-sws.org/~dreyer/papers/safe-sysprog-rust/paper.pdf).


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Wedson Almeida Filho
On Sat, Apr 17, 2021 at 12:41:23PM +, David Laight wrote:
> Or the cases where the locks are released in the 'wrong' order.
> Typically for:
>   lock(table)
>   item = lookup(table, key)
>   lock(item)
>   unlock(table)
>   ...
>   unlock(item)

This is expressible in Rust with something like:

table = table_mutex.lock()
item = table.lookup(key).lock()
drop(table)
...
// item will be unlocked when it goes out of scope or on drop(item)

The added bonus here from Rust is that table is not accessible after
drop(table), so a developer cannot accidentally access fields after unlocking
it.

> 
> (In the kernel the table lock might be RCU.)
> 
> Or, with similar data:
>   write_lock(table);
>   foreach(item, table)
>   lock(item)
>   unlock(item)
>   /* No items can be locked until we release the write_lock.
>   ...
>   unlock(table)

I think I'm missing something here. Would you help me understand what part is
out of the ordinary in the code above? It would be expressible in Rust with
something like:

table = table_mutex.write();
for (item_mutex in table)
item = item_mutex.lock
// item is unlocked at the end of the loop iteration (out of scope)
// table gets unlocked when it goes out of scope

Cheers,
-Wedson


RE: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread David Laight
..
> The more you make it look like (Kernel) C, the easier it is for us C
> people to actually read. My eyes have been reading C for almost 30 years
> by now, they have a lexer built in the optical nerve; reading something
> that looks vaguely like C but is definitely not C is an utterly painful
> experience.

I'll see your 30 years and raise to over 35.
(And writing code that accesses hardware for 6 or 7 years before that.)

Both Java and go can look more like the K style C than any of the
examples from microsoft - which seem to utilise as much vertical space
as humanly? possible.

Those rust examples seemed to be of the horrid microsoft sytle.
Nothing about that style makes reading code easy.

David

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



RE: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread David Laight
From: Peter Zijlstra
> Sent: 16 April 2021 15:19
> 
> On Fri, Apr 16, 2021 at 02:07:49PM +0100, Wedson Almeida Filho wrote:
> > On Fri, Apr 16, 2021 at 01:24:23PM +0200, Peter Zijlstra wrote:
> 
> > >  int perf_event_task_enable(void)
> > >  {
> > > + DEFINE_MUTEX_GUARD(event_mutex, >perf_event_mutex);
> >
> > There is nothing in C forcing developers to actually use 
> > DEFINE_MUTEX_GUARD. So
> > someone may simply forget (or not know that they need) to lock
> > current->perf_event_mutex and directly access some field protected by it. 
> > This
> > is unlikely to happen when one first writes the code, but over time as 
> > different
> > people modify the code and invariants change, it is possible for this to 
> > happen.
> >
> > In Rust, this isn't possible: the data protected by a lock is only 
> > accessible
> > when the lock is locked. So developers cannot accidentally make mistakes of 
> > this
> > kind. And since the enforcement happens at compile time, there is no runtime
> > cost.
> >
> > This, we believe, is fundamental to the discussion: we agree that many of 
> > these
> > idioms can be implemented in C (albeit in this case with a compiler 
> > extension),
> > but their use is optional, people can (and do) still make mistakes that 
> > lead to
> > vulnerabilities; Rust disallows classes of  mistakes by construction.
> 
> Does this also not prohibit constructs where modification must be done
> while holding two locks, but reading can be done while holding either
> lock?
> 
> That's a semi common scheme in the kernel, but not something that's
> expressible by, for example, the Java sync keyword.
> 
> It also very much doesn't work for RCU, where modification must be done
> under a lock, but access is done essentially lockless.
...

Or the cases where the locks are released in the 'wrong' order.
Typically for:
lock(table)
item = lookup(table, key)
lock(item)
unlock(table)
...
unlock(item)

(In the kernel the table lock might be RCU.)

Or, with similar data:
write_lock(table);
foreach(item, table)
lock(item)
unlock(item)
/* No items can be locked until we release the write_lock.
...
unlock(table)

You can also easily end up with a 'fubar' we have at work where
someone wrote a C++ condvar class that inherits from mutex.

David

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



Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Willy Tarreau
On Sat, Apr 17, 2021 at 01:17:21PM +0200, Peter Zijlstra wrote:
> Well, I think the rules actually make sense, at the point in the syntax
> tree where + happens, we have 'unsigned char' and 'int', so at that
> point we promote to 'int'. Subsequently 'int' gets shifted and bad
> things happen.

That's always the problem caused by signedness being applied to the
type while modern machines do not care about that and use it during
(or even after) the operation instead :-/

We'd need to define some macros to zero-extend and sign-extend some
values to avoid such issues. I'm sure this would be more intuitive
than trying to guess how many casts (and in what order) to place to
make sure an operation works as desired.

> The 'unsigned long' doesn't happen until quite a bit later.
> 
> Anyway, the rules are imo fairly clear and logical, but yes they can be
> annoying. The really silly thing here is that << and >> have UB at all,
> and I would love a -fwrapv style flag that simply defines it. Yes it
> will generate worse code in some cases, but having the UB there is just
> stupid.

I'd also love to have a UB-less mode with well defined semantics for
plenty of operations that are known to work well on modern machines,
like integer wrapping, bit shifts ignoring higher bits etc. Lots of
stuff we often have to write useless code for, just to please the
compiler.

> That of course doesn't help your case here, it would simply misbehave
> and not be UB.
> 
> Another thing the C rules cannot really express is a 32x32->64
> multiplication, some (older) versions of GCC can be tricked into it, but
> mostly it just doesn't want to do that sanely and the C rules are
> absolutely no help there.

For me the old trick of casting one side as long long still works:

  unsigned long long mul3264(unsigned int a, unsigned int b)
  {
return (unsigned long long)a * b;
  }

i386:
   :
 0: 8b 44 24 08   mov0x8(%esp),%eax
 4: f7 64 24 04   mull   0x4(%esp)
 8: c3ret

x86_64:
   :
 0: 89 f8 mov%edi,%eax
 2: 89 f7 mov%esi,%edi
 4: 48 0f af c7   imul   %rdi,%rax
 8: c3retq   

Or maybe you had something else in mind ?

Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-17 Thread Peter Zijlstra
On Fri, Apr 16, 2021 at 07:08:29PM +0100, Matthew Wilcox wrote:
> On Fri, Apr 16, 2021 at 07:18:48PM +0200, Peter Zijlstra wrote:
> > On Fri, Apr 16, 2021 at 07:10:17PM +0200, Miguel Ojeda wrote:
> > 
> > > Of course, UB is only a subset of errors, but it is a major one, and
> > > particularly critical for privileged code.
> > 
> > I've seen relatively few UBSAN warnings that weren't due to UBSAN being
> > broken.
> 
> Lucky you.
> 
> 84c34df158cf215b0cd1475ab3b8e6f212f81f23
> 
> (i'd argue this is C being broken; promoting only as far as int, when
> assigning to an unsigned long is Bad, but until/unless either GCC fixes
> that or the language committee realises that being stuck in the 1970s
> is Bad, people are going to keep making this kind of mistake)

Well, I think the rules actually make sense, at the point in the syntax
tree where + happens, we have 'unsigned char' and 'int', so at that
point we promote to 'int'. Subsequently 'int' gets shifted and bad
things happen.

The 'unsigned long' doesn't happen until quite a bit later.

Anyway, the rules are imo fairly clear and logical, but yes they can be
annoying. The really silly thing here is that << and >> have UB at all,
and I would love a -fwrapv style flag that simply defines it. Yes it
will generate worse code in some cases, but having the UB there is just
stupid.

That of course doesn't help your case here, it would simply misbehave
and not be UB.

Another thing the C rules cannot really express is a 32x32->64
multiplication, some (older) versions of GCC can be tricked into it, but
mostly it just doesn't want to do that sanely and the C rules are
absolutely no help there.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread comex
On Fri, Apr 16, 2021 at 4:24 AM Peter Zijlstra  wrote:
> Simlar thing for RCU; C11 can't optimally do that; it needs to make
> rcu_dereference() a load-acquire [something ARM64 has already done in C
> because the compiler might be too clever by half when doing LTO :-(].
> But it's the compiler needing the acquire semantics, not the computer,
> which is just bloody wrong.

You may already know, but perhaps worth clarifying:

C11 does have atomic_signal_fence() which is a compiler fence.  But a
compiler fence only ensures the loads will be emitted in the right
order, not that the CPU will execute them in the right order.  CPU
architectures tend to guarantee that two loads will be executed in the
right order if the second one's address depends on the first one's
result, but a dependent load can stop being dependent after compiler
optimizations involving value speculation.  Using a load-acquire works
around this, not because it stops the compiler from performing any
optimization, but because it tells the computer to execute the loads
in the right order *even if* the compiler has broken the value
dependence.

So C11 atomics don't make the situation worse, compared to Linux's
atomics implementation based on volatile and inline assembly.  Both
are unsound in the presence of value speculation.  C11 atomics were
*supposed* to make the situation better, with memory_order_consume,
which would have specifically forbidden the compiler from performing
value speculation.  But all the compilers punted on getting this to
work and instead just implemented memory_order_consume as
memory_order_acquire.

As for Rust, it compiles to the same LLVM IR that Clang compiles C
into.  Volatile, inline assembly, and C11-based atomics: all of these
are available in Rust, and generate exactly the same code as their C
counterparts, for better or for worse.  Unfortunately, the Rust
project has relatively limited muscle when it comes to contributing to
LLVM.  So while it would definitely be nice if Rust could make RCU
sound, and from a specification perspective I think people would be
quite willing and probably easier to work with than the C committee...
I suspect that implementing this would require the kind of sweeping
change to LLVM that is probably not going to come from Rust.

There are other areas where I think that kind of discussion might be
more fruitful.  For example, the Rust documentation currently says
that a volatile read racing with a non-volatile write (i.e. seqlocks)
is undefined behavior. [1]  However, I am of the opinion that this is
essentially a spec bug, for reasons that are probably not worth
getting into here.

[1] https://doc.rust-lang.org/nightly/std/ptr/fn.read_volatile.html


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Josh Triplett
On Fri, Apr 16, 2021 at 12:27:39PM +0800, Boqun Feng wrote:
> Josh, I think it's good if we can connect to the people working on Rust
> memoryg model, I think the right person is Ralf Jung and the right place
> is https://github.com/rust-lang/unsafe-code-guidelines, but you
> cerntainly know better than me ;-) Or maybe we can use Rust-for-Linux or
> linux-toolchains list to discuss.

Ralf is definitely the right person to talk to. I don't think the UCG
repository is the right place to start that discussion, though. For now,
I'd suggest starting an email thread with Ralf and some C-and-kernel
memory model folks (hi Paul!) to suss out the most important changes
that would be needed.

With my language team hat on, I'd *absolutely* like to see the Rust
memory model support RCU-style deferred reclamation in a sound way,
ideally with as little unsafe code as possible.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Paul E. McKenney
On Thu, Apr 15, 2021 at 11:04:37PM -0700, Nick Desaulniers wrote:
> On Thu, Apr 15, 2021 at 9:27 PM Boqun Feng  wrote:
> >
> > [Copy LKMM people, Josh, Nick and Wedson]
> >
> > On Thu, Apr 15, 2021 at 08:58:16PM +0200, Peter Zijlstra wrote:
> > > On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> > >
> > > > Rust is a systems programming language that brings several key
> > > > advantages over C in the context of the Linux kernel:
> > > >
> > > >   - No undefined behavior in the safe subset (when unsafe code is
> > > > sound), including memory safety and the absence of data races.
> > >
> > > And yet I see not a single mention of the Rust Memory Model and how it
> > > aligns (or not) with the LKMM. The C11 memory model for example is a
> > > really poor fit for LKMM.
> > >
> >
> > I think Rust currently uses C11 memory model as per:
> >
> > https://doc.rust-lang.org/nomicon/atomics.html
> >
> > , also I guess another reason that they pick C11 memory model is because
> > LLVM has the support by default.
> >
> > But I think the Rust Community still wants to have a good memory model,
> > and they are open to any kind of suggestion and input. I think we (LKMM
> > people) should really get involved, because the recent discussion on
> > RISC-V's atomics shows that if we didn't people might get a "broken"
> > design because they thought C11 memory model is good enough:
> >
> > https://lore.kernel.org/lkml/YGyZPCxJYGOvqYZQ@boqun-archlinux/
> >
> > And the benefits are mutual: a) Linux Kernel Memory Model (LKMM) is
> > defined by combining the requirements of developers and the behavior of
> > hardwares, it's pratical and can be a very good input for memory model
> > designing in Rust; b) Once Rust has a better memory model, the compiler
> > technologies whatever Rust compilers use to suppor the memory model can
> > be adopted to C compilers and we can get that part for free.
> 
> Yes, I agree; I think that's a very good approach.  Avoiding the ISO
> WG14 is interesting; at least the merits could be debated in the
> public and not behind closed doors.

WG14 (C) and WG21 (C++) are at least somewhat open.  Here are some of
the proposals a few of us have in flight:

P2055R0 A Relaxed Guide to memory_order_relaxed
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2055r0.pdf
P0124R7 Linux-Kernel Memory Model (vs. that of C/C++)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0124r7.html
P1726R4 Pointer lifetime-end zap
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1726r4.pdf

https://docs.google.com/document/d/1MfagxTa6H0rTxtq9Oxyh4X53NzKqOt7y3hZBVzO_LMk/edit?usp=sharing
P1121R2 Hazard Pointers: Proposed Interface and Wording for Concurrency TS 2
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1121r2.pdf
P1382R1 volatile_load and volatile_store
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1382r1.pdf
P1122R2 Proposed Wording for Concurrent Data Structures: Read-Copy-Update (RCU)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1122r2.pdf

https://docs.google.com/document/d/1MfagxTa6H0rTxtq9Oxyh4X53NzKqOt7y3hZBVzO_LMk/edit?usp=sharing
P0190R4 Proposal for New memory order consume Definition
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf
P0750R1 Consume
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0750r1.html

P1726R4 is of particular concern, along with consume.

> > At least I personally is very intereted to help Rust on a complete and
> > pratical memory model ;-)
> >
> > Josh, I think it's good if we can connect to the people working on Rust
> > memoryg model, I think the right person is Ralf Jung and the right place
> > is https://github.com/rust-lang/unsafe-code-guidelines, but you
> > cerntainly know better than me ;-) Or maybe we can use Rust-for-Linux or
> > linux-toolchains list to discuss.
> >
> > [...]
> > > >   - Boqun Feng is working hard on the different options for
> > > > threading abstractions and has reviewed most of the `sync` PRs.
> > >
> > > Boqun, I know you're familiar with LKMM, can you please talk about how
> > > Rust does things and how it interacts?
> >
> > As Wedson said in the other email, currently there is no code requiring
> > synchronization between C side and Rust side, so we are currently fine.
> > But in the longer term, we need to teach Rust memory model about the
> > "design patterns" used in Linux kernel for parallel programming.
> >
> > What I have been doing so far is reviewing patches which have memory
> > orderings in Rust-for-Linux project, try to make sure we don't include
> > memory ordering bugs for the beginning.

I believe that compatibility with both C/C++ and the Linux kernel are
important.

Thanx, Paul


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Matthew Wilcox
On Fri, Apr 16, 2021 at 07:18:48PM +0200, Peter Zijlstra wrote:
> On Fri, Apr 16, 2021 at 07:10:17PM +0200, Miguel Ojeda wrote:
> 
> > Of course, UB is only a subset of errors, but it is a major one, and
> > particularly critical for privileged code.
> 
> I've seen relatively few UBSAN warnings that weren't due to UBSAN being
> broken.

Lucky you.

84c34df158cf215b0cd1475ab3b8e6f212f81f23

(i'd argue this is C being broken; promoting only as far as int, when
assigning to an unsigned long is Bad, but until/unless either GCC fixes
that or the language committee realises that being stuck in the 1970s
is Bad, people are going to keep making this kind of mistake)


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Connor Kuehl
On 4/16/21 12:37 PM, Willy Tarreau wrote:
> Hi Miguel,
> 
> On Fri, Apr 16, 2021 at 07:10:17PM +0200, Miguel Ojeda wrote:
>> And by having the compiler enforce this safe-unsafe split, you can
>> review safe code without having to constantly worry about UB; and be
>> extra alert when dealing with `unsafe` blocks.
> 
> I do appreciate this safe/unsafe split and a few other things I've seen
> in the language. The equivalent I'm using in C is stronger typing and
> "const" modifiers wherever possible. Of course it's much more limited,
> it's just to explain that I do value this. I just feel like "unsafe"
> is the universal response to any question "how would I do this" while
> at the same time "safe" is the best selling argument for the language.
> As such, I strongly doubt about the real benefits once facing reality
> with everything marked unsafe. Except that it will be easier to blame
> the person having written the unsafe one-liner instead of writing 60
> cryptic lines doing the functional equivalent using some lesser known
> extensions :-/
> 

It's possible that many of the questions you've been specifically asking
about, by sheer coincidence, are targeted towards the problems that would
indeed require a lower-level abstraction built within an unsafe block; meaning
you've managed to evade the tons of other upper layers that could be written
in safe Rust.

Indeed, at a certain layer, unsafe is unavoidable for the kind of work that
is done in the kernel. The goal is to shrink the unsafe blocks as much as
possible and confirm the correctness of those pieces, then build safe
abstractions on top of it.

For what it's worth, if there was some post-human apocalyptic world where
literally everything had to go inside an unsafe block, the silver lining
in a hypothetical situation like this is that unsafe does not disable all
of Rust's static analysis like the borrow checker, etc. It allows you to
do things like directly dereference a pointer, etc. Unsafe also doesn't
automatically mean that the code is wrong or that it has memory issues;
it just means that the compiler can't guarantee that it doesn't based on
what you do in the unsafe block.

Connor



Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Willy Tarreau
Hi Miguel,

On Fri, Apr 16, 2021 at 07:10:17PM +0200, Miguel Ojeda wrote:
> And by having the compiler enforce this safe-unsafe split, you can
> review safe code without having to constantly worry about UB; and be
> extra alert when dealing with `unsafe` blocks.

I do appreciate this safe/unsafe split and a few other things I've seen
in the language. The equivalent I'm using in C is stronger typing and
"const" modifiers wherever possible. Of course it's much more limited,
it's just to explain that I do value this. I just feel like "unsafe"
is the universal response to any question "how would I do this" while
at the same time "safe" is the best selling argument for the language.
As such, I strongly doubt about the real benefits once facing reality
with everything marked unsafe. Except that it will be easier to blame
the person having written the unsafe one-liner instead of writing 60
cryptic lines doing the functional equivalent using some lesser known
extensions :-/

> Of course, UB is only a subset of errors, but it is a major one, and
> particularly critical for privileged code.

Not in my experience. I do create bugs that very seldomly stem from UB,
like any of us probably. But the vast majority of my bugs are caused by
stupid logic errors. When you invert an error check somewhere because
the function name looks like a boolean but its result works the other
way around, you can pass 10 times over it without noticing, and the
compiler will not help. And these ones are due to the human brain not
being that powerful in front of a computer, and whatever language will
not change this. Or worse, if it's harder to express what I want, I
will write more bugs. It happened to me quite a few times already
trying to work around absurd gcc warnings.

Based on the comments in this thread and the responses often being
around "we'll try to get this done" or "we'll bring the issue to the
compiler team", combined with the difficulty to keep control over
resources usage, I'm really not convinced at all it's suited for
low-level development. I understand the interest of the experiment
to help the language evolve into that direction, but I fear that
the kernel will soon be as bloated and insecure as a browser, and
that's really not to please me.

Cheers,
Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Peter Zijlstra
On Fri, Apr 16, 2021 at 07:10:17PM +0200, Miguel Ojeda wrote:

> Of course, UB is only a subset of errors, but it is a major one, and
> particularly critical for privileged code.

I've seen relatively few UBSAN warnings that weren't due to UBSAN being
broken.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Miguel Ojeda
On Fri, Apr 16, 2021 at 6:14 PM Willy Tarreau  wrote:
>
> I'm really afraid by languages which force developers to do this or that.
> Many bugs in C come from casts because developers know their use case
> better than the compiler's developers, and result in lack of warnings
> when the code evolves, leaving pending bugs behind. What is important
> in my opinion is to let developers express what they want and report
> suspicious constructs, not to force them to dirtily work around rules
> that conflict with their use case :-/

I understand your concerns. The idea is that by restricting some
patterns (in the safe subset), you gain the ability to guarantee the
absence of UB (as long as the `unsafe` code is sound).

But please note that the `unsafe` side is still there, and you can
reach out for it when needed.

Thus, if you find yourself in a situation where the safe abstractions
are not enough for what you need to convey, you have two options:
ideally, you think about how to model that pattern in a way that can
be exposed as a safe API so that others can reuse it. And if that is
not possible, you reach out for `unsafe` yourself.

Even in those cases where there is no other way around `unsafe`, note
that you still have gained something very important: now you have made
it explicit in the code that this is needed, and you will have written
a `SAFETY` annotation that tells others why your usage is sound (i.e.
why it cannot trigger UB).

And by having the compiler enforce this safe-unsafe split, you can
review safe code without having to constantly worry about UB; and be
extra alert when dealing with `unsafe` blocks.

Of course, UB is only a subset of errors, but it is a major one, and
particularly critical for privileged code.

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Miguel Ojeda
On Fri, Apr 16, 2021 at 5:43 PM Peter Zijlstra  wrote:
>
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2659.htm
>
> That's just not making any damn sense what so ever. That seems to be
> about sprinkling abort() all over the place, which is just total
> rubbish.

No, it is not about that. It is semantically a no-op: N2659 is not
about a safe subset of C -- it just triggered discussions about it in
the reflector.

The point is that we think it is important to improve C for the kernel
too. We are not working on bringing Rust to the kernel "just because
we want Rust", but because we believe it has a sizable amount of
advantages that outweigh the costs.

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Wedson Almeida Filho
On Fri, Apr 16, 2021 at 11:58:05AM -0400, Theodore Ts'o wrote:
> Another fairly common use case is a lockless, racy test of a
> particular field, as an optimization before we take the lock before we
> test it for realsies.  In this particular case, we can't allocate
> memory while holding a spinlock, so we check to see without taking the
> spinlock to see whether we should allocate memory (which is expensive,
> and unnecessasry most of the time):

I'd have to think more about whether we can build generic safe abstraction for
this pattern. But even if we can't, we always have the unsafe escape hatch: we
can grant unsafe unlocked access to the data; in such cases, the onus is on the
caller to convince themselves that what they're doing is safe, i.e., the
compiler won't offer compile-time guarantees.

However, and I think this is also an advantage of Rust, such unsafe accesses
*must* be explicitly tagged as such (and this is enforced at compile-time), so
you'd do something like:

// SAFETY: The below is safe because...
if !unsafe{ journal.access_unlocked().j_running_transaction } {
}

And the idea is that unsafe blocks like the one above will require additional
scrutiny from reviewers. So this also makes the lives of maintainers/reviewers
easier as they'd know that these sections need more attention.

> The other thing that I'll note is that diferent elements in thet
> journal structure are protected by different spinlocks; we don't have
> a global lock protecting the entire structure, which is critical for
> scalability on systems with a large number of CPU's with a lot of
> threads all wanting to perform file system operations.

Yes, this is fine, the way to do it in Rust would be to break your struct up
into something like (we have something like this in Binder):

struct X {
[...]
}

struct Y {
[...]
}

struct Z {
x: SpinLock,
y: SpinLock,
a: u32,
[...]
}
  
> So having a guard structure which can't be bypassed on the entire
> structure would result in a pretty massive performance penalty for the
> ext4 file system.  I know that initially the use of Rust in the kernel
> is targetted for less performance critical modules, such as device
> drivers, but I thought I would mention some of the advantages of more
> advanced locking techniques.

Thanks for this. Yes, while the initial target is drivers, we do want to provide
a general framework that could potentially be used anywhere.

Please let us know if you find other patterns that seem problematic.

Cheers,
-Wedson


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Willy Tarreau
On Fri, Apr 16, 2021 at 04:33:51PM +0100, Wedson Almeida Filho wrote:
> On Fri, Apr 16, 2021 at 04:19:07PM +0200, Peter Zijlstra wrote:
> > Does this also not prohibit constructs where modification must be done
> > while holding two locks, but reading can be done while holding either
> > lock?
> 
> I don't believe it does. Remember that we have full control of the 
> abstractions,
> so we can (and will when the need arises) build an abstraction that provides 
> the
> functionality you describe. For the read path, we can have functions that 
> return
> a read-only guard (which is the gateway to the data in Rust) when locking 
> either
> of the locks, or when showing evidence that either lock is already locked 
> (i.e.,
> by temporarily transferring ownership of another guard).

But will this remain syntactically readable/writable by mere humans ?
I mean, I keep extremely bad memories of having tried to write a loop
oconcatenating at most N times a string to another one, where N was a
number provided on the command line, with the compiler shouting at me
all the time until I blindly copy-pasted random pieces of unreadable
code from the net with a horribly complicated syntax that still
resulted in the impossibility for me to check for memory allocation
before failing. So I'm wondering how complicated that can become after
adding all sort of artificial protections on top of this :-/

> Note that this is
> another area where Rust offers advantages: read-only guards (in C, if you 
> take a
> read lock, nothing prevents you from making changes to fields you should only 
> be
> allowed to read);

But I'm happily doing that when I know what I'm doing. What you call a
read lock usually is in fact a shared lock as opposed to an exclusive
lock (generally used for writes). For me it's perfectly valid to perform
atomic writes under a read lock instead of forcing everyone to wait by
taking a write lock. You may for example take a read lock on a structure
to make sure that a field you're accessing in it points to stable memory
that is only modified under the write lock, but the pointer itself is
atomically accessed and swapped under the read lock.

> In fact, this is also an advantage of Rust. It would *force* developers to
> lock/unlock the RCU lock before they can access the protected data.

I'm really afraid by languages which force developers to do this or that.
Many bugs in C come from casts because developers know their use case
better than the compiler's developers, and result in lack of warnings
when the code evolves, leaving pending bugs behind. What is important
in my opinion is to let developers express what they want and report
suspicious constructs, not to force them to dirtily work around rules
that conflict with their use case :-/

Willy


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Theodore Ts'o
On Fri, Apr 16, 2021 at 02:07:49PM +0100, Wedson Almeida Filho wrote:
> On Fri, Apr 16, 2021 at 01:24:23PM +0200, Peter Zijlstra wrote:
> > On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> > >   - Featureful language: sum types, pattern matching, generics,
> > > RAII, lifetimes, shared & exclusive references, modules &
> > > visibility, powerful hygienic and procedural macros...
> > 
> > IMO RAII is over-valued, but just in case you care, the below seems to
> > work just fine. No fancy new language needed, works today. Similarly you
> > can create refcount_t guards, or with a little more work full blown
> > smart_ptr crud.
> 
> Peter, we do care, thank you for posting this. It's a great example for us to
> discuss some of the minutiae of what we think Rust brings to the table in
> addition to what's already possible in C.

Another fairly common use case is a lockless, racy test of a
particular field, as an optimization before we take the lock before we
test it for realsies.  In this particular case, we can't allocate
memory while holding a spinlock, so we check to see without taking the
spinlock to see whether we should allocate memory (which is expensive,
and unnecessasry most of the time):

alloc_transaction:
/*
 * This check is racy but it is just an optimization of allocating new
 * transaction early if there are high chances we'll need it. If we
 * guess wrong, we'll retry or free the unused transaction.
 */
if (!data_race(journal->j_running_transaction)) {
/*
 * If __GFP_FS is not present, then we may be being called from
 * inside the fs writeback layer, so we MUST NOT fail.
 */
if ((gfp_mask & __GFP_FS) == 0)
gfp_mask |= __GFP_NOFAIL;
new_transaction = kmem_cache_zalloc(transaction_cache,
gfp_mask);
if (!new_transaction)
return -ENOMEM;
}
...
repeat:
read_lock(>j_state_lock);
...
if (!journal->j_running_transaction) {
read_unlock(>j_state_lock);
if (!new_transaction)
goto alloc_transaction;
write_lock(>j_state_lock);
if (!journal->j_running_transaction &&
(handle->h_reserved || !journal->j_barrier_count)) {
jbd2_get_transaction(journal, new_transaction);
new_transaction = NULL;
}
write_unlock(>j_state_lock);
goto repeat;
}
...


The other thing that I'll note is that diferent elements in thet
journal structure are protected by different spinlocks; we don't have
a global lock protecting the entire structure, which is critical for
scalability on systems with a large number of CPU's with a lot of
threads all wanting to perform file system operations.

So having a guard structure which can't be bypassed on the entire
structure would result in a pretty massive performance penalty for the
ext4 file system.  I know that initially the use of Rust in the kernel
is targetted for less performance critical modules, such as device
drivers, but I thought I would mention some of the advantages of more
advanced locking techniques.

Cheers,

- Ted


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Peter Zijlstra
On Fri, Apr 16, 2021 at 05:04:41PM +0200, Miguel Ojeda wrote:
> Of course, we could propose something similar for C -- in fact, there
> was a recent discussion around this in the C committee triggered by my
> n2659 "Safety attributes for C" paper. 

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2659.htm

That's just not making any damn sense what so ever. That seems to be
about sprinkling abort() all over the place, which is just total
rubbish.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Wedson Almeida Filho
On Fri, Apr 16, 2021 at 04:19:07PM +0200, Peter Zijlstra wrote:
> Does this also not prohibit constructs where modification must be done
> while holding two locks, but reading can be done while holding either
> lock?

I don't believe it does. Remember that we have full control of the abstractions,
so we can (and will when the need arises) build an abstraction that provides the
functionality you describe. For the read path, we can have functions that return
a read-only guard (which is the gateway to the data in Rust) when locking either
of the locks, or when showing evidence that either lock is already locked (i.e.,
by temporarily transferring ownership of another guard). Note that this is
another area where Rust offers advantages: read-only guards (in C, if you take a
read lock, nothing prevents you from making changes to fields you should only be
allowed to read); and the ability to take temporary ownership, giving it back
even within the same function.

Similarly, to access a mutable guard, you'd have to show evidence that both
locks are held.

> That's a semi common scheme in the kernel, but not something that's
> expressible by, for example, the Java sync keyword.
> 
> It also very much doesn't work for RCU, where modification must be done
> under a lock, but access is done essentially lockless.

Why not? RCU is a lock -- it may have zero cost in most (all?) architectures on
the read path, but it is a lock. We can model access to variables/fields
protected by it just like any other lock, with the implementation of lock/unlock
optimizing to no-ops on the read path where possible.

In fact, this is also an advantage of Rust. It would *force* developers to
lock/unlock the RCU lock before they can access the protected data.

> I would much rather have a language extention where we can associate
> custom assertions with variable access, sorta like a sanitizer:
> 
> static inline void assert_foo_bar(struct foo *f)
> {
>   lockdep_assert_held(>lock);
> }
> 
> struct foo {
>   spinlock_t lock;
>   int bar __assert__(assert_foo_bar);
> };
> 
> Such things can be optional and only enabled for debug builds on new
> compilers.

These would be great, but would still fall short of the compile-time guaranteed
safety that Rust offers in these cases.

> C does indeed not have the concept of ownership, unlike modern C++ I
> think. But I would much rather see a C language extention for that than
> go Rust.
> 
> This would mean a far more agressive push for newer C compilers than
> we've ever done before, but at least it would all still be a single
> language. Convertion to the new stuff can be done gradually and where
> it makes sense and new extentions can be evaluated on performance impact
> etc.

I encourage you to pursue this. We'd all benefit from better C. I'd be happy to
review and provide feedback on proposed extensions that are deemed
equivalent/better than what Rust offers.

My background is also in C. I'm no Rust fanboy, I'm just taking what I think is
a pragmatic view of the available options.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Miguel Ojeda
On Fri, Apr 16, 2021 at 4:19 PM Peter Zijlstra  wrote:
>
> Does this also not prohibit constructs where modification must be done
> while holding two locks, but reading can be done while holding either
> lock?

Yeah, this came up in some discussions we had. There are some locking
patterns that we need to think about how to model best within Rust's
type system.

But even if some patterns cannot be made safe, that is fine and does
not diminish the advantages everywhere else.

> I would much rather have a language extention where we can associate
> custom assertions with variable access, sorta like a sanitizer:
>
> static inline void assert_foo_bar(struct foo *f)
> {
> lockdep_assert_held(>lock);
> }
>
> struct foo {
> spinlock_t lock;
> int bar __assert__(assert_foo_bar);
> };
>
> Such things can be optional and only enabled for debug builds on new
> compilers.

More sanitizers and ways to check "unsafe" code is sound are always
welcome -- not just for C, also for Rust `unsafe` code (e.g. Miri).

However, the main advantage of Rust for us is its safe subset (which
handles quite a lot of patterns, thanks to the lifetime tracking /
borrow checker).

Of course, we could propose something similar for C -- in fact, there
was a recent discussion around this in the C committee triggered by my
n2659 "Safety attributes for C" paper. However, achieving that would
require a lot of work, time, new syntax, etc. It is not something that
is in the radar just yet.

Similarly, if some compiler ends up implementing an extension that
actually realizes the same guarantees as Rust, we would likely end up
wrapping everything with macros like in the guards example you
mentioned, and even then we would not have got the rest of the
advantages that Rust brings to the table.

> C does indeed not have the concept of ownership, unlike modern C++ I
> think. But I would much rather see a C language extention for that than
> go Rust.

Many "resource-like" C++ types model ownership, yes; e.g.
`std::unique_ptr` for memory, as well as a myriad of ones in different
projects for different kinds of resources, plus generic ones like  the
proposed P0052. However, they do not enforce their usage is correct.

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Matthew Wilcox
On Fri, Apr 16, 2021 at 02:07:49PM +0100, Wedson Almeida Filho wrote:
> There is nothing in C forcing developers to actually use DEFINE_MUTEX_GUARD. 
> So
> someone may simply forget (or not know that they need) to lock
> current->perf_event_mutex and directly access some field protected by it. This
> is unlikely to happen when one first writes the code, but over time as 
> different
> people modify the code and invariants change, it is possible for this to 
> happen.
> 
> In Rust, this isn't possible: the data protected by a lock is only accessible
> when the lock is locked. So developers cannot accidentally make mistakes of 
> this
> kind. And since the enforcement happens at compile time, there is no runtime
> cost.

Well, we could do that in C too.

struct unlocked_inode {
spinlock_t i_lock;
};

struct locked_inode {
spinlock_t i_lock;
unsigned short i_bytes;
blkcnt_t i_blocks;
};

struct locked_inode *lock_inode(struct unlocked_inode *inode)
{
spin_lock(>i_lock);
return (struct locked_inode *)inode;
}

There's a combinatoric explosion when you have multiple locks in a data
structure that protect different things in it (and things in a data
structure that are protected by locks outside that data structure),
but I'm not sufficiently familiar with Rust to know if/how it solves
that problem.

Anyway, my point is that if we believe this is a sufficiently useful
feature to have, and we're willing to churn the kernel, it's less churn
to do this than it is to rewrite in Rust.

> Another scenario: suppose within perf_event_task_enable you need to call a
> function that requires the mutex to be locked and that will unlock it for you 
> on
> error (or unconditionally, doesn't matter). How would you do that in C? In 
> Rust,
> there is a clean idiomatic way of transferring ownership of a guard (or any
> other object) such that the previous owner cannot continue to use it after
> ownership is transferred. Again, this is enforced at compile time. I'm happy 
> to
> provide a small example if that would help.

I think we could do that too with an __attribute__((free)).  It isn't,
of course, actually freeing the pointer to the locked_inode, but it will
make the compiler think the pointer is invalid after the function returns.

(hm, looks like gcc doesn't actually have __attribute__((free)) yet.
that's unfortunate.  there's a potential solution in gcc-11 that might
do what we need)



Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Miguel Ojeda
On Fri, Apr 16, 2021 at 1:24 PM Peter Zijlstra  wrote:
>
> IMO RAII is over-valued, but just in case you care, the below seems to
> work just fine. No fancy new language needed, works today. Similarly you
> can create refcount_t guards, or with a little more work full blown
> smart_ptr crud.

Please note that even smart pointers (as in C++'s `std::unique_ptr`
etc.) do not guarantee memory safety. Yes, they help a lot writing
sound code (in particular exception-safe C++ code), but they do not
bring the same guarantees.

That's why using C language extensions (the existing ones, that is) to
recreate RAII/guards, smart pointers, etc. would only bring you to a
point closer to C++, but not to Rust.

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Peter Zijlstra
On Fri, Apr 16, 2021 at 02:07:49PM +0100, Wedson Almeida Filho wrote:
> On Fri, Apr 16, 2021 at 01:24:23PM +0200, Peter Zijlstra wrote:

> >  int perf_event_task_enable(void)
> >  {
> > +   DEFINE_MUTEX_GUARD(event_mutex, >perf_event_mutex);
> 
> There is nothing in C forcing developers to actually use DEFINE_MUTEX_GUARD. 
> So
> someone may simply forget (or not know that they need) to lock
> current->perf_event_mutex and directly access some field protected by it. This
> is unlikely to happen when one first writes the code, but over time as 
> different
> people modify the code and invariants change, it is possible for this to 
> happen.
> 
> In Rust, this isn't possible: the data protected by a lock is only accessible
> when the lock is locked. So developers cannot accidentally make mistakes of 
> this
> kind. And since the enforcement happens at compile time, there is no runtime
> cost.
> 
> This, we believe, is fundamental to the discussion: we agree that many of 
> these
> idioms can be implemented in C (albeit in this case with a compiler 
> extension),
> but their use is optional, people can (and do) still make mistakes that lead 
> to
> vulnerabilities; Rust disallows classes of  mistakes by construction.

Does this also not prohibit constructs where modification must be done
while holding two locks, but reading can be done while holding either
lock?

That's a semi common scheme in the kernel, but not something that's
expressible by, for example, the Java sync keyword.

It also very much doesn't work for RCU, where modification must be done
under a lock, but access is done essentially lockless.

I would much rather have a language extention where we can associate
custom assertions with variable access, sorta like a sanitizer:

static inline void assert_foo_bar(struct foo *f)
{
lockdep_assert_held(>lock);
}

struct foo {
spinlock_t lock;
int bar __assert__(assert_foo_bar);
};

Such things can be optional and only enabled for debug builds on new
compilers.

> Another scenario: suppose within perf_event_task_enable you need to call a
> function that requires the mutex to be locked and that will unlock it for you 
> on
> error (or unconditionally, doesn't matter). How would you do that in C? In 
> Rust,
> there is a clean idiomatic way of transferring ownership of a guard (or any
> other object) such that the previous owner cannot continue to use it after
> ownership is transferred. Again, this is enforced at compile time. I'm happy 
> to
> provide a small example if that would help.

C does indeed not have the concept of ownership, unlike modern C++ I
think. But I would much rather see a C language extention for that than
go Rust.

This would mean a far more agressive push for newer C compilers than
we've ever done before, but at least it would all still be a single
language. Convertion to the new stuff can be done gradually and where
it makes sense and new extentions can be evaluated on performance impact
etc.



Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Wedson Almeida Filho
On Fri, Apr 16, 2021 at 01:24:23PM +0200, Peter Zijlstra wrote:
> On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> >   - Featureful language: sum types, pattern matching, generics,
> > RAII, lifetimes, shared & exclusive references, modules &
> > visibility, powerful hygienic and procedural macros...
> 
> IMO RAII is over-valued, but just in case you care, the below seems to
> work just fine. No fancy new language needed, works today. Similarly you
> can create refcount_t guards, or with a little more work full blown
> smart_ptr crud.

Peter, we do care, thank you for posting this. It's a great example for us to
discuss some of the minutiae of what we think Rust brings to the table in
addition to what's already possible in C.

> 
> ---
> diff --git a/include/linux/mutex.h b/include/linux/mutex.h
> index e19323521f9c..f03a72dd8cea 100644
> --- a/include/linux/mutex.h
> +++ b/include/linux/mutex.h
> @@ -197,4 +197,22 @@ extern void mutex_unlock(struct mutex *lock);
>  
>  extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
>  
> +struct mutex_guard {
> + struct mutex *mutex;
> +};
> +
> +static inline struct mutex_guard mutex_guard_lock(struct mutex *mutex)
> +{
> + mutex_lock(mutex);
> + return (struct mutex_guard){ .mutex = mutex, };
> +}
> +
> +static inline void mutex_guard_unlock(struct mutex_guard *guard)
> +{
> + mutex_unlock(guard->mutex);
> +}
> +
> +#define DEFINE_MUTEX_GUARD(name, lock)   \
> + struct mutex_guard __attribute__((__cleanup__(mutex_guard_unlock))) 
> name = mutex_guard_lock(lock)
> +
>  #endif /* __LINUX_MUTEX_H */
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 8ee3249de2f0..603d197a83b8 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -5715,16 +5715,15 @@ static long perf_compat_ioctl(struct file *file, 
> unsigned int cmd,
>  
>  int perf_event_task_enable(void)
>  {
> + DEFINE_MUTEX_GUARD(event_mutex, >perf_event_mutex);

There is nothing in C forcing developers to actually use DEFINE_MUTEX_GUARD. So
someone may simply forget (or not know that they need) to lock
current->perf_event_mutex and directly access some field protected by it. This
is unlikely to happen when one first writes the code, but over time as different
people modify the code and invariants change, it is possible for this to happen.

In Rust, this isn't possible: the data protected by a lock is only accessible
when the lock is locked. So developers cannot accidentally make mistakes of this
kind. And since the enforcement happens at compile time, there is no runtime
cost.

This, we believe, is fundamental to the discussion: we agree that many of these
idioms can be implemented in C (albeit in this case with a compiler extension),
but their use is optional, people can (and do) still make mistakes that lead to
vulnerabilities; Rust disallows classes of  mistakes by construction.

Another scenario: suppose within perf_event_task_enable you need to call a
function that requires the mutex to be locked and that will unlock it for you on
error (or unconditionally, doesn't matter). How would you do that in C? In Rust,
there is a clean idiomatic way of transferring ownership of a guard (or any
other object) such that the previous owner cannot continue to use it after
ownership is transferred. Again, this is enforced at compile time. I'm happy to
provide a small example if that would help.

Again, thanks for bringing this up. And please keep your concerns and feedback
coming, we very much want to have these discussions and try to improve what we
have based on feedback from the community.

>   struct perf_event_context *ctx;
>   struct perf_event *event;
>  
> - mutex_lock(>perf_event_mutex);
>   list_for_each_entry(event, >perf_event_list, owner_entry) {
>   ctx = perf_event_ctx_lock(event);
>   perf_event_for_each_child(event, _perf_event_enable);
>   perf_event_ctx_unlock(event, ctx);
>   }
> - mutex_unlock(>perf_event_mutex);
>  
>   return 0;
>  }


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Peter Zijlstra
On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
>   - Featureful language: sum types, pattern matching, generics,
> RAII, lifetimes, shared & exclusive references, modules &
> visibility, powerful hygienic and procedural macros...

IMO RAII is over-valued, but just in case you care, the below seems to
work just fine. No fancy new language needed, works today. Similarly you
can create refcount_t guards, or with a little more work full blown
smart_ptr crud.

---
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index e19323521f9c..f03a72dd8cea 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -197,4 +197,22 @@ extern void mutex_unlock(struct mutex *lock);
 
 extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
 
+struct mutex_guard {
+   struct mutex *mutex;
+};
+
+static inline struct mutex_guard mutex_guard_lock(struct mutex *mutex)
+{
+   mutex_lock(mutex);
+   return (struct mutex_guard){ .mutex = mutex, };
+}
+
+static inline void mutex_guard_unlock(struct mutex_guard *guard)
+{
+   mutex_unlock(guard->mutex);
+}
+
+#define DEFINE_MUTEX_GUARD(name, lock) \
+   struct mutex_guard __attribute__((__cleanup__(mutex_guard_unlock))) 
name = mutex_guard_lock(lock)
+
 #endif /* __LINUX_MUTEX_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8ee3249de2f0..603d197a83b8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5715,16 +5715,15 @@ static long perf_compat_ioctl(struct file *file, 
unsigned int cmd,
 
 int perf_event_task_enable(void)
 {
+   DEFINE_MUTEX_GUARD(event_mutex, >perf_event_mutex);
struct perf_event_context *ctx;
struct perf_event *event;
 
-   mutex_lock(>perf_event_mutex);
list_for_each_entry(event, >perf_event_list, owner_entry) {
ctx = perf_event_ctx_lock(event);
perf_event_for_each_child(event, _perf_event_enable);
perf_event_ctx_unlock(event, ctx);
}
-   mutex_unlock(>perf_event_mutex);
 
return 0;
 }


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Willy Tarreau
On Fri, Apr 16, 2021 at 10:16:05AM +0200, Michal Kubecek wrote:
> And I don't see how the two languages might coexist peacefully without
> rust toolchain being necessary for building any kernel useful in
> practice and anyone seriously involved in kernel development having to
> be proficient in both languages.

Two languages ? No, one is specified and multiple-implemented, the other
one is the defined as what its only compiler understands at the moment,
so it's not a language, it's a compiler's reference manual at best. I'm
waiting for the day you're force to write things which look wrong with a
big comment around saying "it's not a bug it's a workaround for a bug in
the unique compiler, waiting to be retrofitted into the spec to solve the
problem for every user". Already seen for at least another "language"
implemented by a single vendor 22 years ago.

> Neither of these looks appealing to me.
> 
> The dependency on rust toolchain was exactly what made me give up on
> building Firefox from mercurial snapshots few years ago. To be able to
> build them, one needed bleeding edge snapshots of rust toolchain which
> my distribution couldn't possibly provide and building them myself
> required way too much effort. This very discussion already revealed that
> rust kernel code would provide similar experience. I also have my doubts
> about the "optional" part; once there are some interesting drivers
> written in rust, even if only in the form of out of tree modules, there
> will be an enormous pressure on distributions, both community and
> enterprise, to enable rust support.

Yes this scarily looks like the usual "embrace and extend... and abandon
the corpse once it doesn't move anymore".

I've already faced situations where I couldn't compile a recent 5.x kernel
using my previous gcc-4.7 compiler and this really really really pissed me
off because I'd had it in a build farm for many architectures and I had to
give up. But I also know that updating to a newer version will take time,
will be durable and will be worth it for the long term (except for the fact
that gcc doubles the build time every two versions). But here having to use
*the* compiler of the day and being prepared to keep a collection of them
to work with different stable kernels, no!

Also, I'm a bit worried about long-term survival of the new
language-of-the-day-that-makes-you-look-cool-at-beer-events. I was once
told perl would replace C everywhere. Does someone use it outside of
checkpatch.pl anymore ? Then I was told that C was dead because PHP was
appearing everywhere. I've even seen (slow) log processors written with
it. Now PHP seems to only be a WAF-selling argument. Then Ruby was "safe"
and would rule them all. Safe as its tab[-1] which crashed the interpreter.
Anyone heard of it recently ? Then Python, whose 2.7 is still present on
a lot of systems because the forced transition to 3 broke tons of code.
Will there ever be a 4 after this sore experience ? Then JS, Rust, Go,
Zig and I don't know what. What I'm noting is that such languages appear,
serve a purpose well, have their moment of fame, last a decade and
disappear except at a few enthousiasts. C has been there for 50 years
and served as the basis of many newer languages so it's still well
understood. I'm sure about one thing, the C bugs we have today will be
fixable in 20 years. I'm not even sure the Rust code we'll merge today
will still be compilable in 10 years nor will support the relevant
architectures available by then, and probably this code will have to
be rewritten in C to become maintained again.

> The other problem is even worse. Once we have non-trivial amount of rust
> code around the tree, even if it's "just some drivers", you cannot
> completely ignore it. One example would be internal API changes. Today,
> if I want to touch e.g. ethtool_ops, I need to adjust all in tree NIC
> drivers providing the affected callback and adjust them. Usually most of
> the patch is generated by spatch but manual tweaks are often needed here
> and there. In the world of bilingual kernel with nontrivial number of
> NIC drivers written in rust, I don't see how I could do that without
> also being proficient in rust.

You'll simply change the code you're able to change and those in charge
of their driver will use your commit message as instruction to fix the
build on theirs. How do you want it to be otherwise ?

> Rust enthusiasts tell us they want to
> open kernel development to more people but the result could as well be
> exactly the opposite: it could restrict kernel development to people
> proficient in _both_ languages.

This has been my understanding from the very beginning. Language prophets
always want to conquier very visible targets as a gauge of their baby's
popularity.

> As Peter said, it's not an imminent problem but as it's obvious this is
> just the first step, we should have a clear idea what the plan is and
> what we can and should expect.

I think the experience could 

Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Michal Kubecek
On Thu, Apr 15, 2021 at 08:58:16PM +0200, Peter Zijlstra wrote:
> 
> This; can we mercilessly break the .rs bits when refactoring? What
> happens the moment we cannot boot x86_64 without Rust crap on?
> 
> We can ignore this as a future problem, but I think it's only fair to
> discuss now. I really don't care for that future, and IMO adding this
> Rust or any other second language is a fail.

I believe this is the most important question and we really need
a honest answer in advance: where exactly is this heading? At the moment
and with this experimental RFC, rust stuff can be optional and isolated
but it's obvious that the plan is very different: to have rust all
around the standard kernel tree. (If not, why is the example driver in
drivers/char/ ?)

And I don't see how the two languages might coexist peacefully without
rust toolchain being necessary for building any kernel useful in
practice and anyone seriously involved in kernel development having to
be proficient in both languages. Neither of these looks appealing to
me.

The dependency on rust toolchain was exactly what made me give up on
building Firefox from mercurial snapshots few years ago. To be able to
build them, one needed bleeding edge snapshots of rust toolchain which
my distribution couldn't possibly provide and building them myself
required way too much effort. This very discussion already revealed that
rust kernel code would provide similar experience. I also have my doubts
about the "optional" part; once there are some interesting drivers
written in rust, even if only in the form of out of tree modules, there
will be an enormous pressure on distributions, both community and
enterprise, to enable rust support. Once the major distributions do,
most others will have to follow. And from what I have seen, you need
rust toolchain for build even if you want to only load modules written
in rust.

The other problem is even worse. Once we have non-trivial amount of rust
code around the tree, even if it's "just some drivers", you cannot
completely ignore it. One example would be internal API changes. Today,
if I want to touch e.g. ethtool_ops, I need to adjust all in tree NIC
drivers providing the affected callback and adjust them. Usually most of
the patch is generated by spatch but manual tweaks are often needed here
and there. In the world of bilingual kernel with nontrivial number of
NIC drivers written in rust, I don't see how I could do that without
also being proficient in rust.

Also, how about maintainers and reviewers? What if someone comes with
a new module under foo/ or foo/bar/ and relevant maintainer does not
know rust or just not well enough to be able to review the submission
properly? Can they simply say "Sorry, I don't speak rust so no rust in
foo/bar/"? Leaf drivers are one thing, how about netfilter matches and
targets, TCP congestion control algorighms, qdiscs, filesystems, ...?
Having kernel tree divided into "rusty" and "rustfree" zones does not
sound like a great idea. But if we don't want that, do we expect every
subsystem maintainer and reviewer to learn rust to a level sufficient
for reviewing rust (kernel) code? Rust enthusiasts tell us they want to
open kernel development to more people but the result could as well be
exactly the opposite: it could restrict kernel development to people
proficient in _both_ languages.

As Peter said, it's not an imminent problem but as it's obvious this is
just the first step, we should have a clear idea what the plan is and
what we can and should expect.

Michal


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Peter Zijlstra
On Fri, Apr 16, 2021 at 06:02:33AM +0100, Wedson Almeida Filho wrote:
> On Fri, Apr 16, 2021 at 04:25:34AM +, Al Viro wrote:

> > And as one of those freaks I can tell
> > you where exactly I would like you to go and what I would like you to do
> > with implicit suggestions to start a browser when I need to read some
> > in-tree documentation.
> 
> I could be mistaken but you seem angry. Perhaps it wouldn't be a bad idea to
> read your own code of conduct, I don't think you need a browser for that 
> either.

Welcome to LKML. CoC does not forbid human emotions just yet. Deal with
it.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Peter Zijlstra
On Fri, Apr 16, 2021 at 03:22:16AM +0100, Wedson Almeida Filho wrote:
> On Thu, Apr 15, 2021 at 08:58:16PM +0200, Peter Zijlstra wrote:
> > On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> > 
> > > Rust is a systems programming language that brings several key
> > > advantages over C in the context of the Linux kernel:
> > > 
> > >   - No undefined behavior in the safe subset (when unsafe code is
> > > sound), including memory safety and the absence of data races.
> > 
> > And yet I see not a single mention of the Rust Memory Model and how it
> > aligns (or not) with the LKMM. The C11 memory model for example is a
> > really poor fit for LKMM.
> 
> We don't intend to directly expose C data structures to Rust code (outside the
> kernel crate). Instead, we intend to provide wrappers that expose safe
> interfaces even though the implementation may use unsafe blocks. So we expect
> the vast majority of Rust code to just care about the Rust memory model.
> 
> We admittedly don't have a huge number of wrappers yet, but we do have enough 
> to
> implement most of Binder and so far it's been ok. We do intend to eventually
> cover other classes of drivers that may unveil unforeseen difficulties, we'll
> see.
> 
> If you have concerns that we might have overlooked, we'd be happy to hear 
> about
> them from you (or anyone else).

Well, the obvious example would be seqlocks. C11 can't do them. The not
sharing of data structures would avoid most of that, but will also cost
you in performance.

Simlar thing for RCU; C11 can't optimally do that; it needs to make
rcu_dereference() a load-acquire [something ARM64 has already done in C
because the compiler might be too clever by half when doing LTO :-(].
But it's the compiler needing the acquire semantics, not the computer,
which is just bloody wrong.

And there's more sharp corners to be had. But yes, if you're not
actually sharing anything; and taking the performance hit that comes
with that, you might get away with it.

> > HTML is not a valid documentation format. Heck, markdown itself is
> > barely readable.
> 
> Are you stating [what you perceive as] a fact or just venting? If the former,
> would you mind enlightening us with some evidence?

I've yet to see a program that renders HTML (including all the cruft
often used in docs, which might include SVG graphics and whatnot) sanely
in ASCII. Lynx does not qualify, it's output is atrocious crap.

Yes, lynx lets you read HTML in ASCII, but at the cost of bleeding
eyeballs and missing content.

Nothing beats a sane ASCII document with possibly, where really needed
some ASCII art.

Sadly the whole kernel documentation project is moving away from that as
well, which just means I'm back to working on an undocumented codebase.
This rst crap they adopted is unreadable garbage.

> > It is really *really* hard to read. It has all sorts of weird things,
> > like operators at the beginning after a line break:
> > 
> > if (foo
> > || bar)
> > 
> > which is just wrong. And it suffers from CamelCase, which is just about
> > the worst thing ever. Not even the C++ std libs have that (or had, back
> > when I still did knew C++).
> > 
> > I also see:
> > 
> > if (foo) {
> > ...
> > }
> > 
> > and
> > 
> > if foo {
> > }
> > 
> > the latter, ofcourse, being complete rubbish.
> 
> There are advantages to adopting the preferred style of a language (when one
> exists). We, of course, are not required to adopt it but I am of the opinion
> that we should have good reasons to diverge if that's our choice in the end.
> 
> "Not having parentheses around the if-clause expression is complete rubbish"
> doesn't sound like a good reason to me.

Of course it does; my internal lexer keeps screaming syntax error at me;
how am I going to understand code when I can't sanely read it?

The more you make it look like (Kernel) C, the easier it is for us C
people to actually read. My eyes have been reading C for almost 30 years
by now, they have a lexer built in the optical nerve; reading something
that looks vaguely like C but is definitely not C is an utterly painful
experience.

You're asking to join us, not the other way around. I'm fine in a world
without Rust.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-16 Thread Nick Desaulniers
On Thu, Apr 15, 2021 at 9:27 PM Boqun Feng  wrote:
>
> [Copy LKMM people, Josh, Nick and Wedson]
>
> On Thu, Apr 15, 2021 at 08:58:16PM +0200, Peter Zijlstra wrote:
> > On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> >
> > > Rust is a systems programming language that brings several key
> > > advantages over C in the context of the Linux kernel:
> > >
> > >   - No undefined behavior in the safe subset (when unsafe code is
> > > sound), including memory safety and the absence of data races.
> >
> > And yet I see not a single mention of the Rust Memory Model and how it
> > aligns (or not) with the LKMM. The C11 memory model for example is a
> > really poor fit for LKMM.
> >
>
> I think Rust currently uses C11 memory model as per:
>
> https://doc.rust-lang.org/nomicon/atomics.html
>
> , also I guess another reason that they pick C11 memory model is because
> LLVM has the support by default.
>
> But I think the Rust Community still wants to have a good memory model,
> and they are open to any kind of suggestion and input. I think we (LKMM
> people) should really get involved, because the recent discussion on
> RISC-V's atomics shows that if we didn't people might get a "broken"
> design because they thought C11 memory model is good enough:
>
> https://lore.kernel.org/lkml/YGyZPCxJYGOvqYZQ@boqun-archlinux/
>
> And the benefits are mutual: a) Linux Kernel Memory Model (LKMM) is
> defined by combining the requirements of developers and the behavior of
> hardwares, it's pratical and can be a very good input for memory model
> designing in Rust; b) Once Rust has a better memory model, the compiler
> technologies whatever Rust compilers use to suppor the memory model can
> be adopted to C compilers and we can get that part for free.

Yes, I agree; I think that's a very good approach.  Avoiding the ISO
WG14 is interesting; at least the merits could be debated in the
public and not behind closed doors.

>
> At least I personally is very intereted to help Rust on a complete and
> pratical memory model ;-)
>
> Josh, I think it's good if we can connect to the people working on Rust
> memoryg model, I think the right person is Ralf Jung and the right place
> is https://github.com/rust-lang/unsafe-code-guidelines, but you
> cerntainly know better than me ;-) Or maybe we can use Rust-for-Linux or
> linux-toolchains list to discuss.
>
> [...]
> > >   - Boqun Feng is working hard on the different options for
> > > threading abstractions and has reviewed most of the `sync` PRs.
> >
> > Boqun, I know you're familiar with LKMM, can you please talk about how
> > Rust does things and how it interacts?
>
> As Wedson said in the other email, currently there is no code requiring
> synchronization between C side and Rust side, so we are currently fine.
> But in the longer term, we need to teach Rust memory model about the
> "design patterns" used in Linux kernel for parallel programming.
>
> What I have been doing so far is reviewing patches which have memory
> orderings in Rust-for-Linux project, try to make sure we don't include
> memory ordering bugs for the beginning.
>
> Regards,
> Boqun



-- 
Thanks,
~Nick Desaulniers


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Paul Zimmerman
On Fri, Apr 16, 2021 at 06:02:33 +0100, Wedson Almeida Filho wrote:
> On Fri, Apr 16, 2021 at 04:25:34AM +, Al Viro wrote:
>
>>> Are you stating [what you perceive as] a fact or just venting? If the 
>>> former,
>>> would you mind enlightening us with some evidence?
>> 
>> How about "not everyone uses a browser as a part of their workflow"?
>
> The documentation is available in markdown alongside the code. You don't need 
> a
> browser to see it. I, for one, use neovim and a rust LSP, so I can see the
> documentation by pressing shift+k.
>
>> I realize that it might sound ridiculous for folks who spent a while
>> around Mozilla, but it's really true and kernel community actually
>> has quite a few of such freaks.
>
> I haven't spent any time around Mozilla myself (not that there's anything 
> wrong
> with it), so I can't really comment on this.
>
>> And as one of those freaks I can tell
>> you where exactly I would like you to go and what I would like you to do
>> with implicit suggestions to start a browser when I need to read some
>> in-tree documentation.
>
> I could be mistaken but you seem angry. Perhaps it wouldn't be a bad idea to
> read your own code of conduct, I don't think you need a browser for that 
> either.

Haven't you folks ever head of lynx? Good old-fashioned command-line tool that
opens html files in a terminal window, supports following links within the file,
good stuff like that. I don't see how the dinosaurs^W traditional folks could
object to that!

-- Paul


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Wedson Almeida Filho
On Fri, Apr 16, 2021 at 04:25:34AM +, Al Viro wrote:

> > Are you stating [what you perceive as] a fact or just venting? If the 
> > former,
> > would you mind enlightening us with some evidence?
> 
> How about "not everyone uses a browser as a part of their workflow"?

The documentation is available in markdown alongside the code. You don't need a
browser to see it. I, for one, use neovim and a rust LSP, so I can see the
documentation by pressing shift+k.

> I realize that it might sound ridiculous for folks who spent a while
> around Mozilla, but it's really true and kernel community actually
> has quite a few of such freaks.

I haven't spent any time around Mozilla myself (not that there's anything wrong
with it), so I can't really comment on this.

> And as one of those freaks I can tell
> you where exactly I would like you to go and what I would like you to do
> with implicit suggestions to start a browser when I need to read some
> in-tree documentation.

I could be mistaken but you seem angry. Perhaps it wouldn't be a bad idea to
read your own code of conduct, I don't think you need a browser for that either.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Boqun Feng
[Copy LKMM people, Josh, Nick and Wedson]

On Thu, Apr 15, 2021 at 08:58:16PM +0200, Peter Zijlstra wrote:
> On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> 
> > Rust is a systems programming language that brings several key
> > advantages over C in the context of the Linux kernel:
> > 
> >   - No undefined behavior in the safe subset (when unsafe code is
> > sound), including memory safety and the absence of data races.
> 
> And yet I see not a single mention of the Rust Memory Model and how it
> aligns (or not) with the LKMM. The C11 memory model for example is a
> really poor fit for LKMM.
> 

I think Rust currently uses C11 memory model as per:

https://doc.rust-lang.org/nomicon/atomics.html

, also I guess another reason that they pick C11 memory model is because
LLVM has the support by default.

But I think the Rust Community still wants to have a good memory model,
and they are open to any kind of suggestion and input. I think we (LKMM
people) should really get involved, because the recent discussion on
RISC-V's atomics shows that if we didn't people might get a "broken"
design because they thought C11 memory model is good enough:

https://lore.kernel.org/lkml/YGyZPCxJYGOvqYZQ@boqun-archlinux/

And the benefits are mutual: a) Linux Kernel Memory Model (LKMM) is
defined by combining the requirements of developers and the behavior of
hardwares, it's pratical and can be a very good input for memory model
designing in Rust; b) Once Rust has a better memory model, the compiler
technologies whatever Rust compilers use to suppor the memory model can
be adopted to C compilers and we can get that part for free.

At least I personally is very intereted to help Rust on a complete and
pratical memory model ;-)

Josh, I think it's good if we can connect to the people working on Rust
memoryg model, I think the right person is Ralf Jung and the right place
is https://github.com/rust-lang/unsafe-code-guidelines, but you
cerntainly know better than me ;-) Or maybe we can use Rust-for-Linux or
linux-toolchains list to discuss.

[...]
> >   - Boqun Feng is working hard on the different options for
> > threading abstractions and has reviewed most of the `sync` PRs.
> 
> Boqun, I know you're familiar with LKMM, can you please talk about how
> Rust does things and how it interacts?

As Wedson said in the other email, currently there is no code requiring
synchronization between C side and Rust side, so we are currently fine.
But in the longer term, we need to teach Rust memory model about the
"design patterns" used in Linux kernel for parallel programming.

What I have been doing so far is reviewing patches which have memory
orderings in Rust-for-Linux project, try to make sure we don't include
memory ordering bugs for the beginning.

Regards,
Boqun


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Al Viro
On Fri, Apr 16, 2021 at 03:22:16AM +0100, Wedson Almeida Filho wrote:

> > HTML is not a valid documentation format. Heck, markdown itself is
> > barely readable.
> 
> Are you stating [what you perceive as] a fact or just venting? If the former,
> would you mind enlightening us with some evidence?

How about "not everyone uses a browser as a part of their workflow"?
I realize that it might sound ridiculous for folks who spent a while
around Mozilla, but it's really true and kernel community actually
has quite a few of such freaks.  And as one of those freaks I can tell
you where exactly I would like you to go and what I would like you to do
with implicit suggestions to start a browser when I need to read some
in-tree documentation.

Linus might have different reasons, obviously.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Wedson Almeida Filho
On Thu, Apr 15, 2021 at 08:58:16PM +0200, Peter Zijlstra wrote:
> On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> 
> > Rust is a systems programming language that brings several key
> > advantages over C in the context of the Linux kernel:
> > 
> >   - No undefined behavior in the safe subset (when unsafe code is
> > sound), including memory safety and the absence of data races.
> 
> And yet I see not a single mention of the Rust Memory Model and how it
> aligns (or not) with the LKMM. The C11 memory model for example is a
> really poor fit for LKMM.

We don't intend to directly expose C data structures to Rust code (outside the
kernel crate). Instead, we intend to provide wrappers that expose safe
interfaces even though the implementation may use unsafe blocks. So we expect
the vast majority of Rust code to just care about the Rust memory model.

We admittedly don't have a huge number of wrappers yet, but we do have enough to
implement most of Binder and so far it's been ok. We do intend to eventually
cover other classes of drivers that may unveil unforeseen difficulties, we'll
see.

If you have concerns that we might have overlooked, we'd be happy to hear about
them from you (or anyone else).

> HTML is not a valid documentation format. Heck, markdown itself is
> barely readable.

Are you stating [what you perceive as] a fact or just venting? If the former,
would you mind enlightening us with some evidence?

> It is really *really* hard to read. It has all sorts of weird things,
> like operators at the beginning after a line break:
> 
>   if (foo
>   || bar)
> 
> which is just wrong. And it suffers from CamelCase, which is just about
> the worst thing ever. Not even the C++ std libs have that (or had, back
> when I still did knew C++).
> 
> I also see:
> 
>   if (foo) {
>   ...
>   }
> 
> and
> 
>   if foo {
>   }
> 
> the latter, ofcourse, being complete rubbish.

There are advantages to adopting the preferred style of a language (when one
exists). We, of course, are not required to adopt it but I am of the opinion
that we should have good reasons to diverge if that's our choice in the end.

"Not having parentheses around the if-clause expression is complete rubbish"
doesn't sound like a good reason to me.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Peter Zijlstra
On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:

> Rust is a systems programming language that brings several key
> advantages over C in the context of the Linux kernel:
> 
>   - No undefined behavior in the safe subset (when unsafe code is
> sound), including memory safety and the absence of data races.

And yet I see not a single mention of the Rust Memory Model and how it
aligns (or not) with the LKMM. The C11 memory model for example is a
really poor fit for LKMM.

> ## Why not?
> 
> Rust also has disadvantages compared to C in the context of
> the Linux kernel:
> 
>   - The many years of effort in tooling for C around the kernel,
> including compiler plugins, sanitizers, Coccinelle, lockdep,
> sparse... However, this will likely improve if Rust usage in
> the kernel grows over time.

This; can we mercilessly break the .rs bits when refactoring? What
happens the moment we cannot boot x86_64 without Rust crap on?

We can ignore this as a future problem, but I think it's only fair to
discuss now. I really don't care for that future, and IMO adding this
Rust or any other second language is a fail.

> Thirdly, in Rust code bases, most documentation is written alongside
> the source code, in Markdown. We follow this convention, thus while
> we have a few general documents in `Documentation/rust/`, most of
> the actual documentation is in the source code itself.
> 
> In order to read this documentation easily, Rust provides a tool
> to generate HTML documentation, just like Sphinx/kernel-doc, but
> suited to Rust code bases and the language concepts.

HTML is not a valid documentation format. Heck, markdown itself is
barely readable.

> Moreover, as explained above, we are taking the chance to enforce
> some documentation guidelines. We are also enforcing automatic code
> formatting, a set of Clippy lints, etc. We decided to go with Rust's
> idiomatic style, i.e. keeping `rustfmt` defaults. For instance, this
> means 4 spaces are used for indentation, rather than a tab. We are
> happy to change that if needed -- we think what is important is
> keeping the formatting automated.

It is really *really* hard to read. It has all sorts of weird things,
like operators at the beginning after a line break:

if (foo
|| bar)

which is just wrong. And it suffers from CamelCase, which is just about
the worst thing ever. Not even the C++ std libs have that (or had, back
when I still did knew C++).

I also see:

if (foo) {
...
}

and

if foo {
}

the latter, ofcourse, being complete rubbish.

> Another important topic we would like feedback on is the Rust
> "native" documentation that is written alongside the code, as
> explained above. We have uploaded it here:
> 
> https://rust-for-linux.github.io/docs/kernel/
> 
> We like how this kind of generated documentation looks. Please take
> a look and let us know what you think!

I cannot view with less or vim. Therefore it looks not at all.

>   - Boqun Feng is working hard on the different options for
> threading abstractions and has reviewed most of the `sync` PRs.

Boqun, I know you're familiar with LKMM, can you please talk about how
Rust does things and how it interacts?


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Kees Cook
On Thu, Apr 15, 2021 at 08:26:21AM +, David Laight wrote:
> ...
> > Besides just FP, 128-bit, etc, I remain concerned about just basic
> > math operations. C has no way to describe the intent of integer
> > overflow, so the kernel was left with the only "predictable" result:
> > wrap around. Unfortunately, this is wrong in most cases, and we're left
> > with entire classes of vulnerability related to such overflows.
> 
> I'm not sure any of the alternatives (except perhaps panic)
> are much better.
> Many years ago I used a COBOL system that skipped the assignment
> if ADD X to Y (y += x) would overflow.
> That gave a very hard to spot error when the sump of a long list
> way a little too large.
> If it had wrapped the error would be obvious.
> 
> There are certainly places where saturate is good.
> Mostly when dealing with analogue samples.
> 
> I guess the problematic code is stuff that checks:
>   if (foo->size + constant > limit) goto error;
> instead of:
>   if (foo->size > limit - constant) goto error;

Right. This and alloc(size * count) are the primary offenders. :)

-- 
Kees Cook


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Miguel Ojeda
On Thu, Apr 15, 2021 at 3:38 AM Kees Cook  wrote:
>
> Before anything else: yay! I'm really glad to see this RFC officially
> hit LKML. :)

Thanks! :)

> When originally learning Rust I was disappointed to see that (by default)
> Rust similarly ignores the overflow problem, but I'm glad to see the
> very intentional choices in the Rust-in-Linux design to deal with it
> directly. I think the default behavior should be saturate-with-WARN
> (this will match the ultimate goals of the UBSAN overflow support[1][2]
> in the C portions of the kernel). Rust code wanting wrapping/checking
> can expressly use those. The list of exploitable overflows is lng,
> and this will remain a weakness in Rust unless we get it right from
> the start. What's not clear to me is if it's better to say "math with
> undeclared overflow expectation" will saturate" or to say "all math must
> declare its overflow expectation".

+1 Agreed, we need to get this right (and ideally make both the C and
Rust sides agree...).

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread Miguel Ojeda
On Thu, Apr 15, 2021 at 2:23 AM Nick Desaulniers
 wrote:
>
> Looks like Wedson's writeup is now live. Nice job Wedson!
> https://security.googleblog.com/2021/04/rust-in-linux-kernel.html

+1 It is very nicely written and explains the semaphore samples
(included in the RFC) he wrote, with nice tables comparing how
different parts look like between C and Rust!

Anyone interested in this RFC, C or Rust, please take a look!

Cheers,
Miguel


RE: [PATCH 00/13] [RFC] Rust support

2021-04-15 Thread David Laight
...
> Besides just FP, 128-bit, etc, I remain concerned about just basic
> math operations. C has no way to describe the intent of integer
> overflow, so the kernel was left with the only "predictable" result:
> wrap around. Unfortunately, this is wrong in most cases, and we're left
> with entire classes of vulnerability related to such overflows.

I'm not sure any of the alternatives (except perhaps panic)
are much better.
Many years ago I used a COBOL system that skipped the assignment
if ADD X to Y (y += x) would overflow.
That gave a very hard to spot error when the sump of a long list
way a little too large.
If it had wrapped the error would be obvious.

There are certainly places where saturate is good.
Mostly when dealing with analogue samples.

I guess the problematic code is stuff that checks:
if (foo->size + constant > limit) goto error;
instead of:
if (foo->size > limit - constant) goto error;

David

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



Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Kees Cook
Before anything else: yay! I'm really glad to see this RFC officially
hit LKML. :)

On Wed, Apr 14, 2021 at 10:20:51PM +0200, Miguel Ojeda wrote:
>   - On floating-point, 128-bit, etc.: the main issue is that the
> `core` library is a single big blob at the moment. I have already
> mentioned this to some Rust team folks. We will need a way to "cut"
> some things out, for instance with the "feature flags" they already
> have for other crates (or they can split `core` in to several, like
> `alloc` is for similar reasons). Or we could do it on our side
> somehow, but I prefer to avoid that (we cannot easily customize `core`
> like we can with `alloc`, because it is tied to the compiler too
> tightly).

Besides just FP, 128-bit, etc, I remain concerned about just basic
math operations. C has no way to describe the intent of integer
overflow, so the kernel was left with the only "predictable" result:
wrap around. Unfortunately, this is wrong in most cases, and we're left
with entire classes of vulnerability related to such overflows.

When originally learning Rust I was disappointed to see that (by default)
Rust similarly ignores the overflow problem, but I'm glad to see the
very intentional choices in the Rust-in-Linux design to deal with it
directly. I think the default behavior should be saturate-with-WARN
(this will match the ultimate goals of the UBSAN overflow support[1][2]
in the C portions of the kernel). Rust code wanting wrapping/checking
can expressly use those. The list of exploitable overflows is lng,
and this will remain a weakness in Rust unless we get it right from
the start. What's not clear to me is if it's better to say "math with
undeclared overflow expectation" will saturate" or to say "all math must
declare its overflow expectation".

-Kees

[1] https://github.com/KSPP/linux/issues/26
[2] https://github.com/KSPP/linux/issues/27

-- 
Kees Cook


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Nick Desaulniers
On Wed, Apr 14, 2021 at 11:47 AM  wrote:
>
> From: Miguel Ojeda 
>
> Some of you have noticed the past few weeks and months that
> a serious attempt to bring a second language to the kernel was
> being forged. We are finally here, with an RFC that adds support
> for Rust to the Linux kernel.
>
> This cover letter is fairly long, since there are quite a few topics
> to describe, but I hope it answers as many questions as possible
> before the discussion starts.
>
> If you are interested in following this effort, please join us
> in the mailing list at:
>
> rust-for-li...@vger.kernel.org
>
> and take a look at the project itself at:
>
> https://github.com/Rust-for-Linux

Looks like Wedson's writeup is now live. Nice job Wedson!
https://security.googleblog.com/2021/04/rust-in-linux-kernel.html
-- 
Thanks,
~Nick Desaulniers


RE: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread David Laight
From: Linus Torvalds
> Sent: 14 April 2021 21:22
> 
> On Wed, Apr 14, 2021 at 1:10 PM Matthew Wilcox  wrote:
> >
> > There's a philosophical point to be discussed here which you're skating
> > right over!  Should rust-in-the-linux-kernel provide the same memory
> > allocation APIs as the rust-standard-library, or should it provide a Rusty
> > API to the standard-linux-memory-allocation APIs?
> 
> Yeah, I think that the standard Rust API may simply not be acceptable
> inside the kernel, if it has similar behavior to the (completely
> broken) C++ "new" operator.

ISTM that having memory allocation failure cause a user process
to exit is a complete failure in something designed to run as
and kind of service program.

There are all sorts of reasons why malloc() might fail.
You almost never want a 'real' program to abort on one.

David

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


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Josh Triplett
On Wed, Apr 14, 2021 at 01:21:52PM -0700, Linus Torvalds wrote:
> On Wed, Apr 14, 2021 at 1:10 PM Matthew Wilcox  wrote:
> >
> > There's a philosophical point to be discussed here which you're skating
> > right over!  Should rust-in-the-linux-kernel provide the same memory
> > allocation APIs as the rust-standard-library, or should it provide a Rusty
> > API to the standard-linux-memory-allocation APIs?
> 
> Yeah, I think that the standard Rust API may simply not be acceptable
> inside the kernel, if it has similar behavior to the (completely
> broken) C++ "new" operator.
> 
> So anything that does "panic!" in the normal Rust API model needs to
> be (statically) caught, and never exposed as an actual call to
> "panic()/BUG()" in the kernel.

Rust has both kinds of allocation APIs: you can call a method like
`Box::new` that panics on allocation failure, or a method like
`Box::try_new` that returns an error on allocation failure.

With some additional infrastructure that's still in progress, we could
just not supply the former kind of methods at all, and *only* supply the
latter, so that you're forced to handle allocation failure. That just
requires introducing some further ability to customize the Rust standard
library.

(There are some cases of methods in the standard library that don't have
a `try_` equivalent, but we could fix that. Right now, for instance,
there isn't a `try_` equivalent of every Vec method, and you're instead
expected to call `try_reserve` to make sure you have enough memory
first; however, that could potentially be changed.)


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Miguel Ojeda
On Wed, Apr 14, 2021 at 10:10 PM Matthew Wilcox  wrote:
>
> On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
> >   - Manish Goregaokar implemented the fallible `Box`, `Arc`, and `Rc`
> > allocator APIs in Rust's `alloc` standard library for us.
>
> There's a philosophical point to be discussed here which you're skating
> right over!  Should rust-in-the-linux-kernel provide the same memory
> allocation APIs as the rust-standard-library, or should it provide a Rusty
> API to the standard-linux-memory-allocation APIs?  You seem to be doing
> both ... there was a wrapper around alloc_pages() in the Binder patches,
> and then you talk about Box, Arc and Rc here.

Please see my reply to Linus. The Rust standard library team is doing
work on allocators, fallible allocations, etc., but that is very much
a WIP. We hope that our usage and needs inform them in their design.

Manish Goregaokar implemented the `try_reserve` feature since he knew
we wanted to have fallible allocations etc. (I was not really involved
in that, perhaps somebody else can comment); but we will have to
replace `alloc` anyway in the near feature, and we wanted to give
Manish credit for advancing the state of the art there nevertheless.

> Maybe there's some details about when one can use one kind of API and
> when to use another.  But I fear that we'll have Rust code at interrupt
> level trying to use allocators which assume that they can sleep, and
> things will go badly wrong.

Definitely. In fact, we want to have all public functions exposed by
Rust infrastructure tagged with the context they can work in, etc.
Ideally, we could propose a language feature like "colored `unsafe`"
so that one can actually inform the compiler that a function is only
safe in some contexts, e.g. `unsafe(interrupt)`. But language features
are a moonshot, for the moment we want to go with the annotation in
the doc-comment, like we do with the `Safety` preconditions and type
invariants.

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Linus Torvalds
On Wed, Apr 14, 2021 at 1:10 PM Matthew Wilcox  wrote:
>
> There's a philosophical point to be discussed here which you're skating
> right over!  Should rust-in-the-linux-kernel provide the same memory
> allocation APIs as the rust-standard-library, or should it provide a Rusty
> API to the standard-linux-memory-allocation APIs?

Yeah, I think that the standard Rust API may simply not be acceptable
inside the kernel, if it has similar behavior to the (completely
broken) C++ "new" operator.

So anything that does "panic!" in the normal Rust API model needs to
be (statically) caught, and never exposed as an actual call to
"panic()/BUG()" in the kernel.

So "Result" is basically the way to go, and if the standard Rust
library alloc() model is based on "panic!" then that kind of model
must simply not be used in the kernel.

 Linus

   Linus


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Miguel Ojeda
On Wed, Apr 14, 2021 at 9:45 PM Linus Torvalds
 wrote:
>
> With the main point of Rust being safety, there is no way I will ever
> accept "panic dynamically" (whether due to out-of-memory or due to
> anything else - I also reacted to the "floating point use causes
> dynamic panics") as a feature in the Rust model.

Agreed on all your points. As I mentioned in the other message (we
crossed emails), we have a lot of work to do regarding `alloc` and
slicing `core` for things that are not needed for the kernel
(floating-point, etc.).

We haven't done it just yet because it is not a trivial amount of work
and we wanted to have some overall sentiment from you and the
community overall before tackling everything. But it is doable and
there isn't any fundamental reason that prevents it (in fact, the
language supports no-allocation code).

Worst case, we may need to request a few bits here and there to the
`rustc` and standard library teams, but that should be about it.

In summary, to be clear:

  - On allocation: this is just our usage of `alloc` in order to speed
development up -- it will be replaced (or customized, we have to
decide how we will approach it) with our own allocation and data
structures.

  - On floating-point, 128-bit, etc.: the main issue is that the
`core` library is a single big blob at the moment. I have already
mentioned this to some Rust team folks. We will need a way to "cut"
some things out, for instance with the "feature flags" they already
have for other crates (or they can split `core` in to several, like
`alloc` is for similar reasons). Or we could do it on our side
somehow, but I prefer to avoid that (we cannot easily customize `core`
like we can with `alloc`, because it is tied to the compiler too
tightly).

Thanks a lot for having taken a look so quickly, by the way!

Cheers,
Miguel


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Matthew Wilcox
On Wed, Apr 14, 2021 at 08:45:51PM +0200, oj...@kernel.org wrote:
>   - Manish Goregaokar implemented the fallible `Box`, `Arc`, and `Rc`
> allocator APIs in Rust's `alloc` standard library for us.

There's a philosophical point to be discussed here which you're skating
right over!  Should rust-in-the-linux-kernel provide the same memory
allocation APIs as the rust-standard-library, or should it provide a Rusty
API to the standard-linux-memory-allocation APIs?  You seem to be doing
both ... there was a wrapper around alloc_pages() in the Binder patches,
and then you talk about Box, Arc and Rc here.

Maybe there's some details about when one can use one kind of API and
when to use another.  But I fear that we'll have Rust code at interrupt
level trying to use allocators which assume that they can sleep, and
things will go badly wrong.

By the way, I don't think that Rust necessarily has to conform to the
current way that Linux works.  If this prompted us to track the current
context (inside spinlock, handling interrupt, performing writeback, etc)
and do away with (some) GFP flags, that's not the end of the world.
We're already moving in that direction to a certain extent with the
scoped memory allocation APIs to replace GFP_NOFS / GFP_NOIO.


Re: [PATCH 00/13] [RFC] Rust support

2021-04-14 Thread Linus Torvalds
On Wed, Apr 14, 2021 at 11:46 AM  wrote:
>
> Some of you have noticed the past few weeks and months that
> a serious attempt to bring a second language to the kernel was
> being forged. We are finally here, with an RFC that adds support
> for Rust to the Linux kernel.

So I replied with my reactions to a couple of the individual patches,
but on the whole I don't hate it.

HOWEVER.

I do think that the "run-time failure panic" is a fundamental issue.

I may not understand the ramifications of when it can happen, so maybe
it's less of an issue than I think it is, but very fundamentally I
think that if some Rust allocation can cause a panic, this is simply
_fundamentally_ not acceptable.

Allocation failures in a driver or non-core code - and that is by
definition all of any new Rust code - can never EVER validly cause
panics. Same goes for "oh, some case I didn't test used 128-bit
integers or floating point".

So if the Rust compiler causes hidden allocations that cannot be
caught and returned as errors, then I seriously think that this whole
approach needs to be entirely NAK'ed, and the Rust infrastructure -
whether at the compiler level or in the kernel wrappers - needs more
work.

So if the panic was just some placeholder for things that _can_ be
caught, then I think that catching code absolutely needs to be
written, and not left as a to-do.

And if the panic situation is some fundamental "this is what the Rust
compiler does for internal allocation failures", then I think it needs
more than just kernel wrapper work - it needs the Rust compiler to be
*fixed*.

Because kernel code is different from random user-space system tools.
Running out of memory simply MUST NOT cause an abort.  It needs to
just result in an error return.

I don't know enough about how the out-of-memory situations would be
triggered and caught to actually know whether this is a fundamental
problem or not, so my reaction comes from ignorance, but basically the
rule has to be that there are absolutely zero run-time "panic()"
calls. Unsafe code has to either be caught at compile time, or it has
to be handled dynamically as just a regular error.

With the main point of Rust being safety, there is no way I will ever
accept "panic dynamically" (whether due to out-of-memory or due to
anything else - I also reacted to the "floating point use causes
dynamic panics") as a feature in the Rust model.

   Linus


[PATCH 00/13] [RFC] Rust support

2021-04-14 Thread ojeda
From: Miguel Ojeda 

Some of you have noticed the past few weeks and months that
a serious attempt to bring a second language to the kernel was
being forged. We are finally here, with an RFC that adds support
for Rust to the Linux kernel.

This cover letter is fairly long, since there are quite a few topics
to describe, but I hope it answers as many questions as possible
before the discussion starts.

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

rust-for-li...@vger.kernel.org

and take a look at the project itself at:

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

Cheers,
Miguel


# A second language in the kernel

We know there are huge costs and risks in introducing a new main
language in the kernel. We risk dividing efforts and we increase
the knowledge required to contribute to some parts of the kernel.

Most importantly, any new language introduced means any module
written in that language will be way harder to replace later on
if the support for the new language gets dropped.

Nevertheless, we believe that, even today, the advantages of using
Rust outweighs the cost. We will explain why in the following
sections.

Please note that the Rust support is intended to enable writing
drivers and similar "leaf" modules in Rust, at least for the
foreseeable future. In particular, we do not intend to rewrite
the kernel core nor the major kernel subsystems (e.g. `kernel/`,
`mm/`, `sched/`...). Instead, the Rust support is built on top
of those.


## Goals

By using Rust in the Linux kernel, our hope is that:

  - New code written in Rust has a reduced risk of memory safety bugs,
data races and logic bugs overall, thanks to the language
properties mentioned below.

  - Maintainers are more confident in refactoring and accepting
patches for modules thanks to the safe subset of Rust.

  - New drivers and modules become easier to write, thanks to
abstractions that are easier to reason about, based on modern
language features, as well as backed by detailed documentation.

  - More people get involved overall in developing the kernel
thanks to the usage of a modern language.

  - By taking advantage of Rust tooling, we keep enforcing the
documentation guidelines we have established so far in the
project. For instance, we require having all public APIs, safety
preconditions, `unsafe` blocks and type invariants documented.


## Why Rust?

Rust is a systems programming language that brings several key
advantages over C in the context of the Linux kernel:

  - No undefined behavior in the safe subset (when unsafe code is
sound), including memory safety and the absence of data races.

  - Stricter type system for further reduction of logic errors.

  - A clear distinction between safe and `unsafe` code.

  - Featureful language: sum types, pattern matching, generics,
RAII, lifetimes, shared & exclusive references, modules &
visibility, powerful hygienic and procedural macros...

  - Extensive freestanding standard library: vocabulary types such
as `Result` and `Option`, iterators, formatting, pinning,
checked/saturating/wrapping integer arithmetic, etc.

  - Integrated out of the box tooling: documentation generator,
formatter and linter all based on the compiler itself.

Overall, Rust is a language that has successfully leveraged decades
of experience from system programming languages as well as functional
ones, and added lifetimes and borrow checking on top.


## Why not?

Rust also has disadvantages compared to C in the context of
the Linux kernel:

  - The many years of effort in tooling for C around the kernel,
including compiler plugins, sanitizers, Coccinelle, lockdep,
sparse... However, this will likely improve if Rust usage in
the kernel grows over time.

  - Single implementation based on LLVM. There are third-party
efforts underway to fix this, such as a GCC frontend,
a `rustc` backend based on Cranelift and `mrustc`,
a compiler intended to reduce the bootstrapping chain.
Any help for those projects would be very welcome!

  - Not standardized. While it is not clear whether standardization
would be beneficial for the kernel, several points minimize
this issue in any case: the Rust stability promise, the extensive
documentation, the WIP reference, the detailed RFCs...

  - Slower compilation in general, due to more complex language
features and limitations in the current compiler.

  - At the present time, we require certain nightly features.
That is, features that are not available in the stable compiler.
Nevertheless, we aim to remove this restriction within a year
by either `rustc` landing the features in stable or removing
our usage of them otherwise. We maintain a report here:

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

  - Bigger than needed text currently, due to the unused parts from
the `core` and `alloc` Rust standard