基于x86的KVM实现之vcpu建立过程

在用户态通过ioctl设置KVM_CREATE_VCPU时,内核会创建一个虚拟CPU环境:
kvm_vm_ioctl_create_vcpu()
	--> kvm_arch_vcpu_create() --> vmx_create_vcpu
	--> kvm_arch_vcpu_setup(vcpu);
函数首先通过kvm_arch_vcpu_create()创建基本信息,之后调用kvm_arch_vcpu_setup()建立整个环境信息。
 

struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,       unsigned int id) {  struct kvm_vcpu *vcpu;

 if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0)需要稳定的TSC   printk_once(KERN_WARNING   "kvm: SMP vm created on host with unstable TSC; "   "guest TSC will not be reliable\n");

 vcpu = kvm_x86_ops->vcpu_create(kvm, id);这里我们针对VMX来说,调用函数vmx_create_vcpu

 return vcpu; }

vmx.c static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) {  int err;  struct vcpu_vmx *vmx = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);  int cpu;

 if (!vmx)   return ERR_PTR(-ENOMEM);

 vmx->vpid = allocate_vpid();

 err = kvm_vcpu_init(&vmx->vcpu, kvm, id);建立kvm,vcpu,id三者关系。  if (err)   goto free_vcpu;

 err = -ENOMEM;

 /*   * If PML is turned on, failure on enabling PML just results in failure   * of creating the vcpu, therefore we can simplify PML logic (by   * avoiding dealing with cases, such as enabling PML partially on vcpus   * for the guest, etc.   */  if (enable_pml) {开启PML时,分配页   vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);   if (!vmx->pml_pg)    goto uninit_vcpu;  }

 vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);  BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])        > PAGE_SIZE);

 if (!vmx->guest_msrs)   goto free_pml;

//初始化VMCS对象

 vmx->loaded_vmcs = &vmx->vmcs01;  vmx->loaded_vmcs->vmcs = alloc_vmcs();  vmx->loaded_vmcs->shadow_vmcs = NULL;  if (!vmx->loaded_vmcs->vmcs)   goto free_msrs;

 if (!vmm_exclusive)   kvm_cpu_vmxon(__pa(per_cpu(vmxarea, raw_smp_processor_id())));

loadVMCS和初始化  loaded_vmcs_init(vmx->loaded_vmcs);  if (!vmm_exclusive)   kvm_cpu_vmxoff();

 cpu = get_cpu();  vmx_vcpu_load(&vmx->vcpu, cpu);  vmx->vcpu.cpu = cpu;  err = vmx_vcpu_setup(vmx);  vmx_vcpu_put(&vmx->vcpu);  put_cpu();  if (err)   goto free_vmcs;

 if (cpu_need_virtualize_apic_accesses(&vmx->vcpu)) {   err = alloc_apic_access_page(kvm);   if (err)    goto free_vmcs;  }

 

 if (enable_ept) {   if (!kvm->arch.ept_identity_map_addr)    kvm->arch.ept_identity_map_addr =     VMX_EPT_IDENTITY_PAGETABLE_ADDR;   err = init_rmode_identity_map(kvm);   if (err)    goto free_vmcs;  }

 

 if (nested) {   nested_vmx_setup_ctls_msrs(vmx);   vmx->nested.vpid02 = allocate_vpid();  }

 vmx->nested.posted_intr_nv = -1;  vmx->nested.current_vmptr = -1ull;  vmx->nested.current_vmcs12 = NULL;

 vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;

 return &vmx->vcpu;

free_vmcs:  free_vpid(vmx->nested.vpid02);  free_loaded_vmcs(vmx->loaded_vmcs); free_msrs:  kfree(vmx->guest_msrs); free_pml:  vmx_destroy_pml_buffer(vmx); uninit_vcpu:  kvm_vcpu_uninit(&vmx->vcpu); free_vcpu:  free_vpid(vmx->vpid);  kmem_cache_free(kvm_vcpu_cache, vmx);  return ERR_PTR(err); }

kvm_arch_vcpu_setup

int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) {  int r;

 kvm_vcpu_mtrr_init(vcpu);  r = vcpu_load(vcpu);  if (r)   return r;  kvm_vcpu_reset(vcpu, false);  kvm_mmu_setup(vcpu);  vcpu_put(vcpu);  return r; }

 

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值