%% SCRAP: architecture/03-architecture/hal/platform-implementations %% SOURCE: docs/working/architecture/03-architecture/hal/platform-implementations.md %% STATUS: WORKING %% FITS: dev-guide/ch-platform %% EDITORIAL: lifted — prose rewritten to press voice \section{HAL Platform Implementation Guide} This section explains how to implement the Hardware Abstraction Layer for a new target. It walks through the hosted Linux reference and the freestanding StarKernel implementation, then sets out a testing strategy and the pitfalls that most often defeat a new platform. \subsection{Directory Layout and Build Integration} Each platform lives under its own directory and supplies one source file per subsystem --- time, interrupt, memory, console, CPU, and panic --- plus an optional initialization file. The build selects a platform and compiles only its sources. The freestanding kernel target additionally adds the flags that strip the hosted runtime. \begin{lstlisting}[language=bash] PLATFORM ?= linux # linux | l4re | kernel PLATFORM_SOURCES = \ src/platform/$(PLATFORM)/hal_time.c \ src/platform/$(PLATFORM)/hal_interrupt.c \ src/platform/$(PLATFORM)/hal_memory.c \ src/platform/$(PLATFORM)/hal_console.c \ src/platform/$(PLATFORM)/hal_cpu.c \ src/platform/$(PLATFORM)/hal_panic.c ifeq ($(PLATFORM),kernel) CFLAGS += -ffreestanding -nostdlib -mno-red-zone LDFLAGS += -nostdlib -static endif \end{lstlisting} \subsection{The Linux Reference Platform} Linux is the reference platform, chosen for its rich debugging environment. Its implementation is thin. Time maps onto \texttt{clock\_gettime(CLOCK\_MONOTONIC)}, with the periodic timer built from a POSIX timer and a real-time signal whose handler dispatches the registered callback. Memory wraps \texttt{malloc} and \texttt{free}, zero-initializing every allocation to satisfy the contract, and treats page allocation as a heap allocation under an identity-mapping assumption. The console wraps standard I/O, flushing after each write and polling standard input for the non-blocking check. Interrupts are emulated: enable and disable are no-ops because signals cannot be masked through this path, and interrupt context is reported through a thread-local flag set inside the signal handler. CPU identity is fixed at zero for the single-threaded case, relax calls \texttt{sched\_yield()}, and panic prints to standard error and aborts. \begin{lstlisting}[language=C] uint64_t hal_time_now_ns(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec; } \end{lstlisting} \subsection{The StarKernel Freestanding Platform} The kernel platform is freestanding: no C library, no operating system, direct hardware access. Time reads the TSC, calibrated against the HPET at initialization, validates monotonicity, and panics if calibration fails; the periodic timer programs the local APIC timer, and its ISR invokes the callback and issues an end-of-interrupt. Interrupts are real: enable and disable issue \texttt{sti} and \texttt{cli}, the disable path captures and returns the flags register for later restoration, ISR registration writes the dispatch table and routes the IRQ through the IOAPIC, and interrupt context is tracked by a nesting counter incremented and decremented around each dispatch. Memory binds to the physical memory manager, the virtual memory manager, and the \texttt{kmalloc} heap, translating the HAL mapping flags into page-table flags. The console drives a 16550 UART and a UEFI GOP framebuffer in parallel. CPU identity comes from the local APIC, relax issues \texttt{pause}, and halt issues \texttt{hlt}. \begin{lstlisting}[language=C] uint64_t hal_time_now_ns(void) { uint64_t tsc = rdtsc(); return tsc_to_ns(tsc) - tsc_offset_ns; } \end{lstlisting} \subsection{Testing Strategy} A new platform is validated at three levels. First, per-platform unit tests exercise each HAL function in isolation --- confirming, for example, that \texttt{hal\_time\_now\_ns()} is monotonic and that a requested delay elapses. Second, the cross-platform VM test suite must pass identically on every target. Third, determinism is validated by running the design-of-experiments harness on each platform and confirming that the output is identical across them, which demonstrates zero algorithmic variance. \subsection{Common Pitfalls} Four failure modes recur. \emph{Non-monotonic time}: a TSC that runs backward under multi-core scheduling or frequency scaling corrupts the rolling window; the remedy is \texttt{rdtscp}, cross-core synchronization, or an HPET fallback. \emph{Timer jitter}: signal latency on Linux or interrupt latency on a kernel widens heartbeat intervals and inflates metric variance; minimize ISR work, use a high-priority interrupt, and disable frequency scaling. \emph{Memory leaks}: allocations without matching frees, often in error paths; track them with Valgrind on Linux and by hand on the kernel. \emph{Interrupt-context violations}: calling a blocking HAL function from an ISR; guard blocking functions with an assertion that the caller is not in interrupt context.