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