From: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com>
To: herbert@gondor.apana.org.au
Cc: linux-crypto@vger.kernel.org, qat-linux@intel.com,
Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com>,
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Subject: [PATCH v2] crypto: qat - add anti-rollback support for GEN6 devices
Date: Thu, 19 Mar 2026 11:02:57 +0000 [thread overview]
Message-ID: <20260319110331.248189-1-suman.kumar.chakraborty@intel.com> (raw)
Anti-Rollback (ARB) is a QAT GEN6 hardware feature that prevents loading
firmware with a Security Version Number (SVN) lower than an authorized
minimum. This protects against downgrade attacks by ensuring that only
firmware at or above a committed SVN can run on the acceleration device.
During firmware loading, the driver checks the SVN validation status via
a hardware CSR. If the check reports a failure, firmware authentication
is aborted. If it reports a retry status, the driver reissues the
authentication command up to a maximum number of retries.
Extend the firmware admin interface with two new messages,
ICP_QAT_FW_SVN_READ and ICP_QAT_FW_SVN_COMMIT, to query and commit the
SVN, respectively. Integrate the SVN check into the firmware
authentication path in qat_uclo.c so the driver can react to
anti-rollback status during device bring-up.
Expose SVN information to userspace via a new sysfs attribute group,
qat_svn, under the PCI device directory. The group provides read-only
attributes for the active, enforced minimum, and permanent minimum SVN
values, as well as a write-only commit attribute that allows a system
administrator to commit the currently active SVN as the new authorized
minimum.
This is based on earlier work by Ciunas Bennett.
Signed-off-by: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
v1->v2
- Replaced "Secure" with "Security" in the required files as SVN
means Security version number.
- Style changes in adf_anti_rb.h
.../ABI/testing/sysfs-driver-qat_svn | 114 +++++++++++++++
.../intel/qat/qat_6xxx/adf_6xxx_hw_data.c | 16 +++
.../intel/qat/qat_6xxx/adf_6xxx_hw_data.h | 6 +
drivers/crypto/intel/qat/qat_common/Makefile | 2 +
.../intel/qat/qat_common/adf_accel_devices.h | 2 +
.../crypto/intel/qat/qat_common/adf_admin.c | 70 +++++++++
.../crypto/intel/qat/qat_common/adf_admin.h | 2 +
.../crypto/intel/qat/qat_common/adf_anti_rb.c | 66 +++++++++
.../crypto/intel/qat/qat_common/adf_anti_rb.h | 37 +++++
.../crypto/intel/qat/qat_common/adf_init.c | 3 +
.../intel/qat/qat_common/adf_sysfs_anti_rb.c | 133 ++++++++++++++++++
.../intel/qat/qat_common/adf_sysfs_anti_rb.h | 11 ++
.../qat/qat_common/icp_qat_fw_init_admin.h | 15 +-
.../crypto/intel/qat/qat_common/qat_uclo.c | 25 +++-
14 files changed, 497 insertions(+), 5 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-driver-qat_svn
create mode 100644 drivers/crypto/intel/qat/qat_common/adf_anti_rb.c
create mode 100644 drivers/crypto/intel/qat/qat_common/adf_anti_rb.h
create mode 100644 drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.c
create mode 100644 drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.h
diff --git a/Documentation/ABI/testing/sysfs-driver-qat_svn b/Documentation/ABI/testing/sysfs-driver-qat_svn
new file mode 100644
index 000000000000..3832b523dcb0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-qat_svn
@@ -0,0 +1,114 @@
+What: /sys/bus/pci/devices/<BDF>/qat_svn/
+Date: June 2026
+KernelVersion: 7.1
+Contact: qat-linux@intel.com
+Description: Directory containing Security Version Number (SVN) attributes for
+ the Anti-Rollback (ARB) feature. The ARB feature prevents downloading
+ older firmware versions to the acceleration device.
+
+What: /sys/bus/pci/devices/<BDF>/qat_svn/enforced_min
+Date: June 2026
+KernelVersion: 7.1
+Contact: qat-linux@intel.com
+Description:
+ (RO) Reports the minimum allowed firmware SVN.
+
+ Returns an integer greater than zero. Firmware with SVN lower than
+ this value is rejected.
+
+ A write to qat_svn/commit will update this value. The update is not
+ persistent across reboot; on reboot, this value is reset from
+ qat_svn/permanent_min.
+
+ Example usage::
+
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/enforced_min
+ 2
+
+ This attribute is available only on devices that support
+ Anti-Rollback.
+
+What: /sys/bus/pci/devices/<BDF>/qat_svn/permanent_min
+Date: June 2026
+KernelVersion: 7.1
+Contact: qat-linux@intel.com
+Description:
+ (RO) Reports the persistent minimum SVN used to initialize
+ qat_svn/enforced_min on each reboot.
+
+ Returns an integer greater than zero. A write to qat_svn/commit
+ may update this value, depending on platform/BIOS settings.
+
+ Example usage::
+
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/permanent_min
+ 3
+
+ This attribute is available only on devices that support
+ Anti-Rollback.
+
+What: /sys/bus/pci/devices/<BDF>/qat_svn/active
+Date: June 2026
+KernelVersion: 7.1
+Contact: qat-linux@intel.com
+Description:
+ (RO) Reports the SVN of the currently active firmware image.
+
+ Returns an integer greater than zero.
+
+ Example usage::
+
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/active
+ 2
+
+ This attribute is available only on devices that support
+ Anti-Rollback.
+
+What: /sys/bus/pci/devices/<BDF>/qat_svn/commit
+Date: June 2026
+KernelVersion: 7.1
+Contact: qat-linux@intel.com
+Description:
+ (WO) Commits the currently active SVN as the minimum allowed SVN.
+
+ Writing 1 sets qat_svn/enforced_min to the value of qat_svn/active,
+ preventing future firmware loads with lower SVN.
+
+ Depending on platform/BIOS settings, a commit may also update
+ qat_svn/permanent_min.
+
+ Note that on reboot, qat_svn/enforced_min reverts to
+ qat_svn/permanent_min.
+
+ It is advisable to use this attribute with caution, only when
+ it is necessary to set a new minimum SVN for the firmware.
+
+ Before committing the SVN update, it is crucial to check the
+ current values of qat_svn/active, qat_svn/enforced_min and
+ qat_svn/permanent_min. This verification helps ensure that the
+ commit operation aligns with the intended outcome.
+
+ While writing to the file, any value other than '1' will result
+ in an error and have no effect.
+
+ Example usage::
+
+ ## Read current values
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/enforced_min
+ 2
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/permanent_min
+ 2
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/active
+ 3
+
+ ## Commit active SVN
+ # echo 1 > /sys/bus/pci/devices/<BDF>/qat_svn/commit
+
+ ## Read updated values
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/enforced_min
+ 3
+ # cat /sys/bus/pci/devices/<BDF>/qat_svn/permanent_min
+ 3
+
+ This attribute is available only on devices that support
+ Anti-Rollback.
diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c
index f4c61978b048..177bc4eb3c24 100644
--- a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c
@@ -462,6 +462,21 @@ static int reset_ring_pair(void __iomem *csr, u32 bank_number)
return 0;
}
+static bool adf_anti_rb_enabled(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+
+ return !!(hw_data->fuses[0] & ADF_GEN6_ANTI_RB_FUSE_BIT);
+}
+
+static void adf_gen6_init_anti_rb(struct adf_anti_rb_hw_data *anti_rb_data)
+{
+ anti_rb_data->anti_rb_enabled = adf_anti_rb_enabled;
+ anti_rb_data->svncheck_offset = ADF_GEN6_SVNCHECK_CSR_MSG;
+ anti_rb_data->svncheck_retry = 0;
+ anti_rb_data->sysfs_added = false;
+}
+
static int ring_pair_reset(struct adf_accel_dev *accel_dev, u32 bank_number)
{
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
@@ -1024,6 +1039,7 @@ void adf_init_hw_data_6xxx(struct adf_hw_device_data *hw_data)
adf_gen6_init_ras_ops(&hw_data->ras_ops);
adf_gen6_init_tl_data(&hw_data->tl_data);
adf_gen6_init_rl_data(&hw_data->rl_data);
+ adf_gen6_init_anti_rb(&hw_data->anti_rb_data);
}
void adf_clean_hw_data_6xxx(struct adf_hw_device_data *hw_data)
diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h
index fa31d6d584e6..e4d433bdd379 100644
--- a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h
+++ b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h
@@ -53,6 +53,12 @@
#define ADF_GEN6_ADMINMSGLR_OFFSET 0x500578
#define ADF_GEN6_MAILBOX_BASE_OFFSET 0x600970
+/* Anti-rollback */
+#define ADF_GEN6_SVNCHECK_CSR_MSG 0x640004
+
+/* Fuse bits */
+#define ADF_GEN6_ANTI_RB_FUSE_BIT BIT(24)
+
/*
* Watchdog timers
* Timeout is in cycles. Clock speed may vary across products but this
diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile
index 89845754841b..016b81e60cfb 100644
--- a/drivers/crypto/intel/qat/qat_common/Makefile
+++ b/drivers/crypto/intel/qat/qat_common/Makefile
@@ -4,6 +4,7 @@ ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"CRYPTO_QAT"'
intel_qat-y := adf_accel_engine.o \
adf_admin.o \
adf_aer.o \
+ adf_anti_rb.o \
adf_bank_state.o \
adf_cfg.o \
adf_cfg_services.o \
@@ -29,6 +30,7 @@ intel_qat-y := adf_accel_engine.o \
adf_rl_admin.o \
adf_rl.o \
adf_sysfs.o \
+ adf_sysfs_anti_rb.o \
adf_sysfs_ras_counters.o \
adf_sysfs_rl.o \
adf_timer.o \
diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
index 9fe3239f0114..cac110215c5e 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/qat/qat_mig_dev.h>
#include <linux/wordpart.h>
+#include "adf_anti_rb.h"
#include "adf_cfg_common.h"
#include "adf_dc.h"
#include "adf_rl.h"
@@ -328,6 +329,7 @@ struct adf_hw_device_data {
struct adf_dev_err_mask dev_err_mask;
struct adf_rl_hw_data rl_data;
struct adf_tl_hw_data tl_data;
+ struct adf_anti_rb_hw_data anti_rb_data;
struct qat_migdev_ops vfmig_ops;
const char *fw_name;
const char *fw_mmp_name;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c
index 573388c37100..841aa802c79e 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_admin.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c
@@ -6,8 +6,10 @@
#include <linux/iopoll.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include "adf_accel_devices.h"
#include "adf_admin.h"
+#include "adf_anti_rb.h"
#include "adf_common_drv.h"
#include "adf_cfg.h"
#include "adf_heartbeat.h"
@@ -19,6 +21,7 @@
#define ADF_ADMIN_POLL_DELAY_US 20
#define ADF_ADMIN_POLL_TIMEOUT_US (5 * USEC_PER_SEC)
#define ADF_ONE_AE 1
+#define ADF_ADMIN_RETRY_MAX 60
static const u8 const_tab[1024] __aligned(1024) = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -536,6 +539,73 @@ int adf_send_admin_tl_stop(struct adf_accel_dev *accel_dev)
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
+static int adf_send_admin_retry(struct adf_accel_dev *accel_dev, u8 cmd_id,
+ struct icp_qat_fw_init_admin_resp *resp,
+ unsigned int sleep_ms)
+{
+ u32 admin_ae_mask = GET_HW_DATA(accel_dev)->admin_ae_mask;
+ struct icp_qat_fw_init_admin_req req = { };
+ unsigned int retries = ADF_ADMIN_RETRY_MAX;
+ int ret;
+
+ req.cmd_id = cmd_id;
+
+ do {
+ ret = adf_send_admin(accel_dev, &req, resp, admin_ae_mask);
+ if (!ret)
+ return 0;
+
+ if (resp->status != ICP_QAT_FW_INIT_RESP_STATUS_RETRY)
+ return ret;
+
+ msleep(sleep_ms);
+ } while (--retries);
+
+ return -ETIMEDOUT;
+}
+
+static int adf_send_admin_svn(struct adf_accel_dev *accel_dev, u8 cmd_id,
+ struct icp_qat_fw_init_admin_resp *resp)
+{
+ return adf_send_admin_retry(accel_dev, cmd_id, resp, ADF_SVN_RETRY_MS);
+}
+
+int adf_send_admin_arb_query(struct adf_accel_dev *accel_dev, int cmd, u8 *svn)
+{
+ struct icp_qat_fw_init_admin_resp resp = { };
+ int ret;
+
+ ret = adf_send_admin_svn(accel_dev, ICP_QAT_FW_SVN_READ, &resp);
+ if (ret)
+ return ret;
+
+ switch (cmd) {
+ case ARB_ENFORCED_MIN_SVN:
+ *svn = resp.enforced_min_svn;
+ break;
+ case ARB_PERMANENT_MIN_SVN:
+ *svn = resp.permanent_min_svn;
+ break;
+ case ARB_ACTIVE_SVN:
+ *svn = resp.active_svn;
+ break;
+ default:
+ *svn = 0;
+ dev_err(&GET_DEV(accel_dev),
+ "Unknown secure version number request\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int adf_send_admin_arb_commit(struct adf_accel_dev *accel_dev)
+{
+ struct icp_qat_fw_init_admin_resp resp = { };
+
+ return adf_send_admin_svn(accel_dev, ICP_QAT_FW_SVN_COMMIT, &resp);
+}
+
int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
struct adf_admin_comms *admin;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.h b/drivers/crypto/intel/qat/qat_common/adf_admin.h
index 647c8e196752..9704219f2eb7 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_admin.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_admin.h
@@ -27,5 +27,7 @@ int adf_send_admin_tl_start(struct adf_accel_dev *accel_dev,
dma_addr_t tl_dma_addr, size_t layout_sz, u8 *rp_indexes,
struct icp_qat_fw_init_admin_slice_cnt *slice_count);
int adf_send_admin_tl_stop(struct adf_accel_dev *accel_dev);
+int adf_send_admin_arb_query(struct adf_accel_dev *accel_dev, int cmd, u8 *svn);
+int adf_send_admin_arb_commit(struct adf_accel_dev *accel_dev);
#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_anti_rb.c b/drivers/crypto/intel/qat/qat_common/adf_anti_rb.c
new file mode 100644
index 000000000000..2c19a82d89ad
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_anti_rb.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2026 Intel Corporation */
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kstrtox.h>
+
+#include "adf_accel_devices.h"
+#include "adf_admin.h"
+#include "adf_anti_rb.h"
+#include "adf_common_drv.h"
+#include "icp_qat_fw_init_admin.h"
+
+#define ADF_SVN_RETRY_MAX 60
+
+int adf_anti_rb_commit(struct adf_accel_dev *accel_dev)
+{
+ return adf_send_admin_arb_commit(accel_dev);
+}
+
+int adf_anti_rb_query(struct adf_accel_dev *accel_dev, enum anti_rb cmd, u8 *svn)
+{
+ return adf_send_admin_arb_query(accel_dev, cmd, svn);
+}
+
+int adf_anti_rb_check(struct pci_dev *pdev)
+{
+ struct adf_anti_rb_hw_data *anti_rb;
+ u32 svncheck_sts, cfc_svncheck_sts;
+ struct adf_accel_dev *accel_dev;
+ void __iomem *pmisc_addr;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+ if (!accel_dev)
+ return -EINVAL;
+
+ anti_rb = GET_ANTI_RB_DATA(accel_dev);
+ if (!anti_rb->anti_rb_enabled || !anti_rb->anti_rb_enabled(accel_dev))
+ return 0;
+
+ pmisc_addr = adf_get_pmisc_base(accel_dev);
+
+ cfc_svncheck_sts = ADF_CSR_RD(pmisc_addr, anti_rb->svncheck_offset);
+
+ svncheck_sts = FIELD_GET(ADF_SVN_STS_MASK, cfc_svncheck_sts);
+ switch (svncheck_sts) {
+ case ADF_SVN_NO_STS:
+ return 0;
+ case ADF_SVN_PASS_STS:
+ anti_rb->svncheck_retry = 0;
+ return 0;
+ case ADF_SVN_FAIL_STS:
+ dev_err(&GET_DEV(accel_dev), "Security Version Number failure\n");
+ return -EIO;
+ case ADF_SVN_RETRY_STS:
+ if (anti_rb->svncheck_retry++ >= ADF_SVN_RETRY_MAX) {
+ anti_rb->svncheck_retry = 0;
+ return -ETIMEDOUT;
+ }
+ msleep(ADF_SVN_RETRY_MS);
+ return -EAGAIN;
+ default:
+ dev_err(&GET_DEV(accel_dev), "Invalid SVN check status\n");
+ return -EINVAL;
+ }
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_anti_rb.h b/drivers/crypto/intel/qat/qat_common/adf_anti_rb.h
new file mode 100644
index 000000000000..531af41a3db8
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_anti_rb.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2026 Intel Corporation */
+#ifndef ADF_ANTI_RB_H_
+#define ADF_ANTI_RB_H_
+
+#include <linux/types.h>
+
+#define GET_ANTI_RB_DATA(accel_dev) (&(accel_dev)->hw_device->anti_rb_data)
+
+#define ADF_SVN_NO_STS 0x00
+#define ADF_SVN_PASS_STS 0x01
+#define ADF_SVN_RETRY_STS 0x02
+#define ADF_SVN_FAIL_STS 0x03
+#define ADF_SVN_RETRY_MS 250
+#define ADF_SVN_STS_MASK GENMASK(7, 0)
+
+enum anti_rb {
+ ARB_ENFORCED_MIN_SVN,
+ ARB_PERMANENT_MIN_SVN,
+ ARB_ACTIVE_SVN,
+};
+
+struct adf_accel_dev;
+struct pci_dev;
+
+struct adf_anti_rb_hw_data {
+ bool (*anti_rb_enabled)(struct adf_accel_dev *accel_dev);
+ u32 svncheck_offset;
+ u32 svncheck_retry;
+ bool sysfs_added;
+};
+
+int adf_anti_rb_commit(struct adf_accel_dev *accel_dev);
+int adf_anti_rb_query(struct adf_accel_dev *accel_dev, enum anti_rb cmd, u8 *svn);
+int adf_anti_rb_check(struct pci_dev *pdev);
+
+#endif /* ADF_ANTI_RB_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c
index 46491048e0bb..ec376583b3ae 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_init.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_init.c
@@ -10,6 +10,7 @@
#include "adf_dbgfs.h"
#include "adf_heartbeat.h"
#include "adf_rl.h"
+#include "adf_sysfs_anti_rb.h"
#include "adf_sysfs_ras_counters.h"
#include "adf_telemetry.h"
@@ -263,6 +264,7 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
adf_dbgfs_add(accel_dev);
adf_sysfs_start_ras(accel_dev);
+ adf_sysfs_start_arb(accel_dev);
return 0;
}
@@ -292,6 +294,7 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
adf_rl_stop(accel_dev);
adf_dbgfs_rm(accel_dev);
adf_sysfs_stop_ras(accel_dev);
+ adf_sysfs_stop_arb(accel_dev);
clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.c
new file mode 100644
index 000000000000..789341ad1bdc
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2026 Intel Corporation */
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#include "adf_anti_rb.h"
+#include "adf_common_drv.h"
+#include "adf_sysfs_anti_rb.h"
+
+static ssize_t enforced_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+ int err;
+ u8 svn;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ err = adf_anti_rb_query(accel_dev, ARB_ENFORCED_MIN_SVN, &svn);
+ if (err)
+ return err;
+
+ return sysfs_emit(buf, "%u\n", svn);
+}
+static DEVICE_ATTR_RO(enforced_min);
+
+static ssize_t active_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+ int err;
+ u8 svn;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ err = adf_anti_rb_query(accel_dev, ARB_ACTIVE_SVN, &svn);
+ if (err)
+ return err;
+
+ return sysfs_emit(buf, "%u\n", svn);
+}
+static DEVICE_ATTR_RO(active);
+
+static ssize_t permanent_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+ int err;
+ u8 svn;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ err = adf_anti_rb_query(accel_dev, ARB_PERMANENT_MIN_SVN, &svn);
+ if (err)
+ return err;
+
+ return sysfs_emit(buf, "%u\n", svn);
+}
+static DEVICE_ATTR_RO(permanent_min);
+
+static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adf_accel_dev *accel_dev;
+ bool val;
+ int err;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ err = kstrtobool(buf, &val);
+ if (err)
+ return err;
+
+ if (!val)
+ return -EINVAL;
+
+ err = adf_anti_rb_commit(accel_dev);
+ if (err)
+ return err;
+
+ return count;
+}
+static DEVICE_ATTR_WO(commit);
+
+static struct attribute *qat_svn_attrs[] = {
+ &dev_attr_commit.attr,
+ &dev_attr_active.attr,
+ &dev_attr_enforced_min.attr,
+ &dev_attr_permanent_min.attr,
+ NULL
+};
+
+static const struct attribute_group qat_svn_group = {
+ .attrs = qat_svn_attrs,
+ .name = "qat_svn",
+};
+
+void adf_sysfs_start_arb(struct adf_accel_dev *accel_dev)
+{
+ struct adf_anti_rb_hw_data *anti_rb = GET_ANTI_RB_DATA(accel_dev);
+
+ if (!anti_rb->anti_rb_enabled || !anti_rb->anti_rb_enabled(accel_dev))
+ return;
+
+ if (device_add_group(&GET_DEV(accel_dev), &qat_svn_group)) {
+ dev_warn(&GET_DEV(accel_dev),
+ "Failed to create qat_svn attribute group\n");
+ return;
+ }
+
+ anti_rb->sysfs_added = true;
+}
+
+void adf_sysfs_stop_arb(struct adf_accel_dev *accel_dev)
+{
+ struct adf_anti_rb_hw_data *anti_rb = GET_ANTI_RB_DATA(accel_dev);
+
+ if (!anti_rb->sysfs_added)
+ return;
+
+ device_remove_group(&GET_DEV(accel_dev), &qat_svn_group);
+
+ anti_rb->sysfs_added = false;
+ anti_rb->svncheck_retry = 0;
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.h b/drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.h
new file mode 100644
index 000000000000..f0c2b6e464f7
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_anti_rb.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2026 Intel Corporation */
+#ifndef ADF_SYSFS_ANTI_RB_H_
+#define ADF_SYSFS_ANTI_RB_H_
+
+struct adf_accel_dev;
+
+void adf_sysfs_start_arb(struct adf_accel_dev *accel_dev);
+void adf_sysfs_stop_arb(struct adf_accel_dev *accel_dev);
+
+#endif /* ADF_SYSFS_ANTI_RB_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h
index 63cf18e2a4e5..6b0f0d100cb9 100644
--- a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h
+++ b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h
@@ -31,11 +31,15 @@ enum icp_qat_fw_init_admin_cmd_id {
ICP_QAT_FW_RL_REMOVE = 136,
ICP_QAT_FW_TL_START = 137,
ICP_QAT_FW_TL_STOP = 138,
+ ICP_QAT_FW_SVN_READ = 146,
+ ICP_QAT_FW_SVN_COMMIT = 147,
};
enum icp_qat_fw_init_admin_resp_status {
ICP_QAT_FW_INIT_RESP_STATUS_SUCCESS = 0,
- ICP_QAT_FW_INIT_RESP_STATUS_FAIL
+ ICP_QAT_FW_INIT_RESP_STATUS_FAIL = 1,
+ ICP_QAT_FW_INIT_RESP_STATUS_RETRY = 2,
+ ICP_QAT_FW_INIT_RESP_STATUS_UNSUPPORTED = 4,
};
struct icp_qat_fw_init_admin_tl_rp_indexes {
@@ -159,6 +163,15 @@ struct icp_qat_fw_init_admin_resp {
};
struct icp_qat_fw_init_admin_slice_cnt slices;
__u16 fw_capabilities;
+ struct {
+ __u8 enforced_min_svn;
+ __u8 permanent_min_svn;
+ __u8 active_svn;
+ __u8 resrvd9;
+ __u16 svn_status;
+ __u16 resrvd10;
+ __u64 resrvd11;
+ };
};
} __packed;
diff --git a/drivers/crypto/intel/qat/qat_common/qat_uclo.c b/drivers/crypto/intel/qat/qat_common/qat_uclo.c
index e61a367b0d17..a00ca2a0900f 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_uclo.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_uclo.c
@@ -12,6 +12,7 @@
#include <linux/pci_ids.h>
#include <linux/wordpart.h>
#include "adf_accel_devices.h"
+#include "adf_anti_rb.h"
#include "adf_common_drv.h"
#include "icp_qat_uclo.h"
#include "icp_qat_hal.h"
@@ -1230,10 +1231,11 @@ static int qat_uclo_map_suof(struct icp_qat_fw_loader_handle *handle,
static int qat_uclo_auth_fw(struct icp_qat_fw_loader_handle *handle,
struct icp_qat_fw_auth_desc *desc)
{
- u32 fcu_sts, retry = 0;
+ unsigned int retries = FW_AUTH_MAX_RETRY;
u32 fcu_ctl_csr, fcu_sts_csr;
u32 fcu_dram_hi_csr, fcu_dram_lo_csr;
u64 bus_addr;
+ u32 fcu_sts;
bus_addr = ADD_ADDR(desc->css_hdr_high, desc->css_hdr_low)
- sizeof(struct icp_qat_auth_chunk);
@@ -1248,17 +1250,32 @@ static int qat_uclo_auth_fw(struct icp_qat_fw_loader_handle *handle,
SET_CAP_CSR(handle, fcu_ctl_csr, FCU_CTRL_CMD_AUTH);
do {
+ int arb_ret;
+
msleep(FW_AUTH_WAIT_PERIOD);
fcu_sts = GET_CAP_CSR(handle, fcu_sts_csr);
+
+ arb_ret = adf_anti_rb_check(handle->pci_dev);
+ if (arb_ret == -EAGAIN) {
+ if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_FAIL) {
+ SET_CAP_CSR(handle, fcu_ctl_csr, FCU_CTRL_CMD_AUTH);
+ continue;
+ }
+ } else if (arb_ret) {
+ goto auth_fail;
+ }
+
if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_FAIL)
goto auth_fail;
+
if (((fcu_sts >> FCU_STS_AUTHFWLD_POS) & 0x1))
if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_DONE)
return 0;
- } while (retry++ < FW_AUTH_MAX_RETRY);
+ } while (--retries);
+
auth_fail:
- pr_err("authentication error (FCU_STATUS = 0x%x),retry = %d\n",
- fcu_sts & FCU_AUTH_STS_MASK, retry);
+ pr_err("authentication error (FCU_STATUS = 0x%x)\n", fcu_sts & FCU_AUTH_STS_MASK);
+
return -EINVAL;
}
base-commit: 36ac8112732d88459ca7e240d1a8e39c7d6c52c0
--
2.52.0
next reply other threads:[~2026-03-19 11:03 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-19 11:02 Suman Kumar Chakraborty [this message]
2026-03-27 10:07 ` [PATCH v2] crypto: qat - add anti-rollback support for GEN6 devices Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260319110331.248189-1-suman.kumar.chakraborty@intel.com \
--to=suman.kumar.chakraborty@intel.com \
--cc=giovanni.cabiddu@intel.com \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=qat-linux@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox