SylixOS 多核SMP BSP开发(二十二)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2021年4月11日12:59:39 评论 1,445

实现bspLib.c中多核相关接口

在bspLib.c中有3个接口是需要我们来实现的,另外为了配合多核启动,我们还需要另外再自己实现几个接口以和bspInit.c来一起将多核启动起来。

1. bspMpInt

这个接口主要是向某一个核发送一个核间中断,核间中断IPI(Inter-Processor Interrupts)是多核之间进行通信的一种方法。发起方cpu核首先将消息写到一块事先约定好的共享内存中,然后发起核间中断,产生核间中断的cpu核在核间中断服务程序中读取该内存,以获得发起方通知的消息。

至于如何产生核间中断则需要看具体的中断控制器了,另外还有一个问题就是核间中断的中断号是多少?在arm架构中,每个核的核间中断号就是本核的ID,也就是cpu0的核间中断号是0,cpu1的是1,依此类推。

一般的多核控制器都有向多个核同时发送核间中断的功能,具体的参考控制器的手册和相应的Linux源码:

/*********************************************************************************************************
** 函数名称: bspMpInt
** 功能描述: 产生一个核间中断
** 输  入  : ulCPUId      目标 CPU
** 输  出  : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID   bspMpInt (ULONG  ulCPUId)
{
    /*
     * TODO: 加入你的处理代码
     */
    armGicSoftwareIntSend(ulCPUId, GIC_SW_INT_OPTION_USE_TARGET_LIST, 1 << ulCPUId);
}

2. bspCpuUp

这个接口功能是启动一个从核,SylixOS下的多核启动流程大致如下图所示:

SylixOS 多核SMP BSP开发(二十二)

主核为了让从核启动后和自己看到的数据是一致的,在唤醒从核启动之前需要将DCache回写并失效,同时还要关闭本核中断,防止在中断处理中对内存访问从而改变Cache中的数据。接着就是具体的从核唤醒操作了,这是和具体的处理器相关的,从核启动后主核需要等待从核初始化完成后才能接着去唤醒下一个cpu核,在SylixOS中一般是通过轮询一个全局变量的值是否改变来实现的:

static volatile BOOL cpuStartDone[LW_CFG_MAX_PROCESSORS];

/*********************************************************************************************************
** 函数名称: bspCpuUp
** 功能描述: 启动一个 CPU
** 输  入  : ulCPUId      目标 CPU
** 输  出  : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID   bspCpuUp (ULONG  ulCPUId)
{
    /*
     * TODO: 加入你的处理代码, 如果没有, 请保留下面的调试信息
     */
    INTREG  iregInterLevel;

    iregInterLevel = KN_INT_DISABLE();

    API_CacheClear(DATA_CACHE, LW_NULL, (size_t)~0);

    /*
     *  TODO: 唤醒从核启动
     */
    cpuEnable(ulCPUId);

    while (!cpuStartDone[ulCPUId]);

    KN_INT_ENABLE(iregInterLevel);
}

cpuStartDone 中的值默认都是0,在从核启动完成后会将相应核对应的变量置1,这样主核就知道从核已经启动完成了,就继续去启动下一个cpu核,这个循环控制是在bspInit.c 中做的。

当所有核都启动完成后还需要进行DCache的同步,这在SylixOS下是通过API_CacheBarrier 接口来实现的,这个会在下面小节讲解。

3. bspCpuDown

这个接口功能就是关闭一个cpu核,不过在SylixOS中一般cpu核启动后就不会再动态去关闭它了,所以这个接口使用默认实现即可。

4. bspCpuUpDone

在第2小节我们知道从核启动后需要告知主核它已经启动完成了,这是通过将全局变量置1来实现的:

VOID  bspCpuUpDone (VOID)
{
    cpuStartDone[LW_CPU_GET_CUR_ID()] = LW_TRUE;

    KN_SMP_MB();
}

这个接口是我们自己定义的,并不是SylixOS内核要求的,并且这个接口会在bspInit.c 中被调用,这个我们将在下一章节看到。

5. bspCpuUpSync

从第二小节的图中我们可以知道SylixOS所有核启动完成后需要进行DCache同步操作,这是通过API_CacheBarrier 接口实现的,这个接口可以让所有核同步执行某个回调函数,然后再同步等待所有核都执行完这个回调函数再继续运行:

static VOID  bspCpuCacheSync (VOID)
{
    API_CacheClear(DATA_CACHE, LW_NULL, (size_t)~0);
}

VOID  bspCpuUpSync (VOID)
{
    INT i;
    LW_CLASS_CPUSET cpuset;

    LW_CPU_ZERO(&cpuset);

    LW_CPU_FOREACH (i) {
        LW_CPU_SET(i, &cpuset);
    }

    API_CacheBarrier(bspCpuCacheSync, LW_NULL, sizeof(cpuset), &cpuset);
}

API_CacheClear 接口将当前cpu核的DCache先回写再失效,这样每个核在API_CacheBarrier 执行完之后DCache中的数据是一致的。

bspCpuUpSync 接口同样也是我们自己实现的,不是SylixOS内核要求的,这个接口同样会在bspInit.c中被主核和从核调用。

gewenbin
  • 本文由 发表于 2021年4月11日12:59:39
  • 转载请务必保留本文链接:http://www.databusworld.cn/10239.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: