zoukankan      html  css  js  c++  java
  • ARM多核处理器启动过程分析

    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/qianlong4526888/article/details/27695173



    说明:

    该流程图依照代码运行时间顺序划分为4部分:

    1.     Bootloader在图片上半部,最先启动;

    2.     Kernel在图片下半部,由bootloader引导启动;

    3.CPU0运行流程在图片左半部,bootloader代码会进行推断,先行启动CPU0。

    4.  Secondary CPUs在图片右半部,由CPU唤醒

     

    详细启动流程例如以下:

    1.     在bootloader启动时,会推断运行代码的是否为CPU0,假设不是,则运行wfe等待CPU0发出sev指令唤醒。假设是CPU0。则继续进行初始化工作。

     

             mrs  x4,mpidr_el1

             tst    x4,#15             //testwether the current cpu is CPU0, ie. mpidr_el1=15

             b.eq 2f

    /*

     * Secondary CPUs

     */

    1: wfe

    ldr x4, mbox               

    cbz x4, 1b        //if x4==0(ie. The value in address of mbox is 0) dead loop,or jump to x4

    br x4 // branch to thegiven address

     

    2:……        //UART initialisation (38400 8N1)

     

    以上mbox的地址在Makefile中写定。是0x8000fff8,该地址处初始状态内容为全0。

    上面代码推断,若mbox地址处内容为0。则死循环;假设不为0则直接跳转到该地址所包括内容处运行。

     

    2.     在dts中,对cpu-release-addr进行赋值,将其地址设为0x8000fff8。即仅仅要往该地址写入对应的值,比如地址A,而且发送sev指令,就能将次级CPU唤醒,并跳转到A地址处运行。

    cpu-release-addr = <0x0 0x8000fff8>; 

     

    3. 内核中smp_prepare_cpus 函数对0x8000fff8地址处内容进行了赋值,其值为函数secondary_holding_pen 的地址:

    release_addr = __va(cpu_release_addr[cpu]);

    release_addr[0] = (void*)__pa(secondary_holding_pen);//write function address to mbox

     

    以上代码运行完后发送sev指令,唤醒其它次级CPU运行secondary_holding_pen函数:

    /*

     * Send an event to wake up the secondaries.

     */

    sev();

     

    4. secondary cpu 运行secondary_holding_pen()函数时都会去推断当前CPU的ID。并与secondary_holding_pen_release变量做比对。假设相等,则运行进一步初始化,否则运行WFE等待;

    secondary_holding_pen_release变量的改动过程由CPU0调用smp_init()函数进行。

    该函数首先为对应CPU绑定一个idle线程,然后改动secondary_holding_pen_release的值(其值即CPU0欲唤醒的CPU的ID)。最后发送sev指令,唤醒对应CPU运行idle线程。

     

    secondary_holding_pen()函数代码例如以下:

             /*

              * This provides a"holding pen" for platforms to hold all secondary

              * cores are helduntil we're ready for them to initialise.

              */

    ENTRY(secondary_holding_pen)

             bl      el2_setup                          // Drop to EL1

             mrs  x0, mpidr_el1

             and  x0, x0, #15                        // CPU number

             adr   x1, 1b

             ldp   x2, x3, [x1]

             sub   x1, x1, x2

             add  x3, x3, x1

    pen: ldr    x4, [x3]

             cmp x4,x0

             b.eq secondary_startup

             wfe

             b       pen

    ENDPROC(secondary_holding_pen)

     

     

    附录:

    内核中启动secondary cpus函数调用过程大致例如以下:

    start_kernel èrest_initèkernel_inièkernel_init_freeable èsmp_init()  kernel/smp.c line 649, 由CPU0激活剩余的处理器

    cpu_upè_cpu_up()è__cpu_up ()èboot_secondary ()èwrite_pen_release该函数中有一句:secondary_holding_pen_release = val; 然后发送sev指令,激活剩余处理器。


查看全文
  • 相关阅读:
    linux笔记
    初探hook的键盘获取
    python pyHook安装
    转: ZigBee/Z-Stack CC2530实现低功耗运行的配置简介
    三种zigbee网络架构详解
    adc verilog spi 时序
    dac verilog ad5601
    verilog 三段式状态机的技巧
    fpga 状态机 检测1011序列
    lattice diamond fpga 状态机的理解
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10842777.html
  • Copyright © 2011-2022 走看看