From: Joerg Roedel <[email protected]>

When creating one VCPU object per plane there is still a lot of VCPU
state which needes to be shared across all planes. Create struct
kvm_vcpu_common as a container for this shared state.

Co-developed-by: Carlos López <[email protected]>
Signed-off-by: Joerg Roedel <[email protected]>
---
 include/linux/kvm_host.h | 10 ++++++++++
 virt/kvm/kvm_main.c      | 36 ++++++++++++++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 5a72f73a2f31..c4c4922df965 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -322,6 +322,13 @@ struct kvm_mmio_fragment {
        unsigned int len;
 };
 
+struct kvm_vcpu_common {
+       struct kvm *kvm;
+
+       /* Currently active VCPU */
+       struct kvm_vcpu *current_vcpu;
+};
+
 struct kvm_vcpu {
        struct kvm *kvm;
        struct kvm_plane *plane;
@@ -400,6 +407,9 @@ struct kvm_vcpu {
         */
        struct kvm_memory_slot *last_used_slot;
        u64 last_used_slot_gen;
+
+       struct kvm_vcpu_common *common;
+       unsigned plane_level;
 };
 
 /*
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 668645dd3945..fb840d029c56 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -438,6 +438,20 @@ void *kvm_mmu_memory_cache_alloc(struct 
kvm_mmu_memory_cache *mc)
 }
 #endif
 
+static int kvm_vcpu_init_common(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+       struct kvm_vcpu_common *common = kzalloc(sizeof(*common), 
GFP_KERNEL_ACCOUNT);
+
+       if (common == NULL)
+               return -ENOMEM;
+
+       common->kvm = kvm;
+       common->current_vcpu = vcpu;
+       vcpu->common = common;
+
+       return 0;
+}
+
 static void kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
 {
        mutex_init(&vcpu->mutex);
@@ -459,14 +473,26 @@ static void kvm_vcpu_init(struct kvm_vcpu *vcpu, struct 
kvm *kvm, unsigned id)
        preempt_notifier_init(&vcpu->preempt_notifier, &kvm_preempt_ops);
        vcpu->last_used_slot = NULL;
 
+       vcpu->plane_level = 0;
+
        /* Fill the stats id string for the vcpu */
        snprintf(vcpu->stats_id, sizeof(vcpu->stats_id), "kvm-%d/vcpu-%d",
                 task_pid_nr(current), id);
 }
 
+static void kvm_vcpu_common_destroy(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->plane_level == 0)
+               kfree(vcpu->common);
+
+       vcpu->common = NULL;
+}
+
 static void kvm_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        kvm_arch_vcpu_destroy(vcpu);
+
+       kvm_vcpu_common_destroy(vcpu);
        kvm_dirty_ring_free(&vcpu->dirty_ring);
 
        /*
@@ -1360,8 +1386,8 @@ static void kvm_destroy_vm(struct kvm *kvm)
 #ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES
        xa_destroy(&kvm->mem_attr_array);
 #endif
-       kvm_arch_free_vm(kvm);
        kvm_destroy_planes(kvm);
+       kvm_arch_free_vm(kvm);
        preempt_notifier_dec();
        kvm_disable_virtualization();
        mmdrop(mm);
@@ -4246,11 +4272,15 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, 
unsigned long id)
                goto vcpu_decrement;
        }
 
+       r = kvm_vcpu_init_common(vcpu, kvm);
+       if (r)
+               goto vcpu_free;
+
        BUILD_BUG_ON(sizeof(struct kvm_run) > PAGE_SIZE);
        page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
        if (!page) {
                r = -ENOMEM;
-               goto vcpu_free;
+               goto vcpu_free_common;
        }
        vcpu->run = page_address(page);
 
@@ -4318,6 +4348,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, 
unsigned long id)
        kvm_arch_vcpu_destroy(vcpu);
 vcpu_free_run_page:
        free_page((unsigned long)vcpu->run);
+vcpu_free_common:
+       kvm_vcpu_common_destroy(vcpu);
 vcpu_free:
        kmem_cache_free(kvm_vcpu_cache, vcpu);
 vcpu_decrement:
-- 
2.53.0


Reply via email to