From: JiangShui Yang yangjiangshui@h-partners.com
Longfang Liu (1): crypto:hisilicon/qm: bugfix queue parameter issue
Zhangfei Gao (1): uacce: use filep->f_mapping to replace inode->i_mapping
drivers/crypto/hisilicon/hpre/hpre_main.c | 5 +++++ drivers/crypto/hisilicon/qm.c | 14 ++++++++++---- drivers/crypto/hisilicon/qm_common.h | 1 - drivers/crypto/hisilicon/sec2/sec_main.c | 5 +++++ drivers/crypto/hisilicon/zip/zip_main.c | 5 +++++ drivers/misc/uacce/uacce.c | 16 +++++++++------- include/linux/hisi_acc_qm.h | 8 ++++++++ include/linux/uacce.h | 4 ++-- 8 files changed, 44 insertions(+), 14 deletions(-)
From: Longfang Liu liulongfang@huawei.com
driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I79JRM CVE: NA
----------------------------------------------------------------------
After the queue isolation function is enabled in the BIOS. If the current default number of queues is used to enable PF, the default number of queues will be greater than the number of queues supported by the function set in the BIOS, which will cause the driver to fail to load. After modification. If queue isolation is enabled. When the default queue parameter is larger than the number supported by the function. The number of enabled queues will be changed to the number supported by the function. So that the driver can be loaded normally.
Signed-off-by: Longfang Liu liulongfang@huawei.com Signed-off-by: JiangShui Yang yangjiangshui@h-partners.com --- drivers/crypto/hisilicon/hpre/hpre_main.c | 5 +++++ drivers/crypto/hisilicon/qm.c | 14 ++++++++++---- drivers/crypto/hisilicon/qm_common.h | 1 - drivers/crypto/hisilicon/sec2/sec_main.c | 5 +++++ drivers/crypto/hisilicon/zip/zip_main.c | 5 +++++ include/linux/hisi_acc_qm.h | 8 ++++++++ 6 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index f6be30053e3e..4d99bfd90fa1 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -430,8 +430,11 @@ static u32 uacce_mode = UACCE_MODE_NOUACCE; module_param_cb(uacce_mode, &hpre_uacce_mode_ops, &uacce_mode, 0444); MODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC);
+static bool pf_q_num_flag; static int pf_q_num_set(const char *val, const struct kernel_param *kp) { + pf_q_num_flag = true; + return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_HPRE_PF); }
@@ -1154,6 +1157,8 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) qm->qp_num = pf_q_num; qm->debug.curr_qm_qp_num = pf_q_num; qm->qm_list = &hpre_devices; + if (pf_q_num_flag) + set_bit(QM_MODULE_PARAM, &qm->misc_ctl); }
ret = hisi_qm_init(qm); diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 97b64d82c065..28ce6ac69d4e 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -206,7 +206,6 @@ #define REMOVE_WAIT_DELAY 10
#define QM_DRIVER_REMOVING 0 -#define QM_RST_SCHED 1 #define QM_QOS_PARAM_NUM 2 #define QM_QOS_MAX_VAL 1000 #define QM_QOS_RATE 100 @@ -2962,7 +2961,6 @@ static int hisi_qm_pre_init(struct hisi_qm *qm) mutex_init(&qm->mailbox_lock); init_rwsem(&qm->qps_lock); qm->qp_in_used = 0; - qm->misc_ctl = false; qm->use_iommu = is_iommu_used(&pdev->dev); if (test_bit(QM_SUPPORT_RPM, &qm->caps)) { if (!acpi_device_power_manageable(ACPI_COMPANION(&pdev->dev))) @@ -5253,13 +5251,21 @@ static int qm_get_qp_num(struct hisi_qm *qm) qm->max_qp_num = hisi_qm_get_hw_info(qm, qm_basic_info, QM_FUNC_MAX_QP_CAP, is_db_isolation);
- /* check if qp number is valid */ - if (qm->qp_num > qm->max_qp_num) { + if (qm->qp_num <= qm->max_qp_num) + return 0; + + if (test_bit(QM_MODULE_PARAM, &qm->misc_ctl)) { + /* Check whether the set qp number is valid */ dev_err(&qm->pdev->dev, "qp num(%u) is more than max qp num(%u)!\n", qm->qp_num, qm->max_qp_num); return -EINVAL; }
+ dev_info(&qm->pdev->dev, "Default qp num(%u) is too big, reset it to Function's max qp num(%u)!\n", + qm->qp_num, qm->max_qp_num); + qm->qp_num = qm->max_qp_num; + qm->debug.curr_qm_qp_num = qm->qp_num; + return 0; }
diff --git a/drivers/crypto/hisilicon/qm_common.h b/drivers/crypto/hisilicon/qm_common.h index 1406a422d455..8e36aa9c681b 100644 --- a/drivers/crypto/hisilicon/qm_common.h +++ b/drivers/crypto/hisilicon/qm_common.h @@ -4,7 +4,6 @@ #define QM_COMMON_H
#define QM_DBG_READ_LEN 256 -#define QM_RESETTING 2
struct qm_cqe { __le32 rsvd0; diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index 40d7cacc1f56..c9140bccc9cf 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -312,8 +312,11 @@ static int sec_diff_regs_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(sec_diff_regs);
+static bool pf_q_num_flag; static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp) { + pf_q_num_flag = true; + return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF); }
@@ -1121,6 +1124,8 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) qm->qp_num = pf_q_num; qm->debug.curr_qm_qp_num = pf_q_num; qm->qm_list = &sec_devices; + if (pf_q_num_flag) + set_bit(QM_MODULE_PARAM, &qm->misc_ctl); } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { /* * have no way to get qm configure in VM in v1 hardware, diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 138e91aac88b..1b873118d636 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -365,8 +365,11 @@ static u32 uacce_mode = UACCE_MODE_NOUACCE; module_param_cb(uacce_mode, &zip_uacce_mode_ops, &uacce_mode, 0444); MODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC);
+static bool pf_q_num_flag; static int pf_q_num_set(const char *val, const struct kernel_param *kp) { + pf_q_num_flag = true; + return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_ZIP_PF); }
@@ -1140,6 +1143,8 @@ static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) qm->qp_num = pf_q_num; qm->debug.curr_qm_qp_num = pf_q_num; qm->qm_list = &zip_devices; + if (pf_q_num_flag) + set_bit(QM_MODULE_PARAM, &qm->misc_ctl); } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { /* * have no way to get qm configure in VM in v1 hardware, diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 5c8bb9d1cd27..40420a4ef0ae 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -146,6 +146,14 @@ enum vf_state { VF_PREPARE, };
+enum qm_mist_ctl_bits { + QM_DRIVER_DOWN = 0x0, + QM_RST_SCHED, + QM_RESETTING, + QM_DEVICE_DOWN, + QM_MODULE_PARAM, +}; + enum qm_cap_bits { QM_SUPPORT_DB_ISOLATION = 0x0, QM_SUPPORT_FUNC_QOS,
From: Zhangfei Gao zhangfei.gao@linaro.org
driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I79JRM CVE: NA
----------------------------------------------------------------------
The inode can be different in a container, for example, a docker and host both open the same uacce parent device, which uses the same uacce struct but different inode, so uacce->inode is not enough.
What's worse, when docker stopped, the inode will be destroyed as well, causing use-after-free in uacce_remove.
So use q->filep->f_mapping to replace uacce->inode->i_mapping.
Signed-off-by: Zhangfei Gao zhangfei.gao@linaro.org Signed-off-by: JiangShui Yang yangjiangshui@h-partners.com --- drivers/misc/uacce/uacce.c | 16 +++++++++------- include/linux/uacce.h | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c index c7106b69f198..6d2961676a54 100644 --- a/drivers/misc/uacce/uacce.c +++ b/drivers/misc/uacce/uacce.c @@ -355,8 +355,8 @@ static int uacce_fops_open(struct inode *inode, struct file *filep) atomic_inc(&uacce->ref); init_waitqueue_head(&q->wait); filep->private_data = q; - uacce->inode = inode; q->state = UACCE_Q_INIT; + q->private_data = filep; mutex_init(&q->mutex); list_add(&q->list, &uacce->queues); mutex_unlock(&uacce->mutex); @@ -1054,12 +1054,6 @@ void uacce_remove(struct uacce_device *uacce)
if (!uacce) return; - /* - * unmap remaining mapping from user space, preventing user still - * access the mmaped area while parent device is already removed - */ - if (uacce->inode) - unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1);
/* * uacce_fops_open() may be running concurrently, even after we remove @@ -1069,6 +1063,8 @@ void uacce_remove(struct uacce_device *uacce) mutex_lock(&uacce->mutex); /* ensure no open queue remains */ list_for_each_entry_safe(q, next_q, &uacce->queues, list) { + struct file *filep = q->private_data; + /* * Taking q->mutex ensures that fops do not use the defunct * uacce->ops after the queue is disabled. @@ -1077,6 +1073,12 @@ void uacce_remove(struct uacce_device *uacce) uacce_put_queue(q); mutex_unlock(&q->mutex); uacce_unbind_queue(q); + + /* + * unmap remaining mapping from user space, preventing user still + * access the mmaped area while parent device is already removed + */ + unmap_mapping_range(filep->f_mapping, 0, 0, 1); }
/* disable sva now since no opened queues */ diff --git a/include/linux/uacce.h b/include/linux/uacce.h index c4161b0632fe..8187c1bda236 100644 --- a/include/linux/uacce.h +++ b/include/linux/uacce.h @@ -115,6 +115,7 @@ enum uacce_q_state { * @state: queue state machine * @pasid: pasid associated to the mm * @handle: iommu_sva handle returned by iommu_sva_bind_device() + * @private_data: private data for saving filep */ struct uacce_queue { struct uacce_device *uacce; @@ -129,6 +130,7 @@ struct uacce_queue { enum uacce_q_state state; u32 pasid; struct iommu_sva *handle; + void *private_data; };
/** @@ -147,7 +149,6 @@ struct uacce_queue { * @priv: private pointer of the uacce * @queues: list of queues * @ref: reference of the uacce - * @inode: core vfs */ struct uacce_device { const char *algs; @@ -166,7 +167,6 @@ struct uacce_device { atomic_t ref; struct uacce_err_isolate *isolate; struct list_head queues; - struct inode *inode; };
#if IS_ENABLED(CONFIG_UACCE)