Skip to content

Fix randomx_get_flags not reporting hardware AES on RISC-V - #370

Open
thomasbuilds wants to merge 1 commit into
tevador:masterfrom
thomasbuilds:fix-riscv-get-flags-aes
Open

thomasbuilds wants to merge 1 commit into
tevador:masterfrom
thomasbuilds:fix-riscv-get-flags-aes

Conversation

@thomasbuilds

@thomasbuilds thomasbuilds commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

randomx_get_flags() reports RANDOMX_FLAG_HARD_AES only if HAVE_AES is 1, which it never was on RISC-V: rx_aesenc_vec_i128/rx_aesdec_vec_i128 had no RISC-V implementation. So callers that take their flags from it, such as Monero and randomx-benchmark --auto, used software AES even where hardware AES was detected.

This implements both functions with Zvkned in aes_hash_rv64_zvkned.cpp, the file already compiled with Zvkned, and sets HAVE_AES to 1 on RISC-V. They are only called from RANDOMX_FLAG_HARD_AES VMs, which VmBase::allocate() rejects unless cpu.hasAes(). In those VMs, the interpreter's v2 AES mix now uses them instead of software AES. platformError stays defined on RISC-V, where allocate() uses it, and is now a const pointer so GCC's -Wall doesn't flag it as unused. The "Hardware AES not supported" test still runs on RISC-V whenever cpu.hasAes() is false.

@hyc hyc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If the CPU has hardware AES but HAVE_AES is not being defined, then the right thing to do is to fix that, not muck around here.

@SChernykh

Copy link
Copy Markdown
Collaborator

Yes, HAVE_AES should be 1 on RISC-V because there are AES instruction extensions there.

@thomasbuilds
thomasbuilds force-pushed the fix-riscv-get-flags-aes branch 2 times, most recently from 614502d to 6788dd3 Compare October 31, 2026 09:27
@thomasbuilds
thomasbuilds requested a review from hyc October 31, 2026 11:05
Comment thread src/tests/tests.cpp
#else
constexpr bool hardAesCheckedAtRuntime = !HAVE_AES;
#endif
runTest("Hardware AES not supported", hardAesCheckedAtRuntime && !randomx::cpu.hasAes(), []() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This change seems completely unnecessary. Why single out RISC-V?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

With HAVE_AES now 1 on RISC-V, the old condition would skip this test on every RISC-V build, including the riscv64 CI job, where it runs today (QEMU's CPU has VLEN 128 so cpu.hasAes() is false). RISC-V is singled out because it's the only platform where allocate() checks cpu.hasAes(). Elsewhere, with HAVE_AES 1, allocate() executes an AES instruction so with a plain !cpu.hasAes() the test would fail in the ppc64le and Win32 CI jobs, where cpu.hasAes() is never set but the CPU has AES.

Comment thread src/virtual_machine.cpp Outdated
#ifdef __riscv
if (!softAes && !cpu.hasAes())
throw std::runtime_error(platformError);
throw std::runtime_error("Platform doesn't support hardware AES");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Completely unrelated and unnecessary change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

platformError is only declared inside the #ifndef HAVE_AES block of intrin_portable.h so with HAVE_AES now defined on RISC-V the original line fails to compile ('platformError' was not declared in this scope). The message text is unchanged.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I would rather do #if !defined(HAVE_AES) || defined(__riscv) for platformError definition than changing all places where platformError is used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I also made it static const char* const otherwise, when building for RISC-V, GCC -Wall warns 'platformError' defined but not used in every file that includes intrin_portable.h without using it, which would break P2Pool's riscv64 GCC build (side_chain.cpp is built with -Werror).

Comment thread src/vm_interpreted.cpp Outdated
freg[0] = aesenc<softAes>(freg[0], ekey[i]);
freg[1] = aesdec<softAes>(freg[1], ekey[i]);
freg[2] = aesenc<softAes>(freg[2], ekey[i]);
freg[3] = aesdec<softAes>(freg[3], ekey[i]);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why remove it? If HAVE_AES is 0 and softAes is false, this will compile to a code that will throw an exception in intrin_portable.h

@thomasbuilds thomasbuilds Oct 31, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I restored it

@thomasbuilds
thomasbuilds force-pushed the fix-riscv-get-flags-aes branch 2 times, most recently from b63be62 to d21bbd8 Compare October 31, 2026 14:56
@thomasbuilds
thomasbuilds force-pushed the fix-riscv-get-flags-aes branch 2 times, most recently from 987069b to 0892094 Compare November 1, 2026 10:14
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.

3 participants