以imx8为例
在最底层硬件上,A核和M核通讯是靠硬件来进行的,称为MU,如图
Linux RPMsg 是在virtio framework上实现的一个消息传递机制
VirtIO 是一个用来实现“虚拟IO”的通用框架,典型虚拟的pci,网卡,磁盘等虚拟设备,kvm等都使用了这个技术
与virtio对应的还有一个virtio-ring,其实现了 virtio 的具体通信机制和数据流程。
virtio 层属于控制层,负责前后端之间的通知机制(kick,notify)和控制流程,而 virtio-vring 则负责具体数据流转发
从整体架构上看,关系如下:
最底层有platform_bus,负责从dts获取配置来初始化相关对象,如virtio_device,初始化其config操作函数列表以及devID等,同时注册到virtio_bus
dts相关配置:
&rpmsg{
/*
* 64K for one rpmsg instance:
*/
vdev-nums = <2>;
reg = <0x0 0x90000000 0x0 0x20000>;
status = "okay";
};
主要初始化过程在imx_rpmsg_probe中,关键操作有:
注册MU相关的硬件中断
ret = request_irq(irq, imx_mu_rpmsg_isr, IRQF_EARLY_RESUME | IRQF_SHARED,
"imx-mu-rpmsg", rpdev);
初始化MU硬件
ret = imx_rpmsg_mu_init(rpdev);
创建工作队列用于处理MU中断数据
INIT_DELAYED_WORK(&(rpdev->rpmsg_work), rpmsg_work_handler);
创建通知链用于对接virtio queue
BLOCKING_INIT_NOTIFIER_HEAD(&(rpdev->notifier));
初始化virtio_device并注册
for (j = 0; j < rpdev->vdev_nums; j++) {
pr_debug("%s rpdev%d vdev%d: vring0 0x%x, vring1 0x%x\n",
__func__, rpdev->core_id, rpdev->vdev_nums,
rpdev->ivdev[j].vring[0],
rpdev->ivdev[j].vring[1]);
rpdev->ivdev[j].vdev.id.device = VIRTIO_ID_RPMSG;
rpdev->ivdev