libamp_virnetdrv 可以方便的移植到各种平台,为 AMP 架构提供简单、高效的核间通信机制。下面以 T3 AMP(SylixOS + SylixOS)为例介绍具体的移植过程。
1、驱动支持
虚拟网卡包含 libamp_virnetdrv与 libamp_virnetdrv_config 两个部分。T3 是 ARM 平台,因此首先拷贝 libamp_virnetdrv\src\demo\arm_aarch64 下的四个文件到 T3 每个系统的 BSP 目录 bspallwinnert3\SylixOS\driver\virnet 下,如下图所示。
分别在各系统的 Makefile 中添加源文件 virnet.c,如下:
对 virnet.c 进行定制化修改。
1) 修改系统映射表定义 _G_virNetCoreOsMap
static __VIRNET_CORE_OS_MAP _G_virNetCoreOsMap[4] = {
{OS_TYPE_SYLIXOS, 0, 0},
{OS_TYPE_SYLIXOS, 1, 1},
};
系统映射表结构如下:
struct core_os_map {
UINT32 u32OsType; /* 操作系统类型 */
UINT32 u32OsId; /* 操作系统编号 */
UINT32 u32OsInt; /* 操作系统的中断号 */
};
typedef struct core_os_map __VIRNET_CORE_OS_MAP;
typedef struct core_os_map *__PVIRNET_CORE_OS_MAP;
操作系统类型:目前能够支持的选项为: OS_TYPE_LINUX、 OS_TYPE_SYLIXOS;
操作系统编号:需要从 0 开始, 依次递增;
操作系统的中断号:为当前核能够响应的核间中断编号;
例子中 T3 的 4 个核只用了 2 个核, 每个核为一个 SylixOS, 对应核间中断号为 0、 1, 则配置如下:
static __VIRNET_CORE_OS_MAP _G_virNetCoreOsMap[2] = {
{OS_TYPE_SYLIXOS, 0, 0},
{OS_TYPE_SYLIXOS, 1, 1},
{OS_TYPE_SYLIXOS, 2, 2},
{OS_TYPE_SYLIXOS, 3, 3},
};
2)获取当前系统分配的系统 ID
各系统核代码中需要声明宏 CONFIG_VIRNET_OS_ID,其值为当前的系统 ID。
#define CONFIG_VIRNET_OS_ID (0)/* CPU0 运行系统 0 */
#define CONFIG_VIRNET_OS_ID (1)/* CPU1 运行系统 1 */
CONFIG_VIRNET_OS_ID 会在如下接口中被调用。
INT multiVirNetConfigOwnOsIdGet (VOID)
{
return CONFIG_VIRNET_OS_ID;
}
3) 相关地址配置
相关的地址包括如下几个:
配置空间: 用于存储配置信息的空间, 多个系统之间共享, 多个系统的地址需统一。
控制空间: 用于存储控制信息的空间, 会被划分给多个系统使用, 用于存储网卡状态等。
通信空间: 用于存储通信报文的空间, 会把划分为多个通道, 用于系统两两通信存储报文。
需要分配一块足够大小的共享内存供这三种空间使用:
/*
* 虚拟网卡空间
*/
#define BSP_VIRTUAL_NET_MEM_BASE (BSP_CORES_BOOT_SYNC_BASE + BSP_CORES_BOOT_SYNC_SIZE)
#define BSP_VIRTUAL_NET_MEM_SIZE (10U * 1024 * 1024)
配置空间基地址定义,返回指定的物理内存地址。
addr_t multiVirNetConfigBaseGet (VOID)
{
return (BSP_VIRTUAL_NET_MEM_BASE);
}
配置空间大小定义,填写指定的物理内存大小, 当大小不足时, 初始化时会有错误提示。
size_t multiVirNetConfigSizeGet (VOID)
{
return 0x400000;
}
控制空间基地址定义,填写指定的物理内存地址。
addr_t multiVirNetControlBaseGet (VOID)
{
return (BSP_VIRTUAL_NET_MEM_BASE + 0x400000);
}
控制空间大小定义,填写指定的物理内存大小, 当大小不足时, 初始化时会有错误提示。
size_t multiVirNetControlSizeGet (VOID)
{
return 0x100000;
}
通信空间基地址定义,填写指定的物理内存地址。
addr_t multiVirNetMessageBaseGet (VOID)
{
return (BSP_VIRTUAL_NET_MEM_BASE + 0x400000 + 0x100000);
}
通信空间大小定义,填写指定的物理内存大小, 当大小不足时, 初始化时会有错误提示。
size_t multiVirNetMessageSizeGet (VOID)
{
return 0x400000;
}
3)核间中断相关函数
核间中断触发函数,在该接口中根据传入的 中断号 或 系统号 触发对应的核间中断
VOID multiVirNetIsrOccur (INT iOsInt, INT iOsId)
{
VOID bspMpInt(ULONG ulCPUId);
bspMpInt(iOsInt);
}
核间中断使能函数
VOID multiVirNetIsrEnable (INT iOsInt)
{
INT armGicIrqAffinitySet (ULONG ulVector, UINT64 ullMpidr, BOOL bForce);
INT armGicIrqPrioritySet (ULONG ulVector, UINT32 uiPriority);
VOID armGicIrqEnable (ULONG ulVector);
armGicIrqAffinitySet(ARM_SW_INT_VECTOR(iOsInt), iOsInt, LW_TRUE);
armGicIrqPrioritySet(ARM_SW_INT_VECTOR(iOsInt), ARM_SW_INT_PRIORITY);
armGicIrqEnable(ARM_SW_INT_VECTOR(iOsInt));
}
核间中断禁能函数
VOID multiVirNetIsrDisable (INT iOsInt)
{
VOID armGicIrqDisable (ULONG ulVector);
armGicIrqDisable(ARM_SW_INT_VECTOR(iOsInt));
}
2、创建虚拟网卡设备
编译 libamp_virnetdrv与 libamp_virnetdrv_config 这两个库,生成静态库文件。
在编译各 AMP 系统 BSP 时链接此文件:
LOCAL_DEPEND_LIB := \
-lfdt \
-l:libamp_virnetdrv_config.a \
-l:libamp_virnetdrv.a
LOCAL_DEPEND_LIB_PATH := \
-L"$(SYLIXOS_BASE_PATH)/libsylixos/$(Output)" \
-L"$(LIBAMP_VIRNETDRV_CONFIG_DIR)" \
-L"$(LIBAMP_VIRNETDRV_DIR)"
在每个系统 BSP 的 halNetifAttch 中调用如下接口:
multiVirNetDevSymbolInit();
API_VirNetNdCreate();
在 0 号系统 BSP 的 usrStartup 中调用如下接口,需要保证此接口在所有系统调用创建虚拟网卡前调用,且需要在调用 halStdFileInit() 后:
API_VirNetConfig();
3、使用
编译各系统镜像烧录后,如果虚拟网卡创建成功则可以在 ifocnfig 看到对应设备:
使用 vnconfig 命令可以查看虚拟网卡配置的信息:
使用 virnet 命令可以查看当前虚拟网卡的信息:
成功在各系统上创建虚拟网卡后即可通过 socket 接口进行核间通信。