ct3d_reset() re-runs cxl_init_cci() on all three CCIs, and each run
allocates a fresh background timer without freeing the old one, so
every reset leaks three QEMUTimers.  ct3_exit() doesn't free them
either.

Upstream fixed this in 259b877eac36 ("hw/cxl: fix timer leak in
cxl_destroy_cci()") and a004df0be51f ("hw/cxl: destroy primary CCI
before re-initialization on reset"), but both rely on
cxl_destroy_cci() and the .initialized flag from 98cbac128f1c, which
only went in for 10.1.  Add a minimal cxl_destroy_cci() here and call
it before each re-init and from ct3_exit().  timer_free() takes NULL,
so the first reset needs no guard.

ASan on v10.0.15, 5x system_reset on a paused guest with one
cxl-type3: 720 bytes in 15 allocations from cxl_init_cci ->
timer_new_ms before, none after.  cxl-test passes.

Fixes: 221d2cfbdb53 ("hw/cxl/mbox: Add support for background operations")
Cc: [email protected]
Signed-off-by: Junjie Cao <[email protected]>
---
 hw/cxl/cxl-mailbox-utils.c  | 6 ++++++
 hw/mem/cxl_type3.c          | 6 ++++++
 include/hw/cxl/cxl_device.h | 1 +
 3 files changed, 13 insertions(+)

diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 516c01d840..6cbc649367 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -2986,6 +2986,12 @@ void cxl_init_cci(CXLCCI *cci, size_t payload_max)
     cci->fw.slot[cci->fw.active_slot - 1] = true;
 }
 
+void cxl_destroy_cci(CXLCCI *cci)
+{
+    timer_free(cci->bg.timer);
+    cci->bg.timer = NULL;
+}
+
 static void cxl_copy_cci_commands(CXLCCI *cci, const struct cxl_cmd 
(*cxl_cmds)[256])
 {
     for (int set = 0; set < 256; set++) {
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 1606aa3279..df9c70973e 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -973,6 +973,9 @@ static void ct3_exit(PCIDevice *pci_dev)
     cxl_doe_cdat_release(cxl_cstate);
     msix_uninit_exclusive_bar(pci_dev);
     g_free(regs->special_ops);
+    cxl_destroy_cci(&ct3d->cci);
+    cxl_destroy_cci(&ct3d->vdm_fm_owned_ld_mctp_cci);
+    cxl_destroy_cci(&ct3d->ld0_cci);
     if (ct3d->dc.host_dc) {
         cxl_destroy_dc_regions(ct3d);
         address_space_destroy(&ct3d->dc.host_dc_as);
@@ -1222,15 +1225,18 @@ static void ct3d_reset(DeviceState *dev)
 
     pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed);
     cxl_component_register_init_common(reg_state, write_msk, 
CXL2_TYPE3_DEVICE);
+    cxl_destroy_cci(&ct3d->cci);
     cxl_device_register_init_t3(ct3d, CXL_T3_MSIX_MBOX);
 
     /*
      * Bring up an endpoint to target with MCTP over VDM.
      * This device is emulating an MLD with single LD for now.
      */
+    cxl_destroy_cci(&ct3d->vdm_fm_owned_ld_mctp_cci);
     cxl_initialize_t3_fm_owned_ld_mctpcci(&ct3d->vdm_fm_owned_ld_mctp_cci,
                                           DEVICE(ct3d), DEVICE(ct3d),
                                           512); /* Max payload made up */
+    cxl_destroy_cci(&ct3d->ld0_cci);
     cxl_initialize_t3_ld_cci(&ct3d->ld0_cci, DEVICE(ct3d), DEVICE(ct3d),
                              512); /* Max payload made up */
 
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 3a0ee7e8e7..d9238c903e 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -316,6 +316,7 @@ void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, 
size_t payload_max);
 void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
                                   DeviceState *d, size_t payload_max);
 void cxl_init_cci(CXLCCI *cci, size_t payload_max);
+void cxl_destroy_cci(CXLCCI *cci);
 void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd 
(*cxl_cmd_set)[256],
                           size_t payload_max);
 int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd,

base-commit: c2cfbc6c121b4875ac509da605968ff4289b6aef
-- 
2.43.0


Reply via email to