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 RISC-V platform and PAUSE instruction #1262

Merged
merged 2 commits into from
Dec 5, 2021

Conversation

luojia65
Copy link
Contributor

@luojia65 luojia65 commented Dec 2, 2021

This pull request contains two parts: new RISC-V platform core::arch package, and a first platform specific instruction wrapper pause() function on RISC-V platform.

As is defined in RISC-V Unprivileged Specification version 20191214-draft (December 1, 2021, with Zihintpause 2.0 Ratified), the PAUSE instruction is defined as follows:

Chapter 4

“Zihintpause” Pause Hint, Version 2.0

The PAUSE instruction is a HINT that indicates the current hart’s rate of instruction retirement
should be temporarily reduced or paused. The duration of its effect must be bounded and may be
zero. No architectural state is changed.

...

PAUSE is encoded as a FENCE instruction with pred=W, succ=0, fm=0, rd=x0, and rs1=x0.

This instruction is useful when we need to implement core::hint::spin_loop() function for RISC-V platforms.

The function pause() is defined unsafe because caller must ensure it's called on RISC-V platforms. As is defined in the Specification, implementation of the corresponding pause instruction varies between platforms, it may be spin loop hint, a no-op or others, but will never throw illegal instruction exception. This instruction does not perform as a memory barrier.

For using .word: the pause pseudoinstruction would be supported after this LLVM review: D93019, by now (if I am correct) I can't write this instruction in current version Rust's asm! macro. In case if I'm incorrect or this way is inappropriate, I'd submit this pull request as a draft.

@rust-highfive
Copy link

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Amanieu (or someone else) soon.

Please see the contribution instructions for more information.

@lu-zero
Copy link
Contributor

lu-zero commented Dec 2, 2021

Thank you for your contribution!

This pull request contains two parts: new RISC-V platform core::arch package, and a first platform specific instruction wrapper pause() function on RISC-V platform.

Please split it in two commits.

As is defined in RISC-V Unprivileged Specification version 20191214-draft (December 1, 2021, with Zihintpause 2.0 Ratified), the PAUSE instruction is defined as follows:

Chapter 4
“Zihintpause” Pause Hint, Version 2.0
The PAUSE instruction is a HINT that indicates the current hart’s rate of instruction retirement
should be temporarily reduced or paused. The duration of its effect must be bounded and may be
zero. No architectural state is changed.
...
PAUSE is encoded as a FENCE instruction with pred=W, succ=0, fm=0, rd=x0, and rs1=x0.

This instruction is useful when we need to implement core::hint::spin_loop() function for RISC-V platforms.

The function pause() is defined unsafe because caller must ensure it's called on RISC-V platforms. As is defined in the Specification, implementation of the corresponding pause instruction varies between platforms, it may be spin loop hint, a no-op or others, but will never throw illegal instruction exception. This instruction does not perform as a memory barrier.

It is not unsafe for that reason and probably it can be considered safe (see the reasoning of safe/unsafe in wasm).

For using .word: the pause pseudoinstruction would be supported after this LLVM review: D93019, by now (if I am correct) I can't write this instruction in current version Rust's asm! macro. In case if I'm incorrect or this way is inappropriate, I'd submit this pull request as a draft.

Once we use the right version of llvm it should work with asm!, I think.

/// The PAUSE instruction is a HINT that indicates the current hart's rate of instruction retirement
/// should be temporarily reduced or paused. The duration of its effect must be bounded and may be zero.
#[inline(always)]
pub unsafe fn pause() {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should add a feature that maps to the extension, see what it is done for the other arch extensions.

Copy link
Contributor Author

@luojia65 luojia65 Dec 2, 2021

Choose a reason for hiding this comment

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

Yes, adding feature gate to extension specific instructions are necessary. For pause instruction, this instruction is in HINT space (in I set which must be implemented by RISC-V cores), whether there is Zihintpause or not does not change architectural state after instruction is retired. It will always run on all RISC-V cores. I don't know if it's still required to add feature gate to this function, or should we write it down in documentation for clarification. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

You may add a comment about it.

I assume nothing else would use the same value so either it is ignored or it is used as intended and would not change in unexpected ways the behavior in the future.

Can you confirm that I understood correctly?

/// should be temporarily reduced or paused. The duration of its effect must be bounded and may be zero.
#[inline(always)]
pub fn pause() {
unsafe { asm!(".word 0x0100000F") }
Copy link
Member

Choose a reason for hiding this comment

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

Can you set the nomem and nostack options? Also does LLVM have an intrinsic for this instruction?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hello! I'll perform changes soon. BTW, I checked the LLVM source here (https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsRISCV.td), but I didn't find LLVM intrinsic for RISC-V pause instruction.

Copy link
Member

Choose a reason for hiding this comment

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

There is a PR for adding the pause instruction in inline asm. It seems to have been accepted but not yet merged for over a year: https://reviews.llvm.org/D93019

///
/// The PAUSE instruction is a HINT that indicates the current hart's rate of instruction retirement
/// should be temporarily reduced or paused. The duration of its effect must be bounded and may be zero.
#[inline(always)]
Copy link
Member

Choose a reason for hiding this comment

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

Is there a specific reason for using #[inline(always)]. A normal #[inline] should be sufficient.

Copy link
Contributor Author

@luojia65 luojia65 Dec 4, 2021

Choose a reason for hiding this comment

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

Hello! I suspect if a single instruction wrap would gain better performance if it inlines. Yes, for some debug purposes we should not inline these functions. and #[inline] only would behave better in these scenarios.

@Amanieu
Copy link
Member

Amanieu commented Dec 4, 2021

Other than that, LGTM.

Use `#[inline]` instead of `#[inline(always)]`
@Amanieu
Copy link
Member

Amanieu commented Dec 4, 2021

This PR is still marked as a draft, is there anything else to do?

@luojia65
Copy link
Contributor Author

luojia65 commented Dec 5, 2021

@Amanieu The instruction is encoded as .word by now instead of a normal instruction name, other than that that's nothing else to do :)

@luojia65 luojia65 marked this pull request as ready for review December 5, 2021 02:09
@Amanieu Amanieu merged commit 43b4556 into rust-lang:master Dec 5, 2021
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 8, 2021
…anieu

Add spin_loop hint for RISC-V architecture

This commit uses the PAUSE instruction (rust-lang/stdarch#1262) to implement RISC-V spin loop, and updates `stdarch` submodule to use the merged PAUSE instruction.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 8, 2021
…anieu

Add spin_loop hint for RISC-V architecture

This commit uses the PAUSE instruction (rust-lang/stdarch#1262) to implement RISC-V spin loop, and updates `stdarch` submodule to use the merged PAUSE instruction.
@luojia65 luojia65 deleted the riscv-pause branch December 9, 2021 04:07
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 9, 2021
…anieu

Add spin_loop hint for RISC-V architecture

This commit uses the PAUSE instruction (rust-lang/stdarch#1262) to implement RISC-V spin loop, and updates `stdarch` submodule to use the merged PAUSE instruction.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 11, 2021
…anieu

Add spin_loop hint for RISC-V architecture

This commit uses the PAUSE instruction (rust-lang/stdarch#1262) to implement RISC-V spin loop, and updates `stdarch` submodule to use the merged PAUSE instruction.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 11, 2021
…anieu

Add spin_loop hint for RISC-V architecture

This commit uses the PAUSE instruction (rust-lang/stdarch#1262) to implement RISC-V spin loop, and updates `stdarch` submodule to use the merged PAUSE instruction.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 11, 2021
…anieu

Add spin_loop hint for RISC-V architecture

This commit uses the PAUSE instruction (rust-lang/stdarch#1262) to implement RISC-V spin loop, and updates `stdarch` submodule to use the merged PAUSE instruction.
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.

5 participants