Skip to content

cpu.h: join MCIPS vCPU thread at teardown to fix use-after-free#94

Open
Alwalid Salama (alwalidsalama) wants to merge 6 commits into
qualcomm:mainfrom
alwalidsalama:reset_test
Open

cpu.h: join MCIPS vCPU thread at teardown to fix use-after-free#94
Alwalid Salama (alwalidsalama) wants to merge 6 commits into
qualcomm:mainfrom
alwalidsalama:reset_test

Conversation

@alwalidsalama

Copy link
Copy Markdown
Contributor

The MCIPS vCPU is a free-running MTTCG thread not gated to SystemC, and
McipsSync had no on_destroy() hook. end_of_simulation() only requests
halt+unplug asynchronously, so after sc_stop() the thread could still run
in tcg_cpu_exec() and access the QemuInstance after it was freed, causing
intermittent SIGSEGV/hangs in the mcips reset tests under CPU contention.

Add McipsSync::on_destroy() to join the vCPU thread (cpu_remove_sync under
the BQL) before the QemuInstance is destroyed. Safe here because the sim
has stopped and runonsysc jobs are cancelled.

@alwalidsalama
Alwalid Salama (alwalidsalama) force-pushed the reset_test branch 2 times, most recently from 83da827 to ba0f9a8 Compare July 16, 2026 13:26
  The MCIPS vCPU is a free-running MTTCG thread not gated to SystemC, and
  McipsSync had no on_destroy() hook. end_of_simulation() only requests
  halt+unplug asynchronously, so after sc_stop() the thread could still run
  in tcg_cpu_exec() and access the QemuInstance after it was freed, causing
  intermittent SIGSEGV/hangs in the mcips reset tests under CPU contention.

  Add McipsSync::on_destroy() to join the vCPU thread (cpu_remove_sync under
  the BQL) before the QemuInstance is destroyed. Safe here because the sim
  has stopped and runonsysc jobs are cancelled.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
  reset_cb() queues async_safe_run(reset(true)) then spins:
  m_cpu.kick(); wait(m_start_reset_done_ev). qemu_cpu_kick() broadcasts the
  vCPU's halt_cond without the BQL, so a bare kick can be lost against a vCPU
  entering qemu_cond_wait(), a vCPU already sleeping there (e.g. in WFI) never
  runs the queued job, so m_start_reset_done_ev never fires and reset_cb hangs
  (seen as intermittent 100s ctest timeouts on mcips+MULTI tests).
  Take the BQL around the kick so the vCPU is either already waiting
  (gets the broadcast) or sees the queued work when it re-acquires the BQL;
  release it before waiting so the vCPU can run the job.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
@alwalidsalama
Alwalid Salama (alwalidsalama) force-pushed the reset_test branch 6 times, most recently from 047eb15 to 7304cc0 Compare July 16, 2026 18:07
  The Windows coroutine-test guard used `if(... ${num_cpu} in
  WINDOWS_COROUTINE_ALLOWED_NUM_CPU ...)`, but CMake has no `in` operator.
  Older CMake tolerated it; stricter newer CMake (clangarm64 runner) rejects
  it with "Unknown arguments specified".

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
@alwalidsalama
Alwalid Salama (alwalidsalama) force-pushed the reset_test branch 2 times, most recently from f9be0bb to b370b85 Compare July 16, 2026 21:45
  Detaching the last suspending channel must wake a kernel already blocked in
  async_suspend(); SystemC's detach_suspending() clears the flag without posting
  the suspend semaphore. The cross-thread path already re-posts via
  async_request_update(); the same-thread path did not, so a same-thread detach
  of the last channel left the kernel asleep forever (mcips tests hung with 0
  attached channels, main thread stuck in async_suspend). Post from the
  same-thread path too.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants