130 KiB
nt-lite remaining roadmap
Status: living design specification
Scope: unresolved architecture, implementation work, and validation still required.
Intent: completed work and repository-wide development guidance are intentionally omitted; the source tree and development notes are authoritative for those.
Current implementation focus: P7 is complete and runtime-validated. POSIX is intentionally paused before P8 while native ABI cleanup, KFS identity/lifetime work, and native security are corrected at their owning layers. After those prerequisites, resume the revised P8, then P9/P10.
Current near-term sequence:
UABI.1 fixed-width/std-bool/KSTATUS cleanup and ABI assertions
UABI.2 explicit UTF-8 native text contract and validation
UABI.3 opaque prepared-process transaction API
UABI.4 remove stale named-queue publication and legacy global-input paths
KFS.1-7 native backing identity/lifetime/link/rename/times/directory reset
SEC.0-15 native principals/ACLs/authorization/accounts/audit
P8 revised POSIX filesystem projection + FIFOs
P9 tty/termios
P10 leaf APIs/profile closure
Part I — driver lifecycle direction
1. Driver lifecycle overhaul
The next major kernel architecture task is a real driver manager with graph-based startup and shutdown.
The driver manager must solve four related problems together:
- configuration and startup dependencies;
- driver/module state tracking;
- graceful system shutdown;
- future demand loading, unload, and reload.
drivers.ini becomes the declarative source of lifecycle policy. Runtime device topology remains owned by the I/O/PnP manager.
A static configured dependency graph and a runtime device stack are separate structures:
configured module graph runtime device topology
----------------------- -----------------------
usb-hcd -> usb PCI PDO
usb -> usb-storage |
network-adapter -> network-stack v
filesystem after storage xHCI FDO
|
v
USB PDO
|
v
storage FDO
The first graph answers when modules may start/stop. The second answers which concrete devices are above/below one another and therefore how actual hardware is quiesced and removed.
Part II — drivers.ini v2 and the driver manager
2. Design goals
The new driver configuration must have these properties:
- File order has no lifecycle meaning.
- Driver classes are declared in configuration, not compiled into the kernel.
- Class names are opaque lifecycle identities to the kernel.
- A new provider driver can join an existing class without editing consumers.
- Alternatives are represented as multiple members of one class.
- Classes may depend on other classes.
- Individual drivers may additionally have exact driver dependencies for genuine implementation coupling.
- Class dependencies and exact driver dependencies participate in one effective lifecycle model.
- Startup dependencies automatically determine reverse shutdown ordering.
- The bootloader does not understand dependency policy.
- The kernel is the authoritative parser/validator/scheduler.
- The format remains deliberately small and strict, similar in spirit to
services.ini. - The design must admit later
demand, deferred initialization, unload, reload, and cascade reload without replacing the model.
3. Bootloader/kernel responsibility split
3.1 Bootloader
The UEFI loader remains intentionally dumb.
It reads drivers.ini only far enough to locate driver descriptors and identify:
image=
start=boot
For every start=boot driver it:
- loads the raw
.sysimage into boot-owned pages; - records the configured driver ID and image name with the blob;
- includes the raw
drivers.inibytes inBOOT_INFO; - passes the boot-driver blob list and configuration blob to the kernel.
The bootloader does not:
- build the class graph;
- resolve
requires; - resolve
after; - decide startup order;
- interpret
critical; - determine class availability;
- propagate dependency failures;
- initialize a driver image.
The bootloader performs only the parsing needed to safely identify and preload boot images. The kernel re-parses the same configuration authoritatively.
3.2 Boot ABI
BOOT_INFO should gain a raw DriversIni blob. The boot-driver handoff should retain enough identity to match every preloaded blob to a configured driver without relying on list position.
Conceptually:
typedef struct BOOT_DRIVER_FILE {
char DriverId[64];
char Image[64];
uintptr_t PhysicalBase;
uint32_t Length;
uint32_t PageCount;
} BOOT_DRIVER_FILE;
The exact ABI may be shaped differently, but driver identity must be explicit.
The kernel copies/parses the configuration before reclaiming the bootloader pages. The same parsed configuration remains authoritative for the later runtime phase; it should not need to re-read a potentially different drivers.ini after mounting the system root.
3.3 Kernel
Before calling any configured DriverEntry, the kernel:
- parses the full file;
- validates every class and driver descriptor;
- validates boot blob/config correspondence;
- constructs class and exact-driver graphs;
- validates the combined effective graph;
- computes initial eligibility;
- initializes drivers according to graph state.
Malformed lifecycle configuration is an initialization failure, not something silently repaired with fallback ordering.
4. Configuration grammar
All class sections appear before driver sections. This is primarily a human-readability rule and is also easy for the strict parser to enforce.
Initial grammar:
; Lifecycle classes first.
[class.platform]
requires=
after=
[class.bus]
requires=
after=platform
[class.usb-hcd]
requires=bus
after=
[class.usb]
requires=usb-hcd
after=
; Driver descriptors follow.
[driver.pci]
image=pci.sys
start=boot
class=bus
critical=true
requires=
after=
4.1 Class keys
Every class has exactly:
requires=
after=
Both keys are required even when empty.
4.2 Driver keys
Every driver initially has exactly:
image=
start=
class=
critical=
requires=
after=
All keys are required.
Initial start= values:
boot
runtime
disabled
Planned later values include:
demand
manual
A separate deferred policy may be introduced only if it has semantics distinct from demand and graph waiting.
4.3 Identity rules
Class IDs and driver IDs are separate namespaces.
Recommended syntax:
[A-Za-z0-9._-]+
with a bounded length suitable for fixed diagnostic buffers.
IDs are case-sensitive.
The image= field names one file under the system driver directory. Paths outside that directory are not part of the initial format.
One configured driver ID maps to one module image. Duplicate enabled image mappings should be rejected unless a future concrete use case establishes multi-instance image configuration semantics.
5. Class semantics
Classes are config-defined lifecycle groups, not kernel enums and not hardcoded subsystem taxonomy.
The kernel must never contain policy such as:
if (Class == DriverClassStorage) { ... }
It knows only opaque class IDs and graph edges.
A driver initially belongs to exactly one lifecycle class. If a future architecture genuinely needs multi-class membership, change the format deliberately rather than smuggling it into comma syntax now.
5.1 requires= — availability edge
For a class:
[class.usb]
requires=usb-hcd
after=
requires=usb-hcd means:
The
usbclass may begin only afterusb-hcdbecomes available.
A class becomes Available as soon as at least one eligible member driver reaches Started. Availability describes a loaded module/provider contract, not the presence of a physical device. A successfully initialized NIC driver can make network-adapter available even when no NIC is currently enumerated; hotplug and device existence remain PnP/device-topology concerns.
This is intentionally “one provider from the class,” not “every member must succeed.”
Example:
usb-hcd class
xhci Started
ehci Failed
ohci Failed
result: usb-hcd is Available
A dependent usb class may proceed.
If a requirement lists multiple classes, all listed classes are required. Provider alternatives belong as multiple drivers inside one class; the format does not need a requires_any expression language.
5.2 after= — settlement/barrier edge
For a class:
[class.filesystem]
requires=
after=storage-controller,usb-storage
after= means:
Wait until the referenced class has settled for the current automatic startup phase, regardless of whether any member succeeded.
This is useful when the consumer only needs all likely providers to have had their initialization opportunity before it registers or probes.
A filesystem class can therefore start on a machine with no storage controller at all; later hotplug remains possible.
5.3 Class state
The scheduler should represent at least:
Pending
Available
SettledAvailable
SettledUnavailable
Blocked
Useful interpretation:
- Pending: eligible member work or dependencies remain unresolved.
- Available: at least one member reached
Started; more members may still be pending. - SettledAvailable: all automatic members for the current phase are terminal and at least one started.
- SettledUnavailable: all automatic members are terminal and none started.
- Blocked: the class cannot proceed because a required class settled unavailable or an unsatisfiable dependency was discovered.
Blockedis terminal for barrier purposes.
A class with no started member and no remaining eligible provider in the current startup epoch settles unavailable. A member that started in an earlier phase continues to make its class available in later phases. When a later phase introduces additional automatic members, availability may remain true while settlement reopens until those new members reach terminal states.
A requires dependent may become eligible at Available; it need not wait for settlement. A required class that reaches SettledUnavailable or Blocked without an already-started provider cannot satisfy the edge.
An after dependent waits for a terminal class state: SettledAvailable, SettledUnavailable, or Blocked.
5.4 No cardinality policy
The driver manager does not enforce “singleton class” or “only one network stack.”
Multiple members may start in any class. If a subsystem eventually requires exclusivity, that policy belongs in configuration/start selection or in the subsystem that owns the resource, not in generic class machinery.
6. Driver-level exact dependencies
Drivers retain exact dependencies for real module-to-module coupling.
Example:
[driver.foo-filter]
image=foo_filter.sys
start=runtime
class=foo-filter
critical=false
requires=foo-core
after=
Driver-section references name driver IDs, while class-section references name class IDs.
Initial graph domains remain simple:
[class.*].requires -> class IDs
[class.*].after -> class IDs
[driver.*].requires -> driver IDs
[driver.*].after -> driver IDs
Cross-domain references are unnecessary because membership composes the two graphs.
6.1 Driver requires=
An exact required driver must reach Started before the dependent driver may start.
If it reaches a terminal failure/blocked state, the dependent becomes dependency-blocked.
6.2 Driver after=
An exact after target need only reach a terminal startup state. Its failure does not by itself prevent the dependent from starting.
6.3 Combined cycle validation
Validating the class DAG and driver DAG separately is insufficient.
Class membership plus exact driver edges can create an effective cycle even when each individual graph is acyclic. The kernel must validate the combined scheduling constraints before initialization.
7. Driver state model
The driver manager should track configured module state independently from DRIVER_OBJECT device-driver objects.
Suggested module states:
Disabled
Preloaded
Waiting
Loading
Starting
Started
Blocked
Failed
Stopping
Stopped
Unloading
Unloaded
Future demand loading may add an explicit idle/requested state if useful.
A configured driver module owns:
identity
image name
start policy
lifecycle class
critical flag
exact requires/after edges
load/module base
startup status
registered DRIVER_OBJECTs
shutdown status
reload generation
One module may register more than one DRIVER_OBJECT; the module manager must not assume a one-to-one relationship even if driver decomposition gradually makes that common.
8. Startup phases
8.1 Boot phase
All start=boot images are already resident as raw blobs from the bootloader.
The kernel validates the complete graph, then starts eligible boot drivers according to class and exact-driver constraints.
A boot driver may not have an automatic hard dependency whose only possible configured providers are runtime drivers. Such a configuration is unsatisfiable during boot and should be rejected.
8.2 Runtime phase
After the system-root volume is available, start=runtime modules become eligible.
Runtime modules may depend on already-started boot modules/classes or other runtime modules/classes. Boot-started drivers continue contributing to class availability. If a class gains additional start=runtime members, its runtime settlement barrier is reopened until those members are attempted; an already-started member can still satisfy a requires edge while that happens.
The kernel loads runtime images from the system driver directory according to graph eligibility rather than file order.
8.3 Future demand phase
start=demand should mean:
- the descriptor participates in graph validation;
- the module is not started automatically merely because prerequisites are available;
- a PnP match, explicit request, or dependency demand can request it;
- its hard dependency closure is started first;
- failure is returned to the requester and reflected in module/class state.
This allows future device discovery to trigger drivers naturally without replacing the graph model.
9. Criticality and failure propagation
9.1 Ordinary driver failure
When a driver fails to load or DriverEntry returns failure:
- mark the module
Failed; - update its class availability/settlement;
- block exact hard dependents when appropriate;
- block class hard dependents only if the required class ultimately cannot become available;
- allow
afterdependents once the relevant target settles.
9.2 critical=true
For automatic system startup, a critical configured driver represents a requirement for successful system initialization.
A critical driver that:
- fails to load;
- fails import resolution;
- fails
DriverEntry; - becomes blocked by an unsatisfied hard dependency;
causes startup to fail with explicit dependency diagnostics.
Criticality should not be silently inherited by every provider in a multi-provider class. If one class member is critical, that is a property of that configured driver.
For future manual reload/demand operations, critical does not imply that a user-requested reload failure must bugcheck an already-running system; those operations need separate transactional failure semantics.
10. Validation rules
The parser/graph validator rejects at least:
- duplicate class IDs;
- duplicate driver IDs;
- duplicate keys;
- unknown keys;
- malformed section names;
- class sections after driver sections;
- missing required keys;
- invalid
startvalues; - invalid booleans;
- invalid IDs or image names;
- unknown class membership;
- unknown class dependencies;
- unknown driver dependencies;
- self-dependencies;
- duplicate entries in dependency lists;
- the same target present in both
requiresandafterfor one descriptor; - class cycles;
- driver cycles;
- combined effective scheduling cycles;
- enabled boot dependencies impossible to satisfy during the boot phase;
start=bootimages missing from the bootloader handoff;- unexpected or duplicate boot image handoff entries;
- duplicate enabled module-image identities unless deliberately supported later.
No fallback ordered list is synthesized when the graph is invalid.
11. Determinism and scheduling
Graph edges are the only lifecycle ordering contract.
When multiple drivers are simultaneously eligible with no ordering edge between them, the initial implementation may run them serially using a deterministic lexicographic driver-ID tie-breaker for reproducible logs.
That tie-breaker is explicitly not an API or dependency contract.
Once the driver manager is stable, independent graph nodes may be initialized concurrently if profiling shows value. requires=Available and after=Settled semantics are intentionally defined so concurrency does not require a format change.
12. Worked class graph
A useful initial class graph after USB decomposition could look like this:
[class.platform]
requires=
after=
[class.bus]
requires=
after=platform
[class.storage-controller]
requires=bus
after=
[class.usb-hcd]
requires=bus
after=
[class.usb]
requires=usb-hcd
after=
[class.usb-storage]
requires=usb
after=
[class.usb-hid]
requires=usb
after=
[class.filesystem]
requires=
after=storage-controller,usb-storage
[class.audio]
requires=bus
after=
[class.display]
requires=bus
after=
[class.network-adapter]
requires=bus
after=
[class.network-stack]
requires=network-adapter
after=
Graphically:
platform
|
| after
v
bus
_____________|____________________
/ | | \
v v v v
storage-controller usb-hcd audio network-adapter
| |
| requires | requires
v v
usb network-stack
/ \
v v
usb-storage usb-hid
|
| barrier together with storage-controller
v
filesystem
The exact class names are configuration policy and may evolve. The kernel has no semantic knowledge of them.
13. Worked driver configuration
A target configuration after splitting the current USB image could be:
[class.platform]
requires=
after=
[class.bus]
requires=
after=platform
[class.storage-controller]
requires=bus
after=
[class.usb-hcd]
requires=bus
after=
[class.usb]
requires=usb-hcd
after=
[class.usb-storage]
requires=usb
after=
[class.usb-hid]
requires=usb
after=
[class.filesystem]
requires=
after=storage-controller,usb-storage
[class.audio]
requires=bus
after=
[class.display]
requires=bus
after=
[class.network-adapter]
requires=bus
after=
[class.network-stack]
requires=network-adapter
after=
[driver.cereal]
image=cereal.sys
start=boot
class=platform
critical=false
requires=
after=
[driver.ps2]
image=ps2.sys
start=boot
class=platform
critical=false
requires=
after=
[driver.pci]
image=pci.sys
start=boot
class=bus
critical=true
requires=
after=
[driver.hda]
image=hda.sys
start=boot
class=audio
critical=false
requires=
after=
[driver.ahci]
image=ahci.sys
start=boot
class=storage-controller
critical=false
requires=
after=
[driver.ata]
image=ata.sys
start=boot
class=storage-controller
critical=false
requires=
after=
; Future NVMe requires no filesystem edits.
;[driver.nvme]
;image=nvme.sys
;start=boot
;class=storage-controller
;critical=false
;requires=
;after=
[driver.xhci]
image=xhci.sys
start=boot
class=usb-hcd
critical=false
requires=
after=
[driver.usb]
image=usb.sys
start=boot
class=usb
critical=false
requires=
after=
[driver.usbhid]
image=usbhid.sys
start=boot
class=usb-hid
critical=false
requires=
after=
[driver.usbstor]
image=usbstor.sys
start=boot
class=usb-storage
critical=false
requires=
after=
[driver.fat]
image=fat.sys
start=boot
class=filesystem
critical=false
requires=
after=
[driver.ntfs]
image=ntfs.sys
start=boot
class=filesystem
critical=false
requires=
after=
[driver.ext4]
image=ext4.sys
start=boot
class=filesystem
critical=false
requires=
after=
[driver.vmwaresvga]
image=vmwaresvga.sys
start=runtime
class=display
critical=false
requires=
after=
[driver.rtl8139]
image=rtl8139.sys
start=runtime
class=network-adapter
critical=false
requires=
after=
[driver.rtl816x]
image=rtl816x.sys
start=runtime
class=network-adapter
critical=false
requires=
after=
[driver.lwip]
image=lwip.sys
start=runtime
class=network-stack
critical=false
requires=
after=
The important property is structural rather than the exact sample names:
- adding NVMe means adding one
storage-controllermember; - adding EHCI/OHCI means adding another
usb-hcdmember; - adding a NIC means adding another
network-adaptermember; - adding another network stack does not require a generic-driver-manager singleton rule;
- consumers depend on lifecycle classes rather than enumerating every implementation.
14. USB driver decomposition
Split the current USB implementation into four module ownership domains:
xhci.sys
xHCI PCI hardware/controller mechanics
usb.sys
generic USB bus/core, enumeration, hubs, descriptors, configuration,
composite/interface enumeration
usbhid.sys
USB HID function driver
usbstor.sys
USB mass-storage function/transport driver
14.1 xhci.sys
Owns xHCI-specific mechanism:
- PCI BAR/resources;
- xHCI capability/operational/runtime registers;
- DCBAA;
- scratchpads;
- command/event/transfer rings;
- TRBs;
- interrupters;
- slots/endpoints;
- controller DMA;
- xHCI port state;
- controller reset/start/stop;
- hardware interrupt/DPC processing.
Lifecycle class: usb-hcd.
14.2 usb.sys
Owns controller-independent USB behavior:
- host-controller consumption/binding;
- USB addressing;
- standard control transfers;
- descriptors;
- configurations/interfaces;
- hub topology;
- enumeration;
- composite/interface PDO creation;
- USB device identity/matching.
Lifecycle class: usb with requires=usb-hcd at the class level.
The runtime HCD/USB contract should use I/O-manager device/interface mechanisms rather than direct imports from a specific HCD implementation. usb.sys must not know that the provider is xHCI rather than EHCI/OHCI/a future virtual HCD.
14.3 usbhid.sys
Owns:
- HID descriptors;
- report parsing;
- boot keyboard/mouse protocol;
- conversion into the existing logical input mechanism.
Lifecycle class: usb-hid with class-level requires=usb.
14.4 usbstor.sys
Owns:
- USB mass-storage transport;
- BOT initially;
- UAS later if desired;
- SCSI command transport over USB;
- USB storage device lifetime and block-device publication.
Lifecycle class: usb-storage with class-level requires=usb.
14.5 Kept together initially
Hub and composite enumeration remain inside generic usb.sys. They can become separate images later only if independent lifecycle/reload value justifies the extra module boundaries.
Part III — graceful driver and device shutdown
15. Shutdown goals
System shutdown must become a real lifecycle transition rather than jumping from user-mode shutdown directly to ACPI S5 while drivers and devices remain active.
The shutdown contract must ensure:
- filesystems have a chance to flush/freeze;
- pending cached writes are drained;
- network/audio/display workers stop coherently;
- storage flushes complete while controllers remain operational;
- DMA engines are disabled before poweroff;
- interrupt sources are masked/stopped;
- worker threads no longer reference device/module state being torn down;
- shutdown cannot hang forever on one broken driver;
- failure diagnostics remain available before the final hardware power transition.
16. Separate system shutdown, PnP removal, and unload
Three lifecycle operations remain distinct:
System shutdown
The machine is powering off. Devices should quiesce and hardware should stop. Module images do not need to be unmapped before S5.
PnP removal
A concrete runtime device is disappearing. Existing PnP query/remove/surprise/remove semantics remain device-topology operations.
Driver unload
A module image is being unloaded or reloaded. All owned devices/resources must already be detached or quiesced sufficiently for code removal.
DriverUnload remains an unload callback; it should not be overloaded to mean “the whole machine is shutting down.”
17. Proposed shutdown state machine
System shutdown should be explicit:
Running
|
v
UserShutdown
| init stops user-mode services and session processes
v
KernelQuiescing
| prevent creation of new ordinary work that would outlive shutdown
v
DriverPrepare
| reverse dependency graph; flush/freeze/stop producers
v
DeviceCommit
| stop DMA/IRQs and hardware activity using runtime topology
v
DriverCommit
| stop remaining module-global workers/resources
v
FinalFlushDiagnostics
|
v
HAL S5
The exact division between device and module callbacks should be implemented so the same primitives can later support reload without conflating system shutdown with removal.
18. Driver shutdown API shape
Add an explicit shutdown contract separate from DriverUnload.
A two-phase model is preferred:
Prepare
Commit
Prepare
May:
- flush buffered state;
- reject new ordinary requests;
- drain work queues;
- stop higher-level protocol activity;
- freeze filesystem mutation;
- send final device flushes;
- report failure.
Dependencies remain alive while a consumer prepares.
Commit
May:
- disable device DMA;
- disable controller interrupts;
- stop hardware engines;
- terminate device workers;
- transition hardware into a final safe state.
Commit is bounded and best-effort. Once shutdown has committed, the system continues toward poweroff even if a driver reports failure.
The API may be represented as a module callback, a DRIVER_OBJECT callback, a shutdown/power IRP, or a combination. The final implementation should support both module-global state and concrete device stacks without duplicating shutdown order in each driver.
A likely shape is:
configured module graph
orders module prepare/commit callbacks
runtime DEVICE_OBJECT topology
orders per-device shutdown/power IRPs
19. Shutdown ordering
Startup dependency edges reverse naturally for shutdown.
Example:
startup:
bus -> usb-hcd -> usb -> usb-storage -> filesystem
shutdown:
filesystem -> usb-storage -> usb -> usb-hcd -> bus
Likewise:
startup:
bus -> network-adapter -> network-stack
shutdown:
network-stack -> network-adapter -> bus
after edges also reverse for shutdown because they express lifecycle barriers.
Within module order, runtime device topology determines the correct per-device traversal: upper consumers/children quiesce before lower providers/parents.
No separate hand-authored shutdown order should exist in configuration.
20. Shutdown timeouts and failure policy
Every shutdown wait is bounded.
For each driver/device phase record:
start timestamp
completion timestamp
status
outstanding IRP count
worker count if available
Prepare failures/timeouts are logged. The kernel may attempt remaining independent drivers and then continue shutdown according to policy; one noncritical driver cannot create an infinite shutdown hang.
Commit failure is diagnostic. Hardware poweroff continues once all bounded commit attempts finish.
Before HAL S5, print a compact shutdown summary if any component failed or timed out.
Part IV — future driver-manager features
21. Demand loading
Once the graph manager is stable, add start=demand.
Possible triggers:
- PnP device ID match;
- an explicit kernel management request;
- a dependency demand from another requested driver;
- later, controlled user-mode administration if a secure management API is introduced.
Demand loading resolves the hard dependency closure first. The class graph remains applicable; no alternate demand-only dependency system is introduced.
22. Driver unload
Implement real module unload only after lifetime accounting is trustworthy.
Requirements:
- prevent new device binds to the target module;
- identify all
DRIVER_OBJECTs registered by the module; - remove/quiesce all owned runtime devices;
- drain outstanding IRPs;
- stop module worker threads/timers/DPCs;
- unregister interrupt handlers;
- release DMA mappings/adapters;
- call
DriverUnload/module unload callback; - unregister exported module identity/import references;
- unmap image pages only after no executable/data references remain.
The loader must track import/module references strongly enough to reject unloading a module that still supplies imported symbols to another loaded kernel image.
23. Driver reload
Reload builds on unload plus the existing graph.
Initial operation:
reload driver-id
is allowed only when no started hard dependent requires the target and device lifetime permits removal.
Later:
reload --cascade driver-id
may compute the reverse hard-dependency closure, quiesce dependents first, reload the target, and restart the closure in forward graph order.
Class availability may temporarily change during reload. Dependents must not observe a provider as available while its module is stopped.
Reload should be transactional where possible: an ordinary reload failure should return an error rather than intentionally crash an otherwise running system.
24. Driver-manager observability
Add structured diagnostics sufficient to answer:
- which classes exist;
- class dependencies;
- class current state;
- class members;
- which drivers are configured;
- start policy;
- current module state;
- load/start status;
- blocking dependency;
- module base/image identity;
- registered
DRIVER_OBJECTs; - device count;
- shutdown/reload status.
A debug graph dump should show both class and driver edges and explain why a waiting/blocked driver is not eligible.
Later expose a read-only native query interface for system tools rather than parsing debug logs.
Part V — desktop/session work
25. Move the native console into the desktop
The largest remaining architectural cleanup in the current graphical stack is to make the RSSRV native console a real DWM-managed content source.
Target ownership:
RSSRV
owns console state, input queue, cells/text semantics
console renderer/client
renders console state into a kernel surface
DWM
owns the window, z-order, decorations, composition and physical presentation
/Sessions/0/Console remains the native console object. The graphical desktop displays it; DWM does not become the console authority.
Once this path works, moving keyboard focus between console and graphical windows becomes one native desktop/session mechanism instead of a transitional competition between console and DWM targets.
26. Delete stale direct input/console/display application paths
After the console is fully on the intended RSSRV/DWM path, remove old ambient application-facing input and text-console APIs.
Migration rule:
- prove the canonical RSSRV/DWM path;
- migrate every normal caller and test;
- retain only low-level manager/device mechanisms needed by RSSRV/kernel tests;
- remove stale application ABI in one breaking patch;
- shift syscall numbers as required.
Physical display presentation remains capability-restricted to DisplayManager authority. Client surface commit never becomes physical scanout.
27. DWM protocol and compositor growth
DWM is authoritative for native top-level window geometry, interactive move/resize, z-order, activation/focus, capture, decorations, clipping/occlusion, and composition. Applications own client content and may request bounds/minimize/maximize/fullscreen, but a client request is not an unconditional placement command. Interactive move/resize is DWM-driven: DWM hit-tests server-side decoration, captures the pointer, updates authoritative bounds, and sends a configure event so the client redraws.
Use server-side native decorations as the canonical model, with explicit borderless/none modes for applications that need them. The native frame protocol does not become application-defined client-side chrome. Keep theme metrics/fonts/colors/borders/shadows/button layout/animations in a shared userspace theme schema/library used by DWM and the native UI toolkit; do not introduce a theme service until cross-process state actually requires one.
Keep shell policy separate from DWM. DWM owns windows/monitors/work areas/activation/focus/z/composition/decorations. The shell owns taskbar/dock/start/launcher/icons/notifications/file-manager/wallpaper policy as a privileged DWM client and may reserve work areas or enumerate/activate/minimize top-level windows through explicit capabilities.
Treat focus, activation, pointer capture, z-order, and attention as distinct state. Background applications cannot force activation merely by asking; user gestures/shell policy grant it. Security-sensitive desktop operations such as global window enumeration, capture pixels, input injection, secure UI, always-on-top system UI, work-area reservation, global theme selection, and display topology require explicit authority.
Build richer behavior on the current native desktop protocol rather than introducing a Win32-specific compositor contract.
Remaining native window features should include:
- window title/application identity metadata;
- close-request event and explicit client response/lifetime semantics;
- move/resize interaction;
- decorations;
- minimum/maximum size policy if needed;
- activation policy distinct from raw focus requests;
- better z-order groups if concrete use cases require them;
- multiple damage rectangles rather than whole-window dirtying;
- region/occlusion tracking;
- compositor clipping/region algebra;
- incremental composition scheduling;
- optional frame/present timing and future vblank integration;
- explicit monitor/display geometry once multiple displays exist.
Keep CPU composition as the correctness baseline. GPU acceleration can replace selected raster/composition mechanisms later without moving window policy into the kernel.
28. DWM restart and reconstruction
DWM is a natural future restart=on-failure service only after restart semantics are defined.
A restart design must decide what persists outside DWM:
- client desktop connections;
- window identities;
- attached surface capabilities;
- bounds/visibility;
- z-order;
- focus/capture ownership;
- cursor mode;
- decorations/title metadata.
Two acceptable broad models are:
- reconstruct: RSSRV or another durable owner retains enough session/window registration state for a replacement DWM to rebuild;
- loss policy: DWM restart explicitly invalidates graphical windows/connections and clients reconnect/recreate.
Choose one and make failure visible to clients. Do not enable automatic restart while the behavior is accidental.
Once defined, DWM may use the fixed service restart budget: at most three automatic restart attempts in any sliding five-minute window, with deliberate stop/shutdown excluded from the budget.
Part VI — POSIX remaining work
29. POSIX direction
Target a useful POSIX.1-1990-shaped personality while preserving nt-lite extensions and the native process model.
The process model is intentionally not Unix process cloning:
fork()is deliberately unsupported. Do not add copy-on-write address-space cloning, Unix parentage, or a kernelforkcompatibility path.vfork()is the constrained pre-exec construction primitive. Its implementation may temporarily borrow the parent's native address space and caller stack, but it remains a POSIX personality mechanism.execve()is aposixsrvtransaction.posix.dllonly marshals the request and exports inherited POSIX state; it does not load the image, create the replacement process, commit PID identity, or kill the old process on its own.posix_spawn()is also server-owned process construction, notfork()+execemulation.- POSIX PID identity is owned by
posixsrv, not by the kernel native PID allocator.
The kernel must not gain POSIX-named process, signal, session, process-group, or exec mechanisms. If the implementation exposes a missing substrate, add the smallest useful generic native mechanism and keep POSIX policy in userspace.
The public API/profile manifest remains the source of truth for whether each POSIX entry is implemented, partial, planned, or deliberately unsupported. fork() must be marked deliberately unsupported rather than left ambiguously planned.
PE32+ subsystem value 7 is reserved as the POSIX personality marker for future loader selection, but it keeps the native PEB/TEB layout and native GS contract. Finishing POSIX does not depend on changing that layout.
30. posixsrv.exe authority and protocol
Introduce posixsrv as the shared POSIX policy authority. It is an init-managed noncritical service with an explicit RSSRV dependency. Start with restart=never; do not add restart until client reconnection and server-state reconstruction have a defined contract.
posixsrv owns shared state that cannot be process-local without breaking POSIX semantics:
stable POSIX PID allocation
native-process generation bound to each POSIX PID
parent/child launch associations
child exit records and wait collection
uid/euid/gid/egid
supplementary groups
POSIX process groups/session IDs
current directory identity used by server-owned spawn/exec
cross-process and process-group signal routing/pending state
synthetic POSIX filesystem metadata
fake hard-link aliases
FIFO namespace metadata
passwd/group database
POSIX tty line discipline and foreground process-group state
It does not own native console hardware/session routing. POSIX tty remains an adapter above RSSRV console/session mechanisms.
The protocol is versioned and capability-oriented. Port sender identity is kernel-stamped and is never trusted from a client payload. Large argv, envp, descriptor manifests, or metadata transactions are streamed/chunked or transferred through generic mappings; do not raise Port inline/handle limits merely for POSIX.
A server process record should be conceptually close to:
POSIX_PROCESS_RECORD
Pid
ParentPid
ProcessGroupId
SessionId
NativeProcessHandle
NativePid
NativeGeneration
State
Constructing
Running
VforkBorrowed
ExecPreparing
ExecCommitting
Exited
Credentials
SupplementaryGroups
CurrentDirectory
ProcessPendingSignals
ChildList / wait records
ExitStatus
NativeProcessHandle and NativePid are replaceable implementation identities. Pid is the stable POSIX identity.
Every POSIX process receives a server-issued bootstrap token/generation in userspace startup data. A replacement image proves that it initialized successfully with that token before posixsrv commits an exec transition.
31. Stable POSIX process lifecycle
Stable PID and parentage
getpid() returns the cached posixsrv PID from process/thread personality state. It must not expose SysGetCurrentPid() once server-owned identity is active.
getppid() uses the server launch association. There is no kernel process-parent field, Unix reparenting, adoption, or init-reaper model. Parent death and orphaned child records need one explicit POSIX policy, but native process ancestry never becomes authoritative.
A process can move through multiple native generations while retaining one POSIX PID:
POSIX pid 42
generation 1 -> native pid 113
execve()
generation 2 -> native pid 126
execve()
generation 3 -> native pid 141
A native generation retired by exec is not a POSIX process exit. It produces no waitable child completion and no SIGCHLD solely because the old native process died.
Server-owned execve()
execve() in posix.dll is a thin client operation:
capture path/argv/envp
capture the caller's logical descriptor table and FD_CLOEXEC state
export required native capabilities/open-description state
send EXEC transaction to posixsrv
failure before commit:
receive errno
return -1
success:
never return to application code
posixsrv performs the replacement transaction:
- resolve the executable according to the POSIX process current directory/path facade;
- validate the image before changing the old process;
- build a new native process with the userspace process builder;
- install inherited non-
FD_CLOEXECdescriptors and reconstruct process-local wrappers; - build
argv,envp, loader/bootstrap data, signal state, credentials, pgid/sid, and cwd; - start the replacement behind a userspace POSIX bootstrap barrier;
- wait for the new runtime to report READY with the server-issued exec token;
- enter
ExecCommitting, queue new process-directed signals instead of routing them to the retiring generation; - retire the old native generation;
- bind the stable POSIX PID to the new generation, apply queued signal state, and release the new image.
For an ordinary process, the old execve() caller remains blocked in its Port call and posixsrv terminates the retained old native process handle. There is no success reply.
An exec transaction must either fail while the old image is still valid or reach the committed replacement state. Do not expose a user-visible interval in which the POSIX PID disappears merely because native generations are changing.
Signal exec semantics are applied by the personality: caught handlers reset to default, ignored dispositions remain ignored where required, the calling thread's blocked mask becomes the initial replacement-thread mask, and process-pending signals survive according to the selected POSIX profile.
vfork()
Implement vfork() without cloning a native process or address space.
The intended mechanism is a temporary borrowed native thread:
native process A
parent calling thread -> POSIX pid 20
borrowed child thread -> POSIX pid 21, state=VforkBorrowed
The parent calling thread is suspended until the borrowed child either _exit()s or successfully execve()s. Other native threads in the parent process need not be frozen unless testing proves a stricter contract is required.
The child receives a distinct stable POSIX PID and thread-local logical process state. It must not overwrite the parent's process-global POSIX state. A child descriptor-table overlay references the same inherited open descriptions while keeping descriptor-number mutations logically separate from the parent.
The architecture-specific vfork trampoline may borrow the parent's user stack while the parent is blocked. It must make the child continuation observe a return value of zero and the parent continuation eventually observe the child POSIX PID. This is userspace continuation machinery, not a kernel clone operation.
Initial supported child behavior is deliberately narrow: _exit() and execve() are the safe terminal operations. Do not add kernel complexity to make arbitrary post-vfork mutation safe.
For vfork()+execve():
- the borrowed child sends the normal EXEC request under its child POSIX identity;
posixsrvbuilds a new independent native process for the child PID;- the replacement reports READY behind its bootstrap barrier;
posixsrvcommits the child PID to the new native generation;- the borrowed child receives an internal retire result and calls
SysExitThread()without returning to application code; - the parent waits on the borrowed native thread handle, so its user stack cannot be reused until the child is actually gone;
- once the borrowed thread is dead,
posixsrvreleases the parent and replacement image.
For vfork()+_exit(), the server records a genuine POSIX child exit and the borrowed thread self-terminates; the parent then resumes and may collect the child through wait/waitpid.
wait and _exit
wait()/waitpid() observe POSIX_PROCESS_RECORD completion, not raw native process exit events. Native process handles remain useful mechanisms for observing generations, but only posixsrv decides whether a native exit means POSIX process death or exec retirement.
Implement:
_exit
getpid
getppid
wait
waitpid including WNOHANG
Child exit records remain collectible after native object teardown until the POSIX parent collects them or the selected orphan policy discards them.
32. Credentials, groups, sessions, and identity database
Keep POSIX identity metadata separate from native security authority. Unix mode/uid/gid data is a personality facade unless an explicit bridge to native security is designed later.
Implement shared server state and APIs for:
getuid/geteuid/getgid/getegid
setuid/setgid
getgroups/getlogin
getpgrp/setpgid/setsid
getpwnam/getpwuid
getgrnam/getgrgid
The initial passwd/group database may be synthesized/configured rather than requiring /etc/passwd or /etc/group.
Credential policy is explicit: synthetic effective uid 0 is currently the credential-changing authority. setuid() by uid 0 replaces both real and effective uid; setgid() is authorized by effective uid 0 and replaces both real and effective gid. After dropping uid 0, the current API cannot regain it.
This is transitional POSIX personality state, not the final native security model. Once SEC lands, POSIX uid/gid/group identities map onto stable native principal IDs and POSIX permission APIs become projections of native security descriptors. Do not preserve a second synthetic filesystem-security authority in posixsrv.
Process-group/session state is authoritative in posixsrv because it is consumed by kill, tty foreground-group policy, spawn attributes, and future job-control behavior.
Move the authoritative POSIX current directory into the process record, or otherwise give posixsrv a stable capability/path representation sufficient to resolve relative server-owned spawn/exec requests. chdir/fchdir must update that authority consistently.
33. POSIX process construction, environment, and descriptor inheritance
Userspace native prepared-process transaction
Replace the public fixed-size NTL_PROCESS_BUILDER.Opaque[...] storage with a genuinely opaque userspace preparation object. The implementation owns its allocation and may change size without freezing private loader state into the public ABI.
Target shape:
NtlPrepareProcess(...) -> NTL_PROCESS_PREPARATION*
NtlPreparedProcessGetHandle(...) -> borrowed process capability
NtlStartPreparedProcess(...) -> consumes preparation
NtlAbortPreparedProcess(...) -> consumes preparation without start
A valid NtlStartPreparedProcess() call consumes the preparation on both success and ordinary start failure. This gives the transaction one terminal operation and removes cleanup ambiguity.
The preparation should permit posixsrv to:
create inert native process
load main PE and dependency modules
inspect PE32+ subsystem/personality
install arbitrary inherited native handles/capabilities
build loader/personality bootstrap data
start the process
retain the process capability
NtlCreateProcessAt remains a convenience wrapper over this mechanism for ordinary native callers. If a service needs the initial native thread capability, expose it generically from the prepared-process transaction rather than adding personality-specific thread lookup.
argv and environment
Add a userspace process bootstrap representation for argv and envp. environ/getenv are process-local runtime views of the environment block; posix_spawn and execve may replace it.
Do not require a kernel-defined POSIX environment block. The kernel only validates that generic loader/bootstrap memory is user-readable as it already does for native loader data.
Implement:
getenv
environ
posix_spawn envp
execve envp
Transferable POSIX open descriptions
Before process inheritance, make the existing open-description model transferable across native processes without changing its same-process dup semantics.
Requirements:
- descriptor flags such as
FD_CLOEXECremain descriptor-local; - mutable status belongs to the shared open description;
- duplicate regular-file native handles continue to share the native file object's offset and append state;
- duplicate socket handles continue to share native socket status;
- pipe endpoint state and
O_NONBLOCKmust remain shared across inherited duplicates; - the replacement/child gets process-local wrapper allocations around shared/native backing state;
- closing one process-local wrapper must not invalidate another process's inherited description.
The current shared pipe fast path also needs a supported way to map the pipe backing into an inheriting/replacement process. Do not rely on the current shared-PML4 accident. First try to express this with a reusable native mapping object. If the kernel lacks the needed mechanism, add one generic shared-memory/section mapping capability and use it for pipe backing rather than adding spawn/exec-specific VM syscalls.
Descriptor export uses a logical manifest of unique open descriptions plus FD-to-description references. Port handle transfer is batched within existing limits; do not raise the eight-handle message limit just to transfer a large descriptor table.
posix_spawn()
posix_spawn() sends construction policy to posixsrv; the server allocates a new POSIX PID, builds the native process, installs inherited descriptors, and returns the stable POSIX PID only after the child bootstrap has succeeded.
Support:
envp;- file actions: close, dup2, open;
- process-group attribute;
- signal mask/default attributes once signal state exists;
- cwd inheritance;
- exact open-description sharing and
FD_CLOEXECbehavior.
The server applies file actions to the logical descriptor manifest before the new process is released. The child must not briefly execute with the wrong descriptor table.
34. POSIX signals
Implement signal policy in posix.dll/posixsrv over a personality-neutral asynchronous native mechanism.
Ownership split:
POSIX process-local/shared runtime state
dispositions
POSIX thread state
blocked mask
thread-pending set
posixsrv
process-pending set
process-group routing
target-thread selection policy
alarm/process lifecycle association
Implement:
sigemptyset/sigfillset/sigaddset/sigdelset/sigismember
sigaction
sigprocmask
sigpending
sigsuspend
kill
alarm
pause
sleep
signal
raise
Per-thread registration must let posixsrv identify a target native thread capability without trusting user-supplied numeric IDs alone.
The current kernel already has user APC machinery for asynchronous I/O, but userspace has no generic operation that lets a service queue an asynchronous notification to an arbitrary thread capability. If no existing mechanism can satisfy signal delivery, expose the smallest generic native thread-targeted user-APC/notification primitive with explicit handle rights. Do not add SysKillPosix, kernel signal masks, or kernel signal numbers.
Signal handlers run through a POSIX userspace dispatcher. Blocked/process-pending state remains POSIX policy. A generic APC is only the mechanism used to interrupt the selected user thread and enter the dispatcher.
Translate selected native user exceptions into POSIX signals at the personality boundary, including access/page faults, illegal instruction, and arithmetic faults. Kernel exception codes remain personality-neutral.
Process-group kill routing uses server pgid/session state. Tty-generated VINTR/VQUIT later reuses the same signal routing path.
35. POSIX filesystem facade
P8 is deferred until KFS and SEC establish the native semantics it projects. Do not land the previous synthetic-metadata/fake-hard-link design as an intermediate architecture.
The revised POSIX filesystem facade should implement:
rewinddir
creat
umask
link
mkdir
mkfifo
rmdir
rename
access
chmod/fchmod
chown/fchown
utime
pathconf/fpathconf
Native filesystem identity, open-after-unlink lifetime, hard links, rename replacement, timestamps, directory reset, and security are owned below posixsrv. POSIX translates those semantics rather than recreating them.
Permissions and ownership
- uid/gid/group values map to native principal IDs through the POSIX/account layer;
chmod()transforms the owner/group/everyone projection of the native ACL;chown()updates native owner/owning-group state subject to native privilege checks;access()evaluates the POSIX view of native authorization;umaskremains POSIX creation-time restriction policy and is not persisted as a kernel concept.
Hard links and pathname operations
link() uses the native filesystem hard-link operation. NTFS and ext4 providers implement real links; filesystems such as FAT may return NTLSTATUS_NOT_SUPPORTED. POSIX must not maintain fake alias tables or synthetic link counts.
rename() uses native replace-existing semantics and maps cross-volume operations through the canonical native status mapper. utime() uses the generic native file-information setter. rewinddir() uses native directory reset rather than close-and-reopen-by-path.
FIFOs
mkfifo() remains a POSIX namespace/rendezvous feature owned by posixsrv; data transport continues to use native pipe endpoints/shared backing. Blocking/nonblocking FIFO-open semantics must not use busy polling.
Native/RSSRV symbolic links and POSIX filesystem symbolic-link semantics remain separate namespaces/features.
36. POSIX tty/termios
Layer POSIX terminal behavior over RSSRV's native console/input mechanisms:
kernel device input/display
-> RSSRV native console/session
-> posixsrv tty/line discipline
-> POSIX tty open description
Implement:
ctermid/ttyname/isatty
cfgetispeed/cfgetospeed
cfsetispeed/cfsetospeed
tcgetattr/tcsetattr
tcsendbreak
tcdrain
tcflush
tcflow
tcgetpgrp/tcsetpgrp
Initial useful flags/control characters:
ICANON ECHO ECHOE ISIG
VINTR VQUIT VERASE VKILL VEOF VMIN VTIME
OPOST ONLCR
Foreground POSIX process-group policy belongs in posixsrv; RSSRV retains actual native input/session authority.
ISIG, VINTR, and VQUIT route through the same server signal mechanism implemented earlier. Do not create a second tty-specific signaling path.
37. POSIX staged implementation plan
The following is the active implementation sequence. Finish each stage with focused runtime coverage before beginning the next architectural move.
P0 — status boundary and profile audit
Implementation state: final cleanup bundled with P2. The first P0/P1 patch was runtime-validated. The bundled P2 patch finishes the ABI cleanup by giving POSIX errno a deliberate nt-lite-owned numbering and replacing Windows-numbered native exception codes with compact nt-lite exception classes. Win32 now translates native exceptions explicitly at the personality boundary. Runtime validation of that bundled ABI break is still required before marking P0 complete.
Goal: make later POSIX APIs fail consistently before adding more calls.
Work:
- audit the POSIX profile manifest against exported headers and current implementations;
- explicitly mark
fork()unsupported andvfork/execveplanned; - add missing personality-neutral native status distinctions needed by remaining POSIX work, including directory/type errors, non-empty directory, cross-device operation, no child, exec format, long name, too many links, read-only filesystem, and file too large;
- make
PosixStatusToErrnothe one complete POSIX mapper; - assign public POSIX errno values from one compact nt-lite-owned table rather than preserving accidental Linux/BSD/newlib numeric inheritance; third-party errno domains remain private and translate through
KSTATUS; - keep native exception IDs personality-neutral and nt-lite-owned; Win32 maps them to Windows exception values and the later POSIX signal layer maps them to signals; user-raised exceptions carry an opaque personality/application code separately from the native exception class;
- remove POSIX-local ad-hoc status mappings as each distinction becomes canonical.
Exit criteria:
- one native status maps to one intentional POSIX errno;
- public errno numbers have one documented nt-lite provenance and no dependency on third-party numeric coincidence;
- native exception IDs contain no Win32 values and every personality translation is explicit;
- no new stage is allowed to add a private errno switch in an API implementation;
- profile manifest exactly describes the starting surface.
P1 — posixsrv service and protocol skeleton
Implementation state: complete and runtime-validated. The generic service READY contract exports one public Port listener, init publishes it at /Services/posix through RSSRV, and the versioned connection/transaction bootstrap protocol plus native smoke coverage pass. No POSIX process semantics were added to the kernel.
Goal: establish the shared authority before moving policy into it.
Work:
- add the real generic-service startup/READY adapter;
- add init service configuration with explicit RSSRV dependency and
restart=never; - define a versioned
posixsrvPort protocol; - implement connection lifecycle, kernel-stamped client identity validation, request dispatch, diagnostics, and disconnect cleanup;
- define server-side transaction IDs so large/multi-message spawn/exec/FD transfers are bounded and cancelable;
- provide a native test client before moving POSIX APIs.
Exit criteria:
- service starts, reports READY, accepts multiple clients, rejects malformed protocol versions, and cleans up disconnected transactions;
- no POSIX process semantics have been duplicated in the kernel.
P2 — stable POSIX PID registry and bootstrap
Implementation state: started in the bundled ABI-cleanup/P2 patch. posixsrv now allocates stable POSIX PIDs, retains an attenuated native process capability to observe genuine termination, recovers the same identity across Port reconnects, and the POSIX runtime registers itself during startup. getpid() now reads thread-selected logical POSIX identity. Generic opaque process-loader startup data and reserved POSIX bootstrap token/generation fields are present for later server-owned spawn/exec construction; nonzero bootstrap tokens are intentionally not activated in P2.
Goal: sever POSIX process identity from native PID identity.
Work:
- add server POSIX PID allocator and
POSIX_PROCESS_RECORDlifecycle; - add bootstrap token/generation data to userspace process startup metadata;
- register the initial POSIX runtime with the server and cache stable PID in
POSIX_PROCESS_STATE; - make POSIX thread state identify its logical POSIX process rather than blindly assuming one process-global identity;
- change
getpid()to return stable POSIX PID; - retain/native-open process capabilities needed to observe termination;
- distinguish genuine exit from disconnect/protocol failure.
Tests:
- stable PID differs safely from native PID;
- multiple processes receive unique stable PIDs;
- disconnect does not masquerade as process exit, and native process death transitions the correct record;
- reconnecting the same live native generation recovers the same stable POSIX PID;
- thread attachment inherits the same logical POSIX identity;
- generic startup data reaches a child unchanged and reserved zero-token bootstrap framing is validated;
- no
SysGetCurrentPid()value leaks throughgetpid().
P3 — shared process attributes: cwd, credentials, pgid/sid, identity database
Goal: establish state needed by spawn, signals, filesystem metadata, and tty before those subsystems use it.
Current implementation, awaiting runtime validation:
POSIX_PROCESS_RECORDowns canonical native cwd, uid/euid/gid/egid, supplementary groups, login identity, pgid and sid;- initial standalone registrations begin as synthetic root and as their own process-group/session leader;
- POSIX
chdir()updates the native process-local resolver first, publishes the canonical result toposixsrv, and rolls back the native cwd if the server commit fails; - POSIX
getcwd()reads the server-owned cwd so tests cannot accidentally validate only the native mirror; - synthetic uid 0 is the explicit credential-changing authority; dropping it through
setuid()is irreversible with the current API; - a minimal server-owned identity database provides
root/userandroot/usersrecords; getuid/geteuid/getgid/getegid,setuid/setgid,getgroups/getlogin,getpgrp/setsid,getpwnam/getpwuid/getgrnam/getgrgidare implemented;setpgidis PARTIAL until P5 establishes authoritative parent/child launch associations; self/session validation is already server-owned;fchdiris not in the current POSIX.1-1990 public profile and is not introduced merely to satisfy an internal planning bullet.
P3 runtime gate:
- server registration reports the correct cwd/credentials/pgid/sid and synthesized login;
chdirfollowed by server-backedgetcwdproves cwd synchronization;- process-group/session leader rejection is correct;
- uid 0 can drop gid/uid and cannot regain authority afterward;
- passwd/group lookup agrees with the synthesized database.
Inheritance of cwd/credentials and successful parent-driven setpgid are P5 acceptance tests because P5 is the stage that makes parent/child launch association authoritative.
P4 — transferable descriptors and open descriptions
Goal: make FD inheritance correct before implementing server-owned process creation, using the SASOS directly rather than introducing a conventional shared-memory mapping API.
The VM audit established the ownership rule:
- user virtual addresses are globally meaningful through the shared PML4;
- page faults resolve against the global VAD list, so another process may directly use a pointer into a live owner's VAD;
- native process teardown destroys that process's VADs and frames, so shared POSIX state must not be allocated in an ordinary client if it must outlive that client;
- therefore long-lived shared POSIX control/data allocations belong to
posixsrv, while each native process retains only process-local capability handles/wrappers.
P4.1 — server-owned shared open descriptions
Status: implemented and runtime validated.
- protocol v4 adds stable open-description IDs and pointers to
posixsrv-owned shared control blocks; - each native process keeps a local wrapper containing its local native handle plus the shared description pointer/ID;
FD_CLOEXECremains descriptor-local and never enters the shared control block;dup/dup2/F_DUPFDremain local and do not create extra server holders;posixsrvretains one attenuated master capability for file/socket/pipe descriptions and one holder per POSIX process/open-description pair;- genuine native-process death releases every holder even if userspace did not close its descriptors;
F_GETFLis a direct shared-memory read;F_SETFLis serialized byposixsrv, which changes native file/socket state through the master capability and only then publishesStatusFlags;setsockopt(SO_NONBLOCK)uses that same authority instead of maintaining a second status path;- P4.1 left the pipe ring VAD client-owned as its one remaining lifetime exception; P4.2 below removes that exception;
- no kernel API or VM change is introduced.
Validation for P4.1:
- existing descriptor duplication/file-offset tests must continue to pass;
- existing
F_SETFLsharing/append tests exercise server-serialized file status; - socket nonblocking behavior must remain coherent between
F_SETFL,setsockopt, andF_GETFL; - service smoke directly dereferences a
posixsrv-owned shared description, checks create/set/release accounting, rejects double release, and proves process-death cleanup of an intentionally leaked holder.
P4.2 — server-owned pipe backing
Status: implemented; runtime validation pending.
- protocol v5 adds
CREATE_PIPE, reply-side capability transfer, a second open-description result slot, and shared-description data-plane pointers; SysCreatePipe()is invoked only byposixsrv, so the resultingSYS_PIPE_SHARED_STATEVAD is owned by the long-lived personality server while clients use the same globally meaningful pointer;- the process-owned
POSIX_PIPE_MAPPINGlifetime wrapper and client-sideSysFreeVm()path are deleted; posixsrvretains the read/write master endpoint capabilities and transfers attenuated aliases to the requesting client;- ordinary
read,write,poll, blocking waits, notifications, andPIPE_BUFhandling continue to use the shared-ring/native-endpoint fast path with no byte pumping through the server; - each pipe endpoint shared description points at the same server-owned ring through
SharedObjectData; - local wrappers close their native aliases before releasing the server holder, so the server may free backing only after the client no longer owns that endpoint capability;
- the server closes each master endpoint only when its description loses the final holder, preserving kernel-object EOF/broken-pipe semantics;
- the server frees the pipe VAD only after both endpoint descriptions are destroyed;
posix_service_smokechecks two-description accounting, direct shared-state visibility, master/alias close ordering, and final cleanup; existingposix_pipe_smokeremains the end-to-end data/readiness/lifetime test;- no kernel API, VAD, or syscall change is introduced.
Validation for P4.2 remains part of the combined P4 runtime gate below.
P4.3 — cross-process descriptor export/import
Status: implemented; runtime validation pending.
- protocol v6 adds bounded descriptor-inheritance snapshots, one-shot import tokens, batched description metadata/capability transfer, and an explicit child-lifetime arm operation;
- a snapshot contains exact descriptor numbers, descriptor-local flags, and stable open-description IDs; shared status and pipe data-plane pointers are not copied or reconstructed;
FD_CLOEXECfiltering is performed while the parent snapshots its descriptor table, and descriptor-local flags remain process-local in the receiver;posixsrvpins every unique referenced open description while the snapshot exists and creates at most one holder per receiving POSIX process/open-description pair;- each unique inherited native-backed description receives one fresh process-local capability alias from the server-retained master handle, in batches bounded by
SYS_PORT_MAX_TRANSFER_HANDLES; - duplicate inherited descriptors in one process share one local open-description wrapper and therefore one native alias;
- the receiving process reconstructs exact descriptor numbers from the manifest before user entry continues;
- the current partial
posix_spawn()uses this inheritance transport so P4 can be exercised before P5 moves process construction intoposixsrv; - after native child creation, the parent arms the snapshot by transferring a restricted child process capability to
posixsrv; only that native child PID may claim an armed snapshot; - an arm monitor contains only
{token, native pid, process handle}rather than a raw snapshot pointer: child exit before import reclaims the snapshot, while successful import makes the monitor a harmless no-op; - once armed, source-process exit no longer destroys an unclaimed snapshot; once claimed, the receiver process lifetime owns incomplete-import cleanup;
posix_fd_smokenow exercises two real native processes and verifies shared file offset, cross-process sharedF_SETFL,FD_CLOEXECfiltering/locality, inherited pipe status, cross-process pipe I/O, EOF, and broken-pipe transitions;- no kernel API, VM, or syscall change is introduced.
Combined P4 runtime gate:
- full
all_testspasses with P4.1 + P4.2 + P4.3; posix_service_smokepasses shared-description/pipe ownership and cleanup checks;posix_pipe_smokepasses blocking/nonblocking, EOF, broken pipe, poll, andPIPE_BUF;posix_fd_smokepasses the new cross-process inheritance scenario;- no regression appears in unrelated VM/page-cache tests;
- after this gate P4 is complete and P5 becomes the active stage.
P5 — userspace builder, environment, server-owned posix_spawn, and wait
Goal: make ordinary POSIX child creation entirely server-owned.
Work:
- refactor native userspace process construction into a builder API;
- let
posixsrvresolve/load the executable and retain the native process handle; - add userspace bootstrap
argv/envpdata and implementenviron/getenv; - allocate the POSIX child PID before starting the image;
- install inherited descriptors and apply close/dup2/open file actions before child release;
- support cwd and process-group spawn attributes;
- register child bootstrap READY before returning the child PID;
- replace the fixed process-local spawn table with server child associations;
- implement
_exit,getppid,wait,waitpid, andWNOHANGover server exit records.
Tests:
- env replacement/inheritance;
- file actions including collisions and close-on-exec descriptors;
- parent/child relationship independent of native PID;
- child exits before parent waits;
- multiple children exit out of order;
WNOHANGandECHILDbehavior;- process construction failure leaves no leaked POSIX PID or native process.
P6 — signals and generic asynchronous delivery substrate
Goal: complete signal semantics before exec/vfork need to preserve/reset them.
Work:
- implement signal-set operations, dispositions, per-thread masks, pending sets,
raise, and local dispatch; - register every POSIX native thread with
posixsrvusing retained/transferred thread capabilities; - if required, expose a generic thread-targeted user APC/notification syscall and explicit capability right; reuse existing kernel APC machinery rather than adding POSIX semantics;
- implement cross-process/process-group
killrouting; - implement
sigsuspend,pause,alarm, andsleepinteraction with pending delivery; - translate selected native exceptions at the POSIX boundary;
- complete
posix_spawnsignal-mask/default attributes.
Tests:
- per-thread blocked masks;
- pending signal becomes deliverable after unblock;
- process-directed delivery chooses an eligible thread;
- process-group routing;
- signal interrupts POSIX blocking operations correctly;
- caught/ignored/default dispositions;
- nested and repeated delivery remains bounded;
- exception-to-signal translation does not alter native exception ABI.
P7 — execve() replacement and vfork()
Implementation state: complete and runtime-validated by the full all_tests suite. P7.1 execve() replacement, P7.2 borrowed logical-child substrate, and P7.3 public vfork() Option A server-monitor finalization are all complete. The generic SysResumeThreadAndWait primitive atomically resumes the borrowed thread and waits for its death without a userspace return window.
Goal: complete the non-fork POSIX process model.
Work:
- add EXEC prepare/READY/commit transaction to
posixsrv; - implement descriptor export with
FD_CLOEXECfiltering; - create replacement native generation behind bootstrap barrier;
- preserve stable POSIX PID, parent, credentials, cwd, pgid/sid, process-pending signals, and inherited descriptors;
- reset/preserve signal state according to exec semantics;
- retire the old native generation without generating child exit;
- implement assembly
vforkcontinuation/trampoline; - create borrowed child thread + logical child POSIX process state and descriptor overlay;
- suspend parent on the borrowed thread handle;
- implement
vfork()+_exitandvfork()+execveretirement handshakes; - make
fork()return-1/ENOSYSif it remains declared at all; do not emulate it.
Tests:
- successful exec retains POSIX PID while native PID changes;
- failed exec returns with the old image/process state intact;
- exec does not satisfy parent's
waitpid; FD_CLOEXECfiltering;- environment/argv replacement;
- signal disposition/mask semantics across exec;
- repeated exec generations;
vforkchild observes zero, parent observes child PID;- parent cannot resume while child still uses its borrowed stack;
vfork()+_exitcreates a waitable child exit;vfork()+execveproduces an independent running child without native process cloning.
P8 — revised POSIX filesystem projection and FIFO namespace
Status: paused until KFS and SEC complete the required native substrate.
Goal: finish the POSIX filesystem facade by projecting native identity, links, timestamps, directory iteration, and security rather than synthesizing competing filesystem semantics in posixsrv.
Work:
- map POSIX uid/gid/groups to native principals;
- implement
chmod/chown/accessas projections of native security descriptors; - keep
umaskas POSIX creation-time restriction policy; - implement
link()with the native hard-link operation; - use native rename-replace and cross-device status;
- use native file-information time mutation for
utime; - use native directory reset for
rewinddir; - finish remaining path/directory APIs and canonical errno mapping;
- implement FIFO namespace/rendezvous records in
posixsrv; - use native pipe endpoint/shared backing transfer for FIFO data transport.
Tests:
- native owner/group/mode projection is coherent across reopen and hard-link aliases;
- umask restricts creation without granting rights absent from inherited native policy;
- real hard-link data/link-count behavior;
- open-after-unlink and rename-replacement edge cases;
- timestamp mutation and directory reset;
- FIFO blocking/nonblocking open, data transfer, EOF, broken-pipe, and cleanup.
P9 — tty/termios
Goal: finish interactive POSIX process behavior over RSSRV.
Work:
- add tty object/open-description adapter over RSSRV console/session capabilities;
- implement canonical/raw input queues and output postprocessing;
- implement speed/control APIs and drain/flush/flow operations;
- implement foreground pgid state in
posixsrv; - route
VINTR/VQUITthrough the signal subsystem; - implement
ctermid,ttyname,isatty,tcgetpgrp, andtcsetpgrp.
Tests:
- canonical line completion/editing/EOF;
- raw VMIN/VTIME behavior;
- echo and output newline translation;
- foreground/background process-group behavior selected by the profile;
VINTR/VQUITsignal routing;- disconnect/console loss cleanup.
P10 — leaf APIs, cleanup, and POSIX completion gate
Goal: close the profile rather than leave a nearly-finished personality.
Work:
- implement remaining leaf APIs such as
uname,time/times,sysconf, and any unfinishedpathconf/fpathconfcases; - audit every public POSIX header/export against the profile manifest;
- remove old process-local spawn associations and any compatibility paths replaced by
posixsrv; - remove stale local errno mappings and temporary process-construction helpers;
- document deliberate non-support such as
fork(); - run the full native + POSIX test suite after each cleanup patch.
POSIX is complete for this roadmap when:
- all shared process policy has one
posixsrvowner; spawn,wait,execve, andvforkfollow the stable-PID model;fork()is deliberately unsupported with no hidden clone substrate;- inherited descriptors/open descriptions are correct across processes;
- signals are asynchronous and process-group aware without kernel POSIX policy;
- filesystem metadata/aliases/FIFOs are coherent;
- tty/termios uses RSSRV rather than bypassing native session authority;
- the profile manifest accurately describes every exposed POSIX API;
- the full test suite passes without relying on the shared-PML4 accident for cross-process correctness.
Part VI-A — native ABI, filesystem, and security prerequisites
UABI — native interface cleanup before KFS
Perform the public/native ABI cleanup as separate architectural moves before changing filesystem/security contracts.
UABI.1 — fixed-width types, booleans, statuses, and atomics
- use
<stdint.h>widths where persistent/shared/module interfaces require an exact width; - use
<stdbool.h>andtrue/falsefor genuine predicates; - use
KSTATUSfor native status-returning APIs rather than raw integer aliases; - keep POSIX/Win32/UEFI/third-party externally mandated types intact;
- keep compiler
_Interlocked*conventions confined behind typed<ntlite/atomic.h>helpers; - add ABI layout assertions around important shared structs;
- sweep implementation state and callbacks as well as public syscalls; do not mechanically rewrite ordinary local arithmetic indices.
UABI.2 — UTF-8 native text contract
nt-lite native text is UTF-8. SYS_STRING_VIEW lengths are byte lengths. Paths, resource names, module names, thread descriptions, window titles, account names, service names, and other retained native text use UTF-8. Validate malformed UTF-8 at trust/ownership boundaries before namespace or persistent state accepts it.
Do not impose Unicode normalization or Unicode case folding on native identity. Byte-exact valid UTF-8 remains the native namespace identity unless one subsystem explicitly documents an ASCII-only compatibility rule. Byte payloads remain byte payloads and do not become text merely because they use char*.
Single-character APIs must not pretend one UTF-8 byte is one Unicode character. Where an interface genuinely represents one character, use a Unicode scalar value or a separate text event; keep sophisticated composition/IME work for the input/desktop stack.
UABI.3+ — prepared process and stale path deletion
- replace fixed-size opaque process-builder storage with the prepared-process transaction from Section 33;
- remove the legacy kernel-global input convenience/snapshot syscalls once all callers use RSSRV's capability-scoped logical-input path;
- remove the kernel named-queue publication namespace while retaining anonymous queue objects if still useful; RSSRV remains the global resource namespace owner;
- keep
SysResolveHostand its existing comment until networking is actually redesigned rather than cosmetically hiding the current lwIP-in-kernel shortcut.
KFS — coherent native filesystem substrate
KFS.1 — backing identity and coherent file cache
Introduce an internal refcounted IO_FILE_BACKING (name illustrative) distinct from FILE_OBJECT. Independent opens retain separate open descriptions/offsets but converge on one backing identity for shared size, page-cache identity, mapped-file coherence, and file security.
Provider identity is mounted volume + stable FileId + generation/reuse discriminator. NTFS MFT sequence and ext4 inode generation should be wired where available. FAT needs a provider-specific identity policy that remains correct across rename.
KFS.2 — unlink/open lifetime
Native unlink removes one directory link. A backing with link count zero survives while native opens/mappings retain it and is reclaimed after the final backing reference disappears. Providers must support this contract rather than having the VFS fake it.
KFS.3 — native hard links
Add one generic capability-relative native hard-link operation. Source and destination authority are independently checked, cross-volume returns NTLSTATUS_CROSS_DEVICE, NTFS maps to ntfs_link, ext4 maps to ext4_flink, and FAT may return NTLSTATUS_NOT_SUPPORTED.
KFS.4 — rename replacement
Native rename supports atomic destination replacement when the provider can do so and reports cross-volume operations canonically. Do not preserve adapters that only support rename-to-nonexistent as the generic contract.
KFS.5 — generic file-information mutation
Add one generic setter for mutable file information, including persistent timestamps. Persistent filesystem timestamps use a small UTC timestamp type rather than SYS_SYSTEM_TIME, which contains current-clock provenance/timezone fields.
KFS.6 — directory reset
Add provider reset/restart-directory support and a native operation so rewinddir() does not close and reopen by pathname after rename. Do not invent seekdir/telldir semantics until required.
KFS.7 — validation
Runtime tests cover alias/cache coherence, independent-open coherence, open-after-unlink, hard-link counts/data identity, rename replacement, timestamps, directory reset, mmap/page-cache aliases, and provider-specific unsupported cases.
SEC — native principals, ACLs, authorization, accounts, and audit
Security model
Use one simple native nt-lite security descriptor rather than filesystem-dependent kernel semantics. A descriptor stores concrete owner and owning-group principal IDs plus an access ACL and directory creation policy (FileAcl and DirectoryAcl). ACL subjects support specific principal IDs plus OWNER, OWNING_GROUP, and EVERYONE.
For all matching subjects:
allowed = union of matching allow masks
denied = union of matching deny masks
effective = allowed & ~denied
ACE order has no meaning; deny always wins. Owner status implicitly grants security-descriptor mutation authority but does not grant object data read/write/delete.
Authorization is capability-first: ACL/security is checked when authority is acquired/opened. Once a capability is granted, possession is sufficient. Explicit capability transfer/derivation delegates the granted authority without rechecking the receiver ACL. ACL/security changes affect future acquisitions; existing capabilities remain valid unless explicitly revoked.
Principal and context model
Human names remain userspace data. The kernel sees stable opaque PRINCIPAL_IDs and immutable/materialized SECURITY_CONTEXTs containing primary principal, groups/roles, privileges, restrictions, authentication/session identity, and a unique context/audit ID. Do not reuse current SecurityId as an account ID; rename that concept to SecurityContextId/equivalent when SEC1 lands.
A userspace account/authentication service owns name↔principal mapping, password hashes/secrets, group database, account state, profile/home data, and login policy. Access checks never synchronously call that service; group membership is materialized into the security context.
Inheritance and filesystem translation
Directory AccessAcl controls the directory itself. Creation policy contains independent file and directory ACL templates. Creation materializes the relevant template into the child; a new directory recursively copies the parent's creation templates unless an authorized creator supplies different ones. Inheritance occurs at creation only.
POSIX mode translation maps owner/group/other bits to OWNER/OWNING_GROUP/EVERYONE; named POSIX ACL entries map to specific principals and the POSIX ACL mask is folded into effective translated rights. NTFS descriptors translate best-effort into the simpler native flavor; exact Windows round-trip fidelity is not a goal. ext4 ownership/mode/ACL data translates to the same native semantics.
Security metadata belongs to KFS backing identity, not to a pathname or one FILE_OBJECT.
Privileges, restriction, and audit
Do not encode Unix root as a native kernel special case. Use separable privileges such as security administration, take ownership, backup-read, restore-write, context creation, impersonation, raw storage, driver load, process debugging, service administration, and shutdown. POSIX root maps to an appropriate native context.
Make restricted/sandbox contexts first-class and add kernel-stamped audit records for security-context creation, privilege use, failed access checks, security/ownership changes, capability delegation/revocation, cross-process opens, raw storage/driver/service administration, and similar authority transitions. A userspace service persists/filters audit data.
SASOS threat boundary
The current shared-PML4 SASOS model intentionally does not claim inter-process userspace memory confidentiality/integrity. Accounts and ACLs protect kernel-mediated authority; hostile userspace may still inspect live userspace mappings under this model. Do not silently introduce page-table isolation as part of SEC unless that threat-model decision changes.
SEC staged sequence
SEC0 threat model + rights taxonomy
SEC1 principal IDs + SECURITY_CONTEXT v2
SEC2 native security descriptor/ACL
SEC3 generic access check
SEC4 object-manager authorization
SEC5 filesystem provider security contract
SEC6 ext4 translation
SEC7 NTFS translation
SEC8 creation/inheritance
SEC9 ownership/security mutation
SEC10 privilege architecture
SEC11 restricted/sandbox contexts
SEC12 account/authentication service
SEC13 audit subsystem
SEC14 process/device/service/IPC security sweep
SEC15 personality mappings/migration
Part VII — native status, loader identity, and personality runtime
38. Native status cleanup
Keep kernel/native status values personality-neutral and make mapping complete at personality boundaries.
Add missing distinctions as needed, including equivalents for:
not a directory
is a directory
directory not empty
cross-device operation
no child
exec format error
name too long
too many links
read-only filesystem
file too large
Then maintain exactly one complete mapper per personality:
KSTATUS -> Win32 LastError
KSTATUS -> POSIX errno
The POSIX-required slice is Stage P0 and may be completed before the broader Win32 mapper cleanup. Remove ad-hoc per-call mappings after the canonical mappers cover the necessary status space.
39. Loader module identity
Before the planned CRT/personality DLL split, change loaded-module identity from requested basename to resolved file/object identity.
A loaded image needs:
resolved file identity
canonical module object
requested-name aliases
reference/import counts
Two names referring to the same backing image must not create two independent runtime instances.
This is required before making aliases such as msvcrt.dll refer to the same module identity as the nt-lite CRT.
It also becomes important for kernel driver unload/reload because the kernel loader must know which loaded modules import from which provider modules.
40. PE32+ subsystem personality selection and Win32 userspace GS shim
Use the PE32+ Optional Header Subsystem value as the loader's initial personality selector. This is userspace image-loader policy; do not teach the kernel PE loader about Win32 or POSIX personalities.
Initial mapping:
Subsystem 1 IMAGE_SUBSYSTEM_NATIVE
nt-lite native personality
current SYS_PEB / SYS_TEB layout
initial user GS base -> native TEB
GS:[0] -> native PEB pointer under the native TEB ABI
Subsystem 2 IMAGE_SUBSYSTEM_WINDOWS_GUI
Win32 personality
Win64-compatible PEB/TEB userspace shim
GUI startup policy
Subsystem 3 IMAGE_SUBSYSTEM_WINDOWS_CUI
Win32 personality
same Win64-compatible PEB/TEB shape as subsystem 2
console-oriented Win32 startup policy
Subsystem 7 IMAGE_SUBSYSTEM_POSIX_CUI
POSIX personality marker
keep native SYS_PEB / SYS_TEB layout
no GS layout change
Subsystem 7 exists so future loader/runtime policy can identify POSIX images without inventing a new executable format. Finishing POSIX does not require converting existing POSIX runtime state away from the native TEB layout.
Win32 process bootstrap
For subsystems 2 and 3, the userspace process loader loads/chooses a Win32 bootstrap shim and starts that shim before the application's original PE entry point.
The initial thread may begin with the normal native bootstrap environment so generic nt-lite process startup remains unchanged. The Win32 bootstrap then:
- captures any native loader/process data it still needs;
- constructs the Win64-compatible PEB and initial TEB in userspace;
- places the Win32 PEB pointer at TEB offset
0x60; - initializes only fields actually required by the compatibility layer/runtime;
- executes
WRGSBASEto make the Win32 TEB the application-visible GS base; - transfers control to the original image entry point.
Win32 CreateThread similarly uses a userspace thread bootstrap: the native thread begins on its kernel-created stack/native bootstrap TEB, constructs the Win32 TEB using the known native stack bounds/thread ID, switches GS with WRGSBASE, then calls the Win32 start routine.
Raw native SysCreateThread remains a native extension. Win32 ABI guarantees apply to threads created through the Win32 shim.
Generic FS/GS architectural-state requirement
FS and GS bases are ordinary per-thread architectural state. The kernel preserves them because the scheduler preserves machine state, not because either register has a personality-specific meaning.
Keep the kernel-owned native TEB pointer separate from the live architectural bases:
THREAD.Teb / TebSize
kernel-owned native bootstrap allocation and lifetime metadata
thread saved machine context
FsBase
GsBase
At native user-thread creation, initialize GsBase = THREAD.Teb. This preserves the existing convenient native ABI: a new thread starts with GS addressing its native TEB and does not need a replacement syscall to rediscover state that was previously ambient. Initialize FS according to the native ABI's existing rule.
After the first user instruction, there is no invariant connecting THREAD.Teb to the current FS or GS base. Userspace may execute WRFSBASE and WRGSBASE arbitrarily. It may point either base at a personality TEB/TLS block, ordinary process memory, zero, or any other user-selected address. The kernel must not validate or infer personality from those values.
On kernel entry, swapgs places the interrupted user GS base in IA32_KERNEL_GS_BASE while active GS addresses trusted per-CPU kernel state. If a context switch occurs in kernel mode, save the outgoing thread's user GS base from IA32_KERNEL_GS_BASE into its architectural context and load the incoming thread's saved GsBase into IA32_KERNEL_GS_BASE. Save/restore FSBASE as normal thread architectural state. The eventual swapgs on user return restores the incoming thread's opaque user-selected GS base.
The kernel may retain THREAD.Teb for native bootstrap, APC/runtime bookkeeping, and cleanup, but it must never assert that THREAD.Teb == GsBase after thread startup. Do not add GetTeb, SetPersonalityGs, or similar syscalls merely to replace what userspace can do directly with FSGSBASE.
Verify/enable CR4.FSGSBASE as generic architectural substrate if it is not already enabled. Kernel code must not use user FS as kernel-private state, and no Win32 or POSIX PEB/TEB structure enters the scheduler.
Native helper boundary
After a Win32 thread switches GS, native inline helpers that assume SYS_TEB at GS can no longer be called blindly. The Win32 bootstrap must cache/native-wrap any process-loader state it needs before switching, and Win32-facing libraries must use their Win32 TEB/PEB view.
Low-level syscall stubs remain GS-independent. Do not add hidden GS swaps around every syscall merely to keep native helper code working inside Win32 processes.
Validation
Future tests must include:
- subsystem 1 keeps native
GS:[0]behavior; - subsystems 2/3 execute ordinary compiled
gs:[60h]PEB access; - preemption/migration after
WRGSBASEpreserves the Win32 TEB; - Win32-created secondary threads receive independent TEBs;
- subsystem 7 selects POSIX personality policy while retaining native PEB/TEB layout;
- unknown/unsupported subsystem values fail deliberately rather than silently selecting native.
41. CRT and personality DLL split
After module identity is correct, split monolithic compatibility/runtime modules along real ownership boundaries.
Native/POSIX runtime
crt.dll
malloc/free/realloc
memory/string CRT
stdio
environment
locale
C time bindings
process startup/termination
exit/atexit
setjmp family as appropriate
posix.dll
POSIX FD APIs
signals
credentials/process groups
termios
POSIX filesystem facade
POSIX extensions
Win32-facing split
Move toward real module names/ownership:
kernel32.dll
user32.dll
gdi32.dll
ole32.dll
winmm.dll
The PE subsystem shim chooses personality startup; it does not replace module identity. Aliases belong in loader/module-name policy, not in PE import parsing.
Part VIII — minimal WinDbg KD support
42. Basic serial KD target
Add a deliberately small WinDbg-compatible KD target after POSIX work. The goal is source/symbol debugging, breakpoints, registers, memory inspection, and panic entry—not Windows kernel emulation.
Scope
Initial supported debugger behavior should be limited to the useful core:
connect / reset / reconnect
host break-in
exception stop notification
get/set AMD64 register context
read/write virtual memory
software breakpoint insert/remove
continue
single-step
kernel debug print forwarding where practical
minimal kernel/module identity sufficient for symbols
Physical-memory, MSR, I/O-port manipulation, crash-dump writing, KDNET, and rich debugger extension commands are not initial requirements.
Do not fabricate EPROCESS, ETHREAD, NT pool headers, Windows IRPs, or other Windows internals merely so Windows-specific !process/!thread extensions appear to work. A future nt-lite WinDbg extension may inspect native structures explicitly.
Serial transport
Start with a polling 16550 transport, normally COM1 in QEMU:
KdSerialPutByte
KdSerialGetByte
KdSerialPollBreakIn
The debugger transport must not depend on the scheduler, normal serial input driver, interrupt-driven I/O, heap allocation, or ordinary locks.
COM1 is already used by HAL serial logging and the serial input driver. KD mode therefore claims the selected UART exclusively at boot. When KD owns COM1:
- HAL must not register the ordinary COM1 text-output endpoint on that UART;
- the normal serial input driver must not bind it;
- pre-attach diagnostics continue through other output paths;
- once attached, debugger-oriented output may use KD DEBUG_IO rather than intermixing raw text with KD packets.
Use a boot/debug configuration switch to select KD serial ownership. Do not make debugger packet auto-detection race normal console traffic.
KD protocol core
Implement the classic KD packet framing/acknowledgement/reset subset required by current WinDbg serial sessions. Keep protocol definitions isolated under a KD compatibility layer.
The target translates between WinDbg AMD64 context structures and nt-lite trap/thread context structures. nt-lite internal structures remain canonical.
Debugger memory accesses must be fault-contained: an invalid WinDbg address returns a failed manipulate request rather than recursively panicking the target.
Exception and panic integration
#BP, #DB, explicit debugger break, and fatal exception/panic paths may enter KD when it is enabled and attached.
The normal panic path remains available when KD is disabled or cannot establish a session. KD failure must not make panic diagnostics disappear.
Host break-in may initially be polled from safe recurring kernel points/idle. Do not require the ordinary serial IRQ driver for Ctrl+Break.
SMP rendezvous
Single-vCPU QEMU is acceptable for first protocol bring-up, but SMP stop-the-world is required before KD is considered complete.
When one CPU becomes debugger owner:
owner CPU enters KD
-> send debugger-stop IPI to other online CPUs
-> each CPU saves minimal architectural context and enters a lockless hold loop
-> owner speaks KD
continue
-> publish release generation
-> held CPUs resume
The rendezvous must use debugger-owned atomics/IPIs only. It must not wait on scheduler mutexes or ordinary kernel objects because KD is expected to work when those systems are damaged.
Symbols and module identity
Expose the smallest synthetic KD version/module view WinDbg needs to associate the running kernel and later drivers with their PE/PDB images.
The compatibility view is debugger metadata only. It does not make nt-lite module/process/thread objects adopt Windows layouts.
KD implementation stages
K0 — UART ownership and packet loop
- boot-time KD serial option;
- exclusive COM1 claim;
- polling RX/TX with bounded hardware waits;
- packet framing, checksum, ACK/resend/reset;
- deterministic test harness against captured/constructed KD packets.
K1 — single-CPU debugger stop
int3/debug exception entry;- AMD64 context translation;
- read/write virtual memory;
- breakpoint add/remove;
- continue and trap-flag single-step;
- WinDbg connection on one-vCPU QEMU.
K2 — panic and host break-in
- panic/fatal-exception entry when attached;
- safe host break-in polling;
- invalid debugger memory access recovery;
- debugger detach/reconnect behavior.
K3 — SMP freeze/release
- debugger owner arbitration;
- stop IPI and per-CPU context capture;
- release generation;
- breakpoint/panic testing under SMP load.
K4 — symbols/module polish
- minimal KD version block;
- kernel module record and driver module notifications as needed;
- PDB packaging/path documentation;
- optional nt-lite-specific WinDbg extension later, outside the initial KD acceptance gate.
KD is complete for this roadmap when WinDbg can attach over serial to SMP QEMU, break in, stop all CPUs, inspect/modify registers and virtual memory, set/clear a kernel software breakpoint, single-step, continue, and enter on panic without depending on the ordinary serial driver.
Part IX — USER/GDI and display architecture
43. Native desktop stays below Win32 USER/GDI
DWM is the native session desktop/window manager, not a Win32 server.
Future USER/GDI libraries translate Win32 ABI semantics onto native DWM/RSSRV/surface facilities.
Initial useful USER/GDI surface may include:
CreateWindow / DestroyWindow / ShowWindow / SetWindowPos
BeginPaint / EndPaint
GetMessage / PeekMessage / DispatchMessage / PostMessage
CreateCompatibleDC
CreateCompatibleBitmap
SelectObject
DeleteObject
BitBlt
PatBlt
FillRect
TextOut
A GDI bitmap may use a kernel surface as backing, but kernel surfaces remain generic pixel storage rather than becoming HBITMAP/HDC/window objects.
Only introduce winsrv.exe if genuinely shared Win32-only server state appears.
X11 compatibility service
Add X11 as a userspace compatibility service over the native desktop rather than teaching DWM or the kernel X semantics. x11srv.exe is a sibling of posixsrv.exe: posixsrv remains the POSIX process/filesystem/signal authority, while x11srv owns X protocol state such as XIDs, atoms, properties, selections, grabs, pixmaps, colormaps, and X event routing.
Target layering:
X applications
|
libX11
|
x11srv.exe
|
native DWM/RSSRV/surface protocols
|
kernel surfaces/display/input mechanisms
Do not require a socket merely to imitate Unix when both endpoints are local. An initial nt-lite libX11 transport may use native Ports; add TCP/network-transparent X later only as an explicit transport.
Support two explicit presentation modes rather than pretending they have identical window-manager semantics:
Rootless mode
- map each X top-level window to a native DWM top-level window;
- keep X child-window hierarchy and X-only resources inside
x11srv; - DWM remains authoritative for physical placement, activation, z-order, capture, and outer decorations;
- translate X configure/map/focus requests into native DWM requests and report resulting geometry/state back through X events;
- do not claim that a traditional X window manager is authoritative in this mode; X WM behavior may be constrained or redundant because the native DWM owns the real desktop.
Nested mode
- expose one native DWM window as the X root desktop;
- keep all X windows, stacking, focus, decorations, and workspace policy inside that root;
- allow traditional X window managers such as
twmto operate normally within the nested X desktop; - treat the entire nested X desktop as one ordinary native DWM client from the host desktop's perspective.
Input remains native-session controlled: RSSRV/DWM choose the native focused/captured target, then x11srv translates delivered input into X events and implements X event masks/grabs within the authority granted by the native desktop. X grabs must not become unrestricted native input capture.
Start rendering with userspace software X rasterization into kernel surfaces. CPU composition remains the correctness baseline; acceleration may replace selected rendering mechanisms later without moving X protocol policy into the kernel or DWM.
x11srv holds whatever native desktop capabilities are required to represent X clients. Ordinary X clients do not receive DWM, physical scanout, input-injection, or display-manager authority merely because they can connect to the X server.
43A. Native 2D graphics and text layers
Applications may render directly into mapped surfaces, but ordinary applications should not have to hand-roll clipping, fills, blits, scaling, composition, or glyph-mask rendering. Add a userspace native 2D library without adopting GDI's kernel object/DC model.
The native 2D context is userspace state only: target surface, clip, transform, and blend mode. Initial operations should cover clear/fill, copy/blit, stretch, alpha composition, clipping, simple geometry, and glyph-mask/glyph-run composition. Direct pixel access remains first-class for games, emulators, X11, Mesa/software renderers, and custom engines.
Text is a separate layer: UTF-8 decoding, font discovery/loading, metrics, shaping/layout, glyph rasterization, and glyph cache produce glyph runs/masks that the 2D layer composites. Do not make a byte-oriented TextOutA-style contract the native text architecture.
CPU software rendering is the correctness baseline. Initial canonical surface formats should remain intentionally small (for example premultiplied BGRA8888, opaque BGRX8888, and A8 masks) until real requirements justify more.
Future gdi32.dll, the native UI toolkit, DWM decorations, and x11srv may all consume these primitives, but none of them owns the underlying surface ABI.
44. Display miniport/raster split
Refactor the display-driver boundary so hardware miniports do not own generic raster policy.
Hardware/video miniport
Owns:
- adapter lifecycle;
- mode enumeration;
- mode set;
- framebuffer/VRAM mappings;
- scanout/present;
- vblank/interrupt/fence mechanism;
- hardware cursor;
- optional low-level acceleration/DMA primitives.
Generic raster/display layer
Owns:
- software copy/blit/fill/composite/stretch correctness paths;
- clipping and format conversion;
- generic raster/present helpers;
- capability selection and substitution of optional hardware acceleration.
Optional display/render engine
Use an NT-3.x-inspired ownership split without importing GDI/DDI semantics. A hardware miniport owns adapter mechanisms; an optional display/render engine exposes acceleration capabilities such as copy, fill, blit, composition, synchronization/fences, and command submission. The generic layer chooses accelerated operations only when advertised and always retains the software fallback.
Do not expose one syscall per drawing primitive. When real hardware acceleration requires kernel submission, prefer validated batched command buffers referencing explicit surface/context capabilities. Applications do not receive unrestricted GPU MMIO, DMA, VRAM, or physical scanout authority.
Long-term GPU objects may include device/context, memory, GPU virtual-address space, command submission, and fence/synchronization capabilities. Display (modes, scanout, vblank, cursor) and render (memory, contexts, execution) are separate interfaces even when one driver module implements both.
Target layering:
DWM / native gfx / future GDI / x11srv / Mesa
|
generic graphics/display class
/ \
software raster acceleration dispatch
|
display/render engine
|
video miniport
|
hardware
The compositor/window manager remains userspace and owns composition policy, not hardware mechanism.
Experimental modern-GPU ports
Keep modern-GPU ports as consumers of the native GPU ABI rather than design authorities. A plausible NVIDIA experiment is to port the open NVIDIA kernel-module OS-abstraction boundary onto nt-lite and use GSP where supported, rather than emulate a Linux kernel. For native graphics userspace, prefer a Mesa/NVK path with an nt-lite nvkmd-style backend over making Linux DRM the native ABI. Proprietary NVIDIA userspace, CUDA, or media stacks may later use a deliberately boxed Linux/NVIDIA compatibility personality; that compatibility ABI must not leak into native nt-lite graphics interfaces.
Part X — remaining driver cleanup
45. Driver source/module decomposition
Split only where ownership/lifecycle boundaries are real.
Priority candidates:
- USB into
xhci.sys,usb.sys,usbhid.sys,usbstor.sysas specified above. - xHCI source further into controller/ring/transfer/interrupt pieces if the post-split HCD remains monolithic.
- NTFS where ntfs-3g integration and nt-lite glue are unnecessarily entangled.
- VMware SVGA into hardware miniport versus generic display/raster responsibilities.
- Other very large driver translation units discovered during work.
Do not split files merely to increase file count.
46. Input cleanup
Finish moving repeat/typematic policy into the logical input owner so physical keyboard drivers deliver physical state and RSSRV owns logical repeat behavior consistently.
Add personality wrappers for thread naming when useful:
kernel32 SetThreadDescription/GetThreadDescription
pthread_setname_np/pthread_getname_np
These are small cleanup items and should not block the larger lifecycle work.
Part X-A — native networking and compatibility-driver experiments
Native network-device model remains canonical
The native network stack talks to a neutral NET_DEVICE/packet abstraction. Compatibility drivers adapt to it; they do not redefine native packet, DMA, PnP, or network policy. Networking eventually moves protocol processing such as lwIP out of the kernel where practical, using kernel-managed capability/waitable endpoints and efficient shared data transfer analogous to pipes. SysResolveHost remains an acknowledged temporary shortcut until that redesign is implemented.
NDIS subset
A useful NDIS subset is reasonable as a compatibility layer. Target NDIS 6 Ethernet miniport behavior first; do not initially implement Windows protocol drivers or filter drivers. Translate miniport lifecycle, NBL/NB/MDL packet views, basic OIDs, interrupts, DMA, PCI/MMIO, timers/work, and status indication onto native nt-lite mechanisms. Start with copying packet translation; optimize later.
Binary .sys compatibility additionally requires a boxed Win32 kernel-driver environment (ntoskrnl/HAL/NDIS imports, PE driver loading, observable IRQL constraints, configuration/registry projection, and possibly framework dependencies). Keep that namespace under a compatibility subsystem rather than exporting fake Windows APIs as native kernel interfaces.
Do not begin with Wi-Fi, protocol/filter drivers, SR-IOV, advanced offloads, or KMDF. A first success criterion is an unmodified direct NDIS 6 Ethernet miniport reaching DHCP/ping through the native stack.
Native Wi-Fi ports and reverse engineering
Full binary compatibility for KMDF + NetAdapterCx + WiFiCx is a distant research target, not a prerequisite. A much more reasonable path for unsupported vendor hardware is machine-assisted reverse engineering followed by a clean native port:
vendor binary + metadata
-> hardware/firmware protocol specification
-> native nt-lite driver
Recover firmware loading/boot, register programming, DMA/ring descriptors, interrupts, firmware command/event formats, TX/RX queue mechanics, scan/connect/key operations, and reset/recovery. Do not mechanically transliterate decompiler output or preserve Windows framework object lifetimes.
Keep Wi-Fi policy primarily in a future userspace wifisrv: discovery, saved networks, credentials, association/roaming policy, and UI-facing state. The kernel driver owns time-critical hardware/firmware mechanisms, TX/RX, primitive scan/radio/key operations, and events. The exact split may tighten where firmware timing requires it.
Part XI — implementation sequence
47. Recommended execution order
P0-P7 are complete; P7 is runtime-validated by the full suite. The active work is now the generic substrate that must exist before POSIX P8 can be correct. Do not land synthetic P8 architecture merely to keep the old stage numbering moving.
Active milestone — native ABI cleanup
Execute UABI.1-UABI.4 as independent reviewable changes. UABI.1 is a whole-tree semantic type sweep, not merely public-syscall cosmetics; real MSVC build/runtime validation remains the gate. UABI.2 makes UTF-8 the explicit native text contract. UABI.3 removes the fixed-size process-builder storage. UABI.4 deletes stale duplicated namespaces/input paths after callers are migrated.
Active milestone after UABI — KFS then SEC
Execute KFS.1-KFS.7 before filesystem ACL integration. Then execute the SEC sequence so file security attaches to coherent backing identity. Revisit rights taxonomy before freezing hard-link/open/security syscalls.
Resume POSIX after native prerequisites
P8 revised filesystem projection + FIFOs
P9 tty/termios
P10 leaf APIs/profile closure
Do not start the future Win32 GS shim, KD, NDIS compatibility, or experimental GPU ports during this sequence unless the active native milestone independently needs the same generic primitive.
Parked milestone A — drivers.ini v2 parser and graph manager
- define public/internal config structures;
- extend
BOOT_INFOwith rawdrivers.iniand explicit boot-driver identities; - replace ordered-list UEFI parsing with minimal descriptor preload scanning;
- implement strict kernel parser;
- implement class and driver graph validation;
- implement state machines and deterministic scheduler;
- initialize current drivers through the graph;
- remove ordered
[boot]/[runtime]initialization paths.
Parked milestone B — graceful driver/device shutdown
- define Prepare/Commit shutdown interfaces;
- add module/device lifetime accounting required by shutdown;
- implement reverse effective-graph shutdown;
- implement runtime device-topology shutdown traversal;
- flush/freeze filesystems and caches;
- stop storage/network/audio/display/USB hardware and DMA;
- add bounded timeouts and shutdown summary diagnostics;
- call HAL S5 only after lifecycle shutdown completes.
Parked milestone C — USB split
- extract xHCI HCD;
- establish neutral HCD device/interface contract;
- extract generic USB core;
- extract USB HID;
- extract USB storage;
- place all four into lifecycle classes;
- verify QEMU USB input/storage and real-hardware USB paths;
- verify shutdown ordering through
usb-storage -> usb -> usb-hcd.
Parked milestone D — unload/reload substrate
- module import/reference tracking;
- PnP/device ownership accounting by module;
- real
DriverUnloadcallers; - manual unload/reload;
- optional cascade reload;
- only then add
start=demand.
Parked milestone E — finish native desktop migration
- render RSSRV console through a surface/window;
- make desktop focus the normal console/GUI transition;
- delete stale direct application input/console/display paths;
- improve damage regions;
- add title/close/move/resize/decorations;
- define DWM restart/loss behavior.
Future milestone F — native status remainder, loader identity, and personality selection
- complete non-POSIX KSTATUS/Win32 mapping cleanup;
- resolved-file module identity;
- import/reference tracking;
- PE subsystem personality selection;
- generic mutable user-GS persistence;
- userspace Win32 PEB/TEB bootstrap for subsystems 2/3;
- subsystem 7 POSIX marker with native layout;
crt.dll/posix.dlland Win32-facing DLL ownership split.
Future milestone G — minimal serial KD
- K0-K4 from Section 42;
- keep transport independent of ordinary COM1 logging/input;
- stop at basic WinDbg source/symbol debugging before considering KDNET or Windows-specific extension compatibility.
Future milestone H — richer USER/GDI
- build USER/GDI over native DWM/RSSRV protocols;
- retain kernel surface distinction;
- optimize only after functionality/profiling establishes hot paths.
Future milestone I — X11 compatibility service
- add
x11srv.exeas a sibling userspace service rather than putting X protocol state inposixsrvor DWM; - implement local
libX11transport over native IPC first; - implement nested mode with one native DWM window as the X root and full traditional X window-manager authority inside it;
- implement rootless mode mapping X top-levels to native DWM windows while retaining native DWM authority over physical desktop policy;
- keep X child windows/resources, selections, properties, grabs, pixmaps, and event routing inside
x11srv; - translate native input/capture into X semantics without giving X clients ambient native input authority;
- render through native surfaces with software rasterization as the initial correctness path;
- add network-transparent/TCP X only after the local server and security model are stable.
Future milestone J — display stack split and remaining driver cleanup
- hardware miniport versus generic raster/display layer;
- VMware SVGA cleanup;
- NTFS/source decomposition where justified;
- remaining large-driver ownership cleanup.
Future milestone K — native 2D/text stack and accelerated graphics
- userspace native 2D raster library with direct-surface escape hatch;
- native UTF-8 text/font/shaping/glyph stack;
- shared theme schema for DWM chrome and native UI toolkit;
- optional display/render acceleration interface with software fallback;
- batched validated command submission only when real accelerated hardware needs it;
- later Mesa/native Vulkan WSI work over the native GPU ABI.
Future milestone L — network-driver compatibility experiments
- narrow NDIS 6 Ethernet miniport compatibility layer over native
NET_DEVICE; - prove one unmodified miniport through DHCP/ping before expanding;
- keep KMDF/NetAdapterCx/WiFiCx binary compatibility explicitly experimental;
- prefer clean native Wi-Fi ports derived from documented/reverse-engineered hardware/firmware protocols;
- introduce
wifisrvwhen native Wi-Fi policy work begins.
Experimental milestone M — modern NVIDIA path
- port the open NVIDIA kernel-module OS abstraction only if it fits the native GPU interfaces;
- bring up PCI/BAR/GSP/interrupt/modeset before render acceleration;
- prototype Mesa/NVK with an nt-lite kernel backend before attempting proprietary Linux graphics userspace;
- keep any Linux/NVIDIA proprietary userspace compatibility environment isolated from the native GPU ABI.
Part XII — validation matrix
48. Driver-manager tests
Add deterministic unit/kernel tests for parsing, graph validation, state semantics, and boot handoff:
- valid empty dependency lists;
- duplicate section/key rejection;
- unknown key rejection;
- malformed IDs;
- class-after-driver rejection;
- missing key rejection;
- class/driver/combined cycles;
- missing or disabled providers;
- boot dependency available only at runtime;
- provider alternatives with mixed success/failure;
requiresversusaftersettlement behavior;- critical blocked-driver startup failure;
- configured boot blob identity matching and raw-config handoff.
49. Shutdown tests
Create synthetic drivers for successful prepare/commit, prepare failure/timeout, commit failure, draining workers, outstanding IRPs, and DMA/interrupt state.
Verify reverse graph order, storage flush-before-controller shutdown, USB-storage/HID/core before HCD, network stack before adapters, and eventual HAL shutdown after bounded noncritical failures.
50. Reload tests
Before enabling reload generally, test:
- unload with no devices;
- unload with attached devices rejected or properly removed;
- unload with outstanding IRP;
- unload with active import dependent rejected;
- reload success and DriverEntry failure;
- dependent closure calculation/cascade order;
- class availability changes and rebinding.
Current runtime regression investigation — DOOM first-frame stall
A current DOOM run reaches doom: entering game loop and the asynchronous SoundFont loader reaches doom: MIDI synthesizer ready, but no frame becomes visible afterward. The first game-loop path contains three blocking boundaries worth isolating before changing architecture: display-clock pacing, the first RSSRV logical-input query, and acquisition of the audio/core mutex. Use one-shot first-frame diagnostics and a bounded display-clock wait to identify the exact boundary. Do not attribute the stall to MIDI merely because the last log line comes from the asynchronous synth-loader thread.
51. Desktop tests
Extend desktop tests to cover console-window visibility/focus, close, move/resize, capture, relative lock, damage clipping, overlapping composition, disconnect cleanup, and the chosen DWM crash/restart contract.
X11 compatibility tests
When x11srv is implemented, cover:
- nested X root creation inside one native DWM window;
- a traditional X window manager moving/decorating/stacking clients correctly in nested mode;
- rootless top-level creation, map/unmap, configure, focus, and close translation through DWM;
- X child windows remaining server-internal rather than becoming native windows;
- X grabs bounded by native DWM/RSSRV capture authority;
- selections/properties and disconnect resource cleanup;
- software raster output and damage propagation to native surfaces;
- rootless mode retaining DWM authority when an X client or X WM requests conflicting geometry/z-order;
- X clients having no physical scanout, global input-injection, or unrelated native-window authority.
51A. UABI/KFS/security tests
UABI gates include standalone compilation of every owned public header, ABI-layout assertions, compiler-warning-clean builds across changed callers, explicit checks that compatibility/vendor ABIs were not mechanically rewritten, and the full runtime suite after each ABI break. UTF-8 tests cover malformed sequences, boundary validation, embedded-NUL policy, and byte-exact namespace behavior.
KFS tests cover independent-open/cache/mmap coherence, unlink with live opens, real hard-link counts/data identity, rename replacement/cross-device errors, timestamp mutation, and directory reset. Security tests cover order-independent deny-wins ACL evaluation, owner security-mutation authority without implicit data authority, creation-time inheritance, existing-capability survival across ACL changes, explicit revocation, principal/group materialization, provider translation, restrictions/privileges, and audit records.
51B. Graphics/network compatibility tests
Graphics tests retain CPU software rendering as the reference result and compare accelerated fill/copy/composite paths against it. Validate that ordinary applications cannot acquire physical scanout/MMIO/DMA authority, and that DWM policy remains unchanged when the backend changes.
NDIS experiments must prove lifecycle, PCI/MMIO, interrupt, DMA, RX/TX, basic OIDs, link state, clean halt/unload, and DHCP/ping through the native stack before adding wider compatibility. Native Wi-Fi ports stage firmware boot, event/command transport, scan, RX/TX, association, key installation, DHCP/ping, reset, and suspend/resume.
52. POSIX tests
The POSIX suite is stage-gated, not one final smoke test.
Process identity and construction
- stable POSIX PID independent of native PID;
getppidlaunch association;- spawn environment and file actions;
- inherited descriptor/open-description sharing;
wait/waitpid/WNOHANGand child collection;- failed spawn cleanup;
- successful exec retains POSIX PID while changing native generation;
- failed exec leaves the old image usable;
- repeated exec;
FD_CLOEXECfiltering;vfork()+execveandvfork()+_exit;- explicit
fork()unsupported behavior if exported.
Signals
- per-thread masks and pending sets;
- process-directed target selection;
- process-group routing;
- handler/default/ignore transitions;
- signal interruption of waits/I/O;
- exec disposition/mask behavior;
- exception translation.
Filesystem facade
- POSIX owner/group/mode projection over native principals/ACLs;
- umask creation-time restriction;
- native hard-link aliases and link counts;
- open-after-unlink and rename-replacement behavior;
- timestamp mutation and directory reset;
- pathconf/fpathconf;
- FIFO open/rendezvous, nonblocking, EOF, broken-pipe, cleanup.
Tty/termios
- canonical/raw behavior;
- VMIN/VTIME;
- echo/editing/output postprocessing;
- foreground process groups;
- VINTR/VQUIT signal routing.
End-to-end integration
Run a shell-like scenario:
parent POSIX process
-> pipe
-> spawn producer with envp + dup2 file action
-> spawn consumer in a process group
-> signal the group
-> waitpid children
-> exec replacement retaining parent POSIX PID
The full native all_tests suite must still pass after every POSIX stage.
53. PE subsystem/personality tests
Future personality tests must verify subsystem 1 native layout, subsystem 2/3 Win32 gs:[60h], GS persistence across preemption/migration, independent secondary-thread TEBs, subsystem 7 native-layout POSIX selection, and deliberate rejection of unsupported subsystem values.
54. KD tests
Future minimal KD validation must cover:
- packet checksum/ACK/resend/reset unit tests;
- COM1 exclusive ownership in KD mode;
- WinDbg serial attach on one-vCPU QEMU;
- register read/write;
- valid and invalid virtual-memory access;
- software breakpoint add/remove;
- single-step/continue;
- host break-in;
- panic entry;
- reconnect after debugger reset where supported;
- SMP stop/release with workload on every CPU;
- no dependency on the ordinary serial input/logging driver while stopped.
Part XIII — architectural acceptance criteria
55. Driver subsystem
The driver lifecycle overhaul is complete when file order cannot affect startup semantics, the bootloader only preloads boot images/raw config, the kernel owns validation/scheduling, startup reverses into graceful shutdown, shutdown waits are bounded, and unload/reload/demand loading use the same graph/lifetime model.
56. Desktop/session subsystem
The desktop architecture reaches its next stable point when console is rendered through DWM as native desktop content, RSSRV remains console/input/session authority, DWM remains graphical policy, stale ambient application paths are gone, and DWM crash/restart behavior is explicit.
57. POSIX subsystem
The POSIX personality is complete for this roadmap when:
posixsrvowns stable POSIX PIDs and all genuinely shared POSIX policy;- native PID/process generations are replaceable implementation details;
fork()is deliberately unsupported and no COW/process-clone substrate exists for it;vfork()andexecve()use the server-owned model in Section 31;posix_spawn, wait, environment, and descriptor file actions are complete;- inherited open descriptions remain coherent across processes;
- signals are asynchronous, per-thread-mask aware, and process-group routable without kernel POSIX semantics;
- tty, identity, and process groups/sessions have one coherent POSIX owner while filesystem identity/links/security remain native KFS/SEC authority;
- POSIX filesystem permission/link/time APIs project native semantics and FIFOs remain coherently owned by
posixsrv; - the POSIX profile manifest accurately describes every exposed API;
- full native and POSIX runtime suites pass.
58. Runtime/personality subsystem
The future loader/runtime cleanup is complete when:
- module identity is backing-file/object based;
- imports create real provider references;
- PE subsystem selects native, Win32 GUI/CUI, or POSIX personality intentionally;
- subsystems 2/3 receive userspace Win64 PEB/TEB state with persistent user GS;
- subsystem 7 remains native-layout POSIX unless deliberately redesigned;
- aliases resolve to one module instance;
- kernel module unloading can prove no import/lifetime references remain;
crt.dll,posix.dll, and Win32-facing DLLs have distinct ownership boundaries.
59. Minimal KD subsystem
Basic KD support is complete when WinDbg can attach to SMP QEMU over an exclusively-owned polling serial transport, break in, freeze all CPUs, inspect/modify AMD64 registers and virtual memory, set/clear a software breakpoint, single-step, continue, and enter on panic while nt-lite retains its own kernel object layouts.
60. X11 compatibility subsystem
X11 compatibility is complete for this roadmap when x11srv remains a userspace translation service over the native desktop, nested mode supports a conventional X root and traditional X window manager, rootless mode integrates individual X top-levels without surrendering native DWM authority, X-specific state remains out of the kernel/DWM, native input/capture authority is preserved, and local X clients can render through native surfaces without receiving ambient desktop/display authority.
61. Native filesystem/security prerequisite subsystem
The KFS/security prerequisite reaches its stable point when independent opens and aliases share one coherent backing identity; unlink/open lifetime, real hard links, rename replacement, timestamps, and directory reset are native provider contracts; file security attaches to backing identity; ACL evaluation and principal contexts are generic kernel concepts; account secrets/names remain userspace-owned; and POSIX/NTFS/ext4 all translate into one native security flavor rather than defining competing kernel models.
62. Native graphics subsystem
The graphics architecture reaches its stable point when mapped surfaces remain the fundamental client rendering ABI, the optional native 2D/text libraries do not require kernel GDI objects, software rendering is a complete correctness path, hardware miniports expose mechanisms rather than UI policy, accelerated render/display engines are optional substitutions, DWM remains userspace policy, and future Mesa/GDI/X11 backends can target the same native primitives.
63. Compatibility-driver experiments
NDIS, Linux/NVIDIA userspace, KMDF-class frameworks, and reverse-engineered vendor drivers remain compatibility or porting projects layered over stable native DMA/PnP/network/GPU primitives. Success in one compatibility target must not make its foreign ABI the native nt-lite contract.
Target architecture
UEFI loader
|
| loads kernel/HAL + configured boot driver blobs
| passes raw drivers.ini without dependency policy
v
kernel
|
| generic mechanisms only:
| process/thread/VM/handles/Ports/APCs/waits
| driver/device lifecycle
| native exception/trap context
|
+------------------------- init.exe -------------------------+
| |
| rssrv.exe
| / | \
| / | \
| posixsrv.exe x11srv.exe dwm.exe
| | / \ |
| stable POSIX policy libX11 native DWM -----+
| | | | |
| posix.dll X/POSIX native gfx/text |
| | apps | |
| POSIX apps native UI future USER/GDI
|
+-- future auth/account service -> principal names/secrets/groups -> kernel SECURITY_CONTEXT creation
+-- future wifisrv -> Wi-Fi discovery/association/credential policy -> native Wi-Fi device class
|
+-- userspace PE loader
| |
| +-- subsystem 1 -> native SYS_PEB/SYS_TEB
| +-- subsystem 2 -> Win32 GUI shim -> Win64 PEB/TEB via WRGSBASE
| +-- subsystem 3 -> Win32 CUI shim -> Win64 PEB/TEB via WRGSBASE
| +-- subsystem 7 -> POSIX marker, native PEB/TEB layout
|
+-- optional KD core
|
+-- exclusive polling 16550 serial transport
+-- WinDbg compatibility packets/context view
+-- SMP debugger stop/release
The important separation is:
configuration graph = module lifecycle policy
runtime device graph = actual hardware/device relationships
services graph = user-mode service lifecycle
RSSRV session state = native session authority
DWM = replaceable graphical policy
posixsrv = stable POSIX identity and shared POSIX policy
KFS backing = native file identity/cache/lifetime/security attachment point
SECURITY_CONTEXT/ACL = kernel-mediated principal authority, not account-name/password storage
DWM = native window/composition policy; native gfx/text remains optional userspace rendering support
native NET_DEVICE/GPU = canonical hardware abstractions; NDIS/NVIDIA/Linux compatibility stays outside them
PE subsystem selector = userspace personality bootstrap policy
KD compatibility view = debugger protocol metadata, not Windows kernel architecture
Each graph/state domain has one owner and one purpose. Personality implementations may request generic native mechanisms, but they do not move their policy into the kernel.