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

proposed work-around for https://github.com/rust-lang/rust/issues/86693 #358

Closed
wants to merge 1 commit into from

Conversation

bunnie
Copy link

@bunnie bunnie commented Jun 29, 2021

For 32-bit targets on RISC-V, we have encountered a problem in the
non_adjacent_form() routine inside Scalar. To the best we can tell,
there is a compiler bug which is causing 64-bit types on 32-bit platforms
to not be properly aligned (see issue rust-lang/rust#86693).
This bug results in the lower 32 bits of a 64-bit number being replicated
into the top 32 bits, as a result of pointer arithmetic optimizations that
rely on correct alignment of the data types.

So far, we have only seen this problem inside one function that affects
ed25519 verifications, but it could be in other libraries we haven't
used yet.

Thanks to @xobs we have a work-around, which is to wrap the [u64; 5]
type inside an AlignedU64Slice newtype which is annotated with
a #[repr(align(32))]. In our tests this causes the ed25519 signatures
tests to pass on our platform.

Unfortunately, we are unable to get the bug to express on x86 using a u32
backend; the bug seems to be specific to RISC-V. However, I think this
patch is light-fingered enough that it might be worth considering
absorbing into the upstream crate. Based on the age of similar bugs filed against
the Rust project, it may take some months or years even before this issue
gets properly addressed...

For 32-bit targets on RISC-V, we have encountered a problem in the
non_adjacent_form() routine inside Scalar. To the best we can tell,
there is a compiler bug which is causing 64-bit types on 32-bit platforms
to not be properly aligned (see issue rust-lang/rust#86693).
This bug results in the lower 32 bits of a 64-bit number being replicated
into the top 32 bits, as a result of pointer arithmetic optimizations that
rely on correct alignment of the data types.

So far, we have only seen this problem inside one function that affects
ed25519 verifications, but it could be in other libraries we haven't
used yet.

Thanks to @xobs we have a work-around, which is to wrap the `[u64; 5]`
type inside an `AlignedU64Slice` `newtype` which is annotated with
a `#[repr(align(32))]`. In our tests this causes the ed25519 signatures
tests to pass on our platform.

Unfortunately, we are unable to get the bug to express on x86 using a u32
backend; the bug seems to be specific to RISC-V. However, I think this
patch is light-fingered enough that it might be worth considering
absorbing into the crate. Based on the age of similar bugs filed against
the Rust project, it may take some months or years even before this
gets properly addressed...
@bunnie
Copy link
Author

bunnie commented Jul 11, 2021

I'm going to close this PR. Turns out the root cause is that $sp needs to be aligned to 16-byte boundaries for llvm to work correctly. Our runtime wasn't doing this. Now that this is done, we're running the stock code correctly.

Sorry for the distraction!

@bunnie bunnie closed this Jul 11, 2021
@isislovecruft
Copy link
Member

No problem! Glad you got it working and thanks for the thorough writeup on your investigations!

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.

2 participants