ASELSANMicrokernel
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: 6d0444042af5file 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: befed9506e44file 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: d05503245ed4file 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 --quiet
Registry schema v5 · generator website/scripts/generate-code-gates.mjs · Tam SHA-256: 91d38c7b6222f0b4c117be786454853543da55a160e543d9b951057cc20dcc06