转载请注明出处:
http://www.openext.org/2014/04/kvmvcpu/
http://blog.csdn.net/muge0913/article/details/24660731
qemu/kvm为客户机提供了完整的硬件环境,在客户机看来其所拥有的CPU为vCPU,在KVM看来每个客户机都是一个标准的linux进程qemu进程。在宿主机上vCPU是qemu进程派生出来的普通线程。
在linux中进程有两种模式:用户模式,内核模式。而kvm增加了第三种模式:客户模式。用户模式主要是一些IO的模拟管理。内核模式主要执行一些安全性高性能的指令。客户模式执行大部分的代码。
下面讲下vcpu的创建。创建vCPU就是创建vCPU描述符,在KVM中,vCPU对应的数据结构体为kvm_vcpu。kvm_vcpu中描述符包含的内容,包含各个平台通用的内容和平台相关的内容。
主要过程:分配VCPU标识,设置cpu_id属于哪个KVM虚拟机,并且分配对该VCPU的唯一标识符。
初始化虚拟寄存器组。
初始化kvm_vcpu的状态信息,设置kvm_vcpu在被调度前需要配置的必要标志。
初始化额外的信息,并且配置apic等虚拟化组件。
最终目的就是将kvm_vcpu的各个数据结构体设置成为可用的状态
创建vcpu函数kvm_vm_ioctl_create_vcpu其代码如下。
static int kvm_vm_ioctl_create_vcpu(struct kvm*kvm, u32 id)
{
int r;
struct kvm_vcpu *vcpu, *v;
// 创建kvm_vcpu结构体
vcpu = kvm_arch_vcpu_create(kvm, id);
if (IS_ERR(vcpu))
return PTR_ERR(vcpu);
preempt_notifier_init(&vcpu->preempt_notifier,&kvm_preempt_ops);
//设置结构体内容
r = kvm_arch_vcpu_setup(vcpu);
if (r)
return r;
//加锁,以便vcpu_fd正确加载
mutex_lock(&kvm->lock);
if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
r = -EINVAL;
goto vcpu_destroy;
}
//检查创建出来的vcpu是否存在
kvm_for_each_vcpu(r, v, kvm)
if (v->vcpu_id == id) {
r = -EEXIST;
goto vcpu_destroy;
}
BUG_ON(kvm->vcpus[atomic_read(&kvm->online_vcpus)]);
/* Now it‘s all set up, let userspace reach it */
kvm_get_kvm(kvm);
//创建vcp_fd
r = create_vcpu_fd(vcpu);
if (r < 0) {
kvm_put_kvm(kvm);
goto vcpu_destroy;
}
kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu;
smp_wmb();
atomic_inc(&kvm->online_vcpus);
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
if (kvm->bsp_vcpu_id == id)
kvm->bsp_vcpu = vcpu;
#endif
//解锁
mutex_unlock(&kvm->lock);
return r;
vcpu_destroy:
mutex_unlock(&kvm->lock);
kvm_arch_vcpu_destroy(vcpu);
return r;
}
原文地址:http://blog.csdn.net/muge0913/article/details/24660731