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

Is there a mechanism to emulate only CAS operations? #123

Closed
romancardenas opened this issue Oct 2, 2023 · 6 comments · Fixed by #124
Closed

Is there a mechanism to emulate only CAS operations? #123

romancardenas opened this issue Oct 2, 2023 · 6 comments · Fixed by #124
Labels
C-enhancement Category: A new feature or an improvement for an existing one O-riscv Target: RISC-V architecture

Comments

@romancardenas
Copy link

I'm working with the SparkFun RED-V RedBoard, which contains an E310g002 RISC-V microcontroller. This microcontroller is supposed to support atomic operations, and therefore I can compile projects targeting riscv32imac-unknown-none-elf. However, this microcontroller always raises an exception for CAS instructions (i.e., in practice only amoxxx instructions are allowed).

Is there any mechanism to configure portable-atomic to only emulate CAS instructions while natively executing the other atomic operations? Or am I doomed to compiling for riscv32imc-unknown-none-elf and forgetting about native atomic support?

Thanks in advance!

@taiki-e
Copy link
Owner

taiki-e commented Oct 2, 2023

However, this microcontroller always raises an exception for CAS instructions (i.e., in practice only amoxxx instructions are allowed).

Is this an officially recognized bug? If not, it is not very clear whether it is a bug in the chip or a bug in your environment.

For example, I have seen several cases where there is a bug in the linker script, resulting in misalignment (mvdnes/spin-rs#154 (comment), rust-lang/rust#86693, etc.). Atomic instructions require proper alignment, so I would not be surprised if some atomic instructions caused exceptions in such cases. Could you check to see if the pointer is aligned correctly?

If this is really a bug in the chip, I can consider providing a way to work around it in some way.

@romancardenas
Copy link
Author

It is not a bug, it is a (very annoying) feature.

The microcontroller datasheet explicitly mentions that it supports atomic operations except CAS, which raise a LoadFault/StoreFault exception.

@taiki-e
Copy link
Owner

taiki-e commented Oct 7, 2023

The microcontroller datasheet explicitly mentions that it supports atomic operations except CAS, which raise a LoadFault/StoreFault exception.

Thanks for the clarification.

I can compile projects targeting riscv32imac-unknown-none-elf

As far as I know, at least both LLVM and GCC treat RISC-V with the A extension as if all instructions in the A extension are available (godbolt). So, compiling as riscv32imac for this CPU should usually be considered unsound because it is impossible to safely run a binary that is compiled as riscv32imac, even though it claims to be riscv32imac (unless you can ensure that the instructions causing the problem are not used by auditing the standard library, all dependencies, and the C library to which it is linked).

So, we should compile as riscv32imc for this CPU, which supports some instructions of the A extension.

only emulate CAS instructions while natively executing the other atomic operations

RISC-V A extension does not actually have CAS instructions and has LR/SC and AMO (CAS is implemented by using LR/SC), but the actual situation here is more complicated:

  • RISC-V does not have {8,16}-bit AMOs, so some of the {8,16}-bit atomic RMWs are implemented by using LR/SC, which isn't supported in this CPU. (godbolt)
  • There is not an AMO for all the operations we provide, CAS is probably not the only operation for which we actually need to provide emulation. (e.g., fetch_neg)
  • If the A extension is not enabled, the compiler will not generate code that uses AMO.

Considering the above, the implementation would be in the form of:

  • Add Cargo feature to use AMO on RISC-V without A extension (such as riscv32imc).
    • This feature requires unsafe-assume-single-core feature.
      • critical-section implementation may not be lock-free, so it cannot be used together with critical-section feature for now.
  • Use AMO for 32-bit RMWs that have corresponding AMO instructions and {8,16}-bit RMWs that can be emulated by 32-bit AMOs (e.g., fetch_and/fetch_or).
    • Other RMWs will be emulated as before.
  • Use inline assembly for implementation.
    • I have code that implements atomics in AMO in another repository, so it would basically be porting and extending that code.
      • Instructions in the A extension are not available on RISC-V without A extension by default, but can be made available by using the .option arch, +a directive.

Any thoughts?

@romancardenas
Copy link
Author

Sorry for not being precise. The instructions that are missing in E310x are LR and SC.

I agree with your approach:

  • We compile for riscv32imc targets.
  • We add a feature to use LR/SC-free AMO instructions when available.
    • We use the unsafe-assume-single-core feature for the other atomic functions.

@taiki-e taiki-e added C-enhancement Category: A new feature or an improvement for an existing one O-riscv Target: RISC-V architecture labels Oct 10, 2023
@taiki-e
Copy link
Owner

taiki-e commented Oct 10, 2023

Filed #124 to implement this.

@taiki-e
Copy link
Owner

taiki-e commented Oct 23, 2023

#124 has been published in 1.5.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: A new feature or an improvement for an existing one O-riscv Target: RISC-V architecture
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants