diff --git a/Makefile b/Makefile index 1c378f8..1699d01 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ diligence-demo: echo "diligence-demo: host Path B golden lines ok" # Host sell-path: named attacks the kernel already refuses. Reuses -# blast / blast-hops / blast-nodes / bank-color / uncolored-compute / foreign-tenant-color / qos-credits / fence-not-ready / outside-slice / typed-window-sid / silent-remote / hbm-bw / xqueue-sid-override / set-sid-unbound / submit-sid / sid-budget / stage2-fault / softnoi-exhausted / hodge-harmonic-tree / hodge-curl-tree / hodge-quota / SoftCmdFirewall / firewall-ident-pa / greenctx-overcommit / greenctx-unbound / greenctx-exhausted / SoftSFI / SoftNoI-IS / PASID clips. +# blast / blast-hops / blast-nodes / bank-color / uncolored-compute / foreign-tenant-color / qos-credits / fence-not-ready / outside-slice / typed-window-sid / silent-remote / hbm-bw / xqueue-sid-override / set-sid-unbound / submit-sid / sid-budget / stage2-fault / softnoi-exhausted / hodge-harmonic-tree / hodge-curl-tree / hodge-quota / SoftCmdFirewall / firewall-ident-pa / greenctx-overcommit / greenctx-unbound / greenctx-exhausted / greenctx-busy / SoftSFI / SoftNoI-IS / PASID clips. # CI greps the [redteam] proof lines. Not a QEMU guest. REDTEAM_LOG := $(BUILD)/redteam.log @@ -176,6 +176,7 @@ red-team: grep -q "\\[redteam\\] attack=greenctx-overcommit result=refused" $(REDTEAM_LOG) grep -q "\\[redteam\\] attack=greenctx-unbound result=refused" $(REDTEAM_LOG) grep -q "\\[redteam\\] attack=greenctx-exhausted result=refused" $(REDTEAM_LOG) + grep -q "\\[redteam\\] attack=greenctx-busy result=refused" $(REDTEAM_LOG) grep -F -x -q "[redteam] fabric-class admit/refuse" $(REDTEAM_LOG) grep -F -x -q "[redteam] ATOMIC_ADD accept/reject" $(REDTEAM_LOG) grep -F -x -q "[softsfi] tensor=refused" $(REDTEAM_LOG) diff --git a/core/src/greenctx.rs b/core/src/greenctx.rs index 78496be..60a4a25 100644 --- a/core/src/greenctx.rs +++ b/core/src/greenctx.rs @@ -602,6 +602,57 @@ pub fn run_greenctx_exhausted_demo() -> GreenCtxExhaustedReport { } } + +/// Host red-team report for SoftGreenPool migrate_to_yield Busy refuse. +/// +/// Sell line `[redteam] attack=greenctx-busy` — existing +/// [`SoftGreenPool::migrate_to_yield`] path only. Dest ctx already bound to +/// another queue → [`GreenCtxError::Busy`]. Same-SID happy migrate still OK on +/// a free dest. **Not** greenctx-unbound (never-bound queue), **not** +/// greenctx-overcommit / greenctx-exhausted, **not** xqueue-sid-override Soft-CP +/// Busy, **not** HW MIG / BAR0 / SoftNPU. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct GreenCtxBusyReport { + /// Bind lo→0 and hi→1; migrate 0→hi (dest busy with 1) → Busy; queues stick. + pub busy: bool, + /// Optional same-pool bind contrast: re-bind lo to a foreign queue → Busy. + pub bind_busy: bool, + /// Contrast: never-bound queue still → Unbound (sibling needle stays separate). + pub contrast_unbound: bool, +} + +impl GreenCtxBusyReport { + pub fn all_ok(&self) -> bool { + self.busy && self.bind_busy && self.contrast_unbound + } +} + +/// `SoftGreenPool::migrate_to_yield` when dest is bound elsewhere → [`GreenCtxError::Busy`]. +/// Occupied dest path — not Unbound / Overcommit / Exhausted / xqueue Busy / HW MIG. +pub fn run_greenctx_busy_demo() -> GreenCtxBusyReport { + let mut p = SoftGreenPool::new(); + let (hi, lo) = p.split_70_30().unwrap(); + p.bind(lo, 0).unwrap(); + p.bind(hi, 1).unwrap(); + let sid = StreamId::from_raw(0x11_22_33_44); + // Dest hi already holds queue 1 ≠ 0 → Busy. Queues stay put. + let busy = p.migrate_to_yield(0, hi, sid) == Err(GreenCtxError::Busy) + && p.ctx_for_queue(0) == Some(lo) + && p.ctx_for_queue(1) == Some(hi); + // Optional bind-busy (same Error::Busy; not a separate PR): lo already on 0. + let bind_busy = p.bind(lo, 1) == Err(GreenCtxError::Busy); + // Fresh pool: never-bound queue → Unbound (sibling contrast). + let mut p2 = SoftGreenPool::new(); + let (hi2, _lo2) = p2.split_70_30().unwrap(); + let contrast_unbound = p2.migrate_to_yield(1, hi2, sid) == Err(GreenCtxError::Unbound); + + GreenCtxBusyReport { + busy, + bind_busy, + contrast_unbound, + } +} + #[cfg(test)] mod tests { use super::*; @@ -725,4 +776,14 @@ mod tests { assert!(r.contrast_overcommit, "70/30 fill → Overcommit contrast"); assert!(r.all_ok()); } + + #[test] + fn greenctx_busy_demo_refuses_occupied_dest() { + let r = run_greenctx_busy_demo(); + assert!(r.busy, "dest bound elsewhere → Busy"); + assert!(r.bind_busy, "re-bind foreign queue → Busy"); + assert!(r.contrast_unbound, "never-bound → Unbound contrast"); + assert!(r.all_ok()); + } + } diff --git a/core/src/lib.rs b/core/src/lib.rs index 2942b2d..bc38c8f 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -80,8 +80,8 @@ pub use elf::{parse_elf64, ElfError, ElfImage}; pub use fabric::{ChipletRoute, EndpointId, Fabric, FabricError, Message, MsgFlags}; pub use fence::{run_fence_not_ready_demo, Fence, FenceId, FenceNotReadyReport, Timeline, TimelineId, MAX_IN_FLIGHT}; pub use greenctx::{ - run_greenctx_demo, run_greenctx_exhausted_demo, run_greenctx_overcommit_demo, - run_greenctx_unbound_demo, GreenCtxError, GreenCtxExhaustedReport, GreenCtxId, + run_greenctx_busy_demo, run_greenctx_demo, run_greenctx_exhausted_demo, run_greenctx_overcommit_demo, + run_greenctx_unbound_demo, GreenCtxBusyReport, GreenCtxError, GreenCtxExhaustedReport, GreenCtxId, GreenCtxOvercommitReport, GreenCtxReport, GreenCtxUnboundReport, MemcpyReport, SmWqBudget, SoftGreenCtx, SoftGreenPool, DEMO_MEMCPY_BYTES, MAX_GREEN_CTX, SHARED_BW_TAX_MILLI, SOFT_SM_POOL, SOFT_WQ_POOL, SPLIT_30, SPLIT_70, diff --git a/docs/DILIGENCE.md b/docs/DILIGENCE.md index c3a7b70..998a77a 100644 --- a/docs/DILIGENCE.md +++ b/docs/DILIGENCE.md @@ -42,7 +42,7 @@ reserved. Freeze proof: `make design-win-standin`. Port skipped | Command | What they see | | --- | --- | | `make diligence-demo` | blast / pjrt / event + fence counts / softcct package ≪ broadcast + single-chiplet=noop + incorrect-elision=refused / `[scope] soft≠strict` / firewall / greenctx 70/30 + interference + migrate SID-sticky / cdt revoke descendants / softcp sparsify DROP / opinject resident+hot-add / partner-hello bad-exec | -| `make red-team` | named refuses + fabric-class + `ATOMIC_ADD` + `[softsfi] tensor=refused` + `[softsfi] heap=refused` + `[softsfi] unknown=refused` + `[softsfi] unknown-base=refused` + `typed-window-sid` + `hbm-bw` + `xqueue-sid-override` + `set-sid-unbound` + `submit-sid` + `sid-budget` + `stage2-fault` + `softnoi-exhausted` + `hodge-harmonic-tree` + `hodge-curl-tree` + `hodge-quota` + `firewall-ident-pa` + `greenctx-overcommit` + `greenctx-unbound` + `greenctx-exhausted` + `foreign-tenant-color` | +| `make red-team` | named refuses + fabric-class + `ATOMIC_ADD` + `[softsfi] tensor=refused` + `[softsfi] heap=refused` + `[softsfi] unknown=refused` + `[softsfi] unknown-base=refused` + `typed-window-sid` + `hbm-bw` + `xqueue-sid-override` + `set-sid-unbound` + `submit-sid` + `sid-budget` + `stage2-fault` + `softnoi-exhausted` + `hodge-harmonic-tree` + `hodge-curl-tree` + `hodge-quota` + `firewall-ident-pa` + `greenctx-overcommit` + `greenctx-unbound` + `greenctx-exhausted` / `greenctx-busy` + `foreign-tenant-color` | | `make partner-hello` | frozen `IreeHalCmd` → `IreeShapedCp`; bad exec refused | | `make mp-shim` | MicroPerceptron-shaped thin consumer (PR #83). Inspiration name only. Not a port. | | `make design-win-check` / `make design-win-standin` | blank they fill, or the IREE HAL research stand-in (not a partner). TRANSFER-only refused. | @@ -323,7 +323,7 @@ task-local AP_EL0 leaves + Soft SMMU” (no PAN on cortex-a72). | --- | --- | --- | | Host tests | `cargo test --workspace` | Caps + CDT properties, fabric, arenas, color, map, typed window stub, sched, SoftNPU, Laplacian, ELF, ramfs, bootfs, mmap, opkernel, sparsify, diligence-demo + red-team + accel-client + aether-mp-shim + design-win-check crates, partner-hello | | Diligence demo | `make diligence-demo` | Host Path B partner clip; greps `[blast]` / `[pjrt]` / `[event]` / `[softcct]` (package ≪ broadcast + `single-chiplet=noop` + `incorrect-elision=refused`) / `[scope] soft≠strict` / `[firewall]` / `[greenctx]` (incl. M3 interference + migrate SID-sticky) / `[cdt] revoke descendants ok` / `[softcp] sparsify DROP` / `[opinject] resident worker + hot-add sealed` / `[partner-hello] bad executable` + proves/does-not. No QEMU rebuild. Caps/CDT honesty ≠ CapTable milestone | -| Red-team clip | `make red-team` | Host stdout; greps `[redteam] attack=… result=refused` plus fabric-class / `ATOMIC_ADD` / `[softsfi] tensor=refused` / `[softsfi] heap=refused` / `[softsfi] unknown=refused` / `[softsfi] unknown-base=refused` / `typed-window-sid` / `hbm-bw` / `xqueue-sid-override` / `set-sid-unbound` / `submit-sid` / `sid-budget` / `stage2-fault` / `softnoi-exhausted` / `hodge-harmonic-tree` / `hodge-curl-tree` / `hodge-quota` / `firewall-ident-pa` / `greenctx-overcommit` / `greenctx-unbound` / `greenctx-exhausted` / `foreign-tenant-color` and the “what this is not” closer | +| Red-team clip | `make red-team` | Host stdout; greps `[redteam] attack=… result=refused` plus fabric-class / `ATOMIC_ADD` / `[softsfi] tensor=refused` / `[softsfi] heap=refused` / `[softsfi] unknown=refused` / `[softsfi] unknown-base=refused` / `typed-window-sid` / `hbm-bw` / `xqueue-sid-override` / `set-sid-unbound` / `submit-sid` / `sid-budget` / `stage2-fault` / `softnoi-exhausted` / `hodge-harmonic-tree` / `hodge-curl-tree` / `hodge-quota` / `firewall-ident-pa` / `greenctx-overcommit` / `greenctx-unbound` / `greenctx-exhausted` / `greenctx-busy` / `foreign-tenant-color` and the “what this is not” closer | | Design-win checker | `make design-win-check` | Loads sample filled worksheet; refuses unknown executable / SID 0 / TRANSFER-only. No pipes | | IREE HAL stand-in | `make design-win-standin` | Admits `docs/design-win/iree-hal-standin.toml`. Not a partner | | Partner hello | `make partner-hello-ci` | Frozen `IreeHalCmd` pack/submit + bad executable refuse; no QEMU | @@ -383,6 +383,7 @@ runs `examples/red-team` on the host and prints grep-able lines. It | SoftGreenPool SM/WQ overcommit | `run_greenctx_overcommit_demo` — `SoftGreenPool::create` → `GreenCtxError::Overcommit` past pool (in-budget admits; after 70/30 fill refuses). **Not** diligence `run_greenctx_demo` 70/30 sell; not HW MIG / BAR0 / SoftNPU | refused | | SoftGreenPool migrate unbound | `run_greenctx_unbound_demo` — `SoftGreenPool::migrate_to_yield` → `GreenCtxError::Unbound` on never-bound queue (bound migrate keeps SID). **Not** set-sid-unbound Soft-CP Fault; not greenctx-overcommit; not HW MIG / BAR0 / SoftNPU | refused | | SoftGreenPool slot exhausted | `run_greenctx_exhausted_demo` — `SoftGreenPool::create` past `MAX_GREEN_CTX` → `GreenCtxError::Exhausted` (tiny in-budget fills admit; contrast after 70/30 → Overcommit). **Not** greenctx-overcommit SM/WQ; not SoftNoI Exhausted; not HW MIG / BAR0 / SoftNPU | refused | +| SoftGreenPool migrate dest busy | `run_greenctx_busy_demo` — `SoftGreenPool::migrate_to_yield` → `GreenCtxError::Busy` when dest bound to another queue (`bind(lo,0); bind(hi,1); migrate 0→hi`). **Not** greenctx-unbound; not overcommit/exhausted; not xqueue-sid-override Soft-CP Busy; not HW MIG / BAR0 / SoftNPU | refused | Expected stdout (CI greps these): @@ -416,6 +417,7 @@ Expected stdout (CI greps these): [redteam] attack=greenctx-overcommit result=refused [redteam] attack=greenctx-unbound result=refused [redteam] attack=greenctx-exhausted result=refused +[redteam] attack=greenctx-busy result=refused [redteam] fabric-class admit/refuse [redteam] ATOMIC_ADD accept/reject [softsfi] tensor=refused diff --git a/examples/red-team/README.md b/examples/red-team/README.md index 8fac252..b36f925 100644 --- a/examples/red-team/README.md +++ b/examples/red-team/README.md @@ -4,7 +4,7 @@ Host stdout a buyer can grep. Reuses `run_blast_demo`, `run_blast_hops_demo`, `run_blast_nodes_demo`, `run_bank_color_demo`, `run_uncolored_compute_demo`, `run_foreign_tenant_color_demo`, `run_qos_credits_demo`, `run_fence_not_ready_demo`, `run_outside_slice_demo`, `run_typed_window_sid_demo`, `run_silent_remote_demo`, `run_hbm_bw_demo`, `run_xqueue_sid_override_demo`, `run_set_sid_unbound_demo`, `run_submit_sid_demo`, `run_sid_budget_demo`, `run_stage2_fault_demo`, `run_softnoi_exhausted_demo`, -`run_hodge_harmonic_tree_demo`, `run_hodge_curl_tree_demo`, `run_hodge_quota_demo`, `run_firewall_demo`, `run_firewall_ident_pa_demo`, `run_greenctx_overcommit_demo`, `run_greenctx_unbound_demo`, `run_greenctx_exhausted_demo`, `run_softsfi_demo`, +`run_hodge_harmonic_tree_demo`, `run_hodge_curl_tree_demo`, `run_hodge_quota_demo`, `run_firewall_demo`, `run_firewall_ident_pa_demo`, `run_greenctx_overcommit_demo`, `run_greenctx_unbound_demo`, `run_greenctx_exhausted_demo`, `run_greenctx_busy_demo`, `run_softsfi_demo`, `run_softnoi_demo`, and `run_sva_demo`. Not a new isolator, not a QEMU guest, not a slide. Blast-nodes needle: `[redteam] attack=blast-nodes result=refused` (`admit_nodes` → `BlastRadius`; @@ -69,6 +69,8 @@ set-sid-unbound Soft-CP Fault; not greenctx-overcommit; not HW MIG / BAR0 / Soft Greenctx-exhausted needle: `[redteam] attack=greenctx-exhausted result=refused` (`SoftGreenPool::create` past `MAX_GREEN_CTX` slots → `GreenCtxError::Exhausted`; not greenctx-overcommit SM/WQ ceiling; not SoftNoI Exhausted; not HW MIG / BAR0 / SoftNPU). +Greenctx-busy needle: `[redteam] attack=greenctx-busy result=refused` +(`SoftGreenPool::migrate_to_yield` when dest bound to another queue → `GreenCtxError::Busy`; not greenctx-unbound; not overcommit/exhausted; not xqueue-sid-override Soft-CP Busy; not HW MIG / BAR0 / SoftNPU). SoftSFI tensor needle: `[softsfi] tensor=refused` (`SoftOp::Tensor` → `Unmodeled`; heap line stays separate). SoftSFI unknown needle: `[softsfi] unknown=refused` / `[softsfi] unknown-base=refused` (bad opcode / illegal width → diff --git a/examples/red-team/src/main.rs b/examples/red-team/src/main.rs index c519282..d975778 100644 --- a/examples/red-team/src/main.rs +++ b/examples/red-team/src/main.rs @@ -5,7 +5,7 @@ //! `run_bank_color_demo`, `run_uncolored_compute_demo`, //! `run_foreign_tenant_color_demo`, `run_qos_credits_demo`, `run_fence_not_ready_demo`, `run_outside_slice_demo`, `run_typed_window_sid_demo`, //! `run_silent_remote_demo`, `run_hbm_bw_demo`, `run_xqueue_sid_override_demo`, -//! `run_set_sid_unbound_demo`, `run_submit_sid_demo`, `run_sid_budget_demo`, `run_stage2_fault_demo`, `run_softnoi_exhausted_demo`, `run_hodge_harmonic_tree_demo`, `run_hodge_curl_tree_demo`, `run_hodge_quota_demo`, `run_firewall_demo`, `run_firewall_ident_pa_demo`, `run_greenctx_overcommit_demo`, `run_greenctx_unbound_demo`, `run_greenctx_exhausted_demo`, +//! `run_set_sid_unbound_demo`, `run_submit_sid_demo`, `run_sid_budget_demo`, `run_stage2_fault_demo`, `run_softnoi_exhausted_demo`, `run_hodge_harmonic_tree_demo`, `run_hodge_curl_tree_demo`, `run_hodge_quota_demo`, `run_firewall_demo`, `run_firewall_ident_pa_demo`, `run_greenctx_overcommit_demo`, `run_greenctx_unbound_demo`, `run_greenctx_exhausted_demo`, `run_greenctx_busy_demo`, //! `run_softsfi_demo`, `run_softnoi_demo`, `run_sva_demo`). //! This crate does not invent a new isolation mechanism. //! @@ -60,7 +60,9 @@ //! `migrate_to_yield` on a queue with no bound ctx → `GreenCtxError::Unbound` (not set-sid-unbound Soft-CP //! Fault; not greenctx-overcommit SM/WQ ceiling; not HW MIG / BAR0 / SoftNPU). Greenctx-exhausted is SoftGreenPool //! `create` past `MAX_GREEN_CTX` slots → `GreenCtxError::Exhausted` (not greenctx-overcommit SM/WQ ceiling; -//! not SoftNoI Exhausted; not HW MIG / BAR0 / SoftNPU). The closer names what this is **not**: +//! not SoftNoI Exhausted; not HW MIG / BAR0 / SoftNPU). Greenctx-busy is SoftGreenPool +//! `migrate_to_yield` when dest is bound to another queue → `GreenCtxError::Busy` (not greenctx-unbound; +//! not greenctx-overcommit / exhausted; not xqueue-sid-override Soft-CP Busy; not HW MIG / BAR0 / SoftNPU). The closer names what this is **not**: //! confidential GPU, HW MIG, hardware SMMU (Soft SMMU is software). //! //! Run: `make red-team` or `cargo run -p aether-redteam`. @@ -81,7 +83,7 @@ use aether_core::sva::run_sva_demo; use aether_core::window::run_typed_window_sid_demo; use aether_core::opkernel::{run_hodge_curl_tree_demo, run_hodge_harmonic_tree_demo}; use aether_core::hodge::run_hodge_quota_demo; -use aether_core::greenctx::{run_greenctx_exhausted_demo, run_greenctx_overcommit_demo, run_greenctx_unbound_demo}; +use aether_core::greenctx::{run_greenctx_busy_demo, run_greenctx_exhausted_demo, run_greenctx_overcommit_demo, run_greenctx_unbound_demo}; use aether_drivers::{ run_firewall_demo, run_firewall_ident_pa_demo, run_set_sid_unbound_demo, run_xqueue_sid_override_demo, @@ -117,6 +119,7 @@ const LINE_FIREWALL_IDENT_PA: &str = "[redteam] attack=firewall-ident-pa result= const LINE_GREENCTX_OVERCOMMIT: &str = "[redteam] attack=greenctx-overcommit result=refused"; const LINE_GREENCTX_UNBOUND: &str = "[redteam] attack=greenctx-unbound result=refused"; const LINE_GREENCTX_EXHAUSTED: &str = "[redteam] attack=greenctx-exhausted result=refused"; +const LINE_GREENCTX_BUSY: &str = "[redteam] attack=greenctx-busy result=refused"; const LINE_CLASS: &str = "[redteam] fabric-class admit/refuse"; const LINE_ATOMIC: &str = "[redteam] ATOMIC_ADD accept/reject"; const LINE_TENSOR: &str = "[softsfi] tensor=refused"; @@ -158,6 +161,7 @@ struct RedTeamReport { greenctx_overcommit: bool, greenctx_unbound: bool, greenctx_exhausted: bool, + greenctx_busy: bool, class: bool, atomic: bool, tensor: bool, @@ -197,6 +201,7 @@ impl RedTeamReport { && self.greenctx_overcommit && self.greenctx_unbound && self.greenctx_exhausted + && self.greenctx_busy && self.class && self.atomic && self.tensor @@ -234,6 +239,7 @@ fn run_redteam() -> RedTeamReport { let greenctx_over = run_greenctx_overcommit_demo(); let greenctx_unbound = run_greenctx_unbound_demo(); let greenctx_exhausted = run_greenctx_exhausted_demo(); + let greenctx_busy = run_greenctx_busy_demo(); let sfi = run_softsfi_demo(); let noi = run_softnoi_demo(); let sva = run_sva_demo(); @@ -324,6 +330,9 @@ fn run_redteam() -> RedTeamReport { // SoftGreenPool::create past MAX_GREEN_CTX slots → Exhausted. // Not greenctx-overcommit SM/WQ; not SoftNoI Exhausted; not HW MIG. greenctx_exhausted: greenctx_exhausted.all_ok(), + // SoftGreenPool::migrate_to_yield dest bound elsewhere → Busy. + // Not greenctx-unbound; not overcommit/exhausted; not xqueue Soft-CP Busy; not HW MIG. + greenctx_busy: greenctx_busy.all_ok(), // Fabric-class tag: Gradient admits; second Curl refuses (ring). class: noi.class_grad_admit && noi.class_curl_refuse, // SID-proved toy fetch-add: in-bounds accept, foreign span Oob. @@ -388,6 +397,7 @@ fn print_clip(r: &RedTeamReport) { emit(r.greenctx_overcommit, LINE_GREENCTX_OVERCOMMIT); emit(r.greenctx_unbound, LINE_GREENCTX_UNBOUND); emit(r.greenctx_exhausted, LINE_GREENCTX_EXHAUSTED); + emit(r.greenctx_busy, LINE_GREENCTX_BUSY); emit_tagged(r.class, LINE_CLASS); emit_tagged(r.atomic, LINE_ATOMIC); emit_tagged(r.tensor, LINE_TENSOR); @@ -486,6 +496,10 @@ mod tests { r.greenctx_exhausted, "SoftGreenPool::create past MAX_GREEN_CTX → Exhausted" ); + assert!( + r.greenctx_busy, + "SoftGreenPool::migrate_to_yield dest bound elsewhere → Busy" + ); assert!(r.class, "fabric-class Gradient admit / Curl refuse"); assert!(r.atomic, "ATOMIC_ADD accept/reject"); assert!(r.tensor, "SoftSFI tensor named refuse"); @@ -565,6 +579,10 @@ mod tests { LINE_GREENCTX_EXHAUSTED, "[redteam] attack=greenctx-exhausted result=refused" ); + assert_eq!( + LINE_GREENCTX_BUSY, + "[redteam] attack=greenctx-busy result=refused" + ); assert_eq!(LINE_CLASS, "[redteam] fabric-class admit/refuse"); assert_eq!(LINE_ATOMIC, "[redteam] ATOMIC_ADD accept/reject"); assert_eq!(LINE_TENSOR, "[softsfi] tensor=refused"); @@ -597,6 +615,7 @@ mod tests { LINE_GREENCTX_OVERCOMMIT, LINE_GREENCTX_UNBOUND, LINE_GREENCTX_EXHAUSTED, + LINE_GREENCTX_BUSY, ] { assert!( line.starts_with("[redteam] attack=") && line.ends_with(" result=refused"),