Lab1: Basic Initialization
Requirement:
- Let only one core proceed, and let others enter a busy loop.
- Initialize the BSS segment.
- Set the stack pointer to an appropriate position.
解析 start.s
start.s 符合上述要求,解析一下:
1 | .section ".text.boot" |
MRS Xd, <system register>: 將system register內容寫入至Xd(d=0-30),Xd為AArch64提供的31個64-bit general purpose register。用Wd存取Xd的低32-bit。CBZ Xn, label: 用來測試ALU指令運算後的flags是否為0,含0則跳躍至label。CNBZ是相反的情況。WFE: 在競爭相同資源的場景中,使CPU進入STANDBTWFE省電狀態,由其他CPU執行SEV指令喚醒所有在STANDBTWFE狀態的CPU。B label: 跳躍至labelBL label: 複製下一個指令的地址到r14(Link Register),同時跳躍至labelLDR W0/X0, [<address>]:載入(load)到X0/W0,寫入(store)對應到STR。定址模式參考ARM Cortex-A Series Programmer’s Guide for ARMv8的Index modes章節。sp: stack pointer1f, 1b,...Nb,Nf: Symbol Names,1f為往該指令前找1的label,1b往該指令後找1的label。
我們的目標是希望GPU在載入kernel8.img到記憶體(0x80000)之後,各個CPU讀取同一份kernel時依據CPU ID(mpidr_el1)來決定執行流程。
看到CPU ID>0時跑進無窮迴圈:
1
21: wfe
b 1bCPU ID=0初始化stack並呼叫
main(雖然題目只有要求初始化stack pointer),在此之前需要曉得ARM stack frame是如何佈局。
如果要在組語中用到 #include 之類的還得先把副檔名改成大寫 .S
You can use the GNU C compiler driver to get other “CPP” style preprocessing, by giving the input file a ’.S’ suffix. See section `Options Controlling the Kind of Output’ in Using GNU CC.
Stack Frame Layout
X86

呼叫函數時進行以下動作
push argumentspush eip(return address)push ebpmov ebp, esp:esp設為當前frame pointersub esp, n:預留n bytes給local variable
1 | -stack bottom- |
Stack保存了argument、frame pointer、local variable、return address。
ARM

- 使用B系列指令跳躍,其中BL指令將return address儲存在LR register (Link Register)
- 參數透過
R0~R7傳入,如果超過8個,就要從後面的參數開始 push stack,最後返回透過 R0~R1。
1 | Register |
記憶體佈局
因此,在沒有參數、沒local variable的情況下,預期進到main的記憶體佈局:
1 | Register |
所以start.s分成三步驟進行
- 設定
sp - 以
__bss_start為起點、8 bytes為單位初始化。
1 | // clear bss |
- 最後用
BL指令設定LR register。
Linker script
1 | SECTIONS |
NOLOAD: Mark a section to not be loaded at run time. (REF: Optional Section Attributes)
KEEP: Mark sections that should not be eliminated. (REF: Input Section and Garbage Collection)
Makefile
1 | CFLAGS = -Wall -I include -c -ffreestanding -O2 -nostdinc -nostdlib -nostartfiles |
nostdinc: Do not use the C library or system libraries tightly coupled with it when linking. (REF:Options for Linking)
nostdlib: Do not use the standard system startup files or libraries when linking.
nostartfiles: Do not use the standard system startup files when linking.