Provide a generic mechanism so that users of struct kvm_run's 'immediate_exit' flag can register a callback that can be issued after returning from KVM. Utilize the recently-added async_run_on_cpu_after_accel() interface, with a small wrapper to set the 'immediate_exit' to arm any new callbacks.
As with async_run_on_cpu_after_accel(), these callbacks are not run with the BQL held; that is left to individual callback implementations when needed. Signed-off-by: Michael Roth <[email protected]> Signed-off-by: Melody Wang <[email protected]> --- accel/kvm/kvm-all.c | 20 ++++++++++++++++++++ include/system/kvm.h | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index db8fba53f3..a6bc0b3bed 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3449,6 +3449,19 @@ out_unref: return ret; } +/* + * Queue up CPU work to run after the next call to KVM_RUN. + * + * Requires KVM_CAP_IMMEDIATE_EXIT. + */ +void kvm_add_immediate_exit_callback(CPUState *cpu, run_on_cpu_func cb, + run_on_cpu_data data) +{ + assert(kvm_immediate_exit); + async_run_on_cpu_after_accel(cpu, cb, data); + kvm_cpu_kick(cpu); +} + int kvm_cpu_exec(CPUState *cpu) { struct kvm_run *run = cpu->kvm_run; @@ -3511,6 +3524,13 @@ int kvm_cpu_exec(CPUState *cpu) if (run_ret == -EINTR || run_ret == -EAGAIN) { trace_kvm_io_window_exit(); kvm_eat_signals(cpu); + /* + * This will process any events queued by + * kvm_add_immediate_exit_callback(). This is intentionally run + * after 'immediate_exit' field is cleared by kvm_eat_signal() + * so that queued accel work can requeue itself if needed. + */ + process_queued_cpu_accel_work(cpu); ret = EXCP_INTERRUPT; break; } diff --git a/include/system/kvm.h b/include/system/kvm.h index d29624034c..2c08992bce 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -21,6 +21,7 @@ #include "qemu/accel.h" #include "accel/accel-route.h" #include "qom/object.h" +#include "hw/core/cpu.h" #ifdef COMPILING_PER_TARGET # ifdef CONFIG_KVM @@ -594,4 +595,14 @@ void kvm_vcpufd_add_change_notifier(NotifierWithReturn *n); */ void kvm_vcpufd_remove_change_notifier(NotifierWithReturn *n); +/** + * kvm_add_immediate_exit_callback - register a callback to be performed after + * the next call to KVM_RUN (with immediate_exit set via kvm_cpu_kick()). + * @cpu: CPU to run the callback on. + * @cb: The callback to run. + * @data: The data to pass to the callback. + */ +void kvm_add_immediate_exit_callback(CPUState *cpu, run_on_cpu_func cb, + run_on_cpu_data data); + #endif -- 2.43.0
