将鞭炮移植到覆盆子派4

2020-10-24 20:47:15

自从我们拿到了新的Raspberry PI 4之后,我们就开始探索各种虚拟化技术在黑板上是如何运行的。我们首先尝试的是如何在其上运行Nabla,以及它与本机KVM的比较。

接下来我们想尝试的是“爆竹”,亚马逊Lambda&;Fargate在其上运行的臭名昭著的微型VMM。令我们失望的是,“爆竹”还没有在RPi4上运行。因此,我们开始研究必要的更改中的编码:)。

经过一些调查,我们发现缺少的关键部分是对GICv2 ARM中断控制器的支持。事实上,鞭炮只支持GIC版本3,因为它是开源的,但不支持版本2,这是出现在Raspberry Pi系列中的版本,以及其他流行的板子,比如我们拿到的Hikey 970,或者Khadas VIM3。更深入地研究了鞭炮和Linux内核的内部结构,帮助我们解决了细节问题,并打开了一个Pull-Request,它增加了对这些部分的支持。

通用中断控制器(GIC)是ARM处理器中实现中断处理的IP块。Linux内核支持GICv2、GICv3和v4的用户和内核空间仿真。但是,Firecracker仅处理虚拟GIC(VGIC)的与GICv3相关的配置。类似地,从Firecracker为来宾微VM设置FDT仅处理GIC-v3设备。

在代码组织方面,GIC相关代码目前公开了用于设置GICv3执行相应的ioctl KVM命令的功能。我们公关的第一部分通过引入GIC特性来改变这一点,该特性定义了所有GIC实现的通用接口。尽管它还在讨论中,但它的最终形式到底会是什么,它将围绕以下几个方面进行讨论:

/GIC设备的特征。Pub特征GICDevice{/返回设备FN版本(&;self)的GIC版本->;u32;/返回GIC设备fn device_fd(&;self)->;&;DeviceFd;/返回具有GIC设备属性的数组fn device_properties(&;self)->;&;[U64];}。

有了这些,我们就可以为实现thisTrait的每个GIC版本定义对象,并且仍然让其余的代码处理GICDevice特性,这对GIC版本是透明的。

每个版本的实现都实现了特征和用于创建新对象的新函数:

这两个版本之间的区别在于每个设备公开的VGIC寄存器属性。因此,我们需要做的工作实质上是映射它们的地址。

/*设置分发服务器属性。我们将GIC放在1 GB以下,因此需要减去分配器的大小。*/SET_DEVICE_ATTRIBUTE(&;VITIC_FD,KVM_BINDINGS::KVM_DEV_ARM_VGIC_GRP_ADDR,u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_DIST),&;GET_DIST_ADDR()as*const U64 as U64,0,)?;/*设置cpu属性。*/SET_DEVICE_ATTRIBUTE(&;VIGIC_FD,KVM_BINDINGS::KVM_DEV_ARM_VGIC_GRP_ADDR,u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_CPU),&;GET_CPUADR()AS*Const U64 AS U64,0,)?;

/*设置分发服务器属性。我们将GIC放在1 GB以下,因此需要减去分配器的大小。*/SET_DEVICE_ATTRIBUTE(&;VITIC_FD,KVM_BINDINGS::KVM_DEV_ARM_VGIC_GRP_ADDR,u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),&;GET_DIST_ADDR()as*const U64 as U64,0,)?;/*设置再分发者属性。我们在这里计算分销商地址的起点。我们的每个CPU都有一个。*/SET_DEVICE_ATTRIBUTE(&;VIGIC_FD,KVM_BINDINGS::KVM_DEV_ARM_VGIC_GRP_ADDR,u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),&;GET_REDISTS_ADR(U64::FROM(VCPU_COUNT))As*Const U64 as U64,0,)??

最后,对于两个版本的GIC,我们通过设置支持的中断数和CONTROL_INIT组来完成设备初始化。

/完成GIC设备pub fn finalize_device(fd:&;DeviceFd)->;result<;()>;{/*我们需要告诉内核此VIC支持多少IRQ。*详见`layout`模块。*/let nr_irqs:u32=SUPER::Layout::IRQ_MAX-SUPER::Layout::IRQ_BASE+1;让nr_irqs_ptr=&;nr_irqs as*const u32;set_device_attribute(FD,KVM_BINDINGS::KVM_DEV_ARM_VGIC_GRP_NR_IRQS,0,nr_irqs_ptr as U64,0,?);/*完成GIC。*请参阅https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211.。*/SET_DEVICE_ATTRIBUTE(FD,KVM_BINDINGS::KVM_DEV_ARM_VGIC_GRP_CTRL,u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),0,0,)?;OK(())}。

关于FDT创建,v2和v3在中断控制器INTC节点方面存在差异。

首先,我们需要将GICv2兼容属性定义为ARM、GIC-400,因为它是实现GICv2的GIC-400芯片。接下来是FDT的regproperty,它包括GIC寄存器的地址和相应的大小,即GICv2的分配器和CPU,GICv3的分配器和再分配器。最后,我们修正了中断属性,它决定了VGIC维护中断的中断源。GICv2的对应值取自相应的Linux内核条目。

在等待补丁向上合并的同时,您可以继续自己检查它。

克隆并构建我们的鞭炮分叉(请记住,在公关审查进行期间,我们可能会强制更新分支)。

接下来,您需要一个内核映像和一个根文件系统来与firecrackerbuild一起运行。您可以在这里获取预建的内核镜像和rootfs:

或者,您也可以使用此处的鞭炮文档提供的以下步骤构建您自己的内核和rootfs。

要启动我们的映像,我们将使用firectl工具。我们需要为网络或我们的爆竹微虚拟机设置一个磁带设备。

$sudo ip tunap add dev tap0模式分路器$sudo IP addr add 172.16.0.1/24 dev分路器0$sudo IP链路设置分路器0。

Curl 172.16.0.42<;!DOCTYPE html>;<;html>;<;head>;<;title>;欢迎使用nginx!<;/title>;<;style>;body{width:35 em;edge:0 auto;font-family:tahoma,verdana,Arial,sans-serif;}<;/style>;<;/head>;<;body>;h1>;欢迎使用nginx!<;/h1>;<;p>;如果您看到此页面,则表明nginx Web服务器已成功安装并正常工作。需要进一步配置。<;/p>;<;有关联机文档和支持,请参阅<;a href=";http://nginx.org/";>;nginx.org<;/a>;。<;br/>;商业支持位于<;a href=";http://nginx.com/";>;nginx.com<;/a>;。<;/p>;<;<;em>;感谢您使用nginx。<;/em>;<;/p>;<;/body>;<;/html>;