开发 QuickVisor Scenario

更新时间:
2024-01-10

开发 QuickVisor Scenario

场景工程简介

场景工程(Scenario Project)主要用于将多个不同类型的 GuestVM 集成到同一个硬件平台上。Scenario 工程主要包含 Platform 资源文件、QuickVisor 资源文件 和 GuestVM 资源文件。编译 Scenario 工程时,构建系统将编译并打包所需的资源文件到 QuickVisor 的 ROMFS 文件中。在 QuickVisor 启动时,QuickVisor 将根据 ROMFS 中的配置文件和镜像文件创建虚拟机。

  • Platform 资源文件主要包含硬件平台的设备树文件。
  • QuickVisor 资源文件主要包含硬件资源设备树文件和虚拟资源配置文件,虚拟资源配置文件也使用设备树文件的格式进行编辑。
  • GuestVM 资源文件主要包含虚拟机设备树文件、虚拟机镜像文件和虚拟机 ROMFS 文件。

创建场景工程

Scenario 工程的创建流程

首先,选择 File > New > QuickVisor Scenario 菜单,开始创建 Scenario 工程,为新建的 Scenario 工程输入名称,单击 Next 按钮进入编译链配置界面。

然后,右键工程 Propeities > QuickVisor Setting > Scenario Setting 进入 Scenario 配置页面,在配置页面中可以新建虚拟机。

接着,选中目标工程单击右键选择 Build Project 或者单击工具栏的一键编译按钮,进行工程编译。

Scenario 工程的目录结构

Scenario 工程模板的目录结构如下:

项目说明
/src/platform/platform.dts创建工程时选择目标板卡,此文件为目标板卡对应的设备树文件。
/src/quickvisor/quickvisor.dtsQuickVisor 的设备树文件,空的模板文件。
/src/quickvisor/quickvisor.cfgQuickVisor 的配置文件,空的模板文件。
/src/guest-vm0/guest-vm0.dts用于描述 VM0 的设备树文件,空的模板文件。
/src/guest-vm0/guest-vm0.bin在 VM0 中运行的 GuestOS 二进制文件。
/src/guest-vm0/guest-vm0.rfs传递给 GuestOS 使用的 ROMFS 镜像文件。
/readme.txt场景工程的使用说明文档。

实现场景工程

Scenario 工程的开发流程

场景工程的开发流程如下:

  1. 获取 platform.dts 文件:在创建工程时选择板卡型号,工程的 platform 目录下将自动导入板卡的设备文件。
  2. 编辑 quickvisor.dts 文件:根据 platform.dts 编辑 quickvisor.dts,描述 Hypervisor 占用的硬件资源。
  3. 编辑 quickvisor.cfg 文件:描述物理 CPU 域的划分、描述内核提供的虚拟资源、描述虚拟机的可访问视图。
  4. 编辑 guest-vmx.dts 文件:根据 quickvisor.cfg 编辑 guest-vmx.dts,描述 GuestVM 的硬件资源。
  5. 添加 guest-vmx.bin 文件:将编译好的 GuestOS 镜像文件拷贝到相应的资源目录下。每个 GuestVM 都必须有这个文件。
  6. 添加 guest-vmx.rfs 文件:将编译好的 ROMFS 镜像文件拷贝到相应的资源目录下。如果 GuestOS 不需要则不用添加此文件。
  7. 配置场景工程:通过编辑场景工程 Makefile 文件的方式,或者通过配置场景工程 IDE 配置页的方式,配置各个 GuestVM 所使用的资源文件。
  8. 编译场景工程:编译时将会把 dts 文件编译成 dtb 文件,然后把所有 dtb 文件和客户机的 bin 文件打包到 Debug/Release 目录下的 quickvisor.rfs 文件中。
  9. 部署和启动:QuickVisor 启动时,将挂载 quickvisor.bin 到 ROMFS 文件系统,然后解析 QuickVisor 配置文件,从而创建相应的内核资源和虚拟机。

Scenario 工程的编译配置

场景工程的编译配置项主要包括:Platform 配置项、QuickVisor 配置项 和 GuestVM 配置项。这些配置项被记录在 Scenario 工程对应的 Makefile 文件中。scenario_name.mk 中各个变量的含义如下:

  • PLATFORM_DTS:该变量用于记录 目标板卡对应的设备树文件。
  • QUICKVISOR_DTS:该变量用于记录 QuickVisor 的设备树文件。
  • QUICKVISOR_CFG:该变量用于记录 QuickVisor 的配置文件。
  • GUEST_VMx_BIN:该变量用于记录 GuestOS 内核镜像文件。
  • GUEST_VMx_DTS:该变量用于记录 GuestOS 使用的设备树文件。
  • GUEST_VMx_RFS:该变量用于记录 GuestOS 使用的 ROMFS 文件。
  • LOCAL_GUEST_VMS:该变量用于记录 需要打包到 QuickVisor ROMFS 的 GuestVM。

GUEST_VMx_BIN 变量名中的 x 代表 GuestVM 的编号,x 可以是 '0-n'。GUEST_VMx_BIN、GUEST_VMx_DTS、GUEST_VMx_RFS 都用于记录 VMx 对应的各种资源文件。

编辑 quickvisor.dts 文件

根据 platform.dts 编辑 quickvisor.dts,描述 Hypervisor 占用的硬件资源。本文档不会专门介绍设备树的语法规则,开发者可以通过设备树官方手册open in new window自行学习。当前 QuickVisor 并没有完全使用设备树来识别和管理所有设备,开发者仍需通过硬编码的方式向内核提供初始化参数 qv_bsp_params_t ,该结构体主要记录了 CPU 相关的信息、QuickVisor 程序段相关的信息、系统的初始映射关系。

typedef struct {
    const char             *name;
    qv_virt_addr_t          vaddr;
    qv_phys_addr_t          paddr;
    qv_size_t               size;
    qv_uint32_t             type;
#define QV_INIT_MAP_TYPE_INVALID    0	//非法的映射关系
#define QV_INIT_MAP_TYPE_KTEXT      1	//内核代码段的映射
#define QV_INIT_MAP_TYPE_KDATA      2	//内核数据段的映射
#define QV_INIT_MAP_TYPE_DEVICE     3	//物理设备的寄存器地址空间映射
#define QV_INIT_MAP_TYPE_ROMFS      4	//ROMFS 所在内存区域的映射
#define QV_INIT_MAP_TYPE_DMAIO      5	//DMA 传输所需内存的映射
#define QV_INIT_MAP_TYPE_GUEST      6	//GuestVM 所需内存的映射,包括 ROM 和 RAM
#define QV_INIT_MAP_TYPE_RESV       7	//保留的内存空间,在不支持IOMMU时给具有直通设备的VM使用
} qv_init_mapping_t;

编辑 quickvisor.cfg 文件

编辑 quickvisor.cfg 文件 ,主要步骤为:

  1. 向 quickvisor.cfg 添加 domain 节点,domain 节点用于配置物理 CPU 分区。

  2. 向 quickvisor.cfg 添加 hvdev 节点,hvdev 节点用于描述位于 Hypervisor 内的虚拟设备。

  3. 向 quickvisor.cfg 添加 guest 节点,guest 节点用于描述需要创建的 GuestVM 虚拟硬件视图。

编辑 domain 节点,节点属性的含义可以在 /quickvisor/libquickvisor/src/include/qv_hypconf.h 文件中找到。

domains {
	domain0 {
		compatible = "qv-domain";
		dom_name = "domain0";
		dom_cpus = <0x03>;
		dom_algo = "default-class";		 
		dom_ticks = <100>;
	};
	
	domain1 {
		compatible = "qv-domain";
		dom_name = "domain1";
		dom_cpus = <0x0C>;
		dom_algo = "default-class";		 
		dom_ticks = <100>;
	};
};

domain 节点属性说明如下:

节点属性名称节点属性类型节点属性说明
compatible"qv-domain"CPU 域节点标识符
dom_name字符串CPU 域名称
dom_cpus32 位掩码CPU 域管理的物理 CPU
dom_algo字符串CPU 域使用的调度算法
dom_ticks32 位整数含义取决于调度算法

编辑 hvdev 节点,节点属性的含义可以在 /quickvisor/libquickvisor/src/include/qv_hypconf.h 文件中找到。

hvdevs {
	hvdev0 {
		compatible = "qv-hvdev";
		hvdev_name = "serial0";
		hvdev_type = "serial-line";		 
		hvdev_mem_size = <0>;
		hvdev_port_num = <2>;
	};

	hvdev1 {
		compatible = "qv-hvdev";
		hvdev_name = "bridge0";
		hvdev_type = "net-bridge";		 
		hvdev_mem_size = <0>;
		hvdev_port_num = <8>;
	};
	
	hvdev2 {
		compatible = "qv-hvdev";
		hvdev_name = "disk0";
		hvdev_type = "blk-disk";		 
		hvdev_mem_size = <0>;
		hvdev_port_num = <1>;
		hvdev_host_dev = "ramdisk-p0";
	};
};

hvdev 节点属性说明如下:

节点属性名称节点属性类型节点属性说明
compatible"qv-hvdev"HVDEV 节点标识符
hvdev_name字符串HVDEV 名称
hvdev_type字符串HVDEV 模型
hvdev_mem_size32 位整数HVDEV 存储空间
hvdev_port_num32 位整数HVDEV 通道数(可选)
hvdev_host_dev字符串HVDEV 后端设备(可选)

编辑 guest 节点,节点属性的含义可以在 /quickvisor/libquickvisor/src/include/qv_hypconf.h 文件中找到。

guests {
	guest0 {
		compatible = "qv-guest";
		
		guest_name    = "vm0";
		guest_domain  = "domain0";
		guest_startup = <1>;
		guest_window  = <50>;
		guest_permiss = <0>;
		
		guest_cpu_nr = <2>;
		guest_cpu_pc = <0>;
		guest_cpu_r0 = <0>;
	
		rom {
			compatible = "qv-guest-device";
			guest_device_type = "vdev";
			guest_device_class = "rom";
			guest_device_fw = "/guest-vm0.bin";
			guest_aspace_gpa = <0x0 0x00000000>;
			guest_aspace_siz = <0x0 0x01000000>;
		};
		
		ram {
			compatible = "qv-guest-device";
			guest_device_type = "vdev";
			guest_device_class = "ram";
			guest_aspace_gpa = <0x0 0x80000000>;
			guest_aspace_siz = <0x0 0x04000000>;
		};
		
		gic_dist {
			compatible = "qv-guest-device";
			guest_device_type = "vdev";
			guest_device_class = "irq"; 
			guest_device_model = "arm,vgicv2,dist";
			guest_aspace_gpa = <0x0 0x01400000>;
			guest_aspace_siz = <0x0 0x1000>;
		};
		
		gic_cpu {
			compatible = "qv-guest-device";
			guest_device_type = "pdev";
			guest_device_class = "dev";
			guest_aspace_gpa = <0x0 0x01410000>;
			guest_aspace_siz = <0x0 0x1000>;
			guest_aspace_hpa = <0x0 0x01460000>;
		};
		
		gen_timer {
			compatible = "qv-guest-device";
			guest_device_type = "vdev";
			guest_device_class = "dev";
			guest_device_model = "arm,vgtimer";
		};

		uart0 {
			compatible = "qv-guest-device";
			guest_device_type = "vdev";
			guest_device_class = "dev";
			guest_device_model = "arm,pl011";
			guest_aspace_gpa = <0x0 0x21c0000>;
			guest_aspace_siz = <0x0 0x10000>;
			guest_interrupt_guest = <86>;
			guest_backend_name = "serial0";
			guest_backend_chan = <0>;
		};
	};
};

guest 节点属性说明如下:

节点属性名称节点属性类型节点属性说明
compatible"qv-guest"VM 节点标识符
guest_name字符串VM 虚拟机名称
guest_domain字符串VM 所属 CPU 域
guest_profile文件路径VM 虚拟机配置文件
guest_startup布尔值VM 创建后是否启动
guest_window32 位整数VM 占用 CPU 时间片
guest_permiss32 位整数VM 可访问 hypcall 的权限
guest_cpu_nr32 位整数VM 拥有的 vcpu 个数
guest_cpu_pc32 位整数VM 主核启动时的地址
guest_cpu_r032 位整数VM 主核启动时的 r0 参数
guest_cpu_r132 位整数VM 主核启动时的 r1 参数
guest_cpu_r232 位整数VM 主核启动时的 r2 参数
guest_cpu_r332 位整数VM 主核启动时的 r3 参数
compatible"qv-guest-device"客户机设备节点标识
guest_device_status布尔值标识设备节点是否使能
guest_device_type32 位整数标识设备节点是否为虚拟设备
guest_device_class32 位整数标识设备节点所代表设备的类型
guest_device_fw文件路径标识设备节点初始固件路径
guest_device_model字符串虚拟设备对应的设备模型
guest_device_serial字符串虚拟设备序列号
guest_aspace_gpa64 位整数虚拟设备占用的 GPA
guest_aspace_siz64 位整数虚拟设备占用的 GPA 空间大小
guest_aspace_hpa64 位整数指明 GPA 实际映射到的 HPA
guest_interrupt_guest32 位整数虚拟设备占用的客户机中断号
guest_interrupt_host32 位整数客户机中断实际映射到的主机中断
guest_backend_name字符串虚拟设备使用哪一个后端设备
guest_backend_chan32 位整数虚拟设备使用后端的哪一个通道

注意:当前 QuickVisor 并不支持多地址区间和多中断号,因此在编辑 quickvisor.cfg 文件时,需要将实际设备节点拆分成多个简单节点。

编辑 guest-vmx.dts 文件

根据 quickvisor.cfg 编辑 guest-vmx.dts,描述 GuestVM 的硬件资源。本文档不会专门介绍设备树的语法规则,开发者可以通过设备树官方手册open in new window自行学习。编辑 guest-vmx.dts 文件 ,主要步骤为:

  1. 在设备树文件中添加 CPU 设备树节点。
  2. 在设备树文件中添加 ROM 设备树节点、RAM 设备树节点。
  3. 在设备树文件中添加 PSCI 设备树节点。
  4. 在设备树文件中添加 GenTimer 设备树节点。
  5. 在设备树文件中添加 GIC 设备树节点。
  6. 在设备树文件中添加 UART 设备树节点。

以上这些设备树节点描述了一个完整的虚拟机最小硬件系统,其中 CPU 节点的个数不可以大于物理 CPU 节点的个数,ROM/RAM 节点占用的内存不可以大于 QuickVisor BSP 中 GUEST-MEM-REGION 区域的内存大小,PSCI 节点必须配置为 hvc 启动方法,GenTimer 节点描述真实物理设备的信息,GIC 节点描述真实物理设备的信息,UART 描述真实物理设备或虚拟设备的信息。

构建 guest-vmx.bin 文件

QuickVisor GuestOS 镜像的构建将在 开发 QuickVisor GuestOS 章节中介绍。用户只需要根据虚拟机视图,即根据 guest-vmx.dts 构建自己 GuestOS 镜像即可。GuestOS 构建完成后,需要将镜像文件拷贝到对应 GuestVM 的资源文件夹下。

文档内容是否对您有所帮助?
有帮助
没帮助