|
qemu-kvm虚拟化 vpid 代码分析
1.页表实现线性地址到物理地址转换。
2.ept (Extended Page Tables)实现客户机物理地址到宿主机物理地址装换。
3.tlb (Translation lookaside buffer )旁路装换缓冲区,改进虚拟地址(线性地址)到物理地址转换速度的缓存。
操作系统中我们知道每个进程都有自己页表,进程切换重新设置cr3寄存器,同时刷新tlb。但是进程切换并不一定要刷新tlb,相同页表的进程切换和内核线程与普通进程切换,其实就不需要。
对于虚拟化来说,Vm-Entry 和Vm-Exit时,会强制cpu刷新tlb,全部内容失效, 不管是VMM页表, 还是各个虚拟机的ept页表的tlb缓存。
4.vpid 就是避免tlb刷新整体失效,区分是vmm ,各个vm页表,这样提高虚拟机切换效率。要使用vpid很简单,首先判断cpu是否支持vpid(读取VMCS相应域),然后分配vcpu时同时分配vpid(设置VMCS相应域),剩下事情属于硬件事情了。
1).硬件是否支持
cat /proc/cpuinfo | grep vpid
cat /proc/cpuinfo | grep ept
2).模块是否启用
cat /sys/module/kvm_intel/parameters/ept
cat /sys/module/kvm_intel/parameters/vpid
代码分析
判断cpu是否支持vpid
static inline int cpu_has_vmx_vpid(void)
{
return vmcs_config.cpu_based_2nd_exec_ctrl &
SECONDARY_EXEC_ENABLE_VPID;
}
分配vpid
static void allocate_vpid(struct vcpu_vmx *vmx)
{
int vpid;
vmx->vpid = 0;
if (!enable_vpid)
return;
spin_lock(&vmx_vpid_lock);
vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
if (vpid < VMX_NR_VPIDS) {
vmx->vpid = vpid;
__set_bit(vpid, vmx_vpid_bitmap);
}
spin_unlock(&vmx_vpid_lock);
}
释放vpid
static void free_vpid(struct vcpu_vmx *vmx)
{
if (!enable_vpid)
return;
spin_lock(&vmx_vpid_lock);
if (vmx->vpid != 0)
__clear_bit(vmx->vpid, vmx_vpid_bitmap);
spin_unlock(&vmx_vpid_lock);
}
刷新vpid
static inline void vpid_sync_vcpu_all(struct vcpu_vmx *vmx)
{
if (vmx->vpid == 0)
return;
__invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vmx->vpid, 0);
} |
|
|