OptimaOS: архитектура Rust-ядра, которое загружается на реальном железе

от автора

Центральная идея: одно ядро, runtime-профили

Проблема, которую решает OptimaOS — фрагментация через форкинг. Android — форк Linux. Embedded-дистрибутивы — форки с кастомными патчами под каждый SoC. AI-стеки — отдельные кодовые базы. Каждый форк — это отдельный security-аудит, отдельная команда и свой накапливающийся регресс.

POST UEFI MODE. MM_OK INTR_OK SCHED_OK` — это на реальном x86_64, не в QEMU.

POST UEFI MODE. MM_OK INTR_OK SCHED_OK` — это на реальном x86_64, не в QEMU.

Архитектурная ставка: один kernel-core binary для всех сценариев, а профильные различия — это runtime policy, не fork кодовой базы.

Это зафиксировано в ADR-0002 как Single Kernel + Runtime Profile Overlays. Разделение жёсткое:

Ядро (механизмы) — не меняется ни для какой конфигурации:

  • Memory manager + MMU page tables (PML4 → PDPT → PD → PT)

  • Scheduler (процессы, потоки, SMP)

  • IPC-шина с типизированными endpoint’ами

  • Capability-граф с квотами и TTL

  • Syscall ABI (optima_syscall_v0)

  • Page fault handler

Профили (политика) — меняются runtime:

  • Policy rules: что какому процессу разрешено

  • Запуск и параметры userspace-сервисов

  • Параметры планировщика (latency-first для home, throughput-first для server)

  • Разрешённые syscall-паттерны

На практике: один бинарь ядра, при старте загружается policy-файл, policy-service применяет его поверх. Пересборки ядра нет. Это не идеально — часть server-оптимизаций, которые затрагивают kernel semantics, требует отдельного ADR и пересборки. Но это управляемый компромисс.

Устройство ядра

kernel-core — одна Rust workspace crate, ~33K строк. #[forbid(unsafe_code)] — не рекомендация, а запрет компилятора. Весь unsafe изолирован в HAL-слое (hardware/mod.rs) и явно аннотирован. Итого ~600 строк unsafe на всё ядро.

Память

memory.rs — базовый менеджер: mmap/munmap/protect с флагами PROT_READ/WRITE/EXEC.

mm.rs — полные x86_64 page tables. Структура классическая: PML4 (level 4) → PDPT → PD → PT → 4KB страница. Реализованы PageFlags, PageTableEntry, PageTable, PML4, PageTableAllocator (512 страниц) и VirtualMemoryManager. Memory isolation levels по ADR-0008: Level 1 (Capability IPC) — готово, Level 2 (MPU Regions) — stub, Level 3 (MMU Page Tables) — готово.

page_fault.rs — обработчик страничных ошибок через interrupt vector #14. Разбирает PageFaultErrorCode (P/W/U/RSVD/ID биты), собирает статистику, подключён к runtime IDT.

Demand paging и Copy-on-Write — базовые структуры есть, полная реализация в планах.

IPC

Process A ──send(endpoint_B, data)──> IpcBus ──enqueue──> Process B                                         │                                    capability check                                    type check                                    rate limit                                    audit log

Каждый endpoint имеет owner PID и очередь сообщений (VecDeque<Message>). Сообщение несёт from_pid, payload и список передаваемых capabilities — так что capabilities можно делегировать через IPC без обхода системы разрешений.

Производительность (QEMU-surrogate): p50 = 900ns, p95 = 1700ns, p99 = 2500ns, throughput = 904k req/s. Под нагрузкой (4 concurrent senders, 64-byte messages) прирост латентности — менее 2x. На реальном железе цифры будут другими, сейчас замеряем.

Безопасность IPC не опциональная:

  • Capability check — отправитель обязан иметь право на endpoint

  • Type check — тип сообщения верифицируется

  • Session-level и per-method rate limiting

  • Audit log на границах доверия

Capabilities

Capability — это struct:

pub struct Capability {    pub id: CapId,    pub owner_pid: u64,    pub resource: Resource,      // Endpoint(u64) | MemoryRegion(u64) | Process(u64)    pub permission: Permission,  // read / write / manage    pub quota: ResourceQuota,    pub created_at: u64,    pub expires_at: Option<u64>, // TTL для временных    pub priority: QuotaPriority,    pub violation_count: u32,}

ResourceQuota задаёт лимиты: max_memory_bytes (1 GB default), max_ipc_per_second (10K/sec), max_threads (256), max_file_handles (1024), max_capabilities (512).

Поведение при нарушении квоты — не crash, а деградация приоритета: High → Normal → Low → Degraded. Это защита от DoS на уровне ядра. Временные capabilities (create_temporary_capability с TTL) автоматически инвалидируются — не нужен garbage collector разрешений.

API CapabilityManager: grant, grant_with_quota, create_temporary_capability, revoke, transfer, inspect, check_quota, check_ipc_rate_limit, degrade_priority, update_quota, is_expired. 23 теста покрывают все ветки, включая boundary values и quota combinations.

Планировщик

Task states: Ready / Running / Blocked / Terminated.

Context switch: сохранение регистров → загрузка CR3 нового потока (если другое адресное пространство) → TLB flush → восстановление регистров → переход на новый стек.

SMP поддержка через SmpManager с PerCpuData, CpuInfo (family/model/stepping/features) и IPI (Inter-Processor Interrupts): Halt, Init, Call, Resched.

Политика планировщика меняется профилем: home → Interactive (приоритет интерактивным задачам), server → Throughput (максимизация пропускной способности). Syscall-уровень: sys.spawn, sys.exit, sys.sleep, sys.yield.

Boot chain: двухслойная архитектура

ADR-0003 фиксирует модель Hybrid Staged Console Integration. На первый взгляд — усложнение, на деле — чёткое разделение ответственности.

Stage A (UEFI shim): transport + diagnostics. Публикует input-события, рендерит output frames от runtime. Команды не исполняет — никакой бизнес-логики.

Stage B (kernel-core runtime): единственная точка исполнения команд. Один parser/dispatcher для host и device контуров.

Граница между ними — console_proto=v1. Shim передаёт input events в runtime, рендерит output frames. Несовместимые изменения протокола — только через новый major и ADR.

UEFI-код работает в привилегированном режиме с доступом к boot services. Граница между boot и runtime должна быть явной и верифицируемой — иначе аудит системы становится принципиально сложнее. Строгое разделение позволяет верифицировать каждый слой независимо.

Жизненный цикл: BootInit → ShimReady → RuntimeAttach → Interactive → Degraded

Failure policy зафиксирована: при деградации input path система остаётся bootable в diagnostics-mode. Runtime state не ломается от transport-level ошибок.

BootData ABI v2: передаётся реальная карта памяти (region list), не только агрегаты. Self-check handoff (SELFCHK) + коды ошибок — верификация передачи состояния между bootloader и ядром.

Linux ABI: поэтапно

linux-compat реализует маппинг Linux syscall’ов на optima_syscall_v0. Зависит от kernel-core явно — это единственное такое исключение.

L1: clone, exit, nanosleep, mmap, munmap, sendmsg, recvmsg, сигналы (минимум), epoll (минимум).

L2-A: fd lifecycle (open/close/read/write), dup/dup2, poll/epoll_wait.

L2-B: signal masks, pending queue.

L2-C: epoll_ctl(DEL/MOD), расширенная epoll-семантика.

129 тестов, 100% pass. Linux bridge API помечен как draft — это не стабильный публичный ABI. Стабильность будет объявлена отдельно.

Каждый новый syscall — расширение attack surface. Поэтому поэтапно, и каждый этап закрывается compatibility matrix тестами.

Userspace-сервисы

Сервисы не зависят от kernel-core как от библиотеки. Общение — только через typed IPC + capabilities.

Сервис

Что делает

policy-service

Применяет policy overlays, управляет runtime-правилами

device-manager

Управление устройствами, IOMMU домены

filesystem-service

Файловая система в userspace

network-service

Сетевой стек в userspace

profile-service

Управление профильными overlays

Такая структура — прямое следствие микроядерной архитектуры. Crash в filesystem-service не уронит ядро. Компрометация network-service не даёт доступ к capability-графу.

xHCI USB host controller driver реализован полностью и работает в QEMU.

Безопасность в ядре

Здесь не список фич, а архитектурные инварианты.

Capability-граф вместо root. Глобального root нет. Каждое действие требует явного capability с проверкой owner PID.

Typed IPC. Нельзя отправить неверный тип сообщения — это проверяется в ядре, не в userspace.

Quota-based DoS protection. Процесс, превышающий лимиты, деградирует по приоритету — не падает и не блокирует систему.

Tamper-evident audit log. Hash chain integrity для всех security-событий: AUTHZ_DENY, CAPABILITY_GRANT, CAPABILITY_REVOKE, IPC_AUTH_FAIL, POLICY_BYPASS_ATTEMPT, KERNEL_PANIC, SERVICE_CRASH_RECOVERY.

Crypto-service (stub). Криптография вынесена в отдельный userspace-сервис. Ядро знает только про capabilities. PqcAlgorithm enum — ML-KEM-512/768/1024 и ML-DSA-44/65/87. CryptoManager с генерацией ключей, KEM операциями, подписями, ротацией, перешифрованием legacy-файлов. 18 тестов, полная архитектура. Для production нужна интеграция с liboqs.

pub enum PqcAlgorithm {    MlKem512, MlKem768, MlKem1024,  // NIST Level 1/3/5    MlDsa44, MlDsa65, MlDsa87,      // NIST Level 2/3/5}pub struct CryptoManager {    keys: Vec<CryptoKey>,    policy: CryptoPolicy,  // AllAllowed | PqcOnly | PqcMinimumLevel    stats: CryptoStats,}

Потенциал этой архитектуры в том, что миграция с ECDSA на ML-KEM — это обновление одного userspace-бинарника без пересборки ядра. В монолитном ядре это потребует обновления ядра, lsass, защищённых процессов и замены прошивок.

Лицензия: GPL-3 + dual licensing

Изначально в плане была MIT/Apache. В итоге выбрана GPL-3 плюс отдельная коммерческая лицензия — dual licensing.

Почему GPL-3, а не MIT:

Copyleft на уровне ядра работает иначе, чем в обычных библиотеках. Если кто-то берёт kernel-core, модифицирует и встраивает в устройство — GPL-3 обязывает публиковать изменения. Именно это защищает от сценария, который проект пытается решить: форк без обратного вклада. MIT не защищает — вендор возьмёт ядро, добавит тысячу патчей под свой SoC и навсегда уйдёт в закрытую ветку.

Ещё одно отличие GPL-3 от GPL-2 — anti-tivoization (Section 3). GPLv2 позволяет производителю залочить hardware через secure boot так, что пользователь не может запустить модифицированное ядро на своём же устройстве. GPL-3 это запрещает. Для проекта, который целится в Edge и IoT, это не абстракция.

GPL-3 содержит явный патентный грант — распространяя код, вы предоставляете получателям права на патенты, которые могут быть нарушены этим кодом. MIT такой защиты не даёт.

Почему при этом нужна коммерческая лицензия:

GPL-3 закрывает путь компаниям, которые хотят встроить OptimaOS в проприетарный продукт без обязательства публиковать изменения. Это реальный барьер для части потенциальных пользователей — особенно в промышленных и embedded-сценариях, где исходный код прошивки не принято публиковать. Dual licensing решает это: community получает GPL-3, коммерческие пользователи платят за право не публиковать изменения.

Схема стандартная: так работают Qt, MySQL, MongoDB.

CLA для контрибьюторов:

Dual licensing требует единого правообладателя — иначе нельзя выдавать коммерческую лицензию на чужой код. Поэтому все контрибьюторы подписывают CLA (Contributor License Agreement): они сохраняют авторские права на свой код, но предоставляют проекту право перелицензировать его в том числе под коммерческой лицензией. Без CLA, принятого до первого внешнего патча, dual licensing становится юридически невозможным.

Это зафиксировано в CONTRIBUTING.md и README.md до публичного открытия репозитория.

Текущий статус

Компонент

Статус

Kernel-core (memory + MMU, scheduler, IPC, capability, syscall)

Рабочий прототип

Home / Server профили

Готово

Linux ABI L1 + L2 (129 тестов)

Готово

Page tables x86_64 (PML4→PT, page fault handler)

Реализовано

xHCI USB host controller

Полная реализация (QEMU)

UEFI bootloader + BootData v2 ABI

Готово

Boot на реальном x86_64

Работает

Hardware interrupts (PIC/PIT/IDT, hardware ticks)

Работает

Scheduler в post-UEFI hardware runtime

Работает

GUI framework (Desktop, Start Menu, File Browser)

Базовая реализация

Crypto-service (PQC)

Stub, полная архитектура

Physical security (IOMMU, MemoryZeroize)

Stub, полная архитектура

On-device smoke harness (task execution)

В процессе

847 тестов, 100% pass.

P0 performance baseline (QEMU, февраль 2026):

  • IPC p95 ≤ 25 µs, context-switch p95 ≤ 35 µs

  • Throughput ≥ 30k req/s, tail p99 ≤ 80 ms

Реальные числа с железа — следующая точка данных.

Планы

Ближайшее — реальный task execution на железе. Scheduler показывает модель (TASK1…TASK4, RUN/RDY/SLP), но не запускает реальные задачи. Следующий шаг — task execution с IPC между процессами на физическом устройстве. Это закрывает on-device smoke harness.

Декомпозиция kernel-модулей. runtime_scheduler.rs уже вынесен, runtime_arch.rs начат. Hardware bring-up показал, где границы нечёткие — это исправляется.

Linux L2 completion. L2-C реализован, следующий рубеж — signalfd/eventfd. После стабилизации — Android Binder IPC на optima_syscall_v0 в backlog.

Публикация кода. Репозиторий подготовлен: LICENSE (GPL-3.0), README, CONTRIBUTING, SECURITY, CODEOWNERS, .github templates. Публичный Git — после прохождения stable hardware milestone с реальным task execution.

Дальше — Win32 L3. Это самый сложный слой, далёкая перспектива. Но архитектура уже рассчитана под него.

Глобальная цель: проверить гипотезу — один kernel binary, работающий с разными профилями на десктопе, сервере и Edge-устройстве без деградации производительности. Boot chain на реальном железе — первая точка данных. Реальный task execution — следующая.

Код на Github выложил — https://github.com/dev993848/optimaos

P.S. Сразу говорю к разработке, написанию документации и статьи, наравне со мной, приложили руку такие иностранные партнеры как Claude и Codex, а также наши китайские друзья DeepSeek, Qwen, GLM и другие)

ссылка на оригинал статьи https://habr.com/ru/articles/1028378/