The CXL Type-3 device reset path (ct3d_reset) has several issues:
1) Resource leaks:
- cxl_destroy_cci() never frees the QEMUTimer allocated by
cxl_init_cci(), leaking a timer on each destroy/reinit cycle.
- The primary CCI (ct3d->cci) is re-initialized through
cxl_device_register_init_t3() without being destroyed first,
leaking the timer and leaving the mutex undestroyed on every
reset.
- The secondary CCIs are never destroyed at device exit time,
leaking their timers and mutexes on device removal.
2) Incomplete state cleanup:
- Background commands do not survive Conventional Resets (CXL r4.0
Section 8.2.9.4), yet the in-flight sanitize state is never freed.
- Scan media results are explicitly invalidated after reset (Section
8.2.10.9.4.6), yet scan_media_hasrun is never cleared.
- Event interrupt settings shall be reset to 00b on Conventional
Reset (Section 8.2.10.2.5), yet irq_enabled is never cleared.
- When "Injects Persistent Poison" is 0 (the QEMU default), injected
poison shall be automatically cleared on reset (Table 8-309), yet
the poison lists are never drained.
- Stale event records remain in the queues across reset even though
the Event Status register (Table 8-203) is non-sticky.
3) Deprecated API usage:
- Uses device_class_set_legacy_reset() instead of the three-phase
resettable interface, preventing reset-type-aware behavior.
This series fixes the issues incrementally:
- Patches 1-2: fix resource leaks (deterministic bugs)
- Patch 3: mechanical conversion to three-phase reset
- Patches 4-6: clean up device state on reset
The state cleanup in patches 4-6 is gated on reset type:
RESET_TYPE_WAKEUP returns early (patch 5) since a resume from S3 is
not a Conventional or CXL Reset. The CCI re-initialization and the
in-flight sanitize free run unconditionally regardless of type.
Not addressed here:
- Committed Feature attributes and alert thresholds (Table 8-276
Deepest Reset Persistence = None) are not reverted to defaults.
Factoring the realize-time defaults into a reset helper is left
for a follow-up.
- Dynamic Capacity extent lifecycle across reset.
- The Media Disabled latch after an interrupted Sanitize (Section
8.2.10.9.5.1); patch 4 addresses only the resource leak.
Tested: per-commit build clean; qtest passes. Differential
LeakSanitizer (5x system_reset): pre-series leaks 720 B / 15 allocs
in cxl_init_cci -> timer_new_ms; post-series zero. Poison inject ->
reset -> re-inject same DPAs succeeds (no stale "Overlap" rejection).
20x inject+reset stress cycles with no crash.
Changes since v1:
- Patch 1: reorder cxl_destroy_cci() teardown to reverse
cxl_init_cci() order, per Jonathan's review.
v1: https://lore.kernel.org/qemu-devel/20260626062149.1844334-1-junjie.cao@intel.com/
Junjie Cao (6):
hw/cxl: fix timer leak in cxl_destroy_cci()
hw/cxl: destroy primary CCI before re-initialization on reset
hw/cxl: convert cxl-type3 to three-phase reset
hw/cxl: free in-flight sanitize state on reset
hw/cxl: clear event logs, scan media and interrupt policy on reset
hw/cxl: clear poison lists and feature transfer state on reset
hw/cxl/cxl-mailbox-utils.c | 2 +
hw/mem/cxl_type3.c | 74 ++++++++++++++++++++++++++++++++++---
include/hw/cxl/cxl_device.h | 2 +
3 files changed, 73 insertions(+), 5 deletions(-)
base-commit: cbd42e2b75b23953a9bdb073c8531518b1bd6163
--
2.43.0