Skip to content

Commit 8bb7170

Browse files
Longfang Liuawilliam
authored andcommitted
hisi_acc_vfio_pci: fix XQE dma address error
The dma addresses of EQE and AEQE are wrong after migration and results in guest kernel-mode encryption services failure. Comparing the definition of hardware registers, we found that there was an error when the data read from the register was combined into an address. Therefore, the address combination sequence needs to be corrected. Even after fixing the above problem, we still have an issue where the Guest from an old kernel can get migrated to new kernel and may result in wrong data. In order to ensure that the address is correct after migration, if an old magic number is detected, the dma address needs to be updated. Fixes: b0eed08 ("hisi_acc_vfio_pci: Add support for VFIO live migration") Signed-off-by: Longfang Liu <liulongfang@huawei.com> Reviewed-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Link: https://lore.kernel.org/r/20250510081155.55840-2-liulongfang@huawei.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 07970d0 commit 8bb7170

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,32 @@ static int vf_qm_func_stop(struct hisi_qm *qm)
350350
return hisi_qm_mb(qm, QM_MB_CMD_PAUSE_QM, 0, 0, 0);
351351
}
352352

353+
static int vf_qm_version_check(struct acc_vf_data *vf_data, struct device *dev)
354+
{
355+
switch (vf_data->acc_magic) {
356+
case ACC_DEV_MAGIC_V2:
357+
if (vf_data->major_ver != ACC_DRV_MAJOR_VER) {
358+
dev_info(dev, "migration driver version<%u.%u> not match!\n",
359+
vf_data->major_ver, vf_data->minor_ver);
360+
return -EINVAL;
361+
}
362+
break;
363+
case ACC_DEV_MAGIC_V1:
364+
/* Correct dma address */
365+
vf_data->eqe_dma = vf_data->qm_eqc_dw[QM_XQC_ADDR_HIGH];
366+
vf_data->eqe_dma <<= QM_XQC_ADDR_OFFSET;
367+
vf_data->eqe_dma |= vf_data->qm_eqc_dw[QM_XQC_ADDR_LOW];
368+
vf_data->aeqe_dma = vf_data->qm_aeqc_dw[QM_XQC_ADDR_HIGH];
369+
vf_data->aeqe_dma <<= QM_XQC_ADDR_OFFSET;
370+
vf_data->aeqe_dma |= vf_data->qm_aeqc_dw[QM_XQC_ADDR_LOW];
371+
break;
372+
default:
373+
return -EINVAL;
374+
}
375+
376+
return 0;
377+
}
378+
353379
static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev,
354380
struct hisi_acc_vf_migration_file *migf)
355381
{
@@ -363,7 +389,8 @@ static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev,
363389
if (migf->total_length < QM_MATCH_SIZE || hisi_acc_vdev->match_done)
364390
return 0;
365391

366-
if (vf_data->acc_magic != ACC_DEV_MAGIC) {
392+
ret = vf_qm_version_check(vf_data, dev);
393+
if (ret) {
367394
dev_err(dev, "failed to match ACC_DEV_MAGIC\n");
368395
return -EINVAL;
369396
}
@@ -418,7 +445,9 @@ static int vf_qm_get_match_data(struct hisi_acc_vf_core_device *hisi_acc_vdev,
418445
int vf_id = hisi_acc_vdev->vf_id;
419446
int ret;
420447

421-
vf_data->acc_magic = ACC_DEV_MAGIC;
448+
vf_data->acc_magic = ACC_DEV_MAGIC_V2;
449+
vf_data->major_ver = ACC_DRV_MAJOR_VER;
450+
vf_data->minor_ver = ACC_DRV_MINOR_VER;
422451
/* Save device id */
423452
vf_data->dev_id = hisi_acc_vdev->vf_dev->device;
424453

@@ -496,12 +525,12 @@ static int vf_qm_read_data(struct hisi_qm *vf_qm, struct acc_vf_data *vf_data)
496525
return -EINVAL;
497526

498527
/* Every reg is 32 bit, the dma address is 64 bit. */
499-
vf_data->eqe_dma = vf_data->qm_eqc_dw[1];
528+
vf_data->eqe_dma = vf_data->qm_eqc_dw[QM_XQC_ADDR_HIGH];
500529
vf_data->eqe_dma <<= QM_XQC_ADDR_OFFSET;
501-
vf_data->eqe_dma |= vf_data->qm_eqc_dw[0];
502-
vf_data->aeqe_dma = vf_data->qm_aeqc_dw[1];
530+
vf_data->eqe_dma |= vf_data->qm_eqc_dw[QM_XQC_ADDR_LOW];
531+
vf_data->aeqe_dma = vf_data->qm_aeqc_dw[QM_XQC_ADDR_HIGH];
503532
vf_data->aeqe_dma <<= QM_XQC_ADDR_OFFSET;
504-
vf_data->aeqe_dma |= vf_data->qm_aeqc_dw[0];
533+
vf_data->aeqe_dma |= vf_data->qm_aeqc_dw[QM_XQC_ADDR_LOW];
505534

506535
/* Through SQC_BT/CQC_BT to get sqc and cqc address */
507536
ret = qm_get_sqc(vf_qm, &vf_data->sqc_dma);

drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#define QM_REG_ADDR_OFFSET 0x0004
4040

4141
#define QM_XQC_ADDR_OFFSET 32U
42+
#define QM_XQC_ADDR_LOW 0x1
43+
#define QM_XQC_ADDR_HIGH 0x2
44+
4245
#define QM_VF_AEQ_INT_MASK 0x0004
4346
#define QM_VF_EQ_INT_MASK 0x000c
4447
#define QM_IFC_INT_SOURCE_V 0x0020
@@ -50,18 +53,25 @@
5053
#define QM_EQC_DW0 0X8000
5154
#define QM_AEQC_DW0 0X8020
5255

56+
#define ACC_DRV_MAJOR_VER 1
57+
#define ACC_DRV_MINOR_VER 0
58+
59+
#define ACC_DEV_MAGIC_V1 0XCDCDCDCDFEEDAACC
60+
#define ACC_DEV_MAGIC_V2 0xAACCFEEDDECADEDE
61+
5362
struct acc_vf_data {
5463
#define QM_MATCH_SIZE offsetofend(struct acc_vf_data, qm_rsv_state)
5564
/* QM match information */
56-
#define ACC_DEV_MAGIC 0XCDCDCDCDFEEDAACC
5765
u64 acc_magic;
5866
u32 qp_num;
5967
u32 dev_id;
6068
u32 que_iso_cfg;
6169
u32 qp_base;
6270
u32 vf_qm_state;
6371
/* QM reserved match information */
64-
u32 qm_rsv_state[3];
72+
u16 major_ver;
73+
u16 minor_ver;
74+
u32 qm_rsv_state[2];
6575

6676
/* QM RW regs */
6777
u32 aeq_int_mask;

0 commit comments

Comments
 (0)