All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Huth <thuth@redhat.com>
To: qemu-devel@nongnu.org, Stefan Hajnoczi <stefanha@redhat.com>
Cc: "Xiangfeng Cai" <caixiangfeng@bytedance.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [PULL 2/7] hw/usb/hcd-xhci-pci: break host link cycle so device_finalize() runs on unplug
Date: Mon, 20 Jul 2026 12:38:28 +0200	[thread overview]
Message-ID: <20260720103833.364506-3-thuth@redhat.com> (raw)
In-Reply-To: <20260720103833.364506-1-thuth@redhat.com>

From: Xiangfeng Cai <caixiangfeng@bytedance.com>

The xHCI PCI wrapper embeds an xhci-core child via object_initialize_child()
and, in usb_xhci_pci_realize(), points the child's "host" link back at the PCI
device:

    object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);

"host" is a DEFINE_PROP_LINK property, which qdev registers as an
OBJ_PROP_LINK_STRONG link. A strong link takes a reference on its target, so
this creates a refcount cycle: the PCI device owns the child, and the child's
strong link pins the PCI device.

On unplug (guest ACPI eject or QMP device_del), pci_qdev_unrealize() calls
pc->exit() but never unrealizes the no-bus child. object_unparent() then drops
only the parent/bus references, leaving the link reference in place. The PCI
device stays at refcount 1 forever, so object_finalize()/device_finalize() is
never reached. Symptom observed under gdb after eject:

    p *((Object *)dev)  =>  ref = 1, parent = 0x0, realized = false
    p ((XHCIPciState *)dev)->xhci.hostOpaque  =>  points back at dev

Fix usb_xhci_pci_exit() to tear down the embedded child explicitly: unrealize
it first (so the set-link-before-realize check passes), then clear the "host"
link. This releases the strong reference, lets the PCI device refcount reach 0,
and allows device_finalize() to run.

Fixes: 8ddab8dd3d81 ("usb/hcd-xhci: Split pci wrapper for xhci base model")
Signed-off-by: Xiangfeng Cai <caixiangfeng@bytedance.com>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260618110119.3084296-2-caixiangfeng@bytedance.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/usb/hcd-xhci-pci.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
index c5446a4a5e1..b124251ae33 100644
--- a/hw/usb/hcd-xhci-pci.c
+++ b/hw/usb/hcd-xhci-pci.c
@@ -196,6 +196,18 @@ static void usb_xhci_pci_exit(PCIDevice *dev)
         && dev->msix_entry_used) {
         msix_uninit(dev, &s->xhci.mem, &s->xhci.mem);
     }
+    /*
+     * The embedded xhci-core child holds a strong "host" link back to this
+     * PCI device (set in usb_xhci_pci_realize()), forming a refcount cycle:
+     * the PCI device owns the child, and the child's strong link pins the PCI
+     * device. On unplug, object_unparent() only drops the parent/bus refs, so
+     * the link ref keeps this device at refcount 1 forever and
+     * device_finalize() never runs. Unrealize the child first (so the
+     * realized-check in set_link passes), then clear the link to break the
+     * cycle.
+     */
+    qdev_unrealize(DEVICE(&s->xhci));
+    object_property_set_link(OBJECT(&s->xhci), "host", NULL, &error_abort);
 }
 
 static const VMStateDescription vmstate_xhci_pci = {
-- 
2.55.0



  parent reply	other threads:[~2026-07-20 10:39 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 10:38 [PULL 0/7] USB-related bug fixes Thomas Huth
2026-07-20 10:38 ` [PULL 1/7] hw/usb/xhci: clamp interval exponent to avoid UB shift in xhci_init_epctx() Thomas Huth
2026-07-20 10:38 ` Thomas Huth [this message]
2026-07-20 10:38 ` [PULL 3/7] tests/qtest: add xhci-pci unplug finalize regression test Thomas Huth
2026-07-20 10:38 ` [PULL 4/7] usbredir: fix use-after-free on buffered bulk packet overflow Thomas Huth
2026-07-20 10:38 ` [PULL 5/7] usbredir: fix infinite loop and SIGFPE with zero max_packet_size Thomas Huth
2026-07-20 10:38 ` [PULL 6/7] hw/usb/hcd-xhci: Fix guest-triggerable assert() in xhci_find_stream() Thomas Huth
2026-07-20 10:38 ` [PULL 7/7] hw/usb/hcd-xhci-sysbus: Fix OOB heap access in xhci_sysbus_intr_raise() Thomas Huth
2026-07-20 17:11 ` [PULL 0/7] USB-related bug fixes Stefan Hajnoczi
2026-07-20 19:08 ` Michael Tokarev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260720103833.364506-3-thuth@redhat.com \
    --to=thuth@redhat.com \
    --cc=caixiangfeng@bytedance.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.