1. 程式人生 > >ARM多核處理器啟動過程分析

ARM多核處理器啟動過程分析

說明:

該流程圖按照程式碼執行時間順序劃分為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指令,啟用剩餘處理器。