S157 · SOURCE-BOUND GATE EVIDENCE
G8i: per-CPU IRQ stack ve exception context ownership model
Operations --test hedefi → test hedefiyle aynı adlı uygulama/model modülü → kaynak kesiti Bu sayfa yalnız S157 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.
S157Focused kod testiOperations id exactsource SHA exacttest target exact
operation: g8i-per-cpu-irq-stack-context-model-partial
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 Rust öğesiL1–L129
simulation/src/g8i_exception_stack.rs::IRQ_STACK_DEPTH
//! G8i bounded per-CPU IRQ-stack and exception-context ownership model.
//!
//! This is the next source/model slice after the S156 dormant runtime. It
//! keeps exception frames on fixed per-CPU stacks, requires the exact CPU
//! owner for every mutation, and makes overflow/stale return fail closed. It
//! does not wire production AArch64 exception assembly or a live scheduler.
use crate::g8i_runqueue::{ExceptionFrame, MAX_CPUS};
pub const IRQ_STACK_DEPTH: usize = 4;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ExceptionStackError {
InvalidCpu,
ForeignMutation,
StackFull,
StackEmpty,
OwnerMismatch,
TaskAlreadyStackedOnAnotherCpu,
NestedTaskMismatch,
GenerationNotMonotonic,
}
pub struct PerCpuExceptionStackModel {
stacks: [[Option<ExceptionFrame>; IRQ_STACK_DEPTH]; MAX_CPUS],
last_generation: [u64; MAX_CPUS],
}
impl PerCpuExceptionStackModel {
pub const fn new() -> Self {
Self {
stacks: [[None; IRQ_STACK_DEPTH]; MAX_CPUS],
last_generation: [0; MAX_CPUS],
}
}
fn valid_cpu(cpu: usize) -> Result<(), ExceptionStackError> {
if cpu < MAX_CPUS {
Ok(())
} else {
Err(ExceptionStackError::InvalidCpu)
}
}
fn task_stack_owner(&self, task_id: u64) -> Option<usize> {
self.stacks.iter().enumerate().find_map(|(cpu, stack)| {
stack
.iter()
.flatten()
.any(|frame| frame.task_id == task_id)
.then_some(cpu)
})
}
pub fn enter(
&mut self,
caller_cpu: usize,
frame: ExceptionFrame,
) -> Result<(), ExceptionStackError> {
Self::valid_cpu(caller_cpu)?;
Self::valid_cpu(frame.owner_cpu)?;
if caller_cpu != frame.owner_cpu {
return Err(ExceptionStackError::ForeignMutation);
}
if self
.task_stack_owner(frame.task_id)
.is_some_and(|owner_cpu| owner_cpu != caller_cpu)
{
return Err(ExceptionStackError::TaskAlreadyStackedOnAnotherCpu);
}
if self.stacks[caller_cpu]
.iter()
.flatten()
.next()
.is_some_and(|active| active.task_id != frame.task_id)
{
return Err(ExceptionStackError::NestedTaskMismatch);
}
if frame.generation <= self.last_generation[caller_cpu] {
return Err(ExceptionStackError::GenerationNotMonotonic);
}
let slot = self.stacks[caller_cpu]
.iter_mut()
.find(|entry| entry.is_none())
.ok_or(ExceptionStackError::StackFull)?;
*slot = Some(frame);
self.last_generation[caller_cpu] = frame.generation;
Ok(())
}
pub fn leave(
&mut self,
caller_cpu: usize,
expected: ExceptionFrame,
) -> Result<(), ExceptionStackError> {
Self::valid_cpu(caller_cpu)?;
if expected.owner_cpu != caller_cpu {
return Err(ExceptionStackError::OwnerMismatch);
}
let top = self.stacks[caller_cpu]
.iter_mut()
.rev()
.find(|entry| entry.is_some())
.ok_or(ExceptionStackError::StackEmpty)?;
if *top != Some(expected) {
return Err(ExceptionStackError::OwnerMismatch);
}
*top = None;
Ok(())
}
pub fn depth(&self, cpu: usize) -> Result<usize, ExceptionStackError> {
Self::valid_cpu(cpu)?;
Ok(self.stacks[cpu]
.iter()
.filter(|entry| entry.is_some())
.count())
}
pub fn peek(&self, cpu: usize) -> Result<Option<ExceptionFrame>, ExceptionStackError> {
Self::valid_cpu(cpu)?;
Ok(self.stacks[cpu].iter().rev().find_map(|entry| *entry))
}
pub fn last_generation(&self, cpu: usize) -> Result<u64, ExceptionStackError> {
Self::valid_cpu(cpu)?;
Ok(self.last_generation[cpu])
}
}snippet sha256: 733922b46956…file sha256: fd60a4fa153a…
02 · Doğrulayan test kodu
Operations komutuna bağlı focused test
tam Rust öğesiL102–L114
simulation/tests/g8i_exception_stack.rs::stale_generation_is_rejected_without_mutation
#[test]
fn stale_generation_is_rejected_without_mutation() {
let mut stacks = PerCpuExceptionStackModel::new();
stacks.enter(0, frame(0, 51, 7)).unwrap();
assert_eq!(
stacks.enter(0, frame(0, 51, 7)),
Err(ExceptionStackError::GenerationNotMonotonic)
);
assert_eq!(stacks.depth(0), Ok(1));
assert_eq!(stacks.peek(0), Ok(Some(frame(0, 51, 7))));
assert_eq!(stacks.last_generation(0), Ok(7));
}snippet sha256: f13096b14c4c…file sha256: ee8a9bdd0ff3…
03 · Kapı kimlik kaydı
Operations sıra, kimlik ve başlık bağı
tam Operations kaydıL23690–L23730
website/src/lib/operations.ts::g8i-per-cpu-irq-stack-context-model-partial
{
id: "g8i-per-cpu-irq-stack-context-model-partial",
date: "2026-08-24",
sequence: 157,
status: "passed",
umbrella_status: "partial",
title: "G8i: per-CPU IRQ stack ve exception context ownership model",
summary:
"S157, S156 dormant runtime modelinin açık bıraktığı per-CPU IRQ stack sınırını bounded host model olarak kapattı: dört CPU, IRQ_STACK_DEPTH=4, exact owner push/pop, same-task nested LIFO, cross-CPU duplicate-task reddi, stale generation, foreign mutation, transactional overflow ve boş/invalid dönüş fail-closed kuralları 8/8 geçti. Production exception assembly, context switch, QEMU ve fiziksel runtime açılmadı.",
evidence: [
"g8i_exception_stack: 8/8 PASS; dört bağımsız stack, exact owner, foreign mutation reddi ve owner doğrulamalı return geçti.",
"Nested frame LIFO döndü; kapasite taşması mevcut frame'leri kaybetmeden reddedildi; stale generation ve invalid/empty dönüşler mutasyonsuz fail-closed kaldı.",
"Aynı task iki CPU IRQ stack'inde bulunamıyor; nested frame farklı task kimliği taşıyamıyor ve non-top return stack'i değiştirmeden reddediliyor.",
"Overflow denemesindeki yüksek generation commit edilmedi; top pop sonrası sıradaki monoton generation kabul edilerek sayaç transaction'ı doğrulandı.",
"Kalıcı kapsam: `docs/M8.1-RPi5-G8i-PerCpu-IRQ-Stack-Context-Proof.md`.",
"S157 fiziksel/device operasyonu yapmadı: physical/device operations=0 ve RUNBOOK_EXECUTED_IN_S157=NO.",
],
commands: [
"cargo test -p aselsan_microkernel_simulation --test g8i_exception_stack -- --test-threads=1",
],
terminalSessions: [
{
id: "s157-g8i-irq-stack-context-model",
title: "G8i per-CPU IRQ stack/context host model kapısı",
commandLines: [
"cargo test -p aselsan_microkernel_simulation --test g8i_exception_stack -- --test-threads=1",
],
outputLines: ["running 8 tests", "test result: ok. 8 passed; 0 failed"],
exitCode: 0,
outputMode: "selected",
},
],
terminalSessionsNote:
"S157 yalnız bounded host/model stack sözleşmesidir; production AArch64 exception assembly, scheduler/context switch, QEMU, fiziksel RPi ve generic SMP runtime sonucu değildir.",
limitations: [
"Gerçek per-CPU IRQ stack allocation, exception trampoline ve context switch production path'e bağlanmadı.",
"G8j shared-root/ASID0 migration, G8k ASID/TLB shootdown, QEMU ve fiziksel runtime sonraki kapılardır.",
"Generic SMP arbitration, CPU2/CPU3, hotplug, long soak ve signed product budgets kapsam dışıdır.",
"Fiziksel/device operations=0; RUNBOOK_EXECUTED_IN_S157=NO.",
],
},snippet sha256: 826cdbfa756d…file sha256: 9726dbf00f84…
Focused test komutu
cargo test -p aselsan_microkernel_simulation --test g8i_exception_stack -- --test-threads=1Registry schema v5 · generator
website/scripts/generate-code-gates.mjs · Tam SHA-256: 3050638b71a684d8f8f947a8a6faa237a17fa8db5dc0db04fb207b668b462af9