S128 · SOURCE-BOUND GATE EVIDENCE
K1/MEM2: audited RuntimeMemory pressure/OOM karar köprüsü
Operations --test hedefi → focused test içindeki include_str!/#[path] bağı → kaynak kesiti Bu sayfa yalnız S128 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.
S128Focused kod testiOperations id exactsource SHA exacttest target exact
operation: k1-mem2-audited-runtime-pressure-oom-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 öğesiL1212–L3355
kernel/src/mm/runtime_memory.rs::audited_domain_memory
impl<'metadata> RuntimeMemoryState<'metadata> {
/// Construct the sole state for a claimed inventory.
///
/// # Safety
///
/// `metadata` must be stable, exclusively writable bookkeeping storage
/// which cannot physically alias any allocatable frame in `inventory`.
/// Its backing pages must remain reserved from this and every other
/// allocator for the complete state lifetime. The inventory authority
/// itself proves the separate physical-region uniqueness obligation.
pub(crate) unsafe fn try_new(
inventory: RuntimeMemoryInventory,
metadata: &'metadata mut [u8],
) -> Result<Self, RuntimeAllocationError> {
let mut destination = core::mem::MaybeUninit::<Self>::uninit();
// SAFETY: `destination` is aligned, writable, and uninitialized. This
// function carries the remaining inventory and metadata contracts.
unsafe { Self::try_initialize_at(destination.as_mut_ptr(), inventory, metadata)? };
// SAFETY: success writes every field exactly once.
Ok(unsafe { destination.assume_init() })
}
/// Build a runtime state directly in permanent manager-owned storage.
/// This is crate-private so arbitrary production callers cannot obtain a
/// raw placement constructor or bypass the boot authority manager.
///
/// # Safety
///
/// In addition to [`Self::try_new`]'s contracts, `destination` must be
/// aligned, writable storage for one uninitialized `Self`. It must never
/// have held a live state and must not be observed until success returns.
pub(crate) unsafe fn try_initialize_at(
destination: *mut Self,
inventory: RuntimeMemoryInventory,
metadata: &'metadata mut [u8],
) -> Result<(), RuntimeAllocationError> {
let instance_epoch = mint_instance_epoch()?;
#[allow(unused_unsafe)]
// SAFETY: `RuntimeMemoryInventory::claim_bounded` and this function's
// metadata contract jointly satisfy the raw constructor requirements.
let pmm = unsafe {
RuntimePmm::try_new_bounded(
inventory.regions(),
inventory.reserved(),
metadata,
inventory.max_end,
)
}
.map_err(RuntimeAllocationError::Pmm)?;
// No fallible operations remain. Initialize fields without first
// materializing the large ledger as a stack value.
// SAFETY: The caller supplied exclusive uninitialized storage.
unsafe {
core::ptr::addr_of_mut!((*destination).inventory).write(inventory);
core::ptr::addr_of_mut!((*destination).pmm).write(pmm);
RuntimeMemoryLedger::initialize_at(core::ptr::addr_of_mut!((*destination).ledger));
core::ptr::addr_of_mut!((*destination).instance_epoch).write(instance_epoch);
}
Ok(())
}
pub const fn snapshot(&self) -> RuntimeMemorySnapshot {
RuntimeMemorySnapshot {
instance_epoch: self.instance_epoch,
inventory_region_count: self.inventory.region_count,
inventory_reserved_count: self.inventory.reserved_count,
inventory_max_end: self.inventory.max_end,
pmm: self.pmm.snapshot(),
registered_domains: self.ledger.registered_domains,
active_allocations: self.ledger.active_allocations,
retired_allocations: self.ledger.retired_allocations,
pin_references: self.ledger.pin_references,
prepared_mappings: self.ledger.prepared_mappings,
active_mappings: self.ledger.active_mappings,
pending_tlb_invalidations: self.ledger.pending_tlb_invalidations,
kernel_access_references: self.ledger.kernel_access_references,
scrub_access_references: self.ledger.scrub_access_references,
scrubs_in_progress: self.ledger.scrubs_in_progress,
release_scrubbed_allocations: self.ledger.release_scrubbed_allocations,
last_allocation_generation: self.ledger.last_allocation_generation,
last_pin_generation: self.ledger.last_pin_generation,
last_mapping_generation: self.ledger.last_mapping_generation,
last_access_generation: self.ledger.last_access_generation,
last_scrub_generation: self.ledger.last_scrub_generation,
}
}
/// Rebuild all internal ledgers and require exact PMM agreement.
pub fn audited_snapshot(&self) -> Result<RuntimeMemorySnapshot, RuntimeAllocationError> {
let snapshot = self.snapshot();
let pmm = self
.pmm
.audited_snapshot()
.map_err(RuntimeAllocationError::Pmm)?;
if pmm != snapshot.pmm
|| self.instance_epoch == 0
|| self.inventory.region_count == 0
|| self.inventory.region_count > MAX_RUNTIME_REGIONS
|| self.inventory.reserved_count > MAX_RUNTIME_RESERVED_RANGES
{
return Err(RuntimeAllocationError::InvariantViolation);
}
let allocatable_frames = pmm
.total_frames
.checked_sub(pmm.reserved_frames)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let mut observed_domains = 0usize;
for (index, record) in self.ledger.domains.iter().copied().enumerate() {
if !record.occupied {
if record != DomainRecord::EMPTY {
return Err(RuntimeAllocationError::InvariantViolation);
}
continue;
}
if record.generation == 0
|| record.hard_limit_frames == 0
|| record.hard_limit_frames > allocatable_frames
|| self.domain_allocated_frames(record.id)? > record.hard_limit_frames
{
return Err(RuntimeAllocationError::InvariantViolation);
}
observed_domains = observed_domains
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
if self.ledger.domains[index + 1..]
.iter()
.any(|other| other.occupied && other.id == record.id)
{
return Err(RuntimeAllocationError::InvariantViolation);
}
}
if observed_domains != self.ledger.registered_domains {
return Err(RuntimeAllocationError::InvariantViolation);
}
let mut observed_pin_records = 0u64;
for (index, pin) in self.ledger.pins.iter().copied().enumerate() {
if !pin.active {
if pin != PinRecord::EMPTY {
return Err(RuntimeAllocationError::InvariantViolation);
}
continue;
}
if pin.generation == 0
|| pin.generation > self.ledger.last_pin_generation
|| pin.owner.instance_epoch != self.instance_epoch
|| self.ledger.pins[index + 1..]
.iter()
.any(|other| other.active && other.generation == pin.generation)
{
return Err(RuntimeAllocationError::InvariantViolation);
}
let allocation = self
.allocation_record_by_generation(pin.allocation_generation)
.map(|(_, record)| record)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
if allocation.owner != pin.owner || pin.frame_offset >= allocation.frame_count {
return Err(RuntimeAllocationError::InvariantViolation);
}
observed_pin_records = observed_pin_records
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
let mut observed_prepared = 0u64;
let mut observed_mapped = 0u64;
let mut observed_pending_tlb = 0u64;
for (index, mapping) in self.ledger.mappings.iter().copied().enumerate() {
if !mapping.active {
if mapping != MappingRecord::EMPTY {
return Err(RuntimeAllocationError::InvariantViolation);
}
continue;
}
if mapping.generation == 0
|| mapping.generation > self.ledger.last_mapping_generation
|| mapping.owner.instance_epoch != self.instance_epoch
|| !mapping_descriptor_is_valid(mapping.descriptor)
|| self.ledger.mappings[index + 1..].iter().any(|other| {
other.active
&& (other.generation == mapping.generation
|| other.descriptor == mapping.descriptor)
})
{
return Err(RuntimeAllocationError::InvariantViolation);
}
let allocation = self
.allocation_record_by_generation(mapping.allocation_generation)
.map(|(_, record)| record)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
if allocation.owner != mapping.owner
|| allocation.frame_count != mapping.descriptor.page_count
{
return Err(RuntimeAllocationError::InvariantViolation);
}
match mapping.phase {
MappingPhase::Prepared => {
observed_prepared = observed_prepared
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?
}
MappingPhase::Mapped => {
observed_mapped = observed_mapped
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?
}
MappingPhase::PendingTlb => {
observed_pending_tlb = observed_pending_tlb
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?
}
}
}
let mut observed_kernel_accesses = 0u64;
let mut observed_scrub_accesses = 0u64;
for (index, access) in self.ledger.accesses.iter().copied().enumerate() {
if !access.active {
if access != AccessRecord::EMPTY {
return Err(RuntimeAllocationError::InvariantViolation);
}
continue;
}
if access.generation == 0
|| access.generation > self.ledger.last_access_generation
|| access.owner.instance_epoch != self.instance_epoch
|| !kernel_access_descriptor_is_valid(access.descriptor)
|| self.ledger.accesses[index + 1..].iter().any(|other| {
other.active
&& (other.generation == access.generation
|| other.descriptor == access.descriptor)
})
{
return Err(RuntimeAllocationError::InvariantViolation);
}
let allocation = self
.allocation_record_by_generation(access.allocation_generation)
.map(|(_, record)| record)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
if allocation.owner != access.owner
|| !kernel_access_range_is_valid(access.descriptor, allocation.frame_count)
{
return Err(RuntimeAllocationError::InvariantViolation);
}
match access.kind {
AccessKind::Kernel => {
if access.descriptor.purpose == KernelAccessPurpose::Scrub
|| allocation.scrub_in_progress
{
return Err(RuntimeAllocationError::InvariantViolation);
}
observed_kernel_accesses = observed_kernel_accesses
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
AccessKind::Scrub { scrub_generation } => {
if scrub_generation == 0
|| !allocation.scrub_in_progress
|| allocation.scrub_generation != scrub_generation
|| allocation.scrub_access_completed
|| access.descriptor.purpose != KernelAccessPurpose::Scrub
|| access.descriptor.permissions != KernelAccessPermissions::ReadWrite
|| access.descriptor.frame_offset != 0
|| access.descriptor.frame_count != allocation.frame_count
{
return Err(RuntimeAllocationError::InvariantViolation);
}
observed_scrub_accesses = observed_scrub_accesses
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
}
}
let mut observed_allocations = 0usize;
let mut observed_retired = 0usize;
let mut observed_frames = 0u64;
let mut observed_pin_references = 0u64;
let mut observed_pinned_frames = 0u64;
let mut observed_scrubs = 0usize;
let mut observed_release_scrubbed = 0usize;
let mut allocation_prepared = 0u64;
let mut allocation_mapped = 0u64;
let mut allocation_pending = 0u64;
let mut allocation_kernel_accesses = 0u64;
let mut allocation_scrub_accesses = 0u64;
for (index, record) in self.ledger.allocations.iter().copied().enumerate() {
if !record.active {
if record != AllocationRecord::EMPTY {
return Err(RuntimeAllocationError::InvariantViolation);
}
continue;
}
if record.generation == 0
|| record.generation > self.ledger.last_allocation_generation
|| record.frame_count == 0
|| record.owner.instance_epoch != self.instance_epoch
{
return Err(RuntimeAllocationError::InvariantViolation);
}
let (_, domain) = self
.domain_record(record.owner.id)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
if record.owner.generation > domain.generation {
return Err(RuntimeAllocationError::InvariantViolation);
}
if record.owner.generation < domain.generation {
observed_retired = observed_retired
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
if self.ledger.allocations[index + 1..].iter().any(|other| {
other.active
&& (other.generation == record.generation
|| allocation_ranges_overlap(record, *other))
}) {
return Err(RuntimeAllocationError::InvariantViolation);
}
let (pmm_pins, pinned_frames) = self.observed_record_pins(record)?;
let token_pins = u64::try_from(
self.ledger
.pins
.iter()
.filter(|pin| pin.active && pin.allocation_generation == record.generation)
.count(),
)
.map_err(|_| RuntimeAllocationError::CounterOverflow)?;
if pmm_pins != record.pin_references || token_pins != record.pin_references {
return Err(RuntimeAllocationError::InvariantViolation);
}
let record_prepared = count_mapping_phase(
&self.ledger.mappings,
record.generation,
MappingPhase::Prepared,
)?;
let record_mapped = count_mapping_phase(
&self.ledger.mappings,
record.generation,
MappingPhase::Mapped,
)?;
let record_pending = count_mapping_phase(
&self.ledger.mappings,
record.generation,
MappingPhase::PendingTlb,
)?;
let record_kernel_accesses =
count_access_kind(&self.ledger.accesses, record.generation, false)?;
let record_scrub_accesses =
count_access_kind(&self.ledger.accesses, record.generation, true)?;
let mapping_references = record.mapping_references()?;
let access_references = record.access_references()?;
if record_prepared != record.prepared_mappings
|| record_mapped != record.active_mappings
|| record_pending != record.pending_tlb_invalidations
|| record_kernel_accesses != record.kernel_access_references
|| record_scrub_accesses != record.scrub_access_references
|| (record.release_scrubbed
&& (record.pin_references != 0
|| mapping_references != 0
|| record.scrub_in_progress))
|| (record.scrub_in_progress
&& (record.scrub_generation == 0
|| record.scrub_generation > self.ledger.last_scrub_generation
|| record.release_scrubbed
|| record.pin_references != 0
|| mapping_references != 0
|| record.kernel_access_references != 0
|| (record.scrub_access_completed && record.scrub_access_references != 0)
|| self.ledger.allocations[index + 1..].iter().any(|other| {
other.active
&& other.scrub_in_progress
&& other.scrub_generation == record.scrub_generation
})))
|| (!record.scrub_in_progress
&& (record.scrub_generation != 0
|| record.scrub_access_completed
|| record.scrub_access_references != 0))
|| (record.owner.generation < domain.generation
&& (!record.release_scrubbed
|| record.pin_references != 0
|| mapping_references != 0
|| access_references != 0
|| record.scrub_in_progress))
{
return Err(RuntimeAllocationError::InvariantViolation);
}
observed_allocations = observed_allocations
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
observed_frames = observed_frames
.checked_add(
u64::try_from(record.frame_count)
.map_err(|_| RuntimeAllocationError::CounterOverflow)?,
)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
observed_pin_references = observed_pin_references
.checked_add(record.pin_references)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
observed_pinned_frames = observed_pinned_frames
.checked_add(pinned_frames)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
allocation_prepared = allocation_prepared
.checked_add(record.prepared_mappings)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
allocation_mapped = allocation_mapped
.checked_add(record.active_mappings)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
allocation_pending = allocation_pending
.checked_add(record.pending_tlb_invalidations)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
allocation_kernel_accesses = allocation_kernel_accesses
.checked_add(record.kernel_access_references)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
allocation_scrub_accesses = allocation_scrub_accesses
.checked_add(record.scrub_access_references)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
if record.scrub_in_progress {
observed_scrubs = observed_scrubs
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
if record.release_scrubbed {
observed_release_scrubbed = observed_release_scrubbed
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
}
if observed_allocations != self.ledger.active_allocations
|| observed_retired != self.ledger.retired_allocations
|| observed_frames != pmm.allocated_frames
|| observed_pin_references != observed_pin_records
|| observed_pin_references != self.ledger.pin_references
|| observed_pin_references != pmm.pin_references
|| observed_pinned_frames != pmm.pinned_frames
|| observed_prepared != allocation_prepared
|| observed_prepared != self.ledger.prepared_mappings
|| observed_mapped != allocation_mapped
|| observed_mapped != self.ledger.active_mappings
|| observed_pending_tlb != allocation_pending
|| observed_pending_tlb != self.ledger.pending_tlb_invalidations
|| observed_kernel_accesses != allocation_kernel_accesses
|| observed_kernel_accesses != self.ledger.kernel_access_references
|| observed_scrub_accesses != allocation_scrub_accesses
|| observed_scrub_accesses != self.ledger.scrub_access_references
|| observed_scrubs != self.ledger.scrubs_in_progress
|| observed_release_scrubbed != self.ledger.release_scrubbed_allocations
{
return Err(RuntimeAllocationError::InvariantViolation);
}
Ok(snapshot)
}
/// Reconcile every live ownership record with the authoritative PMM and
/// aggregate it into the closed MEM0 class vocabulary.
pub fn audited_reconciliation(
&self,
) -> Result<RuntimeMemoryReconciliationSnapshot, RuntimeAllocationError> {
let memory = self.audited_snapshot()?;
let mut classes = [RuntimeMemoryClassSnapshot::default(); RUNTIME_MEMORY_CLASS_COUNT];
for record in self
.ledger
.allocations
.iter()
.copied()
.filter(|record| record.active)
{
let (_, domain) = self
.domain_record(record.owner.id)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let (_, pinned_frames) = self.observed_record_pins(record)?;
accumulate_class_snapshot(
&mut classes[record.class.index()],
record,
pinned_frames,
record.owner.generation < domain.generation,
)?;
}
let snapshot = RuntimeMemoryReconciliationSnapshot { memory, classes };
if !snapshot.is_consistent() {
return Err(RuntimeAllocationError::InvariantViolation);
}
Ok(snapshot)
}
/// Strict MEM0 gate: physical reconciliation alone is insufficient while
/// any live allocation remains in the compatibility bucket.
pub fn audited_mem0_reconciliation(
&self,
) -> Result<RuntimeMemoryReconciliationSnapshot, RuntimeAllocationError> {
let snapshot = self.audited_reconciliation()?;
let unclassified = snapshot.class(RuntimeMemoryClass::Unclassified);
if unclassified != RuntimeMemoryClassSnapshot::default() {
return Err(RuntimeAllocationError::UnclassifiedAllocations {
allocations: unclassified.allocations,
frames: unclassified.frames,
});
}
Ok(snapshot)
}
/// Rebuild one quota domain's current and retired ownership without
/// exposing the underlying allocation records or raw PMM.
pub fn audited_domain_memory(
&self,
current: AllocationDomain,
) -> Result<RuntimeDomainMemorySnapshot, RuntimeAllocationError> {
self.validate_current_domain(current)?;
self.audited_snapshot()?;
let mut classes = [RuntimeMemoryClassSnapshot::default(); RUNTIME_MEMORY_CLASS_COUNT];
for record in self.ledger.allocations.iter().copied().filter(|record| {
record.active
&& record.owner.instance_epoch == current.instance_epoch
&& record.owner.id == current.id
}) {
let (_, pinned_frames) = self.observed_record_pins(record)?;
accumulate_class_snapshot(
&mut classes[record.class.index()],
record,
pinned_frames,
record.owner.generation < current.generation,
)?;
}
let snapshot = RuntimeDomainMemorySnapshot {
domain: current,
classes,
};
if !snapshot.is_consistent() {
return Err(RuntimeAllocationError::InvariantViolation);
}
Ok(snapshot)
}
/// Reconcile one domain's hard limit against its current and retired
/// physical ownership. This derives usage from allocation records instead
/// of trusting a second mutable quota counter.
pub fn audited_domain_quota(
&self,
current: AllocationDomain,
) -> Result<RuntimeDomainQuotaSnapshot, RuntimeAllocationError> {
let memory = self.audited_domain_memory(current)?;
let (_, domain) = self
.domain_record(current.id)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let mut allocated_frames = 0u64;
let mut retired_frames = 0u64;
let mut pinned_frames = 0u64;
let mut pin_references = 0u64;
for class in memory.classes {
allocated_frames = allocated_frames
.checked_add(class.frames)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
pinned_frames = pinned_frames
.checked_add(class.pinned_frames)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
pin_references = pin_references
.checked_add(class.pin_references)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
for record in self.ledger.allocations.iter().copied().filter(|record| {
record.active
&& record.owner.instance_epoch == current.instance_epoch
&& record.owner.id == current.id
&& record.owner.generation < current.generation
}) {
retired_frames = retired_frames
.checked_add(
u64::try_from(record.frame_count)
.map_err(|_| RuntimeAllocationError::CounterOverflow)?,
)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
if allocated_frames != self.domain_allocated_frames(current.id)? {
return Err(RuntimeAllocationError::InvariantViolation);
}
let remaining_frames = domain
.hard_limit_frames
.checked_sub(allocated_frames)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let snapshot = RuntimeDomainQuotaSnapshot {
domain: current,
hard_limit_frames: domain.hard_limit_frames,
allocated_frames,
remaining_frames,
retired_frames,
pinned_frames,
pin_references,
};
if !snapshot.is_consistent() {
return Err(RuntimeAllocationError::InvariantViolation);
}
Ok(snapshot)
}
/// Resolve one physical frame to its exact domain/allocation/class only
/// after a complete ledger/PMM audit. Orphan allocated frames and records
/// covering free or reserved PMM entries are rejected fail-closed.
pub fn audited_frame_ownership(
&self,
address: PhysAddr,
) -> Result<RuntimeFrameOwnership, RuntimeAllocationError> {
self.audited_snapshot()?;
let state = self
.pmm
.frame_state(address)
.map_err(RuntimeAllocationError::Pmm)?;
let mut matched = None;
for record in self
.ledger
.allocations
.iter()
.copied()
.filter(|record| record.active && allocation_contains_address(*record, address))
{
if matched.replace(record).is_some() {
return Err(RuntimeAllocationError::InvariantViolation);
}
}
match (state, matched) {
(RuntimeFrameState::Free, None) => Ok(RuntimeFrameOwnership::Free),
(RuntimeFrameState::Reserved, None) => Ok(RuntimeFrameOwnership::Reserved),
(RuntimeFrameState::Allocated { pin_count }, Some(record)) => {
let frame_offset = usize::try_from(
(address.as_u64() - record.start.as_u64()) / RUNTIME_FRAME_SIZE,
)
.map_err(|_| RuntimeAllocationError::CounterOverflow)?;
let (_, domain) = self
.domain_record(record.owner.id)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
Ok(RuntimeFrameOwnership::Owned {
owner: record.owner,
allocation_generation: record.generation,
class: record.class,
frame_offset,
pin_count,
retired: record.owner.generation < domain.generation,
})
}
_ => Err(RuntimeAllocationError::InvariantViolation),
}
}
/// Preflight an exact, empty shutdown without consuming the state.
pub fn shutdown_readiness(&self) -> Result<(), RuntimeAllocationError> {
let snapshot = self.audited_snapshot()?;
let mapping_references = snapshot
.prepared_mappings
.checked_add(snapshot.active_mappings)
.and_then(|value| value.checked_add(snapshot.pending_tlb_invalidations))
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let access_references = snapshot
.kernel_access_references
.checked_add(snapshot.scrub_access_references)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
if snapshot.active_allocations != 0
|| snapshot.pmm.allocated_frames != 0
|| snapshot.pin_references != 0
|| mapping_references != 0
|| access_references != 0
|| snapshot.scrubs_in_progress != 0
{
return Err(RuntimeAllocationError::ShutdownBusy {
active_allocations: snapshot.active_allocations,
pin_references: snapshot.pin_references,
mapping_references,
access_references,
scrubs_in_progress: snapshot.scrubs_in_progress,
});
}
Ok(())
}
/// Return the inventory only after an exact, empty audit.
///
/// Call [`Self::shutdown_readiness`] first if an outstanding lifecycle must
/// be recoverable. A failure here consumes the state and loses its inventory
/// fail-closed, avoiding a heap allocation or a 60-KiB error value.
pub fn try_shutdown(self) -> Result<RuntimeMemoryInventory, RuntimeAllocationError> {
self.shutdown_readiness()?;
let Self {
inventory,
pmm: _,
ledger: _,
instance_epoch: _,
} = self;
Ok(inventory)
}
/// Compatibility registration with a hard limit equal to the complete
/// allocatable inventory. Production domains can select a smaller limit
/// through [`Self::register_domain_with_quota`].
pub fn register_domain(&mut self, id: u32) -> Result<AllocationDomain, RuntimeAllocationError> {
let allocatable_frames = self.allocatable_frame_capacity()?;
self.register_domain_with_quota(id, allocatable_frames)
}
/// Register one quota domain. The limit is immutable across generation
/// rotation and cannot exceed the physical inventory governed by this
/// runtime authority.
pub fn register_domain_with_quota(
&mut self,
id: u32,
hard_limit_frames: u64,
) -> Result<AllocationDomain, RuntimeAllocationError> {
if hard_limit_frames == 0 {
return Err(RuntimeAllocationError::EmptyDomainQuota);
}
let allocatable_frames = self.allocatable_frame_capacity()?;
if hard_limit_frames > allocatable_frames {
return Err(RuntimeAllocationError::DomainQuotaExceedsInventory {
hard_limit_frames,
allocatable_frames,
});
}
if self.domain_record(id).is_some() {
return Err(RuntimeAllocationError::DomainAlreadyRegistered);
}
let index = self
.ledger
.domains
.iter()
.position(|record| !record.occupied)
.ok_or(RuntimeAllocationError::DomainCapacity)?;
let registered_domains = self
.ledger
.registered_domains
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let authority = AllocationDomain {
instance_epoch: self.instance_epoch,
id,
generation: 1,
};
self.ledger.domains[index] = DomainRecord {
id,
generation: authority.generation,
hard_limit_frames,
occupied: true,
};
self.ledger.registered_domains = registered_domains;
Ok(authority)
}
/// Validate that a copied domain handle is current for this exact state.
/// This exposes no allocator or ledger mutation authority.
pub fn validate_domain_authority(
&self,
current: AllocationDomain,
) -> Result<(), RuntimeAllocationError> {
self.validate_current_domain(current).map(|_| ())
}
/// Retire only allocations already unreferenced and release-scrubbed.
pub fn rotate_domain(
&mut self,
current: AllocationDomain,
) -> Result<AllocationDomain, RuntimeAllocationError> {
let domain_index = self.validate_current_domain(current)?;
let next_generation = current
.generation
.checked_add(1)
.ok_or(RuntimeAllocationError::DomainGenerationOverflow)?;
let mut pins = 0u64;
let mut mapping_references = 0u64;
let mut access_references = 0u64;
let mut scrubs = 0usize;
let mut dirty = 0usize;
let mut newly_retired = 0usize;
for record in self.ledger.allocations.iter().copied().filter(|record| {
record.active
&& record.owner.instance_epoch == self.instance_epoch
&& record.owner.id == current.id
}) {
let (observed_pins, _) = self.observed_record_pins(record)?;
if observed_pins != record.pin_references {
return Err(RuntimeAllocationError::InvariantViolation);
}
pins = pins
.checked_add(observed_pins)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
mapping_references = mapping_references
.checked_add(record.mapping_references()?)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
access_references = access_references
.checked_add(record.access_references()?)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
if record.scrub_in_progress {
scrubs = scrubs
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
if !record.release_scrubbed {
dirty = dirty
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
if record.owner.generation == current.generation {
newly_retired = newly_retired
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
} else if record.owner.generation > current.generation {
return Err(RuntimeAllocationError::InvariantViolation);
}
}
if pins != 0 {
return Err(RuntimeAllocationError::DomainPinned {
domain_id: current.id,
pin_references: pins,
});
}
if mapping_references != 0 || access_references != 0 || scrubs != 0 || dirty != 0 {
return Err(RuntimeAllocationError::DomainLifecycleIncomplete {
domain_id: current.id,
mapping_references,
access_references,
scrubs_in_progress: scrubs,
dirty_allocations: dirty,
});
}
let retired = self
.ledger
.retired_allocations
.checked_add(newly_retired)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
self.ledger.domains[domain_index].generation = next_generation;
self.ledger.retired_allocations = retired;
Ok(AllocationDomain {
instance_epoch: self.instance_epoch,
id: current.id,
generation: next_generation,
})
}
pub fn allocate(
&mut self,
current: AllocationDomain,
frame_count: usize,
) -> Result<AllocationToken, RuntimeAllocationError> {
self.allocate_classified(current, RuntimeMemoryClass::Unclassified, frame_count)
}
/// Allocate one exact run and bind its complete frame range to both the
/// quota domain and a closed MEM0 resource class before publication.
pub fn allocate_classified(
&mut self,
current: AllocationDomain,
class: RuntimeMemoryClass,
frame_count: usize,
) -> Result<AllocationToken, RuntimeAllocationError> {
let domain_index = self.validate_current_domain(current)?;
if frame_count == 0 {
return Err(RuntimeAllocationError::Pmm(RuntimePmmError::ZeroFrameCount));
}
let requested_frames =
u64::try_from(frame_count).map_err(|_| RuntimeAllocationError::CounterOverflow)?;
// Preserve the physical allocator boundary when both global exhaustion
// and a domain limit would reject the same request. No PMM mutation is
// needed to prove that a request larger than the total free count
// cannot be satisfied contiguously.
if requested_frames > self.pmm.snapshot().free_frames {
return Err(RuntimeAllocationError::Pmm(RuntimePmmError::OutOfMemory));
}
let allocated_frames = self.domain_allocated_frames(current.id)?;
let hard_limit_frames = self.ledger.domains[domain_index].hard_limit_frames;
let charged_frames = allocated_frames
.checked_add(requested_frames)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
if charged_frames > hard_limit_frames {
return Err(RuntimeAllocationError::DomainQuotaExceeded {
domain_id: current.id,
hard_limit_frames,
allocated_frames,
requested_frames,
});
}
let record_index = self
.ledger
.allocations
.iter()
.position(|record| !record.active)
.ok_or(RuntimeAllocationError::AllocationCapacity)?;
let generation = self
.ledger
.last_allocation_generation
.checked_add(1)
.ok_or(RuntimeAllocationError::AllocationGenerationOverflow)?;
let active = self
.ledger
.active_allocations
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let run = self
.pmm
.allocate_contiguous(frame_count)
.map_err(RuntimeAllocationError::Pmm)?;
self.ledger.allocations[record_index] = AllocationRecord {
generation,
owner: current,
class,
start: run.start_address(),
frame_count: run.frame_count(),
pin_references: 0,
prepared_mappings: 0,
active_mappings: 0,
pending_tlb_invalidations: 0,
kernel_access_references: 0,
scrub_access_references: 0,
scrub_generation: 0,
scrub_in_progress: false,
scrub_access_completed: false,
release_scrubbed: false,
active: true,
};
self.ledger.active_allocations = active;
self.ledger.last_allocation_generation = generation;
Ok(AllocationToken {
run,
owner: current,
allocation_generation: generation,
class,
state: AuthorityState::Live,
})
}
pub fn free(
&mut self,
current: AllocationDomain,
token: &mut AllocationToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let index = self.validate_allocation_record(token)?;
let record = self.ledger.allocations[index];
self.ensure_release_ready(record)?;
let active = self
.ledger
.active_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let scrubbed = self
.ledger
.release_scrubbed_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
self.pmm
.free_contiguous(record.start, record.frame_count)
.map_err(RuntimeAllocationError::Pmm)?;
self.ledger.allocations[index] = AllocationRecord::EMPTY;
self.ledger.active_allocations = active;
self.ledger.release_scrubbed_allocations = scrubbed;
token.state = AuthorityState::Consumed;
Ok(())
}
/// Create exact ownership of one pin reference.
pub fn pin(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
frame_offset: usize,
) -> Result<PinToken, RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let allocation = self.ledger.allocations[allocation_index];
if allocation.scrub_in_progress {
return Err(lifecycle_busy(allocation));
}
let address = token.frame_address(frame_offset)?;
let pin_index = self
.ledger
.pins
.iter()
.position(|record| !record.active)
.ok_or(RuntimeAllocationError::PinCapacity)?;
let generation = self
.ledger
.last_pin_generation
.checked_add(1)
.ok_or(RuntimeAllocationError::PinGenerationOverflow)?;
let allocation_pins = allocation
.pin_references
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let ledger_pins = self
.ledger
.pin_references
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let scrubbed = if allocation.release_scrubbed {
self.ledger
.release_scrubbed_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?
} else {
self.ledger.release_scrubbed_allocations
};
self.pmm
.pin_frame(address)
.map_err(RuntimeAllocationError::Pmm)?;
self.ledger.pins[pin_index] = PinRecord {
generation,
owner: current,
allocation_generation: token.allocation_generation,
frame_offset,
active: true,
};
self.ledger.allocations[allocation_index].pin_references = allocation_pins;
self.ledger.allocations[allocation_index].release_scrubbed = false;
self.ledger.pin_references = ledger_pins;
self.ledger.release_scrubbed_allocations = scrubbed;
self.ledger.last_pin_generation = generation;
Ok(PinToken {
owner: current,
allocation_generation: token.allocation_generation,
pin_generation: generation,
frame_offset,
state: AuthorityState::Live,
})
}
/// # Safety
/// The external user represented by this exact pin must no longer access
/// the frame. The allocation remains dirty until a final scrub.
pub unsafe fn unpin(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
pin: &mut PinToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let pin_index = self.validate_pin_record(token, pin)?;
let allocation = self.ledger.allocations[allocation_index];
if allocation.access_references()? != 0 {
return Err(lifecycle_busy(allocation));
}
let allocation_pins = self.ledger.allocations[allocation_index]
.pin_references
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_pins = self
.ledger
.pin_references
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let address = token.frame_address(pin.frame_offset)?;
self.pmm
.unpin_frame(address)
.map_err(RuntimeAllocationError::Pmm)?;
self.ledger.pins[pin_index] = PinRecord::EMPTY;
self.ledger.allocations[allocation_index].pin_references = allocation_pins;
self.ledger.pin_references = ledger_pins;
pin.state = AuthorityState::Consumed;
Ok(())
}
/// Reserve ledger space before page-table mutation.
pub fn prepare_mapping(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
descriptor: MappingDescriptor,
) -> Result<MappingToken, RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let allocation = self.ledger.allocations[allocation_index];
if !mapping_descriptor_is_valid(descriptor) {
return Err(RuntimeAllocationError::InvalidMappingDescriptor);
}
if descriptor.page_count != allocation.frame_count {
return Err(RuntimeAllocationError::MappingPageCountMismatch {
allocation_frames: allocation.frame_count,
mapping_pages: descriptor.page_count,
});
}
if allocation.scrub_in_progress || allocation.pending_tlb_invalidations != 0 {
return Err(lifecycle_busy(allocation));
}
if allocation.prepared_mappings == 0
&& allocation.active_mappings == 0
&& !allocation.release_scrubbed
{
return Err(RuntimeAllocationError::AllocationNeedsScrub {
allocation_generation: allocation.generation,
});
}
if self
.ledger
.mappings
.iter()
.any(|mapping| mapping.active && mapping.descriptor == descriptor)
{
return Err(RuntimeAllocationError::MappingAlreadyExists);
}
let mapping_index = self
.ledger
.mappings
.iter()
.position(|record| !record.active)
.ok_or(RuntimeAllocationError::MappingCapacity)?;
let generation = self
.ledger
.last_mapping_generation
.checked_add(1)
.ok_or(RuntimeAllocationError::MappingGenerationOverflow)?;
let allocation_prepared = allocation
.prepared_mappings
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let ledger_prepared = self
.ledger
.prepared_mappings
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let scrubbed = if allocation.release_scrubbed {
self.ledger
.release_scrubbed_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?
} else {
self.ledger.release_scrubbed_allocations
};
self.ledger.mappings[mapping_index] = MappingRecord {
generation,
owner: current,
allocation_generation: token.allocation_generation,
descriptor,
phase: MappingPhase::Prepared,
active: true,
};
self.ledger.allocations[allocation_index].prepared_mappings = allocation_prepared;
self.ledger.allocations[allocation_index].release_scrubbed = false;
self.ledger.prepared_mappings = ledger_prepared;
self.ledger.release_scrubbed_allocations = scrubbed;
self.ledger.last_mapping_generation = generation;
Ok(MappingToken {
owner: current,
allocation_generation: token.allocation_generation,
mapping_generation: generation,
descriptor,
phase: MappingTokenPhase::Prepared,
})
}
/// # Safety
/// The complete mapping must be installed with the required permissions and
/// publication barriers, after its reservation was created.
pub unsafe fn confirm_mapping(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
mapping: &mut MappingToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let mapping_index = self.validate_mapping_record(token, mapping, MappingPhase::Prepared)?;
let allocation_prepared = self.ledger.allocations[allocation_index]
.prepared_mappings
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let allocation_mapped = self.ledger.allocations[allocation_index]
.active_mappings
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let ledger_prepared = self
.ledger
.prepared_mappings
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_mapped = self
.ledger
.active_mappings
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
self.ledger.mappings[mapping_index].phase = MappingPhase::Mapped;
self.ledger.allocations[allocation_index].prepared_mappings = allocation_prepared;
self.ledger.allocations[allocation_index].active_mappings = allocation_mapped;
self.ledger.prepared_mappings = ledger_prepared;
self.ledger.active_mappings = ledger_mapped;
mapping.phase = MappingTokenPhase::Mapped;
Ok(())
}
pub fn cancel_prepared_mapping(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
mapping: &mut MappingToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let mapping_index = self.validate_mapping_record(token, mapping, MappingPhase::Prepared)?;
let allocation_prepared = self.ledger.allocations[allocation_index]
.prepared_mappings
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_prepared = self
.ledger
.prepared_mappings
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
self.ledger.mappings[mapping_index] = MappingRecord::EMPTY;
self.ledger.allocations[allocation_index].prepared_mappings = allocation_prepared;
self.ledger.prepared_mappings = ledger_prepared;
mapping.phase = MappingTokenPhase::Consumed;
Ok(())
}
/// # Safety
/// Every PTE represented by `mapping` must already be invalid with the
/// required page-table update barriers.
pub unsafe fn begin_unmap(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
mapping: &mut MappingToken,
) -> Result<TlbInvalidationToken, RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let mapping_index = self.validate_mapping_record(token, mapping, MappingPhase::Mapped)?;
let allocation_mapped = self.ledger.allocations[allocation_index]
.active_mappings
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let allocation_pending = self.ledger.allocations[allocation_index]
.pending_tlb_invalidations
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let ledger_mapped = self
.ledger
.active_mappings
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_pending = self
.ledger
.pending_tlb_invalidations
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
self.ledger.mappings[mapping_index].phase = MappingPhase::PendingTlb;
self.ledger.allocations[allocation_index].active_mappings = allocation_mapped;
self.ledger.allocations[allocation_index].pending_tlb_invalidations = allocation_pending;
self.ledger.active_mappings = ledger_mapped;
self.ledger.pending_tlb_invalidations = ledger_pending;
mapping.phase = MappingTokenPhase::Consumed;
Ok(TlbInvalidationToken {
owner: mapping.owner,
allocation_generation: mapping.allocation_generation,
mapping_generation: mapping.mapping_generation,
descriptor: mapping.descriptor,
state: AuthorityState::Live,
})
}
/// # Safety
/// All required local/remote TLBI and ordering barriers for the descriptor
/// must be durably complete.
pub unsafe fn complete_tlb_invalidation(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
tlb: &mut TlbInvalidationToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let mapping_index = self.validate_tlb_record(token, tlb)?;
let allocation_pending = self.ledger.allocations[allocation_index]
.pending_tlb_invalidations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_pending = self
.ledger
.pending_tlb_invalidations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
self.ledger.mappings[mapping_index] = MappingRecord::EMPTY;
self.ledger.allocations[allocation_index].pending_tlb_invalidations = allocation_pending;
self.ledger.pending_tlb_invalidations = ledger_pending;
tlb.state = AuthorityState::Consumed;
Ok(())
}
/// Reserve a bounded temporary kernel mapping before mutating page tables.
/// Dirty and pinned allocations are accepted; the exact linear reference
/// still prevents unpin, scrub, release, and domain rotation until closed.
pub fn prepare_kernel_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
descriptor: KernelAccessDescriptor,
) -> Result<KernelAccessToken, RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let allocation = self.ledger.allocations[allocation_index];
if !kernel_access_descriptor_is_valid(descriptor) {
return Err(RuntimeAllocationError::InvalidKernelAccessDescriptor);
}
if descriptor.purpose == KernelAccessPurpose::Scrub {
return Err(RuntimeAllocationError::InvalidKernelAccessPurpose);
}
validate_kernel_access_range(descriptor, allocation.frame_count)?;
if allocation.scrub_in_progress {
return Err(lifecycle_busy(allocation));
}
if self
.ledger
.accesses
.iter()
.any(|access| access.active && access.descriptor == descriptor)
{
return Err(RuntimeAllocationError::KernelAccessAlreadyExists);
}
let access_index = self
.ledger
.accesses
.iter()
.position(|record| !record.active)
.ok_or(RuntimeAllocationError::AccessCapacity)?;
let generation = self
.ledger
.last_access_generation
.checked_add(1)
.ok_or(RuntimeAllocationError::AccessGenerationOverflow)?;
let allocation_accesses = allocation
.kernel_access_references
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let ledger_accesses = self
.ledger
.kernel_access_references
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let scrubbed = if descriptor.permissions == KernelAccessPermissions::ReadWrite
&& allocation.release_scrubbed
{
self.ledger
.release_scrubbed_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?
} else {
self.ledger.release_scrubbed_allocations
};
let physical_start = token.frame_address(descriptor.frame_offset)?;
self.ledger.accesses[access_index] = AccessRecord {
generation,
owner: current,
allocation_generation: token.allocation_generation,
descriptor,
kind: AccessKind::Kernel,
phase: AccessPhase::Prepared,
active: true,
};
self.ledger.allocations[allocation_index].kernel_access_references = allocation_accesses;
if descriptor.permissions == KernelAccessPermissions::ReadWrite {
self.ledger.allocations[allocation_index].release_scrubbed = false;
}
self.ledger.kernel_access_references = ledger_accesses;
self.ledger.release_scrubbed_allocations = scrubbed;
self.ledger.last_access_generation = generation;
Ok(KernelAccessToken {
owner: current,
allocation_generation: token.allocation_generation,
access_generation: generation,
physical_start,
descriptor,
phase: KernelAccessTokenPhase::Prepared,
})
}
/// # Safety
/// The exact physical subrange and virtual range in `access.descriptor()`
/// must now be mapped with its read/write permission, PXN+UXN, nG, and all
/// required page-table publication barriers. No undeclared alias may have
/// been installed.
pub unsafe fn confirm_kernel_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
access: &mut KernelAccessToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
self.validate_allocation_record(token)?;
let access_index =
self.validate_kernel_access_record(token, access, AccessPhase::Prepared)?;
self.ledger.accesses[access_index].phase = AccessPhase::Mapped;
access.phase = KernelAccessTokenPhase::Mapped;
Ok(())
}
/// Cancel a reservation which was never installed. Writable reservations
/// remain conservatively dirty and require a scrub before reuse.
pub fn cancel_prepared_kernel_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
access: &mut KernelAccessToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let access_index =
self.validate_kernel_access_record(token, access, AccessPhase::Prepared)?;
self.retire_kernel_access_record(allocation_index, access_index)?;
access.phase = KernelAccessTokenPhase::Consumed;
Ok(())
}
/// # Safety
/// Every PTE in this exact temporary mapping must already be invalid, and
/// all local/remote TLB invalidations plus ordering barriers must be durably
/// complete. This single-use close is the unmap/TLBI witness.
pub unsafe fn close_kernel_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
access: &mut KernelAccessToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
let access_index =
self.validate_kernel_access_record(token, access, AccessPhase::Mapped)?;
self.retire_kernel_access_record(allocation_index, access_index)?;
access.phase = KernelAccessTokenPhase::Consumed;
Ok(())
}
/// Reserve the exact full-run RW/NX/nG mapping for one live scrub.
pub fn prepare_scrub_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
scrub: &ScrubToken,
address_space_generation: u64,
virtual_start: u64,
) -> Result<ScrubAccessToken, RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
self.validate_scrub_record(token, scrub)?;
let allocation = self.ledger.allocations[allocation_index];
if allocation.scrub_access_completed {
return Err(RuntimeAllocationError::ScrubAccessAlreadyCompleted {
allocation_generation: allocation.generation,
scrub_generation: allocation.scrub_generation,
});
}
if allocation.access_references()? != 0 {
return Err(lifecycle_busy(allocation));
}
let descriptor = KernelAccessDescriptor::try_new(
address_space_generation,
virtual_start,
0,
allocation.frame_count,
KernelAccessPermissions::ReadWrite,
KernelAccessPurpose::Scrub,
true,
)?;
if self
.ledger
.accesses
.iter()
.any(|access| access.active && access.descriptor == descriptor)
{
return Err(RuntimeAllocationError::KernelAccessAlreadyExists);
}
let access_index = self
.ledger
.accesses
.iter()
.position(|record| !record.active)
.ok_or(RuntimeAllocationError::AccessCapacity)?;
let generation = self
.ledger
.last_access_generation
.checked_add(1)
.ok_or(RuntimeAllocationError::AccessGenerationOverflow)?;
let allocation_accesses = allocation
.scrub_access_references
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
let ledger_accesses = self
.ledger
.scrub_access_references
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
self.ledger.accesses[access_index] = AccessRecord {
generation,
owner: current,
allocation_generation: token.allocation_generation,
descriptor,
kind: AccessKind::Scrub {
scrub_generation: scrub.scrub_generation,
},
phase: AccessPhase::Prepared,
active: true,
};
self.ledger.allocations[allocation_index].scrub_access_references = allocation_accesses;
self.ledger.scrub_access_references = ledger_accesses;
self.ledger.last_access_generation = generation;
Ok(ScrubAccessToken {
owner: current,
allocation_generation: token.allocation_generation,
scrub_generation: scrub.scrub_generation,
access_generation: generation,
physical_start: token.start_address(),
descriptor,
phase: KernelAccessTokenPhase::Prepared,
})
}
/// # Safety
/// The exact full allocation must now be mapped RW, PXN+UXN, nG at the
/// descriptor virtual range with all page-table publication barriers.
pub unsafe fn confirm_scrub_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
scrub: &ScrubToken,
access: &mut ScrubAccessToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
self.validate_allocation_record(token)?;
self.validate_scrub_record(token, scrub)?;
let access_index =
self.validate_scrub_access_record(token, scrub, access, AccessPhase::Prepared)?;
self.ledger.accesses[access_index].phase = AccessPhase::Mapped;
access.phase = KernelAccessTokenPhase::Mapped;
Ok(())
}
pub fn cancel_prepared_scrub_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
scrub: &ScrubToken,
access: &mut ScrubAccessToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
self.validate_scrub_record(token, scrub)?;
let access_index =
self.validate_scrub_access_record(token, scrub, access, AccessPhase::Prepared)?;
self.retire_scrub_access_record(allocation_index, access_index)?;
access.phase = KernelAccessTokenPhase::Consumed;
Ok(())
}
/// # Safety
/// Every byte in the exact full run must have been overwritten, every PTE
/// must be invalid, and all cache maintenance, local/remote TLBI, and
/// ordering barriers must be durably complete. This consumes the only
/// evidence accepted by `complete_scrub`.
pub unsafe fn close_scrub_access(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
scrub: &ScrubToken,
access: &mut ScrubAccessToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let allocation_index = self.validate_allocation_record(token)?;
self.validate_scrub_record(token, scrub)?;
let access_index =
self.validate_scrub_access_record(token, scrub, access, AccessPhase::Mapped)?;
self.retire_scrub_access_record(allocation_index, access_index)?;
self.ledger.allocations[allocation_index].scrub_access_completed = true;
access.phase = KernelAccessTokenPhase::Consumed;
Ok(())
}
pub fn begin_scrub(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
) -> Result<ScrubToken, RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let index = self.validate_allocation_record(token)?;
let allocation = self.ledger.allocations[index];
if allocation.pin_references != 0
|| allocation.mapping_references()? != 0
|| allocation.access_references()? != 0
|| allocation.scrub_in_progress
{
return Err(lifecycle_busy(allocation));
}
if allocation.release_scrubbed {
return Err(RuntimeAllocationError::AllocationAlreadyScrubbed {
allocation_generation: allocation.generation,
});
}
let generation = self
.ledger
.last_scrub_generation
.checked_add(1)
.ok_or(RuntimeAllocationError::ScrubGenerationOverflow)?;
let scrubs = self
.ledger
.scrubs_in_progress
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
self.ledger.allocations[index].scrub_generation = generation;
self.ledger.allocations[index].scrub_in_progress = true;
self.ledger.allocations[index].scrub_access_completed = false;
self.ledger.scrubs_in_progress = scrubs;
self.ledger.last_scrub_generation = generation;
Ok(ScrubToken {
owner: current,
allocation_generation: token.allocation_generation,
scrub_generation: generation,
start: token.start_address(),
frame_count: token.frame_count(),
state: AuthorityState::Live,
})
}
/// # Safety
/// Every byte in the exact run must have been overwritten, with all cache
/// maintenance and barriers required before reuse.
pub unsafe fn complete_scrub(
&mut self,
current: AllocationDomain,
token: &AllocationToken,
scrub: &mut ScrubToken,
) -> Result<(), RuntimeAllocationError> {
self.validate_live_token(current, token)?;
let index = self.validate_allocation_record(token)?;
self.validate_scrub_record(token, scrub)?;
let allocation = self.ledger.allocations[index];
if allocation.access_references()? != 0 {
return Err(lifecycle_busy(allocation));
}
if !allocation.scrub_access_completed {
return Err(RuntimeAllocationError::ScrubAccessRequired {
allocation_generation: allocation.generation,
scrub_generation: allocation.scrub_generation,
});
}
let scrubs = self
.ledger
.scrubs_in_progress
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let scrubbed = self
.ledger
.release_scrubbed_allocations
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
self.ledger.allocations[index].scrub_generation = 0;
self.ledger.allocations[index].scrub_in_progress = false;
self.ledger.allocations[index].scrub_access_completed = false;
self.ledger.allocations[index].release_scrubbed = true;
self.ledger.scrubs_in_progress = scrubs;
self.ledger.release_scrubbed_allocations = scrubbed;
scrub.state = AuthorityState::Consumed;
Ok(())
}
pub fn reap_one_retired(
&mut self,
current: AllocationDomain,
) -> Result<Option<ReapedAllocation>, RuntimeAllocationError> {
self.validate_current_domain(current)?;
let Some((index, record)) =
self.ledger
.allocations
.iter()
.copied()
.enumerate()
.find(|(_, record)| {
record.active
&& record.owner.instance_epoch == self.instance_epoch
&& record.owner.id == current.id
&& record.owner.generation < current.generation
})
else {
return Ok(None);
};
self.ensure_release_ready(record)?;
let active = self
.ledger
.active_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let retired = self
.ledger
.retired_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let scrubbed = self
.ledger
.release_scrubbed_allocations
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let reaped = ReapedAllocation {
owner: record.owner,
allocation_generation: record.generation,
class: record.class,
start: record.start,
frame_count: record.frame_count,
};
self.pmm
.free_contiguous(record.start, record.frame_count)
.map_err(RuntimeAllocationError::Pmm)?;
self.ledger.allocations[index] = AllocationRecord::EMPTY;
self.ledger.active_allocations = active;
self.ledger.retired_allocations = retired;
self.ledger.release_scrubbed_allocations = scrubbed;
Ok(Some(reaped))
}
fn domain_record(&self, id: u32) -> Option<(usize, DomainRecord)> {
self.ledger
.domains
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.occupied && record.id == id)
}
fn allocatable_frame_capacity(&self) -> Result<u64, RuntimeAllocationError> {
let snapshot = self.pmm.snapshot();
snapshot
.total_frames
.checked_sub(snapshot.reserved_frames)
.ok_or(RuntimeAllocationError::InvariantViolation)
}
fn domain_allocated_frames(&self, id: u32) -> Result<u64, RuntimeAllocationError> {
let mut frames = 0u64;
for record in self
.ledger
.allocations
.iter()
.copied()
.filter(|record| record.active && record.owner.id == id)
{
if record.owner.instance_epoch != self.instance_epoch {
return Err(RuntimeAllocationError::InvariantViolation);
}
frames = frames
.checked_add(
u64::try_from(record.frame_count)
.map_err(|_| RuntimeAllocationError::CounterOverflow)?,
)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
Ok(frames)
}
fn allocation_record_by_generation(
&self,
generation: u64,
) -> Option<(usize, AllocationRecord)> {
self.ledger
.allocations
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.active && record.generation == generation)
}
fn validate_current_domain(
&self,
current: AllocationDomain,
) -> Result<usize, RuntimeAllocationError> {
if current.instance_epoch != self.instance_epoch {
return Err(RuntimeAllocationError::ForeignDomainInstance {
expected: self.instance_epoch,
provided: current.instance_epoch,
});
}
let (index, record) = self
.domain_record(current.id)
.ok_or(RuntimeAllocationError::UnknownDomain)?;
if current.generation != record.generation {
return Err(RuntimeAllocationError::StaleGeneration {
domain_id: current.id,
expected: record.generation,
provided: current.generation,
});
}
Ok(index)
}
fn validate_live_token(
&self,
current: AllocationDomain,
token: &AllocationToken,
) -> Result<(), RuntimeAllocationError> {
if token.is_consumed() {
return Err(RuntimeAllocationError::TokenConsumed);
}
self.validate_current_domain(current)?;
if token.owner.instance_epoch != self.instance_epoch {
return Err(RuntimeAllocationError::ForeignTokenInstance {
expected: self.instance_epoch,
provided: token.owner.instance_epoch,
});
}
if current.id != token.owner.id {
return Err(RuntimeAllocationError::CrossDomain {
expected: token.owner.id,
provided: current.id,
});
}
if token.owner.generation != current.generation {
return Err(RuntimeAllocationError::TokenFromRetiredGeneration {
domain_id: token.owner.id,
current: current.generation,
token: token.owner.generation,
});
}
Ok(())
}
fn validate_allocation_record(
&self,
token: &AllocationToken,
) -> Result<usize, RuntimeAllocationError> {
let Some((index, record)) =
self.allocation_record_by_generation(token.allocation_generation)
else {
return Err(RuntimeAllocationError::StaleAllocation {
allocation_generation: token.allocation_generation,
});
};
if record.owner != token.owner
|| record.class != token.class
|| record.start != token.run.start_address()
|| record.frame_count != token.run.frame_count()
{
return Err(RuntimeAllocationError::AllocationRecordMismatch);
}
Ok(index)
}
fn validate_pin_record(
&self,
allocation: &AllocationToken,
pin: &PinToken,
) -> Result<usize, RuntimeAllocationError> {
if pin.is_consumed() {
return Err(RuntimeAllocationError::PinTokenConsumed);
}
let Some((index, record)) = self
.ledger
.pins
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.active && record.generation == pin.pin_generation)
else {
return Err(RuntimeAllocationError::PinRecordMismatch);
};
if pin.owner != allocation.owner
|| pin.allocation_generation != allocation.allocation_generation
|| record.owner != pin.owner
|| record.allocation_generation != pin.allocation_generation
|| record.frame_offset != pin.frame_offset
{
return Err(RuntimeAllocationError::PinRecordMismatch);
}
Ok(index)
}
fn validate_mapping_record(
&self,
allocation: &AllocationToken,
mapping: &MappingToken,
expected: MappingPhase,
) -> Result<usize, RuntimeAllocationError> {
let token_phase = match mapping.phase {
MappingTokenPhase::Prepared => MappingPhase::Prepared,
MappingTokenPhase::Mapped => MappingPhase::Mapped,
MappingTokenPhase::Consumed => {
return Err(RuntimeAllocationError::MappingTokenConsumed)
}
};
if token_phase != expected {
return Err(RuntimeAllocationError::InvalidMappingPhase);
}
let Some((index, record)) = self
.ledger
.mappings
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.active && record.generation == mapping.mapping_generation)
else {
return Err(RuntimeAllocationError::MappingRecordMismatch);
};
if record.phase != expected
|| mapping.owner != allocation.owner
|| mapping.allocation_generation != allocation.allocation_generation
|| record.owner != mapping.owner
|| record.allocation_generation != mapping.allocation_generation
|| record.descriptor != mapping.descriptor
{
return Err(RuntimeAllocationError::MappingRecordMismatch);
}
Ok(index)
}
fn validate_tlb_record(
&self,
allocation: &AllocationToken,
tlb: &TlbInvalidationToken,
) -> Result<usize, RuntimeAllocationError> {
if tlb.is_consumed() {
return Err(RuntimeAllocationError::TlbTokenConsumed);
}
let Some((index, record)) = self
.ledger
.mappings
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.active && record.generation == tlb.mapping_generation)
else {
return Err(RuntimeAllocationError::MappingRecordMismatch);
};
if record.phase != MappingPhase::PendingTlb
|| tlb.owner != allocation.owner
|| tlb.allocation_generation != allocation.allocation_generation
|| record.owner != tlb.owner
|| record.allocation_generation != tlb.allocation_generation
|| record.descriptor != tlb.descriptor
{
return Err(RuntimeAllocationError::MappingRecordMismatch);
}
Ok(index)
}
fn validate_kernel_access_record(
&self,
allocation: &AllocationToken,
access: &KernelAccessToken,
expected: AccessPhase,
) -> Result<usize, RuntimeAllocationError> {
let token_phase = access_token_phase(access.phase, false)?;
if token_phase != expected {
return Err(RuntimeAllocationError::InvalidKernelAccessPhase);
}
let Some((index, record)) = self
.ledger
.accesses
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.active && record.generation == access.access_generation)
else {
return Err(RuntimeAllocationError::AccessRecordMismatch);
};
let expected_start = allocation.frame_address(access.descriptor.frame_offset)?;
if record.phase != expected
|| record.kind != AccessKind::Kernel
|| access.owner != allocation.owner
|| access.allocation_generation != allocation.allocation_generation
|| access.physical_start != expected_start
|| record.owner != access.owner
|| record.allocation_generation != access.allocation_generation
|| record.descriptor != access.descriptor
{
return Err(RuntimeAllocationError::AccessRecordMismatch);
}
Ok(index)
}
fn validate_scrub_access_record(
&self,
allocation: &AllocationToken,
scrub: &ScrubToken,
access: &ScrubAccessToken,
expected: AccessPhase,
) -> Result<usize, RuntimeAllocationError> {
let token_phase = access_token_phase(access.phase, true)?;
if token_phase != expected {
return Err(RuntimeAllocationError::InvalidKernelAccessPhase);
}
let Some((index, record)) = self
.ledger
.accesses
.iter()
.copied()
.enumerate()
.find(|(_, record)| record.active && record.generation == access.access_generation)
else {
return Err(RuntimeAllocationError::AccessRecordMismatch);
};
if record.phase != expected
|| record.kind
!= (AccessKind::Scrub {
scrub_generation: scrub.scrub_generation,
})
|| access.owner != allocation.owner
|| access.allocation_generation != allocation.allocation_generation
|| access.scrub_generation != scrub.scrub_generation
|| access.physical_start != allocation.start_address()
|| record.owner != access.owner
|| record.allocation_generation != access.allocation_generation
|| record.descriptor != access.descriptor
{
return Err(RuntimeAllocationError::AccessRecordMismatch);
}
Ok(index)
}
fn retire_kernel_access_record(
&mut self,
allocation_index: usize,
access_index: usize,
) -> Result<(), RuntimeAllocationError> {
let allocation_accesses = self.ledger.allocations[allocation_index]
.kernel_access_references
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_accesses = self
.ledger
.kernel_access_references
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
self.ledger.accesses[access_index] = AccessRecord::EMPTY;
self.ledger.allocations[allocation_index].kernel_access_references = allocation_accesses;
self.ledger.kernel_access_references = ledger_accesses;
Ok(())
}
fn retire_scrub_access_record(
&mut self,
allocation_index: usize,
access_index: usize,
) -> Result<(), RuntimeAllocationError> {
let allocation_accesses = self.ledger.allocations[allocation_index]
.scrub_access_references
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
let ledger_accesses = self
.ledger
.scrub_access_references
.checked_sub(1)
.ok_or(RuntimeAllocationError::InvariantViolation)?;
self.ledger.accesses[access_index] = AccessRecord::EMPTY;
self.ledger.allocations[allocation_index].scrub_access_references = allocation_accesses;
self.ledger.scrub_access_references = ledger_accesses;
Ok(())
}
fn validate_scrub_record(
&self,
allocation: &AllocationToken,
scrub: &ScrubToken,
) -> Result<(), RuntimeAllocationError> {
if scrub.is_consumed() {
return Err(RuntimeAllocationError::ScrubTokenConsumed);
}
let (_, record) = self
.allocation_record_by_generation(allocation.allocation_generation)
.ok_or(RuntimeAllocationError::ScrubRecordMismatch)?;
if scrub.owner != allocation.owner
|| scrub.allocation_generation != allocation.allocation_generation
|| scrub.start != allocation.start_address()
|| scrub.frame_count != allocation.frame_count()
|| !record.scrub_in_progress
|| record.scrub_generation != scrub.scrub_generation
{
return Err(RuntimeAllocationError::ScrubRecordMismatch);
}
Ok(())
}
fn ensure_release_ready(&self, record: AllocationRecord) -> Result<(), RuntimeAllocationError> {
let (observed_pins, _) = self.observed_record_pins(record)?;
if observed_pins != record.pin_references {
return Err(RuntimeAllocationError::InvariantViolation);
}
if observed_pins != 0 {
return Err(RuntimeAllocationError::AllocationPinned {
allocation_generation: record.generation,
pin_references: observed_pins,
});
}
if record.mapping_references()? != 0
|| record.access_references()? != 0
|| record.scrub_in_progress
{
return Err(lifecycle_busy(record));
}
if !record.release_scrubbed {
return Err(RuntimeAllocationError::AllocationNeedsScrub {
allocation_generation: record.generation,
});
}
Ok(())
}
fn observed_record_pins(
&self,
record: AllocationRecord,
) -> Result<(u64, u64), RuntimeAllocationError> {
let mut pins = 0u64;
let mut pinned_frames = 0u64;
for frame_offset in 0..record.frame_count {
let address = record_frame_address(record, frame_offset)?;
let token_pin_count = u64::try_from(
self.ledger
.pins
.iter()
.filter(|pin| {
pin.active
&& pin.allocation_generation == record.generation
&& pin.frame_offset == frame_offset
})
.count(),
)
.map_err(|_| RuntimeAllocationError::CounterOverflow)?;
match self
.pmm
.frame_state(address)
.map_err(RuntimeAllocationError::Pmm)?
{
RuntimeFrameState::Allocated { pin_count } => {
if token_pin_count != pin_count as u64 {
return Err(RuntimeAllocationError::InvariantViolation);
}
if pin_count != 0 {
pinned_frames = pinned_frames
.checked_add(1)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
pins = pins
.checked_add(pin_count as u64)
.ok_or(RuntimeAllocationError::CounterOverflow)?;
}
RuntimeFrameState::Free | RuntimeFrameState::Reserved => {
return Err(RuntimeAllocationError::InvariantViolation);
}
}
}
Ok((pins, pinned_frames))
}
}snippet sha256: 55bfb6853c4c…file sha256: f0f53099668f…
02 · Doğrulayan test kodu
Operations komutuna bağlı focused test
tam Rust öğesiL44–L80
simulation/tests/runtime_boot_authority_fail_closed.rs::insufficient_metadata_permanently_poisoned_the_one_shot_slot
#[test]
fn insufficient_metadata_permanently_poisoned_the_one_shot_slot() {
let transfer = BumpAllocator::try_from_regions(&[(0x1000, 0x2000)])
.unwrap()
.into_runtime_transfer()
.unwrap();
let too_small = unsafe { static_slice(core::ptr::addr_of_mut!(SMALL_METADATA).cast(), 1) };
assert_eq!(
// SAFETY: Simulation-only addresses and permanent disjoint metadata.
unsafe { install_boot_runtime_memory(transfer, &[], too_small) },
Err(BootRuntimeMemoryError::MetadataTooSmall {
required: 2,
provided: 1,
})
);
assert_eq!(
boot_runtime_memory_status(),
BootRuntimeMemoryStatus::PermanentlyFailed
);
assert_eq!(
with_boot_runtime_memory(|memory| memory.snapshot()),
Err(BootRuntimeMemoryError::PermanentlyFailed)
);
let retry = BumpAllocator::try_from_regions(&[(0x8000, 0x2000)])
.unwrap()
.into_runtime_transfer()
.unwrap();
let retry_metadata = unsafe { static_slice(core::ptr::addr_of_mut!(RETRY_METADATA).cast(), 2) };
assert_eq!(
// SAFETY: The call is expected to reject before observing these
// disjoint simulation-only resources.
unsafe { install_boot_runtime_memory(retry, &[], retry_metadata) },
Err(BootRuntimeMemoryError::PermanentlyFailed)
);
}snippet sha256: ae68ba3d5c4e…file sha256: 39285624ff93…
03 · Kapı kimlik kaydı
Operations sıra, kimlik ve başlık bağı
tam Operations kaydıL26621–L26714
website/src/lib/operations.ts::k1-mem2-audited-runtime-pressure-oom-partial
{
id: "k1-mem2-audited-runtime-pressure-oom-partial",
date: "2026-08-23",
sequence: 128,
status: "passed",
umbrella_status: "partial",
title: "K1/MEM2: audited RuntimeMemory pressure/OOM karar köprüsü",
summary:
"S127'nin authoritative frame/domain ledger'ı üzerinde S128, pressure free-frame gözlemi ile bütün OOM kullanım sayaçlarını audited RuntimeMemoryState ve RuntimePmm envanterinden yeniden kurar. Çağıran yalnız current AllocationDomain, OOM priority ve protected politikasını verir; eksik/duplicate/stale/foreign-instance politika kümeleri controller level/epoch mutasyonundan önce fail-closed reddedilir. Protected veya pinli domain kurban seçilmez; uygun aday yoksa karar açıkça victim=None taşır. Bu yalnız immutable karar handoff'udur: task öldürme, reclaim ve supervisor delivery bağlı değildir. K1/MEM0–MEM2 PARTIAL kalır.",
evidence: [
"Focused serialized host 46/46 PASS: runtime_pressure_authority 4/4, memory_pressure 4/4, runtime_domain_quota 3/3, runtime_memory_reconciliation 5/5, runtime_allocation_token 18/18, memory_accounting 9/9 ve runtime_boot_authority family 3/3.",
"Pressure free frames ile allocated/retired/pinned/pin-reference/reclaimable OOM sayaçları caller girdisinden değil audited RuntimeMemoryState/RuntimePmm snapshot'ından türetilir.",
"Exact runtime instance, bütün registered domain'lerin eksiksiz ve tekil coverage'ı ile current generation doğrulaması controller mutasyonundan önce tamamlanır.",
"Protected veya tek bir pini bulunan domain bütünüyle aday dışı kalır; Critical OOM epoch'unda uygun kurban yoksa kernel hedef uydurmadan explicit victim=None döndürür.",
"AArch64 board-qemu, board-rpi4, board-rpi5 ve board-rpi5+smp compile applicability 4/4 PASS.",
"QEMU smoke mevcut strict ELF MEM0 ledger/reclaim, hello x4096, IPC 3/3 ve scheduler SEC5 regresyonunu geçti; S128 monitor scheduler/boot yoluna bağlı olmadığı için bu OOM runtime-effect kanıtı değildir.",
"Tam workspace, S128 dışındaki frozen S96 SHA-256, S97 byte identity ve S100 reconstruction identity yüzeylerinde toplam dört assertion nedeniyle GREEN değildir; bunlar dışlandığında kalan workspace PASS. Frozen testler gevşetilmedi.",
"Kalıcı kapsam ve açık sınırlar: `docs/K1-S128-Audited-Runtime-Pressure-OOM-Proof.md`.",
],
commands: [
"cargo test -p aselsan_microkernel_simulation --test runtime_pressure_authority --test memory_pressure --test runtime_domain_quota --test runtime_memory_reconciliation --test runtime_allocation_token --test memory_accounting --test runtime_boot_authority --test runtime_boot_authority_fail_closed --test runtime_boot_authority_no_alloc -- --test-threads=1",
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-qemu",
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-rpi4",
"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-rpi5,smp",
"make verify-qemu",
"cargo test --workspace -- --test-threads=1",
],
terminalSessions: [
{
id: "s128-audited-pressure-focused-host",
title: "Audited pressure/OOM authority host kapıları",
commandLines: [
"cargo test -p aselsan_microkernel_simulation --test runtime_pressure_authority --test memory_pressure --test runtime_domain_quota --test runtime_memory_reconciliation --test runtime_allocation_token --test memory_accounting --test runtime_boot_authority --test runtime_boot_authority_fail_closed --test runtime_boot_authority_no_alloc -- --test-threads=1",
],
outputLines: [
"runtime_pressure_authority: 4 passed",
"memory_pressure: 4 passed",
"runtime_domain_quota: 3 passed",
"runtime_memory_reconciliation: 5 passed",
"runtime_allocation_token: 18 passed",
"memory_accounting: 9 passed",
"runtime_boot_authority family: 3 passed",
"focused total: 46/46 PASS",
],
exitCode: 0,
outputMode: "selected",
},
{
id: "s128-compile-and-qemu-regression",
title: "Dört AArch64 profil ve mevcut QEMU runtime regresyonu",
commandLines: [
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-qemu",
"cargo check -p aselsan_kernel --target aarch64-unknown-none --no-default-features --features board-rpi4",
"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-rpi5,smp",
"make verify-qemu",
],
outputLines: [
"AArch64 compile profiles: 4/4 PASS",
"QEMU smoke PASS: strict ELF MEM0 ledger/reclaim baseline + hello x4096 + IPC reply 3/3 + scheduler SEC 5",
"S128 RuntimePressureMonitor invocation: NOT_WIRED",
],
exitCode: 0,
outputMode: "selected",
},
{
id: "s128-workspace-independent-history-red",
title: "Tam workspace: S128 dışı frozen tarihsel assertion'lar",
commandLines: ["cargo test --workspace -- --test-threads=1"],
outputLines: [
"S96 exceptions.S SHA-256: observed f7b47672...04fd, frozen expected c0eed3e2...cb89",
"S97 G8h integration identity: observed 15003 bytes, frozen expected 14770",
"S100 package-source reconstruction: observed 52911 bytes, frozen expected 52745",
"four independent frozen assertions skipped: remaining workspace PASS",
"full-workspace GREEN is not claimed",
],
exitCode: 101,
outputMode: "selected",
outputNote:
"S128 bu frozen G8h dosyalarını, identity sabitlerini veya testleri değiştirmedi ya da gevşetmedi.",
},
],
terminalSessionsNote:
"S128 audited decision API'sinin host, compile ve mevcut QEMU regresyon kaydıdır. Scheduler/supervisor etkisi çalıştırılmadı; fiziksel veya device işlemi yapılmadı.",
limitations: [
"K1, MEM0, MEM1 ve MEM2 COMPLETE değildir. Karar API'si task termination, frame reclaim veya supervisor event delivery çağırmaz.",
"Threshold ve priority değerleri signed ürün/service manifestinden ya da ölçülmüş RAM bütçesinden gelmez.",
"Legacy bump, page-table, capability, endpoint, IRQ, DMA, surface ve IPC-loan üreticilerinin tamamı authoritative runtime ledger'da değildir.",
"Repeated spawn/fault/exit soak ile injected malformed-ELF/page-fault/OOM runtime matrisi açıktır.",
"S124 archive/promotion STOP kalır. Son fiziksel boot/runtime PASS S92 BOOT8G / CPU1_PER_CPU_TIMER_ONLY; S123 PHYSICAL_BOOT8H=REJECTED_NO_PASS.",
"CARD_WRITE=0, PHYSICAL_CARD_READBACK=0, SYNC=0, EJECT=0, UART=STOP, POWER=STOP ve PHYSICAL_BOOT8H=STOP.",
],
},snippet sha256: 8007605986df…file sha256: 9726dbf00f84…
Focused test komutu
cargo test -p aselsan_microkernel_simulation --test runtime_pressure_authority --test memory_pressure --test runtime_domain_quota --test runtime_memory_reconciliation --test runtime_allocation_token --test memory_accounting --test runtime_boot_authority --test runtime_boot_authority_fail_closed --test runtime_boot_authority_no_alloc -- --test-threads=1proof: docs/K1-S128-Audited-Runtime-Pressure-OOM-Proof.md
Registry schema v5 · generator
website/scripts/generate-code-gates.mjs · Tam SHA-256: 91d38c7b6222f0b4c117be786454853543da55a160e543d9b951057cc20dcc06