Commit 40a7f76b authored by Longfang Liu's avatar Longfang Liu Committed by JangShui Yang
Browse files

vfio/migration: bugfix cache write-back issue

virt inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9DRAC


CVE: NA

----------------------------------------------------------------------

In the new vfio framework, cache write-back is placed in the
device data copy stage after stopping the device operation.
Writing back to the cache at this stage will cause the data
obtained by the cache to be written back to be empty.

In order to ensure that the cache data is written back
successfully, the data needs to be written back into the
stop device stage.

Signed-off-by: default avatarLongfang Liu <liulongfang@huawei.com>
Signed-off-by: default avatarJiangShui Yang <yangjiangshui@h-partners.com>
parent 392cea5e
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -444,7 +444,7 @@ static int vf_qm_get_match_data(struct hisi_acc_vf_core_device *hisi_acc_vdev,
	return 0;
}

static void vf_qm_xqc_restore(struct hisi_qm *qm,
static void vf_qm_xeqc_save(struct hisi_qm *qm,
	struct hisi_acc_vf_migration_file *migf)
{
	struct acc_vf_data *vf_data = &migf->vf_data;
@@ -521,23 +521,17 @@ static int vf_qm_state_save(struct hisi_acc_vf_core_device *hisi_acc_vdev,
	vf_data->vf_qm_state = QM_READY;
	hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state;

	ret = vf_qm_cache_wb(vf_qm);
	if (ret) {
		dev_err(dev, "failed to writeback QM Cache!\n");
		return ret;
	}

	ret = qm_get_regs(vf_qm, vf_data);
	if (ret)
		return -EINVAL;

	/* Every reg is 32 bit, the dma address is 64 bit. */
	vf_data->eqe_dma = vf_data->qm_eqc_dw[1];
	vf_data->eqe_dma = vf_data->qm_eqc_dw[QM_XQC_ADDR_HIGH];
	vf_data->eqe_dma <<= QM_XQC_ADDR_OFFSET;
	vf_data->eqe_dma |= vf_data->qm_eqc_dw[0];
	vf_data->aeqe_dma = vf_data->qm_aeqc_dw[1];
	vf_data->eqe_dma |= vf_data->qm_eqc_dw[QM_XQC_ADDR_LOW];
	vf_data->aeqe_dma = vf_data->qm_aeqc_dw[QM_XQC_ADDR_HIGH];
	vf_data->aeqe_dma <<= QM_XQC_ADDR_OFFSET;
	vf_data->aeqe_dma |= vf_data->qm_aeqc_dw[0];
	vf_data->aeqe_dma |= vf_data->qm_aeqc_dw[QM_XQC_ADDR_LOW];

	/* Through SQC_BT/CQC_BT to get sqc and cqc address */
	ret = qm_get_sqc(vf_qm, &vf_data->sqc_dma);
@@ -554,6 +548,9 @@ static int vf_qm_state_save(struct hisi_acc_vf_core_device *hisi_acc_vdev,

	migf->total_length = sizeof(struct acc_vf_data);

	/* Save eqc and aeqc interrupt information */
	vf_qm_xeqc_save(vf_qm, migf);

	return 0;
}

@@ -696,9 +693,6 @@ static int hisi_acc_vf_load_state(struct hisi_acc_vf_core_device *hisi_acc_vdev)
		return ret;
	}

	/* Restore eqc and aeqc interrupt information */
	vf_qm_xqc_restore(vf_qm, migf);

	return 0;
}

@@ -969,6 +963,13 @@ static int hisi_acc_vf_stop_device(struct hisi_acc_vf_core_device *hisi_acc_vdev
		dev_err(dev, "failed to check QM INT state!\n");
		return ret;
	}

	ret = vf_qm_cache_wb(vf_qm);
	if (ret) {
		dev_err(dev, "failed to writeback QM cache!\n");
		return ret;
	}

	return 0;
}

+3 −0
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@
#define QM_REG_ADDR_OFFSET	0x0004

#define QM_XQC_ADDR_OFFSET	32U
#define QM_XQC_ADDR_LOW	0x1
#define QM_XQC_ADDR_HIGH	0x2

#define QM_VF_AEQ_INT_MASK	0x0004
#define QM_VF_EQ_INT_MASK	0x000c
#define QM_IFC_INT_SOURCE_V	0x0020