Public > -----Original Message----- > From: Irshad, Luqmaan <[email protected]> > Sent: Thursday, October 8, 2026 3:28 PM > To: [email protected] > Cc: Deucher, Alexander <[email protected]>; Koenig, Christian > <[email protected]>; Li, Yunxiang (Teddy) <[email protected]>; > Irshad, Luqmaan <[email protected]> > Subject: [PATCH v2] drm/amdgpu: defer XCP DRM device free until primary > release > > XCP unplug currently restores the partition minors' device pointers to the > synthetic p_ddev and frees that device while files opened through those > minors may still be active. Those files acquired drm_device references on the > primary ddev because the minors were redirected at XCP allocation time. After > unplug reverses the redirection, close paths operate on the already-freed > p_ddev, causing a use-after-free and p_ddev refcount underflow while leaking > the matching primary-device references. > > Split teardown into two phases. amdgpu_xcp_dev_unplug() only calls > drm_dev_unplug() so new opens fail, leaving minor->dev pointing at the > primary device. amdgpu_xcp_dev_fini() restores the partition device pointers > and frees p_ddev from amdgpu_driver_release_kms(), when the primary > drm_device reaches final release and all references held by redirected files > have > been dropped. > > Signed-off-by: Luqmaan Irshad <[email protected]>
Reviewed-by: Alex Deucher <[email protected]> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 + > drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 40 > ++++++++++++++++++++----- > drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h | 1 + > 3 files changed, 35 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c > index f2f179421c4d..f4bc9e6eb97b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c > @@ -1638,6 +1638,7 @@ void amdgpu_driver_release_kms(struct > drm_device *dev) { > struct amdgpu_device *adev = drm_to_adev(dev); > > + amdgpu_xcp_dev_fini(adev); > amdgpu_device_fini_sw(adev); > pci_set_drvdata(adev->pdev, NULL); > } > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c > index a8c79a66df1d..c780d6794b89 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c > @@ -412,7 +412,6 @@ int amdgpu_xcp_dev_register(struct amdgpu_device > *adev, > > void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev) { > - struct drm_device *p_ddev; > int i; > > if (!adev->xcp_mgr) > @@ -422,12 +421,39 @@ void amdgpu_xcp_dev_unplug(struct > amdgpu_device *adev) > if (!adev->xcp_mgr->xcp[i].ddev) > break; > > - p_ddev = adev->xcp_mgr->xcp[i].ddev; > - drm_dev_unplug(p_ddev); > - p_ddev->render->dev = adev->xcp_mgr->xcp[i].rdev; > - p_ddev->primary->dev = adev->xcp_mgr->xcp[i].pdev; > - p_ddev->driver = adev->xcp_mgr->xcp[i].driver; > - p_ddev->vma_offset_manager = adev->xcp_mgr- > >xcp[i].vma_offset_manager; > + drm_dev_unplug(adev->xcp_mgr->xcp[i].ddev); > + } > +} > + > +void amdgpu_xcp_dev_fini(struct amdgpu_device *adev) { > + struct amdgpu_xcp *xcp; > + struct drm_device *p_ddev; > + int i; > + > + if (!adev->xcp_mgr) > + return; > + > + for (i = 1; i < MAX_XCP; i++) { > + xcp = &adev->xcp_mgr->xcp[i]; > + if (!xcp->ddev) > + break; > + > + p_ddev = xcp->ddev; > + > + /* Unregister devices on paths that did not unplug them > earlier. */ > + if (p_ddev->registered) > + drm_dev_unplug(p_ddev); > + > + /* > + * All XCP minor files have been released, so it is now safe to > + * restore the partition device and free it. > + */ > + p_ddev->render->dev = xcp->rdev; > + p_ddev->primary->dev = xcp->pdev; > + p_ddev->driver = xcp->driver; > + p_ddev->vma_offset_manager = xcp->vma_offset_manager; > + xcp->ddev = NULL; > amdgpu_xcp_drm_dev_free(p_ddev); > } > } > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h > index 33157409eda0..e2fd32af9932 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h > @@ -181,6 +181,7 @@ int amdgpu_xcp_get_inst_details(struct amdgpu_xcp > *xcp, int amdgpu_xcp_dev_register(struct amdgpu_device *adev, > const struct pci_device_id *ent); > void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev); > +void amdgpu_xcp_dev_fini(struct amdgpu_device *adev); > int amdgpu_xcp_open_device(struct amdgpu_device *adev, > struct amdgpu_fpriv *fpriv, > struct drm_file *file_priv); > -- > 2.53.0
