@samitouri / QOSamiQemu / commits / 9bf93903f7

target/mips: add Octeon AES COP2 helpers

Add helper support for the Octeon AES operation selectors. Direct register-transfer selectors do not need helpers; the ECB/CBC encrypt and decrypt operations consume the AES input, key, IV, and key-length state. AESRESINP is modeled as one architectural register bank; operation helpers consume the current AESRESINP block and write the result back to the same bank. Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-8-daef7a0d8b04@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

James Hilliard committed Jun 8, 2026 at 12:59 UTC 9bf93903f715d1188d0a9640f727ffe554fc5b7d
2 files changed +149
target/mips/helper.h
+4
@@ -52,6 +52,10 @@ DEF_HELPER_2(octeon_cp2_mt_zuc_start, void, env, i64)
52 DEF_HELPER_2(octeon_cp2_mt_zuc_more, void, env, i64)
53 DEF_HELPER_2(octeon_cp2_mt_snow3g_start, void, env, i64)
54 DEF_HELPER_2(octeon_cp2_mt_snow3g_more, void, env, i64)
55 +DEF_HELPER_2(octeon_cp2_mt_aes_enc_cbc1, void, env, i64)
56 +DEF_HELPER_2(octeon_cp2_mt_aes_enc1, void, env, i64)
57 +DEF_HELPER_2(octeon_cp2_mt_aes_dec_cbc1, void, env, i64)
58 +DEF_HELPER_2(octeon_cp2_mt_aes_dec1, void, env, i64)
59
60 /* microMIPS functions */
61 DEF_HELPER_4(lwm, void, env, tl, tl, i32)
target/mips/tcg/octeon_crypto.c
+145
@@ -840,6 +840,151 @@ static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto)
840 octeon_snow3g_queue_result(crypto);
841 }
842
843 +static int octeon_aes_key_bits(const MIPSOcteonCryptoState *crypto)
844 +{
845 + enum {
846 + OCTEON_AES_KEYLEN_128 = 1,
847 + OCTEON_AES_KEYLEN_192 = 2,
848 + OCTEON_AES_KEYLEN_256 = 3,
849 + };
850 +
851 + switch (crypto->aes_keylen) {
852 + case OCTEON_AES_KEYLEN_128:
853 + return 128;
854 + case OCTEON_AES_KEYLEN_192:
855 + return 192;
856 + case OCTEON_AES_KEYLEN_256:
857 + return 256;
858 + default:
859 + return 0;
860 + }
861 +}
862 +
863 +static void octeon_aes_load_key(const MIPSOcteonCryptoState *crypto,
864 + uint8_t *key, size_t keylen)
865 +{
866 + stq_be_p(key, crypto->aes_key[0]);
867 + stq_be_p(key + 8, crypto->aes_key[1]);
868 + if (keylen > 16) {
869 + stq_be_p(key + 16, crypto->aes_key[2]);
870 + }
871 + if (keylen > 24) {
872 + stq_be_p(key + 24, crypto->aes_key[3]);
873 + }
874 +}
875 +
876 +static void octeon_aes_load_block(const uint64_t regs[2], uint8_t *block)
877 +{
878 + stq_be_p(block, regs[0]);
879 + stq_be_p(block + 8, regs[1]);
880 +}
881 +
882 +static void octeon_aes_store_block(uint64_t regs[2], const uint8_t *block)
883 +{
884 + regs[0] = ldq_be_p(block);
885 + regs[1] = ldq_be_p(block + 8);
886 +}
887 +
888 +static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
889 +{
890 + AES_KEY key;
891 + uint8_t in[16];
892 + uint8_t out[16];
893 + uint8_t iv[16];
894 + uint8_t raw_key[32] = {};
895 + int bits = octeon_aes_key_bits(crypto);
896 +
897 + if (!bits) {
898 + return;
899 + }
900 +
901 + octeon_aes_load_key(crypto, raw_key, bits / 8);
902 + octeon_aes_load_block(crypto->aes_resinp, in);
903 + if (cbc) {
904 + int i;
905 +
906 + octeon_aes_load_block(crypto->aes_iv, iv);
907 + for (i = 0; i < sizeof(in); i++) {
908 + in[i] ^= iv[i];
909 + }
910 + }
911 +
912 + AES_set_encrypt_key(raw_key, bits, &key);
913 + AES_encrypt(in, out, &key);
914 + octeon_aes_store_block(crypto->aes_resinp, out);
915 + if (cbc) {
916 + octeon_aes_store_block(crypto->aes_iv, out);
917 + }
918 +}
919 +
920 +static void octeon_aes_decrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
921 +{
922 + AES_KEY key;
923 + uint8_t in[16];
924 + uint8_t out[16];
925 + uint8_t iv[16];
926 + uint8_t next_iv[16];
927 + uint8_t raw_key[32] = {};
928 + int bits = octeon_aes_key_bits(crypto);
929 + int i;
930 +
931 + if (!bits) {
932 + return;
933 + }
934 +
935 + octeon_aes_load_key(crypto, raw_key, bits / 8);
936 + octeon_aes_load_block(crypto->aes_resinp, in);
937 + if (cbc) {
938 + memcpy(next_iv, in, sizeof(next_iv));
939 + octeon_aes_load_block(crypto->aes_iv, iv);
940 + }
941 +
942 + AES_set_decrypt_key(raw_key, bits, &key);
943 + AES_decrypt(in, out, &key);
944 + if (cbc) {
945 + for (i = 0; i < sizeof(out); i++) {
946 + out[i] ^= iv[i];
947 + }
948 + }
949 +
950 + octeon_aes_store_block(crypto->aes_resinp, out);
951 + if (cbc) {
952 + octeon_aes_store_block(crypto->aes_iv, next_iv);
953 + }
954 +}
955 +
956 +void helper_octeon_cp2_mt_aes_enc_cbc1(CPUMIPSState *env, uint64_t value)
957 +{
958 + MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
959 +
960 + crypto->aes_resinp[1] = value;
961 + octeon_aes_encrypt_common(crypto, true);
962 +}
963 +
964 +void helper_octeon_cp2_mt_aes_enc1(CPUMIPSState *env, uint64_t value)
965 +{
966 + MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
967 +
968 + crypto->aes_resinp[1] = value;
969 + octeon_aes_encrypt_common(crypto, false);
970 +}
971 +
972 +void helper_octeon_cp2_mt_aes_dec_cbc1(CPUMIPSState *env, uint64_t value)
973 +{
974 + MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
975 +
976 + crypto->aes_resinp[1] = value;
977 + octeon_aes_decrypt_common(crypto, true);
978 +}
979 +
980 +void helper_octeon_cp2_mt_aes_dec1(CPUMIPSState *env, uint64_t value)
981 +{
982 + MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
983 +
984 + crypto->aes_resinp[1] = value;
985 + octeon_aes_decrypt_common(crypto, false);
986 +}
987 +
988 void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
989 {
990 octeon_snow3g_start(&env->octeon_crypto, value);