[PATCH 07/12] coco: host: arm64: Add helper to stop and tear down an RMM pdev

Aneesh Kumar K.V (Arm)
2025-10-27T09:50:40Z

- describe the RMI_PDEV_STOP/RMI_PDEV_DESTROY SMC IDs and provide
wrappers in rmi_cmds.h
- implement pdev_stop_and_destroy() so the host driver stops the pdev,
waits for it to reach RMI_PDEV_STOPPED, destroys it, frees auxiliary
granules, and drops the delegated page

Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
arch/arm64/include/asm/rmi_cmds.h | 18 +++++++++++++++
arch/arm64/include/asm/rmi_smc.h | 2 ++
drivers/virt/coco/arm-cca-host/rmi-da.c | 30 +++++++++++++++++++++++++
drivers/virt/coco/arm-cca-host/rmi-da.h | 1 +
4 files changed, 51 insertions(+)

diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
index b86bf15afcda..f10a0dcaa308 100644
--- a/arch/arm64/include/asm/rmi_cmds.h
+++ b/arch/arm64/include/asm/rmi_cmds.h
@@ -556,4 +556,22 @@ static inline unsigned long rmi_pdev_abort(unsigned long pdev_phys)
return res.a0;
}

+static inline unsigned long rmi_pdev_stop(unsigned long pdev_phys)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_invoke(SMC_RMI_PDEV_STOP, pdev_phys, &res);
+
+ return res.a0;
+}
+
+static inline unsigned long rmi_pdev_destroy(unsigned long pdev_phys)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_invoke(SMC_RMI_PDEV_DESTROY, pdev_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 53e46e24c921..6eb6f7e4b77f 100644
--- a/arch/arm64/include/asm/rmi_smc.h
+++ b/arch/arm64/include/asm/rmi_smc.h
@@ -50,7 +50,9 @@
#define SMC_RMI_PDEV_ABORT SMC_RMI_CALL(0x0174)
#define SMC_RMI_PDEV_COMMUNICATE SMC_RMI_CALL(0x0175)
#define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176)
+#define SMC_RMI_PDEV_DESTROY SMC_RMI_CALL(0x0177)
#define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178)
+#define SMC_RMI_PDEV_STOP SMC_RMI_CALL(0x017c)

#define RMI_ABI_MAJOR_VERSION 1
#define RMI_ABI_MINOR_VERSION 0
diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/arm-cca-host/rmi-da.c
index 592abe0dd252..644609618a7a 100644
--- a/drivers/virt/coco/arm-cca-host/rmi-da.c
+++ b/drivers/virt/coco/arm-cca-host/rmi-da.c
@@ -412,3 +412,33 @@ int pdev_ide_setup(struct pci_dev *pdev)
{
return submit_pdev_comm_work(pdev, RMI_PDEV_NEEDS_KEY);
}
+
+void pdev_stop_and_destroy(struct pci_dev *pdev)
+{
+ unsigned long ret;
+ struct cca_host_pf0_dsc *pf0_dsc = to_cca_pf0_dsc(pdev);
+ phys_addr_t rmm_pdev_phys = virt_to_phys(pf0_dsc->rmm_pdev);
+
+ ret = rmi_pdev_stop(rmm_pdev_phys);
+ if (WARN_ON(ret != RMI_SUCCESS))
+ return;
+
+ submit_pdev_comm_work(pdev, RMI_PDEV_STOPPED);
+
+ ret = rmi_pdev_destroy(rmm_pdev_phys);
+ if (WARN_ON(ret != RMI_SUCCESS))
+ return;
+
+ kfree(pf0_dsc->cert_chain.public_key);
+ kvfree(pf0_dsc->cert_chain.cache);
+ kvfree(pf0_dsc->vca);
+ pf0_dsc->cert_chain.cache = NULL;
+ pf0_dsc->vca = NULL;
+
+ /* Free the aux granules */
+ free_aux_pages(pf0_dsc->num_aux, pf0_dsc->aux);
+ pf0_dsc->num_aux = 0;
+ if (!rmi_granule_undelegate(rmm_pdev_phys))
+ free_page((unsigned long)pf0_dsc->rmm_pdev);
+ pf0_dsc->rmm_pdev = NULL;
+}
diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/arm-cca-host/rmi-da.h
index 1d513e0b74d9..e556ccecc1cb 100644
--- a/drivers/virt/coco/arm-cca-host/rmi-da.h
+++ b/drivers/virt/coco/arm-cca-host/rmi-da.h
@@ -104,6 +104,7 @@ static inline struct cca_host_comm_data *to_cca_comm_data(struct pci_dev *pdev)
}

int pdev_create(struct pci_dev *pdev);
+void pdev_stop_and_destroy(struct pci_dev *pdev);
void pdev_communicate_work(struct work_struct *work);
int pdev_ide_setup(struct pci_dev *pdev);
#endif
--
2.43.0