TAIOS ARM64 İşletim Sistemi - Sıfırdan Geliştirme Faz 1 (Part 1)

.section .text.boot .global _start // Exception Vector Table .align 11 exception_vector_table: .rept 16 .align 7 b hang .endr _start: // Boot entry point // CPU initialization will follow...

boot.S Nedir? Neden Var?

boot.S, TAI-OS çekirdeğinin ilk çalışan (entry-stage) kodudur. Bu dosya:

  • CPU’yu tanımlı bir başlangıç durumuna getirir (interrupt maskeleri, istisna vektör tablosu vb.),
  • Mimariye özel ARM64 donanım kayıtlarını ayarlar,
  • Sonraki aşamada C koduna kernel güvenle geçişe zemin hazırlar.

Bu seviyede C çalışma zamanı henüz hazır değil. (stack, .bss temizliği, global init vs. yapılmamıştır). Bu yüzden boot aşamasında assembly tercih edilir. boot.S ayrıca linker script ile yakından ilişkilidir: kodun hangi bellek bölümüne yerleşeceğini, vektör tablosunun hizalamasını ve giriş sembolünü _start linker belirler.

Kısaca CPU’yu deterministik hale getir, minimum gereklileri kur, sonra C’ye bırak.

Önemli Notlar

  1. Dosya uzantısının .S (büyük S) olması GNU as’ın C-önişlemcisini de cpp çalıştırmasına izin verir ki böylelikle macro ve #define önişlemcileri kullanabilelim.
  2. ARM64 için aarch64-none-elf- veya aarch64-linux-gnu- toolchain’ler yaygındır.
  3. Linker, ENTRY(_start) ile giriş noktasını _start sembolüne bağlar.

Normal de tüm boot.S’i anlatacaktım ama bu kısma olanı anlatacağım ki, çok sıkıcı olmasın ki zaten yeterince sıkıcı oldu :D


Boot Entry’ye Kadar, Satır Satır Açıklama

1) Dosya üst bilgisi

// boot.S - ARM64 bootloader
  • Yalnızca bilgilendirme amaçlı bir yorum.

2) Özel kod bölümü seçimi

.section .text.boot

Bu direktif, derleyiciye ve linker’e bu kodun .text.boot isimli ayrı bir kod bölümüne konulacağını söyler.

Peki neden ayrı bir bölüm? Cevap: Linker script’te genelde şöyle bir blok olur:

.text.boot : { KEEP(*(.text.boot)) . = ALIGN(4096); } > RAM

3) Giriş sembolünü dışa açma

.global _start
  • _start etiketini global görünür yapar.
  • Linker, ENTRY(_start) ile program girişini bu sembole bağlar.

4) Exception Vektör Tablosu Başlığı

// Exception Vector Table .align 11 exception_vector_table:
  • Amaç: ARM64’te istisna (exception) vektör tablosu, 2048 bayt hizalı bir adreste olmalıdır.
  • exception_vector_table: etiketi, tablonun başlangıç adresini belirler.

Not: Bazı platformlarda .align 2^n hizalama iken bazılarında n bayt hizalama davranabilir. ARM64 tarafında 2^n olarak çalışır; en güvenlisi .balign 2048 kullanmaktır. Eğitim metninde .align 11 yeterli, ama üretimde: .balign 2048 olmalı.

Bu tabloyu .vectors gibi ayrı bir bölüme koyup linker’da

.vectors ALIGN(2048) : { KEEP(*(.vectors)) }

ile çöp toplayıcıdan korunmuş ve zorunlu hizalanmış hale getirmek iyi pratiktir. Bu örnekte tablo .text.boot içindedir; yine de hizalama garantili olduğu sürece sorun yok.

5) 16 Adet Vektör Slotu Üretme

.rept 16 .align 7 b hang .endr

Bu blok, 16 adet vektör girişini minimal bir “iskele” ile üretir:

.rept 16, .endr: İçerideki talimatları 16 kez tekrarlar. ARMv8-A, AArch64 vektör tablosunun 16 slotu vardır:

Slot Exception Type Source
0-3 Current EL with SP_EL0 Sync, IRQ, FIQ, SError
4-7 Current EL with SP_ELx Sync, IRQ, FIQ, SError
8-11 Lower EL (AArch64) Sync, IRQ, FIQ, SError
12-15 Lower EL (AArch32) Sync, IRQ, FIQ, SError

.align 7 → 2^7 = 128 bayt hizalama: ARM64’te her vektör girişi 128 baytlık bir slot kabul edilir. Burada her tekrarın başında hizalama ile bir sonraki 128 bayt sınırına atlanır.

b hang: Her slotun ilk talimatı, şimdilik basitçe hang fonksiyonuna dalan bir branch. Bu minimalist yaklaşım şunları garanti eder:

  1. Her istisna, geçici olarak aynı “bekleme” döngüsüne yönlendirilir (sistem donmaz, kontrol sizde kalır).
  2. Slotların geri kalan padding alanı, .align sayesinde otomatik doldurulur; böylece bir sonraki slot tam 128 bayt sınırında başlar

Not: “128 bayt slot = 128 bayt kod yazmak zorundasın” demek değildir. İlk komut (branch) fiilen birkaç bayt; kalan alan hizalama dolgusu. Donanım, slot başlangıcındaki kodu yürütür; içeride daha sonra ister ayrıntılı handler, ister kayıt dökümü koyabilirsiniz.

Bu tarz doldurmalar genelde kriptografide de vardır ama konumuz bu değil. Konu bu değil olm, konu bu değil :D

Bu Noktada Ne Oldu?

  • Vektör tablosu 2048B hizayla belleğe yerleştirildi.
  • İçinde 16 adet, 128B hizalı slot üretildi.
  • Tüm slotlar, şimdilik güvenli bir yere (sonsuz bekleme döngüsü hang) branch ediyor.
  • Henüz VBAR_EL1, EL2, EL3 gibi kayıtlar ayarlanmadı (bu, Boot Entry’den sonra yapılacak iş). Yani tabloyu oluşturduk, ama CPU’ya “vektör tabanın bu” demedik. O kısım _start sonrasındaki init aşamasında.

Devamı Gelecek…

Gördüğünüz gibi, BOOT ENTRY kısmına anca gelebildik. Ama burada duralım onu diğer makaleye bırakalım. Eğer ikinci makaleye geçerseniz, bu işi sevdiniz demektir. Bırakırsanız da çok normal, çünkü çok sıkıcı :D

Boot Entry kısmı da şu şekilde gözükecek en azından fikir olması açısından:

_start: // Set exception level and stack pointer msr daifset, #0xF // Disable all interrupts // Set up temporary stack adr x0, stack_top mov sp, x0 // Clear BSS section bl clear_bss // Jump to C kernel bl kernel_main // Should never reach here b hang hang: wfe b hang

Bu serinin devamında CPU initialization, memory management, ve C runtime setup’ını detaylı olarak inceleyeceğiz. ARM64’ün güzelliklerini ve Apple Internals’in derinliklerini birlikte keşfedeceğiz.

Sonraki bölümde: Exception Level management, Stack pointer setup, ve BSS section clearing işlemlerini göreceğiz.


Kaynaklar