Zircon의 QEMU용 이니시에이터(arch64)

이 보도는 QEMU에서 arch64용 Zircon 커널을 가동할 때의 동작을 소개했다.
Zircon의 QEMU 시작의 계속.
소개된 소스 코드는 2021년 9월 28일 아래의 제출을 바탕으로 한다.
b2a4698c4363a0b8742bbb6a7bfac4b65f32dba5

qemu-boot-shim


%%{init:{'theme':'base','themeVariables':{'primaryColor':'#6A7FAB','primaryTextColor':'#FAFBF9','primaryBorderColor':'#6A7FAB','lineColor':'#6A7FABCC','textColor':'#6A7FABCC','fontSize':'20px'}}}%%
graph LR
  q(QEMU) --> b[qemu-boot-shim] --> physboot --> zircon
  style b fill:#F96A76,stroke:#F96A76

주요 처리

  • 命令・データキャッシュと MMU を無効にする
  • QEMU が用意した DTB から必要な情報を抜き出し、fuchsia-ssh.zbi へ追記する
  • fuchsia-ssh.zbi 中の physboot を ZBI データの後方へコピーする
  • physboot へジャンプする

주요 소스 코드 관계

%%{init:{'theme':'base','themeVariables':{'primaryColor':'#6A7FAB','primaryTextColor':'#FAFBF9','primaryBorderColor':'#6A7FAB','lineColor':'#6A7FABCC','textColor':'#6A7FABCC','fontSize':'20px'}}}%%
graph LR
  %%classDef node stroke-width:2px,fill:#6A7FAB,stroke:#6A7FAB,color:#FAFBF9
  %%classDef edgePath stroke-width:1.5px,stroke:#6A7FAB,stroke-fill:none,fill:#6A7FAB

  bss[boot-shim.S] --> bsc[boot-shim.c]
  bsc --> zbi[zbi.c]
  bsc --> dt[devicetree.c]
%%{init:{'theme':'base','themeVariables':{'primaryColor':'#6A7FAB','primaryTextColor':'#FAFBF9','primaryBorderColor':'#6A7FAB','secondaryColor':'#6A7FAB','lineColor':'#6A7FABCC','noteTextColor':'#FAFBF9','noteBkgColor':'#6A7FABBB','textColor':'#6A7FABCC','fontSize':'20px'},'themeCSS':"text.actor {font-size:24px !important;}"}}%%
sequenceDiagram
    %%participant qemu as QEMU
    participant bss as boot-shim.S
    participant bsc as boot-shim.c
    participant zbi as zbi.c
    participant dt as devicetree.c

    %%qemu ->> bss: _start へジャンプ <br>(x0レジスタはdevice_treeを参照)
    Note over bss: QEMU から起動
    activate bss
    bss ->> bsc: boot_shim()
    activate bsc
    bsc ->> dt: dt_walk()
    bsc ->> zbi: zbi_check()
    bsc ->> zbi: zbi_create_entry_with_payload()
    deactivate bsc
    deactivate bss
    Note over bss: physboot へジャンプ

기본 소스 코드

boot-shim.S의 개요

%%{init:{'theme':'base','themeVariables':{'primaryColor':'#6A7FAB','primaryTextColor':'#FAFBF9','primaryBorderColor':'#6A7FAB','lineColor':'#6A7FABCC','textColor':'#6A7FABCC','fontSize':'20px'}}}%%
graph TD

  qemu(QEMU) --> disable["キャッシュとMMUを無効化"]
  disable --> stack["スタックの用意"]
  stack --> bsc["boot_shim()を呼び出す"]
  bsc --> jump["physboot エントリポイントへジャンプ"]

캐시 및 MMU 해제

SCTLR_EL2 レジスタの I,C,M ビットをクリアして、キャッシュと MMU を無効化します。

Bit Description
I, bit [12] Instruction access Cacheability control, for accesses at EL2
C, bit [2] Cacheability control, for data accesses
M, bit [0] MMU enable for EL2 stage 1 address translation

— D13.2.114 SCTLR_EL2, System Control Register (EL2), Arm® Architecture Reference Manual

SCTLR_EL2 レジスタ変更後、

  • システムレジスタ変更の反映のために、ISB を実行
  • キャッシュアクセスを完了するために、DSB SY を実行

스택 준비

boot-shim のメモリマップ
Address Size Section
0x00000000 0x0090 .text.boot0
0x00000090 0x16AC .text
0x00001740 0x03B9 .rodata
0x00001AFC 0x0004 .data
0x00001B00 0x1010 .bss
スタック
Address Symbol
0x00001B10 stack
0x00002B10 stack_end

.bss セクション内の 4096 Byte がスタック領域です。

実際のアドレスは、boot-shim がロードされた 0x40080000 にオフセット 0x00002B10 を加算した、0x40082B10 となります。
SP レジスタに 0x40082B10 をセットして、スタックとして使用可能にします。

boot_shim 호출()

boot-shim.c の boot_shim() を実行します。

引数
Register Value Description
x0 0x49800000 Device Tree Blob
戻り値
Register Value Description
x0 0x48000000 ZBI データ
x1 0x4989436c physboot のエントリポイント(_start)

戻り値は、x0、x1 レジスタに格納されています。

physboot 입구점으로 이동

physboot へ渡す情報
Register Value Description
x0 0x48000000 ZBI データ
x1 0x4989436c physboot のエントリポイント(_start)
CPU の状態
Function Status
Exception Level EL2
IRQ Mask
FIQ Mask
I-Cache Disable
D-Cache Disable
MMU Disable
メモリの状態
Load Address Size Description
0x40000000 40 qemu bootloader
0x40080000 65,536 qemu-boot-shim.bin
0x48000000 25,719,600 fucnshia-ssh.zbi+α
0x49800000 1,048,576 Device Tree Blob
0x49890000 659,088 physboot.zbi
  • DTB は fuchsia-ssh.zbi+α の α 部分にコピーされます

boot-shim.c의 개요

%%{init:{'theme':'base','themeVariables':{'primaryColor':'#6A7FAB','primaryTextColor':'#FAFBF9','primaryBorderColor':'#6A7FAB','lineColor':'#6A7FABCC','textColor':'#6A7FABCC','fontSize':'20px'}}}%%
graph TD

  bss(boot-shim.S) --> readdt[device treeからinitrdのアドレス取得]
  readdt --> readzbi["initrd(=ZBIデータ)からphysbootを探す"]
  readzbi --> writezbi["ZBIデータにボード情報を追加"]
  writezbi --> reloc["physbootをZBIデータの後方へコピー"]
  reloc --> return(boot-shim.Sへ戻る)

device tree에서 initrd 주소 가져오기

chosen {
        linux,initrd-end = < 0x497887e0 >;
        linux,initrd-start = < 0x48000000 >;
  • initrd(fuchia-ssh.zbi)의 마운트 주소 0x48000
  • 기타 정보
    initrd 이외에 device tree는 device만 필요합니다tree_context 구조체에 저장합니다.
    typedef struct {
      dt_slice_t devicetree;
      node_t node;
      uintptr_t initrd_start;
      size_t memory_base;
      size_t memory_size;
      char* cmdline;
      size_t cmdline_length;
      uint32_t cpu_count;
      int gic_version;
    } device_tree_context_t;
    
  • devicetreenodedevice tree 분석에 사용되는 임시 변수
  • initrd_startinitrd(fuchsia-ssh.zibi)의 마운트 주소
  • memory_basememory_sizeRAM의 시작 주소, 크기
  • cmdlinecmdline_length명령줄 옵션, 크기
  • cpu_countCPU 수
  • gic_versionGIC 버전
  • ZBI에서 physboot 찾기


    Name
    Size
    Description
    ZBI Header
    32
    ZBI의 Container Header
    Boot Item Header
    32
    physboot 헤더
    Boot Item Payload
    physboot용 Payload
    ...
    ZBI에서 최초 부트 Item이 유형ZBI_TYPE_KERNEL_ARM64(physboot)인지 확인합니다.

    ZBI 데이터에 섹션 정보 추가


    ZBI 데이터 끝에서 개별 부트 Item 추가 보드 정보로 사용합니다.
    ZBI에 추가된 정보는 다음과 같습니다.
    Boot Item Type
    Data
    Description
    ZBI_TYPE_CPU_TOPOLOGY
    cluster_id, cpu_id, ...
    CPU 토폴로지 정보
    ZBI_TYPE_NVRAM
    base, length
    예열 시작 시 데이터의 저장 영역을 유지합니다.충돌 로그에 사용
    ZBI_TYPE_KERNEL_DRIVER(KDRV_PL011_UART)
    mmio_phys,irq
    UART 드라이버 설정
    ZBI_TYPE_KERNEL_DRIVER(KDRV_ARM_GIC_V3)
    mmio_phys,gicd_offs,...
    Generic Interrupt Controller 드라이버 설정
    ZBI_TYPE_KERNEL_DRIVER(KDRV_ARM_PSCI)
    -
    Power State Coordination Interface 드라이버 설정
    ZBI_TYPE_KERNEL_DRIVER(KDRV_ARM_GENERIC_TIMER)
    irq_phys,irq_virt
    타이머 드라이버 설정
    ZBI_TYPE_PLATFORM_ID
    vendor_id,product_id
    공급업체 ID, 제품 ID
    ZBI_TYPE_SERIAL_NUMBER
    serial_number
    일련 번호
    ZBI_TYPE_MEM_CONFIG(ZBI_MEM_RANGE_PERIPHERAL)
    memory_base, memory_size
    주변 장치의 메모리 매핑 I/O 영역
    ZBI_TYPE_MEM_CONFIG(ZBI_MEM_RANGE_RAM)
    memory_base, memory_size
    RAM 영역
    ZBI_TYPE_CMDLINE
    cmdline
    명령줄 옵션
    ZBI_TYPE_DEVICETREE
    DTB
    Device Tree Blob
  • QEMU의 virt판에 제공된 드라이버 등 규정 타입 지정
  • DTB에서qemu 명령의 매개 변수에 의해 결정된 정보,qemu에 의해 결정된 정보
  • 추가 전 사이즈 246762320 → 추가 후 사이즈 257196600
    대부분 DTB
  • ZBI 데이터 뒤에 physboot 복사

    fuchsia-ssh.zbi 뒤에 있는 4KIB 경계로 복사합니다.
    +----------+-------------------+---------+--------+---------+
    |ZBI Header|Boot Item(physboot)|Boot Item|  ...   |Boot Item|
    +----------+-------------------+---------+--------+---------+
    |                              |                                         ^
    +--------------+---------------+                                         |
                   |                            copy                         |
                   +---------------------------------------------------------+
    

  • fuchsia-ssh.zbi+α
    %%{init:{'theme':'base','themeVariables':{'primaryColor':'#6A7FAB','primaryTextColor':'#FAFBF9', 'primaryBorderColor':'#6A7FAB','lineColor':'#fff','textColor':'#6A7FABCC','fontSize':'20px'}, 'flowchart':{'rankSpacing':1}}}%%
    graph LR
    classDef default stroke:#fff
    c["ZBI Header"]:::update --- b["Boot Item(physboot)"]:::update --- b2[Boot Item] --- b3[...]--- b4[Boot Item]
    classDef update fill:#F96A76,stroke:#fff
    그림의 빨간색 부분 (physboot.zbi라고 함) 을 주소 0x49890000에 복사합니다.
    복제된 대상 ZBI Header의 length를 업데이트합니다.
  • Address
    Description
    복제 소스
    0x48000000
    fucnshia-ssh.zbi+α
    복제 대상
    0x49890000
    physboot.zbi
    복사된 메모리
    Load Address
    Size
    Description
    0x48000000
    25,719,600
    fucnshia-ssh.zbi+α
    0x49890000
    659,088
    physboot.zbi

    총결산


  • QEMU와 실제 시스템의 차이점 흡수
  • physboot 이후 QEMU, 실기 모두 같은 코드를 실행
  • qemu-boot-shim 숨겨진 실기 U-Boot으로 처리

  • QEMU 준비 상태를 physboot 호출에 적합한 형식으로 변경
  • QEMU에서 준비한 device tree를 ZBI 데이터로 전송
  • 좋은 웹페이지 즐겨찾기