Per-core MSR setup (EFER.SCE, STAR, LSTAR, SFMASK) enables syscall; the
GDT layout was already chosen so sysret lands on CS 0x23 / SS 0x1B. A new
syscall_entry stub swaps in the kernel GS, switches to the task's kernel
stack via the per-CPU block, builds a CpuState frame identical to the
interrupt path's, and reuses interruptDispatch (vector 128) — then
sysretq back. enter_user now also publishes kernel_rsp so the borrowed
path's syscalls land on a good stack. /sbin/init uses the `syscall`
instruction. int 0x80 stays for the test blobs. Suite 27/27.
(Noted in the stub: sysretq #GPs in ring 0 on a non-canonical return
RIP — a hardening item once untrusted user code exists.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ring 3 works: user GDT descriptors (sysret-ready layout), TSS.rsp0,
U/S-bit user mappings (W^X preserved), an int 0x80 syscall gate with a
mutable trap frame, and a setjmp-style enter/exit path. /sbin/init is a
real freestanding Zig binary built from sbin/, shipped on the ESP,
loaded by the bootloader (BootInfo.init_base/len), validated and mapped
by an in-kernel user-ELF loader, and run at CPL 3 — syscalls: exit,
ping, write. Tests: user, user-pf (U/S isolation proof, error code
0x5), init. Suite 27/27.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>