02

はじめに

Githubで公開されている,GitHub - bztsrc/raspi3-tutorial: Bare metal Raspberry Pi 3 tutorialsのコードを読んでいく.今回は02_multicorecを理解することを目的とする.

登場ファイル:start.S, main.c, link.ld, Makefile
キーワード:アセンブリ言語c言語,無限ループ,マルチコア

アセンブリ言語ソースファイル(start.S)

.section ".text.boot"

.global _start

_start:
    // CPUの番号を取得
    mrs     x1, mpidr_el1      //x1レジスタにmpidr_el1レジスタの値を格納
    and     x1, x1, #3         //x1=x1 & 3
    cbz     x1, 2f             //x1==0なら,直後のラベル2へジャンプ
    // CPU番号0番以外は, スリープ
1:  wfe                        //スリープ
    b       1b                 //直前のラベル1へジャンプ
2:  // cpu id == 0

    // スタックポインタの設定
    ldr     x1, =_start        //ラベル_startのアドレスをx1レジスタに格納
    mov     sp, x1             //spレジスタにx1レジスタの値を格納

    // BSS領域のゼロクリア
    ldr     x1, =__bss_start   //__bss_start(アドレス)をx1レジスタに格納
    ldr     w2, =__bss_size    //__bss_size(アドレス)をw2レジスタに格納
3:  cbz     w2, 4f             //w2==0なら,直後のラベル4へジャンプ
    str     xzr, [x1], #8      //x1番地に0をストア,その後x1=x1+8
    sub     w2, w2, #1         //w2=w2-1
    cbnz    w2, 3b             //w2!=0なら,直前の3にジャンプ

    // C言語のコードに処理を移す.ここには戻ってこない
4:  bl      main               //main関数へジャンプ
    // 戻ってきてしまった場合に備えて無限ループ
    b       1b                 //直前のラベル1へジャンプ

・x1レジスタ ... 64 ビット汎用レジスタの一つ
・mpidr_el1レジスタ ... レジスタの全体的な機能はよくわからない.しかし,Stanford CS140e - Operating Systemsによると,下位2ビットにはコードを実行しているコアの番号が入るらしい.
・spレジスタ ... スタックポインタ
・w2レジスタ ... x2レジスタの下半分の32ビット部分
・xzrレジスタ ... 64ビットのゼロレジスタ

cソースファイル(main.c)

void main()
{
    while(1);
}

無限ループし,アセンブリ言語のコードには戻らない

リンカスクリプト(link.ld)

SECTIONS
{
    . = 0x80000;
    .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
    .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
    PROVIDE(_data = .);
    .data : { *(.data .data.* .gnu.linkonce.d*) }
    .bss (NOLOAD) : {
        . = ALIGN(16);
        __bss_start = .;
        *(.bss .bss.*)
        *(COMMON)
        __bss_end = .;
    }
    _end = .;

   /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;

Makefile

SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles

all: clean kernel8.img

start.o: start.S
	aarch64-elf-gcc $(CFLAGS) -c start.S -o start.o

%.o: %.c
	aarch64-elf-gcc $(CFLAGS) -c $< -o $@

kernel8.img: start.o $(OBJS)
	aarch64-elf-ld -nostdlib -nostartfiles start.o $(OBJS) -T link.ld -o kernel8.elf
	aarch64-elf-objcopy -O binary kernel8.elf kernel8.img

clean:
	rm kernel8.elf *.o >/dev/null 2>/dev/null || true

run:
	qemu-system-aarch64 -M raspi3 -kernel kernel8.img -d in_asm