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)
Next commit will complete the feature and expose its availability
to the guest by setting the AES bit in CFR.
Tested-by: Philippe Mathieu-Daudé <[email protected]>
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Stian Halseth <[email protected]>
---
target/sparc/crypto_helper.c | 89 ++++++++++++++++++++++++++++++++++++
target/sparc/helper.h | 8 ++++
target/sparc/insns.decode | 9 ++++
target/sparc/meson.build | 2 +-
target/sparc/translate.c | 16 +++++++
5 files changed, 123 insertions(+), 1 deletion(-)
create mode 100644 target/sparc/crypto_helper.c
diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c
new file mode 100644
index 0000000000..7dd4dd5144
--- /dev/null
+++ b/target/sparc/crypto_helper.c
@@ -0,0 +1,89 @@
+/*
+ * 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; 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.
+ *
+ * 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, 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;
+ 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];
+}
+
+uint64_t helper_aes_eround01(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 0, false, false);
+}
+
+uint64_t helper_aes_eround23(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 1, false, false);
+}
+
+uint64_t helper_aes_dround01(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 0, true, false);
+}
+
+uint64_t helper_aes_dround23(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 1, true, false);
+}
+
+uint64_t helper_aes_eround01_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 0, false, true);
+}
+
+uint64_t helper_aes_eround23_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 1, false, true);
+}
+
+uint64_t helper_aes_dround01_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 0, true, true);
+}
+
+uint64_t helper_aes_dround23_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+ return aes_round(key, s2, s3, 1, true, true);
+}
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 3a7f7dc129..9bfd643b09 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -122,6 +122,14 @@ DEF_HELPER_FLAGS_2(fchksm16, TCG_CALL_NO_RWG_SE, i64, i64,
i64)
DEF_HELPER_FLAGS_2(fmean16, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(fslas16, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(fslas32, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround01, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround23, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround01, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround23, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround01_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround01_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
#define VIS_CMPHELPER(name) \
DEF_HELPER_FLAGS_2(f##name##8, TCG_CALL_NO_RWG_SE, \
i64, i64, i64) \
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index 55f8528ffe..99c9147e7d 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -596,6 +596,15 @@ FCMPEq 10 000 cc:2 110101 ..... 0 0101 0111 .....
\
NCP 10 ----- 110111 ----- --------- ----- # v8 CPop2
}
+AES_EROUND01 10 ..... 011001 ..... ..... 0000 ..... @d_d_d_d
+AES_EROUND23 10 ..... 011001 ..... ..... 0001 ..... @d_d_d_d
+AES_DROUND01 10 ..... 011001 ..... ..... 0010 ..... @d_d_d_d
+AES_DROUND23 10 ..... 011001 ..... ..... 0011 ..... @d_d_d_d
+AES_EROUND01_L 10 ..... 011001 ..... ..... 0100 ..... @d_d_d_d
+AES_EROUND23_L 10 ..... 011001 ..... ..... 0101 ..... @d_d_d_d
+AES_DROUND01_L 10 ..... 011001 ..... ..... 0110 ..... @d_d_d_d
+AES_DROUND23_L 10 ..... 011001 ..... ..... 0111 ..... @d_d_d_d
+
##
## Major Opcode 11 -- load and store instructions
##
diff --git a/target/sparc/meson.build b/target/sparc/meson.build
index 46289c8669..af65c933bf 100644
--- a/target/sparc/meson.build
+++ b/target/sparc/meson.build
@@ -12,7 +12,7 @@ sparc_ss.add(files(
'win_helper.c',
))
sparc_ss.add(when: 'TARGET_SPARC', if_true: files('int32_helper.c'))
-sparc_ss.add(when: 'TARGET_SPARC64', if_true: files('int64_helper.c',
'vis_helper.c'))
+sparc_ss.add(when: 'TARGET_SPARC64', if_true: files('int64_helper.c',
'vis_helper.c', 'crypto_helper.c'))
sparc_system_ss = ss.source_set()
sparc_system_ss.add(files(
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index a1562f5047..16907b1085 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -101,6 +101,14 @@
# define gen_helper_xmulx ({ qemu_build_not_reached(); NULL; })
# define gen_helper_xmulxhi ({ qemu_build_not_reached(); NULL; })
# define MAXTL_MASK 0
+# define gen_helper_aes_eround01 ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_eround23 ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround01 ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround23 ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_eround01_l ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_eround23_l ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround01_l ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround23_l ({ qemu_build_not_reached(); NULL; })
#endif
#define DISAS_EXIT DISAS_TARGET_0
@@ -5418,6 +5426,14 @@ TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd)
TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd)
TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx)
TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi)
+TRANS(AES_EROUND01, CRYPTO, do_dddd, a, gen_helper_aes_eround01)
+TRANS(AES_EROUND23, CRYPTO, do_dddd, a, gen_helper_aes_eround23)
+TRANS(AES_DROUND01, CRYPTO, do_dddd, a, gen_helper_aes_dround01)
+TRANS(AES_DROUND23, CRYPTO, do_dddd, a, gen_helper_aes_dround23)
+TRANS(AES_EROUND01_L, CRYPTO, do_dddd, a, gen_helper_aes_eround01_l)
+TRANS(AES_EROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_eround23_l)
+TRANS(AES_DROUND01_L, CRYPTO, do_dddd, a, gen_helper_aes_dround01_l)
+TRANS(AES_DROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_dround23_l)
static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a)
{