Skip to content

mcips plugin: Sync time between qemu and systemC#62

Open
alwalidsalama wants to merge 14 commits into
qualcomm:mainfrom
alwalidsalama:ips
Open

mcips plugin: Sync time between qemu and systemC#62
alwalidsalama wants to merge 14 commits into
qualcomm:mainfrom
alwalidsalama:ips

Conversation

@alwalidsalama
Copy link
Copy Markdown
Contributor

No description provided.

@alwalidsalama alwalidsalama self-assigned this May 21, 2026
@alwalidsalama alwalidsalama force-pushed the ips branch 7 times, most recently from a4bc492 to 21e8273 Compare June 1, 2026 11:16
- libqemu: expose TCG plugin API through LibQemuExports

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Plugin functions are now exported via libqemu's auto-generated
LibQemuExports struct (the same path used by every other libqemu
function), reachable through a new accessor on the LibQemu class.

- Add a const LibQemuExports& plugin_api() accessor.
- Pull libqemu/libqemu.h into libqemu-cxx.h so plugin types
  (qemu_plugin_id_t, qemu_plugin_tb, ...) are visible to consumers
  via the auto-generated typedefs.h.
- Add a small glib.h shim under qemu-components/common/include/glib_shim
  with opaque forward-decls of GArray and GByteArray. libqemu's
  typedefs.h is wrapped in extern "C" and pulls in qemu-plugin.h, which
  itself includes <glib.h>. Modern glib has C++ template inline
  functions that fail with "template with C linkage" inside extern "C".
  The shim is on the qbox library target's BUILD_INTERFACE include path
  (BEFORE), so in-tree TUs see the forward-decls instead of real glib;
  installed-qbox consumers do not pick up the shim.

Call sites read:
    m_inst.plugin_api().qemu_plugin_xxx(...)

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
- add attach(), detach() and is_attached() helper functions for sync_window
- Add m_is_attached flag to track attach/detach state and validate
async_set_window() calls. Fatal error if called while detached.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Introduce LibQemuPlugin, a SystemC module providing a C++ interface
for QEMU's TCG plugin API.

Two dispatch paths, one shared safety net:

- ID-keyed callbacks (vcpu_init, vcpu_idle, vcpu_resume, ...): QEMU
  passes only qemu_plugin_id_t, no userdata. Resolved via an
  id_map<id, plugin*> registry. Use the REGISTER_CALLBACK_ID macro to
  declare them.

- USERDATA-keyed callbacks (vcpu_tb_exec_cond, register_time_cb, ...):
  QEMU forwards a void* userdata. Plugins pass handle_as_userdata()
  at registration; the static bridge calls dispatch_userdata() with a
  lambda. No map lookup, no macro.

Both paths share a heap-allocated PluginHandle that is intentionally
leaked at plugin destruction so any callback QEMU still has registered
finds alive==false and returns early instead of dereferencing freed
memory. shutdown_bridge() flips alive once and waits for the shared
refcount to drain.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Implement McipsPlugin (Multi Core Instructions Per Second), which
synchronizes time between QEMU and SystemC based on a configurable
instructions-per-second rate per vCPU.

- Track executed instructions per vCPU via QEMU's scoreboard API.
- Trigger vcpu_tb_exec_cond when a vCPU's instruction count reaches
  the quantum threshold.
- Compute vCPU time from instruction count and ips rate.
- Track which CPU is advancing QEMU's global time (active CPU); pause
  CPUs that run ahead, resume those that fall behind, send updated
  sync windows to SystemC.

Includes a wall-clock-gated watchdog for the iothread-livelock corner
case: when get_qemu_clock observes m_qemu_time unchanged for more
than one second of wall time, idle_tick_method bumps m_qemu_time and
the active CPU's cpu_time by one quantum so the iothread reads a
fresh deadline. The 1-second threshold keeps sub-second unit tests
from tripping the watchdog.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
- add mcips_plugin as a std::unique_ptr for conditional construction.
- add CCI params: "p_enable_mcips_plugin" (enable/disable mcips_plugin).
- push plugin args (idlinker) in QemuInstance constructor only when enabled.
- add helper functions:
    * get_mcips_plugin() asserts plugin is constructed before returning reference.
    * is_mcips_enabled() checks both CCI parameter and actual construction state.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
- Skip QK and related scheduling/timer/wait logic if multi core instructions per second (mcips) is enabled
- if mcips is enabled pass the ips value for this cpu to the plugin by calling mcips_plugin.set_vcpu_insn_per_second(cpu_index, insn_per_second)

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
- export plugin status such as qemu_time, cpu_time, cpu_speed(ips), cpu_index, cpu_status(IDLE, PAUSED, RUNNING) and more to monitor
- add cci value p_refresh_interval_ms (refresh interval in milliseconds for the web interface)

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Only generate mcips=true when threading=MULTI and accel=tcg.
For COROUTINE or SINGLE (or non-tcg), only mcips=false is generated.
add option -DQBOX_ENABLE_MCIPS_TESTS to enable/disable MCIPS tests (default=ON)

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
…cycle (SC_ZERO_TIME)

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
Replace m_cpus[cpuid].halt_cb(true) with a per-cpu gs::async_event array
so each CPU independently detaches the suspending event when it completes,
preventing early simulation termination in multi-cpu runs. Also add
async_event suspend/detach to the hexagon ld-st-mmio test.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
jobs_handler used to call sc_suspendable() immediately after the
job ran. TLM components that end b_transport with
event.notify(SC_ZERO_TIME) (ipcc, qupv3 UART/SPI/I2C, apss_mbox,
rsc, ...) expect an SC_METHOD to fire in the next delta cycle to
drive an IRQ. Under heavy load the SC scheduler can return to
async_suspend before that delta runs, leaving the IRQ stranded
until something unrelated (e.g. an SSH connect) wakes the kernel.
Symptom fingerprint: "X is stuck, but attaching SSH unhangs it."

Yield one delta cycle while still sc_unsuspendable so the SC
scheduler can drain queued processes before the kernel suspends.

Signed-off-by: Alwalid Salama <asalama@qti.qualcomm.com>
covering configuration, behavior, and synchronization model

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.

1 participant