====== Lyx OS – Systemarchitektur ======
Diese Seite beschreibt den Aufbau von Lyx OS: welcher Code in **Ring 0** läuft und welcher in **Ring 3**, wie beide miteinander reden, und wo Prozesse und Treiber dabei sitzen. Dazu die Schichten vom UEFI-Boot bis zum Ring-3-Userspace, das Speicherlayout, die Kernel-Module und das Capability-Routing-Gate.
→ [[lyxos:start|Übersicht]] · [[lyxos:syscalls|Syscall-ABI]] · [[lyxos:kernel|Kernel-Interna]] · [[lyxos:treiber|Treibermodell]] · [[lyxos:prozesse|Prozesse & Ring-3]] · [[lyxos:bin|Werkzeuge in /bin]] · [[lyxos:vega|Vega]]
----
===== 1. Die zwei Ringe =====
Lyx OS benutzt genau **zwei** Schutzringe der CPU: Ring 0 für den Kernel, Ring 3 für alles andere. Ring 1 und 2 bleiben ungenutzt — sie tragen auf x86-64 keinen Nutzen, den eine saubere Syscall-Grenze nicht besser erbringt.
┌─────────────────────────────────────────────────────────────┐
│ RING 3 │
│ │
│ Vega-Compositor ← Startziel, preemptiver Scheduler-Faden │
│ ├── term Terminal │
│ ├── taskmgr Aufgabenverwaltung │
│ └── /bin/ als Kind des Terminals │
│ │
│ Tier-1-Treiber: usbhid · i2chid │
│ lyxc (als LBF) │
│ shell.elf Wartungs-Shell (Rückfallebene) │
│ Lyra — noch nicht umgesetzt │
├─────────────────────────────────────────────────────────────┤
│ SYSCALL-GRENZE r3_sc_block + Capability Routing Gate │
├─────────────────────────────────────────────────────────────┤
│ RING 0 — TCB │
│ │
│ Speicher PMM · VMM · Bump-Arena │
│ Ablauf Scheduler (4096 Fäden, ≤ 8 Kerne) · SMP · IDT │
│ Dateien VFS · FAT32 · IOFS · Initrd │
│ Tier-0-Treiber: │
│ Platten ATA · AHCI · NVMe · virtio-blk · RAM · USB-MSC │
│ Netz e1000 · pcnet · rtl8139 · virtio-net + TCP/IP │
│ Bus PCI · ACPI · xHCI · I²C (DesignWare) │
│ Ton HDA · AC97 Eingabe PS/2-Tastatur │
│ Laden ELF64-Loader · LBF-Loader (LYX!) │
├─────────────────────────────────────────────────────────────┤
│ UEFI-Bootloader (boot.asm, PE32+ → BOOTX64.EFI) │
├─────────────────────────────────────────────────────────────┤
│ UEFI-Firmware (OVMF) / PC-Hardware │
└─────────────────────────────────────────────────────────────┘
**Mechanismus und Intelligenz sind strikt getrennt:** Der TCB enthält kein LLM und ruft keines auf. Lyra (Ring 3) soll das Modell halten, vorschlagen und Capabilities erteilen — erzwingen tut ausschließlich Ring 0.
==== Was in Ring 0 läuft — und warum ====
^ Bereich ^ Warum Ring 0 ^
| Speicher- und Seitenverwaltung, IDT, SMP | ohne Ring-0-Rechte nicht möglich |
| Scheduler | er schaltet die Kontexte um, die er verwaltet |
| Dateisysteme (VFS, FAT32, IOFS, Initrd) | hängen unmittelbar an den Blocktreibern |
| **Tier-0-Treiber** | boot- und latenzkritisch: ohne Platte kein Dateisystem, ohne Netzkarte kein Netz. Sie tragen sich in **eine** Registry ein (''kernel/drv.lyx''), statt sich über if-Ketten zu verteilen → [[lyxos:treiber|Treibermodell]] |
| ELF- und LBF-Loader | sie bauen die Adressräume auf, in denen Ring 3 startet |
==== Was in Ring 3 läuft ====
^ Was ^ Wie gestartet ^ Anmerkung ^
| **Vega-Compositor** | vom Kernel als preemptiver Scheduler-Faden (''SchedBootCompositor("/vega.elf")'') | das **Startziel**: fehlt ''vega.elf'', startet stattdessen ''shell.elf''. Priorität NORMAL mit längerer Zeitscheibe — ein höher priorisierter Compositor würde die Dienstfäden aushungern |
| ''term'', ''taskmgr'', ''uidemo'', ''lbfwin'' | von Vega | Fenster des Compositors |
| **42 Werkzeuge in ''/bin''** | vom Terminal als Kind | → [[lyxos:bin|Werkzeuge in /bin]] |
| **Tier-1-Treiber** ''usbhid'', ''i2chid'' | wie ein gewöhnliches Programm | vollständig in Ring 3; der Kernel stellt nur MMIO, PCI, DMA und den I²C-Bus → [[lyxos:treiber|Treibermodell]] |
| ''lyxc'' | aus dem Terminal | der Compiler läuft als LBF im Userland |
| ''shell.elf'' | Rückfallebene beim Hochfahren | die Wartungs-Shell, → [[lyxos:shell|Shell]] |
| **Lyra** | — | noch nicht umgesetzt |
**Ein Treiber in Ring 3 ist kein Widerspruch zum Rest.** Der Unterschied ist nicht „wichtig gegen unwichtig", sondern **wann** er gebraucht wird: Was zum Hochfahren nötig ist, muss in Ring 0 liegen; alles Übrige kann darüber laufen und mit einem Fehler nur sich selbst mitreißen. Ein abgestürztes ''usbhid'' kostet die Maus, keinen Neustart.
==== Zwei Wege, einen Ring-3-Prozess zu führen ====
Historisch gewachsen, und beide sind heute in Gebrauch:
^ ^ Fadentabelle des Schedulers ^ ''achild''-Tabelle ^
| Wo | ''kernel/sched_types.lyx'' | ''kernel/ring3.lyx'' |
| Größe | ''MAX_THREADS'' = 4096, ''MAX_CPUS'' = 16 (hochgefahren werden ≤ 8) | ''ACHILD_MAX'' = 8 Plätze |
| Zustände | frei, bereit, läuft, blockiert, tot | ''0'' = frei, ''1'' = aktiv, ''-1'' = beendet |
| Je Eintrag | vollständiger Fadenzustand, Priorität, Zeitscheibe, Affinität | 64 Byte: RSP, RCX, R11, RBP, CR3, Heap, Status, verbrauchte Ticks |
| Wer benutzt es | Compositor, Dienstfäden, alles preemptiv Geplante | die Kinder, die das Terminal startet |
''ps'' liest die **Fadentabelle** (Syscalls 206/207), ''top'' die ''achild''-Plätze (202). Dass beides nebeneinandersteht, ist kein Entwurf, sondern der Stand: die Ereigniswarteschlangen wurden bereits von den acht ''slot+2''-Kennungen auf die Faden-Kennungen umgestellt (''EV_PIDS'' = 256).
==== Mehrere Kerne ====
Der Bootstrap-Kern (BSP) trägt den Compositor. Die übrigen Kerne werden hochgefahren und laufen im Leerlauf; ein fest zugeordneter Rechenfaden auf Kern 1 ist die geprüfte Vorgabe. Das MP3-Dekodieren auf einem eigenen Kern ist gebaut, aber noch nicht die Vorgabe — unter KVM mit vier vCPUs erreicht der Bootlauf die Diagnoseausgabe nicht zuverlässig. Deshalb zeigt [[lyxos:bin:top|top]] regelmäßig Kern 0 nahe 100 % und die übrigen nahe 0 %.
----
===== 2. Boot-Ablauf =====
Der Bootloader (''bootloader/boot.asm'', NASM, ~2900 Zeilen) ist ein PE32+-Flat-Binary. UEFI lädt es als ''BOOTX64.EFI'' und ruft ''efi_main(ImageHandle, SystemTable)'' auf (MS x64 ABI).
Schritte:
- **Begrüßung** über UEFI ''ConOut''
- **Kernel laden** — ''\\kernel.elf'' vom UEFI SimpleFileSystem lesen
- **ELF64 parsen** — ''PT_LOAD''-Segmente mappen, BSS nullen
- **UEFI Memory Map** holen, ''ExitBootServices'' aufrufen
- **GDT laden** (64-Bit Code 0x08, Data 0x10)
- **COM1 initialisieren** (0x3F8 — serielle Debug-Ausgabe)
- **SYSCALL-MSR** (''IA32_LSTAR'') auf den Ring-0-Einsprungpunkt setzen
- **Page Tables** aufbauen (Identity-Map 4 GB)
- **Bump-Allocator** ab physisch 0x2000000 (32 MB) initialisieren
- **Sprung in Kernel-Entry** (''pub fn main(boot_info_ptr: int64)'' in ''kernel.lyx'')
----
===== 3. Speicherlayout =====
^ Adressbereich ^ Inhalt ^
| ''0x0000'' – ''0x0FFF'' | Null-Page (unmapped, für null-Checks) |
| ''0x1000'' – ''0x1FFFF'' | Bootloader-Code (PE32+ Text-Section) |
| ''0x100000'' – ''0x1FFFFF'' | Bootloader-Heap / Temporäre Strukturen |
| ''0x200000'' – ~ | Kernel-ELF (''PT_LOAD''-Segmente) |
| ''0x2000000'' | Bump-Allocator-Basis (Kernel-Heap) |
| ''0x1800000'' (24 MB) | ''SHELL_PHYS_BASE'' — Ring-3 ELF-Binary (physisch = virtuell mit Identity-Map) |
| ''0x10000000'' (256 MB) | ''USER_HEAP_BASE'' — virtueller Basis für ''user_mmap'' (wächst aufwärts) |
| '' – 4 GB'' | Identity-Map (1:1 physisch ↔ virtuell) |
| ''0xFFFF800000000000''+ | (Zukünftig: höhere Hälfte Kernel-Space) |
**Page-Größen:**
* Kernel: 2 MB Huge Pages (''PDE'' mit ''PS''-Bit) für die ersten 4 GB
* Userspace (M5+): 4 KB Seiten für granulare Rechteverwaltung
----
===== 4. Kernel-Module =====
Der Kernel besteht aus 25 Lyx-Units, die beim Build einzeln zu ''.lyu'' vorkompiliert und dann zu ''kernel.elf'' zusammengelinkt werden:
^ Modul ^ Datei ^ Aufgabe ^
| Exceptions | ''exceptions.lyx'' | IDT (256 Gates), CPU-Fault-Routing, ''panic''/''assert'' |
| PMM | ''pmm.lyx'' | Physical Memory Manager — Bitmap-basiert, 4 GB, UEFI-Memory-Map als Basis |
| VMM | ''vmm.lyx'' | Virtual Memory Manager — PML4, Huge Pages, per-Prozess CR3, User-Page-Mapping |
| Process | ''process.lyx'' | Prozess-Modell: ''ProcCreate'', ''ProcActivate'' |
| Sync | ''sync.lyx'' | Synchronisations-Primitive: Spinlock, Mutex, Semaphor — → [[lyxos:sync|Sync-Primitive]] |
| SMP | ''smp.lyx'' | Symmetric Multiprocessing — LAPIC, Trampoline, AP-Startup, Task-API — → [[lyxos:smp|SMP & Tasks]] |
| ATA | ''ata.lyx'' | ATA-Disk-I/O — Legacy (Primary Master) und Multi-Disk (4 Kanäle, vmm_op42-44) |
| Disk | ''disk.lyx'' | Disk-Abstraktion — probt alle 4 ATA-Kanäle beim Start, cacht Sektorzahl + Modell |
| MBR | ''mbr.lyx'' | MBR-Partition-Tabelle — Lesen und Schreiben von Einträgen (Typ 0x0C FAT32 LBA) |
| FAT32 | ''fat32.lyx'' | Vollständige FAT32-Implementierung mit LFN-Lesen und LFN-Schreiben |
| VFS | ''vfs.lyx'' | Virtual-Filesystem-Layer — FAT32 + Initrd; open/read/write/stat/seek/mkdir/dir/dup |
| Keyboard | ''keyboard.lyx'' | Tastatureingabe (PS/2), Tastaturbelegung (Layout-Index via ''KbdSetLayout'') |
| Initrd | ''initrd.lyx'' | In-Memory-Ramdisk (Format: ''LIXR''-Magic + Einträge + 4B-Terminator) |
| Locale | ''locale.lyx'' | Internationalisierung — 5 Locales, Zahlen-/Zeit-/Datumsformat, ''LocaleInit'' liest ''/config/locale.cfg'' |
| Ring-3 | ''ring3.lyx'' | ELF64-Loader, ''SysSpawn'', Syscall-Handler, Capability Routing Gate (PLEDGE_*) — → [[lyxos:prozesse|Prozesse & Ring-3]] |
| XHCI | ''xhci.lyx'' | USB 3.x-Host-Controller-Treiber — Enumerierung, Datentransfer (WP25) → [[lyxos:xhci|XHCI]] |
| RAM-Disk | ''ramdisk.lyx'' | RAM-Disk-Treiber, Disk-IDs 8–11 (''DISK_RAM_BASE'' = 8, vier Plätze) — Syscalls 153–154 (WP30) → [[lyxos:ramdisk|RAM-Disk]] |
| IOFS-Alloc | ''iofs_alloc.lyx'' | Block-Allocator, mkfs, CRC32C, Page-I/O — Syscall 155 (WP01+WP09) |
| IOFS-RW | ''iofs_rw.lyx'' | Mount, Read/Write, Checkpoint — Syscalls 156–164 (WP02) |
| IOFS-WAL | ''iofs_wal.lyx'' | Write-Ahead-Log — kernel-intern, kein Syscall (WP04) |
| IOFS-Graph | ''iofs_graph.lyx'' | Graph-Kanten — Syscalls 165–169 (WP05) |
| IOFS-Traverse | ''iofs_traverse.lyx'' | Graph-Traversal BFS/DFS/Reachable/ShortestPath — Syscalls 170–173 (WP06) |
| IOFS-Names | ''iofs_names.lyx'' | Named Nodes, Name-Store, GC — Syscalls 174–179 (WP07+GC) → [[lyxos:iofs|IOFS]] |
| Net + TCP | ''net.lyx'' | E1000-Treiber, DHCP, ARP, TCP — Syscalls 180–184 (WP26, WP16-TCP) → [[lyxos:syscalls|Syscall-ABI]] |
| Kernel | ''kernel.lyx'' | Einstiegspunkt — importiert und initialisiert alle Module |
→ Welche Controller, Busse und Geräteklassen heute bedient werden — und womit man einen eigenen Treiber schreibt: [[lyxos:treiber|Treibermodell]].
**Initialisierungsreihenfolge** in ''kernel.lyx'':
PMM → VMM → RNG-Seed → SMP → VFS (→ Fat32VolumeInit, MbrInit) → DiskInit
→ FAT32-Mount → LocaleInit → Initrd-Mount → SysSpawn (Ring-3 Shell)
→ Keyboard-Poll → Sync-Tests → Scheduler (ProcInit, ProcActivate)
----
===== 5. Syscall-Grenze =====
Ring-3-Code kommuniziert mit dem Kernel über einen gemeinsamen Speicherblock (''r3_sc_block'') und einen dedizierten Trigger-Mechanismus — kein traditionelles ''SYSCALL''-Register-Layout.
**r3_sc_block-Protokoll:**
// Shared block (physische Adresse wird bei Boot-Start übergeben)
offset 0: nr — Syscall-Nummer (int64)
offset 8: a0 — Argument 0 (int64)
offset 16: a1 — Argument 1 (int64)
offset 24: a2 — Argument 2 (int64)
offset 32: a3 — Argument 3 (int64)
offset 40: result — Rückgabewert (int64), wird vom Kernel geschrieben
// Ablauf aus Ring-3-Sicht:
var sc: int64 := lyx_get_r3sc(); // einmalig: mmap(0,-5,...) → Blockadresse holen
poke64(sc + 0, NR); // Syscall-Nummer schreiben
poke64(sc + 8, arg0); // Argumente schreiben
lyx_trigger(); // mmap(0,-6,...) → Kernel-Handler aufrufen
var result: int64 := peek64(sc + 40);
* ''lyx_get_r3sc()'' und ''lyx_trigger()'' sind keine echten mmap-Aufrufe — der Bootloader fängt negative Größen als ''vmm_op''-Sentinel ab (op -5 = Block-Adresse holen, op -6 = Trigger).
* User-virtuelle Puffer-Adressen (z.B. Lese-Buffer) werden im Kernel via ''VmmPhysFromUserVirt(proc_cr3, vaddr)'' in physische Adressen übersetzt, bevor sie an VFS-Funktionen weitergegeben werden.
* Ring-3-FDs sind VFS-FDs + 3 (fd 0 bleibt für stdin/Keyboard reserviert).
→ Implementierung im Kernel: ''ring3.lyx'' (''handle_r3_syscall'') · Vollständige ABI-Spezifikation: [[lyxos:syscalls|Syscall-Referenz]] · Prozess-Lebenszyklus: [[lyxos:prozesse|Prozesse & Ring-3]]
----
===== 6. Capabilities — alles ist ein fd =====
Lyx OS kennt keine root-Privileg-Eskalation. Jeder ''fd'' ist eine **Capability**: er kodiert sowohl die Ressource als auch die erlaubten Operationen (Lesen, Schreiben, Mappen, Löschen …). Capabilities können nur eingeschränkt, nie erweitert werden.
^ Designprinzip ^ Konsequenz ^
| Kein Root | Kein ''chmod 4755'', kein ''sudo''-Äquivalent |
| CLOEXEC by default | Neue ''fd'' werden nicht über ''sys_spawn'' vererbt — opt-in mit ''O_INHERIT'' |
| Ein ''fd''-Typ | ''fd'' für Dateien, Sockets, Prozesse, AI-Sessions sind konzeptuell gleich |
| Alle Pfad-Syscalls nehmen ''dir_fd'' | ''AT_CWD'' als Default — keine TOCTOU-Lücken durch absolute Pfade |
**PLEDGE_*-Bitmask (implementiert in ''ring3.lyx''):**
pub con PLEDGE_STDIO: int64 := 1; // stdin/stdout lesen/schreiben
pub con PLEDGE_VFS: int64 := 2; // sys_open, sys_read, sys_write, stat
pub con PLEDGE_EXEC: int64 := 4; // sys_spawn
pub con PLEDGE_BLOCK: int64 := 8; // Rohzugriff auf Blockgeräte
pub con PLEDGE_NET: int64 := 16; // Netzwerk-Sockets
pub con PLEDGE_PROC: int64 := 32; // Prozessverwaltung (kill, nice …)
pub con PLEDGE_ALL: int64 := 63; // die sechs oben
pub con PLEDGE_DISPLAY: int64 := 65536; // Bildspeicher beanspruchen (sys_fb_map)
pub con PLEDGE_DEVICE: int64 := 131072; // MMIO abbilden, PCI lesen (Tier-1-Treiber)
pub con PLEDGE_CONFIG: int64 := 262144; // persistente Konfiguration SCHREIBEN
SysPledge(PLEDGE_STDIO %%|%% PLEDGE_VFS); // Capabilities einschränken (irreversibel)
> **''PLEDGE_ALL'' ist nicht „alles".** Der Wert ist ''63'' und deckt damit genau die sechs ursprünglichen Bits ab — ''PLEDGE_DISPLAY'', ''PLEDGE_DEVICE'' und ''PLEDGE_CONFIG'' kamen später dazu und liegen **außerhalb**. Wer einem Prozess Geräte- oder Anzeigerechte geben will, muss sie ausdrücklich dazunehmen; ''PLEDGE_ALL'' allein genügt nicht.
>
> Für ''PLEDGE_CONFIG'' gilt zusätzlich: hier hilft auch „Maske 0 = unbeschränkt" nicht — das Recht muss im Manifest stehen.
Der **Capability Routing Gate** in ''handle_r3_syscall'' prüft für jede Syscall-Nummer die benötigte Capability-Klasse (''syscall_capability_class'') gegen die ''pledge_mask'' des Prozesses. Verstöße erzeugen ''ERR_CAPVIOL'' (Implementierung: WP15).
→ Details: [[lyxos:prozesse|Prozesse & Ring-3]]
===== 7. Drei-Domänen-Architektur =====
Perspektivisch teilt Lyx OS den Adressraum in drei Domänen. Zwei davon gibt es, eine ist Entwurf:
^ Domäne ^ Ring ^ Stand ^
| **TCB** (Trusted Computing Base) | Ring 0 | **da** — deterministisch, vollständiger Hardwarezugriff, ruft nie ein LLM |
| **Lyra** | Ring 3, privilegiert | **Entwurf** (WP17): KI-Agent, hält Modell und Compiler, erteilt Capabilities |
| **User** | Ring 3, minimal | **da** — Compositor, Terminal, Werkzeuge, Tier-1-Treiber, jeweils mit eigener Maske |
Die frühere Angabe „heute läuft ausschließlich die Shell als Ring-3-Prozess" ist überholt: In Ring 3 laufen inzwischen der Compositor als Startziel, seine Fenster, 42 Werkzeuge in ''/bin'', zwei Treiber und der Compiler selbst. Die Wartungs-Shell ist die Rückfallebene, nicht mehr der Normalfall.
**Was die Trennung heute schon leistet und was nicht:** Der Kernel hält jeden Prozess an seiner Maske fest — ein LBF ohne Manifest bekommt nur ''PLEDGE_STDIO''. Was er **nicht** leistet: das Manifest ist eine Selbstauskunft, und für Tier-1-Treiber wird keine Isolationsgarantie nach außen behauptet. Die Grenzen stehen im [[lyxos:treiber|Treibermodell]].
----
Letzte Aktualisierung: 2026-08-27 — Abschnitt 1 als „Die zwei Ringe" neu geschrieben (was in Ring 0 und Ring 3 läuft, die beiden Prozesstabellen, SMP-Rollen); ''PLEDGE''-Liste um DISPLAY/DEVICE/CONFIG ergänzt samt Hinweis, dass ''PLEDGE_ALL'' sie nicht enthält; Abschnitt 7 auf den Stand gebracht. Erhoben aus ''kernel/kernel.lyx'', ''ring3.lyx'', ''sched_ring3.lyx'', ''sched_types.lyx'', ''drv.lyx''.
Vorherige Aktualisierung: 2026-06-25