From: Joerg Roedel <[email protected]>

Implement the plane event handling infrastructure and handle the
KVM_PLANE_EVENT_CREATE_CPU event.

Co-developed-by: Tom Lendacky <[email protected]>
Signed-off-by: Joerg Roedel <[email protected]>
---
 accel/kvm/kvm-all.c   | 13 +++++++---
 include/system/kvm.h  |  2 +-
 target/i386/kvm/kvm.c | 57 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index dbfef63a84b0..c5fe6d189e62 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -573,11 +573,17 @@ static void kvm_alloc_vcpu_plane(CPUState *cpu, unsigned 
plane_id, int kvm_fd)
     cpu->kvm_plane_state[plane_id] = p;
 }
 
-void kvm_create_vcpu_plane(CPUState *cpu, unsigned plane_id, int kvm_fd)
+void kvm_create_vcpu_plane(CPUState *cpu, unsigned plane_id)
 {
-    int vcpu_fd = cpu_kvm_plane(cpu, 0)->kvm_fd;
-    int plane_fd = kvm_vm_plane_ioctl(cpu->kvm_state, plane_id, 
KVM_CREATE_VCPU, vcpu_fd);
+    X86CPU *x86_cpu = X86_CPU(cpu);
+    int plane_fd;
 
+    if (kvm_get_or_create_plane_fd(cpu->kvm_state, plane_id) < 0) {
+        fprintf(stderr, "Failed to create plane %d\n", plane_id);
+        abort();
+    }
+
+    plane_fd = kvm_vm_plane_ioctl(cpu->kvm_state, plane_id, KVM_CREATE_VCPU, 
x86_cpu->apic_id);
     if (plane_fd < 0) {
         fprintf(stderr, "Failed to create plane vcpu\n");
         abort();
@@ -586,7 +592,6 @@ void kvm_create_vcpu_plane(CPUState *cpu, unsigned 
plane_id, int kvm_fd)
     kvm_alloc_vcpu_plane(cpu, plane_id, plane_fd);
 }
 
-
 /**
  * kvm_create_vcpu - Gets a parked KVM vCPU or creates a KVM vCPU
  * @cpu: QOM CPUState object for which KVM vCPU has to be fetched/created.
diff --git a/include/system/kvm.h b/include/system/kvm.h
index 16597333cfa5..24a21915366f 100644
--- a/include/system/kvm.h
+++ b/include/system/kvm.h
@@ -221,7 +221,7 @@ int kvm_vm_ioctl(KVMState *s, unsigned long type, ...);
 int kvm_vm_plane_ioctl(KVMState *s, unsigned plane_id, unsigned long type, 
...);
 
 int kvm_get_or_create_plane_fd(KVMState *s, unsigned id);
-void kvm_create_vcpu_plane(CPUState *cpu, unsigned plane, int kvm_fd);
+void kvm_create_vcpu_plane(CPUState *cpu, unsigned plane);
 
 void kvm_flush_coalesced_mmio_buffer(void);
 
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 9e352882c8c3..30fba9e75016 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -6524,6 +6524,60 @@ static int kvm_handle_hypercall(X86CPU *cpu, struct 
kvm_run *run)
     return -EINVAL;
 }
 
+static CPUState *kvm_get_cpu_by_apicid(CPUState *cpu, unsigned apic_id)
+{
+    CPU_FOREACH(cpu) {
+        X86CPU *x86_cpu = X86_CPU(cpu);
+        if (x86_cpu->apic_id == apic_id) {
+            return cpu;
+        }
+    }
+
+    return NULL;
+}
+
+static void create_plane_vcpu_cb(CPUState *cs, run_on_cpu_data data)
+{
+    int plane = data.host_int;
+
+    kvm_create_vcpu_plane(cs, plane);
+}
+
+static int kvm_handle_plane_create_vcpu(CPUState *cpu, struct kvm_run *run)
+{
+    CPUState *target_cpu = NULL;
+    int plane = -EINVAL;
+
+    plane = run->plane_event.plane;
+    if (plane < 0) {
+        return plane;
+    }
+
+    target_cpu = kvm_get_cpu_by_apicid(cpu, run->plane_event.extra[0]);
+    if (target_cpu == NULL) {
+        return -EINVAL;
+    }
+
+    bql_lock();
+    run_on_cpu(target_cpu, create_plane_vcpu_cb, RUN_ON_CPU_HOST_INT(plane));
+    bql_unlock();
+
+    return 0;
+}
+
+static int kvm_handle_plane_event(CPUState *cpu, struct kvm_run *run)
+{
+    switch (run->plane_event.cause) {
+        case KVM_PLANE_EVENT_CREATE_VCPU:
+            return kvm_handle_plane_create_vcpu(cpu, run);
+        default:
+            fprintf(stderr, "KVM: unknown plane event %d\n", 
run->plane_event.cause);
+            break;
+    }
+
+    return -EINVAL;
+}
+
 #define VMX_INVALID_GUEST_STATE 0x80000021
 
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
@@ -6648,6 +6702,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run 
*run)
             break;
         }
         ret = 0;
+       break;
+    case KVM_EXIT_PLANE_EVENT:
+        ret = kvm_handle_plane_event(cs, run);
         break;
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
-- 
2.53.0


Reply via email to