Add ML-KEM and ML-DSA support.

Signed-off-by: Gowrishankar Muthukrishnan <[email protected]>
---
 doc/guides/cryptodevs/features/cn20k.ini      |   3 +
 doc/guides/cryptodevs/features/default.ini    |   1 +
 doc/guides/rel_notes/release_26_07.rst        |   3 +
 drivers/common/cnxk/hw/cpt.h                  |   1 +
 drivers/common/cnxk/meson.build               |   1 +
 drivers/common/cnxk/roc_cpt.c                 |   4 +
 drivers/common/cnxk/roc_platform.h            |   5 +
 .../common/cnxk/roc_platform_base_symbols.c   |   2 +
 drivers/common/cnxk/roc_re.h                  |  31 ++
 drivers/common/cnxk/roc_re_ml_tables.c        | 248 +++++++++++
 drivers/common/cnxk/roc_re_ml_tables.h        |  19 +
 drivers/crypto/cnxk/cnxk_ae.h                 | 399 +++++++++++++++++-
 drivers/crypto/cnxk/cnxk_cryptodev.c          |  11 +
 drivers/crypto/cnxk/cnxk_cryptodev.h          |   4 +-
 .../crypto/cnxk/cnxk_cryptodev_capabilities.c |  62 ++-
 drivers/crypto/cnxk/cnxk_cryptodev_ops.c      |  45 +-
 16 files changed, 817 insertions(+), 22 deletions(-)
 create mode 100644 drivers/common/cnxk/roc_re.h
 create mode 100644 drivers/common/cnxk/roc_re_ml_tables.c
 create mode 100644 drivers/common/cnxk/roc_re_ml_tables.h

diff --git a/doc/guides/cryptodevs/features/cn20k.ini 
b/doc/guides/cryptodevs/features/cn20k.ini
index d4c52082c6..8180128744 100644
--- a/doc/guides/cryptodevs/features/cn20k.ini
+++ b/doc/guides/cryptodevs/features/cn20k.ini
@@ -21,6 +21,7 @@ Asymmetric sessionless = Y
 Sym raw data path API  = Y
 Inner checksum         = Y
 Rx inject              = Y
+ML-DSA sign prehash    = Y
 
 ;
 ; Supported crypto algorithms of 'cn20k' crypto driver.
@@ -110,6 +111,8 @@ ECDSA                   = Y
 ECPM                    = Y
 SM2                     = Y
 EdDSA                   = Y
+ML-DSA                  = Y
+ML-KEM                  = Y
 
 ;
 ; Supported Operating systems of the 'cn20k' crypto driver.
diff --git a/doc/guides/cryptodevs/features/default.ini 
b/doc/guides/cryptodevs/features/default.ini
index d8026c3750..be4ee777fb 100644
--- a/doc/guides/cryptodevs/features/default.ini
+++ b/doc/guides/cryptodevs/features/default.ini
@@ -35,6 +35,7 @@ Cipher multiple data units =
 Cipher wrapped key     =
 Inner checksum         =
 Rx inject              =
+ML-DSA sign prehash    =
 
 ;
 ; Supported crypto algorithms of a default crypto driver.
diff --git a/doc/guides/rel_notes/release_26_07.rst 
b/doc/guides/rel_notes/release_26_07.rst
index 8b4f8401e2..67c1842afe 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -87,6 +87,9 @@ New Features
   Added AGENTS.md file for AI review
   and supporting scripts to review patches and documentation.
 
+* **Updated Marvell cnxk crypto driver.**
+
+  * Added support for ML-KEM and ML-DSA on CN20K platform.
 
 Removed Items
 -------------
diff --git a/drivers/common/cnxk/hw/cpt.h b/drivers/common/cnxk/hw/cpt.h
index eb795f61ac..12aeb4d054 100644
--- a/drivers/common/cnxk/hw/cpt.h
+++ b/drivers/common/cnxk/hw/cpt.h
@@ -58,6 +58,7 @@ enum cpt_eng_type {
        CPT_ENG_TYPE_AE = 1,
        CPT_ENG_TYPE_SE = 2,
        CPT_ENG_TYPE_IE = 3,
+       CPT_ENG_TYPE_RE = 4,
        CPT_MAX_ENG_TYPES,
 };
 
diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build
index 9db77a9702..3303ad9354 100644
--- a/drivers/common/cnxk/meson.build
+++ b/drivers/common/cnxk/meson.build
@@ -65,6 +65,7 @@ sources = files(
         'roc_npc_utils.c',
         'roc_platform.c',
         'roc_platform_base_symbols.c',
+        'roc_re_ml_tables.c',
         'roc_se.c',
         'roc_sso.c',
         'roc_sso_debug.c',
diff --git a/drivers/common/cnxk/roc_cpt.c b/drivers/common/cnxk/roc_cpt.c
index 21d5e7f2ba..686c9eae7e 100644
--- a/drivers/common/cnxk/roc_cpt.c
+++ b/drivers/common/cnxk/roc_cpt.c
@@ -632,6 +632,9 @@ roc_cpt_dev_configure(struct roc_cpt *roc_cpt, int nb_lf, 
bool rxc_ena, uint16_t
                eng_grpmsk = (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_AE]) |
                             (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_SE]);
 
+       if (roc_model_is_cn20k())
+               eng_grpmsk |= (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_RE]);
+
        if (roc_errata_cpt_has_ctx_fetch_issue()) {
                ctx_ilen_valid = true;
                /* Inbound SA size is max context size */
@@ -1097,6 +1100,7 @@ roc_cpt_eng_grp_add(struct roc_cpt *roc_cpt, enum 
cpt_eng_type eng_type)
        case CPT_ENG_TYPE_AE:
        case CPT_ENG_TYPE_SE:
        case CPT_ENG_TYPE_IE:
+       case CPT_ENG_TYPE_RE:
                break;
        default:
                ret = -EINVAL;
diff --git a/drivers/common/cnxk/roc_platform.h 
b/drivers/common/cnxk/roc_platform.h
index e22a50d47a..19f1d6005b 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h
@@ -41,6 +41,7 @@
        ".arch_extension lse\n"
 #endif
 
+#define PLT_ATOMIC              RTE_ATOMIC
 #define PLT_ASSERT              RTE_ASSERT
 #define PLT_VERIFY              RTE_VERIFY
 #define PLT_MEMZONE_NAMESIZE    RTE_MEMZONE_NAMESIZE
@@ -217,6 +218,10 @@ plt_thread_is_valid(plt_thread_t thr)
 #define plt_memory_order_release  rte_memory_order_release
 #define plt_memory_order_acquire  rte_memory_order_acquire
 #define plt_memory_order_relaxed  rte_memory_order_relaxed
+#define plt_memory_order_seq_cst  rte_memory_order_seq_cst
+
+#define plt_atomic_fetch_add_explicit rte_atomic_fetch_add_explicit
+#define plt_atomic_fetch_sub_explicit rte_atomic_fetch_sub_explicit
 
 #define plt_bit_relaxed_get32   rte_bit_relaxed_get32
 #define plt_bit_relaxed_set32   rte_bit_relaxed_set32
diff --git a/drivers/common/cnxk/roc_platform_base_symbols.c 
b/drivers/common/cnxk/roc_platform_base_symbols.c
index cf080b1bdc..75775fbe09 100644
--- a/drivers/common/cnxk/roc_platform_base_symbols.c
+++ b/drivers/common/cnxk/roc_platform_base_symbols.c
@@ -497,6 +497,8 @@ RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_aged_flow_ctx_get)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_defrag_mcam_banks)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_get_key_type)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_flow_mcam_dump)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_re_ml_zeta_get)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_re_ml_zeta_put)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_ree_queues_attach)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_ree_queues_detach)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_ree_msix_offsets_get)
diff --git a/drivers/common/cnxk/roc_re.h b/drivers/common/cnxk/roc_re.h
new file mode 100644
index 0000000000..a8cbda41c0
--- /dev/null
+++ b/drivers/common/cnxk/roc_re.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2026 Marvell.
+ */
+
+#ifndef __ROC_RE_H__
+#define __ROC_RE_H__
+
+/* RE ML opcodes */
+#define ROC_RE_MAJOR_OP_MLKEM        0x1A
+#define ROC_RE_MAJOR_OP_MLDSA        0x1B
+#define ROC_RE_MINOR_OP_MLKEM_KEYGEN 0x00
+#define ROC_RE_MINOR_OP_MLKEM_ENCAP  0x01
+#define ROC_RE_MINOR_OP_MLKEM_DECAP  0x02
+#define ROC_RE_MINOR_OP_MLDSA_KEYGEN 0x00
+#define ROC_RE_MINOR_OP_MLDSA_SIGN   0x01
+#define ROC_RE_MINOR_OP_MLDSA_VERIFY 0x02
+
+/* ML-KEM param2 fields */
+#define ROC_RE_ML_KEM_PARAM2_INMSG_BIT  4
+#define ROC_RE_ML_KEM_PARAM2_INSEED_BIT 5
+
+/* ML-DSA param2 fields */
+#define ROC_RE_ML_DSA_PARAM2_SIGN_BIT   4
+#define ROC_RE_ML_DSA_PARAM2_SEED_BIT   5
+#define ROC_RE_ML_DSA_PARAM2_CTXN_BIT   8
+
+/* ML-DSA minor op fields */
+#define ROC_RE_ML_DSA_MINOR_SIGN_TYPE_BIT 2
+#define ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT  4
+
+#endif /* __ROC_RE_H__ */
diff --git a/drivers/common/cnxk/roc_re_ml_tables.c 
b/drivers/common/cnxk/roc_re_ml_tables.c
new file mode 100644
index 0000000000..933e35e3c9
--- /dev/null
+++ b/drivers/common/cnxk/roc_re_ml_tables.c
@@ -0,0 +1,248 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2026 Marvell.
+ */
+
+#include "roc_re_ml_tables.h"
+
+#define RE_ML_TBL_NAME "re_ml_tbl"
+#define RE_MLKEM_ZETA_LEN 256
+#define RE_MLDSA_ZETA_LEN 1024
+
+/* ML table address and length */
+struct re_ml_entry {
+       const uint8_t *data;
+       int len;
+};
+
+struct re_ml_tbl {
+       PLT_ATOMIC(uint64_t) refcount;
+       uint8_t ml_tbl[];
+};
+
+const uint8_t re_mlkem_zeta_tbl[RE_MLKEM_ZETA_LEN] = {
+       0x01, 0x00, 0xc1, 0x06, 0x14, 0x0a, 0xd9, 0x0c,
+       0x52, 0x0a, 0x76, 0x02, 0x69, 0x07, 0x50, 0x03,
+       0x26, 0x04, 0x7f, 0x07, 0xc1, 0x00, 0x1d, 0x03,
+       0xe2, 0x0a, 0xbc, 0x0c, 0x39, 0x02, 0xd2, 0x06,
+       0x28, 0x01, 0x8f, 0x09, 0x3b, 0x05, 0xc4, 0x05,
+       0xe6, 0x0b, 0x38, 0x00, 0xc0, 0x08, 0x35, 0x05,
+       0x92, 0x05, 0x2e, 0x08, 0x17, 0x02, 0x42, 0x0b,
+       0x59, 0x09, 0x3f, 0x0b, 0xb6, 0x07, 0x35, 0x03,
+       0x21, 0x01, 0x4b, 0x01, 0xb5, 0x0c, 0xdc, 0x06,
+       0xad, 0x04, 0x00, 0x09, 0xe5, 0x08, 0x07, 0x08,
+       0x8a, 0x02, 0xb9, 0x07, 0xd1, 0x09, 0x78, 0x02,
+       0x31, 0x0b, 0x21, 0x00, 0x28, 0x05, 0x7b, 0x07,
+       0x0f, 0x09, 0x9b, 0x05, 0x27, 0x03, 0xc4, 0x01,
+       0x9e, 0x05, 0x34, 0x0b, 0xfe, 0x05, 0x62, 0x09,
+       0x57, 0x0a, 0x39, 0x0a, 0xc9, 0x05, 0x88, 0x02,
+       0xaa, 0x09, 0x26, 0x0c, 0xcb, 0x04, 0x8e, 0x03,
+       0x11, 0x00, 0xc9, 0x0a, 0x47, 0x02, 0x59, 0x0a,
+       0x65, 0x06, 0xd3, 0x02, 0xf0, 0x08, 0x4c, 0x04,
+       0x81, 0x05, 0x66, 0x0a, 0xd1, 0x0c, 0xe9, 0x00,
+       0xf4, 0x02, 0x6c, 0x08, 0xc7, 0x0b, 0xea, 0x0b,
+       0xa7, 0x06, 0x73, 0x06, 0xe5, 0x0a, 0xfd, 0x06,
+       0x37, 0x07, 0xb8, 0x03, 0xb5, 0x05, 0x7f, 0x0a,
+       0xab, 0x03, 0x04, 0x09, 0x85, 0x09, 0x54, 0x09,
+       0xdd, 0x02, 0x21, 0x09, 0x0c, 0x01, 0x81, 0x02,
+       0x30, 0x06, 0xfa, 0x08, 0xf5, 0x07, 0x94, 0x0c,
+       0x77, 0x01, 0xf5, 0x09, 0x2a, 0x08, 0x6d, 0x06,
+       0x27, 0x04, 0x3f, 0x01, 0xd5, 0x0a, 0xf5, 0x02,
+       0x33, 0x08, 0x31, 0x02, 0xa2, 0x09, 0x22, 0x0a,
+       0xf4, 0x0a, 0x44, 0x04, 0x93, 0x01, 0x02, 0x04,
+       0x77, 0x04, 0x66, 0x08, 0xd7, 0x0a, 0x76, 0x03,
+       0xba, 0x06, 0xbc, 0x04, 0x52, 0x07, 0x05, 0x04,
+       0x3e, 0x08, 0x77, 0x0b, 0x75, 0x03, 0x6a, 0x08,
+};
+
+const uint8_t re_mldsa_zeta_tbl[RE_MLDSA_ZETA_LEN] = {
+       0x01, 0x00, 0x00, 0x00, 0x02, 0x5e, 0x49, 0x00,
+       0x67, 0x75, 0x39, 0x00, 0x69, 0x65, 0x39, 0x00,
+       0x2b, 0x06, 0x4f, 0x00, 0x73, 0xdf, 0x53, 0x00,
+       0x33, 0xe0, 0x4f, 0x00, 0x6b, 0x06, 0x4f, 0x00,
+       0xae, 0xb1, 0x76, 0x00, 0xd5, 0x0d, 0x36, 0x00,
+       0xb0, 0xed, 0x28, 0x00, 0xe4, 0x7f, 0x20, 0x00,
+       0x83, 0x72, 0x39, 0x00, 0x4a, 0x89, 0x70, 0x00,
+       0x92, 0x81, 0x08, 0x00, 0xc8, 0x3d, 0x6d, 0x00,
+       0x94, 0x72, 0x4c, 0x00, 0xb4, 0xe0, 0x41, 0x00,
+       0xd2, 0xa3, 0x28, 0x00, 0x8a, 0x52, 0x66, 0x00,
+       0xa7, 0x18, 0x4a, 0x00, 0x34, 0x40, 0x79, 0x00,
+       0xee, 0x52, 0x0a, 0x00, 0x81, 0x7d, 0x6b, 0x00,
+       0x1d, 0x9f, 0x4e, 0x00, 0x77, 0x28, 0x1a, 0x00,
+       0xdf, 0x71, 0x25, 0x00, 0xee, 0x49, 0x16, 0x00,
+       0xbd, 0x11, 0x76, 0x00, 0xb7, 0x2b, 0x49, 0x00,
+       0x97, 0xf6, 0x2a, 0x00, 0xd5, 0xd8, 0x22, 0x00,
+       0x2a, 0xf7, 0x36, 0x00, 0x1e, 0x91, 0x30, 0x00,
+       0x3f, 0xd1, 0x29, 0x00, 0x73, 0x26, 0x49, 0x00,
+       0x5f, 0x68, 0x50, 0x00, 0xa2, 0x10, 0x20, 0x00,
+       0xf7, 0x87, 0x38, 0x00, 0xc3, 0xb2, 0x11, 0x00,
+       0xa4, 0x03, 0x06, 0x00, 0xed, 0x2b, 0x0e, 0x00,
+       0x2c, 0xb7, 0x10, 0x00, 0x35, 0x5f, 0x4a, 0x00,
+       0x15, 0x9d, 0x1f, 0x00, 0xd4, 0x8c, 0x42, 0x00,
+       0xf4, 0x77, 0x31, 0x00, 0x12, 0xe6, 0x20, 0x00,
+       0x1d, 0x1c, 0x34, 0x00, 0x73, 0xd8, 0x1a, 0x00,
+       0x81, 0x66, 0x73, 0x00, 0x3f, 0x55, 0x49, 0x00,
+       0xf6, 0x52, 0x39, 0x00, 0x4a, 0x56, 0x62, 0x00,
+       0x05, 0xad, 0x65, 0x00, 0x1c, 0x9a, 0x43, 0x00,
+       0x5f, 0xaa, 0x53, 0x00, 0x22, 0xb6, 0x30, 0x00,
+       0x38, 0x7f, 0x08, 0x00, 0x6d, 0x0e, 0x3b, 0x00,
+       0xda, 0x83, 0x2c, 0x00, 0x6e, 0x49, 0x1c, 0x00,
+       0x2b, 0x0e, 0x33, 0x00, 0x70, 0x5b, 0x1c, 0x00,
+       0xf1, 0xe3, 0x2e, 0x00, 0xb9, 0x7e, 0x13, 0x00,
+       0x30, 0xa9, 0x57, 0x00, 0xef, 0xc6, 0x3a, 0x00,
+       0x4c, 0xd5, 0x3f, 0x00, 0xea, 0xb2, 0x4e, 0x00,
+       0xe1, 0x3e, 0x50, 0x00, 0x75, 0xb1, 0x7b, 0x00,
+       0xb4, 0x48, 0x26, 0x00, 0x56, 0xf2, 0x1e, 0x00,
+       0xa2, 0x90, 0x1d, 0x00, 0xd4, 0xa6, 0x45, 0x00,
+       0x9b, 0xe5, 0x2a, 0x00, 0x9c, 0x58, 0x52, 0x00,
+       0xf5, 0xf1, 0x6e, 0x00, 0x88, 0x72, 0x3f, 0x00,
+       0x02, 0x51, 0x17, 0x00, 0x59, 0x5d, 0x07, 0x00,
+       0xba, 0x87, 0x11, 0x00, 0xa9, 0xac, 0x52, 0x00,
+       0x9e, 0x3e, 0x77, 0x00, 0xd8, 0x96, 0x02, 0x00,
+       0xec, 0x92, 0x25, 0x00, 0x12, 0xff, 0x4c, 0x00,
+       0xe8, 0x4c, 0x40, 0x00, 0x82, 0xa5, 0x4a, 0x00,
+       0xe6, 0x54, 0x1e, 0x00, 0xc1, 0x16, 0x4f, 0x00,
+       0x79, 0x7e, 0x1a, 0x00, 0x8f, 0x97, 0x03, 0x00,
+       0x17, 0x48, 0x4e, 0x00, 0x59, 0xb8, 0x31, 0x00,
+       0xcc, 0x84, 0x58, 0x00, 0x27, 0x48, 0x1b, 0x00,
+       0xd0, 0x63, 0x5b, 0x00, 0x7a, 0x78, 0x5d, 0x00,
+       0x5e, 0x22, 0x35, 0x00, 0x7e, 0x0c, 0x40, 0x00,
+       0xd1, 0x09, 0x6c, 0x00, 0x32, 0xd5, 0x5b, 0x00,
+       0xd3, 0xc4, 0x6b, 0x00, 0xcb, 0x8e, 0x25, 0x00,
+       0x4c, 0x53, 0x2e, 0x00, 0x6c, 0x7a, 0x09, 0x00,
+       0x20, 0x88, 0x3b, 0x00, 0x5c, 0x28, 0x6d, 0x00,
+       0xf8, 0xa4, 0x2c, 0x00, 0xaa, 0x7c, 0x33, 0x00,
+       0xa0, 0xb2, 0x14, 0x00, 0x36, 0x85, 0x55, 0x00,
+       0x86, 0xf1, 0x28, 0x00, 0x5d, 0x79, 0x55, 0x00,
+       0x70, 0xf6, 0x4a, 0x00, 0x86, 0x4a, 0x23, 0x00,
+       0x26, 0xe8, 0x75, 0x00, 0x66, 0xde, 0x78, 0x00,
+       0x8c, 0x52, 0x05, 0x00, 0x59, 0xdf, 0x7a, 0x00,
+       0x17, 0x6e, 0x0f, 0x00, 0xda, 0xf3, 0x5b, 0x00,
+       0x7e, 0x9b, 0x45, 0x00, 0x34, 0x8b, 0x62, 0x00,
+       0xcb, 0xbe, 0x5d, 0x00, 0x7b, 0x9e, 0x1a, 0x00,
+       0xd9, 0x06, 0x00, 0x00, 0xc5, 0x57, 0x62, 0x00,
+       0x3c, 0x4b, 0x57, 0x00, 0xef, 0xa8, 0x69, 0x00,
+       0x38, 0x98, 0x28, 0x00, 0xfe, 0xb5, 0x64, 0x00,
+       0xf5, 0xf8, 0x7e, 0x00, 0x78, 0x4e, 0x2a, 0x00,
+       0x23, 0x0a, 0x12, 0x00, 0xa8, 0x54, 0x01, 0x00,
+       0xff, 0xb7, 0x09, 0x00, 0x87, 0x5e, 0x43, 0x00,
+       0xf8, 0x7f, 0x43, 0x00, 0xb4, 0xd5, 0x5c, 0x00,
+       0x4e, 0xc0, 0x4d, 0x00, 0xaf, 0x28, 0x47, 0x00,
+       0x5d, 0x73, 0x7f, 0x00, 0x0d, 0x8d, 0x0c, 0x00,
+       0xd5, 0x66, 0x0f, 0x00, 0x80, 0x6d, 0x5a, 0x00,
+       0x98, 0xab, 0x61, 0x00, 0x96, 0x5d, 0x18, 0x00,
+       0x31, 0x7f, 0x43, 0x00, 0x98, 0x82, 0x46, 0x00,
+       0x60, 0x29, 0x66, 0x00, 0x79, 0xd5, 0x4b, 0x00,
+       0x06, 0xde, 0x28, 0x00, 0x8d, 0x5d, 0x46, 0x00,
+       0xe3, 0xb0, 0x49, 0x00, 0x34, 0xb4, 0x09, 0x00,
+       0xb3, 0x0d, 0x7c, 0x00, 0xb0, 0x68, 0x5a, 0x00,
+       0xa9, 0x9b, 0x40, 0x00, 0xd5, 0xd3, 0x64, 0x00,
+       0x2a, 0x76, 0x21, 0x00, 0x91, 0x85, 0x65, 0x00,
+       0x39, 0x6e, 0x24, 0x00, 0x9b, 0xc3, 0x48, 0x00,
+       0x59, 0xc7, 0x7b, 0x00, 0x59, 0x58, 0x4f, 0x00,
+       0xb2, 0x2d, 0x39, 0x00, 0x23, 0x09, 0x23, 0x00,
+       0x67, 0xeb, 0x12, 0x00, 0xf2, 0x4d, 0x45, 0x00,
+       0x1c, 0xc3, 0x30, 0x00, 0x24, 0x54, 0x28, 0x00,
+       0x2e, 0x23, 0x13, 0x00, 0x80, 0xaf, 0x7f, 0x00,
+       0xcb, 0xbf, 0x2d, 0x00, 0x0b, 0x2a, 0x02, 0x00,
+       0x2c, 0x83, 0x7e, 0x00, 0x7a, 0x58, 0x26, 0x00,
+       0x75, 0x33, 0x6b, 0x00, 0x76, 0x5b, 0x09, 0x00,
+       0xcc, 0xe1, 0x6b, 0x00, 0x1e, 0x06, 0x5e, 0x00,
+       0x0d, 0xe0, 0x78, 0x00, 0x37, 0x8c, 0x62, 0x00,
+       0x04, 0xa6, 0x3d, 0x00, 0x3c, 0xe5, 0x4a, 0x00,
+       0x68, 0x1d, 0x1f, 0x00, 0xbb, 0x30, 0x63, 0x00,
+       0xb8, 0x61, 0x73, 0x00, 0x6c, 0xa0, 0x5e, 0x00,
+       0xc7, 0x1a, 0x67, 0x00, 0xc6, 0x1f, 0x20, 0x00,
+       0xff, 0xa4, 0x5b, 0x00, 0x72, 0xd7, 0x60, 0x00,
+       0x01, 0xf2, 0x08, 0x00, 0x24, 0xe0, 0x6d, 0x00,
+       0x6d, 0x0e, 0x08, 0x00, 0x8e, 0x03, 0x56, 0x00,
+       0x88, 0x56, 0x69, 0x00, 0x3e, 0x6d, 0x1e, 0x00,
+       0xbd, 0x03, 0x26, 0x00, 0xfa, 0x9d, 0x6a, 0x00,
+       0x17, 0xc0, 0x07, 0x00, 0xd4, 0xbf, 0x6d, 0x00,
+       0xbd, 0xd0, 0x74, 0x00, 0xe3, 0xe1, 0x63, 0x00,
+       0x73, 0x95, 0x51, 0x00, 0x0d, 0xb6, 0x7a, 0x00,
+       0xba, 0x67, 0x28, 0x00, 0xd4, 0xec, 0x2d, 0x00,
+       0x8c, 0x01, 0x58, 0x00, 0xf5, 0x4c, 0x3f, 0x00,
+       0x09, 0x70, 0x0b, 0x00, 0x23, 0x7e, 0x42, 0x00,
+       0x37, 0xbd, 0x3c, 0x00, 0x33, 0x33, 0x27, 0x00,
+       0x57, 0x39, 0x67, 0x00, 0x5d, 0x4b, 0x1a, 0x00,
+       0x26, 0x69, 0x19, 0x00, 0x06, 0xf2, 0x1e, 0x00,
+       0x4e, 0xc1, 0x11, 0x00, 0xc8, 0x76, 0x4c, 0x00,
+       0x2f, 0xf4, 0x3c, 0x00, 0x9a, 0xb1, 0x7f, 0x00,
+       0x6c, 0xf6, 0x6a, 0x00, 0x69, 0x16, 0x2e, 0x00,
+       0xd6, 0x52, 0x33, 0x00, 0x60, 0x47, 0x03, 0x00,
+       0x60, 0x52, 0x08, 0x00, 0x78, 0x1e, 0x74, 0x00,
+       0x16, 0x63, 0x2f, 0x00, 0x11, 0x0a, 0x6f, 0x00,
+       0xf1, 0xc0, 0x07, 0x00, 0x0b, 0x6d, 0x77, 0x00,
+       0xf0, 0x1f, 0x0d, 0x00, 0x24, 0x58, 0x34, 0x00,
+       0xd4, 0x23, 0x02, 0x00, 0x59, 0xc5, 0x68, 0x00,
+       0x85, 0x88, 0x5e, 0x00, 0x32, 0xaa, 0x2f, 0x00,
+       0x65, 0xfc, 0x23, 0x00, 0x42, 0x69, 0x5e, 0x00,
+       0xed, 0xe0, 0x51, 0x00, 0xb3, 0xad, 0x65, 0x00,
+       0xe6, 0xa5, 0x2c, 0x00, 0xfe, 0xe1, 0x79, 0x00,
+       0x64, 0x40, 0x7b, 0x00, 0xdd, 0xe1, 0x35, 0x00,
+       0xac, 0x3a, 0x43, 0x00, 0xde, 0x4a, 0x46, 0x00,
+       0x14, 0xfe, 0x1c, 0x00, 0xce, 0xf1, 0x73, 0x00,
+       0x0e, 0x17, 0x10, 0x00, 0xd7, 0xb6, 0x74, 0x00,
+};
+
+const struct re_ml_entry re_ml_zeta_tbl[2] = {
+       {
+               .data = re_mlkem_zeta_tbl,
+               .len = sizeof(re_mlkem_zeta_tbl)
+       },
+       {
+               .data = re_mldsa_zeta_tbl,
+               .len = sizeof(re_mldsa_zeta_tbl)
+       }
+};
+
+int
+roc_re_ml_zeta_get(uint64_t *tbl)
+{
+       int len = (RE_MLKEM_ZETA_LEN + RE_MLDSA_ZETA_LEN);
+       const char name[] = RE_ML_TBL_NAME;
+       const struct plt_memzone *mz;
+       struct re_ml_tbl *ml;
+       uint8_t *data;
+
+       if (tbl == NULL)
+               return -EINVAL;
+
+       mz = plt_memzone_lookup(name);
+       if (mz == NULL) {
+               /* Create memzone first time */
+               mz = plt_memzone_reserve_cache_align(name, sizeof(struct 
re_ml_tbl) + len);
+               if (mz == NULL)
+                       return -ENOMEM;
+       }
+
+       ml = (struct re_ml_tbl *)mz->addr;
+       if (plt_atomic_fetch_add_explicit(&ml->refcount, 1, 
plt_memory_order_seq_cst) != 0)
+               return 0;
+
+       data = PLT_PTR_ADD(mz->addr, sizeof(uint64_t));
+       memcpy(data, re_ml_zeta_tbl[0].data, re_ml_zeta_tbl[0].len);
+       tbl[0] = plt_cpu_to_be_64((uintptr_t)data);
+
+       data = PLT_PTR_ADD(data, re_ml_zeta_tbl[0].len);
+       memcpy(data, re_ml_zeta_tbl[1].data, re_ml_zeta_tbl[1].len);
+       tbl[1] = plt_cpu_to_be_64((uintptr_t)data);
+
+       return 0;
+}
+
+void
+roc_re_ml_zeta_put(void)
+{
+       const char name[] = RE_ML_TBL_NAME;
+       const struct plt_memzone *mz;
+       struct re_ml_tbl *ml;
+
+       mz = plt_memzone_lookup(name);
+       if (mz == NULL)
+               return;
+
+       ml = (struct re_ml_tbl *)mz->addr;
+       if (plt_atomic_fetch_sub_explicit(&ml->refcount, 1, 
plt_memory_order_seq_cst) == 1)
+               plt_memzone_free(mz);
+}
diff --git a/drivers/common/cnxk/roc_re_ml_tables.h 
b/drivers/common/cnxk/roc_re_ml_tables.h
new file mode 100644
index 0000000000..0a425f711d
--- /dev/null
+++ b/drivers/common/cnxk/roc_re_ml_tables.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2026 Marvell.
+ */
+
+#ifndef _ROC_RE_ML_TABLES_H_
+#define _ROC_RE_ML_TABLES_H_
+
+#include "roc_platform.h"
+
+enum roc_re_ml_zeta_idx {
+       ROC_RE_ML_ZETA_IDX_KEM = 0,
+       ROC_RE_ML_ZETA_IDX_DSA,
+       ROC_RE_ML_ZETA_IDX_MAX
+};
+
+int __roc_api roc_re_ml_zeta_get(uint64_t *tbl);
+void __roc_api roc_re_ml_zeta_put(void);
+
+#endif /* _ROC_RE_ML_TABLES_H_ */
diff --git a/drivers/crypto/cnxk/cnxk_ae.h b/drivers/crypto/cnxk/cnxk_ae.h
index 21a0c8068a..691f9bfce5 100644
--- a/drivers/crypto/cnxk/cnxk_ae.h
+++ b/drivers/crypto/cnxk/cnxk_ae.h
@@ -10,6 +10,7 @@
 #include <rte_malloc.h>
 
 #include "roc_ae.h"
+#include "roc_re.h"
 
 #include "cnxk_cryptodev_ops.h"
 
@@ -24,8 +25,11 @@ struct cnxk_ae_sess {
                struct rte_crypto_rsa_xform rsa_ctx;
                struct rte_crypto_modex_xform mod_ctx;
                struct roc_ae_ec_ctx ec_ctx;
+               struct rte_crypto_ml_kem_xform ml_kem_ctx;
+               struct rte_crypto_ml_dsa_xform ml_dsa_ctx;
        };
        uint64_t *cnxk_fpm_iova;
+       uint64_t *cnxk_ml_iova;
        struct roc_ae_ec_group **ec_grp;
        uint64_t cpt_inst_w4;
        uint64_t cpt_inst_w7;
@@ -52,6 +56,15 @@ struct cnxk_ae_sess {
        } hw_ctx __plt_aligned(ROC_ALIGN);
 };
 
+static const uint8_t mldsa_hash_algo[] = {
+       [RTE_CRYPTO_AUTH_SHA3_224] = 0xA,
+       [RTE_CRYPTO_AUTH_SHA3_256] = 0xB,
+       [RTE_CRYPTO_AUTH_SHA3_384] = 0xC,
+       [RTE_CRYPTO_AUTH_SHA3_512] = 0xD,
+       [RTE_CRYPTO_AUTH_SHAKE_128] = 0xE,
+       [RTE_CRYPTO_AUTH_SHAKE_256] = 0xF,
+};
+
 static __rte_always_inline void
 cnxk_ae_modex_param_normalize(uint8_t **data, size_t *len, size_t max)
 {
@@ -259,6 +272,32 @@ cnxk_ae_fill_ec_params(struct cnxk_ae_sess *sess, struct 
rte_crypto_asym_xform *
        return 0;
 }
 
+static __rte_always_inline int
+cnxk_ae_fill_ml_kem_params(struct cnxk_ae_sess *sess,
+                          struct rte_crypto_asym_xform *xform)
+{
+       struct rte_crypto_ml_kem_xform *ml_kem = &sess->ml_kem_ctx;
+       if (xform->mlkem.type == RTE_CRYPTO_ML_KEM_NONE)
+               return -EINVAL;
+
+       ml_kem->type = xform->mlkem.type;
+       return 0;
+}
+
+static __rte_always_inline int
+cnxk_ae_fill_ml_dsa_params(struct cnxk_ae_sess *sess,
+                          struct rte_crypto_asym_xform *xform)
+{
+       struct rte_crypto_ml_dsa_xform *ml_dsa = &sess->ml_dsa_ctx;
+       if (xform->mldsa.type == RTE_CRYPTO_ML_DSA_NONE)
+               return -EINVAL;
+
+       ml_dsa->type = xform->mldsa.type;
+       ml_dsa->sign_deterministic = xform->mldsa.sign_deterministic;
+       ml_dsa->sign_prehash = xform->mldsa.sign_prehash;
+       return 0;
+}
+
 static __rte_always_inline int
 cnxk_ae_fill_session_parameters(struct cnxk_ae_sess *sess,
                                struct rte_crypto_asym_xform *xform)
@@ -284,6 +323,12 @@ cnxk_ae_fill_session_parameters(struct cnxk_ae_sess *sess,
        case RTE_CRYPTO_ASYM_XFORM_EDDSA:
                ret = cnxk_ae_fill_ec_params(sess, xform);
                break;
+       case RTE_CRYPTO_ASYM_XFORM_ML_KEM:
+               ret = cnxk_ae_fill_ml_kem_params(sess, xform);
+               break;
+       case RTE_CRYPTO_ASYM_XFORM_ML_DSA:
+               ret = cnxk_ae_fill_ml_dsa_params(sess, xform);
+               break;
        default:
                return -ENOTSUP;
        }
@@ -563,6 +608,280 @@ cnxk_ae_enqueue_rsa_op(struct rte_crypto_op *op, struct 
roc_ae_buf_ptr *meta_buf
        return 0;
 }
 
+static __rte_always_inline int __rte_hot
+cnxk_ae_enqueue_ml_kem_op(struct rte_crypto_op *op, struct roc_ae_buf_ptr 
*meta_buf,
+                      struct cnxk_ae_sess *sess, struct cpt_inst_s *inst)
+{
+       size_t metabuf_len = cnxk_cpt_asym_get_mlen(), reqbuf_len;
+       struct rte_crypto_ml_kem_op *mlkem = &op->asym->mlkem;
+       union cpt_inst_w4 w4;
+       uint32_t dlen = 0;
+       uint16_t param2;
+       uint8_t *dptr;
+
+       /* Input buffer */
+       dptr = meta_buf->vaddr;
+       inst->dptr = (uintptr_t)dptr;
+
+       switch (mlkem->op) {
+       case RTE_CRYPTO_ML_KEM_OP_KEYGEN:
+               reqbuf_len = mlkem->keygen.d.length + mlkem->keygen.z.length;
+               if (reqbuf_len > (metabuf_len - dlen)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -ENOMEM;
+               }
+
+               memcpy(dptr, mlkem->keygen.d.data, mlkem->keygen.d.length);
+               dptr += mlkem->keygen.d.length;
+               memcpy(dptr, mlkem->keygen.z.data, mlkem->keygen.z.length);
+               dptr += mlkem->keygen.z.length;
+
+               dlen = mlkem->keygen.d.length + mlkem->keygen.z.length;
+               w4.s.opcode_major = ROC_RE_MAJOR_OP_MLKEM;
+               w4.s.opcode_minor = ROC_RE_MINOR_OP_MLKEM_KEYGEN;
+               param2 = sess->ml_kem_ctx.type;
+               param2 |= (!!dlen << ROC_RE_ML_KEM_PARAM2_INSEED_BIT);
+               break;
+       case RTE_CRYPTO_ML_KEM_OP_ENCAP:
+               reqbuf_len = mlkem->encap.message.length + 
mlkem->encap.ek.length;
+               if (reqbuf_len > (metabuf_len - dlen)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -ENOMEM;
+               }
+
+               memcpy(dptr, mlkem->encap.message.data, 
mlkem->encap.message.length);
+               dptr += mlkem->encap.message.length;
+               memcpy(dptr, mlkem->encap.ek.data, mlkem->encap.ek.length);
+               dptr += mlkem->encap.ek.length;
+
+               dlen = mlkem->encap.message.length + mlkem->encap.ek.length;
+               w4.s.opcode_major = ROC_RE_MAJOR_OP_MLKEM;
+               w4.s.opcode_minor = ROC_RE_MINOR_OP_MLKEM_ENCAP;
+               param2 = sess->ml_kem_ctx.type;
+               param2 |= (!!mlkem->encap.message.length << 
ROC_RE_ML_KEM_PARAM2_INMSG_BIT);
+               break;
+       case RTE_CRYPTO_ML_KEM_OP_DECAP:
+               reqbuf_len = mlkem->decap.dk.length + 
mlkem->decap.cipher.length;
+               if (reqbuf_len > (metabuf_len - dlen)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -ENOMEM;
+               }
+
+               memcpy(dptr, mlkem->decap.dk.data, mlkem->decap.dk.length);
+               dptr += mlkem->decap.dk.length;
+               memcpy(dptr, mlkem->decap.cipher.data, 
mlkem->decap.cipher.length);
+               dptr += mlkem->decap.cipher.length;
+
+               dlen = mlkem->decap.cipher.length + mlkem->decap.dk.length;
+               w4.s.opcode_major = ROC_RE_MAJOR_OP_MLKEM;
+               w4.s.opcode_minor = ROC_RE_MINOR_OP_MLKEM_DECAP;
+               param2 = sess->ml_kem_ctx.type;
+               break;
+       default:
+               op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+               return -EINVAL;
+       }
+
+       w4.s.param1 = 0;
+       w4.s.param2 = param2;
+       w4.s.dlen = dlen;
+
+       inst->w4.u64 = w4.u64;
+
+       /* Reuse entire space of meta buffer as output is large in PQC */
+       inst->rptr = (uintptr_t)meta_buf->vaddr;
+
+       return 0;
+}
+
+static __rte_always_inline int __rte_hot
+cnxk_ae_enqueue_ml_dsa_op(struct rte_crypto_op *op, struct roc_ae_buf_ptr 
*meta_buf,
+                      struct cnxk_ae_sess *sess, struct cpt_inst_s *inst)
+{
+       size_t metabuf_len = cnxk_cpt_asym_get_mlen(), reqbuf_len;
+       struct rte_crypto_ml_dsa_op *mldsa = &op->asym->mldsa;
+       enum rte_crypto_auth_algorithm hash;
+       bool sign_deterministic;
+       union cpt_inst_w4 w4;
+       uint16_t param1 = 0;
+       uint32_t dlen = 0;
+       uint16_t param2;
+       uint8_t *dptr;
+       uint8_t minor;
+
+       /* Input buffer */
+       dptr = meta_buf->vaddr;
+       inst->dptr = (uintptr_t)dptr;
+
+       switch (mldsa->op) {
+       case RTE_CRYPTO_ML_DSA_OP_KEYGEN:
+               reqbuf_len = mldsa->keygen.seed.length;
+               if (reqbuf_len > (metabuf_len - dlen)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -ENOMEM;
+               }
+
+               param2 = sess->ml_dsa_ctx.type;
+
+               memcpy(dptr, mldsa->keygen.seed.data, 
mldsa->keygen.seed.length);
+               dptr += mldsa->keygen.seed.length;
+               param2 |= (!!mldsa->keygen.seed.length << 
ROC_RE_ML_DSA_PARAM2_SEED_BIT);
+
+               dlen += mldsa->keygen.seed.length;
+               w4.s.opcode_major = ROC_RE_MAJOR_OP_MLDSA;
+               w4.s.opcode_minor = ROC_RE_MINOR_OP_MLDSA_KEYGEN;
+               break;
+       case RTE_CRYPTO_ML_DSA_OP_SIGN:
+               reqbuf_len = mldsa->siggen.message.length + 
mldsa->siggen.privkey.length +
+                            mldsa->siggen.ctx.length + mldsa->siggen.mu.length 
+
+                            mldsa->siggen.seed.length;
+
+               if (reqbuf_len > (metabuf_len - dlen)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -ENOMEM;
+               }
+
+               sign_deterministic = sess->ml_dsa_ctx.sign_deterministic;
+               hash = op->asym->mldsa.siggen.hash;
+               minor = ROC_RE_MINOR_OP_MLDSA_SIGN;
+
+               param1 = mldsa->siggen.message.length;
+               param2 = sess->ml_dsa_ctx.type;
+               if (hash == 0) {
+                       minor |= (0 << ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT);
+               } else if (mldsa->siggen.mu.length != 0) {
+                       minor |= (3 << ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT);
+               } else {
+                       if (!sess->ml_dsa_ctx.sign_prehash ||
+                               hash >= RTE_DIM(mldsa_hash_algo) || 
mldsa_hash_algo[hash] == 0) {
+                               op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                               return -EINVAL;
+                       }
+
+                       minor |= (1 << ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT);
+                       param2 |= (mldsa_hash_algo[hash] << 
ROC_RE_ML_DSA_PARAM2_SIGN_BIT);
+               }
+
+               minor |= ((sign_deterministic ? 0 : 2) << 
ROC_RE_ML_DSA_MINOR_SIGN_TYPE_BIT);
+
+               if (!sign_deterministic) {
+                       if (!mldsa->siggen.seed.length) {
+                               op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                               return -EINVAL;
+                       }
+
+                       memcpy(dptr, mldsa->siggen.seed.data, 
mldsa->siggen.seed.length);
+                       dptr += mldsa->siggen.seed.length;
+                       dlen += mldsa->siggen.seed.length;
+               }
+
+               memcpy(dptr, mldsa->siggen.privkey.data, 
mldsa->siggen.privkey.length);
+               dptr += mldsa->siggen.privkey.length;
+               dlen += mldsa->siggen.privkey.length;
+
+               memcpy(dptr, mldsa->siggen.ctx.data, mldsa->siggen.ctx.length);
+               dptr += mldsa->siggen.ctx.length;
+               dlen += mldsa->siggen.ctx.length;
+               if (mldsa->siggen.ctx.length > (UINT16_MAX >> 
ROC_RE_ML_DSA_PARAM2_CTXN_BIT)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -EINVAL;
+               }
+               param2 |= ((uint16_t)mldsa->siggen.ctx.length
+                               << ROC_RE_ML_DSA_PARAM2_CTXN_BIT);
+
+               if (mldsa->siggen.mu.length != 0) {
+                       memcpy(dptr, mldsa->siggen.mu.data, 
mldsa->siggen.mu.length);
+                       dptr += mldsa->siggen.mu.length;
+                       dlen += mldsa->siggen.mu.length;
+                       param1 = mldsa->siggen.mu.length;
+               } else if (mldsa->siggen.message.length != 0) {
+                       memcpy(dptr, mldsa->siggen.message.data, 
mldsa->siggen.message.length);
+                       dptr += mldsa->siggen.message.length;
+                       dlen += mldsa->siggen.message.length;
+               }
+
+               w4.s.opcode_major = ROC_RE_MAJOR_OP_MLDSA;
+               w4.s.opcode_minor = minor;
+               break;
+       case RTE_CRYPTO_ML_DSA_OP_VERIFY:
+               reqbuf_len = mldsa->sigver.message.length + 
mldsa->sigver.pubkey.length +
+                            mldsa->sigver.ctx.length + mldsa->sigver.mu.length 
+
+                            mldsa->sigver.sign.length;
+
+               if (reqbuf_len > (metabuf_len - dlen)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -ENOMEM;
+               }
+
+               hash = op->asym->mldsa.sigver.hash;
+               minor = ROC_RE_MINOR_OP_MLDSA_VERIFY;
+
+               param1 = mldsa->sigver.message.length;
+               param2 = sess->ml_dsa_ctx.type;
+               if (hash == 0) {
+                       minor |= (0 << ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT);
+               } else if (mldsa->sigver.mu.length != 0) {
+                       minor |= (3 << ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT);
+               } else {
+                       if (!sess->ml_dsa_ctx.sign_prehash ||
+                               hash >= RTE_DIM(mldsa_hash_algo) || 
mldsa_hash_algo[hash] == 0) {
+                               op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                               return -EINVAL;
+                       }
+
+                       minor |= (1 << ROC_RE_ML_DSA_MINOR_MSG_TYPE_BIT);
+                       param2 |= (mldsa_hash_algo[hash] << 
ROC_RE_ML_DSA_PARAM2_SIGN_BIT);
+               }
+
+               memcpy(dptr, mldsa->sigver.pubkey.data, 
mldsa->sigver.pubkey.length);
+               dptr += mldsa->sigver.pubkey.length;
+               dlen += mldsa->sigver.pubkey.length;
+
+               memcpy(dptr, mldsa->sigver.ctx.data, mldsa->sigver.ctx.length);
+               dptr += mldsa->sigver.ctx.length;
+               dlen += mldsa->sigver.ctx.length;
+               if (mldsa->sigver.ctx.length > (UINT16_MAX >> 
ROC_RE_ML_DSA_PARAM2_CTXN_BIT)) {
+                       op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+                       return -EINVAL;
+               }
+               param2 |= ((uint16_t)mldsa->sigver.ctx.length
+                               << ROC_RE_ML_DSA_PARAM2_CTXN_BIT);
+
+               if (mldsa->sigver.mu.length != 0) {
+                       memcpy(dptr, mldsa->sigver.mu.data, 
mldsa->sigver.mu.length);
+                       dptr += mldsa->sigver.mu.length;
+                       dlen += mldsa->sigver.mu.length;
+                       param1 = mldsa->sigver.mu.length;
+               } else if (mldsa->sigver.message.length != 0) {
+                       memcpy(dptr, mldsa->sigver.message.data, 
mldsa->sigver.message.length);
+                       dptr += mldsa->sigver.message.length;
+                       dlen += mldsa->sigver.message.length;
+               }
+
+               memcpy(dptr, mldsa->sigver.sign.data, 
mldsa->sigver.sign.length);
+               dptr += mldsa->sigver.sign.length;
+               dlen += mldsa->sigver.sign.length;
+
+               w4.s.opcode_major = ROC_RE_MAJOR_OP_MLDSA;
+               w4.s.opcode_minor = minor;
+               break;
+       default:
+               op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+               return -EINVAL;
+       }
+
+       w4.s.param1 = param1;
+       w4.s.param2 = param2;
+       w4.s.dlen = dlen;
+
+       inst->w4.u64 = w4.u64;
+
+       /* Reuse entire space of meta buffer as output is large in PQC */
+       inst->rptr = (uintptr_t)meta_buf->vaddr;
+
+       return 0;
+}
+
 static __rte_always_inline void
 cnxk_ae_ecdsa_sign_prep(struct rte_crypto_ecdsa_op_param *ecdsa,
                        struct roc_ae_buf_ptr *meta_buf,
@@ -1712,6 +2031,55 @@ cnxk_ae_dequeue_ecdh_op(struct rte_crypto_ecdh_op_param 
*ecdh, uint8_t *rptr,
        }
 }
 
+static __rte_always_inline void
+cnxk_ae_dequeue_mlkem_op(struct rte_crypto_ml_kem_op *mlkem, uint8_t *rptr,
+       enum rte_crypto_ml_kem_type type)
+{
+       switch (mlkem->op) {
+       case RTE_CRYPTO_ML_KEM_OP_KEYGEN:
+               mlkem->keygen.dk.length = rte_crypto_ml_kem_privkey_size[type];
+               memcpy(mlkem->keygen.dk.data, rptr, mlkem->keygen.dk.length);
+               mlkem->keygen.ek.length = rte_crypto_ml_kem_pubkey_size[type];
+               memcpy(mlkem->keygen.ek.data, rptr + 384 * (type + 1), 
mlkem->keygen.ek.length);
+               break;
+       case RTE_CRYPTO_ML_KEM_OP_ENCAP:
+               mlkem->encap.sk.length = 32;
+               memcpy(mlkem->encap.sk.data, rptr, mlkem->encap.sk.length);
+               mlkem->encap.cipher.length = 
rte_crypto_ml_kem_cipher_size[type];
+               memcpy(mlkem->encap.cipher.data, rptr + 32, 
mlkem->encap.cipher.length);
+               break;
+       case RTE_CRYPTO_ML_KEM_OP_DECAP:
+               mlkem->decap.sk.length = 32;
+               memcpy(mlkem->decap.sk.data, rptr, mlkem->decap.sk.length);
+               break;
+       default:
+               break;
+       }
+}
+
+static __rte_always_inline void
+cnxk_ae_dequeue_mldsa_op(struct rte_crypto_ml_dsa_op *mldsa, uint8_t *rptr,
+       enum rte_crypto_ml_dsa_type type)
+{
+       switch (mldsa->op) {
+       case RTE_CRYPTO_ML_DSA_OP_KEYGEN:
+               mldsa->keygen.pubkey.length = 
rte_crypto_ml_dsa_pubkey_size[type];
+               memcpy(mldsa->keygen.pubkey.data, rptr, 
mldsa->keygen.pubkey.length);
+               mldsa->keygen.privkey.length = 
rte_crypto_ml_dsa_privkey_size[type];
+               memcpy(mldsa->keygen.privkey.data, rptr + 
mldsa->keygen.pubkey.length,
+                      mldsa->keygen.privkey.length);
+               break;
+       case RTE_CRYPTO_ML_DSA_OP_SIGN:
+               mldsa->siggen.sign.length = rte_crypto_ml_dsa_sign_size[type];
+               memcpy(mldsa->siggen.sign.data, rptr, 
mldsa->siggen.sign.length);
+               break;
+       case RTE_CRYPTO_ML_DSA_OP_VERIFY:
+               break;
+       default:
+               break;
+       }
+}
+
 static __rte_always_inline void *
 cnxk_ae_alloc_meta(struct roc_ae_buf_ptr *buf,
                   struct rte_mempool *cpt_meta_pool,
@@ -1752,56 +2120,46 @@ cnxk_ae_enqueue(struct cnxk_cpt_qp *qp, struct 
rte_crypto_op *op,
        switch (sess->xfrm_type) {
        case RTE_CRYPTO_ASYM_XFORM_MODEX:
                ret = cnxk_ae_modex_prep(op, &meta_buf, &sess->mod_ctx, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_RSA:
                ret = cnxk_ae_enqueue_rsa_op(op, &meta_buf, sess, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_ECDSA:
                ret = cnxk_ae_enqueue_ecdsa_op(op, &meta_buf, sess,
                                               sess->cnxk_fpm_iova,
                                               sess->ec_grp, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_EDDSA:
                ret = cnxk_ae_enqueue_eddsa_op(op, &meta_buf, sess,
                                               sess->cnxk_fpm_iova,
                                               sess->ec_grp, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_SM2:
                ret = cnxk_ae_enqueue_sm2_op(op, &meta_buf, sess,
                                               sess->cnxk_fpm_iova,
                                               sess->ec_grp, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_ECPM:
                ret = cnxk_ae_ecpm_prep(&asym_op->ecpm.scalar, 
&asym_op->ecpm.p, &meta_buf,
                                        sess->ec_grp[sess->ec_ctx.curveid],
                                        sess->ec_ctx.curveid, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_ECFPM:
                ret = cnxk_ae_ecfpm_prep(&asym_op->ecpm.scalar, &meta_buf,
                                         sess->cnxk_fpm_iova,
                                         sess->ec_grp[sess->ec_ctx.curveid],
                                         sess->ec_ctx.curveid, inst);
-               if (unlikely(ret))
-                       goto req_fail;
                break;
        case RTE_CRYPTO_ASYM_XFORM_ECDH:
                ret = cnxk_ae_enqueue_ecdh_op(op, &meta_buf, sess,
                                               sess->cnxk_fpm_iova,
                                               sess->ec_grp, inst);
-               if (unlikely(ret))
-                       goto req_fail;
+               break;
+       case RTE_CRYPTO_ASYM_XFORM_ML_KEM:
+               ret = cnxk_ae_enqueue_ml_kem_op(op, &meta_buf, sess, inst);
+               break;
+       case RTE_CRYPTO_ASYM_XFORM_ML_DSA:
+               ret = cnxk_ae_enqueue_ml_dsa_op(op, &meta_buf, sess, inst);
                break;
        default:
                op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
@@ -1809,6 +2167,9 @@ cnxk_ae_enqueue(struct cnxk_cpt_qp *qp, struct 
rte_crypto_op *op,
                goto req_fail;
        }
 
+       if (unlikely(ret))
+               goto req_fail;
+
        mop = mdata;
        mop[0] = inst->rptr;
        return 0;
@@ -1852,6 +2213,12 @@ cnxk_ae_post_process(struct rte_crypto_op *cop, struct 
cnxk_ae_sess *sess,
                cnxk_ae_dequeue_ecdh_op(&op->ecdh, rptr, &sess->ec_ctx,
                                        sess->ec_grp, op->flags);
                break;
+       case RTE_CRYPTO_ASYM_XFORM_ML_KEM:
+               cnxk_ae_dequeue_mlkem_op(&op->mlkem, rptr, 
sess->ml_kem_ctx.type);
+               break;
+       case RTE_CRYPTO_ASYM_XFORM_ML_DSA:
+               cnxk_ae_dequeue_mldsa_op(&op->mldsa, rptr, 
sess->ml_dsa_ctx.type);
+               break;
        default:
                cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
                break;
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev.c 
b/drivers/crypto/cnxk/cnxk_cryptodev.c
index 5828a502e4..de27c4a580 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev.c
@@ -28,6 +28,9 @@ cnxk_cpt_default_ff_get(void)
        if (roc_model_is_cn10ka_b0() || roc_model_is_cn10kb() || 
roc_model_is_cn20k())
                ff |= RTE_CRYPTODEV_FF_SECURITY_RX_INJECT;
 
+       if (roc_model_is_cn20k())
+               ff |= RTE_CRYPTODEV_FF_MLDSA_SIGN_PREHASH;
+
        return ff;
 }
 
@@ -56,6 +59,14 @@ cnxk_cpt_eng_grp_add(struct roc_cpt *roc_cpt)
                return -ENOTSUP;
        }
 
+       if (roc_model_is_cn20k()) {
+               ret = roc_cpt_eng_grp_add(roc_cpt, CPT_ENG_TYPE_RE);
+               if (ret < 0) {
+                       plt_err("Could not add CPT RE engines");
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev.h 
b/drivers/crypto/cnxk/cnxk_cryptodev.h
index f88162ad3c..bdc5752905 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev.h
+++ b/drivers/crypto/cnxk/cnxk_cryptodev.h
@@ -10,8 +10,9 @@
 
 #include "roc_ae.h"
 #include "roc_cpt.h"
+#include "roc_re_ml_tables.h"
 
-#define CNXK_CPT_MAX_CAPS               60
+#define CNXK_CPT_MAX_CAPS               62
 #define CNXK_SEC_IPSEC_CRYPTO_MAX_CAPS  16
 #define CNXK_SEC_TLS_1_3_CRYPTO_MAX_CAPS 3
 #define CNXK_SEC_TLS_1_2_CRYPTO_MAX_CAPS 7
@@ -33,6 +34,7 @@ struct cnxk_cpt_vf {
                sec_dtls_1_2_crypto_caps[CNXK_SEC_TLS_1_2_CRYPTO_MAX_CAPS];
        struct rte_security_capability sec_caps[CNXK_SEC_MAX_CAPS];
        uint64_t cnxk_fpm_iova[ROC_AE_EC_ID_PMAX];
+       uint64_t cnxk_ml_iova[ROC_RE_ML_ZETA_IDX_MAX];
        struct roc_ae_ec_group *ec_grp[ROC_AE_EC_ID_PMAX];
        uint16_t max_qps_limit;
        uint16_t rx_inject_qp;
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c 
b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
index be6d383717..736d588bde 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
@@ -129,6 +129,63 @@ static const struct rte_cryptodev_capabilities caps_mul[] 
= {
        },
 };
 
+static const struct rte_cryptodev_capabilities caps_pqc[] = {
+       {
+               /* ML-KEM */
+               .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+               .asym = {
+                       .xform_capa = {
+                               .xform_type = RTE_CRYPTO_ASYM_XFORM_ML_KEM,
+                               .op_types =
+                               ((1 << RTE_CRYPTO_ML_KEM_OP_KEYGEN) |
+                                (1 << RTE_CRYPTO_ML_KEM_OP_ENCAP) |
+                                (1 << RTE_CRYPTO_ML_KEM_OP_DECAP)),
+                               .mlkem_capa = {
+                                       [RTE_CRYPTO_ML_KEM_OP_KEYGEN] =
+                                               (1 << RTE_CRYPTO_ML_KEM_512) |
+                                               (1 << RTE_CRYPTO_ML_KEM_768) |
+                                               (1 << RTE_CRYPTO_ML_KEM_1024),
+                                       [RTE_CRYPTO_ML_KEM_OP_ENCAP] =
+                                               (1 << RTE_CRYPTO_ML_KEM_512) |
+                                               (1 << RTE_CRYPTO_ML_KEM_768) |
+                                               (1 << RTE_CRYPTO_ML_KEM_1024),
+                                       [RTE_CRYPTO_ML_KEM_OP_DECAP] =
+                                               (1 << RTE_CRYPTO_ML_KEM_512) |
+                                               (1 << RTE_CRYPTO_ML_KEM_768) |
+                                               (1 << RTE_CRYPTO_ML_KEM_1024)
+                               }
+                       }
+               }
+       },
+       {
+               /* ML-DSA */
+               .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+               .asym = {
+                       .xform_capa = {
+                               .xform_type = RTE_CRYPTO_ASYM_XFORM_ML_DSA,
+                               .op_types =
+                               ((1 << RTE_CRYPTO_ML_DSA_OP_SIGN) |
+                                (1 << RTE_CRYPTO_ML_DSA_OP_KEYGEN) |
+                                (1 << RTE_CRYPTO_ML_DSA_OP_VERIFY)),
+                               .mldsa_capa = {
+                                       [RTE_CRYPTO_ML_DSA_OP_KEYGEN] =
+                                               (1 << RTE_CRYPTO_ML_DSA_44) |
+                                               (1 << RTE_CRYPTO_ML_DSA_65) |
+                                               (1 << RTE_CRYPTO_ML_DSA_87),
+                                       [RTE_CRYPTO_ML_DSA_OP_SIGN] =
+                                               (1 << RTE_CRYPTO_ML_DSA_44) |
+                                               (1 << RTE_CRYPTO_ML_DSA_65) |
+                                               (1 << RTE_CRYPTO_ML_DSA_87),
+                                       [RTE_CRYPTO_ML_DSA_OP_VERIFY] =
+                                               (1 << RTE_CRYPTO_ML_DSA_44) |
+                                               (1 << RTE_CRYPTO_ML_DSA_65) |
+                                               (1 << RTE_CRYPTO_ML_DSA_87)
+                               }
+                       }
+               }
+       },
+};
+
 static const struct rte_cryptodev_capabilities caps_sha1_sha2[] = {
        {       /* SHA1 */
                .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
@@ -2079,10 +2136,13 @@ crypto_caps_populate(struct rte_cryptodev_capabilities 
cnxk_caps[],
        if (roc_model_is_cn10k() || roc_model_is_cn20k())
                cn10k_20k_crypto_caps_add(cnxk_caps, hw_caps, &cur_pos);
 
-       if (roc_model_is_cn20k())
+       if (roc_model_is_cn20k()) {
                CPT_CAPS_ADD(cnxk_caps, &cur_pos, hw_caps, zuc256_snow5g);
+               cpt_caps_add(cnxk_caps, &cur_pos, caps_pqc, RTE_DIM(caps_pqc));
+       }
 
        cpt_caps_add(cnxk_caps, &cur_pos, caps_null, RTE_DIM(caps_null));
+
        cpt_caps_add(cnxk_caps, &cur_pos, caps_end, RTE_DIM(caps_end));
 
        if (roc_model_is_cn10k() || roc_model_is_cn20k())
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev_ops.c 
b/drivers/crypto/cnxk/cnxk_cryptodev_ops.c
index 2f9eb322dc..0f44a393db 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev_ops.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev_ops.c
@@ -23,6 +23,7 @@
 #else
 #include "roc_io_generic.h"
 #endif
+#include "roc_re_ml_tables.h"
 
 #include "cnxk_ae.h"
 #include "cnxk_cryptodev.h"
@@ -41,6 +42,14 @@
 
 #define CNXK_CPT_MAX_ASYM_OP_NUM_PARAMS         5
 #define CNXK_CPT_MAX_ASYM_OP_MOD_LEN    1024
+
+/*
+ * PQC requests currently use a shared metabuf region for concatenated input
+ * and output. ML-DSA-87 SIGN requires at least 9523 bytes for private key
+ * input plus signature output, along with additional space for message and
+ * context parameters, so set it for the possible max.
+ */
+#define CNXK_CPT_MAX_ASYM_OP_PQC_LEN    16384
 #define CNXK_CPT_META_BUF_MAX_CACHE_SIZE 128
 
 static_assert((uint16_t)RTE_PMD_CNXK_AE_EC_ID_P192 == 
(uint16_t)ROC_AE_EC_ID_P192,
@@ -107,7 +116,10 @@ cnxk_cpt_asym_get_mlen(void)
        len = sizeof(uint64_t);
 
        /* Get meta len for asymmetric operations */
-       len += CNXK_CPT_MAX_ASYM_OP_NUM_PARAMS * CNXK_CPT_MAX_ASYM_OP_MOD_LEN;
+       if (roc_model_is_cn20k())
+               len += CNXK_CPT_MAX_ASYM_OP_PQC_LEN;
+       else
+               len += CNXK_CPT_MAX_ASYM_OP_NUM_PARAMS * 
CNXK_CPT_MAX_ASYM_OP_MOD_LEN;
 
        return len;
 }
@@ -121,6 +133,8 @@ cnxk_cpt_dev_clear(struct rte_cryptodev *dev)
        if (dev->feature_flags & RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO) {
                roc_ae_fpm_put();
                roc_ae_ec_grp_put();
+               if (roc_model_is_cn20k())
+                       roc_re_ml_zeta_put();
        }
 
        ret = roc_cpt_int_misc_cb_unregister(cnxk_cpt_int_misc_cb, NULL);
@@ -182,8 +196,15 @@ cnxk_cpt_dev_config(struct rte_cryptodev *dev, struct 
rte_cryptodev_config *conf
                ret = roc_ae_ec_grp_get(vf->ec_grp);
                if (ret) {
                        plt_err("Could not get EC grp table");
-                       roc_ae_fpm_put();
-                       return ret;
+                       goto fpm_put;
+               }
+
+               if (roc_model_is_cn20k()) {
+                       ret = roc_re_ml_zeta_get(vf->cnxk_ml_iova);
+                       if (ret) {
+                               plt_err("Could not initialize RE ML lookup 
table");
+                               goto ec_grp_put;
+                       }
                }
        }
        roc_cpt->opaque = dev;
@@ -191,6 +212,12 @@ cnxk_cpt_dev_config(struct rte_cryptodev *dev, struct 
rte_cryptodev_config *conf
        roc_cpt_int_misc_cb_register(cnxk_cpt_int_misc_cb, NULL);
 
        return 0;
+
+ec_grp_put:
+       roc_ae_ec_grp_put();
+fpm_put:
+       roc_ae_fpm_put();
+       return ret;
 }
 
 int
@@ -992,7 +1019,16 @@ cnxk_ae_session_cfg(struct rte_cryptodev *dev, struct 
rte_crypto_asym_xform *xfo
        priv->lf = roc_cpt->lf[0];
 
        w7.u64 = 0;
-       w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_AE];
+       if (xform->xform_type == RTE_CRYPTO_ASYM_XFORM_ML_KEM) {
+               w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_RE];
+               w7.s.cptr = 
rte_cpu_to_be_64(vf->cnxk_ml_iova[ROC_RE_ML_ZETA_IDX_KEM]);
+       } else if (xform->xform_type == RTE_CRYPTO_ASYM_XFORM_ML_DSA) {
+               w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_RE];
+               w7.s.cptr = 
rte_cpu_to_be_64(vf->cnxk_ml_iova[ROC_RE_ML_ZETA_IDX_DSA]);
+       } else {
+               w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_AE];
+               w7.s.cptr = 0;
+       }
 
        if (roc_errata_cpt_hang_on_mixed_ctx_val()) {
                hwc = &priv->hw_ctx;
@@ -1007,6 +1043,7 @@ cnxk_ae_session_cfg(struct rte_cryptodev *dev, struct 
rte_crypto_asym_xform *xfo
 
        priv->cpt_inst_w7 = w7.u64;
        priv->cnxk_fpm_iova = vf->cnxk_fpm_iova;
+       priv->cnxk_ml_iova = vf->cnxk_ml_iova;
        priv->ec_grp = vf->ec_grp;
 
        return 0;
-- 
2.37.1


Reply via email to