KVM同步脏页原理

2023-11-09


QEMU在内存迁移阶段首先会标脏所有内存页,然后通知KVM开启脏页统计。本章主要介绍KVM在脏页统计中的作用,首先介绍intel x86脏页统计的硬件基础,然后介绍KVM中脏页统计相关数据结构、脏页开启的IOCTL命令字介绍、脏页统计发起流程,最后实验验证上述分析。

硬件基础

  • KVM脏页统计离不开硬件支持,在Intel没有引入PML(Page Modification Logging)特性之前。主要利用SPTE的D状态位跟踪脏页。在引入PML之后,则通过PML跟踪脏页,其主要功能是记录虚机写内存页的行为并将内存页的地址GPA记录下来。我们分别介绍SPTE和PML。

SPTE

硬件要素

请添加图片描述
在这里插入图片描述

  • 上图为intel Page table各个字段定义,其中bit 6称为脏页标记位,我们知道intel Page table有两个作用,一个是指向真正的物理页,一个是指向包含下级页表内容的物理页,用于线性地址转化。
  • 当一个Page table指向真正物理页的条目(作为SPTE)时,如果CPU对该SPTE指向的物理页有写操作,硬件会将脏页标记位置位,CPU下一次写该页时会再次置位(需要软件清零脏页位),通过硬件置位-软件清零的手段,软件可以跟踪到虚拟机脏页状态。

工作流程

  • TODO

PML

硬件要素

在这里插入图片描述

  • PML是Intel为支持虚拟化场景下脏页跟踪而开发的硬件特性,使用该特性涉及到Intel的几个硬件元素,下面根据以上图示一一介绍:
  1. Accessed and Dirty flags:这是EPTP字段中位于bit 6的一个标志位,当设置此标志位后,它告诉CPU每当使用EPT查询HPA时,将页结构存放的表项中的Accessed位(bit 8)置1,对于指向物理页的页表项,当往指向的物理页中写数据时,将它的Dirty位(bit 9)置1。
  2. PML flag:这是VMCS VM-Exection Controls Field区域的一个标志位,用于使能PML特性。只有在Accessed and Dirty flags位开启时,才可以使能PML。
  3. PML Buffer:一块内存区域,用来存放上一次开启PML特性之后,CPU写过的物理页的地址,大小为4K,可以存放512条GPA。KVM就是通过这个区域来跟踪内存脏页。
  4. PML Address:用来保存PML Buffer的内存物理地址,它是VMCS VM-Execution control field的一个字段。
  5. PML index:用来保存PML Buffer的索引,长度16 bit,表示范围0-511,和PML Buffer中的条目对应。PML index用来保存下一次CPU写物理页保存GPA时在PML Buffer中的位置。PML index每次递减。

工作流程

在这里插入图片描述

  • 下面介绍开启PML特性之后,记录脏页的整个工作流程,如图所示,分以下5个步骤:
  1. 当CPU想要记录内存脏页,比如迁移开始时,首先设置Accessed and Dirty flags和PML flag标志,使能脏页记录功能。当CPU写VM的物理内存页时,如果发现Accessed and Dirty和PML都使能了,会首先将对应表项的Access和Dirty位置1,然后将GPA记录到PML Buffer中。每写一次物理内存页,PML Buffer就多一条GPA的记录,PML index减1。
  2. 当PML Buffer被填满时,会产生page-modification log-full event,然后触发VMExit。
  3. CPU退出到根模式的内核态之后,KVM会判断退出原因,如果是PML Buffer满引起的退出,会将PML Buffer的内容保存下来,然后PML Buffer的索引PML index会被重新置为511。
  4. PML Buffer的内容,就是CPU最近写过的内存页地址,它就是内存的脏数据,对于内存迁移来说,该数据可以用来评估虚机的内存变化量。如果PML Buffer中内容较少,那么Qemu可以将虚机暂停然后一次性拷贝完。
  5. 当CPU不想记录内存脏页,迁移已经完成后,就可以关闭PML特性。
  • 注意:上面的过程是Intel PML特性的通用使用过程,对于kvm的实现中,并不是每次迁移开始前才开启PML特性,而是在kvm模块初始化的过程中开启,PML Buffer的分配是在vcpu创建过程中。迁移结束也不会关闭PML特性。PML特性是一直存在于KVM模块的生命周期中的。

数据结构

用户态

  • RAMList
typedef struct {
   ......
   /* 存放记录脏页的位图,一个block元素可以表示的内存范围是256K个内存页 */
    unsigned long *blocks[];
} DirtyMemoryBlocks;

typedef struct RAMList {
	......
	/* 虚机占用的所有主机上的RAM内存块集合 */
    QLIST_HEAD(, RAMBlock) blocks;
    /* 用户态从内核获取虚机脏页信息时保存到的结构体 */
    DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM];
} RAMList;
  • RAMBlock
struct RAMBlock {
	...... 
	/* 内存区域表示的最大范围,单位是字节 */
	ram_addr_t max_length;
	/* dirty bitmap used during migration */
	/* 记录该内存区域脏页情况的位图,一个内存页对应一个bit位
	    它是一个长整形指针数组,整个数组元素长度加起来转换
	    成bit数等于max_length/4K 
	    */
    unsigned long *bmap;								
	......
}
  • 用户态与脏页统计有关的数据结构有以上两个,RAMList和RAMBlock,它们各自的数据结构图示如下,既然都是统计脏页,为什么需要两个数据结构呢?个人觉得,这两个数据结构的使用场景是不一样的,RAMList用在从内核获取脏页的时候,它表示脏页的粒度是kvm中的一个slot;而RAMBlock中的位图用来描述一个RAMBlock的脏页使用情况,它表示的脏页粒度是Qemu中的一个RAMBlock。在内存迁移统计脏页过程中,会依次使用这两个数据结构统计剩余内存的脏页数量。
    在这里插入图片描述

内核态

  • vcpu_vmx
struct vcpu_vmx {
	struct page *pml_pg; 
	......
}
  • vmcs_field_to_offset_table
vmcs_field_to_offset_table[] = { 
	......
	FIELD(GUEST_PML_INDEX, guest_pml_index),
	FIELD64(PML_ADDRESS, pml_address)
	......
}
  • kvm_userspace_memory_region
/* for KVM_SET_USER_MEMORY_REGION */
struct kvm_userspace_memory_region {
	/* 内存区间所在的插槽 */
	__u32 slot;								
	/* 当flags包含KVM_SET_USER_MEMORY_REGION标识时
	   表示开启这段内存的脏页记录  
	   */
	__u32 flags;					
	/* 虚机内存区间物理地址 */		
	__u64 guest_phys_addr;
	/* 虚机内存区间大小 */
	__u64 memory_size; /* bytes */
	/* 分配给这段内存区间的实际的用户态地址HVA */
	__u64 userspace_addr; /* start of the userspace allocated memory */
};
  • kvm_dirty_log
/* for KVM_GET_DIRTY_LOG */
struct kvm_dirty_log {
	__u32 slot;
	__u32 padding1;
	union {
		void *dirty_bitmap; /* one bit per page */
		__u64 padding2;
	};
};
  • kvm_memory_slot
struct kvm_memory_slot {
	gfn_t base_gfn;
	unsigned long npages;
	unsigned long *dirty_bitmap;
	u32 flags;
    ....
};

API

  • 为了让用于态统计虚机的脏页,内核提供了两个接口,分别是KVM_SET_USER_MEMORY_REGIONKVM_GET_DIRTY_LOG,这两个接口

脏页开启

  • 内核提供了两个命令供用户态统计虚机的脏页,KVM_SET_USER_MEMORY_REGION、KVM_GET_DIRTY_LOG,KVM_SET_USER_MEMORY_REGION命令字作用在vm的fd,用来通知kvm开启对某段内存区域的脏页跟踪,结构体kvm_userspace_memory_region 是用户态传入的参数,用来描述kvm应该跟踪的内存区域,如下:
Capability: KVM_CAP_USER_MEMORY
Architectures: all
Type: vm ioctl          /* 虚机vm ioctl命令字 */
Parameters: struct kvm_userspace_memory_region (in)
Returns: 0 on success, -1 on error
 
  struct kvm_userspace_memory_region {
    __u32 slot;
    __u32 flags;
    __u64 guest_phys_addr;
    __u64 memory_size; /* bytes */
    __u64 userspace_addr; /* start of the userspace allocated memory */
  };
  /* for kvm_memory_region::flags */
  #define KVM_MEM_LOG_DIRTY_PAGES    (1UL << 0)
  #define KVM_MEM_READONLY    (1UL << 1)

脏页获取

  • KVM_GET_DIRTY_LOG命令字作用在vm的fd,用来获取内核跟踪的脏页信息,结构体kvm_dirty_log作为参数用来指定要查询的内存slot,同时保存内核的脏页查询结果,如下:
Capability: basic
Architectures: all
Type: vm ioctl
Parameters: struct kvm_dirty_log (in/out)
Returns: 0 on success, -1 on error
 
  /* for KVM_GET_DIRTY_LOG */
  struct kvm_dirty_log {
    /* 输入,指定要查询脏页的内存slot */
    __u32 slot;
    __u32 padding;
    union {
        /* 输出,保存kvm查询到的脏页 */
        void __user *dirty_bitmap; /* one bit per page */
        __u64 padding;
    };
  };

流程

使能记录

  • KVM的PML特性在模块初始化的过程中完成,每创建一个vcpu,需要为其分配PML Buffer并初始化PML Index。
使能PML特性:
/* kvm模块初始化入口  */
vmx_init										
	kvm_init
		kvm_arch_hardware_setup
			vmx_x86_ops.hardware_setup
				hardware_setup
					/* 设置VMCS区域内存的内容
					   在VMLAUNCH和VMRESUME的时候被加载到VMCS区域
					 */
					setup_vmcs_config
						/* 设置SECONDARY_EXEC_ENABLE_PML标识使能PML */
						opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | XXX | SECONDARY_EXEC_ENABLE_PML
						adjust_vmx_controls(min2, opt2, MSR_IA32_VMX_PROCBASED_CTLS2, &_cpu_based_2nd_exec_control)
						vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;
设置PML Buffer地址和PML Index初始值:
/* vcpu创建入口 */
vmx_create_vcpu
	vmx_vcpu_setup
		/* 如果使能了PML特性,分配一个物理页给pml_pg用作PML Buffer */
		if (enable_pml) {
			vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
		}
		/* 将分配好的PML Buffer地址写入VMCS的对应区域,同时初始化PMLIndex为511  */
		if (enable_pml) {
			vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); 
			vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
		}

记录脏页

流程图

在这里插入图片描述

具体过程

  • 根据PML的硬件特性,每当CPU在Guest态根据EPT转换地址后,写数据到物理页,这时如果PML特性开启,在设置EPT页表项的Dirty位之后,还会将GPA地址写入PML Buffer。这里intel暗含的假设是之后Dirty标志位从0变成1,才能写PML Buffer,而Dirty标志位的变成1之后的清零动作是软件做的,因此如果想要记录一个slot的脏页,需要将引用这个slot的所有页表项的Dirty标志位都清零。开启脏页记录需要做以下两件事情:
  1. 清零Dirty位:KVM的实现中,在创建slot时,如果不想记录某个slot包含的所有物理页的是否为脏,需要默认将这些物理页对应的页表项的Dirty页置位,因为如果Dirty位是0,Guest态CPU写物理页时会将其置1并且填充GPA到PML Buffer,如果PML Buffer满了,就会触发VMExit,增加不必要的开销。反之,要记录脏页,首先需要将指向slot包含的所有物理页的spte的Dirty位清零,这里需要根据gfn找到指向该gfn对应页的spte,反向映射数组rmap就派上了用场。
  2. 物理页开启写保护:除了清零页表项的Dirty位,记录脏页还需要开启页的写保护,在脏页记录的过程中,所有slot包含的物理页变成只读,当CPU写访问这个页时,发生缺页异常,kvm会重新分配一个新的页给CPU。在脏页记录关闭后,才能将写保护去掉,slot包含的所有页变成可读写。
/* kvm ioctl入口 */
kvm_vm_ioctl
	/* slot命令字,内核根据传入的参数
	   对应地增加,删除和更新slot
	   这里要跟踪slot的脏页,算在更新里面
	   */
    case KVM_SET_USER_MEMORY_REGION
    kvm_vm_ioctl_set_memory_region
        kvm_set_memory_region
            __kvm_set_memory_region
            	/* 根据用户态传入的参数,设置slot,这里是开启脏页的记录*/
                kvm_set_memslot
                    kvm_arch_commit_memory_region           
                        kvm_mmu_slot_apply_flags
                        	/* 根据intel vmx的特性开启脏页记录 */
                        	if (new->flags & KVM_MEM_LOG_DIRTY_PAGES) {
                        		if (kvm_x86_ops.slot_enable_log_dirty) {
                        			/* 对于x86平台,如果intel提供了PML机制可以记录脏页,进入这个流程 */
									kvm_x86_ops.slot_enable_log_dirty(kvm, new)
									kvm_x86_ops.slot_enable_log_dirty   <=>   vmx_slot_enable_log_dirty
								} else {
									/* 在没有PML机制的情况下,使用页只读的方式记录脏页 
									 * 判断两种情况,分别处理:
									 * 1. 首次迭代时位图都标记为1,不需要标记4k小页,但需要标记
									 * 2M的大页为只读,这样kvm在处理虚机大页访问异常时会将其拆
									 * 分成小页。
									 * 2. 对于其它轮次的迭代,需要将所有4k页的页表项都标记为只读
									 */
                        			int level =
										kvm_dirty_log_manual_protect_and_init_set(kvm) ?
										PG_LEVEL_2M : PG_LEVEL_4K;
										kvm_mmu_slot_remove_write_access(kvm, new, level);
                            	}	
                          	}
  • 分析x86架构下使用PML机制记录脏页的流程,kernel中关于PML场景下的comment如下:
        /*
         * Dirty logging tracks sptes in 4k granularity, meaning that
         * large sptes have to be split.  If live migration succeeds,
         * the guest in the source machine will be destroyed and large
         * sptes will be created in the destination.  However, if the
         * guest continues to run in the source machine (for example if
         * live migration fails), small sptes will remain around and
         * cause bad performance.
         *
         * Scan sptes if dirty logging has been stopped, dropping those
         * which can be collapsed into a single large-page spte.  Later
         * page faults will create the large-page sptes.
         */
  • 流程如下:
vmx_slot_enable_log_dirty
	kvm_mmu_slot_apply_flags
		/* cpu_dirty_log_size存在表明开启了PML,使能脏页日志跟踪分两种情况 
         * 1: 对于4K普通的页,只需要清零D-bit状态位即可
         * 2: 对于2M大页,除了清零D-bit状态位,还需要使能写保护
         *    使得虚机访问大页页表时也能触发异常,陷入kvm后以4k页的粒度分配虚机的页
         *    从而将大页拆分为小页
         */
		if (kvm_x86_ops.cpu_dirty_log_size) {
		    /* 清零D状态位,方便硬件下一次统计 */
			kvm_mmu_slot_leaf_clear_dirty(kvm, new);
			   /* 这里通过rmap数据,遍历指向slot包含的所有物理页的spte
	 	 	    * 针对每个spte调用__rmap_clear_dirty函数 
 	 	 	    */
 			    slot_handle_leaf_4k(kvm, memslot, __rmap_clear_dirty, false)
			/* 开启所有2M大页页表项的写保护功能 */
			kvm_mmu_slot_remove_write_access(kvm, new, PG_LEVEL_2M);
		} else {
			kvm_mmu_slot_remove_write_access(kvm, new, PG_LEVEL_4K);
		}
		
/* 清零表项的Dirty位*/
__rmap_clear_dirty
	spte_clear_dirty
		/* 将kvm模块初始化时设置的Dirty默认值取出,用于设置spte的Dirty位 */
		spte &= ~shadow_dirty_mask                          			
		mmu_spte_update
			......
			__set_spte
				/* 更新spte表项 */
				WRITE_ONCE(*sptep, spte)
				
/* 设置slot包含的所有页写保护WP */
kvm_mmu_slot_remove_write_access
	slot_handle_large_level(kvm, memslot, slot_rmap_write_protect, false);
		__rmap_write_protect(kvm, rmap_head, false)
			spte_write_protect(sptep, pt_protect)
				/* 清零页表项的bit 1,不允许CPU写物理页 */
				spte = spte & ~PT_WRITABLE_MASK
				mmu_spte_update
					......
					__set_spte
					/* 更新spte表项 */
					WRITE_ONCE(*sptep, spte)
  • 脏页日志开启后,对于使用位图方式跟踪的4k页,缺页异常的快速处理逻辑中,会首先将脏页在slot的位图中标记,然后将页表项标记为可写,不会进入慢速处理分配页表的阶段,因为这些被标记为写保护的页,本身可能已经分配了物理地址,对于使用PML方式跟踪的4k页同样如此。但是对于PML方式跟踪的大页,这里仍然会开启写保护,其目的是让缺页的慢速路径去处理缺页,使其重新分配一块4K的物理页,从而实现缺页在脏页日志开启情况下大页拆小页的逻辑。代码如下:
fast_page_fault
       /*
         * Currently, to simplify the code, write-protection can
         * be removed in the fast path only if the SPTE was
         * write-protected for dirty-logging or access tracking.
         */
        if (fault->write &&
            spte_can_locklessly_be_made_writable(spte)) {
            new_spte |= PT_WRITABLE_MASK;

            /*
             * Do not fix write-permission on the large spte.  Since
             * we only dirty the first page into the dirty-bitmap in
             * fast_pf_fix_direct_spte(), other pages are missed
             * if its slot has dirty logging enabled.
             *
             * Instead, we let the slow page fault path create a
             * normal spte to fix the access.
             *
             * See the comments in kvm_arch_commit_memory_region().
             */
            if (sp->role.level > PG_LEVEL_4K)
                break;
        }

获取脏页

流程图

在这里插入图片描述

具体过程

  • 获取脏页的流程,实际上也分为了两个步骤,第一步是拷贝dirty bitmap,第二步是清零脏页的标志。
  • kvm在早期的实现中,将这两步合在一起,在KVM_GET_DIRTY_LOG ioctl中实现了,由于第二步需要拿mmu_lock锁修改页表,并且不知道哪些页需要清零,因此会清零虚机所有页,而vcpu缺页退出guest态时,kvm处理缺页这个操作需要竞争mmu_lock,长时间持有mmu_lock会影响vcpu的内存访问性能,因此第二步的开销很大。
  • kvm在之后改进了脏页获取流程,引入了KVM_CAP_MANUAL_DIRTY_LOG_PROTECT特性,将脏页获取分成了两个ioctl命令字,KVM_GET_DIRTY_LOGKVM_CLEAR_DIRTY_LOG,对应之前的两个步骤,第一个命令字只负责拷贝dirty bitmap,第二个命令只负责清零脏页,用户态获取到dirty bitmap之后,可以知道哪些页是脏的,因此KVM_CLEAR_DIRTY_LOG可以是虚机所有页集合的子集,在修改页表时效率会更高。
  • 下面分析具体代码:
kvm_vm_ioctl
    case KVM_GET_DIRTY_LOG: 
        kvm_vm_ioctl_get_dirty_log
            kvm_get_dirty_log_protect 	
                slots = __kvm_memslots(kvm, as_id);
                memslot = id_to_memslot(slots, id);
                /* x86架构使用PML机制获取脏页 */
                kvm_arch_sync_dirty_log
                    kvm_x86_ops.flush_log_dirty <=>   vmx_flush_log_dirty
                        /* kick每个vcpu让其vmexit,这样在vmexit的路径上可以更新pml buffer */
                        kvm_flush_pml_buffers
                            kvm_vcpu_kick
                /* dirty bitmap获取到之后,如果使能了KVM_CAP_MANUAL_DIRTY_LOG_PROTECT
                 * 特性,则跳过清零脏页的步骤,直接拷贝dirty bitmap */
              	if (kvm->manual_dirty_log_protect) {
              	    dirty_bitmap_buffer = dirty_bitmap;
              	} else {
              		/* 获取mmu_lock锁,修改页表,将对应位清零 */
					spin_lock(&kvm->mmu_lock);
						kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot,
													offset, mask);

					spin_unlock(&kvm->mmu_lock);
				}
                kvm_arch_flush_remote_tlbs_memslot
                /* 拷贝dirty bitmap到用户态 */
                copy_to_user(log->dirty_bitmap, dirty_bitmap_buffer, n)                   
  • 使用PML机制获取dirty bitmap时,只是将所有vcpu kick了一遍,具体的更新操作在vcpu从guest退出的路径上完成,简单分析下:
vmx_handle_exit
	if (enable_pml)
		vmx_flush_pml_buffer(vcpu);
			/* 遍历PML buffer的entry,将其更新到内存页所属的slot的dirty bitmap */
			for (; pml_idx < PML_ENTITY_NUM; pml_idx++) {
				gpa = pml_buf[pml_idx];
				kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
					memslot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
					mark_page_dirty_in_slot(vcpu->kvm, memslot, gfn);
			}
  • 分析一下KVM_CAP_MANUAL_DIRTY_LOG_PROTECT特性下清零脏页的流程:
kvm_vm_ioctl
	case KVM_CLEAR_DIRTY_LOG:
		kvm_vm_ioctl_clear_dirty_log
			kvm_clear_dirty_log_protect
				/* 清零脏页前首先同步之前的脏页信息,使dirty bitmap处于最新状态 */
				kvm_arch_sync_dirty_log
				/* 将最新的脏页信息拷贝到用户态 */
				copy_from_user(dirty_bitmap_buffer, log->dirty_bitmap, n)
				/* 拿mmu_lock锁,准备清零脏页,也就是使能脏页日志 */
				spin_lock(&kvm->mmu_lock)
					kvm_arch_mmu_enable_log_dirty_pt_masked
				spin_unlock(&kvm->mmu_lock)

实验

  • 下面两个commit是基于dirty-bitmap机制脏页同步计算脏页速率的commit:
    https://github.com/qemu/qemu/commit/4998a37e4bf2bc47f76775e6e6a0cd50bacfb16a
    https://github.com/qemu/qemu/commit/826b8bc80cb191557a4ce7cf0e155b436d2d1afa
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

KVM同步脏页原理 的相关文章

  • Linux(ubuntu)上安装RDP Server(Xrdp)使用的注意事项

    ubuntu上的基本安装方法 1 apt get install xrdp 基本上就已经安装完成了 但是此时连接会出现异常 类似黑屏的情况 原因 1 Xrdp不支持unity 3D的图形 解决方法 1 使用xfce或者gnome 2d等 如
  • kvm虚拟机读取宿主机usb设备

    1 查看usb设备 用lsusb查看宿主机usb设备信息 2 在kvm虚拟机的xml文件中添加如下
  • KVM添加文件夹存储

    创建基于文件夹的存储池 1 定义一个存储池 virsh pool define as kvm images dir kvm images 2 查看创建的存储池信息 virsh pool list all 3 建立基于文件夹的存储池 virs
  • NVIDIA vGPU License服务器安装过程

    在vGPU场景下 NVIDIA vGPU License Server 是一个很重要的组件 一个vGPU虚拟机没有正常获取License的时候 功能会受到很大限制 因此正式生产环境或者POC测试环境中都建议搭建 在之前的文章介绍过VMwar
  • KVM MMU EPT内存管理

    转载请注明 转载自博客xelatex KVM 并附本文链接 谢谢 注 文章中采用的版本 Linux 3 11 https www kernel org pub linux kernel v3 x linux 3 11 tar gz qemu
  • ESXi6.5中将虚拟机从厚置备转换为精简置备

    用ESXi做虚拟化 创建了一个原始虚拟机并安装好系统做好基本设置 使用ESXi的web界面复制虚拟机 结果后来发现复制出来的都是厚置备 导致占用大量空间 网上找到一篇教程 但不够清晰 遂有此文 首先要通过ssh连接虚拟机 0 删除需要转换磁
  • kvm CPU绑定与查询

    cpu绑定 格式 virsh vcpupin domain name vcpu hostcpu config live 例如 virsh vcpupin 16 3 15 config live 说明 将kvm虚拟机第4个vcpu与宿主机第1
  • 云管平台 — vRealize Suite

    原文地址 https blogs vmware com china 2017 11 08 E4 BA 91 E7 AE A1 E5 B9 B3 E5 8F B0 vrealize suite vRealize Suite 是 vRealiz
  • 60 KVM Skylark虚拟机混部-安装和配置

    文章目录 60 KVM Skylark虚拟机混部 安装和配置 60 1 安装Skylark 60 1 1 硬件要求 60 1 2 软件要求 60 1 3 安装方法 60 2 配置Skylark 60 2 1 日志 60 2 2 功耗干扰控制
  • Windows Server 2019 会话远程桌面-快速部署(RemoteApp)

    目录 一 实验要求 二 搭建远程桌面服务RDS 三 需要软件安装 1 安装Firefox 浏览器 2 安装一款视频播放器 3 安装WPS office 套件 四 发布应用 1 发布Firefox 浏览器 2 发布一款视频播放器 3 发布WP
  • 内核虚拟化KVM/QEMU——guest os,qemu,kvm的运行流程

    内核虚拟化KVM QEMU guest os qemu kvm的运行流程 这里主要介绍基于x86平台的Guest Os Qemu Kvm工作流程 如图 通过KVM APIs可以将qemu的command传递到kvm 1 创建VM syste
  • kvm之多网卡队列开启设置

    背景 目前基于dpdk数据平面开发套件的应用越来越多 而dpdk对于上层应用运行时 服务的进程数多于1时 要求网卡支持多队列 否则项nginx这种多进程应用程序只能再默认配置下运行 只能启动一个worker 要求 在kvm虚机中将网卡设置支
  • KVM源代码分析1:基本工作原理

    http www oenhan com kvm src 1 13年的时候准备挖 KVM源代码分析 的坑 陆陆续续2年过去了 坑也没有填上 当时是因为对KVM了解的肤浅 真正的理解必然要深入到代码级别 所谓 摈弃皮毛 看到血肉 看到真相 当时
  • Qemu-KVM基本工作原理分析

    1 理解KVM与Qemu的关系 我们都知道开源虚拟机KVM 并且知道它总是跟Qemu结合出现 那这两者之间有什么关系呢 首先 Qemu本身并不是KVM的一部分 而是一整套完整的虚拟化解决方案 它是纯软件实现的 包括处理器虚拟化 内存虚拟化以
  • 陷阱标志(TF)和监视器陷阱标志之间的区别?

    像 GDB 这样的调试功能通过设置 eflags 寄存器的 TF 标志来工作 这会在处理器每次执行指令后引发异常 让 gdb 等工具控制调试 当我们运行虚拟机 Ex 时 在 kvm 的情况下执行以下操作同样 您需要设置一个名为 MONITO
  • x86 PIC,QEMU 在所有 CPU 上引发中断是否正确?

    我最近不得不解决 x86 PIC 的专有操作系统问题 其中操作系统预期定时器中断仅在 CPU0 上 我启用了 IO APIC 来解决这个问题并进行了 CPU 控制 因此中断仅到达 CPU0 问题解决了 有人告诉我 我们的硬件已经损坏 无法做
  • Android Studio:/dev/kvm 设备权限被拒绝

    当我尝试在模拟器上运行 Android 应用程序时 出现以下错误 dev kvm 权限被拒绝 我检查了权限并将当前登录的用户添加到 kvm 组中 怎么了 正如评论中提到的 从乌班图18 04 and Linux 薄荷塔拉你需要先sudo a
  • Android模拟器和virtualbox不能同时运行

    每当我运行 Virtualbox 时 我都无法启动 Android 模拟器映像 反之亦然 AVD管理器中的错误消息是 ioctl KVM CREATE VM failed Device or resource busy ko failed
  • QEMU和KVM在虚拟机I/O中扮演什么角色?

    我发现 QEMU 和 KVM 之间的界限非常模糊 我发现有人说虚拟机是qemu进程 而另一些人说是kvm进程 究竟是什么 而QEMU和KVM在虚拟机I O中扮演什么角色呢 比如一个vm做PIO MMIO的时候 是qemu还是kvm会把它困住
  • x86 平台中的 KVM 影子页表处理

    据我了解 在没有硬件支持来宾虚拟到主机物理地址转换的处理器上 KVM 使用影子页表 当来宾操作系统修改其页表时 会构建和更新影子页表 硬件中有没有专门的指令 以x86为参考 来修改页表 除非有特殊说明 否则不会对VMM 造成陷阱 Linux

随机推荐

  • breach靶场练习详细全过程

    补充 桥接 nat host only三种网络模式的区别 模式 特点 场景 bridge桥接模式 特点 虚拟机使用物理机的网卡 不用虚拟网卡 占用一个ip 需要配置ip以后才可以访问互联网 场景 虚拟机需要连接实体设备的时候 nat网络地址
  • 最好用的 6 个 React Tree select 树形组件测评与推荐

    本文完整版 最好用的 6 个 React Tree select 树形组件测评与推荐 React Tree select 树形组件 1 React Sortable Tree 全功能 树状单选多选 可拖拽 过滤搜索 多种主题可选 2 Rea
  • android开发浏览器!写给1-3年安卓程序员的几点建议,聪明人已经收藏了!

    前言 作为一个程序员 如果你在新知识 新技术面前仍一无所知 依然吃着十多年前的老本 那你在知识技术上肯定落伍 如果又未能进入管理层面 那你肯定就会被长江的后浪拍在沙滩上了 而不少与时俱进 善于学习的程序员他们仍是行业的中坚力量 这只是说明当
  • 面试利器(二)-------插入排序(直接插入排序和希尔排序(Shell排序))

    一 直接插入排序 抓住关键字 插入 1 基本思想 顺序地把待排序的序列中的各个数据按其关键字的大小 插入到已排序的序列的适当位置 2 运行过程 1 将待排序序列的第一个数据看做一个有序序列 把第二个数据到最后一个数据当成是未排序序列 2 从
  • openblas第一弹:openblas 使用说明和常用接口介绍

    openblas 使用说明 openblas 是一个开源的矩阵计算库 包含了诸多的精度和形式的矩阵计算算法 就精度而言 包括float和double 两种数据类型的数据 其矩阵调用函数也是不一样 不同矩阵 其计算方式也是有所不同 姑且认为向
  • C++设计模式 - 组合模式(Composite)

    数据结构模式 常常有一 些组件在内部具有特定的数据结构 如果让客户程序依赖这些特定的数据结构 将极大地破坏组件的复用 这时候 将这些特定数据结构封装在内部 在外部提供统一的接口 来实现与特定数据结构无关的访问 是一种行之有效的解决方案 典型
  • 遗传算法基本介绍

    1 主要解决什么问题 是一种仿生全局优化算法 2 原理 思路是什么 选择 优胜劣汰 交叉 变异 一些重要概念 生物遗传概念在遗传算法中的对应关系 编码策略 常用的遗传算法编码方法主要有 二进制编码 浮点数编码等 可以证明 二进制编码比浮点数
  • 在html中加入网址,网页超链接怎么做,添加超链接网址的的详细步骤

    此系列教程主要讲解HTML从基础到精通 自己能够设计一个完整的前端网页项目 程序员写代码 在HTML中添加图片其实很简单 就是添加一个img的标签 图片标签的语法 一般有src alt width height四种属性就够用了 效果 图片的
  • 智能音箱借ChatGPT重获“新生”?

    曾经靠语音助手红极一时的智能音箱 近年来的市场表现却欠佳 据洛图科技发布的最新 中国智能音箱零售市场月度追踪 报告显示 2022年中国智能音箱总销量为2631万台 同比下降28 市场销售额为75 3亿元 同比下降25 而IDC发布的2023
  • 华为OD机试 - 太阳能板最大面积(Java)

    题目描述 给航天器一侧加装长方形或正方形的太阳能板 图中的红色斜线区域 需要先安装两个支柱 图中的黑色竖条 再在支柱的中间部分固定太阳能板 但航天器不同位置的支柱长度不同 太阳能板的安装面积受限于最短一侧的那根支柱长度 如图 现提供一组整形
  • 计算机中的打印机,如何添加打印机,教您电脑如何添加打印机

    打印机是我们工作中不可缺少的办公设备 那如果电脑上没安装打印机 可以进行打印吗 我们可以通过连接到同一网络上的打印机进行打印作业 那电脑怎样进行添加打印机呢 下面 小编给大家带来了电脑添加打印机的图文 打印机是现在我们办公设备的必要用品之一
  • 如何定位Release 版本中程序崩溃的位置 ---利用map文件 拦截windows崩溃函数

    1 案例描述 作为Windows程序员 平时最担心见到的事情可能就是程序发生了崩溃 异常 这时Windows会提示该程序执行了非法操作 即将关闭 请与您的供应商联系 呵呵 这句微软的 名言 恐怕是程序员最怕见也最常见的东西了 在一个大型软件
  • spring boot集成mybatis无法扫描mapper文件(坑)

    大半天耗在这上面 真的无语了 现象解决了 原因待查找 首先 如果你的spring boot集成mybatis项目报这个错 同时你使用的是YML的配置方式 再同时你用的是Intellij 那么就往下看吧 解决方法就是 使用这种配置方式 命名为
  • 马虎的算式

    标题 马虎的算式 小明是个急性子 上小学的时候经常把老师写在黑板上的题目抄错了 有一次 老师出的题目是 36 x 495 他却给抄成了 396 x 45 但结果却很戏剧性 他的答案竟然是对的 因为 36 495 396 45 17820 类
  • 刷题之反转字符串

    编写一个函数 其作用是将输入的字符串反转过来 输入字符串以字符数组 s 的形式给出 不要给另外的数组分配额外的空间 你必须原地修改输入数组 使用 O 1 的额外空间解决这一问题 示例 1 输入 s h e l l o 输出 o l l e
  • LAST_INSERT_ID使用造成订单串单问题

    订单串单问题 代码 String sql insert into this update sql List
  • 用动态数组实现了顺序表

    用动态数组实现了顺序表 作者 吕翔宇 e mail 630056108 qq com ALL RIGHTS RESERVED 版权所有 include
  • Spring Boot定时任务在分布式环境下的轻量级解决方案

    文章非原创 转载简书 原作者 foundwei 转载链接 https www jianshu com p 41970ba48453 Spring Boot提供了一个叫做Spring Task的任务调度工具 支持注解和配置文件形式 支持Cro
  • CGAL计算几何算法库安装和使用(一)

    CGAL是使用C 开发的计算几何算法库 提供Delaunay三角网 网格生成 多边形 以及各种几何处理算法 应用领域 计算机图形学 科学可视化 计算机辅助设计与建模 地理信息系统 分子生物学 医学影像学 机器人学和运动规划 和数值方法 1
  • KVM同步脏页原理

    文章目录 硬件基础 SPTE 硬件要素 工作流程 PML 硬件要素 工作流程 数据结构 用户态 内核态 API 脏页开启 脏页获取 流程 使能记录 记录脏页 流程图 具体过程 获取脏页 流程图 具体过程 实验 QEMU在内存迁移阶段首先会标