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

Add critical-section 1.0 implementation, fix multicore unsoundness. #110

Merged
merged 2 commits into from Oct 13, 2022

Conversation

Dirbaio
Copy link
Member

@Dirbaio Dirbaio commented Aug 21, 2022

Requires #109

This adds a critical-section implementation for single-core chips, based on disabling all interrupts.

interrupt::free is is unsound on multicore systems because it only disables interrupts in the
current core. For multicore chips, a chip-specific critical section implementationis needed instead. Unsoundness is fixed by not returning the CriticalSection token.

This is a breaking change.

This is the riscv equivalent of rust-embedded/cortex-m#447 and rust-embedded/cortex-m#448

Copy link
Member

@dkhayes117 dkhayes117 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Looks good. but I will defer to disasm for final review.

dkhayes117
dkhayes117 previously approved these changes Aug 21, 2022
[dependencies]
bare-metal = "1.0.0"
bit_field = "0.10.0"
critical-section = "1.1.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it optional maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's required unconditionally by the singleton! macro

(and the macro can still be used if critical-section-single-core is not enabled, if the user supplies a c-s implementation from somewhere else, such as a chip-specific impl for a multicore chip, from its HAL crate)

@Disasm
Copy link
Member

Disasm commented Aug 22, 2022

The goal is to release it in 0.8.x so critical-section becomes usable without having to wait for 0.9.

Next release will be "breaking" anyways because one breaking change is already merged. I'd prefer to have this change together with other critical-section-related changes.

@Dirbaio
Copy link
Member Author

Dirbaio commented Aug 22, 2022

Next release will be "breaking" anyways because one breaking change is already merged. I'd prefer to have this change together with other critical-section-related changes.

Oh okay, hadn't noticed that. I've folded PR #111 into this one.

@Dirbaio Dirbaio changed the title Add implementation for critical-section 1.0 for single-core chips. Add critical-section 1.0 implementation, fix multicore unsoundness. Aug 22, 2022
bors bot added a commit to rust-embedded/svd2rust that referenced this pull request Aug 24, 2022
651: Use `critical_section` for `Peripherals::take`. r=therealprof a=reitermarkus

- `cortex_m` rust-embedded/cortex-m#447
- `msp430` rust-embedded/msp430#13
- `riscv` rust-embedded/riscv#110
-  `xtensa_lx` esp-rs/xtensa-lx#20, esp-rs/esp-hal#151
- `mips_mcu` kiffie/pic32-rs#5


Co-authored-by: Markus Reiter <me@reitermark.us>
@almindor
Copy link
Contributor

@Dirbaio sorry I complicated this a bit, we released 0.9 due to a botched 0.8.1 (which contained some other breaking changes and we had to yank it). Could you please bump the changelog? I think that's the only blocker here.

@Dirbaio
Copy link
Member Author

Dirbaio commented Oct 12, 2022

Rebased

Copy link
Contributor

@almindor almindor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I think we might want to look at core vs hart terminlogy and meaning before proceeding.

src/interrupt.rs Outdated

/// Disables all interrupts
/// Disables all interrupts in the current core.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should specify what core means in RISC-V context here. e.g. is it a hard or an actual core with its own fetching unit.

CHANGELOG.md Outdated
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added

- Added `critical-section-single-core` feature which provides an implementation for the `critical_section` crate for single-core systems, based on disabling all interrupts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as below, I wonder if this should be critical-section-single-hart instead. TBF I'm not quite sure on this myself, I didn't use interrupts much yet, will review the spec a bit better.

@Dirbaio
Copy link
Member Author

Dirbaio commented Oct 12, 2022

I'm afraid I don't know enough about riscv to know what's the difference between "core" and "hart" so I'll do whatever you guys choose :)

@almindor
Copy link
Contributor

almindor commented Oct 12, 2022

I'm afraid I don't know enough about riscv to know what's the difference between "core" and "hart" so I'll do whatever you guys choose :)

Heh sadly neither do I. My current understanding is that a core is a 1+ hard (hardware thread) that has its own fetch instructions mechanism. A hard is a separate execution environment but it does not include the fetcher.

Interrupts seem to be mixed between these two, some seem to be core-wide and some seem to be hard-specific but maybe I'm misunderstanding this. I'll try to get a better understanding first so we don't have to fix some UB later.

@FawazTirmizi
Copy link
Contributor

In this case, I think hart is the correct term to use over core. The acquire() and release() functions disable/enable interrupts for the hart by flipping mstatus::mie.

Interrupts seem to be mixed between these two, some seem to be core-wide and some seem to be hard-specific but maybe I'm misunderstanding this.

As far as I am aware, there is nothing ratified that defines "core-wide" interrupts, although an interrupt controller like the PLIC could be configured to route a set of interrupts to all of the harts on a core. This eventually may not always be true, as Section 2 of the Smclic extension does say:

While the current CLIC provides only hart-local interrupt control, future additions might also support directing interrupts to harts within a core, hence the name ...

However, there isn't any further mention of this in the spec so far.

It's entirely possible that I've missed something here; there are a lot of specs relating to interrupts.

@almindor
Copy link
Contributor

In this case, I think hart is the correct term to use over core. The acquire() and release() functions disable/enable interrupts for the hart by flipping mstatus::mie.

Interrupts seem to be mixed between these two, some seem to be core-wide and some seem to be hard-specific but maybe I'm misunderstanding this.

As far as I am aware, there is nothing ratified that defines "core-wide" interrupts, although an interrupt controller like the PLIC could be configured to route a set of interrupts to all of the harts on a core. This eventually may not always be true, as Section 2 of the Smclic extension does say:

While the current CLIC provides only hart-local interrupt control, future additions might also support directing interrupts to harts within a core, hence the name ...

However, there isn't any further mention of this in the spec so far.

It's entirely possible that I've missed something here; there are a lot of specs relating to interrupts.

I think you are correct, we should probably rename things to be hart specific.

This is unsound on multi-hart because it only disables interrupts in the
current hart. For multi-hart chips, a chip-specific critical section implementation
is needed instead.

Unsoundness is fixed by not returning the `CriticalSection` token.

This is a breaking change.
@Dirbaio
Copy link
Member Author

Dirbaio commented Oct 12, 2022

Changed core -> hart.

Copy link
Contributor

@almindor almindor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@almindor
Copy link
Contributor

bors r+

@bors
Copy link
Contributor

bors bot commented Oct 13, 2022

Build succeeded:

@bors bors bot merged commit d9c6076 into rust-embedded:master Oct 13, 2022
romancardenas pushed a commit that referenced this pull request Nov 17, 2023
110: fix: avoid rust-analyzer snake case warning r=almindor a=sethp

It seems that rust-analyzer needs to operate over the expanded text of the proc macro (in order to e.g. support completion in the function body, see #11014 for way more details), so it "sees" the non-snake-case name emitted by riscv-rt's `entry` here.

Without this change, rust-analyzer will show a "weak warning" on invocations of `#[entry]` with the text:

```
Function `__risc_v_rt__main` should have snake_case name, e.g. `__risc_v_rt_main`
```

Co-authored-by: sethp <seth@codecopse.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants