GELİŞTİRME GÜNLÜĞÜ
M1 — Exception & Timer
M1.1
Exception Vector Table
19 Mayıs 2026 • aynı gün
QEMU'da DOĞRULANDI
Yapılanlar
- 16 entry'lik aarch64 vektör tablosu (2 KB hizalı)
-
SAVE_CONTEXT/RESTORE_CONTEXTtrampoline'ları (x0–x30 + ELR + SPSR) - Rust handler'lar (sync / IRQ / FIQ / SError / invalid)
- VBAR_EL1 kurulumu + ESR.EC decode'u
-
brk #0xdeadile sync exception → handler →eretbaşarılı
QEMU UART çıktısı
[BOOT] Şu anki Exception Level: EL1 [M1.1] VBAR_EL1 = 0x0000000040000800 [M1.1] Exception handler'lar aktif. [TEST] Sync exception tetikleniyor (brk #0xdead)... [EXC] ----- Senkron exception (EL1, SP_ELx) ----- ESR_EL1 = 0xf200dead (EC=0x3c → BRK) FAR_EL1 = 0x0000000000000000 ELR_EL1 = 0x00000000400025b8 [EXC] BRK #0xdead yakalandı. Sonrakine atlanıyor. [TEST] Exception'dan başarıyla geri döndük. [OK] M1.1 doğrulandı.
kernel/src/arch/aarch64/exceptions.S •exceptions.rs •mod.rs
Karşılaşılan zorluklar:Cargo workspace içinde
target/ dizini kernel altında değil workspace kökündeydi (Makefile düzeltildi). .cargo/config.tomliçinde [target.aarch64-unknown-none] iki kez tanımlanmıştı — birleştirildi. Vektör tablosunun 0x800 hizalı olması için linker script'e açıkALIGN(0x800) + ayrı .text.exceptionsbölümü eklendi.M1.2
Çalışan Exception Handler — EC-bazlı policy
19 Mayıs 2026 • aynı gün
3/3 PATH DOĞRULANDI
Yapılanlar
-
trigger_brk(),trigger_svc(),trigger_undefined()test API'si - Sync handler'a
match ectabanlı policy - BRK (EC=0x3c) → recover, ELR += 4
- SVC (EC=0x15) → recover (HW otomatik), imm16 logla
- UDF (EC=0x00) → panic, dump_context
- Data Abort (EC=0x25) ve Instruction Abort (EC=0x21) için panic path'leri hazır (FAR_EL1 raporlu)
QEMU UART çıktısı
[TEST] (1/3) BRK — brk #0xdead [EXC] BRK #0xdead (EC=0x3c) — recover (ELR += 4) [TEST] (1/3) BRK'tan geri döndük. OK. [TEST] (2/3) SVC — svc #0x42 [EXC] SVC #0x0042 (EC=0x15) — supervisor call [TEST] (2/3) SVC'den geri döndük. OK. [TEST] (3/3) UDF — udf #0xbeef [EXC] !!! UNDEFINED / UNKNOWN INSTRUCTION !!! ESR_EL1 = 0x02000000 ELR = 0x400027a4 !!! KERNEL PANIC !!! Dosya: kernel/src/arch/aarch64/exceptions.rs:120 Mesaj: undefined instruction
kernel/src/arch/aarch64/exceptions.rs •mod.rs • kernel/src/main.rs
Karşılaşılan zorluk:İlk denemede
core::ptr::write_volatile(null) ile data abort tetiklemeye çalıştım, ama MMU henüz aktif olmadığı için (M2'de gelecek) QEMU bunu silent geçti — kernel devam etti. Çözüm: panic path'ini gerçek-data-abort yerine udf #0xbeefile test ettim. Gerçek MMU-bazlı data abort'u M2'de ekleyeceğiz; handler kodu zaten hazır.M1.3
ARM Generic Timer + GICv2 — Periyodik IRQ
19 Mayıs 2026 • aynı gün • ilk denemede çalıştı
TICK ZİNCİRİ TAM
Yapılanlar
-
gic.rs— GICv2 (GICD @0x0800_0000, GICC @0x0801_0000) init +enable_irq+ ack/eoi -
timer.rs— CNTV:CNTFRQ_EL0oku,CNTV_TVAL_EL0arm,CNTV_CTL_EL0=0b01 -
rust_irq_handler— IAR oku → timer (PPI 27) ise ack+rearm+tick++ → EOIR -
enable_irqs()/disable_irqs()— DAIF.I helper'ları - Atomic
TICKSsayacı (M3 scheduler için temel)
QEMU UART çıktısı
[M1.3] GICv2 init: GICD@0x08000000, GICC@0x08010000 [M1.3] CNTFRQ_EL0 = 62500000 Hz → 2 Hz tick (her tick 31250000 count) [M1.3] GICD ISENABLER: PPI 27 aktif [M1.3] DAIF.I = 0 → IRQ'lar açıldı. [OK] Kernel idle döngüsü (wfi). Timer bekleniyor... [TICK 1] virtual timer (PPI 27) [TICK 2] virtual timer (PPI 27) [TICK 3] virtual timer (PPI 27) [TICK 4] virtual timer (PPI 27) ... [TICK 11] virtual timer (PPI 27)
kernel/src/arch/aarch64/gic.rs •timer.rs •exceptions.rs •mod.rs
Niçin önemli:Artık kernel'ın bir "kalbi" var. Periyodik IRQ olmadan preemptive scheduler kurulamaz — M3'ün ön şartı bu. Şu anda
wfi ile uyuyor, sadece timer IRQ ile uyanıp tick basıyor, sonra tekrar uyuyor. Tam zincir:timer → GIC → vector → SAVE → Rust → EOI → RESTORE → eret → wfi.M1.4
100 Hz drift-free tick + irq_lock!
19 Mayıs 2026 • M1 KAPANDI
~600× DRIFT İYİLEŞMESİ
Yapılanlar
- TICK_HZ 2 → 100 Hz
- UART log her tick yerine her 1 saniyede "[SEC n]" özeti
- Jitter ölçümü:
CNTVCT_EL0ile expected vs actual drift (µs) - TVAL → CVAL geçişi: mutlak compare register, handler latency'si birikmiyor
-
IrqGuardRAII +irq_lock!()makrosu — scope-bazlı kritik bölge (M3 scheduler kuyrukları için)
TVAL → CVAL etkisi
| Süre | TVAL (eski) | CVAL (yeni) |
|---|---|---|
| 1 sn | +19 661 µs | +127 µs |
| 3 sn | +50 820 µs | +166 µs |
| 6 sn | +100 533 µs | +118 µs |
| Eğilim | lineer ↑ | sabit |
QEMU UART çıktısı (CVAL ile)
[M1.3] CNTFRQ_EL0 = 62500000 Hz → 100 Hz tick (her tick 625000 count) [M1.3] GICD ISENABLER: PPI 27 aktif [M1.3] DAIF.I = 0 → IRQ'lar açıldı. [M1.4] Saniyelik özet aktif. [OK] Kernel idle döngüsü (wfi). Timer bekleniyor... [SEC 1] ticks=100 drift=+127 µs (+7957 count) [SEC 2] ticks=200 drift=+121 µs (+7579 count) [SEC 3] ticks=300 drift=+166 µs (+10410 count) [SEC 4] ticks=400 drift=+173 µs (+10868 count) [SEC 5] ticks=500 drift=+97 µs (+6108 count) [SEC 6] ticks=600 drift=+118 µs (+7405 count)
kernel/src/arch/aarch64/timer.rs •exceptions.rs •mod.rs (IrqGuard)
Niçin TVAL biriktiriyordu:Handler her tetiklendiğinde "şu andan {period} sayım sonra tekrar tetikle" diyordu — handler içinde geçen her µs bir sonraki tick'i o kadar geciktirip kalıcı borç oluşturuyordu. CVAL ile "mutlak hedef = bir önceki hedef + period" diyoruz; latency artık tek-tick'lik gecikme olur, bir sonraki tick'i etkilemez. Bu, scheduler için tek-tick jitter'ı toplam ms'lik kayma yapmadan tolere etmemizi sağlıyor.