kvm源码安装 linux_linux kvm源码 - CSDN
  • 1、首先下载KVM源码:http://www.linux-kvm.org/page/Downloads 或者 http://sourceforge.net/projects/kvm/files/  选择最新版本 2、进入KVM官方网站查看安装教程:http://www.linux-kvm.org/page/HOWTO1 3...

    1、首先下载KVM源码:http://www.linux-kvm.org/page/Downloads  或者http://sourceforge.net/projects/kvm/files/   选择最新版本


    2、进入KVM官方网站查看安装教程:http://www.linux-kvm.org/page/HOWTO1


    3、安装函数依赖库

    On a debian etch system you can install the prerequisites with:(Ubuntu系统适用命令:)

     apt-get install gcc libsdl1.2-dev zlib1g-dev libasound2-dev linux-kernel-headers pkg-config libgnutls-dev libpci-dev
    

    Note: When building from git, you also need gawk. (如果你是从git 上获取源码,那么还得需要gawk)


    4、解压编译/安装

    If you are using a recent kernel (2.6.25+) with kvm modules included, boot into it, and:(如果你是用的linux内核版本大于2.6.25,就按照下面的方法做)

    tar xzf qemu-kvm-release.tar.gz
    cd qemu-kvm-release
    ./configure --prefix=/usr/local/kvm
    make
    sudo make install
    sudo /sbin/modprobe kvm-intel   (适用于intel显卡)
    # or: sudo /sbin/modprobe kvm-amd (适用于amd显卡)
     

    If you're using an older kernel, or a kernel from your distribution without the kvm modules, you'll have to compile the modules yourself:(如果linux内核低于2.6,那么你要自己编译)

    tar xjf kvm-kmod-release.tar.bz2
    cd kvm-kmod-release 
    ./configure
    make 
    sudo make install 
    sudo /sbin/modprobe kvm-intel 
    # or: sudo /sbin/modprobe kvm-amd
    
    此处可能会出现一些问题,当执行sudo /sbin/modprobe kvm-intel 时候,可能会出现错误,检测是否执行成功
    的方法:lsmod |grep kvm 如果出现两行信息,那就说明安装无误,如果只有一行 
    kvm          51032  0
    那就说明没成功。解决方法如下:
    1/首先查看你的CPU 是否支持虚拟化。不同型号CPU应该到其官方网站查看是否支持。
    
    如果CPU不支持会提示
    kvm: no hardware support 
    2/如果支持虚拟化,那就是CPU虚拟化被关闭了,打开方式是在BIOS 设置里面,进入BIOS,找到CPU 参数那一项,
    将CPU虚拟化开启即可。
    
    dmesg |grep kvm
    
    输出类似:
    
    [ 4790.548000] kvm: disabled by bios
    说明已关闭。
     
    3/如果以上还没解决的话,那就只能说明你前期安装有问题。

    Note: if sound doesn't play in the guest vm you can add --audio-drv-list="alsa oss" to ./configure as explained inhttp://www.linux-kvm.com/content/sound-problem-solved


    以上是QEMU 管理工具,属于字符界面的操作。如果你对字符界面 不是很感兴趣,那么还可以安装图形界面的管理工具。以下为参考链接

    参考链接:http://www.linuxidc.com/Linux/2012-12/76324.htm     经测试此种方法成功安装!!

    展开全文
  • 13年的时候准备挖“KVM源代码分析”的坑,陆陆续续2年过去了,坑也没有填上,当时是因为对KVM了解的肤浅,真正的理解必然要深入到代码级别,所谓“摈弃皮毛,看到血肉,看到真相”,当时计划写KVM基本工作原理、...

    http://www.oenhan.com/kvm-src-1

    13年的时候准备挖“KVM源代码分析”的坑,陆陆续续2年过去了,坑也没有填上,当时是因为对KVM了解的肤浅,真正的理解必然要深入到代码级别,所谓“摈弃皮毛,看到血肉,看到真相”,当时计划写KVM基本工作原理、虚拟机的创建VCPU调度原理KVM内存管理、KVM设备管理等,实际发现代码过程还是很多,估计后续会针对于不同的点专门来写。

    需要假定读者有一定的内核基础,和虚拟化基础,原理性的东西估计会一笔带过,我在知乎上写过一些基础入门的书籍:1.首先有OS基础,随便操作系统大学课本;2.对Linux kernel有全面了解,关键模块有理解,推荐书籍:深入Linux内核架构(+1)或者深入理解LINUX内核;3.Hypervisor虚拟化,Intel的《系统虚拟化-原理与实现》,赶时间的建议先把第3步完成。

    进入正题:

    1.KVM模型结构

    为什么有OS虚拟化?随着CPU计算能力的提高,单独的OS已不能充分利用CPU的计算能力,1.很多应用的执行需要单独占用一个OS环境,如安全测试等;2.而IAAS云计算厂商也是以OS为范围销售计算能力。那么在所有虚拟化方案中,都是由hypervisor取代原生的OS去控制具体硬件资源,而同时hypervisor将资源分配具体的VM,VM中运行的是没有修改过的OS,如果让VM中的OS能正常运行,hypervisor的任务就是模拟具体的硬件资源,让OS不能识别出是真是假。

    hypervisor-oenhan

    当然上面的模型是Xen示例,OS对应用而言是硬件资源管理中心,那么hypervisor就是具体VM的OS了,KVM是就利用了这一点,利用现有的kernel代码,构建了一个hypervisor,这个样子内存分配进程调度等就无需重写代码,如此hypervisor就是所谓的host,VM中的OS就是guest。

    guest OS保证具体运行场景中的程序正常执行,而KVM的代码则部署在HOST上,Userspace对应的是QEMU,Kernel对应的是KVM Driver,KVM Driver负责模拟虚拟机的CPU运行,内存管理,设备管理等;QEMU则模拟虚拟机的IO设备接口以及用户态控制接口。QEMU通过KVM等fd进行IOCTL控制KVM驱动的运行过程。

    kvm_arch_map_oenhan

    如上图所示,guest自身有自己的用户模式和内核模式;guest是在host中是作为一个用户态进程存在的,这个进程就是qemu,qemu本身就是一个虚拟化程序,只是纯软件虚拟化效率很低,它被KVM进行改造后,作为KVM的前端存在,用来进行创建进程或者IO交互等;而KVM Driver则是Linux内核模式,它提供KVM fd给qemu调用,用来进行cpu虚拟化,内存虚拟化等。QEMU通KVM提供的fd接口,通过ioctl系统调用创建和运行虚拟机。KVM Driver使得整个Linux成为一个虚拟机监控器,负责接收qemu模拟效率很低的命令。

    2.KVM工作原理

    kvm_process

    上图是一个执行过程图,首先启动一个虚拟化管理软件qemu,开始启动一个虚拟机,通过ioctl等系统调用向内核中申请指定的资源,搭建好虚拟环境,启动虚拟机内的OS,执行 VMLAUCH 指令,即进入了guest代码执行过程。如果 Guest OS 发生外部中断或者影子页表缺页之类的事件,暂停 Guest OS 的执行,退出QEMU即guest VM-exit,进行一些必要的处理,然后重新进入客户模式,执行guest代码;这个时候如果是io请求,则提交给用户态下的qemu处理,qemu处理后再次通过IOCTL反馈给KVM驱动。

    3.CPU虚拟化

    X86体系结构CPU虚拟化技术的称为 Intel VT-x 技术,引入了VMX,提供了两种处理器的工作环境。 VMCS 结构实现两种环境之间的切换。 VM Entry 使虚拟机进去guest模式,VM Exit 使虚拟机退出guest模式。

    VMM调度guest执行时,qemu 通过 ioctl 系统调用进入内核模式,在 KVM Driver中获得当前物理 CPU的引用。之后将guest状态从VMCS中读出, 并装入物理CPU中。执行 VMLAUCH 指令使得物理处理器进入非根操作环境,运行guest OS代码。

    当 guest OS 执行一些特权指令或者外部事件时, 比如I/O访问,对控制寄存器的操作,MSR的读写等, 都会导致物理CPU发生 VMExit, 停止运行 Guest OS,将 Guest OS保存到VMCS中, Host 状态装入物理处理器中, 处理器进入根操作环境,KVM取得控制权,通过读取 VMCS 中 VM_EXIT_REASON 字段得到引起 VM Exit 的原因。 从而调用kvm_exit_handler 处理函数。 如果由于 I/O 获得信号到达,则退出到userspace模式的 Qemu 处理。处理完毕后,重新进入guest模式运行虚拟 CPU。

    4.Mem虚拟化

    OS对于物理内存主要有两点认识:1.物理地址从0开始;2.内存地址是连续的。VMM接管了所有内存,但guest OS的对内存的使用就存在这两点冲突了,除此之外,一个guest对内存的操作很有可能影响到另外一个guest乃至host的运行。VMM的内存虚拟化就要解决这些问题。

    在OS代码中,应用也是占用所有的逻辑地址,同时不影响其他应用的关键点在于有线性地址这个中间层;解决方法则是添加了一个中间层:guest物理地址空间;guest看到是从0开始的guest物理地址空间(类比从0开始的线性地址),而且是连续的,虽然有些地址没有映射;同时guest物理地址映射到不同的host逻辑地址,如此保证了VM之间的安全性要求。

    这样MEM虚拟化就是GVA->GPA->HPA的寻址过程,传统软件方法有影子页表,硬件虚拟化提供了EPT支持。

    总体描述到此,后面代码里面见真相。

    展开全文
  • kvm模块,kvm在加载之初,只存在/dev/kvm文件。 针对虚拟处理器最重要的IOCTL调用。 内存虚拟化也是KVM模块实现,并且是一个虚拟机中代码量最大,实现最复杂的部分。 处理器中的MMU通过页表形式将程序运行的虚拟地址...

    概述

    kvm模块,kvm在加载之初,只存在/dev/kvm文件。
    针对虚拟处理器最重要的IOCTL调用。
    内存虚拟化也是KVM模块实现,并且是一个虚拟机中代码量最大,实现最复杂的部分。
    处理器中的MMU通过页表形式将程序运行的虚拟地址转换成物理地址,在虚拟机模式下,内存管理单元的页表必须在一次查询完成两次转换,KVM     模块使用了影子页表技术解决该问题。

    官网代码:

    kvm核心代码:

    下载:git clone  git://git.kernel.org/pub/scm/virt/kvm/kvm.git
    分为三部分:KVM框架的核心源代码,与硬件架构相关的代码,kvm头文件。

    kvm代码的核心代码:
    virt/kvm/中的代码,是与架构无关的代码,有7309行,kvm_main.c是代码中最核心的文件之一,其中的kvm_init()函数是与硬件无关的kvm初始化入口。

    与硬件结构相关的代码:
    位于  arch/*/kvm目录下。[root@localhost kvm]# ls -d arch/*/kvm
    arch/arm64/kvm  arch/mips/kvm     arch/s390/kvm  arch/x86/kvm
    arch/arm/kvm    arch/powerpc/kvm  arch/tile/kvm
    在kvm支持的架构中,x86架构相关代码位于:arch/x86/kvm/目录下,有37067行代码,
    assigned-dev.c  hyperv.h  iommu.c           lapic.c      mmutrace.h     pmu.h        x86.c
    assigned-dev.h  i8254.c   irq.c             lapic.h      mtrr.c         pmu_intel.c  x86.h
    cpuid.c         i8254.h   irq_comm.c        Makefile     page_track.c   svm.c
    cpuid.h         i8259.c   irq.h             mmu_audit.c  paging_tmpl.h  trace.h
    emulate.c       ioapic.c  Kconfig           mmu.c        pmu_amd.c      tss.h
    hyperv.c        ioapic.h  kvm_cache_regs.h  mmu.h        pmu.c          vmx.c
    vmx.c和svm.c分别是intel和AMD CPU架构相关模块kvm-intel和kvm-amd主要代码,vmx_init()是初始化函数。

    kvm相关头文件:
    目录为:ls -d arch/*/include/asm/kvm*
    arch/arm64/include/asm/kvm_arm.h      arch/powerpc/include/asm/kvm_asm.h
    arch/arm64/include/asm/kvm_asm.h      arch/powerpc/include/asm/kvm_book3s_32.h
    arch/arm64/include/asm/kvm_coproc.h   arch/powerpc/include/asm/kvm_book3s_64.h
    arch/arm64/include/asm/kvm_emulate.h  arch/powerpc/include/asm/kvm_book3s_asm.h
    arch/arm64/include/asm/kvm_host.h     arch/powerpc/include/asm/kvm_book3s.h
    arch/arm64/include/asm/kvm_hyp.h      arch/powerpc/include/asm/kvm_booke.h
    arch/arm64/include/asm/kvm_mmio.h     arch/powerpc/include/asm/kvm_booke_hv_asm.h
    arch/arm64/include/asm/kvm_mmu.h      arch/powerpc/include/asm/kvm_fpu.h
    arch/arm64/include/asm/kvm_psci.h     arch/powerpc/include/asm/kvm_host.h
    arch/arm/include/asm/kvm_arm.h        arch/powerpc/include/asm/kvm_para.h
    arch/arm/include/asm/kvm_asm.h        arch/powerpc/include/asm/kvm_ppc.h
    arch/arm/include/asm/kvm_coproc.h     arch/s390/include/asm/kvm_host.h
    arch/arm/include/asm/kvm_emulate.h    arch/s390/include/asm/kvm_para.h
    arch/arm/include/asm/kvm_host.h       arch/um/include/asm/kvm_para.h
    arch/arm/include/asm/kvm_hyp.h        arch/x86/include/asm/kvm_emulate.h
    arch/arm/include/asm/kvm_mmio.h       arch/x86/include/asm/kvm_guest.h
    arch/arm/include/asm/kvm_mmu.h        arch/x86/include/asm/kvm_host.h
    arch/arm/include/asm/kvm_psci.h       arch/x86/include/asm/kvm_page_track.h
    arch/mips/include/asm/kvm_host.h      arch/x86/include/asm/kvm_para.h
    arch/mips/include/asm/kvm_para.h

    Linux内核代码仓库中还有一些关于kvm的文档,主要位于
    Documentation/virtual/kvm/
    Documentation/*/kvm*

    详细介绍:

    (1.)include\kvm\中有2个文件:代码总共行数:4957

    Arm_arch_timer.h:KVM定时器相关的函数      代码行数:103

    Arm_vgic.h:虚拟通用中断控制器相关的数据结构和函数     代码行数:314


    (2)include\trace\events\kvm.h: 代码行数:322

    一些跟踪事件函数的声明

    其中一段代码:

    #define kvm_trace_exit_reason                                        \

           ERSN(UNKNOWN), ERSN(EXCEPTION), ERSN(IO), ERSN(HYPERCALL),  \

           ERSN(DEBUG), ERSN(HLT), ERSN(MMIO), ERSN(IRQ_WINDOW_OPEN),       \

           ERSN(SHUTDOWN), ERSN(FAIL_ENTRY), ERSN(INTR), ERSN(SET_TPR),       \

           ERSN(TPR_ACCESS), ERSN(S390_SIEIC), ERSN(S390_RESET), ERSN(DCR),\

           ERSN(NMI), ERSN(INTERNAL_ERROR), ERSN(OSI), ERSN(PAPR_HCALL),      \

          ERSN(S390_UCONTROL), ERSN(WATCHDOG), ERSN(S390_TSCH)

    2)include\linux\kvm_host.h:      代码行数:1101

    非常重要的头文件

    /*

     * The bit 16 ~ bit 31 of kvm_memory_region::flags are internally used

     * in kvm, other bits are visible for userspace which are defined in

     * include/linux/kvm_h.

     */

    3)include\linux\kvm_para.h:      代码行数:27

    一个函数:static inline int kvm_para_has_feature(unsigned int feature)

    4)include\linux\kvm_types.h:    代码行数:79

    /*

     * Address types:

    *  gva - guest virtual address

     *  gpa - guest physical address

     *  gfn - guest frame number

     *  hva - host virtual address

     *  hpa - host physical address

     *  hfn - host frame number

     */

     

    5)include\uapi\linux\kvm.h:代码行数:1186

     Userspace interface for /dev/kvm - kernel based virtual machine

    /*The bit 0 ~ bit 15 of kvm_memory_region::flags are visible for userspace,

     * other bits are reserved for kvm internal use which are defined in

     * include/linux/kvm_host.h.*/

    6)include\uapi\linux\kvm_para.h:     代码行数:33

    /*

     * This header file provides a method for making a hypercall to the host

     * Architectures should define:

     * - kvm_hypercall0, kvm_hypercall1...

     * - kvm_arch_para_features

     * - kvm_para_available

     */

     

    /* Return values for hypercalls */

    /*

     * hypercalls use architecture specific

     */

     

    7)include\uapi\asm-generic\kvm_para.h: 代码行数:0

    /*

     * There isn't anything here, but the file must not be empty or(否则) patch

     * will delete it.

     */

    8)include\asm-generic\kvm_para.h: 代码行数:27

    This function is used by architectures that support kvm to avoid issuing false soft lockup messages.

    Uapi可能是user api的意思


    (9)virt\kvm\  与体系结构无关的代码   代码总共行数:10629

    包含一个名为arm的文件夹和15个文件。

     

    assigned-dev.c 代码行数:1027

    功能:Kernel-based Virtual Machine - device assignment support

    async_pf.c和async_pf.h:   代码行数:228

    kvm asynchronous fault support  KVM支持异步故障

    coalesced_mmio.c和coalesced_mmio.h:     代码行数:183+39

    KVM  coalesced(合并) MMIO

    MMIO(Memory mapping I/O)即内存映射I/O,它是PCI规范的一部分,I/O设备被放置在内存空间而不是I/O空间。

    eventfd.c: 代码行数:931

    kvm eventfd support - use eventfd objects to signal various KVM events

    ioapic.c和ioapic.h:       代码行数:646+103

    apic: Advanced Programmable Interrupt Controller高级可编程中断控制器.

    Iodev.h: 对io设备的操作头文件 代码行数:71

    Iommu.c : 代码行数:361

     input/output memory management unit。Device的IOMMU类似于CPU的MMU。

    MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权,多用户多进程操作系统。

    Irq_comm.c:   代码行数:370

    Common API for in kernel interrupt controllers .

    irqchip.c:   代码行数:215

    Common API for in kernel interrupt controllers

    This file is derived from virt/kvm/irq_comm.c.

          IRQ全称为Interrupt Request,即是“中断请求”的意思,IRQ的作用就是在我们所用的电脑中,执行硬件中断请求的动作。

    Kconfig: KVM common configuration items and defaults

    Kvm_main.c:     代码行数:3279

    Kernel-based Virtual Machine driver for Linux.This module enables machines with Intel VT-x extensions to run virtual machines without emulation or binary translation.

    Vfio.c: 代码行数:278

     VFIO-KVM bridge pseudo device

    VFIO是一套用户态驱动框架,它提供两种基本服务:(1)向用户态提供访问硬件设备的接口(2) 向用户态提供配置IOMMU的接口

     

    arm文件夹中包含4个文件。

     arch_timer.c:KVM定时器  代码行数:318

    Vgic:virtual generic interrupt controller,其它3个文件功能就是主要描述它的。V2和v3是第二第三个版本。 代码行数:2070+264+246

    10)\arch\x86\kvm\   与体系结构相关的代码 代码总共行数:39246

    包含25个文件

     

     

    Cupid.c和cpuid.h: 代码行数:795+107

     CPU ID 指用户计算机当今的信息处理器的信息。

     Kernel-based Virtual Machine driver for Linux

        cpuid support routines

    derived from arch/x86/kvm/x86.c

    emulate.c: 代码行数:5068

    Generic x86 (32-bit and 64-bit) instruction decoder and emulator.

          Linux coding style, mod r/m decoder, segment base fixes, real-mode privileged instructions

    I8254.c和i8254.h: 代码行数:778+66

    8253/8254 interval timer emulation,就是定时器仿真。Based on QEMU and Xen.

    I8259.c:     代码行数:665

    8259 interrupt controller emulation,中断控制器仿真。Port from Qemu.

    irq.c:    代码行数:130

    API for in kernel interrupt controller

    irq.h:    代码行数:107

     in kernel interrupt controller related definitions

    Kconfig: KVM configuration;  source "virt/kvm/Kconfig"

    Kvm_cache_regs.h: 代码行数:103

    Lapic.c和Lapic.h:   代码行数:1937+174

    Local APIC virtualization。apic: Advanced Programmable Interrupt Controller高级可编程中断控制器

    Mmu.c和mmu.h: 代码行数:4608 + 182

    Kernel-based Virtual Machine driver for Linux

    * This module enables machines with Intel VT-x extensions to run virtual machines without emulation or binary translation.

    * MMU support

    Mmu_audit.c: Audit code for KVM MMU   代码行数:300

    Mmutrace.h:     代码行数:334

    paging_tmpl.h: 代码行数:993

    Kernel-based Virtual Machine driver for Linux;MMU support;

    pmu.c: 代码行数:573

    Kernel-based Virtual Machine -- Performance Monitoring Unit support, 性能监视单元支持

    svm.c:       代码行数:4424

    Kernel-based Virtual Machine driver for Linux; AMD SVM support;svm:安全虚拟机

    Trace.h:     代码行数:862

    Tss.h:        代码行数:60

    Vmx.c: 代码行数:9132

    Kernel-based Virtual Machine driver for Linux;

    X86.c和x86.h: 代码行数:7676 + 172

     * Kernel-based Virtual Machine driver for Linux

     * derived from drivers/kvm/kvm_main.c


    单元测试代码网址:

    自动化测试源码网址:


    参考链接:http://www.cnblogs.com/hsqdboke/p/4166702.html

    展开全文
  • 前段时间挖了一个坑,KVM源代码分析1:基本工作原理,准备写一下kvm的代码机制,结果一直没时间填土,现在还一下旧账,争取能温故而知新。 基本原理里面提到kvm虚拟化由用户态程序Qemu和内核态驱动kvm配合完成,qemu...

    http://www.oenhan.com/kvm-src-2-vm-run

    前段时间挖了一个坑,KVM源代码分析1:基本工作原理,准备写一下kvm的代码机制,结果一直没时间填土,现在还一下旧账,争取能温故而知新。 基本原理里面提到kvm虚拟化由用户态程序Qemu和内核态驱动kvm配合完成,qemu负责HOST用户态层面进程管理,IO处理等,KVM负责把qemu的部分指令在硬件上直接实现,从虚拟机的创建和运行上看,qemu的代码占了流程上的主要部分。下面的代码主要主要针对与qemu,KVM部分另外开篇再说。

    代码:

    QEMU:git://git.qemu.org/qemu.git v2.4.0

    KVM:https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git v4.2

    QEMU和KVM是通过IOCTL进行配合的,直接抓住这个线看有kvm_ioctl、kvm_vm_ioctl、kvm_vcpu_ioctl、kvm_device_ioctl等,他们还都在一个C文件里面。

    使用kvm_ioctl很少了,直接看调用的代码,有KVM_GET_VCPU_MMAP_SIZE,KVM_CHECK_EXTENSION,KVM_GET_API_VERSION,KVM_CREATE_VM,KVM_GET_SUPPORTED_CPUID等等,需要记住只有KVM_CREATE_VM。

    而调用kvm_vm_ioctl的函数真是海了去了,需要看的是KVM_SET_USER_MEMORY_REGION,KVM_CREATE_VCPU,KVM_CREATE_DEVICE。

    所有寄存器的交换信息都是通过kvm_vcpu_ioctl,需要记住的操作只有,KVM_RUN。

    所有看QEMU和KVM的配合流程如下:

    qemu_create_kvm_vm

    接下来参考上图分析qemu代码流程: 从vl.c代码的main函数开始。 atexit(qemu_run_exit_notifiers)注册了qemu的退出处理函数,后面在具体看qemu_run_exit_notifiers函数。 module_call_init则开始初始化qemu的各个模块,陆陆续续的有以下参数:

    最开始初始化的MODULE_INIT_QOM,QOM是qemu实现的一种模拟设备,具体可以参考http://wiki.qemu.org/Features/QOM,代码下面的不远处就MODULE_INIT_MACHINE的初始化,这两条语句放到一起看,直接说一下module_call_init的机制。 module_call_init实际设计的一个函数链表,ModuleTypeList ,链表关系如下图
    qemu_module_init

    它把相关的函数注册到对应的数组链表上,通过执行init项目完成所有设备的初始化。module_call_init就是执行e->init()完成功能的,而e->init是什么时候通过register_module_init注册到ModuleTypeList上的ModuleEntry,是module_init注册的,而调用module_init的有

    那么执行machine_init则是挂到了MODULE_INIT_MACHINE,type_init则将函数挂载了MODULE_INIT_QOM。那么排查一下是,我们只关注PC的注册,那么就是machine_init(pc_machine_init_##suffix),源自DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn)宏,而DEFINE_I440FX_MACHINE有

    DEFINE_PC_MACHINE注册的函数pc_init_##suffix在DEFINE_I440FX_MACHINE中定义,怎么组合都无关,pc_init1(machine)函数一定要执行,本质就是pc_init1赋值给了mc->init,其他爱看不看吧。
    而module_init的宏是

    它前面的修饰是__attribute__((constructor)),这个导致machine_init或者type_init等会在main()之前就被执行。所有type_init(kvm_type_init)-> kvm_accel_type -> kvm_accel_class_init -> kvm_init依次完成了函数注册,所有说module_call_init(MODULE_INIT_QOM)函数已经完成了kvm_init的执行,所有这样就清楚KVM调用关系了。
    如此就先去看kvm_init函数,前面主要干了一件事,填充KVMState *s结构体,然后通过kvm_ioctl(s, KVM_GET_API_VERSION, 0)判断内核KVM驱动和当前QEMU版本是否兼容,下面则是执行kvm_ioctl(s, KVM_CREATE_VM, type)进行虚拟机的创建活动,创建了KVM虚拟机,获取虚拟机句柄。具体KVM_CREATE_VM在内核态做了什么,ioctl的工作等另外再说,现在假定KVM_CREATE_VM所代表的虚拟机创建成功,下面通过检查kvm_check_extension结果填充KVMState,kvm_arch_init初始化KVMState,其中有IDENTITY_MAP_ADDR,TSS_ADDR,NR_MMU_PAGES等,cpu_register_phys_memory_client注册qemu对内存管理的函数集,kvm_create_irqchip创建kvm中断管理内容,通过kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP)实现,具体内核态的工作内容后面分析。到此kvm_init的工作就完成了,最主要的工作就是创建的虚拟机。

    这样绕了这么大圈,重新回到vl.c上面来,前面刚说了module_call_init(MODULE_INIT_MACHINE)本质就是把pc_init1赋值给了mc->init,然后machine_class = find_default_machine(),如此可以看到machine_class的init函数一定会执行pc_init1。

    下面涉及对OPT入参的解析过程略过不提。 qemu准备模拟的机器的类型从下面语句获得:

    machine_class则是通过入参传入的

    man qemu

    下面有cpu_exec_init_all就是执行了qemu的内存结构体的初始化而已,cpudef_init则提供了VCPU的不同型号的模拟,qemu_set_log设置日志输出,kvm对外的日志是从这里配置的。中间的乱七八糟的就忽略掉即可,然后直接到了machine_class->init(current_machine)函数,其实就是执行了pc_init1。暂且记下来,先看下面的,cpu_synchronize_all_post_init就是内核和qemu数据不一致同步一下。下面的函数没有重要的了,只有vm_start()函数需要记一下,后面会用到。

    现在进入pc_init1函数:

    在pc_init1中重点看两个函数,pc_cpus_init和pc_memory_init,顾名思义,CPU和内存的初始化,中断,vga等函数的初始化先忽略掉,先看这两个。
    pc_cpus_init入参是cpu_model,前面说过这是具体的CPU模型,所有X86的CPU模型都在builtin_x86_defs中定义,取其中一个看看

    你可以cat一个本地的/proc/cpuinfo,builtin_x86_defs定义的就是这些参数。
    然后是for循环中针对每个CPU初始化,即pc_new_cpu,直接进入cpu_x86_create函数,
    主要就是把CPUX86State填充了一下,涉及到CPUID和其他的feature。下面是x86_cpu_realize,即唤醒CPU,重点是qemu_init_vcpu,MCE忽略掉,走到qemu_kvm_start_vcpu,qemu创建VCPU,如下:

    线程创建完成,具体任务支线提,回到主流程上,qemu_init_vcpu执行完成后,下面就是cpu_reset,此处的作用是什么呢?答案是无用,本质是一个空函数,它的主要功能就是CPUClass的reset函数,reset在cpu_class_init里面注册的,注册的是cpu_common_reset,这是一个空函数,没有任何作用。cpu_class_init则是被cpu_type_info即TYPE_CPU使用,而cpu_type_info则由type_init(cpu_register_types)完成,type_init则是前面提到的和machine_init对应的注册关系。根据下句完成工作

    从上面看,pc_cpus_init函数过程已经理顺了,下面看一下,vcpu所在的线程对应的qemu_kvm_cpu_thread_fn中:

    CPU进入执行状态的时候我们看到其他的VCPU包括内存可能还没有初始化,关键是此处有一个开关,qemu_cpu_cond,打开这个开关才能进入到CPU执行状态,谁来打开这个开关,后面再说。先看kvm_init_vcpu,通过kvm_vm_ioctl,KVM_CREATE_VCPU创建VCPU,用KVM_GET_VCPU_MMAP_SIZE获取env->kvm_run对应的内存映射,kvm_arch_init_vcpu则填充对应的kvm_arch内容,具体内核部分,后面单独写。kvm_init_vcpu就是获取了vcpu,将相关内容填充了env。
    qemu_kvm_init_cpu_signals则是将中断组合掩码传递给kvm_set_signal_mask,最终给内核KVM_SET_SIGNAL_MASK。kvm_cpu_exec此时还在阻塞过程中,先挂起来,看内存的初始化
    内存初始化函数是pc_memory_init,memory_region_init_ram传入了高端内存和低端内存的值,memory_region_init负责填充mr,重点在qemu_ram_alloc,即qemu_ram_alloc_from_ptr,首先有RAMBlock,ram_list,那就直接借助find_ram_offset函数一起看一下qemu的内存分布模型。
    qemu_memory_module

    qemu模拟了普通内存分布模型,内存的线性也是分块被使用的,每个块称为RAMBlock,由ram_list统领,RAMBlock.offset则是区块的线性地址,即相对于开始的偏移位,RAMBlock.length(size)则是区块的大小,find_ram_offset则是在线性区间内找到没有使用的一段空间,可以完全容纳新申请的ramblock length大小,代码就是进行了所有区块的遍历,找到满足新申请length的最小区间,把ramblock安插进去即可,返回的offset即是新分配区间的开始地址。
    而RAMBlock的物理则是在RAMBlock.host,由kvm_vmalloc(size)分配真正物理内存,内部qemu_vmalloc使用qemu_memalign页对齐分配内存。后续的都是对RAMBlock的插入等处理。
    从上面看,memory_region_init_ram已经将qemu内存模型和实际的物理内存初始化了。
    vmstate_register_ram_global这个函数则是负责将前面提到的ramlist中的ramblock和memory region的初始地址对应一下,将mr->name填充到ramblock的idstr里面,就是让二者有确定的对应关系,如此mr就有了物理内存使用。
    后面则是subregion的处理,memory_region_init_alias初始化,其中将ram传递给mr->owner确定了隶属关系,memory_region_add_subregion则是大头,memory_region_add_subregion_common前面的判断忽略,QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link)就是插入了链表而已,主要内容在memory_region_transaction_commit。
    memory_region_transaction_commit中引入了新的结构address_spaces(AS),注释里面提到“AddressSpace: describes a mapping of addresses to #MemoryRegion objects”,就是内存地址的映射关系,因为内存有不同的应用类型,address_spaces以链表形式存在,commit函数则是对所有AS执行address_space_update_topology,先看AS在哪里注册的,就是前面提到的kvm_init里面,执行memory_listener_register,注册了address_space_memory和address_space_io两个,涉及的另外一个结构体则是MemoryListener,有kvm_memory_listener和kvm_io_listener,就是用于监控内存映射关系发生变化之后执行回调函数。
    下面进入到address_space_update_topology函数,FlatView则是“Flattened global view of current active memory hierarchy”,address_space_get_flatview直接获取当前的,generate_memory_topology则根据前面已经变化的mr重新生成FlatView,然后通过address_space_update_topology_pass比较,简单说address_space_update_topology_pass就是两个FlatView逐条的FlatRange进行对比,以后一个FlatView为准,如果前面FlatView的FlatRange和后面的不一样,则对前面的FlatView的这条FlatRange进行处理,差别就是3种情况,如代码:

    重点在MEMORY_LISTENER_UPDATE_REGION函数上,将变化的FlatRange构造一个MemoryRegionSection,然后遍历所有的memory_listeners,如果memory_listeners监控的内存区域和MemoryRegionSection一样,则执行第四个入参函数,如region_del函数,即kvm_region_del函数,这个是在kvm_init中初始化的。kvm_region_del主要是kvm_set_phys_mem函数,主要是将MemoryRegionSection有效值转换成KVMSlot形式,在kvm_set_user_memory_region中使用kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem)传递给kernel。
    我们看内存初始化真正需要做的是什么?就是qemu申请内存,把申请物理地址传递给kernel进行映射,那我们直接就可以KVMSlot申请内存,然后传递给kvm_vm_ioctl,这样也是OK的,之所以有这么多代码,因为qemu本身是一个软件虚拟机,mr涉及的地址已经是vm的地址,对于KVM是多余的,只是方便函数复用而已。
    内存初始化之后还是pci等处理先跳过,如此pc_init就完成了,但是前面VM线程已经初始化成功,在qemu_kvm_cpu_thread_fn函数中等待运行:

    判断条件就是cpu_can_run函数,即cpu->stop && cpu->stopped && current_run_state != running 都是false,而这几个参数都是由vm_start函数决定的

    如此kvm_cpu_exec就真正进入执行阶段,即通过kvm_vcpu_ioctl传递KVM_RUN给内核。

    KVM源代码分析3:CPU虚拟化

    —结束—

    展开全文
  • linux编译安装kvm、qemu

    2016-11-29 18:51:54
    所以要安装使用kvm,一般需要安装kvm-kmod以及qemu两部分。  安装kvm-kmod:  (1)首先下载kvm-kmod源码并解压。  (2)进入源码目录。  (3)./configure--kerneldir=/lib/modules/2.6.38.8/source //注意该...
  • Linux_KVM虚拟化源代码分析文档
  • 1 先卸载系统的qemu-kvm# yum –y remove qemu-kvm#yum -y remove qemu-img#yum -y remove qemu-guest-agent2 安装依赖包#yum -y install gcc gcc-c++ automake libtool zlib-devel glib2-devel bzip...
  • Linux 虚拟机之--KVM安装和配置(一) 系统环境:  操作系统: RedHat EL6.4(x86_64) 一、前言  KVM,即Kernel-based Virtual Machine的简称,是一个开源的系统虚拟化模块,自Linux 2.6.20之后集成在...
  • KVM源代码框架

    2019-02-22 16:00:12
    KVM源代码框架 自己通过看代码总结的内核中包含kvm的文件夹: (1)Linux-3.17.4\Documentation\virtual\kvm\ (2)Linux-3.17.4\include\ (3)Linux-3.17.4\drivers\s390\kvm\ (4)Linux-3.17.4\virt\kvm\ ...
  • RedHat Linux KVM安装配置

    2019-05-04 00:42:28
    一、前言 KVM,即Kernel-based Virtual Machine的简称...它使用Linux自身的调度器进行管理,所以相对于Xen,其核心源码很少。KVM目前已成为学 术界的主流VMM之一。KVM的虚拟化需要硬件支持(如Intel VT技术或者AMD ...
  • 在centos7下已经集成了kvm 环境:centos7 检查/dev/kvm这个文件,它是kvm内核模块提供给用户空间的qemu-kvm程序使用的一个控制接口,它提供了客户机(Guest)操作系统运行...源码安装qemu-kvm 除了在内核空间的KVM
  • kvm 源码安装

    2013-09-03 18:39:22
    必须安装CentOS 64位,才可以安装KVM虚拟机。32位系统的内核默认没有把KVM模块编译进去,而且源中也没有与虚拟化相关的软件包,如Qemu等。 安装基本系统和开发工具 编译内核 mkdir /root/kvm cd /root/kvm ...
  • Linux运维--KVM 搭建及简单使用一、简介:虚拟化技术之KVM二、安装前的准备三、KVM 安装过程1. 安装qemu-kvm 与 libvirt2. 安装 virt-install3. 启动libvirtd 服务并加入开机启动项,默认情况下,通过ifconfig 命令...
  • KVM和QEMU安装

    2018-08-13 10:08:49
     KVM虚拟机是基于linux内核虚拟化,自linux2.6.20之后就集成在linux的各个主要发行版本中。它使用linux自身的调度器进行管理,所以相对于xen,其核心源码很少。KVM的虚拟化需要硬件的支持(如intel VT技术或者AMD V...
  • KVM安装配置指南

    2018-07-18 11:00:13
    1. KVM介绍 KVM 是基于虚拟化扩展(Intel VT 或者 AMD-V)的 X86 硬件的开源的 Linux 原生的全虚拟化解决方案。KVM 中,虚拟机被实现为常规的 Linux 进程,由标准 Linux 调度程序进行调度;虚机的每个虚拟 CPU 被...
  • 本文将会介绍如何利用spice、qemu-kvm以及libvird源码编译并进行虚机...那么今天就会带大家一起熟悉以下利用常见的qemu-kvm源码创建虚机的过程,源码的好处之一自然就是可以修改优化。下面进入正题。。。 环境准备...
  • 这里写自定义目录标题一.KVM简介二.KVM虚拟化平台构建功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、...
  • Linux KVM 虚拟化技术

    2018-09-21 18:56:32
    KVM 全称是 基于内核的虚拟机(Kernel-based Virtual Machine),它是Linux 的一个内核模块,该内核模块使得 Linux 变成了一个 Hypervisor:  ① 、它由 Quramnet 开发,该公司于 2008年被 Red Hat 收购。  ②、它...
  • 准备:linux系统版本:CentOS-7-x86_64-DVD-1708 (其他系统也可以,内核版本对应就行) 内核版本3.10.0-693.el7.x86_64 1、官网获取相应版本的内核源码,链接:http://vault.centos.org/。例如CentOS-7-x86_64-...
  • KVM源代码分析

    2016-08-01 16:44:43
    1.KVM模型结构 为什么有OS虚拟化?随着CPU计算能力的提高,单独的OS已不能充分利用CPU的计算能力,1.很多应用的执行需要单独占用一个OS环境,如安全测试等;2.而IAAS云计算厂商也是以OS为范围销售计算能力。那么在...
1 2 3 4 5 ... 20
收藏数 8,284
精华内容 3,313
关键字:

kvm源码安装 linux