Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building Tock with stable rustc #1654

Open
24 of 28 tasks
mcy opened this issue Mar 3, 2020 · 29 comments
Open
24 of 28 tasks

Building Tock with stable rustc #1654

mcy opened this issue Mar 3, 2020 · 29 comments

Comments

@mcy
Copy link
Contributor

mcy commented Mar 3, 2020

This issue tracks attempting to build as many Tock libraries as possible with a stable compiler, that is, minimizing the number of #![feature(...)] pragmas used in lib.rs files.

Update Feb 2024

Cortex-M crates can now compile on stable!

Nightly Features

This work is especially attractive to OpenTitan's use of Tock as a secure embedded operating system. Being able to build code without exercising unstable (and, as such, untested and unproven) code paths in the compiler increases confidence in the language-level and hardware-level guarantees provided by Tock. This is not to mention that unstable features are not guaranteed to be stabilized, or to remain in the compiler indefinitely.

This work is divided up according to pragmas still present after #1643, which every pragma that could be removed without causing build failures. Below is a list of all pragmas Tock still uses.

Please comment additional pragmas below as they are used, or edit this list to include them if you have write access.

@alevy
Copy link
Member

alevy commented Mar 3, 2020

Thanks @mcy, this is excellent!

@pfmooney
Copy link
Contributor

pfmooney commented Mar 3, 2020

Indeed. Thanks for your work on this.

asm and naked_functions. Assembly is a hard requirement for any kernel, it is possible to move all of it into .S files instead. This will require build system work to invoke LLVM's assembler through clang or similar. There have been attempts to stabilize this recently (which I have been involved in); driving stabilization forward is also an option, though the stable syntax is likely to be incompatible with the current one, which is just a Clang/GCC dialect.

If there are any other features which mandate sticking with nightly in the short-to-medium term, I hope we would keep asm and naked_functions so this code could remain inline until the "native" rust option stabilizes.

@mcy
Copy link
Contributor Author

mcy commented Mar 4, 2020

Regarding inline assembly, there seems to be some degree of contention on whether inline assembly is even a good idea, in principle (I mostly lean towards the .S side but that's because I think GCC/Clang constraint syntax is hot garbage). I still need to look into pushing stabilization forward; I was very involved in the most recent effort to specify a syntax (I yelled at them very loudly to explicitly support RISC-V).

We can answer the question of inline assembly later; plowing through the other bullet points will probably take me a while, and I think the fate of inline assembly is RFC-worthy.

@bradjc
Copy link
Contributor

bradjc commented Mar 4, 2020

The tension in the initial pull requests is, I think, getting at a deeper issue than just switching toolchains. Pushing towards using stable represents a change in how Tock views Rust. When we started, just creating any architecture for an OS for embedded systems using Rust that an embedded engineer would understand and find reasonable was a challenge, given the disconnect between how embedded software is traditionally written and Rust's ownership model. But, we thought it was worth seeing if Rust could provide any benefit. As Tock developed, the attitude of "let's see what tools Rust can give us" persisted, and I think that has manifested as a willingness to embrace new features of the language and explore how they can be used, like:

  • Do they help with sharing code between embedded platforms?
  • Do they make it easier for a C programmer to understand Rust?
  • Can we remove Tock-specific code and use Rust-provided abstractions instead?
  • Can we eliminate unsafe and the chance for panics?

So, the question might be, is now the right time to say we expect to be able to leverage fewer Rust features to our benefit, and are better served with the stable toolchain? Or is Rust continuing to push with new features that will make it easier to develop Tock, and we shouldn't miss out/delay their use for months? Or has Tock progressed enough that its goals on this issue should change?


My opinion has been that if we can't use stable anyway (because of assembly), then we shouldn't be in this halfway state where we have to use the nightly toolchain, but then also don't get to try out any of its new features. Now, however, if there is a reasonable roadmap to switching to the stable compiler then it might be worth making the change. But, I'm not sure that March 2020 is the deadline to say that if a feature has not been stabilized by now, then Tock cannot use it. I would rather wait until a switch to stable is imminent. Maybe this could be part of Tock 2.0?

@gendx
Copy link
Contributor

gendx commented Mar 4, 2020

Thanks for setting up the list and starting cleaning up the low-hanging fruits!

My comment would go in the opposite direction, but is also quite hypothetical at this stage. Anyway, since we're discussing unstable features here, what about adding more features in the future?

I'm mostly thinking about const generics (which are still highly unstable and not usable for many cases yet, hence the "hypothetical"). However, I see them bringing value in Tock as well.

In particular, because dynamic memory allocation is restricted in Tock, many structures are defined as constant or static arrays of a const size. This means that either the size is fixed and unconfigurable, or we have to pass slices around to support tuning the size for each board or to quickly modify it. Slices have their own set of problems, notably that a suitable lifetime (usually 'static) has to be passed around, and that the Rust compiler limits what's possible w.r.t. statics and w.r.t. borrowing.

Here are a couple of example where I see them bringing value in Tock

  • It was proposed recently in RFC: use const generics for ipc arrays #1585 to have IPC array take a const generic size.
  • Another example that comes to mind is the RingBuffer, which currently takes a slice. It'd be useful to have ring buffer incorporating their own array, but that requires either separately creating a static array (which can be quite tricky given Rust's borrowing rules and limitations around statics), using something like Pin to be able to have a self-referential struct, or using const generics. Here are a couple examples.
// Self-referential struct
struct SelfRingBuffer<T> {
    // Easy to change the size.
    array: [T; 16],
    // Intrusive ring buffer which should reference &self.array.
    ring_buffer: RingBuffer<T>,
}

// Const-generic struct.
struct FixedRingBuffer<T, const N: usize> {
    array: [T; N],
    head: usize,
    tail: usize,
}

In many cases, macros could be used to simulate const-generics, but I don't think that'd be clearer (e.g. worse error messages, not the same level of type checking).

Of course, this is still highly hypothetical as const-generics are not nearly stable enough, but on the other hand given the value they will bring to the Rust ecosystem as a whole, I don't see them as a feature being abandoned by the community - and they will likely eventually be stabilized (although no idea when).

So my question is: what's Tock position regarding adding new unstable features in the future? What bar (current and future stability? value proposition?) should an unstable feature pass to be used in Tock?

@ppannuto
Copy link
Member

ppannuto commented Mar 4, 2020

So my question is: what's Tock position regarding adding new unstable features in the future? What bar (current and future stability? value proposition?) should an unstable feature pass to be used in Tock?

I think historically the answer has been "no bar". If it's in the officially released nightly compiler, it's fair game. We've viewed Tock as a project written in the language "unstable Rust" so anything in the official language (as defined by the compiler that exists for it) is valid.

@gendx
Copy link
Contributor

gendx commented Mar 4, 2020

I think historically the answer has been "no bar". If it's in the officially released nightly compiler, it's fair game. We've viewed Tock as a project written in the language "unstable Rust" so anything in the official language (as defined by the compiler that exists for it) is valid.

I think we should be a bit more nuanced than "whatever is possible today is valid". We regularly update the compiler version (e.g. due to compiler bugs, or to adopt more recent features). I don't think Tock should end up in a situation where:

  • Some shiny_feature is available on week 1. We jump on it to implement some cool component.
  • On week 2, a new compiler has more_shiny_feature, supports CPU architecture awesome and fixes a critical bug in the nightly compiler, but shiny_feature isn't available anymore.

What should we do? Stay stuck on week 1's compiler? Rollback all the changes to migrate to week 2?

This is of course an extreme example, and the Rust compiler has generally been good at avoiding such situations even in nightly (especially given how many projects rely on nightly for the unstable features that it provides). But the more features we use, the riskier it is to end up in such a situation.

Another possible problem is if the nightly of day D has a critical bug, because it's nightly.

For better or worse, Rust is sometimes slow at stabilizing features, which makes nightly more appealing to many projects. But trimming down to "essential" features only (with a minimal bar for allowed features) can reduce the risks, especially as Tock grows to more stakeholders (more developers, more architectures/boards, more applications).

@gkelly
Copy link
Contributor

gkelly commented Mar 4, 2020

So my question is: what's Tock position regarding adding new unstable features in the future? What bar (current and future stability? value proposition?) should an unstable feature pass to be used in Tock?

I think historically the answer has been "no bar". If it's in the officially released nightly compiler, it's fair game. We've viewed Tock as a project written in the language "unstable Rust" so anything in the official language (as defined by the compiler that exists for it) is valid.

I believe that there's a strong argument to be made from a safety standpoint for using stable rust. I believe the unstable features receive significantly less testing than the core stable set, just by virtue of fewer programs ever getting written against them. I also worry about features rotting. Just because it was safe at the original time of implementation to depend on that feature I don't feel comfortable depending on ones who have no clear path to inclusion in rust-stable. If the feature does break the only recourse we have is to fix it after the fact.

@pfmooney
Copy link
Contributor

pfmooney commented Mar 4, 2020

untagged_unions. Allows putting non-Copy traits in unions. Using this is basically asking for weird dtor behavior and general unsoundness. We use it in one place, and can probably just plug the hole with the stable DropManually API (which is just an untagged_union without sharp edges).

Looking at the one piece of code using this, it seems we could solve the specific case by extending tock-registers to support a dual-type mode for device registers which have different behavior/formats for read and write.

@phil-levis
Copy link
Contributor

My opinion has been that if we can't use stable anyway (because of assembly),

I'll go on the record saying I've always been against inline assembly. I'd prefer to just write assembly, follow the C ABI, and then import these functions into Rust as C functions. This is what I do in my (non-Tock) embedded systems work.

@pfmooney
Copy link
Contributor

pfmooney commented Mar 6, 2020

I'll go on the record saying I've always been against inline assembly. I'd prefer to just write assembly, follow the C ABI, and then import these functions into Rust as C functions. This is what I do in my (non-Tock) embedded systems work.

There are a few cases, like the riscv-csr crate, which would be onerous to implement in that fashion. (The CSR identifier is a constant immediate in the instructions, so the rust compiler smarts are pretty great at enabling a nice interface for crate consumers)

@bradjc bradjc mentioned this issue Mar 6, 2020
2 tasks
bors bot added a commit that referenced this issue Mar 7, 2020
1670: update rust to 2020-03-06 r=niklasad1 a=bradjc

### Pull Request Overview

Update Rust version to fix #1657.

The life of running on nightly, I guess :) Probably an argument for #1654


### Testing Strategy

This pull request was tested by travis


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make formatall`.


Co-authored-by: Brad Campbell <bradjc5@gmail.com>
@bradjc
Copy link
Contributor

bradjc commented Mar 9, 2020

Any thoughts on try_trait rust-lang/rust#42327? That proved to be very useful in #1480.

@alevy
Copy link
Member

alevy commented Mar 9, 2020

Any thoughts on try_trait rust-lang/rust#42327? That proved to be very useful in #1480.

@bradjc I believe this has a very high chance of becoming stable in the not far future.

bors bot added a commit that referenced this issue Mar 17, 2020
1661: Handle device register aliases explicitly r=ppannuto a=pfmooney

### Pull Request Overview

This addresses the `untagged_unions` portion of #1654.  By providing an explicit interface for registers which feature different functions and formats based on if they are written or read, we can avoid using a `union` type while still enjoying type safety for values traversing `reg.write()` or the register read functions.

### Testing Strategy

I lack the hardware to confirm that the one effected chip/board still functions as expected.

### TODO or Help Wanted

Testing on the board in question would be very helpful.

### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make formatall`.


Co-authored-by: Patrick Mooney <pmooney@pfmooney.com>
Co-authored-by: Pat Pannuto <pat.pannuto@gmail.com>
@bradjc
Copy link
Contributor

bradjc commented Mar 31, 2020

Any thoughts on cell_update rust-lang/rust#50186? It is used in #1718.

@alistair23
Copy link
Contributor

cell_update looks useful, but we can always just take() and then replace() the Cell value so it doesn't let us do something we couldn't already.

@lschuermann
Copy link
Member

Indeed. However it let's us write code in a way more aligned to what's commonly done with TakeCell and MapCell. I often tend to forget the set() part of the Cell update. It's only development ergonomics, and I'm fine either way - with or without the feature.

@lschuermann
Copy link
Member

I'm using associated_type_defaults rust-lang/rust#29661 in #1727 too. Can be easily removed though, if it doesn't become stable in the near future.

bors bot added a commit that referenced this issue Jun 19, 2020
1958: Remove core::intrinsics::math r=ppannuto a=bradjc

Part of #1654.

This math is old, and probably shouldn't be in the kernel. The only thing using it is a capsule for an obsolete chip. There was some discussion about this somewhere, and I think the conclusion was we don't really need a capsule for a sensor that is not on any boards and is an obsolete part.



### Testing Strategy

travis


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Brad Campbell <bradjc5@gmail.com>
bors bot added a commit that referenced this issue Jun 19, 2020
1955: kernel: remove panic_info_message feature r=ppannuto a=bradjc

### Pull Request Overview

Part of #1654 .

Before:

```
[INFO   ] Using "/dev/cu.usbserial-c098e5130152 - Hail IoT Module - TockOS".
[INFO   ] Listening for serial output.
Initialization complete. Entering main loop.

Kernel panic at kernel/src/process.rs:517:
	"Restart threshold surpassed!"
	Kernel version release-1.5-549-g313a5e122

---| No debug queue found. You can set it with the DebugQueue component.

---| Fault Status |---
Data Access Violation:              true
Forced Hard Fault:                  true
Faulting Memory Address:            0x00000000
Fault Status Register (CFSR):       0x00000082
```

After:

```
[INFO   ] Waiting for other tockloader to finish before listening
[INFO   ] Resuming listening...
[INFO   ] Listening for serial output.
Initialization complete. Entering main loop.

panicked at 'Restart threshold surpassed!', kernel/src/process.rs:517:13
	Kernel version release-1.5-550-g6ad2749fe

---| No debug queue found. You can set it with the DebugQueue component.

---| Fault Status |---
Data Access Violation:              true
Forced Hard Fault:                  true
Faulting Memory Address:            0x00000000
Fault Status Register (CFSR):       0x00000082
Hard Fault Status Register (HFSR):  0x40000000
```


### Testing Strategy

This pull request was tested with crash dummy app on hail.


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Brad Campbell <bradjc5@gmail.com>
bors bot added a commit that referenced this issue Jun 19, 2020
1957: Remove core_intrinsics offset feature r=ppannuto a=bradjc

### Pull Request Overview

Part of #1654. Removes the offset intrinsic.


### Testing Strategy

travis


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


1959: HIL: remove 'static from sensors r=ppannuto a=bradjc

### Pull Request Overview
Part of #1074. Removes 'static from clients in sensors HIL.


### Testing Strategy

travis.


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Brad Campbell <bradjc5@gmail.com>
@bradjc
Copy link
Contributor

bradjc commented Jul 15, 2020

Does anyone know how we can support DefferedCall (which uses AtomicUsize) on earlgrey (rv32imc) without core_intrinsics?

@hudson-ayers
Copy link
Contributor

hudson-ayers commented Jul 17, 2020

Does anyone know how we can support DeferedCall (which uses AtomicUsize) on earlgrey (rv32imc) without core_intrinsics?

(I might be exposing myself here as not understanding something as well as I should).

Why does DeferedCall require atomics? I don't think I was particularly involved at the time they were introduced, but here is my understanding of how they work:

  1. They are only set from within the kernel

  2. They are never set from interrupt context

  3. They are never read from interrupt context

  4. We only ever have 1 kernel thread, so effectively all of these things are done from the same thread.

So why is it necessary that setting deferred calls or servicing them requires atomics? Can we not just use a cell?

For anyone curious, #687 seems to have originally added DeferredCall, and I couldn't find a description there for why atomics are needed either.

bors bot added a commit that referenced this issue Jul 17, 2020
2010: Remove OptionalCell's dependency on feature(const_fn) using `impl<T: Copy>` r=bradjc a=jrvanwhy

### Pull Request Overview

This pull requests makes `OptionalCell` work with non-`Copy` types. This allows it to work without `#![feature(const_fn)]`. I rewrote a few methods that used `Cell::get` (which requires `T` to be `Copy`) that didn't need `T: Copy`.

`tock-cells` still needs `#![feature(const_fn)]` because `TakeCell` contains a mutable reference type, which cannot be initialized in `const` context without `const_fn`. Removing that dependency is possible but would require more `unsafe`, as we would need to replace `TockCell`'s reference with a raw pointer.

I have made the same semantic change using different syntax in #2009 ; I'd like input on which approach seems better.

This change helps migrate towards stable Rust (#1654).

### Testing Strategy

I commented out `#![feature(const_fn)]` and `pub mod take_cell;` in `libraries/tock-cells/src/lib.rs` then ran `cargo check` in `tock-cells` to verify I removed the dependency on `const_fn`. I reverted that change before committing.

I also ran `make allcheck` and `make fmt` in the root of this repository.

### TODO or Help Wanted

I also sent #2009, which makes the same improvement in an equivalent but syntactically-different manner (using an `impl<T: Copy>` block rather than `where` clauses). I'd like feedback on which approach you find more maintainable.


### Documentation Updated

- [X] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [X] Ran `make prepush`.


Co-authored-by: Johnathan Van Why <jrvanwhy@google.com>
@hudson-ayers
Copy link
Contributor

I updated the top level comment with my understanding of the current state of things. To summarize remaining major blockers:

  1. Transition all llvm_asm!() --> asm!(), and wait for asm!() to stabilize. Ideally, we should encourage new contributions to use the new macro.

  2. core_intrinsics. To remove all uses of atomics in the Kernel, we need to modify DeferredCall to not use atomics. This should be safe to do given the design of the Tock kernel, but will require careful review.

  3. const_fn. Board-based instantiation of chip drivers and interrupt --> driver mapping for Apollo3 + SAM4L #2069 presents a design that makes removal of almost all uses of const_fn possible. But the tock register interface still requires it, and removing its use there may be difficult, and is IMO the only remaining open question on the journey to stable.

I think all other remaining features could be removed without too much effort, but deserve to be used for now in the event that they become stabilized before these blockers are resolved.

bradjc added a commit that referenced this issue Jan 12, 2021
Re: #1654

As of Jan 2021, doesn't _seem_ to be making much progress in Rust:
rust-lang/rust#29661
bors bot added a commit that referenced this issue Jan 12, 2021
2325: Add support for WeAct board based on the stm32f401ccu6 chip r=bradjc a=yusefkarim

### Pull Request Overview

This pull request adds support for a [WeAct development board](https://github.com/WeActTC/MiniF4-STM32F4x1) by adding `chips/stm32f401ccu6` and `boards/weact_f401ccu6`. I purchased the board [online here](https://www.banggood.com/STM32F401-Development-Board-STM32F401CCU6-STM32F4-Learning-Board-p-1568897.html?rmmds=search&cur_warehouse=CN)

### Testing Strategy

Tested on-board LED (PC13) by toggling it in the kernel.

Tested UART (USART2) by connecting pins A3 and A2 to a Serial-to-USB adapter and confirming output.

I have added support for this board in Tockloader and can make a pull request there if this gets merged.

### Help Wanted

The on-board button (PA0) is not working. It was tested by uploading `examples/buttons` from libtock-c. I have [bare-metal code with the button working](https://github.com/yusefkarim/STM32F4-Projects/blob/master/rust_without_hal/05_external_interrupt/src/main.rs) (using PA0 and EXTI0 for interrupts).

It would be appreciated if someone more familiar with setting up EXTI0 and an input pin in Tock could look at `boards/weact_f401ccu6/src/main.rs`.

### Documentation Updated

no updates are required.

### Formatting

- [x] Ran `make prepush`.


2346: Remove associated_type_defaults feature r=hudson-ayers a=bradjc

Re: #1654

This feature doesn't _seem_ to be making much progress in Rust: rust-lang/rust#29661.

Also, that was easy.




### Testing Strategy

travis


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Yusef Karim <yusefkarim@riseup.net>
Co-authored-by: Brad Campbell <bradjc5@gmail.com>
@bradjc bradjc pinned this issue Feb 18, 2022
@hudson-ayers
Copy link
Contributor

Update of major blockers to stable Rust:

  1. core_intrinsics. As before, I still believe this could be safely removed with just some implementation effort.
  2. asm_sym + naked_functions: Removing either of these would be very difficult, but both have been nominated for stabilization (and naked_functions has been approved for stabilization), so these are no longer much of a concern.
  3. asm_const: Only one use remains after Remove one use of asm_const #3083 is merged. This use in in riscv_csr. Removing that use would require going back to either the switch statement approach to CSRs (e.g. before https://github.com/tock/tock/pull/2472/files), or revisiting the macro-based approach that Alistair suggested (https://github.com/tock/tock/pull/2470/files), but is certainly technically possible at the expense of that file being harder to maintain.

Everything else is either in boards/ or an option passed in our Makefile, and as such does not prevent any downstream user from using stable Rust, and as such less important to resolve.

bors bot added a commit that referenced this issue Jul 22, 2022
3082: Remove `#![feature(const_mut_refs)]` r=bradjc a=hudson-ayers

### Pull Request Overview

This PR removes the `const_mut_refs` unstable feature and all uses of it. For the most part, this just required making every const constructor that created a `TakeCell` no longer const, as a result of `TakeCell::empty()` no longer being const. Thanks to the updated peripheral instantation approach in #2069 and related PRs, this was very straightforward to perform, as peripherals no longer need to be created in const context.

### Testing Strategy

This pull request was tested by compiling, no functional changes are included.


### TODO or Help Wanted

N/A

### Documentation Updated

- [x] I will update #1654 if/when this is merged.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Hudson Ayers <hayers@stanford.edu>
bors bot added a commit that referenced this issue Oct 28, 2022
3303: Update Nightly Oct 2022 and remove `asm_sym` feature r=lschuermann a=bradjc

### Pull Request Overview
With rust-lang/rust#103168 merged, we can remove the `asm_sym` feature in support of #1654.


### Testing Strategy

travis


### TODO or Help Wanted

n/a


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Brad Campbell <bradjc5@gmail.com>
Co-authored-by: Leon Schuermann <leon@is.currently.online>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Project Tracking
Idea / Discussion
Development

No branches or pull requests