Phase 52
First Service Extractions
m3OS proves that its microkernel direction is real by extracting at least the first visible core services out of the kernel address space. Console and input-related functionality become supervised ring-3 services, and the system demonstrates that they can fail and be restarted without rebooting the machine.
Learning goal
Understand how a kernel-resident service becomes a real ring-3 process.
Category
infrastructure
Components touched
Builds on
Unlocked by this phase
Why this phase matters
m3OS proves that its microkernel direction is real by extracting at least the first visible core services out of the kernel address space. Console and input-related functionality become supervised ring-3 services, and the system demonstrates that they can fail and be restarted without rebooting the machine.
How it works in m3OS
Phase 52 proves that the m3OS microkernel architecture is real by extracting console rendering and keyboard input handling from kernel-resident tasks into supervised ring-3 services. After this phase, the system demonstrates that user-visible subsystems can cross the ring-0 boundary, communicate through the Phase 50 IPC contract, and be restarted by the Phase 51 service manager without rebooting the machine.
How it builds on earlier phases
This phase builds on Service Model Maturity and turns that foundation into First Service Extractions.
Implementation outline
- Choose the first extraction targets and define their ring-3 service contracts.
- Narrow the kernel side to the minimal notification, mapping, and hardware-mediation responsibilities.
- Wire the new services into build, initrd, and service-manager configuration.
- Port console/input policy out of kernel-resident task code.
- Implement restart and reconnect behavior for the extracted services.
- Measure the boundary cost and document the new call/data flow.
- Add smoke or focused validation that proves restartability and correct behavior.
Task progress snapshot
23 of 27 tracked tasks are complete.
Documentation targets
- Documentation deliverables have not been listed yet.
Deferred follow-on work
- Storage, namespace, and networking extraction
- Rich multi-seat or multi-session input policy
- Fully graphical display ownership
- Broad performance tuning of the new boundary
Source materials
Important code
Code spotlight cards
Code spotlight
Stand up a ring-3 console service endpoint
Stand up a ring-3 console service endpoint. Why it matters: Phase 52 is only meaningful if the console becomes a real userspace service with its own endpoint and registration path instead of remaining a kernel-only concept. Focus on `program_main` and `console_server` in `userspace/console_server/src/main.rs` while you trace the snippet.
fn program_main(_args: &[&str]) -> i32 {
syscall_lib::write_str(STDOUT_FILENO, "console_server: starting\n");
// Phase 52 transitional: skip framebuffer_mmap because it calls
// try_yield_console which suppresses ALL kernel framebuffer text output
// (login prompt, shell, everything). The kernel's fb console still
// handles sys_write rendering. The userspace console_server runs as an
// IPC-only service: CONSOLE_WRITE payloads are echoed to stdout which
// the kernel renders to both serial and framebuffer.
//
// Full framebuffer takeover will be enabled in a later phase when
// sys_write(STDOUT) is routed through IPC to this service.
// 1. Create an IPC endpoint.
let ep_handle = syscall_lib::create_endpoint();
if ep_handle == u64::MAX {
syscall_lib::write_str(STDOUT_FILENO, "console_server: create_endpoint failed\n");
return 1;
}
let ep_handle = ep_handle as u32;
// 2. Register as "console" service (takes over from kernel entry).
let ret = syscall_lib::ipc_register_service(ep_handle, "console");
if ret == u64::MAX { Code spotlight
Move keyboard IRQ service ownership to ring 3
Move keyboard IRQ service ownership to ring 3. Why it matters: This is the first completed hardware-facing service extraction in Phase 52: IRQ-driven keyboard delivery no longer depends on a kernel-resident kbd_server_task. Focus on `program_main` and `kbd_server_task` in `userspace/kbd_server/src/main.rs` while you trace the snippet.
fn program_main(_args: &[&str]) -> i32 {
syscall_lib::write_str(STDOUT_FILENO, "kbd_server: starting\n");
// 1. Create an IPC endpoint.
let ep_handle = syscall_lib::create_endpoint();
if ep_handle == u64::MAX {
syscall_lib::write_str(STDOUT_FILENO, "kbd_server: failed to create endpoint\n");
return 1;
}
let ep_handle = ep_handle as u32;
// 2. Register as "kbd" in the service registry.
let ret = syscall_lib::ipc_register_service(ep_handle, "kbd");
if ret == u64::MAX {
syscall_lib::write_str(STDOUT_FILENO, "kbd_server: failed to register 'kbd'\n");
return 1;
}
// 3. Create an IRQ1 notification.
let notif_cap = syscall_lib::create_irq_notification(1);
if notif_cap == u64::MAX {
syscall_lib::write_str(
STDOUT_FILENO,
"kbd_server: failed to create IRQ1 notification\n", Code spotlight
Bridge keyboard IPC back into the existing stdin path
Bridge keyboard IPC back into the existing stdin path. Why it matters: Existing userspace still reads stdin through the traditional TTY path, so Phase 52 needs a bridge from the new keyboard IPC service back into the shared kernel line discipline. Focus on `program_main` and `sys_push_raw_input` in `userspace/stdin_feeder/src/main.rs` while you trace the snippet.
fn program_main(_args: &[&str]) -> i32 {
syscall_lib::write_str(STDOUT_FILENO, "stdin_feeder: starting\n");
// Look up the "kbd" service to obtain an endpoint capability.
// Retry with short sleeps because the service manager starts us as soon
// as kbd_server is forked, which is before it has registered its IPC
// endpoint.
let kbd_handle = {
let mut h = u64::MAX;
for _ in 0..50 {
h = syscall_lib::ipc_lookup_service("kbd");
if h != u64::MAX {
break;
}
syscall_lib::nanosleep(20_000_000); // 20 ms
}
if h == u64::MAX {
syscall_lib::write_str(STDOUT_FILENO, "stdin_feeder: failed to lookup 'kbd'\n");
return 1;
}
h as u32
};
syscall_lib::write_str(STDOUT_FILENO, "stdin_feeder: ready\n"); Key files
- kernel/Cargo.toml — When the phase lands, bump kernel/Cargo.toml and any release/version references to 0.52.0.
- userspace/console_server/src/main.rs — Ring-3 console rendering service
- userspace/kbd_server/src/main.rs — Ring-3 keyboard scancode service
- userspace/stdin_feeder/src/main.rs — Ring-3 scancode-to-byte bridge that forwards via push_raw_input
- userspace/init/src/main.rs — Service manager integration for extracted services
- kernel-core/src/tty.rs — Shared kernel line discipline for serial and keyboard input
- kernel/src/arch/x86_64/syscall/mod.rs — push_raw_input entry point and TTY-facing syscall glue
- kernel/src/main.rs — Narrowed kernel-side mediation (FB mapping, IRQ, buffers)
- kernel/src/ipc/mod.rs — Registry and capability infrastructure
- kernel/initrd/etc/services.d/console.conf — Console service definition
- kernel/initrd/etc/services.d/kbd.conf — Keyboard service definition
How real OSes differ
- Mature microkernels often perform this extraction work earlier and across more subsystems at once.
- Monolithic kernels keep console and input behavior in-kernel for historical and performance reasons, not because that is the only workable design.
- m3OS should optimize here for clarity, restartability, and teaching value over perfect early performance.
Success criteria
- At least one previously kernel-resident core service runs as a real supervised ring-3 process.
- The extracted service uses the Phase 50 IPC path without shared-address-space shortcuts.
- Restarting or crashing the extracted service does not require a full machine reboot to recover basic functionality.
- The service graph, build system, and docs all describe the extracted service as part of the normal system model.
- Boundary measurements and trade-offs are written down for later phases.
Related phases
Keep exploring the roadmap
Phase 51
CompleteService Model Maturity
m3OS turns its new service-management baseline into a reliable lifecycle model: boot ordering is explicit, restart semantics are trustworthy, shutdown behavior is deterministic, logs are coherent, and extracted ring-3 services can plug into the same operator workflow instead of inventing their own.
Phase 52
CompleteKernel Reliability Fixes
All four confirmed kernel bugs from the Phase 52 bug investigations are fixed, with targeted regression tests proving each fix.