[RFC PATCH v1 22/38] coco: host: arm64: Stop and destroy virtual device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add support for vdev_stop and vdev_destroy.

Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@xxxxxxxxxx>
---
 arch/arm64/include/asm/rmi_cmds.h        | 21 ++++++++
 arch/arm64/include/asm/rmi_smc.h         |  3 +-
 drivers/virt/coco/arm-cca-host/arm-cca.c | 10 ++++
 drivers/virt/coco/arm-cca-host/rmm-da.c  | 61 +++++++++++++++++++++++-
 drivers/virt/coco/arm-cca-host/rmm-da.h  |  2 +
 5 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
index 25197f47a0a9..eb4f67eb6b01 100644
--- a/arch/arm64/include/asm/rmi_cmds.h
+++ b/arch/arm64/include/asm/rmi_cmds.h
@@ -609,4 +609,25 @@ static inline unsigned long rmi_vdev_get_state(unsigned long vdev_phys, unsigned
 	return res.a0;
 }
 
+static inline unsigned long rmi_vdev_stop(unsigned long vdev_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_VDEV_STOP, vdev_phys, &res);
+
+	return res.a0;
+}
+
+static inline unsigned long rmi_vdev_destroy(unsigned long rd,
+					     unsigned long pdev_phys,
+					     unsigned long vdev_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_VDEV_DESTROY, rd, pdev_phys, vdev_phys, &res);
+
+	return res.a0;
+}
+
+
 #endif /* __ASM_RMI_CMDS_H */
diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_smc.h
index 127dd0938604..c6e16ab608e1 100644
--- a/arch/arm64/include/asm/rmi_smc.h
+++ b/arch/arm64/include/asm/rmi_smc.h
@@ -55,8 +55,9 @@
 #define SMC_RMI_PDEV_STOP		SMC_RMI_CALL(0x017c)
 #define SMC_RMI_VDEV_COMMUNICATE	SMC_RMI_CALL(0x0186)
 #define SMC_RMI_VDEV_CREATE		SMC_RMI_CALL(0x0187)
+#define SMC_RMI_VDEV_DESTROY		SMC_RMI_CALL(0x0188)
 #define SMC_RMI_VDEV_GET_STATE		SMC_RMI_CALL(0x0189)
-
+#define SMC_RMI_VDEV_STOP		SMC_RMI_CALL(0x018A)
 
 #define RMI_ABI_MAJOR_VERSION	1
 #define RMI_ABI_MINOR_VERSION	0
diff --git a/drivers/virt/coco/arm-cca-host/arm-cca.c b/drivers/virt/coco/arm-cca-host/arm-cca.c
index 2da513f45974..3792d7b5cb99 100644
--- a/drivers/virt/coco/arm-cca-host/arm-cca.c
+++ b/drivers/virt/coco/arm-cca-host/arm-cca.c
@@ -250,12 +250,22 @@ static struct pci_tdi *cca_tsm_bind(struct pci_dev *pdev, struct pci_dev *pf0_de
 	return rmm_vdev;
 }
 
+static void cca_tsm_unbind(struct pci_tdi *tdi)
+{
+	struct realm *realm = &tdi->kvm->arch.realm;
+
+	rme_unbind_vdev(realm, tdi->pdev, tdi->pdev->tsm->dsm_dev);
+
+	module_put(THIS_MODULE);
+}
+
 static const struct pci_tsm_ops cca_pci_ops = {
 	.probe = cca_tsm_pci_probe,
 	.remove = cca_tsm_pci_remove,
 	.connect = cca_tsm_connect,
 	.disconnect = cca_tsm_disconnect,
 	.bind	= cca_tsm_bind,
+	.unbind = cca_tsm_unbind,
 };
 
 static void cca_tsm_remove(void *tsm_core)
diff --git a/drivers/virt/coco/arm-cca-host/rmm-da.c b/drivers/virt/coco/arm-cca-host/rmm-da.c
index 8635f361bbe8..53072610fa67 100644
--- a/drivers/virt/coco/arm-cca-host/rmm-da.c
+++ b/drivers/virt/coco/arm-cca-host/rmm-da.c
@@ -597,7 +597,66 @@ void *rme_create_vdev(struct realm *realm, struct pci_dev *pdev,
 	return ERR_PTR(ret);
 }
 
-static int __maybe_unused do_vdev_communicate(struct pci_tsm *tsm, int target_state)
+static int do_vdev_communicate(struct pci_tsm *tsm, int target_state)
 {
 	return do_dev_communicate(VDEV_COMMUNICATE, tsm, target_state);
 }
+
+static void vdev_stop_work(struct work_struct *work)
+{
+	struct dev_comm_work *stop_work;
+	struct pci_tsm *tsm;
+	unsigned long state;
+
+	stop_work = container_of(work, struct dev_comm_work, work);
+	tsm = stop_work->tsm;
+
+	state = do_vdev_communicate(tsm, RMI_VDEV_STOPPED);
+	WARN_ON(state != RMI_VDEV_STOPPED);
+
+	complete(&stop_work->complete);
+}
+
+static int schedule_vdev_unbind(struct pci_dev *pdev)
+{
+	struct dev_comm_work unbind_work = {
+		.tsm = pdev->tsm,
+	};
+
+	INIT_WORK_ONSTACK(&unbind_work.work, vdev_stop_work);
+	init_completion(&unbind_work.complete);
+	schedule_work(&unbind_work.work);
+	wait_for_completion(&unbind_work.complete);
+	destroy_work_on_stack(&unbind_work.work);
+
+	return 0;
+}
+
+void rme_unbind_vdev(struct realm *realm, struct pci_dev *pdev, struct pci_dev *pf0_dev)
+{
+	int ret;
+	phys_addr_t rmm_pdev_phys;
+	phys_addr_t rmm_vdev_phys;
+	struct cca_host_dsc_pf0 *dsc_pf0;
+	struct cca_host_tdi *host_tdi;
+	phys_addr_t rd_phys = virt_to_phys(realm->rd);
+
+	host_tdi = container_of(pdev->tsm->tdi, struct cca_host_tdi, tdi);
+	rmm_vdev_phys = virt_to_phys(host_tdi->rmm_vdev);
+
+	dsc_pf0 = to_cca_dsc_pf0(pf0_dev);
+	rmm_pdev_phys = virt_to_phys(dsc_pf0->rmm_pdev);
+	/* Request stopping the VDEV */
+	ret = rmi_vdev_stop(rmm_vdev_phys);
+	if (ret) {
+		pr_err("failed to stop vdev (%d)\n", ret);
+		return;
+	}
+
+	schedule_vdev_unbind(pdev);
+	ret = rmi_vdev_destroy(rd_phys, rmm_pdev_phys, rmm_vdev_phys);
+	if (ret) {
+		pr_err("failed to destroy vdev (%d)\n", ret);
+		return;
+	}
+}
diff --git a/drivers/virt/coco/arm-cca-host/rmm-da.h b/drivers/virt/coco/arm-cca-host/rmm-da.h
index 37a8f4dce68e..6361f7403f95 100644
--- a/drivers/virt/coco/arm-cca-host/rmm-da.h
+++ b/drivers/virt/coco/arm-cca-host/rmm-da.h
@@ -93,4 +93,6 @@ void rme_unassign_device(struct pci_dev *pdev);
 int schedule_rme_ide_setup(struct pci_dev *pdev);
 void *rme_create_vdev(struct realm *realm, struct pci_dev *pdev,
 		      struct pci_dev *pf0_dev, u32 guest_rid);
+void rme_unbind_vdev(struct realm *realm, struct pci_dev *pdev,
+		     struct pci_dev *pf0_dev);
 #endif
-- 
2.43.0





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux