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


Reply via email to