
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICX1ZY CVE: NA ---------------------------------------------------------------------- In the previous code, the assignment of the vf_qm_state status was moved from "vf_qm_check_match" in the pre_copy phase to "vf_qm_load_data". This causes the reset operation when starting the VM at the destination end to default the vf_qm_state of the device to QM_NOT_READY. This status is not modified during resume at the destination end, nor corrected during pre_copy, and remains QM_NOT_READY at the final stop_copy stage. This leads to the recovery operation "hisi_acc_vf_load_state" skipping the data write operation, resulting in the data address of the destination end device after migration being a random value. This random address causes the device to access an abnormal address when restoring qp, thereby triggering a ras error Fixes: ee3a5b2359e0 ("hisi_acc_vfio_pci: add new vfio_pci driver for HiSilicon ACC devices") Signed-off-by: Longfang Liu <liulongfang@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- .../vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c index 24655ebf2b76..1f548d963360 100644 --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c @@ -389,7 +389,7 @@ static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev, struct hisi_qm *pf_qm = hisi_acc_vdev->pf_qm; struct device *dev = &vf_qm->pdev->dev; u32 que_iso_state; - int ret; + int qp_num, ret; if (migf->total_length < QM_MATCH_SIZE || hisi_acc_vdev->match_done) return 0; @@ -406,18 +406,18 @@ static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev, } /* VF qp num check */ - ret = qm_get_vft(vf_qm, &vf_qm->qp_base); - if (ret <= 0) { + qp_num = qm_get_vft(vf_qm, &vf_qm->qp_base); + if (qp_num <= 0) { dev_err(dev, "failed to get vft qp nums\n"); - return ret; + return -EINVAL; } - if (ret != vf_data->qp_num) { + if (qp_num != vf_data->qp_num) { dev_err(dev, "failed to match VF qp num\n"); return -EINVAL; } - vf_qm->qp_num = ret; + vf_qm->qp_num = qp_num; /* VF isolation state check */ ret = qm_read_regs(pf_qm, QM_QUE_ISO_CFG_V, &que_iso_state, 1); @@ -431,6 +431,13 @@ static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev, return -EINVAL; } + ret = qm_write_regs(vf_qm, QM_VF_STATE, &vf_data->vf_qm_state, 1); + if (ret) { + dev_err(dev, "failed to write QM_VF_STATE\n"); + return ret; + } + + hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state; hisi_acc_vdev->match_done = true; return 0; } @@ -511,13 +518,6 @@ static int vf_qm_load_data(struct hisi_acc_vf_core_device *hisi_acc_vdev, return 0; } - ret = qm_write_regs(qm, QM_VF_STATE, &vf_data->vf_qm_state, 1); - if (ret) { - dev_err(dev, "failed to write QM_VF_STATE\n"); - return ret; - } - hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state; - qm->eqe_dma = vf_data->eqe_dma; qm->aeqe_dma = vf_data->aeqe_dma; qm->sqc_dma = vf_data->sqc_dma; -- 2.43.0