XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
10.17 KB
Readme.md

Independent C# bootstrap kernel

This x86_64 bare-metal kernel has no Cosmos SDK, runtime, HAL, driver, scheduler, patcher or source dependency. The C# files contain the boot policy, bounded UART, memory-map validation, physical-page allocator, GDT/TSS/IDT construction, exception diagnostics and 32-bit framebuffer access. native.c contains only Limine request/storage declarations and instruction wrappers; entry.S contains the entry, descriptor reload and exception trampolines C# cannot express. Their paths are Native/native.c and Native/entry.S.

The Limine request identifiers and the x86_64 descriptor design were checked against this project's own historical Rust implementation at commit 1139821 (kernel/src/boot.rs, kernel/src/arch/x86_64.rs). They have been reimplemented in C#/C/assembly without copying or renaming Cosmos code. Limine remains an external BSD-2-Clause bootloader; its public boot protocol is 0BSD. The bflat Zero standard library and compiler remain external MIT tooling.

Build C# with pinned bflat 8.0.2, --os:linux --arch:x64 --stdlib:zero --target:Shared -c, and -i:xfe_native so P/Invoke resolves to the local xfe_* symbols directly. Compile native.c and entry.S for x86_64 ELF with Clang, -mno-red-zone, -ffreestanding, -fno-stack-protector, and link with the independent runtime object and a linker script retaining all .limine_requests* sections. The ELF entry is _start; no libc, dynamic loader or managed host process is used.

Exports: XfeKernelMain(NativeBootInfo*), XfeHandleInterrupt(InterruptFrame*). The kernel calls the optional partial method Kernel.OnKernelReady() after real boot self-tests pass. An application implementation in the same namespace and partial class can provide that method. No existing Kernel project is edited.

Bootstrap limits are explicit: one BSP for the managed scheduler, inherited bootloader page tables, physical allocation below 8 GiB, 4 KiB contiguous pages, no managed allocation, 32 single-BSP managed kernel threads, up to 32 real CPUs for native kernel jobs, no user-mode isolation, no storage or network. Memory above the allocator cap is counted as ignored. Only usable memory entries are allocated; bootloader-reclaimable, firmware and executable regions remain reserved. Runtime memory bridges mask IRQs around mutation, which provides single-BSP exclusion rather than a general SMP lock. AP jobs never enter these allocators or the Microsoft runtime. Release checks page ownership and rejects a duplicate release; it does not protect callers from unmapping a still-used allocation.

Serial success markers are emitted after actual C# checks, including zero/reuse/ ownership/contiguous page checks, SGDT/SIDT readback, returning INT3 through our IDT and SSE-preserving trampoline, and a framebuffer pixel readback. Presence of this source or an ELF object alone is not an accepted boot result.

Thread scheduling is single-BSP, with 32 slots and a calibrated periodic LAPIC timer. Context switches preserve System V nonvolatile registers, the real stack, FS base and complete enabled x87/SSE state. OSXSAVE is disabled; AVX/YMM/ZMM are not enabled or promised. New stacks have unmapped guards at both ends. Every thread also owns a separate guarded 64 KiB IRQ stack; the scheduler changes TSS IST3 with interrupts masked before changing context. Asynchronous IRQs preserve the System V 128-byte red zone used by the unchanged Microsoft native runtime archives, and suspended IRQ frames belong to their outgoing thread. The native preemption probe never yields or calls a helper: two threads' independent FS, XMM15 and all sixteen red-zone qwords must survive at least three actual LAPIC ticks and real context switches. Events use generation-tagged handles and real park/wake with manual/auto reset, timeout and close rejection. Full .NET GC hijacking uses the Microsoft runtime's real helper on captured contexts; a missing or inconvenient helper does not count as GC safety.

Multiprocessor.cs uses the Limine MP response to release actual APs. Each has private GDT/TSS, fault/IRQ stacks, SSE state and a recorded APIC identity. An all-AP rendezvous precedes readiness. APs sleep in HLT and wake through directed IPIs; release/acquire generation numbers and a join retain every source mapping until all WC stores complete. They reload CR3 before touching each new job's dynamic mappings. Only the BSP edits page tables, and a submitted buffer must remain pinned/reserved until join. This is native multicore job execution, not full managed SMP, GC safepoint IPIs, migrating runtime threads or TLB shootdown.

Large framebuffer copies can use disjoint AP row ranges. Before the splash, actual black scanout copies compare 1/2/4/8 CPUs; parallel presentation requires at least a 10% improvement in the worst of five samples. Small damage stays on the BSP. These measurements concern CPU copying, not physical refresh or a Windows desktop workload. Physical GPU modesetting, VSync and GPU rendering remain unavailable; the Windows parity acceptance flags remain false.

The 8042 driver initializes keyboard/mouse only after actual ACKs and polls real device bytes on LAPIC ticks. PS/2 set-1 translation and three-byte mouse packets enter a 256-report queue. Overflow or parity/timeout clears stale reports and emits an explicit loss report. USB HID, IME and wheel negotiation are not enabled. The same pure decoder source is linked into host regressions; those regressions are separate from actual guest device acceptance.

xfe_runtime_utc_filetime() double-samples the live CMOS RTC, bounds UIP polling, validates power/data fields and date ranges, handles BCD/binary and 12/24-hour modes, and uses century register 0x32 when valid. With an absent century it uses the explicit 1970/2069 pivot. Read failure returns zero. This is not a fixed build date or host callback. QEMU must use RTC base=utc; physical RTC timezone conventions remain to be verified before claiming that physical machine's UTC accuracy.

The virtual-memory arena uses two empty PML4 slots at low canonical address 0x0000200000000000, covering 1 TiB and up to 256 live reservations. Reserve records an address range without allocating RAM; commit creates zeroed 4 KiB supervisor RW/NX PTEs. Decommit clears PTEs, invalidates the local TLB and returns data pages and empty kernel-owned page-table pages. Release requires the original whole reservation. Protection accepts read=1, write=2, execute=4 and rejects W+X; CR0.WP and EFER.NXE enforce the policy. The boot self-test intentionally triggers two unmapped guard reads, a read-only write and an NX instruction fetch, returning only when the expected CR2, RIP and page-fault error bits match. It also checks zeroed commits and complete page reclamation. Existing and mixed-range commits preserve old pages; failed commits roll back only newly added pages. Physical release validates both ownership and exact allocation block boundaries, rejecting partial or cross-block frees. Only four-level paging and single-BSP edits are supported. No AP TLB shootdown or user-process memory domain is claimed.

The C ABI for the separate .NET module is xfe_runtime_alloc_pages(ulong) returning a zeroed 4 KiB-aligned HHDM pointer, xfe_runtime_free_pages(void*,ulong) returning 1 on success, xfe_runtime_write(byte*,ulong), xfe_runtime_mono_ns(), xfe_runtime_clock_ready(), xfe_runtime_framebuffer_info(NativeFrameSurface*) and xfe_runtime_halt(byte*). Counts for allocation/release are pages, not bytes. The surface structure is a 56-byte sequential value (two ulong fields followed by ten uint fields). Logs accept at most 1 MiB; fatal reasons read at most 256 bytes. These exports exchange no managed references. The TSC clock uses an explicit CPUID crystal/ratio or bounded PIT channel-2 calibration. A non-invariant TSC is identified in the boot log: elapsed-time accuracy across frequency changes is not promised.

To link Zero and .NET together, all Zero compiler/runtime symbols must be prefixed and its __modules, __managedcode and __unbox sections separated from the real runtime module tables. Restore only xfe_* imports and the C ABI exports. Map the Zero references SystemNative_Abort/SystemNative_Malloc to xfe_zero_abort/xfe_zero_malloc; do not bind either module to the other's Rhp* implementations or share Zero objects with the full .NET GC.