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
