Summary
The monitor's /pause route calls sc_core::sc_suspend_all() and nothing else. Under multithread-* sync policies (tcg_mode = "MULTI"), the QEMU vCPU threads and the QEMU virtual clock are not stopped: the guest keeps executing while the simulation is nominally "paused", and on /continue SystemC time jumps forward by roughly the wall-clock duration of the pause.
/pause handler:
|
CROW_ROUTE(m_app, "/pause") |
|
([&]() { |
|
crow::json::wvalue ret; |
|
m_sc.run_on_sysc([&] { |
|
sc_core::sc_suspend_all(); |
|
ret["sc_time_stamp"] = sc_core::sc_time_stamp().to_seconds(); |
|
}); |
|
return ret; |
|
}); |
/continue handler:
|
CROW_ROUTE(m_app, "/continue") |
|
([&]() { |
|
crow::json::wvalue ret; |
|
m_sc.run_on_sysc([&] { |
|
sc_core::sc_unsuspend_all(); |
|
ret["sc_time_stamp"] = sc_core::sc_time_stamp().to_seconds(); |
|
}); |
|
return ret; |
|
}); |
The docs describe the feature as "Pause and resume the simulation" (docs/monitor.md#L12), while the debugging guide already warns "Do not use /pause" (docs/monitor-debugging-guide.md#L262-L264) — this issue is about closing that gap one way or the other.
Reproduction
Any platform using a multithread-* sync policy with the monitor enabled (e.g. the in-tree platforms/ubuntu aarch64 configuration, which uses sync_policy = "multithread-unconstrained": conf_aarch64.lua#L77):
- Boot the platform with the monitor enabled and let Linux start booting.
curl http://localhost:18088/pause
- Observe the guest serial console keeps printing — the vCPUs are still running.
- Wait N seconds (e.g. 60–120 s), then
curl http://localhost:18088/continue.
- Compare
curl http://localhost:18088/sc_time before step 2 and after step 4: SystemC time jumps forward by roughly the wall-clock pause duration (we observed a ~107 s jump after a ~107 s pause), because the vCPUs' quantum-keeper local time kept advancing with the QEMU virtual clock and SystemC then catches up on resume.
Suggestion
Either:
-
Make /pause also stop the QEMU side. The libqemu-cxx wrappers already exist:
LibQemu::vm_stop_paused() / LibQemu::vm_start() declarations:
|
void vm_start(); |
|
void vm_stop_paused(); |
- implementations:
|
void LibQemu::vm_start() { m_int->exports().vm_start(); } |
|
|
|
void LibQemu::vm_stop_paused() { m_int->exports().vm_stop_paused(); } |
Ordering note from our experiments: stop the vCPUs before suspending the SystemC kernel — a vCPU blocked mid-b_transport against an already-suspended kernel cannot park — and resume in the reverse order (sc_unsuspend_all() first, then vm_start()).
-
Or prominently document that /pause is SystemC-only and that guest execution continues under multithread policies (and reconcile docs/monitor.md#L12 with the guide's "Do not use /pause" warning).
Workaround (no QBox change required)
Pass a QMP socket to the embedded QEMU via the QemuInstance qemu_args parameter (qemu-instance.h#L327), e.g. qemu_args = "-qmp tcp:127.0.0.1:<port>,server=on,wait=off", and compose the two:
- pause = QMP
stop first, then /pause
- resume =
/continue first, then QMP cont
Validated under a guest MMIO flood: three pause/continue cycles, each < 0.01 s, resume time-jump 0.000 s, no deadlock.
Summary
The monitor's
/pauseroute callssc_core::sc_suspend_all()and nothing else. Undermultithread-*sync policies (tcg_mode = "MULTI"), the QEMU vCPU threads and the QEMU virtual clock are not stopped: the guest keeps executing while the simulation is nominally "paused", and on/continueSystemC time jumps forward by roughly the wall-clock duration of the pause./pausehandler:qbox/systemc-components/monitor/src/monitor.cc
Lines 278 to 286 in c00e7f7
/continuehandler:qbox/systemc-components/monitor/src/monitor.cc
Lines 287 to 295 in c00e7f7
The docs describe the feature as "Pause and resume the simulation" (docs/monitor.md#L12), while the debugging guide already warns "Do not use
/pause" (docs/monitor-debugging-guide.md#L262-L264) — this issue is about closing that gap one way or the other.Reproduction
Any platform using a
multithread-*sync policy with the monitor enabled (e.g. the in-treeplatforms/ubuntuaarch64 configuration, which usessync_policy = "multithread-unconstrained": conf_aarch64.lua#L77):curl http://localhost:18088/pausecurl http://localhost:18088/continue.curl http://localhost:18088/sc_timebefore step 2 and after step 4: SystemC time jumps forward by roughly the wall-clock pause duration (we observed a ~107 s jump after a ~107 s pause), because the vCPUs' quantum-keeper local time kept advancing with the QEMU virtual clock and SystemC then catches up on resume.Suggestion
Either:
Make
/pausealso stop the QEMU side. The libqemu-cxx wrappers already exist:LibQemu::vm_stop_paused()/LibQemu::vm_start()declarations:qbox/qemu-components/common/include/libqemu-cxx/libqemu-cxx.h
Lines 133 to 134 in c00e7f7
qbox/qemu-components/common/src/libqemu-cxx/libqemu-cxx.cc
Lines 102 to 104 in c00e7f7
Ordering note from our experiments: stop the vCPUs before suspending the SystemC kernel — a vCPU blocked mid-
b_transportagainst an already-suspended kernel cannot park — and resume in the reverse order (sc_unsuspend_all()first, thenvm_start()).Or prominently document that
/pauseis SystemC-only and that guest execution continues under multithread policies (and reconcile docs/monitor.md#L12 with the guide's "Do not use/pause" warning).Workaround (no QBox change required)
Pass a QMP socket to the embedded QEMU via the
QemuInstanceqemu_argsparameter (qemu-instance.h#L327), e.g.qemu_args = "-qmp tcp:127.0.0.1:<port>,server=on,wait=off", and compose the two:stopfirst, then/pause/continuefirst, then QMPcontValidated under a guest MMIO flood: three pause/continue cycles, each < 0.01 s, resume time-jump 0.000 s, no deadlock.