S61 · SOURCE-BOUND GATE EVIDENCE
SMP topology, PerCpu ve secondary-stack temeli host-only tamamlandı; fiziksel yol durduruldu
Operations --test hedefi → focused test içindeki include_str!/#[path] bağı → kaynak kesiti Bu sayfa yalnız S61 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.
S61Focused kod testiOperations id exactsource SHA exacttest target exact
operation: rpi5-g8e-smp-foundation-host-only
uygulama/model · focused test · Operations · 3 exact excerpt
sequence-bound=true · implementation-bound=false
01 · Testin bağlı olduğu uygulama/model kodu
Kapının yürüttüğü gerçek kaynak
tam dosyaL1–L401
kernel/src/arch/aarch64/boot.S::boot.S
// ASELSAN Microkernel - aarch64 Bootstrap
// QEMU virt makinesi için minimal EL1 giriş kodu
.section ".text.boot", "ax"
.global _start
_start:
// ========================================================================
// M8.1 — EL Detection + EL2 → EL1 Drop (Option A: minimal change)
// ========================================================================
//
// QEMU virt genellikle EL1'de başlar.
// Raspberry Pi 4/5 firmware genellikle EL2'de başlar.
//
// Bu blok:
// 1. x0 (DTB pointer) korunur (x19)
// 2. Secondary core'lar park edilir
// 3. CurrentEL okunur
// 4. Eğer EL2 ise → güvenli EL2→EL1 geçişi yapılır (ERET)
// 5. EL1'e düştükten sonra normal boot akışı devam eder.
// ========================================================================
// Boot protokolü: x0 = DTB physical address
mov x19, x0
// Park non-primary cores (MPIDR_EL1.Aff0 != 0).
mrs x1, mpidr_el1
and x1, x1, #0xff
cbz x1, primary_core
1:
wfe
b 1b
primary_core:
ldr x30, =__stack_top
mov sp, x30
.if ASELSAN_BOARD_RPI5
adr x0, rpi5_msg_boot0
bl rpi5_uart_puts
mrs x0, CurrentEL
lsr x0, x0, #2
add w0, w0, #'0'
adr x1, rpi5_msg_boot1_digit
strb w0, [x1]
adr x0, rpi5_msg_boot1
bl rpi5_uart_puts
.endif
// --- EL seviyesi kontrolü (M8.1 güçlendirilmiş) ---
mrs x0, CurrentEL
lsr x0, x0, #2 // x0 = EL seviyesi (0-3)
cmp x0, #3
b.eq el3_detected // Nadir ama savunmacı olalım
cmp x0, #2
b.eq el2_to_el1
cmp x0, #1
b.eq el1_direct
b unsupported_el // EL0'da privileged register yazma
// denemek yerine güvenli biçimde dur.
el2_to_el1:
// ========================================================================
// EL2 → EL1 Drop (Raspberry Pi 4 / gerçek donanım)
// ========================================================================
// Bu register sırası 2024-2026 RPi4 firmware'lerinde test edilmiş
// çalışan konfigürasyondur.
// ========================================================================
// 1. Timer erişimi
mov x0, #0x3
msr CNTHCTL_EL2, x0
msr CNTVOFF_EL2, xzr
// 2. FP/SIMD erişimi (context switch için kritik). Bazı firmware'ler
// CPTR_EL2.TFP'yi set bırakır; EL1'de CPACR_EL1 tek başına yetmez.
mrs x0, CPTR_EL2
bic x0, x0, #(1 << 10)
msr CPTR_EL2, x0
mov x0, #(3 << 20)
msr CPACR_EL1, x0
isb
// 3. HCR_EL2.RW = 1 (EL1 AArch64). EL2 exception handler kurulmadan
// AMO/IMO/FMO yönlendirme bitleri açılmaz.
mov x0, #(1 << 31)
msr HCR_EL2, x0
isb
// 4. SCTLR_EL1 - Armv8 RES1 tabanı, MMU + D/I cache kapalı.
// Tam değer: 0x0000000030d00800.
movz x0, #0x0800
movk x0, #0x30d0, lsl #16
msr SCTLR_EL1, x0
isb
// 5. Dönüş durumu: EL1h + tüm interrupt'lar maskeli
mov x0, #0x3c5 // EL1h | (DAIF << 6)
msr SPSR_EL2, x0
// 6. Dönüş adresi
adr x0, el1_after_drop
msr ELR_EL2, x0
// === Artık EL1'e düşüyoruz ===
eret
el1_after_drop:
// EL1'e başarıyla düştük.
// Bundan sonra SP_EL1'i doğru stack'e kurmalıyız.
// (linker'daki __stack_top EL1 stack'i olarak kullanılacak)
// SP_EL1 — EL2 stack'i ERET sonrası geçerli değildir.
ldr x30, =__stack_top
mov sp, x30
.if ASELSAN_BOARD_RPI5
adr x0, rpi5_msg_boot2
bl rpi5_uart_puts
.endif
b normal_boot_continue
el3_detected:
// EL3'ten geldik (çok nadir, genellikle ATF kullanıldığında).
// Şimdilik panic yerine basit WFI döngüsü (ileride EL3→EL1 de eklenebilir).
1:
wfi
b 1b
unsupported_el:
// Kernel EL0'da başlatılamaz. Ayrı bir exception seviyesi yükseltme
// mekanizması olmadan privileged register erişimine devam etmeyiz.
1:
wfe
b 1b
el1_direct:
// ========================================================================
// Normal EL1 boot yolu (QEMU veya zaten EL1'de olan sistemler). EL2
// yoluyla aynı FP ve SCTLR başlangıç sözleşmesini burada da kuruyoruz.
// ========================================================================
msr DAIFSet, #0xf
mov x0, #(3 << 20)
msr CPACR_EL1, x0
movz x0, #0x0800
movk x0, #0x30d0, lsl #16
msr SCTLR_EL1, x0
isb
ldr x30, =__stack_top
mov sp, x30
.if ASELSAN_BOARD_RPI5
adr x0, rpi5_msg_boot2
bl rpi5_uart_puts
.endif
normal_boot_continue:
// x19 hâlâ DTB pointer'ını tutuyor (BSS clear'dan önce korunmalı)
// İlk Rust UART/DTB/MMIO erişiminden önce geçerli bir vektör tablosu
// kur. Rust tarafındaki install_exception_vectors() bunu daha sonra
// tekrar doğrular; bu erken kurulum aradaki synchronous abort'ları da
// yakalanabilir hale getirir.
ldr x0, =__exception_vectors
msr VBAR_EL1, x0
isb
// BSS bölümünü sıfırla (C/Rust standartı)
ldr x0, =__bss_start
ldr x1, =__bss_end
bl zero_bss
// Rust giriş noktasına atla — x0 = DTB phys (boot protokolü)
mov x0, x19
bl _start_rust
// Rust dönmemeli. Dönerse sonsuz döngü
1:
wfi
b 1b
// BSS sıfırlama yardımcı fonksiyonu
// x0 = başlangıç, x1 = bitiş
zero_bss:
cmp x0, x1
b.eq 2f
1:
str xzr, [x0], #8
cmp x0, x1
b.lt 1b
2:
ret
.if ASELSAN_BOARD_RPI5
// UART10 PL011 at 0x107d001000. x0 = NUL-terminated string.
// Clobbers x0-x5. Firmware already set 115200 8N1.
rpi5_uart_puts:
mov x3, #0x1000
movk x3, #0x7d00, lsl #16
movk x3, #0x0010, lsl #32
10:
ldrb w2, [x0], #1
cbz w2, 12f
mov w4, #10000
11:
ldr w5, [x3, #0x18]
tbz w5, #5, 13f
subs w4, w4, #1
b.ne 11b
13:
str w2, [x3]
b 10b
12:
ret
rpi5_msg_boot0:
.ascii "ASELSAN/BOOT0 BCM2712\r\n"
.byte 0
rpi5_msg_boot1:
.ascii "ASELSAN/BOOT1 CurrentEL="
rpi5_msg_boot1_digit:
.ascii "?\r\n"
.byte 0
rpi5_msg_boot2:
.ascii "ASELSAN/BOOT2 EL1\r\n"
.byte 0
.endif
// ============================================================================
// SMP Secondary Core Entry Trampoline (2+3 yolu)
// ============================================================================
//
// QEMU virt + spin-table ile secondary core'lar bu entry point'te başlar.
// Amaç: Her secondary core kendi per-CPU kernel stack'ine geçsin, sonra
// Rust smp_spin_table_entry veya secondary_core_entry fonksiyonuna atlansın.
//
// Kayıt kullanımı:
// - x0 : çağrı sırasında CPU ID'si (opsiyonel, MPIDR'dan da okuyabiliriz)
// ============================================================================
.global smp_secondary_entry
smp_secondary_entry:
// Stack indeksinden önce tüm affinity alanlarını doğrula. Geçersiz bir
// MPIDR hiçbir koşulda modulo/taşma ile başka CPU'nun stack'ine alias olmaz.
mrs x6, mpidr_el1
.if ASELSAN_BOARD_RPI5
// BCM2712 CPU IDs are 0x000/0x100/0x200/0x300: logical index is Aff1.
ubfx x7, x6, #0, #8
cbnz x7, .Lsmp_secondary_park
ubfx x1, x6, #8, #8
ubfx x7, x6, #16, #8
cbnz x7, .Lsmp_secondary_park
ubfx x7, x6, #32, #8
cbnz x7, .Lsmp_secondary_park
.else
ubfx x1, x6, #0, #8 // x1 = cpu_id (0..3)
ubfx x7, x6, #8, #8
cbnz x7, .Lsmp_secondary_park
ubfx x7, x6, #16, #8
cbnz x7, .Lsmp_secondary_park
ubfx x7, x6, #32, #8
cbnz x7, .Lsmp_secondary_park
.endif
cbz x1, .Lsmp_secondary_park // CPU0 bu secondary entry'ye giremez
cmp x1, #4
b.hs .Lsmp_secondary_park
// Bu CPU için kernel stack top'unu hesapla
// PERCPU_KERNEL_STACKS.stacks[cpu_id].data + KERNEL_STACK_SIZE
//
// PERCPU_KERNEL_STACKS sembolünün adresini al.
// NOT: `adr` ±1 MiB ile sınırlı; PERCPU_KERNEL_STACKS .bss'te (MAX_EARLY_TABLES
// sonrası ~16+ MiB uzakta) → "relocation out of range". `adrp`+`add :lo12:`
// ile ±4 GiB erişim (page-relative + 12-bit offset).
adrp x2, PERCPU_KERNEL_STACKS
add x2, x2, :lo12:PERCPU_KERNEL_STACKS
// Her KernelStack = 16 KiB = 0x4000
mov x3, #0x4000
mul x4, x1, x3 // offset = cpu_id * 0x4000
add x5, x2, x4 // x5 = &stacks[cpu_id]
add x5, x5, #0x4000 // stack top (data sonu)
// Stack pointer'ı bu CPU'nun stack'ine kur
mov sp, x5
// Artık güvenli bir stack'imiz var. Rust fonksiyonuna geç.
// Rust'taki smp_spin_table_entry() çağır (loop içinde entry bekler)
bl smp_spin_table_entry
// Asla dönmemeli
1:
wfi
b 1b
.Lsmp_secondary_park:
wfe
b .Lsmp_secondary_park
// ============================================================================
// G8a Raspberry Pi 5 PSCI CPU1 Entry
// ============================================================================
// PSCI CPU_ON supplies x0=context_id. TF-A may enter the target at EL2 or EL1;
// both paths converge on masked EL1h without clearing shared BSS. BCM2712 uses
// MPIDR.Aff1 as its logical CPU index. The secondary enables CPU0's already
// published identity-mapped Stage-1 root before entering Rust.
.if ASELSAN_BOARD_RPI5
.global rpi5_g8_secondary_entry
.type rpi5_g8_secondary_entry, %function
rpi5_g8_secondary_entry:
msr DAIFSet, #0xf
mov x19, x0 // PSCI context_id
mrs x20, mpidr_el1
ubfx x22, x20, #8, #8 // BCM2712 logical CPU index
cmp x22, #3
b.hi .Lg8_secondary_park
adrp x2, PERCPU_KERNEL_STACKS
add x2, x2, :lo12:PERCPU_KERNEL_STACKS
mov x3, #0x4000
mul x4, x22, x3
add x21, x2, x4
add x21, x21, #0x4000
mrs x0, CurrentEL
lsr x0, x0, #2
cmp x0, #2
b.eq .Lg8_el2_to_el1
cmp x0, #1
b.eq .Lg8_el1_direct
b .Lg8_secondary_park
.Lg8_el2_to_el1:
mov x0, #0x3
msr CNTHCTL_EL2, x0
msr CNTVOFF_EL2, xzr
mov x0, #(1 << 31)
msr HCR_EL2, x0
msr CPACR_EL1, xzr // FP/SIMD stays trapped on CPU1
movz x0, #0x0800
movk x0, #0x30d0, lsl #16
msr SCTLR_EL1, x0
mov x0, #0x3c5 // EL1h, DAIF masked
msr SPSR_EL2, x0
adr x0, .Lg8_el1_ready
msr ELR_EL2, x0
isb
eret
.Lg8_el1_direct:
msr CPACR_EL1, xzr
movz x0, #0x0800
movk x0, #0x30d0, lsl #16
msr SCTLR_EL1, x0
isb
.Lg8_el1_ready:
mov sp, x21
msr TPIDR_EL1, x22
ldr x0, =__exception_vectors
msr VBAR_EL1, x0
isb
bl rpi5_g8_enable_secondary_mmu
mov x0, x19
mov x1, x20
bl rpi5_g8_secondary_rust
.Lg8_secondary_park:
wfe
b .Lg8_secondary_park
.size rpi5_g8_secondary_entry, . - rpi5_g8_secondary_entry
// G8c local stack-call trampoline.
//
// x0 = dedicated stack top, x1 = trusted task entry, x2 = task argument.
// The original CPU1 kernel SP is carried in ABI-preserved x19; x19 and the
// frame record remain only on the old kernel stack. No restore pointer is
// exposed on the task stack, and no global state or FP/SIMD register is
// touched. The task's x0 return value survives the stack restoration.
.global rpi5_g8c_call_on_stack
.type rpi5_g8c_call_on_stack, %function
rpi5_g8c_call_on_stack:
stp x29, x30, [sp, #-16]!
mov x29, sp
stp x19, xzr, [sp, #-16]!
mov x19, sp
mov sp, x0
mov x0, x2
blr x1
mov sp, x19
ldp x19, xzr, [sp], #16
ldp x29, x30, [sp], #16
ret
.size rpi5_g8c_call_on_stack, . - rpi5_g8c_call_on_stack
.endif
snippet sha256: 6d0444042af5…file sha256: 6d0444042af5…
02 · Doğrulayan test kodu
Operations komutuna bağlı focused test
tam Rust öğesiL53–L66
simulation/tests/rpi5_g8b_source.rs::secondary_el2_path_exposes_and_zero_offsets_the_virtual_timer
#[test]
fn secondary_el2_path_exposes_and_zero_offsets_the_virtual_timer() {
let trampoline = BOOT
.split("rpi5_g8_secondary_entry:")
.nth(1)
.expect("G8 secondary entry")
.split(".size rpi5_g8_secondary_entry")
.next()
.expect("bounded G8 trampoline");
assert!(trampoline.contains("msr CNTHCTL_EL2, x0"));
assert!(trampoline.contains("msr CNTVOFF_EL2, xzr"));
assert!(trampoline.contains("msr CPACR_EL1, xzr"));
}snippet sha256: befed9506e44…file sha256: 22d6f31b5440…
03 · Kapı kimlik kaydı
Operations sıra, kimlik ve başlık bağı
tam Operations kaydıL31451–L31536
website/src/lib/operations.ts::rpi5-g8e-smp-foundation-host-only
{
id: "rpi5-g8e-smp-foundation-host-only",
date: "2026-08-21",
sequence: 61,
status: "partial",
title:
"SMP topology, PerCpu ve secondary-stack temeli host-only tamamlandı; fiziksel yol durduruldu",
summary:
"Sıra 58'de görünür olan generic board-rpi5+smp derleme engelleri host-only kapsamda giderildi. PerCpu statikleri Clone gerektirmeyen dört bağımsız const değerle kuruluyor; BCM2712'nin Aff1 tabanlı 0x000/0x100/0x200/0x300 topolojisi fail-closed logical CPU decoder ile çözülüyor; modulo alias kaldırıldı ve secondary trampoline geçersiz affinity'yi stack hesabından önce park ediyor. RPi5/QEMU SMP ve non-SMP cargo check'leri, 38/38 hedefli simülasyon testi, non-SMP G8–G8d layout kapıları ve SMP ELF/disassembly denetimi geçti. Buna rağmen generic SMP fiziksel imaja dahil edilmedi: SMP ELF üzerinde eski G8b/G8c layout regex'leri en yakın .bss sembol etiketleri nedeniyle false-positive RED verdi; `_start` primary seçimi, güvenli scheduler/runqueue katılımı ve per-CPU timer/GIC yolu tamamlanmadan image/flash/runtime açılmadı.",
evidence: [
"Değişiklik kapsamı kernel/src/percpu.rs, kernel/src/task/scheduler.rs, kernel/src/ui/capability.rs ve generic kernel/src/arch/aarch64/boot.S:smp_secondary_entry ile sınırlı tutuldu.",
"SMP PerCpu::from_values(cpu0, cpu1, cpu2, cpu3) dört bağımsız sahipli değerle const-safe kuruldu; scheduler blocked-task ve endpoint registry slotları ayrı Vec::new() değerleri aldı.",
"Kullanılmayan KERNEL_STACKS kaldırıldı; assembly ABI'nin kullandığı PERCPU_KERNEL_STACKS korundu. SMP ELF'de sembol .bss altında exact 65,536 bayttır.",
"BCM2712 MPIDR decoder doğrulanmış 0x000/0x100/0x200/0x300 değerlerini CPU0–CPU3'e eşler; desteklenmeyen affinity None/panic ile reddedilir ve PerCpu checked indexing kullanır. `% MAX_CPUS` alias yolu yoktur.",
"Secondary trampoline Aff0/Aff2/Aff3=0 ve 1<=Aff1<4 koşullarını stack adresi/mul hesabından önce sınar; geçersiz secondary kimliği belleğe dokunmadan park edilir.",
"board-rpi5,smp; board-qemu,smp; board-rpi5 non-SMP ve board-qemu non-SMP cargo check koşularının dördü de exit 0 verdi.",
"G8 topology/source hedefleri rpi5_g8_contract, g8, g8b, g8c ve g8d testlerinde toplam 38/38 PASS verdi; git diff --check exit 0 tamamlandı.",
"Non-SMP RPi5 ELF üzerinde verify-rpi5-g8, g8b, g8c ve g8d layout kapıları 4/4 PASS verdi; SMP ELF link exit 0 ve branch-before-stack disassembly denetimi PASS verdi.",
"SMP ELF'de G8 ve G8d layout kapıları PASS; eski G8b/G8c regex'leri adreslerin en yakın .bss sembol etiketi nedeniyle false-positive RED verdi. Bu iki RED fiziksel runtime kabulü olarak görmezden gelinmedi.",
],
terminalSessionsNote:
"Bütün koşular host-only derleme, test ve disassembly denetimleridir. G8b/G8c SMP layout RED sonucu fail-closed STOP olarak saklanır; generic SMP image, microSD veya Pi üzerinde çalıştırılmadı.",
terminalSessions: [
{
id: "g8e-smp-foundation-build-matrix",
title: "RPi5/QEMU SMP ve non-SMP derleme matrisi",
commandLines: [
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-rpi5,smp",
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-qemu,smp",
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-rpi5",
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-qemu",
],
outputLines: [
"board-rpi5,smp cargo_check_exit=0",
"board-qemu,smp cargo_check_exit=0",
"board-rpi5 non-SMP cargo_check_exit=0",
"board-qemu non-SMP cargo_check_exit=0",
],
exitCode: 0,
outputMode: "complete",
},
{
id: "g8e-smp-foundation-contract-tests",
title: "Topology, source ve sahiplik sözleşmesi",
commandLines: [
"cargo test -p aselsan_microkernel_simulation --test rpi5_g8_contract --test rpi5_g8_source --test rpi5_g8b_source --test rpi5_g8c_source --test rpi5_g8d_source --quiet",
"git diff --check",
],
outputLines: [
"targeted simulation tests=38 pass=38 fail=0",
"MPIDR 0x000/0x100/0x200/0x300 -> CPU0/1/2/3",
"invalid affinity -> None/panic · modulo alias absent",
"git diff --check exit=0",
],
exitCode: 0,
outputMode: "selected",
},
{
id: "g8e-smp-foundation-layout-stop",
title: "ELF/disassembly kabulü ve fail-closed layout STOP",
commandLines: [
"non-SMP RPi5 verify-rpi5-g8/g8b/g8c/g8d layout",
"SMP ELF link + objdump branch/stack/symbol audit",
"SMP RPi5 verify-rpi5-g8/g8b/g8c/g8d layout",
],
outputLines: [
"non-SMP layouts=4/4 PASS",
"SMP ELF link=PASS · invalid-affinity branches precede stack calculation",
"PERCPU_KERNEL_STACKS .bss size=65536",
"SMP G8/G8d=PASS",
"SMP G8b/G8c=RED · old nearest-symbol regex false-positive",
"physical SMP gate=STOP",
],
exitCode: 1,
outputMode: "selected",
outputNote:
"Exit 1 iki eski SMP layout regex'inin false-positive reddidir; sonuç düzeltilmeden fiziksel kapı açılmadı.",
},
],
limitations: [
"Bu kayıt host-only foundation kanıtıdır; generic SMP fiziksel image, microSD yazımı, UART capture veya Pi runtime yapılmadı.",
"secondary_core_entry mevcut global unsafe scheduler'a katılmayacaktır; güvenli per-CPU runqueue/scheduler modeli ayrı bir kapıdır.",
"G8b/G8c SMP layout regex false-positive'leri sağlamlaştırılmadan generic SMP runtime gate yeşil sayılamaz.",
"BCM2712 `_start` primary seçimi hâlâ Aff0'a dayanır; scheduler/runqueue, per-CPU timer/GIC katılımı, TLB shootdown ve migration sonraki işlerdir.",
],
},snippet sha256: d05503245ed4…file sha256: 9726dbf00f84…
Focused test komutu
cargo test -p aselsan_microkernel_simulation --test rpi5_g8_contract --test rpi5_g8_source --test rpi5_g8b_source --test rpi5_g8c_source --test rpi5_g8d_source --quietRegistry schema v5 · generator
website/scripts/generate-code-gates.mjs · Tam SHA-256: 3050638b71a684d8f8f947a8a6faa237a17fa8db5dc0db04fb207b668b462af9