# hypervisor技术讨论会 会议纪要


## 时间


2023.03.24 14:00—17:00


## 人员


advisor: cdg, ck, cy, ld

student: cxy, dsf, jyk, lj, lky, mc, wwt, yjy, zyh


## 内容


**1)zyh:RVM1.5系统代码结构讲解**


RVM1.5的地址空间包括hvheader、每个vcpu的数据和栈空间、cell的地址空间。src目录下的head.rs文件、percpu.rs文件和cell.rs文件分别声明了hvheader、每个vcpu和cell的成员变量和接口的函数;memory目录下的paging.rs文件声明了扩展四级页表的结构体与接口的函数,并使用加锁的方式避免数据冲突。


**2)cxy:jailhouse config analysis**


关于config具体的定义可以参考include/jailhouse/cell-config.h头文件


jailhouse的配置文件以c文件的形式存在,在config文件夹下存在大量已经定义的文件,包括imx8wq.c,我们以此为例来解释config内容


**header**


    .signature = JAILHOUSE_SYSTEM_SIGNATURE,

    .revision = JAILHOUSE_CONFIG_REVISION,

    .architecture = JAILHOUSE_ARM64,


 定义一些版本信息


    .flags = JAILHOUSE_SYS_VIRTUAL_DEBUG_CONSOLE,


JAILHOUSE_SYS_VIRTUAL_DEBUG_CONSOLE允许根单元读virtual console


**hypervisor_memory**


    .hypervisor_memory = {

        .phys_start = 0xfdc00000,

        .size =       0x00400000,

    },


预留的hypervisor地址空间


**debug_console**


    .debug_console = {

        .address = 0x30860000,

        .size = 0x1000,

        .type = JAILHOUSE_CON_TYPE_IMX,

        .flags = JAILHOUSE_CON_ACCESS_MMIO |

        JAILHOUSE_CON_REGDIST_4,

    },


定义了debug console,包括其地址大小类型,其中类型和flag定义如下


    /* Those definitions are used for the type in struct jailhouse_console */

    #define JAILHOUSE_CON_TYPE_NONE 0x0000

    #define JAILHOUSE_CON_TYPE_EFIFB 0x0001

    #define JAILHOUSE_CON_TYPE_8250 0x0002

    #define JAILHOUSE_CON_TYPE_PL011 0x0003

    #define JAILHOUSE_CON_TYPE_XUARTPS 0x0004

    #define JAILHOUSE_CON_TYPE_MVEBU 0x0005

    #define JAILHOUSE_CON_TYPE_HSCIF 0x0006

    #define JAILHOUSE_CON_TYPE_SCIFA 0x0007

    #define JAILHOUSE_CON_TYPE_IMX 0x0008

    #define JAILHOUSE_CON_TYPE_IMX_LPUART 0x0009

    #define JAILHOUSE_CON_TYPE_SCIF 0x000a


flag用于定义访问方式和访问位宽


    /* Flags: bit 0 is used to select PIO (cleared) or MMIO (set) access */

    #define JAILHOUSE_CON_ACCESS_PIO 0x0000

    #define JAILHOUSE_CON_ACCESS_MMIO 0x0001

    /*

     * Flags: bit 1 is used to select 1 (cleared) or 4-bytes (set) register distance.

     * 1 byte implied 8-bit access, 4 bytes 32-bit access.

     */

    #define JAILHOUSE_CON_REGDIST_1 0x0000

    #define JAILHOUSE_CON_REGDIST_4 0x0002


**platform_info**


    .platform_info = {

        .pci_mmconfig_base = 0xbfb00000,

        .pci_mmconfig_end_bus = 0,

        .pci_is_virtual = 1,

        .pci_domain = 2,

    

        .arm = {

            .gic_version = 3,

            .gicd_base = 0x38800000,

            .gicr_base = 0x38880000,

            .maintenance_irq = 25,

        },

    },


pci_mmconfig_base和pci_mmconfig_end_bus用于计算mmcfg_start和mmcfg_size用于将物理设备地址map到虚拟地址


pci_domain属性后续会通过of_changeset_add_property函数用于修改设备树对应信息


maintenance_irq的作用是hypervisor 用来向 GIC 发出它需要执行维护操作的信号的特殊中断(此条存疑)


**root_cell**


    .root_cell = {

        .name = "imx8mq",

    

        .num_pci_devices = ARRAY_SIZE(config.pci_devices),

        .cpu_set_size = sizeof(config.cpus),

        .num_memory_regions = ARRAY_SIZE(config.mem_regions),

        .num_irqchips = ARRAY_SIZE(config.irqchips),

        .vpci_irq_base = 51, /* Not include 32 base */

    },

    

    #define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])


num_pci_devices pci设备数量


cpu_set_size cpu集大小


num_memory_regions 分配给cell的内存大小


num_irqchips 指代表系统中的中断控制器的 Irqchip 的数量


**cpus[1]**


    .cpus = {

        0xf,

    },


分配的cpu信息


**irq_chip**


    .irqchips = {

        /* GIC */ {

            .address = 0x38800000,

            .pin_base = 32,

            .pin_bitmap = {

            0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,

        },

    },

    ......


pin_base 设备使用的第一个IRQ号


pin_bitmap 表示设备使用的 IRQ 的位图 位图中的每一位代表一个 IRQ 号,如果该位设置为 1,则使用该 IRQ


Jailhouse 使用此信息来配置hypervisor以将中断从设备路由到正确的cell


**mem_regions**


    .mem_regions = {

        /* IVHSMEM shared memory region for 00:00.0 */ {

            .phys_start = 0xbfd00000,

            .virt_start = 0xbfd00000,

            .size = 0x1000,

            .flags = JAILHOUSE_MEM_READ ,

        },

        {

            .phys_start = 0xbfd01000,

            .virt_start = 0xbfd01000,

            .size = 0x9000,

            .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE ,

        },

    ......


可用内存区域定义


**pci_devices**


    .pci_devices = {

    { /* IVSHMEM 0000:00:00.0 (demo) */

    .type = JAILHOUSE_PCI_TYPE_IVSHMEM,

    .domain = 2,

    .bdf = 0 << 3,

    .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_INTX,

    .shmem_regions_start = 0,

    .shmem_dev_id = 0,

    .shmem_peers = 3,

    .shmem_protocol = JAILHOUSE_SHMEM_PROTO_UNDEFINED,

    },

    { /* IVSHMEM 0000:00:01.0 (networking) */

    .type = JAILHOUSE_PCI_TYPE_IVSHMEM,

    .domain = 2,

    .bdf = 1 << 3,

    .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_INTX,

    .shmem_regions_start = 5,

    .shmem_dev_id = 0,

    .shmem_peers = 2,

    .shmem_protocol = JAILHOUSE_SHMEM_PROTO_VETH,

    },

    },


type定义如下 其中bridge允许一条总线上的设备和另一条上的交互,而ivshmem是虚拟设备


    #define JAILHOUSE_PCI_TYPE_DEVICE 0x01

    #define JAILHOUSE_PCI_TYPE_BRIDGE 0x02

    #define JAILHOUSE_PCI_TYPE_IVSHMEM 0x03


domain指pci设备所在域


bdf 代表 Bus/Device/Function   用于唯一标识系统上的 PCI 设备


bar_mask 定义了IVSHMEM设备的不同类型的 Base Address Registers 定义内存地址掩码,有如下四种定义


    #define JAILHOUSE_IVSHMEM_BAR_MASK_INTX \

    { \

    0xfffff000, 0x00000000, 0x00000000, \

    0x00000000, 0x00000000, 0x00000000, \

    }

    

    #define JAILHOUSE_IVSHMEM_BAR_MASK_MSIX \

    { \

    0xfffff000, 0xfffff000, 0x00000000, \

    0x00000000, 0x00000000, 0x00000000, \

    }

    

    #define JAILHOUSE_IVSHMEM_BAR_MASK_INTX_64K \

    { \

    0xffff0000, 0x00000000, 0x00000000, \

    0x00000000, 0x00000000, 0x00000000, \

    }

    

    #define JAILHOUSE_IVSHMEM_BAR_MASK_MSIX_64K \

    { \

    0xffff0000, 0xffff0000, 0x00000000, \

    0x00000000, 0x00000000, 0x00000000, \


**device remove**


在cell创建时,调用函数static int pci_cell_init(struct cell *cell)将pci设备从root cell取出并添加到新创建的cell中,关键代码如下


    root_device = pci_get_assigned_device(&root_cell, dev_infos[ndev].bdf);   //获取pci设备信息

    if (root_device)

    pci_remove_physical_device(root_device); //从root cell删除设备

    

    err = pci_add_physical_device(cell, device); //添加设备到新cell中

    if (err)

    goto error;


**3)mc:Rust-Shyper介绍**


Rust-Shyper特点:


- 基于Rust语言的Type I虚拟机监视器, 具备更好的隔离性和更轻量的代码实现。 能够支持Linux、 裸应用等系统软件的运行  

- 灵活、 动态创建并配置虚拟机, 能够为实时操作系统创建实时虚拟机, 保障嵌入式场景的实时需求 

- 具备资源隔离属性, 保障不同虚拟机间的隔离性  

- 实现多种模拟设备, 提供基本的磁盘、 网络、 串口等设备的虚拟化实现, 提高资源利用率  

- 提供传统虚拟机迁移机制以及本地热更新机制, 保障虚拟机监视器正常运行过程中的可靠性  


内存虚拟化 :


通过对第二阶段地址翻译页表的配置,Rust-Shyper可以在保障隔离性的同时,实现虚拟机间共享内存的效果  


设备模型 :


全模拟设备 、半模拟设备 、直通设备 


开发经验分享:


RAII与智能指针 、Clippy、Rust FFI