S408 · SOURCE-BOUND GATE EVIDENCE
S408 · Live offer SGI sender
tam S408 implementation modülü → Operations --test hedefi ile bağlı tam focused test → ayrı Operations kaydı Bu sayfa yalnız S408 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.
S408Focused kod testiOperations id exactsource SHA exacttest target exact
operation: g8l-s408-live-offer-sgi-sender-partial
uygulama/model · focused test · Operations · 3 exact excerpt
sequence-bound=true · implementation-bound=true
01 · Yürütme / doğrulama kodu
Kapının gerçek repository sözleşmesi
tam dosyaL1–L359
kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender.rs::S408 live offer sgi sender implementation
#![allow(unexpected_cfgs)]
//! S408 dedicated SGI3 sender for a live S407 exclusion offer.
//!
//! SGI1 belongs to G8d/G8e and SGI2 to S240. S408 reserves dedicated SGI3,
//! prepares CPU0 during boot, and permits send only while the S407 wrapper is
//! live. IRQ validation/EOI, admission, and physical observation remain open.
use crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s407_live_exclusion_offer_publication::{
G8lS407OfferedScopedProviderAuthority, S407_DIRECT_SCHEDULER_ACCESS_SITES,
S407_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES, S407_SOURCE_AUDIT_UNITS,
S407_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES, S407_UNROUTED_DIRECT_ACCESS_SITES,
};
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
use crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s407_live_exclusion_offer_publication::G8lS407ProductionOfferedScopedProviderAuthority;
pub const S408_SOURCE_AUDIT_UNITS: usize = S407_SOURCE_AUDIT_UNITS;
pub const S408_DIRECT_SCHEDULER_ACCESS_SITES: usize = S407_DIRECT_SCHEDULER_ACCESS_SITES;
pub const S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES: usize =
S407_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES;
pub const S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES: usize =
S407_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES;
pub const S408_UNROUTED_DIRECT_ACCESS_SITES: usize = S407_UNROUTED_DIRECT_ACCESS_SITES;
pub const S408_SGI_INTID: u32 = 3;
pub const S408_SOURCE_CPU1: usize = 1;
pub const S408_TARGET_CPU0: usize = 0;
pub const S408_TARGET_LIST_CPU0: u8 = 0x01;
pub const S408_EXPECTED_ENABLE: u32 = 1u32 << S408_SGI_INTID;
pub const S408_EXPECTED_COMMAND: u32 = ((S408_TARGET_LIST_CPU0 as u32) << 16) | S408_SGI_INTID;
pub const S408_EXPECTED_RAW_ACK: u32 = ((S408_SOURCE_CPU1 as u32) << 10) | S408_SGI_INTID;
pub const S408_PRODUCTION_RECEIVER_PREPARE_CALLSITES: usize = 1;
pub const S408_PRODUCTION_SENDER_INVOCATION_CALLSITES: usize = 0;
pub const S408_IRQ_DELIVERY_COMPLETE: bool = false;
pub const S408_END_TO_END_EXCLUSION_ADMISSION_COMPLETE: bool = false;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS408LiveOfferSgiPhase {
Idle,
ReceiverReady,
Sent,
Failed,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS408LiveOfferSgiError {
InvalidPhase,
WrongReceiverCpu,
WrongSenderCpu,
WrongExpectedSourceCpu,
SgiNotEnabled,
WrongTargetList,
PendingSourceNotClear,
OfferNotLive,
OfferBindingDrift,
WrongCommand,
SendReceiptNotDrained,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS408LiveOfferSgiSendReceipt {
command: u32,
attempt_id: u64,
provider_request_id: u64,
exclusive_token: u64,
}
impl G8lS408LiveOfferSgiSendReceipt {
pub const fn command(&self) -> u32 {
self.command
}
pub const fn attempt_id(&self) -> u64 {
self.attempt_id
}
pub const fn provider_request_id(&self) -> u64 {
self.provider_request_id
}
pub const fn exclusive_token(&self) -> u64 {
self.exclusive_token
}
pub const fn offer_was_live_at_send(&self) -> bool {
true
}
}
#[derive(Debug)]
pub struct G8lS408LiveOfferSgiSenderState {
phase: G8lS408LiveOfferSgiPhase,
command: u32,
}
impl G8lS408LiveOfferSgiSenderState {
pub const fn new() -> Self {
Self {
phase: G8lS408LiveOfferSgiPhase::Idle,
command: 0,
}
}
pub const fn phase(&self) -> G8lS408LiveOfferSgiPhase {
self.phase
}
pub fn prepare_receiver(
&mut self,
receiver_cpu: usize,
expected_source_cpu: usize,
enabled: u32,
target_list: u8,
pending_sources: u8,
) -> Result<(), G8lS408LiveOfferSgiError> {
if self.phase != G8lS408LiveOfferSgiPhase::Idle {
return Err(G8lS408LiveOfferSgiError::InvalidPhase);
}
if receiver_cpu != S408_TARGET_CPU0 {
return Err(G8lS408LiveOfferSgiError::WrongReceiverCpu);
}
if expected_source_cpu != S408_SOURCE_CPU1 {
return Err(G8lS408LiveOfferSgiError::WrongExpectedSourceCpu);
}
if enabled != S408_EXPECTED_ENABLE {
return Err(G8lS408LiveOfferSgiError::SgiNotEnabled);
}
if target_list != S408_TARGET_LIST_CPU0 {
return Err(G8lS408LiveOfferSgiError::WrongTargetList);
}
if pending_sources & (1u8 << S408_SOURCE_CPU1) != 0 {
return Err(G8lS408LiveOfferSgiError::PendingSourceNotClear);
}
self.phase = G8lS408LiveOfferSgiPhase::ReceiverReady;
Ok(())
}
fn begin_send(
&mut self,
sender_cpu: usize,
attempt_id: u64,
provider_request_id: u64,
exclusive_token: u64,
command: u32,
) -> Result<G8lS408LiveOfferSgiSendReceipt, G8lS408LiveOfferSgiError> {
if self.phase != G8lS408LiveOfferSgiPhase::ReceiverReady {
return Err(G8lS408LiveOfferSgiError::InvalidPhase);
}
if sender_cpu != S408_SOURCE_CPU1 {
self.phase = G8lS408LiveOfferSgiPhase::Failed;
return Err(G8lS408LiveOfferSgiError::WrongSenderCpu);
}
if attempt_id == 0 || provider_request_id == 0 || exclusive_token == 0 {
self.phase = G8lS408LiveOfferSgiPhase::Failed;
return Err(G8lS408LiveOfferSgiError::OfferBindingDrift);
}
if command != S408_EXPECTED_COMMAND {
self.phase = G8lS408LiveOfferSgiPhase::Failed;
return Err(G8lS408LiveOfferSgiError::WrongCommand);
}
self.command = command;
self.phase = G8lS408LiveOfferSgiPhase::Sent;
Ok(G8lS408LiveOfferSgiSendReceipt {
command,
attempt_id,
provider_request_id,
exclusive_token,
})
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
fn fail_terminal(&mut self) {
self.phase = G8lS408LiveOfferSgiPhase::Failed;
}
pub fn rearm_after_drained_attempt(
&mut self,
send_receipt_pending: bool,
) -> Result<(), G8lS408LiveOfferSgiError> {
if send_receipt_pending {
return Err(G8lS408LiveOfferSgiError::SendReceiptNotDrained);
}
match self.phase {
G8lS408LiveOfferSgiPhase::ReceiverReady => Ok(()),
G8lS408LiveOfferSgiPhase::Sent | G8lS408LiveOfferSgiPhase::Failed => {
self.command = 0;
self.phase = G8lS408LiveOfferSgiPhase::ReceiverReady;
Ok(())
}
G8lS408LiveOfferSgiPhase::Idle => Err(G8lS408LiveOfferSgiError::InvalidPhase),
}
}
}
impl Default for G8lS408LiveOfferSgiSenderState {
fn default() -> Self {
Self::new()
}
}
pub fn service_s408_model_live_offer_sgi_send(
sender: &mut G8lS408LiveOfferSgiSenderState,
caller_cpu: usize,
offered: &G8lS407OfferedScopedProviderAuthority<'_, '_>,
) -> Result<G8lS408LiveOfferSgiSendReceipt, G8lS408LiveOfferSgiError> {
if !offered.offer_pending()
|| !offered.is_provider_authority()
|| !offered.whole_scheduler_exclusion_proven()
{
return Err(G8lS408LiveOfferSgiError::OfferNotLive);
}
let offer = offered.offer();
if offer.source_cpu != S408_SOURCE_CPU1
|| offer.target_cpu != S408_TARGET_CPU0
|| !offer.requires_live_gate_match
|| offer.is_authority
|| offer.whole_scheduler_exclusion_proven
{
return Err(G8lS408LiveOfferSgiError::OfferBindingDrift);
}
sender.begin_send(
caller_cpu,
offer.attempt_id,
offer.provider_request_id,
offer.exclusive_token,
S408_EXPECTED_COMMAND,
)
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
static S408_PRODUCTION_SGI_SENDER: spin::Mutex<G8lS408LiveOfferSgiSenderState> =
spin::Mutex::new(G8lS408LiveOfferSgiSenderState::new());
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
static S408_PRODUCTION_SEND_RECEIPT: spin::Mutex<Option<G8lS408LiveOfferSgiSendReceipt>> =
spin::Mutex::new(None);
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
#[derive(Debug)]
pub enum G8lS408ProductionSgiError {
WrongCpu,
State(G8lS408LiveOfferSgiError),
Gic(&'static str),
CommandReadbackMismatch,
SendReceiptPending,
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn prepare_s408_live_offer_sgi_receiver_on_cpu0() -> Result<(), G8lS408ProductionSgiError> {
use crate::g8l_runtime_contract::CPU0;
if crate::percpu::try_current_cpu_id() != Some(CPU0) {
return Err(G8lS408ProductionSgiError::WrongCpu);
}
let _irq_guard = crate::arch::aarch64::IrqGuard::new();
let gic_state = crate::arch::aarch64::gic::rpi5_g8d_init_secondary_sgi(
S408_SGI_INTID,
S408_SOURCE_CPU1 as u32,
)
.map_err(G8lS408ProductionSgiError::Gic)?;
S408_PRODUCTION_SGI_SENDER
.lock()
.prepare_receiver(
CPU0,
S408_SOURCE_CPU1,
gic_state.enabled,
gic_state.target_list,
gic_state.pending_sources,
)
.map_err(G8lS408ProductionSgiError::State)
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn send_s408_live_offer_sgi_from_cpu1(
offered: &G8lS407ProductionOfferedScopedProviderAuthority,
) -> Result<u32, G8lS408ProductionSgiError> {
use crate::g8l_runtime_contract::CPU1;
if crate::percpu::try_current_cpu_id() != Some(CPU1) {
return Err(G8lS408ProductionSgiError::WrongCpu);
}
if !offered.offer_pending()
|| !offered.is_provider_authority()
|| !offered.whole_scheduler_exclusion_proven()
{
return Err(G8lS408ProductionSgiError::State(
G8lS408LiveOfferSgiError::OfferNotLive,
));
}
let offer = offered.offer();
let receipt = S408_PRODUCTION_SGI_SENDER
.lock()
.begin_send(
CPU1,
offer.attempt_id,
offer.provider_request_id,
offer.exclusive_token,
S408_EXPECTED_COMMAND,
)
.map_err(G8lS408ProductionSgiError::State)?;
{
let mut slot = S408_PRODUCTION_SEND_RECEIPT.lock();
if slot.is_some() {
return Err(G8lS408ProductionSgiError::SendReceiptPending);
}
*slot = Some(receipt);
}
let command =
match crate::arch::aarch64::gic::rpi5_g8d_send_sgi(S408_SGI_INTID, S408_TARGET_LIST_CPU0) {
Ok(command) => command,
Err(error) => {
S408_PRODUCTION_SEND_RECEIPT.lock().take();
S408_PRODUCTION_SGI_SENDER.lock().fail_terminal();
return Err(G8lS408ProductionSgiError::Gic(error));
}
};
if command != S408_EXPECTED_COMMAND {
S408_PRODUCTION_SEND_RECEIPT.lock().take();
S408_PRODUCTION_SGI_SENDER.lock().fail_terminal();
return Err(G8lS408ProductionSgiError::CommandReadbackMismatch);
}
Ok(command)
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn take_s408_live_offer_sgi_send_receipt_on_cpu0(
) -> Result<Option<G8lS408LiveOfferSgiSendReceipt>, G8lS408ProductionSgiError> {
use crate::g8l_runtime_contract::CPU0;
if crate::percpu::try_current_cpu_id() != Some(CPU0) {
return Err(G8lS408ProductionSgiError::WrongCpu);
}
Ok(S408_PRODUCTION_SEND_RECEIPT.lock().take())
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn s408_production_send_receipt_pending_on_cpu1() -> Result<bool, G8lS408ProductionSgiError> {
use crate::g8l_runtime_contract::CPU1;
if crate::percpu::try_current_cpu_id() != Some(CPU1) {
return Err(G8lS408ProductionSgiError::WrongCpu);
}
Ok(S408_PRODUCTION_SEND_RECEIPT.lock().is_some())
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn s408_production_sender_phase_on_cpu1(
) -> Result<G8lS408LiveOfferSgiPhase, G8lS408ProductionSgiError> {
use crate::g8l_runtime_contract::CPU1;
if crate::percpu::try_current_cpu_id() != Some(CPU1) {
return Err(G8lS408ProductionSgiError::WrongCpu);
}
Ok(S408_PRODUCTION_SGI_SENDER.lock().phase())
}
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn rearm_s408_live_offer_sgi_sender_on_cpu1() -> Result<(), G8lS408ProductionSgiError> {
use crate::g8l_runtime_contract::CPU1;
if crate::percpu::try_current_cpu_id() != Some(CPU1) {
return Err(G8lS408ProductionSgiError::WrongCpu);
}
let pending = S408_PRODUCTION_SEND_RECEIPT.lock().is_some();
S408_PRODUCTION_SGI_SENDER
.lock()
.rearm_after_drained_attempt(pending)
.map_err(G8lS408ProductionSgiError::State)
}
snippet sha256: fe0632ee5590…file sha256: fe0632ee5590…
02 · Doğrulayan test kodu
Operations komutuna bağlı focused test
tam dosyaL1–L321
simulation/tests/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender.rs::S408 live offer sgi sender focused tests
#![recursion_limit = "256"]
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s244_whole_scheduler_exclusion_admission_request::{
service_s245_exclusion_admission_request, G8lS245ExclusionAdmissionRequestOutcome,
G8lS245WholeSchedulerExclusionAdmissionRequestState, S245_SOURCE_CPU0, S245_TARGET_CPU1,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s246_whole_scheduler_read_access_guard::G8lS247WholeSchedulerAccessGate;
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s402_provider_invocation_observation_publication::{
service_s402_model_provider_invocation_observation_publication,
G8lS402ProviderInvocationObservationState,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s404_scoped_authority_request_publication::{
service_s404_model_scoped_authority_request_publication,
G8lS404ScopedAuthorityRequestState,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s407_live_exclusion_offer_publication::{
try_publish_s407_model_live_exclusion_offer, G8lS407LiveExclusionOfferState,
S407_DIRECT_SCHEDULER_ACCESS_SITES, S407_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES,
S407_SOURCE_AUDIT_UNITS, S407_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES,
S407_UNROUTED_DIRECT_ACCESS_SITES,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender::*;
fn paired_states() -> (
G8lS247WholeSchedulerAccessGate,
G8lS245WholeSchedulerExclusionAdmissionRequestState,
G8lS404ScopedAuthorityRequestState,
) {
let gate = G8lS247WholeSchedulerAccessGate::new();
let mut providers = G8lS245WholeSchedulerExclusionAdmissionRequestState::new();
service_s245_exclusion_admission_request(&mut providers, S245_SOURCE_CPU0, true, true).unwrap();
let mut observations = G8lS402ProviderInvocationObservationState::new();
service_s402_model_provider_invocation_observation_publication(
&mut observations,
&gate,
&mut providers,
S245_TARGET_CPU1,
)
.unwrap();
let mut scoped = G8lS404ScopedAuthorityRequestState::new();
service_s404_model_scoped_authority_request_publication(
&mut scoped,
&mut observations,
S245_SOURCE_CPU0,
)
.unwrap();
assert_eq!(
service_s245_exclusion_admission_request(&mut providers, S245_SOURCE_CPU0, true, true),
Ok(G8lS245ExclusionAdmissionRequestOutcome::RequestPublished(2))
);
(gate, providers, scoped)
}
fn module_source() -> &'static str {
include_str!("../../kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender.rs")
}
fn kernel_main_source() -> &'static str {
include_str!("../../kernel/src/main.rs")
}
fn exception_source() -> &'static str {
include_str!("../../kernel/src/arch/aarch64/exceptions.rs")
}
fn simulation_lib_source() -> &'static str {
include_str!("../src/lib.rs")
}
#[test]
fn constants_assign_dedicated_sgi3_without_promoting_delivery() {
assert_eq!(S408_SOURCE_AUDIT_UNITS, 7);
assert_eq!(S408_DIRECT_SCHEDULER_ACCESS_SITES, 113);
assert_eq!(S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES, 113);
assert_eq!(S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES, 113);
assert_eq!(S408_UNROUTED_DIRECT_ACCESS_SITES, 0);
assert_eq!(S408_SGI_INTID, 3);
assert_eq!(S408_SOURCE_CPU1, 1);
assert_eq!(S408_TARGET_CPU0, 0);
assert_eq!(S408_TARGET_LIST_CPU0, 0x01);
assert_eq!(S408_EXPECTED_COMMAND, 0x0001_0003);
assert_eq!(S408_EXPECTED_RAW_ACK, 0x0000_0403);
assert_eq!(S408_PRODUCTION_RECEIVER_PREPARE_CALLSITES, 1);
assert_eq!(S408_PRODUCTION_SENDER_INVOCATION_CALLSITES, 0);
assert!(!S408_IRQ_DELIVERY_COMPLETE);
assert!(!S408_END_TO_END_EXCLUSION_ADMISSION_COMPLETE);
}
#[test]
fn s407_is_the_exact_live_offer_predecessor() {
assert_eq!(S408_SOURCE_AUDIT_UNITS, S407_SOURCE_AUDIT_UNITS);
assert_eq!(
S408_DIRECT_SCHEDULER_ACCESS_SITES,
S407_DIRECT_SCHEDULER_ACCESS_SITES
);
assert_eq!(
S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES,
S407_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES
);
assert_eq!(
S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES,
S407_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES
);
assert_eq!(
S408_UNROUTED_DIRECT_ACCESS_SITES,
S407_UNROUTED_DIRECT_ACCESS_SITES
);
}
#[test]
fn exact_receiver_prepare_then_live_offer_send_records_sgi3_command() {
let (gate, mut providers, mut scoped) = paired_states();
let mut offers = G8lS407LiveExclusionOfferState::new();
let offered = try_publish_s407_model_live_exclusion_offer(
&mut offers,
&gate,
&mut providers,
&mut scoped,
S245_TARGET_CPU1,
)
.unwrap()
.unwrap();
let mut sender = G8lS408LiveOfferSgiSenderState::new();
sender
.prepare_receiver(
S408_TARGET_CPU0,
S408_SOURCE_CPU1,
S408_EXPECTED_ENABLE,
S408_TARGET_LIST_CPU0,
0,
)
.unwrap();
let receipt =
service_s408_model_live_offer_sgi_send(&mut sender, S408_SOURCE_CPU1, &offered).unwrap();
assert_eq!(receipt.command(), S408_EXPECTED_COMMAND);
assert_eq!(receipt.attempt_id(), 1);
assert_eq!(receipt.provider_request_id(), 2);
assert_eq!(receipt.exclusive_token(), 2);
assert!(receipt.offer_was_live_at_send());
assert_eq!(sender.phase(), G8lS408LiveOfferSgiPhase::Sent);
assert!(offered.offer_pending());
assert_eq!(gate.active_exclusive_token(), Some(2));
}
#[test]
fn send_before_receiver_prepare_fails_closed_without_releasing_offer() {
let (gate, mut providers, mut scoped) = paired_states();
let mut offers = G8lS407LiveExclusionOfferState::new();
let offered = try_publish_s407_model_live_exclusion_offer(
&mut offers,
&gate,
&mut providers,
&mut scoped,
S245_TARGET_CPU1,
)
.unwrap()
.unwrap();
let mut sender = G8lS408LiveOfferSgiSenderState::new();
assert_eq!(
service_s408_model_live_offer_sgi_send(&mut sender, S408_SOURCE_CPU1, &offered),
Err(G8lS408LiveOfferSgiError::InvalidPhase)
);
assert!(offered.offer_pending());
assert_eq!(gate.active_exclusive_token(), Some(2));
}
#[test]
fn wrong_sender_cpu_fails_closed_with_offer_still_live() {
let (gate, mut providers, mut scoped) = paired_states();
let mut offers = G8lS407LiveExclusionOfferState::new();
let offered = try_publish_s407_model_live_exclusion_offer(
&mut offers,
&gate,
&mut providers,
&mut scoped,
S245_TARGET_CPU1,
)
.unwrap()
.unwrap();
let mut sender = G8lS408LiveOfferSgiSenderState::new();
sender
.prepare_receiver(0, 1, S408_EXPECTED_ENABLE, 1, 0)
.unwrap();
assert_eq!(
service_s408_model_live_offer_sgi_send(&mut sender, S408_TARGET_CPU0, &offered),
Err(G8lS408LiveOfferSgiError::WrongSenderCpu)
);
assert!(offered.offer_pending());
assert_eq!(gate.active_exclusive_token(), Some(2));
}
#[test]
fn receiver_prepare_rejects_wrong_enable_target_and_pending_source() {
for (enabled, target_list, pending, expected) in [
(0, 1, 0, G8lS408LiveOfferSgiError::SgiNotEnabled),
(
S408_EXPECTED_ENABLE,
2,
0,
G8lS408LiveOfferSgiError::WrongTargetList,
),
(
S408_EXPECTED_ENABLE,
1,
1 << S408_SOURCE_CPU1,
G8lS408LiveOfferSgiError::PendingSourceNotClear,
),
] {
let mut sender = G8lS408LiveOfferSgiSenderState::new();
assert_eq!(
sender.prepare_receiver(0, 1, enabled, target_list, pending),
Err(expected)
);
}
}
#[test]
fn duplicate_send_is_rejected_and_does_not_duplicate_command() {
let (gate, mut providers, mut scoped) = paired_states();
let mut offers = G8lS407LiveExclusionOfferState::new();
let offered = try_publish_s407_model_live_exclusion_offer(
&mut offers,
&gate,
&mut providers,
&mut scoped,
S245_TARGET_CPU1,
)
.unwrap()
.unwrap();
let mut sender = G8lS408LiveOfferSgiSenderState::new();
sender
.prepare_receiver(0, 1, S408_EXPECTED_ENABLE, 1, 0)
.unwrap();
service_s408_model_live_offer_sgi_send(&mut sender, 1, &offered).unwrap();
assert_eq!(
service_s408_model_live_offer_sgi_send(&mut sender, 1, &offered),
Err(G8lS408LiveOfferSgiError::InvalidPhase)
);
}
#[test]
fn model_send_requires_live_wrapper_before_transitioning_to_sent() {
let source = module_source();
let start = source
.find("pub fn service_s408_model_live_offer_sgi_send")
.unwrap();
let function = &source[start..];
let live = function.find("offered.offer_pending()").unwrap();
let authority = function.find("offered.is_provider_authority()").unwrap();
let send = function.find("sender.begin_send(").unwrap();
assert!(live < send && authority < send);
}
#[test]
fn boot_prepares_sgi3_after_sgi2_and_before_timer_init() {
let source = kernel_main_source();
let s240 = source
.find("prepare_s179_notification_sgi_receiver_on_cpu0")
.unwrap();
let s408 = source
.find("prepare_s408_live_offer_sgi_receiver_on_cpu0")
.unwrap();
let timer = source[s408..]
.find("timer::init_checked()")
.map(|offset| offset + s408)
.unwrap();
assert!(s240 < s408 && s408 < timer);
}
#[test]
fn production_sender_uses_exact_gic_sgi3_and_live_wrapper_reference() {
let source = module_source();
let start = source.find("send_s408_live_offer_sgi_from_cpu1").unwrap();
let function = &source[start..];
assert!(function.contains("&G8lS407ProductionOfferedScopedProviderAuthority"));
assert!(function.contains("rpi5_g8d_send_sgi(S408_SGI_INTID, S408_TARGET_LIST_CPU0)"));
assert!(function.contains("offered.offer_pending()"));
}
#[test]
fn production_sender_is_exposed_but_not_invoked_and_s409_owns_sgi3_delivery() {
assert!(!exception_source().contains("send_s408_live_offer_sgi_from_cpu1"));
assert!(exception_source().contains("try_handle_s409_live_offer_sgi_on_cpu0"));
assert_eq!(S408_PRODUCTION_SENDER_INVOCATION_CALLSITES, 0);
assert!(!S408_IRQ_DELIVERY_COMPLETE);
}
#[test]
fn sgi3_is_distinct_from_historical_sgi1_and_s240_sgi2() {
assert_ne!(S408_SGI_INTID, 1);
assert_ne!(S408_SGI_INTID, 2);
assert!(module_source().contains("dedicated SGI3"));
}
#[test]
fn s408_does_not_publish_admission_or_release_live_authority() {
let source = module_source();
for forbidden in [
"publish_s244",
"service_s243_deferred_authority_receipt_join",
"offered.release()",
"addr_of!(",
"addr_of_mut!(",
] {
assert!(
!source.contains(forbidden),
"forbidden promotion: {forbidden}"
);
}
}
#[test]
fn s408_and_its_exact_s409_delivery_are_registered_separately() {
let s408 = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender";
let s409 = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s409_live_offer_sgi_delivery";
assert!(kernel_main_source().contains(&format!("mod {s408};")));
assert!(simulation_lib_source().contains(&format!("pub mod {s408};")));
assert!(kernel_main_source().contains(&format!("mod {s409};")));
assert!(simulation_lib_source().contains(&format!("pub mod {s409};")));
}
snippet sha256: caa620e65d52…file sha256: caa620e65d52…
03 · Kapı kimlik kaydı
Operations sıra, kimlik ve başlık bağı
tam Operations kaydıL219–L235
website/src/lib/operations.ts::g8l-s408-live-offer-sgi-sender-partial
{
id: "g8l-s408-live-offer-sgi-sender-partial",
sequence: 408,
slug: "live_offer_sgi_sender",
title: "Live offer SGI sender",
focusedTests: 14,
sourceBytes: 13057,
sourceSha256:
"fe0632ee55901d6b216292423242f55f6fb145ffd27ebbe3b9db2e4a88ce0d6a",
testBytes: 12065,
testSha256:
"caa620e65d52add7768541fc581c6904ad64d13494a50e717b6a6b5fadf4500a",
acceptance:
"SGI3 için CPU1→CPU0 exact target-list, enable, command ve raw-ACK sözleşmesi; prepare/send/receipt/rearm state machine'i ile source-bound kurulur.",
retainedBoundary:
"Receiver prepare callsite vardır; sender invocation ve IRQ delivery henüz tamamlanmış sayılmaz.",
},snippet sha256: d916699e33e5…file sha256: 9726dbf00f84…
Focused test komutu
CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender -- --test-threads=1proof: docs/M8.1-RPi5-G8l-S408-Live-Offer-SGI-Sender-Proof.md
Registry schema v5 · generator
website/scripts/generate-code-gates.mjs · Tam SHA-256: 91d38c7b6222f0b4c117be786454853543da55a160e543d9b951057cc20dcc06