Hi,
On 20/10/26 16:55, Stian Halseth wrote:
Implement the eight AES round instructions by using QEMU's shared
crypto/aes-round.h, gated behind the crypto CPU feature:
- AES_EROUND01/23 and last variants
- AES_DROUND01/23 and last variants
Based on OSA (Oracle SPARC Architecture) 2011, section 7.3:
AES Cryptographic Operations (4 operand)
Signed-off-by: Stian Halseth <[email protected]>
---
target/sparc/crypto_helper.c | 85 ++++++++++++++++++++++++++++++++++++
target/sparc/helper.h | 8 ++++
target/sparc/insns.decode | 9 ++++
target/sparc/meson.build | 2 +-
target/sparc/translate.c | 16 +++++++
5 files changed, 119 insertions(+), 1 deletion(-)
create mode 100644 target/sparc/crypto_helper.c
Could we add tests (in tests/tcg, following commit 57b484e2d23
"target/riscv: fix RV32 fixed counter accesses" which uses the
debian-all-test-cross image -- where gcc-sparc64-linux-gnu is
available)? Actually we could put them in tests/tcg/multiarch/
as generic AES tests.
diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c
new file mode 100644
index 0000000000..87cc19b930
--- /dev/null
+++ b/target/sparc/crypto_helper.c
@@ -0,0 +1,85 @@
+/*
+ * SPARC crypto instructions for QEMU
+ *
+ * Based on Oracle SPARC Architecture 2011
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "exec/helper-proto.h"
+#include "crypto/aes-round.h"
+
+/*
+ * SPARC four-operand AES round (Section 7.3).
+ * s2:s3 holds the state in big-endian order; half selects output columns
+ * 0-1 or 2-3, and key supplies their round key. dec selects decryption;
+ * last omits MixColumns/InvMixColumns. Return the selected 64-bit half.
Please document the non-obvious invariant:
* Note all 64-bit values (state and key) hold AES bytes in big-endian
* order, i.e. the most significant byte is the first state byte.
+ */
+static uint64_t aes_round(uint64_t key, uint64_t s2, uint64_t s3,
+ int half, bool dec, bool last)
+{
+ AESState st, rk = { 0 }, r;
+ const unsigned first = HOST_BIG_ENDIAN ? 0 : 1;
+ const unsigned out = first ^ half;
+
+ st.d[first] = s2; /* columns 0-1 */
+ st.d[first ^ 1] = s3; /* columns 2-3 */
+ rk.d[out] = key;
Nitpicking, maybe zero the other half explicitly here instead of { 0 }:
rk.d[out ^ 1] = 0;
+
+ if (dec) {
+ if (last) {
+ aesdec_ISB_ISR_AK(&r, &st, &rk, true);
+ } else {
+ aesdec_ISB_ISR_AK_IMC(&r, &st, &rk, true);
+ }
+ } else {
+ if (last) {
+ aesenc_SB_SR_AK(&r, &st, &rk, true);
+ } else {
+ aesenc_SB_SR_MC_AK(&r, &st, &rk, true);
+ }
+ }
+
+ return r.d[out];
+}
Tested-by: Philippe Mathieu-Daudé <[email protected]>